/* * Process Hacker .NET Tools - * CLR data access functions * * Copyright (C) 2011-2015 wj32 * * This file is part of Process Hacker. * * Process Hacker is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Process Hacker is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Process Hacker. If not, see . */ #ifndef CLRSUP_H #define CLRSUP_H #define CINTERFACE #define COBJMACROS #include #undef CINTERFACE #undef COBJMACROS // General interfaces typedef struct _CLR_PROCESS_SUPPORT { struct IXCLRDataProcess *DataProcess; } CLR_PROCESS_SUPPORT, *PCLR_PROCESS_SUPPORT; PCLR_PROCESS_SUPPORT CreateClrProcessSupport( _In_ HANDLE ProcessId ); VOID FreeClrProcessSupport( _In_ PCLR_PROCESS_SUPPORT Support ); PPH_STRING GetRuntimeNameByAddressClrProcess( _In_ PCLR_PROCESS_SUPPORT Support, _In_ ULONG64 Address, _Out_opt_ PULONG64 Displacement ); PPH_STRING GetNameXClrDataAppDomain( _In_ PVOID AppDomain ); PVOID LoadMscordacwks( _In_ BOOLEAN IsClrV4 ); HRESULT CreateXCLRDataProcess( _In_ HANDLE ProcessId, _In_ ICLRDataTarget *Target, _Out_ struct IXCLRDataProcess **DataProcess ); // xclrdata typedef ULONG64 CLRDATA_ENUM; typedef struct IXCLRDataProcess IXCLRDataProcess; typedef struct IXCLRDataAppDomain IXCLRDataAppDomain; typedef struct IXCLRDataTask IXCLRDataTask; typedef struct IXCLRDataStackWalk IXCLRDataStackWalk; typedef struct IXCLRDataFrame IXCLRDataFrame; typedef struct IXCLRDataProcessVtbl { HRESULT (STDMETHODCALLTYPE *QueryInterface)( _In_ IXCLRDataProcess *This, _In_ REFIID riid, _Outptr_ void **ppvObject ); ULONG (STDMETHODCALLTYPE *AddRef)( _In_ IXCLRDataProcess *This ); ULONG (STDMETHODCALLTYPE *Release)( _In_ IXCLRDataProcess *This ); HRESULT (STDMETHODCALLTYPE *Flush)( _In_ IXCLRDataProcess *This ); HRESULT (STDMETHODCALLTYPE *StartEnumTasks)( _In_ IXCLRDataProcess *This, _Out_ CLRDATA_ENUM *handle ); HRESULT (STDMETHODCALLTYPE *EnumTask)( _In_ IXCLRDataProcess *This, _Inout_ CLRDATA_ENUM *handle, _Out_ IXCLRDataTask **task ); HRESULT (STDMETHODCALLTYPE *EndEnumTasks)( _In_ IXCLRDataProcess *This, _In_ CLRDATA_ENUM handle ); HRESULT (STDMETHODCALLTYPE *GetTaskByOSThreadID)( _In_ IXCLRDataProcess *This, _In_ ULONG32 osThreadID, _Out_ IXCLRDataTask **task ); PVOID GetTaskByUniqueID; PVOID GetFlags; PVOID IsSameObject; PVOID GetManagedObject; PVOID GetDesiredExecutionState; PVOID SetDesiredExecutionState; PVOID GetAddressType; HRESULT (STDMETHODCALLTYPE *GetRuntimeNameByAddress)( _In_ IXCLRDataProcess *This, _In_ CLRDATA_ADDRESS address, _In_ ULONG32 flags, _In_ ULONG32 bufLen, _Out_ ULONG32 *nameLen, _Out_ WCHAR *nameBuf, _Out_ CLRDATA_ADDRESS *displacement ); // ... } IXCLRDataProcessVtbl; typedef struct IXCLRDataProcess { struct IXCLRDataProcessVtbl *lpVtbl; } IXCLRDataProcess; #define IXCLRDataProcess_QueryInterface(This, riid, ppvObject) \ ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) #define IXCLRDataProcess_AddRef(This) \ ((This)->lpVtbl->AddRef(This)) #define IXCLRDataProcess_Release(This) \ ((This)->lpVtbl->Release(This)) #define IXCLRDataProcess_GetRuntimeNameByAddress(This, address, flags, bufLen, nameLen, nameBuf, displacement) \ ((This)->lpVtbl->GetRuntimeNameByAddress(This, address, flags, bufLen, nameLen, nameBuf, displacement)) #define IXCLRDataProcess_Flush(This) \ ((This)->lpVtbl->Flush(This)) #define IXCLRDataProcess_StartEnumTasks(This, handle) \ ((This)->lpVtbl->StartEnumTasks(This, handle)) #define IXCLRDataProcess_EnumTask(This, handle, task) \ ((This)->lpVtbl->EnumTask(This, handle, task)) #define IXCLRDataProcess_EndEnumTasks(This, handle) \ ((This)->lpVtbl->EndEnumTasks(This, handle)) #define IXCLRDataProcess_GetTaskByOSThreadID(This, osThreadID, task) \ ((This)->lpVtbl->GetTaskByOSThreadID(This, osThreadID, task)) typedef struct IXCLRDataAppDomainVtbl { HRESULT (STDMETHODCALLTYPE *QueryInterface)( _In_ IXCLRDataAppDomain *This, _In_ REFIID riid, _Outptr_ void **ppvObject ); ULONG (STDMETHODCALLTYPE *AddRef)( _In_ IXCLRDataAppDomain *This ); ULONG (STDMETHODCALLTYPE *Release)( _In_ IXCLRDataAppDomain *This ); HRESULT (STDMETHODCALLTYPE *GetProcess)( _In_ IXCLRDataAppDomain *This, _Out_ IXCLRDataProcess **process ); HRESULT (STDMETHODCALLTYPE *GetName)( _In_ IXCLRDataAppDomain *This, _In_ ULONG32 bufLen, _Out_ ULONG32 *nameLen, _Out_ WCHAR *name ); HRESULT (STDMETHODCALLTYPE *GetUniqueID)( _In_ IXCLRDataAppDomain *This, _Out_ ULONG64 *id ); // ... } IXCLRDataAppDomainVtbl; typedef struct IXCLRDataAppDomain { struct IXCLRDataAppDomainVtbl *lpVtbl; } IXCLRDataAppDomain; #define IXCLRDataAppDomain_QueryInterface(This, riid, ppvObject) \ ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) #define IXCLRDataAppDomain_AddRef(This) \ ((This)->lpVtbl->AddRef(This)) #define IXCLRDataAppDomain_Release(This) \ ((This)->lpVtbl->Release(This)) #define IXCLRDataAppDomain_GetProcess(This, process) \ ((This)->lpVtbl->GetProcess(This, process)) #define IXCLRDataAppDomain_GetName(This, bufLen, nameLen, name) \ ((This)->lpVtbl->GetName(This, bufLen, nameLen, name)) #define IXCLRDataAppDomain_GetUniqueID(This, id) \ ((This)->lpVtbl->GetUniqueID(This, id)) typedef struct IXCLRDataTaskVtbl { HRESULT (STDMETHODCALLTYPE *QueryInterface)( _In_ IXCLRDataTask *This, _In_ REFIID riid, _Outptr_ void **ppvObject ); ULONG (STDMETHODCALLTYPE *AddRef)( _In_ IXCLRDataTask *This ); ULONG (STDMETHODCALLTYPE *Release)( _In_ IXCLRDataTask *This ); HRESULT (STDMETHODCALLTYPE *GetProcess)( _In_ IXCLRDataTask *This, _Out_ IXCLRDataProcess **process ); HRESULT (STDMETHODCALLTYPE *GetCurrentAppDomain)( _In_ IXCLRDataTask *This, _Out_ IXCLRDataAppDomain **appDomain ); HRESULT (STDMETHODCALLTYPE *GetUniqueID)( _In_ IXCLRDataTask *This, _Out_ ULONG64 *id ); HRESULT (STDMETHODCALLTYPE *GetFlags)( _In_ IXCLRDataTask *This, _Out_ ULONG32 *flags ); PVOID IsSameObject; PVOID GetManagedObject; PVOID GetDesiredExecutionState; PVOID SetDesiredExecutionState; HRESULT (STDMETHODCALLTYPE *CreateStackWalk)( _In_ IXCLRDataTask *This, _In_ ULONG32 flags, _Out_ IXCLRDataStackWalk **stackWalk ); HRESULT (STDMETHODCALLTYPE *GetOSThreadID)( _In_ IXCLRDataTask *This, _Out_ ULONG32 *id ); PVOID GetContext; PVOID SetContext; PVOID GetCurrentExceptionState; PVOID Request; HRESULT (STDMETHODCALLTYPE *GetName)( _In_ IXCLRDataTask *This, _In_ ULONG32 bufLen, _Out_ ULONG32 *nameLen, _Out_ WCHAR *name ); PVOID GetLastExceptionState; } IXCLRDataTaskVtbl; typedef struct IXCLRDataTask { struct IXCLRDataTaskVtbl *lpVtbl; } IXCLRDataTask; #define IXCLRDataTask_QueryInterface(This, riid, ppvObject) \ ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) #define IXCLRDataTask_AddRef(This) \ ((This)->lpVtbl->AddRef(This)) #define IXCLRDataTask_Release(This) \ ((This)->lpVtbl->Release(This)) #define IXCLRDataTask_GetProcess(This, process) \ ((This)->lpVtbl->GetProcess(This, process)) #define IXCLRDataTask_GetCurrentAppDomain(This, appDomain) \ ((This)->lpVtbl->GetCurrentAppDomain(This, appDomain)) #define IXCLRDataTask_GetUniqueID(This, id) \ ((This)->lpVtbl->GetUniqueID(This, id)) #define IXCLRDataTask_GetFlags(This, flags) \ ((This)->lpVtbl->GetFlags(This, flags)) #define IXCLRDataTask_CreateStackWalk(This, flags, stackWalk) \ ((This)->lpVtbl->CreateStackWalk(This, flags, stackWalk)) #define IXCLRDataTask_GetOSThreadID(This, id) \ ((This)->lpVtbl->GetOSThreadID(This, id)) #define IXCLRDataTask_GetName(This, bufLen, nameLen, name) \ ((This)->lpVtbl->GetName(This, bufLen, nameLen, name)) typedef enum { CLRDATA_SIMPFRAME_UNRECOGNIZED = 0x1, CLRDATA_SIMPFRAME_MANAGED_METHOD = 0x2, CLRDATA_SIMPFRAME_RUNTIME_MANAGED_CODE = 0x4, CLRDATA_SIMPFRAME_RUNTIME_UNMANAGED_CODE = 0x8 } CLRDataSimpleFrameType; typedef enum { CLRDATA_DETFRAME_UNRECOGNIZED, CLRDATA_DETFRAME_UNKNOWN_STUB, CLRDATA_DETFRAME_CLASS_INIT, CLRDATA_DETFRAME_EXCEPTION_FILTER, CLRDATA_DETFRAME_SECURITY, CLRDATA_DETFRAME_CONTEXT_POLICY, CLRDATA_DETFRAME_INTERCEPTION, CLRDATA_DETFRAME_PROCESS_START, CLRDATA_DETFRAME_THREAD_START, CLRDATA_DETFRAME_TRANSITION_TO_MANAGED, CLRDATA_DETFRAME_TRANSITION_TO_UNMANAGED, CLRDATA_DETFRAME_COM_INTEROP_STUB, CLRDATA_DETFRAME_DEBUGGER_EVAL, CLRDATA_DETFRAME_CONTEXT_SWITCH, CLRDATA_DETFRAME_FUNC_EVAL, CLRDATA_DETFRAME_FINALLY } CLRDataDetailedFrameType; typedef enum { CLRDATA_STACK_SET_UNWIND_CONTEXT = 0x00000000, CLRDATA_STACK_SET_CURRENT_CONTEXT = 0x00000001 } CLRDataStackSetContextFlag; typedef struct IXCLRDataStackWalkVtbl { HRESULT (STDMETHODCALLTYPE *QueryInterface)( _In_ IXCLRDataStackWalk *This, _In_ REFIID riid, _Outptr_ void **ppvObject ); ULONG (STDMETHODCALLTYPE *AddRef)( _In_ IXCLRDataStackWalk *This ); ULONG (STDMETHODCALLTYPE *Release)( _In_ IXCLRDataStackWalk *This ); HRESULT (STDMETHODCALLTYPE *GetContext)( _In_ IXCLRDataStackWalk *This, _In_ ULONG32 contextFlags, _In_ ULONG32 contextBufSize, _Out_ ULONG32 *contextSize, _Out_ BYTE *contextBuf ); PVOID SetContext; HRESULT (STDMETHODCALLTYPE *Next)( _In_ IXCLRDataStackWalk *This ); HRESULT (STDMETHODCALLTYPE *GetStackSizeSkipped)( _In_ IXCLRDataStackWalk *This, _Out_ ULONG64 *stackSizeSkipped ); HRESULT (STDMETHODCALLTYPE *GetFrameType)( _In_ IXCLRDataStackWalk *This, _Out_ CLRDataSimpleFrameType *simpleType, _Out_ CLRDataDetailedFrameType *detailedType ); HRESULT (STDMETHODCALLTYPE *GetFrame)( _In_ IXCLRDataStackWalk *This, _Out_ PVOID *frame ); HRESULT (STDMETHODCALLTYPE *Request)( _In_ IXCLRDataStackWalk *This, _In_ ULONG32 reqCode, _In_ ULONG32 inBufferSize, _In_ BYTE *inBuffer, _In_ ULONG32 outBufferSize, _Out_ BYTE *outBuffer ); HRESULT (STDMETHODCALLTYPE *SetContext2)( _In_ IXCLRDataStackWalk *This, _In_ ULONG32 flags, _In_ ULONG32 contextSize, _In_ BYTE *context ); } IXCLRDataStackWalkVtbl; typedef struct IXCLRDataStackWalk { struct IXCLRDataStackWalkVtbl *lpVtbl; } IXCLRDataStackWalk; #define IXCLRDataStackWalk_QueryInterface(This, riid, ppvObject) \ ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) #define IXCLRDataStackWalk_AddRef(This) \ ((This)->lpVtbl->AddRef(This)) #define IXCLRDataStackWalk_Release(This) \ ((This)->lpVtbl->Release(This)) #define IXCLRDataStackWalk_GetContext(This, contextFlags, contextBufSize, contextSize, contextBuf) \ ((This)->lpVtbl->GetContext(This, contextFlags, contextBufSize, contextSize, contextBuf)) #define IXCLRDataStackWalk_Next(This) \ ((This)->lpVtbl->Next(This)) #define IXCLRDataStackWalk_GetStackSizeSkipped(This, stackSizeSkipped) \ ((This)->lpVtbl->GetStackSizeSkipped(This, stackSizeSkipped)) #define IXCLRDataStackWalk_GetFrameType(This, simpleType, detailedType) \ ((This)->lpVtbl->GetFrameType(This, simpleType, detailedType)) #define IXCLRDataStackWalk_GetFrame(This, frame) \ ((This)->lpVtbl->GetFrame(This, frame)) #define IXCLRDataStackWalk_Request(This, reqCode, inBufferSize, inBuffer, outBufferSize, outBuffer) \ ((This)->lpVtbl->SetContext2(This, reqCode, inBufferSize, inBuffer, outBufferSize, outBuffer)) #define IXCLRDataStackWalk_SetContext2(This, flags, contextSize, context) \ ((This)->lpVtbl->SetContext2(This, flags, contextSize, context)) typedef struct IXCLRDataFrameVtbl { HRESULT (STDMETHODCALLTYPE *QueryInterface)( _In_ IXCLRDataFrame *This, _In_ REFIID riid, _Outptr_ void **ppvObject ); ULONG (STDMETHODCALLTYPE *AddRef)( _In_ IXCLRDataFrame *This ); ULONG (STDMETHODCALLTYPE *Release)( _In_ IXCLRDataFrame *This ); HRESULT (STDMETHODCALLTYPE *GetFrameType)( _In_ IXCLRDataFrame *This, _Out_ CLRDataSimpleFrameType *simpleType, _Out_ CLRDataDetailedFrameType *detailedType ); HRESULT (STDMETHODCALLTYPE *GetContext)( _In_ IXCLRDataFrame *This, _In_ ULONG32 contextFlags, _In_ ULONG32 contextBufSize, _Out_ ULONG32 *contextSize, _Out_ BYTE *contextBuf ); PVOID GetAppDomain; PVOID GetNumArguments; PVOID GetArgumentByIndex; PVOID GetNumLocalVariables; PVOID GetLocalVariableByIndex; HRESULT (STDMETHODCALLTYPE *GetCodeName)( _In_ IXCLRDataFrame *This, _In_ ULONG32 *flags, _In_ ULONG32 *bufLen, _Out_ ULONG32 *nameLen, _Out_ WCHAR *nameBuf ); } IXCLRDataFrameVtbl; typedef struct IXCLRDataFrame { IXCLRDataFrameVtbl *lpVtbl; } IXCLRDataFrame; #define IXCLRDataFrame_QueryInterface(This, riid, ppvObject) \ ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) #define IXCLRDataFrame_AddRef(This) \ ((This)->lpVtbl->AddRef(This)) #define IXCLRDataFrame_Release(This) \ ((This)->lpVtbl->Release(This)) #define IXCLRDataFrame_GetFrameType(This, simpleType, detailedType) \ ((This)->lpVtbl->GetFrameType(This, simpleType, detailedType)) #define IXCLRDataFrame_GetContext(This, contextFlags, contextBufSize, contextSize, contextBuf) \ ((This)->lpVtbl->GetContext(This, contextFlags, contextBufSize, contextSize, contextBuf)) #define IXCLRDataFrame_GetCodeName(This, flags, bufLen, nameLen, nameBuf) \ ((This)->lpVtbl->GetCodeName(This, flags, bufLen, nameLen, nameBuf)) // DnCLRDataTarget typedef struct { ICLRDataTargetVtbl *VTable; ULONG RefCount; HANDLE ProcessId; HANDLE ProcessHandle; BOOLEAN IsWow64; } DnCLRDataTarget; ICLRDataTarget *DnCLRDataTarget_Create( _In_ HANDLE ProcessId ); HRESULT STDMETHODCALLTYPE DnCLRDataTarget_QueryInterface( _In_ ICLRDataTarget *This, _In_ REFIID Riid, _Out_ PVOID *Object ); ULONG STDMETHODCALLTYPE DnCLRDataTarget_AddRef( _In_ ICLRDataTarget *This ); ULONG STDMETHODCALLTYPE DnCLRDataTarget_Release( _In_ ICLRDataTarget *This ); HRESULT STDMETHODCALLTYPE DnCLRDataTarget_GetMachineType( _In_ ICLRDataTarget *This, _Out_ ULONG32 *machineType ); HRESULT STDMETHODCALLTYPE DnCLRDataTarget_GetPointerSize( _In_ ICLRDataTarget *This, _Out_ ULONG32 *pointerSize ); HRESULT STDMETHODCALLTYPE DnCLRDataTarget_GetImageBase( _In_ ICLRDataTarget *This, _In_ LPCWSTR imagePath, _Out_ CLRDATA_ADDRESS *baseAddress ); HRESULT STDMETHODCALLTYPE DnCLRDataTarget_ReadVirtual( _In_ ICLRDataTarget *This, _In_ CLRDATA_ADDRESS address, _Out_ BYTE *buffer, _In_ ULONG32 bytesRequested, _Out_ ULONG32 *bytesRead ); HRESULT STDMETHODCALLTYPE DnCLRDataTarget_WriteVirtual( _In_ ICLRDataTarget *This, _In_ CLRDATA_ADDRESS address, _In_ BYTE *buffer, _In_ ULONG32 bytesRequested, _Out_ ULONG32 *bytesWritten ); HRESULT STDMETHODCALLTYPE DnCLRDataTarget_GetTLSValue( _In_ ICLRDataTarget *This, _In_ ULONG32 threadID, _In_ ULONG32 index, _Out_ CLRDATA_ADDRESS *value ); HRESULT STDMETHODCALLTYPE DnCLRDataTarget_SetTLSValue( _In_ ICLRDataTarget *This, _In_ ULONG32 threadID, _In_ ULONG32 index, _In_ CLRDATA_ADDRESS value ); HRESULT STDMETHODCALLTYPE DnCLRDataTarget_GetCurrentThreadID( _In_ ICLRDataTarget *This, _Out_ ULONG32 *threadID ); HRESULT STDMETHODCALLTYPE DnCLRDataTarget_GetThreadContext( _In_ ICLRDataTarget *This, _In_ ULONG32 threadID, _In_ ULONG32 contextFlags, _In_ ULONG32 contextSize, _Out_ BYTE *context ); HRESULT STDMETHODCALLTYPE DnCLRDataTarget_SetThreadContext( _In_ ICLRDataTarget *This, _In_ ULONG32 threadID, _In_ ULONG32 contextSize, _In_ BYTE *context ); HRESULT STDMETHODCALLTYPE DnCLRDataTarget_Request( _In_ ICLRDataTarget *This, _In_ ULONG32 reqCode, _In_ ULONG32 inBufferSize, _In_ BYTE *inBuffer, _In_ ULONG32 outBufferSize, _Out_ BYTE *outBuffer ); typedef struct _PHP_GET_IMAGE_BASE_CONTEXT { UNICODE_STRING ImagePath; PVOID BaseAddress; } PHP_GET_IMAGE_BASE_CONTEXT, *PPHP_GET_IMAGE_BASE_CONTEXT; #endif