From 9caad3ee0c154840b2cffe2334d782acbfe30f94 Mon Sep 17 00:00:00 2001 From: Juan Hoyos <19413848+hoyosjs@users.noreply.github.com> Date: Thu, 25 Jun 2026 12:11:28 -0700 Subject: [PATCH 1/4] Use noop IMDImporter in dia --- src/coreclr/vm/CMakeLists.txt | 2 + src/coreclr/vm/ceeload.cpp | 27 ++-- src/coreclr/vm/noopmetadataimport.cpp | 191 ++++++++++++++++++++++++++ src/coreclr/vm/noopmetadataimport.h | 117 ++++++++++++++++ 4 files changed, 329 insertions(+), 8 deletions(-) create mode 100644 src/coreclr/vm/noopmetadataimport.cpp create mode 100644 src/coreclr/vm/noopmetadataimport.h diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 451c83760879a6..235e3eddf41393 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -361,6 +361,7 @@ set(VM_SOURCES_WKS nativeeventsource.cpp nativelibrary.cpp nativelibrarynative.cpp + noopmetadataimport.cpp pendingload.cpp pinvokeoverride.cpp profdetach.cpp @@ -467,6 +468,7 @@ set(VM_HEADERS_WKS multicorejit.h multicorejitimpl.h nativeeventsource.h + noopmetadataimport.h pendingload.h profdetach.h profilingenumerators.h diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index a729f1b240846e..4be3ddba58aaf3 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -34,6 +34,9 @@ #include "virtualcallstub.h" #include "typestring.h" #include "stringliteralmap.h" +#ifndef DACCESS_COMPILE +#include "noopmetadataimport.h" +#endif #include #include "fieldmarshaler.h" #include "sigbuilder.h" @@ -1807,7 +1810,14 @@ ISymUnmanagedReader *Module::GetISymUnmanagedReader(void) } if (SUCCEEDED(hr)) { - hr = pBinder->GetReaderFromStream(GetRWImporter(), pIStream, &pReader); + // Hand the reader an inert importer rather than the module's real + // (RW) metadata interface: the reader only needs it to satisfy the + // binder, and producing the real importer would force this module's + // metadata to its locked RW backing store. See noopmetadataimport.h. + IUnknown* pNoopImport = NoopMetadataImport::GetInstance(); + hr = (pNoopImport != NULL) + ? pBinder->GetReaderFromStream(pNoopImport, pIStream, &pReader) + : E_OUTOFMEMORY; } } else @@ -1815,13 +1825,14 @@ ISymUnmanagedReader *Module::GetISymUnmanagedReader(void) // The assembly is on disk, so try and load symbols based on the path to the assembly (case 1) const SString &path = m_pPEAssembly->GetPath(); - // Call Fusion to ensure that any PDB's are shadow copied before - // trying to get a symbol reader. This has to be done once per - // Assembly. - ReleaseHolder pUnk = NULL; - hr = GetReadablePublicMetaDataInterface(ofReadOnly, IID_IMetaDataImport, &pUnk); - if (SUCCEEDED(hr)) - hr = pBinder->GetReaderForFile(pUnk, path, NULL, &pReader); + // Hand the reader an inert importer rather than a readable metadata + // interface for this module: the reader only needs it to satisfy the + // binder, and obtaining the real importer would force this module's + // metadata to its locked RW backing store. See noopmetadataimport.h. + IUnknown* pNoopImport = NoopMetadataImport::GetInstance(); + hr = (pNoopImport != NULL) + ? pBinder->GetReaderForFile(pNoopImport, path, NULL, &pReader) + : E_OUTOFMEMORY; } if (SUCCEEDED(hr)) diff --git a/src/coreclr/vm/noopmetadataimport.cpp b/src/coreclr/vm/noopmetadataimport.cpp new file mode 100644 index 00000000000000..096f1cc84fd5be --- /dev/null +++ b/src/coreclr/vm/noopmetadataimport.cpp @@ -0,0 +1,191 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// +// NoopMetadataImport implementation. See noopmetadataimport.h for design. + +#include "common.h" + +#ifndef DACCESS_COMPILE + +#include "noopmetadataimport.h" + +// Every method asserts in debug so an unexpected call (a future reader consumer +// that walks constant/local signatures, or a diasymreader change) is caught +// immediately; release builds return E_NOTIMPL. +#ifdef _DEBUG +#define NOOPMD_NYI(name) \ + do { \ + _ASSERTE_MSG(false, \ + "NoopMetadataImport: unexpected call to " #name ". This importer is " \ + "handed to Microsoft.DiaSymReader.Native only to satisfy the binder; the " \ + "reader is expected to resolve sequence points without calling back into " \ + "it. A call here means that assumption no longer holds."); \ + return E_NOTIMPL; \ + } while (0) +#else +#define NOOPMD_NYI(name) return E_NOTIMPL +#endif + +// --------------------------------------------------------------------------- +// Singleton accessor +// --------------------------------------------------------------------------- + +IUnknown* NoopMetadataImport::GetInstance() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + // Lazily created once and intentionally leaked for the process lifetime, so + // there is no static-initialization ordering or teardown to reason about. + static NoopMetadataImport* volatile s_pInstance = NULL; + + NoopMetadataImport* pInstance = VolatileLoad(&s_pInstance); + if (pInstance == NULL) + { + NoopMetadataImport* pNew = new (nothrow) NoopMetadataImport(); + if (pNew == NULL) + return NULL; + + if (InterlockedCompareExchangeT(&s_pInstance, pNew, (NoopMetadataImport*)NULL) != NULL) + delete pNew; // lost the race; another thread published first + + pInstance = VolatileLoad(&s_pInstance); + } + + return static_cast(pInstance); +} + +// --------------------------------------------------------------------------- +// IUnknown +// --------------------------------------------------------------------------- + +STDMETHODIMP NoopMetadataImport::QueryInterface(REFIID riid, void** ppvObject) +{ + LIMITED_METHOD_CONTRACT; + + if (ppvObject == NULL) + return E_POINTER; + + *ppvObject = NULL; + + // IMetaDataImport2 derives from IMetaDataImport derives from IUnknown -- a + // single-inheritance chain -- so one pointer, the IMetaDataImport2*, is the + // layout-compatible answer for all three IIDs. IID_IGetIMDInternalImport (the + // public->internal back-conversion the runtime uses to push a module to RW + // metadata) is intentionally not exposed. + if (riid == IID_IUnknown || + riid == IID_IMetaDataImport || + riid == IID_IMetaDataImport2) + { + *ppvObject = static_cast(this); + AddRef(); + return S_OK; + } + + return E_NOINTERFACE; +} + +// The singleton lives for the process, so refcounting is a no-op: returning a +// constant tells COM callers the object is never destroyed. +STDMETHODIMP_(ULONG) NoopMetadataImport::AddRef() +{ + LIMITED_METHOD_CONTRACT; + return 1; +} + +STDMETHODIMP_(ULONG) NoopMetadataImport::Release() +{ + LIMITED_METHOD_CONTRACT; + return 1; +} + +// --------------------------------------------------------------------------- +// Fail-fast stubs for every metadata method. +// --------------------------------------------------------------------------- + +STDMETHODIMP_(void) NoopMetadataImport::CloseEnum(HCORENUM /*hEnum*/) { LIMITED_METHOD_CONTRACT; _ASSERTE_MSG(false, "NoopMetadataImport::CloseEnum NYI"); } +STDMETHODIMP NoopMetadataImport::CountEnum(HCORENUM, ULONG*) { NOOPMD_NYI(CountEnum); } +STDMETHODIMP NoopMetadataImport::ResetEnum(HCORENUM, ULONG) { NOOPMD_NYI(ResetEnum); } +STDMETHODIMP NoopMetadataImport::EnumTypeDefs(HCORENUM*, mdTypeDef[], ULONG, ULONG*) { NOOPMD_NYI(EnumTypeDefs); } +STDMETHODIMP NoopMetadataImport::EnumInterfaceImpls(HCORENUM*, mdTypeDef, mdInterfaceImpl[], ULONG, ULONG*) { NOOPMD_NYI(EnumInterfaceImpls); } +STDMETHODIMP NoopMetadataImport::EnumTypeRefs(HCORENUM*, mdTypeRef[], ULONG, ULONG*) { NOOPMD_NYI(EnumTypeRefs); } +STDMETHODIMP NoopMetadataImport::FindTypeDefByName(LPCWSTR, mdToken, mdTypeDef*) { NOOPMD_NYI(FindTypeDefByName); } +STDMETHODIMP NoopMetadataImport::GetScopeProps(LPWSTR, ULONG, ULONG*, GUID*) { NOOPMD_NYI(GetScopeProps); } +STDMETHODIMP NoopMetadataImport::GetModuleFromScope(mdModule*) { NOOPMD_NYI(GetModuleFromScope); } +STDMETHODIMP NoopMetadataImport::GetTypeDefProps(mdTypeDef, LPWSTR, ULONG, ULONG*, DWORD*, mdToken*) { NOOPMD_NYI(GetTypeDefProps); } +STDMETHODIMP NoopMetadataImport::GetInterfaceImplProps(mdInterfaceImpl, mdTypeDef*, mdToken*) { NOOPMD_NYI(GetInterfaceImplProps); } +STDMETHODIMP NoopMetadataImport::GetTypeRefProps(mdTypeRef, mdToken*, LPWSTR, ULONG, ULONG*) { NOOPMD_NYI(GetTypeRefProps); } +STDMETHODIMP NoopMetadataImport::ResolveTypeRef(mdTypeRef, REFIID, IUnknown**, mdTypeDef*) { NOOPMD_NYI(ResolveTypeRef); } +STDMETHODIMP NoopMetadataImport::EnumMembers(HCORENUM*, mdTypeDef, mdToken[], ULONG, ULONG*) { NOOPMD_NYI(EnumMembers); } +STDMETHODIMP NoopMetadataImport::EnumMembersWithName(HCORENUM*, mdTypeDef, LPCWSTR, mdToken[], ULONG, ULONG*) { NOOPMD_NYI(EnumMembersWithName); } +STDMETHODIMP NoopMetadataImport::EnumMethods(HCORENUM*, mdTypeDef, mdMethodDef[], ULONG, ULONG*) { NOOPMD_NYI(EnumMethods); } +STDMETHODIMP NoopMetadataImport::EnumMethodsWithName(HCORENUM*, mdTypeDef, LPCWSTR, mdMethodDef[], ULONG, ULONG*) { NOOPMD_NYI(EnumMethodsWithName); } +STDMETHODIMP NoopMetadataImport::EnumFields(HCORENUM*, mdTypeDef, mdFieldDef[], ULONG, ULONG*) { NOOPMD_NYI(EnumFields); } +STDMETHODIMP NoopMetadataImport::EnumFieldsWithName(HCORENUM*, mdTypeDef, LPCWSTR, mdFieldDef[], ULONG, ULONG*) { NOOPMD_NYI(EnumFieldsWithName); } +STDMETHODIMP NoopMetadataImport::EnumParams(HCORENUM*, mdMethodDef, mdParamDef[], ULONG, ULONG*) { NOOPMD_NYI(EnumParams); } +STDMETHODIMP NoopMetadataImport::EnumMemberRefs(HCORENUM*, mdToken, mdMemberRef[], ULONG, ULONG*) { NOOPMD_NYI(EnumMemberRefs); } +STDMETHODIMP NoopMetadataImport::EnumMethodImpls(HCORENUM*, mdTypeDef, mdToken[], mdToken[], ULONG, ULONG*) { NOOPMD_NYI(EnumMethodImpls); } +STDMETHODIMP NoopMetadataImport::EnumPermissionSets(HCORENUM*, mdToken, DWORD, mdPermission[], ULONG, ULONG*) { NOOPMD_NYI(EnumPermissionSets); } +STDMETHODIMP NoopMetadataImport::FindMember(mdTypeDef, LPCWSTR, PCCOR_SIGNATURE, ULONG, mdToken*) { NOOPMD_NYI(FindMember); } +STDMETHODIMP NoopMetadataImport::FindMethod(mdTypeDef, LPCWSTR, PCCOR_SIGNATURE, ULONG, mdMethodDef*) { NOOPMD_NYI(FindMethod); } +STDMETHODIMP NoopMetadataImport::FindField(mdTypeDef, LPCWSTR, PCCOR_SIGNATURE, ULONG, mdFieldDef*) { NOOPMD_NYI(FindField); } +STDMETHODIMP NoopMetadataImport::FindMemberRef(mdTypeRef, LPCWSTR, PCCOR_SIGNATURE, ULONG, mdMemberRef*) { NOOPMD_NYI(FindMemberRef); } +STDMETHODIMP NoopMetadataImport::GetMethodProps(mdMethodDef, mdTypeDef*, LPWSTR, ULONG, ULONG*, DWORD*, PCCOR_SIGNATURE*, ULONG*, ULONG*, DWORD*) { NOOPMD_NYI(GetMethodProps); } +STDMETHODIMP NoopMetadataImport::GetMemberRefProps(mdMemberRef, mdToken*, LPWSTR, ULONG, ULONG*, PCCOR_SIGNATURE*, ULONG*) { NOOPMD_NYI(GetMemberRefProps); } +STDMETHODIMP NoopMetadataImport::EnumProperties(HCORENUM*, mdTypeDef, mdProperty[], ULONG, ULONG*) { NOOPMD_NYI(EnumProperties); } +STDMETHODIMP NoopMetadataImport::EnumEvents(HCORENUM*, mdTypeDef, mdEvent[], ULONG, ULONG*) { NOOPMD_NYI(EnumEvents); } +STDMETHODIMP NoopMetadataImport::GetEventProps(mdEvent, mdTypeDef*, LPCWSTR, ULONG, ULONG*, DWORD*, mdToken*, mdMethodDef*, mdMethodDef*, mdMethodDef*, mdMethodDef[], ULONG, ULONG*) { NOOPMD_NYI(GetEventProps); } +STDMETHODIMP NoopMetadataImport::EnumMethodSemantics(HCORENUM*, mdMethodDef, mdToken[], ULONG, ULONG*) { NOOPMD_NYI(EnumMethodSemantics); } +STDMETHODIMP NoopMetadataImport::GetMethodSemantics(mdMethodDef, mdToken, DWORD*) { NOOPMD_NYI(GetMethodSemantics); } +STDMETHODIMP NoopMetadataImport::GetClassLayout(mdTypeDef, DWORD*, COR_FIELD_OFFSET[], ULONG, ULONG*, ULONG*) { NOOPMD_NYI(GetClassLayout); } +STDMETHODIMP NoopMetadataImport::GetFieldMarshal(mdToken, PCCOR_SIGNATURE*, ULONG*) { NOOPMD_NYI(GetFieldMarshal); } +STDMETHODIMP NoopMetadataImport::GetRVA(mdToken, ULONG*, DWORD*) { NOOPMD_NYI(GetRVA); } +STDMETHODIMP NoopMetadataImport::GetPermissionSetProps(mdPermission, DWORD*, void const**, ULONG*) { NOOPMD_NYI(GetPermissionSetProps); } +STDMETHODIMP NoopMetadataImport::GetModuleRefProps(mdModuleRef, LPWSTR, ULONG, ULONG*) { NOOPMD_NYI(GetModuleRefProps); } +STDMETHODIMP NoopMetadataImport::EnumModuleRefs(HCORENUM*, mdModuleRef[], ULONG, ULONG*) { NOOPMD_NYI(EnumModuleRefs); } +STDMETHODIMP NoopMetadataImport::GetTypeSpecFromToken(mdTypeSpec, PCCOR_SIGNATURE*, ULONG*) { NOOPMD_NYI(GetTypeSpecFromToken); } +STDMETHODIMP NoopMetadataImport::GetNameFromToken(mdToken, MDUTF8CSTR*) { NOOPMD_NYI(GetNameFromToken); } +STDMETHODIMP NoopMetadataImport::EnumUnresolvedMethods(HCORENUM*, mdToken[], ULONG, ULONG*) { NOOPMD_NYI(EnumUnresolvedMethods); } +STDMETHODIMP NoopMetadataImport::GetUserString(mdString, LPWSTR, ULONG, ULONG*) { NOOPMD_NYI(GetUserString); } +STDMETHODIMP NoopMetadataImport::GetPinvokeMap(mdToken, DWORD*, LPWSTR, ULONG, ULONG*, mdModuleRef*) { NOOPMD_NYI(GetPinvokeMap); } +STDMETHODIMP NoopMetadataImport::EnumSignatures(HCORENUM*, mdSignature[], ULONG, ULONG*) { NOOPMD_NYI(EnumSignatures); } +STDMETHODIMP NoopMetadataImport::EnumTypeSpecs(HCORENUM*, mdTypeSpec[], ULONG, ULONG*) { NOOPMD_NYI(EnumTypeSpecs); } +STDMETHODIMP NoopMetadataImport::EnumUserStrings(HCORENUM*, mdString[], ULONG, ULONG*) { NOOPMD_NYI(EnumUserStrings); } +STDMETHODIMP NoopMetadataImport::GetParamForMethodIndex(mdMethodDef, ULONG, mdParamDef*) { NOOPMD_NYI(GetParamForMethodIndex); } +STDMETHODIMP NoopMetadataImport::EnumCustomAttributes(HCORENUM*, mdToken, mdToken, mdCustomAttribute[], ULONG, ULONG*) { NOOPMD_NYI(EnumCustomAttributes); } +STDMETHODIMP NoopMetadataImport::GetCustomAttributeProps(mdCustomAttribute, mdToken*, mdToken*, void const**, ULONG*) { NOOPMD_NYI(GetCustomAttributeProps); } +STDMETHODIMP NoopMetadataImport::FindTypeRef(mdToken, LPCWSTR, mdTypeRef*) { NOOPMD_NYI(FindTypeRef); } +STDMETHODIMP NoopMetadataImport::GetMemberProps(mdToken, mdTypeDef*, LPWSTR, ULONG, ULONG*, DWORD*, PCCOR_SIGNATURE*, ULONG*, ULONG*, DWORD*, DWORD*, UVCP_CONSTANT*, ULONG*) { NOOPMD_NYI(GetMemberProps); } +STDMETHODIMP NoopMetadataImport::GetFieldProps(mdFieldDef, mdTypeDef*, LPWSTR, ULONG, ULONG*, DWORD*, PCCOR_SIGNATURE*, ULONG*, DWORD*, UVCP_CONSTANT*, ULONG*) { NOOPMD_NYI(GetFieldProps); } +STDMETHODIMP NoopMetadataImport::GetPropertyProps(mdProperty, mdTypeDef*, LPCWSTR, ULONG, ULONG*, DWORD*, PCCOR_SIGNATURE*, ULONG*, DWORD*, UVCP_CONSTANT*, ULONG*, mdMethodDef*, mdMethodDef*, mdMethodDef[], ULONG, ULONG*) { NOOPMD_NYI(GetPropertyProps); } +STDMETHODIMP NoopMetadataImport::GetParamProps(mdParamDef, mdMethodDef*, ULONG*, LPWSTR, ULONG, ULONG*, DWORD*, DWORD*, UVCP_CONSTANT*, ULONG*) { NOOPMD_NYI(GetParamProps); } +STDMETHODIMP NoopMetadataImport::GetCustomAttributeByName(mdToken, LPCWSTR, const void**, ULONG*) { NOOPMD_NYI(GetCustomAttributeByName); } + +STDMETHODIMP_(BOOL) NoopMetadataImport::IsValidToken(mdToken /*tk*/) +{ + LIMITED_METHOD_CONTRACT; + _ASSERTE_MSG(false, "NoopMetadataImport::IsValidToken NYI"); + return FALSE; +} + +STDMETHODIMP NoopMetadataImport::GetNestedClassProps(mdTypeDef, mdTypeDef*) { NOOPMD_NYI(GetNestedClassProps); } +STDMETHODIMP NoopMetadataImport::GetNativeCallConvFromSig(void const*, ULONG, ULONG*) { NOOPMD_NYI(GetNativeCallConvFromSig); } +STDMETHODIMP NoopMetadataImport::IsGlobal(mdToken, int*) { NOOPMD_NYI(IsGlobal); } +STDMETHODIMP NoopMetadataImport::GetSigFromToken(mdSignature, PCCOR_SIGNATURE*, ULONG*) { NOOPMD_NYI(GetSigFromToken); } + +// IMetaDataImport2 +STDMETHODIMP NoopMetadataImport::EnumGenericParams(HCORENUM*, mdToken, mdGenericParam[], ULONG, ULONG*) { NOOPMD_NYI(EnumGenericParams); } +STDMETHODIMP NoopMetadataImport::GetGenericParamProps(mdGenericParam, ULONG*, DWORD*, mdToken*, DWORD*, LPWSTR, ULONG, ULONG*) { NOOPMD_NYI(GetGenericParamProps); } +STDMETHODIMP NoopMetadataImport::GetMethodSpecProps(mdMethodSpec, mdToken*, PCCOR_SIGNATURE*, ULONG*) { NOOPMD_NYI(GetMethodSpecProps); } +STDMETHODIMP NoopMetadataImport::EnumGenericParamConstraints(HCORENUM*, mdGenericParam, mdGenericParamConstraint[], ULONG, ULONG*) { NOOPMD_NYI(EnumGenericParamConstraints); } +STDMETHODIMP NoopMetadataImport::GetGenericParamConstraintProps(mdGenericParamConstraint, mdGenericParam*, mdToken*) { NOOPMD_NYI(GetGenericParamConstraintProps); } +STDMETHODIMP NoopMetadataImport::GetPEKind(DWORD*, DWORD*) { NOOPMD_NYI(GetPEKind); } +STDMETHODIMP NoopMetadataImport::GetVersionString(LPWSTR, DWORD, DWORD*) { NOOPMD_NYI(GetVersionString); } +STDMETHODIMP NoopMetadataImport::EnumMethodSpecs(HCORENUM*, mdToken, mdMethodSpec[], ULONG, ULONG*) { NOOPMD_NYI(EnumMethodSpecs); } + +#endif // !DACCESS_COMPILE diff --git a/src/coreclr/vm/noopmetadataimport.h b/src/coreclr/vm/noopmetadataimport.h new file mode 100644 index 00000000000000..d6007b4b7c00c8 --- /dev/null +++ b/src/coreclr/vm/noopmetadataimport.h @@ -0,0 +1,117 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + + +#ifndef __NOOPMETADATAIMPORT_H__ +#define __NOOPMETADATAIMPORT_H__ + +#ifndef DACCESS_COMPILE + +#include "cor.h" +#include "metadata.h" + +// Process-wide IMetaDataImport2 singleton used only to satisfy the symbol-reader +// binder's non-null metadata-import requirement without materializing the module's +// real public importer (which would switch metadata access to the RW-backed path and +// slow all md operations after requesting sequence points for a module). The object +// is intentionally inert: all metadata methods assert in debug and return E_NOTIMPL in release. +// +// It carries no per-module state, so one instance is shared across modules and +// avoids collectible-module lifetime coupling. +class NoopMetadataImport final : public IMetaDataImport2 +{ +public: + // Returns the process-wide singleton as an IUnknown* suitable for handing to + // ISymUnmanagedBinder::GetReaderFromStream / GetReaderForFile. Returns NULL + // only if the one-time allocation fails. + static IUnknown* GetInstance(); + + // IUnknown + STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) override; + STDMETHOD_(ULONG, AddRef)() override; + STDMETHOD_(ULONG, Release)() override; + + // IMetaDataImport / IMetaDataImport2 -- every method asserts in debug and + // returns E_NOTIMPL in release. The full set is declared so the class is + // concrete. + STDMETHOD_(void, CloseEnum)(HCORENUM hEnum) override; + STDMETHOD(CountEnum)(HCORENUM hEnum, ULONG* pulCount) override; + STDMETHOD(ResetEnum)(HCORENUM hEnum, ULONG ulPos) override; + STDMETHOD(EnumTypeDefs)(HCORENUM* phEnum, mdTypeDef rTypeDefs[], ULONG cMax, ULONG* pcTypeDefs) override; + STDMETHOD(EnumInterfaceImpls)(HCORENUM* phEnum, mdTypeDef td, mdInterfaceImpl rImpls[], ULONG cMax, ULONG* pcImpls) override; + STDMETHOD(EnumTypeRefs)(HCORENUM* phEnum, mdTypeRef rTypeRefs[], ULONG cMax, ULONG* pcTypeRefs) override; + STDMETHOD(FindTypeDefByName)(LPCWSTR szTypeDef, mdToken tkEnclosingClass, mdTypeDef* ptd) override; + STDMETHOD(GetScopeProps)(LPWSTR szName, ULONG cchName, ULONG* pchName, GUID* pmvid) override; + STDMETHOD(GetModuleFromScope)(mdModule* pmd) override; + STDMETHOD(GetTypeDefProps)(mdTypeDef td, LPWSTR szTypeDef, ULONG cchTypeDef, ULONG* pchTypeDef, DWORD* pdwTypeDefFlags, mdToken* ptkExtends) override; + STDMETHOD(GetInterfaceImplProps)(mdInterfaceImpl iiImpl, mdTypeDef* pClass, mdToken* ptkIface) override; + STDMETHOD(GetTypeRefProps)(mdTypeRef tr, mdToken* ptkResolutionScope, LPWSTR szName, ULONG cchName, ULONG* pchName) override; + STDMETHOD(ResolveTypeRef)(mdTypeRef tr, REFIID riid, IUnknown** ppIScope, mdTypeDef* ptd) override; + STDMETHOD(EnumMembers)(HCORENUM* phEnum, mdTypeDef cl, mdToken rMembers[], ULONG cMax, ULONG* pcTokens) override; + STDMETHOD(EnumMembersWithName)(HCORENUM* phEnum, mdTypeDef cl, LPCWSTR szName, mdToken rMembers[], ULONG cMax, ULONG* pcTokens) override; + STDMETHOD(EnumMethods)(HCORENUM* phEnum, mdTypeDef cl, mdMethodDef rMethods[], ULONG cMax, ULONG* pcTokens) override; + STDMETHOD(EnumMethodsWithName)(HCORENUM* phEnum, mdTypeDef cl, LPCWSTR szName, mdMethodDef rMethods[], ULONG cMax, ULONG* pcTokens) override; + STDMETHOD(EnumFields)(HCORENUM* phEnum, mdTypeDef cl, mdFieldDef rFields[], ULONG cMax, ULONG* pcTokens) override; + STDMETHOD(EnumFieldsWithName)(HCORENUM* phEnum, mdTypeDef cl, LPCWSTR szName, mdFieldDef rFields[], ULONG cMax, ULONG* pcTokens) override; + STDMETHOD(EnumParams)(HCORENUM* phEnum, mdMethodDef mb, mdParamDef rParams[], ULONG cMax, ULONG* pcTokens) override; + STDMETHOD(EnumMemberRefs)(HCORENUM* phEnum, mdToken tkParent, mdMemberRef rMemberRefs[], ULONG cMax, ULONG* pcTokens) override; + STDMETHOD(EnumMethodImpls)(HCORENUM* phEnum, mdTypeDef td, mdToken rMethodBody[], mdToken rMethodDecl[], ULONG cMax, ULONG* pcTokens) override; + STDMETHOD(EnumPermissionSets)(HCORENUM* phEnum, mdToken tk, DWORD dwActions, mdPermission rPermission[], ULONG cMax, ULONG* pcTokens) override; + STDMETHOD(FindMember)(mdTypeDef td, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdToken* pmb) override; + STDMETHOD(FindMethod)(mdTypeDef td, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdMethodDef* pmb) override; + STDMETHOD(FindField)(mdTypeDef td, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdFieldDef* pmb) override; + STDMETHOD(FindMemberRef)(mdTypeRef td, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdMemberRef* pmr) override; + STDMETHOD(GetMethodProps)(mdMethodDef mb, mdTypeDef* pClass, LPWSTR szMethod, ULONG cchMethod, ULONG* pchMethod, DWORD* pdwAttr, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pcbSigBlob, ULONG* pulCodeRVA, DWORD* pdwImplFlags) override; + STDMETHOD(GetMemberRefProps)(mdMemberRef mr, mdToken* ptk, LPWSTR szMember, ULONG cchMember, ULONG* pchMember, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pbSig) override; + STDMETHOD(EnumProperties)(HCORENUM* phEnum, mdTypeDef td, mdProperty rProperties[], ULONG cMax, ULONG* pcProperties) override; + STDMETHOD(EnumEvents)(HCORENUM* phEnum, mdTypeDef td, mdEvent rEvents[], ULONG cMax, ULONG* pcEvents) override; + STDMETHOD(GetEventProps)(mdEvent ev, mdTypeDef* pClass, LPCWSTR szEvent, ULONG cchEvent, ULONG* pchEvent, DWORD* pdwEventFlags, mdToken* ptkEventType, mdMethodDef* pmdAddOn, mdMethodDef* pmdRemoveOn, mdMethodDef* pmdFire, mdMethodDef rmdOtherMethod[], ULONG cMax, ULONG* pcOtherMethod) override; + STDMETHOD(EnumMethodSemantics)(HCORENUM* phEnum, mdMethodDef mb, mdToken rEventProp[], ULONG cMax, ULONG* pcEventProp) override; + STDMETHOD(GetMethodSemantics)(mdMethodDef mb, mdToken tkEventProp, DWORD* pdwSemanticsFlags) override; + STDMETHOD(GetClassLayout)(mdTypeDef td, DWORD* pdwPackSize, COR_FIELD_OFFSET rFieldOffset[], ULONG cMax, ULONG* pcFieldOffset, ULONG* pulClassSize) override; + STDMETHOD(GetFieldMarshal)(mdToken tk, PCCOR_SIGNATURE* ppvNativeType, ULONG* pcbNativeType) override; + STDMETHOD(GetRVA)(mdToken tk, ULONG* pulCodeRVA, DWORD* pdwImplFlags) override; + STDMETHOD(GetPermissionSetProps)(mdPermission pm, DWORD* pdwAction, void const** ppvPermission, ULONG* pcbPermission) override; + STDMETHOD(GetModuleRefProps)(mdModuleRef mur, LPWSTR szName, ULONG cchName, ULONG* pchName) override; + STDMETHOD(EnumModuleRefs)(HCORENUM* phEnum, mdModuleRef rModuleRefs[], ULONG cmax, ULONG* pcModuleRefs) override; + STDMETHOD(GetTypeSpecFromToken)(mdTypeSpec typespec, PCCOR_SIGNATURE* ppvSig, ULONG* pcbSig) override; + STDMETHOD(GetNameFromToken)(mdToken tk, MDUTF8CSTR* pszUtf8NamePtr) override; + STDMETHOD(EnumUnresolvedMethods)(HCORENUM* phEnum, mdToken rMethods[], ULONG cMax, ULONG* pcTokens) override; + STDMETHOD(GetUserString)(mdString stk, LPWSTR szString, ULONG cchString, ULONG* pchString) override; + STDMETHOD(GetPinvokeMap)(mdToken tk, DWORD* pdwMappingFlags, LPWSTR szImportName, ULONG cchImportName, ULONG* pchImportName, mdModuleRef* pmrImportDLL) override; + STDMETHOD(EnumSignatures)(HCORENUM* phEnum, mdSignature rSignatures[], ULONG cmax, ULONG* pcSignatures) override; + STDMETHOD(EnumTypeSpecs)(HCORENUM* phEnum, mdTypeSpec rTypeSpecs[], ULONG cmax, ULONG* pcTypeSpecs) override; + STDMETHOD(EnumUserStrings)(HCORENUM* phEnum, mdString rStrings[], ULONG cmax, ULONG* pcStrings) override; + STDMETHOD(GetParamForMethodIndex)(mdMethodDef md, ULONG ulParamSeq, mdParamDef* ppd) override; + STDMETHOD(EnumCustomAttributes)(HCORENUM* phEnum, mdToken tk, mdToken tkType, mdCustomAttribute rCustomAttributes[], ULONG cMax, ULONG* pcCustomAttributes) override; + STDMETHOD(GetCustomAttributeProps)(mdCustomAttribute cv, mdToken* ptkObj, mdToken* ptkType, void const** ppBlob, ULONG* pcbSize) override; + STDMETHOD(FindTypeRef)(mdToken tkResolutionScope, LPCWSTR szName, mdTypeRef* ptr) override; + STDMETHOD(GetMemberProps)(mdToken mb, mdTypeDef* pClass, LPWSTR szMember, ULONG cchMember, ULONG* pchMember, DWORD* pdwAttr, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pcbSigBlob, ULONG* pulCodeRVA, DWORD* pdwImplFlags, DWORD* pdwCPlusTypeFlag, UVCP_CONSTANT* ppValue, ULONG* pcchValue) override; + STDMETHOD(GetFieldProps)(mdFieldDef mb, mdTypeDef* pClass, LPWSTR szField, ULONG cchField, ULONG* pchField, DWORD* pdwAttr, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pcbSigBlob, DWORD* pdwCPlusTypeFlag, UVCP_CONSTANT* ppValue, ULONG* pcchValue) override; + STDMETHOD(GetPropertyProps)(mdProperty prop, mdTypeDef* pClass, LPCWSTR szProperty, ULONG cchProperty, ULONG* pchProperty, DWORD* pdwPropFlags, PCCOR_SIGNATURE* ppvSig, ULONG* pbSig, DWORD* pdwCPlusTypeFlag, UVCP_CONSTANT* ppDefaultValue, ULONG* pcchDefaultValue, mdMethodDef* pmdSetter, mdMethodDef* pmdGetter, mdMethodDef rmdOtherMethod[], ULONG cMax, ULONG* pcOtherMethod) override; + STDMETHOD(GetParamProps)(mdParamDef tk, mdMethodDef* pmd, ULONG* pulSequence, LPWSTR szName, ULONG cchName, ULONG* pchName, DWORD* pdwAttr, DWORD* pdwCPlusTypeFlag, UVCP_CONSTANT* ppValue, ULONG* pcchValue) override; + STDMETHOD(GetCustomAttributeByName)(mdToken tkObj, LPCWSTR szName, const void** ppData, ULONG* pcbData) override; + STDMETHOD_(BOOL, IsValidToken)(mdToken tk) override; + STDMETHOD(GetNestedClassProps)(mdTypeDef tdNestedClass, mdTypeDef* ptdEnclosingClass) override; + STDMETHOD(GetNativeCallConvFromSig)(void const* pvSig, ULONG cbSig, ULONG* pCallConv) override; + STDMETHOD(IsGlobal)(mdToken pd, int* pbGlobal) override; + STDMETHOD(GetSigFromToken)(mdSignature mdSig, PCCOR_SIGNATURE* ppvSig, ULONG* pcbSig) override; + + // IMetaDataImport2 + STDMETHOD(EnumGenericParams)(HCORENUM* phEnum, mdToken tk, mdGenericParam rGenericParams[], ULONG cMax, ULONG* pcGenericParams) override; + STDMETHOD(GetGenericParamProps)(mdGenericParam gp, ULONG* pulParamSeq, DWORD* pdwParamFlags, mdToken* ptOwner, DWORD* reserved, LPWSTR wzname, ULONG cchName, ULONG* pchName) override; + STDMETHOD(GetMethodSpecProps)(mdMethodSpec mi, mdToken* tkParent, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pcbSigBlob) override; + STDMETHOD(EnumGenericParamConstraints)(HCORENUM* phEnum, mdGenericParam tk, mdGenericParamConstraint rGenericParamConstraints[], ULONG cMax, ULONG* pcGenericParamConstraints) override; + STDMETHOD(GetGenericParamConstraintProps)(mdGenericParamConstraint gpc, mdGenericParam* ptGenericParam, mdToken* ptkConstraintType) override; + STDMETHOD(GetPEKind)(DWORD* pdwPEKind, DWORD* pdwMachine) override; + STDMETHOD(GetVersionString)(LPWSTR pwzBuf, DWORD ccBufSize, DWORD* pccBufSize) override; + STDMETHOD(EnumMethodSpecs)(HCORENUM* phEnum, mdToken tk, mdMethodSpec rMethodSpecs[], ULONG cMax, ULONG* pcMethodSpecs) override; + +private: + NoopMetadataImport() = default; + ~NoopMetadataImport() = default; +}; + +#endif // !DACCESS_COMPILE + +#endif // __NOOPMETADATAIMPORT_H__ From 45679f82e7a2a6db694b036511ac03bd946a6346 Mon Sep 17 00:00:00 2001 From: Juan Hoyos <19413848+hoyosjs@users.noreply.github.com> Date: Thu, 25 Jun 2026 14:09:08 -0700 Subject: [PATCH 2/4] Rect to aaron's feedback --- src/coreclr/inc/corpriv.h | 5 +- src/coreclr/vm/CMakeLists.txt | 1 - src/coreclr/vm/ceeload.cpp | 23 +- src/coreclr/vm/noopmetadataimport.cpp | 306 ++++++++++++-------------- src/coreclr/vm/noopmetadataimport.h | 117 ---------- 5 files changed, 158 insertions(+), 294 deletions(-) delete mode 100644 src/coreclr/vm/noopmetadataimport.h diff --git a/src/coreclr/inc/corpriv.h b/src/coreclr/inc/corpriv.h index 8086a3f9cb580b..d5645fb825d35c 100644 --- a/src/coreclr/inc/corpriv.h +++ b/src/coreclr/inc/corpriv.h @@ -21,6 +21,10 @@ STDAPI CreateMetaDataDispenser( REFIID riid, void ** pMetaDataDispenserOut); +// Creation function to get a do-nothing IMetaDataImport2 instance for DIA. +STDAPI CreateNoopMetaDataImport2( + IMetaDataImport2** ppImport); + // Helper function to get an Internal interface with an in-memory metadata section STDAPI GetMDInternalInterface( LPVOID pData, // [IN] in memory metadata section @@ -370,4 +374,3 @@ DECLARE_INTERFACE_(IGetIMDInternalImport, IUnknown) }; #endif // _CORPRIV_H_ - diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index 235e3eddf41393..3aaaf919901f9f 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -468,7 +468,6 @@ set(VM_HEADERS_WKS multicorejit.h multicorejitimpl.h nativeeventsource.h - noopmetadataimport.h pendingload.h profdetach.h profilingenumerators.h diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index 4be3ddba58aaf3..d253c040a109b1 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -34,9 +34,6 @@ #include "virtualcallstub.h" #include "typestring.h" #include "stringliteralmap.h" -#ifndef DACCESS_COMPILE -#include "noopmetadataimport.h" -#endif #include #include "fieldmarshaler.h" #include "sigbuilder.h" @@ -1813,11 +1810,11 @@ ISymUnmanagedReader *Module::GetISymUnmanagedReader(void) // Hand the reader an inert importer rather than the module's real // (RW) metadata interface: the reader only needs it to satisfy the // binder, and producing the real importer would force this module's - // metadata to its locked RW backing store. See noopmetadataimport.h. - IUnknown* pNoopImport = NoopMetadataImport::GetInstance(); - hr = (pNoopImport != NULL) - ? pBinder->GetReaderFromStream(pNoopImport, pIStream, &pReader) - : E_OUTOFMEMORY; + // metadata to its locked RW backing store. + IMetaDataImport2* pNoopImport = NULL; + hr = CreateNoopMetaDataImport2(&pNoopImport); + if (SUCCEEDED(hr)) + hr = pBinder->GetReaderFromStream(pNoopImport, pIStream, &pReader); } } else @@ -1828,11 +1825,11 @@ ISymUnmanagedReader *Module::GetISymUnmanagedReader(void) // Hand the reader an inert importer rather than a readable metadata // interface for this module: the reader only needs it to satisfy the // binder, and obtaining the real importer would force this module's - // metadata to its locked RW backing store. See noopmetadataimport.h. - IUnknown* pNoopImport = NoopMetadataImport::GetInstance(); - hr = (pNoopImport != NULL) - ? pBinder->GetReaderForFile(pNoopImport, path, NULL, &pReader) - : E_OUTOFMEMORY; + // metadata to its locked RW backing store. + IMetaDataImport2* pNoopImport = NULL; + hr = CreateNoopMetaDataImport2(&pNoopImport); + if (SUCCEEDED(hr)) + hr = pBinder->GetReaderForFile(pNoopImport, path, NULL, &pReader); } if (SUCCEEDED(hr)) diff --git a/src/coreclr/vm/noopmetadataimport.cpp b/src/coreclr/vm/noopmetadataimport.cpp index 096f1cc84fd5be..d3741b0bb78313 100644 --- a/src/coreclr/vm/noopmetadataimport.cpp +++ b/src/coreclr/vm/noopmetadataimport.cpp @@ -1,36 +1,158 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // -// NoopMetadataImport implementation. See noopmetadataimport.h for design. +// NoopMetadataImport implementation. #include "common.h" #ifndef DACCESS_COMPILE -#include "noopmetadataimport.h" - -// Every method asserts in debug so an unexpected call (a future reader consumer -// that walks constant/local signatures, or a diasymreader change) is caught -// immediately; release builds return E_NOTIMPL. +// This importer is only used to satisfy the symbol binder's non-null parameter. +// It is intentionally inert so we do not materialize the module's real public importer. #ifdef _DEBUG -#define NOOPMD_NYI(name) \ - do { \ - _ASSERTE_MSG(false, \ - "NoopMetadataImport: unexpected call to " #name ". This importer is " \ - "handed to Microsoft.DiaSymReader.Native only to satisfy the binder; the " \ - "reader is expected to resolve sequence points without calling back into " \ - "it. A call here means that assumption no longer holds."); \ - return E_NOTIMPL; \ +#define NOOPMD_NYI(name) \ + do { \ + _ASSERTE_MSG(false, \ + "NoopMetadataImport: unexpected call to " #name ". The binder should not " \ + "be asking this importer for metadata."); \ + return E_NOTIMPL; \ } while (0) #else #define NOOPMD_NYI(name) return E_NOTIMPL #endif -// --------------------------------------------------------------------------- -// Singleton accessor -// --------------------------------------------------------------------------- +namespace +{ +class NoopMetadataImport final : public IMetaDataImport2 +{ +public: + // IUnknown + STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) override + { + LIMITED_METHOD_CONTRACT; + + if (ppvObject == NULL) + return E_POINTER; + + *ppvObject = NULL; + + // IMetaDataImport2 derives from IMetaDataImport derives from IUnknown -- a + // single-inheritance chain -- so one pointer, the IMetaDataImport2*, is the + // layout-compatible answer for all three IIDs. + if (riid == IID_IUnknown || + riid == IID_IMetaDataImport || + riid == IID_IMetaDataImport2) + { + *ppvObject = static_cast(this); + AddRef(); + return S_OK; + } + + return E_NOINTERFACE; + } + STDMETHOD_(ULONG, AddRef)() override + { + LIMITED_METHOD_CONTRACT; + return 1; + } + STDMETHOD_(ULONG, Release)() override + { + LIMITED_METHOD_CONTRACT; + return 1; + } -IUnknown* NoopMetadataImport::GetInstance() + // IMetaDataImport / IMetaDataImport2 -- every method asserts in debug and + // returns a failure or empty result in release. + STDMETHOD_(void, CloseEnum)(HCORENUM /*hEnum*/) override + { + LIMITED_METHOD_CONTRACT; + _ASSERTE_MSG(false, "NoopMetadataImport::CloseEnum NYI"); + } + STDMETHOD(CountEnum)(HCORENUM hEnum, ULONG* pulCount) override { NOOPMD_NYI(CountEnum); } + STDMETHOD(ResetEnum)(HCORENUM hEnum, ULONG ulPos) override { NOOPMD_NYI(ResetEnum); } + STDMETHOD(EnumTypeDefs)(HCORENUM* phEnum, mdTypeDef rTypeDefs[], ULONG cMax, ULONG* pcTypeDefs) override { NOOPMD_NYI(EnumTypeDefs); } + STDMETHOD(EnumInterfaceImpls)(HCORENUM* phEnum, mdTypeDef td, mdInterfaceImpl rImpls[], ULONG cMax, ULONG* pcImpls) override { NOOPMD_NYI(EnumInterfaceImpls); } + STDMETHOD(EnumTypeRefs)(HCORENUM* phEnum, mdTypeRef rTypeRefs[], ULONG cMax, ULONG* pcTypeRefs) override { NOOPMD_NYI(EnumTypeRefs); } + STDMETHOD(FindTypeDefByName)(LPCWSTR szTypeDef, mdToken tkEnclosingClass, mdTypeDef* ptd) override { NOOPMD_NYI(FindTypeDefByName); } + STDMETHOD(GetScopeProps)(LPWSTR szName, ULONG cchName, ULONG* pchName, GUID* pmvid) override { NOOPMD_NYI(GetScopeProps); } + STDMETHOD(GetModuleFromScope)(mdModule* pmd) override { NOOPMD_NYI(GetModuleFromScope); } + STDMETHOD(GetTypeDefProps)(mdTypeDef td, LPWSTR szTypeDef, ULONG cchTypeDef, ULONG* pchTypeDef, DWORD* pdwTypeDefFlags, mdToken* ptkExtends) override { NOOPMD_NYI(GetTypeDefProps); } + STDMETHOD(GetInterfaceImplProps)(mdInterfaceImpl iiImpl, mdTypeDef* pClass, mdToken* ptkIface) override { NOOPMD_NYI(GetInterfaceImplProps); } + STDMETHOD(GetTypeRefProps)(mdTypeRef tr, mdToken* ptkResolutionScope, LPWSTR szName, ULONG cchName, ULONG* pchName) override { NOOPMD_NYI(GetTypeRefProps); } + STDMETHOD(ResolveTypeRef)(mdTypeRef tr, REFIID riid, IUnknown** ppIScope, mdTypeDef* ptd) override { NOOPMD_NYI(ResolveTypeRef); } + STDMETHOD(EnumMembers)(HCORENUM* phEnum, mdTypeDef cl, mdToken rMembers[], ULONG cMax, ULONG* pcTokens) override { NOOPMD_NYI(EnumMembers); } + STDMETHOD(EnumMembersWithName)(HCORENUM* phEnum, mdTypeDef cl, LPCWSTR szName, mdToken rMembers[], ULONG cMax, ULONG* pcTokens) override { NOOPMD_NYI(EnumMembersWithName); } + STDMETHOD(EnumMethods)(HCORENUM* phEnum, mdTypeDef cl, mdMethodDef rMethods[], ULONG cMax, ULONG* pcTokens) override { NOOPMD_NYI(EnumMethods); } + STDMETHOD(EnumMethodsWithName)(HCORENUM* phEnum, mdTypeDef cl, LPCWSTR szName, mdMethodDef rMethods[], ULONG cMax, ULONG* pcTokens) override { NOOPMD_NYI(EnumMethodsWithName); } + STDMETHOD(EnumFields)(HCORENUM* phEnum, mdTypeDef cl, mdFieldDef rFields[], ULONG cMax, ULONG* pcTokens) override { NOOPMD_NYI(EnumFields); } + STDMETHOD(EnumFieldsWithName)(HCORENUM* phEnum, mdTypeDef cl, LPCWSTR szName, mdFieldDef rFields[], ULONG cMax, ULONG* pcTokens) override { NOOPMD_NYI(EnumFieldsWithName); } + STDMETHOD(EnumParams)(HCORENUM* phEnum, mdMethodDef mb, mdParamDef rParams[], ULONG cMax, ULONG* pcTokens) override { NOOPMD_NYI(EnumParams); } + STDMETHOD(EnumMemberRefs)(HCORENUM* phEnum, mdToken tkParent, mdMemberRef rMemberRefs[], ULONG cMax, ULONG* pcTokens) override { NOOPMD_NYI(EnumMemberRefs); } + STDMETHOD(EnumMethodImpls)(HCORENUM* phEnum, mdTypeDef td, mdToken rMethodBody[], mdToken rMethodDecl[], ULONG cMax, ULONG* pcTokens) override { NOOPMD_NYI(EnumMethodImpls); } + STDMETHOD(EnumPermissionSets)(HCORENUM* phEnum, mdToken tk, DWORD dwActions, mdPermission rPermission[], ULONG cMax, ULONG* pcTokens) override { NOOPMD_NYI(EnumPermissionSets); } + STDMETHOD(FindMember)(mdTypeDef td, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdToken* pmb) override { NOOPMD_NYI(FindMember); } + STDMETHOD(FindMethod)(mdTypeDef td, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdMethodDef* pmb) override { NOOPMD_NYI(FindMethod); } + STDMETHOD(FindField)(mdTypeDef td, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdFieldDef* pmb) override { NOOPMD_NYI(FindField); } + STDMETHOD(FindMemberRef)(mdTypeRef td, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdMemberRef* pmr) override { NOOPMD_NYI(FindMemberRef); } + STDMETHOD(GetMethodProps)(mdMethodDef mb, mdTypeDef* pClass, LPWSTR szMethod, ULONG cchMethod, ULONG* pchMethod, DWORD* pdwAttr, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pcbSigBlob, ULONG* pulCodeRVA, DWORD* pdwImplFlags) override { NOOPMD_NYI(GetMethodProps); } + STDMETHOD(GetMemberRefProps)(mdMemberRef mr, mdToken* ptk, LPWSTR szMember, ULONG cchMember, ULONG* pchMember, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pbSig) override { NOOPMD_NYI(GetMemberRefProps); } + STDMETHOD(EnumProperties)(HCORENUM* phEnum, mdTypeDef td, mdProperty rProperties[], ULONG cMax, ULONG* pcProperties) override { NOOPMD_NYI(EnumProperties); } + STDMETHOD(EnumEvents)(HCORENUM* phEnum, mdTypeDef td, mdEvent rEvents[], ULONG cMax, ULONG* pcEvents) override { NOOPMD_NYI(EnumEvents); } + STDMETHOD(GetEventProps)(mdEvent ev, mdTypeDef* pClass, LPCWSTR szEvent, ULONG cchEvent, ULONG* pchEvent, DWORD* pdwEventFlags, mdToken* ptkEventType, mdMethodDef* pmdAddOn, mdMethodDef* pmdRemoveOn, mdMethodDef* pmdFire, mdMethodDef rmdOtherMethod[], ULONG cMax, ULONG* pcOtherMethod) override { NOOPMD_NYI(GetEventProps); } + STDMETHOD(EnumMethodSemantics)(HCORENUM* phEnum, mdMethodDef mb, mdToken rEventProp[], ULONG cMax, ULONG* pcEventProp) override { NOOPMD_NYI(EnumMethodSemantics); } + STDMETHOD(GetMethodSemantics)(mdMethodDef mb, mdToken tkEventProp, DWORD* pdwSemanticsFlags) override { NOOPMD_NYI(GetMethodSemantics); } + STDMETHOD(GetClassLayout)(mdTypeDef td, DWORD* pdwPackSize, COR_FIELD_OFFSET rFieldOffset[], ULONG cMax, ULONG* pcFieldOffset, ULONG* pulClassSize) override { NOOPMD_NYI(GetClassLayout); } + STDMETHOD(GetFieldMarshal)(mdToken tk, PCCOR_SIGNATURE* ppvNativeType, ULONG* pcbNativeType) override { NOOPMD_NYI(GetFieldMarshal); } + STDMETHOD(GetRVA)(mdToken tk, ULONG* pulCodeRVA, DWORD* pdwImplFlags) override { NOOPMD_NYI(GetRVA); } + STDMETHOD(GetPermissionSetProps)(mdPermission pm, DWORD* pdwAction, void const** ppvPermission, ULONG* pcbPermission) override { NOOPMD_NYI(GetPermissionSetProps); } + STDMETHOD(GetModuleRefProps)(mdModuleRef mur, LPWSTR szName, ULONG cchName, ULONG* pchName) override { NOOPMD_NYI(GetModuleRefProps); } + STDMETHOD(EnumModuleRefs)(HCORENUM* phEnum, mdModuleRef rModuleRefs[], ULONG cmax, ULONG* pcModuleRefs) override { NOOPMD_NYI(EnumModuleRefs); } + STDMETHOD(GetTypeSpecFromToken)(mdTypeSpec typespec, PCCOR_SIGNATURE* ppvSig, ULONG* pcbSig) override { NOOPMD_NYI(GetTypeSpecFromToken); } + STDMETHOD(GetNameFromToken)(mdToken tk, MDUTF8CSTR* pszUtf8NamePtr) override { NOOPMD_NYI(GetNameFromToken); } + STDMETHOD(EnumUnresolvedMethods)(HCORENUM* phEnum, mdToken rMethods[], ULONG cMax, ULONG* pcTokens) override { NOOPMD_NYI(EnumUnresolvedMethods); } + STDMETHOD(GetUserString)(mdString stk, LPWSTR szString, ULONG cchString, ULONG* pchString) override { NOOPMD_NYI(GetUserString); } + STDMETHOD(GetPinvokeMap)(mdToken tk, DWORD* pdwMappingFlags, LPWSTR szImportName, ULONG cchImportName, ULONG* pchImportName, mdModuleRef* pmrImportDLL) override { NOOPMD_NYI(GetPinvokeMap); } + STDMETHOD(EnumSignatures)(HCORENUM* phEnum, mdSignature rSignatures[], ULONG cmax, ULONG* pcSignatures) override { NOOPMD_NYI(EnumSignatures); } + STDMETHOD(EnumTypeSpecs)(HCORENUM* phEnum, mdTypeSpec rTypeSpecs[], ULONG cmax, ULONG* pcTypeSpecs) override { NOOPMD_NYI(EnumTypeSpecs); } + STDMETHOD(EnumUserStrings)(HCORENUM* phEnum, mdString rStrings[], ULONG cmax, ULONG* pcStrings) override { NOOPMD_NYI(EnumUserStrings); } + STDMETHOD(GetParamForMethodIndex)(mdMethodDef md, ULONG ulParamSeq, mdParamDef* ppd) override { NOOPMD_NYI(GetParamForMethodIndex); } + STDMETHOD(EnumCustomAttributes)(HCORENUM* phEnum, mdToken tk, mdToken tkType, mdCustomAttribute rCustomAttributes[], ULONG cMax, ULONG* pcCustomAttributes) override { NOOPMD_NYI(EnumCustomAttributes); } + STDMETHOD(GetCustomAttributeProps)(mdCustomAttribute cv, mdToken* ptkObj, mdToken* ptkType, void const** ppBlob, ULONG* pcbSize) override { NOOPMD_NYI(GetCustomAttributeProps); } + STDMETHOD(FindTypeRef)(mdToken tkResolutionScope, LPCWSTR szName, mdTypeRef* ptr) override { NOOPMD_NYI(FindTypeRef); } + STDMETHOD(GetMemberProps)(mdToken mb, mdTypeDef* pClass, LPWSTR szMember, ULONG cchMember, ULONG* pchMember, DWORD* pdwAttr, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pcbSigBlob, ULONG* pulCodeRVA, DWORD* pdwImplFlags, DWORD* pdwCPlusTypeFlag, UVCP_CONSTANT* ppValue, ULONG* pcchValue) override { NOOPMD_NYI(GetMemberProps); } + STDMETHOD(GetFieldProps)(mdFieldDef mb, mdTypeDef* pClass, LPWSTR szField, ULONG cchField, ULONG* pchField, DWORD* pdwAttr, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pcbSigBlob, DWORD* pdwCPlusTypeFlag, UVCP_CONSTANT* ppValue, ULONG* pcchValue) override { NOOPMD_NYI(GetFieldProps); } + STDMETHOD(GetPropertyProps)(mdProperty prop, mdTypeDef* pClass, LPCWSTR szProperty, ULONG cchProperty, ULONG* pchProperty, DWORD* pdwPropFlags, PCCOR_SIGNATURE* ppvSig, ULONG* pbSig, DWORD* pdwCPlusTypeFlag, UVCP_CONSTANT* ppDefaultValue, ULONG* pcchDefaultValue, mdMethodDef* pmdSetter, mdMethodDef* pmdGetter, mdMethodDef rmdOtherMethod[], ULONG cMax, ULONG* pcOtherMethod) override { NOOPMD_NYI(GetPropertyProps); } + STDMETHOD(GetParamProps)(mdParamDef tk, mdMethodDef* pmd, ULONG* pulSequence, LPWSTR szName, ULONG cchName, ULONG* pchName, DWORD* pdwAttr, DWORD* pdwCPlusTypeFlag, UVCP_CONSTANT* ppValue, ULONG* pcchValue) override { NOOPMD_NYI(GetParamProps); } + STDMETHOD(GetCustomAttributeByName)(mdToken tkObj, LPCWSTR szName, const void** ppData, ULONG* pcbData) override { NOOPMD_NYI(GetCustomAttributeByName); } + STDMETHOD_(BOOL, IsValidToken)(mdToken /*tk*/) override + { + LIMITED_METHOD_CONTRACT; + _ASSERTE_MSG(false, "NoopMetadataImport::IsValidToken NYI"); + return FALSE; + } + STDMETHOD(GetNestedClassProps)(mdTypeDef tdNestedClass, mdTypeDef* ptdEnclosingClass) override { NOOPMD_NYI(GetNestedClassProps); } + STDMETHOD(GetNativeCallConvFromSig)(void const* pvSig, ULONG cbSig, ULONG* pCallConv) override { NOOPMD_NYI(GetNativeCallConvFromSig); } + STDMETHOD(IsGlobal)(mdToken pd, int* pbGlobal) override { NOOPMD_NYI(IsGlobal); } + STDMETHOD(GetSigFromToken)(mdSignature mdSig, PCCOR_SIGNATURE* ppvSig, ULONG* pcbSig) override { NOOPMD_NYI(GetSigFromToken); } + + // IMetaDataImport2 + STDMETHOD(EnumGenericParams)(HCORENUM* phEnum, mdToken tk, mdGenericParam rGenericParams[], ULONG cMax, ULONG* pcGenericParams) override { NOOPMD_NYI(EnumGenericParams); } + STDMETHOD(GetGenericParamProps)(mdGenericParam gp, ULONG* pulParamSeq, DWORD* pdwParamFlags, mdToken* ptOwner, DWORD* reserved, LPWSTR wzname, ULONG cchName, ULONG* pchName) override { NOOPMD_NYI(GetGenericParamProps); } + STDMETHOD(GetMethodSpecProps)(mdMethodSpec mi, mdToken* tkParent, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pcbSigBlob) override { NOOPMD_NYI(GetMethodSpecProps); } + STDMETHOD(EnumGenericParamConstraints)(HCORENUM* phEnum, mdGenericParam tk, mdGenericParamConstraint rGenericParamConstraints[], ULONG cMax, ULONG* pcGenericParamConstraints) override { NOOPMD_NYI(EnumGenericParamConstraints); } + STDMETHOD(GetGenericParamConstraintProps)(mdGenericParamConstraint gpc, mdGenericParam* ptGenericParam, mdToken* ptkConstraintType) override { NOOPMD_NYI(GetGenericParamConstraintProps); } + STDMETHOD(GetPEKind)(DWORD* pdwPEKind, DWORD* pdwMachine) override { NOOPMD_NYI(GetPEKind); } + STDMETHOD(GetVersionString)(LPWSTR pwzBuf, DWORD ccBufSize, DWORD* pccBufSize) override { NOOPMD_NYI(GetVersionString); } + STDMETHOD(EnumMethodSpecs)(HCORENUM* phEnum, mdToken tk, mdMethodSpec rMethodSpecs[], ULONG cMax, ULONG* pcMethodSpecs) override { NOOPMD_NYI(EnumMethodSpecs); } + + NoopMetadataImport() = default; + ~NoopMetadataImport() = default; +}; + +NoopMetadataImport g_NoopMetadataImport; +} // namespace + +STDAPI CreateNoopMetaDataImport2(IMetaDataImport2** ppImport) { CONTRACTL { @@ -40,152 +162,12 @@ IUnknown* NoopMetadataImport::GetInstance() } CONTRACTL_END; - // Lazily created once and intentionally leaked for the process lifetime, so - // there is no static-initialization ordering or teardown to reason about. - static NoopMetadataImport* volatile s_pInstance = NULL; - - NoopMetadataImport* pInstance = VolatileLoad(&s_pInstance); - if (pInstance == NULL) - { - NoopMetadataImport* pNew = new (nothrow) NoopMetadataImport(); - if (pNew == NULL) - return NULL; - - if (InterlockedCompareExchangeT(&s_pInstance, pNew, (NoopMetadataImport*)NULL) != NULL) - delete pNew; // lost the race; another thread published first - - pInstance = VolatileLoad(&s_pInstance); - } - - return static_cast(pInstance); -} - -// --------------------------------------------------------------------------- -// IUnknown -// --------------------------------------------------------------------------- - -STDMETHODIMP NoopMetadataImport::QueryInterface(REFIID riid, void** ppvObject) -{ - LIMITED_METHOD_CONTRACT; - - if (ppvObject == NULL) + if (ppImport == NULL) return E_POINTER; - *ppvObject = NULL; - - // IMetaDataImport2 derives from IMetaDataImport derives from IUnknown -- a - // single-inheritance chain -- so one pointer, the IMetaDataImport2*, is the - // layout-compatible answer for all three IIDs. IID_IGetIMDInternalImport (the - // public->internal back-conversion the runtime uses to push a module to RW - // metadata) is intentionally not exposed. - if (riid == IID_IUnknown || - riid == IID_IMetaDataImport || - riid == IID_IMetaDataImport2) - { - *ppvObject = static_cast(this); - AddRef(); - return S_OK; - } - - return E_NOINTERFACE; + *ppImport = &g_NoopMetadataImport; + g_NoopMetadataImport.AddRef(); + return S_OK; } -// The singleton lives for the process, so refcounting is a no-op: returning a -// constant tells COM callers the object is never destroyed. -STDMETHODIMP_(ULONG) NoopMetadataImport::AddRef() -{ - LIMITED_METHOD_CONTRACT; - return 1; -} - -STDMETHODIMP_(ULONG) NoopMetadataImport::Release() -{ - LIMITED_METHOD_CONTRACT; - return 1; -} - -// --------------------------------------------------------------------------- -// Fail-fast stubs for every metadata method. -// --------------------------------------------------------------------------- - -STDMETHODIMP_(void) NoopMetadataImport::CloseEnum(HCORENUM /*hEnum*/) { LIMITED_METHOD_CONTRACT; _ASSERTE_MSG(false, "NoopMetadataImport::CloseEnum NYI"); } -STDMETHODIMP NoopMetadataImport::CountEnum(HCORENUM, ULONG*) { NOOPMD_NYI(CountEnum); } -STDMETHODIMP NoopMetadataImport::ResetEnum(HCORENUM, ULONG) { NOOPMD_NYI(ResetEnum); } -STDMETHODIMP NoopMetadataImport::EnumTypeDefs(HCORENUM*, mdTypeDef[], ULONG, ULONG*) { NOOPMD_NYI(EnumTypeDefs); } -STDMETHODIMP NoopMetadataImport::EnumInterfaceImpls(HCORENUM*, mdTypeDef, mdInterfaceImpl[], ULONG, ULONG*) { NOOPMD_NYI(EnumInterfaceImpls); } -STDMETHODIMP NoopMetadataImport::EnumTypeRefs(HCORENUM*, mdTypeRef[], ULONG, ULONG*) { NOOPMD_NYI(EnumTypeRefs); } -STDMETHODIMP NoopMetadataImport::FindTypeDefByName(LPCWSTR, mdToken, mdTypeDef*) { NOOPMD_NYI(FindTypeDefByName); } -STDMETHODIMP NoopMetadataImport::GetScopeProps(LPWSTR, ULONG, ULONG*, GUID*) { NOOPMD_NYI(GetScopeProps); } -STDMETHODIMP NoopMetadataImport::GetModuleFromScope(mdModule*) { NOOPMD_NYI(GetModuleFromScope); } -STDMETHODIMP NoopMetadataImport::GetTypeDefProps(mdTypeDef, LPWSTR, ULONG, ULONG*, DWORD*, mdToken*) { NOOPMD_NYI(GetTypeDefProps); } -STDMETHODIMP NoopMetadataImport::GetInterfaceImplProps(mdInterfaceImpl, mdTypeDef*, mdToken*) { NOOPMD_NYI(GetInterfaceImplProps); } -STDMETHODIMP NoopMetadataImport::GetTypeRefProps(mdTypeRef, mdToken*, LPWSTR, ULONG, ULONG*) { NOOPMD_NYI(GetTypeRefProps); } -STDMETHODIMP NoopMetadataImport::ResolveTypeRef(mdTypeRef, REFIID, IUnknown**, mdTypeDef*) { NOOPMD_NYI(ResolveTypeRef); } -STDMETHODIMP NoopMetadataImport::EnumMembers(HCORENUM*, mdTypeDef, mdToken[], ULONG, ULONG*) { NOOPMD_NYI(EnumMembers); } -STDMETHODIMP NoopMetadataImport::EnumMembersWithName(HCORENUM*, mdTypeDef, LPCWSTR, mdToken[], ULONG, ULONG*) { NOOPMD_NYI(EnumMembersWithName); } -STDMETHODIMP NoopMetadataImport::EnumMethods(HCORENUM*, mdTypeDef, mdMethodDef[], ULONG, ULONG*) { NOOPMD_NYI(EnumMethods); } -STDMETHODIMP NoopMetadataImport::EnumMethodsWithName(HCORENUM*, mdTypeDef, LPCWSTR, mdMethodDef[], ULONG, ULONG*) { NOOPMD_NYI(EnumMethodsWithName); } -STDMETHODIMP NoopMetadataImport::EnumFields(HCORENUM*, mdTypeDef, mdFieldDef[], ULONG, ULONG*) { NOOPMD_NYI(EnumFields); } -STDMETHODIMP NoopMetadataImport::EnumFieldsWithName(HCORENUM*, mdTypeDef, LPCWSTR, mdFieldDef[], ULONG, ULONG*) { NOOPMD_NYI(EnumFieldsWithName); } -STDMETHODIMP NoopMetadataImport::EnumParams(HCORENUM*, mdMethodDef, mdParamDef[], ULONG, ULONG*) { NOOPMD_NYI(EnumParams); } -STDMETHODIMP NoopMetadataImport::EnumMemberRefs(HCORENUM*, mdToken, mdMemberRef[], ULONG, ULONG*) { NOOPMD_NYI(EnumMemberRefs); } -STDMETHODIMP NoopMetadataImport::EnumMethodImpls(HCORENUM*, mdTypeDef, mdToken[], mdToken[], ULONG, ULONG*) { NOOPMD_NYI(EnumMethodImpls); } -STDMETHODIMP NoopMetadataImport::EnumPermissionSets(HCORENUM*, mdToken, DWORD, mdPermission[], ULONG, ULONG*) { NOOPMD_NYI(EnumPermissionSets); } -STDMETHODIMP NoopMetadataImport::FindMember(mdTypeDef, LPCWSTR, PCCOR_SIGNATURE, ULONG, mdToken*) { NOOPMD_NYI(FindMember); } -STDMETHODIMP NoopMetadataImport::FindMethod(mdTypeDef, LPCWSTR, PCCOR_SIGNATURE, ULONG, mdMethodDef*) { NOOPMD_NYI(FindMethod); } -STDMETHODIMP NoopMetadataImport::FindField(mdTypeDef, LPCWSTR, PCCOR_SIGNATURE, ULONG, mdFieldDef*) { NOOPMD_NYI(FindField); } -STDMETHODIMP NoopMetadataImport::FindMemberRef(mdTypeRef, LPCWSTR, PCCOR_SIGNATURE, ULONG, mdMemberRef*) { NOOPMD_NYI(FindMemberRef); } -STDMETHODIMP NoopMetadataImport::GetMethodProps(mdMethodDef, mdTypeDef*, LPWSTR, ULONG, ULONG*, DWORD*, PCCOR_SIGNATURE*, ULONG*, ULONG*, DWORD*) { NOOPMD_NYI(GetMethodProps); } -STDMETHODIMP NoopMetadataImport::GetMemberRefProps(mdMemberRef, mdToken*, LPWSTR, ULONG, ULONG*, PCCOR_SIGNATURE*, ULONG*) { NOOPMD_NYI(GetMemberRefProps); } -STDMETHODIMP NoopMetadataImport::EnumProperties(HCORENUM*, mdTypeDef, mdProperty[], ULONG, ULONG*) { NOOPMD_NYI(EnumProperties); } -STDMETHODIMP NoopMetadataImport::EnumEvents(HCORENUM*, mdTypeDef, mdEvent[], ULONG, ULONG*) { NOOPMD_NYI(EnumEvents); } -STDMETHODIMP NoopMetadataImport::GetEventProps(mdEvent, mdTypeDef*, LPCWSTR, ULONG, ULONG*, DWORD*, mdToken*, mdMethodDef*, mdMethodDef*, mdMethodDef*, mdMethodDef[], ULONG, ULONG*) { NOOPMD_NYI(GetEventProps); } -STDMETHODIMP NoopMetadataImport::EnumMethodSemantics(HCORENUM*, mdMethodDef, mdToken[], ULONG, ULONG*) { NOOPMD_NYI(EnumMethodSemantics); } -STDMETHODIMP NoopMetadataImport::GetMethodSemantics(mdMethodDef, mdToken, DWORD*) { NOOPMD_NYI(GetMethodSemantics); } -STDMETHODIMP NoopMetadataImport::GetClassLayout(mdTypeDef, DWORD*, COR_FIELD_OFFSET[], ULONG, ULONG*, ULONG*) { NOOPMD_NYI(GetClassLayout); } -STDMETHODIMP NoopMetadataImport::GetFieldMarshal(mdToken, PCCOR_SIGNATURE*, ULONG*) { NOOPMD_NYI(GetFieldMarshal); } -STDMETHODIMP NoopMetadataImport::GetRVA(mdToken, ULONG*, DWORD*) { NOOPMD_NYI(GetRVA); } -STDMETHODIMP NoopMetadataImport::GetPermissionSetProps(mdPermission, DWORD*, void const**, ULONG*) { NOOPMD_NYI(GetPermissionSetProps); } -STDMETHODIMP NoopMetadataImport::GetModuleRefProps(mdModuleRef, LPWSTR, ULONG, ULONG*) { NOOPMD_NYI(GetModuleRefProps); } -STDMETHODIMP NoopMetadataImport::EnumModuleRefs(HCORENUM*, mdModuleRef[], ULONG, ULONG*) { NOOPMD_NYI(EnumModuleRefs); } -STDMETHODIMP NoopMetadataImport::GetTypeSpecFromToken(mdTypeSpec, PCCOR_SIGNATURE*, ULONG*) { NOOPMD_NYI(GetTypeSpecFromToken); } -STDMETHODIMP NoopMetadataImport::GetNameFromToken(mdToken, MDUTF8CSTR*) { NOOPMD_NYI(GetNameFromToken); } -STDMETHODIMP NoopMetadataImport::EnumUnresolvedMethods(HCORENUM*, mdToken[], ULONG, ULONG*) { NOOPMD_NYI(EnumUnresolvedMethods); } -STDMETHODIMP NoopMetadataImport::GetUserString(mdString, LPWSTR, ULONG, ULONG*) { NOOPMD_NYI(GetUserString); } -STDMETHODIMP NoopMetadataImport::GetPinvokeMap(mdToken, DWORD*, LPWSTR, ULONG, ULONG*, mdModuleRef*) { NOOPMD_NYI(GetPinvokeMap); } -STDMETHODIMP NoopMetadataImport::EnumSignatures(HCORENUM*, mdSignature[], ULONG, ULONG*) { NOOPMD_NYI(EnumSignatures); } -STDMETHODIMP NoopMetadataImport::EnumTypeSpecs(HCORENUM*, mdTypeSpec[], ULONG, ULONG*) { NOOPMD_NYI(EnumTypeSpecs); } -STDMETHODIMP NoopMetadataImport::EnumUserStrings(HCORENUM*, mdString[], ULONG, ULONG*) { NOOPMD_NYI(EnumUserStrings); } -STDMETHODIMP NoopMetadataImport::GetParamForMethodIndex(mdMethodDef, ULONG, mdParamDef*) { NOOPMD_NYI(GetParamForMethodIndex); } -STDMETHODIMP NoopMetadataImport::EnumCustomAttributes(HCORENUM*, mdToken, mdToken, mdCustomAttribute[], ULONG, ULONG*) { NOOPMD_NYI(EnumCustomAttributes); } -STDMETHODIMP NoopMetadataImport::GetCustomAttributeProps(mdCustomAttribute, mdToken*, mdToken*, void const**, ULONG*) { NOOPMD_NYI(GetCustomAttributeProps); } -STDMETHODIMP NoopMetadataImport::FindTypeRef(mdToken, LPCWSTR, mdTypeRef*) { NOOPMD_NYI(FindTypeRef); } -STDMETHODIMP NoopMetadataImport::GetMemberProps(mdToken, mdTypeDef*, LPWSTR, ULONG, ULONG*, DWORD*, PCCOR_SIGNATURE*, ULONG*, ULONG*, DWORD*, DWORD*, UVCP_CONSTANT*, ULONG*) { NOOPMD_NYI(GetMemberProps); } -STDMETHODIMP NoopMetadataImport::GetFieldProps(mdFieldDef, mdTypeDef*, LPWSTR, ULONG, ULONG*, DWORD*, PCCOR_SIGNATURE*, ULONG*, DWORD*, UVCP_CONSTANT*, ULONG*) { NOOPMD_NYI(GetFieldProps); } -STDMETHODIMP NoopMetadataImport::GetPropertyProps(mdProperty, mdTypeDef*, LPCWSTR, ULONG, ULONG*, DWORD*, PCCOR_SIGNATURE*, ULONG*, DWORD*, UVCP_CONSTANT*, ULONG*, mdMethodDef*, mdMethodDef*, mdMethodDef[], ULONG, ULONG*) { NOOPMD_NYI(GetPropertyProps); } -STDMETHODIMP NoopMetadataImport::GetParamProps(mdParamDef, mdMethodDef*, ULONG*, LPWSTR, ULONG, ULONG*, DWORD*, DWORD*, UVCP_CONSTANT*, ULONG*) { NOOPMD_NYI(GetParamProps); } -STDMETHODIMP NoopMetadataImport::GetCustomAttributeByName(mdToken, LPCWSTR, const void**, ULONG*) { NOOPMD_NYI(GetCustomAttributeByName); } - -STDMETHODIMP_(BOOL) NoopMetadataImport::IsValidToken(mdToken /*tk*/) -{ - LIMITED_METHOD_CONTRACT; - _ASSERTE_MSG(false, "NoopMetadataImport::IsValidToken NYI"); - return FALSE; -} - -STDMETHODIMP NoopMetadataImport::GetNestedClassProps(mdTypeDef, mdTypeDef*) { NOOPMD_NYI(GetNestedClassProps); } -STDMETHODIMP NoopMetadataImport::GetNativeCallConvFromSig(void const*, ULONG, ULONG*) { NOOPMD_NYI(GetNativeCallConvFromSig); } -STDMETHODIMP NoopMetadataImport::IsGlobal(mdToken, int*) { NOOPMD_NYI(IsGlobal); } -STDMETHODIMP NoopMetadataImport::GetSigFromToken(mdSignature, PCCOR_SIGNATURE*, ULONG*) { NOOPMD_NYI(GetSigFromToken); } - -// IMetaDataImport2 -STDMETHODIMP NoopMetadataImport::EnumGenericParams(HCORENUM*, mdToken, mdGenericParam[], ULONG, ULONG*) { NOOPMD_NYI(EnumGenericParams); } -STDMETHODIMP NoopMetadataImport::GetGenericParamProps(mdGenericParam, ULONG*, DWORD*, mdToken*, DWORD*, LPWSTR, ULONG, ULONG*) { NOOPMD_NYI(GetGenericParamProps); } -STDMETHODIMP NoopMetadataImport::GetMethodSpecProps(mdMethodSpec, mdToken*, PCCOR_SIGNATURE*, ULONG*) { NOOPMD_NYI(GetMethodSpecProps); } -STDMETHODIMP NoopMetadataImport::EnumGenericParamConstraints(HCORENUM*, mdGenericParam, mdGenericParamConstraint[], ULONG, ULONG*) { NOOPMD_NYI(EnumGenericParamConstraints); } -STDMETHODIMP NoopMetadataImport::GetGenericParamConstraintProps(mdGenericParamConstraint, mdGenericParam*, mdToken*) { NOOPMD_NYI(GetGenericParamConstraintProps); } -STDMETHODIMP NoopMetadataImport::GetPEKind(DWORD*, DWORD*) { NOOPMD_NYI(GetPEKind); } -STDMETHODIMP NoopMetadataImport::GetVersionString(LPWSTR, DWORD, DWORD*) { NOOPMD_NYI(GetVersionString); } -STDMETHODIMP NoopMetadataImport::EnumMethodSpecs(HCORENUM*, mdToken, mdMethodSpec[], ULONG, ULONG*) { NOOPMD_NYI(EnumMethodSpecs); } - #endif // !DACCESS_COMPILE diff --git a/src/coreclr/vm/noopmetadataimport.h b/src/coreclr/vm/noopmetadataimport.h deleted file mode 100644 index d6007b4b7c00c8..00000000000000 --- a/src/coreclr/vm/noopmetadataimport.h +++ /dev/null @@ -1,117 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - - -#ifndef __NOOPMETADATAIMPORT_H__ -#define __NOOPMETADATAIMPORT_H__ - -#ifndef DACCESS_COMPILE - -#include "cor.h" -#include "metadata.h" - -// Process-wide IMetaDataImport2 singleton used only to satisfy the symbol-reader -// binder's non-null metadata-import requirement without materializing the module's -// real public importer (which would switch metadata access to the RW-backed path and -// slow all md operations after requesting sequence points for a module). The object -// is intentionally inert: all metadata methods assert in debug and return E_NOTIMPL in release. -// -// It carries no per-module state, so one instance is shared across modules and -// avoids collectible-module lifetime coupling. -class NoopMetadataImport final : public IMetaDataImport2 -{ -public: - // Returns the process-wide singleton as an IUnknown* suitable for handing to - // ISymUnmanagedBinder::GetReaderFromStream / GetReaderForFile. Returns NULL - // only if the one-time allocation fails. - static IUnknown* GetInstance(); - - // IUnknown - STDMETHOD(QueryInterface)(REFIID riid, void** ppvObject) override; - STDMETHOD_(ULONG, AddRef)() override; - STDMETHOD_(ULONG, Release)() override; - - // IMetaDataImport / IMetaDataImport2 -- every method asserts in debug and - // returns E_NOTIMPL in release. The full set is declared so the class is - // concrete. - STDMETHOD_(void, CloseEnum)(HCORENUM hEnum) override; - STDMETHOD(CountEnum)(HCORENUM hEnum, ULONG* pulCount) override; - STDMETHOD(ResetEnum)(HCORENUM hEnum, ULONG ulPos) override; - STDMETHOD(EnumTypeDefs)(HCORENUM* phEnum, mdTypeDef rTypeDefs[], ULONG cMax, ULONG* pcTypeDefs) override; - STDMETHOD(EnumInterfaceImpls)(HCORENUM* phEnum, mdTypeDef td, mdInterfaceImpl rImpls[], ULONG cMax, ULONG* pcImpls) override; - STDMETHOD(EnumTypeRefs)(HCORENUM* phEnum, mdTypeRef rTypeRefs[], ULONG cMax, ULONG* pcTypeRefs) override; - STDMETHOD(FindTypeDefByName)(LPCWSTR szTypeDef, mdToken tkEnclosingClass, mdTypeDef* ptd) override; - STDMETHOD(GetScopeProps)(LPWSTR szName, ULONG cchName, ULONG* pchName, GUID* pmvid) override; - STDMETHOD(GetModuleFromScope)(mdModule* pmd) override; - STDMETHOD(GetTypeDefProps)(mdTypeDef td, LPWSTR szTypeDef, ULONG cchTypeDef, ULONG* pchTypeDef, DWORD* pdwTypeDefFlags, mdToken* ptkExtends) override; - STDMETHOD(GetInterfaceImplProps)(mdInterfaceImpl iiImpl, mdTypeDef* pClass, mdToken* ptkIface) override; - STDMETHOD(GetTypeRefProps)(mdTypeRef tr, mdToken* ptkResolutionScope, LPWSTR szName, ULONG cchName, ULONG* pchName) override; - STDMETHOD(ResolveTypeRef)(mdTypeRef tr, REFIID riid, IUnknown** ppIScope, mdTypeDef* ptd) override; - STDMETHOD(EnumMembers)(HCORENUM* phEnum, mdTypeDef cl, mdToken rMembers[], ULONG cMax, ULONG* pcTokens) override; - STDMETHOD(EnumMembersWithName)(HCORENUM* phEnum, mdTypeDef cl, LPCWSTR szName, mdToken rMembers[], ULONG cMax, ULONG* pcTokens) override; - STDMETHOD(EnumMethods)(HCORENUM* phEnum, mdTypeDef cl, mdMethodDef rMethods[], ULONG cMax, ULONG* pcTokens) override; - STDMETHOD(EnumMethodsWithName)(HCORENUM* phEnum, mdTypeDef cl, LPCWSTR szName, mdMethodDef rMethods[], ULONG cMax, ULONG* pcTokens) override; - STDMETHOD(EnumFields)(HCORENUM* phEnum, mdTypeDef cl, mdFieldDef rFields[], ULONG cMax, ULONG* pcTokens) override; - STDMETHOD(EnumFieldsWithName)(HCORENUM* phEnum, mdTypeDef cl, LPCWSTR szName, mdFieldDef rFields[], ULONG cMax, ULONG* pcTokens) override; - STDMETHOD(EnumParams)(HCORENUM* phEnum, mdMethodDef mb, mdParamDef rParams[], ULONG cMax, ULONG* pcTokens) override; - STDMETHOD(EnumMemberRefs)(HCORENUM* phEnum, mdToken tkParent, mdMemberRef rMemberRefs[], ULONG cMax, ULONG* pcTokens) override; - STDMETHOD(EnumMethodImpls)(HCORENUM* phEnum, mdTypeDef td, mdToken rMethodBody[], mdToken rMethodDecl[], ULONG cMax, ULONG* pcTokens) override; - STDMETHOD(EnumPermissionSets)(HCORENUM* phEnum, mdToken tk, DWORD dwActions, mdPermission rPermission[], ULONG cMax, ULONG* pcTokens) override; - STDMETHOD(FindMember)(mdTypeDef td, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdToken* pmb) override; - STDMETHOD(FindMethod)(mdTypeDef td, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdMethodDef* pmb) override; - STDMETHOD(FindField)(mdTypeDef td, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdFieldDef* pmb) override; - STDMETHOD(FindMemberRef)(mdTypeRef td, LPCWSTR szName, PCCOR_SIGNATURE pvSigBlob, ULONG cbSigBlob, mdMemberRef* pmr) override; - STDMETHOD(GetMethodProps)(mdMethodDef mb, mdTypeDef* pClass, LPWSTR szMethod, ULONG cchMethod, ULONG* pchMethod, DWORD* pdwAttr, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pcbSigBlob, ULONG* pulCodeRVA, DWORD* pdwImplFlags) override; - STDMETHOD(GetMemberRefProps)(mdMemberRef mr, mdToken* ptk, LPWSTR szMember, ULONG cchMember, ULONG* pchMember, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pbSig) override; - STDMETHOD(EnumProperties)(HCORENUM* phEnum, mdTypeDef td, mdProperty rProperties[], ULONG cMax, ULONG* pcProperties) override; - STDMETHOD(EnumEvents)(HCORENUM* phEnum, mdTypeDef td, mdEvent rEvents[], ULONG cMax, ULONG* pcEvents) override; - STDMETHOD(GetEventProps)(mdEvent ev, mdTypeDef* pClass, LPCWSTR szEvent, ULONG cchEvent, ULONG* pchEvent, DWORD* pdwEventFlags, mdToken* ptkEventType, mdMethodDef* pmdAddOn, mdMethodDef* pmdRemoveOn, mdMethodDef* pmdFire, mdMethodDef rmdOtherMethod[], ULONG cMax, ULONG* pcOtherMethod) override; - STDMETHOD(EnumMethodSemantics)(HCORENUM* phEnum, mdMethodDef mb, mdToken rEventProp[], ULONG cMax, ULONG* pcEventProp) override; - STDMETHOD(GetMethodSemantics)(mdMethodDef mb, mdToken tkEventProp, DWORD* pdwSemanticsFlags) override; - STDMETHOD(GetClassLayout)(mdTypeDef td, DWORD* pdwPackSize, COR_FIELD_OFFSET rFieldOffset[], ULONG cMax, ULONG* pcFieldOffset, ULONG* pulClassSize) override; - STDMETHOD(GetFieldMarshal)(mdToken tk, PCCOR_SIGNATURE* ppvNativeType, ULONG* pcbNativeType) override; - STDMETHOD(GetRVA)(mdToken tk, ULONG* pulCodeRVA, DWORD* pdwImplFlags) override; - STDMETHOD(GetPermissionSetProps)(mdPermission pm, DWORD* pdwAction, void const** ppvPermission, ULONG* pcbPermission) override; - STDMETHOD(GetModuleRefProps)(mdModuleRef mur, LPWSTR szName, ULONG cchName, ULONG* pchName) override; - STDMETHOD(EnumModuleRefs)(HCORENUM* phEnum, mdModuleRef rModuleRefs[], ULONG cmax, ULONG* pcModuleRefs) override; - STDMETHOD(GetTypeSpecFromToken)(mdTypeSpec typespec, PCCOR_SIGNATURE* ppvSig, ULONG* pcbSig) override; - STDMETHOD(GetNameFromToken)(mdToken tk, MDUTF8CSTR* pszUtf8NamePtr) override; - STDMETHOD(EnumUnresolvedMethods)(HCORENUM* phEnum, mdToken rMethods[], ULONG cMax, ULONG* pcTokens) override; - STDMETHOD(GetUserString)(mdString stk, LPWSTR szString, ULONG cchString, ULONG* pchString) override; - STDMETHOD(GetPinvokeMap)(mdToken tk, DWORD* pdwMappingFlags, LPWSTR szImportName, ULONG cchImportName, ULONG* pchImportName, mdModuleRef* pmrImportDLL) override; - STDMETHOD(EnumSignatures)(HCORENUM* phEnum, mdSignature rSignatures[], ULONG cmax, ULONG* pcSignatures) override; - STDMETHOD(EnumTypeSpecs)(HCORENUM* phEnum, mdTypeSpec rTypeSpecs[], ULONG cmax, ULONG* pcTypeSpecs) override; - STDMETHOD(EnumUserStrings)(HCORENUM* phEnum, mdString rStrings[], ULONG cmax, ULONG* pcStrings) override; - STDMETHOD(GetParamForMethodIndex)(mdMethodDef md, ULONG ulParamSeq, mdParamDef* ppd) override; - STDMETHOD(EnumCustomAttributes)(HCORENUM* phEnum, mdToken tk, mdToken tkType, mdCustomAttribute rCustomAttributes[], ULONG cMax, ULONG* pcCustomAttributes) override; - STDMETHOD(GetCustomAttributeProps)(mdCustomAttribute cv, mdToken* ptkObj, mdToken* ptkType, void const** ppBlob, ULONG* pcbSize) override; - STDMETHOD(FindTypeRef)(mdToken tkResolutionScope, LPCWSTR szName, mdTypeRef* ptr) override; - STDMETHOD(GetMemberProps)(mdToken mb, mdTypeDef* pClass, LPWSTR szMember, ULONG cchMember, ULONG* pchMember, DWORD* pdwAttr, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pcbSigBlob, ULONG* pulCodeRVA, DWORD* pdwImplFlags, DWORD* pdwCPlusTypeFlag, UVCP_CONSTANT* ppValue, ULONG* pcchValue) override; - STDMETHOD(GetFieldProps)(mdFieldDef mb, mdTypeDef* pClass, LPWSTR szField, ULONG cchField, ULONG* pchField, DWORD* pdwAttr, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pcbSigBlob, DWORD* pdwCPlusTypeFlag, UVCP_CONSTANT* ppValue, ULONG* pcchValue) override; - STDMETHOD(GetPropertyProps)(mdProperty prop, mdTypeDef* pClass, LPCWSTR szProperty, ULONG cchProperty, ULONG* pchProperty, DWORD* pdwPropFlags, PCCOR_SIGNATURE* ppvSig, ULONG* pbSig, DWORD* pdwCPlusTypeFlag, UVCP_CONSTANT* ppDefaultValue, ULONG* pcchDefaultValue, mdMethodDef* pmdSetter, mdMethodDef* pmdGetter, mdMethodDef rmdOtherMethod[], ULONG cMax, ULONG* pcOtherMethod) override; - STDMETHOD(GetParamProps)(mdParamDef tk, mdMethodDef* pmd, ULONG* pulSequence, LPWSTR szName, ULONG cchName, ULONG* pchName, DWORD* pdwAttr, DWORD* pdwCPlusTypeFlag, UVCP_CONSTANT* ppValue, ULONG* pcchValue) override; - STDMETHOD(GetCustomAttributeByName)(mdToken tkObj, LPCWSTR szName, const void** ppData, ULONG* pcbData) override; - STDMETHOD_(BOOL, IsValidToken)(mdToken tk) override; - STDMETHOD(GetNestedClassProps)(mdTypeDef tdNestedClass, mdTypeDef* ptdEnclosingClass) override; - STDMETHOD(GetNativeCallConvFromSig)(void const* pvSig, ULONG cbSig, ULONG* pCallConv) override; - STDMETHOD(IsGlobal)(mdToken pd, int* pbGlobal) override; - STDMETHOD(GetSigFromToken)(mdSignature mdSig, PCCOR_SIGNATURE* ppvSig, ULONG* pcbSig) override; - - // IMetaDataImport2 - STDMETHOD(EnumGenericParams)(HCORENUM* phEnum, mdToken tk, mdGenericParam rGenericParams[], ULONG cMax, ULONG* pcGenericParams) override; - STDMETHOD(GetGenericParamProps)(mdGenericParam gp, ULONG* pulParamSeq, DWORD* pdwParamFlags, mdToken* ptOwner, DWORD* reserved, LPWSTR wzname, ULONG cchName, ULONG* pchName) override; - STDMETHOD(GetMethodSpecProps)(mdMethodSpec mi, mdToken* tkParent, PCCOR_SIGNATURE* ppvSigBlob, ULONG* pcbSigBlob) override; - STDMETHOD(EnumGenericParamConstraints)(HCORENUM* phEnum, mdGenericParam tk, mdGenericParamConstraint rGenericParamConstraints[], ULONG cMax, ULONG* pcGenericParamConstraints) override; - STDMETHOD(GetGenericParamConstraintProps)(mdGenericParamConstraint gpc, mdGenericParam* ptGenericParam, mdToken* ptkConstraintType) override; - STDMETHOD(GetPEKind)(DWORD* pdwPEKind, DWORD* pdwMachine) override; - STDMETHOD(GetVersionString)(LPWSTR pwzBuf, DWORD ccBufSize, DWORD* pccBufSize) override; - STDMETHOD(EnumMethodSpecs)(HCORENUM* phEnum, mdToken tk, mdMethodSpec rMethodSpecs[], ULONG cMax, ULONG* pcMethodSpecs) override; - -private: - NoopMetadataImport() = default; - ~NoopMetadataImport() = default; -}; - -#endif // !DACCESS_COMPILE - -#endif // __NOOPMETADATAIMPORT_H__ From 57c848b7787fe4a06c211b9c74a9cfdbfa98066f Mon Sep 17 00:00:00 2001 From: Juan Hoyos <19413848+hoyosjs@users.noreply.github.com> Date: Thu, 25 Jun 2026 16:28:28 -0700 Subject: [PATCH 3/4] Apply suggestion from @AaronRobinsonMSFT Co-authored-by: Aaron R Robinson --- src/coreclr/vm/noopmetadataimport.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/coreclr/vm/noopmetadataimport.cpp b/src/coreclr/vm/noopmetadataimport.cpp index d3741b0bb78313..ffc5e6b7eae6d0 100644 --- a/src/coreclr/vm/noopmetadataimport.cpp +++ b/src/coreclr/vm/noopmetadataimport.cpp @@ -165,9 +165,7 @@ STDAPI CreateNoopMetaDataImport2(IMetaDataImport2** ppImport) if (ppImport == NULL) return E_POINTER; - *ppImport = &g_NoopMetadataImport; - g_NoopMetadataImport.AddRef(); - return S_OK; + return g_NoopMetadataImport.QueryInterface(IID_IMetaDataImport2, (void**)ppImport2); } #endif // !DACCESS_COMPILE From 5514c7f16f38f8c7e77c9a50d7170cc9bd75b909 Mon Sep 17 00:00:00 2001 From: Juan Hoyos <19413848+hoyosjs@users.noreply.github.com> Date: Thu, 25 Jun 2026 17:16:55 -0700 Subject: [PATCH 4/4] Fix feedback --- src/coreclr/vm/ceeload.cpp | 4 ++-- src/coreclr/vm/noopmetadataimport.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/vm/ceeload.cpp b/src/coreclr/vm/ceeload.cpp index d253c040a109b1..045f36f7440315 100644 --- a/src/coreclr/vm/ceeload.cpp +++ b/src/coreclr/vm/ceeload.cpp @@ -1811,7 +1811,7 @@ ISymUnmanagedReader *Module::GetISymUnmanagedReader(void) // (RW) metadata interface: the reader only needs it to satisfy the // binder, and producing the real importer would force this module's // metadata to its locked RW backing store. - IMetaDataImport2* pNoopImport = NULL; + SafeComHolder pNoopImport = NULL; hr = CreateNoopMetaDataImport2(&pNoopImport); if (SUCCEEDED(hr)) hr = pBinder->GetReaderFromStream(pNoopImport, pIStream, &pReader); @@ -1826,7 +1826,7 @@ ISymUnmanagedReader *Module::GetISymUnmanagedReader(void) // interface for this module: the reader only needs it to satisfy the // binder, and obtaining the real importer would force this module's // metadata to its locked RW backing store. - IMetaDataImport2* pNoopImport = NULL; + SafeComHolder pNoopImport = NULL; hr = CreateNoopMetaDataImport2(&pNoopImport); if (SUCCEEDED(hr)) hr = pBinder->GetReaderForFile(pNoopImport, path, NULL, &pReader); diff --git a/src/coreclr/vm/noopmetadataimport.cpp b/src/coreclr/vm/noopmetadataimport.cpp index ffc5e6b7eae6d0..84b31be8855540 100644 --- a/src/coreclr/vm/noopmetadataimport.cpp +++ b/src/coreclr/vm/noopmetadataimport.cpp @@ -165,7 +165,7 @@ STDAPI CreateNoopMetaDataImport2(IMetaDataImport2** ppImport) if (ppImport == NULL) return E_POINTER; - return g_NoopMetadataImport.QueryInterface(IID_IMetaDataImport2, (void**)ppImport2); + return g_NoopMetadataImport.QueryInterface(IID_IMetaDataImport2, (void**)ppImport); } #endif // !DACCESS_COMPILE