2 * Win32 debugger functions
4 * Copyright (C) 1999 Alexandre Julliard
10 #include "debugtools.h"
13 /**********************************************************************
16 * Internal helper to send a debug event request to the server.
18 static DWORD
DEBUG_SendEvent( int code
, void *data
, int size
)
20 struct send_debug_event_request req
;
21 struct send_debug_event_reply reply
;
24 CLIENT_SendRequest( REQ_SEND_DEBUG_EVENT
, -1, 2, &req
, sizeof(req
), data
, size
);
25 if (CLIENT_WaitSimpleReply( &reply
, sizeof(reply
), NULL
)) return 0;
30 /**********************************************************************
31 * DEBUG_SendExceptionEvent
33 * Send an EXCEPTION_DEBUG_EVENT event to the current process debugger.
35 DWORD
DEBUG_SendExceptionEvent( EXCEPTION_RECORD
*rec
, BOOL first_chance
)
37 struct debug_event_exception event
;
40 event
.code
= rec
->ExceptionCode
;
41 event
.flags
= rec
->ExceptionFlags
;
42 event
.record
= rec
->ExceptionRecord
;
43 event
.addr
= rec
->ExceptionAddress
;
44 event
.nb_params
= rec
->NumberParameters
;
45 for (i
= 0; i
< event
.nb_params
; i
++) event
.params
[i
] = rec
->ExceptionInformation
[i
];
46 event
.first_chance
= first_chance
;
47 return DEBUG_SendEvent( EXCEPTION_DEBUG_EVENT
, &event
, sizeof(event
) );
51 /**********************************************************************
52 * DEBUG_SendCreateProcessEvent
54 * Send an CREATE_PROCESS_DEBUG_EVENT event to the current process debugger.
55 * Must be called from the context of the new process.
57 DWORD
DEBUG_SendCreateProcessEvent( HFILE file
, HMODULE module
, void *entry
)
59 struct debug_event_create_process event
;
62 event
.process
= 0; /* will be filled by server */
63 event
.thread
= 0; /* will be filled by server */
64 event
.base
= (void *)module
;
65 event
.dbg_offset
= 0; /* FIXME */
66 event
.dbg_size
= 0; /* FIXME */
67 event
.teb
= NtCurrentTeb();
69 event
.name
= 0; /* FIXME */
70 event
.unicode
= 0; /* FIXME */
71 return DEBUG_SendEvent( CREATE_PROCESS_DEBUG_EVENT
, &event
, sizeof(event
) );
75 /**********************************************************************
76 * DEBUG_SendCreateThreadEvent
78 * Send an CREATE_THREAD_DEBUG_EVENT event to the current process debugger.
79 * Must be called from the context of the new thread.
81 DWORD
DEBUG_SendCreateThreadEvent( void *entry
)
83 struct debug_event_create_thread event
;
85 event
.handle
= 0; /* will be filled by server */
86 event
.teb
= NtCurrentTeb();
88 return DEBUG_SendEvent( CREATE_THREAD_DEBUG_EVENT
, &event
, sizeof(event
) );
92 /**********************************************************************
93 * DEBUG_SendLoadDLLEvent
95 * Send an LOAD_DLL_DEBUG_EVENT event to the current process debugger.
97 DWORD
DEBUG_SendLoadDLLEvent( HFILE file
, HMODULE module
, LPSTR name
)
99 struct debug_event_load_dll event
;
102 event
.base
= (void *)module
;
103 event
.dbg_offset
= 0; /* FIXME */
104 event
.dbg_size
= 0; /* FIXME */
107 return DEBUG_SendEvent( LOAD_DLL_DEBUG_EVENT
, &event
, sizeof(event
) );
111 /**********************************************************************
112 * DEBUG_SendUnloadDLLEvent
114 * Send an UNLOAD_DLL_DEBUG_EVENT event to the current process debugger.
116 DWORD
DEBUG_SendUnloadDLLEvent( HMODULE module
)
118 struct debug_event_unload_dll event
;
120 event
.base
= (void *)module
;
121 return DEBUG_SendEvent( UNLOAD_DLL_DEBUG_EVENT
, &event
, sizeof(event
) );
125 /******************************************************************************
126 * WaitForDebugEvent (KERNEL32.720)
128 * Waits for a debugging event to occur in a process being debugged
131 * event [I] Address of structure for event information
132 * timeout [I] Number of milliseconds to wait for event
136 BOOL WINAPI
WaitForDebugEvent( LPDEBUG_EVENT event
, DWORD timeout
)
138 /* size of the event data */
139 static const int event_sizes
[] =
142 sizeof(struct debug_event_exception
), /* EXCEPTION_DEBUG_EVENT */
143 sizeof(struct debug_event_create_thread
), /* CREATE_THREAD_DEBUG_EVENT */
144 sizeof(struct debug_event_create_process
), /* CREATE_PROCESS_DEBUG_EVENT */
145 sizeof(struct debug_event_exit
), /* EXIT_THREAD_DEBUG_EVENT */
146 sizeof(struct debug_event_exit
), /* EXIT_PROCESS_DEBUG_EVENT */
147 sizeof(struct debug_event_load_dll
), /* LOAD_DLL_DEBUG_EVENT */
148 sizeof(struct debug_event_unload_dll
), /* UNLOAD_DLL_DEBUG_EVENT */
149 sizeof(struct debug_event_output_string
), /* OUTPUT_DEBUG_STRING_EVENT */
150 sizeof(struct debug_event_rip_info
) /* RIP_EVENT */
153 struct wait_debug_event_request req
;
154 struct wait_debug_event_reply reply
;
155 union debug_event_data data
;
158 req
.timeout
= timeout
;
159 CLIENT_SendRequest( REQ_WAIT_DEBUG_EVENT
, -1, 1, &req
, sizeof(req
) );
160 if (CLIENT_WaitReply( &len
, NULL
, 2, &reply
, sizeof(reply
),
161 &data
, sizeof(data
) )) return FALSE
;
162 if ((reply
.code
< 0) || (reply
.code
> RIP_EVENT
))
163 CLIENT_ProtocolError( "WaitForDebugEvent: bad code %d\n", reply
.code
);
164 if (len
!= sizeof(reply
) + event_sizes
[reply
.code
])
165 CLIENT_ProtocolError( "WaitForDebugEvent: bad len %d for code %d\n", len
, reply
.code
);
167 event
->dwDebugEventCode
= reply
.code
;
168 event
->dwProcessId
= (DWORD
)reply
.pid
;
169 event
->dwThreadId
= (DWORD
)reply
.tid
;
172 case EXCEPTION_DEBUG_EVENT
:
173 event
->u
.Exception
.ExceptionRecord
.ExceptionCode
= data
.exception
.code
;
174 event
->u
.Exception
.ExceptionRecord
.ExceptionFlags
= data
.exception
.flags
;
175 event
->u
.Exception
.ExceptionRecord
.ExceptionRecord
= data
.exception
.record
;
176 event
->u
.Exception
.ExceptionRecord
.ExceptionAddress
= data
.exception
.addr
;
177 event
->u
.Exception
.ExceptionRecord
.NumberParameters
= data
.exception
.nb_params
;
178 for (i
= 0; i
< data
.exception
.nb_params
; i
++)
179 event
->u
.Exception
.ExceptionRecord
.ExceptionInformation
[i
] = data
.exception
.params
[i
];
180 event
->u
.Exception
.dwFirstChance
= data
.exception
.first_chance
;
182 case CREATE_THREAD_DEBUG_EVENT
:
183 event
->u
.CreateThread
.hThread
= data
.create_thread
.handle
;
184 event
->u
.CreateThread
.lpThreadLocalBase
= data
.create_thread
.teb
;
185 event
->u
.CreateThread
.lpStartAddress
= data
.create_thread
.start
;
187 case CREATE_PROCESS_DEBUG_EVENT
:
188 event
->u
.CreateProcessInfo
.hFile
= data
.create_process
.file
;
189 event
->u
.CreateProcessInfo
.hProcess
= data
.create_process
.process
;
190 event
->u
.CreateProcessInfo
.hThread
= data
.create_process
.thread
;
191 event
->u
.CreateProcessInfo
.lpBaseOfImage
= data
.create_process
.base
;
192 event
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
= data
.create_process
.dbg_offset
;
193 event
->u
.CreateProcessInfo
.nDebugInfoSize
= data
.create_process
.dbg_size
;
194 event
->u
.CreateProcessInfo
.lpThreadLocalBase
= data
.create_process
.teb
;
195 event
->u
.CreateProcessInfo
.lpStartAddress
= data
.create_process
.start
;
196 event
->u
.CreateProcessInfo
.lpImageName
= data
.create_process
.name
;
197 event
->u
.CreateProcessInfo
.fUnicode
= data
.create_process
.unicode
;
198 if (data
.create_process
.file
== -1) event
->u
.CreateProcessInfo
.hFile
= 0;
200 case EXIT_THREAD_DEBUG_EVENT
:
201 event
->u
.ExitThread
.dwExitCode
= data
.exit
.exit_code
;
203 case EXIT_PROCESS_DEBUG_EVENT
:
204 event
->u
.ExitProcess
.dwExitCode
= data
.exit
.exit_code
;
206 case LOAD_DLL_DEBUG_EVENT
:
207 event
->u
.LoadDll
.hFile
= data
.load_dll
.handle
;
208 event
->u
.LoadDll
.lpBaseOfDll
= data
.load_dll
.base
;
209 event
->u
.LoadDll
.dwDebugInfoFileOffset
= data
.load_dll
.dbg_offset
;
210 event
->u
.LoadDll
.nDebugInfoSize
= data
.load_dll
.dbg_size
;
211 event
->u
.LoadDll
.lpImageName
= data
.load_dll
.name
;
212 event
->u
.LoadDll
.fUnicode
= data
.load_dll
.unicode
;
213 if (data
.load_dll
.handle
== -1) event
->u
.LoadDll
.hFile
= 0;
215 case UNLOAD_DLL_DEBUG_EVENT
:
216 event
->u
.UnloadDll
.lpBaseOfDll
= data
.unload_dll
.base
;
218 case OUTPUT_DEBUG_STRING_EVENT
:
219 event
->u
.DebugString
.lpDebugStringData
= data
.output_string
.string
;
220 event
->u
.DebugString
.fUnicode
= data
.output_string
.unicode
;
221 event
->u
.DebugString
.nDebugStringLength
= data
.output_string
.length
;
224 event
->u
.RipInfo
.dwError
= data
.rip_info
.error
;
225 event
->u
.RipInfo
.dwType
= data
.rip_info
.type
;
232 /**********************************************************************
233 * ContinueDebugEvent (KERNEL32.146)
235 BOOL WINAPI
ContinueDebugEvent( DWORD pid
, DWORD tid
, DWORD status
)
237 struct continue_debug_event_request req
;
239 req
.pid
= (void *)pid
;
240 req
.tid
= (void *)tid
;
242 CLIENT_SendRequest( REQ_CONTINUE_DEBUG_EVENT
, -1, 1, &req
, sizeof(req
) );
243 return !CLIENT_WaitReply( NULL
, NULL
, 0 );
247 /**********************************************************************
248 * DebugActiveProcess (KERNEL32.180)
250 BOOL WINAPI
DebugActiveProcess( DWORD pid
)
252 struct debug_process_request req
;
253 req
.pid
= (void *)pid
;
254 CLIENT_SendRequest( REQ_DEBUG_PROCESS
, -1, 1, &req
, sizeof(req
) );
255 return !CLIENT_WaitReply( NULL
, NULL
, 0 );
259 /***********************************************************************
260 * OutputDebugStringA (KERNEL32.548)
262 void WINAPI
OutputDebugStringA( LPCSTR str
)
264 if (PROCESS_Current()->flags
& PDB32_DEBUGGED
)
266 struct debug_event_output_string event
;
267 event
.string
= (void *)str
;
269 event
.length
= strlen(str
) + 1;
270 DEBUG_SendEvent( OUTPUT_DEBUG_STRING_EVENT
, &event
, sizeof(event
) );
272 else DPRINTF("OutputDebugStringA: %s\n", debugstr_a(str
) );
276 /***********************************************************************
277 * OutputDebugStringW (KERNEL32.549)
279 void WINAPI
OutputDebugStringW( LPCWSTR str
)
281 if (PROCESS_Current()->flags
& PDB32_DEBUGGED
)
283 struct debug_event_output_string event
;
284 event
.string
= (void *)str
;
286 event
.length
= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
287 DEBUG_SendEvent( OUTPUT_DEBUG_STRING_EVENT
, &event
, sizeof(event
) );
289 else DPRINTF("OutputDebugStringW: %s\n", debugstr_w(str
) );
293 /***********************************************************************
294 * OutputDebugString16 (KERNEL.115)
296 void WINAPI
OutputDebugString16( LPCSTR str
)
298 OutputDebugStringA( str
);