File.Windows.cs 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. using Microsoft.Win32;
  5. using Microsoft.Win32.SafeHandles;
  6. using System.IO;
  7. using System.Runtime.InteropServices;
  8. namespace Internal.IO
  9. {
  10. internal static partial class File
  11. {
  12. internal static bool InternalExists(string fullPath)
  13. {
  14. Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data = new Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA();
  15. int errorCode = FillAttributeInfo(fullPath, ref data, returnErrorOnNotFound: true);
  16. return (errorCode == 0) && (data.dwFileAttributes != -1)
  17. && ((data.dwFileAttributes & Interop.Kernel32.FileAttributes.FILE_ATTRIBUTE_DIRECTORY) == 0);
  18. }
  19. /// <summary>
  20. /// Returns 0 on success, otherwise a Win32 error code. Note that
  21. /// classes should use -1 as the uninitialized state for dataInitialized.
  22. /// </summary>
  23. /// <param name="returnErrorOnNotFound">Return the error code for not found errors?</param>
  24. internal static int FillAttributeInfo(string path, ref Interop.Kernel32.WIN32_FILE_ATTRIBUTE_DATA data, bool returnErrorOnNotFound)
  25. {
  26. int errorCode = Interop.Errors.ERROR_SUCCESS;
  27. using (DisableMediaInsertionPrompt.Create())
  28. {
  29. if (!Interop.Kernel32.GetFileAttributesEx(path, Interop.Kernel32.GET_FILEEX_INFO_LEVELS.GetFileExInfoStandard, ref data))
  30. {
  31. errorCode = Marshal.GetLastWin32Error();
  32. if (errorCode == Interop.Errors.ERROR_ACCESS_DENIED)
  33. {
  34. // Files that are marked for deletion will not let you GetFileAttributes,
  35. // ERROR_ACCESS_DENIED is given back without filling out the data struct.
  36. // FindFirstFile, however, will. Historically we always gave back attributes
  37. // for marked-for-deletion files.
  38. var findData = new Interop.Kernel32.WIN32_FIND_DATA();
  39. using (SafeFindHandle handle = Interop.Kernel32.FindFirstFile(path, ref findData))
  40. {
  41. if (handle.IsInvalid)
  42. {
  43. errorCode = Marshal.GetLastWin32Error();
  44. }
  45. else
  46. {
  47. errorCode = Interop.Errors.ERROR_SUCCESS;
  48. data.PopulateFrom(ref findData);
  49. }
  50. }
  51. }
  52. }
  53. }
  54. if (errorCode != Interop.Errors.ERROR_SUCCESS && !returnErrorOnNotFound)
  55. {
  56. switch (errorCode)
  57. {
  58. case Interop.Errors.ERROR_FILE_NOT_FOUND:
  59. case Interop.Errors.ERROR_PATH_NOT_FOUND:
  60. case Interop.Errors.ERROR_NOT_READY: // Removable media not ready
  61. // Return default value for backward compatibility
  62. data.dwFileAttributes = -1;
  63. return Interop.Errors.ERROR_SUCCESS;
  64. }
  65. }
  66. return errorCode;
  67. }
  68. }
  69. }