Commit d848a25b authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Implement DbgUiConvertStateChangeStructure().

parent c8f5cced
......@@ -36,7 +36,7 @@
# @ stub DbgSetDebugFilterState
@ stdcall DbgUiConnectToDbg()
@ stdcall DbgUiContinue(ptr long)
@ stub DbgUiConvertStateChangeStructure
@ stdcall DbgUiConvertStateChangeStructure(ptr ptr)
@ stdcall DbgUiDebugActiveProcess(long)
@ stdcall DbgUiGetThreadDebugObject()
@ stdcall DbgUiIssueRemoteBreakin(long)
......
......@@ -178,6 +178,115 @@ NTSTATUS WINAPI DbgUiContinue( CLIENT_ID *client, NTSTATUS status )
return NtDebugContinue( DbgUiGetThreadDebugObject(), client, status );
}
/* helper for DbgUiConvertStateChangeStructure */
static inline void *get_thread_teb( HANDLE thread )
{
THREAD_BASIC_INFORMATION info;
if (NtQueryInformationThread( thread, ThreadBasicInformation, &info, sizeof(info), NULL )) return NULL;
return info.TebBaseAddress;
}
/***********************************************************************
* DbgUiConvertStateChangeStructure (NTDLL.@)
*/
NTSTATUS WINAPI DbgUiConvertStateChangeStructure( DBGUI_WAIT_STATE_CHANGE *state, DEBUG_EVENT *event )
{
event->dwProcessId = HandleToULong( state->AppClientId.UniqueProcess );
event->dwThreadId = HandleToULong( state->AppClientId.UniqueThread );
switch (state->NewState)
{
case DbgCreateThreadStateChange:
{
DBGUI_CREATE_THREAD *info = &state->StateInfo.CreateThread;
event->dwDebugEventCode = CREATE_THREAD_DEBUG_EVENT;
event->u.CreateThread.hThread = info->HandleToThread;
event->u.CreateThread.lpThreadLocalBase = get_thread_teb( info->HandleToThread );
event->u.CreateThread.lpStartAddress = info->NewThread.StartAddress;
break;
}
case DbgCreateProcessStateChange:
{
DBGUI_CREATE_PROCESS *info = &state->StateInfo.CreateProcessInfo;
event->dwDebugEventCode = CREATE_PROCESS_DEBUG_EVENT;
event->u.CreateProcessInfo.hFile = info->NewProcess.FileHandle;
event->u.CreateProcessInfo.hProcess = info->HandleToProcess;
event->u.CreateProcessInfo.hThread = info->HandleToThread;
event->u.CreateProcessInfo.lpBaseOfImage = info->NewProcess.BaseOfImage;
event->u.CreateProcessInfo.dwDebugInfoFileOffset = info->NewProcess.DebugInfoFileOffset;
event->u.CreateProcessInfo.nDebugInfoSize = info->NewProcess.DebugInfoSize;
event->u.CreateProcessInfo.lpThreadLocalBase = get_thread_teb( info->HandleToThread );
event->u.CreateProcessInfo.lpStartAddress = info->NewProcess.InitialThread.StartAddress;
event->u.CreateProcessInfo.lpImageName = NULL;
event->u.CreateProcessInfo.fUnicode = TRUE;
break;
}
case DbgExitThreadStateChange:
{
DBGKM_EXIT_THREAD *info = &state->StateInfo.ExitThread;
event->dwDebugEventCode = EXIT_THREAD_DEBUG_EVENT;
event->u.ExitThread.dwExitCode = info->ExitStatus;
break;
}
case DbgExitProcessStateChange:
{
DBGKM_EXIT_PROCESS *info = &state->StateInfo.ExitProcess;
event->dwDebugEventCode = EXIT_PROCESS_DEBUG_EVENT;
event->u.ExitProcess.dwExitCode = info->ExitStatus;
break;
}
case DbgExceptionStateChange:
case DbgBreakpointStateChange:
case DbgSingleStepStateChange:
{
DBGKM_EXCEPTION *info = &state->StateInfo.Exception;
DWORD code = info->ExceptionRecord.ExceptionCode;
if (code == DBG_PRINTEXCEPTION_C && info->ExceptionRecord.NumberParameters >= 2)
{
event->dwDebugEventCode = OUTPUT_DEBUG_STRING_EVENT;
event->u.DebugString.lpDebugStringData = (void *)info->ExceptionRecord.ExceptionInformation[1];
event->u.DebugString.fUnicode = FALSE;
event->u.DebugString.nDebugStringLength = info->ExceptionRecord.ExceptionInformation[0];
}
else if (code == DBG_RIPEXCEPTION && info->ExceptionRecord.NumberParameters >= 2)
{
event->dwDebugEventCode = RIP_EVENT;
event->u.RipInfo.dwError = info->ExceptionRecord.ExceptionInformation[0];
event->u.RipInfo.dwType = info->ExceptionRecord.ExceptionInformation[1];
}
else
{
event->dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
event->u.Exception.ExceptionRecord = info->ExceptionRecord;
event->u.Exception.dwFirstChance = info->FirstChance;
}
break;
}
case DbgLoadDllStateChange:
{
DBGKM_LOAD_DLL *info = &state->StateInfo.LoadDll;
event->dwDebugEventCode = LOAD_DLL_DEBUG_EVENT;
event->u.LoadDll.hFile = info->FileHandle;
event->u.LoadDll.lpBaseOfDll = info->BaseOfDll;
event->u.LoadDll.dwDebugInfoFileOffset = info->DebugInfoFileOffset;
event->u.LoadDll.nDebugInfoSize = info->DebugInfoSize;
event->u.LoadDll.lpImageName = info->NamePointer;
event->u.LoadDll.fUnicode = TRUE;
break;
}
case DbgUnloadDllStateChange:
{
DBGKM_UNLOAD_DLL *info = &state->StateInfo.UnloadDll;
event->dwDebugEventCode = UNLOAD_DLL_DEBUG_EVENT;
event->u.UnloadDll.lpBaseOfDll = info->BaseAddress;
break;
}
default:
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}
/***********************************************************************
* DbgUiRemoteBreakin (NTDLL.@)
*/
......
......@@ -45,6 +45,7 @@ static NTSTATUS (WINAPI * pNtOpenThread)(HANDLE *, ACCESS_MASK, const OBJECT_ATT
static NTSTATUS (WINAPI * pNtQueryObject)(HANDLE, OBJECT_INFORMATION_CLASS, void *, ULONG, ULONG *);
static NTSTATUS (WINAPI * pNtCreateDebugObject)( HANDLE *, ACCESS_MASK, OBJECT_ATTRIBUTES *, ULONG );
static NTSTATUS (WINAPI * pNtSetInformationDebugObject)(HANDLE,DEBUGOBJECTINFOCLASS,PVOID,ULONG,ULONG*);
static NTSTATUS (WINAPI * pDbgUiConvertStateChangeStructure)(DBGUI_WAIT_STATE_CHANGE*,DEBUG_EVENT*);
static BOOL is_wow64;
......@@ -96,6 +97,7 @@ static BOOL InitFunctionPtrs(void)
NTDLL_GET_PROC(NtQueryObject);
NTDLL_GET_PROC(NtCreateDebugObject);
NTDLL_GET_PROC(NtSetInformationDebugObject);
NTDLL_GET_PROC(DbgUiConvertStateChangeStructure);
/* not present before XP */
pNtGetCurrentProcessorNumber = (void *) GetProcAddress(hntdll, "NtGetCurrentProcessorNumber");
......@@ -2759,6 +2761,8 @@ static void test_debug_object(void)
HANDLE handle;
OBJECT_ATTRIBUTES attr = { sizeof(attr) };
ULONG len, flag = 0;
DBGUI_WAIT_STATE_CHANGE state;
DEBUG_EVENT event;
status = pNtCreateDebugObject( &handle, DEBUG_ALL_ACCESS, &attr, 0 );
ok( !status, "NtCreateDebugObject failed %x\n", status );
......@@ -2802,6 +2806,57 @@ static void test_debug_object(void)
}
pNtClose( handle );
memset( &state, 0xdd, sizeof(state) );
state.NewState = DbgIdle;
memset( &event, 0xcc, sizeof(event) );
status = pDbgUiConvertStateChangeStructure( &state, &event );
ok( status == STATUS_UNSUCCESSFUL, "DbgUiConvertStateChangeStructure failed %x\n", status );
ok( event.dwProcessId == 0xdddddddd, "event not updated %x\n", event.dwProcessId );
ok( event.dwThreadId == 0xdddddddd, "event not updated %x\n", event.dwThreadId );
state.NewState = DbgReplyPending;
memset( &event, 0xcc, sizeof(event) );
status = pDbgUiConvertStateChangeStructure( &state, &event );
ok( status == STATUS_UNSUCCESSFUL, "DbgUiConvertStateChangeStructure failed %x\n", status );
ok( event.dwProcessId == 0xdddddddd, "event not updated %x\n", event.dwProcessId );
ok( event.dwThreadId == 0xdddddddd, "event not updated %x\n", event.dwThreadId );
state.NewState = 11;
memset( &event, 0xcc, sizeof(event) );
status = pDbgUiConvertStateChangeStructure( &state, &event );
ok( status == STATUS_UNSUCCESSFUL, "DbgUiConvertStateChangeStructure failed %x\n", status );
ok( event.dwProcessId == 0xdddddddd, "event not updated %x\n", event.dwProcessId );
ok( event.dwThreadId == 0xdddddddd, "event not updated %x\n", event.dwThreadId );
state.NewState = DbgExitProcessStateChange;
state.StateInfo.ExitProcess.ExitStatus = 0x123456;
status = pDbgUiConvertStateChangeStructure( &state, &event );
ok( !status, "DbgUiConvertStateChangeStructure failed %x\n", status );
ok( event.dwProcessId == 0xdddddddd, "event not updated %x\n", event.dwProcessId );
ok( event.dwThreadId == 0xdddddddd, "event not updated %x\n", event.dwThreadId );
ok( event.u.ExitProcess.dwExitCode == 0x123456, "event not updated %x\n", event.u.ExitProcess.dwExitCode );
memset( &state, 0xdd, sizeof(state) );
state.NewState = DbgCreateProcessStateChange;
status = pDbgUiConvertStateChangeStructure( &state, &event );
ok( !status, "DbgUiConvertStateChangeStructure failed %x\n", status );
ok( event.dwProcessId == 0xdddddddd, "event not updated %x\n", event.dwProcessId );
ok( event.dwThreadId == 0xdddddddd, "event not updated %x\n", event.dwThreadId );
ok( event.u.CreateProcessInfo.nDebugInfoSize == 0xdddddddd, "event not updated %x\n", event.u.CreateProcessInfo.nDebugInfoSize );
ok( event.u.CreateProcessInfo.lpThreadLocalBase == NULL, "event not updated %p\n", event.u.CreateProcessInfo.lpThreadLocalBase );
ok( event.u.CreateProcessInfo.lpImageName == NULL, "event not updated %p\n", event.u.CreateProcessInfo.lpImageName );
ok( event.u.CreateProcessInfo.fUnicode == TRUE, "event not updated %x\n", event.u.CreateProcessInfo.fUnicode );
memset( &state, 0xdd, sizeof(state) );
state.NewState = DbgLoadDllStateChange;
status = pDbgUiConvertStateChangeStructure( &state, &event );
ok( !status, "DbgUiConvertStateChangeStructure failed %x\n", status );
ok( event.dwProcessId == 0xdddddddd, "event not updated %x\n", event.dwProcessId );
ok( event.dwThreadId == 0xdddddddd, "event not updated %x\n", event.dwThreadId );
ok( event.u.LoadDll.nDebugInfoSize == 0xdddddddd, "event not updated %x\n", event.u.LoadDll.nDebugInfoSize );
ok( PtrToUlong(event.u.LoadDll.lpImageName) == 0xdddddddd, "event not updated %p\n", event.u.LoadDll.lpImageName );
ok( event.u.LoadDll.fUnicode == TRUE, "event not updated %x\n", event.u.LoadDll.fUnicode );
}
START_TEST(info)
......
......@@ -3007,6 +3007,98 @@ typedef struct _PS_CREATE_INFO
};
} PS_CREATE_INFO, *PPS_CREATE_INFO;
typedef struct _DBGKM_EXCEPTION
{
EXCEPTION_RECORD ExceptionRecord;
ULONG FirstChance;
} DBGKM_EXCEPTION, *PDBGKM_EXCEPTION;
typedef struct _DBGKM_CREATE_THREAD
{
ULONG SubSystemKey;
PVOID StartAddress;
} DBGKM_CREATE_THREAD, *PDBGKM_CREATE_THREAD;
typedef struct _DBGKM_CREATE_PROCESS
{
ULONG SubSystemKey;
HANDLE FileHandle;
PVOID BaseOfImage;
ULONG DebugInfoFileOffset;
ULONG DebugInfoSize;
DBGKM_CREATE_THREAD InitialThread;
} DBGKM_CREATE_PROCESS, *PDBGKM_CREATE_PROCESS;
typedef struct _DBGKM_EXIT_THREAD
{
NTSTATUS ExitStatus;
} DBGKM_EXIT_THREAD, *PDBGKM_EXIT_THREAD;
typedef struct _DBGKM_EXIT_PROCESS
{
NTSTATUS ExitStatus;
} DBGKM_EXIT_PROCESS, *PDBGKM_EXIT_PROCESS;
typedef struct _DBGKM_LOAD_DLL
{
HANDLE FileHandle;
PVOID BaseOfDll;
ULONG DebugInfoFileOffset;
ULONG DebugInfoSize;
PVOID NamePointer;
} DBGKM_LOAD_DLL, *PDBGKM_LOAD_DLL;
typedef struct _DBGKM_UNLOAD_DLL
{
PVOID BaseAddress;
} DBGKM_UNLOAD_DLL, *PDBGKM_UNLOAD_DLL;
typedef enum _DBG_STATE
{
DbgIdle,
DbgReplyPending,
DbgCreateThreadStateChange,
DbgCreateProcessStateChange,
DbgExitThreadStateChange,
DbgExitProcessStateChange,
DbgExceptionStateChange,
DbgBreakpointStateChange,
DbgSingleStepStateChange,
DbgLoadDllStateChange,
DbgUnloadDllStateChange
} DBG_STATE, *PDBG_STATE;
typedef struct _DBGUI_CREATE_THREAD
{
HANDLE HandleToThread;
DBGKM_CREATE_THREAD NewThread;
} DBGUI_CREATE_THREAD, *PDBGUI_CREATE_THREAD;
typedef struct _DBGUI_CREATE_PROCESS
{
HANDLE HandleToProcess;
HANDLE HandleToThread;
DBGKM_CREATE_PROCESS NewProcess;
} DBGUI_CREATE_PROCESS, *PDBGUI_CREATE_PROCESS;
typedef struct _DBGUI_WAIT_STATE_CHANGE
{
DBG_STATE NewState;
CLIENT_ID AppClientId;
union
{
DBGKM_EXCEPTION Exception;
DBGUI_CREATE_THREAD CreateThread;
DBGUI_CREATE_PROCESS CreateProcessInfo;
DBGKM_EXIT_THREAD ExitThread;
DBGKM_EXIT_PROCESS ExitProcess;
DBGKM_LOAD_DLL LoadDll;
DBGKM_UNLOAD_DLL UnloadDll;
} StateInfo;
} DBGUI_WAIT_STATE_CHANGE, *PDBGUI_WAIT_STATE_CHANGE;
struct _DEBUG_EVENT;
#define DEBUG_READ_EVENT 0x0001
#define DEBUG_PROCESS_ASSIGN 0x0002
#define DEBUG_SET_INFORMATION 0x0004
......@@ -3030,6 +3122,7 @@ NTSYSAPI NTSTATUS WINAPIV DbgPrint(LPCSTR fmt, ...);
NTSYSAPI NTSTATUS WINAPIV DbgPrintEx(ULONG iComponentId, ULONG Level, LPCSTR fmt, ...);
NTSYSAPI NTSTATUS WINAPI DbgUiConnectToDbg(void);
NTSYSAPI NTSTATUS WINAPI DbgUiContinue(CLIENT_ID*,NTSTATUS);
NTSYSAPI NTSTATUS WINAPI DbgUiConvertStateChangeStructure(DBGUI_WAIT_STATE_CHANGE*,struct _DEBUG_EVENT*);
NTSYSAPI NTSTATUS WINAPI DbgUiDebugActiveProcess(HANDLE);
NTSYSAPI HANDLE WINAPI DbgUiGetThreadDebugObject(void);
NTSYSAPI NTSTATUS WINAPI DbgUiIssueRemoteBreakin(HANDLE);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment