Ejemplo n.º 1
0
        /// <summary>
        /// Returns an enumerator detailing the child items of the
        /// <see cref="ShellItem"/>.
        /// </summary>
        ///
        /// <param name="filter">
        /// A filter describing the types of child items to be included.
        /// </param>
        ///
        /// <returns>
        /// An enumerator over all child items.
        /// </returns>
        public IEnumerator <ShellItem> GetEnumerator(SHCONTF filter)
        {
            IShellFolder folder = GetIShellFolder();
            IEnumIDList  enumId = GetIEnumIDList(folder, filter);
            uint         count;
            IntPtr       pidl;
            HResult      result;

            if (enumId == null)
            {
                yield break;
            }

            result = enumId.Next(1, out pidl, out count);
            while (result == HResult.S_OK)
            {
                yield return(new ShellItem(this, pidl));

                Shell32.ILFree(pidl);
                result = enumId.Next(1, out pidl, out count);
            }

            if (result != HResult.S_FALSE)
            {
                Marshal.ThrowExceptionForHR((int)result);
            }

            yield break;
        }
Ejemplo n.º 2
0
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            using (var key = OpenKey(false))
            {
                var list = new List <ShellItem>();
                if (key != null)
                {
                    if ((options & SHCONTF.SHCONTF_FOLDERS) == SHCONTF.SHCONTF_FOLDERS)
                    {
                        foreach (var name in key.GetSubKeyNames())
                        {
                            list.Add(new RegistryKeyFolder(this, name));
                        }
                    }

                    if ((options & SHCONTF.SHCONTF_NONFOLDERS) == SHCONTF.SHCONTF_NONFOLDERS)
                    {
                        // always add the default value
                        var def = new RegistryDefaultValueItem(this);
                        list.Add(def);
                        foreach (var name in key.GetValueNames())
                        {
                            if (name.Length == 0) // default value, already added
                            {
                                continue;
                            }

                            list.Add(new RegistryValueItem(this, name));
                        }
                    }
                }
                return(list);
            }
        }
Ejemplo n.º 3
0
        /// <summary>Enumerates all children of this item. If this item is not a folder/container, this method will return an empty enumeration.</summary>
        /// <param name="filter">A filter for the types of children to enumerate.</param>
        /// <returns>An enumerated list of children matching the filter.</returns>
        public IEnumerable <ShellItem> EnumerateChildren(SHCONTF filter = SHCONTF.SHCONTF_FOLDERS | SHCONTF.SHCONTF_INCLUDEHIDDEN | SHCONTF.SHCONTF_NONFOLDERS)
        {
            if (!IsFolder)
            {
                yield break;
            }
            var folder = GetIShellFolder();
            var enumId = GetIEnumIDList(folder, filter);

            if (enumId == null)
            {
                yield break;
            }

            int     count;
            PIDL    cpidl;
            HRESULT result;

            while ((result = enumId.Next(1, out cpidl, out count)) == HRESULT.S_OK)
            {
                yield return(new ShellItem(this, cpidl));
            }
            if (result != HRESULT.S_FALSE)
            {
                Marshal.ThrowExceptionForHR((int)result);
            }
        }
Ejemplo n.º 4
0
        public static IEnumIDList GetIEnumIDList(IShellFolder folder, SHCONTF flags, out HResult navResult)
        {
            IEnumIDList result;
            var         res = folder.EnumObjects(IsCareForMessageHandle ? MessageHandle : IntPtr.Zero, flags, out result);

            navResult = res;
            return(res == HResult.S_OK ? result : null);
        }
Ejemplo n.º 5
0
        /// <summary>
        ///     <see cref="ShellFolderEnumerator" />クラスの新しいインスタンスを初期化します。
        /// </summary>
        /// <param name="parentFolder">親フォルダー。</param>
        /// <param name="options">フォルダー反復処理オプション。 </param>
        /// <remarks>
        ///     <para>
        ///         <see cref="System.IO.FileNotFoundException" />が発生する場合は、
        ///         プロジェクトのプロパティ -> ビルドの「32ビットを優先」のチェックを外す。
        ///     </para>
        /// </remarks>
        internal ShellFolderEnumerator(ShellFolder parentFolder, SHCONTF options)
        {
            Contract.Requires <ArgumentNullException>(parentFolder != null);

            this.Parent = parentFolder;

            this.enumIdList = this.Parent.ShellFolderItem.EnumObjects(options);
        }
