kernel32: Duplicate OutputDebugStringA implementation.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=48059
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2019-12-16 12:00:36 +01:00
parent 802803a028
commit 4ac3cbd6cc
2 changed files with 103 additions and 1 deletions

View File

@ -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.@)
*

View File

@ -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)