Skip to content

Commit 9f4b2dd

Browse files
committed
Introduce InteropException for all P/Invoke errors
Add a new custom exception type `InteropException` that wraps up failures from interop (P/Invoke) code. `Win32Exception`s, macOS and POSIX error codes are now wrapped in `InteropException`.
1 parent 8cde266 commit 9f4b2dd

File tree

3 files changed

+53
-11
lines changed

3 files changed

+53
-11
lines changed

src/shared/Microsoft.Git.CredentialManager/Application.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.ComponentModel;
55
using System.Threading.Tasks;
66
using Microsoft.Git.CredentialManager.Commands;
7+
using Microsoft.Git.CredentialManager.Interop;
78

89
namespace Microsoft.Git.CredentialManager
910
{
@@ -81,8 +82,8 @@ protected bool WriteException(Exception ex)
8182
// Try and use a nicer format for some well-known exception types
8283
switch (ex)
8384
{
84-
case Win32Exception w32Ex:
85-
Context.StdError.WriteLine("fatal: {0} [0x{1:x}]", w32Ex.Message, w32Ex.NativeErrorCode);
85+
case InteropException interopEx:
86+
Context.StdError.WriteLine("fatal: {0} [0x{1:x}]", interopEx.Message, interopEx.ErrorCode);
8687
break;
8788
default:
8889
Context.StdError.WriteLine("fatal: {0}", ex.Message);
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System;
2+
using System.ComponentModel;
3+
using System.Diagnostics;
4+
5+
namespace Microsoft.Git.CredentialManager.Interop
6+
{
7+
/// <summary>
8+
/// An unexpected error occurred in interop-code.
9+
/// </summary>
10+
[DebuggerDisplay("{DebuggerDisplay}")]
11+
public class InteropException : Exception
12+
{
13+
public InteropException()
14+
: base() { }
15+
16+
public InteropException(string message, int errorCode)
17+
: base(message)
18+
{
19+
ErrorCode = errorCode;
20+
}
21+
22+
public InteropException(string message, int errorCode, Exception innerException)
23+
: base(message, innerException)
24+
{
25+
ErrorCode = errorCode;
26+
}
27+
28+
public InteropException(string message, Win32Exception w32Exception)
29+
: base(message, w32Exception)
30+
{
31+
ErrorCode = w32Exception.NativeErrorCode;
32+
}
33+
34+
/// <summary>
35+
/// Native error code.
36+
/// </summary>
37+
public int ErrorCode { get; }
38+
39+
private string DebuggerDisplay => $"{Message} [0x{ErrorCode:x}]";
40+
}
41+
}

src/shared/Microsoft.Git.CredentialManager/Interop/MacOS/Native/SecurityFramework.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,23 +80,23 @@ public static void ThrowIfError(int error, string defaultErrorMessage = "Unknown
8080
case OK:
8181
return;
8282
case ErrorSecNoSuchKeychain:
83-
throw new InvalidOperationException($"The keychain does not exist. ({ErrorSecNoSuchKeychain})");
83+
throw new InteropException("The keychain does not exist.", error);
8484
case ErrorSecInvalidKeychain:
85-
throw new InvalidOperationException($"The keychain is not valid. ({ErrorSecInvalidKeychain})");
85+
throw new InteropException("The keychain is not valid.", error);
8686
case ErrorSecAuthFailed:
87-
throw new InvalidOperationException($"Authorization/Authentication failed. ({ErrorSecAuthFailed})");
87+
throw new InteropException("Authorization/Authentication failed.", error);
8888
case ErrorSecDuplicateItem:
89-
throw new InvalidOperationException($"The item already exists. ({ErrorSecDuplicateItem})");
89+
throw new InteropException("The item already exists.", error);
9090
case ErrorSecItemNotFound:
91-
throw new InvalidOperationException($"The item cannot be found. ({ErrorSecItemNotFound})");
91+
throw new InteropException("The item cannot be found.", error);
9292
case ErrorSecInteractionNotAllowed:
93-
throw new InvalidOperationException($"Interaction with the Security Server is not allowed. ({ErrorSecInteractionNotAllowed})");
93+
throw new InteropException("Interaction with the Security Server is not allowed.", error);
9494
case ErrorSecInteractionRequired:
95-
throw new InvalidOperationException($"User interaction is required. ({ErrorSecInteractionRequired})");
95+
throw new InteropException("User interaction is required.", error);
9696
case ErrorSecNoSuchAttr:
97-
throw new InvalidOperationException($"The attribute does not exist. ({ErrorSecNoSuchAttr})");
97+
throw new InteropException("The attribute does not exist.", error);
9898
default:
99-
throw new Exception($"{defaultErrorMessage} ({error})");
99+
throw new InteropException(defaultErrorMessage, error);
100100
}
101101
}
102102
}

0 commit comments

Comments
 (0)