diff options
Diffstat (limited to 'src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs')
-rw-r--r-- | src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs | 1059 |
1 files changed, 0 insertions, 1059 deletions
diff --git a/src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs b/src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs deleted file mode 100644 index 0105866415..0000000000 --- a/src/mscorlib/src/System/Runtime/InteropServices/RegistrationServices.cs +++ /dev/null @@ -1,1059 +0,0 @@ -// 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. - -/*============================================================================= -** -** -** -** Purpose: This class provides services for registering and unregistering -** a managed server for use by COM. -** -** -** -** -** Change the way how to register and unregister a managed server -** -=============================================================================*/ -namespace System.Runtime.InteropServices { - - using System; - using System.Collections; - using System.IO; - using System.Reflection; - using System.Security; - using System.Security.Permissions; - using System.Text; - using System.Threading; - using Microsoft.Win32; - using System.Runtime.CompilerServices; - using System.Globalization; - using System.Runtime.Versioning; - using System.Diagnostics; - using System.Diagnostics.Contracts; - - [Flags] - public enum RegistrationClassContext - { - - - InProcessServer = 0x1, - InProcessHandler = 0x2, - LocalServer = 0x4, - InProcessServer16 = 0x8, - RemoteServer = 0x10, - InProcessHandler16 = 0x20, - Reserved1 = 0x40, - Reserved2 = 0x80, - Reserved3 = 0x100, - Reserved4 = 0x200, - NoCodeDownload = 0x400, - Reserved5 = 0x800, - NoCustomMarshal = 0x1000, - EnableCodeDownload = 0x2000, - NoFailureLog = 0x4000, - DisableActivateAsActivator = 0x8000, - EnableActivateAsActivator = 0x10000, - FromDefaultContext = 0x20000 - } - - - [Flags] - public enum RegistrationConnectionType - { - SingleUse = 0, - MultipleUse = 1, - MultiSeparate = 2, - Suspended = 4, - Surrogate = 8, - } - - [Guid("475E398F-8AFA-43a7-A3BE-F4EF8D6787C9")] - [ClassInterface(ClassInterfaceType.None)] -[System.Runtime.InteropServices.ComVisible(true)] - public class RegistrationServices : IRegistrationServices - { - #region Constants - - private const String strManagedCategoryGuid = "{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}"; - private const String strDocStringPrefix = ""; - private const String strManagedTypeThreadingModel = "Both"; - private const String strComponentCategorySubKey = "Component Categories"; - private const String strManagedCategoryDescription = ".NET Category"; - private const String strImplementedCategoriesSubKey = "Implemented Categories"; - private const String strMsCorEEFileName = "mscoree.dll"; - private const String strRecordRootName = "Record"; - private const String strClsIdRootName = "CLSID"; - private const String strTlbRootName = "TypeLib"; - private static Guid s_ManagedCategoryGuid = new Guid(strManagedCategoryGuid); - - #endregion - - - #region IRegistrationServices - - public virtual bool RegisterAssembly(Assembly assembly, AssemblyRegistrationFlags flags) - { - // Validate the arguments. - if (assembly == null) - throw new ArgumentNullException(nameof(assembly)); - - if (assembly.ReflectionOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsmLoadedForReflectionOnly")); - Contract.EndContractBlock(); - - RuntimeAssembly rtAssembly = assembly as RuntimeAssembly; - if (rtAssembly == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly")); - - // Retrieve the assembly names. - String strAsmName = assembly.FullName; - if (strAsmName == null) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoAsmName")); - - // Retrieve the assembly codebase. - String strAsmCodeBase = null; - if ((flags & AssemblyRegistrationFlags.SetCodeBase) != 0) - { - strAsmCodeBase = rtAssembly.GetCodeBase(false); - if (strAsmCodeBase == null) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NoAsmCodeBase")); - } - - // Go through all the registerable types in the assembly and register them. - Type[] aTypes = GetRegistrableTypesInAssembly(assembly); - int NumTypes = aTypes.Length; - - String strAsmVersion = rtAssembly.GetVersion().ToString(); - - // Retrieve the runtime version used to build the assembly. - String strRuntimeVersion = assembly.ImageRuntimeVersion; - - for (int cTypes = 0; cTypes < NumTypes; cTypes++) - { - if (IsRegisteredAsValueType(aTypes[cTypes])) - RegisterValueType(aTypes[cTypes], strAsmName, strAsmVersion, strAsmCodeBase, strRuntimeVersion); - else if (TypeRepresentsComType(aTypes[cTypes])) - RegisterComImportedType(aTypes[cTypes], strAsmName, strAsmVersion, strAsmCodeBase, strRuntimeVersion); - else - RegisterManagedType(aTypes[cTypes], strAsmName, strAsmVersion, strAsmCodeBase, strRuntimeVersion); - - CallUserDefinedRegistrationMethod(aTypes[cTypes], true); - } - - // If this assembly has the PIA attribute, then register it as a PIA. - Object[] aPIAAttrs = assembly.GetCustomAttributes(typeof(PrimaryInteropAssemblyAttribute), false); - int NumPIAAttrs = aPIAAttrs.Length; - for (int cPIAAttrs = 0; cPIAAttrs < NumPIAAttrs; cPIAAttrs++) - RegisterPrimaryInteropAssembly(rtAssembly, strAsmCodeBase, (PrimaryInteropAssemblyAttribute)aPIAAttrs[cPIAAttrs]); - - // Return value indicating if we actually registered any types. - if (aTypes.Length > 0 || NumPIAAttrs > 0) - return true; - else - return false; - } - - public virtual bool UnregisterAssembly(Assembly assembly) - { - // Validate the arguments. - if (assembly == null) - throw new ArgumentNullException(nameof(assembly)); - - if (assembly.ReflectionOnly) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsmLoadedForReflectionOnly")); - Contract.EndContractBlock(); - - RuntimeAssembly rtAssembly = assembly as RuntimeAssembly; - if (rtAssembly == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly")); - - bool bAllVersionsGone = true; - - // Go through all the registrable types in the assembly and register them. - Type[] aTypes = GetRegistrableTypesInAssembly(assembly); - int NumTypes = aTypes.Length; - - // Retrieve the assembly version - String strAsmVersion = rtAssembly.GetVersion().ToString(); - for (int cTypes = 0;cTypes < NumTypes;cTypes++) - { - CallUserDefinedRegistrationMethod(aTypes[cTypes], false); - - if (IsRegisteredAsValueType(aTypes[cTypes])) - { - if (!UnregisterValueType(aTypes[cTypes], strAsmVersion)) - bAllVersionsGone = false; - } - else if (TypeRepresentsComType(aTypes[cTypes])) - { - if (!UnregisterComImportedType(aTypes[cTypes], strAsmVersion)) - bAllVersionsGone = false; - } - else - { - if (!UnregisterManagedType(aTypes[cTypes], strAsmVersion)) - bAllVersionsGone = false; - } - } - - // If this assembly has the PIA attribute, then unregister it as a PIA. - Object[] aPIAAttrs = assembly.GetCustomAttributes(typeof(PrimaryInteropAssemblyAttribute),false); - int NumPIAAttrs = aPIAAttrs.Length; - if (bAllVersionsGone) - { - for (int cPIAAttrs = 0;cPIAAttrs < NumPIAAttrs;cPIAAttrs++) - UnregisterPrimaryInteropAssembly(assembly, (PrimaryInteropAssemblyAttribute)aPIAAttrs[cPIAAttrs]); - } - - // Return value indicating if we actually un-registered any types. - if (aTypes.Length > 0 || NumPIAAttrs > 0) - return true; - else - return false; - } - - public virtual Type[] GetRegistrableTypesInAssembly(Assembly assembly) - { - // Validate the arguments. - if (assembly == null) - throw new ArgumentNullException(nameof(assembly)); - Contract.EndContractBlock(); - - if (!(assembly is RuntimeAssembly)) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), nameof(assembly)); - - // Retrieve the list of types in the assembly. - Type[] aTypes = assembly.GetExportedTypes(); - int NumTypes = aTypes.Length; - - // Create an array list that will be filled in. - ArrayList TypeList = new ArrayList(); - - // Register all the types that require registration. - for (int cTypes = 0; cTypes < NumTypes; cTypes++) - { - Type CurrentType = aTypes[cTypes]; - if (TypeRequiresRegistration(CurrentType)) - TypeList.Add(CurrentType); - } - - // Copy the array list to an array and return it. - Type[] RetArray = new Type[TypeList.Count]; - TypeList.CopyTo(RetArray); - return RetArray; - } - - public virtual String GetProgIdForType(Type type) - { - return Marshal.GenerateProgIdForType(type); - } - - public virtual void RegisterTypeForComClients(Type type, ref Guid g) - { -#if FEATURE_COMINTEROP_MANAGED_ACTIVATION - if(type == null) - throw new ArgumentNullException(nameof(type)); - Contract.EndContractBlock(); - if((type as RuntimeType) == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"),nameof(type)); - if(!TypeRequiresRegistration(type)) - throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"),nameof(type)); - - // Call the native method to do CoRegisterClassObject - RegisterTypeForComClientsNative(type, ref g); -#else // FEATURE_COMINTEROP_MANAGED_ACTIVATION - throw new NotImplementedException("CoreCLR_REMOVED -- managed activation removed"); -#endif // FEATURE_COMINTEROP_MANAGED_ACTIVATION - } - - public virtual Guid GetManagedCategoryGuid() - { - return s_ManagedCategoryGuid; - } - - public virtual bool TypeRequiresRegistration(Type type) - { - return TypeRequiresRegistrationHelper(type); - } - - public virtual bool TypeRepresentsComType(Type type) - { - // If the type is not a COM import, then it does not represent a COM type. - if (!type.IsCOMObject) - return false; - - // If it is marked as tdImport, then it represents a COM type directly. - if (type.IsImport) - return true; - - // If the type is derived from a tdImport class and has the same GUID as the - // imported class, then it represents a COM type. - Type baseComImportType = GetBaseComImportType(type); - Debug.Assert(baseComImportType != null, "baseComImportType != null"); - if (Marshal.GenerateGuidForType(type) == Marshal.GenerateGuidForType(baseComImportType)) - return true; - - return false; - } - - #endregion - - - #region Public methods not on IRegistrationServices - [ComVisible(false)] - public virtual int RegisterTypeForComClients(Type type, RegistrationClassContext classContext, RegistrationConnectionType flags) - { -#if FEATURE_COMINTEROP_MANAGED_ACTIVATION - if (type == null) - throw new ArgumentNullException(nameof(type)); - Contract.EndContractBlock(); - if ((type as RuntimeType) == null) - throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"),nameof(type)); - if (!TypeRequiresRegistration(type)) - throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"),nameof(type)); - - // Call the native method to do CoRegisterClassObject - return RegisterTypeForComClientsExNative(type, classContext, flags); -#else // FEATURE_COMINTEROP_MANAGED_ACTIVATION - throw new NotImplementedException("CoreCLR_REMOVED -- managed activation removed"); -#endif // FEATURE_COMINTEROP_MANAGED_ACTIVATION - } - - [ComVisible(false)] - public virtual void UnregisterTypeForComClients(int cookie) - { - // Call the native method to do CoRevokeClassObject. - CoRevokeClassObject(cookie); - } - - #endregion - - - #region Internal helpers - - internal static bool TypeRequiresRegistrationHelper(Type type) - { - // If the type is not a class or a value class, then it does not get registered. - if (!type.IsClass && !type.IsValueType) - return false; - - // If the type is abstract then it does not get registered. - if (type.IsAbstract) - return false; - - // If the does not have a public default constructor then is not creatable from COM so - // it does not require registration unless it is a value class. - if (!type.IsValueType && type.GetConstructor(BindingFlags.Instance | BindingFlags.Public,null,Array.Empty<Type>(),null) == null) - return false; - - // All other conditions are met so check to see if the type is visible from COM. - return Marshal.IsTypeVisibleFromCom(type); - } - - #endregion - - - #region Private helpers - - private void RegisterValueType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion) - { - // Retrieve some information that will be used during the registration process. - String strRecordId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; - - // Create the HKEY_CLASS_ROOT\Record key. - using (RegistryKey RecordRootKey = Registry.ClassesRoot.CreateSubKey(strRecordRootName)) - { - // Create the HKEY_CLASS_ROOT\Record\<RecordID> key. - using (RegistryKey RecordKey = RecordRootKey.CreateSubKey(strRecordId)) - { - // Create the HKEY_CLASS_ROOT\Record\<RecordId>\<version> key. - using (RegistryKey RecordVersionKey = RecordKey.CreateSubKey(strAsmVersion)) - { - // Set the class value. - RecordVersionKey.SetValue("Class", type.FullName); - - // Set the assembly value. - RecordVersionKey.SetValue("Assembly", strAsmName); - - // Set the runtime version value. - RecordVersionKey.SetValue("RuntimeVersion", strRuntimeVersion); - - // Set the assembly code base value if a code base was specified. - if (strAsmCodeBase != null) - RecordVersionKey.SetValue("CodeBase", strAsmCodeBase); - } - } - } - } - - private void RegisterManagedType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion) - { - // - // Retrieve some information that will be used during the registration process. - // - - String strDocString = strDocStringPrefix + type.FullName; - String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; - String strProgId = GetProgIdForType(type); - - - // - // Write the actual type information in the registry. - // - - if (strProgId != String.Empty) - { - // Create the HKEY_CLASS_ROOT\<wzProgId> key. - using (RegistryKey TypeNameKey = Registry.ClassesRoot.CreateSubKey(strProgId)) - { - TypeNameKey.SetValue("", strDocString); - - // Create the HKEY_CLASS_ROOT\<wzProgId>\CLSID key. - using (RegistryKey ProgIdClsIdKey = TypeNameKey.CreateSubKey("CLSID")) - { - ProgIdClsIdKey.SetValue("", strClsId); - } - } - } - - // Create the HKEY_CLASS_ROOT\CLSID key. - using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.CreateSubKey(strClsIdRootName)) - { - // Create the HKEY_CLASS_ROOT\CLSID\<CLSID> key. - using (RegistryKey ClsIdKey = ClsIdRootKey.CreateSubKey(strClsId)) - { - ClsIdKey.SetValue("", strDocString); - - // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32 key. - using (RegistryKey InProcServerKey = ClsIdKey.CreateSubKey("InprocServer32")) - { - InProcServerKey.SetValue("", strMsCorEEFileName); - InProcServerKey.SetValue("ThreadingModel", strManagedTypeThreadingModel); - InProcServerKey.SetValue("Class", type.FullName); - InProcServerKey.SetValue("Assembly", strAsmName); - InProcServerKey.SetValue("RuntimeVersion", strRuntimeVersion); - if (strAsmCodeBase != null) - InProcServerKey.SetValue("CodeBase", strAsmCodeBase); - - // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32\<Version> subkey - using (RegistryKey VersionSubKey = InProcServerKey.CreateSubKey(strAsmVersion)) - { - VersionSubKey.SetValue("Class", type.FullName); - VersionSubKey.SetValue("Assembly", strAsmName); - VersionSubKey.SetValue("RuntimeVersion", strRuntimeVersion); - if (strAsmCodeBase != null) - VersionSubKey.SetValue("CodeBase", strAsmCodeBase); - } - - if (strProgId != String.Empty) - { - // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\ProdId key. - using (RegistryKey ProgIdKey = ClsIdKey.CreateSubKey("ProgId")) - { - ProgIdKey.SetValue("", strProgId); - } - } - } - - // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\Implemented Categories\<Managed Category Guid> key. - using (RegistryKey CategoryKey = ClsIdKey.CreateSubKey(strImplementedCategoriesSubKey)) - { - using (RegistryKey ManagedCategoryKey = CategoryKey.CreateSubKey(strManagedCategoryGuid)) {} - } - } - } - - - // - // Ensure that the managed category exists. - // - - EnsureManagedCategoryExists(); - } - - private void RegisterComImportedType(Type type, String strAsmName, String strAsmVersion, String strAsmCodeBase, String strRuntimeVersion) - { - // Retrieve some information that will be used during the registration process. - String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; - - // Create the HKEY_CLASS_ROOT\CLSID key. - using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.CreateSubKey(strClsIdRootName)) - { - // Create the HKEY_CLASS_ROOT\CLSID\<CLSID> key. - using (RegistryKey ClsIdKey = ClsIdRootKey.CreateSubKey(strClsId)) - { - // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\InProcServer32 key. - using (RegistryKey InProcServerKey = ClsIdKey.CreateSubKey("InprocServer32")) - { - // Set the class value. - InProcServerKey.SetValue("Class", type.FullName); - - // Set the assembly value. - InProcServerKey.SetValue("Assembly", strAsmName); - - // Set the runtime version value. - InProcServerKey.SetValue("RuntimeVersion", strRuntimeVersion); - - // Set the assembly code base value if a code base was specified. - if (strAsmCodeBase != null) - InProcServerKey.SetValue("CodeBase", strAsmCodeBase); - - // Create the HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32\<Version> subkey - using (RegistryKey VersionSubKey = InProcServerKey.CreateSubKey(strAsmVersion)) - { - VersionSubKey.SetValue("Class", type.FullName); - VersionSubKey.SetValue("Assembly", strAsmName); - VersionSubKey.SetValue("RuntimeVersion", strRuntimeVersion); - if (strAsmCodeBase != null) - VersionSubKey.SetValue("CodeBase", strAsmCodeBase); - } - } - } - } - } - - private bool UnregisterValueType(Type type, String strAsmVersion) - { - bool bAllVersionsGone = true; - - // Try to open the HKEY_CLASS_ROOT\Record key. - String strRecordId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; - - using (RegistryKey RecordRootKey = Registry.ClassesRoot.OpenSubKey(strRecordRootName, true)) - { - if (RecordRootKey != null) - { - // Open the HKEY_CLASS_ROOT\Record\{RecordId} key. - using (RegistryKey RecordKey = RecordRootKey.OpenSubKey(strRecordId,true)) - { - if (RecordKey != null) - { - using (RegistryKey VersionSubKey = RecordKey.OpenSubKey(strAsmVersion,true)) - { - if (VersionSubKey != null) - { - // Delete the values we created. - VersionSubKey.DeleteValue("Assembly",false); - VersionSubKey.DeleteValue("Class",false); - VersionSubKey.DeleteValue("CodeBase",false); - VersionSubKey.DeleteValue("RuntimeVersion",false); - - // delete the version sub key if no value or subkeys under it - if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0)) - RecordKey.DeleteSubKey(strAsmVersion); - } - } - - // If there are sub keys left then there are versions left. - if (RecordKey.SubKeyCount != 0) - bAllVersionsGone = false; - - // If there are no other values or subkeys then we can delete the HKEY_CLASS_ROOT\Record\{RecordId}. - if ((RecordKey.SubKeyCount == 0) && (RecordKey.ValueCount == 0)) - RecordRootKey.DeleteSubKey(strRecordId); - } - } - - // If there are no other values or subkeys then we can delete the HKEY_CLASS_ROOT\Record. - if ((RecordRootKey.SubKeyCount == 0) && (RecordRootKey.ValueCount == 0)) - Registry.ClassesRoot.DeleteSubKey(strRecordRootName); - } - } - - return bAllVersionsGone; - } - - // UnregisterManagedType - // - // Return : - // true: All versions are gone. - // false: Some versions are still left in registry - private bool UnregisterManagedType(Type type,String strAsmVersion) - { - bool bAllVersionsGone = true; - - // - // Create the CLSID string. - // - - String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; - String strProgId = GetProgIdForType(type); - - - // - // Remove the entries under HKEY_CLASS_ROOT\CLSID key. - // - - using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.OpenSubKey(strClsIdRootName, true)) - { - if (ClsIdRootKey != null) - { - // - // Remove the entries under HKEY_CLASS_ROOT\CLSID\<CLSID> key. - // - - using (RegistryKey ClsIdKey = ClsIdRootKey.OpenSubKey(strClsId, true)) - { - if (ClsIdKey != null) - { - // - // Remove the entries in the HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32 key. - // - - using (RegistryKey InProcServerKey = ClsIdKey.OpenSubKey("InprocServer32", true)) - { - if (InProcServerKey != null) - { - // - // Remove the entries in HKEY_CLASS_ROOT\CLSID\<CLSID>\InprocServer32\<Version> - // - - using (RegistryKey VersionSubKey = InProcServerKey.OpenSubKey(strAsmVersion, true)) - { - if (VersionSubKey != null) - { - // Delete the values we created - VersionSubKey.DeleteValue("Assembly",false); - VersionSubKey.DeleteValue("Class",false); - VersionSubKey.DeleteValue("RuntimeVersion",false); - VersionSubKey.DeleteValue("CodeBase",false); - - // If there are no other values or subkeys then we can delete the VersionSubKey. - if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0)) - InProcServerKey.DeleteSubKey(strAsmVersion); - } - } - - // If there are sub keys left then there are versions left. - if (InProcServerKey.SubKeyCount != 0) - bAllVersionsGone = false; - - // If there are no versions left, then delete the threading model and default value. - if (bAllVersionsGone) - { - InProcServerKey.DeleteValue("",false); - InProcServerKey.DeleteValue("ThreadingModel",false); - } - - InProcServerKey.DeleteValue("Assembly",false); - InProcServerKey.DeleteValue("Class",false); - InProcServerKey.DeleteValue("RuntimeVersion",false); - InProcServerKey.DeleteValue("CodeBase",false); - - // If there are no other values or subkeys then we can delete the InProcServerKey. - if ((InProcServerKey.SubKeyCount == 0) && (InProcServerKey.ValueCount == 0)) - ClsIdKey.DeleteSubKey("InprocServer32"); - } - } - - // remove HKEY_CLASS_ROOT\CLSID\<CLSID>\ProgId - // and HKEY_CLASS_ROOT\CLSID\<CLSID>\Implemented Category - // only when all versions are removed - if (bAllVersionsGone) - { - // Delete the value we created. - ClsIdKey.DeleteValue("",false); - - if (strProgId != String.Empty) - { - // - // Remove the entries in the HKEY_CLASS_ROOT\CLSID\<CLSID>\ProgId key. - // - - using (RegistryKey ProgIdKey = ClsIdKey.OpenSubKey("ProgId", true)) - { - if (ProgIdKey != null) - { - // Delete the value we created. - ProgIdKey.DeleteValue("",false); - - // If there are no other values or subkeys then we can delete the ProgIdSubKey. - if ((ProgIdKey.SubKeyCount == 0) && (ProgIdKey.ValueCount == 0)) - ClsIdKey.DeleteSubKey("ProgId"); - } - } - } - - - // - // Remove entries in the HKEY_CLASS_ROOT\CLSID\<CLSID>\Implemented Categories\<Managed Category Guid> key. - // - - using (RegistryKey CategoryKey = ClsIdKey.OpenSubKey(strImplementedCategoriesSubKey, true)) - { - if (CategoryKey != null) - { - using (RegistryKey ManagedCategoryKey = CategoryKey.OpenSubKey(strManagedCategoryGuid, true)) - { - if (ManagedCategoryKey != null) - { - // If there are no other values or subkeys then we can delete the ManagedCategoryKey. - if ((ManagedCategoryKey.SubKeyCount == 0) && (ManagedCategoryKey.ValueCount == 0)) - CategoryKey.DeleteSubKey(strManagedCategoryGuid); - } - } - - // If there are no other values or subkeys then we can delete the CategoryKey. - if ((CategoryKey.SubKeyCount == 0) && (CategoryKey.ValueCount == 0)) - ClsIdKey.DeleteSubKey(strImplementedCategoriesSubKey); - } - } - } - - // If there are no other values or subkeys then we can delete the ClsIdKey. - if ((ClsIdKey.SubKeyCount == 0) && (ClsIdKey.ValueCount == 0)) - ClsIdRootKey.DeleteSubKey(strClsId); - } - } - - // If there are no other values or subkeys then we can delete the CLSID key. - if ((ClsIdRootKey.SubKeyCount == 0) && (ClsIdRootKey.ValueCount == 0)) - Registry.ClassesRoot.DeleteSubKey(strClsIdRootName); - } - - - // - // Remove the entries under HKEY_CLASS_ROOT\<wzProgId> key. - // - - if (bAllVersionsGone) - { - if (strProgId != String.Empty) - { - using (RegistryKey TypeNameKey = Registry.ClassesRoot.OpenSubKey(strProgId, true)) - { - if (TypeNameKey != null) - { - // Delete the values we created. - TypeNameKey.DeleteValue("",false); - - - // - // Remove the entries in the HKEY_CLASS_ROOT\<wzProgId>\CLSID key. - // - - using (RegistryKey ProgIdClsIdKey = TypeNameKey.OpenSubKey("CLSID", true)) - { - if (ProgIdClsIdKey != null) - { - // Delete the values we created. - ProgIdClsIdKey.DeleteValue("",false); - - // If there are no other values or subkeys then we can delete the ProgIdClsIdKey. - if ((ProgIdClsIdKey.SubKeyCount == 0) && (ProgIdClsIdKey.ValueCount == 0)) - TypeNameKey.DeleteSubKey("CLSID"); - } - } - - // If there are no other values or subkeys then we can delete the TypeNameKey. - if ((TypeNameKey.SubKeyCount == 0) && (TypeNameKey.ValueCount == 0)) - Registry.ClassesRoot.DeleteSubKey(strProgId); - } - } - } - } - } - - return bAllVersionsGone; - } - - // UnregisterComImportedType - // Return: - // true: All version information are gone. - // false: There are still some version left in registry - private bool UnregisterComImportedType(Type type, String strAsmVersion) - { - bool bAllVersionsGone = true; - - String strClsId = "{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; - - // Try to open the HKEY_CLASS_ROOT\CLSID key. - using (RegistryKey ClsIdRootKey = Registry.ClassesRoot.OpenSubKey(strClsIdRootName, true)) - { - if (ClsIdRootKey != null) - { - // Try to open the HKEY_CLASS_ROOT\CLSID\<CLSID> key. - using (RegistryKey ClsIdKey = ClsIdRootKey.OpenSubKey(strClsId, true)) - { - if (ClsIdKey != null) - { - // Try to open the HKEY_CLASS_ROOT\CLSID\<CLSID>\InProcServer32 key. - using (RegistryKey InProcServerKey = ClsIdKey.OpenSubKey("InprocServer32", true)) - { - if (InProcServerKey != null) - { - // Delete the values we created. - InProcServerKey.DeleteValue("Assembly",false); - InProcServerKey.DeleteValue("Class",false); - InProcServerKey.DeleteValue("RuntimeVersion",false); - InProcServerKey.DeleteValue("CodeBase",false); - - // Try to open the entries in HKEY_CLASS_ROOT\CLSID\<CLSID>\InProcServer32\<Version> - using (RegistryKey VersionSubKey = InProcServerKey.OpenSubKey(strAsmVersion,true)) - { - if (VersionSubKey != null) - { - // Delete the value we created - VersionSubKey.DeleteValue("Assembly",false); - VersionSubKey.DeleteValue("Class",false); - VersionSubKey.DeleteValue("RuntimeVersion",false); - VersionSubKey.DeleteValue("CodeBase",false); - - // If there are no other values or subkeys then we can delete the VersionSubKey - if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0)) - InProcServerKey.DeleteSubKey(strAsmVersion); - } - } - - // If there are sub keys left then there are versions left. - if (InProcServerKey.SubKeyCount != 0) - bAllVersionsGone = false; - - // If there are no other values or subkeys then we can delete the InProcServerKey. - if ((InProcServerKey.SubKeyCount == 0) && (InProcServerKey.ValueCount == 0)) - ClsIdKey.DeleteSubKey("InprocServer32"); - } - } - - // If there are no other values or subkeys then we can delete the ClsIdKey. - if ((ClsIdKey.SubKeyCount == 0) && (ClsIdKey.ValueCount == 0)) - ClsIdRootKey.DeleteSubKey(strClsId); - } - } - - // If there are no other values or subkeys then we can delete the CLSID key. - if ((ClsIdRootKey.SubKeyCount == 0) && (ClsIdRootKey.ValueCount == 0)) - Registry.ClassesRoot.DeleteSubKey(strClsIdRootName); - } - } - - return bAllVersionsGone; - } - - private void RegisterPrimaryInteropAssembly(RuntimeAssembly assembly, String strAsmCodeBase, PrimaryInteropAssemblyAttribute attr) - { - // Validate that the PIA has a strong name. - if (assembly.GetPublicKey().Length == 0) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_PIAMustBeStrongNamed")); - - String strTlbId = "{" + Marshal.GetTypeLibGuidForAssembly(assembly).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; - String strVersion = attr.MajorVersion.ToString("x", CultureInfo.InvariantCulture) + "." + attr.MinorVersion.ToString("x", CultureInfo.InvariantCulture); - - // Create the HKEY_CLASS_ROOT\TypeLib key. - using (RegistryKey TypeLibRootKey = Registry.ClassesRoot.CreateSubKey(strTlbRootName)) - { - // Create the HKEY_CLASS_ROOT\TypeLib\<TLBID> key. - using (RegistryKey TypeLibKey = TypeLibRootKey.CreateSubKey(strTlbId)) - { - // Create the HKEY_CLASS_ROOT\TypeLib\<TLBID>\<Major.Minor> key. - using (RegistryKey VersionSubKey = TypeLibKey.CreateSubKey(strVersion)) - { - // Create the HKEY_CLASS_ROOT\TypeLib\<TLBID>\PrimaryInteropAssembly key. - VersionSubKey.SetValue("PrimaryInteropAssemblyName", assembly.FullName); - if (strAsmCodeBase != null) - VersionSubKey.SetValue("PrimaryInteropAssemblyCodeBase", strAsmCodeBase); - } - } - } - } - - private void UnregisterPrimaryInteropAssembly(Assembly assembly, PrimaryInteropAssemblyAttribute attr) - { - String strTlbId = "{" + Marshal.GetTypeLibGuidForAssembly(assembly).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; - String strVersion = attr.MajorVersion.ToString("x", CultureInfo.InvariantCulture) + "." + attr.MinorVersion.ToString("x", CultureInfo.InvariantCulture); - - // Try to open the HKEY_CLASS_ROOT\TypeLib key. - using (RegistryKey TypeLibRootKey = Registry.ClassesRoot.OpenSubKey(strTlbRootName, true)) - { - if (TypeLibRootKey != null) - { - // Try to open the HKEY_CLASS_ROOT\TypeLib\<TLBID> key. - using (RegistryKey TypeLibKey = TypeLibRootKey.OpenSubKey(strTlbId, true)) - { - if (TypeLibKey != null) - { - // Try to open the HKEY_CLASS_ROOT\TypeLib<TLBID>\<Major.Minor> key. - using (RegistryKey VersionSubKey = TypeLibKey.OpenSubKey(strVersion, true)) - { - if (VersionSubKey != null) - { - // Delete the values we created. - VersionSubKey.DeleteValue("PrimaryInteropAssemblyName",false); - VersionSubKey.DeleteValue("PrimaryInteropAssemblyCodeBase",false); - - // If there are no other values or subkeys then we can delete the VersionKey. - if ((VersionSubKey.SubKeyCount == 0) && (VersionSubKey.ValueCount == 0)) - TypeLibKey.DeleteSubKey(strVersion); - } - } - - // If there are no other values or subkeys then we can delete the TypeLibKey. - if ((TypeLibKey.SubKeyCount == 0) && (TypeLibKey.ValueCount == 0)) - TypeLibRootKey.DeleteSubKey(strTlbId); - } - } - - // If there are no other values or subkeys then we can delete the TypeLib key. - if ((TypeLibRootKey.SubKeyCount == 0) && (TypeLibRootKey.ValueCount == 0)) - Registry.ClassesRoot.DeleteSubKey(strTlbRootName); - } - } - } - - private void EnsureManagedCategoryExists() - { - if (!ManagedCategoryExists()) - { - // Create the HKEY_CLASS_ROOT\Component Category key. - using (RegistryKey ComponentCategoryKey = Registry.ClassesRoot.CreateSubKey(strComponentCategorySubKey)) - { - // Create the HKEY_CLASS_ROOT\Component Category\<Managed Category Guid> key. - using (RegistryKey ManagedCategoryKey = ComponentCategoryKey.CreateSubKey(strManagedCategoryGuid)) - { - ManagedCategoryKey.SetValue("0", strManagedCategoryDescription); - } - } - } - } - - private static bool ManagedCategoryExists() - { - using (RegistryKey componentCategoryKey = Registry.ClassesRoot.OpenSubKey(strComponentCategorySubKey, - false)) - { - if (componentCategoryKey == null) - return false; - using (RegistryKey managedCategoryKey = componentCategoryKey.OpenSubKey(strManagedCategoryGuid, - false)) - { - if (managedCategoryKey == null) - return false; - object value = managedCategoryKey.GetValue("0"); - if (value == null || value.GetType() != typeof(string)) - return false; - string stringValue = (string)value; - if (stringValue != strManagedCategoryDescription) - return false; - } - } - - return true; - } - - private void CallUserDefinedRegistrationMethod(Type type, bool bRegister) - { - bool bFunctionCalled = false; - - // Retrieve the attribute type to use to determine if a function is the requested user defined - // registration function. - Type RegFuncAttrType = null; - if(bRegister) - RegFuncAttrType = typeof(ComRegisterFunctionAttribute); - else - RegFuncAttrType = typeof(ComUnregisterFunctionAttribute); - - for(Type currType = type; !bFunctionCalled && currType != null; currType = currType.BaseType) - { - // Retrieve all the methods. - MethodInfo[] aMethods = currType.GetMethods(BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Static); - int NumMethods = aMethods.Length; - - // Go through all the methods and check for the ComRegisterMethod custom attribute. - for(int cMethods = 0;cMethods < NumMethods;cMethods++) - { - MethodInfo CurrentMethod = aMethods[cMethods]; - - // Check to see if the method has the custom attribute. - if(CurrentMethod.GetCustomAttributes(RegFuncAttrType, true).Length != 0) - { - // Check to see if the method is static before we call it. - if(!CurrentMethod.IsStatic) - { - if(bRegister) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NonStaticComRegFunction",CurrentMethod.Name,currType.Name)); - else - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NonStaticComUnRegFunction",CurrentMethod.Name,currType.Name)); - } - - // Finally check that the signature is string ret void. - ParameterInfo[] aParams = CurrentMethod.GetParameters(); - if (CurrentMethod.ReturnType != typeof(void) || - aParams == null || - aParams.Length != 1 || - (aParams[0].ParameterType != typeof(String) && aParams[0].ParameterType != typeof(Type))) - { - if(bRegister) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_InvalidComRegFunctionSig",CurrentMethod.Name,currType.Name)); - else - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_InvalidComUnRegFunctionSig",CurrentMethod.Name,currType.Name)); - } - - // There can only be one register and one unregister function per type. - if(bFunctionCalled) - { - if(bRegister) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MultipleComRegFunctions",currType.Name)); - else - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MultipleComUnRegFunctions",currType.Name)); - } - - // The function is valid so set up the arguments to call it. - Object[] objs = new Object[1]; - if(aParams[0].ParameterType == typeof(String)) - { - // We are dealing with the string overload of the function. - objs[0] = "HKEY_CLASSES_ROOT\\CLSID\\{" + Marshal.GenerateGuidForType(type).ToString().ToUpper(CultureInfo.InvariantCulture) + "}"; - } - else - { - // We are dealing with the type overload of the function. - objs[0] = type; - } - - // Invoke the COM register function. - CurrentMethod.Invoke(null, objs); - - // Mark the function as having been called. - bFunctionCalled = true; - } - } - } - } - - private Type GetBaseComImportType(Type type) - { - for (; type != null && !type.IsImport; type = type.BaseType); - return type; - } - - private bool IsRegisteredAsValueType(Type type) - { - if (!type.IsValueType) - return false; - - return true; - } - - #endregion - - - #region FCalls and DllImports - -#if FEATURE_COMINTEROP_MANAGED_ACTIVATION - // GUID versioning can be controlled by using the GuidAttribute or - // letting the runtime generate it based on type and assembly strong name. - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern void RegisterTypeForComClientsNative(Type type,ref Guid g); - - // GUID versioning can be controlled by using the GuidAttribute or - // letting the runtime generate it based on type and assembly strong name. - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern int RegisterTypeForComClientsExNative(Type t, RegistrationClassContext clsContext, RegistrationConnectionType flags); -#endif // FEATURE_COMINTEROP_MANAGED_ACTIVATION - - [DllImport(Win32Native.OLE32,CharSet=CharSet.Auto,PreserveSig=false)] - private static extern void CoRevokeClassObject(int cookie); - #endregion - } -} |