/// <summary> /// Entry point for unmanaged COM activation API from managed code /// </summary> /// <param name="cxt">Reference to a <see cref="ComActivationContext"/> instance</param> public static object GetClassFactoryForType(ComActivationContext cxt) { #if FEATURE_COMINTEROP_UNMANAGED_ACTIVATION if (cxt.InterfaceId != typeof(IClassFactory).GUID && cxt.InterfaceId != typeof(IClassFactory2).GUID) { throw new NotSupportedException(); } if (!Path.IsPathRooted(cxt.AssemblyPath)) { throw new ArgumentException(null, nameof(cxt)); } Type classType = FindClassType(cxt.ClassId, cxt.AssemblyPath, cxt.AssemblyName, cxt.TypeName); if (LicenseInteropProxy.HasLicense(classType)) { return(new LicenseClassFactory(cxt.ClassId, classType)); } return(new BasicClassFactory(cxt.ClassId, classType)); #else throw new PlatformNotSupportedException(); #endif }
/// <summary> /// Entry point for unmanaged COM register/unregister API from managed code /// </summary> /// <param name="cxt">Reference to a <see cref="ComActivationContext"/> instance</param> /// <param name="register">true if called for register or false to indicate unregister</param> public static void ClassRegistrationScenarioForType(ComActivationContext cxt, bool register) { #if FEATURE_COMINTEROP_UNMANAGED_ACTIVATION // Retrieve the attribute type to use to determine if a function is the requested user defined // registration function. string attributeName = register ? "ComRegisterFunctionAttribute" : "ComUnregisterFunctionAttribute"; Type? regFuncAttrType = Type.GetType($"System.Runtime.InteropServices.{attributeName}, System.Runtime.InteropServices", throwOnError: false); if (regFuncAttrType == null) { // If the COM registration attributes can't be found then it is not on the type. return; } if (!Path.IsPathRooted(cxt.AssemblyPath)) { throw new ArgumentException(null, nameof(cxt)); } Type classType = FindClassType(cxt.ClassId, cxt.AssemblyPath, cxt.AssemblyName, cxt.TypeName); Type?currentType = classType; bool calledFunction = false; // Walk up the inheritance hierarchy. The first register/unregister function found is called; any additional functions on base types are ignored. while (currentType != null && !calledFunction) { // Retrieve all the methods. MethodInfo[] methods = currentType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static); // Go through all the methods and check for the custom attribute. foreach (MethodInfo method in methods) { // Check to see if the method has the custom attribute. if (method.GetCustomAttributes(regFuncAttrType !, inherit: true).Length == 0) { continue; } // Check to see if the method is static before we call it. if (!method.IsStatic) { string msg = register ? SR.InvalidOperation_NonStaticComRegFunction : SR.InvalidOperation_NonStaticComUnRegFunction; throw new InvalidOperationException(SR.Format(msg)); } // Finally validate signature ParameterInfo[] methParams = method.GetParameters(); if (method.ReturnType != typeof(void) || methParams == null || methParams.Length != 1 || (methParams[0].ParameterType != typeof(string) && methParams[0].ParameterType != typeof(Type))) { string msg = register ? SR.InvalidOperation_InvalidComRegFunctionSig : SR.InvalidOperation_InvalidComUnRegFunctionSig; throw new InvalidOperationException(SR.Format(msg)); } if (calledFunction) { string msg = register ? SR.InvalidOperation_MultipleComRegFunctions : SR.InvalidOperation_MultipleComUnRegFunctions; throw new InvalidOperationException(SR.Format(msg)); } // The function is valid so set up the arguments to call it. var objs = new object[1]; if (methParams[0].ParameterType == typeof(string)) { // We are dealing with the string overload of the function - provide the registry key - see comhost.dll implementation objs[0] = $"HKEY_LOCAL_MACHINE\\SOFTWARE\\Classes\\CLSID\\{cxt.ClassId.ToString("B")}"; } else { // We are dealing with the type overload of the function. objs[0] = classType; } // Invoke the COM register function. method.Invoke(null, objs); calledFunction = true; } // Go through all the base types currentType = currentType.BaseType; } #else throw new PlatformNotSupportedException(); #endif }