Created
September 21, 2020 04:36
-
-
Save MSDN-WhiteKnight/d10244fd97bfb33ce00b26b49deea2f4 to your computer and use it in GitHub Desktop.
ICorDebug
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <Windows.h> | |
#include <CorHdr.h> | |
#include <metahost.h> | |
#include <CorDebug.h> | |
#pragma comment(lib, "mscoree.lib") | |
#pragma comment(lib, "CorGuids.lib") | |
void PrintProcessInfo(ICorDebugProcess* pDebug) { | |
ICorDebugThreadEnum* pThreadEnum; | |
HRESULT hr = pDebug->EnumerateThreads(&pThreadEnum); | |
if (FAILED(hr)) { | |
printf("EnumerateThreads error"); | |
return; | |
} | |
ICorDebugThread* pTh = NULL; | |
ICorDebugFrame* pFrame; | |
ICorDebugFunction* pFunc; | |
ULONG c; | |
DWORD id; | |
while (1) { | |
c = 0; | |
hr = pThreadEnum->Next(1, &pTh, &c); | |
if (FAILED(hr))break; | |
if (c == 0)break; | |
id = 0; | |
pTh->GetID(&id); | |
printf("Thread ID: %u\n", id); | |
hr = pTh->GetActiveFrame(&pFrame); | |
if (FAILED(hr))continue; | |
} | |
} | |
class UnmanagedCallback : | |
public ICorDebugUnmanagedCallback | |
{ | |
public: | |
UnmanagedCallback() { | |
this->m_cRef = 0; | |
} | |
volatile unsigned int m_cRef; | |
// Унаследовано через ICorDebugUnmanagedCallback | |
virtual HRESULT __stdcall QueryInterface(REFIID riid, void ** ppvObj) override | |
{ | |
if (!ppvObj) | |
return E_INVALIDARG; | |
*ppvObj = NULL; | |
if (riid == IID_IUnknown || riid == IID_ICorDebugUnmanagedCallback) | |
{ | |
// Increment the reference count and return the pointer. | |
*ppvObj = (LPVOID)this; | |
AddRef(); | |
return NOERROR; | |
} | |
return E_NOINTERFACE; | |
} | |
virtual ULONG __stdcall AddRef(void) override | |
{ | |
InterlockedIncrement(&m_cRef); | |
return m_cRef; | |
} | |
virtual ULONG __stdcall Release(void) override | |
{ | |
// Decrement the object's internal counter. | |
ULONG ulRefCount = InterlockedDecrement(&m_cRef); | |
if (0 == m_cRef) | |
{ | |
delete this; | |
} | |
return ulRefCount; | |
} | |
virtual HRESULT __stdcall DebugEvent(LPDEBUG_EVENT pDebugEvent, BOOL fOutOfBand) override | |
{ | |
; | |
return 0; | |
} | |
}; | |
class ManagedCallback : | |
public ICorDebugManagedCallback, | |
public ICorDebugManagedCallback2 | |
{ | |
public: | |
ManagedCallback() { | |
this->m_cRef = 0; | |
} | |
volatile unsigned int m_cRef; | |
// Унаследовано через ICorDebugManagedCallback | |
virtual HRESULT __stdcall QueryInterface(REFIID riid, void ** ppvObj) override | |
{ | |
if (!ppvObj) | |
return E_INVALIDARG; | |
*ppvObj = NULL; | |
if (riid == IID_IUnknown || riid == IID_ICorDebugManagedCallback || | |
riid == IID_ICorDebugManagedCallback2) | |
{ | |
// Increment the reference count and return the pointer. | |
*ppvObj = (LPVOID)this; | |
AddRef(); | |
return NOERROR; | |
} | |
return E_NOINTERFACE; | |
} | |
virtual ULONG __stdcall AddRef(void) override | |
{ | |
InterlockedIncrement(&m_cRef); | |
return m_cRef; | |
} | |
virtual ULONG __stdcall Release(void) override | |
{ | |
// Decrement the object's internal counter. | |
ULONG ulRefCount = InterlockedDecrement(&m_cRef); | |
if (0 == m_cRef) | |
{ | |
delete this; | |
} | |
return ulRefCount; | |
} | |
virtual HRESULT __stdcall Breakpoint(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugBreakpoint * pBreakpoint) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall StepComplete(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugStepper * pStepper, CorDebugStepReason reason) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall Break(ICorDebugAppDomain * pAppDomain, ICorDebugThread * thread) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall Exception(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, BOOL unhandled) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall EvalComplete(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugEval * pEval) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall EvalException(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugEval * pEval) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall ExitProcess(ICorDebugProcess * pProcess) override | |
{ | |
pProcess->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall CreateThread(ICorDebugAppDomain * pAppDomain, ICorDebugThread * thread) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall ExitThread(ICorDebugAppDomain * pAppDomain, ICorDebugThread * thread) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall LoadModule(ICorDebugAppDomain * pAppDomain, ICorDebugModule * pModule) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall UnloadModule(ICorDebugAppDomain * pAppDomain, ICorDebugModule * pModule) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall LoadClass(ICorDebugAppDomain * pAppDomain, ICorDebugClass * c) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall UnloadClass(ICorDebugAppDomain * pAppDomain, ICorDebugClass * c) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall DebuggerError(ICorDebugProcess * pProcess, HRESULT errorHR, DWORD errorCode) override | |
{ | |
pProcess->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall LogMessage(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, LONG lLevel, WCHAR * pLogSwitchName, WCHAR * pMessage) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall LogSwitch(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, LONG lLevel, ULONG ulReason, WCHAR * pLogSwitchName, WCHAR * pParentName) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall CreateAppDomain(ICorDebugProcess * pProcess, ICorDebugAppDomain * pAppDomain) override | |
{ | |
pProcess->Continue(FALSE); | |
printf("CreateAppDomain\n"); | |
PrintProcessInfo(pProcess); | |
HRESULT hr = pProcess->Detach(); | |
if(FAILED(hr)) printf("Detach error:0x%x\n",hr); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall ExitAppDomain(ICorDebugProcess * pProcess, ICorDebugAppDomain * pAppDomain) override | |
{ | |
pProcess->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall LoadAssembly(ICorDebugAppDomain * pAppDomain, ICorDebugAssembly * pAssembly) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall UnloadAssembly(ICorDebugAppDomain * pAppDomain, ICorDebugAssembly * pAssembly) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall ControlCTrap(ICorDebugProcess * pProcess) override | |
{ | |
pProcess->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall NameChange(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall UpdateModuleSymbols(ICorDebugAppDomain * pAppDomain, ICorDebugModule * pModule, IStream * pSymbolStream) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall EditAndContinueRemap(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugFunction * pFunction, BOOL fAccurate) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall BreakpointSetError(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugBreakpoint * pBreakpoint, DWORD dwError) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall CreateProcess(ICorDebugProcess *pProcess) override | |
{ | |
pProcess->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
// Унаследовано через ICorDebugManagedCallback2 | |
virtual HRESULT __stdcall FunctionRemapOpportunity(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugFunction * pOldFunction, ICorDebugFunction * pNewFunction, ULONG32 oldILOffset) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall CreateConnection(ICorDebugProcess * pProcess, CONNID dwConnectionId, WCHAR * pConnName) override | |
{ | |
pProcess->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall ChangeConnection(ICorDebugProcess * pProcess, CONNID dwConnectionId) override | |
{ | |
pProcess->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall DestroyConnection(ICorDebugProcess * pProcess, CONNID dwConnectionId) override | |
{ | |
pProcess->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall Exception(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugFrame * pFrame, ULONG32 nOffset, CorDebugExceptionCallbackType dwEventType, DWORD dwFlags) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall ExceptionUnwind(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, CorDebugExceptionUnwindCallbackType dwEventType, DWORD dwFlags) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall FunctionRemapComplete(ICorDebugAppDomain * pAppDomain, ICorDebugThread * pThread, ICorDebugFunction * pFunction) override | |
{ | |
pAppDomain->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
virtual HRESULT __stdcall MDANotification(ICorDebugController * pController, ICorDebugThread * pThread, ICorDebugMDA * pMDA) override | |
{ | |
pController->Continue(FALSE); | |
return ERROR_SUCCESS; | |
} | |
}; | |
int main() { | |
ICLRMetaHost *pMetaHost = NULL; | |
ICLRDebugging *pCLRDebugging = NULL; | |
HRESULT hr; | |
CoInitialize(NULL); | |
hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_ICLRMetaHost, | |
(LPVOID*)&pMetaHost); | |
hr = CLRCreateInstance(CLSID_CLRDebugging, IID_ICLRDebugging, | |
(LPVOID*)&pCLRDebugging); | |
DWORD pid = GetCurrentProcessId(); | |
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, pid); | |
IEnumUnknown* pEnumUnk; | |
hr = pMetaHost->EnumerateLoadedRuntimes(hProcess, &pEnumUnk); | |
IUnknown* unk; | |
hr = pEnumUnk->Next(1, &unk, NULL); | |
ICLRRuntimeInfo * pInfo; | |
unk->QueryInterface(__uuidof(ICLRRuntimeInfo), (void**)&pInfo); | |
ICorDebug* pDebug; | |
hr = pInfo->GetInterface(CLSID_CLRDebuggingLegacy,__uuidof(ICorDebug), (void**)&pDebug); | |
hr = pDebug->Initialize(); | |
ICorDebugProcess* pDebugProcess; | |
ManagedCallback* mc=new ManagedCallback(); | |
UnmanagedCallback* uc=new UnmanagedCallback(); | |
hr = pDebug->SetManagedHandler((ICorDebugManagedCallback*)mc); | |
//hr = pDebug->SetUnmanagedHandler((ICorDebugUnmanagedCallback*)uc); | |
hr = pDebug->DebugActiveProcess(pid, FALSE, &pDebugProcess); | |
/**/ | |
if (SUCCEEDED(hr)) printf("Attached"); | |
else printf("DebugActiveProcess Error: 0x%x",hr); | |
getchar(); | |
; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment