From: Eric Pouech epouech@codeweavers.com
Also modifying WaitForDebugEvent() to force resending the ansi DBG_PRINTEXCEPTION_C exception instead.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/kernelbase/debug.c | 29 +++++++++++++++++++++++++- dlls/kernelbase/sync.c | 11 ++++++++++ dlls/ntdll/tests/exception.c | 40 +++++++++++++++++++++--------------- 3 files changed, 62 insertions(+), 18 deletions(-)
diff --git a/dlls/kernelbase/debug.c b/dlls/kernelbase/debug.c index 7132f63bb52..e571378e2df 100644 --- a/dlls/kernelbase/debug.c +++ b/dlls/kernelbase/debug.c @@ -264,6 +264,11 @@ void WINAPI DECLSPEC_HOTPATCH OutputDebugStringA( LPCSTR str ) } }
+static LONG WINAPI debug_exception_handler_wide( EXCEPTION_POINTERS *eptr ) +{ + EXCEPTION_RECORD *rec = eptr->ExceptionRecord; + return (rec->ExceptionCode == DBG_PRINTEXCEPTION_WIDE_C) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH; +}
/*********************************************************************** * OutputDebugStringW (kernelbase.@) @@ -273,10 +278,32 @@ void WINAPI DECLSPEC_HOTPATCH OutputDebugStringW( LPCWSTR str ) UNICODE_STRING strW; STRING strA;
+ WARN( "%s\n", debugstr_w(str) ); + RtlInitUnicodeString( &strW, str ); if (!RtlUnicodeStringToAnsiString( &strA, &strW, TRUE )) { - OutputDebugStringA( strA.Buffer ); + BOOL exc_handled; + + __TRY + { + ULONG_PTR args[4]; + args[0] = wcslen(str) + 1; + args[1] = (ULONG_PTR)str; + args[2] = strlen(strA.Buffer) + 1; + args[3] = (ULONG_PTR)strA.Buffer; + RaiseException( DBG_PRINTEXCEPTION_WIDE_C, 0, 4, args ); + exc_handled = TRUE; + } + __EXCEPT(debug_exception_handler_wide) + { + exc_handled = FALSE; + } + __ENDTRY + + if (!exc_handled) + OutputDebugStringA( strA.Buffer ); + RtlFreeAnsiString( &strA ); } } diff --git a/dlls/kernelbase/sync.c b/dlls/kernelbase/sync.c index 3033a4ea245..3bb4589453f 100644 --- a/dlls/kernelbase/sync.c +++ b/dlls/kernelbase/sync.c @@ -404,6 +404,17 @@ BOOL WINAPI DECLSPEC_HOTPATCH WaitForDebugEvent( DEBUG_EVENT *event, DWORD timeo switch (status) { case STATUS_SUCCESS: + /* continue on wide print exceptions to force resending an ANSI one. */ + if (state.NewState == DbgExceptionStateChange) + { + DBGKM_EXCEPTION *info = &state.StateInfo.Exception; + DWORD code = info->ExceptionRecord.ExceptionCode; + if (code == DBG_PRINTEXCEPTION_WIDE_C && info->ExceptionRecord.NumberParameters >= 2) + { + DbgUiContinue( &state.AppClientId, DBG_EXCEPTION_NOT_HANDLED ); + break; + } + } DbgUiConvertStateChangeStructure( &state, event ); return TRUE; case STATUS_USER_APC: diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c index 9da6b756c31..f5c0b70de4c 100644 --- a/dlls/ntdll/tests/exception.c +++ b/dlls/ntdll/tests/exception.c @@ -8715,7 +8715,8 @@ static LONG CALLBACK outputdebugstring_vectored_handler(EXCEPTION_POINTERS *Exce return EXCEPTION_CONTINUE_SEARCH; }
-static void test_outputdebugstring(BOOL unicode, DWORD numexc_ansi, BOOL todo_ansi, DWORD numexc_unicode) +static void test_outputdebugstring(BOOL unicode, DWORD numexc_ansi, BOOL todo_ansi, + DWORD numexc_unicode_low, DWORD numexc_unicode_high) { PVOID vectored_handler;
@@ -8739,10 +8740,11 @@ static void test_outputdebugstring(BOOL unicode, DWORD numexc_ansi, BOOL todo_an ok(outputdebugstring_exceptions_ansi == numexc_ansi, "OutputDebugString%c generated %ld ansi exceptions, expected %ld\n", unicode ? 'W' : 'A', outputdebugstring_exceptions_ansi, numexc_ansi); - todo_wine_if(unicode && numexc_unicode) - ok(outputdebugstring_exceptions_unicode == numexc_unicode, - "OutputDebugString%c generated %lu unicode exceptions, expected %ld\n", - unicode ? 'W' : 'A', outputdebugstring_exceptions_unicode, numexc_unicode); + todo_wine_if(unicode && numexc_unicode_low) + ok(outputdebugstring_exceptions_unicode >= numexc_unicode_low && + outputdebugstring_exceptions_unicode <= numexc_unicode_high, + "OutputDebugString%c generated %lu unicode exceptions, expected %ld-%ld\n", + unicode ? 'W' : 'A', outputdebugstring_exceptions_unicode, numexc_unicode_low, numexc_unicode_high);
pRtlRemoveVectoredExceptionHandler(vectored_handler); } @@ -8804,11 +8806,6 @@ static void test_outputdebugstring_newmodel(void) }; int i;
- if (!pWaitForDebugEventEx) - { - skip("Unsupported new unicode debug string model\n"); - return; - } if (!pRtlAddVectoredExceptionHandler || !pRtlRemoveVectoredExceptionHandler) { skip("RtlAddVectoredExceptionHandler or RtlRemoveVectoredExceptionHandler not found\n"); @@ -11326,13 +11323,16 @@ START_TEST(exception) #endif
test_stage = STAGE_OUTPUTDEBUGSTRINGA_CONTINUE; - test_outputdebugstring(FALSE, 0, FALSE, 0); + + test_outputdebugstring(FALSE, 0, FALSE, 0, 0); test_stage = STAGE_OUTPUTDEBUGSTRINGA_NOT_HANDLED; - test_outputdebugstring(FALSE, 2, TRUE, 0); /* is 2 a Windows bug? */ + test_outputdebugstring(FALSE, 2, TRUE, 0, 0); /* is 2 a Windows bug? */ test_stage = STAGE_OUTPUTDEBUGSTRINGW_CONTINUE; - test_outputdebugstring(TRUE, 0, FALSE, 0); + /* depending on value passed DebugContinue we can get the unicode exception or not */ + test_outputdebugstring(TRUE, 0, FALSE, 0, 1); test_stage = STAGE_OUTPUTDEBUGSTRINGW_NOT_HANDLED; - test_outputdebugstring(TRUE, 2, TRUE, 1); /* is 2 a Windows bug? */ + /* depending on value passed DebugContinue we can get the unicode exception or not */ + test_outputdebugstring(TRUE, 2, TRUE, 0, 1); /* is 2 a Windows bug? */ test_stage = STAGE_RIPEVENT_CONTINUE; test_ripevent(0); test_stage = STAGE_RIPEVENT_NOT_HANDLED; @@ -11449,9 +11449,15 @@ START_TEST(exception) test_debugger(DBG_EXCEPTION_HANDLED, TRUE); test_debugger(DBG_CONTINUE, TRUE); test_thread_context(); - test_outputdebugstring(FALSE, 1, FALSE, 0); - test_outputdebugstring(TRUE, 1, FALSE, 1); - test_outputdebugstring_newmodel(); + test_outputdebugstring(FALSE, 1, FALSE, 0, 0); + if (pWaitForDebugEventEx) + { + test_outputdebugstring(TRUE, 1, FALSE, 1, 1); + test_outputdebugstring_newmodel(); + } + else + skip("Unsupported new unicode debug string model\n"); + test_ripevent(1); test_fastfail(); test_breakpoint(1);