|  | /* | 
|  | * Win32 debugger functions | 
|  | * | 
|  | * Copyright (C) 1999 Alexandre Julliard | 
|  | */ | 
|  |  | 
|  | #include <string.h> | 
|  |  | 
|  | #include "winerror.h" | 
|  | #include "server.h" | 
|  | #include "debugtools.h" | 
|  |  | 
|  | DEFAULT_DEBUG_CHANNEL(debugstr); | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | *           WaitForDebugEvent   (KERNEL32.720) | 
|  | * | 
|  | * Waits for a debugging event to occur in a process being debugged | 
|  | * | 
|  | * PARAMS | 
|  | *    event   [I] Address of structure for event information | 
|  | *    timeout [I] Number of milliseconds to wait for event | 
|  | * | 
|  | * RETURNS STD | 
|  | */ | 
|  | BOOL WINAPI WaitForDebugEvent( LPDEBUG_EVENT event, DWORD timeout ) | 
|  | { | 
|  | struct wait_debug_event_request *req = get_req_buffer(); | 
|  |  | 
|  | req->timeout = timeout; | 
|  | if (server_call( REQ_WAIT_DEBUG_EVENT )) return FALSE; | 
|  | if ((req->event.code < 0) || (req->event.code > RIP_EVENT)) | 
|  | server_protocol_error( "WaitForDebugEvent: bad code %d\n", req->event.code ); | 
|  |  | 
|  | event->dwDebugEventCode = req->event.code; | 
|  | event->dwProcessId      = (DWORD)req->pid; | 
|  | event->dwThreadId       = (DWORD)req->tid; | 
|  | switch(req->event.code) | 
|  | { | 
|  | case 0:  /* timeout */ | 
|  | SetLastError( ERROR_SEM_TIMEOUT ); | 
|  | return FALSE; | 
|  | case EXCEPTION_DEBUG_EVENT: | 
|  | event->u.Exception.ExceptionRecord = req->event.info.exception.record; | 
|  | event->u.Exception.dwFirstChance   = req->event.info.exception.first; | 
|  | break; | 
|  | case CREATE_THREAD_DEBUG_EVENT: | 
|  | event->u.CreateThread.hThread           = req->event.info.create_thread.handle; | 
|  | event->u.CreateThread.lpThreadLocalBase = req->event.info.create_thread.teb; | 
|  | event->u.CreateThread.lpStartAddress    = req->event.info.create_thread.start; | 
|  | break; | 
|  | case CREATE_PROCESS_DEBUG_EVENT: | 
|  | event->u.CreateProcessInfo.hFile                 = req->event.info.create_process.file; | 
|  | event->u.CreateProcessInfo.hProcess              = req->event.info.create_process.process; | 
|  | event->u.CreateProcessInfo.hThread               = req->event.info.create_process.thread; | 
|  | event->u.CreateProcessInfo.lpBaseOfImage         = req->event.info.create_process.base; | 
|  | event->u.CreateProcessInfo.dwDebugInfoFileOffset = req->event.info.create_process.dbg_offset; | 
|  | event->u.CreateProcessInfo.nDebugInfoSize        = req->event.info.create_process.dbg_size; | 
|  | event->u.CreateProcessInfo.lpThreadLocalBase     = req->event.info.create_process.teb; | 
|  | event->u.CreateProcessInfo.lpStartAddress        = req->event.info.create_process.start; | 
|  | event->u.CreateProcessInfo.lpImageName           = req->event.info.create_process.name; | 
|  | event->u.CreateProcessInfo.fUnicode              = req->event.info.create_process.unicode; | 
|  | if (req->event.info.create_process.file == -1) event->u.CreateProcessInfo.hFile = 0; | 
|  | break; | 
|  | case EXIT_THREAD_DEBUG_EVENT: | 
|  | event->u.ExitThread.dwExitCode = req->event.info.exit.exit_code; | 
|  | break; | 
|  | case EXIT_PROCESS_DEBUG_EVENT: | 
|  | event->u.ExitProcess.dwExitCode = req->event.info.exit.exit_code; | 
|  | break; | 
|  | case LOAD_DLL_DEBUG_EVENT: | 
|  | event->u.LoadDll.hFile                 = req->event.info.load_dll.handle; | 
|  | event->u.LoadDll.lpBaseOfDll           = req->event.info.load_dll.base; | 
|  | event->u.LoadDll.dwDebugInfoFileOffset = req->event.info.load_dll.dbg_offset; | 
|  | event->u.LoadDll.nDebugInfoSize        = req->event.info.load_dll.dbg_size; | 
|  | event->u.LoadDll.lpImageName           = req->event.info.load_dll.name; | 
|  | event->u.LoadDll.fUnicode              = req->event.info.load_dll.unicode; | 
|  | if (req->event.info.load_dll.handle == -1) event->u.LoadDll.hFile = 0; | 
|  | break; | 
|  | case UNLOAD_DLL_DEBUG_EVENT: | 
|  | event->u.UnloadDll.lpBaseOfDll = req->event.info.unload_dll.base; | 
|  | break; | 
|  | case OUTPUT_DEBUG_STRING_EVENT: | 
|  | event->u.DebugString.lpDebugStringData  = req->event.info.output_string.string; | 
|  | event->u.DebugString.fUnicode           = req->event.info.output_string.unicode; | 
|  | event->u.DebugString.nDebugStringLength = req->event.info.output_string.length; | 
|  | break; | 
|  | case RIP_EVENT: | 
|  | event->u.RipInfo.dwError = req->event.info.rip_info.error; | 
|  | event->u.RipInfo.dwType  = req->event.info.rip_info.type; | 
|  | break; | 
|  | } | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /********************************************************************** | 
|  | *           ContinueDebugEvent   (KERNEL32.146) | 
|  | */ | 
|  | BOOL WINAPI ContinueDebugEvent( DWORD pid, DWORD tid, DWORD status ) | 
|  | { | 
|  | struct continue_debug_event_request *req = get_req_buffer(); | 
|  | req->pid    = (void *)pid; | 
|  | req->tid    = (void *)tid; | 
|  | req->status = status; | 
|  | return !server_call( REQ_CONTINUE_DEBUG_EVENT ); | 
|  | } | 
|  |  | 
|  |  | 
|  | /********************************************************************** | 
|  | *           DebugActiveProcess   (KERNEL32.180) | 
|  | */ | 
|  | BOOL WINAPI DebugActiveProcess( DWORD pid ) | 
|  | { | 
|  | struct debug_process_request *req = get_req_buffer(); | 
|  | req->pid = (void *)pid; | 
|  | return !server_call( REQ_DEBUG_PROCESS ); | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           OutputDebugStringA   (KERNEL32.548) | 
|  | */ | 
|  | void WINAPI OutputDebugStringA( LPCSTR str ) | 
|  | { | 
|  | struct output_debug_string_request *req = get_req_buffer(); | 
|  | req->string  = (void *)str; | 
|  | req->unicode = 0; | 
|  | req->length  = strlen(str) + 1; | 
|  | server_call_noerr( REQ_OUTPUT_DEBUG_STRING ); | 
|  | WARN("%s\n", str); | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           OutputDebugStringW   (KERNEL32.549) | 
|  | */ | 
|  | void WINAPI OutputDebugStringW( LPCWSTR str ) | 
|  | { | 
|  | struct output_debug_string_request *req = get_req_buffer(); | 
|  | req->string  = (void *)str; | 
|  | req->unicode = 1; | 
|  | req->length  = (lstrlenW(str) + 1) * sizeof(WCHAR); | 
|  | server_call_noerr( REQ_OUTPUT_DEBUG_STRING ); | 
|  | WARN("%s\n", debugstr_w(str)); | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           OutputDebugString16   (KERNEL.115) | 
|  | */ | 
|  | void WINAPI OutputDebugString16( LPCSTR str ) | 
|  | { | 
|  | OutputDebugStringA( str ); | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           DebugBreak   (KERNEL32.181) | 
|  | */ | 
|  | void WINAPI DebugBreak(void) | 
|  | { | 
|  | DbgBreakPoint(); | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           DebugBreak16   (KERNEL.203) | 
|  | */ | 
|  | void WINAPI DebugBreak16( CONTEXT86 *context ) | 
|  | { | 
|  | #ifdef __i386__ | 
|  | EXCEPTION_RECORD rec; | 
|  |  | 
|  | rec.ExceptionCode    = EXCEPTION_BREAKPOINT; | 
|  | rec.ExceptionFlags   = 0; | 
|  | rec.ExceptionRecord  = NULL; | 
|  | rec.ExceptionAddress = GET_IP(context); | 
|  | rec.NumberParameters = 0; | 
|  | NtRaiseException( &rec, context, TRUE ); | 
|  | #endif  /* defined(__i386__) */ | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           IsDebuggerPresent   (KERNEL32) | 
|  | */ | 
|  | BOOL WINAPI IsDebuggerPresent(void) | 
|  | { | 
|  | BOOL ret = FALSE; | 
|  | struct get_process_info_request *req = get_req_buffer(); | 
|  | req->handle = GetCurrentProcess(); | 
|  | if (!server_call( REQ_GET_PROCESS_INFO )) ret = req->debugged; | 
|  | return ret; | 
|  | } |