// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. //***************************************************************************** // File: task.cpp // // // ClrDataTask. // //***************************************************************************** #include "stdafx.h" // XXX Microsoft - Why aren't these extra MD APIs in a header? STDAPI GetMDPublicInterfaceFromInternal( void *pIUnkPublic, // [IN] Given scope. REFIID riid, // [in] The interface desired. void **ppIUnkInternal); // [out] Return interface on success. STDAPI GetMetaDataPublicInterfaceFromInternal( void *pv, // [IN] Given interface. REFIID riid, // [IN] desired interface. void **ppv) // [OUT] returned interface { return GetMDPublicInterfaceFromInternal(pv, riid, ppv); } //---------------------------------------------------------------------------- // // ClrDataTask. // //---------------------------------------------------------------------------- ClrDataTask::ClrDataTask(ClrDataAccess* dac, Thread* thread) { m_dac = dac; m_dac->AddRef(); m_instanceAge = m_dac->m_instanceAge; m_thread = thread; m_refs = 1; } ClrDataTask::~ClrDataTask(void) { m_dac->Release(); } STDMETHODIMP ClrDataTask::QueryInterface(THIS_ IN REFIID interfaceId, OUT PVOID* iface) { if (IsEqualIID(interfaceId, IID_IUnknown) || IsEqualIID(interfaceId, __uuidof(IXCLRDataTask))) { AddRef(); *iface = static_cast (static_cast(this)); return S_OK; } else { *iface = NULL; return E_NOINTERFACE; } } STDMETHODIMP_(ULONG) ClrDataTask::AddRef(THIS) { return InterlockedIncrement(&m_refs); } STDMETHODIMP_(ULONG) ClrDataTask::Release(THIS) { SUPPORTS_DAC_HOST_ONLY; LONG newRefs = InterlockedDecrement(&m_refs); if (newRefs == 0) { delete this; } return newRefs; } HRESULT STDMETHODCALLTYPE ClrDataTask::GetProcess( /* [out] */ IXCLRDataProcess **process) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { *process = static_cast(m_dac); m_dac->AddRef(); status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::GetCurrentAppDomain( /* [out] */ IXCLRDataAppDomain **appDomain) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { if (m_thread->GetDomain()) { *appDomain = new (nothrow) ClrDataAppDomain(m_dac, m_thread->GetDomain()); status = *appDomain ? S_OK : E_OUTOFMEMORY; } else { status = E_INVALIDARG; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::GetName( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX - Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::GetUniqueID( /* [out] */ ULONG64 *id) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { *id = m_thread->GetThreadId(); status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::GetFlags( /* [out] */ ULONG32 *flags) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft - GC check. *flags = CLRDATA_TASK_DEFAULT; status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::IsSameObject( /* [in] */ IXCLRDataTask* task) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = PTR_HOST_TO_TADDR(m_thread) == PTR_HOST_TO_TADDR(((ClrDataTask*)task)->m_thread) ? S_OK : S_FALSE; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::GetManagedObject( /* [out] */ IXCLRDataValue **value) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::GetDesiredExecutionState( /* [out] */ ULONG32 *state) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::SetDesiredExecutionState( /* [in] */ ULONG32 state) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::CreateStackWalk( /* [in] */ ULONG32 flags, /* [out] */ IXCLRDataStackWalk **stackWalk) { HRESULT status; if (flags & ~SIMPFRAME_ALL) { return E_INVALIDARG; } DAC_ENTER_SUB(m_dac); ClrDataStackWalk* walkClass = NULL; EX_TRY { walkClass = new (nothrow) ClrDataStackWalk(m_dac, m_thread, flags); if (!walkClass) { status = E_OUTOFMEMORY; } else if ((status = walkClass->Init()) != S_OK) { delete walkClass; } else { *stackWalk = static_cast(walkClass); } } EX_CATCH { if (walkClass) { delete walkClass; } if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::GetOSThreadID( /* [out] */ ULONG32 *id) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { if (m_thread->GetOSThreadId() && m_thread->GetOSThreadId() != 0xbaadf00d) { *id = m_thread->GetOSThreadId(); status = S_OK; } else { *id = 0; status = S_FALSE; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::GetContext( /* [in] */ ULONG32 contextFlags, /* [in] */ ULONG32 contextBufSize, /* [out] */ ULONG32 *contextSize, /* [size_is][out] */ BYTE contextBuf[ ]) { HRESULT status; if (contextSize) { *contextSize = ContextSizeForFlags(contextFlags); } if (!CheckContextSizeForFlags(contextBufSize, contextFlags)) { return E_INVALIDARG; } DAC_ENTER_SUB(m_dac); EX_TRY { if (m_thread->GetOSThreadId()) { status = m_dac->m_pTarget-> GetThreadContext(m_thread->GetOSThreadId(), contextFlags, contextBufSize, contextBuf); } else { status = E_INVALIDARG; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::SetContext( /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE context[ ]) { HRESULT status; if (!CheckContextSizeForBuffer(contextSize, context)) { return E_INVALIDARG; } DAC_ENTER_SUB(m_dac); EX_TRY { if (m_thread->GetOSThreadId()) { status = m_dac->m_pMutableTarget-> SetThreadContext(m_thread->GetOSThreadId(), contextSize, context); } else { status = E_INVALIDARG; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::GetCurrentExceptionState( /* [out] */ IXCLRDataExceptionState **exception) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = ClrDataExceptionState::NewFromThread(m_dac, m_thread, NULL, exception); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::GetLastExceptionState( /* [out] */ IXCLRDataExceptionState **exception) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { if (m_thread->m_LastThrownObjectHandle) { *exception = new (nothrow) ClrDataExceptionState(m_dac, m_thread->GetDomain(), m_thread, CLRDATA_EXCEPTION_PARTIAL, NULL, m_thread->m_LastThrownObjectHandle, NULL); status = *exception ? S_OK : E_OUTOFMEMORY; } else { status = E_NOINTERFACE; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataTask::Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { switch(reqCode) { case CLRDATA_REQUEST_REVISION: if (inBufferSize != 0 || inBuffer || outBufferSize != sizeof(ULONG32)) { status = E_INVALIDARG; } else { *(ULONG32*)outBuffer = 3; status = S_OK; } break; default: status = E_INVALIDARG; break; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } //---------------------------------------------------------------------------- // // ClrDataAppDomain. // //---------------------------------------------------------------------------- ClrDataAppDomain::ClrDataAppDomain(ClrDataAccess* dac, AppDomain* appDomain) { m_dac = dac; m_dac->AddRef(); m_instanceAge = m_dac->m_instanceAge; m_appDomain = appDomain; m_refs = 1; } ClrDataAppDomain::~ClrDataAppDomain(void) { m_dac->Release(); } STDMETHODIMP ClrDataAppDomain::QueryInterface(THIS_ IN REFIID interfaceId, OUT PVOID* iface) { if (IsEqualIID(interfaceId, IID_IUnknown) || IsEqualIID(interfaceId, __uuidof(IXCLRDataAppDomain))) { AddRef(); *iface = static_cast (static_cast(this)); return S_OK; } else { *iface = NULL; return E_NOINTERFACE; } } STDMETHODIMP_(ULONG) ClrDataAppDomain::AddRef(THIS) { return InterlockedIncrement(&m_refs); } STDMETHODIMP_(ULONG) ClrDataAppDomain::Release(THIS) { SUPPORTS_DAC_HOST_ONLY; LONG newRefs = InterlockedDecrement(&m_refs); if (newRefs == 0) { delete this; } return newRefs; } HRESULT STDMETHODCALLTYPE ClrDataAppDomain::GetProcess( /* [out] */ IXCLRDataProcess **process) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { *process = static_cast(m_dac); m_dac->AddRef(); status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAppDomain::GetName( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]) { HRESULT status = S_OK; DAC_ENTER_SUB(m_dac); EX_TRY { bool isUtf8; PVOID rawName = m_appDomain->GetFriendlyNameNoSet(&isUtf8); if (rawName) { if (isUtf8) { status = ConvertUtf8((LPCUTF8)rawName, bufLen, nameLen, name); } else { status = StringCchCopy(name, bufLen, (PCWSTR)rawName) == S_OK ? S_OK : S_FALSE; if (nameLen) { size_t cchName = wcslen((PCWSTR)rawName) + 1; if (FitsIn(cchName)) { *nameLen = (ULONG32) cchName; } else { status = COR_E_OVERFLOW; } } } } else { status = E_NOINTERFACE; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAppDomain::GetFlags( /* [out] */ ULONG32 *flags) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { *flags = CLRDATA_DOMAIN_DEFAULT; status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAppDomain::IsSameObject( /* [in] */ IXCLRDataAppDomain* appDomain) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = PTR_HOST_TO_TADDR(m_appDomain) == PTR_HOST_TO_TADDR(((ClrDataAppDomain*)appDomain)->m_appDomain) ? S_OK : S_FALSE; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAppDomain::GetManagedObject( /* [out] */ IXCLRDataValue **value) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAppDomain::GetUniqueID( /* [out] */ ULONG64 *id) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { *id = m_appDomain->GetId().m_dwId; status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAppDomain::Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = E_INVALIDARG; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } //---------------------------------------------------------------------------- // // ClrDataAssembly. // //---------------------------------------------------------------------------- ClrDataAssembly::ClrDataAssembly(ClrDataAccess* dac, Assembly* assembly) { m_dac = dac; m_dac->AddRef(); m_instanceAge = m_dac->m_instanceAge; m_refs = 1; m_assembly = assembly; } ClrDataAssembly::~ClrDataAssembly(void) { m_dac->Release(); } STDMETHODIMP ClrDataAssembly::QueryInterface(THIS_ IN REFIID interfaceId, OUT PVOID* iface) { if (IsEqualIID(interfaceId, IID_IUnknown) || IsEqualIID(interfaceId, __uuidof(IXCLRDataAssembly))) { AddRef(); *iface = static_cast (static_cast(this)); return S_OK; } else { *iface = NULL; return E_NOINTERFACE; } } STDMETHODIMP_(ULONG) ClrDataAssembly::AddRef(THIS) { return InterlockedIncrement(&m_refs); } STDMETHODIMP_(ULONG) ClrDataAssembly::Release(THIS) { SUPPORTS_DAC_HOST_ONLY; LONG newRefs = InterlockedDecrement(&m_refs); if (newRefs == 0) { delete this; } return newRefs; } HRESULT STDMETHODCALLTYPE ClrDataAssembly::StartEnumModules( /* [out] */ CLRDATA_ENUM* handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { Assembly::ModuleIterator* iter = new (nothrow) Assembly::ModuleIterator; if (iter) { *iter = m_assembly->IterateModules(); *handle = TO_CDENUM(iter); status = S_OK; } else { status = E_OUTOFMEMORY; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAssembly::EnumModule( /* [in, out] */ CLRDATA_ENUM* handle, /* [out] */ IXCLRDataModule **mod) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { Assembly::ModuleIterator* iter = FROM_CDENUM(Assembly::ModuleIterator, *handle); if (iter->Next()) { *mod = new (nothrow) ClrDataModule(m_dac, iter->GetModule()); status = *mod ? S_OK : E_OUTOFMEMORY; } else { status = S_FALSE; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAssembly::EndEnumModules( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { Assembly::ModuleIterator* iter = FROM_CDENUM(Assembly::ModuleIterator, handle); delete iter; status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAssembly::StartEnumAppDomains( /* [out] */ CLRDATA_ENUM* handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAssembly::EnumAppDomain( /* [in, out] */ CLRDATA_ENUM* handle, /* [out] */ IXCLRDataAppDomain **appDomain) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAssembly::EndEnumAppDomains( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAssembly::GetName( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = ConvertUtf8(m_assembly->GetSimpleName(), bufLen, nameLen, name); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAssembly::GetFileName( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { COUNT_T _nameLen; if (m_assembly->GetManifestFile()->GetPath(). DacGetUnicode(bufLen, name, &_nameLen)) { if (nameLen) { *nameLen = _nameLen; } status = S_OK; } else { status = E_FAIL; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAssembly::GetDisplayName( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAssembly::GetFlags( /* [out] */ ULONG32 *flags) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { *flags = CLRDATA_ASSEMBLY_DEFAULT; status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAssembly::IsSameObject( /* [in] */ IXCLRDataAssembly* assembly) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = (PTR_HOST_TO_TADDR(m_assembly) == PTR_HOST_TO_TADDR(((ClrDataAssembly*)assembly)-> m_assembly)) ? S_OK : S_FALSE; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataAssembly::Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { switch(reqCode) { case CLRDATA_REQUEST_REVISION: if (inBufferSize != 0 || inBuffer || outBufferSize != sizeof(ULONG32)) { status = E_INVALIDARG; } else { *(ULONG32*)outBuffer = 2; status = S_OK; } break; default: status = E_INVALIDARG; break; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } //---------------------------------------------------------------------------- // // ClrDataModule. // //---------------------------------------------------------------------------- ClrDataModule::ClrDataModule(ClrDataAccess* dac, Module* module) { m_dac = dac; m_dac->AddRef(); m_instanceAge = m_dac->m_instanceAge; m_refs = 1; m_module = module; m_mdImport = NULL; m_setExtents = false; } ClrDataModule::~ClrDataModule(void) { m_dac->Release(); if (m_mdImport) { m_mdImport->Release(); } } STDMETHODIMP ClrDataModule::QueryInterface(THIS_ IN REFIID interfaceId, OUT PVOID* iface) { _ASSERTE(iface != NULL); if (IsEqualIID(interfaceId, IID_IUnknown) || IsEqualIID(interfaceId, __uuidof(IXCLRDataModule))) { AddRef(); *iface = static_cast (static_cast(this)); return S_OK; } else if (IsEqualIID(interfaceId, __uuidof(IXCLRDataModule2))) { AddRef(); *iface = static_cast (static_cast(this)); return S_OK; } else if (IsEqualIID(interfaceId, IID_IMetaDataImport)) { return GetMdInterface(iface); } else { *iface = NULL; return E_NOINTERFACE; } } STDMETHODIMP_(ULONG) ClrDataModule::AddRef(THIS) { return InterlockedIncrement(&m_refs); } STDMETHODIMP_(ULONG) ClrDataModule::Release(THIS) { SUPPORTS_DAC_HOST_ONLY; LONG newRefs = InterlockedDecrement(&m_refs); if (newRefs == 0) { delete this; } return newRefs; } HRESULT STDMETHODCALLTYPE ClrDataModule::StartEnumAssemblies( /* [out] */ CLRDATA_ENUM* handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { ProcessModIter* iter = new (nothrow) ProcessModIter; if (iter) { *handle = TO_CDENUM(iter); status = S_OK; } else { status = E_OUTOFMEMORY; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EnumAssembly( /* [in, out] */ CLRDATA_ENUM* handle, /* [out] */ IXCLRDataAssembly **assembly) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { ProcessModIter* iter = FROM_CDENUM(ProcessModIter, *handle); Module* module; // // Iterate over all of the modules in the process. // When this module is found, return the containing // assembly. // Is there a more direct way? // for (;;) { if (!(module = iter->NextModule())) { status = S_FALSE; break; } if (PTR_HOST_TO_TADDR(module) == PTR_HOST_TO_TADDR(m_module)) { *assembly = new (nothrow) ClrDataAssembly(m_dac, iter->m_curAssem); status = *assembly ? S_OK : E_OUTOFMEMORY; break; } } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EndEnumAssemblies( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { ProcessModIter* iter = FROM_CDENUM(ProcessModIter, handle); delete iter; status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::StartEnumAppDomains( /* [out] */ CLRDATA_ENUM* handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EnumAppDomain( /* [in, out] */ CLRDATA_ENUM* handle, /* [out] */ IXCLRDataAppDomain **appDomain) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EndEnumAppDomains( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::StartEnumTypeDefinitions( /* [out] */ CLRDATA_ENUM* handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = MetaEnum::New(m_module, mdtTypeDef, 0, NULL, NULL, handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EnumTypeDefinition( /* [in, out] */ CLRDATA_ENUM* handle, /* [out] */ IXCLRDataTypeDefinition **typeDefinition) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { mdTypeDef token; if ((status = MetaEnum::CdNextToken(handle, &token)) == S_OK) { status = ClrDataTypeDefinition:: NewFromModule(m_dac, m_module, token, NULL, typeDefinition); } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EndEnumTypeDefinitions( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = MetaEnum::CdEnd(handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::StartEnumTypeInstances( /* [in] */ IXCLRDataAppDomain* appDomain, /* [out] */ CLRDATA_ENUM* handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = MetaEnum::New(m_module, mdtTypeDef, 0, appDomain, NULL, handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EnumTypeInstance( /* [in, out] */ CLRDATA_ENUM* handle, /* [out] */ IXCLRDataTypeInstance **typeInstance) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { for (;;) { AppDomain* appDomain; mdTypeDef token; if ((status = MetaEnum:: CdNextDomainToken(handle, &appDomain, &token)) != S_OK) { break; } // If the type hasn't been used there won't be anything // loaded. It's not an instance, then, just keep going. if ((status = ClrDataTypeInstance:: NewFromModule(m_dac, appDomain, m_module, token, NULL, typeInstance)) != E_INVALIDARG) { break; } } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EndEnumTypeInstances( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = MetaEnum::CdEnd(handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::StartEnumTypeDefinitionsByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [out] */ CLRDATA_ENUM* handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = SplitName::CdStartType(name, flags, m_module, NULL, NULL, NULL, handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EnumTypeDefinitionByName( /* [out][in] */ CLRDATA_ENUM* handle, /* [out] */ IXCLRDataTypeDefinition **type) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { mdTypeDef token; if ((status = SplitName::CdNextType(handle, &token)) == S_OK) { status = ClrDataTypeDefinition:: NewFromModule(m_dac, m_module, token, NULL, type); } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EndEnumTypeDefinitionsByName( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = SplitName::CdEnd(handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::StartEnumTypeInstancesByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataAppDomain *appDomain, /* [out] */ CLRDATA_ENUM* handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = SplitName::CdStartType(name, flags, m_module, NULL, appDomain, NULL, handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EnumTypeInstanceByName( /* [out][in] */ CLRDATA_ENUM* handle, /* [out] */ IXCLRDataTypeInstance **type) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { SplitName* split; split = FROM_CDENUM(SplitName, *handle); for (;;) { AppDomain* appDomain; mdTypeDef token; if ((status = SplitName:: CdNextDomainType(handle, &appDomain, &token)) != S_OK) { break; } // If the type hasn't been used there won't be anything // loaded. It's not an instance, then, just keep going. if ((status = ClrDataTypeInstance:: NewFromModule(m_dac, appDomain, m_module, token, NULL, type)) != E_INVALIDARG) { break; } } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EndEnumTypeInstancesByName( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = SplitName::CdEnd(handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::GetTypeDefinitionByToken( /* [in] */ mdTypeDef token, /* [out] */ IXCLRDataTypeDefinition **typeDefinition) { HRESULT status; // This isn't critically necessary but it prevents // an assert in the metadata code. if (TypeFromToken(token) != mdtTypeDef) { return E_INVALIDARG; } DAC_ENTER_SUB(m_dac); EX_TRY { status = ClrDataTypeDefinition:: NewFromModule(m_dac, m_module, token, NULL, typeDefinition); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::StartEnumMethodDefinitionsByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [out] */ CLRDATA_ENUM* handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = SplitName::CdStartMethod(name, flags, m_module, mdTypeDefNil, NULL, NULL, NULL, handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EnumMethodDefinitionByName( /* [out][in] */ CLRDATA_ENUM* handle, /* [out] */ IXCLRDataMethodDefinition **method) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { mdMethodDef token; if ((status = SplitName::CdNextMethod(handle, &token)) == S_OK) { status = ClrDataMethodDefinition:: NewFromModule(m_dac, m_module, token, NULL, method); } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EndEnumMethodDefinitionsByName( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = SplitName::CdEnd(handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::StartEnumMethodInstancesByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataAppDomain* appDomain, /* [out] */ CLRDATA_ENUM* handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = SplitName::CdStartMethod(name, flags, m_module, mdTypeDefNil, NULL, appDomain, NULL, handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EnumMethodInstanceByName( /* [out][in] */ CLRDATA_ENUM* handle, /* [out] */ IXCLRDataMethodInstance **method) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { SplitName* split; split = FROM_CDENUM(SplitName, *handle); for (;;) { AppDomain* appDomain; mdMethodDef token; if ((status = SplitName:: CdNextDomainMethod(handle, &appDomain, &token)) != S_OK) { break; } // If the method doesn't have a MethodDesc or hasn't // been JIT'ed yet it's not an instance and should // just be skipped. if ((status = ClrDataMethodInstance:: NewFromModule(m_dac, appDomain, m_module, token, NULL, method)) != E_INVALIDARG) { break; } } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EndEnumMethodInstancesByName( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = SplitName::CdEnd(handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::GetMethodDefinitionByToken( /* [in] */ mdMethodDef token, /* [out] */ IXCLRDataMethodDefinition **methodDefinition) { HRESULT status; // This isn't critically necessary but it prevents // an assert in the metadata code. if (TypeFromToken(token) != mdtMethodDef) { return E_INVALIDARG; } DAC_ENTER_SUB(m_dac); EX_TRY { status = ClrDataMethodDefinition:: NewFromModule(m_dac, m_module, token, NULL, methodDefinition); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::StartEnumDataByName( /* [in] */ LPCWSTR name, /* [in] */ ULONG32 flags, /* [in] */ IXCLRDataAppDomain* appDomain, /* [in] */ IXCLRDataTask* tlsTask, /* [out] */ CLRDATA_ENUM* handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = SplitName::CdStartField(name, flags, INH_STATIC, NULL, TypeHandle(), m_module, mdTypeDefNil, 0, NULL, tlsTask, NULL, appDomain, NULL, handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EnumDataByName( /* [out][in] */ CLRDATA_ENUM* handle, /* [out] */ IXCLRDataValue **value) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = SplitName::CdNextDomainField(m_dac, handle, value); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EndEnumDataByName( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = SplitName::CdEnd(handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::GetName( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = ConvertUtf8(m_module->GetSimpleName(), bufLen, nameLen, name); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::GetFileName( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ __out_ecount_part(bufLen, *nameLen) WCHAR name[ ]) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { COUNT_T _nameLen; // Try to get the file name through GetPath. // If the returned name is empty, then try to get the guessed module file name. // The guessed file name is propogated from metadata's module name. // if ((m_module->GetFile()->GetPath().DacGetUnicode(bufLen, name, &_nameLen) && name[0])|| (m_module->GetFile()->GetModuleFileNameHint().DacGetUnicode(bufLen, name, &_nameLen) && name[0])) { if (nameLen) { *nameLen = _nameLen; } status = S_OK; } else { status = E_FAIL; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::GetVersionId( /* [out] */ GUID* vid) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { if (!m_module->GetFile()->HasMetadata()) { status = E_NOINTERFACE; } else { GUID mdVid; status = m_module->GetMDImport()->GetScopeProps(NULL, &mdVid); if (SUCCEEDED(status)) { *vid = mdVid; } } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::GetFlags( /* [out] */ ULONG32 *flags) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { *flags = 0; if (m_module->IsReflection()) { (*flags) |= CLRDATA_MODULE_IS_DYNAMIC; } if (m_module->IsIStream()) { (*flags) |= CLRDATA_MODULE_IS_MEMORY_STREAM; } status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::IsSameObject( /* [in] */ IXCLRDataModule* mod) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = (PTR_HOST_TO_TADDR(m_module) == PTR_HOST_TO_TADDR(((ClrDataModule*)mod)-> m_module)) ? S_OK : S_FALSE; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::StartEnumExtents( /* [out] */ CLRDATA_ENUM* handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { if (!m_setExtents) { PEFile* file = m_module->GetFile(); if (!file) { *handle = 0; status = E_INVALIDARG; goto Exit; } CLRDATA_MODULE_EXTENT* extent = m_extents; if (file->GetLoadedImageContents() != NULL) { extent->base = TO_CDADDR( PTR_TO_TADDR(file->GetLoadedImageContents(&extent->length)) ); extent->type = CLRDATA_MODULE_PE_FILE; extent++; } if (file->HasNativeImage()) { extent->base = TO_CDADDR(PTR_TO_TADDR(file->GetLoadedNative()->GetBase())); extent->length = file->GetLoadedNative()->GetVirtualSize(); extent->type = CLRDATA_MODULE_PREJIT_FILE; extent++; } m_setExtents = true; m_extentsEnd = extent; } *handle = TO_CDENUM(m_extents); status = m_extents != m_extentsEnd ? S_OK : S_FALSE; Exit: ; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EnumExtent( /* [in, out] */ CLRDATA_ENUM* handle, /* [out] */ CLRDATA_MODULE_EXTENT *extent) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { CLRDATA_MODULE_EXTENT* curExtent = FROM_CDENUM(CLRDATA_MODULE_EXTENT, *handle); if (!m_setExtents || curExtent < m_extents || curExtent > m_extentsEnd) { status = E_INVALIDARG; } else if (curExtent < m_extentsEnd) { *extent = *curExtent++; *handle = TO_CDENUM(curExtent); status = S_OK; } else { status = S_FALSE; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::EndEnumExtents( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // Enumerator holds no resources. status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT ClrDataModule::RequestGetModulePtr( /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) { // Validate params. // Input: Nothing. // Output: a DacpGetModuleAddress structure. if ((inBufferSize != 0) || (inBuffer != NULL) || (outBufferSize != sizeof(DacpGetModuleAddress)) || (outBuffer == NULL)) { return E_INVALIDARG; } DacpGetModuleAddress * outGMA = reinterpret_cast (outBuffer); outGMA->ModulePtr = TO_CDADDR(PTR_HOST_TO_TADDR(m_module)); return S_OK; } HRESULT ClrDataModule::RequestGetModuleData( /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) { // Validate params. // Input: Nothing. // Output: a DacpGetModuleData structure. if ((inBufferSize != 0) || (inBuffer != NULL) || (outBufferSize != sizeof(DacpGetModuleData)) || (outBuffer == NULL)) { return E_INVALIDARG; } DacpGetModuleData * outGMD = reinterpret_cast(outBuffer); ZeroMemory(outGMD, sizeof(DacpGetModuleData)); Module* pModule = GetModule(); PEFile *pPEFile = pModule->GetFile(); outGMD->PEFile = TO_CDADDR(PTR_HOST_TO_TADDR(pPEFile)); outGMD->IsDynamic = pModule->IsReflection(); if (pPEFile != NULL) { outGMD->IsInMemory = pPEFile->GetPath().IsEmpty(); COUNT_T peSize; outGMD->LoadedPEAddress = TO_CDADDR(PTR_TO_TADDR(pPEFile->GetLoadedImageContents(&peSize))); outGMD->LoadedPESize = (ULONG64)peSize; outGMD->IsFileLayout = pPEFile->GetLoaded()->IsFlat(); } // If there is a in memory symbol stream CGrowableStream* stream = pModule->GetInMemorySymbolStream(); if (stream != NULL) { // Save the in-memory PDB address and size MemoryRange range = stream->GetRawBuffer(); outGMD->InMemoryPdbAddress = TO_CDADDR(PTR_TO_TADDR(range.StartAddress())); outGMD->InMemoryPdbSize = range.Size(); } return S_OK; } HRESULT STDMETHODCALLTYPE ClrDataModule::Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { switch(reqCode) { case CLRDATA_REQUEST_REVISION: if (inBufferSize != 0 || inBuffer || outBufferSize != sizeof(ULONG32)) { status = E_INVALIDARG; } else { *(ULONG32*)outBuffer = 3; status = S_OK; } break; case DACDATAMODULEPRIV_REQUEST_GET_MODULEPTR: status = RequestGetModulePtr(inBufferSize, inBuffer, outBufferSize, outBuffer); break; case DACDATAMODULEPRIV_REQUEST_GET_MODULEDATA: status = RequestGetModuleData(inBufferSize, inBuffer, outBufferSize, outBuffer); break; default: status = E_INVALIDARG; break; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataModule::SetJITCompilerFlags( /* [in] */ DWORD dwFlags) { // Note: this is similar but not equivalent to the DacDbi version of this function HRESULT hr = S_OK; DAC_ENTER_SUB(m_dac); EX_TRY { // can't have a subset of these, eg 0x101, so make sure we have an exact match if ((dwFlags != CORDEBUG_JIT_DEFAULT) && (dwFlags != CORDEBUG_JIT_DISABLE_OPTIMIZATION)) { hr = E_INVALIDARG; } #ifdef FEATURE_PREJIT else if (m_module->HasNativeImage()) { hr = CORDBG_E_CANT_CHANGE_JIT_SETTING_FOR_ZAP_MODULE; } #endif else { _ASSERTE(m_module != NULL); BOOL fAllowJitOpts = ((dwFlags & CORDEBUG_JIT_DISABLE_OPTIMIZATION) != CORDEBUG_JIT_DISABLE_OPTIMIZATION); // Initialize dwBits. DWORD dwBits = (m_module->GetDebuggerInfoBits() & ~(DACF_ALLOW_JIT_OPTS | DACF_ENC_ENABLED)); dwBits &= DACF_CONTROL_FLAGS_MASK; if (fAllowJitOpts) { dwBits |= DACF_ALLOW_JIT_OPTS; } // Settings from the debugger take precedence over all other settings. dwBits |= DACF_USER_OVERRIDE; // set flags. This will write back to the target m_module->SetDebuggerInfoBits((DebuggerAssemblyControlFlags)dwBits); _ASSERTE(SUCCEEDED(hr)); } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &hr)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return hr; } HRESULT ClrDataModule::GetMdInterface(PVOID* retIface) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { if (m_mdImport == NULL) { if (!m_module->GetFile()->HasMetadata()) { status = E_NOINTERFACE; goto Exit; } // // Make sure internal MD is in RW format. // IMDInternalImport* rwMd; status = ConvertMDInternalImport(m_module->GetMDImport(), &rwMd); if (FAILED(status)) { goto Exit; } // If no conversion took place the same interface was // was returned without an AddRef. AddRef now so // that rwMd has a reference either way. if (status == S_FALSE) { rwMd->AddRef(); } status = GetMDPublicInterfaceFromInternal((PVOID)rwMd, IID_IMetaDataImport, (PVOID*)&m_mdImport); rwMd->Release(); if (status != S_OK) { goto Exit; } } _ASSERTE(m_mdImport != NULL); m_mdImport->AddRef(); *retIface = m_mdImport; status = S_OK; Exit: ; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } //---------------------------------------------------------------------------- // // ClrDataMethodDefinition. // //---------------------------------------------------------------------------- ClrDataMethodDefinition::ClrDataMethodDefinition(ClrDataAccess* dac, Module* module, mdMethodDef token, MethodDesc* methodDesc) { m_dac = dac; m_dac->AddRef(); m_instanceAge = m_dac->m_instanceAge; m_refs = 1; m_module = module; m_token = token; m_methodDesc = methodDesc; } ClrDataMethodDefinition::~ClrDataMethodDefinition(void) { m_dac->Release(); } STDMETHODIMP ClrDataMethodDefinition::QueryInterface(THIS_ IN REFIID interfaceId, OUT PVOID* iface) { if (IsEqualIID(interfaceId, IID_IUnknown) || IsEqualIID(interfaceId, __uuidof(IXCLRDataMethodDefinition))) { AddRef(); *iface = static_cast (static_cast(this)); return S_OK; } else { *iface = NULL; return E_NOINTERFACE; } } STDMETHODIMP_(ULONG) ClrDataMethodDefinition::AddRef(THIS) { return InterlockedIncrement(&m_refs); } STDMETHODIMP_(ULONG) ClrDataMethodDefinition::Release(THIS) { SUPPORTS_DAC_HOST_ONLY; LONG newRefs = InterlockedDecrement(&m_refs); if (newRefs == 0) { delete this; } return newRefs; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::GetTypeDefinition( /* [out] */ IXCLRDataTypeDefinition **typeDefinition) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { TypeHandle typeHandle; mdTypeDef token; if (m_methodDesc) { typeHandle = TypeHandle(m_methodDesc->GetMethodTable()); token = typeHandle.GetMethodTable()->GetCl(); } else { if ((status = m_module->GetMDImport()-> GetParentToken(m_token, &token)) != S_OK) { goto Exit; } } *typeDefinition = new (nothrow) ClrDataTypeDefinition(m_dac, m_module, token, typeHandle); status = *typeDefinition ? S_OK : E_OUTOFMEMORY; Exit: ; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::StartEnumInstances( /* [in] */ IXCLRDataAppDomain* appDomain, /* [out] */ CLRDATA_ENUM *handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { if (m_methodDesc) { status = EnumMethodInstances::CdStart(m_methodDesc, appDomain, handle); } else { status = S_FALSE; *handle = 0; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::EnumInstance( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ IXCLRDataMethodInstance **instance) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = EnumMethodInstances::CdNext(m_dac, handle, instance); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::EndEnumInstances( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = EnumMethodInstances::CdEnd(handle); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::GetName( /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ __out_ecount_part_opt(bufLen, *nameLen) WCHAR name[ ]) { HRESULT status; if (flags != 0) { return E_INVALIDARG; } DAC_ENTER_SUB(m_dac); EX_TRY { if (m_methodDesc) { status = m_dac->GetFullMethodName(m_methodDesc, bufLen, nameLen, name); } else { char methName[MAX_CLASSNAME_LENGTH]; status = GetFullMethodNameFromMetadata(m_module->GetMDImport(), m_token, NumItems(methName), methName); if (status == S_OK) { status = ConvertUtf8(methName, bufLen, nameLen, name); } } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::GetTokenAndScope( /* [out] */ mdToken *token, /* [out] */ IXCLRDataModule **Module) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = S_OK; if (token) { *token = m_token; } if (Module) { *Module = new (nothrow) ClrDataModule(m_dac, m_module); status = *Module ? S_OK : E_OUTOFMEMORY; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::GetFlags( /* [out] */ ULONG32 *flags) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = GetSharedMethodFlags(m_methodDesc, flags); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::IsSameObject( /* [in] */ IXCLRDataMethodDefinition* method) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { if (m_methodDesc) { status = (PTR_HOST_TO_TADDR(m_methodDesc) == PTR_HOST_TO_TADDR(((ClrDataMethodDefinition*)method)-> m_methodDesc)) ? S_OK : S_FALSE; } else { status = (PTR_HOST_TO_TADDR(m_module) == PTR_HOST_TO_TADDR(((ClrDataMethodDefinition*)method)-> m_module) && m_token == ((ClrDataMethodDefinition*)method)->m_token) ? S_OK : S_FALSE; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::GetLatestEnCVersion( /* [out] */ ULONG32* version) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. *version = 0; status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::StartEnumExtents( /* [out] */ CLRDATA_ENUM *handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { COR_ILMETHOD* ilMeth = GetIlMethod(); status = ilMeth ? S_OK : S_FALSE; *handle = TO_CDENUM(ilMeth); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::EnumExtent( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ CLRDATA_METHDEF_EXTENT *extent) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { if (*handle) { COR_ILMETHOD* ilMeth = FROM_CDENUM(COR_ILMETHOD, *handle); COR_ILMETHOD_DECODER ilDec(ilMeth); *handle = 0; extent->startAddress = TO_CDADDR(PTR_HOST_TO_TADDR(ilMeth) + 4 * ilDec.GetSize()); extent->endAddress = extent->startAddress + ilDec.GetCodeSize() - 1; extent->type = CLRDATA_METHDEF_IL; // XXX Microsoft - EnC version. extent->enCVersion = 0; status = S_OK; } else { status = E_INVALIDARG; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::EndEnumExtents( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // Nothing to do. status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::GetCodeNotification( /* [out] */ ULONG32 *flags) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { JITNotifications jn(m_dac->GetHostJitNotificationTable()); if (!jn.IsActive()) { status = E_OUTOFMEMORY; } else { TADDR modulePtr = PTR_HOST_TO_TADDR(m_module); *flags = jn.Requested(modulePtr, m_token); status = S_OK; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::SetCodeNotification( /* [in] */ ULONG32 flags) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { if (!IsValidMethodCodeNotification(flags)) { status = E_INVALIDARG; } else { JITNotifications jn(m_dac->GetHostJitNotificationTable()); if (!jn.IsActive()) { status = E_OUTOFMEMORY; } else { TADDR modulePtr = PTR_HOST_TO_TADDR(m_module); USHORT NType = jn.Requested(modulePtr, m_token); if (NType == flags) { // notification already set status = S_OK; } else { if (jn.SetNotification(modulePtr, m_token, flags) && jn.UpdateOutOfProcTable()) { // new notification added status = S_OK; } else { // error setting notification status = E_FAIL; } } } } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::GetRepresentativeEntryAddress( /* [out] */ CLRDATA_ADDRESS* addr) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { COR_ILMETHOD* ilMeth = GetIlMethod(); if (ilMeth) { COR_ILMETHOD_DECODER ilDec(ilMeth); *addr = TO_CDADDR(PTR_HOST_TO_TADDR(ilMeth) + 4 * ilDec.GetSize()); status = S_OK; } else { status = E_UNEXPECTED; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::HasClassOrMethodInstantiation( /* [out] */ BOOL* bGeneric) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { if (m_methodDesc) { *bGeneric = m_methodDesc->HasClassOrMethodInstantiation(); status = S_OK; } else { status = E_UNEXPECTED; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodDefinition::Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { switch(reqCode) { case CLRDATA_REQUEST_REVISION: if (inBufferSize != 0 || inBuffer || outBufferSize != sizeof(ULONG32)) { status = E_INVALIDARG; } else { *(ULONG32*)outBuffer = 1; status = S_OK; } break; default: status = E_INVALIDARG; break; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } COR_ILMETHOD* ClrDataMethodDefinition::GetIlMethod(void) { if (m_methodDesc) { if (!m_methodDesc->HasILHeader()) { return NULL; } else { return m_methodDesc->GetILHeader(); } } else { ULONG ilRva; ULONG implFlags; if (FAILED(m_module->GetMDImport()-> GetMethodImplProps(m_token, &ilRva, &implFlags))) { return NULL; } if (!ilRva) { return NULL; } else { return DacGetIlMethod(m_module->GetIL((RVA)ilRva)); } } } HRESULT ClrDataMethodDefinition::NewFromModule(ClrDataAccess* dac, Module* module, mdMethodDef token, ClrDataMethodDefinition** methDef, IXCLRDataMethodDefinition** pubMethDef) { // The method may not have internal runtime data yet, // so the absence of a MethodDesc is not a failure. // It'll just produce a metadata-query MethoDefinition. MethodDesc* methodDesc = module->LookupMethodDef(token); ClrDataMethodDefinition* def = new (nothrow) ClrDataMethodDefinition(dac, module, token, methodDesc); if (!def) { return E_OUTOFMEMORY; } PREFIX_ASSUME(methDef || pubMethDef); if (methDef) { *methDef = def; } if (pubMethDef) { *pubMethDef = def; } return S_OK; } HRESULT ClrDataMethodDefinition::GetSharedMethodFlags(MethodDesc* methodDesc, ULONG32* flags) { *flags = CLRDATA_METHOD_DEFAULT; if (methodDesc) { MetaSig sig(methodDesc); if (sig.HasThis()) { (*flags) |= CLRDATA_METHOD_HAS_THIS; } } return S_OK; } //---------------------------------------------------------------------------- // // ClrDataMethodInstance. // //---------------------------------------------------------------------------- ClrDataMethodInstance::ClrDataMethodInstance(ClrDataAccess* dac, AppDomain* appDomain, MethodDesc* methodDesc) { m_dac = dac; m_dac->AddRef(); m_instanceAge = m_dac->m_instanceAge; m_refs = 1; m_appDomain = appDomain; m_methodDesc = methodDesc; } ClrDataMethodInstance::~ClrDataMethodInstance(void) { m_dac->Release(); } STDMETHODIMP ClrDataMethodInstance::QueryInterface(THIS_ IN REFIID interfaceId, OUT PVOID* iface) { if (IsEqualIID(interfaceId, IID_IUnknown) || IsEqualIID(interfaceId, __uuidof(IXCLRDataMethodInstance))) { AddRef(); *iface = static_cast (static_cast(this)); return S_OK; } else { *iface = NULL; return E_NOINTERFACE; } } STDMETHODIMP_(ULONG) ClrDataMethodInstance::AddRef(THIS) { SUPPORTS_DAC_HOST_ONLY; return InterlockedIncrement(&m_refs); } STDMETHODIMP_(ULONG) ClrDataMethodInstance::Release(THIS) { LONG newRefs = InterlockedDecrement(&m_refs); if (newRefs == 0) { delete this; } return newRefs; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::GetTypeInstance( /* [out] */ IXCLRDataTypeInstance **typeInstance) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { if (!m_appDomain) { status = E_UNEXPECTED; } else { *typeInstance = new (nothrow) ClrDataTypeInstance(m_dac, m_appDomain, TypeHandle(m_methodDesc-> GetMethodTable())); status = *typeInstance ? S_OK : E_OUTOFMEMORY; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::GetDefinition( /* [out] */ IXCLRDataMethodDefinition **methodDefinition) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { *methodDefinition = new (nothrow) ClrDataMethodDefinition(m_dac, m_methodDesc->GetModule(), m_methodDesc->GetMemberDef(), m_methodDesc); status = *methodDefinition ? S_OK : E_OUTOFMEMORY; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::GetTokenAndScope( /* [out] */ mdToken *token, /* [out] */ IXCLRDataModule **mod) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = S_OK; if (token) { *token = m_methodDesc->GetMemberDef(); } if (mod) { *mod = new (nothrow) ClrDataModule(m_dac, m_methodDesc->GetModule()); status = *mod ? S_OK : E_OUTOFMEMORY; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::GetName( /* [in] */ ULONG32 flags, /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *nameLen, /* [size_is][out] */ __out_ecount_part(bufLen, *nameLen) WCHAR name[ ]) { HRESULT status; if (flags != 0) { return E_INVALIDARG; } DAC_ENTER_SUB(m_dac); EX_TRY { status = m_dac->GetFullMethodName(m_methodDesc, bufLen, nameLen, name); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } else { static WCHAR nameUnk[] = W("Unknown"); wcscpy_s(name, bufLen, nameUnk); if (nameLen != NULL) { *nameLen = _countof(nameUnk); } status = S_OK; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::GetFlags( /* [out] */ ULONG32 *flags) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = ClrDataMethodDefinition:: GetSharedMethodFlags(m_methodDesc, flags); } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::IsSameObject( /* [in] */ IXCLRDataMethodInstance* method) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { status = (PTR_HOST_TO_TADDR(m_appDomain) == PTR_HOST_TO_TADDR(((ClrDataMethodInstance*)method)-> m_appDomain) && PTR_HOST_TO_TADDR(m_methodDesc) == PTR_HOST_TO_TADDR(((ClrDataMethodInstance*)method)-> m_methodDesc)) ? S_OK : S_FALSE; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::GetEnCVersion( /* [out] */ ULONG32* version) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. *version = 0; status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::GetNumTypeArguments( /* [out] */ ULONG32 *numTypeArgs) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::GetTypeArgumentByIndex( /* [in] */ ULONG32 index, /* [out] */ IXCLRDataTypeInstance **typeArg) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::GetILOffsetsByAddress( /* [in] */ CLRDATA_ADDRESS address, /* [in] */ ULONG32 offsetsLen, /* [out] */ ULONG32 *offsetsNeeded, /* [size_is][out] */ ULONG32 ilOffsets[ ]) { HRESULT status; DebuggerILToNativeMap* map = NULL; bool mapAllocated = false; DAC_ENTER_SUB(m_dac); EX_TRY { ULONG32 numMap; ULONG32 codeOffset; ULONG32 hits = 0; #ifdef _TARGET_ARM_ address &= ~THUMB_CODE; // on ARM windbg passes in an address with the mode flag set... need to workaround #endif if ((status = m_dac->GetMethodNativeMap(m_methodDesc, CLRDATA_ADDRESS_TO_TADDR(address), &numMap, &map, &mapAllocated, NULL, &codeOffset)) != S_OK) { goto Exit; } for (ULONG32 i = 0; i < numMap; i++) { if (codeOffset >= map[i].nativeStartOffset && (((LONG)map[i].ilOffset == ICorDebugInfo::EPILOG && !map[i].nativeEndOffset) || codeOffset < map[i].nativeEndOffset)) { hits++; if (offsetsLen && ilOffsets) { *ilOffsets = map[i].ilOffset; ilOffsets++; offsetsLen--; } } } if (offsetsNeeded) { *offsetsNeeded = hits; } status = hits ? S_OK : E_NOINTERFACE; Exit: ; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) if (mapAllocated) { delete [] map; } DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::GetAddressRangesByILOffset( /* [in] */ ULONG32 ilOffset, /* [in] */ ULONG32 rangesLen, /* [out] */ ULONG32 *rangesNeeded, /* [size_is][out] */ CLRDATA_ADDRESS_RANGE addressRanges[ ]) { HRESULT status; DebuggerILToNativeMap* map = NULL; bool mapAllocated = false; DAC_ENTER_SUB(m_dac); EX_TRY { ULONG32 numMap; CLRDATA_ADDRESS codeStart; ULONG32 hits = 0; if ((status = m_dac->GetMethodNativeMap(m_methodDesc, 0, &numMap, &map, &mapAllocated, &codeStart, NULL)) != S_OK) { goto Exit; } for (ULONG32 i = 0; i < numMap; i++) { if (map[i].ilOffset == ilOffset) { hits++; if (rangesLen && addressRanges) { addressRanges->startAddress = TO_CDADDR(codeStart + map[i].nativeStartOffset); if ((LONG)map[i].ilOffset == ICorDebugInfo::EPILOG && !map[i].nativeEndOffset) { addressRanges->endAddress = 0; } else { addressRanges->endAddress = TO_CDADDR(codeStart + map[i].nativeEndOffset); } addressRanges++; rangesLen--; } } } if (rangesNeeded) { *rangesNeeded = hits; } status = hits ? S_OK : E_NOINTERFACE; Exit: ; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) if (mapAllocated) { delete [] map; } DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::GetILAddressMap( /* [in] */ ULONG32 mapLen, /* [out] */ ULONG32 *mapNeeded, /* [size_is][out] */ CLRDATA_IL_ADDRESS_MAP maps[ ]) { HRESULT status; DebuggerILToNativeMap* map = NULL; bool mapAllocated = false; DAC_ENTER_SUB(m_dac); EX_TRY { ULONG32 numMap; CLRDATA_ADDRESS codeStart; if ((status = m_dac->GetMethodNativeMap(m_methodDesc, 0, &numMap, &map, &mapAllocated, &codeStart, NULL)) != S_OK) { goto Exit; } for (ULONG32 i = 0; i < numMap; i++) { if (mapLen && maps) { maps->ilOffset = map[i].ilOffset; maps->startAddress = TO_CDADDR(codeStart + map[i].nativeStartOffset); maps->endAddress = TO_CDADDR(codeStart + map[i].nativeEndOffset); // XXX Microsoft - Define types as mapping of // ICorDebugInfo::SourceTypes. maps->type = CLRDATA_SOURCE_TYPE_INVALID; maps++; mapLen--; } else { break; } } if (mapNeeded) { *mapNeeded = numMap; } status = numMap ? S_OK : E_NOINTERFACE; Exit: ; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) if (mapAllocated) { delete [] map; } DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::StartEnumExtents( /* [out] */ CLRDATA_ENUM *handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { METH_EXTENTS* extents; if ((status = m_dac-> GetMethodExtents(m_methodDesc, &extents)) == S_OK) { *handle = TO_CDENUM(extents); } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::EnumExtent( /* [out][in] */ CLRDATA_ENUM *handle, /* [out] */ CLRDATA_ADDRESS_RANGE *extent) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { METH_EXTENTS* extents = FROM_CDENUM(METH_EXTENTS, *handle); if (extents->curExtent >= extents->numExtents) { status = S_FALSE; } else { CLRDATA_ADDRESS_RANGE* curExtent = extents->extents + extents->curExtent++; *extent = *curExtent; status = S_OK; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::EndEnumExtents( /* [in] */ CLRDATA_ENUM handle) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { delete FROM_CDENUM(METH_EXTENTS, handle); status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::GetRepresentativeEntryAddress( /* [out] */ CLRDATA_ADDRESS* addr) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { if (m_methodDesc->HasNativeCode()) { *addr = TO_CDADDR(m_methodDesc->GetNativeCode()); status = S_OK; } else { status = E_UNEXPECTED; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataMethodInstance::Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { switch(reqCode) { case CLRDATA_REQUEST_REVISION: if (inBufferSize != 0 || inBuffer || outBufferSize != sizeof(ULONG32)) { status = E_INVALIDARG; } else { *(ULONG32*)outBuffer = 1; status = S_OK; } break; default: status = E_INVALIDARG; break; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT ClrDataMethodInstance::NewFromModule(ClrDataAccess* dac, AppDomain* appDomain, Module* module, mdMethodDef token, ClrDataMethodInstance** methInst, IXCLRDataMethodInstance** pubMethInst) { MethodDesc* methodDesc = module->LookupMethodDef(token); if (!methodDesc || !methodDesc->HasNativeCode()) { return E_INVALIDARG; } ClrDataMethodInstance* inst = new (nothrow) ClrDataMethodInstance(dac, appDomain, methodDesc); if (!inst) { return E_OUTOFMEMORY; } PREFIX_ASSUME(methInst || pubMethInst); if (methInst) { *methInst = inst; } if (pubMethInst) { *pubMethInst = inst; } return S_OK; } //---------------------------------------------------------------------------- // // ClrDataExceptionState. // //---------------------------------------------------------------------------- ClrDataExceptionState::ClrDataExceptionState(ClrDataAccess* dac, AppDomain* appDomain, Thread* thread, ULONG32 flags, ClrDataExStateType* exInfo, OBJECTHANDLE throwable, ClrDataExStateType* prevExInfo) { m_dac = dac; m_dac->AddRef(); m_instanceAge = m_dac->m_instanceAge; m_appDomain = appDomain; m_thread = thread; m_flags = flags; m_exInfo = exInfo; m_throwable = throwable; m_prevExInfo = prevExInfo; m_refs = 1; } ClrDataExceptionState::~ClrDataExceptionState(void) { m_dac->Release(); } STDMETHODIMP ClrDataExceptionState::QueryInterface(THIS_ IN REFIID interfaceId, OUT PVOID* iface) { if (IsEqualIID(interfaceId, IID_IUnknown) || IsEqualIID(interfaceId, __uuidof(IXCLRDataExceptionState))) { AddRef(); *iface = static_cast (static_cast(this)); return S_OK; } else { *iface = NULL; return E_NOINTERFACE; } } STDMETHODIMP_(ULONG) ClrDataExceptionState::AddRef(THIS) { return InterlockedIncrement(&m_refs); } STDMETHODIMP_(ULONG) ClrDataExceptionState::Release(THIS) { SUPPORTS_DAC_HOST_ONLY; LONG newRefs = InterlockedDecrement(&m_refs); if (newRefs == 0) { delete this; } return newRefs; } HRESULT STDMETHODCALLTYPE ClrDataExceptionState::GetFlags( /* [out] */ ULONG32 *flags) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { *flags = m_flags; if (m_prevExInfo) { (*flags) |= CLRDATA_EXCEPTION_NESTED; } status = S_OK; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataExceptionState::GetPrevious( /* [out] */ IXCLRDataExceptionState **exState) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { if (m_prevExInfo) { *exState = new (nothrow) ClrDataExceptionState(m_dac, m_appDomain, m_thread, CLRDATA_EXCEPTION_DEFAULT, m_prevExInfo, m_prevExInfo->m_hThrowable, m_prevExInfo->m_pPrevNestedInfo); status = *exState ? S_OK : E_OUTOFMEMORY; } else { *exState = NULL; status = S_FALSE; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataExceptionState::GetManagedObject( /* [out] */ IXCLRDataValue **value) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { PTR_UNCHECKED_OBJECTREF throwRef(m_throwable); if (!throwRef.IsValid()) { status = E_INVALIDARG; goto Exit; } NativeVarLocation varLoc; ClrDataValue* RefVal; varLoc.addr = TO_CDADDR(m_throwable); varLoc.size = sizeof(TADDR); varLoc.contextReg = false; RefVal = new (nothrow) ClrDataValue(m_dac, m_appDomain, m_thread, CLRDATA_VALUE_IS_REFERENCE, TypeHandle((*throwRef)->GetMethodTable()), varLoc.addr, 1, &varLoc); if (!RefVal) { status = E_OUTOFMEMORY; goto Exit; } status = RefVal->GetAssociatedValue(value); delete RefVal; Exit: ; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataExceptionState::GetBaseType( /* [out] */ CLRDataBaseExceptionType *type) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataExceptionState::GetCode( /* [out] */ ULONG32 *code) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { // XXX Microsoft. status = E_NOTIMPL; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataExceptionState::GetString( /* [in] */ ULONG32 bufLen, /* [out] */ ULONG32 *strLen, /* [size_is][out] */ __out_ecount_part(bufLen, *strLen) WCHAR str[ ]) { HRESULT status = E_FAIL; DAC_ENTER_SUB(m_dac); EX_TRY { PTR_UNCHECKED_OBJECTREF throwRef(m_throwable); STRINGREF message = EXCEPTIONREF(*throwRef)->GetMessage(); if (message == NULL) { if (strLen) { *strLen = 0; } if (bufLen >= 1) { str[0] = 0; } status = S_OK; } else { PWSTR msgStr = DacInstantiateStringW((TADDR)message->GetBuffer(), message->GetStringLength(), true); status = StringCchCopy(str, bufLen, msgStr) == S_OK ? S_OK : S_FALSE; if (strLen != NULL) { size_t cchName = wcslen(msgStr) + 1; if (FitsIn(cchName)) { *strLen = (ULONG32) cchName; } else { status = COR_E_OVERFLOW; } } } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataExceptionState::IsSameState( /* [in] */ EXCEPTION_RECORD64 *exRecord, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE cxRecord[ ]) { return IsSameState2(CLRDATA_EXSAME_SECOND_CHANCE, exRecord, contextSize, cxRecord); } HRESULT STDMETHODCALLTYPE ClrDataExceptionState::IsSameState2( /* [in] */ ULONG32 flags, /* [in] */ EXCEPTION_RECORD64 *exRecord, /* [in] */ ULONG32 contextSize, /* [size_is][in] */ BYTE cxRecord[ ]) { HRESULT status; if ((flags & ~(CLRDATA_EXSAME_SECOND_CHANCE | CLRDATA_EXSAME_FIRST_CHANCE)) != 0) { return E_INVALIDARG; } DAC_ENTER_SUB(m_dac); EX_TRY { PTR_EXCEPTION_RECORD infoExRecord; // XXX Microsoft - This should also check that the // context matches the context at the time // of the exception, but it's not clear // how to do that in all cases. status = S_FALSE; if (!m_exInfo) { // We don't have full state, but that's expected // on a first chance exception so allow that. if ((flags & CLRDATA_EXSAME_FIRST_CHANCE) != 0) { status = S_OK; } goto Exit; } infoExRecord = GetCurrentExceptionRecord(); if ((TADDR)infoExRecord->ExceptionAddress == (TADDR)exRecord->ExceptionAddress) { status = S_OK; } Exit: ; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataExceptionState::GetTask( /* [out] */ IXCLRDataTask** task) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { *task = new (nothrow) ClrDataTask(m_dac, m_thread); status = *task ? S_OK : E_OUTOFMEMORY; } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT STDMETHODCALLTYPE ClrDataExceptionState::Request( /* [in] */ ULONG32 reqCode, /* [in] */ ULONG32 inBufferSize, /* [size_is][in] */ BYTE *inBuffer, /* [in] */ ULONG32 outBufferSize, /* [size_is][out] */ BYTE *outBuffer) { HRESULT status; DAC_ENTER_SUB(m_dac); EX_TRY { switch(reqCode) { case CLRDATA_REQUEST_REVISION: if (inBufferSize != 0 || inBuffer || outBufferSize != sizeof(ULONG32)) { status = E_INVALIDARG; } else { *(ULONG32*)outBuffer = 2; status = S_OK; } break; default: status = E_INVALIDARG; break; } } EX_CATCH { if (!DacExceptionFilter(GET_EXCEPTION(), m_dac, &status)) { EX_RETHROW; } } EX_END_CATCH(SwallowAllExceptions) DAC_LEAVE(); return status; } HRESULT ClrDataExceptionState::NewFromThread(ClrDataAccess* dac, Thread* thread, ClrDataExceptionState** exception, IXCLRDataExceptionState** pubException) { if (!thread->HasException()) { return E_NOINTERFACE; } ClrDataExStateType* exState; ClrDataExceptionState* exIf; #ifdef WIN64EXCEPTIONS exState = thread->GetExceptionState()->m_pCurrentTracker; #else exState = &(thread->GetExceptionState()->m_currentExInfo); #endif // WIN64EXCEPTIONS exIf = new (nothrow) ClrDataExceptionState(dac, thread->GetDomain(), thread, CLRDATA_EXCEPTION_DEFAULT, exState, exState->m_hThrowable, exState->m_pPrevNestedInfo); if (!exIf) { return E_OUTOFMEMORY; } PREFIX_ASSUME(exception || pubException); if (exception) { *exception = exIf; } if (pubException) { *pubException = exIf; } return S_OK; } PTR_EXCEPTION_RECORD ClrDataExceptionState::GetCurrentExceptionRecord() { PTR_EXCEPTION_RECORD pExRecord = NULL; #ifdef WIN64EXCEPTIONS pExRecord = m_exInfo->m_ptrs.ExceptionRecord; #else // WIN64EXCEPTIONS pExRecord = m_exInfo->m_pExceptionRecord; #endif // WIN64EXCEPTIONS return pExRecord; } PTR_CONTEXT ClrDataExceptionState::GetCurrentContextRecord() { PTR_CONTEXT pContext = NULL; #ifdef WIN64EXCEPTIONS pContext = m_exInfo->m_ptrs.ContextRecord; #else // WIN64EXCEPTIONS pContext = m_exInfo->m_pContext; #endif // WIN64EXCEPTIONS return pContext; } //---------------------------------------------------------------------------- // // EnumMethodDefinitions. // //---------------------------------------------------------------------------- HRESULT EnumMethodDefinitions::Start(Module* mod, bool useAddrFilter, CLRDATA_ADDRESS addrFilter) { m_module = mod; m_useAddrFilter = useAddrFilter; m_addrFilter = addrFilter; m_typeToken = mdTokenNil; m_needMethodStart = true; return m_typeEnum.Start(m_module->GetMDImport(), mdtTypeDef, mdTokenNil); } HRESULT EnumMethodDefinitions::Next(ClrDataAccess* dac, IXCLRDataMethodDefinition **method) { HRESULT status; NextType: if (m_typeToken == mdTokenNil) { if ((status = m_typeEnum.NextToken(&m_typeToken, NULL, NULL)) != S_OK) { return status; } m_needMethodStart = true; } if (m_needMethodStart) { if ((status = m_methodEnum. Start(m_module->GetMDImport(), mdtMethodDef, m_typeToken)) != S_OK) { return status; } m_needMethodStart = false; } NextMethod: mdToken methodToken; if ((status = m_methodEnum.NextToken(&methodToken, NULL, NULL)) != S_OK) { if (status == S_FALSE) { m_typeToken = mdTokenNil; goto NextType; } return status; } if (m_useAddrFilter) { ULONG ilRva; ULONG implFlags; status = m_module->GetMDImport()-> GetMethodImplProps(methodToken, &ilRva, &implFlags); if (FAILED(status)) { return status; } if (!ilRva) { goto NextMethod; } COR_ILMETHOD* ilMeth = DacGetIlMethod(m_module->GetIL((RVA)ilRva)); COR_ILMETHOD_DECODER ilDec(ilMeth); CLRDATA_ADDRESS start = TO_CDADDR(PTR_HOST_TO_TADDR(ilMeth) + 4 * ilDec.GetSize()); if (m_addrFilter < start || m_addrFilter > start + ilDec.GetCodeSize() - 1) { goto NextMethod; } } return ClrDataMethodDefinition:: NewFromModule(dac, m_module, methodToken, NULL, method); } HRESULT EnumMethodDefinitions::CdStart(Module* mod, bool useAddrFilter, CLRDATA_ADDRESS addrFilter, CLRDATA_ENUM* handle) { HRESULT status; *handle = NULL; if (!mod) { return S_FALSE; } EnumMethodDefinitions* iter = new (nothrow) EnumMethodDefinitions; if (!iter) { return E_OUTOFMEMORY; } if ((status = iter->Start(mod, useAddrFilter, addrFilter)) != S_OK) { delete iter; return status; } *handle = TO_CDENUM(iter); return S_OK; } HRESULT EnumMethodDefinitions::CdNext(ClrDataAccess* dac, CLRDATA_ENUM* handle, IXCLRDataMethodDefinition** method) { EnumMethodDefinitions* iter = FROM_CDENUM(EnumMethodDefinitions, *handle); if (!iter) { return S_FALSE; } return iter->Next(dac, method); } HRESULT EnumMethodDefinitions::CdEnd(CLRDATA_ENUM handle) { EnumMethodDefinitions* iter = FROM_CDENUM(EnumMethodDefinitions, handle); if (iter) { delete iter; return S_OK; } else { return E_INVALIDARG; } } //---------------------------------------------------------------------------- // // EnumMethodInstances. // //---------------------------------------------------------------------------- EnumMethodInstances::EnumMethodInstances(MethodDesc* methodDesc, IXCLRDataAppDomain* givenAppDomain) : m_domainIter(FALSE) { m_methodDesc = methodDesc; if (givenAppDomain) { m_givenAppDomain = ((ClrDataAppDomain*)givenAppDomain)->GetAppDomain(); } else { m_givenAppDomain = NULL; } m_givenAppDomainUsed = false; m_appDomain = NULL; } HRESULT EnumMethodInstances::Next(ClrDataAccess* dac, IXCLRDataMethodInstance **instance) { NextDomain: if (!m_appDomain) { if (m_givenAppDomainUsed || !m_domainIter.Next()) { return S_FALSE; } if (m_givenAppDomain) { m_appDomain = m_givenAppDomain; m_givenAppDomainUsed = true; } else { m_appDomain = m_domainIter.GetDomain(); } m_methodIter.Start(m_appDomain, m_methodDesc->GetModule(), // module m_methodDesc->GetMemberDef(), // token m_methodDesc); // intial method desc } NextMethod: { // Note: DAC doesn't need to keep the assembly alive - see code:CollectibleAssemblyHolder#CAH_DAC CollectibleAssemblyHolder pDomainAssembly; if (!m_methodIter.Next(pDomainAssembly.This())) { m_appDomain = NULL; goto NextDomain; } } if (!m_methodIter.Current()->HasNativeCode()) { goto NextMethod; } *instance = new (nothrow) ClrDataMethodInstance(dac, m_appDomain, m_methodIter.Current()); return *instance ? S_OK : E_OUTOFMEMORY; } HRESULT EnumMethodInstances::CdStart(MethodDesc* methodDesc, IXCLRDataAppDomain* appDomain, CLRDATA_ENUM* handle) { if (!methodDesc->HasClassOrMethodInstantiation() && !methodDesc->HasNativeCode()) { *handle = 0; return S_FALSE; } EnumMethodInstances* iter = new (nothrow) EnumMethodInstances(methodDesc, appDomain); if (iter) { *handle = TO_CDENUM(iter); return S_OK; } else { *handle = 0; return E_OUTOFMEMORY; } } HRESULT EnumMethodInstances::CdNext(ClrDataAccess* dac, CLRDATA_ENUM* handle, IXCLRDataMethodInstance** method) { EnumMethodInstances* iter = FROM_CDENUM(EnumMethodInstances, *handle); if (!iter) { return S_FALSE; } return iter->Next(dac, method); } HRESULT EnumMethodInstances::CdEnd(CLRDATA_ENUM handle) { EnumMethodInstances* iter = FROM_CDENUM(EnumMethodInstances, handle); if (iter) { delete iter; return S_OK; } else { return E_INVALIDARG; } }