{"id":40443,"date":"2004-03-02T06:57:00","date_gmt":"2004-03-02T06:57:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2004\/03\/02\/why-are-handle-return-values-so-inconsistent\/"},"modified":"2004-03-02T06:57:00","modified_gmt":"2004-03-02T06:57:00","slug":"why-are-handle-return-values-so-inconsistent","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20040302-00\/?p=40443","title":{"rendered":"Why are HANDLE return values so inconsistent?"},"content":{"rendered":"<p>\nIf you look at the various functions that return <code>HANDLE<\/code>s,\nyou&#8217;ll see that some of them return <code>NULL<\/code>\n(like <code>CreateThread<\/code>)\nand some of them return <code>INVALID_HANDLE_VALUE<\/code>\n(like <code>CreateFile<\/code>).\nYou have to check the documentation to see what each particular function\nreturns on failure.<\/p>\n<p>\nWhy are the return values so inconsistent?<\/p>\n<p>\nThe reasons, as you may suspect, are historical.<\/p>\n<p>\nThe values were chosen to be compatible with 16-bit Windows.\nThe 16-bit functions <code>OpenFile<\/code>, <code>_lopen<\/code> and\n<code>_lcreat<\/code> return <code>-1<\/code> on failure, so the 32-bit\n<code>CreateFile<\/code> function returns <code>INVALID_HANDLE_VALUE<\/code>\nin order to facilitate porting code from Win16.<\/p>\n<p>\n(Armed with this, you can now answer the following trivia\nquestion: Why do I call <code>CreateFile<\/code>\nwhen I&#8217;m not actually creating a file?  Shouldn&#8217;t it be called\n<code>OpenFile<\/code>?  Answer:  Yes, <code>OpenFile<\/code> would have\nbeen a better name, but\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/en-us\/fileio\/base\/openfile.asp\">\nthat name was already taken<\/a>.)<\/p>\n<p>\nOn the other hand, there are no Win16 equivalents for\n<code>CreateThread<\/code> or <code>CreateMutex<\/code>, so they\nreturn <code>NULL<\/code>.<\/p>\n<p>\nSince the precedent had now been set for inconsistent return values,\nwhenever a new function got added, it was a bit of a toss-up whether\nthe new function returned <code>NULL<\/code> or\n<code>INVALID_HANDLE_VALUE<\/code>.<\/p>\n<p>\nThis inconsistency has multiple consequences.<\/p>\n<p>\nFirst, of course, you have to be careful to check the return values\nproperly.<\/p>\n<p>\nSecond, it means that if you write a generic handle-wrapping class,\nyou have to be mindful of two possible &#8220;not a handle&#8221; values.<\/p>\n<p>\nThird, if you want to pre-initialize a <code>HANDLE<\/code> variable,\nyou have to initialize it in a manner compatible with the function\nyou intend to use.  For example, the following code is wrong:<\/p>\n<pre>\nHANDLE h = NULL;\nif (UseLogFile()) {\n    h = CreateFile(...);\n}\nDoOtherStuff();\nif (h) {\n   Log(h);\n}\nDoOtherStuff();\nif (h) {\n    CloseHandle(h);\n}\n<\/pre>\n<p>This code has two bugs.  First, the return value from\n<code>CreateFile<\/code> is checked incorrectly.  The code above\nchecks for <code>NULL<\/code> instead of <code>INVALID_HANDLE_VALUE<\/code>.\nSecond, the code initializes the <code>h<\/code> variable incorrectly.\nHere&#8217;s the corrected version:<\/p>\n<pre>\nHANDLE h = INVALID_HANDLE_VALUE;\nif (UseLogFile()) {\n    h = CreateFile(...);\n}\nDoOtherStuff();\nif (h != INVALID_HANDLE_VALUE) {\n   Log(h);\n}\nDoOtherStuff();\nif (h != INVALID_HANDLE_VALUE) {\n    CloseHandle(h);\n}\n<\/pre>\n<p>\nFourth, you have to be particularly careful with the\n<code>INVALID_HANDLE_VALUE<\/code> value:\nBy coincidence, the value <code>INVALID_HANDLE_VALUE<\/code>\nhappens to be numerically equal to the pseudohandle returned by\n<code>GetCurrentProcess()<\/code>.\nMany kernel functions accept pseudohandles, so if\nif you mess up\nand accidentally call, say, <code>WaitForSingleObject<\/code> on a\nfailed <code>INVALID_HANDLE_VALUE<\/code> handle, you will actually\nend up waiting on your own process.  This wait will, of course,\nnever complete, because a process is signalled when it exits,\nso you ended up waiting for yourself.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you look at the various functions that return HANDLEs, you&#8217;ll see that some of them return NULL (like CreateThread) and some of them return INVALID_HANDLE_VALUE (like CreateFile). You have to check the documentation to see what each particular function returns on failure. Why are the return values so inconsistent? The reasons, as you may [&hellip;]<\/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":[2],"class_list":["post-40443","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>If you look at the various functions that return HANDLEs, you&#8217;ll see that some of them return NULL (like CreateThread) and some of them return INVALID_HANDLE_VALUE (like CreateFile). You have to check the documentation to see what each particular function returns on failure. Why are the return values so inconsistent? The reasons, as you may [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/40443","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=40443"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/40443\/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=40443"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=40443"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=40443"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}