Rewrite Type.GetTypeFromProgID in C# (#42546)
authorJan Kotas <jkotas@microsoft.com>
Wed, 23 Sep 2020 01:08:15 +0000 (18:08 -0700)
committerGitHub <noreply@github.com>
Wed, 23 Sep 2020 01:08:15 +0000 (18:08 -0700)
- Move CoreRT managed implementation of Type.GetTypeFromProgID to CoreCLR
- Delete dead code and unnecessary levels of indirection
- Add tests for Type.GetTypeFromProgID and Type.GetTypeFromCLSID

23 files changed:
src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs
src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs
src/coreclr/src/System.Private.CoreLib/src/System/Type.CoreCLR.cs
src/coreclr/src/vm/ecalllist.h
src/coreclr/src/vm/eehash.cpp
src/coreclr/src/vm/eehash.h
src/coreclr/src/vm/interoputil.cpp
src/coreclr/src/vm/interoputil.h
src/coreclr/src/vm/marshalnative.cpp
src/coreclr/src/vm/marshalnative.h
src/coreclr/src/vm/reflectioninvocation.cpp
src/coreclr/src/vm/reflectioninvocation.h
src/coreclr/src/vm/runtimecallablewrapper.cpp
src/coreclr/src/vm/runtimecallablewrapper.h
src/libraries/Common/src/Interop/Windows/Ole32/Interop.CLSIDFromProgID.cs [new file with mode: 0644]
src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NoCom.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Unix.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Windows.cs
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.cs
src/libraries/System.Private.CoreLib/src/System/Type.cs
src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetTypeFromCLSIDTests.cs
src/mono/netcore/System.Private.CoreLib/src/System/Type.Mono.cs

index 3d04b92..f979ed4 100644 (file)
@@ -275,8 +275,18 @@ namespace System.Runtime.InteropServices
 
         // This method is identical to Type.GetTypeFromCLSID. Since it's interop specific, we expose it
         // on Marshal for more consistent API surface.
-        [SupportedOSPlatform("windows")]
-        public static Type? GetTypeFromCLSID(Guid clsid) => RuntimeType.GetTypeFromCLSIDImpl(clsid, null, throwOnError: false);
+        internal static Type? GetTypeFromCLSID(Guid clsid, string? server, bool throwOnError)
+        {
+            // Note: "throwOnError" is a vacuous parameter. Any errors due to the CLSID not being registered or the server not being found will happen
+            // on the Activator.CreateInstance() call. GetTypeFromCLSID() merely wraps the data in a Type object without any validation.
+
+            Type? type = null;
+            GetTypeFromCLSID(clsid, server, ObjectHandleOnStack.Create(ref type));
+            return type;
+        }
+
+        [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)]
+        private static extern void GetTypeFromCLSID(in Guid clsid, string? server, ObjectHandleOnStack retType);
 
         /// <summary>
         /// Return the IUnknown* for an Object if the current context is the one
index f0d6247..9aef6b1 100644 (file)
@@ -4085,24 +4085,6 @@ namespace System
             bool[]? byrefModifiers, int culture, string[]? namedParameters);
 #endif // FEATURE_COMINTEROP
 
-#if FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        internal static extern Type? GetTypeFromProgIDImpl(string progID, string? server, bool throwOnError);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        internal static extern Type? GetTypeFromCLSIDImpl(Guid clsid, string? server, bool throwOnError);
-#else // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
-        internal static Type GetTypeFromProgIDImpl(string progID, string? server, bool throwOnError)
-        {
-            throw new NotImplementedException("CoreCLR_REMOVED -- Unmanaged activation removed");
-        }
-
-        internal static Type GetTypeFromCLSIDImpl(Guid clsid, string? server, bool throwOnError)
-        {
-            throw new NotImplementedException("CoreCLR_REMOVED -- Unmanaged activation removed");
-        }
-#endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
-
         #endregion
 
 #if FEATURE_COMINTEROP
index 5bd6cc2..7a39e6e 100644 (file)
@@ -81,34 +81,6 @@ namespace System
             return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark);
         }
 
