/animeplugin3/MyAnimePlugin3/ShellItem.cs
C# | 2334 lines | 2317 code | 7 blank | 10 comment | 90 complexity | 9b807895a5af4736537348782ed636b8 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*
- * This class is converted VB.Net from the CScItem
- * from http://www.codeproject.com/KB/cpp/VbNetExpTree.aspx
- */
-
- using System.IO;
- using System.Runtime.InteropServices;
- using System.Text;
- using System;
- using System.Collections;
- using System.Windows.Forms;
- using System.Diagnostics;
- using System.Management;
-
- public class ShellItem : IDisposable, IComparable
- {
-
- #region " Shared Private Fields"
- //This class has occasion to refer to the TypeName as reported by
- // ShellDll.SHGetFileInfo. It needs to compare this to the string
- // (in English) "System Folder"
- //on non-English systems, we do not know, in the general case,
- // what the equivalent string is to compare against
- //The following variable is set by Sub New() to the string that
- // corresponds to "System Folder" on the current machine
- // Sub New() depends on the existance of My Computer(ShellDll.CSIDL.DRIVES),
- // to determine what the equivalent string is
- private static string m_strSystemFolder;
-
- //My Computer is also commonly used (though not internally),
- // so save & expose its name on the current machine
- private static string m_strMyComputer;
-
- //To get My Documents sorted first, we need to know the Locale
- //specific name of that folder.
- private static string m_strMyDocuments;
-
- // The DesktopBase is set up via Sub New() (one time only) and
- // disposed of only when DesktopBase is finally disposed of
- private static ShellItem DesktopBase;
-
- //We can avoid an extra ShellDll.SHGetFileInfo call once this is set up
- private static int OpenFolderIconIndex = -1;
-
- // It is also useful to know if the OS is XP or above.
- // Set up in Sub New() to avoid multiple calls to find this info
- private static bool XPorAbove;
- // Likewise if OS is Win2K or Above
- private static bool Win2KOrAbove;
-
- // DragDrop, possibly among others, needs to know the Path of
- // the DeskTopDirectory in addition to the Desktop itself
- // Also need the actual ShellItem for the DeskTopDirectory, so get it
- private static ShellItem m_DeskTopDirectory;
-
-
- #endregion
-
- #region " Instance Private Fields"
- //m_Folder and m_Pidl must be released/freed at Dispose time
- private ShellDll.IShellFolder m_Folder;
- //if item is a folder, contains the Folder interface for this instance
- private IntPtr m_Pidl;
- //The Absolute PIDL for this item (not retained for files)
- private string m_DisplayName = "";
- private string m_Path;
- private string m_TypeName;
- private ShellItem m_Parent;
- //= Nothing
- private int m_IconIndexNormal;
- //index into the System Image list for Normal icon
- private int m_IconIndexOpen;
- //index into the SystemImage list for Open icon
- private bool m_IsBrowsable;
- private bool m_IsFileSystem;
- private bool m_IsFolder;
- private bool m_HasSubFolders;
- private bool m_IsLink;
- private bool m_IsDisk;
- private bool m_IsShared;
- private bool m_IsHidden;
- private bool m_IsNetWorkDrive;
- //= False
- private bool m_IsRemovable;
- //= False
- private bool m_IsReadOnly;
- //= False
- //Properties of interest to Drag Operations
- private bool m_CanMove;
- //= False
- private bool m_CanCopy;
- //= False
- private bool m_CanDelete;
- //= False
- private bool m_CanLink;
- //= False
- private bool m_IsDropTarget;
- //= False
- private ShellDll.SFGAO m_Attributes;
- //the original, returned from GetAttributesOf
-
- private int m_SortFlag;
- //= 0 'Used in comparisons
-
- private ArrayList m_Directories;
-
- //The following elements are only filled in on demand
- private bool m_XtrInfo;
- //= False
- private DateTime m_LastWriteTime;
- private DateTime m_CreationTime;
- private DateTime m_LastAccessTime;
- private long m_Length;
-
- //Indicates whether DisplayName, TypeName, SortFlag have been set up
- private bool m_HasDispType;
- //= False
-
- //Indicates whether IsReadOnly has been set up
- private bool m_IsReadOnlySetup;
- //= False
-
- //Holds a byte() representation of m_PIDL -- filled when needed
- private cPidl m_cPidl;
-
- //Flags for Dispose state
- private bool m_Disposed;
-
- #endregion
-
- #region " Destructor"
- /// <summary>
- /// Summary of Dispose.
- /// </summary>
- ///
- public void Dispose()
- {
- Dispose(true);
- // Take yourself off of the finalization queue
- // to prevent finalization code for this object
- // from executing a second time.
- GC.SuppressFinalize(this);
- }
- /// <summary>
- /// Deallocates CoTaskMem contianing m_Pidl and removes reference to m_Folder
- /// </summary>
- /// <param name="disposing"></param>
- ///
- protected virtual void Dispose(bool disposing)
- {
- // Allow your Dispose method to be called multiple times,
- // but throw an exception if the object has been disposed.
- // Whenever you do something with this class,
- // check to see if it has been disposed.
- if (!(m_Disposed)) {
- // If disposing equals true, dispose all managed
- // and unmanaged resources.
- m_Disposed = true;
- if ((disposing)) {
- }
- // Release unmanaged resources. If disposing is false,
- // only the following code is executed.
- if ((m_Folder != null)) {
- Marshal.ReleaseComObject(m_Folder);
- }
- if (!m_Pidl.Equals(IntPtr.Zero)) {
- Marshal.FreeCoTaskMem(m_Pidl);
- }
- }
- else {
- throw new Exception("ShellItem Disposed more than once");
- }
- }
-
- // This Finalize method will run only if the
- // Dispose method does not get called.
- // By default, methods are NotOverridable.
- // This prevents a derived class from overriding this method.
- /// <summary>
- /// Summary of Finalize.
- /// </summary>
- ///
- ~ShellItem()
- {
- // Do not re-create Dispose clean-up code here.
- // Calling Dispose(false) is optimal in terms of
- // readability and maintainability.
- Dispose(false);
- }
-
- #endregion
-
- #region " Constructors"
-
- #region " Private Sub New(ByVal folder As ShellDll.IShellFolder, ByVal pidl As IntPtr, ByVal parent As ShellItem)"
- /// <summary>
- /// Private Constructor, creates new ShellItem from the item's parent folder and
- /// the item's PIDL relative to that folder.</summary>
- /// <param name="folder">the folder interface of the parent</param>
- /// <param name="pidl">the Relative PIDL of this item</param>
- /// <param name="parent">the CShitem of the parent</param>
- ///
- private ShellItem(ShellDll.IShellFolder folder, IntPtr pidl, ShellItem parent)
- {
- if ((DesktopBase == null)) {
- //This initializes the Desktop folder
- DesktopBase = new ShellItem();
- }
- m_Parent = parent;
- m_Pidl = concatPidls(parent.PIDL, pidl);
-
- //Get some attributes
- SetUpAttributes(folder, pidl);
-
- //Set unfetched value for IconIndex....
- m_IconIndexNormal = -1;
- m_IconIndexOpen = -1;
- //finally, set up my Folder
- if (m_IsFolder) {
- int HR = 0;
- HR = folder.BindToObject(pidl, IntPtr.Zero, ref ShellDll.IID_IShellFolder, ref m_Folder);
- if (HR != ShellDll.NOERROR) {
- Marshal.ThrowExceptionForHR(HR);
- }
- }
- }
- #endregion
-
- #region " Sub New()"
- /// <summary>
- /// Private Constructor. Creates ShellItem of the Desktop
- /// </summary>
- ///
- private ShellItem()
- {
- //only used when desktopfolder has not been intialized
- if ((DesktopBase != null)) {
- throw new Exception("Attempt to initialize ShellItem for second time");
- }
-
- int HR = 0;
- //firstly determine what the local machine calls a "System Folder" and "My Computer"
- IntPtr tmpPidl = default(IntPtr);
- HR = ShellDll.SHGetSpecialFolderLocation(0, (int)ShellDll.CSIDL.DRIVES, ref tmpPidl);
- ShellDll.SHFILEINFO shfi = new ShellDll.SHFILEINFO();
- int dwflag = (int)(ShellDll.SHGFI.DISPLAYNAME | ShellDll.SHGFI.TYPENAME | ShellDll.SHGFI.PIDL);
- int dwAttr = 0;
- ShellDll.SHGetFileInfo(tmpPidl, dwAttr, ref shfi, (int)ShellDll.cbFileInfo, dwflag);
- m_strSystemFolder = shfi.szTypeName;
- m_strMyComputer = shfi.szDisplayName;
- Marshal.FreeCoTaskMem(tmpPidl);
- //set OS version info
- XPorAbove = ShellDll.IsXpOrAbove();
- Win2KOrAbove = ShellDll.Is2KOrAbove();
-
- //With That done, now set up Desktop ShellItem
- m_Path = "::{" + ShellDll.DesktopGUID.ToString() + "}";
- m_IsFolder = true;
- m_HasSubFolders = true;
- m_IsBrowsable = false;
- HR = ShellDll.SHGetDesktopFolder(ref m_Folder);
- m_Pidl = ShellDll.GetSpecialFolderLocation(IntPtr.Zero, (int)ShellDll.CSIDL.DESKTOP);
- dwflag = (int)(ShellDll.SHGFI.DISPLAYNAME | ShellDll.SHGFI.TYPENAME | ShellDll.SHGFI.SYSICONINDEX | ShellDll.SHGFI.PIDL);
- dwAttr = 0;
- IntPtr H = ShellDll.SHGetFileInfo(m_Pidl, dwAttr, ref shfi, (int)ShellDll.cbFileInfo, dwflag);
- m_DisplayName = shfi.szDisplayName;
- m_TypeName = strSystemFolder;
- //not returned correctly by ShellDll.SHGetFileInfo
- m_IconIndexNormal = shfi.iIcon;
- m_IconIndexOpen = shfi.iIcon;
- m_HasDispType = true;
- m_IsDropTarget = true;
- m_IsReadOnly = false;
- m_IsReadOnlySetup = true;
-
- //also get local name for "My Documents"
- int pchEaten = 0;
- tmpPidl = IntPtr.Zero;
- int tmp = 0;
- HR = m_Folder.ParseDisplayName(0, IntPtr.Zero, "::{450d8fba-ad25-11d0-98a8-0800361b1103}", ref pchEaten, ref tmpPidl, ref tmp);
- shfi = new ShellDll.SHFILEINFO();
- dwflag = (int)(ShellDll.SHGFI.DISPLAYNAME | ShellDll.SHGFI.TYPENAME | ShellDll.SHGFI.PIDL);
- dwAttr = 0;
- ShellDll.SHGetFileInfo(tmpPidl, dwAttr, ref shfi, ShellDll.cbFileInfo, dwflag);
- m_strMyDocuments = shfi.szDisplayName;
- Marshal.FreeCoTaskMem(tmpPidl);
- //this must be done after getting "My Documents" string
- m_SortFlag = ComputeSortFlag();
- //Set DesktopBase
- DesktopBase = this;
- // Lastly, get the Path and ShellItem of the DesktopDirectory -- useful for DragDrop
- m_DeskTopDirectory = new ShellItem(ShellDll.CSIDL.DESKTOPDIRECTORY);
- }
- #endregion
-
- #region " New(ByVal ID As ShellDll.CSIDL)"
- /// <summary>Create instance based on a non-desktop ShellDll.CSIDL.
- /// Will create based on any ShellDll.CSIDL Except the DeskTop ShellDll.CSIDL</summary>
- /// <param name="ID">Value from ShellDll.CSIDL enumeration denoting the folder to create this ShellItem of.</param>
- ///
- public ShellItem(ShellDll.CSIDL ID)
- {
- if ((DesktopBase == null)) {
- //This initializes the Desktop folder
- DesktopBase = new ShellItem();
- }
- int HR = 0;
- if (ID == ShellDll.CSIDL.MYDOCUMENTS) {
- int pchEaten = 0;
- int tmp = 0;
- HR = DesktopBase.m_Folder.ParseDisplayName(0, IntPtr.Zero, "::{450d8fba-ad25-11d0-98a8-0800361b1103}", ref pchEaten, ref m_Pidl, ref tmp);
- }
- else {
- HR = ShellDll.SHGetSpecialFolderLocation(0, (int)ID, ref m_Pidl);
- }
- if (HR == ShellDll.NOERROR) {
- ShellDll.IShellFolder pParent = default(ShellDll.IShellFolder);
- IntPtr relPidl = IntPtr.Zero;
-
- pParent = GetParentOf(m_Pidl, ref relPidl);
- //Get the Attributes
- SetUpAttributes(pParent, relPidl);
- //Set unfetched value for IconIndex....
- m_IconIndexNormal = -1;
- m_IconIndexOpen = -1;
- //finally, set up my Folder
- if (m_IsFolder) {
- HR = pParent.BindToObject(relPidl, IntPtr.Zero, ref ShellDll.IID_IShellFolder, ref m_Folder);
- if (HR != ShellDll.NOERROR) {
- Marshal.ThrowExceptionForHR(HR);
- }
- }
- Marshal.ReleaseComObject(pParent);
- //if PidlCount(m_Pidl) = 1 then relPidl is same as m_Pidl, don't release
- if (PidlCount(m_Pidl) > 1) Marshal.FreeCoTaskMem(relPidl);
- }
- else {
- Marshal.ThrowExceptionForHR(HR);
- }
- }
- #endregion
-
- #region " New(ByVal path As String)"
- /// <summary>Create a new ShellItem based on a Path Must be a valid FileSystem Path</summary>
- /// <param name="path"></param>
- ///
- public ShellItem(string path)
- {
- if ((DesktopBase == null)) {
- //This initializes the Desktop folder
- DesktopBase = new ShellItem();
- }
- //Removal of following code allows Path(GUID) of Special FOlders to serve
- // as a valid Path for ShellItem creation (part of Calum's refresh code needs this
- //If Not Directory.Exists(path) AndAlso Not File.Exists(path) Then
- // Throw New Exception("ShellItem -- Invalid Path specified")
- //End If
- int HR = 0;
- int tmp1 = 0, tmp2 = 0;
- HR = DesktopBase.m_Folder.ParseDisplayName(0, IntPtr.Zero, path, ref tmp1, ref m_Pidl, ref tmp2);
- if (!(HR == ShellDll.NOERROR)) Marshal.ThrowExceptionForHR(HR);
- ShellDll.IShellFolder pParent = default(ShellDll.IShellFolder);
- IntPtr relPidl = IntPtr.Zero;
-
- pParent = GetParentOf(m_Pidl, ref relPidl);
-
- //Get the Attributes
- SetUpAttributes(pParent, relPidl);
- //Set unfetched value for IconIndex....
- m_IconIndexNormal = -1;
- m_IconIndexOpen = -1;
- //finally, set up my Folder
- if (m_IsFolder) {
- HR = pParent.BindToObject(relPidl, IntPtr.Zero, ref ShellDll.IID_IShellFolder, ref m_Folder);
- if (HR != ShellDll.NOERROR) {
- Marshal.ThrowExceptionForHR(HR);
- }
- }
- Marshal.ReleaseComObject(pParent);
- //if PidlCount(m_Pidl) = 1 then relPidl is same as m_Pidl, don't release
- if (PidlCount(m_Pidl) > 1) {
- Marshal.FreeCoTaskMem(relPidl);
- }
- }
- #endregion
-
- #region " ShellItem(byte[] FoldBytes, byte[] ItemBytes)"
- ///<Summary>Given a Byte() containing the Pidl of the parent
- /// folder and another Byte() containing the Pidl of the Item,
- /// relative to the Folder, Create a ShellItem for the Item.
- /// This is of primary use in dealing with "Shell IDList Array"
- /// formatted info passed in a Drag Operation
- /// </Summary>
- public ShellItem(byte[] FoldBytes, byte[] ItemBytes)
- {
- if ((DesktopBase == null)) {
- //This initializes the Desktop folder
- DesktopBase = new ShellItem();
- }
- ShellDll.IShellFolder pParent = MakeFolderFromBytes(FoldBytes);
- IntPtr ipParent = cPidl.BytesToPidl(FoldBytes);
- IntPtr ipItem = cPidl.BytesToPidl(ItemBytes);
- if ((pParent == null)) {
- //m_PIDL will = IntPtr.Zero for really bad CShitem
- goto XIT;
- }
- if (ipParent.Equals(IntPtr.Zero) | ipItem.Equals(IntPtr.Zero)) {
- goto XIT;
- }
- // Now process just like sub new(folder,pidl,parent) version
- m_Pidl = concatPidls(ipParent, ipItem);
-
- //Get some attributes
- SetUpAttributes(pParent, ipItem);
-
- //Set unfetched value for IconIndex....
- m_IconIndexNormal = -1;
- m_IconIndexOpen = -1;
- //finally, set up my Folder
- if (m_IsFolder) {
- int HR = 0;
- HR = pParent.BindToObject(ipItem, IntPtr.Zero, ref ShellDll.IID_IShellFolder, ref m_Folder);
- #if Debug
- if (HR != NOERROR) {
- Marshal.ThrowExceptionForHR(HR);
- }
- #endif
- }
- XIT:
- //On any kind of exit, free the allocated memory
- #if Debug
- if (m_Pidl.Equals(IntPtr.Zero)) {
- Debug.WriteLine("CShItem.New(FoldBytes,ItemBytes) Failed");
- }
- else {
- Debug.WriteLine("CShItem.New(FoldBytes,ItemBytes) Created " + this.Path);
- }
- #endif
- if (!ipParent.Equals(IntPtr.Zero)) {
- Marshal.FreeCoTaskMem(ipParent);
- }
- if (!ipItem.Equals(IntPtr.Zero)) {
- Marshal.FreeCoTaskMem(ipItem);
- }
- }
-
- #endregion
-
- #region " Utility functions used in Constructors"
-
- #region " IsValidPidl"
- ///<Summary>It is impossible to validate a PIDL completely since its contents
- /// are arbitrarily defined by the creating Shell Namespace. However, it
- /// is possible to validate the structure of a PIDL.</Summary>
- public static bool IsValidPidl(byte[] b)
- {
- bool IsValidPidl = false;
- //assume failure
- int bMax = b.Length - 1;
- //max value that index can have
- if (bMax < 1) return IsValidPidl;
-
- //min Size is 2 bytes
- int cb = b[0] + (b[1] * 256);
- int indx = 0;
- while (cb > 0) {
- if ((indx + cb + 1) > bMax) return IsValidPidl;
-
- //an error
- indx += cb;
- cb = b[indx] + (b[indx + 1] * 256);
- }
- // on fall thru, it is ok as far as we can check
- return true;
- }
- #endregion
-
- #region " MakeFolderFromBytes"
- public static ShellDll.IShellFolder MakeFolderFromBytes(byte[] b)
- {
- ShellDll.IShellFolder functionReturnValue = default(ShellDll.IShellFolder);
- functionReturnValue = null;
- //get rid of VS2005 warning
- if (!IsValidPidl(b)) return null;
- if (b.Length == 2 && ((b[0] == 0) & (b[1] == 0))) {
- //this is the desktop
- return DesktopBase.Folder;
- }
- else if (b.Length == 0) {
- //Also indicates the desktop
- return DesktopBase.Folder;
- }
- else {
- IntPtr ptr = Marshal.AllocCoTaskMem(b.Length);
- if (ptr.Equals(IntPtr.Zero)) return null;
- Marshal.Copy(b, 0, ptr, b.Length);
- //the next statement assigns a IshellFolder object to the function return, or has an error
- int hr = DesktopBase.Folder.BindToObject(ptr, IntPtr.Zero, ref ShellDll.IID_IShellFolder, ref functionReturnValue);
- if (hr != 0) functionReturnValue = null;
- Marshal.FreeCoTaskMem(ptr);
- }
- return functionReturnValue;
- }
- #endregion
-
- #region " GetParentOf"
-
- ///<Summary>Returns both the ShellDll.IShellFolder interface of the parent folder
- /// and the relative pidl of the input PIDL</Summary>
- ///<remarks>Several internal functions need this information and do not have
- /// it readily available. GetParentOf serves those functions</remarks>
- private static ShellDll.IShellFolder GetParentOf(IntPtr pidl, ref IntPtr relPidl)
- {
- ShellDll.IShellFolder functionReturnValue = default(ShellDll.IShellFolder);
- functionReturnValue = null;
- //avoid VB2005 warning
- int HR = 0;
- int itemCnt = PidlCount(pidl);
- if (itemCnt == 1) {
- //parent is desktop
- HR = ShellDll.SHGetDesktopFolder(ref functionReturnValue);
- relPidl = pidl;
- }
- else {
- IntPtr tmpPidl = default(IntPtr);
- tmpPidl = TrimPidl(pidl, ref relPidl);
- HR = DesktopBase.m_Folder.BindToObject(tmpPidl, IntPtr.Zero, ref ShellDll.IID_IShellFolder, ref functionReturnValue);
- Marshal.FreeCoTaskMem(tmpPidl);
- }
- if (!(HR == ShellDll.NOERROR)) Marshal.ThrowExceptionForHR(HR);
- return functionReturnValue;
- }
- #endregion
-
- #region " SetUpAttributes"
- /// <summary>Get the base attributes of the folder/file that this ShellItem represents</summary>
- /// <param name="folder">Parent Folder of this Item</param>
- /// <param name="pidl">Relative Pidl of this Item.</param>
- ///
- private void SetUpAttributes(ShellDll.IShellFolder folder, IntPtr pidl)
- {
- ShellDll.SFGAO attrFlag = default(ShellDll.SFGAO);
- attrFlag = ShellDll.SFGAO.BROWSABLE;
- attrFlag = attrFlag | ShellDll.SFGAO.FILESYSTEM;
- attrFlag = attrFlag | ShellDll.SFGAO.HASSUBFOLDER;
- attrFlag = attrFlag | ShellDll.SFGAO.FOLDER;
- attrFlag = attrFlag | ShellDll.SFGAO.LINK;
- attrFlag = attrFlag | ShellDll.SFGAO.SHARE;
- attrFlag = attrFlag | ShellDll.SFGAO.HIDDEN;
- attrFlag = attrFlag | ShellDll.SFGAO.REMOVABLE;
- //attrFlag = attrFlag Or ShellDll.SFGAO.RDONLY 'made into an on-demand attribute
- attrFlag = attrFlag | ShellDll.SFGAO.CANCOPY;
- attrFlag = attrFlag | ShellDll.SFGAO.CANDELETE;
- attrFlag = attrFlag | ShellDll.SFGAO.CANLINK;
- attrFlag = attrFlag | ShellDll.SFGAO.CANMOVE;
- attrFlag = attrFlag | ShellDll.SFGAO.DROPTARGET;
- //Note: for GetAttributesOf, we must provide an array, in all cases with 1 element
- IntPtr[] aPidl = new IntPtr[1];
- aPidl[0] = pidl;
- folder.GetAttributesOf(1, aPidl, ref attrFlag);
- m_Attributes = attrFlag;
- m_IsBrowsable = ((attrFlag & ShellDll.SFGAO.BROWSABLE) != 0);
- m_IsFileSystem = ((attrFlag & ShellDll.SFGAO.FILESYSTEM) != 0);
- m_HasSubFolders = ((attrFlag & ShellDll.SFGAO.HASSUBFOLDER) != 0);
- m_IsFolder = ((attrFlag & ShellDll.SFGAO.FOLDER) != 0);
- m_IsLink = ((attrFlag & ShellDll.SFGAO.LINK) != 0);
- m_IsShared = ((attrFlag & ShellDll.SFGAO.SHARE) != 0);
- m_IsHidden = ((attrFlag & ShellDll.SFGAO.HIDDEN) != 0);
- m_IsRemovable = ((attrFlag & ShellDll.SFGAO.REMOVABLE) != 0);
- //m_IsReadOnly = CBool(attrFlag And ShellDll.SFGAO.RDONLY) 'made into an on-demand attribute
- m_CanCopy = ((attrFlag & ShellDll.SFGAO.CANCOPY) != 0);
- m_CanDelete = ((attrFlag & ShellDll.SFGAO.CANDELETE) != 0);
- m_CanLink = ((attrFlag & ShellDll.SFGAO.CANLINK) != 0);
- m_CanMove = ((attrFlag & ShellDll.SFGAO.CANMOVE) != 0);
- m_IsDropTarget = ((attrFlag & ShellDll.SFGAO.DROPTARGET) != 0);
-
- //Get the Path
- IntPtr strr = Marshal.AllocCoTaskMem(ShellDll.MAX_PATH * 2 + 4);
- Marshal.WriteInt32(strr, 0, 0);
- StringBuilder buf = new StringBuilder(ShellDll.MAX_PATH);
- ShellDll.SHGDN itemflags = ShellDll.SHGDN.FORPARSING;
- folder.GetDisplayNameOf(pidl, itemflags, strr);
- int HR = ShellDll.StrRetToBuf(strr, pidl, buf, ShellDll.MAX_PATH);
- Marshal.FreeCoTaskMem(strr);
- //now done with it
- if (HR == ShellDll.NOERROR) {
- m_Path = buf.ToString();
- //check for zip file = folder on xp, leave it a file
- if (m_IsFolder && m_IsFileSystem && XPorAbove) {
- //Note:meaning of ShellDll.SFGAO.STREAM changed between win2k and winXP
- //Version 20 code
- //If File.Exists(m_Path) Then
- // m_IsFolder = False
- //End If
- //Version 21 code
- aPidl[0] = pidl;
- attrFlag = ShellDll.SFGAO.STREAM;
- folder.GetAttributesOf(1, aPidl, ref attrFlag);
- if ((attrFlag & ShellDll.SFGAO.STREAM) != 0) {
- m_IsFolder = false;
- }
- }
- if (m_Path.Length == 3 && m_Path.Substring(1).Equals(":\\")) {
- m_IsDisk = true;
- }
- }
- else {
- Marshal.ThrowExceptionForHR(HR);
- }
- }
-
- #endregion
-
- #endregion
-
- #region " Public Shared Function GetCShItem(ByVal path As String) As ShellItem"
- public static ShellItem GetCShItem(string path)
- {
- ShellItem functionReturnValue = default(ShellItem);
- functionReturnValue = null;
- //assume failure
- int HR = 0;
- IntPtr tmpPidl = default(IntPtr);
- int tmp1 = 0, tmp2 = 0;
- HR = GetDeskTop().Folder.ParseDisplayName(0, IntPtr.Zero, path, ref tmp1, ref tmpPidl, ref tmp2);
- if (HR == 0) {
- functionReturnValue = FindCShItem(tmpPidl);
- if ((functionReturnValue == null))
- {
- try {
- functionReturnValue = new ShellItem(path);
- }
- catch {
- functionReturnValue = null;
- }
- }
- }
- if (!tmpPidl.Equals(IntPtr.Zero)) {
- Marshal.FreeCoTaskMem(tmpPidl);
- }
- return functionReturnValue;
- }
- #endregion
-
- #region " Public Shared Function GetCShItem(ByVal ID As ShellDll.CSIDL) As ShellItem"
- public static ShellItem GetCShItem(ShellDll.CSIDL ID)
- {
- ShellItem functionReturnValue = default(ShellItem);
- functionReturnValue = null;
- //avoid VB2005 Warning
- if (ID == ShellDll.CSIDL.DESKTOP) {
- return GetDeskTop();
- }
- int HR = 0;
- IntPtr tmpPidl = default(IntPtr);
- if (ID == ShellDll.CSIDL.MYDOCUMENTS) {
- int pchEaten = 0;
- int tmp = 0;
- HR = GetDeskTop().Folder.ParseDisplayName(0, IntPtr.Zero, "::{450d8fba-ad25-11d0-98a8-0800361b1103}", ref pchEaten, ref tmpPidl, ref tmp);
- }
- else {
- HR = ShellDll.SHGetSpecialFolderLocation(0, (int)ID, ref tmpPidl);
- }
- if (HR == ShellDll.NOERROR) {
- functionReturnValue = FindCShItem(tmpPidl);
- if ((functionReturnValue == null))
- {
- try {
- functionReturnValue = new ShellItem(ID);
- }
- catch {
- functionReturnValue = null;
- }
- }
- }
- if (!tmpPidl.Equals(IntPtr.Zero)) {
- Marshal.FreeCoTaskMem(tmpPidl);
- }
- return functionReturnValue;
- }
- #endregion
-
- #region " Public Shared Function GetCShItem(ByVal FoldBytes() As Byte, ByVal ItemBytes() As Byte) As ShellItem"
- public static ShellItem GetCShItem(byte[] FoldBytes, byte[] ItemBytes)
- {
- ShellItem functionReturnValue = default(ShellItem);
- functionReturnValue = null;
- //assume failure
- byte[] b = cPidl.JoinPidlBytes(FoldBytes, ItemBytes);
- if ((b == null)) return functionReturnValue;
-
- //can do no more with invalid pidls
- //otherwise do like below, skipping unnecessary validation check
- IntPtr thisPidl = Marshal.AllocCoTaskMem(b.Length);
- if (thisPidl.Equals(IntPtr.Zero)) return null;
- Marshal.Copy(b, 0, thisPidl, b.Length);
- functionReturnValue = FindCShItem(thisPidl);
- Marshal.FreeCoTaskMem(thisPidl);
- if ((functionReturnValue == null))
- {
- //didn't find it, make new
- try {
- functionReturnValue = new ShellItem(FoldBytes, ItemBytes);
- }
- catch {
-
- }
- }
- if (functionReturnValue.PIDL.Equals(IntPtr.Zero)) functionReturnValue = null;
- return functionReturnValue;
- }
- #endregion
-
- #region " Public Shared Function FindCShItem(ByVal b() As Byte) As ShellItem"
- public static ShellItem FindCShItem(byte[] b)
- {
- ShellItem functionReturnValue = default(ShellItem);
- if (!IsValidPidl(b)) return null;
- IntPtr thisPidl = Marshal.AllocCoTaskMem(b.Length);
- if (thisPidl.Equals(IntPtr.Zero)) return null;
- Marshal.Copy(b, 0, thisPidl, b.Length);
- functionReturnValue = FindCShItem(thisPidl);
- Marshal.FreeCoTaskMem(thisPidl);
- return functionReturnValue;
- }
- #endregion
-
- #region " Public Shared Function FindCShItem(ByVal ptr As IntPtr) As ShellItem"
- public static ShellItem FindCShItem(IntPtr ptr)
- {
- ShellItem functionReturnValue = default(ShellItem);
- functionReturnValue = null;
- //avoid VB2005 Warning
- ShellItem BaseItem = ShellItem.GetDeskTop();
- //ShellItem CSI = default(ShellItem);
- bool FoundIt = false;
- //True if we found item or an ancestor
- while (!(FoundIt)) {
- foreach (var obj in BaseItem.GetDirectories(true)) {
- ShellItem CSI = obj as ShellItem;
- if (IsAncestorOf(CSI.PIDL, ptr, false)) {
- if (ShellItem.IsEqual(CSI.PIDL, ptr)) {
- //we found the desired item
- return CSI;
- }
- else {
- BaseItem = CSI;
- FoundIt = true;
- break; // TODO: might not be correct. Was : Exit For
- }
- }
- }
- if (!FoundIt) return null;
- //didn't find an ancestor
- //The complication is that the desired item may not be a directory
- if (!IsAncestorOf(BaseItem.PIDL, ptr, true)) {
- //Don't have immediate ancestor
- //go around again
- FoundIt = false;
- }
- else {
- foreach (var obj in BaseItem.GetItems()) {
- ShellItem CSI = obj as ShellItem;
- if (ShellItem.IsEqual(CSI.PIDL, ptr))
- {
- return CSI;
- }
- }
- //fall thru here means it doesn't exist or we can't find it because of funny PIDL from SHParseDisplayName
- return null;
- }
- }
- return functionReturnValue;
- }
- #endregion
-
- #endregion
-
- #region " Icomparable -- for default Sorting"
-
- /// <summary>Computes the Sort key of this ShellItem, based on its attributes</summary>
- ///
- private int ComputeSortFlag()
- {
- int rVal = 0;
- if (m_IsDisk) rVal = 0x100000;
- if (m_TypeName.Equals(strSystemFolder)) {
- if (!m_IsBrowsable) {
- rVal = rVal | 0x10000;
- if (m_strMyDocuments.Equals(m_DisplayName)) {
- rVal = rVal | 0x1;
- }
- }
- else {
- rVal = rVal | 0x1000;
- }
- }
- if (m_IsFolder) rVal = rVal | 0x100;
- return rVal;
- }
-
- ///<Summary> CompareTo(obj as object)
- /// Compares obj to this instance based on SortFlag-- obj must be a ShellItem</Summary>
- ///<SortOrder> (low)Disks,non-browsable System Folders,
- /// browsable System Folders,
- /// Directories, Files, Nothing (high)</SortOrder>
- public virtual int CompareTo(object obj)
- {
- ShellItem Other = obj as ShellItem;
- if ((Other == null)) return 1;
- //non-existant is always low
- if (!m_HasDispType) SetDispType();
- int cmp = Other.SortFlag - m_SortFlag;
- //Note the reversal
- if (cmp != 0) {
- return cmp;
- }
- else {
- if (m_IsDisk) {
- //implies that both are
- return string.Compare(m_Path, Other.Path);
- }
- else {
- return string.Compare(m_DisplayName, Other.DisplayName);
- }
- }
- }
- #endregion
-
- #region " Properties"
-
- #region " Shared Properties"
- public static string strMyComputer {
- get { return m_strMyComputer; }
- }
-
- public static string strSystemFolder {
- get { return m_strSystemFolder; }
- }
-
- public static string DesktopDirectoryPath {
- get { return m_DeskTopDirectory.Path; }
- }
-
- #endregion
-
- #region " Normal Properties"
- public IntPtr PIDL {
- get { return m_Pidl; }
- }
-
- public ShellDll.IShellFolder Folder {
- get { return m_Folder; }
- }
-
- public string Path {
- get { return m_Path; }
- }
- public ShellItem Parent {
- get { return m_Parent; }
- }
-
- public ShellDll.SFGAO Attributes {
- get { return m_Attributes; }
- }
- public bool IsBrowsable {
- get { return m_IsBrowsable; }
- }
- public bool IsFileSystem {
- get { return m_IsFileSystem; }
- }
- public bool IsFolder {
- get { return m_IsFolder; }
- }
- public bool HasSubFolders {
- get { return m_HasSubFolders; }
- }
- public bool IsDisk {
- get { return m_IsDisk; }
- }
- public bool IsLink {
- get { return m_IsLink; }
- }
- public bool IsShared {
- get { return m_IsShared; }
- }
- public bool IsHidden {
- get { return m_IsHidden; }
- }
- public bool IsRemovable {
- get { return m_IsRemovable; }
- }
-
- #region " Drag Ops Properties"
- public bool CanMove {
- get { return m_CanMove; }
- }
- public bool CanCopy {
- get { return m_CanCopy; }
- }
- public bool CanDelete {
- get { return m_CanDelete; }
- }
- public bool CanLink {
- get { return m_CanLink; }
- }
- public bool IsDropTarget {
- get { return m_IsDropTarget; }
- }
- #endregion
-
- #endregion
-
- #region " Filled on Demand Properties"
-
- #region " Filled based on m_HasDispType"
- /// <summary>
- /// Set DisplayName, TypeName, and SortFlag when actually needed
- /// </summary>
- ///
- private void SetDispType()
- {
- //Get Displayname, TypeName
- ShellDll.SHFILEINFO shfi = new ShellDll.SHFILEINFO();
- int dwflag = (int)(ShellDll.SHGFI.DISPLAYNAME | ShellDll.SHGFI.TYPENAME | ShellDll.SHGFI.PIDL);
- int dwAttr = 0;
- if (m_IsFileSystem & !m_IsFolder) {
- dwflag = dwflag | (int)ShellDll.SHGFI.USEFILEATTRIBUTES;
- dwAttr = (int)ShellDll.FILE_ATTRIBUTE_NORMAL;
- }
- IntPtr H = ShellDll.SHGetFileInfo(m_Pidl, dwAttr, ref shfi, ShellDll.cbFileInfo, dwflag);
- m_DisplayName = shfi.szDisplayName;
- m_TypeName = shfi.szTypeName;
- //fix DisplayName
- if (m_DisplayName.Equals("")) {
- m_DisplayName = m_Path;
- }
- //Fix TypeName
- //If m_IsFolder And m_TypeName.Equals("File") Then
- // m_TypeName = "File Folder"
- //End If
- m_SortFlag = ComputeSortFlag();
- m_HasDispType = true;
- }
-
- public string DisplayName {
- get {
- if (!m_HasDispType) SetDispType();
- return m_DisplayName;
- }
- }
-
- private int SortFlag {
- get {
- if (!m_HasDispType) SetDispType();
- return m_SortFlag;
- }
- }
-
- public string TypeName {
- get {
- if (!m_HasDispType) SetDispType();
- return m_TypeName;
- }
- }
- #endregion
-
- #region " IconIndex properties"
- public int IconIndexNormal {
- get {
- if (m_IconIndexNormal < 0) {
- if (!m_HasDispType) SetDispType();
- ShellDll.SHFILEINFO shfi = new ShellDll.SHFILEINFO();
- int dwflag = (int)(ShellDll.SHGFI.PIDL | ShellDll.SHGFI.SYSICONINDEX);
- int dwAttr = 0;
- if (m_IsFileSystem & !m_IsFolder) {
- dwflag = dwflag | (int)ShellDll.SHGFI.USEFILEATTRIBUTES;
- dwAttr = (int)ShellDll.FILE_ATTRIBUTE_NORMAL;
- }
- IntPtr H = ShellDll.SHGetFileInfo(m_Pidl, dwAttr, ref shfi, ShellDll.cbFileInfo, dwflag);
- m_IconIndexNormal = shfi.iIcon;
- }
- return m_IconIndexNormal;
- }
- }
- // IconIndexOpen is Filled on demand
- public int IconIndexOpen {
- get {
- if (m_IconIndexOpen < 0) {
- if (!m_HasDispType) SetDispType();
- if (!m_IsDisk & m_IsFileSystem & m_IsFolder) {
- if (OpenFolderIconIndex < 0) {
- int dwflag = (int)(ShellDll.SHGFI.SYSICONINDEX | ShellDll.SHGFI.PIDL);
- ShellDll.SHFILEINFO shfi = new ShellDll.SHFILEINFO();
- IntPtr H = ShellDll.SHGetFileInfo(m_Pidl, 0, ref shfi, ShellDll.cbFileInfo, dwflag | (int)ShellDll.SHGFI.OPENICON);
- m_IconIndexOpen = shfi.iIcon;
- }
- else {
- //If m_TypeName.Equals("File Folder") Then
- // OpenFolderIconIndex = shfi.iIcon
- //End If
- m_IconIndexOpen = OpenFolderIconIndex;
- }
- }
- else {
- m_IconIndexOpen = m_IconIndexNormal;
- }
- }
- return m_IconIndexOpen;
- }
- }
- #endregion
-
- #region " FileInfo type Information"
-
- /// <summary>
- /// Obtains information available from FileInfo.
- /// </summary>
- ///
- private void FillDemandInfo()
- {
- if (m_IsDisk) {
- try {
- //See if this is a network drive
- //NoRoot = 1
- //Removable = 2
- //LocalDisk = 3
- //Network = 4
- //CD = 5
- //RAMDrive = 6
- System.Management.ManagementObject disk = new System.Management.ManagementObject("win32_logicaldisk.deviceid=\"" + m_Path.Substring(0, 2) + "\"");
- m_Length = (long)(UInt64)disk["Size"];
- if ((UInt32)disk["DriveType"] == 4) {
- m_IsNetWorkDrive = true;
- }
- }
- catch (Exception) {
- //Disconnected Network Drives etc. will generate
- //an error here, just assume that it is a network
- //drive
- m_IsNetWorkDrive = true;
- }
- finally {
- m_XtrInfo = true;
- }
- }
- else if (!m_IsDisk & m_IsFileSystem & !m_IsFolder) {
- //in this case, it's a file
- if (File.Exists(m_Path)) {
- FileInfo fi = new FileInfo(m_Path);
- m_LastWriteTime = fi.LastWriteTime;
- m_LastAccessTime = fi.LastAccessTime;
- m_CreationTime = fi.CreationTime;
- m_Length = fi.Length;
- m_XtrInfo = true;
- }
- }
- else {
- if (m_IsFileSystem & m_IsFolder) {
- if (Directory.Exists(m_Path)) {
- DirectoryInfo di = new DirectoryInfo(m_Path);
- m_LastWriteTime = di.LastWriteTime;
- m_LastAccessTime = di.LastAccessTime;
- m_CreationTime = di.CreationTime;
- m_XtrInfo = true;
- }
- }
- }
- }
-
- public DateTime LastWriteTime {
- get {
- if (!m_XtrInfo) {
- FillDemandInfo();
- }
- return m_LastWriteTime;
- }
- }
- public DateTime LastAccessTime {
- get {
- if (!m_XtrInfo) {
- FillDemandInfo();
- }
- return m_LastAccessTime;
- }
- }
- public DateTime CreationTime {
- get {
- if (!m_XtrInfo) {
- FillDemandInfo();
- }
- return m_CreationTime;
- }
- }
- public long Length {
- get {
- if (!m_XtrInfo) {
- FillDemandInfo();
- }
- return m_Length;
- }
- }
- public bool IsNetworkDrive {
- get {
- if (!m_XtrInfo) {
- FillDemandInfo();
- }
- return m_IsNetWorkDrive;
- }
- }
- #endregion
-
- #region " cPidl information"
- public cPidl clsPidl {
- get {
- if ((m_cPidl == null)) {
- m_cPidl = new cPidl(m_Pidl);
- }
- return m_cPidl;
- }
- }
- #endregion
-
- #region " IsReadOnly and IsSystem"
- ///<Summary>The IsReadOnly attribute causes an annoying access to any floppy drives
- /// on the system. To postpone this (or avoid, depending on user action),
- /// the attribute is only queried when asked for</Summary>
- public bool IsReadOnly {
- get {
- if (m_IsReadOnlySetup) {
- return m_IsReadOnly;
- }
- else {
- ShellDll.SHFILEINFO shfi = new ShellDll.SHFILEINFO();
- shfi.dwAttributes = (int)ShellDll.SFGAO.RDONLY;
- int dwflag = (int)(ShellDll.SHGFI.PIDL | ShellDll.SHGFI.ATTRIBUTES | ShellDll.SHGFI.ATTR_SPECIFIED);
- int dwAttr = 0;
- IntPtr H = ShellDll.SHGetFileInfo(m_Pidl, dwAttr, ref shfi, ShellDll.cbFileInfo, dwflag);
- if (H.ToInt32() != ShellDll.NOERROR && H.ToInt32() != 1) {
- Marshal.ThrowExceptionForHR(H.ToInt32());
- }
- m_IsReadOnly = ((shfi.dwAttributes & (int)ShellDll.SFGAO.RDONLY) != 0);
- //If m_IsReadOnly Then Debug.WriteLine("IsReadOnly -- " & m_Path)
- m_IsReadOnlySetup = true;
- return m_IsReadOnly;
- }
- }
- //If Not m_XtrInfo Then
- // FillDemandInfo()
- //End If
- //Return m_Attributes And FileAttributes.ReadOnly = FileAttributes.ReadOnly
- }
- ///<Summary>The IsSystem attribute is seldom used, but required by DragDrop operations.
- /// Since there is no way of getting ONLY the System attribute without getting
- /// the RO attribute (which forces a reference to the floppy drive), we pay
- /// the price of getting its own File/DirectoryInfo for this purpose alone.
- ///</Summary>
- public bool IsSystem {
- get {
- //true once we have gotten this attr
- //the value of this attr once we have it
- if (!static_IsSystem_HaveSysInfo) {
- try {
- static_IsSystem_m_IsSystem = (File.GetAttributes(m_Path) & FileAttributes.System) == FileAttributes.System;
- static_IsSystem_HaveSysInfo = true;
- }
- catch (Exception) {
- static_IsSystem_HaveSysInfo = true;
- }
- }
- Debug.WriteLine("In IsSystem -- Path = " + m_Path + " IsSystem = " + static_IsSystem_m_IsSystem);
- return static_IsSystem_m_IsSystem;
- }
- }
- static bool static_IsSystem_m_IsSystem = false;
- static bool static_IsSystem_HaveSysInfo = false;
-
- #endregion
-
- #endregion
-
- #endregion
-
- #region " Public Methods"
-
- #region " Shared Public Methods"
-
- #region " GetDeskTop"
- /// <summary>
- /// If not initialized, then build DesktopBase
- /// once done, or if initialized already,
- /// </summary>
- ///<returns>The DesktopBase ShellItem representing the desktop</returns>
- ///
- public static ShellItem GetDeskTop()
- {
- if ((DesktopBase == null)) {
- DesktopBase = new ShellItem();
- }
- return DesktopBase;
- }
- #endregion
-
- #region " IsAncestorOf"
- ///<Summary>IsAncestorOf returns True if ShellItem ancestor is an ancestor of ShellItem current
- /// if OS is Win2K or above, uses the ILIsParent API, otherwise uses the
- /// cPidl function StartsWith. This is necessary since ILIsParent in only available
- /// in Win2K or above systems AND StartsWith fails on some folders on XP systems (most
- /// obviously some Network Folder Shortcuts, but also Control Panel. Note, StartsWith
- /// always works on systems prior to XP.
- /// NOTE: if ancestor and current reference the same Item, both
- /// methods return True</Summary>
- public static bool IsAncestorOf(ShellItem ancestor, ShellItem current, [System.Runtime.InteropServices.OptionalAttribute, System.Runtime.InteropServices.DefaultParameterValueAttribute(false)] // ERROR: Optional parameters aren't supported in C#
- bool fParent)
- {
- return IsAncestorOf(ancestor.PIDL, current.PIDL, fParent);
- }
- ///<Summary> Compares a candidate Ancestor PIDL with a Child PIDL and
- /// returns True if Ancestor is an ancestor of the child.
- /// if fParent is True, then only return True if Ancestor is the immediate
- /// parent of the Child</Summary>
- public static bool IsAncestorOf(IntPtr AncestorPidl, IntPtr ChildPidl, [System.Runtime.InteropServices.OptionalAttribute, System.Runtime.InteropServices.DefaultParameterValueAttribute(false)] // ERROR: Optional parameters aren't supported in C#
- bool fParent)
- {
- bool functionReturnValue = false;
- if (ShellDll.Is2KOrAbove()) {
- return ShellDll.ILIsParent(AncestorPidl, ChildPidl, fParent);
- }
- else {
- cPidl Child = new cPidl(ChildPidl);
- cPidl Ancestor = new cPidl(AncestorPidl);
- functionReturnValue = Child.StartsWith(Ancestor);
- if (!functionReturnValue) return functionReturnValue;
-
- if (fParent) {
- // check for immediate ancestor, if desired
- object[] oAncBytes = Ancestor.Decompose();
- object[] oChildBytes = Child.Decompose();
- if (oAncBytes.Length != (oChildBytes.Length - 1)) {
- functionReturnValue = false;
- }
- }
- }
- return functionReturnValue;
- }
- #endregion
-
- #region " AllFolderWalk"
- ///<Summary>The WalkAllCallBack delegate defines the signature of
- /// the routine to be passed to DirWalker
- /// Usage: dim d1 as new CshItem.WalkAllCallBack(addressof yourroutine)
- /// Callback function receives a ShellItem for each file and Directory in
- /// Starting Directory and each sub-directory of this directory and
- /// each sub-dir of each sub-dir ....
- ///</Summary>
- public delegate bool WalkAllCallBack(ShellItem info, int UserLevel, int Tag);
- ///<Summary>
- /// AllFolderWalk recursively walks down directories from cStart, calling its
- /// callback routine, WalkAllCallBack, for each Directory and File encountered, including those in
- /// cStart. UserLevel is incremented by 1 for each level of dirs that DirWalker
- /// recurses thru. Tag in an Integer that is simply passed, unmodified to the
- /// callback, with each ShellItem encountered, both File and Directory CShItems.
- /// </Summary>
- /// <param name="cStart"></param>
- /// <param name="cback"></param>
- /// <param name="UserLevel"></param>
- /// <param name="Tag"></param>
- ///
- public static bool AllFolderWalk(ShellItem cStart, WalkAllCallBack cback, int UserLevel, int Tag)
- {
- if ((cStart != null) && cStart.IsFolder) {
- //ShellItem cItem = default(ShellItem);
- //first processes all files in this directory
- foreach (var obj in cStart.GetFiles()) {
- ShellItem cItem = obj as ShellItem;
- if (!cback(cItem, UserLevel, Tag)) {
- //user said stop
- return false;
- }
- }
- //then process all dirs in this directory, recursively
- foreach (var obj in cStart.GetDirectories(true)) {
- ShellItem cItem = obj as ShellItem;
- if (!cback(cItem, UserLevel + 1, Tag)) {
- //user said stop
- return false;
- }
- else {
- if (!AllFolderWalk(cItem, cback, UserLevel + 1, Tag)) {
- return false;
- }
- }
- }
- return true;
- }
- else {
- //Invalid call
- throw new ApplicationException("AllFolderWalk -- Invalid Start Directory");
- }
- }
- #endregion
-
- #endregion
-
- #region " Public Instance Methods"
-
- #region " Equals"
- public bool Equals(ShellItem other)
- {
- return this.Path.Equals(other.Path);
- }
- #endregion
-
- #region " GetDirectories"
- /// <summary>
- /// Returns the Directories of this sub-folder as an ArrayList of CShitems
- /// </summary>
- /// <param name="doRefresh">Optional, default=True, Refresh the directories</param>
- /// <returns>An ArrayList of CShItems. May return an empty ArrayList if there are none.</returns>
- /// <remarks>revised to alway return an up-to-date list unless
- /// specifically instructed not to (useful in constructs like:
- //…
Large files files are truncated, but you can click here to view the full file