{"id":21053,"date":"2008-08-28T10:00:00","date_gmt":"2008-08-28T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2008\/08\/28\/what-possible-use-are-those-extra-bits-in-kernel-handles-part-2-overcoming-limited-expressiveness\/"},"modified":"2008-08-28T10:00:00","modified_gmt":"2008-08-28T10:00:00","slug":"what-possible-use-are-those-extra-bits-in-kernel-handles-part-2-overcoming-limited-expressiveness","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20080828-00\/?p=21053","title":{"rendered":"What possible use are those extra bits in kernel handles? Part 2: Overcoming limited expressiveness"},"content":{"rendered":"<p><P>\nLast time, we saw how\n<A HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/08\/27\/8898863.aspx\">\nthose extra bits can be used to develop safe sentinel values<\/A>.\nThat is a special case of a more general problem:\nHow do you pack 33&nbsp;bits of information into\na 32-bit value?\nWhereas last time, we weren&#8217;t forced into the use of a sentinel value\nbecause we could develop a (cumbersome) helper class and switch\npeople over to the helper class\n(or to pass two parameters to every function that used to take one),\nthere are places where you are forced to try to squeeze 33&nbsp;bits\nof information into a 32-bit value,\nand the helper class simply isn&#8217;t going to work.\n(I&#8217;m going to assume 32-bit Windows for concreteness,\nbut the same considerations apply to 64-bit Windows.\nJust make the appropriate changes.)\n<\/P>\n<P>\nSuppose you have a window message that does some work and\nreturns a <CODE>HANDLE<\/CODE>, but it can fail, and when it does,\nyou want to return an error code.\nIn other words, you want to return either\n<CODE>(TRUE, HANDLE)<\/CODE>\nor\n<CODE>(FALSE, HRESULT)<\/CODE>.\nBut that&#8217;s 33&nbsp;bits of information, and you can return only 32&nbsp;bits.\nHow can you provide 33&nbsp;bits of information with only 32&nbsp;bits?\n<\/P>\n<P>\nWell, it turns out that you don&#8217;t actually have 33&nbsp;bits of information\nto return.\nSince handle values are multiples of four, the bottom two bits are\nalways zero and therefore convey no information.\nA kernel handle is really only 30&nbsp;bits.\nSimilarly, a COM error code in the form of an <CODE>HRESULT<\/CODE> always\nhas the top bit set&mdash;after all if the top bit were clear, it would be\na success code!\nTherefore, there are only 31&nbsp;bits of information in an\n<CODE>HRESULT<\/CODE> error code.\n<\/P>\n<P>\nOkay, so it turns out that <CODE>(TRUE, HANDLE)<\/CODE> is only\n1 + 30 = 31 bits of information,\nand <CODE>(FALSE, HRESULT)<\/CODE> is only\n1 + 31 = 32 bits of information.\nWe can fit them inside a single 32-bit value after all!\n<\/P>\n<PRE>\nLRESULT PackHandleIntoLresult(HANDLE Handle)\n{\n  LRESULT Lresult = (LRESULT)Handle;<\/p>\n<p>  \/\/ if this assertion fires, then somebody tried to\n  \/\/ pack an invalid handle!\n  assert((Lresult &amp; 1) == 0);<\/p>\n<p>  return Lresult;\n}<\/p>\n<p>LRESULT PackErrorHresultIntoLresult(HRESULT Hresult)\n{\n  \/\/ if this assertion fires, then somebody tried to\n  \/\/ pack a success code!\n  assert(FAILED(Hresult));<\/p>\n<p>  return ((DWORD)Hresult &lt;&lt; 1) | 1;\n}\n<\/PRE>\n<P>\nThe bottom bit is our boolean that tells us whether we have\na success or failure.\nIf the bit is clear, then the operation succeeded and the entire\nvalue is the handle,\nrelying on the fact that valid handles always have the bottom two bits\nclear.\nOn the other hand, if the bottom bit is set,\nthen we have an error code, and the remaining 31&nbsp;bits give us\nthe significant bits of the <CODE>HRESULT<\/CODE>.\nUnpacking the values would then go like this:\n<\/P>\n<PRE>\nBOOL IsLresultError(LRESULT Lresult)\n{\n  return Lresult &amp; 1;\n}<\/p>\n<p>HANDLE UnpackLresultToHandle(LRESULT Lresult)\n{\n  assert(!IsLresultError(Lresult));\n  return (HANDLE)Lresult;\n}<\/p>\n<p>HRESULT UnpackLresultToHresult(LRESULT Lresult)\n{\n  assert(IsLresultError(Lresult));\n  return (HRESULT)(0x80000000 | ((DWORD)Lresult &gt;&gt; 1));\n}\n<\/PRE>\n<P>\nIn pictures (since people like pictures):\n<\/P>\n<PRE>\nSuccess:\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x|0|0| HANDLE\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |\n v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x|0|0| LRESULT\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |\n v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x|0|0| HANDLE\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<\/p>\n<p>Failure:\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|1|e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e| HRESULT\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n  \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/\n v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e|1| LRESULT\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n  \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\ \\\n   v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v v\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n|1|e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e e| HRESULT\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n<\/PRE>\n<P>\nThat bottom bit tells us whether the upper 31&nbsp;bits are\nthe meaningful bits from a <CODE>HANDLE<\/CODE>\nor the meaningful bits from an <CODE>HRESULT<\/CODE>.\nOnce we know which case we are in, we can take those upper bits\nand put them back into meaningful parts of the source data.\n<\/P>\n<P>\nIf you want to put this trick on a more formal footing, you could\nexpress the multiplexing in the form of a discriminant in a union:\n<\/P>\n<PRE>\n\/\/ Type-specific value for HANDLE is the upper 31 bits\nLRESULT TypeSpecificValueFromHandle(HANDLE Handle)\n{\n  LRESULT Lresult = (LRESULT)Handle;<\/p>\n<p>  \/\/ if this assertion fires, then somebody tried to\n  \/\/ pack an invalid handle!\n  assert((Lresult &amp;1) == 0);<\/p>\n<p>  \/\/ discard the bottom bit since we know it is zero\n  return Lresult &gt;&gt; 1;\n}<\/p>\n<p>HANDLE HandleFromTypeSpecificValue(LRESULT Lresult)\n{\n  \/\/ regenerate the bottom bit which we know is zero\n  return (HANDLE)(Lresult &lt;&lt; 1);\n}<\/p>\n<p>\/\/ Type-specific value for HRESULT is the lower 31 bits\nLRESULT TypeSpecificValueFromHresult(HRESULT Hresult)\n{\n  \/\/ if this assertion fires, then somebody tried to\n  \/\/ pack a success code!\n  assert(FAILED(Hresult));<\/p>\n<p>  \/\/ discard the top bit since we know it is 1\n  return (DWORD)Hresult &amp; 0x7FFFFFFF;\n}<\/p>\n<p>HRESULT HresultFromTypeSpecificValue(LRESULT Lresult)\n{\n  \/\/ regenerate the top bit which we know is 1\n  return (HRESULT)(Lresult | 0x80000000);\n}<\/p>\n<p>\/\/ Oh boy, let&#8217;s pack and unpack these puppies\n#define TYPE_HANDLE  0\n#define TYPE_HRESULT 1<\/p>\n<p>typedef struct PACKEDLRESULT {\n int Type:1;\n LRESULT TypeSpecificValue:sizeof(LRESULT)*8-1;\n} PACKEDLRESULT;<\/p>\n<p>typedef union PACKEDLRESULTHELPER {\n PACKEDLRESULT Structure;\n LRESULT Lresult;\n} PACKEDLRESULTHELPER;<\/p>\n<p>LRESULT PackLresult(int Type, LRESULT TypeSpecificValue)\n{\n  PACKEDLRESULTHELPER Helper;\n  Helper.Structure.Type = Type;\n  Helper.Structure.TypeSpecificValue = TypeSpecificValue;\n  return Helper.Lresult;\n}<\/p>\n<p>int GetPackedLresultType(LRESULT Lresult)\n{\n  PACKEDLRESULTHELPER Helper;\n  Helper.Lresult = Lresult;\n  return Helper.Structure.Type;\n}<\/p>\n<p>HANDLE GetHandleFromPackedLresult(LRESULT Lresult)\n{\n  PACKEDLRESULTHELPER Helper;\n  Helper.Lresult = Lresult;\n  return HandleFromTypeSpecificValue(Helper.Structure.TypeSpecificValue);\n}<\/p>\n<p>HRESULT GetHresultFromPackedLresult(LRESULT Lresult)\n{\n  PACKEDLRESULTHELPER Helper;\n  Helper.Lresult = Lresult;\n  return HresultFromTypeSpecificValue(Helper.Structure.TypeSpecificValue);\n}\n<\/PRE>\n<P>\nThis more explicit form may be more helpful if you have more than just\ntwo types to discriminate among, but in our case, the extra typing\nprobably just confuses the matter more than clearing it up.\n<\/P>\n<P>\nThis type of trick is actually quite common.\nFor example, the\n<A HREF=\"http:\/\/msdn2.microsoft.com\/en-us\/library\/ms696170.aspx\">\n<CODE>LresultFromObject<\/CODE><\/A>\nfunction uses a variation of this technique in order to pack\na marshallable object <I>and<\/I> a COM error code into a single 32-bit value.\nIt&#8217;s also common in lisp systems, where it is known by the name\n<I>tagged pointers<\/I>.\n<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last time, we saw how those extra bits can be used to develop safe sentinel values. That is a special case of a more general problem: How do you pack 33&nbsp;bits of information into a 32-bit value? Whereas last time, we weren&#8217;t forced into the use of a sentinel value because we could develop a [&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-21053","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Last time, we saw how those extra bits can be used to develop safe sentinel values. That is a special case of a more general problem: How do you pack 33&nbsp;bits of information into a 32-bit value? Whereas last time, we weren&#8217;t forced into the use of a sentinel value because we could develop a [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/21053","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=21053"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/21053\/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=21053"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=21053"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=21053"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}