Sebastian Lackner : kernel32: Raise DBG_PRINTEXCEPTION_C exception in OutputDebugStringA.

Alexandre Julliard julliard at winehq.org
Tue Jun 17 14:40:50 CDT 2014


Module: wine
Branch: master
Commit: 1b3d67aaceaa58cbe0dfc32d4b1cb0f4e17eaf23
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=1b3d67aaceaa58cbe0dfc32d4b1cb0f4e17eaf23

Author: Sebastian Lackner <sebastian at fds-team.de>
Date:   Sat Jun 14 09:39:24 2014 +0200

kernel32: Raise DBG_PRINTEXCEPTION_C exception in OutputDebugStringA.

---

 dlls/kernel32/debugger.c     |   21 +++++++++++++++++++++
 dlls/ntdll/tests/exception.c |   41 +++++++++++++++++++++++++++++++++++++++++
 include/ntstatus.h           |    1 +
 include/winnt.h              |    1 +
 4 files changed, 64 insertions(+)

diff --git a/dlls/kernel32/debugger.c b/dlls/kernel32/debugger.c
index 5300fb5..34ef30a 100644
--- a/dlls/kernel32/debugger.c
+++ b/dlls/kernel32/debugger.c
@@ -28,6 +28,7 @@
 #include "wine/server.h"
 #include "kernel_private.h"
 #include "wine/debug.h"
+#include "wine/exception.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(debugstr);
 
@@ -227,6 +228,11 @@ BOOL WINAPI DebugActiveProcessStop( DWORD pid )
     return ret;
 }
 
+static LONG WINAPI debug_exception_handler( EXCEPTION_POINTERS *eptr )
+{
+    EXCEPTION_RECORD *rec = eptr->ExceptionRecord;
+    return (rec->ExceptionCode == DBG_PRINTEXCEPTION_C) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH;
+}
 
 /***********************************************************************
  *           OutputDebugStringA   (KERNEL32.@)
@@ -248,7 +254,22 @@ void WINAPI OutputDebugStringA( LPCSTR str )
 
     if (!str) str = "";
 
+    /* raise fake exception to make copy protections happy */
+    __TRY
+    {
+        ULONG_PTR args[2];
+        args[0] = strlen(str) + 1;
+        args[1] = (ULONG_PTR)str;
+        RaiseException( DBG_PRINTEXCEPTION_C, 0, 2, args );
+    }
+    __EXCEPT(debug_exception_handler)
+    {
+    }
+    __ENDTRY
+
     /* send string to attached debugger */
+    /* FIXME should only send to debugger if exception is not caught by user-mode application */
+
     SERVER_START_REQ( output_debug_string )
     {
         req->string  = wine_server_client_ptr( str );
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 8a80928..05bc15c 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -1572,6 +1572,45 @@ static void test_dynamic_unwind(void)
 
 #endif  /* __x86_64__ */
 
+static DWORD outputdebugstring_exceptions;
+
+static LONG CALLBACK outputdebugstring_vectored_handler(EXCEPTION_POINTERS *ExceptionInfo)
+{
+    PEXCEPTION_RECORD rec = ExceptionInfo->ExceptionRecord;
+    trace("vect. handler %08x addr:%p\n", rec->ExceptionCode, rec->ExceptionAddress);
+
+    ok(rec->ExceptionCode == DBG_PRINTEXCEPTION_C, "ExceptionCode is %08x instead of %08x\n",
+        rec->ExceptionCode, DBG_PRINTEXCEPTION_C);
+    ok(rec->NumberParameters == 2, "ExceptionParameters is %d instead of 2\n", rec->NumberParameters);
+    ok(rec->ExceptionInformation[0] == 12, "ExceptionInformation[0] = %d instead of 12\n", (DWORD)rec->ExceptionInformation[0]);
+    ok(!strcmp((char *)rec->ExceptionInformation[1], "Hello World"),
+        "ExceptionInformation[1] = '%s' instead of 'Hello World'\n", (char *)rec->ExceptionInformation[1]);
+
+    outputdebugstring_exceptions++;
+    return EXCEPTION_CONTINUE_SEARCH;
+}
+
+static void test_outputdebugstring(void)
+{
+    PVOID vectored_handler;
+
+    if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler)
+    {
+        skip("RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n");
+        return;
+    }
+
+    vectored_handler = pRtlAddVectoredExceptionHandler(TRUE, &outputdebugstring_vectored_handler);
+    ok(vectored_handler != 0, "RtlAddVectoredExceptionHandler failed\n");
+
+    outputdebugstring_exceptions = 0;
+    OutputDebugStringA("Hello World");
+    ok(outputdebugstring_exceptions == 1, "OutputDebugStringA generated %d exceptions, expected one\n",
+        outputdebugstring_exceptions);
+
+    pRtlRemoveVectoredExceptionHandler(vectored_handler);
+}
+
 START_TEST(exception)
 {
     HMODULE hntdll = GetModuleHandleA("ntdll.dll");
@@ -1675,5 +1714,7 @@ START_TEST(exception)
 
 #endif
 
+    test_outputdebugstring();
+
     VirtualFree(code_mem, 0, MEM_FREE);
 }
diff --git a/include/ntstatus.h b/include/ntstatus.h
index 1eaae2d..9a7ca7a 100644
--- a/include/ntstatus.h
+++ b/include/ntstatus.h
@@ -1211,6 +1211,7 @@
 #define DBG_TERMINATE_THREAD        ((NTSTATUS) 0x40010003)
 #define DBG_TERMINATE_PROCESS       ((NTSTATUS) 0x40010004)
 #define DBG_CONTROL_C               ((NTSTATUS) 0x40010005)
+#define DBG_PRINTEXCEPTION_C        ((NTSTATUS) 0x40010006)
 #define DBG_CONTROL_BREAK           ((NTSTATUS) 0x40010008)
 #define DBG_COMMAND_EXCEPTION       ((NTSTATUS) 0x40010009)
 #define DBG_EXCEPTION_NOT_HANDLED   ((NTSTATUS) 0x80010001)
diff --git a/include/winnt.h b/include/winnt.h
index 280cba0..e9e330d 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -622,6 +622,7 @@ typedef DWORD FLONG;
 #define DBG_TERMINATE_THREAD        ((DWORD) 0x40010003)
 #define DBG_TERMINATE_PROCESS       ((DWORD) 0x40010004)
 #define DBG_CONTROL_C               ((DWORD) 0x40010005)
+#define DBG_PRINTEXCEPTION_C        ((DWORD) 0x40010006)
 #define DBG_CONTROL_BREAK           ((DWORD) 0x40010008)
 #define DBG_COMMAND_EXCEPTION       ((DWORD) 0x40010009)
 #define DBG_EXCEPTION_NOT_HANDLED   ((DWORD) 0x80010001)




More information about the wine-cvs mailing list