internal ShellItem(ShellBrowser browser, ShellAPI.CSIDL specialFolder)
        {
            IntPtr pidl = IntPtr.Zero;
            ShellAPI.SHGetSpecialFolderLocation(IntPtr.Zero, specialFolder, out pidl);
            //
            IntPtr shellFolderPtr;
            this.browser = browser;
            //
            if (specialFolder == ShellAPI.CSIDL.DESKTOP)
            {
                ShellAPI.SHGetDesktopFolder(out shellFolderPtr);
                //
                this.shellFolderPtr = shellFolderPtr;
                this.shellFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(shellFolderPtr, typeof(IShellFolder));
            }
            else
            {
                this.shellFolder = GetShellFolderFromPidl(pidl, out shellFolderPtr);
                //
                this.parentItem = browser.DesktopItem;
            }
            //
            subFiles = new ShellItemCollection(this);
            subFolders = new ShellItemCollection(this);

            pidlRel = new PIDL(pidl, false);

            ShellAPI.SHFILEINFO info = new ShellAPI.SHFILEINFO();
            ShellAPI.SHGetFileInfo(pidlRel.Ptr, 0, ref info, ShellAPI.cbFileInfo,
                ShellAPI.SHGFI.PIDL | ShellAPI.SHGFI.TYPENAME | ShellAPI.SHGFI.SYSICONINDEX | ShellAPI.SHGFI.DISPLAYNAME);

            type = info.szTypeName;
            text = info.szDisplayName;
            //
            StringBuilder pathBuilder = new StringBuilder(ShellAPI.MAX_PATH);
            ShellAPI.SHGetFolderPath(
                    IntPtr.Zero, specialFolder,
                    IntPtr.Zero, ShellAPI.SHGFP.TYPE_CURRENT, pathBuilder);
            this.path = pathBuilder.ToString();
            //
            if (specialFolder == ShellAPI.CSIDL.DESKTOP)
            {
                ShellImageList.SetIconIndex(this, info.iIcon, false);
                ShellImageList.SetIconIndex(this, info.iIcon, true);
                //
                SetAttributesDesktop(this);
            }
            else
            {
                SetAttributesFolder(this);
                SetInfo(this);
            }
            sortFlag = 1;
        }
        /// <summary>
        /// This method will use the GetUIObjectOf method of IShellFolder to obtain the IDataObject of a
        /// ShellItem.
        /// </summary>
        /// <param name="items">The item for which to obtain the IDataObject</param>
        /// <returns>the IDataObject the ShellItem</returns>
        public static IntPtr GetIDataObject(ShellItem[] items)
        {
            ShellItem parent = items[0].ParentItem != null ? items[0].ParentItem : items[0];

            IntPtr[] pidls = new IntPtr[items.Length];
            for (int i = 0; i < items.Length; i++)
                pidls[i] = items[i].PIDLRel.Ptr;

            IntPtr dataObjectPtr;
            if (parent.ShellFolder.GetUIObjectOf(
                    IntPtr.Zero,
                    (uint)pidls.Length,
                    pidls,
                    ref ShellAPI.IID_IDataObject,
                    IntPtr.Zero,
                    out dataObjectPtr) == ShellAPI.S_OK)
            {
                return dataObjectPtr;
            }
            else
            {
                return IntPtr.Zero;
            }
        }
        public static DragDropEffects CanDropClipboard(ShellItem item)
        {
            IntPtr dataObject;
            ShellAPI.OleGetClipboard(out dataObject);

            IntPtr targetPtr;
            Raccoom.Win32.IDropTarget target;

            DragDropEffects retVal = DragDropEffects.None;
            if (GetIDropTarget(item, out targetPtr, out target))
            {
                #region Check Copy
                DragDropEffects effects = DragDropEffects.Copy;
                if (target.DragEnter(
                    dataObject,
                    ShellAPI.MK.CONTROL,
                    new ShellAPI.POINT(0, 0),
                    ref effects) == ShellAPI.S_OK)
                {
                    if (effects == DragDropEffects.Copy)
                        retVal |= DragDropEffects.Copy;

                    target.DragLeave();
                }
                #endregion

                #region Check Move
                effects = DragDropEffects.Move;
                if (target.DragEnter(
                    dataObject,
                    ShellAPI.MK.SHIFT,
                    new ShellAPI.POINT(0, 0),
                    ref effects) == ShellAPI.S_OK)
                {
                    if (effects == DragDropEffects.Move)
                        retVal |= DragDropEffects.Move;

                    target.DragLeave();
                }
                #endregion

                #region Check Lick
                effects = DragDropEffects.Link;
                if (target.DragEnter(
                    dataObject,
                    ShellAPI.MK.ALT,
                    new ShellAPI.POINT(0, 0),
                    ref effects) == ShellAPI.S_OK)
                {
                    if (effects == DragDropEffects.Link)
                        retVal |= DragDropEffects.Link;

                    target.DragLeave();
                }
                #endregion

                Marshal.ReleaseComObject(target);
                Marshal.Release(targetPtr);
            }

            return retVal;
        }
        internal ShellItem(ShellBrowser browser, ShellItem parentItem, IntPtr pidl, IntPtr shellFolderPtr)
        {
            this.browser = browser;

            this.parentItem = parentItem;
            this.shellFolderPtr = shellFolderPtr;
            this.shellFolder = (IShellFolder)Marshal.GetTypedObjectForIUnknown(shellFolderPtr, typeof(IShellFolder));
            subFiles = new ShellItemCollection(this);
            subFolders = new ShellItemCollection(this);

            pidlRel = new PIDL(pidl, false);

            SetText(this);
            SetPath(this);
            SetAttributesFolder(this);
            SetInfo(this);

            sortFlag = MakeSortFlag(this);
        }
        internal void RemoveItem(ShellItem item)
        {
            browser.UpdateCondition.ContinueUpdate = false;

            lock (browser)
            {
                try
                {
                    if (item.IsFolder)
                        SubFolders.Remove(item);
                    else
                        SubFiles.Remove(item);

                    Browser.OnShellItemUpdate(this, new ShellItemUpdateEventArgs(item, null, ShellItemUpdateType.Deleted));
                    ((IDisposable)item).Dispose();
                }
                catch (Exception) { }
            }
        }
        internal bool Expand(bool expandFiles, bool expandFolders, IntPtr winHandle)
        {
            if (((expandFiles && !filesExpanded) || !expandFiles) &&
                ((expandFolders && !foldersExpanded) || !expandFolders) &&
                (expandFiles || expandFolders) && ShellFolder != null && !disposed)
            {
                #region Fields

                IntPtr fileEnumPtr = IntPtr.Zero, folderEnumPtr = IntPtr.Zero;
                IEnumIDList fileEnum = null, folderEnum = null;
                IntPtr pidlSubItem;
                int celtFetched;

                ShellAPI.SHCONTF fileFlag =
                        ShellAPI.SHCONTF.NONFOLDERS |
                        ShellAPI.SHCONTF.INCLUDEHIDDEN;

                ShellAPI.SHCONTF folderFlag =
                        ShellAPI.SHCONTF.FOLDERS |
                        ShellAPI.SHCONTF.INCLUDEHIDDEN;

                #endregion

                try
                {
                    #region Add Files

                    if (expandFiles)
                    {
                        if (this.Equals(browser.DesktopItem) || (parentItem != null && parentItem.Equals(browser.DesktopItem)))
                        {
                            if (ShellFolder.EnumObjects(
                                    winHandle,
                                    fileFlag,
                                    out fileEnumPtr) == ShellAPI.S_OK)
                            {
                                fileEnum = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(fileEnumPtr, typeof(IEnumIDList));
                                ShellAPI.SFGAO attribs = ShellAPI.SFGAO.FOLDER;
                                while (fileEnum.Next(1, out pidlSubItem, out celtFetched) == ShellAPI.S_OK && celtFetched == 1)
                                {
                                    ShellFolder.GetAttributesOf(1, new IntPtr[] { pidlSubItem }, ref attribs);

                                    if ((attribs & ShellAPI.SFGAO.FOLDER) == 0)
                                    {
                                        ShellItem newItem = new ShellItem(browser, this, pidlSubItem);

                                        if (!subFolders.Contains(newItem.Text))
                                            subFiles.Add(newItem);
                                    }
                                    else
                                        Marshal.FreeCoTaskMem(pidlSubItem);
                                }

                                subFiles.Sort();
                                filesExpanded = true;
                            }
                        }
                        else
                        {
                            if (ShellFolder.EnumObjects(
                                    winHandle,
                                    fileFlag,
                                    out fileEnumPtr) == ShellAPI.S_OK)
                            {
                                fileEnum = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(fileEnumPtr, typeof(IEnumIDList));
                                while (fileEnum.Next(1, out pidlSubItem, out celtFetched) == ShellAPI.S_OK && celtFetched == 1)
                                {
                                    ShellItem newItem = new ShellItem(browser, this, pidlSubItem);
                                    subFiles.Add(newItem);
                                }

                                subFiles.Sort();
                                filesExpanded = true;
                            }
                        }
                    }

                    #endregion

                    #region Add Folders

                    if (expandFolders)
                    {
                        if (ShellFolder.EnumObjects(
                                    winHandle,
                                    folderFlag,
                                    out folderEnumPtr) == ShellAPI.S_OK)
                        {
                            folderEnum = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(folderEnumPtr, typeof(IEnumIDList));
                            while (folderEnum.Next(1, out pidlSubItem, out celtFetched) == ShellAPI.S_OK && celtFetched == 1)
                            {
                                IntPtr shellFolderPtr;
                                if (ShellFolder.BindToObject(
                                            pidlSubItem,
                                            IntPtr.Zero,
                                            ref ShellAPI.IID_IShellFolder,
                                            out shellFolderPtr) == ShellAPI.S_OK)
                                {
                                    ShellItem newItem = new ShellItem(
                                        browser,
                                        this,
                                        pidlSubItem,
                                        shellFolderPtr);
                                    subFolders.Add(newItem);
                                }
                            }

                            subFolders.Sort();
                            foldersExpanded = true;
                        }
                    }

                    #endregion
                }
                catch (Exception) { }
                finally
                {
                    #region Free

                    if (folderEnum != null)
                    {
                        Marshal.ReleaseComObject(folderEnum);
                        Marshal.Release(folderEnumPtr);
                    }

                    if (fileEnum != null)
                    {
                        Marshal.ReleaseComObject(fileEnum);
                        Marshal.Release(fileEnumPtr);
                    }

                    #endregion
                }
            }

            return ((expandFiles == filesExpanded || !expandFiles) && (expandFolders == foldersExpanded || !expandFolders));
        }
        internal void AddItem(ShellItem item)
        {
            browser.UpdateCondition.ContinueUpdate = false;
            lock (browser)
            {
                try
                {
                    if (item.IsFolder)
                        SubFolders.Add(item);
                    else
                        SubFiles.Add(item);

                    Browser.OnShellItemUpdate(this, new ShellItemUpdateEventArgs(null, item, ShellItemUpdateType.Created));
                }
                catch (Exception) { }
            }
        }
        public static string GetRealPath(ShellItem item)
        {
            if (item.Equals(item.browser.DesktopItem))
            {
                return "::{450d8fba-ad25-11d0-98a8-0800361b1103}";
            }
            else if (item.Type == item.Browser.SystemFolderName)
            {
                IntPtr strr = Marshal.AllocCoTaskMem(ShellAPI.MAX_PATH * 2 + 4);
                Marshal.WriteInt32(strr, 0, 0);
                StringBuilder buf = new StringBuilder(ShellAPI.MAX_PATH);

                if (item.ParentItem.ShellFolder.GetDisplayNameOf(
                                item.PIDLRel.Ptr,
                                ShellAPI.SHGNO.FORPARSING,
                                strr) == ShellAPI.S_OK)
                {
                    ShellAPI.StrRetToBuf(strr, item.PIDLRel.Ptr, buf, ShellAPI.MAX_PATH);
                }

                Marshal.FreeCoTaskMem(strr);

                return buf.ToString();
            }
            else
                return item.Path;
        }
 internal void Remove(ShellItem value)
 {
     items.Remove(value);
 }
        private static void SetAttributesFile(ShellItem item)
        {
            // file/folder attributes
            ShellAPI.SFGAO attribs =
                ShellAPI.SFGAO.LINK |
                ShellAPI.SFGAO.SHARE |
                ShellAPI.SFGAO.FILESYSTEM |
                ShellAPI.SFGAO.HIDDEN |
                ShellAPI.SFGAO.CANRENAME |
                ShellAPI.SFGAO.STREAM;
            item.ParentItem.ShellFolder.GetAttributesOf(
                1, new IntPtr[] { item.PIDLRel.Ptr }, ref attribs);

            item.isFolder = false;
            item.isLink = (attribs & ShellAPI.SFGAO.LINK) != 0;
            item.isShared = (attribs & ShellAPI.SFGAO.SHARE) != 0;
            item.isFileSystem = (attribs & ShellAPI.SFGAO.FILESYSTEM) != 0;
            item.isHidden = (attribs & ShellAPI.SFGAO.HIDDEN) != 0;
            item.hasSubfolder = false;
            item.isBrowsable = false;
            item.canRename = (attribs & ShellAPI.SFGAO.CANRENAME) != 0;
            item.canRead = (attribs & ShellAPI.SFGAO.STREAM) != 0;

            item.isDisk = false;
        }
 private static void SetAttributesDesktop(ShellItem item)
 {
     item.isFolder = true;
     item.isLink = false;
     item.isShared = false;
     item.isFileSystem = true;
     item.isHidden = false;
     item.hasSubfolder = true;
     item.isBrowsable = true;
     item.canRename = false;
     item.canRead = true;
 }
 private static short MakeSortFlag(ShellItem item)
 {
     if (item.IsFolder)
     {
         if (item.IsDisk)
             return 1;
         if (item.Text == item.browser.MyDocumentsName &&
             item.Type == item.Browser.SystemFolderName)
             return 2;
         else if (item.Text == item.browser.MyComputerName)
             return 3;
         else if (item.Type == item.Browser.SystemFolderName)
         {
             if (!item.IsBrowsable)
                 return 4;
             else
                 return 5;
         }
         else if (item.IsFolder && !item.IsBrowsable)
             return 6;
         else
             return 7;
     }
     else
         return 8;
 }
        internal ShellItem(ShellBrowser browser, ShellItem parentItem, IntPtr pidl)
        {
            this.browser = browser;

            this.parentItem = parentItem;

            pidlRel = new PIDL(pidl, false);

            SetText(this);
            SetPath(this);
            SetAttributesFile(this);
            SetInfo(this);

            sortFlag = MakeSortFlag(this);
        }
 public static bool GetIStream(ShellItem item, out IntPtr streamPtr, out IStream stream)
 {
     if (item.ParentItem.ShellFolder.BindToStorage(
                 item.PIDLRel.Ptr,
                 IntPtr.Zero,
                 ref ShellAPI.IID_IStream,
                 out streamPtr) == ShellAPI.S_OK)
     {
         stream = (IStream)Marshal.GetTypedObjectForIUnknown(streamPtr, typeof(IStream));
         return true;
     }
     else
     {
         stream = null;
         streamPtr = IntPtr.Zero;
         return false;
     }
 }
        public static bool GetIQueryInfo(ShellItem item, out IntPtr iQueryInfoPtr, out IQueryInfo iQueryInfo)
        {
            ShellItem parent = item.ParentItem != null ? item.ParentItem : item;

            if (parent.ShellFolder.GetUIObjectOf(
                    IntPtr.Zero,
                    1,
                    new IntPtr[] { item.PIDLRel.Ptr },
                    ref ShellAPI.IID_IQueryInfo,
                    IntPtr.Zero,
                    out iQueryInfoPtr) == ShellAPI.S_OK)
            {
                iQueryInfo =
                    (IQueryInfo)Marshal.GetTypedObjectForIUnknown(iQueryInfoPtr, typeof(IQueryInfo));

                return true;
            }
            else
            {
                iQueryInfo = null;
                iQueryInfoPtr = IntPtr.Zero;
                return false;
            }
        }
 internal int Add(ShellItem value)
 {
     return items.Add(value);
 }
 internal void Insert(int index, ShellItem value)
 {
     items.Insert(index, value);
 }
        private static void SetAttributesFolder(ShellItem item)
        {
            // file/folder attributes
            ShellAPI.SFGAO attribs =
                ShellAPI.SFGAO.SHARE |
                ShellAPI.SFGAO.FILESYSTEM |
                ShellAPI.SFGAO.HIDDEN |
                ShellAPI.SFGAO.HASSUBFOLDER |
                ShellAPI.SFGAO.BROWSABLE |
                ShellAPI.SFGAO.CANRENAME |
                ShellAPI.SFGAO.STORAGE;
            item.ParentItem.ShellFolder.GetAttributesOf(
                1, new IntPtr[] { item.PIDLRel.Ptr }, ref attribs);

            item.isFolder = true;
            item.isLink = false;
            item.isShared = (attribs & ShellAPI.SFGAO.SHARE) != 0;
            item.isFileSystem = (attribs & ShellAPI.SFGAO.FILESYSTEM) != 0;
            item.isHidden = (attribs & ShellAPI.SFGAO.HIDDEN) != 0;
            item.hasSubfolder = (attribs & ShellAPI.SFGAO.HASSUBFOLDER) != 0;
            item.isBrowsable = (attribs & ShellAPI.SFGAO.BROWSABLE) != 0;
            item.canRename = (attribs & ShellAPI.SFGAO.CANRENAME) != 0;
            item.canRead = (attribs & ShellAPI.SFGAO.STORAGE) != 0;

            item.isDisk = (item.path.Length == 3 && item.path.EndsWith(":\\"));
        }
        private static void SetInfo(ShellItem item)
        {
            PIDL pidlFull = item.PIDLFull;

            ShellAPI.SHFILEINFO info = new ShellAPI.SHFILEINFO();
            ShellAPI.SHGetFileInfo(pidlFull.Ptr, 0, ref info, ShellAPI.cbFileInfo,
                ShellAPI.SHGFI.PIDL | ShellAPI.SHGFI.TYPENAME | ShellAPI.SHGFI.SYSICONINDEX);

            pidlFull.Free();

            ShellImageList.SetIconIndex(item, info.iIcon, false);
            ShellImageList.SetIconIndex(item, info.iIcon, true);

            item.type = info.szTypeName;
        }
        private static void SetText(ShellItem item)
        {
            IntPtr strr = Marshal.AllocCoTaskMem(ShellAPI.MAX_PATH * 2 + 4);
            Marshal.WriteInt32(strr, 0, 0);
            StringBuilder buf = new StringBuilder(ShellAPI.MAX_PATH);

            if (item.ParentItem.ShellFolder.GetDisplayNameOf(
                            item.PIDLRel.Ptr,
                            ShellAPI.SHGNO.INFOLDER,
                            strr) == ShellAPI.S_OK)
            {
                ShellAPI.StrRetToBuf(strr, item.PIDLRel.Ptr, buf, ShellAPI.MAX_PATH);
                item.text = buf.ToString();
            }

            Marshal.FreeCoTaskMem(strr);
        }
        public static void UpdateShellFolders(ShellItem item)
        {
            item.UpdateShellFolder = true;

            foreach (ShellItem child in item.SubFolders)
                ShellItem.UpdateShellFolders(child);
        }
 public ShellItemEnumerator(ShellItem parent)
 {
     this.parent = parent;
     index = -1;
 }
 internal bool Contains(ShellItem value)
 {
     return (SubFolders.Contains(value) || SubFiles.Contains(value));
 }
 public ShellItemCollection(ShellItem shellItem)
 {
     this.shellItem = shellItem;
     items = new ArrayList();
 }
        internal int IndexOf(ShellItem value)
        {
            int index;
            index = SubFolders.IndexOf(value);

            if (index > -1)
                return index;

            index = SubFiles.IndexOf(value);

            if (index > -1)
                return SubFolders.Count + index;

            return -1;
        }
 public bool Contains(ShellItem value)
 {
     return items.Contains(value);
 }
        internal void Update(bool updateFiles, bool updateFolders)
        {
            if (browser.UpdateCondition.ContinueUpdate && (updateFiles || updateFolders) && ShellFolder != null && !disposed)
            {
                lock (browser)
                {
                    #region Fields

                    IntPtr fileEnumPtr = IntPtr.Zero, folderEnumPtr = IntPtr.Zero;
                    IEnumIDList fileEnum = null, folderEnum = null;
                    IntPtr pidlSubItem;
                    int celtFetched;

                    ShellAPI.SHCONTF fileFlag =
                            ShellAPI.SHCONTF.NONFOLDERS |
                            ShellAPI.SHCONTF.INCLUDEHIDDEN;

                    ShellAPI.SHCONTF folderFlag =
                            ShellAPI.SHCONTF.FOLDERS |
                            ShellAPI.SHCONTF.INCLUDEHIDDEN;

                    bool[] fileExists;
                    fileExists = new bool[subFiles.Count];

                    bool[] folderExists;
                    folderExists = new bool[subFolders.Count];

                    int index;

                    #endregion

                    try
                    {
                        #region Update Files

                        if (browser.UpdateCondition.ContinueUpdate && updateFiles)
                        {
                            ShellItemCollection add = new ShellItemCollection(this);
                            ShellItemCollection remove = new ShellItemCollection(this);

                            bool fileEnumCompleted = false;

                            #region Add Files

                            if (this.Equals(browser.DesktopItem) || parentItem.Equals(browser.DesktopItem))
                            {
                                if (ShellFolder.EnumObjects(
                                        IntPtr.Zero,
                                        fileFlag,
                                        out fileEnumPtr) == ShellAPI.S_OK)
                                {
                                    fileEnum = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(fileEnumPtr, typeof(IEnumIDList));
                                    ShellAPI.SFGAO attribs = ShellAPI.SFGAO.FOLDER;
                                    while (browser.UpdateCondition.ContinueUpdate &&
                                           fileEnum.Next(1, out pidlSubItem, out celtFetched) == ShellAPI.S_OK && celtFetched == 1)
                                    {
                                        ShellFolder.GetAttributesOf(1, new IntPtr[] { pidlSubItem }, ref attribs);

                                        if ((attribs & ShellAPI.SFGAO.FOLDER) == 0)
                                        {
                                            if ((index = subFiles.IndexOf(pidlSubItem)) == -1)
                                            {
                                                ShellItem newItem = new ShellItem(browser, this, pidlSubItem);

                                                if (!subFolders.Contains(newItem.Text))
                                                {
                                                    add.Add(newItem);
                                                }
                                            }
                                            else if (index < fileExists.Length)
                                            {
                                                fileExists[index] = true;
                                                Marshal.FreeCoTaskMem(pidlSubItem);
                                            }
                                        }
                                        else
                                            Marshal.FreeCoTaskMem(pidlSubItem);
                                    }

                                    fileEnumCompleted = true;
                                }

                            }
                            else
                            {
                                if (ShellFolder.EnumObjects(
                                        IntPtr.Zero,
                                        fileFlag,
                                        out fileEnumPtr) == ShellAPI.S_OK)
                                {
                                    fileEnum = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(fileEnumPtr, typeof(IEnumIDList));
                                    while (browser.UpdateCondition.ContinueUpdate &&
                                           fileEnum.Next(1, out pidlSubItem, out celtFetched) == ShellAPI.S_OK && celtFetched == 1)
                                    {
                                        if ((index = subFiles.IndexOf(pidlSubItem)) == -1)
                                        {
                                            add.Add(new ShellItem(browser, this, pidlSubItem));
                                        }
                                        else if (index < fileExists.Length)
                                        {
                                            fileExists[index] = true;
                                            Marshal.FreeCoTaskMem(pidlSubItem);
                                        }
                                    }

                                    fileEnumCompleted = true;
                                }
                            }

                            #endregion

                            #region Remove Files

                            for (int i = 0; fileEnumCompleted && browser.UpdateCondition.ContinueUpdate && i < fileExists.Length; i++)
                            {
                                if (!fileExists[i] && subFiles[i] != null)
                                {
                                    remove.Add(subFiles[i]);
                                }
                            }

                            #endregion

                            #region Do Events

                            if (fileEnumCompleted && browser.UpdateCondition.ContinueUpdate)
                            {
                                int newIndex;
                                foreach (ShellItem oldItem in remove)
                                {
                                    if ((newIndex = add.IndexOf(oldItem.Text)) > -1)
                                    {
                                        ShellItem newItem = add[newIndex];
                                        add.Remove(newItem);

                                        oldItem.pidlRel.Free();
                                        oldItem.pidlRel = new PIDL(newItem.pidlRel.Ptr, true);

                                        oldItem.shellFolder = newItem.shellFolder;
                                        oldItem.shellFolderPtr = newItem.shellFolderPtr;

                                        ((IDisposable)newItem).Dispose();

                                        browser.OnShellItemUpdate(this, new ShellItemUpdateEventArgs(oldItem, oldItem, ShellItemUpdateType.Updated));
                                    }
                                    else
                                    {
                                        subFiles.Remove(oldItem);
                                        browser.OnShellItemUpdate(this, new ShellItemUpdateEventArgs(oldItem, null, ShellItemUpdateType.Deleted));
                                        ((IDisposable)oldItem).Dispose();
                                    }
                                }

                                foreach (ShellItem newItem in add)
                                {
                                    subFiles.Add(newItem);
                                    browser.OnShellItemUpdate(this, new ShellItemUpdateEventArgs(null, newItem, ShellItemUpdateType.Created));
                                }

                                subFiles.Capacity = subFiles.Count;
                                subFiles.Sort();

                                filesExpanded = true;
                            }

                            #endregion
                        }

                        #endregion

                        #region Update Folders

                        if (browser.UpdateCondition.ContinueUpdate && updateFolders)
                        {
                            ShellItemCollection add = new ShellItemCollection(this);
                            ShellItemCollection remove = new ShellItemCollection(this);

                            bool folderEnumCompleted = false;

                            #region Add Folders

                            if (ShellFolder.EnumObjects(
                                        IntPtr.Zero,
                                        folderFlag,
                                        out folderEnumPtr) == ShellAPI.S_OK)
                            {
                                folderEnum = (IEnumIDList)Marshal.GetTypedObjectForIUnknown(folderEnumPtr, typeof(IEnumIDList));
                                while (browser.UpdateCondition.ContinueUpdate &&
                                       folderEnum.Next(1, out pidlSubItem, out celtFetched) == ShellAPI.S_OK && celtFetched == 1)
                                {
                                    if ((index = subFolders.IndexOf(pidlSubItem)) == -1)
                                    {
                                        IntPtr shellFolderPtr;
                                        if (ShellFolder.BindToObject(
                                                    pidlSubItem,
                                                    IntPtr.Zero,
                                                    ref ShellAPI.IID_IShellFolder,
                                                    out shellFolderPtr) == ShellAPI.S_OK)
                                        {
                                            add.Add(new ShellItem(
                                                browser,
                                                this,
                                                pidlSubItem,
                                                shellFolderPtr));
                                        }
                                    }
                                    else if (index < folderExists.Length)
                                    {
                                        folderExists[index] = true;
                                        Marshal.FreeCoTaskMem(pidlSubItem);
                                    }
                                }

                                folderEnumCompleted = true;
                            }

                            #endregion

                            #region Remove Folders

                            for (int i = 0; folderEnumCompleted && browser.UpdateCondition.ContinueUpdate && i < folderExists.Length; i++)
                            {
                                if (!folderExists[i] && subFolders[i] != null)
                                {
                                    remove.Add(subFolders[i]);
                                }
                            }

                            #endregion

                            #region Do Events

                            if (folderEnumCompleted && browser.UpdateCondition.ContinueUpdate)
                            {
                                int newIndex;
                                foreach (ShellItem oldItem in remove)
                                {
                                    if ((newIndex = add.IndexOf(oldItem.Text)) > -1)
                                    {
                                        ShellItem newItem = add[newIndex];
                                        add.Remove(newItem);

                                        oldItem.pidlRel.Free();
                                        oldItem.pidlRel = new PIDL(newItem.pidlRel, true);

                                        Marshal.ReleaseComObject(oldItem.shellFolder);
                                        Marshal.Release(oldItem.shellFolderPtr);

                                        oldItem.shellFolder = newItem.shellFolder;
                                        oldItem.shellFolderPtr = newItem.shellFolderPtr;

                                        newItem.shellFolder = null;
                                        newItem.shellFolderPtr = IntPtr.Zero;
                                        ((IDisposable)newItem).Dispose();

                                        browser.OnShellItemUpdate(this, new ShellItemUpdateEventArgs(oldItem, oldItem, ShellItemUpdateType.Updated));
                                    }
                                    else
                                    {
                                        subFolders.Remove(oldItem);
                                        browser.OnShellItemUpdate(this, new ShellItemUpdateEventArgs(oldItem, null, ShellItemUpdateType.Deleted));
                                        ((IDisposable)oldItem).Dispose();
                                    }
                                }

                                foreach (ShellItem newItem in add)
                                {
                                    subFolders.Add(newItem);

                                    browser.OnShellItemUpdate(this, new ShellItemUpdateEventArgs(null, newItem, ShellItemUpdateType.Created));
                                }

                                subFolders.Capacity = subFolders.Count;
                                subFolders.Sort();
                                foldersExpanded = true;
                            }

                            #endregion
                        }

                        #endregion
                    }
                    catch (Exception) { }
                    finally
                    {
                        #region Free

                        if (folderEnum != null)
                        {
                            Marshal.ReleaseComObject(folderEnum);
                            Marshal.Release(folderEnumPtr);
                        }

                        if (fileEnum != null)
                        {
                            Marshal.ReleaseComObject(fileEnum);

                            if (!(type == browser.SystemFolderName && string.Compare(text, "Control Panel", true) == 0))
                                Marshal.Release(fileEnumPtr);
                        }

                        #endregion
                    }
                }
            }
        }
 public int IndexOf(ShellItem value)
 {
     return items.IndexOf(value);
 }
        internal static void SetIconIndex(ShellItem item, int index, bool SelectedIcon)
        {
            bool HasOverlay = false; //true if it's an overlay
            int rVal = 0; //The returned Index

            ShellAPI.SHGFI dwflag = ShellAPI.SHGFI.SYSICONINDEX | ShellAPI.SHGFI.PIDL | ShellAPI.SHGFI.ICON;
            ShellAPI.FILE_ATTRIBUTE dwAttr = 0;
            //build Key into HashTable for this Item
            int Key = index * 256;
            if (item.IsLink)
            {
                Key = Key | 1;
                dwflag = dwflag | ShellAPI.SHGFI.LINKOVERLAY;
                HasOverlay = true;
            }
            if (item.IsShared)
            {
                Key = Key | 2;
                dwflag = dwflag | ShellAPI.SHGFI.ADDOVERLAYS;
                HasOverlay = true;
            }
            if (SelectedIcon)
            {
                Key = Key | 4;
                dwflag = dwflag | ShellAPI.SHGFI.OPENICON;
                HasOverlay = true; //not really an overlay, but handled the same
            }

            if (imageTable.ContainsKey(Key))
            {
                rVal = (int)imageTable[Key];
            }
            else if (!HasOverlay && !item.IsHidden) //for non-overlay icons, we already have
            {
                rVal = (int)System.Math.Floor((double)Key / 256); // the right index -- put in table
                imageTable[Key] = rVal;
            }
            else //don't have iconindex for an overlay, get it.
            {
                if (item.IsFileSystem & !item.IsDisk & !item.IsFolder)
                {
                    dwflag = dwflag | ShellAPI.SHGFI.USEFILEATTRIBUTES;
                    dwAttr = dwAttr | ShellAPI.FILE_ATTRIBUTE.NORMAL;
                }

                PIDL pidlFull = item.PIDLFull;

                ShellAPI.SHFILEINFO shfiSmall = new ShellAPI.SHFILEINFO();
                ShellAPI.SHGetFileInfo(pidlFull.Ptr, dwAttr, ref shfiSmall, ShellAPI.cbFileInfo, dwflag | ShellAPI.SHGFI.SMALLICON);

                ShellAPI.SHFILEINFO shfiLarge = new ShellAPI.SHFILEINFO();
                ShellAPI.SHGetFileInfo(pidlFull.Ptr, dwAttr, ref shfiLarge, ShellAPI.cbFileInfo, dwflag | ShellAPI.SHGFI.LARGEICON);

                Marshal.FreeCoTaskMem(pidlFull.Ptr);

                lock (imageTable)
                {
                    rVal = ShellAPI.ImageList_ReplaceIcon(smallImageListHandle, -1, shfiSmall.hIcon);
                    ShellAPI.ImageList_ReplaceIcon(largeImageListHandle, -1, shfiLarge.hIcon);
                }

                ShellAPI.DestroyIcon(shfiSmall.hIcon);
                ShellAPI.DestroyIcon(shfiLarge.hIcon);
                imageTable[Key] = rVal;
            }

            if (SelectedIcon)
                item.SelectedImageIndex = rVal;
            else
                item.ImageIndex = rVal;
        }
        public static bool GetIDropTarget(ShellItem item, out IntPtr dropTargetPtr, out Raccoom.Win32.IDropTarget dropTarget)
        {
            ShellItem parent = item.ParentItem != null ? item.ParentItem : item;

            if (parent.ShellFolder.GetUIObjectOf(
                    IntPtr.Zero,
                    1,
                    new IntPtr[] { item.PIDLRel.Ptr },
                    ref ShellAPI.IID_IDropTarget,
                    IntPtr.Zero,
                    out dropTargetPtr) == ShellAPI.S_OK)
            {
                dropTarget =
                    (Raccoom.Win32.IDropTarget)Marshal.GetTypedObjectForIUnknown(dropTargetPtr, typeof(Raccoom.Win32.IDropTarget));

                return true;
            }
            else
            {
                dropTarget = null;
                dropTargetPtr = IntPtr.Zero;
                return false;
            }
        }