Ejemplo n.º 6
0
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            int max = 2;

            for (int i = 0; i < max; i++)
            {
                yield return(new SimpleItem(this, i.ToString()));
            }
        }
Ejemplo n.º 7
0
 private static IEnumIDList GetIEnumIDList(IShellFolder folder, SHCONTF flags)
 {
     try
     {
         return(folder.EnumObjects(IntPtr.Zero, flags));
     }
     catch { }
     return(null);
 }
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            if (!options.HasFlag(SHCONTF.SHCONTF_NONFOLDERS))
            {
                return(Enumerable.Empty <ShellItem>());
            }

            return(_items.Values);
        }
Ejemplo n.º 9
0
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            if (!options.HasFlag(SHCONTF.SHCONTF_FOLDERS))
            {
                return(Enumerable.Empty <ShellItem>());
            }

            return(_deviceClassFolders.Values);
        }
Ejemplo n.º 10
0
        IEnumerator <ShellItem> GetFolderEnumerator(ShellItem folder)
        {
            SHCONTF filter = SHCONTF.FOLDERS;

            if (ShouldShowHidden())
            {
                filter |= SHCONTF.INCLUDEHIDDEN;
            }
            return(folder.GetEnumerator(filter));
        }
Ejemplo n.º 11
0
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            var items = ApiItem.EnumerateChildren(options);

            foreach (var item in items)
            {
                var shellItem = ShellItemFromApi(item);
                yield return(shellItem);
            }
        }
Ejemplo n.º 12
0
        private static IEnumIDList GetIEnumIdList(IShellFolder folder, SHCONTF flags)
        {
            IEnumIDList result;

            if (folder.EnumObjects(IntPtr.Zero, flags, out result) == HResult.S_OK)
            {
                return(result);
            }
            return(null);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Allows a client to determine the contents of a folder by creating an item identifier enumeration object and returning its IEnumIDList interface.
        /// Return value: error code, if any
        /// </summary>
        /// <param name="hwnd">If user input is required to perform the enumeration, this window handle should be used by the enumeration object as the parent window to take user input.</param>
        /// <param name="grfFlags">Flags indicating which items to include in the  enumeration. For a list of possible values, see the SHCONTF enum.</param>
        /// <param name="ppenumIDList">Address that receives a pointer to the IEnumIDList interface of the enumeration object created by this method.</param>
        /// <returns>
        /// If this method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.
        /// </returns>
        /// <exception cref="System.NotImplementedException"></exception>
        int IShellFolder.EnumObjects(IntPtr hwnd, SHCONTF grfFlags, out IEnumIDList ppenumIDList)
        {
            //  Create an object that will enumerate the contents of this shell folder (that implements
            //  IEnumIdList). This can be returned to the shell.
            ppenumIDList = new ShellNamespaceFolderIdListEnumerator(proxyFolder, grfFlags, 0);

            //  TODO we should also store the window handle for user interaction.

            //  We're done.
            return(WinError.S_OK);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Allows a client to determine the contents of a folder by creating an item identifier enumeration object and returning its IEnumIDList interface.
        /// Return value: error code, if any
        /// </summary>
        /// <param name="hwnd">If user input is required to perform the enumeration, this window handle should be used by the enumeration object as the parent window to take user input.</param>
        /// <param name="grfFlags">Flags indicating which items to include in the  enumeration. For a list of possible values, see the SHCONTF enum.</param>
        /// <param name="ppenumIDList">Address that receives a pointer to the IEnumIDList interface of the enumeration object created by this method.</param>
        /// <returns>
        /// If this method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.
        /// </returns>
        /// <exception cref="System.NotImplementedException"></exception>
        int IShellFolder.EnumObjects(IntPtr hwnd, SHCONTF grfFlags, out IEnumIDList ppenumIDList)
        {
            //  Create an object that will enumerate the contents of this shell folder (that implements
            //  IEnumIdList). This can be returned to the shell.
            ppenumIDList = new ShellNamespaceFolderIdListEnumerator(proxyFolder, grfFlags, 0);

            //  TODO we should also store the window handle for user interaction.

            //  We're done.
            return WinError.S_OK;
        }
Ejemplo n.º 15
0
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            yield return(new RegistryBaseKeyFolder(this, RegistryHive.ClassesRoot));

            yield return(new RegistryBaseKeyFolder(this, RegistryHive.CurrentUser));

            yield return(new RegistryBaseKeyFolder(this, RegistryHive.LocalMachine));

            yield return(new RegistryBaseKeyFolder(this, RegistryHive.Users));

            yield return(new RegistryBaseKeyFolder(this, RegistryHive.CurrentConfig));
        }
Ejemplo n.º 16
0
 public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
 {
     foreach (var item in EnumItems(Folder.Id, options.HasFlag(SHCONTF.SHCONTF_FOLDERS), options.HasFlag(SHCONTF.SHCONTF_NONFOLDERS)))
     {
         if (item.Type == AGMTools.ItemType.Folder)
         {
             yield return(new WebShellFolder(this, item));
         }
         else
         {
             yield return(new WebShellItem(this, item));
         }
     }
 }
Ejemplo n.º 17
0
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            yield return(new SimpleItem(this, "Client Principal Name: " + ShellContext.Current.ClientPrincipalName));

            yield return(new SimpleItem(this, "Client Process Id: " + ShellContext.Current.ClientProcessId));

            yield return(new SimpleItem(this, "Client Process: " + Process.GetProcessById(ShellContext.Current.ClientProcessId)?.ProcessName));

            // if we impersonate, this will be the same as the client principal name
            // otherwise it will be the identity that runs the service process
            yield return(new SimpleItem(this, "Server Windows Identity: " + WindowsIdentity.GetCurrent()?.Name));

            yield return(new SimpleItem(this, "Server Process: " + Process.GetCurrentProcess().ProcessName));
        }
