VM86 exceptions handling bug - tests

Andrey Turkin pancha at mail.nnov.ru
Mon Jun 5 08:52:48 CDT 2006


__wine_enter_vm86 uses functions which doesn't know about VM86 and try 
to use Get/SetContextThread on VM86 CONTEXT structure. Attached is test 
cases for it. Actually these tests may fail in case of winedos/kernel 
bug too, but I failed to find more precise way to check it.

Changelog: add tests for VM86 exception handling (emulating instructions 
etc)

PS: Please let me know if this patch would be rejected (and that's wrong).
-------------- next part --------------
diff -Nru wine-0.9.14-orig/dlls/ntdll/tests/Makefile.in wine-0.9.14/dlls/ntdll/tests/Makefile.in
--- wine-0.9.14-orig/dlls/ntdll/tests/Makefile.in	2006-05-24 21:40:03.000000000 +0400
+++ wine-0.9.14/dlls/ntdll/tests/Makefile.in	2006-06-05 17:27:19.000000000 +0400
@@ -22,7 +22,8 @@
 	rtlbitmap.c \
 	rtlstr.c \
 	string.c \
-	time.c
+	time.c \
+	vm86.c
 
 @MAKE_TEST_RULES@
 
diff -Nru wine-0.9.14-orig/dlls/ntdll/tests/vm86.c wine-0.9.14/dlls/ntdll/tests/vm86.c
--- wine-0.9.14-orig/dlls/ntdll/tests/vm86.c	1970-01-01 03:00:00.000000000 +0300
+++ wine-0.9.14/dlls/ntdll/tests/vm86.c	2006-06-05 17:30:57.000000000 +0400
@@ -0,0 +1,159 @@
+/*
+ * Unit test suite for ntdll vm86 signal handling
+ *
+ * Copyright 2006 Andrey Turkin
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#include "windows.h"
+#include "wine/test.h"
+
+#ifdef __i386__
+BYTE testio[] = {
+    0xBA, 0x60, 0x00, /* mov  dx, 0x60 */
+    0xEC,             /* in   al, dx   */
+    0xB4, 0x02,       /* mov  ah, 2    */
+    0xB2, 0x4F,       /* mov  dl, 'O'  */
+    0xCD, 0x21,       /* int  0x21     */
+    0xB2, 0x4B,       /* mov  dl, 'K'  */
+    0xCD, 0x21,       /* int  0x21     */
+    0xCD, 0x20};      /* int  0x20     */
+
+BYTE testint3[] = {
+    0x31, 0xC0,         /*  xor    ax,ax         */
+    0x8E, 0xC0,         /*  mov    es,ax         */
+    0x8C,0xC8,          /*  mov    ax,cs         */
+    0x26,0xA3,0x0E,0x00,/*  mov    es:[3*4+2],ax */
+    0xE8,0x0C,0x00,     /*  call   _2            */
+    0xB4,0x02,          /*  mov    ah,2          */
+    0xB2,0x4F,          /*  mov    dl,'O'        */
+    0xCD,0x21,          /*  int    0x21          */
+    0xB2,0x4B,          /*  mov    dl,'K'        */
+    0xCD,0x21,          /*  int    0x21          */
+    0xCD,0x20,          /*  int    0x20          */
+    0x58,               /*  _2:pop ax            */
+    0x26,0xA3,0x0C,0x00,/*  mov    es:[3*4],ax   */
+    0xCC};              /*  int    3             */
+
+BYTE testint1[] = {
+    0x31,0xC0,          /*  xor    ax,ax           */
+    0x8E,0xC0,          /*  mov    es,ax           */
+    0x8C,0xC8,          /*  mov    ax,cs           */
+    0x8E,0xD8,          /*  mov    ds,ax           */
+    0x26,0xA3,0x06,0x00,/*  mov    es:[1*4+2],ax   */
+    0xB8,0x21,0x01,     /*  mov    ax, offset _2   */
+    0x26,0xA3,0x04,0x00,/*  mov    es:[1*4],ax     */
+    0xB2,0x53,          /*  mov    dl,'O'+('O'-'K')*/
+    0x9C,               /*  pushf                  */
+    0x58,               /*  pop    ax              */
+    0x50,               /*  push   ax              */
+    0x80,0xCC,0x01,     /*  or     ah, 1           */
+    0x50,               /*  push   ax              */
+    0x9D,               /*  popf                   */
+    0x90,               /*  nop                    */
+    0x9D,               /*  popf                   */
+    0xCD,0x20,          /*  int    0x20            */
+    0xB4,0x02,          /*  _2:mov ah,2            */
+    0x80,0xEA,0x04,     /*  sub    dl,'O'-'K'      */
+    0xCD,0x21,          /*  int    0x21            */
+    0xCF};              /*  iret                   */
+
+BOOL TestDOS(const BYTE* prog, DWORD progsize, const char* name)
+{
+    char filename[MAX_PATH];
+    DWORD wr;
+    BOOL result = FALSE;
+    HANDLE hndl;
+
+    GetTempPathA(sizeof(filename)-sizeof(name)-1, filename);
+    lstrcatA(filename, name);
+    hndl = CreateFileA(filename, FILE_GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+    if (hndl == INVALID_HANDLE_VALUE)
+        trace("cannot create file: %lu\n", GetLastError());
+    else {
+        if (!WriteFile(hndl, prog, progsize, &wr, NULL) || wr!=progsize)
+        {
+            trace("cannot write: %lu\n", GetLastError());
+            CloseHandle(hndl);
+        } else {
+            STARTUPINFO si;
+            PROCESS_INFORMATION pi;
+            HANDLE hPipe;
+            
+            CloseHandle(hndl);
+            ZeroMemory(&si, sizeof(si));
+            si.cb = sizeof(si);
+            si.dwFlags = STARTF_USESTDHANDLES;
+            if (!CreatePipe(&si.hStdInput, &si.hStdError, NULL, 0x1000))
+            {
+                trace("cannot create pipe: %lu\n", GetLastError());
+            } else {
+                if (!CreatePipe(&hPipe, &si.hStdOutput, NULL, 0x1000))
+                {
+                    trace("cannot create pipe: %lu\n", GetLastError());
+
+                } else {
+                    if (!CreateProcessA(NULL, filename, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
+                    {
+                        trace("cannot create DOS process: %lu\n", GetLastError());
+                    } else {
+                        char buf[5];
+                        DWORD rd=0;
+                        DWORD res = WaitForSingleObject(pi.hProcess, 1500);
+                        if (res != WAIT_OBJECT_0 && res != WAIT_TIMEOUT)
+                        {
+                            trace("WaitForSingleObject failed: %lu\n", res);
+                        } else if (res == WAIT_TIMEOUT) {
+                            trace("child process seemengly hang\n");
+                            TerminateProcess(pi.hProcess, 0);
+                        } else {
+                            if (ReadFile(hPipe, buf, sizeof(buf), &rd, NULL) && rd==2)
+                            {
+                                if (buf[0]=='O' && buf[1]=='K')
+                                {
+                                    result = TRUE;
+                                } else
+                                {
+                                    trace("strange input from child process: %02X%02X\n", buf[0], buf[1]);
+                                }
+                            }
+                        }
+                        CloseHandle(pi.hProcess);
+                        CloseHandle(pi.hThread);
+                    }
+                }
+                CloseHandle(si.hStdInput);
+                CloseHandle(si.hStdOutput);
+            }
+        }
+        DeleteFileA(filename);
+    }
+    return result;
+}
+#endif  /* __i386__ */
+
+START_TEST(vm86)
+{
+#ifdef __i386__
+todo_wine {
+    ok(TestDOS(testio ,sizeof(testio), "\\_vm86emt2.com"), "I/O test failed\n");
+    ok(TestDOS(testint3, sizeof(testint3), "\\_vm86int3.com"), "int 3 test failed\n");
+    ok(TestDOS(testint1, sizeof(testint1), "\\_vm86int1.com"), "single-step trace failed\n");
+}
+#endif
+}


More information about the wine-patches mailing list