{"id":105520,"date":"2021-08-05T07:00:00","date_gmt":"2021-08-05T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=105520"},"modified":"2021-08-05T07:35:17","modified_gmt":"2021-08-05T14:35:17","slug":"20210805-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20210805-00\/?p=105520","title":{"rendered":"An example of using Windows Runtime interop methods from C++\/WinRT: <CODE>Request&shy;Token&shy;For&shy;Window&shy;Async<\/CODE>"},"content":{"rendered":"<p>A customer was trying to use the <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/win32\/api\/webauthenticationcoremanagerinterop\/nf-webauthenticationcoremanagerinterop-iwebauthenticationcoremanagerinterop-requesttokenforwindowasync\"> <code>IWeb\u00adAuthentication\u00adCore\u00adManager\u00adInterop::<wbr \/>Request\u00adToken\u00adFor\u00adWindow\u00adAsync<\/code> method<\/a> from C++\/WinRT. The <code>IWeb\u00adAuthentication\u00adCore\u00adManager\u00adInterop<\/code> interface follows <a title=\"How do I show the sharing pane from a Win32 desktop application?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170315-00\/?p=95735\"> the interop pattern<\/a> and lets a Win32 program use the Windows Runtime <code>Web\u00adAuthentication\u00adCore\u00adManager<\/code> by associating it with a <code>HWND<\/code> instead of a <code>Core\u00adWindow<\/code>.<\/p>\n<p>A customer was having trouble getting this to work, though:<\/p>\n<pre>#include &lt;WebAuthenticationCoreManagerInterop.h&gt;\r\n#include &lt;winrt\/Windows.Foundation.h&gt;\r\n#include &lt;winrt\/Windows.Security.Authentication.Web.Core.h&gt;\r\n\r\nnamespace winrt\r\n{\r\n    using namespace Windows::Foundation;\r\n    using namespace Windows::Security::Authentication::Web::Core;\r\n}\r\n\r\n\/\/ Note: Code in italics is wrong; see discussion\r\nwinrt::IAsyncOperation&lt;winrt::WebTokenRequestResult&gt;\r\nRequestTokenForWindowAsync(HWND window, winrt::WebTokenRequest const&amp; request)\r\n{\r\n    auto interop = winrt::get_activation_factory&lt;winrt::WebAuthenticationCoreManager,\r\n                                                ::IWebAuthenticationCoreManagerInterop&gt;();\r\n\r\n    winrt::com_ptr&lt;winrt::IAsyncOperation&lt;winrt::WebTokenRequestResult&gt;&gt; operation;\r\n    auto requestInspectable = static_cast&lt;::IInspectable*&gt;(winrt::get_abi(request));\r\n\r\n    <i>winrt::check_hresult(\r\n        interop-&gt;RequestTokenForWindowAsync(\r\n        window,\r\n        requestInspectable,\r\n        __uuidof(operation),\r\n        operation.put_void()));<\/i>\r\n\r\n    co_return co_await operation;\r\n}\r\n<\/pre>\n<p>The <code>__uuid(operation)<\/code> fails to compile, producing the error<\/p>\n<pre style=\"white-space: pre-wrap;\">error C2787: 'winrt::<wbr \/>com_ptr&lt;<wbr \/>winrt::<wbr \/>Windows::<wbr \/>Foundation::<wbr \/>IAsyncOperation&lt;<wbr \/>winrt::<wbr \/>Windows::<wbr \/>Security::<wbr \/>Authentication::<wbr \/>Web::<wbr \/>Core::<wbr \/>Web\u00adToken\u00adRequest\u00adResult&gt;&gt;': no GUID has been associated with this object\r\n<\/pre>\n<p>What&#8217;s going on?<\/p>\n<p>The first order of business is understanding the error message.<\/p>\n<p>The <code>__uuidof<\/code> nonstandard extension keyword can be applied to a type or a variable. If you apply it to a variable, then it uses the type of that variable. If the type is a pointer or reference, the pointed-to or referenced type is used. And then the compiler checks if the resulting type has a <code>__declspec(uuid(...))<\/code> attribute.<\/p>\n<p>What happened here is that we passed a variable whose type is <code>winrt::com_ptr&lt;something&gt;<\/code>, and <code>winrt::com_ptr<\/code> doesn&#8217;t have a <code>__declspec(uuid(...))<\/code> attribute because the UUID associated with a <code>winrt::com_ptr<\/code> depends on what the <code>something<\/code> is.<\/p>\n<p>Okay, so let&#8217;s fix that by using the <code>something<\/code>.<\/p>\n<pre>    winrt::check_hresult(\r\n        interop-&gt;RequestTokenForWindowAsync(\r\n        window,\r\n        requestInspectable,\r\n        <span style=\"color: blue;\">__uuidof(winrt::IAsyncOperation&lt;winrt::WebTokenRequestResult&gt;)<\/span>,\r\n        operation.put_void()));\r\n<\/pre>\n<p>That still doesn&#8217;t work. We just get the same error again:<\/p>\n<pre style=\"white-space: pre-wrap;\">error C2787: 'winrt::<wbr \/>Windows::<wbr \/>Foundation::<wbr \/>IAsyncOperation&lt;<wbr \/>winrt::<wbr \/>Windows::<wbr \/>Security::<wbr \/>Authentication::<wbr \/>Web::<wbr \/>Core::<wbr \/>Web\u00adToken\u00adRequest\u00adResult&gt;': no GUID has been associated with this object\r\n<\/pre>\n<p>It&#8217;s the same problem again. <code><wbr \/>winrt::<wbr \/>IAsyncOperation&lt;<wbr \/>winrt::<wbr \/>Web\u00adToken\u00adRequest\u00adResult&gt;<\/code> doesn&#8217;t have a <code>__declspec(uuid(...))<\/code> because the UUID depends on the thing inside.<\/p>\n<p>But this time, we can&#8217;t unwrap it because we really do want the UUID of the <code>IAsyncOperation&lt;something&gt;<\/code>, not the UUID of the <code>something<\/code>.<\/p>\n<p>It turns out that we ran astray much earlier:<\/p>\n<pre>    winrt::com_ptr&lt;winrt::IAsyncOperation&lt;winrt::WebTokenRequestResult&gt;&gt; operation;\r\n<\/pre>\n<p>We created a <code>winrt::<wbr \/>com_ptr<\/code> to a <code>winrt::<wbr \/>IAsyncOperation&lt;T&gt;<\/code>. But the catch is that <code>winrt::<wbr \/>IAsyncOperation&lt;T&gt;<\/code> is itself already a smart pointer. You created a smart pointer to a smart pointer, and that&#8217;s the source of confusion.<\/p>\n<p>The type wrapped by a <code>winrt::<wbr \/>com_ptr<\/code> is expected to be a type that has methods <code>Query\u00adInterface<\/code>, <code>AddRef<\/code>, and <code>Release<\/code>, according to the conventions of the ABI <code>::IUnknown<\/code>. The thing to pass here is not another smart pointer, but rather the ABI COM interface type.<\/p>\n<pre>    \/\/ Oh my goodness, please don't make me type this.\r\n    winrt::com_ptr&lt;ABI::Windows::Foundation::IAsyncOperation&lt;\r\n        ABI::Windows::Security::Authentication::Web::Core::WebTokenRequestResult*&gt;&gt;\r\n        operation;\r\n<\/pre>\n<p>That is a horrible mouthful, and requires you to include the Windows Runtime ABI header files. Mixing the Windows Runtime ABI header files with C++\/WinRT does work, but it usually creates mass confusion for the developer, so let&#8217;s try not to do that.<\/p>\n<p>Even if you wade into this world, you have to take the COM ABI version of <code>IAsyncOperation&lt;WebTokenResult&gt;<\/code> and convert it back to its C++\/WinRT equivalent before you can <code>co_await<\/code> it, which is another level of annoying typing.<\/p>\n<p>Fortunately, there&#8217;s a way out of this mess. One is to realize that <code>winrt::IAsyncOperation&lt;winrt::WebTokenRequestResult&gt;<\/code> is the thing we want: A smart pointer around a raw ABI pointer. So use that.<\/p>\n<pre>winrt::IAsyncOperation&lt;winrt::WebTokenRequestResult&gt;\r\nRequestTokenForWindowAsync(HWND window, winrt::WebTokenRequest const&amp; request)\r\n{\r\n    auto interop = winrt::get_activation_factory&lt;winrt::WebAuthenticationCoreManager,\r\n                                                ::IWebAuthenticationCoreManagerInterop&gt;();\r\n\r\n    <span style=\"color: blue;\">winrt::IAsyncOperation&lt;winrt::WebTokenRequestResult&gt;<\/span> operation;\r\n    auto requestInspectable = static_cast&lt;::IInspectable*&gt;(winrt::get_abi(request));\r\n\r\n    winrt::check_hresult(\r\n        interop-&gt;RequestTokenForWindowAsync(\r\n        window,\r\n        requestInspectable,\r\n        <span style=\"color: blue;\">winrt::guid_of&lt;decltype(operation)&gt;()<\/span>,\r\n        operation.put_void()));\r\n\r\n    co_return co_await operation;\r\n}\r\n<\/pre>\n<p>Once we have it in this form, we can call upon our old friend <a title=\"The C++\/WinRT &quot;capture&quot; function helps you interoperate with the COM ABI world\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200917-00\/?p=104230\"> <code>winrt::capture<\/code><\/a>, whose job is to help obtain COM ABI objects and convert them to C++\/WinRT objects.<\/p>\n<pre>winrt::IAsyncOperation&lt;winrt::WebTokenRequestResult&gt;\r\nRequestTokenForWindowAsync(HWND window, winrt::WebTokenRequest const&amp; request)\r\n{\r\n    auto interop = winrt::get_activation_factory&lt;winrt::WebAuthenticationCoreManager,\r\n                                                ::IWebAuthenticationCoreManagerInterop&gt;();\r\n\r\n    auto requestInspectable = static_cast&lt;::IInspectable*&gt;(winrt::get_abi(request));\r\n\r\n    co_return co_await\r\n        winrt::capture&lt;winrt::IAsyncOperation&lt;winrt::WebTokenRequestResult&gt;&gt;(\r\n            interop,\r\n            &amp;::IWebAuthenticationCoreManagerInterop::RequestTokenForWindowAsync,\r\n            window,\r\n            requestInspectable);\r\n}\r\n<\/pre>\n<p>For style points, you could collapse the entire function into a one-liner.<\/p>\n<pre>winrt::IAsyncOperation&lt;winrt::WebTokenRequestResult&gt;\r\nRequestTokenForWindowAsync(HWND window, winrt::WebTokenRequest const&amp; request)\r\n{\r\n    return\r\n        winrt::capture&lt;winrt::IAsyncOperation&lt;winrt::WebTokenRequestResult&gt;&gt;(\r\n            winrt::get_activation_factory&lt;winrt::WebAuthenticationCoreManager,\r\n                                          ::IWebAuthenticationCoreManagerInterop&gt;(),\r\n            &amp;::IWebAuthenticationCoreManagerInterop::RequestTokenForWindowAsync,\r\n            window,\r\n            static_cast&lt;::IInspectable*&gt;(winrt::get_abi(request)));\r\n}\r\n<\/pre>\n<p>Replacing <code>co_return co_await<\/code> with a simple <code>return<\/code> works here because we are just returning the operation, so we can pass it through instead of wrapping it inside a coroutine. (This sort of trick is <a title=\"Why can't you return an IAsyncAction from a coroutine that also does a co_await?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200416-00\/?p=103677\"> not available in general<\/a>, but we can use it here.)<\/p>\n<p>One final tweak is using the WIL helper method <code>com_raw_ptr<\/code> to extract the ABI <code>IInspectable*<\/code> from a C++\/WinRT object.<\/p>\n<pre>winrt::IAsyncOperation&lt;winrt::WebTokenRequestResult&gt;\r\nRequestTokenForWindowAsync(HWND window, winrt::WebTokenRequest const&amp; request)\r\n{\r\n    return\r\n        winrt::capture&lt;winrt::IAsyncOperation&lt;winrt::WebTokenRequestResult&gt;&gt;(\r\n            winrt::get_activation_factory&lt;winrt::WebAuthenticationCoreManager,\r\n                                          ::IWebAuthenticationCoreManagerInterop&gt;(),\r\n            &amp;::IWebAuthenticationCoreManagerInterop::RequestTokenForWindowAsync,\r\n            window,\r\n            wil::com_raw_ptr(request));\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Understanding how the C++\/WinRT interop pieces fit together.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-105520","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Understanding how the C++\/WinRT interop pieces fit together.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105520","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=105520"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/105520\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=105520"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=105520"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=105520"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}