public ShellNode(ShellBrowser browser, ShellNode 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); }
public void Update(bool updateFiles, bool updateFolders) { if (Browser.UpdateCondition.ContinueUpdate && (updateFiles || updateFolders) && ShellFolder != null && !disposed) { lock (Browser) { IEnumIDList fileList = null; IEnumIDList folderList = null; IntPtr pidlSubItem; int celtFetched; SHCONT fileFlag = SHCONT.NonFolders | SHCONT.IncludeHidden; SHCONT folderFlag = SHCONT.Folders | SHCONT.IncludeHidden; bool[] fileExists; fileExists = new bool[SubFiles.Count]; bool[] folderExists; folderExists = new bool[SubFolders.Count]; int index; 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 fileList) == 0) { SFGAO attribs = SFGAO.Folder; while (Browser.UpdateCondition.ContinueUpdate && fileList.Next(1, out pidlSubItem, out celtFetched) == 0 && celtFetched == 1) { ShellFolder.GetAttributesOf(1, new IntPtr[] { pidlSubItem }, ref attribs); if ((attribs & SFGAO.Folder) == 0) { if ((index = SubFiles.IndexOf(pidlSubItem)) == -1) { ShellNode newItem = new ShellNode(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 fileList) == 0) { while (Browser.UpdateCondition.ContinueUpdate && fileList.Next(1, out pidlSubItem, out celtFetched) == 0 && celtFetched == 1) { if ((index = SubFiles.IndexOf(pidlSubItem)) == -1) { add.Add(new ShellNode(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 (ShellNode oldItem in remove) { if ((newIndex = add.IndexOf(oldItem.Text)) > -1) { ShellNode 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 (ShellNode 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 folderList) == 0) { while (Browser.UpdateCondition.ContinueUpdate && folderList.Next(1, out pidlSubItem, out celtFetched) == 0 && celtFetched == 1) { if ((index = SubFolders.IndexOf(pidlSubItem)) == -1) { IntPtr shellFolderPtr; if (ShellFolder.BindToObject(pidlSubItem, IntPtr.Zero, ref ShellGuids.IShellFolder, out shellFolderPtr) == 0) { add.Add(new ShellNode(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 (ShellNode oldItem in remove) { if ((newIndex = add.IndexOf(oldItem.Text)) > -1) { ShellNode 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 (ShellNode 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 (folderList != null) { Marshal.ReleaseComObject(folderList); } if (fileList != null) { Marshal.ReleaseComObject(fileList); } #endregion } } } }