Skip to content

Commit 0a69f02

Browse files
authored
Rewrite Type.GetTypeFromProgID in C# (#42546)
- 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
1 parent a0e1831 commit 0a69f02

File tree

23 files changed

+170
-528
lines changed

23 files changed

+170
-528
lines changed

src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.CoreCLR.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -275,8 +275,18 @@ public static string GetTypeInfoName(ITypeInfo typeInfo)
275275

276276
// This method is identical to Type.GetTypeFromCLSID. Since it's interop specific, we expose it
277277
// on Marshal for more consistent API surface.
278-
[SupportedOSPlatform("windows")]
279-
public static Type? GetTypeFromCLSID(Guid clsid) => RuntimeType.GetTypeFromCLSIDImpl(clsid, null, throwOnError: false);
278+
internal static Type? GetTypeFromCLSID(Guid clsid, string? server, bool throwOnError)
279+
{
280+
// Note: "throwOnError" is a vacuous parameter. Any errors due to the CLSID not being registered or the server not being found will happen
281+
// on the Activator.CreateInstance() call. GetTypeFromCLSID() merely wraps the data in a Type object without any validation.
282+
283+
Type? type = null;
284+
GetTypeFromCLSID(clsid, server, ObjectHandleOnStack.Create(ref type));
285+
return type;
286+
}
287+
288+
[DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)]
289+
private static extern void GetTypeFromCLSID(in Guid clsid, string? server, ObjectHandleOnStack retType);
280290

281291
/// <summary>
282292
/// Return the IUnknown* for an Object if the current context is the one

src/coreclr/src/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4085,24 +4085,6 @@ private extern object InvokeDispMethod(
40854085
bool[]? byrefModifiers, int culture, string[]? namedParameters);
40864086
#endif // FEATURE_COMINTEROP
40874087

4088-
#if FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
4089-
[MethodImpl(MethodImplOptions.InternalCall)]
4090-
internal static extern Type? GetTypeFromProgIDImpl(string progID, string? server, bool throwOnError);
4091-
4092-
[MethodImpl(MethodImplOptions.InternalCall)]
4093-
internal static extern Type? GetTypeFromCLSIDImpl(Guid clsid, string? server, bool throwOnError);
4094-
#else // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
4095-
internal static Type GetTypeFromProgIDImpl(string progID, string? server, bool throwOnError)
4096-
{
4097-
throw new NotImplementedException("CoreCLR_REMOVED -- Unmanaged activation removed");
4098-
}
4099-
4100-
internal static Type GetTypeFromCLSIDImpl(Guid clsid, string? server, bool throwOnError)
4101-
{
4102-
throw new NotImplementedException("CoreCLR_REMOVED -- Unmanaged activation removed");
4103-
}
4104-
#endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
4105-
41064088
#endregion
41074089

41084090
#if FEATURE_COMINTEROP

src/coreclr/src/System.Private.CoreLib/src/System/Type.CoreCLR.cs

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -81,34 +81,6 @@ public bool IsInterface
8181
return TypeNameParser.GetType(typeName, assemblyResolver, typeResolver, throwOnError, ignoreCase, ref stackMark);
8282
}
8383

