diff options
Diffstat (limited to 'src/inc/clrprivbinderutil.h')
-rw-r--r-- | src/inc/clrprivbinderutil.h | 872 |
1 files changed, 872 insertions, 0 deletions
diff --git a/src/inc/clrprivbinderutil.h b/src/inc/clrprivbinderutil.h new file mode 100644 index 0000000000..129e90388e --- /dev/null +++ b/src/inc/clrprivbinderutil.h @@ -0,0 +1,872 @@ +// 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. +// + +// +// Contains helper types for assembly binding host infrastructure. + +#ifndef __CLRPRIVBINDERUTIL_H__ +#define __CLRPRIVBINDERUTIL_H__ + +#include "holder.h" +#include "internalunknownimpl.h" +#ifdef FEATURE_FUSION +#include "fusion.h" +#endif +#include "clrprivbinding.h" +#include "slist.h" +#ifdef FEATURE_COMINTEROP +#include "windowsstring.h" +#endif // FEATURE_COMINTEROP +#include "strongnameholders.h" + +//===================================================================================================================== +#define STANDARD_BIND_CONTRACT \ + CONTRACTL { \ + NOTHROW; \ + GC_TRIGGERS; \ + MODE_PREEMPTIVE; \ + } CONTRACTL_END + +//===================================================================================================================== +// Forward declarations +interface ICLRPrivAssembly; +typedef DPTR(ICLRPrivAssembly) PTR_ICLRPrivAssembly; +typedef DPTR(ICLRPrivBinder) PTR_ICLRPrivBinder; +class PEAssembly; +class AssemblySpec; + +//===================================================================================================================== +#define VALIDATE_CONDITION(condition, fail_op) \ + do { \ + _ASSERTE((condition)); \ + if (!(condition)) \ + fail_op; \ + } while (false) + +#define VALIDATE_PTR_RET(val) VALIDATE_CONDITION(val != nullptr, return E_POINTER) +#define VALIDATE_PTR_THROW(val) VALIDATE_CONDITION(val != nullptr, ThrowHR(E_POINTER)) +#define VALIDATE_ARG_RET(condition) VALIDATE_CONDITION(condition, return E_INVALIDARG) +#define VALIDATE_ARG_THROW(condition) VALIDATE_CONDITION(condition, ThrowHR(E_INVALIDARG)) + +//===================================================================================================================== +namespace CLRPrivBinderUtil +{ + //================================================================================================================= + enum BindFlags + { + BF_BindIL = 1, + BF_BindNI = 2, + BF_Default = BF_BindIL | BF_BindNI, + }; + + //================================================================================================================= + template <typename ItfT, typename ObjT> + inline ItfT * ToInterface( + ObjT * && pObj) + { + STATIC_CONTRACT_THROWS; + + ItfT * pItf = nullptr; + IfFailThrow(pObj->QueryInterface(__uuidof(ItfT), (void **)&pItf)); + return pItf; + } + + //================================================================================================================= + template <typename ItfT, typename ObjT> + inline ItfT * ToInterface_NoThrow( + ObjT * && pObj) + { + LIMITED_METHOD_CONTRACT; + + ItfT * pItf = nullptr; + if (FAILED(pObj->QueryInterface(__uuidof(ItfT), (void **)&pItf))) + { + return nullptr; + } + return pItf; + } + + //===================================================================================================================== +#ifdef FEATURE_FUSION + class CLRPrivAssemblyBindResultWrapper : + public IUnknownCommon< + IBindResult, + IAssemblyLocation> + { + public: + //----------------------------------------------------------------------------------------------------------------- + CLRPrivAssemblyBindResultWrapper( + IAssemblyName *pIAssemblyName, + PCWSTR wzAssemblyPath, + IILFingerprintFactory *pILFingerprintFactory + ); + + //----------------------------------------------------------------------------------------------------------------- + ~CLRPrivAssemblyBindResultWrapper(); + + protected: + //================================================================================================================= + // IBindResult methods + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetAssemblyNameDef)( + /*out*/ IAssemblyName **ppIAssemblyNameDef); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetNextAssemblyModuleName)( + /*in*/ DWORD dwNIndex, + __inout_ecount(*pdwCCModuleName) LPWSTR pwzModuleName, + /*in, out, annotation("__inout")*/ LPDWORD pdwCCModuleName); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetAssemblyLocation)( + /*out*/ IAssemblyLocation **ppIAssemblyLocation); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetNativeImage)( + /*out*/ IBindResult **ppIBindResultNI, + /*out*/ BOOL *pfIBindResultNIProbed); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(SetNativeImage)( + /*in*/ IBindResult *pIBindResultNI, + /*out*/ IBindResult **ppIBindResultNIFinal); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(IsEqual)( + /*in*/ IUnknown *pIUnk); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetNextAssemblyNameRef)( + /*in*/ DWORD dwNIndex, + /*out*/ IAssemblyName **ppIAssemblyNameRef); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetNextDependentAssembly)( + /*in*/ DWORD dwNIndex, + /*out*/ IUnknown **ppIUnknownAssembly); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetAssemblyLocationOfILImage)( + /*out*/ IAssemblyLocation **ppAssemblyLocation); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetILFingerprint)( + /*out*/ IILFingerprint **ppFingerprint); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetSourceILTimestamp)( + /*out*/ FILETIME* pFileTime); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetSourceILSize)( + /*out*/ DWORD* pSize); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetNIInfo)( + /*out*/ INativeImageInstallInfo** pInfo); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetFlags)( + /*out*/ DWORD * pdwFlags); + + //================================================================================================================= + // IAssemblyLocation methods + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetLocationType)( + /*out*/DWORD *pdwLocationType); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetPath)( + __inout_ecount(*pdwccAssemblyPath) LPWSTR pwzAssemblyPath, + /*in, annotation("__inout")*/ LPDWORD pdwccAssemblyPath); + + //----------------------------------------------------------------------------------------------------------------- + STDMETHOD(GetHostID)( + /*out*/ UINT64 *puiHostID); + + private: + inline PCWSTR GetILAssemblyPath() + { LIMITED_METHOD_CONTRACT; return m_wzAssemblyPath; } + + NewArrayHolder<WCHAR> m_wzAssemblyPath; + IAssemblyName * m_pIAssemblyName; + + // Since m_bIBindResultNISet and m_pIBindResultNI are separate data, they both need + // to be treated as volatile, making sure to always fetch m_bIBindResultNISet first + // and only read m_pIBindResultNI if m_bIBindResultNISet is true. + Volatile<bool> m_bIBindResultNISet; + VolatilePtr<IBindResult> m_pIBindResultNI; + + IILFingerprint * m_pIILFingerprint; + ReleaseHolder<IILFingerprintFactory> m_pILFingerprintFactory; + + // Used as a leaf lock for publishing, such as m_pIBindResultNI. + Crst m_lock; + }; // class CLRPrivAssemblyBindResultWrapper +#endif // FEATURE_FUSION + + //================================================================================================================= + // Used to create an identity-only ICLRPrivAssembly from an ICLRPrivBinder. This is currently used when + // creating dynamic assemblies as these use the parent assembly's ICLRPrivBinder object to provide binding + // functionaltiy. + + class CLRPrivBinderAsAssemblyWrapper : + public IUnknownCommon<ICLRPrivAssembly> + { + public: + //----------------------------------------------------------------------------------------------------------------- + CLRPrivBinderAsAssemblyWrapper( + ICLRPrivBinder *pWrapped) + : _pWrapped(clr::SafeAddRef(pWrapped)) + { + STANDARD_VM_CONTRACT; + VALIDATE_ARG_THROW(pWrapped); + } + + //----------------------------------------------------------------------------------------------------------------- + // Forwards to wrapped binder. + STDMETHOD(BindAssemblyByName)( + IAssemblyName * pAssemblyName, + ICLRPrivAssembly ** ppAssembly) + { + WRAPPER_NO_CONTRACT; + return _pWrapped->BindAssemblyByName(pAssemblyName, ppAssembly); + } + + //----------------------------------------------------------------------------------------------------------------- + // Forwards to wrapped binder. + STDMETHOD(VerifyBind)( + IAssemblyName *pAssemblyName, + ICLRPrivAssembly *pAssembly, + ICLRPrivAssemblyInfo *pAssemblyInfo) + { + WRAPPER_NO_CONTRACT; + return _pWrapped->VerifyBind(pAssemblyName, pAssembly, pAssemblyInfo); + } + + //--------------------------------------------------------------------------------------------- + // Forwards to wrapped binder. + STDMETHOD(GetBinderFlags)( + DWORD *pBinderFlags) + { + WRAPPER_NO_CONTRACT; + return _pWrapped->GetBinderFlags(pBinderFlags); + } + + //----------------------------------------------------------------------------------------------------------------- + // Forwards to wrapped binder. + STDMETHOD(GetBinderID)( + UINT_PTR *pBinderId) + { + WRAPPER_NO_CONTRACT; + return _pWrapped->GetBinderID(pBinderId); + } + + //----------------------------------------------------------------------------------------------------------------- + // Forwards to wrapped binder. + STDMETHOD(FindAssemblyBySpec)( + LPVOID pvAppDomain, + LPVOID pvAssemblySpec, + HRESULT * pResult, + ICLRPrivAssembly ** ppAssembly) + { STATIC_CONTRACT_WRAPPER; return _pWrapped->FindAssemblyBySpec(pvAppDomain, pvAssemblySpec, pResult, ppAssembly); } + + //----------------------------------------------------------------------------------------------------------------- + // ICLRPrivAssembly method is unsupported. + STDMETHOD(IsShareable)( + BOOL * pbIsShareable) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE_MSG(false, "CLRPrivBinderAsAssemblyWrapper does not support ICLRPrivAssembly methods (just ICLRPrivBinder ones)!"); + VALIDATE_ARG_RET(pbIsShareable); + *pbIsShareable = FALSE; + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + //----------------------------------------------------------------------------------------------------------------- + // ICLRPrivAssembly method is unsupported. + STDMETHOD(GetAvailableImageTypes)( + LPDWORD pdwImageTypes) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE_MSG(false, "CLRPrivBinderAsAssemblyWrapper does not support ICLRPrivAssembly methods (just ICLRPrivBinder ones)!"); + VALIDATE_ARG_RET(pdwImageTypes); + *pdwImageTypes = 0; + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + //----------------------------------------------------------------------------------------------------------------- + // ICLRPrivAssembly method is unsupported. + STDMETHOD(GetImageResource)( + DWORD dwImageType, + DWORD* pdwImageType, + ICLRPrivResource ** ppIResource) + { + LIMITED_METHOD_CONTRACT; + _ASSERTE_MSG(false, "CLRPrivBinderAsAssemblyWrapper does not support ICLRPrivAssembly methods (just ICLRPrivBinder ones)!"); + VALIDATE_ARG_RET(pdwImageType); + *pdwImageType = 0; + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + } + + private: + ReleaseHolder<ICLRPrivBinder> _pWrapped; + }; + + //================================================================================================================= + // Provides a struct that can be accessed at the QWORD, DWORD, or WORD level, and is structured + + struct AssemblyVersion + { +#if BIGENDIAN + union + { + UINT64 qwMajorMinorBuildRevision; + struct + { + union + { + DWORD dwMajorMinor; + struct + { + WORD wMajor; + WORD wMinor; + }; + }; + union + { + DWORD dwBuildRevision; + struct + { + WORD wBuild; + WORD wRevision; + }; + }; + }; + }; +#else + union + { + UINT64 qwMajorMinorBuildRevision; + struct + { + union + { + DWORD dwBuildRevision; + struct + { + WORD wRevision; + WORD wBuild; + }; + }; + union + { + DWORD dwMajorMinor; + struct + { + WORD wMinor; + WORD wMajor; + }; + }; + }; + }; +#endif + + // Default value is 0.0.0.0 + AssemblyVersion() + : qwMajorMinorBuildRevision(static_cast<UINT64>(0)) + { LIMITED_METHOD_CONTRACT; } + + // Copy constructor + AssemblyVersion(AssemblyVersion const & other) + : qwMajorMinorBuildRevision(other.qwMajorMinorBuildRevision) + { LIMITED_METHOD_CONTRACT; } + + // Initialize version using an IAssemblyName object. + HRESULT Initialize(IAssemblyName * pName); + + // Initialize version using an ICLRPrivAssemblyInfo object. + HRESULT Initialize(ICLRPrivAssemblyInfo * pInfo); + + // Relative ordering of versions. + static inline int Compare( + AssemblyVersion const & left, + AssemblyVersion const & right) + { + LIMITED_METHOD_CONTRACT; + + if (left.qwMajorMinorBuildRevision < right.qwMajorMinorBuildRevision) + return -1; + else if (left.qwMajorMinorBuildRevision == right.qwMajorMinorBuildRevision) + return 0; + else + return 1; + } + }; // struct AssemblyVersion + + inline bool operator ==(AssemblyVersion const & lhs, AssemblyVersion const & rhs) + { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision == rhs.qwMajorMinorBuildRevision; } + + inline bool operator !=(AssemblyVersion const & lhs, AssemblyVersion const & rhs) + { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision != rhs.qwMajorMinorBuildRevision; } + + inline bool operator <(AssemblyVersion const & lhs, AssemblyVersion const & rhs) + { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision < rhs.qwMajorMinorBuildRevision; } + + inline bool operator <=(AssemblyVersion const & lhs, AssemblyVersion const & rhs) + { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision <= rhs.qwMajorMinorBuildRevision; } + + inline bool operator >(AssemblyVersion const & lhs, AssemblyVersion const & rhs) + { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision > rhs.qwMajorMinorBuildRevision; } + + inline bool operator >=(AssemblyVersion const & lhs, AssemblyVersion const & rhs) + { LIMITED_METHOD_CONTRACT; return lhs.qwMajorMinorBuildRevision >= rhs.qwMajorMinorBuildRevision; } + + //================================================================================================================= + // Encapsulates PublicKey value, can be initialized using a variety of data sources. + + struct PublicKey + { + // Defaults to empty value. + PublicKey() + : m_key(nullptr) + , m_key_owned(false) + , m_size((DWORD)-1) + { LIMITED_METHOD_CONTRACT; } + + // Construct directly from existing public key data. + PublicKey(PBYTE pbKey, DWORD cbKey) + : m_key(pbKey) + , m_key_owned(false) + , m_size(cbKey) + { LIMITED_METHOD_CONTRACT; } + + ~PublicKey() + { WRAPPER_NO_CONTRACT; Uninitialize(); } + + // Frees any public key data and resets to default value. + void Uninitialize() + { + LIMITED_METHOD_CONTRACT; + + if (m_key_owned) + { + delete [] m_key; + m_key_owned = false; + } + m_key = nullptr; + m_size = 0; + } + + // Initialize PK data form an ICLRPrivAssemblyInfo object. + HRESULT Initialize(ICLRPrivAssemblyInfo * pAssemblyInfo); + + // Returns PK data pointer. + inline BYTE const * GetKey() const + { LIMITED_METHOD_CONTRACT; return m_key; } + + // Returns size in bytes of the PK data. + inline DWORD GetSize() const + { LIMITED_METHOD_CONTRACT; return m_size; } + + private: + PBYTE m_key; + bool m_key_owned; + DWORD m_size; + }; + + //================================================================================================================= + // Encapsulates PublicKeyToken value, can be initialized using a variety of data sources. + // + // Constraints: assumes that non-empty PKT data will always be 8 bytes long. + // + + struct PublicKeyToken + { + PublicKeyToken() + : m_cbKeyToken(0) + { LIMITED_METHOD_CONTRACT; ZeroMemory(&m_rbKeyToken, sizeof(m_rbKeyToken)); } + + PublicKeyToken(PublicKeyToken const & other) + : m_cbKeyToken(other.m_cbKeyToken) + { LIMITED_METHOD_CONTRACT; CopyMemory(m_rbKeyToken, other.m_rbKeyToken, sizeof(m_rbKeyToken)); } + + // Initialize directly from PKT data. + HRESULT Initialize(BYTE * pbKeyToken, DWORD cbKeyToken); + + // Converts PK data to PKT data. + HRESULT Initialize(PublicKey const & pk); + + // Initialize using the PKT value contained by pName; returns S_FALSE if there is no associated PKT. + HRESULT Initialize(IAssemblyName * pName); + + // Initialize using the PK data contained by pInfo; returns S_FALSE if there is no associated PK. + HRESULT Initialize(ICLRPrivAssemblyInfo * pInfo); + + // PKT data. + BYTE const * GetToken() const + { LIMITED_METHOD_CONTRACT; return m_rbKeyToken; } + + // Size in bytes of the PKT (should always be 0 or 8). + DWORD GetSize() const + { LIMITED_METHOD_CONTRACT; return m_cbKeyToken; } + + private: + static const DWORD PUBLIC_KEY_TOKEN_LEN1 = 8; + BYTE m_rbKeyToken[PUBLIC_KEY_TOKEN_LEN1]; + DWORD m_cbKeyToken; + }; + + bool operator==(PublicKeyToken const & lhs, PublicKeyToken const & rhs); + + inline bool operator!=(PublicKeyToken const & lhs, PublicKeyToken const & rhs) + { WRAPPER_NO_CONTRACT; return !(lhs == rhs); } + + //================================================================================================================= + // Encapsulates data required for packaged assembly identity: simple name, version, and public key token. + // + // Constraints: assumes that the assembly simple name is no longer than _MAX_PATH + // + + struct AssemblyIdentity + { + AssemblyIdentity() + { LIMITED_METHOD_CONTRACT; Name[0] = W('\0'); } + + AssemblyIdentity(AssemblyIdentity const & other) + : Version(other.Version) + , KeyToken(other.KeyToken) + { LIMITED_METHOD_CONTRACT; CopyMemory(Name, other.Name, sizeof(Name)); } + + // Initialize from assembly simple name; default version and empty PKT values are used. + HRESULT Initialize(LPCWSTR wzName); + + // Initialize from an ICLRPrivAssemblyInfo object. + HRESULT Initialize(ICLRPrivAssemblyInfo * pAssemblyInfo); + + // Initialize from an IAssemblyName object. + HRESULT Initialize(IAssemblyName * pAssemblyName); + + // Initialize from an AssemblySpec object. + HRESULT Initialize(AssemblySpec * pSpec); + + // Assembly simple name + WCHAR Name[_MAX_PATH]; + + // Assembly version; defaults to 0.0.0.0. + CLRPrivBinderUtil::AssemblyVersion Version; + + // Assembly public key token; defaults to none. + CLRPrivBinderUtil::PublicKeyToken KeyToken; + }; + + //================================================================================================================= + HRESULT VerifyBind( + IAssemblyName *pRefAssemblyName, + ICLRPrivAssemblyInfo *pDefAssemblyInfo); + + //================================================================================================================= + HRESULT VerifyBind( + CLRPrivBinderUtil::AssemblyIdentity const & refIdentity, + CLRPrivBinderUtil::AssemblyIdentity const & defIdentity); + + //================================================================================================= + template <typename ItfT> + struct CLRPrivResourceBase : + public IUnknownCommon<ICLRPrivResource> + { + //--------------------------------------------------------------------------------------------- + STDMETHOD(GetResourceType)( + IID *pIID) + { + LIMITED_METHOD_CONTRACT; + if (pIID == nullptr) + return E_INVALIDARG; + *pIID = __uuidof(ItfT); + return S_OK; + } + }; + + //================================================================================================================= + class CLRPrivResourcePathImpl : + public IUnknownCommon< ItfBase< CLRPrivResourceBase< ICLRPrivResourcePath > >, + ICLRPrivResourcePath > + { + public: + //--------------------------------------------------------------------------------------------- + CLRPrivResourcePathImpl(LPCWSTR wzPath); + + //--------------------------------------------------------------------------------------------- + LPCWSTR GetPath() + { return m_wzPath; } + + // + // ICLRPrivResourcePath methods + // + + //--------------------------------------------------------------------------------------------- + STDMETHOD(GetPath)( + DWORD cchBuffer, + LPDWORD pcchBuffer, + __inout_ecount_part(cchBuffer, *pcchBuffer) LPWSTR wzBuffer); + + private: + //--------------------------------------------------------------------------------------------- + NewArrayHolder<WCHAR> m_wzPath; + }; + + //================================================================================================================= + class CLRPrivResourceStreamImpl : + public IUnknownCommon< ItfBase< CLRPrivResourceBase<ICLRPrivResourceStream > >, + ICLRPrivResourceStream> + { + public: + //--------------------------------------------------------------------------------------------- + CLRPrivResourceStreamImpl(IStream * pStream); + + //--------------------------------------------------------------------------------------------- + STDMETHOD(GetStream)( + REFIID riid, + LPVOID * ppvStream); + + private: + //--------------------------------------------------------------------------------------------- + ReleaseHolder<IStream> m_pStream; + }; + + //================================================================================================================= + // Helper to prioritize binder errors. This class will ensure that all other errors have priority over + // CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT. This class should be used just like an HRESULT variable. + class BinderHRESULT + { + public: + BinderHRESULT() + : m_hr(S_OK) + {} + + BinderHRESULT(HRESULT hr) + : m_hr(hr) + {} + + operator HRESULT() const + { return m_hr; } + + BinderHRESULT & operator=(HRESULT hr) + { + // Always record change in success/failure status. + if (FAILED(hr) != FAILED(m_hr)) + m_hr = hr; + + if (FAILED(hr)) + { + if (SUCCEEDED(m_hr)) + m_hr = hr; + else if (m_hr == CLR_E_BIND_UNRECOGNIZED_IDENTITY_FORMAT) + m_hr = hr; + } + else + { + m_hr = hr; + } + return *this; + } + + private: + HRESULT m_hr; + }; // class BinderHRESULT + + //================================================================================================================= + // Types for WStringList (used in WinRT binders) + + typedef SListElem< PTR_WSTR > WStringListElem; + typedef DPTR(WStringListElem) PTR_WStringListElem; + typedef SList< WStringListElem, false /* = fHead default value */, PTR_WStringListElem > WStringList; + typedef DPTR(WStringList) PTR_WStringList; + + // Destroys list of strings (code:WStringList). + void WStringList_Delete(WStringList * pList); + +#ifndef DACCESS_COMPILE + //===================================================================================================================== + // Holder of allocated code:WStringList (helper class for WinRT binders - e.g. code:CLRPrivBinderWinRT::GetFileNameListForNamespace). + class WStringListHolder + { + public: + WStringListHolder(WStringList * pList = nullptr) + { + LIMITED_METHOD_CONTRACT; + m_pList = pList; + } + ~WStringListHolder() + { + LIMITED_METHOD_CONTRACT; + Destroy(); + } + + void InsertTail(LPCWSTR wszValue) + { + CONTRACTL + { + THROWS; + GC_NOTRIGGER; + MODE_ANY; + } + CONTRACTL_END; + + NewArrayHolder<WCHAR> wszElemValue = DuplicateStringThrowing(wszValue); + NewHolder<WStringListElem> pElem = new WStringListElem(wszElemValue); + + if (m_pList == nullptr) + { + m_pList = new WStringList(); + } + + m_pList->InsertTail(pElem.Extract()); + // The string is now owned by the list + wszElemValue.SuppressRelease(); + } + + WStringList * GetValue() + { + LIMITED_METHOD_CONTRACT; + return m_pList; + } + + WStringList * Extract() + { + LIMITED_METHOD_CONTRACT; + + WStringList * pList = m_pList; + m_pList = nullptr; + return pList; + } + + private: + void Destroy() + { + LIMITED_METHOD_CONTRACT; + + if (m_pList != nullptr) + { + WStringList_Delete(m_pList); + m_pList = nullptr; + } + } + + private: + WStringList * m_pList; + }; // class WStringListHolder +#endif //!DACCESS_COMPILE + +#ifdef FEATURE_COMINTEROP + //===================================================================================================================== + // Holder of allocated array of HSTRINGs (helper class for WinRT binders - e.g. code:CLRPrivBinderWinRT::m_rgAltPaths). + class HSTRINGArrayHolder + { + public: + HSTRINGArrayHolder() + { + LIMITED_METHOD_CONTRACT; + + m_cValues = 0; + m_rgValues = nullptr; + } +#ifndef DACCESS_COMPILE + ~HSTRINGArrayHolder() + { + LIMITED_METHOD_CONTRACT; + Destroy(); + } + + // Destroys current array and allocates a new one with cValues elements. + void Allocate(DWORD cValues) + { + STANDARD_VM_CONTRACT; + + Destroy(); + _ASSERTE(m_cValues == 0); + + if (cValues > 0) + { + m_rgValues = new HSTRING[cValues]; + m_cValues = cValues; + + // Initialize the array values + for (DWORD i = 0; i < cValues; i++) + { + m_rgValues[i] = nullptr; + } + } + } +#endif //!DACCESS_COMPILE + + HSTRING GetAt(DWORD index) const + { + LIMITED_METHOD_CONTRACT; + return m_rgValues[index]; + } + + HSTRING * GetRawArray() + { + LIMITED_METHOD_CONTRACT; + return m_rgValues; + } + + DWORD GetCount() + { + LIMITED_METHOD_CONTRACT; + return m_cValues; + } + + private: +#ifndef DACCESS_COMPILE + void Destroy() + { + LIMITED_METHOD_CONTRACT; + + for (DWORD i = 0; i < m_cValues; i++) + { + if (m_rgValues[i] != nullptr) + { + WindowsDeleteString(m_rgValues[i]); + } + } + m_cValues = 0; + + if (m_rgValues != nullptr) + { + delete [] m_rgValues; + m_rgValues = nullptr; + } + } +#endif //!DACCESS_COMPILE + + private: + DWORD m_cValues; + HSTRING * m_rgValues; + }; // class HSTRINGArrayHolder + +#endif // FEATURE_COMINTEROP + + //////////////////////////////////////////////////////////////////////////////////////////////////// + ///// ----------------------------- Questionable stuff ------------------------------------------- + //////////////////////////////////////////////////////////////////////////////////////////////////// + + /** probably should be exposed on an instance (of something) method rather that magically calling GetAppDomain() **/ + ICLRPrivAssembly* RaiseAssemblyResolveEvent(IAssemblyName *pAssemblyName, ICLRPrivAssembly* pRequestingAssembly); + + /** PLACEHOLDER - CLRPRivBinderFusion::BindAssemblyByName throws, despite being an HRESULT function, + most presumably because returning HRESULT is too lossy **/ + + /** Ultimately, only the binder can do ref-def matching, and it should be opaque to CLR. + This is not trivial to do, however, since we cannot do data conversion as the function is nofault **/ + BOOL CompareHostBinderSpecs(AssemblySpec* a1, AssemblySpec* a2); + + /** PLACEHOLDER - the same issue as CompareHostBinderSpecs applies to hashing assemblyspecs **/ +} // namespace CLRPrivBinderUtil + +#endif // __CLRPRIVBINDERUTIL_H__ |