2 * Win32 debugger functions
4 * Copyright (C) 1999 Alexandre Julliard
9 #include "server/request.h"
11 #include "debugtools.h"
14 /**********************************************************************
17 * Internal helper to send a debug event request to the server.
19 static DWORD
DEBUG_SendEvent( int code
, void *data
, int size
)
21 struct send_debug_event_request req
;
22 struct send_debug_event_reply reply
;
25 CLIENT_SendRequest( REQ_SEND_DEBUG_EVENT
, -1, 2, &req
, sizeof(req
), data
, size
);
26 if (CLIENT_WaitSimpleReply( &reply
, sizeof(reply
), NULL
)) return 0;
31 /**********************************************************************
32 * DEBUG_SendExceptionEvent
34 * Send an EXCEPTION_DEBUG_EVENT event to the current process debugger.
36 DWORD
DEBUG_SendExceptionEvent( EXCEPTION_RECORD
*rec
, BOOL first_chance
)
38 struct debug_event_exception event
;
41 event
.code
= rec
->ExceptionCode
;
42 event
.flags
= rec
->ExceptionFlags
;
43 event
.record
= rec
->ExceptionRecord
;
44 event
.addr
= rec
->ExceptionAddress
;
45 event
.nb_params
= rec
->NumberParameters
;
46 for (i
= 0; i
< event
.nb_params
; i
++) event
.params
[i
] = rec
->ExceptionInformation
[i
];
47 event
.first_chance
= first_chance
;
48 return DEBUG_SendEvent( EXCEPTION_DEBUG_EVENT
, &event
, sizeof(event
) );
52 /**********************************************************************
53 * DEBUG_SendCreateProcessEvent
55 * Send an CREATE_PROCESS_DEBUG_EVENT event to the current process debugger.
56 * Must be called from the context of the new process.
58 DWORD
DEBUG_SendCreateProcessEvent( HFILE file
, HMODULE module
, void *entry
)
60 struct debug_event_create_process event
;
63 event
.process
= 0; /* will be filled by server */
64 event
.thread
= 0; /* will be filled by server */
65 event
.base
= (void *)module
;
66 event
.dbg_offset
= 0; /* FIXME */
67 event
.dbg_size
= 0; /* FIXME */
68 event
.teb
= NtCurrentTeb();
70 event
.name
= 0; /* FIXME */
71 event
.unicode
= 0; /* FIXME */
72 return DEBUG_SendEvent( CREATE_PROCESS_DEBUG_EVENT
, &event
, sizeof(event
) );
76 /**********************************************************************
77 * DEBUG_SendCreateThreadEvent
79 * Send an CREATE_THREAD_DEBUG_EVENT event to the current process debugger.
80 * Must be called from the context of the new thread.
82 DWORD
DEBUG_SendCreateThreadEvent( void *entry
)
84 struct debug_event_create_thread event
;
86 event
.handle
= 0; /* will be filled by server */
87 event
.teb
= NtCurrentTeb();
89 return DEBUG_SendEvent( CREATE_THREAD_DEBUG_EVENT
, &event
, sizeof(event
) );
93 /**********************************************************************
94 * DEBUG_SendLoadDLLEvent
96 * Send an LOAD_DLL_DEBUG_EVENT event to the current process debugger.
98 DWORD
DEBUG_SendLoadDLLEvent( HFILE file
, HMODULE module
, LPSTR name
)
100 struct debug_event_load_dll event
;
103 event
.base
= (void *)module
;
104 event
.dbg_offset
= 0; /* FIXME */
105 event
.dbg_size
= 0; /* FIXME */
108 return DEBUG_SendEvent( LOAD_DLL_DEBUG_EVENT
, &event
, sizeof(event
) );
112 /**********************************************************************
113 * DEBUG_SendUnloadDLLEvent
115 * Send an UNLOAD_DLL_DEBUG_EVENT event to the current process debugger.
117 DWORD
DEBUG_SendUnloadDLLEvent( HMODULE module
)
119 struct debug_event_unload_dll event
;
121 event
.base
= (void *)module
;
122 return DEBUG_SendEvent( UNLOAD_DLL_DEBUG_EVENT
, &event
, sizeof(event
) );
126 /******************************************************************************
127 * WaitForDebugEvent (KERNEL32.720)
129 * Waits for a debugging event to occur in a process being debugged
132 * event [I] Address of structure for event information
133 * timeout [I] Number of milliseconds to wait for event
137 BOOL WINAPI
WaitForDebugEvent( LPDEBUG_EVENT event
, DWORD timeout
)
139 /* size of the event data */
140 static const int event_sizes
[] =
143 sizeof(struct debug_event_exception
), /* EXCEPTION_DEBUG_EVENT */
144 sizeof(struct debug_event_create_thread
), /* CREATE_THREAD_DEBUG_EVENT */
145 sizeof(struct debug_event_create_process
), /* CREATE_PROCESS_DEBUG_EVENT */
146 sizeof(struct debug_event_exit
), /* EXIT_THREAD_DEBUG_EVENT */
147 sizeof(struct debug_event_exit
), /* EXIT_PROCESS_DEBUG_EVENT */
148 sizeof(struct debug_event_load_dll
), /* LOAD_DLL_DEBUG_EVENT */
149 sizeof(struct debug_event_unload_dll
), /* UNLOAD_DLL_DEBUG_EVENT */
150 sizeof(struct debug_event_output_string
), /* OUTPUT_DEBUG_STRING_EVENT */
151 sizeof(struct debug_event_rip_info
) /* RIP_EVENT */
154 struct wait_debug_event_request req
;
155 struct wait_debug_event_reply reply
;
156 union debug_event_data data
;
159 req
.timeout
= timeout
;
160 CLIENT_SendRequest( REQ_WAIT_DEBUG_EVENT
, -1, 1, &req
, sizeof(req
) );
161 if (CLIENT_WaitReply( &len
, NULL
, 2, &reply
, sizeof(reply
),
162 &data
, sizeof(data
) )) return FALSE
;
163 if ((reply
.code
< 0) || (reply
.code
> RIP_EVENT
))
164 CLIENT_ProtocolError( "WaitForDebugEvent: bad code %d\n", reply
.code
);
165 if (len
!= sizeof(reply
) + event_sizes
[reply
.code
])
166 CLIENT_ProtocolError( "WaitForDebugEvent: bad len %d for code %d\n", len
, reply
.code
);
168 event
->dwDebugEventCode
= reply
.code
;
169 event
->dwProcessId
= (DWORD
)reply
.pid
;
170 event
->dwThreadId
= (DWORD
)reply
.tid
;
173 case EXCEPTION_DEBUG_EVENT
:
174 event
->u
.Exception
.ExceptionRecord
.ExceptionCode
= data
.exception
.code
;
175 event
->u
.Exception
.ExceptionRecord
.ExceptionFlags
= data
.exception
.flags
;
176 event
->u
.Exception
.ExceptionRecord
.ExceptionRecord
= data
.exception
.record
;
177 event
->u
.Exception
.ExceptionRecord
.ExceptionAddress
= data
.exception
.addr
;
178 event
->u
.Exception
.ExceptionRecord
.NumberParameters
= data
.exception
.nb_params
;
179 for (i
= 0; i
< data
.exception
.nb_params
; i
++)
180 event
->u
.Exception
.ExceptionRecord
.ExceptionInformation
[i
] = data
.exception
.params
[i
];
181 event
->u
.Exception
.dwFirstChance
= data
.exception
.first_chance
;
183 case CREATE_THREAD_DEBUG_EVENT
:
184 event
->u
.CreateThread
.hThread
= data
.create_thread
.handle
;
185 event
->u
.CreateThread
.lpThreadLocalBase
= data
.create_thread
.teb
;
186 event
->u
.CreateThread
.lpStartAddress
= data
.create_thread
.start
;
188 case CREATE_PROCESS_DEBUG_EVENT
:
189 event
->u
.CreateProcessInfo
.hFile
= data
.create_process
.file
;
190 event
->u
.CreateProcessInfo
.hProcess
= data
.create_process
.process
;
191 event
->u
.CreateProcessInfo
.hThread
= data
.create_process
.thread
;
192 event
->u
.CreateProcessInfo
.lpBaseOfImage
= data
.create_process
.base
;
193 event
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
= data
.create_process
.dbg_offset
;
194 event
->u
.CreateProcessInfo
.nDebugInfoSize
= data
.create_process
.dbg_size
;
195 event
->u
.CreateProcessInfo
.lpThreadLocalBase
= data
.create_process
.teb
;
196 event
->u
.CreateProcessInfo
.lpStartAddress
= data
.create_process
.start
;
197 event
->u
.CreateProcessInfo
.lpImageName
= data
.create_process
.name
;
198 event
->u
.CreateProcessInfo
.fUnicode
= data
.create_process
.unicode
;
199 if (data
.create_process
.file
== -1) event
->u
.CreateProcessInfo
.hFile
= 0;
201 case EXIT_THREAD_DEBUG_EVENT
:
202 event
->u
.ExitThread
.dwExitCode
= data
.exit
.exit_code
;
204 case EXIT_PROCESS_DEBUG_EVENT
:
205 event
->u
.ExitProcess
.dwExitCode
= data
.exit
.exit_code
;
207 case LOAD_DLL_DEBUG_EVENT
:
208 event
->u
.LoadDll
.hFile
= data
.load_dll
.handle
;
209 event
->u
.LoadDll
.lpBaseOfDll
= data
.load_dll
.base
;
210 event
->u
.LoadDll
.dwDebugInfoFileOffset
= data
.load_dll
.dbg_offset
;
211 event
->u
.LoadDll
.nDebugInfoSize
= data
.load_dll
.dbg_size
;
212 event
->u
.LoadDll
.lpImageName
= data
.load_dll
.name
;
213 event
->u
.LoadDll
.fUnicode
= data
.load_dll
.unicode
;
214 if (data
.load_dll
.handle
== -1) event
->u
.LoadDll
.hFile
= 0;
216 case UNLOAD_DLL_DEBUG_EVENT
:
217 event
->u
.UnloadDll
.lpBaseOfDll
= data
.unload_dll
.base
;
219 case OUTPUT_DEBUG_STRING_EVENT
:
220 event
->u
.DebugString
.lpDebugStringData
= data
.output_string
.string
;
221 event
->u
.DebugString
.fUnicode
= data
.output_string
.unicode
;
222 event
->u
.DebugString
.nDebugStringLength
= data
.output_string
.length
;
225 event
->u
.RipInfo
.dwError
= data
.rip_info
.error
;
226 event
->u
.RipInfo
.dwType
= data
.rip_info
.type
;
233 /**********************************************************************
234 * ContinueDebugEvent (KERNEL32.146)
236 BOOL WINAPI
ContinueDebugEvent( DWORD pid
, DWORD tid
, DWORD status
)
238 struct continue_debug_event_request req
;
240 req
.pid
= (void *)pid
;
241 req
.tid
= (void *)tid
;
243 CLIENT_SendRequest( REQ_CONTINUE_DEBUG_EVENT
, -1, 1, &req
, sizeof(req
) );
244 return !CLIENT_WaitReply( NULL
, NULL
, 0 );
248 /**********************************************************************
249 * DebugActiveProcess (KERNEL32.180)
251 BOOL WINAPI
DebugActiveProcess( DWORD pid
)
253 struct debug_process_request req
;
254 req
.pid
= (void *)pid
;
255 CLIENT_SendRequest( REQ_DEBUG_PROCESS
, -1, 1, &req
, sizeof(req
) );
256 return !CLIENT_WaitReply( NULL
, NULL
, 0 );
260 /***********************************************************************
261 * OutputDebugStringA (KERNEL32.548)
263 void WINAPI
OutputDebugStringA( LPCSTR str
)
265 if (PROCESS_Current()->flags
& PDB32_DEBUGGED
)
267 struct debug_event_output_string event
;
268 event
.string
= (void *)str
;
270 event
.length
= strlen(str
) + 1;
271 DEBUG_SendEvent( OUTPUT_DEBUG_STRING_EVENT
, &event
, sizeof(event
) );
273 else DPRINTF("OutputDebugStringA: %s\n", debugstr_a(str
) );
277 /***********************************************************************
278 * OutputDebugStringW (KERNEL32.549)
280 void WINAPI
OutputDebugStringW( LPCWSTR str
)
282 if (PROCESS_Current()->flags
& PDB32_DEBUGGED
)
284 struct debug_event_output_string event
;
285 event
.string
= (void *)str
;
287 event
.length
= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
288 DEBUG_SendEvent( OUTPUT_DEBUG_STRING_EVENT
, &event
, sizeof(event
) );
290 else DPRINTF("OutputDebugStringW: %s\n", debugstr_w(str
) );
294 /***********************************************************************
295 * OutputDebugString16 (KERNEL.115)
297 void WINAPI
OutputDebugString16( LPCSTR str
)
299 OutputDebugStringA( str
);