Beispiel #1
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;
            }
        }
Beispiel #2
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);
            }
        }
        // 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);
            }
        }