{"id":106483,"date":"2022-04-14T07:00:00","date_gmt":"2022-04-14T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=106483"},"modified":"2022-04-14T07:17:41","modified_gmt":"2022-04-14T14:17:41","slug":"20220414-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20220414-00\/?p=106483","title":{"rendered":"How can I tell the WIL <CODE>RETURN_<WBR>IF_<WBR>FAILED<\/CODE> macro that some errors are ignorable?"},"content":{"rendered":"<p>The WIL <code>RETURN_<wbr \/>IF_<wbr \/>FAILED<\/code> macro evaluates its argument, and if it is a COM failure <code>HRESULT<\/code>, then it returns immediately from the function with that <code>HRESULT<\/code>. There is also a <code>RETURN_<wbr \/>IF_<wbr \/>FAILED_<wbr \/>EXPECTED<\/code> macro that behaves the same, except that any failures are not recorded in the error log. The <code>EXPECTED<\/code> version is for the case where a function fails, but you don&#8217;t want it cluttering your error log.<\/p>\n<p>But one case that&#8217;s not covered is &#8220;Call this function, and return immediately if the call fails, except that certain errors should be ignored and allow execution to continue.&#8221; How do you do that?<\/p>\n<p>You can build a filter function that you send the result through, and the filter function can convert all the harmless errors into <code>S_OK<\/code>.<\/p>\n<pre>HRESULT AllowPending(HRESULT hr)\r\n{\r\n    if (hr == E_PENDING) return S_OK;\r\n    return hr;\r\n}\r\n<\/pre>\n<p>You can then combine this with <code>RETURN_<wbr \/>IF_<wbr \/>FAILED<\/code>:<\/p>\n<pre>    RETURN_IF_FAILED(AllowPending(GetItem()));\r\n<\/pre>\n<p>You can even generalize this to allow the list of allowed errors to be passed as a parameter:<\/p>\n<pre>HRESULT IgnoreSpecificErrors(\r\n    HRESULT hr,\r\n    std::initializer_list&lt;HRESULT&gt; ignored)\r\n{\r\n    for (auto candidate : ignored) {\r\n        if (hr == candidate) return S_OK;\r\n    }\r\n    return hr;\r\n}\r\n\r\n\r\n    RETURN_IF_FAILED(IgnoreSpecificErrors(GetItem(), { E_PENDING }));\r\n<\/pre>\n<p>You can also create sets of ignorable errors:<\/p>\n<pre>constexpr HRESULT rpc_errors[] {\r\n    RPC_E_DISCONNECTED,\r\n    RPC_E_SERVER_DIED,\r\n    RPC_E_SERVER_DIED_DNE,\r\n};\r\n\r\n    RETURN_IF_FAILED(IgnoreSpecificErrors(GetItem(), rpc_errors));\r\n<\/pre>\n<p>The nice thing about using a filter function is that you can add whatever other features you like.<\/p>\n<pre>HRESULT IgnoreSpecificErrors(\r\n    HRESULT hr,\r\n    std::initializer_list&lt;HRESULT&gt; ignored)\r\n{\r\n    for (auto candidate : ignored) {\r\n        if (hr == candidate) {\r\n            LOG_HR(hr); \/\/ log the failure before transforming it\r\n            return S_OK;\r\n        }\r\n    }\r\n    return hr;\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>You can create a custom filter using things you already know how to do.<\/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-106483","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You can create a custom filter using things you already know how to do.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/106483","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=106483"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/106483\/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=106483"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=106483"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=106483"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}