ntdll: Implement DbgUiConvertStateChangeStructure().
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
c8f5cced47
commit
d848a25b76
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue