// Note that fullPath is fully qualified, while userPath may be // relative. Use userPath for all exception messages to avoid leaking // fully qualified path information. private static void DeleteHelper(String fullPath, String userPath, bool recursive) { bool r; Exception ex = null; ErrorCode error; if (recursive) { Native.FIND_DATA data = new Native.FIND_DATA(); // Open a Find handle (Win32 is weird) IntPtr hnd = Native.FindFirstFile(fullPath + Path.DirectorySeparatorChar + "*", out data); if (hnd == IntPtr.Zero) { __Error.WinIOError(1, userPath); } do { assert data != null; // implied by FindFirst/NextFile and return status bool isDir = (0 != (data.dwFileAttributes & Native.FILE_ATTRIBUTE_DIRECTORY)); if (isDir) { if (data.cFileName.Equals(".") || data.cFileName.Equals("..")) { continue; } // recurse String newFullPath = Path.InternalCombine(fullPath, data.cFileName); String newUserPath = Path.InternalCombine(userPath, data.cFileName); try { DeleteHelper(newFullPath, newUserPath, recursive); } catch (Exception e) { if (ex == null) { ex = e; } } } else { String fileName = fullPath + Path.DirectorySeparatorChar + data.cFileName; r = Native.DeleteFile(fileName, out error); if (!r) { // __Error.WinIOError(1, data.cFileName); __Error.SingularityIOError(error, data.cFileName); } } } while (Native.FindNextFile(hnd, out data)); // Make sure we quit with a sensible error. Native.FindClose(hnd); // Close Find handle in all cases. if (ex != null) { throw ex; } } r = Native.RemoveDirectory(fullPath, out error); if (!r) { //__Error.WinIOError(1, userPath); __Error.SingularityIOError(error, fullPath); } }
// Private helper function that does not do any security checks internal static String[] !InternalGetFileDirectoryNames(String !fullPath, String userPath, bool file) { // If path ends in a trailing slash (\), append a * or we'll // get a "Cannot find the file specified" exception char lastChar = fullPath[fullPath.Length - 1]; if (lastChar == Path.DirectorySeparatorChar || lastChar == Path.AltDirectorySeparatorChar || lastChar == Path.VolumeSeparatorChar) { fullPath = fullPath + '*'; } String[] list = new String[10]; int listSize = 0; Native.FIND_DATA data = new Native.FIND_DATA(); // Open a Find handle (Win32 is weird) IntPtr hnd = Native.FindFirstFile(fullPath, out data); if (hnd == IntPtr.Zero) { return(new String[0]); } // Keep asking for more matching files, adding file names to list int numEntries = 0; // Number of DirectoryInfo entities we see. do { assert data != null; // implied by result of FindFirst/Next not being Zero bool includeThis; // Should this file/DirectoryInfo be included in the output? if (file) { includeThis = (0 == (data.dwFileAttributes & Native.FILE_ATTRIBUTE_DIRECTORY)); } else { includeThis = (0 != (data.dwFileAttributes & Native.FILE_ATTRIBUTE_DIRECTORY)); // Don't add "." nor ".." if (includeThis && (data.cFileName.Equals(".") || data.cFileName.Equals(".."))) { includeThis = false; } } if (includeThis) { numEntries++; if (listSize == list.Length) { String[] newList = new String[list.Length * 2]; Array.Copy(list, 0, newList, 0, listSize); list = newList; } list[listSize++] = data.cFileName; } } while (Native.FindNextFile(hnd, out data)); // Make sure we quit with a sensible error. Native.FindClose(hnd); // Close Find handle in all cases. // Check for a string such as "C:\tmp", in which case we return // just the DirectoryInfo name. FindNextFile fails first time, and // data still contains a directory. // The above comment seems wrong. I don't see why data should still be // non-null here. assert data != null; if (!file && numEntries == 1 && (0 != (data.dwFileAttributes & Native.FILE_ATTRIBUTE_DIRECTORY))) { String[] sa = new String[1]; sa[0] = data.cFileName; return(sa); } // Return list of files/directories as an array of strings if (listSize == list.Length) { return(list); } String[] items = new String[listSize]; Array.Copy(list, 0, items, 0, listSize); return(items); }