{"id":103679,"date":"2020-04-17T07:00:00","date_gmt":"2020-04-17T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=103679"},"modified":"2020-04-17T06:11:49","modified_gmt":"2020-04-17T13:11:49","slug":"20200417-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200417-00\/?p=103679","title":{"rendered":"What will be placed in the output parameter if the function fails?"},"content":{"rendered":"<p>A customer wanted to know what, if anything, can be said about the value in the output parameter of the <code>Open\u00adProcess\u00adToken<\/code> function if the call fails.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20060320-13\/?p=31853\"> According to the ground rules<\/a>, the contents of output parameters are unspecified on failure. There is a special rule for COM which says that the contents of output parameters on failure must be valid values for their type. For example, if the output parameter is a COM interface pointer, then it must contain a valid value for a COM interface pointer on return, even if the call failed.\u00b9<\/p>\n<p>However, as a concession to the widespread use of <a href=\"https:\/\/en.cppreference.com\/w\/cpp\/language\/raii\"> RAII types<\/a>, the <i>de facto<\/i> rule is that if the output parameter is a resource that requires management (disposal, release, etc.), then the value on failure is either unchanged or set to a &#8220;no resource&#8221; value.<\/p>\n<p>If you use an RAII type, then you are going to pass an empty\u00b2 RAII object to the function because the function may put a valid object into the RAII object, and you don&#8217;t want to leak the old object. Therefore, if the function that fails leaves the RAII object empty or explicitly sets it to empty, the RAII object can be destructed without harm. On the other hand, if the function put garbage in the output parameter, then the RAII type is going to try to clean up a garbage resource, which is unlikely to end well.<\/p>\n<p>In other words, for types that require cleanup, &#8220;empty stays empty&#8221; on failure. (On the other hand, if the original object was not empty, it&#8217;s not specified whether the result is empty or not.)<\/p>\n<p>Now, if the output doesn&#8217;t require resource management, then this rule doesn&#8217;t apply. For example, if the output is a string buffer, the buffer could very well be filled with garbage on failure. You need to free the buffer, and a buffer of garbage can be freed just as easily as a buffer with a valid string in it.<\/p>\n<p>Examples:<\/p>\n<pre>BOOL GetSomething(HSOMETHING* result);\r\n<\/pre>\n<p>Does the <code>HSOMETHING<\/code> need to be destroyed in a special way? If so, then on failure, <code>Get\u00adSomething<\/code> will either leave the <code>*result<\/code> unchanged, or set it to <code>nullptr<\/code>. If you are using an RAII type to hold the <code>HSOMETHING<\/code>, then you will have arranged for <code>*result<\/code> to contain <code>nullptr<\/code> before calling <code>Get\u00adSomething<\/code>, which means that on failure, <code>*result<\/code> will still be <code>nullptr<\/code>.<\/p>\n<pre>HRESULT GetWidgetName(HWIDGET widget, wchar_t buffer[], size_t size);\r\n<\/pre>\n<p>Since <code>wchar_t<\/code> does not require any special resource management, the <code>buffer<\/code> could be filled with garbage if <code>Get\u00adWidget\u00adName<\/code> fails.<\/p>\n<pre>HRESULT GetWidgetName(HWIDGET widget, PWSTR* name);\r\n<\/pre>\n<p>This case is different. Let&#8217;s say that the <code>name<\/code> needs to be freed with a function like <code>Co\u00adTask\u00adMem\u00adFree<\/code>. In that case, the function cannot set <code>*name<\/code> to a garbage pointer, because that would cause <code>Co\u00adTask\u00adMem\u00adFree<\/code> to crash. On failure, <code>*name<\/code> will be unchanged or set to <code>nullptr<\/code>.<\/p>\n<p><b>Bonus chatter<\/b>: WIL has <a href=\"https:\/\/github.com\/microsoft\/wil\/blob\/master\/include\/wil\/token_helpers.h\"> a number of helper functions<\/a> for manipulating tokens.<\/p>\n<p>\u00b9 For COM interface pointers, the value is typically <code>nullptr<\/code> on failure. Exceptions are called out in the function documentation if the result is anything else. For example, a function might return <code>E_PENDING<\/code> and put a provisional answer in the output pointer, with a complete answer provided when the operation completes.<\/p>\n<p>\u00b2 The word <i>empty<\/i> is a term of art which refers to the case where an object of an RAII type is not managing anything.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Officially, it could be anything. In practice, though, there are some constraints.<\/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-103679","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Officially, it could be anything. In practice, though, there are some constraints.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103679","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=103679"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103679\/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=103679"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=103679"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=103679"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}