{"id":111753,"date":"2025-11-03T07:00:00","date_gmt":"2025-11-03T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=111753"},"modified":"2025-11-03T10:14:53","modified_gmt":"2025-11-03T18:14:53","slug":"20251103-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20251103-00\/?p=111753","title":{"rendered":"Why does <CODE>SHFormat&shy;Date&shy;Time<\/CODE> take an unaligned <CODE>FILETIME<\/CODE>?"},"content":{"rendered":"<p>I noted some time ago <a title=\"Why do some Windows functions fail if I pass an unaligned Unicode string?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20250605-00\/?p=111250\"> Windows requires that pointers be aligned unless explicitly permitted to be unaligned<\/a>. I gave as an example of a function that explicitly permits unaligned pointers the <code>SHFormat\u00adDate\u00adTime<\/code> function:<\/p>\n<pre>LWSTDAPI_(int)\r\n    SHFormatDateTimeA(\r\n        _In_ const FILETIME <span style=\"border: solid 1px currentcolor;\">UNALIGNED<\/span> * pft,\r\n        _Inout_opt_ DWORD * pdwFlags,\r\n        _Out_writes_(cchBuf) LPSTR pszBuf,\r\n        UINT cchBuf); \r\n<\/pre>\n<p>Why does this function go out of its way to allow an unaligned <code>FILETIME<\/code>?<\/p>\n<p>The <code>SHFormat\u00adDate\u00adTime<\/code> was originally written for Explorer to use when formatting dates and times in details view and in property sheets. And a common source of these <code>FILETIME<\/code> structures are embedded inside Shell item ID lists, commonly known as &#8220;pidls&#8221; (rhymes with &#8220;riddles&#8221;) because the Hungarian notation for them is <code>pidl<\/code>, a &#8220;pointer to an ID list&#8221;.<\/p>\n<p>Shell item ID lists require only byte alignment, so any structures you embed in them will be unaligned. The <code>SHFormat\u00adDate\u00adTime<\/code> bent over backward to accommodate its primary audience and allowed unaligned <code>FILETIME<\/code> structures to be passed in. (It presumably just copies it to an aligned local variable.)<\/p>\n<p>I suspect that the <code>SHFormat\u00adDate\u00adTime<\/code> function was originally written for the Windows 95 series, which ran on x86-class processors, and x86-class processors are forgiving of misalignment. <a title=\"How did the Windows 95 user interface code get brought to the Windows NT code base?\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20251028-00\/?p=111733\"> When the Windows NT team ported the code to alignment-sensitive RISC processors<\/a>, they got tired of fixing all the individual call sites to copy the misaligned <code>FILETIME<\/code> to an aligned local, and they instead just taught the <code>SHFormat\u00adDate\u00adTime<\/code> function to be forgiving of misalignment and transfer the work of copying the misaligned <code>FILETIME<\/code> to a local into the <code>SHFormat\u00adDate\u00adTime<\/code> function.<\/p>\n<p>So really, the fact that <code>SHFormat\u00adDate\u00adTime<\/code> accepts a misaligned pointer is just a historical expediency and not something that was part of its original design. Nowadays, we&#8217;d just tell everybody to align the <code>FILETIME<\/code> on the caller side instead of doing it on the receiving end.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Designed for its original use case.<\/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-111753","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>Designed for its original use case.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111753","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=111753"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/111753\/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=111753"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=111753"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=111753"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}