private static unsafe void ThrowExceptionEncryptDecryptFail(string fullPath) { int errorCode = Marshal.GetLastWin32Error(); if (errorCode == Interop.Errors.ERROR_ACCESS_DENIED) { // Check to see if the file system support the Encrypted File System (EFS) string name = DriveInfoInternal.NormalizeDriveName(Path.GetPathRoot(fullPath) !); using (DisableMediaInsertionPrompt.Create()) { if (!Interop.Kernel32.GetVolumeInformation(name, null, 0, null, null, out int fileSystemFlags, null, 0)) { errorCode = Marshal.GetLastWin32Error(); throw Win32Marshal.GetExceptionForWin32Error(errorCode, name); } if ((fileSystemFlags & Interop.Kernel32.FILE_SUPPORTS_ENCRYPTION) == 0) { throw new NotSupportedException(SR.PlatformNotSupported_FileEncryption); } } } throw Win32Marshal.GetExceptionForWin32Error(errorCode, fullPath); }
private static unsafe SafeFileHandle CreateFileHandle(string fullPath, FileMode mode, FileSystemRights rights, FileShare share, FileOptions options, FileSecurity security) { Debug.Assert(fullPath != null); // Must use a valid Win32 constant if (mode == FileMode.Append) { mode = FileMode.OpenOrCreate; } // For mitigating local elevation of privilege attack through named pipes make sure we always call CreateFile with SECURITY_ANONYMOUS so that the // named pipe server can't impersonate a high privileged client security context (note that this is the effective default on CreateFile2) // SECURITY_SQOS_PRESENT flags that a SECURITY_ flag is present. int flagsAndAttributes = (int)options | Interop.Kernel32.SecurityOptions.SECURITY_SQOS_PRESENT | Interop.Kernel32.SecurityOptions.SECURITY_ANONYMOUS; SafeFileHandle handle; fixed(byte *pSecurityDescriptor = security.GetSecurityDescriptorBinaryForm()) { var secAttrs = new Interop.Kernel32.SECURITY_ATTRIBUTES { nLength = (uint)sizeof(Interop.Kernel32.SECURITY_ATTRIBUTES), bInheritHandle = ((share & FileShare.Inheritable) != 0) ? Interop.BOOL.TRUE : Interop.BOOL.FALSE, lpSecurityDescriptor = (IntPtr)pSecurityDescriptor }; using (DisableMediaInsertionPrompt.Create()) { handle = Interop.Kernel32.CreateFile(fullPath, (int)rights, share, ref secAttrs, mode, flagsAndAttributes, IntPtr.Zero); ValidateFileHandle(handle, fullPath); } } return(handle); }
private unsafe SafeFileHandle CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); int fAccess = ((_access & FileAccess.Read) == FileAccess.Read ? GENERIC_READ : 0) | ((_access & FileAccess.Write) == FileAccess.Write ? GENERIC_WRITE : 0); // Our Inheritable bit was stolen from Windows, but should be set in // the security attributes class. Don't leave this bit set. share &= ~FileShare.Inheritable; // Must use a valid Win32 constant here... if (mode == FileMode.Append) { mode = FileMode.OpenOrCreate; } int flagsAndAttributes = (int)options; // For mitigating local elevation of privilege attack through named pipes // make sure we always call CreateFile with SECURITY_ANONYMOUS so that the // named pipe server can't impersonate a high privileged client security context // (note that this is the effective default on CreateFile2) flagsAndAttributes |= (Interop.Kernel32.SecurityOptions.SECURITY_SQOS_PRESENT | Interop.Kernel32.SecurityOptions.SECURITY_ANONYMOUS); using (DisableMediaInsertionPrompt.Create()) { Debug.Assert(_path != null); return(ValidateFileHandle( Interop.Kernel32.CreateFile(_path, fAccess, share, ref secAttrs, mode, flagsAndAttributes, IntPtr.Zero))); } }
private unsafe SafeFileHandle CreateFile2OpenHandle(FileMode mode, FileShare share, FileOptions options) { Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs = GetSecAttrs(share); int access = ((_access & FileAccess.Read) == FileAccess.Read ? GENERIC_READ : 0) | ((_access & FileAccess.Write) == FileAccess.Write ? GENERIC_WRITE : 0); // Our Inheritable bit was stolen from Windows, but should be set in // the security attributes class. Don't leave this bit set. share &= ~FileShare.Inheritable; // Must use a valid Win32 constant here... if (mode == FileMode.Append) { mode = FileMode.OpenOrCreate; } Interop.Kernel32.CREATEFILE2_EXTENDED_PARAMETERS parameters = new Interop.Kernel32.CREATEFILE2_EXTENDED_PARAMETERS(); parameters.dwSize = (uint)sizeof(Interop.Kernel32.CREATEFILE2_EXTENDED_PARAMETERS); parameters.dwFileFlags = (uint)options; parameters.lpSecurityAttributes = &secAttrs; using (DisableMediaInsertionPrompt.Create()) { return(ValidateFileHandle(Interop.FileApiInterop.CreateFile2FromApp( lpFileName: _path, dwDesiredAccess: access, dwShareMode: share, dwCreationDisposition: mode, pCreateExParams: ref parameters))); } }
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.Kernel32.WIN32_FIND_DATA data = new Interop.Kernel32.WIN32_FIND_DATA(); using (DisableMediaInsertionPrompt.Create()) { // Open a Find handle _hnd = Interop.Kernel32.FindFirstFile(searchPath, ref data); if (_hnd.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); if (errorCode != Interop.Errors.ERROR_FILE_NOT_FOUND && errorCode != Interop.Errors.ERROR_NO_MORE_FILES) { throw 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; } } } if (_searchOption == SearchOption.TopDirectoryOnly) { // fast path for TopDirectoryOnly. If we have a result, go ahead and set it to // current. If empty, dispose handle. if (_empty) { _hnd.Dispose(); } else { TSource result; if (IsResultIncluded(ref data, out result)) { current = result; } } } else { // for AllDirectories, we first recurse into dirs, so cleanup and add searchData // to the list _hnd.Dispose(); _searchList = new List <PathPair>(); _searchList.Add(_searchData); } }
static unsafe SafeFileHandle CreateFileHandleInternal(string fullPath, FileMode mode, FileSystemRights rights, FileShare share, int flagsAndAttributes, Interop.Kernel32.SECURITY_ATTRIBUTES *secAttrs) { SafeFileHandle handle; using (DisableMediaInsertionPrompt.Create()) { // The Inheritable bit is only set in the SECURITY_ATTRIBUTES struct, // and should not be passed to the CreateFile P/Invoke. handle = Interop.Kernel32.CreateFile(fullPath, (int)rights, (share & ~FileShare.Inheritable), secAttrs, mode, flagsAndAttributes, IntPtr.Zero); ValidateFileHandle(handle, fullPath); } return(handle); }
/// <summary> /// Returns 0 on success, otherwise a Win32 error code. Note that /// classes should use -1 as the uninitialized state for dataInitialized. /// </summary> /// <param name="returnErrorOnNotFound">Return the error code for not found errors?</param> internal static int FillAttributeInfo(string path, ref Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data, bool returnErrorOnNotFound) { int errorCode = Interop.Errors.ERROR_SUCCESS; // Neither GetFileAttributes or FindFirstFile like trailing separators path = path.TrimEnd(PathHelpers.DirectorySeparatorChars); using (DisableMediaInsertionPrompt.Create()) { if (!Interop.Kernel32.GetFileAttributesEx(path, Interop.Kernel32.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data)) { errorCode = Marshal.GetLastWin32Error(); if (errorCode == Interop.Errors.ERROR_ACCESS_DENIED) { // Files that are marked for deletion will not let you GetFileAttributes, // ERROR_ACCESS_DENIED is given back without filling out the data struct. // FindFirstFile, however, will. Historically we always gave back attributes // for marked-for-deletion files. var findData = new Interop.Kernel32.WIN32_FIND_DATA(); using (SafeFindHandle handle = Interop.Kernel32.FindFirstFile(path, ref findData)) { if (handle.IsInvalid) { errorCode = Marshal.GetLastWin32Error(); } else { errorCode = Interop.Errors.ERROR_SUCCESS; data.PopulateFrom(ref findData); } } } } } if (errorCode != Interop.Errors.ERROR_SUCCESS && !returnErrorOnNotFound) { switch (errorCode) { case Interop.Errors.ERROR_FILE_NOT_FOUND: case Interop.Errors.ERROR_PATH_NOT_FOUND: case Interop.Errors.ERROR_NOT_READY: // Removable media not ready // Return default value for backward compatibility data.dwFileAttributes = -1; return(Interop.Errors.ERROR_SUCCESS); } } return(errorCode); }
/// <summary> /// Returns 0 on success, otherwise a Win32 error code. Note that /// classes should use -1 as the uninitialized state for dataInitialized. /// </summary> /// <param name="returnErrorOnNotFound">Return the error code for not found errors?</param> internal static int FillAttributeInfo(string path, ref Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data, bool returnErrorOnNotFound) { int errorCode = Interop.Errors.ERROR_SUCCESS; // Neither GetFileAttributes or FindFirstFile like trailing separators path = PathInternal.TrimEndingDirectorySeparator(path); using (DisableMediaInsertionPrompt.Create()) { if (!Interop.Kernel32.GetFileAttributesEx(path, Interop.Kernel32.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data)) { errorCode = Marshal.GetLastWin32Error(); if (errorCode != Interop.Errors.ERROR_FILE_NOT_FOUND && errorCode != Interop.Errors.ERROR_PATH_NOT_FOUND && errorCode != Interop.Errors.ERROR_NOT_READY && errorCode != Interop.Errors.ERROR_INVALID_NAME && errorCode != Interop.Errors.ERROR_BAD_PATHNAME && errorCode != Interop.Errors.ERROR_BAD_NETPATH && errorCode != Interop.Errors.ERROR_BAD_NET_NAME && errorCode != Interop.Errors.ERROR_INVALID_PARAMETER && errorCode != Interop.Errors.ERROR_NETWORK_UNREACHABLE) { // Assert so we can track down other cases (if any) to add to our test suite Debug.Assert(errorCode == Interop.Errors.ERROR_ACCESS_DENIED || errorCode == Interop.Errors.ERROR_SHARING_VIOLATION, $"Unexpected error code getting attributes {errorCode}"); // Files that are marked for deletion will not let you GetFileAttributes, // ERROR_ACCESS_DENIED is given back without filling out the data struct. // FindFirstFile, however, will. Historically we always gave back attributes // for marked-for-deletion files. // // Another case where enumeration works is with special system files such as // pagefile.sys that give back ERROR_SHARING_VIOLATION on GetAttributes. // // Ideally we'd only try again for known cases due to the potential performance // hit. The last attempt to do so baked for nearly a year before we found the // pagefile.sys case. As such we're probably stuck filtering out specific // cases that we know we don't want to retry on. var findData = new Interop.Kernel32.WIN32_FIND_DATA(); using (SafeFindHandle handle = Interop.Kernel32.FindFirstFile(path, ref findData)) { if (handle.IsInvalid) { errorCode = Marshal.GetLastWin32Error(); } else { errorCode = Interop.Errors.ERROR_SUCCESS; data.PopulateFrom(ref findData); } } } } } if (errorCode != Interop.Errors.ERROR_SUCCESS && !returnErrorOnNotFound) { switch (errorCode) { case Interop.Errors.ERROR_FILE_NOT_FOUND: case Interop.Errors.ERROR_PATH_NOT_FOUND: case Interop.Errors.ERROR_NOT_READY: // Removable media not ready // Return default value for backward compatibility data.dwFileAttributes = -1; return(Interop.Errors.ERROR_SUCCESS); } } return(errorCode); }
private void AddSearchableDirsToList(PathPair localSearchData) { string searchPath = Path.Combine(localSearchData.FullPath, "*"); SafeFindHandle hnd = null; Interop.Kernel32.WIN32_FIND_DATA data = new Interop.Kernel32.WIN32_FIND_DATA(); try { using (DisableMediaInsertionPrompt.Create()) { // Get all files and dirs hnd = Interop.Kernel32.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 switch (errorCode) { case Interop.Errors.ERROR_FILE_NOT_FOUND: case Interop.Errors.ERROR_NO_MORE_FILES: case Interop.Errors.ERROR_PATH_NOT_FOUND: return; default: throw HandleError(errorCode, localSearchData.FullPath); } } } // Add subdirs to _searchList. Exempt ReparsePoints as appropriate Debug.Assert(_searchList != null, "_searchList should not be null"); int initialCount = _searchList.Count; do { if (Win32FileSystemEnumerableHelpers.IsDir(ref data)) { string fileName = data.cFileName.GetStringFromFixedBuffer(); Debug.Assert(fileName.Length != 0 && !Path.IsPathRooted(fileName), "Expected file system enumeration to not have empty file/directory name and not have rooted name"); string tempFullPath = Path.Combine(localSearchData.FullPath, fileName); string tempUserPath = Path.Combine(localSearchData.UserPath, fileName); // Setup search data for the sub directory and push it into the list PathPair searchDataSubDir = new PathPair(tempUserPath, tempFullPath); _searchList.Add(searchDataSubDir); } } while (Interop.Kernel32.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 { hnd?.Dispose(); } }
public override bool MoveNext() { Interop.Kernel32.WIN32_FIND_DATA data = new Interop.Kernel32.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); using (DisableMediaInsertionPrompt.Create()) { // Open a Find handle _hnd = Interop.Kernel32.FindFirstFile(searchPath, ref data); if (_hnd.IsInvalid) { int errorCode = Marshal.GetLastWin32Error(); switch (errorCode) { case Interop.Errors.ERROR_FILE_NOT_FOUND: case Interop.Errors.ERROR_NO_MORE_FILES: case Interop.Errors.ERROR_PATH_NOT_FOUND: continue; } _hnd.Dispose(); throw 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) { using (DisableMediaInsertionPrompt.Create()) { // Keep asking for more matching files/dirs, add it to the list while (Interop.Kernel32.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(); _hnd?.Dispose(); switch (errorCode) { case Interop.Errors.ERROR_SUCCESS: case Interop.Errors.ERROR_NO_MORE_FILES: // 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 case Interop.Errors.ERROR_FILE_NOT_FOUND: break; default: throw 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); }