Ejemplo n.º 18
0
 public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
 {
     // our sample drive root's id always Guid.Empty
     foreach (var item in WebShellFolder.EnumItems(Guid.Empty, options.HasFlag(SHCONTF.SHCONTF_FOLDERS), options.HasFlag(SHCONTF.SHCONTF_NONFOLDERS)))
     {
         if (item.Type == Api.ItemType.Folder)
         {
             yield return(new WebShellFolder(this, item));
         }
         else
         {
             yield return(new WebShellItem(this, item));
         }
     }
 }
        public ShellNamespaceFolderIdListEnumerator(IShellNamespaceFolder shellNamespaceFolder, SHCONTF grfFlags, uint index)
        {
            //  todo: The flags should be a type in the sharpshell domain, not the shell.
            //  todo the flags might change how we have to do this.
            //  Store the extension for the folder we're enuerating.
            this.shellNamespaceFolder = shellNamespaceFolder;

            this.currentIndex = index;
            this.flags = grfFlags;
            //  Map the flags.
            //  TODO: more to be done here.
            _shellNamespaceEnumerationFlags = 0;
            if (grfFlags.HasFlag(SHCONTF.SHCONTF_FOLDERS))
                _shellNamespaceEnumerationFlags |= ShellNamespaceEnumerationFlags.Folders;
            if (grfFlags.HasFlag(SHCONTF.SHCONTF_NONFOLDERS))
                _shellNamespaceEnumerationFlags |= ShellNamespaceEnumerationFlags.Items;
        }
Ejemplo n.º 20
0
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            if (options.HasFlag(SHCONTF.SHCONTF_FOLDERS))
            {
                foreach (var folder in Folder.Folders)
                {
                    yield return(new ArchiveFolderShellFolder(this, folder));
                }
            }

            if (options.HasFlag(SHCONTF.SHCONTF_NONFOLDERS))
            {
                foreach (var file in Folder.Files)
                {
                    yield return(new ArchiveFileShellItem(this, file));
                }
            }
        }
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            // add folders
            // note in this sample we only add folders up to two levels
            var maxLevels = 2;

            if (options.HasFlag(SHCONTF.SHCONTF_FOLDERS) && Level <= maxLevels)
            {
                var maxFolders = 2;
                for (var i = 0; i < maxFolders; i++)
                {
                    yield return(new SimpleFolder(this, "Virtual Folder " + Level + "." + i));
                }
            }

            // add items
            if (options.HasFlag(SHCONTF.SHCONTF_NONFOLDERS))
            {
                var maxItems = 2;
                if (ShowImages)
                {
                    maxItems *= 2;
                    var i = 0;
                    for (; i < maxItems / 2; i++)
                    {
                        yield return(new SimpleItem(this, "Virtual Item #" + i + ".txt"));
                    }

                    for (; i < maxItems; i++)
                    {
                        var imgKey = (ulong)(Level * 10 + i);
                        yield return(new SimplePngItem(this, "Virtual Image Key#" + imgKey + ".png", imgKey));
                    }
                }
                else
                {
                    for (var i = 0; i < maxItems; i++)
                    {
                        yield return(new SimpleItem(this, "Virtual Item #" + i + ".txt"));
                    }
                }
            }
        }
