Example #1
0
        /// <summary>
        /// Turns HRESULT errors into the appropriate exception (that maps with existing .NET behavior as much as possible).
        /// There are additional IOException derived errors for ease of client error handling.
        /// </summary>
        public static Exception GetIoExceptionForHResult(HRESULT hr, string path = null)
        {
            string message = path == null
                ? $"{HResultToString(hr)}"
                : $"{HResultToString(hr)} '{path}'";

            switch (hr)
            {
            case HRESULT.E_ACCESSDENIED:
                return(new UnauthorizedAccessException(message));

            case HRESULT.E_INVALIDARG:
                return(new ArgumentException(message));

            default:
                if (ErrorMacros.HRESULT_FACILITY(hr) == Facility.WIN32)
                {
                    return(WindowsErrorToException((WindowsError)ErrorMacros.HRESULT_CODE(hr), message, path));
                }
                else
                {
                    return(new IOException(message, (int)hr));
                }
            }
        }
Example #2
0
        // .NET's Win32Exception impements the error code lookup on FormatMessage using FORMAT_MESSAGE_FROM_SYSTEM.
        // It won't handle Network Errors (NERR_BASE..MAX_NERR), which come from NETMSG.DLL.

        public static string FormatMessage(
            uint messageId,
            IntPtr source,
            FormatMessageFlags flags,
            params string[] args)
        {
            using (StringBuffer buffer = new StringBuffer())
            {
                // Don't use line breaks
                flags |= FormatMessageFlags.FORMAT_MESSAGE_MAX_WIDTH_MASK;
                if (args == null || args.Length == 0)
                {
                    flags |= FormatMessageFlags.FORMAT_MESSAGE_IGNORE_INSERTS;
                }

                WindowsError lastError = WindowsError.ERROR_INSUFFICIENT_BUFFER;
                uint         capacity  = byte.MaxValue;
                uint         result    = 0;

                while (lastError == WindowsError.ERROR_INSUFFICIENT_BUFFER && capacity <= short.MaxValue)
                {
                    buffer.EnsureCharCapacity(capacity);
                    result = Imports.FormatMessageW(
                        dwFlags: flags,
                        lpSource: source,
                        dwMessageId: messageId,
                        // Do the default language lookup
                        dwLanguageId: 0,
                        lpBuffer: buffer.DangerousGetHandle(),
                        nSize: buffer.CharCapacity,
                        Arguments: args);

                    if (result == 0)
                    {
                        lastError = Errors.GetLastError();
                        capacity  = (uint)Math.Min(capacity * 2, short.MaxValue);
                    }
                    else
                    {
                        buffer.Length = result;
                        return(buffer.ToString());
                    }
                }

                throw new IOException("Failed to get error string.", (int)ErrorMacros.HRESULT_FROM_WIN32(lastError));
            }
        }
Example #3
0
        private static Exception WindowsErrorToException(WindowsError error, string message, string path)
        {
            switch (error)
            {
            case WindowsError.ERROR_FILE_NOT_FOUND:
                return(new FileNotFoundException(message, path));

            case WindowsError.ERROR_PATH_NOT_FOUND:
                return(new DirectoryNotFoundException(message));

            case WindowsError.ERROR_ACCESS_DENIED:
            // Network access doesn't throw UnauthorizedAccess in .NET
            case WindowsError.ERROR_NETWORK_ACCESS_DENIED:
                return(new UnauthorizedAccessException(message));

            case WindowsError.ERROR_FILENAME_EXCED_RANGE:
                return(new PathTooLongException(message));

            case WindowsError.ERROR_INVALID_DRIVE:
                // Not available in Portable libraries
                // return new DriveNotFoundException(message);
                goto default;

            case WindowsError.ERROR_OPERATION_ABORTED:
                return(new OperationCanceledException(message));

            case WindowsError.ERROR_NOT_READY:
                return(new DriveNotReadyException(message));

            case WindowsError.FVE_E_LOCKED_VOLUME:
                return(new DriveLockedException(message));

            case WindowsError.ERROR_INVALID_PARAMETER:
                return(new ArgumentException(message));

            case WindowsError.ERROR_NOT_SUPPORTED:
            case WindowsError.ERROR_NOT_SUPPORTED_IN_APPCONTAINER:
                return(new NotSupportedException(message));

            case WindowsError.ERROR_ALREADY_EXISTS:
            case WindowsError.ERROR_SHARING_VIOLATION:
            case WindowsError.ERROR_FILE_EXISTS:
            default:
                return(new IOException(message, (int)ErrorMacros.HRESULT_FROM_WIN32(error)));
            }
        }
Example #4
0
        /// <summary>
        /// Try to get the string for an HRESULT
        /// </summary>
        public static string HResultToString(HRESULT hr)
        {
            string message;

            if (ErrorMacros.HRESULT_FACILITY(hr) == Facility.WIN32)
            {
                // Win32 Error, extract the code
                message = ErrorMethods.FormatMessage(
                    messageId: (uint)ErrorMacros.HRESULT_CODE(hr),
                    source: IntPtr.Zero,
                    flags: FormatMessageFlags.FORMAT_MESSAGE_FROM_SYSTEM);
            }
            else
            {
                // Hope that we get a rational IErrorInfo
                Exception exception = Marshal.GetExceptionForHR((int)hr);
                message = exception.Message;
            }

            return($"HRESULT {(int)hr:D} [0x{(int)hr:X}]: {message}");
        }