{"id":112539,"date":"2026-07-16T07:00:00","date_gmt":"2026-07-16T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=112539"},"modified":"2026-07-16T07:11:29","modified_gmt":"2026-07-16T14:11:29","slug":"20260716-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20260716-00\/?p=112539","title":{"rendered":"Speculating on how the buggy control panel extension truncated a value that it had right in front of it"},"content":{"rendered":"<p>Last time, <a title=\"The case of the invalid function pointer when shutting down the display control panel\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20260715-00\/?p=112535\"> we found that a crash in a control panel extension was caused by pointer truncation<\/a>. The code had a perfectly good 64-bit pointer in its hand, but somehow lost its mind and opted to throw away the top 32 bits.<\/p>\n<p>How could something like this happen?<\/p>\n<p>My guess is that this code started out as perfectly good 32-bit code:<\/p>\n<pre>HWND hwndButton = GetDlgItem(hdlg, ID_BUTTON);\r\nSetWindowLong(hwndButton, GWL_WNDPROC, (LONG)g_originalWndProc);\r\n<\/pre>\n<p>And then they recompiled it as 64-bit code and got an error.<\/p>\n<pre>error C2065: 'GWL_WNDPROC': undeclared identifier\r\n<\/pre>\n<p>They then went back to the documentation and saw that for 64-bit Windows, <a title=\"The evolution of system-windows window and class extra bytes\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20260629-00\/?p=112484\"> <code>GWL_<wbr \/>WNDPROC<\/code> was renamed to <code>GWLP_<wbr \/>WNDPROC<\/code><\/a>.<\/p>\n<p>So they fixed it by changing <code>GWL_<wbr \/>WNDPROC<\/code> to <code>GWLP_<wbr \/>WNDPROC<\/code>.<\/p>\n<pre>HWND hwndButton = GetDlgItem(hdlg, ID_BUTTON);\r\nSetWindowLong(hwndButton, <span style=\"border: solid 1px currentcolor;\">GWL_WNDPROC<\/span>, (LONG)g_originalWndProc);\r\n<\/pre>\n<p>However, the point of renaming the value was not to annoy you. The point of renaming the value was to call your attention to places where pointer truncation is likely to occur. In this case, it&#8217;s the final parameter, the original 64-bit window procedure. The build break is telling you that you are probably passing a 32-bit value as something that should be 64-bit. In this case, because it was being cast to <code>(LONG)<\/code>. You are expected to upgrade the <code>GWL_<wbr \/>WNDPROC<\/code> to <code>GWLP_<wbr \/>WNDPROC<\/code> and at the same time upgrade the cast from <code>(LONG)<\/code> to <code>(LONG_PTR)<\/code>.<\/p>\n<pre>HWND hwndButton = GetDlgItem(hdlg, ID_BUTTON);\r\nSetWindowLong(hwndButton, <span style=\"border: solid 1px currentcolor;\">GWL_WNDPROC<\/span>, (<span style=\"border: solid 1px currentcolor;\">LONG_PTR<\/span>)g_originalWndProc);\r\n<\/pre>\n<p>Now, this was likely an oversight rather than a systemic failure, because they did manage to subclass the window properly:<\/p>\n<pre>WNDPROC g_originalWndProc;\r\n\r\nHWND hwndButton = GetDlgItem(hdlg, ID_BUTTON);\r\ng_originalWndProc = (WNDPROC)SetWindowLong(hwndButton, <span style=\"border: solid 1px currentcolor;\">GWLP_WNDPROC<\/span>,\r\n    (<span style=\"border: solid 1px currentcolor;\">LONG_PTR<\/span>)subclassWndProc);\r\n<\/pre>\n<p>They merely missed a spot. Perhaps the developer got distracted after fixing the symbol name and forgot to come back and fix the pointer.<\/p>\n<p>Next time, we&#8217;ll look at why this bug has remained unfixed for so long.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Inferring the code&#8217;s history.<\/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-112539","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Inferring the code&#8217;s history.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/112539","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=112539"}],"version-history":[{"count":1,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/112539\/revisions"}],"predecessor-version":[{"id":112540,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/112539\/revisions\/112540"}],"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=112539"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=112539"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=112539"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}