Ejemplo n.º 22
0
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            // shell is asking for folders, use Xml elements as folder
            if (options.HasFlag(SHCONTF.SHCONTF_FOLDERS))
            {
                foreach (var child in Element.ChildNodes.OfType <XmlElement>())
                {
                    yield return(new XmlElementShellFolder(this, child));
                }
            }

            // shell is asking for non folders (items), use Xml attributes as items
            if (options.HasFlag(SHCONTF.SHCONTF_NONFOLDERS))
            {
                foreach (var att in Element.Attributes.OfType <XmlAttribute>())
                {
                    yield return(new XmlAttributeShellItem(this, att));
                }
            }
        }
Ejemplo n.º 23
0
        public IEnumerable <PIDLIST> EnumObjects(HWND hwnd, SHCONTF flags)
        {
            IEnumIDList enumIdList;
            HRESULT     hr = Com.EnumObjects(hwnd, flags, out enumIdList);

            if (hr == HRESULT.S_FALSE)
            {
                yield break;
            }
            hr.ThrowIfFailed();
            if (enumIdList == null)
            {
                yield break;
            }
            using (var enumerator = new NativeEnumIDList(enumIdList))
                while (enumerator.MoveNext())
                {
                    yield return(enumerator.Current);
                }
        }
Ejemplo n.º 24
0
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            var xml = new XmlDocument();

            try
            {
                xml.Load(Info.FullName);
            }
            catch
            {
                yield break;
            }

            if (xml.DocumentElement == null)
            {
                yield break;
            }

            yield return(new XmlElementShellFolder(this, xml.DocumentElement));
        }
Ejemplo n.º 25
0
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            // we have no folder to show
            if (!options.HasFlag(SHCONTF.SHCONTF_NONFOLDERS))
            {
                yield break;
            }

            // show 5 virtual & physical files
            for (int i = 0; i < 5; i++)
            {
                yield return(new VirtualAndPhysicalShellItem(this, "virtual and physical item " + i));
            }

            // show 5 virtual files
            for (int i = 0; i < 5; i++)
            {
                yield return(new VirtualShellItem(this, "virtual item " + i + ".txt"));
            }
        }
        /// <summary>
        ///     Get the <see cref="IEnumIDList" />.
        /// </summary>
        /// <param name="options"></param>
        /// <returns></returns>
        internal IEnumIDList EnumObjects(SHCONTF options)
        {
            IEnumIDList result;
            var         hr = this.ShellFolderInterface.EnumObjects(
                IntPtr.Zero,
                options,
                out result);

            if (hr == COMErrorCodes.Cancelled)
            {
                var inner = Marshal.GetExceptionForHR(hr);
                throw new DirectoryNotFoundException(inner.Message, inner);
            }
            else if (HRESULT.Failed(hr))
            {
                throw ShellException.FromHRESULT(hr);
            }
            // hr == S_FALSEの場合は、子が存在しない。(result = null)
            // In the case of hr == S_FALSE, there is no child.(result = null)
            return(result);
        }
Ejemplo n.º 27
0
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            yield return(new VirtualAndPhysicalShellFolder(this, "This is a virtual folder"));

            foreach (var fi in LocalShellFolder.EnumerateFileSystemItems(Server.Info, "*"))
            {
                if (fi is DirectoryInfo di)
                {
                    if (di.Name.EqualsIgnoreCase(VirtualAndPhysicalShellFolder.PhysicalStorageName))
                    {
                        continue;
                    }

                    yield return(new LocalShellFolder(this, di));
                }
                else
                {
                    yield return(new LocalShellItem(this, (FileInfo)fi));
                }
            }

            yield return(_dropTarget);
        }