84-
////////////////////////////////////////////////////////////////////////////////
85-
// This will return a class based upon the progID. This is provided for
86-
// COM classic support. Program ID's are not used in COM+ because they
87-
// have been superceded by namespace. (This routine is called this instead
88-
// of getClass() because of the name conflict with the first method above.)
89-
//
90-
// param progID: the progID of the class to retrieve
91-
// returns: the class object associated to the progID
92-
////
93-
[SupportedOSPlatform("windows")]
94-
public static Type? GetTypeFromProgID(string progID, string? server, bool throwOnError)
95-
{
96-
return RuntimeType.GetTypeFromProgIDImpl(progID, server, throwOnError);
97-
}
98-
99-
////////////////////////////////////////////////////////////////////////////////
100-
// This will return a class based upon the CLSID. This is provided for
101-
// COM classic support.
102-
//
103-
// param CLSID: the CLSID of the class to retrieve
104-
// returns: the class object associated to the CLSID
105-
////
106-
[SupportedOSPlatform("windows")]
107-
public static Type? GetTypeFromCLSID(Guid clsid, string? server, bool throwOnError)
108-
{
109-
return RuntimeType.GetTypeFromCLSIDImpl(clsid, server, throwOnError);
110-
}
111-
11284
internal virtual RuntimeTypeHandle GetTypeHandleInternal()
11385
{
11486
return TypeHandle;

src/coreclr/src/vm/ecalllist.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,6 @@ FCFuncStart(gSystem_RuntimeType)
200200
FCFuncElement("CanValueSpecialCast", ReflectionInvocation::CanValueSpecialCast)
201201
FCFuncElement("AllocateValueType", ReflectionInvocation::AllocateValueType)
202202
#if defined(FEATURE_COMINTEROP)
203-
FCFuncElement("GetTypeFromCLSIDImpl", ReflectionInvocation::GetClassFromCLSID)
204-
FCFuncElement("GetTypeFromProgIDImpl", ReflectionInvocation::GetClassFromProgID)
205203
FCFuncElement("InvokeDispMethod", ReflectionInvocation::InvokeDispMethod)
206204
#endif // defined(FEATURE_COMINTEROP)
207205
FCFuncEnd()
@@ -794,6 +792,7 @@ FCFuncStart(gInteropMarshalFuncs)
794792
FCFuncElement("GetTypedObjectForIUnknown", MarshalNative::GetTypedObjectForIUnknown)
795793
FCFuncElement("ChangeWrapperHandleStrength", MarshalNative::ChangeWrapperHandleStrength)
796794
FCFuncElement("CleanupUnusedObjectsInCurrentContext", MarshalNative::CleanupUnusedObjectsInCurrentContext)
795+
QCFuncElement("GetTypeFromCLSID", MarshalNative::GetTypeFromCLSID)
797796
#endif // FEATURE_COMINTEROP
798797
FCFuncEnd()
799798

src/coreclr/src/vm/eehash.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ DWORD EEClassFactoryInfoHashTableHelper::Hash(ClassFactoryInfo *pKey)
431431

432432
if (pKey->m_strServerName)
433433
{
434-
WCHAR *pSrvNameData = pKey->m_strServerName;
434+
PCWSTR pSrvNameData = pKey->m_strServerName;
435435

436436
while (*pSrvNameData != 0)
437437
{

src/coreclr/src/vm/eehash.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -563,8 +563,8 @@ typedef EEHashTable<const SigTypeContext*, EEInstantiationHashTableHelper, FALSE
563563

564564
struct ClassFactoryInfo
565565
{
566-
GUID m_clsid;
567-
WCHAR *m_strServerName;
566+
GUID m_clsid;
567+
PCWSTR m_strServerName;
568568
};
569569

570570
class EEClassFactoryInfoHashTableHelper

src/coreclr/src/vm/interoputil.cpp

Lines changed: 9 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -3772,22 +3772,20 @@ void IUInvokeDispMethod(
37723772

37733773
#if defined(FEATURE_COMINTEROP_UNMANAGED_ACTIVATION) && defined(FEATURE_COMINTEROP)
37743774

3775-
void GetComClassHelper(
3775+
static void GetComClassHelper(
37763776
_Out_ OBJECTREF *pRef,
37773777
_In_ EEClassFactoryInfoHashTable *pClassFactHash,
3778-
_In_ ClassFactoryInfo *pClassFactInfo,
3779-
_In_opt_ WCHAR *wszProgID)
3778+
_In_ ClassFactoryInfo *pClassFactInfo)
37803779
{
37813780
CONTRACTL
37823781
{
37833782
THROWS;
37843783
GC_TRIGGERS;
3785-
MODE_ANY;
3784+
MODE_COOPERATIVE;
37863785
INJECT_FAULT(ThrowOutOfMemory());
37873786
PRECONDITION(CheckPointer(pRef));
37883787
PRECONDITION(CheckPointer(pClassFactHash));
37893788
PRECONDITION(CheckPointer(pClassFactInfo));
3790-
PRECONDITION(CheckPointer(wszProgID, NULL_OK));
37913789
}
37923790
CONTRACTL_END;
37933791

@@ -3809,17 +3807,9 @@ void GetComClassHelper(
38093807
// represent it.
38103808
//
38113809

3812-
NewHolder<ComClassFactory> pComClsFac = ComClassFactoryCreator::Create(pClassFactInfo->m_clsid);
3810+
NewHolder<ComClassFactory> pComClsFac = new ComClassFactory(pClassFactInfo->m_clsid);
38133811
pComClsFac->SetManagedVersion();
38143812

3815-
NewArrayHolder<WCHAR> wszRefProgID = NULL;
3816-
if (wszProgID)
3817-
{
3818-
size_t len = wcslen(wszProgID)+1;
3819-
wszRefProgID = new WCHAR[len];
3820-
wcscpy_s(wszRefProgID, len, wszProgID);
3821-
}
3822-
38233813
NewArrayHolder<WCHAR> wszRefServer = NULL;
38243814
if (pClassFactInfo->m_strServerName)
38253815
{
@@ -3828,7 +3818,7 @@ void GetComClassHelper(
38283818
wcscpy_s(wszRefServer, len, pClassFactInfo->m_strServerName);
38293819
}
38303820

3831-
pComClsFac->Init(wszRefProgID, wszRefServer, NULL);
3821+
pComClsFac->Init(wszRefServer, NULL);
38323822
AllocateComClassObject(pComClsFac, pRef);
38333823

38343824
// Insert to hash.
@@ -3838,130 +3828,25 @@ void GetComClassHelper(
38383828
// Make sure the hash code is working.
38393829
_ASSERTE (pClassFactHash->GetValue(pClassFactInfo, (HashDatum *)&hRef));
38403830

3841-
wszRefProgID.SuppressRelease();
38423831
wszRefServer.SuppressRelease();
38433832
pComClsFac.SuppressRelease();
38443833
}
38453834
}
38463835

38473836
//-------------------------------------------------------------
38483837
// returns a ComClass reflect class that wraps the IClassFactory
3849-
void GetComClassFromProgID(STRINGREF srefProgID, STRINGREF srefServer, OBJECTREF *pRef)
3838+
void GetComClassFromCLSID(REFCLSID clsid, _In_opt_z_ PCWSTR wszServer, OBJECTREF *pRef)
38503839
{
38513840
CONTRACTL
38523841
{
38533842
THROWS;
38543843
GC_TRIGGERS;
38553844
MODE_COOPERATIVE;
38563845
INJECT_FAULT(COMPlusThrowOM());
3857-
PRECONDITION(srefProgID != NULL);
38583846
PRECONDITION(pRef != NULL);
38593847
}
38603848
CONTRACTL_END;
38613849

3862-
NewArrayHolder<WCHAR> wszProgID;
3863-
NewArrayHolder<WCHAR> wszServer;
3864-
HRESULT hr = S_OK;
3865-
MethodTable* pMT = NULL;
3866-
CLSID clsid = {0};
3867-
3868-
//
3869-
// Allocate strings for the ProgID and the server.
3870-
//
3871-
3872-
int len = srefProgID->GetStringLength();
3873-
3874-
wszProgID = new WCHAR[len+1];
3875-
3876-
if (len)
3877-
memcpy(wszProgID, srefProgID->GetBuffer(), (len*2));
3878-
wszProgID[len] = W('\0');
3879-
3880-
if (srefServer != NULL)
3881-
{
3882-
len = srefServer->GetStringLength();
3883-
3884-
wszServer = new WCHAR[len+1];
3885-
3886-
if (len)
3887-
memcpy(wszServer, srefServer->GetBuffer(), (len*2));
3888-
wszServer[len] = W('\0');
3889-
}
3890-
3891-
3892-
//
3893-
// Call GetCLSIDFromProgID() to convert the ProgID to a CLSID.
3894-
//
3895-
3896-
EnsureComStarted();
3897-
3898-
{
3899-
GCX_PREEMP();
3900-
hr = GetCLSIDFromProgID(wszProgID, &clsid);
3901-
}
3902-
3903-
if (FAILED(hr))
3904-
COMPlusThrowHR(hr);
3905-
3906-
//
3907-
// See if we can find the well known managed class for this CLSID.
3908-
//
3909-
3910-
// Check if we have in the hash.
3911-
OBJECTHANDLE hRef;
3912-
ClassFactoryInfo ClassFactInfo;
3913-
ClassFactInfo.m_clsid = clsid;
3914-
ClassFactInfo.m_strServerName = wszServer;
3915-
EEClassFactoryInfoHashTable *pClassFactHash = GetAppDomain()->GetClassFactHash();
3916-
3917-
if (pClassFactHash->GetValue(&ClassFactInfo, (HashDatum *)&hRef))
3918-
{
3919-
*pRef = ObjectFromHandle(hRef);
3920-
}
3921-
else
3922-
{
3923-
GetComClassHelper(pRef, pClassFactHash, &ClassFactInfo, wszProgID);
3924-
}
3925-
3926-
// If we made it this far *pRef better be set.
3927-
_ASSERTE(*pRef != NULL);
3928-
}
3929-
3930-
//-------------------------------------------------------------
3931-
// returns a ComClass reflect class that wraps the IClassFactory
3932-
void GetComClassFromCLSID(REFCLSID clsid, STRINGREF srefServer, OBJECTREF *pRef)
3933-
{
3934-
CONTRACTL
3935-
{
3936-
THROWS;
3937-
GC_TRIGGERS;
3938-
MODE_COOPERATIVE;
3939-
INJECT_FAULT(COMPlusThrowOM());
3940-
PRECONDITION(pRef != NULL);
3941-
}
3942-
CONTRACTL_END;
3943-
3944-
NewArrayHolder<WCHAR> wszServer;
3945-
HRESULT hr = S_OK;
3946-
MethodTable* pMT = NULL;
3947-
3948-
//
3949-
// Allocate strings for the server.
3950-
//
3951-
3952-
if (srefServer != NULL)
3953-
{
3954-
int len = srefServer->GetStringLength();
3955-
3956-
wszServer = new WCHAR[len+1];
3957-
3958-
if (len)
3959-
memcpy(wszServer, srefServer->GetBuffer(), (len*2));
3960-
3961-
wszServer[len] = W('\0');
3962-
}
3963-
3964-
39653850
//
39663851
// See if we can find the well known managed class for this CLSID.
39673852
//
@@ -3979,7 +3864,7 @@ void GetComClassFromCLSID(REFCLSID clsid, STRINGREF srefServer, OBJECTREF *pRef)
39793864
}
39803865
else
39813866
{
3982-
GetComClassHelper(pRef, pClassFactHash, &ClassFactInfo, NULL);
3867+
GetComClassHelper(pRef, pClassFactHash, &ClassFactInfo);
39833868
}
39843869

39853870
// If we made it this far *pRef better be set.
@@ -4027,11 +3912,11 @@ ClassFactoryBase *GetComClassFactory(MethodTable* pClassMT)
40273912
GUID guid;
40283913
pClassMT->GetGuid(&guid, TRUE);
40293914

4030-
ComClassFactory *pComClsFac = ComClassFactoryCreator::Create(guid);
3915+
ComClassFactory *pComClsFac = new ComClassFactory(guid);
40313916

40323917
pNewFactory = pComClsFac;
40333918

4034-
pComClsFac->Init(NULL, NULL, pClassMT);
3919+
pComClsFac->Init(NULL, pClassMT);
40353920

40363921
// store the class factory in EE Class
40373922
if (!pClassMT->SetComClassFactory(pNewFactory))

src/coreclr/src/vm/interoputil.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -352,13 +352,9 @@ void IUInvokeDispMethod(
352352
#ifdef FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
353353
// Class Factory helpers
354354

355-
//--------------------------------------------------------------------------
356-
// GetComClassFromProgID used by reflection class to setup a Class based on ProgID
357-
void GetComClassFromProgID(STRINGREF srefProgID, STRINGREF srefServer, OBJECTREF* pRef);
358-
359355
//--------------------------------------------------------------------------
360356
// GetComClassFromCLSID used by reflection class to setup a Class based on CLSID
361-
void GetComClassFromCLSID(REFCLSID clsid, STRINGREF srefServer, OBJECTREF* pRef);
357+
void GetComClassFromCLSID(REFCLSID clsid, _In_opt_z_ PCWSTR wszServer, OBJECTREF* pRef);
362358

363359
//-------------------------------------------------------------
364360
// check if a ComClassFactory has been setup for this class

0 commit comments

Comments
 (0)