Пример #1
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");
        }
Пример #2
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");
        }
        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());
                    }
                }
            }
        }
Пример #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");
        }
Пример #6
0
        public LspHandlerTypeDescriptor(Type handlerType) : base(handlerType)
        {
            if (HasParamsType)
            {
                PartialItemsType = ParamsType !.GetInterfaces()
                                   .FirstOrDefault(z => z.IsGenericType && typeof(IPartialItems <>).IsAssignableFrom(z.GetGenericTypeDefinition()))
                                   ?.GetGenericArguments()[0];

                PartialItemType = ParamsType.GetInterfaces()
                                  .FirstOrDefault(z => z.IsGenericType && typeof(IPartialItem <>).IsAssignableFrom(z.GetGenericTypeDefinition()))
                                  ?.GetGenericArguments()[0];
            }

            HasPartialItems = PartialItemsType != null;
            HasPartialItem  = PartialItemType != null;

            RegistrationType = HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration <>), handlerType)
                               ?? HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration <,>), handlerType, 0);
            HasRegistration    = RegistrationType != null && RegistrationType != typeof(object);
            RegistrationMethod = RegistrationNameAttribute.AllFrom(RegistrationType).FirstOrDefault()?.Method ?? Method;
            if (!HasRegistration)
            {
                RegistrationType = null;
            }

            CapabilityType = HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(ICapability <>), handlerType)
                             ?? HandlerTypeDescriptorHelper.UnwrapGenericType(typeof(IRegistration <,>), handlerType, 1);
            HasCapability = CapabilityType != null;
            if (!HasCapability)
            {
                CapabilityType = null;
            }

            if (HasCapability)
            {
                IsDynamicCapability = typeof(IDynamicCapability).GetTypeInfo().IsAssignableFrom(CapabilityType);
            }
        }
        internal static IDisposable DynamicallyRegisterHandlers(
            IClientLanguageServer client,
            IObservable <Unit> initializeComplete,
            IServerWorkDoneManager serverWorkDoneManager,
            ISupportedCapabilities supportedCapabilities,
            IReadOnlyList <ILspHandlerDescriptor> descriptors
            )
        {
            if (descriptors.Count == 0)
            {
                return(Disposable.Empty); // No dynamic registrations supported by client.
            }
            var disposable = new CompositeDisposable();

            var result = initializeComplete
                         .LastOrDefaultAsync()
                         .Select(
                _ => {
                var registrations = new HashSet <Registration>();
                foreach (var descriptor in descriptors)
                {
                    if (descriptor.HasCapability && supportedCapabilities.AllowsDynamicRegistration(descriptor.CapabilityType !))
                    {
                        if (descriptor.RegistrationOptions is IWorkDoneProgressOptions wdpo)
                        {
                            wdpo.WorkDoneProgress = serverWorkDoneManager.IsSupported;
                        }

                        registrations.Add(
                            new Registration {
                            Id              = descriptor.Id.ToString(),
                            Method          = RegistrationNameAttribute.From(descriptor.RegistrationType)?.Method ?? descriptor.Method,
                            RegisterOptions = descriptor.RegistrationOptions
                        }
                            );
                    }
                }

                return(registrations.Distinct(new Registration.TextDocumentComparer()).ToArray());
            }
                )
                         .SelectMany(
                registrations => Observable.FromAsync(ct => client.RegisterCapability(new RegistrationParams {
                Registrations = registrations.ToArray()
            }, ct)),
                (a, b) => a
                )
                         .Aggregate((z, b) => z)
                         .Subscribe(
                registrations => {
                disposable.Add(
                    Disposable.Create(
                        () => {
                    client.UnregisterCapability(
                        new UnregistrationParams {
                        Unregisterations = registrations.ToArray()
                    }
                        ).ToObservable().Subscribe();
                }
                        )
                    );
            }
                );

            disposable.Add(result);
            return(disposable);
        }