-        ////////////////////////////////////////////////////////////////////////////////
-        // This will return a class based upon the progID.  This is provided for
-        // COM classic support.  Program ID's are not used in COM+ because they
-        // have been superceded by namespace.  (This routine is called this instead
-        // of getClass() because of the name conflict with the first method above.)
-        //
-        //   param progID:     the progID of the class to retrieve
-        //   returns:          the class object associated to the progID
-        ////
-        [SupportedOSPlatform("windows")]
-        public static Type? GetTypeFromProgID(string progID, string? server, bool throwOnError)
-        {
-            return RuntimeType.GetTypeFromProgIDImpl(progID, server, throwOnError);
-        }
-
-        ////////////////////////////////////////////////////////////////////////////////
-        // This will return a class based upon the CLSID.  This is provided for
-        // COM classic support.
-        //
-        //   param CLSID:      the CLSID of the class to retrieve
-        //   returns:          the class object associated to the CLSID
-        ////
-        [SupportedOSPlatform("windows")]
-        public static Type? GetTypeFromCLSID(Guid clsid, string? server, bool throwOnError)
-        {
-            return RuntimeType.GetTypeFromCLSIDImpl(clsid, server, throwOnError);
-        }
-
         internal virtual RuntimeTypeHandle GetTypeHandleInternal()
         {
             return TypeHandle;
index 87eed0c..ca9ef6a 100644 (file)
@@ -200,8 +200,6 @@ FCFuncStart(gSystem_RuntimeType)
     FCFuncElement("CanValueSpecialCast", ReflectionInvocation::CanValueSpecialCast)
     FCFuncElement("AllocateValueType", ReflectionInvocation::AllocateValueType)
 #if defined(FEATURE_COMINTEROP)
-    FCFuncElement("GetTypeFromCLSIDImpl", ReflectionInvocation::GetClassFromCLSID)
-    FCFuncElement("GetTypeFromProgIDImpl", ReflectionInvocation::GetClassFromProgID)
     FCFuncElement("InvokeDispMethod", ReflectionInvocation::InvokeDispMethod)
 #endif // defined(FEATURE_COMINTEROP)
 FCFuncEnd()
@@ -794,6 +792,7 @@ FCFuncStart(gInteropMarshalFuncs)
     FCFuncElement("GetTypedObjectForIUnknown", MarshalNative::GetTypedObjectForIUnknown)
     FCFuncElement("ChangeWrapperHandleStrength", MarshalNative::ChangeWrapperHandleStrength)
     FCFuncElement("CleanupUnusedObjectsInCurrentContext", MarshalNative::CleanupUnusedObjectsInCurrentContext)
+    QCFuncElement("GetTypeFromCLSID", MarshalNative::GetTypeFromCLSID)
 #endif // FEATURE_COMINTEROP
 FCFuncEnd()
 
index 97bcb58..39054c7 100644 (file)
@@ -431,7 +431,7 @@ DWORD EEClassFactoryInfoHashTableHelper::Hash(ClassFactoryInfo *pKey)
 
     if (pKey->m_strServerName)
     {
-        WCHAR *pSrvNameData = pKey->m_strServerName;
+        PCWSTR pSrvNameData = pKey->m_strServerName;
 
         while (*pSrvNameData != 0)
         {
index f45935c..f499668 100644 (file)
@@ -563,8 +563,8 @@ typedef EEHashTable<const SigTypeContext*, EEInstantiationHashTableHelper, FALSE
 
 struct ClassFactoryInfo
 {
-    GUID     m_clsid;
-    WCHAR   *m_strServerName;
+    GUID    m_clsid;
+    PCWSTR  m_strServerName;
 };
 
 class EEClassFactoryInfoHashTableHelper
index fc2fb3c..43dda1c 100644 (file)
@@ -3772,22 +3772,20 @@ void IUInvokeDispMethod(
 
 #if defined(FEATURE_COMINTEROP_UNMANAGED_ACTIVATION) && defined(FEATURE_COMINTEROP)
 
-void GetComClassHelper(
+static void GetComClassHelper(
     _Out_ OBJECTREF *pRef,
     _In_ EEClassFactoryInfoHashTable *pClassFactHash,
-    _In_ ClassFactoryInfo *pClassFactInfo,
-    _In_opt_ WCHAR *wszProgID)
+    _In_ ClassFactoryInfo *pClassFactInfo)
 {
     CONTRACTL
     {
         THROWS;
         GC_TRIGGERS;
-        MODE_ANY;
+        MODE_COOPERATIVE;
         INJECT_FAULT(ThrowOutOfMemory());
         PRECONDITION(CheckPointer(pRef));
         PRECONDITION(CheckPointer(pClassFactHash));
         PRECONDITION(CheckPointer(pClassFactInfo));
-        PRECONDITION(CheckPointer(wszProgID, NULL_OK));
     }
     CONTRACTL_END;
 
@@ -3809,17 +3807,9 @@ void GetComClassHelper(
         // represent it.
         //
 
-        NewHolder<ComClassFactory> pComClsFac = ComClassFactoryCreator::Create(pClassFactInfo->m_clsid);
+        NewHolder<ComClassFactory> pComClsFac = new ComClassFactory(pClassFactInfo->m_clsid);
         pComClsFac->SetManagedVersion();
 
-        NewArrayHolder<WCHAR> wszRefProgID = NULL;
-        if (wszProgID)
-        {
-            size_t len = wcslen(wszProgID)+1;
-            wszRefProgID = new WCHAR[len];
-            wcscpy_s(wszRefProgID, len, wszProgID);
-        }
-
         NewArrayHolder<WCHAR> wszRefServer = NULL;
         if (pClassFactInfo->m_strServerName)
         {
@@ -3828,7 +3818,7 @@ void GetComClassHelper(
             wcscpy_s(wszRefServer, len, pClassFactInfo->m_strServerName);
         }
 
-        pComClsFac->Init(wszRefProgID, wszRefServer, NULL);
+        pComClsFac->Init(wszRefServer, NULL);
         AllocateComClassObject(pComClsFac, pRef);
 
         // Insert to hash.
@@ -3838,7 +3828,6 @@ void GetComClassHelper(
         // Make sure the hash code is working.
         _ASSERTE (pClassFactHash->GetValue(pClassFactInfo, (HashDatum *)&hRef));
 
-        wszRefProgID.SuppressRelease();
         wszRefServer.SuppressRelease();
         pComClsFac.SuppressRelease();
     }
@@ -3846,7 +3835,7 @@ void GetComClassHelper(
 
 //-------------------------------------------------------------
 // returns a ComClass reflect class that wraps the IClassFactory
-void GetComClassFromProgID(STRINGREF srefProgID, STRINGREF srefServer, OBJECTREF *pRef)
+void GetComClassFromCLSID(REFCLSID clsid, _In_opt_z_ PCWSTR wszServer, OBJECTREF *pRef)
 {
     CONTRACTL
     {
@@ -3854,114 +3843,10 @@ void GetComClassFromProgID(STRINGREF srefProgID, STRINGREF srefServer, OBJECTREF
         GC_TRIGGERS;
         MODE_COOPERATIVE;
         INJECT_FAULT(COMPlusThrowOM());
-        PRECONDITION(srefProgID != NULL);
         PRECONDITION(pRef != NULL);
     }
     CONTRACTL_END;
 
-    NewArrayHolder<WCHAR>   wszProgID;
-    NewArrayHolder<WCHAR>   wszServer;
-    HRESULT                 hr          = S_OK;
-    MethodTable*            pMT         = NULL;
-    CLSID                   clsid       = {0};
-
-    //
-    // Allocate strings for the ProgID and the server.
-    //
-
-    int len = srefProgID->GetStringLength();
-
-    wszProgID = new WCHAR[len+1];
-
-    if (len)
-        memcpy(wszProgID, srefProgID->GetBuffer(), (len*2));
-    wszProgID[len] = W('\0');
-
-    if (srefServer != NULL)
-    {
-        len = srefServer->GetStringLength();
-
-        wszServer = new WCHAR[len+1];
-
-        if (len)
-            memcpy(wszServer, srefServer->GetBuffer(), (len*2));
-        wszServer[len] = W('\0');
-    }
-
-
-    //
-    // Call GetCLSIDFromProgID() to convert the ProgID to a CLSID.
-    //
-
-    EnsureComStarted();
-
-    {
-        GCX_PREEMP();
-        hr = GetCLSIDFromProgID(wszProgID, &clsid);
-    }
-
-    if (FAILED(hr))
-        COMPlusThrowHR(hr);
-
-    //
-    // See if we can find the well known managed class for this CLSID.
-    //
-
-    // Check if we have in the hash.
-    OBJECTHANDLE hRef;
-    ClassFactoryInfo ClassFactInfo;
-    ClassFactInfo.m_clsid = clsid;
-    ClassFactInfo.m_strServerName = wszServer;
-    EEClassFactoryInfoHashTable *pClassFactHash = GetAppDomain()->GetClassFactHash();
-
-    if (pClassFactHash->GetValue(&ClassFactInfo, (HashDatum *)&hRef))
-    {
-        *pRef = ObjectFromHandle(hRef);
-    }
-    else
-    {
-        GetComClassHelper(pRef, pClassFactHash, &ClassFactInfo, wszProgID);
-    }
-
-    // If we made it this far *pRef better be set.
-    _ASSERTE(*pRef != NULL);
-}
-
-//-------------------------------------------------------------
-// returns a ComClass reflect class that wraps the IClassFactory
-void GetComClassFromCLSID(REFCLSID clsid, STRINGREF srefServer, OBJECTREF *pRef)
-{
-    CONTRACTL
-    {
-        THROWS;
-        GC_TRIGGERS;
-        MODE_COOPERATIVE;
-        INJECT_FAULT(COMPlusThrowOM());
-        PRECONDITION(pRef != NULL);
-    }
-    CONTRACTL_END;
-
-    NewArrayHolder<WCHAR>   wszServer;
-    HRESULT                 hr              = S_OK;
-    MethodTable*            pMT             = NULL;
-
-    //
-    // Allocate strings for the server.
-    //
-
-    if (srefServer != NULL)
-    {
-        int len = srefServer->GetStringLength();
-
-        wszServer = new WCHAR[len+1];
-
-        if (len)
-            memcpy(wszServer, srefServer->GetBuffer(), (len*2));
-
-        wszServer[len] = W('\0');
-    }
-
-
     //
     // See if we can find the well known managed class for this CLSID.
     //
@@ -3979,7 +3864,7 @@ void GetComClassFromCLSID(REFCLSID clsid, STRINGREF srefServer, OBJECTREF *pRef)
     }
     else
     {
-        GetComClassHelper(pRef, pClassFactHash, &ClassFactInfo, NULL);
+        GetComClassHelper(pRef, pClassFactHash, &ClassFactInfo);
     }
 
     // If we made it this far *pRef better be set.
@@ -4027,11 +3912,11 @@ ClassFactoryBase *GetComClassFactory(MethodTable* pClassMT)
         GUID guid;
         pClassMT->GetGuid(&guid, TRUE);
 
-        ComClassFactory *pComClsFac = ComClassFactoryCreator::Create(guid);
+        ComClassFactory *pComClsFac = new ComClassFactory(guid);
 
         pNewFactory = pComClsFac;
 
-        pComClsFac->Init(NULL, NULL, pClassMT);
+        pComClsFac->Init(NULL, pClassMT);
 
         // store the class factory in EE Class
         if (!pClassMT->SetComClassFactory(pNewFactory))
index 3938a0a..9f51dfe 100644 (file)
@@ -353,12 +353,8 @@ void IUInvokeDispMethod(
 // Class Factory helpers
 
 //--------------------------------------------------------------------------
-// GetComClassFromProgID used by reflection class to setup a Class based on ProgID
-void GetComClassFromProgID(STRINGREF srefProgID, STRINGREF srefServer, OBJECTREF* pRef);
-
-//--------------------------------------------------------------------------
 // GetComClassFromCLSID used by reflection class to setup a Class based on CLSID
-void GetComClassFromCLSID(REFCLSID clsid, STRINGREF srefServer, OBJECTREF* pRef);
+void GetComClassFromCLSID(REFCLSID clsid, _In_opt_z_ PCWSTR wszServer, OBJECTREF* pRef);
 
 //-------------------------------------------------------------
 // check if a ComClassFactory has been setup for this class
index 46a7742..91f311b 100644 (file)
@@ -1318,171 +1318,6 @@ FCIMPL2(Object*, MarshalNative::GetObjectsForNativeVariants, VARIANT* aSrcNative
 }
 FCIMPLEND
 
-FCIMPL2(void, MarshalNative::DoGetTypeLibGuid, GUID * result, Object* refTlbUNSAFE)
-{
-    FCALL_CONTRACT;
-
-    OBJECTREF refTlb = (OBJECTREF) refTlbUNSAFE;
-    HELPER_METHOD_FRAME_BEGIN_1(refTlb);
-    GCPROTECT_BEGININTERIOR (result);
-
-    if (refTlb == NULL)
-        COMPlusThrowArgumentNull(W("pTLB"));
-
-    // Ensure COM is started up.
-    EnsureComStarted();
-
-    SafeComHolder<ITypeLib> pTLB = (ITypeLib*)GetComIPFromObjectRef(&refTlb, IID_ITypeLib);
-    if (!pTLB)
-        COMPlusThrow(kArgumentException, W("Arg_NoITypeLib"));
-
-    GCX_PREEMP();
-
-    // Retrieve the TLIBATTR.
-    TLIBATTR *pAttr;
-    IfFailThrow(pTLB->GetLibAttr(&pAttr));
-
-    // Extract the guid from the TLIBATTR.
-    *result = pAttr->guid;
-
-    // Release the TLIBATTR now that we have the GUID.
-    pTLB->ReleaseTLibAttr(pAttr);
-
-    GCPROTECT_END ();
-    HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-FCIMPL1(LCID, MarshalNative::GetTypeLibLcid, Object* refTlbUNSAFE)
-{
-    FCALL_CONTRACT;
-
-    LCID retVal = 0;
-    OBJECTREF refTlb = (OBJECTREF) refTlbUNSAFE;
-    HELPER_METHOD_FRAME_BEGIN_RET_1(refTlb);
-
-    if (refTlb == NULL)
-        COMPlusThrowArgumentNull(W("pTLB"));
-
-    // Ensure COM is started up.
-    EnsureComStarted();
-
-    SafeComHolder<ITypeLib> pTLB = (ITypeLib*)GetComIPFromObjectRef(&refTlb, IID_ITypeLib);
-    if (!pTLB)
-        COMPlusThrow(kArgumentException, W("Arg_NoITypeLib"));
-
-    GCX_PREEMP();
-
-    // Retrieve the TLIBATTR.
-    TLIBATTR *pAttr;
-    IfFailThrow(pTLB->GetLibAttr(&pAttr));
-
-    // Extract the LCID from the TLIBATTR.
-    retVal = pAttr->lcid;
-
-    // Release the TLIBATTR now that we have the LCID.
-    pTLB->ReleaseTLibAttr(pAttr);
-
-    HELPER_METHOD_FRAME_END();
-    return retVal;
-}
-FCIMPLEND
-
-FCIMPL3(void, MarshalNative::GetTypeLibVersion, Object* refTlbUNSAFE, int *pMajor, int *pMinor)
-{
-    FCALL_CONTRACT;
-
-    OBJECTREF refTlb = (OBJECTREF) refTlbUNSAFE;
-    HELPER_METHOD_FRAME_BEGIN_1(refTlb);
-
-    if (refTlb == NULL)
-        COMPlusThrowArgumentNull(W("typeLibrary"));
-
-    // Ensure COM is started up.
-    EnsureComStarted();
-
-    SafeComHolder<ITypeLib> pTLB = (ITypeLib*)GetComIPFromObjectRef(&refTlb, IID_ITypeLib);
-    if (!pTLB)
-        COMPlusThrow(kArgumentException, W("Arg_NoITypeLib"));
-
-    GCX_PREEMP();
-
-    // Retrieve the TLIBATTR.
-    TLIBATTR *pAttr;
-    IfFailThrow(pTLB->GetLibAttr(&pAttr));
-
-    // Extract the LCID from the TLIBATTR.
-    *pMajor = pAttr->wMajorVerNum;
-    *pMinor = pAttr->wMinorVerNum;
-
-    // Release the TLIBATTR now that we have the version numbers.
-    pTLB->ReleaseTLibAttr(pAttr);
-
-    HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-FCIMPL2(void, MarshalNative::DoGetTypeInfoGuid, GUID * result, Object* refTypeInfoUNSAFE)
-{
-    FCALL_CONTRACT;
-
-    OBJECTREF refTypeInfo = (OBJECTREF) refTypeInfoUNSAFE;
-    HELPER_METHOD_FRAME_BEGIN_1(refTypeInfo);
-    GCPROTECT_BEGININTERIOR (result);
-
-    if (refTypeInfo == NULL)
-        COMPlusThrowArgumentNull(W("typeInfo"));
-
-    // Ensure COM is started up.
-    EnsureComStarted();
-
-    SafeComHolder<ITypeInfo> pTI = (ITypeInfo*)GetComIPFromObjectRef(&refTypeInfo, IID_ITypeInfo);
-    if (!pTI)
-        COMPlusThrow(kArgumentException, W("Arg_NoITypeInfo"));
-
-    GCX_PREEMP();
-
-    // Retrieve the TYPEATTR.
-    TYPEATTR *pAttr;
-    IfFailThrow(pTI->GetTypeAttr(&pAttr));
-
-    // Extract the guid from the TYPEATTR.
-    *result = pAttr->guid;
-
-    // Release the TYPEATTR now that we have the GUID.
-    pTI->ReleaseTypeAttr(pAttr);
-
-    GCPROTECT_END ();
-    HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
-FCIMPL2(void, MarshalNative::DoGetTypeLibGuidForAssembly, GUID * result, AssemblyBaseObject* refAsmUNSAFE)
-{
-    FCALL_CONTRACT;
-
-    // Validate the arguments.
-    _ASSERTE(refAsmUNSAFE != NULL);
-    _ASSERTE(result != NULL);
-
-    ASSEMBLYREF refAsm = (ASSEMBLYREF) refAsmUNSAFE;
-    HELPER_METHOD_FRAME_BEGIN_1(refAsm);
-    GCPROTECT_BEGININTERIOR (result)
-
-    HRESULT hr = S_OK;
-
-    // Retrieve the assembly from the ASSEMBLYREF.
-    Assembly *pAssembly = refAsm->GetAssembly();
-    _ASSERTE(pAssembly);
-
-    // Retrieve the TLBID for the assembly.
-    IfFailThrow(::GetTypeLibGuidForAssembly(pAssembly, result));
-
-    GCPROTECT_END ();
-    HELPER_METHOD_FRAME_END();
-}
-FCIMPLEND
-
 FCIMPL1(int, MarshalNative::GetStartComSlot, ReflectClassBaseObject* tUNSAFE)
 {
     FCALL_CONTRACT;
@@ -1714,4 +1549,24 @@ BOOL MarshalNative::IsObjectInContext(OBJECTREF *pObj)
     }
 }
 
+void QCALLTYPE MarshalNative::GetTypeFromCLSID(REFCLSID clsid, PCWSTR wszServer, QCall::ObjectHandleOnStack retType)
+{
+    QCALL_CONTRACT;
+
+    BEGIN_QCALL;
+
+    // Ensure COM is started up.       
+    EnsureComStarted();
+
+    GCX_COOP();
+
+    OBJECTREF orType = NULL;
+    GCPROTECT_BEGIN(orType);
+    GetComClassFromCLSID(clsid, wszServer, &orType);
+    retType.Set(orType);
+    GCPROTECT_END();
+
+    END_QCALL;
+}
+
 #endif // FEATURE_COMINTEROP
index 5218e12..aa2803f 100644 (file)
@@ -159,20 +159,6 @@ public:
     static FCDECL2(Object*, GetObjectsForNativeVariants, VARIANT* aSrcNativeVariant, int cVars);
 
     //====================================================================
-    // Methods to retrieve information from TypeLibs and TypeInfos.
-    //====================================================================
-    static FCDECL2(void, DoGetTypeLibGuid, GUID * result, Object* refTlbUNSAFE);
-    static FCDECL1(LCID, GetTypeLibLcid, Object* refTlbUNSAFE);
-    static FCDECL3(void, GetTypeLibVersion, Object* refTlbUNSAFE, int *pMajor, int *pMinor);
-    static FCDECL2(void, DoGetTypeInfoGuid, GUID * result, Object* refTypeInfoUNSAFE);
-
-    //====================================================================
-    // Given a assembly, return the TLBID that will be generated for the
-    // typelib exported from the assembly.
-    //====================================================================
-    static FCDECL2(void, DoGetTypeLibGuidForAssembly, GUID * result, AssemblyBaseObject* refAsmUNSAFE);
-
-    //====================================================================
     // These methods are used to map COM slots to method info's.
     //====================================================================
     static FCDECL1(int, GetStartComSlot, ReflectClassBaseObject* tUNSAFE);
@@ -181,6 +167,12 @@ public:
     static FCDECL1(Object*, WrapIUnknownWithComObject, IUnknown* pUnk);
 
     static FCDECL2(void, ChangeWrapperHandleStrength, Object* orefUNSAFE, CLR_BOOL fIsWeak);
+
+    //====================================================================
+    // Create type for given CLSID.
+    //====================================================================
+    static void QCALLTYPE GetTypeFromCLSID(REFCLSID clsid, PCWSTR wszServer, QCall::ObjectHandleOnStack retType);
+
 private:
     static int GetComSlotInfo(MethodTable *pMT, MethodTable **ppDefItfMT);
     static BOOL IsObjectInContext(OBJECTREF *pObj);
index 5297b44..7b9da6c 100644 (file)
@@ -2061,113 +2061,6 @@ FCIMPL2_IV(Object*, ReflectionInvocation::CreateEnum, ReflectClassBaseObject *pT
 FCIMPLEND
 
 #ifdef FEATURE_COMINTEROP
-
-static void TryGetClassFromProgID(STRINGREF className, STRINGREF server, OBJECTREF* pRefClass, DWORD bThrowOnError) {
-    CONTRACTL {
-        THROWS;
-        GC_TRIGGERS;
-        MODE_COOPERATIVE;
-    }
-    CONTRACTL_END;
-
-    EX_TRY
-    {
-        // NOTE: this call enables GC
-        GetComClassFromProgID(className, server, pRefClass);
-    }
-    EX_CATCH
-    {
-        if (bThrowOnError)
-        {
-            EX_RETHROW;
-        }
-    }
-    EX_END_CATCH(SwallowAllExceptions)
-}
-
-// GetClassFromProgID
-// This method will return a Class object for a COM Classic object based
-//  upon its ProgID.  The COM Classic object is found and a wrapper object created
-FCIMPL3(Object*, ReflectionInvocation::GetClassFromProgID, StringObject* classNameUNSAFE,
-                                                           StringObject* serverUNSAFE,
-                                                           CLR_BOOL bThrowOnError) {
-    FCALL_CONTRACT;
-
-    REFLECTCLASSBASEREF refClass    = NULL;
-    STRINGREF           className   = (STRINGREF) classNameUNSAFE;
-    STRINGREF           server      = (STRINGREF) serverUNSAFE;
-
-    HELPER_METHOD_FRAME_BEGIN_RET_2(className, server);
-
-    GCPROTECT_BEGIN(refClass)
-
-    // Since we will be returning a type that represents a COM component, we need
-    // to make sure COM is started before we return it.
-    EnsureComStarted();
-
-    // Make sure a prog id was provided
-    if (className == NULL)
-        COMPlusThrowArgumentNull(W("progID"),W("ArgumentNull_String"));
-
-    TryGetClassFromProgID(className, server, (OBJECTREF*) &refClass, bThrowOnError);
-    GCPROTECT_END();
-
-    HELPER_METHOD_FRAME_END();
-    return OBJECTREFToObject(refClass);
-}
-FCIMPLEND
-
-static void TryGetClassFromCLSID(GUID clsid, STRINGREF server, OBJECTREF* pRefClass, DWORD bThrowOnError) {
-    CONTRACTL {
-        THROWS;
-        GC_TRIGGERS;
-        MODE_COOPERATIVE;
-    }
-    CONTRACTL_END;
-
-    EX_TRY
-    {
-        // NOTE: this call enables GC
-        GetComClassFromCLSID(clsid, server, pRefClass);
-    }
-    EX_CATCH
-    {
-        if (bThrowOnError)
-        {
-            EX_RETHROW;
-        }
-    }
-    EX_END_CATCH(SwallowAllExceptions)
-}
-
-// GetClassFromCLSID
-// This method will return a Class object for a COM Classic object based
-//  upon its ProgID.  The COM Classic object is found and a wrapper object created
-FCIMPL3(Object*, ReflectionInvocation::GetClassFromCLSID, GUID clsid, StringObject* serverUNSAFE, CLR_BOOL bThrowOnError) {
-    FCALL_CONTRACT;
-
-    struct _gc {
-        REFLECTCLASSBASEREF refClass;
-        STRINGREF           server;
-    } gc;
-
-    gc.refClass = NULL;
-    gc.server   = (STRINGREF) serverUNSAFE;
-
-    HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc.server);
-
-    // Since we will be returning a type that represents a COM component, we need
-    // to make sure COM is started before we return it.
-    EnsureComStarted();
-
-    TryGetClassFromCLSID(clsid, gc.server, (OBJECTREF*) &gc.refClass, bThrowOnError);
-
-    HELPER_METHOD_FRAME_END();
-    return OBJECTREFToObject(gc.refClass);
-}
-FCIMPLEND
-
-
 FCIMPL8(Object*, ReflectionInvocation::InvokeDispMethod, ReflectClassBaseObject* refThisUNSAFE,
                                                          StringObject* nameUNSAFE,
                                                          INT32 invokeAttr,
index 25ce314..bd358e8 100644 (file)
@@ -62,8 +62,6 @@ public:
     static FCDECL1(Object*, TypedReferenceToObject, TypedByRef * value);
 
 #ifdef FEATURE_COMINTEROP
-    static FCDECL3(Object*, GetClassFromProgID, StringObject* classNameUNSAFE, StringObject* serverUNSAFE, CLR_BOOL bThrowOnError);
-    static FCDECL3(Object*, GetClassFromCLSID, GUID clsid, StringObject* serverUNSAFE, CLR_BOOL bThrowOnError);
     static FCDECL8(Object*, InvokeDispMethod, ReflectClassBaseObject* refThisUNSAFE, StringObject* nameUNSAFE, INT32 invokeAttr, Object* targetUNSAFE, PTRArray* argsUNSAFE, PTRArray* byrefModifiersUNSAFE, LCID lcid, PTRArray* namedParametersUNSAFE);
 #endif  // FEATURE_COMINTEROP
     static FCDECL2(void, GetGUID, ReflectClassBaseObject* refThisUNSAFE, GUID * result);
index 27ed0b7..f7a29f8 100644 (file)
@@ -483,12 +483,12 @@ IClassFactory *ComClassFactory::GetIClassFactory()
     GCX_PREEMP();
 
     // If a server name is specified, then first try CLSCTX_REMOTE_SERVER.
-    if (m_pwszServer)
+    if (m_wszServer)
     {
         // Set up the COSERVERINFO struct.
         COSERVERINFO ServerInfo;
         memset(&ServerInfo, 0, sizeof(COSERVERINFO));
-        ServerInfo.pwszName = m_pwszServer;
+        ServerInfo.pwszName = (LPWSTR)m_wszServer;
 
         // Try to retrieve the IClassFactory passing in CLSCTX_REMOTE_SERVER.
         hr = CoGetClassObject(m_rclsid, CLSCTX_REMOTE_SERVER, &ServerInfo, IID_IClassFactory, (void**)&pClassFactory);
@@ -519,10 +519,10 @@ IClassFactory *ComClassFactory::GetIClassFactory()
         GetHRMsg(hr, strHRDescription);
 
         // Throw the actual exception indicating we couldn't find the class factory.
-        if (m_pwszServer == NULL)
+        if (m_wszServer == NULL)
             COMPlusThrowHR(hr, IDS_EE_LOCAL_COGETCLASSOBJECT_FAILED, strHRHex, strClsid, strHRDescription.GetUnicode());
         else
-            COMPlusThrowHR(hr, IDS_EE_REMOTE_COGETCLASSOBJECT_FAILED, strHRHex, strClsid, m_pwszServer, strHRDescription.GetUnicode());
+            COMPlusThrowHR(hr, IDS_EE_REMOTE_COGETCLASSOBJECT_FAILED, strHRHex, strClsid, m_wszServer, strHRDescription.GetUnicode());
     }
 
     RETURN pClassFactory;
@@ -587,12 +587,11 @@ OBJECTREF ComClassFactory::CreateInstance(MethodTable* pMTClass, BOOL ForManaged
 
 //--------------------------------------------------------------
 // Init the ComClassFactory.
-void ComClassFactory::Init(__in_opt WCHAR* pwszProgID, __in_opt WCHAR* pwszServer, MethodTable* pClassMT)
+void ComClassFactory::Init(__in_opt PCWSTR wszServer, MethodTable* pClassMT)
 {
     LIMITED_METHOD_CONTRACT;
 
-    m_pwszProgID = pwszProgID;
-    m_pwszServer = pwszServer;
+    m_wszServer = wszServer;
     m_pClassMT = pClassMT;
 }
 
@@ -610,11 +609,8 @@ void ComClassFactory::Cleanup()
     if (m_bManagedVersion)
         return;
 
-    if (m_pwszProgID != NULL)
-        delete [] m_pwszProgID;
-
-    if (m_pwszServer != NULL)
-        delete [] m_pwszServer;
+    if (m_wszServer != NULL)
+        delete [] m_wszServer;
 
     delete this;
 }
index fe3149d..3922eee 100644 (file)
@@ -707,7 +707,6 @@ protected:
     MethodTable *m_pClassMT;
 };
 
-class ComClassFactoryCreator;
 //-------------------------------------------------------------------------
 // Class that wraps an IClassFactory
 // This class allows a Reflection Class to wrap an IClassFactory
@@ -719,9 +718,7 @@ class ComClassFactoryCreator;
 //
 class ComClassFactory : public ClassFactoryBase
 {
-protected:
-    friend ComClassFactoryCreator;
-
+public:
     // We have two types of ComClassFactory:
     // 1. We build for reflection purpose.  We should not clean up.
     // 2. We build for IClassFactory.  We should clean up.
@@ -731,15 +728,13 @@ protected:
     {
         WRAPPER_NO_CONTRACT;
 
-        m_pwszProgID = NULL;
-        m_pwszServer = NULL;
+        m_wszServer = NULL;
 
         // Default to unmanaged version.
         m_bManagedVersion = FALSE;
         m_rclsid = rclsid;
     }
 
-public :
     //---------------------------------------------------------
     // Mark this instance as Managed Version, so we will not do clean up.
     void SetManagedVersion()
@@ -750,7 +745,7 @@ public :
 
     //--------------------------------------------------------------
     // Init the ComClassFactory
-    void Init(__in_opt WCHAR* pwszProgID, __in_opt WCHAR* pwszServer, MethodTable* pClassMT);
+    void Init(__in_opt PCWSTR wszServer, MethodTable* pClassMT);
 
     //-------------------------------------------------------------
     // create instance, calls IClassFactory::CreateInstance
@@ -786,32 +781,12 @@ private:
     IUnknown *CreateInstanceFromClassFactory(IClassFactory *pClassFact, IUnknown *punkOuter, BOOL *pfDidContainment);
 
 public:;
-    WCHAR*          m_pwszProgID;   // progId
     CLSID           m_rclsid;       // CLSID
-    WCHAR*          m_pwszServer;   // server name
+    PCWSTR          m_wszServer;   // server name
 
 private:
     BOOL            m_bManagedVersion;
 };
-
-//--------------------------------------------------------------
-// Creates the right ComClassFactory for you
-class ComClassFactoryCreator
-{
-public :
-    static ComClassFactory *Create(REFCLSID rclsid)
-    {
-        CONTRACT(ComClassFactory *)
-        {
-            THROWS;
-            GC_NOTRIGGER;
-            MODE_ANY;
-        }
-        CONTRACT_END;
-
-        RETURN new ComClassFactory(rclsid);
-    }
-};
 #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
 
 FORCEINLINE void NewRCWHolderRelease(RCW* p)
diff --git a/src/libraries/Common/src/Interop/Windows/Ole32/Interop.CLSIDFromProgID.cs b/src/libraries/Common/src/Interop/Windows/Ole32/Interop.CLSIDFromProgID.cs
new file mode 100644 (file)
index 0000000..dfdd12b
--- /dev/null
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.InteropServices;
+
+internal static partial class Interop
+{
+    internal static partial class Ole32
+    {
+        [DllImport(Interop.Libraries.Ole32, CharSet = CharSet.Unicode)]
+        internal static extern int CLSIDFromProgID(string lpszProgID, out Guid lpclsid);
+    }
+}
index 1841c52..2daf3bc 100644 (file)
     <Compile Include="$(CommonPath)Interop\Windows\OleAut32\Interop.SysFreeString.cs">
       <Link>Common\Interop\Windows\OleAut32\Interop.SysFreeString.cs</Link>
     </Compile>
+    <Compile Include="$(CommonPath)Interop\Windows\Ole32\Interop.CLSIDFromProgID.cs">
+      <Link>Common\Interop\Windows\Ole32\Interop.CLSIDFromProgID.cs</Link>
+    </Compile>
     <Compile Include="$(CommonPath)Interop\Windows\Ole32\Interop.CoCreateGuid.cs">
       <Link>Common\Interop\Windows\Ole32\Interop.CoCreateGuid.cs</Link>
     </Compile>
index ed7d492..3fa9d56 100644 (file)
@@ -175,10 +175,12 @@ namespace System.Runtime.InteropServices
             throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
         }
 
-        [SupportedOSPlatform("windows")]
-        public static Type? GetTypeFromCLSID(Guid clsid)
+        internal static Type? GetTypeFromCLSID(Guid clsid, string? server, bool throwOnError)
         {
-            throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
+            if (throwOnError)
+                throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
+
+            return null;
         }
 
         [SupportedOSPlatform("windows")]
index 64ac71c..9598679 100644 (file)
@@ -188,5 +188,16 @@ namespace System.Runtime.InteropServices
                 Interop.Sys.MemFree(ptr - sizeof(IntPtr));
             }
         }
+
+        internal static Type? GetTypeFromProgID(string progID, string? server, bool throwOnError)
+        {
+            if (progID == null)
+                throw new ArgumentNullException(nameof(progID));
+
+            if (throwOnError)
+                throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
+
+            return null;
+        }
     }
 }
index 3d82999..6df77c5 100644 (file)
@@ -217,5 +217,21 @@ namespace System.Runtime.InteropServices
                 Interop.OleAut32.SysFreeString(ptr);
             }
         }
+
+        internal static Type? GetTypeFromProgID(string progID, string? server, bool throwOnError)
+        {
+            if (progID == null)
+                throw new ArgumentNullException(nameof(progID));
+
+            int hr = Interop.Ole32.CLSIDFromProgID(progID, out Guid clsid);
+            if (hr < 0)
+            {
+                if (throwOnError)
+                    throw Marshal.GetExceptionForHR(hr, new IntPtr(-1))!;
+                return null;
+            }
+
+            return GetTypeFromCLSID(clsid, server, throwOnError);
+        }
     }
 }
index 80a221e..c136b57 100644 (file)
@@ -1,13 +1,14 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using System.Security;
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using System.Runtime.CompilerServices;
+using System.Runtime.Versioning;
+using System.Security;
 using System.Text;
 
 using Internal.Runtime.CompilerServices;
-using System.Diagnostics.CodeAnalysis;
 
 namespace System.Runtime.InteropServices
 {
@@ -996,5 +997,8 @@ namespace System.Runtime.InteropServices
         {
             return *(((uint*)s) - 1);
         }
+
+        [SupportedOSPlatform("windows")]
+        public static Type? GetTypeFromCLSID(Guid clsid) => GetTypeFromCLSID(clsid, null, throwOnError: false);
     }
 }
index 743d314..9991def 100644 (file)
@@ -406,6 +406,8 @@ namespace System
         public static Type? GetTypeFromCLSID(Guid clsid, bool throwOnError) => GetTypeFromCLSID(clsid, null, throwOnError: throwOnError);
         [SupportedOSPlatform("windows")]
         public static Type? GetTypeFromCLSID(Guid clsid, string? server) => GetTypeFromCLSID(clsid, server, throwOnError: false);
+        [SupportedOSPlatform("windows")]
+        public static Type? GetTypeFromCLSID(Guid clsid, string? server, bool throwOnError) => Marshal.GetTypeFromCLSID(clsid, server, throwOnError);
 
         [SupportedOSPlatform("windows")]
         public static Type? GetTypeFromProgID(string progID) => GetTypeFromProgID(progID, null, throwOnError: false);
@@ -413,6 +415,8 @@ namespace System
         public static Type? GetTypeFromProgID(string progID, bool throwOnError) => GetTypeFromProgID(progID, null, throwOnError: throwOnError);
         [SupportedOSPlatform("windows")]
         public static Type? GetTypeFromProgID(string progID, string? server) => GetTypeFromProgID(progID, server, throwOnError: false);
+        [SupportedOSPlatform("windows")]
+        public static Type? GetTypeFromProgID(string progID, string? server, bool throwOnError) => Marshal.GetTypeFromProgID(progID, server, throwOnError);
 
         public abstract Type? BaseType { get; }
 
index c9ca396..e25683e 100644 (file)
@@ -8,6 +8,11 @@ namespace System.Runtime.InteropServices.Tests
 {
     public class GetTypeFromCLSIDTests
     {
+        private static readonly Guid TestCLSID = new Guid("927971f5-0939-11d1-8be1-00c04fd8d503");
+
+        private const string TestProgID = "LargeInteger";
+        private const string TestServerName = "____NonExistingServer____";
+
         [Fact]
         [PlatformSpecific(TestPlatforms.Windows)]
         public void GetTypeFromCLSID_NoSuchCLSIDExists_ReturnsExpected()
@@ -16,6 +21,9 @@ namespace System.Runtime.InteropServices.Tests
             Assert.NotNull(type);
             Assert.Same(type, Marshal.GetTypeFromCLSID(Guid.Empty));
 
+            Assert.Same(type, Type.GetTypeFromCLSID(Guid.Empty));
+            Assert.Same(type, Type.GetTypeFromCLSID(Guid.Empty, throwOnError: true));
+
             Assert.Throws<COMException>(() => Activator.CreateInstance(type));
         }
 
@@ -23,20 +31,53 @@ namespace System.Runtime.InteropServices.Tests
         [PlatformSpecific(TestPlatforms.Windows)]
         public void GetTypeFromCLSID_CLSIDExists_ReturnsExpected()
         {
-            var guid = new Guid("927971f5-0939-11d1-8be1-00c04fd8d503");
-
-            Type type = Marshal.GetTypeFromCLSID(guid);
+            Type type = Marshal.GetTypeFromCLSID(TestCLSID);
             Assert.NotNull(type);
-            Assert.Same(type, Marshal.GetTypeFromCLSID(guid));
+            Assert.Same(type, Marshal.GetTypeFromCLSID(TestCLSID));
+
+            Assert.Same(type, Type.GetTypeFromCLSID(TestCLSID));
+            Assert.Same(type, Type.GetTypeFromCLSID(TestCLSID, throwOnError: true));
+            Assert.Same(type, Type.GetTypeFromCLSID(TestCLSID, server: null, throwOnError: true));
+
+            Assert.Same(type, Type.GetTypeFromProgID(TestProgID));
+            Assert.Same(type, Type.GetTypeFromProgID(TestProgID, throwOnError: true));
+            Assert.Same(type, Type.GetTypeFromProgID(TestProgID, server: null, throwOnError: true));
 
             Assert.NotNull(Activator.CreateInstance(type));
         }
 
+        [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotWindowsNanoServer))]
+        [PlatformSpecific(TestPlatforms.Windows)]
+        public void GetTypeFromCLSID_CLSIDExists_Server_ReturnsExpected()
+        {
+            Type type = Type.GetTypeFromCLSID(TestCLSID, server: TestServerName, throwOnError: true);
+            Assert.NotNull(type);
+            Assert.Same(type, Type.GetTypeFromProgID(TestProgID, server: TestServerName, throwOnError: true));
+
+            Assert.Throws<COMException>(() => Activator.CreateInstance(type));
+        }
+
         [Fact]
         [PlatformSpecific(TestPlatforms.AnyUnix)]
-        public void GetTypeFromCLSID_Unix_ThrowsPlatformNotSupportedException()
+        public void GetTypeFromCLSID_Unix()
+        {
+            Assert.Null(Marshal.GetTypeFromCLSID(Guid.Empty));
+            Assert.Null(Type.GetTypeFromCLSID(Guid.Empty, throwOnError: false));
+            Assert.Throws<PlatformNotSupportedException>(() => Type.GetTypeFromCLSID(Guid.Empty, throwOnError: true));
+        }
+
+        [Fact]
+        [PlatformSpecific(TestPlatforms.AnyUnix)]
+        public void GetTypeFromProgID_Unix()
+        {
+            Assert.Null(Type.GetTypeFromProgID(TestProgID, throwOnError: false));
+            Assert.Throws<PlatformNotSupportedException>(() => Type.GetTypeFromProgID(TestProgID, throwOnError: true));
+        }
+
+        [Fact]
+        public void GetTypeFromProgID_ReturnsExpected()
         {
-            Assert.Throws<PlatformNotSupportedException>(() => Marshal.GetTypeFromCLSID(Guid.Empty));
+            AssertExtensions.Throws<ArgumentNullException>("progID", () => Type.GetTypeFromProgID(null));
         }
     }
 }
index ac3c805..085dc6a 100644 (file)
@@ -97,12 +97,6 @@ namespace System
             return internal_from_handle(handle.Value);
         }
 
-        [SupportedOSPlatform("windows")]
-        public static Type? GetTypeFromCLSID(Guid clsid, string? server, bool throwOnError) => throw new PlatformNotSupportedException();
-
-        [SupportedOSPlatform("windows")]
-        public static Type? GetTypeFromProgID(string progID, string? server, bool throwOnError) => throw new PlatformNotSupportedException();
-
         internal virtual Type InternalResolve()
         {
             return UnderlyingSystemType;