Ejemplo n.º 1
0
        /// <summary>
        /// Actually performs registration. The ComRegisterFunction decorated method will call this function
        /// internally with the flag appropriate for the operating system processor architecture.
        /// However, this function can also be called manually if needed.
        /// </summary>
        /// <param name="type">The type of object to register, this must be a SharpShellServer derived class.</param>
        /// <param name="registrationType">Type of the registration.</param>
        internal static void DoRegister(Type type, RegistrationType registrationType)
        {
            Logging.Log($"Preparing to register SharpShell Server {type.Name} as {registrationType}");

            //  Get the association data.
            var associationAttributes = type.GetCustomAttributes(typeof(COMServerAssociationAttribute), true)
                                        .OfType <COMServerAssociationAttribute>().ToList();

            //  Get the server type and the registration name.
            var serverType       = ServerTypeAttribute.GetServerType(type);
            var registrationName = RegistrationNameAttribute.GetRegistrationNameOrTypeName(type);

            //  Register the server associations, if there are any.
            if (associationAttributes.Any())
            {
                ServerRegistrationManager.RegisterServerAssociations(
                    type.GUID, serverType, registrationName, associationAttributes, registrationType);
            }

            //  If a DisplayName attribute has been set, then set the display name of the COM server.
            var displayName = DisplayNameAttribute.GetDisplayName(type);

            if (!string.IsNullOrEmpty(displayName))
            {
                ServerRegistrationManager.SetServerDisplayName(type.GUID, displayName, registrationType);
            }

            //  Execute the custom register function, if there is one.
            CustomRegisterFunctionAttribute.ExecuteIfExists(type, registrationType);

            //  Notify the shell we've updated associations.
            Shell32.SHChangeNotify(Shell32.SHCNE_ASSOCCHANGED, 0, IntPtr.Zero, IntPtr.Zero);
            Logging.Log($"Registration of {type.Name} completed");
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Actually performs unregistration. The ComUnregisterFunction decorated method will call this function
        /// internally with the flag appropriate for the operating system processor architecture.
        /// However, this function can also be called manually if needed.
        /// </summary>
        /// <param name="type">The type of object to unregister, this must be a SharpShellServer derived class.</param>
        /// <param name="registrationType">Type of the registration to unregister.</param>
        internal static void DoUnregister(Type type, RegistrationType registrationType)
        {
            Logging.Log($"Preparing to unregister SharpShell Server {type.Name} as {registrationType}");

            //  Get the association data.
            var associationAttributes = type.GetCustomAttributes(typeof(COMServerAssociationAttribute), true)
                                        .OfType <COMServerAssociationAttribute>().ToList();

            //  Get the server type and the registration name.
            var serverType       = ServerTypeAttribute.GetServerType(type);
            var registrationName = RegistrationNameAttribute.GetRegistrationNameOrTypeName(type);

            //  Unregister the server associations, if there are any.
            if (associationAttributes.Any())
            {
                ServerRegistrationManager.UnregisterServerAssociations(
                    type.GUID, serverType, registrationName, associationAttributes, registrationType);
            }

            //  Execute the custom unregister function, if there is one.
            CustomUnregisterFunctionAttribute.ExecuteIfExists(type, registrationType);

            //  Notify the shell we've updated associations.
            Shell32.SHChangeNotify(Shell32.SHCNE_ASSOCCHANGED, 0, IntPtr.Zero, IntPtr.Zero);
            Logging.Log($"Unregistration of {type.Name} completed");
        }
        internal static void CustomUnregisterFunction(Type serverType, RegistrationType registrationType)
        {
            var keyName = RegistrationNameAttribute.GetRegistrationNameOrTypeName(serverType);

            Logging.Log($"IconOverlayHandler: Preparing to unregister {registrationType} Icon Overlay Handler for type '{serverType.Name}' with key name '{keyName}'");

            //  Open the local machine.
            using (var localMachineBaseKey = registrationType == RegistrationType.OS64Bit
                ? RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64) :
                                             RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
            {
                //  Open the ShellIconOverlayIdentifiers.
                using (var overlayIdentifiers = localMachineBaseKey
                                                .OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers",
                                                            RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.Delete | RegistryRights.EnumerateSubKeys | RegistryRights.ReadKey))
                {
                    //  If we don't have the key, we've got a problem.
                    if (overlayIdentifiers == null)
                    {
                        throw new InvalidOperationException("Cannot open the ShellIconOverlayIdentifiers key.");
                    }

                    //  Delete the overlay key.
                    if (overlayIdentifiers.GetSubKeyNames().Any(skn => skn == keyName))
                    {
                        overlayIdentifiers.DeleteSubKey(keyName);
                    }
                }
            }
        }
        internal static void CustomRegisterFunction(Type serverType, RegistrationType registrationType)
        {
            var keyName = RegistrationNameAttribute.GetRegistrationNameOrTypeName(serverType);

            Logging.Log($"IconOverlayHandler: Preparing to register {registrationType} Icon Overlay Handler for type '{serverType.Name}' with key name '{keyName}'");

            //  Open the local machine.
            using (var localMachineBaseKey = registrationType == RegistrationType.OS64Bit
                ? RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64) :
                                             RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
            {
                //  Open the ShellIconOverlayIdentifiers.
                using (var overlayIdentifiers = localMachineBaseKey
                                                .OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers",
                                                            RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.EnumerateSubKeys | RegistryRights.QueryValues | RegistryRights.CreateSubKey | RegistryRights.CreateSubKey))
                {
                    //  If we don't have the key, we've got a problem.
                    if (overlayIdentifiers == null)
                    {
                        throw new InvalidOperationException("Cannot open the ShellIconOverlayIdentifiers key.");
                    }

                    //  How many shell icon overlay identifiers do we have?
                    var overlayHandlersCount = overlayIdentifiers.GetSubKeyNames().Count();
                    if (overlayHandlersCount >= MaximumOverlayIdentifiers)
                    {
                        Logging.Error("There are already the maximum number of overlay " +
                                      "handlers registered for the system. Although " + serverType.Name + " is " +
                                      "being registered, it will not be used by Windows Explorer.");
                    }

                    //  Create the overlay key.
                    using (var overlayKey = overlayIdentifiers.CreateSubKey(keyName))
                    {
                        //  If we don't have the overlay key, we've got a problem.
                        if (overlayKey == null)
                        {
                            throw new InvalidOperationException("Cannot create the key for the overlay server.");
                        }

                        //  Set the server CLSID.
                        overlayKey.SetValue(null, serverType.GUID.ToRegistryString());
                    }
                }
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Actually performs registration. The ComRegisterFunction decorated method will call this function
        /// internally with the flag appropriate for the operating system processor architecture.
        /// However, this function can also be called manually if needed.
        /// </summary>
        /// <param name="type">The type of object to register, this must be a SharpShellServer derived class.</param>
        /// <param name="registrationType">Type of the registration.</param>
        internal static void DoRegister(Type type, RegistrationType registrationType)
        {
            Logging.Log($"Preparing to register SharpShell Server {type.Name} as {registrationType}");

            //  Get the association data.
            var associationAttributes = type.GetCustomAttributes(typeof(COMServerAssociationAttribute), true)
                                        .OfType <COMServerAssociationAttribute>().ToList();

            //  Get the server type and the registration name.
            var serverType       = ServerTypeAttribute.GetServerType(type);
            var registrationName = RegistrationNameAttribute.GetRegistrationNameOrTypeName(type);

            //  Register the server associations, if there are any.
            if (associationAttributes.Any())
            {
                ServerRegistrationManager.RegisterServerAssociations(
                    type.GUID, serverType, registrationName, associationAttributes, registrationType);
            }

            //  If a DisplayName attribute has been set, then set the display name of the COM server.
            var displayName = DisplayNameAttribute.GetDisplayName(type);

            if (!string.IsNullOrEmpty(displayName))
            {
                ServerRegistrationManager.SetServerDisplayName(type.GUID, displayName, registrationType);
            }

            //  If we are a *file* thumbnail handler, we must disable process isolation.
            //  See: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/cc144118(v%3Dvs.85)#thumbnail-processes
            if (serverType == ServerType.ShellItemThumbnailHandler)
            {
                Logging.Log($"Disabling process isolation for SharpFileThumbnailHandler named '{type.Name}'.");
                ServerRegistrationManager.SetDisableProcessIsolationValue(type.GUID, registrationType, 1 /* i.e. disabled */);
            }

            //  Execute the custom register function, if there is one.
            CustomRegisterFunctionAttribute.ExecuteIfExists(type, registrationType);

            //  Notify the shell we've updated associations.
            Shell32.SHChangeNotify(Shell32.SHCNE_ASSOCCHANGED, 0, IntPtr.Zero, IntPtr.Zero);
            Logging.Log($"Registration of {type.Name} completed");
        }