{"id":109782,"date":"2024-05-20T07:00:00","date_gmt":"2024-05-20T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109782"},"modified":"2024-06-07T06:33:18","modified_gmt":"2024-06-07T13:33:18","slug":"20240520-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240520-00\/?p=109782","title":{"rendered":"If you know what interface you want, just pass it directly to CoCreateInstance"},"content":{"rendered":"<p>A pattern I sometimes see is calling <code>Co\u00adCreate\u00adInstance<\/code> for an interface, and immediately turning around and querying for another interface, and never using the original interface.\u00b9<\/p>\n<pre>wil::com_ptr&lt;IWidget&gt; widget;\r\nRETURN_IF_FAILED(\r\n    CoCreateInstance(CLSID_Widget, nullptr,\r\n        CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&amp;widget)));\r\n\r\nwil::com_ptr&lt;IServiceProvider&gt; provider;\r\nRETURN_IF_FAILED(\r\n    widget-&gt;QueryInterface(IID_PPV_ARGS(&amp;provider)));\r\n\r\n\/\/ use the service provider, ignore the widget\r\n<\/pre>\n<p>There&#8217;s rarely any need to request one interface, then immediately exchange it for another interface. You may as well go directly for the interface you want:<\/p>\n<pre>wil::com_ptr&lt;IServiceProvider&gt; provider;\r\nRETURN_IF_FAILED(\r\n    CoCreateInstance(CLSID_Widget, nullptr,\r\n        CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&amp;provider)));\r\n\r\n\/\/ use the service provider\r\n<\/pre>\n<p>For non-local interfaces, collapsing the request into a single call avoids a round trip to the server.<\/p>\n<p>The only case I can think of where the initial interface is significant is if you want to ensure that the object supports the intermediate interface, even though you aren&#8217;t going to be using it right now.<\/p>\n<pre>\/\/ Factories must support IServiceProvider.\r\nwil::com_ptr&lt;IServiceProvider&gt; provider;\r\nRETURN_IF_FAILED(\r\n    CoCreateInstance(factoryClassId, nullptr,\r\n        CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&amp;provider)));\r\n\r\nwil::com_ptr&lt;IWidget&gt; widget;\r\nRETURN_IF_FAILED(\r\n    provider-&gt;QueryInterface(IID_PPV_ARGS(&amp;widget)));\r\n\r\n\/\/ use the widget, ignore the IServiceProvider for now\r\n<\/pre>\n<p>In that case, you can still avoid a round trip to the server by using <code>Co\u00adCreate\u00adInstance\u00adEx<\/code> to request multiple interfaces at once.<\/p>\n<pre>MULTI_QI mqi[2] = {\r\n    { &amp;__uuidof(IWidget), nullptr, 0 },\r\n    { &amp;__uuidof(IServiceProvider), nullptr, 0 },\r\n};\r\n\r\nRETURN_IF_FAILED(CoCreateInstanceEx(\r\n    factoryClassId, nullptr, CLSCTX_LOCAL_SERVER,\r\n    nullptr, ARRAYSIZE(mqi), mqi));\r\n\r\nwil::com_ptr&lt;IWidget&gt; widget;\r\nwidget.attach(mqi[0].pItf);\r\n\r\nwil::com_ptr&lt;IServiceProvider&gt; provider;\r\nprovider.attach(mqi[1].pItf);\r\n\r\nif (hr != S_OK) {\r\n    \/\/ Failed to get at least one interface.\r\n    return E_NOINTERFACE;\r\n}\r\n<\/pre>\n<p>You can refer to <a title=\"Reducing chattiness by querying for multiple interfaces at once, part 1\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20220315-00\/?p=106350\"> my earlier series on <code>MULTI_QI<\/code><\/a> for further discussion.<\/p>\n<p>\u00b9 Note that I&#8217;m using WIL only for its smart pointer class and still programming to the ABI for the most part. WIL itself contains wrappers for many of the patterns here, but this article is really about the pattern and not the WIL wrappers.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Avoiding a second round trip.<\/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-109782","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Avoiding a second round trip.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109782","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=109782"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109782\/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=109782"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109782"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109782"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}