/// <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); }
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> /// 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; } }
internal static IntPtr PidlFromUnknown(IntPtr unknown) { IntPtr pidl; int retCode = ShellNativeMethods.SHGetIDListFromObject(unknown, out pidl); return(CoreErrorHelper.Succeeded(retCode) ? pidl : IntPtr.Zero); }
/// <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; }
/// <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)); }
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); } } }
/// <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); } }
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); }
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); }
/// <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; }
// 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); } }
/// <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)); }
/// <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)); }
/// <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)); }
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); }
/// <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)); }
/// <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); }
/// <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; } }
/// <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); }