From 4cc1b339cfa4ce33f6d6154ee31fdf637162f7cf Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sun, 23 May 1999 19:57:42 +0000 Subject: [PATCH] Implemented the Win32 debug API functions. --- include/winbase.h | 2 + misc/lstr.c | 35 ----- scheduler/Makefile.in | 1 + scheduler/client.c | 2 +- scheduler/debugger.c | 300 ++++++++++++++++++++++++++++++++++++++++++ win32/newfns.c | 18 --- win32/process.c | 8 -- 7 files changed, 304 insertions(+), 62 deletions(-) create mode 100644 scheduler/debugger.c diff --git a/include/winbase.h b/include/winbase.h index ed29e1de4b2..2579ad7d76a 100644 --- a/include/winbase.h +++ b/include/winbase.h @@ -1188,6 +1188,7 @@ BOOL WINAPI AllocConsole(void); BOOL WINAPI AreFileApisANSI(void); BOOL WINAPI Beep(DWORD,DWORD); BOOL WINAPI CloseHandle(HANDLE); +BOOL WINAPI ContinueDebugEvent(DWORD,DWORD,DWORD); HANDLE WINAPI ConvertToGlobalHandle(HANDLE hSrc); BOOL WINAPI CopyFileA(LPCSTR,LPCSTR,BOOL); BOOL WINAPI CopyFileW(LPCWSTR,LPCWSTR,BOOL); @@ -1224,6 +1225,7 @@ HANDLE WINAPI CreateSemaphoreA(LPSECURITY_ATTRIBUTES,LONG,LONG,LPCSTR); HANDLE WINAPI CreateSemaphoreW(LPSECURITY_ATTRIBUTES,LONG,LONG,LPCWSTR); #define CreateSemaphore WINELIB_NAME_AW(CreateSemaphore) HANDLE WINAPI CreateThread(LPSECURITY_ATTRIBUTES,DWORD,LPTHREAD_START_ROUTINE,LPVOID,DWORD,LPDWORD); +BOOL WINAPI DebugActiveProcess(DWORD); BOOL WINAPI DisableThreadLibraryCalls(HMODULE); BOOL WINAPI DosDateTimeToFileTime(WORD,WORD,LPFILETIME); BOOL WINAPI DuplicateHandle(HANDLE,HANDLE,HANDLE,HANDLE*,DWORD,BOOL,DWORD); diff --git a/misc/lstr.c b/misc/lstr.c index 7f2e674a722..9e9a1cc202c 100644 --- a/misc/lstr.c +++ b/misc/lstr.c @@ -172,41 +172,6 @@ SEGPTR WINAPI AnsiPrev16( SEGPTR start, SEGPTR current ) } -/*********************************************************************** - * OutputDebugString16 (KERNEL.115) - */ -void WINAPI OutputDebugString16( LPCSTR str ) -{ - char module[10]; - if (!GetModuleName16( GetCurrentTask(), module, sizeof(module) )) - strcpy( module, "???" ); - - DUMP( "%s says %s\n", module, debugstr_a(str) ); -} - - -/*********************************************************************** - * OutputDebugString32A (KERNEL32 - */ -void WINAPI OutputDebugStringA( LPCSTR str ) -{ - OutputDebugString16( str ); -} - - - -/*********************************************************************** - * OutputDebugString32W (KERNEL32 - */ -void WINAPI OutputDebugStringW( LPCWSTR str ) -{ - LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str ); - OutputDebugStringA( p ); - HeapFree( GetProcessHeap(), 0, p ); -} - - - /*********************************************************************** * CharNext32A (USER32.29) */ diff --git a/scheduler/Makefile.in b/scheduler/Makefile.in index a68fcabf518..528244465d4 100644 --- a/scheduler/Makefile.in +++ b/scheduler/Makefile.in @@ -8,6 +8,7 @@ MODULE = scheduler C_SRCS = \ client.c \ critsection.c \ + debugger.c \ event.c \ handle.c \ mutex.c \ diff --git a/scheduler/client.c b/scheduler/client.c index dce8f779fb8..411427f5354 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -41,7 +41,7 @@ static void CLIENT_Die( THDB *thdb ) /*********************************************************************** * CLIENT_ProtocolError */ -static void CLIENT_ProtocolError( const char *err, ... ) +void CLIENT_ProtocolError( const char *err, ... ) { THDB *thdb = THREAD_Current(); va_list args; diff --git a/scheduler/debugger.c b/scheduler/debugger.c new file mode 100644 index 00000000000..63326476098 --- /dev/null +++ b/scheduler/debugger.c @@ -0,0 +1,300 @@ +/* + * Win32 debugger functions + * + * Copyright (C) 1999 Alexandre Julliard + */ + +#include "process.h" +#include "thread.h" +#include "server/request.h" +#include "server.h" +#include "debugtools.h" + + +/********************************************************************** + * DEBUG_SendEvent + * + * Internal helper to send a debug event request to the server. + */ +static DWORD DEBUG_SendEvent( int code, void *data, int size ) +{ + struct send_debug_event_request req; + struct send_debug_event_reply reply; + + req.code = code; + CLIENT_SendRequest( REQ_SEND_DEBUG_EVENT, -1, 2, &req, sizeof(req), data, size ); + if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return 0; + return reply.status; +} + + +/********************************************************************** + * DEBUG_SendExceptionEvent + * + * Send an EXCEPTION_DEBUG_EVENT event to the current process debugger. + */ +DWORD DEBUG_SendExceptionEvent( EXCEPTION_RECORD *rec, BOOL first_chance ) +{ + struct debug_event_exception event; + int i; + + event.code = rec->ExceptionCode; + event.flags = rec->ExceptionFlags; + event.record = rec->ExceptionRecord; + event.addr = rec->ExceptionAddress; + event.nb_params = rec->NumberParameters; + for (i = 0; i < event.nb_params; i++) event.params[i] = rec->ExceptionInformation[i]; + event.first_chance = first_chance; + return DEBUG_SendEvent( EXCEPTION_DEBUG_EVENT, &event, sizeof(event) ); +} + + +/********************************************************************** + * DEBUG_SendCreateProcessEvent + * + * Send an CREATE_PROCESS_DEBUG_EVENT event to the current process debugger. + * Must be called from the context of the new process. + */ +DWORD DEBUG_SendCreateProcessEvent( HFILE file, HMODULE module, void *entry ) +{ + struct debug_event_create_process event; + + event.file = file; + event.process = 0; /* will be filled by server */ + event.thread = 0; /* will be filled by server */ + event.base = (void *)module; + event.dbg_offset = 0; /* FIXME */ + event.dbg_size = 0; /* FIXME */ + event.teb = NtCurrentTeb(); + event.start = entry; + event.name = 0; /* FIXME */ + event.unicode = 0; /* FIXME */ + return DEBUG_SendEvent( CREATE_PROCESS_DEBUG_EVENT, &event, sizeof(event) ); +} + + +/********************************************************************** + * DEBUG_SendCreateThreadEvent + * + * Send an CREATE_THREAD_DEBUG_EVENT event to the current process debugger. + * Must be called from the context of the new thread. + */ +DWORD DEBUG_SendCreateThreadEvent( void *entry ) +{ + struct debug_event_create_thread event; + + event.handle = 0; /* will be filled by server */ + event.teb = NtCurrentTeb(); + event.start = entry; + return DEBUG_SendEvent( CREATE_THREAD_DEBUG_EVENT, &event, sizeof(event) ); +} + + +/********************************************************************** + * DEBUG_SendLoadDLLEvent + * + * Send an LOAD_DLL_DEBUG_EVENT event to the current process debugger. + */ +DWORD DEBUG_SendLoadDLLEvent( HFILE file, HMODULE module, LPSTR name ) +{ + struct debug_event_load_dll event; + + event.handle = file; + event.base = (void *)module; + event.dbg_offset = 0; /* FIXME */ + event.dbg_size = 0; /* FIXME */ + event.name = name; + event.unicode = 0; + return DEBUG_SendEvent( LOAD_DLL_DEBUG_EVENT, &event, sizeof(event) ); +} + + +/********************************************************************** + * DEBUG_SendUnloadDLLEvent + * + * Send an UNLOAD_DLL_DEBUG_EVENT event to the current process debugger. + */ +DWORD DEBUG_SendUnloadDLLEvent( HMODULE module ) +{ + struct debug_event_unload_dll event; + + event.base = (void *)module; + return DEBUG_SendEvent( UNLOAD_DLL_DEBUG_EVENT, &event, sizeof(event) ); +} + + +/****************************************************************************** + * 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 ) +{ + /* size of the event data */ + static const int event_sizes[] = + { + 0, + sizeof(struct debug_event_exception), /* EXCEPTION_DEBUG_EVENT */ + sizeof(struct debug_event_create_thread), /* CREATE_THREAD_DEBUG_EVENT */ + sizeof(struct debug_event_create_process), /* CREATE_PROCESS_DEBUG_EVENT */ + sizeof(struct debug_event_exit), /* EXIT_THREAD_DEBUG_EVENT */ + sizeof(struct debug_event_exit), /* EXIT_PROCESS_DEBUG_EVENT */ + sizeof(struct debug_event_load_dll), /* LOAD_DLL_DEBUG_EVENT */ + sizeof(struct debug_event_unload_dll), /* UNLOAD_DLL_DEBUG_EVENT */ + sizeof(struct debug_event_output_string), /* OUTPUT_DEBUG_STRING_EVENT */ + sizeof(struct debug_event_rip_info) /* RIP_EVENT */ + }; + + struct wait_debug_event_request req; + struct wait_debug_event_reply reply; + union debug_event_data data; + int i, len; + + req.timeout = timeout; + CLIENT_SendRequest( REQ_WAIT_DEBUG_EVENT, -1, 1, &req, sizeof(req) ); + if (CLIENT_WaitReply( &len, NULL, 2, &reply, sizeof(reply), + &data, sizeof(data) )) return FALSE; + if ((reply.code < 0) || (reply.code > RIP_EVENT)) + CLIENT_ProtocolError( "WaitForDebugEvent: bad code %d\n", reply.code ); + if (len != sizeof(reply) + event_sizes[reply.code]) + CLIENT_ProtocolError( "WaitForDebugEvent: bad len %d for code %d\n", len, reply.code ); + + event->dwDebugEventCode = reply.code; + event->dwProcessId = (DWORD)reply.pid; + event->dwThreadId = (DWORD)reply.tid; + switch(reply.code) + { + case EXCEPTION_DEBUG_EVENT: + event->u.Exception.ExceptionRecord.ExceptionCode = data.exception.code; + event->u.Exception.ExceptionRecord.ExceptionFlags = data.exception.flags; + event->u.Exception.ExceptionRecord.ExceptionRecord = data.exception.record; + event->u.Exception.ExceptionRecord.ExceptionAddress = data.exception.addr; + event->u.Exception.ExceptionRecord.NumberParameters = data.exception.nb_params; + for (i = 0; i < data.exception.nb_params; i++) + event->u.Exception.ExceptionRecord.ExceptionInformation[i] = data.exception.params[i]; + event->u.Exception.dwFirstChance = data.exception.first_chance; + break; + case CREATE_THREAD_DEBUG_EVENT: + event->u.CreateThread.hThread = data.create_thread.handle; + event->u.CreateThread.lpThreadLocalBase = data.create_thread.teb; + event->u.CreateThread.lpStartAddress = data.create_thread.start; + break; + case CREATE_PROCESS_DEBUG_EVENT: + event->u.CreateProcessInfo.hFile = data.create_process.file; + event->u.CreateProcessInfo.hProcess = data.create_process.process; + event->u.CreateProcessInfo.hThread = data.create_process.thread; + event->u.CreateProcessInfo.lpBaseOfImage = data.create_process.base; + event->u.CreateProcessInfo.dwDebugInfoFileOffset = data.create_process.dbg_offset; + event->u.CreateProcessInfo.nDebugInfoSize = data.create_process.dbg_size; + event->u.CreateProcessInfo.lpThreadLocalBase = data.create_process.teb; + event->u.CreateProcessInfo.lpStartAddress = data.create_process.start; + event->u.CreateProcessInfo.lpImageName = data.create_process.name; + event->u.CreateProcessInfo.fUnicode = data.create_process.unicode; + if (data.create_process.file == -1) event->u.CreateProcessInfo.hFile = 0; + break; + case EXIT_THREAD_DEBUG_EVENT: + event->u.ExitThread.dwExitCode = data.exit.exit_code; + break; + case EXIT_PROCESS_DEBUG_EVENT: + event->u.ExitProcess.dwExitCode = data.exit.exit_code; + break; + case LOAD_DLL_DEBUG_EVENT: + event->u.LoadDll.hFile = data.load_dll.handle; + event->u.LoadDll.lpBaseOfDll = data.load_dll.base; + event->u.LoadDll.dwDebugInfoFileOffset = data.load_dll.dbg_offset; + event->u.LoadDll.nDebugInfoSize = data.load_dll.dbg_size; + event->u.LoadDll.lpImageName = data.load_dll.name; + event->u.LoadDll.fUnicode = data.load_dll.unicode; + if (data.load_dll.handle == -1) event->u.LoadDll.hFile = 0; + break; + case UNLOAD_DLL_DEBUG_EVENT: + event->u.UnloadDll.lpBaseOfDll = data.unload_dll.base; + break; + case OUTPUT_DEBUG_STRING_EVENT: + event->u.DebugString.lpDebugStringData = data.output_string.string; + event->u.DebugString.fUnicode = data.output_string.unicode; + event->u.DebugString.nDebugStringLength = data.output_string.length; + break; + case RIP_EVENT: + event->u.RipInfo.dwError = data.rip_info.error; + event->u.RipInfo.dwType = data.rip_info.type; + break; + } + return TRUE; +} + + +/********************************************************************** + * ContinueDebugEvent (KERNEL32.146) + */ +BOOL WINAPI ContinueDebugEvent( DWORD pid, DWORD tid, DWORD status ) +{ + struct continue_debug_event_request req; + + req.pid = (void *)pid; + req.tid = (void *)tid; + req.status = status; + CLIENT_SendRequest( REQ_CONTINUE_DEBUG_EVENT, -1, 1, &req, sizeof(req) ); + return !CLIENT_WaitReply( NULL, NULL, 0 ); +} + + +/********************************************************************** + * DebugActiveProcess (KERNEL32.180) + */ +BOOL WINAPI DebugActiveProcess( DWORD pid ) +{ + struct debug_process_request req; + req.pid = (void *)pid; + CLIENT_SendRequest( REQ_DEBUG_PROCESS, -1, 1, &req, sizeof(req) ); + return !CLIENT_WaitReply( NULL, NULL, 0 ); +} + + +/*********************************************************************** + * OutputDebugStringA (KERNEL32.548) + */ +void WINAPI OutputDebugStringA( LPCSTR str ) +{ + if (PROCESS_Current()->flags & PDB32_DEBUGGED) + { + struct debug_event_output_string event; + event.string = (void *)str; + event.unicode = 0; + event.length = strlen(str) + 1; + DEBUG_SendEvent( OUTPUT_DEBUG_STRING_EVENT, &event, sizeof(event) ); + } + else DPRINTF("OutputDebugStringA: %s\n", debugstr_a(str) ); +} + + +/*********************************************************************** + * OutputDebugStringW (KERNEL32.549) + */ +void WINAPI OutputDebugStringW( LPCWSTR str ) +{ + if (PROCESS_Current()->flags & PDB32_DEBUGGED) + { + struct debug_event_output_string event; + event.string = (void *)str; + event.unicode = 1; + event.length = (lstrlenW(str) + 1) * sizeof(WCHAR); + DEBUG_SendEvent( OUTPUT_DEBUG_STRING_EVENT, &event, sizeof(event) ); + } + else DPRINTF("OutputDebugStringW: %s\n", debugstr_w(str) ); +} + + +/*********************************************************************** + * OutputDebugString16 (KERNEL.115) + */ +void WINAPI OutputDebugString16( LPCSTR str ) +{ + OutputDebugStringA( str ); +} diff --git a/win32/newfns.c b/win32/newfns.c index dc87993a932..63da291e8b1 100644 --- a/win32/newfns.c +++ b/win32/newfns.c @@ -264,24 +264,6 @@ VOID WINAPI SetDebugErrorLevel( DWORD dwLevel ) } -/****************************************************************************** - * WaitForDebugEvent [KERNEL32.720] - * Waits for a debugging event to occur in a process being debugged - * - * PARAMS - * lpDebugEvent [I] Address of structure for event information - * dwMilliseconds [I] Number of milliseconds to wait for event - * - * RETURNS STD - */ -BOOL WINAPI WaitForDebugEvent( LPDEBUG_EVENT lpDebugEvent, - DWORD dwMilliseconds ) -{ - FIXME_(win32)("(%p,%ld): stub\n", lpDebugEvent, dwMilliseconds); - return FALSE; -} - - /****************************************************************************** * SetComputerName32A [KERNEL32.621] */ diff --git a/win32/process.c b/win32/process.c index e64a468664a..1036a89a044 100644 --- a/win32/process.c +++ b/win32/process.c @@ -21,14 +21,6 @@ DEFAULT_DEBUG_CHANNEL(win32) -/********************************************************************** - * ContinueDebugEvent [KERNEL32.146] - */ -BOOL WINAPI ContinueDebugEvent(DWORD pid,DWORD tid,DWORD contstatus) { - FIXME("(0x%lx,%ld,%ld): stub\n",pid,tid,contstatus); - return TRUE; -} - /********************************************************************* * Process_ClockTimeToFileTime * (olorin@fandra.org, 20-Sep-1998)