diff --git a/src/WinRT.Runtime/ExceptionHelpers.cs b/src/WinRT.Runtime/ExceptionHelpers.cs
index 6f0f23752..4727c8a7f 100644
--- a/src/WinRT.Runtime/ExceptionHelpers.cs
+++ b/src/WinRT.Runtime/ExceptionHelpers.cs
@@ -98,6 +98,47 @@ private static bool Initialize()
return true;
}
+ ///
+ /// Unhandled WinRT server exception event.
+ ///
+ public static event EventHandler UnhandledWinRTServerException;
+
+ public class UnhandledWinRTServerExceptionEventArgs : EventArgs
+ {
+ public Exception Exception { get; }
+ public bool Handled { get; set; }
+
+ public UnhandledWinRTServerExceptionEventArgs(Exception exception)
+ {
+ Exception = exception;
+ }
+ }
+
+ public static int HandleWinRTServerException(object sender, Exception ex, bool dispatchExceptionToUnmanagedCode)
+ {
+ EventHandler handler = UnhandledWinRTServerException;
+
+ if (handler != null)
+ {
+ UnhandledWinRTServerExceptionEventArgs args = new(ex);
+ handler.Invoke(sender, args);
+ if (args.Handled)
+ {
+ return 0;
+ }
+ }
+
+ if (dispatchExceptionToUnmanagedCode)
+ {
+ SetErrorInfo(ex);
+ return GetHRForException(ex);
+ }
+ else
+ {
+ return ex.HResult;
+ }
+ }
+
public static void ThrowExceptionForHR(int hr)
{
if (hr < 0)
diff --git a/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt b/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt
new file mode 100644
index 000000000..0493e23d1
--- /dev/null
+++ b/src/WinRT.Runtime/MatchingRefApiCompatBaseline.txt
@@ -0,0 +1,5 @@
+MembersMustExist : Member 'public void WinRT.ExceptionHelpers.add_UnhandledWinRTServerException(System.EventHandler)' does not exist in the reference but it does exist in the implementation.
+MembersMustExist : Member 'public void WinRT.ExceptionHelpers.remove_UnhandledWinRTServerException(System.EventHandler)' does not exist in the reference but it does exist in the implementation.
+TypesMustExist : Type 'WinRT.ExceptionHelpers.UnhandledWinRTServerExceptionEventArgs' does not exist in the reference but it does exist in the implementation.
+MembersMustExist : Member 'public System.Int32 WinRT.ExceptionHelpers.HandleWinRTServerException(System.Object, System.Exception, System.Boolean)' does not exist in the reference but it does exist in the implementation.
+Total Issues: 4
diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h
index 9ae6c4844..dc280a9bc 100644
--- a/src/cswinrt/code_writers.h
+++ b/src/cswinrt/code_writers.h
@@ -5242,7 +5242,7 @@ return eventSource.EventActions;
return std::pair{ marshalers, managed_marshaler{} };
}
- void write_managed_method_call(writer& w, method_signature signature, std::string invoke_expression_format)
+ void write_managed_method_call(writer& w, method_signature signature, std::string type_name, std::string invoke_expression_format)
{
auto generic_abi_types = get_generic_abi_types(w, signature);
bool have_generic_params = std::find_if(generic_abi_types.begin(), generic_abi_types.end(),
@@ -5255,6 +5255,7 @@ return eventSource.EventActions;
w.write(
R"(%
%
+%
try
{
%
@@ -5262,10 +5263,12 @@ try
}
catch (Exception __exception__)
{
-global::WinRT.ExceptionHelpers.SetErrorInfo(__exception__);
-return global::WinRT.ExceptionHelpers.GetHRForException(__exception__);
+return global::WinRT.ExceptionHelpers.HandleWinRTServerException(__this__, __exception__, true);
}
return 0;)",
+ [&](writer& w) {
+ w.write(R"(% __this__ = default;)", type_name);
+ },
[&](writer& w) {
if (!return_sig) return;
return_marshaler.write_local(w);
@@ -5340,7 +5343,8 @@ private static unsafe int Do_Abi_%%
bind(method),
bind(
signature,
- w.write_temp("global::WinRT.ComWrappersSupport.FindObject<%>(%).%%",
+ type_name,
+ w.write_temp("(__this__ = global::WinRT.ComWrappersSupport.FindObject<%>(%)).%%",
type_name,
have_generic_params ? "new IntPtr(thisPtr)" : "thisPtr",
method.Name(),
@@ -5376,7 +5380,8 @@ private static unsafe int Do_Abi_%%
bind(setter),
bind(
setter_sig,
- w.write_temp("global::WinRT.ComWrappersSupport.FindObject<%>(%).% = %",
+ type_name,
+ w.write_temp("(__this__ = global::WinRT.ComWrappersSupport.FindObject<%>(%)).% = %",
type_name,
have_generic_params ? "new IntPtr(thisPtr)" : "thisPtr",
prop.Name(),
@@ -5406,7 +5411,8 @@ private static unsafe int Do_Abi_%%
bind(getter),
bind(
getter_sig,
- w.write_temp("global::WinRT.ComWrappersSupport.FindObject<%>(%).%%",
+ type_name,
+ w.write_temp("(__this__ = global::WinRT.ComWrappersSupport.FindObject<%>(%)).%%",
type_name,
have_generic_params ? "new IntPtr(thisPtr)" : "thisPtr",
prop.Name(),
@@ -5455,10 +5461,11 @@ private static global::System.Runtime.CompilerServices.ConditionalWeakTable<%, g
%
private static unsafe int Do_Abi_%%
{
+% __this = default;
%% = default;
try
{
-var __this = global::WinRT.ComWrappersSupport.FindObject<%>(thisPtr);
+__this = global::WinRT.ComWrappersSupport.FindObject<%>(thisPtr);
var __handler = %.FromAbi(%);
%% = _%_TokenTables.GetOrCreateValue(__this).AddEventHandler(__handler);
__this.% += __handler;
@@ -5466,12 +5473,13 @@ return 0;
}
catch (Exception __ex)
{
-return __ex.HResult;
+return global::WinRT.ExceptionHelpers.TryHandleWinRTServerException(__this, __ex, false);
}
})",
!settings.netstandard_compat && !generic_type ? "[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvStdcall) })]" : "",
get_vmethod_name(w, add_method.Parent(), add_method),
bind(add_method),
+ type_name,
settings.netstandard_compat ? "" : "*",
add_handler_event_token_name,
type_name,
@@ -5486,9 +5494,10 @@ return __ex.HResult;
%
private static unsafe int Do_Abi_%%
{
+% __this = default;
try
{
-var __this = global::WinRT.ComWrappersSupport.FindObject<%>(thisPtr);
+__this = global::WinRT.ComWrappersSupport.FindObject<%>(thisPtr);
if(__this != null && _%_TokenTables.TryGetValue(__this, out var __table) && __table.RemoveEventHandler(%, out var __handler))
{
__this.% -= __handler;
@@ -5497,13 +5506,14 @@ return 0;
}
catch (Exception __ex)
{
-return __ex.HResult;
+return global::WinRT.ExceptionHelpers.TryHandleWinRTServerException(__this, __ex, false);
}
})",
!settings.netstandard_compat && !generic_type ? "[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvStdcall) })]" : "",
get_vmethod_name(w, remove_method.Parent(), remove_method),
bind(remove_method),
type_name,
+ type_name,
evt.Name(),
remove_handler_event_token_name,
evt.Name());
@@ -7082,7 +7092,7 @@ public static Guid PIID = GuidGenerator.CreateIID(typeof(%));)",
[&](writer& w) {
if (settings.netstandard_compat)
{
- write_managed_method_call(w, signature,
+ write_managed_method_call(w, signature, type_name,
w.write_temp(R"(
global::WinRT.ComWrappersSupport.MarshalDelegateInvoke(%, (% invoke) =>
{
@@ -7105,9 +7115,9 @@ global::WinRT.ComWrappersSupport.MarshalDelegateInvoke(%, (% invoke) =>
}
else
{
- write_managed_method_call(w, signature,
+ write_managed_method_call(w, signature, type_name,
w.write_temp(R"(
-global::WinRT.ComWrappersSupport.FindObject<%>(%).Invoke(%)
+(__this__ = global::WinRT.ComWrappersSupport.FindObject<%>(%)).Invoke(%)
)",
type_name,
is_generic ? "new IntPtr(thisPtr)" : "thisPtr",