// 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 System; using System.Diagnostics; using System.Runtime.InteropServices; namespace System.IO { /// /// Provides static methods for converting from Win32 errors codes to exceptions, HRESULTS and error messages. /// internal static class Win32Marshal { /// /// Converts, resetting it, the last Win32 error into a corresponding object. /// internal static Exception GetExceptionForLastWin32Error() { int errorCode = Marshal.GetLastWin32Error(); return GetExceptionForWin32Error(errorCode, string.Empty); } /// /// Converts the specified Win32 error into a corresponding object. /// internal static Exception GetExceptionForWin32Error(int errorCode) { return GetExceptionForWin32Error(errorCode, string.Empty); } /// /// Converts the specified Win32 error into a corresponding object, optionally /// including the specified path in the error message. /// internal static Exception GetExceptionForWin32Error(int errorCode, string path) { switch (errorCode) { case Interop.Errors.ERROR_FILE_NOT_FOUND: if (path.Length == 0) return new FileNotFoundException(SR.IO_FileNotFound); else return new FileNotFoundException(SR.Format(SR.IO_FileNotFound_FileName, path), path); case Interop.Errors.ERROR_PATH_NOT_FOUND: if (path.Length == 0) return new DirectoryNotFoundException(SR.IO_PathNotFound_NoPathName); else return new DirectoryNotFoundException(SR.Format(SR.IO_PathNotFound_Path, path)); case Interop.Errors.ERROR_ACCESS_DENIED: if (path.Length == 0) return new UnauthorizedAccessException(SR.UnauthorizedAccess_IODenied_NoPathName); else return new UnauthorizedAccessException(SR.Format(SR.UnauthorizedAccess_IODenied_Path, path)); case Interop.Errors.ERROR_ALREADY_EXISTS: if (path.Length == 0) goto default; return new IOException(SR.Format(SR.IO_AlreadyExists_Name, path), MakeHRFromErrorCode(errorCode)); case Interop.Errors.ERROR_FILENAME_EXCED_RANGE: return new PathTooLongException(SR.IO_PathTooLong); case Interop.Errors.ERROR_INVALID_PARAMETER: return new IOException(GetMessage(errorCode), MakeHRFromErrorCode(errorCode)); case Interop.Errors.ERROR_SHARING_VIOLATION: if (path.Length == 0) return new IOException(SR.IO_SharingViolation_NoFileName, MakeHRFromErrorCode(errorCode)); else return new IOException(SR.Format(SR.IO_SharingViolation_File, path), MakeHRFromErrorCode(errorCode)); case Interop.Errors.ERROR_FILE_EXISTS: if (path.Length == 0) goto default; return new IOException(SR.Format(SR.IO_FileExists_Name, path), MakeHRFromErrorCode(errorCode)); case Interop.Errors.ERROR_OPERATION_ABORTED: return new OperationCanceledException(); default: return new IOException(GetMessage(errorCode), MakeHRFromErrorCode(errorCode)); } } /// /// Returns a HRESULT for the specified Win32 error code. /// internal static int MakeHRFromErrorCode(int errorCode) { Debug.Assert((0xFFFF0000 & errorCode) == 0, "This is an HRESULT, not an error code!"); return unchecked(((int)0x80070000) | errorCode); } /// /// Returns a string message for the specified Win32 error code. /// internal static string GetMessage(int errorCode) { return Interop.Kernel32.GetMessage(errorCode); } } }