Skip to content

Commit

Permalink
Customize ERROR_INVALID_WINDOW_HANDLE exception text to make window i…
Browse files Browse the repository at this point in the history
…nterop helpers discoverable (#941)

* Customize ERROR_INVALID_WINDOW_HANDLE exception text to make window interop helpers discoverable

* PR feedback
  • Loading branch information
Scottj1s committed Jul 29, 2021
1 parent cfc26e5 commit 0335a5b
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
23 changes: 22 additions & 1 deletion docs/interop.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,28 @@ SetString(MarshalString.GetAbi(marshalStr));
```

#### Interop Interfaces
The CLR still supports marshaling COM (IUnknown), but not WinRT (IInspectable), interop interfaces. The Windows SDK projection provides definitions for several COM interop interfaces, including ***Windows.Storage.Streams.IBufferByteAccess***, ***WinRT.Interop.IWindowNative***, and ***WinRT.Interop.IInitializeWithWindow***. The Windows SDK projection also provides wrappers for all WinRT interop interfaces included in the Universal API Contract, such as ***Windows.Security.Credentials.UI.UserConsentVerifierInterop***. For custom or extension SDK interop interfaces, C#/WinRT supports two marshaling techniques.
The CLR still supports marshaling COM (IUnknown), but not WinRT (IInspectable), interop interfaces. The Windows SDK projection provides several interop interface helpers for common scenarios. For custom or extension SDK interop interfaces, C#/WinRT supports two marshaling techniques.

##### Windows SDK

The Windows SDK projection provides wrappers for common COM interop interfaces, such as ***Windows.Storage.Streams.IBufferByteAccess***, ***WinRT.Interop.IWindowNative***, and ***WinRT.Interop.IInitializeWithWindow***.

The following sample demonstrates creating a folder picker with an owning window:

```csharp
var window = new Microsoft.UI.Xaml.Window();
// ...
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(window);
var folderPicker = new Windows.Storage.Pickers.FolderPicker();
folderPicker.FileTypeFilter.Add("*");
WinRT.Interop.InitializeWithWindow.Initialize(folderPicker, hwnd);
var folder = await folderPicker.PickSingleFolderAsync();
```

The Windows SDK projection also provides wrappers for all WinRT interop interfaces included in the Universal API Contract, such as ***Windows.Security.Credentials.UI.UserConsentVerifierInterop***

For more info, see:
[Call WinRT COM interop interfaces from .NET 5+ apps](https://docs.microsoft.com/en-us/windows/apps/desktop/modernize/winrt-com-interop-csharp)

##### Projected
If possible, the interop interface should be defined in IDL and a C#/WinRT projection produced for it. This automatically generates all marshaling logic so that calling code can pass and receive projected types. This definition of `IUserConsentVerifierInterop` from one of our test components is an example of this:
Expand Down
8 changes: 8 additions & 0 deletions src/WinRT.Runtime/ExceptionHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public static class ExceptionHelpers
internal const int E_LAYOUTCYCLE = unchecked((int)0x802B0014);
internal const int E_ELEMENTNOTENABLED = unchecked((int)0x802B001E);
internal const int E_ELEMENTNOTAVAILABLE = unchecked((int)0x802B001F);
internal const int ERROR_INVALID_WINDOW_HANDLE = unchecked((int)0x80070578);

[DllImport("oleaut32.dll")]
private static extern int SetErrorInfo(uint dwReserved, IntPtr perrinfo);
Expand Down Expand Up @@ -154,6 +155,13 @@ private static Exception GetExceptionForHR(int hr, bool useGlobalErrorState, out
case E_ELEMENTNOTENABLED:
ex = new Microsoft.UI.Xaml.Automation.ElementNotEnabledException();
break;
case ERROR_INVALID_WINDOW_HANDLE:
ex = new System.Runtime.InteropServices.COMException(
@"Invalid window handle. (0x80070578)
Consider WindowNative, InitializeWithWindow
See https://aka.ms/cswinrt/interop#windows-sdk",
ERROR_INVALID_WINDOW_HANDLE);
break;
default:
ex = Marshal.GetExceptionForHR(hr, iErrorInfo?.ThisPtr ?? (IntPtr)(-1));
break;
Expand Down

0 comments on commit 0335a5b

Please sign in to comment.