/// <summary>
        /// Load the library using a number of options
        /// </summary>
        /// <param name="libraryName">The name of the library</param>
        /// <param name="isReadOnly">If <B>true</B>, loads the library in read-only mode.</param>
        /// <returns>A ShellLibrary Object</returns>
        public static ShellLibrary Load(string libraryName, bool isReadOnly)
        {
            CoreHelpers.ThrowIfNotWin7();

            IKnownFolder kf = KnownFolders.Libraries;
            string       librariesFolderPath = (kf != null) ? kf.Path : string.Empty;

            Guid       guid = new Guid(ShellIIDGuid.IShellItem);
            IShellItem nativeShellItem;
            string     shellItemPath = System.IO.Path.Combine(librariesFolderPath, libraryName + FileExtension);
            int        hr            = ShellNativeMethods.SHCreateItemFromParsingName(shellItemPath, IntPtr.Zero, ref guid, out nativeShellItem);

            if (!CoreErrorHelper.Succeeded(hr))
            {
                throw new ShellException(hr);
            }

            INativeShellLibrary nativeShellLibrary = (INativeShellLibrary) new ShellLibraryCoClass();
            AccessModes         flags = isReadOnly ?
                                        AccessModes.Read :
                                        AccessModes.ReadWrite;

            nativeShellLibrary.LoadLibraryFromItem(nativeShellItem, flags);

            ShellLibrary library = new ShellLibrary(nativeShellLibrary);

            try {
                library.nativeShellItem = (IShellItem2)nativeShellItem;
                library.Name            = libraryName;

                return(library);
            } catch {
                library.Dispose();
                throw;
            }
        }
        private static void ShowManageLibraryUI(ShellLibrary shellLibrary, IntPtr windowHandle, string title, string instruction, bool allowAllLocations)
        {
            int hr = 0;

            Thread staWorker = new Thread(() => {
                hr = ShellNativeMethods.SHShowManageLibraryUI(
                    shellLibrary.NativeShellItem,
                    windowHandle,
                    title,
                    instruction,
                    allowAllLocations ?
                    ShellNativeMethods.LibraryManageDialogOptions.NonIndexableLocationWarning :
                    ShellNativeMethods.LibraryManageDialogOptions.Default);
            });

            staWorker.SetApartmentState(ApartmentState.STA);
            staWorker.Start();
            staWorker.Join();

            if (!CoreErrorHelper.Succeeded(hr))
            {
                throw new ShellException(hr);
            }
        }
        /// <summary>
        /// Creates a ShellObject given a native IShellItem interface
        /// </summary>
        /// <param name="nativeShellItem"></param>
        /// <returns>A newly constructed ShellObject object</returns>
        internal static ShellObject Create(IShellItem nativeShellItem)
        {
            // Sanity check
            Debug.Assert(nativeShellItem != null, "nativeShellItem should not be null");

            // Need to make sure we're running on Vista or higher
            if (!CoreHelpers.RunningOnVista)
            {
                throw new PlatformNotSupportedException(LocalizedMessages.ShellObjectFactoryPlatformNotSupported);
            }

            // A lot of APIs need IShellItem2, so just keep a copy of it here
            IShellItem2 nativeShellItem2 = nativeShellItem as IShellItem2;

            // Get the System.ItemType property
            string itemType = ShellHelper.GetItemType(nativeShellItem2);

            if (!string.IsNullOrEmpty(itemType))
            {
                itemType = itemType.ToUpperInvariant();
            }

            // Get some IShellItem attributes
            ShellNativeMethods.ShellFileGetAttributesOptions sfgao;
            nativeShellItem2.GetAttributes(ShellNativeMethods.ShellFileGetAttributesOptions.FileSystem | ShellNativeMethods.ShellFileGetAttributesOptions.Folder, out sfgao);

            // Is this item a FileSystem item?
            bool isFileSystem = (sfgao & ShellNativeMethods.ShellFileGetAttributesOptions.FileSystem) != 0;

            // Is this item a Folder?
            bool isFolder = (sfgao & ShellNativeMethods.ShellFileGetAttributesOptions.Folder) != 0;

            // Shell Library
            ShellLibrary shellLibrary = null;

            // Create the right type of ShellObject based on the above information

            // 1. First check if this is a Shell Link
            if (itemType == ".lnk")
            {
                return(new ShellLink(nativeShellItem2));
            }
            // 2. Check if this is a container or a single item (entity)
            else if (isFolder)
            {
                // 3. If this is a folder, check for types: Shell Library, Shell Folder or Search Container
                if (itemType == ".library-ms" && (shellLibrary = ShellLibrary.FromShellItem(nativeShellItem2, true)) != null)
                {
                    return(shellLibrary);                    // we already created this above while checking for Library
                }
                else if (itemType == ".searchconnector-ms")
                {
                    return(new ShellSearchConnector(nativeShellItem2));
                }
                else if (itemType == ".search-ms")
                {
                    return(new ShellSavedSearchCollection(nativeShellItem2));
                }

                // 4. It's a ShellFolder
                if (isFileSystem)
                {
                    // 5. Is it a (File-System / Non-Virtual) Known Folder
                    if (!IsVirtualKnownFolder(nativeShellItem2))                       //needs to check if it is a known folder and not virtual
                    {
                        FileSystemKnownFolder kf = new FileSystemKnownFolder(nativeShellItem2);
                        return(kf);
                    }

                    return(new ShellFileSystemFolder(nativeShellItem2));
                }

                // 5. Is it a (Non File-System / Virtual) Known Folder
                if (IsVirtualKnownFolder(nativeShellItem2))                   //needs to check if known folder is virtual
                {
                    NonFileSystemKnownFolder kf = new NonFileSystemKnownFolder(nativeShellItem2);
                    return(kf);
                }

                return(new ShellNonFileSystemFolder(nativeShellItem2));
            }

            // 6. If this is an entity (single item), check if its filesystem or not
            if (isFileSystem)
            {
                return(new ShellFile(nativeShellItem2));
            }

            return(new ShellNonFileSystemItem(nativeShellItem2));
        }