summaryrefslogtreecommitdiff
path: root/src/System.Private.CoreLib/shared/Internal/IO/File.Windows.cs
diff options
context:
space:
mode:
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.cs77
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;
+ }
+ }
+}