Module: wine Branch: master Commit: 1b3d67aaceaa58cbe0dfc32d4b1cb0f4e17eaf23 URL: http://source.winehq.org/git/wine.git/?a=commit;h=1b3d67aaceaa58cbe0dfc32d4b...
Author: Sebastian Lackner sebastian@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)