Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / clr / src / BCL / System / IO / Directory.cs / 1 / Directory.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================ ** ** Class: Directory ** ** ** Purpose: Exposes routines for enumerating through a ** directory. ** ** April 11,2000 ** ===========================================================*/ using System; using System.Collections; using System.Collections.Generic; using System.Security; using System.Security.Permissions; using Microsoft.Win32; using Microsoft.Win32.SafeHandles; using System.Text; using System.Runtime.InteropServices; using System.Globalization; using System.Runtime.Versioning; #if !FEATURE_PAL using System.Security.AccessControl; #endif namespace System.IO { [ComVisible(true)] public static class Directory { [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static DirectoryInfo GetParent(String path) { if (path==null) throw new ArgumentNullException("path"); if (path.Length==0) throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty"), "path"); String fullPath = Path.GetFullPathInternal(path); String s = Path.GetDirectoryName(fullPath); if (s==null) return null; return new DirectoryInfo(s); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static DirectoryInfo CreateDirectory(String path) { #if !FEATURE_PAL return CreateDirectory(path, null); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static DirectoryInfo CreateDirectory(String path, DirectorySecurity directorySecurity) { #endif if (path==null) throw new ArgumentNullException("path"); if (path.Length == 0) throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty")); String fullPath = Path.GetFullPathInternal(path); // You need read access to the directory to be returned back and write access to all the directories // that you need to create. If we fail any security checks we will not create any directories at all. // We attempt to create directories only after all the security checks have passed. This is avoid doing // a demand at every level. String demandDir = GetDemandDir(fullPath, true); new FileIOPermission(FileIOPermissionAccess.Read, new String[] { demandDir }, false, false ).Demand(); #if !FEATURE_PAL InternalCreateDirectory(fullPath, path, directorySecurity); #else InternalCreateDirectory(fullPath, path); #endif return new DirectoryInfo(fullPath, false); } // Input to this method should already be fullpath. This method will ensure that we append // the trailing slash only when appropriate and when thisDirOnly is specified append a "." // at the end of the path to indicate that the demand is only for the fullpath and not // everything underneath it. [ResourceExposure(ResourceScope.None)] [ResourceConsumption(ResourceScope.None, ResourceScope.None)] internal static String GetDemandDir(string fullPath, bool thisDirOnly) { String demandPath; if (thisDirOnly) { if (fullPath.EndsWith( Path.DirectorySeparatorChar ) || fullPath.EndsWith( Path.AltDirectorySeparatorChar ) ) demandPath = fullPath + '.'; else demandPath = fullPath + Path.DirectorySeparatorChar + '.'; } else { if (!(fullPath.EndsWith( Path.DirectorySeparatorChar ) || fullPath.EndsWith( Path.AltDirectorySeparatorChar )) ) demandPath = fullPath + Path.DirectorySeparatorChar; else demandPath = fullPath; } return demandPath; } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] internal unsafe static void InternalCreateDirectory(String fullPath, String path #if !FEATURE_PAL , DirectorySecurity dirSecurity #endif ) { int length = fullPath.Length; // We need to trim the trailing slash or the code will try to create 2 directories of the same name. if (length >= 2 && Path.IsDirectorySeparator(fullPath[length - 1])) length--; int lengthRoot = Path.GetRootLength(fullPath); #if !PLATFORM_UNIX // For UNC paths that are only // or /// if (length == 2 && Path.IsDirectorySeparator(fullPath[1])) throw new IOException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("IO.IO_CannotCreateDirectory"), path)); #endif // !PLATFORM_UNIX ListstackDir = new List (); // Attempt to figure out which directories don't exist, and only // create the ones we need. Note that InternalExists may fail due // to Win32 ACL's preventing us from seeing a directory, and this // isn't threadsafe. bool somepathexists = false; if (length > lengthRoot) { // Special case root (fullpath = X:\\) int i = length-1; while (i >= lengthRoot) { String dir = fullPath.Substring(0, i+1); if (!InternalExists(dir)) // Create only the ones missing stackDir.Add(dir); else somepathexists = true; while (i > lengthRoot && fullPath[i] != Path.DirectorySeparatorChar && fullPath[i] != Path.AltDirectorySeparatorChar) i--; i--; } } int count = stackDir.Count; if (stackDir.Count != 0) { String [] securityList = new String[stackDir.Count]; stackDir.CopyTo(securityList, 0); for (int j = 0 ; j < securityList.Length; j++) securityList[j] += "\\."; // leaf will never have a slash at the end // Security check for all directories not present only. #if !FEATURE_PAL AccessControlActions control = (dirSecurity == null) ? AccessControlActions.None : AccessControlActions.Change; new FileIOPermission(FileIOPermissionAccess.Write, control, securityList, false, false ).Demand(); #else new FileIOPermission(FileIOPermissionAccess.Write, securityList, false, false ).Demand(); #endif } // If we were passed a DirectorySecurity, convert it to a security // descriptor and set it in he call to CreateDirectory. Win32Native.SECURITY_ATTRIBUTES secAttrs = null; #if !FEATURE_PAL if (dirSecurity != null) { secAttrs = new Win32Native.SECURITY_ATTRIBUTES(); secAttrs.nLength = (int)Marshal.SizeOf(secAttrs); // For ACL's, get the security descriptor from the FileSecurity. byte[] sd = dirSecurity.GetSecurityDescriptorBinaryForm(); byte * bytesOnStack = stackalloc byte[sd.Length]; Buffer.memcpy(sd, 0, bytesOnStack, 0, sd.Length); secAttrs.pSecurityDescriptor = bytesOnStack; } #endif bool r = true; int firstError = 0; String errorString = path; // If all the security checks succeeded create all the directories while (stackDir.Count > 0) { String name = stackDir[stackDir.Count - 1]; stackDir.RemoveAt(stackDir.Count - 1); if (name.Length > Path.MAX_DIRECTORY_PATH) throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); r = Win32Native.CreateDirectory(name, secAttrs); if (!r && (firstError == 0)) { int currentError = Marshal.GetLastWin32Error(); // While we tried to avoid creating directories that don't // exist above, there are at least two cases that will // cause us to see ERROR_ALREADY_EXISTS here. InternalExists // can fail because we didn't have permission to the // directory. Secondly, another thread or process could // create the directory between the time we check and the // time we try using the directory. Thirdly, it could // fail because the target does exist, but is a file. if (currentError != Win32Native.ERROR_ALREADY_EXISTS) firstError = currentError; else { // If there's a file in this directory's place, throw. if (File.InternalExists(name)) { firstError = currentError; // Give the user a nice error message, but don't leak path information. try { new FileIOPermission(FileIOPermissionAccess.PathDiscovery, GetDemandDir(name, true)).Demand(); errorString = name; } catch(SecurityException) {} } } } } // We need this check to mask OS differences // Handle CreateDirectory("X:\\foo") when X: doesn't exist. Similarly for n/w paths. if ((count == 0) && !somepathexists) { String root = InternalGetDirectoryRoot(fullPath); if (!InternalExists(root)) { // Extract the root from the passed in path again for security. __Error.WinIOError(Win32Native.ERROR_PATH_NOT_FOUND, InternalGetDirectoryRoot(path)); } return; } // Only throw an exception if creating the exact directory we // wanted failed to work correctly. if (!r && (firstError != 0)) { __Error.WinIOError(firstError, errorString); } } // Tests if the given path refers to an existing DirectoryInfo on disk. // // Your application must have Read permission to the directory's // contents. // [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static bool Exists(String path) { try { if (path==null) return false; if (path.Length==0) return false; // Get fully qualified file name ending in \* for security check String fullPath = Path.GetFullPathInternal(path); String demandPath = GetDemandDir(fullPath, true); new FileIOPermission(FileIOPermissionAccess.Read, new String[] { demandPath }, false, false ).Demand(); return InternalExists(fullPath); } catch(ArgumentException) {} catch(NotSupportedException) {} // Security can throw this on ":" catch(SecurityException) {} catch(IOException) {} catch(UnauthorizedAccessException) { #if !FEATURE_PAL BCLDebug.Assert(false,"Ignore this assert and send a repro to [....]. This assert was tracking purposes only."); #endif //!FEATURE_PAL } return false; } // Determine whether path describes an existing directory // on disk, avoiding security checks. [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] internal static bool InternalExists(String path) { Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); int dataInitialised = File.FillAttributeInfo(path, ref data, false, true); return (dataInitialised == 0) && (data.fileAttributes != -1) && ((data.fileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY) != 0); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static void SetCreationTime(String path,DateTime creationTime) { SetCreationTimeUtc(path, creationTime.ToUniversalTime()); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public unsafe static void SetCreationTimeUtc(String path,DateTime creationTimeUtc) { #if !FEATURE_PAL if ((Environment.OSInfo & Environment.OSName.WinNT) == Environment.OSName.WinNT) #endif //!FEATURE_PAL { using (SafeFileHandle handle = Directory.OpenHandle(path)) { Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(creationTimeUtc.ToFileTimeUtc()); bool r = Win32Native.SetFileTime(handle, &fileTime, null, null); if (!r) { int errorCode = Marshal.GetLastWin32Error(); __Error.WinIOError(errorCode, path); } } } } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static DateTime GetCreationTime(String path) { return File.GetCreationTime(path); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static DateTime GetCreationTimeUtc(String path) { return File.GetCreationTimeUtc(path); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static void SetLastWriteTime(String path,DateTime lastWriteTime) { SetLastWriteTimeUtc(path, lastWriteTime.ToUniversalTime()); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public unsafe static void SetLastWriteTimeUtc(String path,DateTime lastWriteTimeUtc) { #if !FEATURE_PAL if ((Environment.OSInfo & Environment.OSName.WinNT) == Environment.OSName.WinNT) #endif //!FEATURE_PAL { using (SafeFileHandle handle = Directory.OpenHandle(path)) { Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(lastWriteTimeUtc.ToFileTimeUtc()); bool r = Win32Native.SetFileTime(handle, null, null, &fileTime); if (!r) { int errorCode = Marshal.GetLastWin32Error(); __Error.WinIOError(errorCode, path); } } } } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static DateTime GetLastWriteTime(String path) { return File.GetLastWriteTime(path); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static DateTime GetLastWriteTimeUtc(String path) { return File.GetLastWriteTimeUtc(path); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static void SetLastAccessTime(String path,DateTime lastAccessTime) { SetLastAccessTimeUtc(path, lastAccessTime.ToUniversalTime()); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public unsafe static void SetLastAccessTimeUtc(String path,DateTime lastAccessTimeUtc) { #if !FEATURE_PAL if ((Environment.OSInfo & Environment.OSName.WinNT) == Environment.OSName.WinNT) #endif //!FEATURE_PAL { using (SafeFileHandle handle = Directory.OpenHandle(path)) { Win32Native.FILE_TIME fileTime = new Win32Native.FILE_TIME(lastAccessTimeUtc.ToFileTimeUtc()); bool r = Win32Native.SetFileTime(handle, null, &fileTime, null); if (!r) { int errorCode = Marshal.GetLastWin32Error(); __Error.WinIOError(errorCode, path); } } } } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static DateTime GetLastAccessTime(String path) { return File.GetLastAccessTime(path); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static DateTime GetLastAccessTimeUtc(String path) { return File.GetLastAccessTimeUtc(path); } #if !FEATURE_PAL [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static DirectorySecurity GetAccessControl(String path) { return new DirectorySecurity(path, AccessControlSections.Access | AccessControlSections.Owner | AccessControlSections.Group); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static DirectorySecurity GetAccessControl(String path, AccessControlSections includeSections) { return new DirectorySecurity(path, includeSections); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static void SetAccessControl(String path, DirectorySecurity directorySecurity) { if (directorySecurity == null) throw new ArgumentNullException("directorySecurity"); String fullPath = Path.GetFullPathInternal(path); directorySecurity.Persist(fullPath); } #endif // Returns an array of filenames in the DirectoryInfo specified by path [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static String[] GetFiles(String path) { return GetFiles(path,"*"); } // Returns an array of Files in the current DirectoryInfo matching the // given search pattern (ie, "*.txt"). [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static String[] GetFiles(String path,String searchPattern) { return GetFiles(path, searchPattern, SearchOption.TopDirectoryOnly); } // Returns an array of Files in the current DirectoryInfo matching the // given search pattern (ie, "*.txt") and search option [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static String[] GetFiles(String path,String searchPattern, SearchOption searchOption) { if (path==null) throw new ArgumentNullException("path"); if (searchPattern==null) throw new ArgumentNullException("searchPattern"); return InternalGetFileDirectoryNames(path, path, searchPattern, true, false, searchOption); } // Returns an array of Directories in the current directory. [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static String[] GetDirectories(String path) { return GetDirectories(path,"*"); } // Returns an array of Directories in the current DirectoryInfo matching the // given search criteria (ie, "*.txt"). [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static String[] GetDirectories(String path,String searchPattern) { return GetDirectories(path, searchPattern, SearchOption.TopDirectoryOnly); } // Returns an array of Directories in the current DirectoryInfo matching the // given search criteria (ie, "*.txt"). [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static String[] GetDirectories(String path,String searchPattern, SearchOption searchOption) { if (path==null) throw new ArgumentNullException("path"); if (searchPattern==null) throw new ArgumentNullException("searchPattern"); return InternalGetFileDirectoryNames(path, path, searchPattern, false, true, searchOption); } // Returns an array of strongly typed FileSystemInfo entries in the path [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static String[] GetFileSystemEntries(String path) { return GetFileSystemEntries(path,"*"); } // Returns an array of strongly typed FileSystemInfo entries in the path with the // given search criteria (ie, "*.txt"). We disallow .. as a part of the search criteria [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static String[] GetFileSystemEntries(String path,String searchPattern) { return GetFileSystemEntries(path, searchPattern, SearchOption.TopDirectoryOnly); } // Returns an array of strongly typed FileSystemInfo entries in the path with the // given search criteria (ie, "*.txt"). We disallow .. as a part of the search criteria [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] private static String[] GetFileSystemEntries(String path,String searchPattern, SearchOption searchOption) { if (path==null) throw new ArgumentNullException("path"); if (searchPattern==null) throw new ArgumentNullException("searchPattern"); return InternalGetFileDirectoryNames(path, path, searchPattern, true, true, searchOption); } // Private class that holds search data that is passed around // in the heap based stack recursion private sealed class SearchData { public SearchData() { } public SearchData(string fullPath, string userPath, SearchOption searchOption) { this.fullPath = fullPath; this.userPath = userPath; this.searchOption = searchOption; } public string fullPath; // Fully qualified search path excluding the search criteria in the end (ex, c:\temp\bar\foo) public string userPath; // User specified path (ex, bar\foo) public SearchOption searchOption; } // Returns fully qualified user path of dirs/files that matches the search parameters. // For recursive search this method will search through all the sub dirs and execute // the given search criteria against every dir. // For all the dirs/files returned, it will then demand path discovery permission for // their parent folders (it will avoid duplicate permission checks) [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] internal static String[] InternalGetFileDirectoryNames(String path, String userPathOriginal, String searchPattern, bool includeFiles, bool includeDirs, SearchOption searchOption) { int hr = 0; if ((searchOption != SearchOption.TopDirectoryOnly) && (searchOption != SearchOption.AllDirectories)) throw new ArgumentOutOfRangeException("searchOption", Environment.GetResourceString("ArgumentOutOfRange_Enum")); searchPattern = searchPattern.TrimEnd(); if (searchPattern.Length == 0) return new String[0]; Path.CheckSearchPattern(searchPattern); // Build various paths and query strings // Must fully qualify the path for the security check String fullPath = Path.GetFullPathInternal(path); // Any illegal chars such as *, ? will be caught by FileIOPermission.HasIllegalCharacters String[] demandPaths = new String[] {GetDemandDir(fullPath, true)}; new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false).Demand(); String userPath = userPathOriginal; String tempPath = Path.GetDirectoryName(searchPattern); if (tempPath != null && tempPath.Length != 0) { // For filters like foo\*.cs we need to verify if the directory foo is not denied access. // Do a demand on the combined path so that we can fail early in case of deny demandPaths = new String[] {GetDemandDir(Path.InternalCombine(fullPath, tempPath), true)}; new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false).Demand(); userPath = Path.Combine(userPath, tempPath); // Need to add the searchPath to return correct path and for right security checks } String tempStr = Path.InternalCombine(fullPath, searchPattern); // If path ends in a trailing slash (\), append a * or we'll // get a "Cannot find the file specified" exception char lastChar = tempStr[tempStr.Length-1]; if (lastChar == Path.DirectorySeparatorChar || lastChar == Path.AltDirectorySeparatorChar || lastChar == Path.VolumeSeparatorChar) tempStr = tempStr + '*'; fullPath = Path.GetDirectoryName(tempStr); BCLDebug.Assert((fullPath != null),"fullpath can't be null!"); String searchCriteria; bool trailingSlash = false; bool trailingSlashUserPath = false; lastChar = fullPath[fullPath.Length-1]; trailingSlash = (lastChar == Path.DirectorySeparatorChar) || (lastChar == Path.AltDirectorySeparatorChar); if (trailingSlash) { // Can happen if the path is C:\temp, in which case GetDirectoryName would return C:\ searchCriteria = tempStr.Substring(fullPath.Length); } else searchCriteria = tempStr.Substring(fullPath.Length + 1); Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA(); SafeFindHandle hnd = null; // Heap based search stack SearchData searchData = new SearchData(fullPath, userPath, searchOption); List searchStack = new List (); searchStack.Add(searchData); List demandPathList = new List (); int numEntries = 0; // Number of directory entities we see. int listSize = 0; String[] list = new String[10]; String searchPath; int oldMode = Win32Native.SetErrorMode(Win32Native.SEM_FAILCRITICALERRORS); try { // Traverse directory structure. We need to get '*' while(searchStack.Count > 0) { searchData = searchStack[searchStack.Count - 1]; searchStack.RemoveAt(searchStack.Count - 1); BCLDebug.Assert((searchData.fullPath != null),"fullpath can't be null!"); lastChar = searchData.fullPath[searchData.fullPath.Length -1]; trailingSlash = (lastChar == Path.DirectorySeparatorChar) || (lastChar == Path.AltDirectorySeparatorChar); if (searchData.userPath.Length > 0) { lastChar = searchData.userPath[searchData.userPath.Length -1]; trailingSlashUserPath = (lastChar == Path.DirectorySeparatorChar) || (lastChar == Path.AltDirectorySeparatorChar); } // Traverse the subdirs if specified if (searchData.searchOption != SearchOption.TopDirectoryOnly) { try { if (trailingSlash) searchPath = searchData.fullPath + "*"; else searchPath = searchData.fullPath + Path.DirectorySeparatorChar + "*"; // Get all files and dirs hnd = Win32Native.FindFirstFile(searchPath, data); if (hnd.IsInvalid) { hr = Marshal.GetLastWin32Error(); // This could happen if the dir doesn't contain any files. // Continue with the recursive search though, eventually // searchStack will become empty if (hr==Win32Native.ERROR_FILE_NOT_FOUND) continue; __Error.WinIOError(hr, searchData.fullPath); } // Add subdirs to searchStack. Exempt ReparsePoints as appropriate do { if ((0 != (data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY)) && !data.cFileName.Equals(".") && !data.cFileName.Equals("..")) { // Setup search data for the sub directory and push it into the stack SearchData searchDataSubDir = new SearchData(); // FullPath StringBuilder strBldr = new StringBuilder(searchData.fullPath); if (!trailingSlash) strBldr.Append(Path.DirectorySeparatorChar); strBldr.Append(data.cFileName); searchDataSubDir.fullPath = strBldr.ToString(); // UserPath strBldr.Length = 0; strBldr.Append(searchData.userPath); if (!trailingSlashUserPath) strBldr.Append(Path.DirectorySeparatorChar); strBldr.Append(data.cFileName); searchDataSubDir.userPath = strBldr.ToString(); // SearchOption searchDataSubDir.searchOption = searchData.searchOption; #if EXCLUDE_REPARSEPOINTS // Traverse reparse points depending on the searchoption specified if ((searchDataSubDir.searchOption == SearchOption.AllDirectories) && (0 != (data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_REPARSE_POINT))) searchDataSubDir.searchOption = SearchOption.TopDirectoryOnly; #endif searchStack.Add(searchDataSubDir); } } while (Win32Native.FindNextFile(hnd, data)); // We don't care about any error here } finally { if (hnd != null) hnd.Dispose(); } } // Execute searchCriteria against the current directory try{ if (trailingSlash) searchPath = searchData.fullPath + searchCriteria; else searchPath = searchData.fullPath + Path.DirectorySeparatorChar + searchCriteria; // Open a Find handle hnd = Win32Native.FindFirstFile(searchPath, data); if (hnd.IsInvalid) { hr = Marshal.GetLastWin32Error(); if (hr == Win32Native.ERROR_FILE_NOT_FOUND) continue; __Error.WinIOError(hr, searchData.fullPath); } numEntries = 0; // Keep asking for more matching files/dirs, add it to the list do { bool includeThis = false; // Should this file/directory be included in the output? if (includeFiles) includeThis = (0 == (data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY)); if (includeDirs) { // Don't add "." nor ".." if ((0 != (data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY)) && !data.cFileName.Equals(".") && !data.cFileName.Equals("..")) { BCLDebug.Assert(!includeThis, data.cFileName + ": current item can't be both file and dir!"); includeThis = true; } } 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++] = Path.InternalCombine(searchData.userPath, data.cFileName); } } while (Win32Native.FindNextFile(hnd, data)); // Make sure we quit with a sensible error. hr = Marshal.GetLastWin32Error(); // Demand pathdiscovery for all the parent dirs that are returned // I.e, if C:\temp\foo\bar is returned, demand C:\temp\foo if (numEntries > 0) { demandPathList.Add(GetDemandDir(searchData.fullPath, true)); } } finally { if (hnd != null) hnd.Dispose(); } } // End while } finally { Win32Native.SetErrorMode(oldMode); } // ERROR_FILE_NOT_FOUND is valid here because if the top level // dir doen't contain any subdirs and matching files then // we will get here with this errorcode from the searchStack walk if ((hr != 0) && (hr != Win32Native.ERROR_NO_MORE_FILES) && (hr != Win32Native.ERROR_FILE_NOT_FOUND)) { __Error.WinIOError(hr, searchData.fullPath); } // Demand pathdiscovery for all the parent dirs that are returned // I.e, if C:\temp\foo\bar is returned, demand C:\temp\foo if (demandPathList.Count > 0) { demandPaths = new String[demandPathList.Count]; demandPathList.CopyTo(demandPaths, 0); // No need to check for dupls as the demandPathList entries should be unique new FileIOPermission(FileIOPermissionAccess.PathDiscovery, demandPaths, false, false ).Demand(); } // 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. /* if (includeDirs && numEntries==1 && (0!=(data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY))) { String[] sa = new String[1]; sa[0] = Path.InternalCombine(searchData.userPath, 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; } // Retrieves the names of the logical drives on this machine in the // form "C:\". // // Your application must have System Info permission. // #if !PLATFORM_UNIX public static String[] GetLogicalDrives() { new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); int drives = Win32Native.GetLogicalDrives(); if (drives==0) __Error.WinIOError(); uint d = (uint)drives; int count = 0; while (d != 0) { if (((int)d & 1) != 0) count++; d >>= 1; } String[] result = new String[count]; char[] root = new char[] {'A', ':', '\\'}; d = (uint)drives; count = 0; while (d != 0) { if (((int)d & 1) != 0) { result[count++] = new String(root); } d >>= 1; root[0]++; } return result; } #else public static String[] GetLogicalDrives() { // On Unix systems, GetLogicalDrives // should return an empty string array return new String[0]; } #endif // !PLATFORM_UNIX [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static String GetDirectoryRoot(String path) { if (path==null) throw new ArgumentNullException("path"); String fullPath = Path.GetFullPathInternal(path); String root = fullPath.Substring(0, Path.GetRootLength(fullPath)); String demandPath = GetDemandDir(root, true); new FileIOPermission(FileIOPermissionAccess.PathDiscovery, new String[] { demandPath }, false, false ).Demand(); return root; } internal static String InternalGetDirectoryRoot(String path) { if (path == null) return null; return path.Substring(0, Path.GetRootLength(path)); } /*===============================CurrentDirectory=============================== **Action: Provides a getter and setter for the current directory. The original ** current DirectoryInfo is the one from which the process was started. **Returns: The current DirectoryInfo (from the getter). Void from the setter. **Arguments: The current DirectoryInfo to which to switch to the setter. **Exceptions: ==============================================================================*/ [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static String GetCurrentDirectory() { StringBuilder sb = new StringBuilder(Path.MAX_PATH + 1); if (Win32Native.GetCurrentDirectory(sb.Capacity, sb) == 0) __Error.WinIOError(); String currentDirectory = sb.ToString(); // Note that if we have somehow put our command prompt into short // file name mode (ie, by running edlin or a DOS grep, etc), then // this will return a short file name. if (currentDirectory.IndexOf('~') >= 0) { int r = Win32Native.GetLongPathName(currentDirectory, sb, sb.Capacity); if (r == 0 || r >= Path.MAX_PATH) { int errorCode = Marshal.GetLastWin32Error(); if (r >= Path.MAX_PATH) errorCode = Win32Native.ERROR_FILENAME_EXCED_RANGE; if (errorCode != Win32Native.ERROR_FILE_NOT_FOUND && errorCode != Win32Native.ERROR_PATH_NOT_FOUND && errorCode != Win32Native.ERROR_INVALID_FUNCTION && // by design - enough said. errorCode != Win32Native.ERROR_ACCESS_DENIED) __Error.WinIOError(errorCode, String.Empty); } currentDirectory = sb.ToString(); } String demandPath = GetDemandDir(currentDirectory, true); new FileIOPermission( FileIOPermissionAccess.PathDiscovery, new String[] { demandPath }, false, false ).Demand(); return currentDirectory; } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static void SetCurrentDirectory(String path) { if (path==null) throw new ArgumentNullException("value"); if (path.Length==0) throw new ArgumentException(Environment.GetResourceString("Argument_PathEmpty")); if (path.Length >= Path.MAX_PATH) throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); // This will have some large effects on the rest of the runtime // and other appdomains in this process. Demand unmanaged code. new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); String fulldestDirName = Path.GetFullPathInternal(path); if (Environment.IsWin9X() && !InternalExists(Path.GetPathRoot(fulldestDirName))) // For Win9x throw new DirectoryNotFoundException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("IO.PathNotFound_Path"), path)); if (!Win32Native.SetCurrentDirectory(fulldestDirName)) { // If path doesn't exist, this sets last error to 2 (File // not Found). This may potentially have worked correctly // on Win9x, maybe. int errorCode = Marshal.GetLastWin32Error(); if (errorCode == Win32Native.ERROR_FILE_NOT_FOUND) errorCode = Win32Native.ERROR_PATH_NOT_FOUND; __Error.WinIOError(errorCode, fulldestDirName); } } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static void Move(String sourceDirName,String destDirName) { if (sourceDirName==null) throw new ArgumentNullException("sourceDirName"); if (sourceDirName.Length==0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "sourceDirName"); if (destDirName==null) throw new ArgumentNullException("destDirName"); if (destDirName.Length==0) throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destDirName"); String fullsourceDirName = Path.GetFullPathInternal(sourceDirName); String sourcePath = GetDemandDir(fullsourceDirName, false); if (sourcePath.Length >= Path.MAX_DIRECTORY_PATH+1) throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); String fulldestDirName = Path.GetFullPathInternal(destDirName); String destPath = GetDemandDir(fulldestDirName, false); if (destPath.Length >= Path.MAX_DIRECTORY_PATH+1) throw new PathTooLongException(Environment.GetResourceString("IO.PathTooLong")); new FileIOPermission(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, new String[] { sourcePath }, false, false ).Demand(); new FileIOPermission(FileIOPermissionAccess.Write, new String[] { destPath }, false, false ).Demand(); if (CultureInfo.InvariantCulture.CompareInfo.Compare(sourcePath, destPath, CompareOptions.IgnoreCase) == 0) throw new IOException(Environment.GetResourceString("IO.IO_SourceDestMustBeDifferent")); String sourceRoot = Path.GetPathRoot(sourcePath); String destinationRoot = Path.GetPathRoot(destPath); if (CultureInfo.InvariantCulture.CompareInfo.Compare(sourceRoot, destinationRoot, CompareOptions.IgnoreCase) != 0) throw new IOException(Environment.GetResourceString("IO.IO_SourceDestMustHaveSameRoot")); if (Environment.IsWin9X() && !Directory.InternalExists(Path.GetPathRoot(fulldestDirName))) // For Win9x throw new DirectoryNotFoundException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("IO.PathNotFound_Path"), destDirName)); if (!Win32Native.MoveFile(sourceDirName, destDirName)) { int hr = Marshal.GetLastWin32Error(); if (hr == Win32Native.ERROR_FILE_NOT_FOUND) // Source dir not found { hr = Win32Native.ERROR_PATH_NOT_FOUND; __Error.WinIOError(hr, fullsourceDirName); } // This check was originally put in for Win9x (unfortunately without special casing it to be for Win9x only). We can't change the NT codepath now for backcomp reasons. if (hr == Win32Native.ERROR_ACCESS_DENIED) // WinNT throws IOException. This check is for Win9x. We can't change it for backcomp. throw new IOException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("UnauthorizedAccess_IODenied_Path"), sourceDirName), Win32Native.MakeHRFromErrorCode(hr)); __Error.WinIOError(hr, String.Empty); } } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static void Delete(String path) { String fullPath = Path.GetFullPathInternal(path); Delete(fullPath, path, false); } [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] public static void Delete(String path, bool recursive) { String fullPath = Path.GetFullPathInternal(path); Delete(fullPath, path, recursive); } // Called from DirectoryInfo as well. FullPath is fully qualified, // while the user path is used for feedback in exceptions. [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] internal static void Delete(String fullPath, String userPath, bool recursive) { String demandPath; // If not recursive, do permission check only on this directory // else check for the whole directory structure rooted below demandPath = GetDemandDir(fullPath, !recursive); // Make sure we have write permission to this directory new FileIOPermission(FileIOPermissionAccess.Write, new String[] { demandPath }, false, false ).Demand(); // Do not recursively delete through reparse points. Perhaps in a // future version we will add a new flag to control this behavior, // but for now we're much safer if we err on the conservative side. // This applies to symbolic links and mount points. Win32Native.WIN32_FILE_ATTRIBUTE_DATA data = new Win32Native.WIN32_FILE_ATTRIBUTE_DATA(); int dataInitialised = File.FillAttributeInfo(fullPath, ref data, false, true); if (dataInitialised != 0) { // Ensure we throw a DirectoryNotFoundException. if (dataInitialised == Win32Native.ERROR_FILE_NOT_FOUND) dataInitialised = Win32Native.ERROR_PATH_NOT_FOUND; __Error.WinIOError(dataInitialised, fullPath); } if (((FileAttributes)data.fileAttributes & FileAttributes.ReparsePoint) != 0) recursive = false; DeleteHelper(fullPath, userPath, recursive); } // Note that fullPath is fully qualified, while userPath may be // relative. Use userPath for all exception messages to avoid leaking // fully qualified path information. [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] private static void DeleteHelper(String fullPath, String userPath, bool recursive) { bool r; int hr; Exception ex = null; // Do not recursively delete through reparse points. Perhaps in a // future version we will add a new flag to control this behavior, // but for now we're much safer if we err on the conservative side. // This applies to symbolic links and mount points. // Note the logic to check whether fullPath is a reparse point is // in Delete(String, String, bool), and will set "recursive" to false. // Note that Win32's DeleteFile and RemoveDirectory will just delete // the reparse point itself. if (recursive) { Win32Native.WIN32_FIND_DATA data = new Win32Native.WIN32_FIND_DATA(); // Open a Find handle using (SafeFindHandle hnd = Win32Native.FindFirstFile(fullPath+Path.DirectorySeparatorChar+"*", data)) { if (hnd.IsInvalid) { hr = Marshal.GetLastWin32Error(); __Error.WinIOError(hr, fullPath); } do { bool isDir = (0!=(data.dwFileAttributes & Win32Native.FILE_ATTRIBUTE_DIRECTORY)); if (isDir) { // Skip ".", "..". if (data.cFileName.Equals(".") || data.cFileName.Equals("..")) continue; // Recurse for all directories, unless they are // reparse points. Do not follow mount points nor // symbolic links, but do delete the reparse point // itself. bool shouldRecurse = (0 == (data.dwFileAttributes & (int) FileAttributes.ReparsePoint)); if (shouldRecurse) { 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 { // Check to see if this is a mount point, and // unmount it. if (data.dwReserved0 == Win32Native.IO_REPARSE_TAG_MOUNT_POINT) { // Use full path plus a trailing '\' String mountPoint = Path.InternalCombine(fullPath, data.cFileName + Path.DirectorySeparatorChar); r = Win32Native.DeleteVolumeMountPoint(mountPoint); if (!r) { hr = Marshal.GetLastWin32Error(); try { __Error.WinIOError(hr, data.cFileName); } catch(Exception e) { if (ex == null) { ex = e; } } } } // RemoveDirectory on a symbolic link will // remove the link itself. String reparsePoint = Path.InternalCombine(fullPath, data.cFileName); r = Win32Native.RemoveDirectory(reparsePoint); if (!r) { hr = Marshal.GetLastWin32Error(); try { __Error.WinIOError(hr, data.cFileName); } catch(Exception e) { if (ex == null) { ex = e; } } } } } else { String fileName = Path.InternalCombine(fullPath, data.cFileName); r = Win32Native.DeleteFile(fileName); if (!r) { hr = Marshal.GetLastWin32Error(); try { __Error.WinIOError(hr, data.cFileName); } catch(Exception e) { if (ex == null) { ex = e; } } } } } while (Win32Native.FindNextFile(hnd, data)); // Make sure we quit with a sensible error. hr = Marshal.GetLastWin32Error(); } if (ex != null) throw ex; if (hr!=0 && hr!=Win32Native.ERROR_NO_MORE_FILES) __Error.WinIOError(hr, userPath); } r = Win32Native.RemoveDirectory(fullPath); if (!r) { hr = Marshal.GetLastWin32Error(); if (hr == Win32Native.ERROR_FILE_NOT_FOUND) // A dubious error code. hr = Win32Native.ERROR_PATH_NOT_FOUND; // This check was originally put in for Win9x (unfortunately without special casing it to be for Win9x only). We can't change the NT codepath now for backcomp reasons. if (hr == Win32Native.ERROR_ACCESS_DENIED) throw new IOException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("UnauthorizedAccess_IODenied_Path"), userPath)); __Error.WinIOError(hr, fullPath); } } // WinNT only. Win9x this code will not work. [ResourceExposure(ResourceScope.Machine)] [ResourceConsumption(ResourceScope.Machine)] private static SafeFileHandle OpenHandle(String path) { #if !FEATURE_PAL BCLDebug.Assert((Environment.OSInfo & Environment.OSName.WinNT) == Environment.OSName.WinNT,"Not running on Winnt OS"); #endif //!FEATURE_PAL String fullPath = Path.GetFullPathInternal(path); String root = Path.GetPathRoot(fullPath); if (root == fullPath && root[1] == Path.VolumeSeparatorChar) throw new ArgumentException(Environment.GetResourceString("Arg_PathIsVolume")); new FileIOPermission(FileIOPermissionAccess.Write, new String[] { GetDemandDir(fullPath, true) }, false, false ).Demand(); SafeFileHandle handle = Win32Native.SafeCreateFile ( fullPath, GENERIC_WRITE, (FileShare) (FILE_SHARE_WRITE|FILE_SHARE_DELETE), null, FileMode.Open, FILE_FLAG_BACKUP_SEMANTICS, Win32Native.NULL ); if (handle.IsInvalid) { int hr = Marshal.GetLastWin32Error(); __Error.WinIOError(hr, fullPath); } return handle; } private const int FILE_ATTRIBUTE_DIRECTORY = 0x00000010; private const int GENERIC_WRITE = unchecked((int)0x40000000); private const int FILE_SHARE_WRITE = 0x00000002; private const int FILE_SHARE_DELETE = 0x00000004; private const int OPEN_EXISTING = 0x00000003; private const int FILE_FLAG_BACKUP_SEMANTICS = 0x02000000; } }
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- WmiInstallComponent.cs
- FreezableDefaultValueFactory.cs
- GradientStop.cs
- FrameworkElement.cs
- Brushes.cs
- FixedDocument.cs
- ReaderWriterLockWrapper.cs
- ExpressionBuilder.cs
- BaseUriHelper.cs
- HwndMouseInputProvider.cs
- DescendantOverDescendantQuery.cs
- ConstantExpression.cs
- RuntimeHandles.cs
- ConfigurationProperty.cs
- Operators.cs
- SemanticValue.cs
- XmlNodeList.cs
- XmlSchemaRedefine.cs
- WindowsGraphicsWrapper.cs
- RadioButtonList.cs
- SpeechRecognitionEngine.cs
- DataTableTypeConverter.cs
- MatrixConverter.cs
- TraceInternal.cs
- ConstructorBuilder.cs
- MetadataArtifactLoaderFile.cs
- AppDomainAttributes.cs
- JsonWriter.cs
- EntityDataSourceUtil.cs
- DataFormats.cs
- XPathDescendantIterator.cs
- ListViewGroup.cs
- SelectorAutomationPeer.cs
- DoubleSumAggregationOperator.cs
- CodeEventReferenceExpression.cs
- ClientClassGenerator.cs
- TemplateParser.cs
- contentDescriptor.cs
- Compiler.cs
- ChannelManager.cs
- ResourceReader.cs
- TimeoutStream.cs
- URLIdentityPermission.cs
- JsonQNameDataContract.cs
- ServiceAuthorizationManager.cs
- HyperLinkField.cs
- AnnotationObservableCollection.cs
- C14NUtil.cs
- MouseGesture.cs
- AbandonedMutexException.cs
- WebConfigurationHostFileChange.cs
- StronglyTypedResourceBuilder.cs
- ActiveXSite.cs
- MediaScriptCommandRoutedEventArgs.cs
- WebBrowser.cs
- ErrorInfoXmlDocument.cs
- SubMenuStyleCollection.cs
- SwitchLevelAttribute.cs
- ServiceOperationWrapper.cs
- DataGridColumnHeaderCollection.cs
- Regex.cs
- XmlNodeReader.cs
- ListMarkerLine.cs
- ArraySet.cs
- DialogWindow.cs
- FileRecordSequenceCompletedAsyncResult.cs
- RequestCacheEntry.cs
- DataGridViewComboBoxCell.cs
- QueryOutputWriter.cs
- FileNotFoundException.cs
- PackageStore.cs
- SiteMapNodeItem.cs
- SQLDateTimeStorage.cs
- HierarchicalDataSourceControl.cs
- FileCodeGroup.cs
- CodeSubDirectory.cs
- StretchValidation.cs
- NetworkStream.cs
- ArgumentsParser.cs
- WindowsPrincipal.cs
- WebPartManagerInternals.cs
- LoaderAllocator.cs
- SqlDataSourceQueryEditorForm.cs
- GroupBox.cs
- WebPartVerbCollection.cs
- DataGridView.cs
- DataGridViewToolTip.cs
- WebPartEditorCancelVerb.cs
- RenderData.cs
- XPathAncestorQuery.cs
- TransactionValidationBehavior.cs
- input.cs
- IndexedSelectQueryOperator.cs
- RayHitTestParameters.cs
- TreeBuilder.cs
- AuthenticateEventArgs.cs
- RectAnimationBase.cs
- _SSPIWrapper.cs
- panel.cs
- PolicyAssertionCollection.cs