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