diff options
Diffstat (limited to 'src/System.Private.CoreLib/shared/Internal/IO/File.Windows.cs')
-rw-r--r-- | src/System.Private.CoreLib/shared/Internal/IO/File.Windows.cs | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/System.Private.CoreLib/shared/Internal/IO/File.Windows.cs b/src/System.Private.CoreLib/shared/Internal/IO/File.Windows.cs new file mode 100644 index 0000000000..0acae3b457 --- /dev/null +++ b/src/System.Private.CoreLib/shared/Internal/IO/File.Windows.cs @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Win32; +using Microsoft.Win32.SafeHandles; +using System.IO; +using System.Runtime.InteropServices; + +namespace Internal.IO +{ + internal static partial class File + { + internal static bool InternalExists(string fullPath) + { + Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA(); + int errorCode = FillAttributeInfo(fullPath, ref data, returnErrorOnNotFound: true); + + return (errorCode == 0) && (data.dwFileAttributes != -1) + && ((data.dwFileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) == 0); + } + + /// <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; + + 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; + } + } +} |