2 * Win32 debugger functions
4 * Copyright (C) 1999 Alexandre Julliard
12 #include "debugtools.h"
14 DEFAULT_DEBUG_CHANNEL(debugstr
);
17 /**********************************************************************
18 * DEBUG_SendExceptionEvent
20 * Send an EXCEPTION_DEBUG_EVENT event to the current process debugger.
22 DWORD
DEBUG_SendExceptionEvent( EXCEPTION_RECORD
*rec
, BOOL first_chance
, CONTEXT
*context
)
26 struct send_debug_event_request
*req
= get_req_buffer();
28 req
->event
.code
= EXCEPTION_DEBUG_EVENT
;
29 req
->event
.info
.exception
.code
= rec
->ExceptionCode
;
30 req
->event
.info
.exception
.flags
= rec
->ExceptionFlags
;
31 req
->event
.info
.exception
.record
= rec
->ExceptionRecord
;
32 req
->event
.info
.exception
.addr
= rec
->ExceptionAddress
;
33 req
->event
.info
.exception
.nb_params
= rec
->NumberParameters
;
34 req
->event
.info
.exception
.first_chance
= first_chance
;
35 req
->event
.info
.exception
.context
= *context
;
36 for (i
= 0; i
< req
->event
.info
.exception
.nb_params
; i
++)
37 req
->event
.info
.exception
.params
[i
] = rec
->ExceptionInformation
[i
];
38 if (!server_call( REQ_SEND_DEBUG_EVENT
))
41 *context
= req
->event
.info
.exception
.context
;
47 /**********************************************************************
48 * DEBUG_SendCreateProcessEvent
50 * Send an CREATE_PROCESS_DEBUG_EVENT event to the current process debugger.
51 * Must be called from the context of the new process.
53 DWORD
DEBUG_SendCreateProcessEvent( HFILE file
, HMODULE module
, void *entry
)
56 struct send_debug_event_request
*req
= get_req_buffer();
58 req
->event
.code
= CREATE_PROCESS_DEBUG_EVENT
;
59 req
->event
.info
.create_process
.file
= file
;
60 req
->event
.info
.create_process
.process
= 0; /* will be filled by server */
61 req
->event
.info
.create_process
.thread
= 0; /* will be filled by server */
62 req
->event
.info
.create_process
.base
= (void *)module
;
63 req
->event
.info
.create_process
.dbg_offset
= 0; /* FIXME */
64 req
->event
.info
.create_process
.dbg_size
= 0; /* FIXME */
65 req
->event
.info
.create_process
.teb
= NtCurrentTeb();
66 req
->event
.info
.create_process
.start
= entry
;
67 req
->event
.info
.create_process
.name
= 0; /* FIXME */
68 req
->event
.info
.create_process
.unicode
= 0; /* FIXME */
69 if (!server_call( REQ_SEND_DEBUG_EVENT
)) ret
= req
->status
;
73 /**********************************************************************
74 * DEBUG_SendCreateThreadEvent
76 * Send an CREATE_THREAD_DEBUG_EVENT event to the current process debugger.
77 * Must be called from the context of the new thread.
79 DWORD
DEBUG_SendCreateThreadEvent( void *entry
)
82 struct send_debug_event_request
*req
= get_req_buffer();
84 req
->event
.code
= CREATE_THREAD_DEBUG_EVENT
;
85 req
->event
.info
.create_thread
.handle
= 0; /* will be filled by server */
86 req
->event
.info
.create_thread
.teb
= NtCurrentTeb();
87 req
->event
.info
.create_thread
.start
= entry
;
88 if (!server_call( REQ_SEND_DEBUG_EVENT
)) ret
= req
->status
;
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
)
101 struct send_debug_event_request
*req
= get_req_buffer();
103 req
->event
.code
= LOAD_DLL_DEBUG_EVENT
;
104 req
->event
.info
.load_dll
.handle
= file
;
105 req
->event
.info
.load_dll
.base
= (void *)module
;
106 req
->event
.info
.load_dll
.dbg_offset
= 0; /* FIXME */
107 req
->event
.info
.load_dll
.dbg_size
= 0; /* FIXME */
108 req
->event
.info
.load_dll
.name
= name
;
109 req
->event
.info
.load_dll
.unicode
= 0;
110 if (!server_call( REQ_SEND_DEBUG_EVENT
)) ret
= req
->status
;
115 /**********************************************************************
116 * DEBUG_SendUnloadDLLEvent
118 * Send an UNLOAD_DLL_DEBUG_EVENT event to the current process debugger.
120 DWORD
DEBUG_SendUnloadDLLEvent( HMODULE module
)
123 struct send_debug_event_request
*req
= get_req_buffer();
125 req
->event
.code
= UNLOAD_DLL_DEBUG_EVENT
;
126 req
->event
.info
.unload_dll
.base
= (void *)module
;
127 if (!server_call( REQ_SEND_DEBUG_EVENT
)) ret
= req
->status
;
132 /******************************************************************************
133 * WaitForDebugEvent (KERNEL32.720)
135 * Waits for a debugging event to occur in a process being debugged
138 * event [I] Address of structure for event information
139 * timeout [I] Number of milliseconds to wait for event
143 BOOL WINAPI
WaitForDebugEvent( LPDEBUG_EVENT event
, DWORD timeout
)
145 struct wait_debug_event_request
*req
= get_req_buffer();
148 req
->timeout
= timeout
;
149 if (server_call( REQ_WAIT_DEBUG_EVENT
)) return FALSE
;
150 if ((req
->event
.code
< 0) || (req
->event
.code
> RIP_EVENT
))
151 server_protocol_error( "WaitForDebugEvent: bad code %d\n", req
->event
.code
);
153 event
->dwDebugEventCode
= req
->event
.code
;
154 event
->dwProcessId
= (DWORD
)req
->pid
;
155 event
->dwThreadId
= (DWORD
)req
->tid
;
156 switch(req
->event
.code
)
158 case EXCEPTION_DEBUG_EVENT
:
159 event
->u
.Exception
.ExceptionRecord
.ExceptionCode
= req
->event
.info
.exception
.code
;
160 event
->u
.Exception
.ExceptionRecord
.ExceptionFlags
= req
->event
.info
.exception
.flags
;
161 event
->u
.Exception
.ExceptionRecord
.ExceptionRecord
= req
->event
.info
.exception
.record
;
162 event
->u
.Exception
.ExceptionRecord
.ExceptionAddress
= req
->event
.info
.exception
.addr
;
163 event
->u
.Exception
.ExceptionRecord
.NumberParameters
= req
->event
.info
.exception
.nb_params
;
164 for (i
= 0; i
< req
->event
.info
.exception
.nb_params
; i
++)
165 event
->u
.Exception
.ExceptionRecord
.ExceptionInformation
[i
] = req
->event
.info
.exception
.params
[i
];
166 event
->u
.Exception
.dwFirstChance
= req
->event
.info
.exception
.first_chance
;
168 case CREATE_THREAD_DEBUG_EVENT
:
169 event
->u
.CreateThread
.hThread
= req
->event
.info
.create_thread
.handle
;
170 event
->u
.CreateThread
.lpThreadLocalBase
= req
->event
.info
.create_thread
.teb
;
171 event
->u
.CreateThread
.lpStartAddress
= req
->event
.info
.create_thread
.start
;
173 case CREATE_PROCESS_DEBUG_EVENT
:
174 event
->u
.CreateProcessInfo
.hFile
= req
->event
.info
.create_process
.file
;
175 event
->u
.CreateProcessInfo
.hProcess
= req
->event
.info
.create_process
.process
;
176 event
->u
.CreateProcessInfo
.hThread
= req
->event
.info
.create_process
.thread
;
177 event
->u
.CreateProcessInfo
.lpBaseOfImage
= req
->event
.info
.create_process
.base
;
178 event
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
= req
->event
.info
.create_process
.dbg_offset
;
179 event
->u
.CreateProcessInfo
.nDebugInfoSize
= req
->event
.info
.create_process
.dbg_size
;
180 event
->u
.CreateProcessInfo
.lpThreadLocalBase
= req
->event
.info
.create_process
.teb
;
181 event
->u
.CreateProcessInfo
.lpStartAddress
= req
->event
.info
.create_process
.start
;
182 event
->u
.CreateProcessInfo
.lpImageName
= req
->event
.info
.create_process
.name
;
183 event
->u
.CreateProcessInfo
.fUnicode
= req
->event
.info
.create_process
.unicode
;
184 if (req
->event
.info
.create_process
.file
== -1) event
->u
.CreateProcessInfo
.hFile
= 0;
186 case EXIT_THREAD_DEBUG_EVENT
:
187 event
->u
.ExitThread
.dwExitCode
= req
->event
.info
.exit
.exit_code
;
189 case EXIT_PROCESS_DEBUG_EVENT
:
190 event
->u
.ExitProcess
.dwExitCode
= req
->event
.info
.exit
.exit_code
;
192 case LOAD_DLL_DEBUG_EVENT
:
193 event
->u
.LoadDll
.hFile
= req
->event
.info
.load_dll
.handle
;
194 event
->u
.LoadDll
.lpBaseOfDll
= req
->event
.info
.load_dll
.base
;
195 event
->u
.LoadDll
.dwDebugInfoFileOffset
= req
->event
.info
.load_dll
.dbg_offset
;
196 event
->u
.LoadDll
.nDebugInfoSize
= req
->event
.info
.load_dll
.dbg_size
;
197 event
->u
.LoadDll
.lpImageName
= req
->event
.info
.load_dll
.name
;
198 event
->u
.LoadDll
.fUnicode
= req
->event
.info
.load_dll
.unicode
;
199 if (req
->event
.info
.load_dll
.handle
== -1) event
->u
.LoadDll
.hFile
= 0;
201 case UNLOAD_DLL_DEBUG_EVENT
:
202 event
->u
.UnloadDll
.lpBaseOfDll
= req
->event
.info
.unload_dll
.base
;
204 case OUTPUT_DEBUG_STRING_EVENT
:
205 event
->u
.DebugString
.lpDebugStringData
= req
->event
.info
.output_string
.string
;
206 event
->u
.DebugString
.fUnicode
= req
->event
.info
.output_string
.unicode
;
207 event
->u
.DebugString
.nDebugStringLength
= req
->event
.info
.output_string
.length
;
210 event
->u
.RipInfo
.dwError
= req
->event
.info
.rip_info
.error
;
211 event
->u
.RipInfo
.dwType
= req
->event
.info
.rip_info
.type
;
218 /**********************************************************************
219 * ContinueDebugEvent (KERNEL32.146)
221 BOOL WINAPI
ContinueDebugEvent( DWORD pid
, DWORD tid
, DWORD status
)
223 struct continue_debug_event_request
*req
= get_req_buffer();
224 req
->pid
= (void *)pid
;
225 req
->tid
= (void *)tid
;
226 req
->status
= status
;
227 return !server_call( REQ_CONTINUE_DEBUG_EVENT
);
231 /**********************************************************************
232 * DebugActiveProcess (KERNEL32.180)
234 BOOL WINAPI
DebugActiveProcess( DWORD pid
)
236 struct debug_process_request
*req
= get_req_buffer();
237 req
->pid
= (void *)pid
;
238 return !server_call( REQ_DEBUG_PROCESS
);
242 /***********************************************************************
243 * OutputDebugStringA (KERNEL32.548)
245 void WINAPI
OutputDebugStringA( LPCSTR str
)
247 if (PROCESS_Current()->flags
& PDB32_DEBUGGED
)
249 struct send_debug_event_request
*req
= get_req_buffer();
250 req
->event
.code
= OUTPUT_DEBUG_STRING_EVENT
;
251 req
->event
.info
.output_string
.string
= (void *)str
;
252 req
->event
.info
.output_string
.unicode
= 0;
253 req
->event
.info
.output_string
.length
= strlen(str
) + 1;
254 server_call( REQ_SEND_DEBUG_EVENT
);
261 /***********************************************************************
262 * OutputDebugStringW (KERNEL32.549)
264 void WINAPI
OutputDebugStringW( LPCWSTR str
)
266 if (PROCESS_Current()->flags
& PDB32_DEBUGGED
)
268 struct send_debug_event_request
*req
= get_req_buffer();
269 req
->event
.code
= OUTPUT_DEBUG_STRING_EVENT
;
270 req
->event
.info
.output_string
.string
= (void *)str
;
271 req
->event
.info
.output_string
.unicode
= 1;
272 req
->event
.info
.output_string
.length
= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
273 server_call( REQ_SEND_DEBUG_EVENT
);
276 TRACE("%s\n", debugstr_w(str
));
280 /***********************************************************************
281 * OutputDebugString16 (KERNEL.115)
283 void WINAPI
OutputDebugString16( LPCSTR str
)
285 OutputDebugStringA( str
);