Alexandre Julliard : kernel32: Duplicate OutputDebugStringA implementation.
Alexandre Julliard
julliard at winehq.org
Mon Dec 16 16:47:55 CST 2019
Module: wine
Branch: master
Commit: 4ac3cbd6ccba52ad8d528ee7456207defc8fdcdb
URL: https://source.winehq.org/git/wine.git/?a=commit;h=4ac3cbd6ccba52ad8d528ee7456207defc8fdcdb
Author: Alexandre Julliard <julliard at winehq.org>
Date: Mon Dec 16 12:00:36 2019 +0100
kernel32: Duplicate OutputDebugStringA implementation.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48059
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/kernel32/debugger.c | 102 ++++++++++++++++++++++++++++++++++++++++++++
dlls/kernel32/kernel32.spec | 2 +-
2 files changed, 103 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/debugger.c b/dlls/kernel32/debugger.c
index 3a2e988741..f9d398fd35 100644
--- a/dlls/kernel32/debugger.c
+++ b/dlls/kernel32/debugger.c
@@ -33,6 +33,108 @@
WINE_DEFAULT_DEBUG_CHANNEL(debugstr);
+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.@)
+ *
+ * Duplicate since IMVU doesn't like it if we call kernelbase.OutputDebugStringA.
+ */
+void WINAPI DECLSPEC_HOTPATCH OutputDebugStringA( LPCSTR str )
+{
+ static HANDLE DBWinMutex = NULL;
+ static BOOL mutex_inited = FALSE;
+ BOOL caught_by_dbg = TRUE;
+
+ if (!str) str = "";
+ WARN( "%s\n", debugstr_a(str) );
+
+ /* raise exception, WaitForDebugEvent() will generate a corresponding debug event */
+ __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)
+ {
+ caught_by_dbg = FALSE;
+ }
+ __ENDTRY
+ if (caught_by_dbg) return;
+
+ /* send string to a system-wide monitor */
+ if (!mutex_inited)
+ {
+ /* first call to OutputDebugString, initialize mutex handle */
+ static const WCHAR mutexname[] = {'D','B','W','i','n','M','u','t','e','x',0};
+ HANDLE mutex = CreateMutexExW( NULL, mutexname, 0, SYNCHRONIZE );
+ if (mutex)
+ {
+ if (InterlockedCompareExchangePointer( &DBWinMutex, mutex, 0 ) != 0)
+ /* someone beat us here... */
+ CloseHandle( mutex );
+ }
+ mutex_inited = TRUE;
+ }
+
+ if (DBWinMutex)
+ {
+ static const WCHAR shmname[] = {'D','B','W','I','N','_','B','U','F','F','E','R',0};
+ static const WCHAR eventbuffername[] = {'D','B','W','I','N','_','B','U','F','F','E','R','_','R','E','A','D','Y',0};
+ static const WCHAR eventdataname[] = {'D','B','W','I','N','_','D','A','T','A','_','R','E','A','D','Y',0};
+ HANDLE mapping;
+
+ mapping = OpenFileMappingW( FILE_MAP_WRITE, FALSE, shmname );
+ if (mapping)
+ {
+ LPVOID buffer;
+ HANDLE eventbuffer, eventdata;
+
+ buffer = MapViewOfFile( mapping, FILE_MAP_WRITE, 0, 0, 0 );
+ eventbuffer = OpenEventW( SYNCHRONIZE, FALSE, eventbuffername );
+ eventdata = OpenEventW( EVENT_MODIFY_STATE, FALSE, eventdataname );
+
+ if (buffer && eventbuffer && eventdata)
+ {
+ /* monitor is present, synchronize with other OutputDebugString invocations */
+ WaitForSingleObject( DBWinMutex, INFINITE );
+
+ /* acquire control over the buffer */
+ if (WaitForSingleObject( eventbuffer, 10000 ) == WAIT_OBJECT_0)
+ {
+ int str_len = strlen( str );
+ struct _mon_buffer_t
+ {
+ DWORD pid;
+ char buffer[1];
+ } *mon_buffer = (struct _mon_buffer_t*) buffer;
+
+ if (str_len > (4096 - sizeof(DWORD) - 1)) str_len = 4096 - sizeof(DWORD) - 1;
+ mon_buffer->pid = GetCurrentProcessId();
+ memcpy( mon_buffer->buffer, str, str_len );
+ mon_buffer->buffer[str_len] = 0;
+
+ /* signal data ready */
+ SetEvent( eventdata );
+ }
+ ReleaseMutex( DBWinMutex );
+ }
+
+ if (buffer) UnmapViewOfFile( buffer );
+ if (eventbuffer) CloseHandle( eventbuffer );
+ if (eventdata) CloseHandle( eventdata );
+ CloseHandle( mapping );
+ }
+ }
+}
+
+
/***********************************************************************
* DebugBreakProcess (KERNEL32.@)
*
diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec
index 408ea41540..b580021706 100644
--- a/dlls/kernel32/kernel32.spec
+++ b/dlls/kernel32/kernel32.spec
@@ -1136,7 +1136,7 @@
@ stdcall -i386 OpenVxDHandle(long)
@ stdcall OpenWaitableTimerA(long long str)
@ stdcall -import OpenWaitableTimerW(long long wstr)
-@ stdcall -import OutputDebugStringA(str)
+@ stdcall OutputDebugStringA(str)
@ stdcall -import OutputDebugStringW(wstr)
@ stdcall -import PeekConsoleInputA(ptr ptr long ptr)
@ stdcall -import PeekConsoleInputW(ptr ptr long ptr)
More information about the wine-cvs
mailing list