{"id":29133,"date":"2006-11-03T10:00:07","date_gmt":"2006-11-03T10:00:07","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2006\/11\/03\/how-do-i-convert-an-hresult-to-a-win32-error-code\/"},"modified":"2006-11-03T10:00:07","modified_gmt":"2006-11-03T10:00:07","slug":"how-do-i-convert-an-hresult-to-a-win32-error-code","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20061103-07\/?p=29133","title":{"rendered":"How do I convert an HRESULT to a Win32 error code?"},"content":{"rendered":"<p>\nEverybody knows that you can use the <code>HRESULT_FROM_WIN32<\/code>\nmacro to convert a Win32 error code to an <code>HRESULT<\/code>,\nbut how do you do the reverse?\n<\/p>\n<p>\nLet&#8217;s look at the definition of <code>HRESULT_FROM_WIN32<\/code>:\n<\/p>\n<pre>\n#define HRESULT_FROM_WIN32(x) \\\n  ((HRESULT)(x) &lt;= 0 ? ((HRESULT)(x)) \\\n: ((HRESULT) (((x) &amp; 0x0000FFFF) | (FACILITY_WIN32 &lt;&lt; 16) | 0x80000000)))\n<\/pre>\n<p>\nIf the value is less than or equal to zero, then the macro returns\nthe value unchanged.\nOtherwise, it takes the lower sixteen bits and combines them with\n<code>FACILITY_WIN32<\/code> and <code>SEVERITY_ERROR<\/code>.\n<\/p>\n<p>\nHow do you reverse this process?\nHow do you write the function\n<code>WIN32_FROM_HRESULT<\/code>?\n<\/p>\n<p>\nIt&#8217;s impossible to write that function since the mapping provided\nby the <code>HRESULT_FROM_WIN32<\/code> function is not one-to-one.\nI leave as an execise to draw the set-to-set mapping diagram\nfrom <code>DWORD<\/code> to <code>HRESULT<\/code>.\n(Original diagram removed since\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/06\/23\/644239.aspx#647297\">\npeople hate VML so much<\/a>,\nand I can&#8217;t use SVG since it requies XHTML.)\nIf you do it correctly, you&#8217;ll have a single line\nwhich maps 0&nbsp;to <code>S_OK<\/code>,\nand a series of blocks that map blocks of 65536 error codes\ninto the same <code>HRESULT<\/code> space.\n<\/p>\n<p>&lt;!&#8211;\nLet&#039;s draw a diagram that shows how the <code>HRESULT_FROM_WIN32<\/code>\nfunction works:<\/p>\n<table BORDER=\"0\">\n<tr>\n<td STYLE=\"padding-top: 10pt\">\n<div>\n<p> Win32\n HRESULT<\/p>\n<\/div>\n<\/td>\n<\/tr>\n<\/table>\n<p>\nThe little sliver at the top is the mapping of zero to zero.\nThe big white box at the bottom is the mapping of all negative\nnumbers to corresponding negative numbers.\nAnd the rainbow represents the mapping of all the positive\nvalues, mod 65536, into the range 0x80070000 through 0x8007FFFF.\n<\/p>\n<p>&#8211;&gt;<\/p>\n<p>\nNotice that the values in the range 1 through 0x7FFFFFFFF\nare impossible results from the <code>HRESULT_FROM_WIN32<\/code> macro.\nFurthermore, values in the range 0x80070000 through 0x8007FFFF\ncould have come from quite a few original Win32 codes; you can&#8217;t\npick just one.\n<\/p>\n<p>\nBut let&#8217;s try to write the reverse function anyway:\n<\/p>\n<pre>\nBOOL WIN32_FROM_HRESULT(HRESULT hr, OUT DWORD *pdwWin32)\n{\n if ((hr &amp; 0xFFFF0000) == MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32)) {\n  \/\/ Could have come from many values, but we choose this one\n  *pdwWin32 = HRESULT_CODE(hr);\n  return TRUE;\n }\n if (hr == S_OK) {\n  *pdwWin32 = HRESULT_CODE(hr);\n  return TRUE;\n }\n \/\/ otherwise, we got an impossible value\n return FALSE;\n}\n<\/pre>\n<p>\nOf course, we could have been petulant and just written<\/p>\n<pre>\nBOOL WIN32_FROM_HRESULT_alternate(HRESULT hr, OUT DWORD *pdwWin32)\n{\n if (hr &lt; 0) {\n  *pdwWin32 = (DWORD)hr;\n  return TRUE;\n }\n \/\/ otherwise, we got an impossible value\n return FALSE;\n}\n<\/pre>\n<p>\nbecause the <code>HRESULT_FROM_WIN32<\/code> macro is idempotent:\n<code>HRESULT_FROM_WIN32(HRESULT_FROM_WIN32(x)) ==\nHRESULT_FROM_WIN32(x)<\/code>.\nTherefore you would be technically correct if you declared that\nthe &#8220;inverse&#8221; function was trivial.\nBut in practice, people want to try to get &#8220;x&#8221; back out, so that&#8217;s\nwhat we give you.\n<\/p>\n<p>\nNow that you understand how the <code>HRESULT_FROM_WIN32<\/code> macro\nworks, you can answer this question, based on an actual customer question:\n<\/p>\n<blockquote CLASS=\"q\"><p>\nSometimes, when I import data from a scanner, I get the error\n&#8220;The directory cannot be removed.&#8221;\nWhat does this mean?\n<\/p><\/blockquote>\n<p>\nYou will have to use some psychic powers, but I think you&#8217;re up to it.\n<\/p>\n<p>\nOne unfortunate aspect of both <code>HRESULT<\/code>s and\nWin32 error codes is that there is no single header file that\ncontains all the errors.\nThis is understandable from a logistical point of view:\nMultiple teams need to make up new error codes for their components,\nbut the <code>winerror.h<\/code> file is maintained by the kernel team.\nIf <code>winerror.h<\/code> were selected to be the master repository\nfor all error codes, it means that any team that wanted to add a new\nerror code or change an existing one would have to pester the kernel\nteam to make the change for them.\nThings get even more complicated if those teams have their own SDK.\nFor example, suppose both the DirectX and Windows Media teams wanted\nto include the new <code>winerror.h<\/code> in their corresponding SDKs.\nIf you install the SDKs in the wrong order (and how are you supposed to\nknow which should be installed first, DirectX 8 or WMSDK 6?),\nyou can end up regressing your <code>winerror.h<\/code> file.\nIt&#8217;s the version conflict problem, but without the benefit of version\nresources.\n<\/p>\n<p>\nMany teams have prevailed upon the kernel team to reserve a chunk of\nerror codes just for them.\n<\/p>\n<table>\n<tr>\n<td>Networking<\/td>\n<td ALIGN=\"RIGHT\">2100&ndash;2999<\/td>\n<\/tr>\n<tr>\n<td>Cluster<\/td>\n<td ALIGN=\"RIGHT\">5000&ndash;5999<\/td>\n<\/tr>\n<tr>\n<td>Traffic Control<\/td>\n<td ALIGN=\"RIGHT\">7500&ndash;7999<\/td>\n<\/tr>\n<tr>\n<td>Active Directory<\/td>\n<td ALIGN=\"RIGHT\">8000&ndash;8999<\/td>\n<\/tr>\n<tr>\n<td>DNS<\/td>\n<td ALIGN=\"RIGHT\">9000&ndash;9999<\/td>\n<\/tr>\n<tr>\n<td>Winsock<\/td>\n<td ALIGN=\"RIGHT\">10000&ndash;11999<\/td>\n<\/tr>\n<tr>\n<td>IPSec<\/td>\n<td ALIGN=\"RIGHT\">13000&ndash;13999<\/td>\n<\/tr>\n<tr>\n<td>Side By Side<\/td>\n<td ALIGN=\"RIGHT\">14000&ndash;14999<\/td>\n<\/tr>\n<\/table>\n<p>\nThere is room for only 65535 Win32 error codes, and over an eighth\nof them have already been carved out by these &#8220;block assignments&#8221;.\nI wonder if we will eventually run out of error codes prematurely\ndue to having given away error codes in too-large chunks.\n(Some sort of analogy with IPv4 could be made here but I&#8217;m not going to try.)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Everybody knows that you can use the HRESULT_FROM_WIN32 macro to convert a Win32 error code to an HRESULT, but how do you do the reverse? Let&#8217;s look at the definition of HRESULT_FROM_WIN32: #define HRESULT_FROM_WIN32(x) \\ ((HRESULT)(x) &lt;= 0 ? ((HRESULT)(x)) \\ : ((HRESULT) (((x) &amp; 0x0000FFFF) | (FACILITY_WIN32 &lt;&lt; 16) | 0x80000000))) If the value [&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":[25],"class_list":["post-29133","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Everybody knows that you can use the HRESULT_FROM_WIN32 macro to convert a Win32 error code to an HRESULT, but how do you do the reverse? Let&#8217;s look at the definition of HRESULT_FROM_WIN32: #define HRESULT_FROM_WIN32(x) \\ ((HRESULT)(x) &lt;= 0 ? ((HRESULT)(x)) \\ : ((HRESULT) (((x) &amp; 0x0000FFFF) | (FACILITY_WIN32 &lt;&lt; 16) | 0x80000000))) If the value [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/29133","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=29133"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/29133\/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=29133"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=29133"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=29133"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}