{"id":28523,"date":"2007-01-03T10:00:15","date_gmt":"2007-01-03T10:00:15","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2007\/01\/03\/wait-but-why-can-i-getprocaddress-for-isdialogmessage\/"},"modified":"2007-01-03T10:00:15","modified_gmt":"2007-01-03T10:00:15","slug":"wait-but-why-can-i-getprocaddress-for-isdialogmessage","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20070103-15\/?p=28523","title":{"rendered":"Wait, but why can I GetProcAddress for IsDialogMessage?"},"content":{"rendered":"<p>\nOkay, so\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2007\/01\/02\/1399230.aspx\">\nI explained<\/a>\nthat a lot of so-called functions are\nreally redirecting macros, function-like macros, intrinsic\nfunctions, and inline functions,\nand consequently, <code>GetProcAddress<\/code> won&#8217;t actually\nget anything since the function doesn&#8217;t exist in the form of\nan exported function.\nBut why, then, can you <code>GetProcAddress<\/code> for\n<code>IsDialogMessage<\/code>?\n<\/p>\n<p>\nLet&#8217;s take a closer look at the exports from <code>user32.dll<\/code>.\nHere&#8217;s the relevant excerpt.\n<\/p>\n<pre>\n        417  1A0 0002C661 IsDialogMessage\n        418  1A1 0002C661 IsDialogMessageA\n        419  1A2 0001DFBC IsDialogMessageW\n<\/pre>\n<p>\nNotice that this function is exported <strong>three<\/strong> ways.\nThe last two are the ones you expect,\n<code>IsDialogMessageA<\/code> for ANSI callers and\n<code>IsDialogMessageW<\/code> for UNICODE callers.\nThat first one is the one you didn&#8217;t expect:\n<code>IsDialogMessage<\/code> with no A or W suffix.\nBut notice that its entry point address is identical to that\nof <code>IsDialogMessageA<\/code>.\nThe\n<code>IsDialogMessage<\/code> entry point is just an alias for\n<code>IsDialogMessageA<\/code>.\n<\/p>\n<p>\nThis phantom third function is hidden from C and C++ programs\nbecause any attempt to call\n<code>IsDialogMessage<\/code> gets converted to\n<code>IsDialogMessageA<\/code> or\n<code>IsDialogMessageW<\/code> due to the redirection macro:\n<\/p>\n<pre>\n#ifdef UNICODE\n#define IsDialogMessage  IsDialogMessageW\n#else\n#define IsDialogMessage  IsDialogMessageA\n#endif \/\/ !UNICODE\n<\/pre>\n<p>\n(Of course, you can play fancy games to remove the redirection\nmacros; I&#8217;m just talking about the non-fancy case.)\nIf nobody can call the function, then why does it exist?\n<\/p>\n<p>\nBecause of mistakes made long ago.\n<\/p>\n<p>\nIf you hunt through <code>user32.dll<\/code> you&#8217;ll find a few\nother functions that follow a similar pattern of having\nthree versions, an A version, a W version, and a phantom\nundecorated version (which is an alias for the A version).\nAt one point long ago, the function existed only in an undecorated\nversion.\nThis turned out to have been a mistake, since there was a\ncharacter set dependency in the parameters (perhaps obvious,\nperhaps subtle).\nThe mistake was corrected by splitting the function into\nthe A and W versions you see today, but in order to maintain\ncompatibility with older programs that were written before\nthe mistake was recognized, the original undecorated function was left\nin the export table.\n<\/p>\n<p>\n<a HREF=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2006\/04\/03\/567318.aspx\">\nWhen you don&#8217;t have a time machine<\/a>,\nyou have to live with your mistakes.\n<\/p>\n<p>\nIn a sense, these functions are vestigial organs of Win32.\n<\/p>\n<p>\n<b>Postscript<\/b>:\nUnfortunately, like your appendix, which can get infected,\nthese vestigial organs can create a different sort of infection:\nIf you are using p\/invoke to call these functions and mistakenly\noverride the default name declaration with\n<code>ExactSpelling=true<\/code>, like so:\n<\/p>\n<pre>\n[DllImport(\"user32.dll\", ExactSpelling=true)]\npublic static extern\nbool IsDialogMessage(IntPtr hWndDlg,\n                     [In] ref MSG msg);\n<\/pre>\n<p>\nthen you will in fact get the normally-inaccessible undecorated name,\nsince you specified that you wanted the exact spelling.\nThis highlights once again that you need to be alert when\ndoing interop programming:\nYou get what you ask for, which might not be what you actually wanted.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Okay, so I explained that a lot of so-called functions are really redirecting macros, function-like macros, intrinsic functions, and inline functions, and consequently, GetProcAddress won&#8217;t actually get anything since the function doesn&#8217;t exist in the form of an exported function. But why, then, can you GetProcAddress for IsDialogMessage? Let&#8217;s take a closer look at the [&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":[2],"class_list":["post-28523","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>Okay, so I explained that a lot of so-called functions are really redirecting macros, function-like macros, intrinsic functions, and inline functions, and consequently, GetProcAddress won&#8217;t actually get anything since the function doesn&#8217;t exist in the form of an exported function. But why, then, can you GetProcAddress for IsDialogMessage? Let&#8217;s take a closer look at the [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/28523","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=28523"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/28523\/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=28523"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=28523"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=28523"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}