diff options
Diffstat (limited to 'src/debug/daccess/task.cpp')
-rw-r--r-- | src/debug/daccess/task.cpp | 5335 |
1 files changed, 5335 insertions, 0 deletions
diff --git a/src/debug/daccess/task.cpp b/src/debug/daccess/task.cpp new file mode 100644 index 0000000000..601ad401af --- /dev/null +++ b/src/debug/daccess/task.cpp @@ -0,0 +1,5335 @@ +// 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<IUnknown*> + (static_cast<IXCLRDataTask*>(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<IXCLRDataProcess*>(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<IXCLRDataStackWalk*>(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<IUnknown*> + (static_cast<IXCLRDataAppDomain*>(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<IXCLRDataProcess*>(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<ULONG32>(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<IUnknown*> + (static_cast<IXCLRDataAssembly*>(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<IUnknown*> + (static_cast<IXCLRDataModule*>(this)); + return S_OK; + } + else if (IsEqualIID(interfaceId, __uuidof(IXCLRDataModule2))) + { + AddRef(); + *iface = static_cast<IUnknown*> + (static_cast<IXCLRDataModule2*>(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<DacpGetModuleAddress *> (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<DacpGetModuleData *>(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<IUnknown*> + (static_cast<IXCLRDataMethodDefinition*>(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<IUnknown*> + (static_cast<IXCLRDataMethodInstance*>(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<IUnknown*> + (static_cast<IXCLRDataExceptionState*>(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<ULONG32>(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<DomainAssembly *> 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; + } +} |