Ejemplo n.º 28
0
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            // add folders
            // only add folders up to two levels
            if (options.HasFlag(SHCONTF.SHCONTF_FOLDERS) && Level < 3)
            {
                var max = 2;
                for (int i = 0; i < max; i++)
                {
                    yield return(new SimpleFolder(this, "Virtual Folder " + Level + "." + i));
                }
            }

            // add items
            if (options.HasFlag(SHCONTF.SHCONTF_NONFOLDERS))
            {
                var max = 2;
                for (int i = 0; i < max; i++)
                {
                    yield return(new SimpleItem(this, "Virtual Item #" + i + ".txt"));
                }
            }
        }
        int IShellFolder2.EnumObjects(IntPtr hwnd, SHCONTF grfFlags, out IEnumIDList ppenumIDList)
        {
            return ((IShellFolder2)shellFolderImpl).EnumObjects(hwnd, grfFlags, out ppenumIDList);

        }
Ejemplo n.º 30
0
        protected override IEnumerable <FileSystemInfo> EnumerateFileSystemInfos(DirectoryInfo info, SHCONTF options, string searchPattern)
        {
            // don't display hidden files
            foreach (var fsi in base.EnumerateFileSystemInfos(info, options, searchPattern))
            {
                if (fsi.Attributes.HasFlag(FileAttributes.Hidden))
                {
                    continue;
                }

                yield return(fsi);
            }
        }
Ejemplo n.º 31
0
        /// <summary>
        /// Gets the children.
        /// </summary>
        /// <param name="childTypes">The child types.</param>
        /// <returns>
        /// The children.
        /// </returns>
        public IEnumerable <ShellItem> GetChildren(ChildTypes childTypes)
        {
            //  We'll return a list of children.
            var children = new List <ShellItem>();

            //  Create the enum flags from the childtypes.
            SHCONTF enumFlags = 0;

            if (childTypes.HasFlag(ChildTypes.Folders))
            {
                enumFlags |= SHCONTF.SHCONTF_FOLDERS;
            }
            if (childTypes.HasFlag(ChildTypes.Files))
            {
                enumFlags |= SHCONTF.SHCONTF_NONFOLDERS;
            }
            if (childTypes.HasFlag(ChildTypes.Hidden))
            {
                enumFlags |= SHCONTF.SHCONTF_INCLUDEHIDDEN;
            }

            try
            {
                //  Create an enumerator for the children.
                IEnumIDList pEnum;
                var         result = ShellFolderInterface.EnumObjects(IntPtr.Zero, enumFlags, out pEnum);

                //  Validate the result.
                if (result != 0)
                {
                    //  Throw the failure as an exception.
                    Marshal.ThrowExceptionForHR((int)result);
                }

                // TODO: This logic should go in the pidl manager.

                //  Enumerate the children, ten at a time.
                const int batchSize = 10;
                var       pidlArray = Marshal.AllocCoTaskMem(IntPtr.Size * 10);
                uint      itemsFetched;
                result = WinError.S_OK;
                do
                {
                    result = pEnum.Next(batchSize, pidlArray, out itemsFetched);

                    //  Get each pidl.
                    var pidls = new IntPtr[itemsFetched];
                    Marshal.Copy(pidlArray, pidls, 0, (int)itemsFetched);
                    foreach (var childPidl in pidls)
                    {
                        //  Create a new shell folder.
                        var childShellFolder = new ShellItem();

                        //  Initialize it.
                        try
                        {
                            childShellFolder.Initialise(childPidl, this);
                        }
                        catch (Exception exception)
                        {
                            throw new InvalidOperationException("Failed to initialise child.", exception);
                        }

                        //  Add the child.
                        children.Add(childShellFolder);

                        //  Free the PIDL, reset the result.
                        Marshal.FreeCoTaskMem(childPidl);
                    }
                } while (result == WinError.S_OK);

                Marshal.FreeCoTaskMem(pidlArray);

                //  Release the enumerator.
                if (Marshal.IsComObject(pEnum))
                {
                    Marshal.ReleaseComObject(pEnum);
                }
            }
            catch (Exception exception)
            {
                throw new InvalidOperationException("Failed to enumerate children.", exception);
            }

            //  Sort the children.
            var sortedChildren = children.Where(c => c.IsFolder).ToList();

            sortedChildren.AddRange(children.Where(c => !c.IsFolder));

            //  Return the children.
            return(sortedChildren);
        }
Ejemplo n.º 32
0
        public override IEnumerable <ShellItem> EnumItems(SHCONTF options)
        {
            yield return(Hello);

            yield return(RootPhysical);
        }
