2 * Win32 debugger functions
4 * Copyright (C) 1999 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #define WIN32_NO_STATUS
28 #include "wine/server.h"
29 #include "kernel_private.h"
31 #include "wine/debug.h"
32 #include "wine/exception.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(debugstr
);
36 static LONG WINAPI
debug_exception_handler( EXCEPTION_POINTERS
*eptr
)
38 EXCEPTION_RECORD
*rec
= eptr
->ExceptionRecord
;
39 return (rec
->ExceptionCode
== DBG_PRINTEXCEPTION_C
) ? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH
;
42 /***********************************************************************
43 * OutputDebugStringA (KERNEL32.@)
45 * Duplicate since IMVU doesn't like it if we call kernelbase.OutputDebugStringA.
47 void WINAPI DECLSPEC_HOTPATCH
OutputDebugStringA( LPCSTR str
)
49 static HANDLE DBWinMutex
= NULL
;
50 static BOOL mutex_inited
= FALSE
;
51 BOOL caught_by_dbg
= TRUE
;
54 WARN( "%s\n", debugstr_a(str
) );
56 /* raise exception, WaitForDebugEvent() will generate a corresponding debug event */
60 args
[0] = strlen(str
) + 1;
61 args
[1] = (ULONG_PTR
)str
;
62 RaiseException( DBG_PRINTEXCEPTION_C
, 0, 2, args
);
64 __EXCEPT(debug_exception_handler
)
66 caught_by_dbg
= FALSE
;
69 if (caught_by_dbg
) return;
71 /* send string to a system-wide monitor */
74 /* first call to OutputDebugString, initialize mutex handle */
75 static const WCHAR mutexname
[] = {'D','B','W','i','n','M','u','t','e','x',0};
76 HANDLE mutex
= CreateMutexExW( NULL
, mutexname
, 0, SYNCHRONIZE
);
79 if (InterlockedCompareExchangePointer( &DBWinMutex
, mutex
, 0 ) != 0)
80 /* someone beat us here... */
88 static const WCHAR shmname
[] = {'D','B','W','I','N','_','B','U','F','F','E','R',0};
89 static const WCHAR eventbuffername
[] = {'D','B','W','I','N','_','B','U','F','F','E','R','_','R','E','A','D','Y',0};
90 static const WCHAR eventdataname
[] = {'D','B','W','I','N','_','D','A','T','A','_','R','E','A','D','Y',0};
93 mapping
= OpenFileMappingW( FILE_MAP_WRITE
, FALSE
, shmname
);
97 HANDLE eventbuffer
, eventdata
;
99 buffer
= MapViewOfFile( mapping
, FILE_MAP_WRITE
, 0, 0, 0 );
100 eventbuffer
= OpenEventW( SYNCHRONIZE
, FALSE
, eventbuffername
);
101 eventdata
= OpenEventW( EVENT_MODIFY_STATE
, FALSE
, eventdataname
);
103 if (buffer
&& eventbuffer
&& eventdata
)
105 /* monitor is present, synchronize with other OutputDebugString invocations */
106 WaitForSingleObject( DBWinMutex
, INFINITE
);
108 /* acquire control over the buffer */
109 if (WaitForSingleObject( eventbuffer
, 10000 ) == WAIT_OBJECT_0
)
111 int str_len
= strlen( str
);
116 } *mon_buffer
= (struct _mon_buffer_t
*) buffer
;
118 if (str_len
> (4096 - sizeof(DWORD
) - 1)) str_len
= 4096 - sizeof(DWORD
) - 1;
119 mon_buffer
->pid
= GetCurrentProcessId();
120 memcpy( mon_buffer
->buffer
, str
, str_len
);
121 mon_buffer
->buffer
[str_len
] = 0;
123 /* signal data ready */
124 SetEvent( eventdata
);
126 ReleaseMutex( DBWinMutex
);
129 if (buffer
) UnmapViewOfFile( buffer
);
130 if (eventbuffer
) CloseHandle( eventbuffer
);
131 if (eventdata
) CloseHandle( eventdata
);
132 CloseHandle( mapping
);
138 /***********************************************************************
139 * DebugBreakProcess (KERNEL32.@)
141 * Raises an exception so that a debugger (if attached)
142 * can take some action. Same as DebugBreak, but applies to any process.
145 * hProc [I] Process to break into.
149 * True if successful.
151 BOOL WINAPI
DebugBreakProcess(HANDLE process
)
155 TRACE("(%p)\n", process
);
157 status
= DbgUiIssueRemoteBreakin(process
);
158 if (status
) SetLastError(RtlNtStatusToDosError(status
));
163 /***********************************************************************
164 * DebugSetProcessKillOnExit (KERNEL32.@)
166 * Let a debugger decide whether a debuggee will be killed upon debugger
170 * kill [I] If set to true then kill the process on exit.
173 * True if successful, false otherwise.
175 BOOL WINAPI
DebugSetProcessKillOnExit(BOOL kill
)
179 SERVER_START_REQ( set_debugger_kill_on_exit
)
181 req
->kill_on_exit
= kill
;
182 ret
= !wine_server_call_err( req
);