{"id":107221,"date":"2022-09-28T07:00:00","date_gmt":"2022-09-28T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=107221"},"modified":"2022-09-28T06:52:42","modified_gmt":"2022-09-28T13:52:42","slug":"20220928-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20220928-00\/?p=107221","title":{"rendered":"Why does COM express GUIDs in a mix of big-endian and little-endian? Why can&#8217;t it just pick a side and stick with it?"},"content":{"rendered":"<p>Wikipedia claims that <a href=\"https:\/\/en.wikipedia.org\/wiki\/Universally_unique_identifier#Encoding\"> the COM textual representation of GUIDs is mixed-endian<\/a>.<\/p>\n<p>Is it, really?<\/p>\n<p>No, it is little-endian all the way. But if you don&#8217;t understand how GUIDs are formed, it might look like some parts are big-endian.<\/p>\n<p><a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/rfc4122#section-4.1.2\"> The parts of a GUID as defined in the specification<\/a> are<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Field<\/th>\n<th>Type<\/th>\n<\/tr>\n<tr>\n<td><tt>time_low<\/tt><\/td>\n<td>32-bit integer<\/td>\n<\/tr>\n<tr>\n<td><tt>time_mid<\/tt><\/td>\n<td>16-bit integer<\/td>\n<\/tr>\n<tr>\n<td><tt>time_hi_and_version<\/tt><\/td>\n<td>16-bit integer<\/td>\n<\/tr>\n<tr>\n<td><tt>clock_seq_hi_and_reserved<\/tt><\/td>\n<td>8-bit integer<\/td>\n<\/tr>\n<tr>\n<td><tt>cloc_seq_low<\/tt><\/td>\n<td>8-bit integer<\/td>\n<\/tr>\n<tr>\n<td><tt>node<\/tt><\/td>\n<td>6-byte MAC address<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The <code>GUID<\/code> structure breaks it down as<\/p>\n<pre>struct GUID\r\n{\r\n    uint32_t Data1;\r\n    uint16_t Data2;\r\n    uint16_t Data3;\r\n    uint8_t  Data4[8];\r\n}\r\n<\/pre>\n<p>Let&#8217;s line up the two pieces against each other.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Field<\/th>\n<th>Type<\/th>\n<th>Structure<\/th>\n<\/tr>\n<tr>\n<td><tt>time_low<\/tt><\/td>\n<td>32-bit integer<\/td>\n<td><code>Data1<\/code><\/td>\n<\/tr>\n<tr>\n<td><tt>time_mid<\/tt><\/td>\n<td>16-bit integer<\/td>\n<td><code>Data2<\/code><\/td>\n<\/tr>\n<tr>\n<td><tt>time_hi_and_version<\/tt><\/td>\n<td>16-bit integer<\/td>\n<td><code>Data3<\/code><\/td>\n<\/tr>\n<tr>\n<td><tt>clock_seq_hi_and_reserved<\/tt><\/td>\n<td>8-bit integer<\/td>\n<td><code>Data4[0]<\/code><\/td>\n<\/tr>\n<tr>\n<td><tt>cloc_seq_low<\/tt><\/td>\n<td>8-bit integer<\/td>\n<td><code>Data4[1]<\/code><\/td>\n<\/tr>\n<tr>\n<td><tt>node<\/tt><\/td>\n<td>6-byte MAC address<\/td>\n<td><code>Data4[2..7]<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>If you print out each piece of the <code>GUID<\/code> structure, with hyphens between each part, then you get<\/p>\n<p><code><span style=\"border: solid 1px gray;\">33221100<\/span>-<!--\n--><span style=\"border: solid 1px gray;\">5544<\/span>-<!--\n--><span style=\"border: solid 1px gray;\">7766<\/span>-<!--\n--><span style=\"border: solid 1px gray;\">88<\/span>-<!--\n--><span style=\"border: solid 1px gray;\">99<\/span>-<!--\n--><span style=\"border: solid 1px gray;\">AA<\/span>-<!--\n--><span style=\"border: solid 1px gray;\">BB<\/span>-<!--\n--><span style=\"border: solid 1px gray;\">CC<\/span>-<!--\n--><span style=\"border: solid 1px gray;\">DD<\/span>-<!--\n--><span style=\"border: solid 1px gray;\">EE<\/span>-<!--\n--><span style=\"border: solid 1px gray;\">FF<\/span>\n<\/code><\/p>\n<p>Notice that everything is still little-endian. We didn&#8217;t have to do any byte flipping when printing:<\/p>\n<pre>printf(\"%04x-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\",\r\n    Data1, Data2, Data3,\r\n    Data4[0], Data4[1], Data4[2], Data4[3],\r\n    Data4[4], Data4[5], Data4[6], Data4[7]);\r\n<\/pre>\n<p>My guess is that the folks who designed the string format thought there were too many dashes, so they removed the byte dashes, except for the one that separates the clock bytes from the MAC address.<\/p>\n<pre>printf(\"%04x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\",\r\n    Data1, Data2, Data3,\r\n    Data4[0], Data4[1], Data4[2], Data4[3],\r\n    Data4[4], Data4[5], Data4[6], Data4[7]);\r\n<\/pre>\n<p><code><span style=\"border: solid 1px gray;\">33221100<\/span>-<!--\n--><span style=\"border: solid 1px gray;\">5544<\/span>-<!--\n--><span style=\"border: solid 1px gray;\">7766<\/span>-<!--\n--><span style=\"border: solid 1px gray;\">88<\/span><!--\n--><span style=\"border: solid 1px gray;\">99<\/span>-<!--\n--><span style=\"border: solid 1px gray;\">AA<\/span><!--\n--><span style=\"border: solid 1px gray;\">BB<\/span><!--\n--><span style=\"border: solid 1px gray;\">CC<\/span><!--\n--><span style=\"border: solid 1px gray;\">DD<\/span><!--\n--><span style=\"border: solid 1px gray;\">EE<\/span><!--\n--><span style=\"border: solid 1px gray;\">FF<\/span>\n<\/code><\/p>\n<p>The result is that the last two pieces of the stringified GUID look big-endian, but they&#8217;re not. They&#8217;re just little-endian with some dashes missing.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Oh, it does pick a side. It&#8217;s just that some dashes are missing.<\/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":[26],"class_list":["post-107221","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>Oh, it does pick a side. It&#8217;s just that some dashes are missing.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/107221","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=107221"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/107221\/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=107221"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=107221"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=107221"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}