private bool IsResultIncluded(ref Interop.mincore.WIN32_FIND_DATA findData, out TSource result) { Contract.Requires(findData.cFileName.Length != 0 && !Path.IsPathRooted(findData.cFileName), "Expected file system enumeration to not have empty file/directory name and not have rooted name"); return(_resultHandler.IsResultIncluded(_searchData.FullPath, _searchData.UserPath, ref findData, out result)); }
[System.Security.SecurityCritical] // auto-generated private void AddSearchableDirsToStack(SearchData localSearchData) { Contract.Requires(localSearchData != null); String searchPath = Path.Combine(localSearchData.fullPath, "*"); SafeFindHandle hnd = null; Interop.mincore.WIN32_FIND_DATA data = new Interop.mincore.WIN32_FIND_DATA(); try { // Get all files and dirs hnd = Interop.mincore.FindFirstFile(searchPath, ref data); if (hnd.IsInvalid) { int errorCode = 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 (errorCode == Interop.mincore.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.mincore.Errors.ERROR_NO_MORE_FILES || errorCode == Interop.mincore.Errors.ERROR_PATH_NOT_FOUND) { return; } HandleError(errorCode, localSearchData.fullPath); } // Add subdirs to searchStack. Exempt ReparsePoints as appropriate int incr = 0; do { if (Win32FileSystemEnumerableHelpers.IsDir(data)) { Debug.Assert(data.cFileName.Length != 0 && !Path.IsPathRooted(data.cFileName), "Expected file system enumeration to not have empty file/directory name and not have rooted name"); String tempFullPath = Path.Combine(localSearchData.fullPath, data.cFileName); String tempUserPath = Path.Combine(localSearchData.userPath, data.cFileName); SearchOption option = localSearchData.searchOption; // Setup search data for the sub directory and push it into the stack SearchData searchDataSubDir = new SearchData(tempFullPath, tempUserPath, option); _searchStack.Insert(incr++, searchDataSubDir); } } while (Interop.mincore.FindNextFile(hnd, ref data)); // We don't care about errors here } finally { if (hnd != null) { hnd.Dispose(); } } }
internal SearchResult(String fullPath, String userPath, Interop.mincore.WIN32_FIND_DATA findData) { Contract.Requires(fullPath != null); Contract.Requires(userPath != null); this._fullPath = fullPath; this._userPath = userPath; this._findData = findData; }
private SearchResult CreateSearchResult(SearchData localSearchData, Interop.mincore.WIN32_FIND_DATA findData) { string findData_fileName = findData.cFileName; Contract.Requires(findData_fileName.Length != 0 && !Path.IsPathRooted(findData_fileName), "Expected file system enumeration to not have empty file/directory name and not have rooted name"); String userPathFinal = Path.Combine(localSearchData.userPath, findData_fileName); String fullPathFinal = Path.Combine(localSearchData.fullPath, findData_fileName); return(new SearchResult(fullPathFinal, userPathFinal, findData)); }
private void CommonInit() { Debug.Assert(_searchCriteria != null, "searchCriteria should be initialized"); // Execute searchCriteria against the current directory PathHelpers.ThrowIfEmptyOrRootedPath(_searchCriteria); string searchPath = Path.Combine(_searchData.FullPath, _searchCriteria); Interop.mincore.WIN32_FIND_DATA data = new Interop.mincore.WIN32_FIND_DATA(); // Open a Find handle _hnd = Interop.mincore.FindFirstFile(searchPath, ref data); if (_hnd.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); if (errorCode != Interop.mincore.Errors.ERROR_FILE_NOT_FOUND && errorCode != Interop.mincore.Errors.ERROR_NO_MORE_FILES) { HandleError(errorCode, _searchData.FullPath); } else { // flag this as empty only if we're searching just top directory // Used in fast path for top directory only _empty = _searchOption == SearchOption.TopDirectoryOnly; } } // fast path for TopDirectoryOnly. If we have a result, go ahead and set it to // current. If empty, dispose handle. if (_searchOption == SearchOption.TopDirectoryOnly) { if (_empty) { _hnd.Dispose(); } else { TSource result; if (IsResultIncluded(ref data, out result)) { current = result; } } } // for AllDirectories, we first recurse into dirs, so cleanup and add searchData // to the list else { _hnd.Dispose(); _searchList = new List <PathPair>(); _searchList.Add(_searchData); } }
public Win32FileSystemObject(string fullPath, Interop.mincore.WIN32_FIND_DATA findData, bool asDirectory) { _asDirectory = asDirectory; _fullPath = fullPath; // Copy the information to data _data.fileAttributes = (int)findData.dwFileAttributes; _data.ftCreationTimeLow = findData.ftCreationTime.dwLowDateTime; _data.ftCreationTimeHigh = findData.ftCreationTime.dwHighDateTime; _data.ftLastAccessTimeLow = findData.ftLastAccessTime.dwLowDateTime; _data.ftLastAccessTimeHigh = findData.ftLastAccessTime.dwHighDateTime; _data.ftLastWriteTimeLow = findData.ftLastWriteTime.dwLowDateTime; _data.ftLastWriteTimeHigh = findData.ftLastWriteTime.dwHighDateTime; _data.fileSizeHigh = findData.nFileSizeHigh; _data.fileSizeLow = findData.nFileSizeLow; _dataInitialized = 0; }
internal override bool IsResultIncluded(string fullPath, string userPath, ref Interop.mincore.WIN32_FIND_DATA findData, out string result) { if ((_includeFiles && Win32FileSystemEnumerableHelpers.IsFile(ref findData)) || (_includeDirs && Win32FileSystemEnumerableHelpers.IsDir(ref findData))) { result = Path.Combine(userPath, findData.cFileName); return(true); } result = null; return(false); }
internal abstract bool IsResultIncluded(string fullPath, string userPath, ref Interop.mincore.WIN32_FIND_DATA findData, out TSource result);
[SecurityCritical] // auto-generated private void AddSearchableDirsToList(PathPair localSearchData) { string searchPath = Path.Combine(localSearchData.FullPath, "*"); SafeFindHandle hnd = null; Interop.mincore.WIN32_FIND_DATA data = new Interop.mincore.WIN32_FIND_DATA(); try { // Get all files and dirs hnd = Interop.mincore.FindFirstFile(searchPath, ref data); if (hnd.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); // This could happen if the dir doesn't contain any files. // Continue with the recursive search though, eventually // _searchList will become empty if (errorCode == Interop.mincore.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.mincore.Errors.ERROR_NO_MORE_FILES || errorCode == Interop.mincore.Errors.ERROR_PATH_NOT_FOUND) { return; } HandleError(errorCode, localSearchData.FullPath); } // Add subdirs to _searchList. Exempt ReparsePoints as appropriate int initialCount = _searchList.Count; do { if (Win32FileSystemEnumerableHelpers.IsDir(ref data)) { Debug.Assert(data.cFileName.Length != 0 && !Path.IsPathRooted(data.cFileName), "Expected file system enumeration to not have empty file/directory name and not have rooted name"); string tempFullPath = Path.Combine(localSearchData.FullPath, data.cFileName); string tempUserPath = Path.Combine(localSearchData.UserPath, data.cFileName); // Setup search data for the sub directory and push it into the list PathPair searchDataSubDir = new PathPair(tempUserPath, tempFullPath); Debug.Assert(_searchList != null, "_searchList should not be null"); _searchList.Add(searchDataSubDir); } } while (Interop.mincore.FindNextFile(hnd, ref data)); // Reverse the items just added to maintain FIFO order if (_searchList.Count > initialCount) { _searchList.Reverse(initialCount, _searchList.Count - initialCount); } // We don't care about errors here } finally { if (hnd != null) { hnd.Dispose(); } } }
[System.Security.SecurityCritical] // auto-generated internal static int FillAttributeInfo(String path, ref Interop.mincore.WIN32_FILE_ATTRIBUTE_DATA data, bool tryagain, bool returnErrorOnNotFound) { int errorCode = 0; if (tryagain) // someone has a handle to the file open, or other error { Interop.mincore.WIN32_FIND_DATA findData; findData = new Interop.mincore.WIN32_FIND_DATA(); // Remove trialing slash since this can cause grief to FindFirstFile. You will get an invalid argument error String tempPath = path.TrimEnd(PathHelpers.DirectorySeparatorChars); // For floppy drives, normally the OS will pop up a dialog saying // there is no disk in drive A:, please insert one. We don't want that. // SetErrorMode will let us disable this, but we should set the error // mode back, since this may have wide-ranging effects. uint oldMode = Interop.mincore.SetErrorMode(Interop.mincore.SEM_FAILCRITICALERRORS); try { bool error = false; SafeFindHandle handle = Interop.mincore.FindFirstFile(tempPath, ref findData); try { if (handle.IsInvalid) { error = true; errorCode = Marshal.GetLastWin32Error(); if (errorCode == Interop.mincore.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.mincore.Errors.ERROR_PATH_NOT_FOUND || errorCode == Interop.mincore.Errors.ERROR_NOT_READY) // floppy device not ready { if (!returnErrorOnNotFound) { // Return default value for backward compatibility errorCode = 0; data.fileAttributes = -1; } } return(errorCode); } } finally { // Close the Win32 handle try { handle.Dispose(); } catch { // if we're already returning an error, don't throw another one. if (!error) { throw Win32Marshal.GetExceptionForLastWin32Error(); } } } } finally { Interop.mincore.SetErrorMode(oldMode); } // Copy the information to data data.PopulateFrom(ref findData); } else { // For floppy drives, normally the OS will pop up a dialog saying // there is no disk in drive A:, please insert one. We don't want that. // SetErrorMode will let us disable this, but we should set the error // mode back, since this may have wide-ranging effects. bool success = false; uint oldMode = Interop.mincore.SetErrorMode(Interop.mincore.SEM_FAILCRITICALERRORS); try { success = Interop.mincore.GetFileAttributesEx(path, Interop.mincore.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data); } finally { Interop.mincore.SetErrorMode(oldMode); } if (!success) { errorCode = Marshal.GetLastWin32Error(); if (errorCode != Interop.mincore.Errors.ERROR_FILE_NOT_FOUND && errorCode != Interop.mincore.Errors.ERROR_PATH_NOT_FOUND && errorCode != Interop.mincore.Errors.ERROR_NOT_READY) // floppy device not ready { // In case someone latched onto the file. Take the perf hit only for failure return(FillAttributeInfo(path, ref data, true, returnErrorOnNotFound)); } else { if (!returnErrorOnNotFound) { // Return default value for backward compatibility errorCode = 0; data.fileAttributes = -1; } } } } return(errorCode); }
[SecurityCritical] // auto-generated internal static bool IsFile(ref Interop.mincore.WIN32_FIND_DATA data) { return(0 == (data.dwFileAttributes & Interop.mincore.FileAttributes.FILE_ATTRIBUTE_DIRECTORY)); }
[System.Security.SecurityCritical] // auto-generated private static void RemoveDirectoryHelper(String fullPath, bool recursive, bool throwOnTopLevelDirectoryNotFound) { bool r; int errorCode; 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) { Interop.mincore.WIN32_FIND_DATA data = new Interop.mincore.WIN32_FIND_DATA(); // Open a Find handle using (SafeFindHandle hnd = Interop.mincore.FindFirstFile(fullPath + PathHelpers.DirectorySeparatorCharAsString + "*", ref data)) { if (hnd.IsInvalid) throw Win32Marshal.GetExceptionForLastWin32Error(fullPath); do { bool isDir = (0 != (data.dwFileAttributes & Interop.mincore.FileAttributes.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.Combine(fullPath, data.cFileName); try { RemoveDirectoryHelper(newFullPath, recursive, false); } catch (Exception e) { if (ex == null) ex = e; } } else { // Check to see if this is a mount point, and // unmount it. if (data.dwReserved0 == Interop.mincore.IOReparseOptions.IO_REPARSE_TAG_MOUNT_POINT) { // Use full path plus a trailing '\' String mountPoint = Path.Combine(fullPath, data.cFileName + PathHelpers.DirectorySeparatorCharAsString); errorCode = Helpers.DeleteVolumeMountPoint(mountPoint); if (errorCode != Interop.mincore.Errors.ERROR_SUCCESS && errorCode != Interop.mincore.Errors.ERROR_PATH_NOT_FOUND) { try { throw Win32Marshal.GetExceptionForWin32Error(errorCode, data.cFileName); } catch (Exception e) { if (ex == null) ex = e; } } } // RemoveDirectory on a symbolic link will // remove the link itself. String reparsePoint = Path.Combine(fullPath, data.cFileName); r = Interop.mincore.RemoveDirectory(reparsePoint); if (!r) { errorCode = Marshal.GetLastWin32Error(); if (errorCode != Interop.mincore.Errors.ERROR_PATH_NOT_FOUND) { try { throw Win32Marshal.GetExceptionForWin32Error(errorCode, data.cFileName); } catch (Exception e) { if (ex == null) ex = e; } } } } } else { String fileName = Path.Combine(fullPath, data.cFileName); r = Interop.mincore.DeleteFile(fileName); if (!r) { errorCode = Marshal.GetLastWin32Error(); if (errorCode != Interop.mincore.Errors.ERROR_FILE_NOT_FOUND) { try { throw Win32Marshal.GetExceptionForWin32Error(errorCode, data.cFileName); } catch (Exception e) { if (ex == null) ex = e; } } } } } while (Interop.mincore.FindNextFile(hnd, ref data)); // Make sure we quit with a sensible error. errorCode = Marshal.GetLastWin32Error(); } if (ex != null) throw ex; if (errorCode != 0 && errorCode != Interop.mincore.Errors.ERROR_NO_MORE_FILES) throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath); } r = Interop.mincore.RemoveDirectory(fullPath); if (!r) { errorCode = Marshal.GetLastWin32Error(); if (errorCode == Interop.mincore.Errors.ERROR_FILE_NOT_FOUND) // A dubious error code. errorCode = Interop.mincore.Errors.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 (errorCode == Interop.mincore.Errors.ERROR_ACCESS_DENIED) throw new IOException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, fullPath)); // don't throw the DirectoryNotFoundException since this is a subdir and // there could be a race condition between two Directory.Delete callers if (errorCode == Interop.mincore.Errors.ERROR_PATH_NOT_FOUND && !throwOnTopLevelDirectoryNotFound) return; throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath); } }
[System.Security.SecurityCritical] // auto-generated internal static int FillAttributeInfo(String path, ref Interop.mincore.WIN32_FILE_ATTRIBUTE_DATA data, bool tryagain, bool returnErrorOnNotFound) { int errorCode = 0; if (tryagain) // someone has a handle to the file open, or other error { Interop.mincore.WIN32_FIND_DATA findData; findData = new Interop.mincore.WIN32_FIND_DATA(); // Remove trialing slash since this can cause grief to FindFirstFile. You will get an invalid argument error String tempPath = path.TrimEnd(PathHelpers.DirectorySeparatorChars); // For floppy drives, normally the OS will pop up a dialog saying // there is no disk in drive A:, please insert one. We don't want that. // SetErrorMode will let us disable this, but we should set the error // mode back, since this may have wide-ranging effects. uint oldMode = Interop.mincore.SetErrorMode(Interop.mincore.SEM_FAILCRITICALERRORS); try { bool error = false; SafeFindHandle handle = Interop.mincore.FindFirstFile(tempPath, ref findData); try { if (handle.IsInvalid) { error = true; errorCode = Marshal.GetLastWin32Error(); if (errorCode == Interop.mincore.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.mincore.Errors.ERROR_PATH_NOT_FOUND || errorCode == Interop.mincore.Errors.ERROR_NOT_READY) // floppy device not ready { if (!returnErrorOnNotFound) { // Return default value for backward compatibility errorCode = 0; data.fileAttributes = -1; } } return errorCode; } } finally { // Close the Win32 handle try { handle.Dispose(); } catch { // if we're already returning an error, don't throw another one. if (!error) { throw Win32Marshal.GetExceptionForLastWin32Error(); } } } } finally { Interop.mincore.SetErrorMode(oldMode); } // Copy the information to data data.PopulateFrom(findData); } else { // For floppy drives, normally the OS will pop up a dialog saying // there is no disk in drive A:, please insert one. We don't want that. // SetErrorMode will let us disable this, but we should set the error // mode back, since this may have wide-ranging effects. bool success = false; uint oldMode = Interop.mincore.SetErrorMode(Interop.mincore.SEM_FAILCRITICALERRORS); try { success = Interop.mincore.GetFileAttributesEx(path, Interop.mincore.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data); } finally { Interop.mincore.SetErrorMode(oldMode); } if (!success) { errorCode = Marshal.GetLastWin32Error(); if (errorCode != Interop.mincore.Errors.ERROR_FILE_NOT_FOUND && errorCode != Interop.mincore.Errors.ERROR_PATH_NOT_FOUND && errorCode != Interop.mincore.Errors.ERROR_NOT_READY) // floppy device not ready { // In case someone latched onto the file. Take the perf hit only for failure return FillAttributeInfo(path, ref data, true, returnErrorOnNotFound); } else { if (!returnErrorOnNotFound) { // Return default value for backward compatibility errorCode = 0; data.fileAttributes = -1; } } } } return errorCode; }
internal FileInfo(string fullPath, ref Interop.mincore.WIN32_FIND_DATA findData) : this(fullPath, findData.cFileName) { Debug.Assert(string.Equals(findData.cFileName, Path.GetFileName(fullPath), StringComparison.Ordinal)); Init(ref findData); }
internal override bool IsResultIncluded(string fullPath, string userPath, ref Interop.mincore.WIN32_FIND_DATA findData, out FileSystemInfo result) { if (Win32FileSystemEnumerableHelpers.IsFile(ref findData)) { string fullPathFinal = Path.Combine(fullPath, findData.cFileName); result = new FileInfo(fullPathFinal, ref findData); return(true); } else if (Win32FileSystemEnumerableHelpers.IsDir(ref findData)) { string fullPathFinal = Path.Combine(fullPath, findData.cFileName); result = new DirectoryInfo(fullPathFinal, ref findData); return(true); } result = null; return(false); }
[SecurityCritical] // auto-generated internal static bool IsDir(ref Interop.mincore.WIN32_FIND_DATA data) { // Don't add "." nor ".." return((0 != (data.dwFileAttributes & Interop.mincore.FileAttributes.FILE_ATTRIBUTE_DIRECTORY)) && !data.cFileName.Equals(".") && !data.cFileName.Equals("..")); }
private static bool ShouldUseWinRT(string fullPath, bool isCreate) { // The purpose of this method is to determine if we can access a path // via Win32 or if we need to fallback to WinRT. // We prefer Win32 since it is faster, WinRT's APIs eventually just // call into Win32 after all, but it doesn't provide access to, // brokered paths (like Pictures or Documents) nor does it handle // placeholder files. So we'd like to fall back to WinRT whenever // we can't access a path, or if it known to be a placeholder file. bool useWinRt = false; do { // first use GetFileAttributesEx as it is faster than FindFirstFile and requires minimum permissions Interop.mincore.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.mincore.WIN32_FILE_ATTRIBUTE_DATA(); if (Interop.mincore.GetFileAttributesEx(fullPath, Interop.mincore.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data)) { // got the attributes if ((data.fileAttributes & Interop.mincore.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) != 0 || (data.fileAttributes & Interop.mincore.FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT) == 0) { // we have a directory or a file that is not a reparse point // useWinRt = false; break; } else { // we need to get the find data to determine if it is a placeholder file Interop.mincore.WIN32_FIND_DATA findData = new Interop.mincore.WIN32_FIND_DATA(); using (SafeFindHandle handle = Interop.mincore.FindFirstFile(fullPath, ref findData)) { if (!handle.IsInvalid) { // got the find data, use WinRT for placeholder files Debug.Assert((findData.dwFileAttributes & Interop.mincore.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) == 0); Debug.Assert((findData.dwFileAttributes & Interop.mincore.FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT) != 0); useWinRt = findData.dwReserved0 == Interop.mincore.IOReparseOptions.IO_REPARSE_TAG_FILE_PLACEHOLDER; break; } } } } int error = Marshal.GetLastWin32Error(); Debug.Assert(error != Interop.mincore.Errors.ERROR_SUCCESS); if (error == Interop.mincore.Errors.ERROR_ACCESS_DENIED) { // The path was not accessible with Win32, so try WinRT useWinRt = true; break; } else if (error != Interop.mincore.Errors.ERROR_PATH_NOT_FOUND && error != Interop.mincore.Errors.ERROR_FILE_NOT_FOUND) { // We hit some error other than ACCESS_DENIED or NOT_FOUND, // Default to Win32 to provide most accurate error behavior break; } // error was ERROR_PATH_NOT_FOUND or ERROR_FILE_NOT_FOUND // if we are creating a file/directory we cannot assume that Win32 will have access to // the parent directory, so we walk up the path. fullPath = PathHelpers.GetDirectoryNameInternal(fullPath); // only walk up the path if we are creating a file/directory and not at the root } while (isCreate && !String.IsNullOrEmpty(fullPath)); return useWinRt; }
private static bool ShouldUseWinRT(string fullPath, bool isCreate) { // The purpose of this method is to determine if we can access a path // via Win32 or if we need to fallback to WinRT. // We prefer Win32 since it is faster, WinRT's APIs eventually just // call into Win32 after all, but it doesn't provide access to, // brokered paths (like Pictures or Documents) nor does it handle // placeholder files. So we'd like to fall back to WinRT whenever // we can't access a path, or if it known to be a placeholder file. bool useWinRt = false; do { // first use GetFileAttributesEx as it is faster than FindFirstFile and requires minimum permissions Interop.mincore.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.mincore.WIN32_FILE_ATTRIBUTE_DATA(); if (Interop.mincore.GetFileAttributesEx(fullPath, Interop.mincore.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data)) { // got the attributes if ((data.fileAttributes & Interop.mincore.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) != 0 || (data.fileAttributes & Interop.mincore.FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT) == 0) { // we have a directory or a file that is not a reparse point // useWinRt = false; break; } else { // we need to get the find data to determine if it is a placeholder file Interop.mincore.WIN32_FIND_DATA findData = new Interop.mincore.WIN32_FIND_DATA(); using (SafeFindHandle handle = Interop.mincore.FindFirstFile(fullPath, ref findData)) { if (!handle.IsInvalid) { // got the find data, use WinRT for placeholder files Debug.Assert((findData.dwFileAttributes & Interop.mincore.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) == 0); Debug.Assert((findData.dwFileAttributes & Interop.mincore.FileAttributes.FILE_ATTRIBUTE_REPARSE_POINT) != 0); useWinRt = findData.dwReserved0 == Interop.mincore.IOReparseOptions.IO_REPARSE_TAG_FILE_PLACEHOLDER; break; } } } } int error = Marshal.GetLastWin32Error(); Debug.Assert(error != Interop.mincore.Errors.ERROR_SUCCESS); if (error == Interop.mincore.Errors.ERROR_ACCESS_DENIED) { // The path was not accessible with Win32, so try WinRT useWinRt = true; break; } else if (error != Interop.mincore.Errors.ERROR_PATH_NOT_FOUND && error != Interop.mincore.Errors.ERROR_FILE_NOT_FOUND) { // We hit some error other than ACCESS_DENIED or NOT_FOUND, // Default to Win32 to provide most accurate error behavior break; } // error was ERROR_PATH_NOT_FOUND or ERROR_FILE_NOT_FOUND // if we are creating a file/directory we cannot assume that Win32 will have access to // the parent directory, so we walk up the path. fullPath = PathHelpers.GetDirectoryNameInternal(fullPath); // only walk up the path if we are creating a file/directory and not at the root } while (isCreate && !String.IsNullOrEmpty(fullPath)); return(useWinRt); }
public override bool MoveNext() { Interop.mincore.WIN32_FIND_DATA data = new Interop.mincore.WIN32_FIND_DATA(); switch (state) { case STATE_INIT: { if (_empty) { state = STATE_FINISH; goto case STATE_FINISH; } if (_searchOption == SearchOption.TopDirectoryOnly) { state = STATE_FIND_NEXT_FILE; if (current != null) { return(true); } else { goto case STATE_FIND_NEXT_FILE; } } else { state = STATE_SEARCH_NEXT_DIR; goto case STATE_SEARCH_NEXT_DIR; } } case STATE_SEARCH_NEXT_DIR: { Debug.Assert(_searchOption != SearchOption.TopDirectoryOnly, "should not reach this code path if searchOption == TopDirectoryOnly"); Debug.Assert(_searchList != null, "_searchList should not be null"); // Traverse directory structure. We need to get '*' while (_searchList.Count > 0) { int index = _searchList.Count - 1; _searchData = _searchList[index]; Debug.Assert((_searchData.FullPath != null), "fullpath can't be null!"); _searchList.RemoveAt(index); // Traverse the subdirs AddSearchableDirsToList(_searchData); // Execute searchCriteria against the current directory string searchPath = Path.Combine(_searchData.FullPath, _searchCriteria); // Open a Find handle _hnd = Interop.mincore.FindFirstFile(searchPath, ref data); if (_hnd.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); if (errorCode == Interop.mincore.Errors.ERROR_FILE_NOT_FOUND || errorCode == Interop.mincore.Errors.ERROR_NO_MORE_FILES || errorCode == Interop.mincore.Errors.ERROR_PATH_NOT_FOUND) { continue; } _hnd.Dispose(); HandleError(errorCode, _searchData.FullPath); } state = STATE_FIND_NEXT_FILE; TSource result; if (IsResultIncluded(ref data, out result)) { current = result; return(true); } else { goto case STATE_FIND_NEXT_FILE; } } state = STATE_FINISH; goto case STATE_FINISH; } case STATE_FIND_NEXT_FILE: { if (_hnd != null) { // Keep asking for more matching files/dirs, add it to the list while (Interop.mincore.FindNextFile(_hnd, ref data)) { TSource result; if (IsResultIncluded(ref data, out result)) { current = result; return(true); } } // Make sure we quit with a sensible error. int errorCode = Marshal.GetLastWin32Error(); if (_hnd != null) { _hnd.Dispose(); } // ERROR_FILE_NOT_FOUND is valid here because if the top level // dir doesn't contain any subdirs and matching files then // we will get here with this errorcode from the _searchList walk if ((errorCode != 0) && (errorCode != Interop.mincore.Errors.ERROR_NO_MORE_FILES) && (errorCode != Interop.mincore.Errors.ERROR_FILE_NOT_FOUND)) { HandleError(errorCode, _searchData.FullPath); } } if (_searchOption == SearchOption.TopDirectoryOnly) { state = STATE_FINISH; goto case STATE_FINISH; } else { state = STATE_SEARCH_NEXT_DIR; goto case STATE_SEARCH_NEXT_DIR; } } case STATE_FINISH: { Dispose(); break; } } return(false); }
[System.Security.SecurityCritical] // auto-generated private static void RemoveDirectoryHelper(string fullPath, bool recursive, bool throwOnTopLevelDirectoryNotFound) { bool r; int errorCode; 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) { Interop.mincore.WIN32_FIND_DATA data = new Interop.mincore.WIN32_FIND_DATA(); // Open a Find handle using (SafeFindHandle hnd = Interop.mincore.FindFirstFile(Directory.EnsureTrailingDirectorySeparator(fullPath) + "*", ref data)) { if (hnd.IsInvalid) { throw Win32Marshal.GetExceptionForLastWin32Error(fullPath); } do { bool isDir = (0 != (data.dwFileAttributes & Interop.mincore.FileAttributes.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.Combine(fullPath, data.cFileName); try { RemoveDirectoryHelper(newFullPath, recursive, false); } catch (Exception e) { if (ex == null) { ex = e; } } } else { // Check to see if this is a mount point, and // unmount it. if (data.dwReserved0 == Interop.mincore.IOReparseOptions.IO_REPARSE_TAG_MOUNT_POINT) { // Use full path plus a trailing '\' String mountPoint = Path.Combine(fullPath, data.cFileName + PathHelpers.DirectorySeparatorCharAsString); if (!Interop.mincore.DeleteVolumeMountPoint(mountPoint)) { errorCode = Marshal.GetLastWin32Error(); if (errorCode != Interop.mincore.Errors.ERROR_SUCCESS && errorCode != Interop.mincore.Errors.ERROR_PATH_NOT_FOUND) { try { throw Win32Marshal.GetExceptionForWin32Error(errorCode, data.cFileName); } catch (Exception e) { if (ex == null) { ex = e; } } } } } // RemoveDirectory on a symbolic link will // remove the link itself. String reparsePoint = Path.Combine(fullPath, data.cFileName); r = Interop.mincore.RemoveDirectory(reparsePoint); if (!r) { errorCode = Marshal.GetLastWin32Error(); if (errorCode != Interop.mincore.Errors.ERROR_PATH_NOT_FOUND) { try { throw Win32Marshal.GetExceptionForWin32Error(errorCode, data.cFileName); } catch (Exception e) { if (ex == null) { ex = e; } } } } } } else { String fileName = Path.Combine(fullPath, data.cFileName); r = Interop.mincore.DeleteFile(fileName); if (!r) { errorCode = Marshal.GetLastWin32Error(); if (errorCode != Interop.mincore.Errors.ERROR_FILE_NOT_FOUND) { try { throw Win32Marshal.GetExceptionForWin32Error(errorCode, data.cFileName); } catch (Exception e) { if (ex == null) { ex = e; } } } } } } while (Interop.mincore.FindNextFile(hnd, ref data)); // Make sure we quit with a sensible error. errorCode = Marshal.GetLastWin32Error(); } if (ex != null) { throw ex; } if (errorCode != 0 && errorCode != Interop.mincore.Errors.ERROR_NO_MORE_FILES) { throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath); } } r = Interop.mincore.RemoveDirectory(fullPath); if (!r) { errorCode = Marshal.GetLastWin32Error(); if (errorCode == Interop.mincore.Errors.ERROR_FILE_NOT_FOUND) // A dubious error code. { errorCode = Interop.mincore.Errors.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 (errorCode == Interop.mincore.Errors.ERROR_ACCESS_DENIED) { throw new IOException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, fullPath)); } // don't throw the DirectoryNotFoundException since this is a subdir and // there could be a race condition between two Directory.Delete callers if (errorCode == Interop.mincore.Errors.ERROR_PATH_NOT_FOUND && !throwOnTopLevelDirectoryNotFound) { return; } throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath); } }
internal void Init(ref Interop.mincore.WIN32_FIND_DATA findData) { // Copy the information to data _data.PopulateFrom(ref findData); _dataInitialized = 0; }