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)
116 * Enables a thread that previously produced a debug event to continue.
120 * True if the debugger is listed as the processes owner and the process
121 * and thread are valid.
123 BOOL WINAPI
ContinueDebugEvent(
124 DWORD pid
, /* The id of the process to continue. */
125 DWORD tid
, /* The id of the thread to continue. */
126 DWORD status
/* The rule to apply to unhandled exeptions. */)
131 struct continue_debug_event_request
*req
= server_alloc_req( sizeof(*req
), 0 );
132 req
->pid
= (void *)pid
;
133 req
->tid
= (void *)tid
;
134 req
->status
= status
;
135 ret
= !server_call( REQ_CONTINUE_DEBUG_EVENT
);
142 /**********************************************************************
143 * DebugActiveProcess (KERNEL32.180)
145 * Attempts to attach the dugger to a process.
149 * True if the debugger was attached to process.
151 BOOL WINAPI
DebugActiveProcess(
152 DWORD pid
/* The process to be debugged. */)
157 struct debug_process_request
*req
= server_alloc_req( sizeof(*req
), 0 );
158 req
->pid
= (void *)pid
;
159 ret
= !server_call( REQ_DEBUG_PROCESS
);
166 /***********************************************************************
167 * OutputDebugStringA (KERNEL32.548)
169 * Output by an application of a unicode string to a debugger (if attached)
172 void WINAPI
OutputDebugStringA(
173 LPCSTR str
/* The message to be logged and given to the debugger. */)
177 struct output_debug_string_request
*req
= server_alloc_req( sizeof(*req
), 0 );
178 req
->string
= (void *)str
;
180 req
->length
= strlen(str
) + 1;
181 server_call_noerr( REQ_OUTPUT_DEBUG_STRING
);
188 /***********************************************************************
189 * OutputDebugStringW (KERNEL32.549)
191 * Output by an appliccation of a unicode string to a debugger (if attached)
194 void WINAPI
OutputDebugStringW(
195 LPCWSTR str
/* The message to be logged and given to the debugger. */)
199 struct output_debug_string_request
*req
= server_alloc_req( sizeof(*req
), 0 );
200 req
->string
= (void *)str
;
202 req
->length
= (lstrlenW(str
) + 1) * sizeof(WCHAR
);
203 server_call_noerr( REQ_OUTPUT_DEBUG_STRING
);
206 WARN("%s\n", debugstr_w(str
));
210 /***********************************************************************
211 * OutputDebugString16 (KERNEL.115)
213 * Output by a 16 bit application of an ascii string to a debugger (if attached)
216 void WINAPI
OutputDebugString16(
217 LPCSTR str
/* The message to be logged and given to the debugger.*/)
219 OutputDebugStringA( str
);
223 /***********************************************************************
224 * DebugBreak (KERNEL32.181)
226 * Raises an exception so that a debugger (if attached)
227 * can take some action.
229 void WINAPI
DebugBreak(void)
235 /***********************************************************************
236 * DebugBreak16 (KERNEL.203)
238 * Raises an expection in a 16 bit application so that a debugger (if attached)
239 * can take some action.
243 * Only 386 compatible processors implemented.
245 void WINAPI
DebugBreak16(
246 CONTEXT86
*context
/* A pointer to the 386 compatible processor state. */)
249 EXCEPTION_RECORD rec
;
251 rec
.ExceptionCode
= EXCEPTION_BREAKPOINT
;
252 rec
.ExceptionFlags
= 0;
253 rec
.ExceptionRecord
= NULL
;
254 rec
.ExceptionAddress
= (LPVOID
)context
->Eip
;
255 rec
.NumberParameters
= 0;
256 NtRaiseException( &rec
, context
, TRUE
);
257 #endif /* defined(__i386__) */
261 /***********************************************************************
262 * IsDebuggerPresent (KERNEL32)
264 * Allows a process to determine if there is a debugger attached.
268 * True if there is a debugger attached.
270 BOOL WINAPI
IsDebuggerPresent(void)
275 struct get_process_info_request
*req
= server_alloc_req( sizeof(*req
), 0 );
276 req
->handle
= GetCurrentProcess();
277 if (!server_call( REQ_GET_PROCESS_INFO
)) ret
= req
->debugged
;
284 /***********************************************************************
285 * _DebugOutput (KERNEL.328)
287 void WINAPIV
_DebugOutput( void )
294 /* Decode caller address */
295 if (!GetModuleName16( GetExePtr(CURRENT_STACK16
->cs
), caller
, sizeof(caller
) ))
296 sprintf( caller
, "%04X:%04X", CURRENT_STACK16
->cs
, CURRENT_STACK16
->ip
);
298 /* Build debug message string */
299 VA_START16( valist
);
300 flags
= VA_ARG16( valist
, WORD
);
301 spec
= VA_ARG16( valist
, SEGPTR
);
302 /* FIXME: cannot use wvsnprintf16 from kernel */
303 /* wvsnprintf16( temp, sizeof(temp), MapSL(spec), valist ); */
306 FIXME("%s %04x %s\n", caller
, flags
, debugstr_a(MapSL(spec
)) );