Ejemplo n.º 33
0
        //public static int CreateViewObject(IShellFolder2 folder, IntPtr Handle, ref Guid shellViewGuid, out IntPtr iShellViewPtr)
        //{
        //    folder.CreateViewObject
        //}

        public static IEnumerable <ShellItem> GetChildren(this ShellItem parent, ChildTypes childTypes, bool lThrow = true)
        {
            //  We'll return a list of children.
            var children = new List <ShellItem>();

            //  Create the enum flags from the childtypes.
            SHCONTF enumFlags = 0;

            if (childTypes.HasFlag(ChildTypes.Folders))
            {
                enumFlags |= SHCONTF.SHCONTF_FOLDERS;
            }
            if (childTypes.HasFlag(ChildTypes.Files))
            {
                enumFlags |= SHCONTF.SHCONTF_NONFOLDERS;

                //enumFlags |= SHCONTF.SHCONTF_NAVIGATION_ENUM
                //    | SHCONTF.SHCONTF_FASTITEMS // The calling application is looking for resources that can be enumerated quickly.
                //    | SHCONTF.SHCONTF_FLATLIST; // Enumerate items as a simple list even if the folder itself is not structured in that way
            }
            if (childTypes.HasFlag(ChildTypes.Hidden))
            {
                enumFlags |= SHCONTF.SHCONTF_INCLUDEHIDDEN;
            }
            //| SHCONTF.SHCONTF_INCLUDESUPERHIDDEN;

            try
            {
                //  Create an enumerator for the children.
                IEnumIDList pEnum;
                var         result = parent.ShellFolderInterface.EnumObjects(IntPtr.Zero, enumFlags, out pEnum);

                //  Validate the result.
                if (result != 0)
                {
                    if (!lThrow)
                    {
                        return(Enumerable.Empty <ShellItem>());
                    }

                    //  Throw the failure as an exception.
                    Marshal.ThrowExceptionForHR((int)result);
                }

                // TODO: This logic should go in the pidl manager.

                //  Enumerate the children, ten at a time.
                const int batchSize = 10;
                var       pidlArray = Marshal.AllocCoTaskMem(IntPtr.Size * 10);
                uint      itemsFetched;
                result = WinError.S_OK;
                do
                {
                    result = pEnum.Next(batchSize, pidlArray, out itemsFetched);

                    //  Get each pidl.
                    var pidls = new IntPtr[itemsFetched];
                    Marshal.Copy(pidlArray, pidls, 0, (int)itemsFetched);
                    foreach (var childPidl in pidls)
                    {
                        //  Create a new shell folder.
                        var childShellFolder = new ShellItem();

                        //  Initialize it.
                        try
                        {
                            childShellFolder.Initialise(childPidl, parent);
                        }
                        catch (Exception exception)
                        {
                            throw new InvalidOperationException("Failed to initialise child.", exception);
                        }

                        //  Add the child.
                        children.Add(childShellFolder);

                        //  Free the PIDL, reset the result.
                        Marshal.FreeCoTaskMem(childPidl);
                    }
                } while (result == WinError.S_OK);

                Marshal.FreeCoTaskMem(pidlArray);

                //  Release the enumerator.
                if (Marshal.IsComObject(pEnum))
                {
                    Marshal.ReleaseComObject(pEnum);
                }
            }
            catch (Exception exception)
            {
                throw new InvalidOperationException("Failed to enumerate children.", exception);
            }

            //  Sort the children.
            var sortedChildren = children.Where(c => c.IsFolder).ToList();

            sortedChildren.AddRange(children.Where(c => !c.IsFolder));

            //  Return the children.
            return(sortedChildren);
        }
 /// <summary>
 /// Allows a client to determine the contents of a folder by creating an item identifier enumeration object and returning its IEnumIDList interface.
 /// Return value: error code, if any
 /// </summary>
 /// <param name="hwnd">If user input is required to perform the enumeration, this window handle should be used by the enumeration object as the parent window to take user input.</param>
 /// <param name="grfFlags">Flags indicating which items to include in the  enumeration. For a list of possible values, see the SHCONTF enum.</param>
 /// <param name="ppenumIDList">Address that receives a pointer to the IEnumIDList interface of the enumeration object created by this method.</param>
 /// <returns>
 /// If this method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.
 /// </returns>
 /// <exception cref="System.NotImplementedException"></exception>
 int IShellFolder.EnumObjects(IntPtr hwnd, SHCONTF grfFlags, out IEnumIDList ppenumIDList)
 {
     //  Use the ShellFolderImpl to handle the details.
     return ((IShellFolder)shellFolderImpl).EnumObjects(hwnd, grfFlags, out ppenumIDList);
 }