{"id":94585,"date":"2016-10-26T07:00:00","date_gmt":"2016-10-26T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=94585"},"modified":"2019-03-13T10:32:59","modified_gmt":"2019-03-13T17:32:59","slug":"20161026-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20161026-00\/?p=94585","title":{"rendered":"Why does the documentation for ReadFile say that the lpNumberOfBytesRead parameter is optional when it is sometimes mandatory?"},"content":{"rendered":"<p>The <a HREF=\"https:\/\/msdn.microsoft.com\/en-us\/library\/windows\/desktop\/aa365467(v=vs.85).aspx\">documentation for the <code>Read&shy;File<\/code> function<\/a> says <\/p>\n<pre>\nBOOL WINAPI ReadFile(\n  _In_ HANDLE hFile,\n  _Out_ LPVOID lpBuffer,\n  _In_ DWORD nNumberOfBytesToRead,\n  _Out_opt_ LPDWORD lpNumberOfBytesRead,\n  _Inout_opt_ LPOVERLAPPED lpOverlapped\n);\n<\/pre>\n<p>The <code>lpNumber&shy;Of&shy;Bytes&shy;Read<\/code> parameter is declared as <code>_Out_opt_<\/code>. The <code>_Out_<\/code> part means that the function writes to the pointed-to value. The <code>_opt_<\/code> part means that the parameter is optional (may be null). And yet, if you call <code>Read&shy;File<\/code> and pass <code>nullptr<\/code> for the fourth parameter, it crashes. What&#8217;s going on here? <\/p>\n<p>What&#8217;s going on is in the fine print: <\/p>\n<blockquote CLASS=\"q\">\n<dl>\n<dt><i>lpNumberOfBytesRead<\/i> [out, optional]<\/dt>\n<dd>\n<p>A pointer to the variable that receives the number of bytes read when using a synchronous <i>hFile<\/i> parameter. <b>Read&shy;File<\/b> sets this value to zero before doing any work or error checking. Use <b>NULL<\/b> for this parameter if this is an asynchronous operation to avoid potentially erroneous results. <\/p>\n<p>This parameter can be <b>NULL<\/b> only when the <i>lpOverlapped<\/i> parameter is not <b>NULL<\/b>. <\/p>\n<p>For more information, see the Remarks section. <\/p>\n<\/dd>\n<\/blockquote>\n<p>Note that second paragraph. <\/p>\n<p>The deal is that the fourth parameter is sometimes optional and sometimes mandatory. The <a HREF=\"https:\/\/msdn.microsoft.com\/en-us\/library\/hh916382.aspx\">simplified annotation language<\/a> used by this function prototype cannot express this sort of conditional mandatory state, so it takes the most generous position of declaring the parameter as optional, so as to avoid raising false positives in <a HREF=\"https:\/\/msdn.microsoft.com\/en-us\/library\/ms182028.aspx\">static analysis tools<\/a>. <\/p>\n<p>A more precise annotation for that parameter would be something like <code>_When_(lpOverlapped == NULL, _Out_opt_) _When_(lpOverlapped != NULL, _Out_)<\/code>. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the fine print, due to incomplete expressiveness.<\/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-94585","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>In the fine print, due to incomplete expressiveness.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/94585","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=94585"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/94585\/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=94585"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=94585"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=94585"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}