Inheritance: IDisposable
Beispiel #1
0
 internal static extern Standard.HRESULT PropVariantClear(PROPVARIANT pvar);
Beispiel #2
0
        private static IShellLinkW CreateLinkFromJumpTask(JumpTask jumpTask, bool allowSeparators)
        {
            Debug.Assert(jumpTask != null);

            // Title is generally required.  If it's missing we need to treat this like a separator.
            // Everything else can still appear on separator elements,
            // but separators can only exist in the Tasks category.
            if (string.IsNullOrEmpty(jumpTask.Title))
            {
                if (!allowSeparators || !string.IsNullOrEmpty(jumpTask.CustomCategory))
                {
                    // Just treat this situation as an InvalidItem.
                    return null;
                }
            }

            var link = (IShellLinkW)Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid(CLSID.ShellLink)));
            try
            {
                string appPath = _FullName;
                if (!string.IsNullOrEmpty(jumpTask.ApplicationPath))
                {
                    appPath = jumpTask.ApplicationPath;
                }

                link.SetPath(appPath);

                // This is optional.  Don't set it if the app hasn't explicitly requested it.
                if (!string.IsNullOrEmpty(jumpTask.WorkingDirectory))
                {
                    // Don't verify this.  It's possible that the directory doesn't exist now, but it will later.
                    // Shell handles this fine when we try to set an improperly formatted path.
                    link.SetWorkingDirectory(jumpTask.WorkingDirectory);
                }

                if (!string.IsNullOrEmpty(jumpTask.Arguments))
                {
                    link.SetArguments(jumpTask.Arguments);
                }

                // -1 is a sentinel value indicating not to use the icon.
                if (jumpTask.IconResourceIndex != -1)
                {
                    string resourcePath = _FullName;
                    if (!string.IsNullOrEmpty(jumpTask.IconResourcePath))
                    {
                        // Shell bug (Windows 7 595770): IShellLink doesn't correctly limit icon location path to MAX_PATH.
                        // It's really too bad we have to enforce this here.  When the shortcut gets
                        // serialized it streams the full string.  On deserialization it only retrieves
                        // MAX_PATH for this field leaving junk behind for subsequent gets, leading to data corruption.
                        // Because we don't want to allow the app to do create something that we know may
                        // be corrupt we have to enforce this ourselves.  If Shell fixes this later then
                        // we need to remove this check to let them handle this as they see fit.
                        // If they fix it by supporting longer paths, then we're artificially constraining this value...
                        if (jumpTask.IconResourcePath.Length >= Win32Value.MAX_PATH)
                        {
                            // we could throw the exception here, but we're already globally catching everything.
                            return null;
                        }
                        resourcePath = jumpTask.IconResourcePath;
                    }
                    link.SetIconLocation(resourcePath, jumpTask.IconResourceIndex);
                }

                if (!string.IsNullOrEmpty(jumpTask.Description))
                {
                    link.SetDescription(jumpTask.Description);
                }

                IPropertyStore propStore = (IPropertyStore)link;
                using (var pv = new PROPVARIANT())
                { 
                    PKEY pkey = default(PKEY);

                    if (!string.IsNullOrEmpty(jumpTask.Title))
                    {
                        pv.SetValue(jumpTask.Title);
                        pkey = PKEY.Title;
                    }
                    else
                    {
                        pv.SetValue(true);
                        pkey = PKEY.AppUserModel_IsDestListSeparator;
                    }

                    propStore.SetValue(ref pkey, pv);
                }

                propStore.Commit();

                IShellLinkW retLink = link;
                link = null;
                return retLink;
            }
            catch (Exception)
            {
                // IShellLinkW::Set* methods tend to return E_FAIL when trying to set invalid data.
                // The create methods don't explicitly check for these kinds of errors.

                // If we aren't able to create the item for any reason just return null to indicate an invalid item.
                return null;
            }
            finally
            {
                Utility.SafeRelease(ref link);
            }
        }
Beispiel #3
0
        private static JumpItem GetJumpItemForShellObject(object shellObject)
        {
            var shellItem = shellObject as IShellItem2;
            var shellLink = shellObject as IShellLinkW;

            if (shellItem != null)
            {
                JumpPath path = new JumpPath
                {
                    Path = shellItem.GetDisplayName(SIGDN.DESKTOPABSOLUTEPARSING),
                };
                return path;
            }

            if (shellLink != null)
            {
                var pathBuilder = new StringBuilder((int)Win32Value.MAX_PATH);
                shellLink.GetPath(pathBuilder, pathBuilder.Capacity, null, SLGP.RAWPATH);
                var argsBuilder = new StringBuilder((int)Win32Value.INFOTIPSIZE);
                shellLink.GetArguments(argsBuilder, argsBuilder.Capacity);
                var descBuilder = new StringBuilder((int)Win32Value.INFOTIPSIZE);
                shellLink.GetDescription(descBuilder, descBuilder.Capacity);
                var iconBuilder = new StringBuilder((int)Win32Value.MAX_PATH);
                int iconIndex;
                shellLink.GetIconLocation(iconBuilder, iconBuilder.Capacity, out iconIndex);
                var dirBuilder = new StringBuilder((int)Win32Value.MAX_PATH);
                shellLink.GetWorkingDirectory(dirBuilder, dirBuilder.Capacity);

                JumpTask task = new JumpTask
                {
                    // Set ApplicationPath and IconResources, even if they're from the current application.
                    // This means that equivalent JumpTasks won't necessarily compare property-for-property.
                    ApplicationPath = pathBuilder.ToString(),
                    Arguments = argsBuilder.ToString(),
                    Description = descBuilder.ToString(),
                    IconResourceIndex = iconIndex,
                    IconResourcePath = iconBuilder.ToString(),
                    WorkingDirectory = dirBuilder.ToString(),
                };

                using (PROPVARIANT pv = new PROPVARIANT())
                {
                    var propStore = (IPropertyStore)shellLink;
                    PKEY pkeyTitle = PKEY.Title;

                    propStore.GetValue(ref pkeyTitle, pv);

                    // PKEY_Title should be an LPWSTR if it's not empty.
                    task.Title = pv.GetValue() ?? "";
                }

                return task;
            }

            // Unsupported type?
            Debug.Assert(false);
            return null;
        }
Beispiel #4
0
        /// <summary>
        /// Generate a unique string for the ShellLink that can be used for equality checks.
        /// </summary>
        private static string ShellLinkToString(IShellLinkW shellLink)
        {
            var pathBuilder = new StringBuilder((int)Win32Value.MAX_PATH);
            shellLink.GetPath(pathBuilder, pathBuilder.Capacity, null, SLGP.RAWPATH);

            string title = null;
            // Need to use the property store to get the title for the link.
            using (PROPVARIANT pv = new PROPVARIANT())
            {
                var propStore = (IPropertyStore)shellLink;
                PKEY pkeyTitle = PKEY.Title;

                propStore.GetValue(ref pkeyTitle, pv);

                // PKEY_Title should be an LPWSTR if it's not empty.
                title = pv.GetValue() ?? "";
            }

            var argsBuilder = new StringBuilder((int)Win32Value.INFOTIPSIZE);
            shellLink.GetArguments(argsBuilder, argsBuilder.Capacity);

            // Path and title should be case insensitive.
            // Shell treats arguments as case sensitive because apps can handle those differently.
            return pathBuilder.ToString().ToUpperInvariant() + title.ToUpperInvariant() + argsBuilder.ToString();
        }
Beispiel #5
0
 internal static extern HRESULT PropVariantClear(PROPVARIANT pvar);