2 * Win32 debugger functions
4 * Copyright (C) 1999 Alexandre Julliard
11 #include "wine/winbase16.h"
13 #include "stackframe.h"
14 #include "debugtools.h"
16 DEFAULT_DEBUG_CHANNEL(debugstr
);
19 /******************************************************************************
20 * WaitForDebugEvent (KERNEL32.720)
22 * Waits for a debugging event to occur in a process being debugged before
23 * filling out the debug event structure.
27 * Returns true if a debug event occurred and false if the call timed out.
29 BOOL WINAPI
WaitForDebugEvent(
30 LPDEBUG_EVENT event
, /* Address of structure for event information. */
31 DWORD timeout
/* Number of milliseconds to wait for event. */)
37 struct wait_debug_event_request
*req
= server_alloc_req( sizeof(*req
), sizeof(*data
) );
39 req
->timeout
= timeout
;
40 if (!(ret
= !server_call( REQ_WAIT_DEBUG_EVENT
))) goto done
;
42 if (!server_data_size(req
)) /* timeout */
44 SetLastError( ERROR_SEM_TIMEOUT
);
48 data
= server_data_ptr(req
);
49 event
->dwDebugEventCode
= data
->code
;
50 event
->dwProcessId
= (DWORD
)req
->pid
;
51 event
->dwThreadId
= (DWORD
)req
->tid
;
54 case EXCEPTION_DEBUG_EVENT
:
55 event
->u
.Exception
.ExceptionRecord
= data
->info
.exception
.record
;
56 event
->u
.Exception
.dwFirstChance
= data
->info
.exception
.first
;
58 case CREATE_THREAD_DEBUG_EVENT
:
59 event
->u
.CreateThread
.hThread
= data
->info
.create_thread
.handle
;
60 event
->u
.CreateThread
.lpThreadLocalBase
= data
->info
.create_thread
.teb
;
61 event
->u
.CreateThread
.lpStartAddress
= data
->info
.create_thread
.start
;
63 case CREATE_PROCESS_DEBUG_EVENT
:
64 event
->u
.CreateProcessInfo
.hFile
= data
->info
.create_process
.file
;
65 event
->u
.CreateProcessInfo
.hProcess
= data
->info
.create_process
.process
;
66 event
->u
.CreateProcessInfo
.hThread
= data
->info
.create_process
.thread
;
67 event
->u
.CreateProcessInfo
.lpBaseOfImage
= data
->info
.create_process
.base
;
68 event
->u
.CreateProcessInfo
.dwDebugInfoFileOffset
= data
->info
.create_process
.dbg_offset
;
69 event
->u
.CreateProcessInfo
.nDebugInfoSize
= data
->info
.create_process
.dbg_size
;
70 event
->u
.CreateProcessInfo
.lpThreadLocalBase
= data
->info
.create_process
.teb
;
71 event
->u
.CreateProcessInfo
.lpStartAddress
= data
->info
.create_process
.start
;
72 event
->u
.CreateProcessInfo
.lpImageName
= data
->info
.create_process
.name
;
73 event
->u
.CreateProcessInfo
.fUnicode
= data
->info
.create_process
.unicode
;
74 if (data
->info
.create_process
.file
== -1) event
->u
.CreateProcessInfo
.hFile
= 0;
76 case EXIT_THREAD_DEBUG_EVENT
:
77 event
->u
.ExitThread
.dwExitCode
= data
->info
.exit
.exit_code
;
79 case EXIT_PROCESS_DEBUG_EVENT
:
80 event
->u
.ExitProcess
.dwExitCode
= data
->info
.exit
.exit_code
;
82 case LOAD_DLL_DEBUG_EVENT
:
83 event
->u
.LoadDll
.hFile
= data
->info
.load_dll
.handle
;
84 event
->u
.LoadDll
.lpBaseOfDll
= data
->info
.load_dll
.base
;
85 event
->u
.LoadDll
.dwDebugInfoFileOffset
= data
->info
.load_dll
.dbg_offset
;
86 event
->u
.LoadDll
.nDebugInfoSize
= data
->info
.load_dll
.dbg_size
;
87 event
->u
.LoadDll
.lpImageName
= data
->info
.load_dll
.name
;
88 event
->u
.LoadDll
.fUnicode
= data
->info
.load_dll
.unicode
;
89 if (data
->info
.load_dll
.handle
== -1) event
->u
.LoadDll
.hFile
= 0;
91 case UNLOAD_DLL_DEBUG_EVENT
:
92 event
->u
.UnloadDll
.lpBaseOfDll
= data
->info
.unload_dll
.base
;
94 case OUTPUT_DEBUG_STRING_EVENT
:
95 event
->u
.DebugString
.lpDebugStringData
= data
->info
.output_string
.string
;
96 event
->u
.DebugString
.fUnicode
= data
->info
.output_string
.unicode
;
97 event
->u
.DebugString
.nDebugStringLength
= data
->info
.output_string
.length
;
100 event
->u
.RipInfo
.dwError
= data
->info
.rip_info
.error
;
101 event
->u
.RipInfo
.dwType
= data
->info
.rip_info
.type
;
104 server_protocol_error( "WaitForDebugEvent: bad code %d\n", data
->code
);
113 /**********************************************************************
114 * ContinueDebugEvent (KERNEL32.146)
115 * ContinueDebugEvent (WIN32S16.5)
117 * Enables a thread that previously produced a debug event to continue.
121 * True if the debugger is listed as the processes owner and the process
122 * and thread are valid.
124 BOOL WINAPI
ContinueDebugEvent(
125 DWORD pid
, /* The id of the process to continue. */
126 DWORD tid
, /* The id of the thread to continue. */
127 DWORD status
/* The rule to apply to unhandled exeptions. */)
132 struct continue_debug_event_request
*req
= server_alloc_req( sizeof(*req
), 0 );
133 req
->pid
= (void *)pid
;
134 req
->tid
= (void *)tid
;
135 req
->status
= status
;
136 ret
= !server_call( REQ_CONTINUE_DEBUG_EVENT
);
143 /**********************************************************************
144 * DebugActiveProcess (KERNEL32.180)
146 * Attempts to attach the dugger to a process.
150 * True if the debugger was attached to process.
152 BOOL WINAPI
DebugActiveProcess(
153 DWORD pid
/* The process to be debugged. */)
158 struct debug_process_request
*req
= server_alloc_req( sizeof(*req
), 0 );
159 req
->pid
= (void *)pid
;
160 ret
= !server_call( REQ_DEBUG_PROCESS
);
167 /***********************************************************************
168 * OutputDebugStringA (KERNEL.115)
169 * OutputDebugStringA (KERNEL32.548)
171 * Output by an application of a unicode string to a debugger (if attached)
174 void WINAPI
OutputDebugStringA(
175 LPCSTR str
/* The message to be logged and given to the debugger. */)
179 struct output_debug_string_request
*req
= server_alloc_req( sizeof(*req
), 0 );
180 req
->string
= (void *)str
;
182 req
->length
= strlen(str
) + 1;
183 server_call_noerr( REQ_OUTPUT_DEBUG_STRING
);
190 /***********************************************************************
191 * OutputDebugStringW (KERNEL32.549)
193 * Output by an appliccation of a unicode string to a debugger (if attached)
196 void WINAPI
OutputDebugStringW(
197 LPCWSTR str
/* The message to be logged and given to the debugger. */)
201 struct output_debug_string_request
*req
= server_alloc_req( sizeof(*req
), 0 );
202 req
->string
= (void *)str
;
204 req
->length
= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
205 server_call_noerr( REQ_OUTPUT_DEBUG_STRING
);
208 WARN("%s\n", debugstr_w(str
));
212 /***********************************************************************
213 * OutputDebugString16 (KERNEL.115)
215 * Output by a 16 bit application of an ascii string to a debugger (if attached)
218 void WINAPI
OutputDebugString16(
219 LPCSTR str
/* The message to be logged and given to the debugger.*/)
221 OutputDebugStringA( str
);
225 /***********************************************************************
226 * DebugBreak (KERNEL32.181)
228 * Raises an exception so that a debugger (if attached)
229 * can take some action.
231 void WINAPI
DebugBreak(void)
237 /***********************************************************************
238 * DebugBreak16 (KERNEL.203)
240 * Raises an expection in a 16 bit application so that a debugger (if attached)
241 * can take some action.
245 * Only 386 compatible processors implemented.
247 void WINAPI
DebugBreak16(
248 CONTEXT86
*context
/* A pointer to the 386 compatible processor state. */)
251 EXCEPTION_RECORD rec
;
253 rec
.ExceptionCode
= EXCEPTION_BREAKPOINT
;
254 rec
.ExceptionFlags
= 0;
255 rec
.ExceptionRecord
= NULL
;
256 rec
.ExceptionAddress
= (LPVOID
)context
->Eip
;
257 rec
.NumberParameters
= 0;
258 NtRaiseException( &rec
, context
, TRUE
);
259 #endif /* defined(__i386__) */
263 /***********************************************************************
264 * IsDebuggerPresent (KERNEL32.827)
266 * Allows a process to determine if there is a debugger attached.
270 * True if there is a debugger attached.
272 BOOL WINAPI
IsDebuggerPresent(void)
277 struct get_process_info_request
*req
= server_alloc_req( sizeof(*req
), 0 );
278 req
->handle
= GetCurrentProcess();
279 if (!server_call( REQ_GET_PROCESS_INFO
)) ret
= req
->debugged
;
286 /***********************************************************************
287 * _DebugOutput (KERNEL.328)
289 void WINAPIV
_DebugOutput( void )
296 /* Decode caller address */
297 if (!GetModuleName16( GetExePtr(CURRENT_STACK16
->cs
), caller
, sizeof(caller
) ))
298 sprintf( caller
, "%04X:%04X", CURRENT_STACK16
->cs
, CURRENT_STACK16
->ip
);
300 /* Build debug message string */
301 VA_START16( valist
);
302 flags
= VA_ARG16( valist
, WORD
);
303 spec
= VA_ARG16( valist
, SEGPTR
);
304 /* FIXME: cannot use wvsnprintf16 from kernel */
305 /* wvsnprintf16( temp, sizeof(temp), MapSL(spec), valist ); */
308 FIXME("%s %04x %s\n", caller
, flags
, debugstr_a(MapSL(spec
)) );