RegistrationServices.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / clr / src / BCL / System / Runtime / InteropServices / RegistrationServices.cs / 1305376 / RegistrationServices.cs

                            // ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
/*==============================================================================
** 
** Class: RegistrationServices 
**
** 
** 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.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
 
        [System.Security.SecurityCritical]  // auto-generated_required
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        public virtual bool RegisterAssembly(Assembly assembly, AssemblyRegistrationFlags flags)
        { 
            // Validate the arguments.
            if (assembly == null)
                throw new ArgumentNullException("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; 
        }
 
        [System.Security.SecurityCritical]  // auto-generated_required 
        public virtual bool UnregisterAssembly(Assembly assembly)
        { 
            // Validate the arguments.
            if (assembly == null)
                throw new ArgumentNullException("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;
        }

        [System.Security.SecurityCritical]  // auto-generated_required 
        public virtual Type[] GetRegistrableTypesInAssembly(Assembly assembly)
        { 
            // Validate the arguments. 
            if (assembly == null)
                throw new ArgumentNullException("assembly"); 
            Contract.EndContractBlock();

            if (!(assembly is RuntimeAssembly))
                throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeAssembly"), "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; 
        } 

        [System.Security.SecurityCritical]  // auto-generated_required 
        public virtual String GetProgIdForType(Type type)
        {
            return Marshal.GenerateProgIdForType(type);
        } 

        [System.Security.SecurityCritical]  // auto-generated_required 
        public virtual void RegisterTypeForComClients(Type type, ref Guid g) 
        {
#if FEATURE_COMINTEROP_MANAGED_ACTIVATION 
            if(type == null)
                throw new ArgumentNullException("type");
            Contract.EndContractBlock();
            if((type as RuntimeType) == null) 
                throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"),"type");
            if(!TypeRequiresRegistration(type)) 
                throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"),"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; 
        }

        [System.Security.SecurityCritical]  // auto-generated_required
        public virtual bool TypeRequiresRegistration(Type type) 
        {
            return TypeRequiresRegistrationHelper(type); 
        } 

        [System.Security.SecuritySafeCritical]  // auto-generated 
        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); 
            Contract.Assert(baseComImportType != null, "baseComImportType != null");
            if (Marshal.GenerateGuidForType(type) == Marshal.GenerateGuidForType(baseComImportType)) 
                return true; 

            return false; 
        }

        #endregion
 

        #region Public methods not on IRegistrationServices 
        [System.Security.SecurityCritical]  // auto-generated_required 
        [ComVisible(false)]
        public virtual int RegisterTypeForComClients(Type type, RegistrationClassContext classContext, RegistrationConnectionType flags) 
        {
#if FEATURE_COMINTEROP_MANAGED_ACTIVATION
            if (type == null)
                throw new ArgumentNullException("type"); 
            Contract.EndContractBlock();
            if ((type as RuntimeType) == null) 
                throw new ArgumentException(Environment.GetResourceString("Argument_MustBeRuntimeType"),"type"); 
            if (!TypeRequiresRegistration(type))
                throw new ArgumentException(Environment.GetResourceString("Argument_TypeMustBeComCreatable"),"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 
        } 

        [System.Security.SecurityCritical]  // auto-generated_required 
        [ComVisible(false)]
        public virtual void UnregisterTypeForComClients(int cookie)
        {
            // Call the native method to do CoRevokeClassObject. 
            CoRevokeClassObject(cookie);
        } 
 
        #endregion
 

        #region Internal helpers

        [System.Security.SecurityCritical]  // auto-generated_required 
        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,new Type[0],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 

        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        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\ key. 
                using (RegistryKey RecordKey = RecordRootKey.CreateSubKey(strRecordId))
                { 
                    // Create the HKEY_CLASS_ROOT\Record\\ 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);
                    } 
                }
            } 
        } 

        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        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\ key.
                using (RegistryKey TypeNameKey = Registry.ClassesRoot.CreateSubKey(strProgId))
                { 
                    TypeNameKey.SetValue("", strDocString);
 
                    // Create the HKEY_CLASS_ROOT\\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\ key. 
                using (RegistryKey ClsIdKey = ClsIdRootKey.CreateSubKey(strClsId))
                {
                    ClsIdKey.SetValue("", strDocString);
 
                    // Create the HKEY_CLASS_ROOT\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\\InprocServer32\ 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\\ProdId key.
                            using (RegistryKey ProgIdKey = ClsIdKey.CreateSubKey("ProgId"))
                            {
                                ProgIdKey.SetValue("", strProgId); 
                            }
                        } 
                    } 

                    // Create the HKEY_CLASS_ROOT\CLSID\\Implemented Categories\ key. 
                    using (RegistryKey CategoryKey = ClsIdKey.CreateSubKey(strImplementedCategoriesSubKey))
                    {
                        using (RegistryKey ManagedCategoryKey = CategoryKey.CreateSubKey(strManagedCategoryGuid)) {}
                    } 
                }
            } 
 

            // 
            // Ensure that the managed category exists.
            //

            EnsureManagedCategoryExists(); 
        }
 
        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)] 
        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\ key. 
                using (RegistryKey ClsIdKey = ClsIdRootKey.CreateSubKey(strClsId))
                {
                    // Create the HKEY_CLASS_ROOT\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\\InprocServer32\ 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);
                        } 
                    }
                }
            }
        } 

        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        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
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        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\ key.
                    // 

                    using (RegistryKey ClsIdKey = ClsIdRootKey.OpenSubKey(strClsId, true))
                    {
                        if (ClsIdKey != null) 
                        {
                            // 
                            // Remove the entries in the HKEY_CLASS_ROOT\CLSID\\InprocServer32 key. 
                            //
 
                            using (RegistryKey InProcServerKey = ClsIdKey.OpenSubKey("InprocServer32", true))
                            {
                                if (InProcServerKey != null)
                                { 
                                    //
                                    // Remove the entries in HKEY_CLASS_ROOT\CLSID\\InprocServer32\ 
                                    // 

                                    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\\ProgId
                            // and HKEY_CLASS_ROOT\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\\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\\Implemented Categories\ 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\ 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\\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
        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.None)]
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        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\ key.
                    using (RegistryKey ClsIdKey = ClsIdRootKey.OpenSubKey(strClsId, true)) 
                    { 
                        if (ClsIdKey != null)
                        { 
                            // Try to open the HKEY_CLASS_ROOT\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\\InProcServer32\
                                    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; 
        } 

        [System.Security.SecurityCritical]  // auto-generated 
        [ResourceExposure(ResourceScope.Machine)]
        [ResourceConsumption(ResourceScope.Machine)]
        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\ key. 
                using (RegistryKey TypeLibKey = TypeLibRootKey.CreateSubKey(strTlbId)) 
                {
                    // Create the HKEY_CLASS_ROOT\TypeLib\\ key. 
                    using (RegistryKey VersionSubKey = TypeLibKey.CreateSubKey(strVersion))
                    {
                        // Create the HKEY_CLASS_ROOT\TypeLib\\PrimaryInteropAssembly key.
                        VersionSubKey.SetValue("PrimaryInteropAssemblyName", assembly.FullName); 
                        if (strAsmCodeBase != null)
                            VersionSubKey.SetValue("PrimaryInteropAssemblyCodeBase", strAsmCodeBase); 
                    } 
                }
            } 
        }

        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        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\ key. 
                    using (RegistryKey TypeLibKey = TypeLibRootKey.OpenSubKey(strTlbId, true))
                    { 
                        if (TypeLibKey != null)
                        {
                            // Try to open the HKEY_CLASS_ROOT\TypeLib\ 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);
                } 
            }
        }

        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        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\ key. 
                    using (RegistryKey ManagedCategoryKey = ComponentCategoryKey.CreateSubKey(strManagedCategoryGuid))
                    { 
                        ManagedCategoryKey.SetValue("0", strManagedCategoryDescription); 
                    }
                } 
            }
        }

        [ResourceExposure(ResourceScope.None)] 
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
        private static bool ManagedCategoryExists() 
        { 
            using (RegistryKey componentCategoryKey = Registry.ClassesRoot.OpenSubKey(strComponentCategorySubKey, RegistryKeyPermissionCheck.ReadSubTree))
            { 
                if (componentCategoryKey == null)
                    return false;
                using (RegistryKey managedCategoryKey = componentCategoryKey.OpenSubKey(strManagedCategoryGuid, RegistryKeyPermissionCheck.ReadSubTree))
                { 
                    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; 
        }
 
        [System.Security.SecurityCritical]  // auto-generated
        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. 
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [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.
        [System.Security.SecurityCritical]  // auto-generated
        [ResourceExposure(ResourceScope.None)] 
        [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)] 
        [ResourceExposure(ResourceScope.None)]
        private static extern void CoRevokeClassObject(int cookie);
        #endregion
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK