2 * Win32 debugger functions
4 * Copyright (C) 1999 Alexandre Julliard
12 #include "debugtools.h"
14 DECLARE_DEBUG_CHANNEL(debugstr
)
16 /**********************************************************************
19 * Internal helper to send a debug event request to the server.
21 static DWORD
DEBUG_SendEvent( int code
, void *data
, int size
)
24 struct send_debug_event_request
*req
= get_req_buffer();
26 memcpy( req
+ 1, data
, size
);
27 if (!server_call( REQ_SEND_DEBUG_EVENT
)) ret
= req
->status
;
32 /**********************************************************************
33 * DEBUG_SendExceptionEvent
35 * Send an EXCEPTION_DEBUG_EVENT event to the current process debugger.
37 DWORD
DEBUG_SendExceptionEvent( EXCEPTION_RECORD
*rec
, BOOL first_chance
, CONTEXT
*context
)
41 struct send_debug_event_request
*req
= get_req_buffer();
42 struct debug_event_exception
*event
= (struct debug_event_exception
*)(req
+ 1);
44 req
->code
= EXCEPTION_DEBUG_EVENT
;
45 event
->code
= rec
->ExceptionCode
;
46 event
->flags
= rec
->ExceptionFlags
;
47 event
->record
= rec
->ExceptionRecord
;
48 event
->addr
= rec
->ExceptionAddress
;
49 event
->nb_params
= rec
->NumberParameters
;
50 for (i
= 0; i
< event
->nb_params
; i
++) event
->params
[i
] = rec
->ExceptionInformation
[i
];
51 event
->first_chance
= first_chance
;
52 event
->context
= *context
;
53 if (!server_call( REQ_SEND_DEBUG_EVENT
))
56 *context
= event
->context
;
62 /**********************************************************************
63 * DEBUG_SendCreateProcessEvent
65 * Send an CREATE_PROCESS_DEBUG_EVENT event to the current process debugger.
66 * Must be called from the context of the new process.
68 DWORD
DEBUG_SendCreateProcessEvent( HFILE file
, HMODULE module
, void *entry
)
70 struct debug_event_create_process event
;
73 event
.process
= 0; /* will be filled by server */
74 event
.thread
= 0; /* will be filled by server */
75 event
.base
= (void *)module
;
76 event
.dbg_offset
= 0; /* FIXME */
77 event
.dbg_size
= 0; /* FIXME */
78 event
.teb
= NtCurrentTeb();
80 event
.name
= 0; /* FIXME */
81 event
.unicode
= 0; /* FIXME */
82 return DEBUG_SendEvent( CREATE_PROCESS_DEBUG_EVENT
, &event
, sizeof(event
) );
86 /**********************************************************************
87 * DEBUG_SendCreateThreadEvent
89 * Send an CREATE_THREAD_DEBUG_EVENT event to the current process debugger.
90 * Must be called from the context of the new thread.
92 DWORD
DEBUG_SendCreateThreadEvent( void *entry
)
94 struct debug_event_create_thread event
;
96 event
.handle
= 0; /* will be filled by server */
97 event
.teb
= NtCurrentTeb();
99 return DEBUG_SendEvent( CREATE_THREAD_DEBUG_EVENT
, &event
, sizeof(event
) );
103 /**********************************************************************
104 * DEBUG_SendLoadDLLEvent
106 * Send an LOAD_DLL_DEBUG_EVENT event to the current process debugger.
108 DWORD
DEBUG_SendLoadDLLEvent( HFILE file
, HMODULE module
, LPSTR
*name
)
110 struct debug_event_load_dll event
;
113 event
.base
= (void *)module
;
114 event
.dbg_offset
= 0; /* FIXME */
115 event
.dbg_size
= 0; /* FIXME */
118 return DEBUG_SendEvent( LOAD_DLL_DEBUG_EVENT
, &event
, sizeof(event
) );
122 /**********************************************************************
123 * DEBUG_SendUnloadDLLEvent
125 * Send an UNLOAD_DLL_DEBUG_EVENT event to the current process debugger.
127 DWORD
DEBUG_SendUnloadDLLEvent( HMODULE module
)
129 struct debug_event_unload_dll event
;
131 event
.base
= (void *)module
;
132 return DEBUG_SendEvent( UNLOAD_DLL_DEBUG_EVENT
, &event
, sizeof(event
) );
136 /******************************************************************************
137 * WaitForDebugEvent (KERNEL32.720)
139 * Waits for a debugging event to occur in a process being debugged
142 * event [I] Address of structure for event information
143 * timeout [I] Number of milliseconds to wait for event
147 BOOL WINAPI
WaitForDebugEvent( LPDEBUG_EVENT event
, DWORD timeout
)
149 struct wait_debug_event_request
*req
= get_req_buffer();
150 union debug_event_data
*data
= (union debug_event_data
*)(req
+ 1);
153 req
->timeout
= timeout
;
154 if (server_call( REQ_WAIT_DEBUG_EVENT
)) return FALSE
;
155 if ((req
->code
< 0) || (req
->code
> RIP_EVENT
))
156 server_protocol_error( "WaitForDebugEvent: bad code %d\n", req
->code
);
158 event
->dwDebugEventCode
= req
->code
;
159 event
->dwProcessId
= (DWORD
)req
->pid
;
160 event
->dwThreadId
= (DWORD
)req
->tid
;
163 case EXCEPTION_DEBUG_EVENT
:
164 event
->u
.Exception
.ExceptionRecord
.ExceptionCode
= data
->exception
.code
;
165 event
->u
.Exception
.ExceptionRecord
.ExceptionFlags
= data
->exception
.flags
;
166 event
->u
.Exception
.ExceptionRecord
.ExceptionRecord
= data
->exception
.record
;
167 event
->u
.Exception
.ExceptionRecord
.ExceptionAddress
= data
->exception
.addr
;
168 event
->u
.Exception
.ExceptionRecord
.NumberParameters
= data
->exception
.nb_params
;
169 for (i
= 0; i
< data
->exception
.nb_params
; i
++)
170 event
->u
.Exception
.ExceptionRecord
.ExceptionInformation
[i
] = data
->exception
.params
[i
];
171 event
->u
.Exception
.dwFirstChance
= data
->exception
.first_chance
;
173 case CREATE_THREAD_DEBUG_EVENT
:
174 event
->u
.CreateThread
.hThread
= data
->create_thread
.handle
;
175 event
->u
.CreateThread
.lpThreadLocalBase
= data
->create_thread
.teb
;
176 event
->u
.CreateThread
.lpStartAddress
= data
->create_thread
.start
;
178 case CREATE_PROCESS_DEBUG_EVENT
:
179 event
->u
.CreateProcessInfo
.hFile
= data
->create_process
.file
;
180 event
->u
.CreateProcessInfo
.hProcess
= data
->create_process
.process
;
181 event
->u
.CreateProcessInfo
.hThread
= data
->create_process
.thread
;
182 event
->u
.CreateProcessInfo
.lpBaseOfImage
= data
->create_process
.base
;
183 event
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
= data
->create_process
.dbg_offset
;
184 event
->u
.CreateProcessInfo
.nDebugInfoSize
= data
->create_process
.dbg_size
;
185 event
->u
.CreateProcessInfo
.lpThreadLocalBase
= data
->create_process
.teb
;
186 event
->u
.CreateProcessInfo
.lpStartAddress
= data
->create_process
.start
;
187 event
->u
.CreateProcessInfo
.lpImageName
= data
->create_process
.name
;
188 event
->u
.CreateProcessInfo
.fUnicode
= data
->create_process
.unicode
;
189 if (data
->create_process
.file
== -1) event
->u
.CreateProcessInfo
.hFile
= 0;
191 case EXIT_THREAD_DEBUG_EVENT
:
192 event
->u
.ExitThread
.dwExitCode
= data
->exit
.exit_code
;
194 case EXIT_PROCESS_DEBUG_EVENT
:
195 event
->u
.ExitProcess
.dwExitCode
= data
->exit
.exit_code
;
197 case LOAD_DLL_DEBUG_EVENT
:
198 event
->u
.LoadDll
.hFile
= data
->load_dll
.handle
;
199 event
->u
.LoadDll
.lpBaseOfDll
= data
->load_dll
.base
;
200 event
->u
.LoadDll
.dwDebugInfoFileOffset
= data
->load_dll
.dbg_offset
;
201 event
->u
.LoadDll
.nDebugInfoSize
= data
->load_dll
.dbg_size
;
202 event
->u
.LoadDll
.lpImageName
= data
->load_dll
.name
;
203 event
->u
.LoadDll
.fUnicode
= data
->load_dll
.unicode
;
204 if (data
->load_dll
.handle
== -1) event
->u
.LoadDll
.hFile
= 0;
206 case UNLOAD_DLL_DEBUG_EVENT
:
207 event
->u
.UnloadDll
.lpBaseOfDll
= data
->unload_dll
.base
;
209 case OUTPUT_DEBUG_STRING_EVENT
:
210 event
->u
.DebugString
.lpDebugStringData
= data
->output_string
.string
;
211 event
->u
.DebugString
.fUnicode
= data
->output_string
.unicode
;
212 event
->u
.DebugString
.nDebugStringLength
= data
->output_string
.length
;
215 event
->u
.RipInfo
.dwError
= data
->rip_info
.error
;
216 event
->u
.RipInfo
.dwType
= data
->rip_info
.type
;
223 /**********************************************************************
224 * ContinueDebugEvent (KERNEL32.146)
226 BOOL WINAPI
ContinueDebugEvent( DWORD pid
, DWORD tid
, DWORD status
)
228 struct continue_debug_event_request
*req
= get_req_buffer();
229 req
->pid
= (void *)pid
;
230 req
->tid
= (void *)tid
;
231 req
->status
= status
;
232 return !server_call( REQ_CONTINUE_DEBUG_EVENT
);
236 /**********************************************************************
237 * DebugActiveProcess (KERNEL32.180)
239 BOOL WINAPI
DebugActiveProcess( DWORD pid
)
241 struct debug_process_request
*req
= get_req_buffer();
242 req
->pid
= (void *)pid
;
243 return !server_call( REQ_DEBUG_PROCESS
);
247 /***********************************************************************
248 * OutputDebugStringA (KERNEL32.548)
250 void WINAPI
OutputDebugStringA( LPCSTR str
)
252 if (PROCESS_Current()->flags
& PDB32_DEBUGGED
)
254 struct debug_event_output_string event
;
255 event
.string
= (void *)str
;
257 event
.length
= strlen(str
) + 1;
258 DEBUG_SendEvent( OUTPUT_DEBUG_STRING_EVENT
, &event
, sizeof(event
) );
261 TRACE_(debugstr
)("%s\n", str
);
265 /***********************************************************************
266 * OutputDebugStringW (KERNEL32.549)
268 void WINAPI
OutputDebugStringW( LPCWSTR str
)
270 if (PROCESS_Current()->flags
& PDB32_DEBUGGED
)
272 struct debug_event_output_string event
;
273 event
.string
= (void *)str
;
275 event
.length
= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
276 DEBUG_SendEvent( OUTPUT_DEBUG_STRING_EVENT
, &event
, sizeof(event
) );
279 TRACE_(debugstr
)("%s\n", debugstr_w(str
));
283 /***********************************************************************
284 * OutputDebugString16 (KERNEL.115)
286 void WINAPI
OutputDebugString16( LPCSTR str
)
288 OutputDebugStringA( str
);