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