예제 #1
0
        /// <summary>
        /// Creates a shell library in a given local folder,
        /// using the given shell library name.
        /// </summary>
        /// <param name="libraryName">The name of this library</param>
        /// <param name="folderPath">The path to the local folder</param>
        /// <param name="overwrite">Override an existing library with the same name</param>
        public ShellLibrary(string libraryName, string folderPath, bool overwrite)
            : this()
        {
            if (string.IsNullOrEmpty(libraryName))
            {
                throw new ArgumentException(LocalizedMessages.ShellLibraryEmptyName, "libraryName");
            }

            if (!Directory.Exists(folderPath))
            {
                throw new DirectoryNotFoundException(LocalizedMessages.ShellLibraryFolderNotFound);
            }

            this.Name = libraryName;

            ShellNativeMethods.LibrarySaveOptions flags = overwrite ?
                                                          ShellNativeMethods.LibrarySaveOptions.OverrideExisting :
                                                          ShellNativeMethods.LibrarySaveOptions.FailIfThere;

            Guid guid = new Guid(ShellIIDGuid.IShellItem);

            IShellItem shellItemIn;

            ShellNativeMethods.SHCreateItemFromParsingName(folderPath, IntPtr.Zero, ref guid, out shellItemIn);

            nativeShellLibrary = (INativeShellLibrary) new ShellLibraryCoClass();
            nativeShellLibrary.Save(shellItemIn, libraryName, flags, out nativeShellItem);
        }
예제 #2
0
        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);
            }
        }
예제 #3
0
        /// <summary>
        /// Release the native and managed objects
        /// </summary>
        /// <param name="disposing">Indicates that this is being called from Dispose(), rather than the finalizer.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                _internalName        = null;
                _internalParsingName = null;
                properties           = null;
                thumbnail            = null;
                parentShellObject    = null;
            }

            if (properties != null)
            {
                properties.Dispose();
            }

            if (_internalPIDL != IntPtr.Zero)
            {
                ShellNativeMethods.ILFree(_internalPIDL);
                _internalPIDL = IntPtr.Zero;
            }

            if (nativeShellItem != null)
            {
                Marshal.ReleaseComObject(nativeShellItem);
                nativeShellItem = null;
            }

            if (NativePropertyStore != null)
            {
                Marshal.ReleaseComObject(NativePropertyStore);
                NativePropertyStore = null;
            }
        }
예제 #4
0
        internal static IntPtr PidlFromUnknown(IntPtr unknown)
        {
            IntPtr pidl;
            int    retCode = ShellNativeMethods.SHGetIDListFromObject(unknown, out pidl);

            return(CoreErrorHelper.Succeeded(retCode) ? pidl : IntPtr.Zero);
        }
예제 #5
0
        /// <summary>
        /// Start the watcher and begin receiving change notifications.
        /// <remarks>
        /// If the watcher is running, has no effect.
        /// Registration for notifications should be done before this is called.
        /// </remarks>
        /// </summary>
        public void Start()
        {
            if (Running)
            {
                return;
            }

            #region Registration
            ShellNativeMethods.SHChangeNotifyEntry entry = new ShellNativeMethods.SHChangeNotifyEntry();
            entry.recursively = _recursive;

            entry.pIdl = _shellObject.PIDL;

            _registrationId = ShellNativeMethods.SHChangeNotifyRegister(
                _listenerHandle,
                ShellNativeMethods.ShellChangeNotifyEventSource.ShellLevel | ShellNativeMethods.ShellChangeNotifyEventSource.InterruptLevel | ShellNativeMethods.ShellChangeNotifyEventSource.NewDelivery,
                _manager.RegisteredTypes,  //ShellObjectChangeTypes.AllEventsMask,
                _message,
                1,
                ref entry);

            if (_registrationId == 0)
            {
                throw new Win32Exception(LocalizedMessages.ShellObjectWatcherRegisterFailed);
            }
            #endregion

            Running = true;
        }
예제 #6
0
        /// <summary>
        /// Creates a ShellObjectCollection from an IDataObject passed during Drop operation.
        /// </summary>
        /// <param name="dataObject">An object that implements the IDataObject COM interface.</param>
        /// <returns>ShellObjectCollection created from the given IDataObject</returns>
        public static ShellObjectCollection FromDataObject(System.Runtime.InteropServices.ComTypes.IDataObject dataObject)
        {
            IShellItemArray shellItemArray;
            Guid            iid = new Guid(ShellIIDGuid.IShellItemArray);

            ShellNativeMethods.SHCreateShellItemArrayFromDataObject(dataObject, ref iid, out shellItemArray);
            return(new ShellObjectCollection(shellItemArray, true));
        }
예제 #7
0
        internal ChangeNotifyLock(Message message)
        {
            IntPtr pidl;
            IntPtr lockId = ShellNativeMethods.SHChangeNotification_Lock(
                message.WParam, (int)message.LParam, out pidl, out _event);

            try
            {
                Trace.TraceInformation("Message: {0}", (ShellObjectChangeTypes)_event);

                var notifyStruct = pidl.MarshalAs <ShellNativeMethods.ShellNotifyStruct>();

                Guid guid = new Guid(ShellIIDGuid.IShellItem2);
                if (notifyStruct.item1 != IntPtr.Zero &&
                    (((ShellObjectChangeTypes)_event) & ShellObjectChangeTypes.SystemImageUpdate) == ShellObjectChangeTypes.None)
                {
                    IShellItem2 nativeShellItem;
                    if (CoreErrorHelper.Succeeded(ShellNativeMethods.SHCreateItemFromIDList(
                                                      notifyStruct.item1, ref guid, out nativeShellItem)))
                    {
                        string name;
                        nativeShellItem.GetDisplayName(ShellNativeMethods.ShellItemDesignNameOptions.FileSystemPath,
                                                       out name);
                        ItemName = name;

                        Trace.TraceInformation("Item1: {0}", ItemName);
                    }
                }
                else
                {
                    ImageIndex = notifyStruct.item1.ToInt32();
                }

                if (notifyStruct.item2 != IntPtr.Zero)
                {
                    IShellItem2 nativeShellItem;
                    if (CoreErrorHelper.Succeeded(ShellNativeMethods.SHCreateItemFromIDList(
                                                      notifyStruct.item2, ref guid, out nativeShellItem)))
                    {
                        string name;
                        nativeShellItem.GetDisplayName(ShellNativeMethods.ShellItemDesignNameOptions.FileSystemPath,
                                                       out name);
                        ItemName2 = name;

                        Trace.TraceInformation("Item2: {0}", ItemName2);
                    }
                }
            }
            finally
            {
                if (lockId != IntPtr.Zero)
                {
                    ShellNativeMethods.SHChangeNotification_Unlock(lockId);
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Returns a known folder given its shell namespace parsing name, such as
        /// <c>::{645FF040-5081-101B-9F08-00AA002F954E}</c> for the Recycle Bin.
        /// </summary>
        /// <param name="parsingName">The parsing name (or path) for the requested known folder.</param>
        /// <returns>A known folder representing the specified name.</returns>
        /// <exception cref="System.ArgumentException">Thrown if the given parsing name is invalid.</exception>
        public static IKnownFolder FromParsingName(string parsingName)
        {
            if (parsingName == null)
            {
                throw new ArgumentNullException("parsingName");
            }

            IntPtr pidl  = IntPtr.Zero;
            IntPtr pidl2 = IntPtr.Zero;

            try
            {
                pidl = ShellHelper.PidlFromParsingName(parsingName);

                if (pidl == IntPtr.Zero)
                {
                    throw new ArgumentException(LocalizedMessages.KnownFolderParsingName, "parsingName");
                }

                // It's probably a special folder, try to get it
                IKnownFolderNative knownFolderNative = KnownFolderHelper.FromPIDL(pidl);
                if (knownFolderNative != null)
                {
                    IKnownFolder kf = KnownFolderHelper.GetKnownFolder(knownFolderNative);
                    if (kf == null)
                    {
                        throw new ArgumentException(LocalizedMessages.KnownFolderParsingName, "parsingName");
                    }
                    return(kf);
                }

                // No physical storage was found for this known folder
                // We'll try again with a different name

                // try one more time with a trailing \0
                pidl2 = ShellHelper.PidlFromParsingName(parsingName.PadRight(1, '\0'));

                if (pidl2 == IntPtr.Zero)
                {
                    throw new ArgumentException(LocalizedMessages.KnownFolderParsingName, "parsingName");
                }

                IKnownFolder kf2 = KnownFolderHelper.GetKnownFolder(KnownFolderHelper.FromPIDL(pidl));
                if (kf2 == null)
                {
                    throw new ArgumentException(LocalizedMessages.KnownFolderParsingName, "parsingName");
                }

                return(kf2);
            }
            finally
            {
                ShellNativeMethods.ILFree(pidl);
                ShellNativeMethods.ILFree(pidl2);
            }
        }
예제 #9
0
        internal static IntPtr PidlFromParsingName(string name)
        {
            IntPtr pidl;

            ShellNativeMethods.ShellFileGetAttributesOptions sfgao;
            int retCode = ShellNativeMethods.SHParseDisplayName(
                name, IntPtr.Zero, out pidl, (ShellNativeMethods.ShellFileGetAttributesOptions) 0,
                out sfgao);

            return(CoreErrorHelper.Succeeded(retCode) ? pidl : IntPtr.Zero);
        }
예제 #10
0
        private Bitmap GetBitmap(System.Windows.Size size)
        {
            IntPtr hBitmap = GetHBitmap(size);

            // return a System.Drawing.Bitmap from the hBitmap
            Bitmap returnValue = Bitmap.FromHbitmap(hBitmap);

            // delete HBitmap to avoid memory leaks
            ShellNativeMethods.DeleteObject(hBitmap);

            return(returnValue);
        }
예제 #11
0
 /// <summary>
 /// Stop the watcher and prevent further notifications from being received.
 /// <remarks>If the watcher is not running, this has no effect.</remarks>
 /// </summary>
 public void Stop()
 {
     if (!Running)
     {
         return;
     }
     if (_registrationId > 0)
     {
         ShellNativeMethods.SHChangeNotifyDeregister(_registrationId);
         _registrationId = 0;
     }
     Running = false;
 }
예제 #12
0
        // This is a work around for the STA thread bug.  This will execute the call on a non-sta thread, then return the result
        private static bool IsVirtualKnownFolder(IShellItem2 nativeShellItem2)
        {
            IntPtr pidl = IntPtr.Zero;

            try
            {
                IKnownFolderNative nativeFolder = null;
                KnownFoldersSafeNativeMethods.NativeFolderDefinition definition = new KnownFoldersSafeNativeMethods.NativeFolderDefinition();

                // We found a bug where the enumeration of shell folders was
                // not reliable when called from a STA thread - it would return
                // different results the first time vs the other times.
                //
                // This is a work around.  We call FindFolderFromIDList on a
                // worker MTA thread instead of the main STA thread.
                //
                // Ultimately, it would be a very good idea to replace the 'getting shell object' logic
                // to get a list of pidl's in 1 step, then look up their information in a 2nd, rather than
                // looking them up as we get them.  This would replace the need for the work around.
                object padlock = new object();
                lock (padlock)
                {
                    IntPtr unknown = Marshal.GetIUnknownForObject(nativeShellItem2);

                    ThreadPool.QueueUserWorkItem(obj =>
                    {
                        lock (padlock)
                        {
                            pidl = ShellHelper.PidlFromUnknown(unknown);

                            new KnownFolderManagerClass().FindFolderFromIDList(pidl, out nativeFolder);

                            if (nativeFolder != null)
                            {
                                nativeFolder.GetFolderDefinition(out definition);
                            }

                            Monitor.Pulse(padlock);
                        }
                    });

                    Monitor.Wait(padlock);
                }

                return(nativeFolder != null && definition.category == FolderCategory.Virtual);
            }
            finally
            {
                ShellNativeMethods.ILFree(pidl);
            }
        }
예제 #13
0
        /// <summary>
        /// Enumerates through contents of the ShellObjectContainer
        /// </summary>
        /// <returns>Enumerated contents</returns>
        public IEnumerator <ShellObject> GetEnumerator()
        {
            if (NativeShellFolder == null)
            {
                if (desktopFolderEnumeration == null)
                {
                    ShellNativeMethods.SHGetDesktopFolder(out desktopFolderEnumeration);
                }

                nativeShellFolder = desktopFolderEnumeration;
            }

            return(new ShellFolderItems(this));
        }
예제 #14
0
        /// <summary>
        /// Constructs a new Shell object from IDList pointer
        /// </summary>
        /// <param name="idListPtr"></param>
        /// <returns></returns>
        internal static ShellObject Create(IntPtr idListPtr)
        {
            // Throw exception if not running on Win7 or newer.
            CoreHelpers.ThrowIfNotVista();

            Guid guid = new Guid(ShellIIDGuid.IShellItem2);

            IShellItem2 nativeShellItem;
            int         retCode = ShellNativeMethods.SHCreateItemFromIDList(idListPtr, ref guid, out nativeShellItem);

            if (!CoreErrorHelper.Succeeded(retCode))
            {
                return(null);
            }
            return(ShellObjectFactory.Create(nativeShellItem));
        }
예제 #15
0
        /// <summary>
        /// Constructs a new Shell object from IDList pointer
        /// </summary>
        /// <param name="idListPtr"></param>
        /// <param name="parent"></param>
        /// <returns></returns>
        internal static ShellObject Create(IntPtr idListPtr, ShellContainer parent)
        {
            IShellItem nativeShellItem;

            int retCode = ShellNativeMethods.SHCreateShellItem(
                IntPtr.Zero,
                parent.NativeShellFolder,
                idListPtr, out nativeShellItem);

            if (!CoreErrorHelper.Succeeded(retCode))
            {
                return(null);
            }

            return(ShellObjectFactory.Create(nativeShellItem));
        }
예제 #16
0
        private BitmapSource GetBitmapSource(System.Windows.Size size)
        {
            IntPtr hBitmap = GetHBitmap(size);

            // return a System.Media.Imaging.BitmapSource
            // Use interop to create a BitmapSource from hBitmap.
            BitmapSource returnValue = Imaging.CreateBitmapSourceFromHBitmap(
                hBitmap,
                IntPtr.Zero,
                System.Windows.Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());

            // delete HBitmap to avoid memory leaks
            ShellNativeMethods.DeleteObject(hBitmap);

            return(returnValue);
        }
예제 #17
0
        /// <summary>
        /// Creates a ShellObject given a parsing name
        /// </summary>
        /// <param name="parsingName"></param>
        /// <returns>A newly constructed ShellObject object</returns>
        internal static ShellObject Create(string parsingName)
        {
            if (string.IsNullOrEmpty(parsingName))
            {
                throw new ArgumentNullException("parsingName");
            }

            // Create a native shellitem from our path
            IShellItem2 nativeShellItem;
            Guid        guid    = new Guid(ShellIIDGuid.IShellItem2);
            int         retCode = ShellNativeMethods.SHCreateItemFromParsingName(parsingName, IntPtr.Zero, ref guid, out nativeShellItem);

            if (!CoreErrorHelper.Succeeded(retCode))
            {
                throw new ShellException(LocalizedMessages.ShellObjectFactoryUnableToCreateItem, Marshal.GetExceptionForHR(retCode));
            }
            return(ShellObjectFactory.Create(nativeShellItem));
        }
예제 #18
0
 /// <summary>
 /// Returns the hash code of the object.
 /// </summary>
 /// <returns></returns>
 public override int GetHashCode()
 {
     if (!hashValue.HasValue)
     {
         uint size = ShellNativeMethods.ILGetSize(PIDL);
         if (size != 0)
         {
             byte[] pidlData = new byte[size];
             Marshal.Copy(PIDL, pidlData, 0, (int)size);
             byte[] hashData = ShellObject.hashProvider.ComputeHash(pidlData);
             hashValue = BitConverter.ToInt32(hashData, 0);
         }
         else
         {
             hashValue = 0;
         }
     }
     return(hashValue.Value);
 }
예제 #19
0
        /// <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;
            }
        }
예제 #20
0
        /// <summary>
        /// Builds the data for the CFSTR_SHELLIDLIST Drag and Clipboard data format from the
        /// ShellObjects in the collection.
        /// </summary>
        /// <returns>A memory stream containing the drag/drop data.</returns>
        public MemoryStream BuildShellIDList()
        {
            if (content.Count == 0)
            {
                throw new InvalidOperationException(LocalizedMessages.ShellObjectCollectionEmptyCollection);
            }


            MemoryStream mstream = new MemoryStream();

            try
            {
                BinaryWriter bwriter = new BinaryWriter(mstream);


                // number of IDLs to be written (shell objects + parent folder)
                uint itemCount = (uint)(content.Count + 1);

                // grab the object IDLs
                IntPtr[] idls = new IntPtr[itemCount];

                for (int index = 0; index < itemCount; index++)
                {
                    if (index == 0)
                    {
                        // Because the ShellObjects passed in may be from anywhere, the
                        // parent folder reference must be the desktop.
                        idls[index] = ((ShellObject)KnownFolders.Desktop).PIDL;
                    }
                    else
                    {
                        idls[index] = content[index - 1].PIDL;
                    }
                }

                // calculate offset array (folder IDL + item IDLs)
                uint[] offsets = new uint[itemCount + 1];
                for (int index = 0; index < itemCount; index++)
                {
                    if (index == 0)
                    {
                        // first offset equals size of CIDA header data
                        offsets[0] = (uint)(sizeof(uint) * (offsets.Length + 1));
                    }
                    else
                    {
                        offsets[index] = offsets[index - 1] + ShellNativeMethods.ILGetSize(idls[index - 1]);
                    }
                }

                // Fill out the CIDA header
                //
                //    typedef struct _IDA {
                //    UINT cidl;          // number of relative IDList
                //    UINT aoffset[1];    // [0]: folder IDList, [1]-[cidl]: item IDList
                //    } CIDA, * LPIDA;
                //
                bwriter.Write(content.Count);
                foreach (uint offset in offsets)
                {
                    bwriter.Write(offset);
                }

                // copy idls
                foreach (IntPtr idl in idls)
                {
                    byte[] data = new byte[ShellNativeMethods.ILGetSize(idl)];
                    Marshal.Copy(idl, data, 0, data.Length);
                    bwriter.Write(data, 0, data.Length);
                }
            }
            catch
            {
                mstream.Dispose();
                throw;
            }
            // return CIDA stream
            return(mstream);
        }