{"id":98575,"date":"2018-04-23T07:00:00","date_gmt":"2018-04-23T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=98575"},"modified":"2019-03-13T00:46:17","modified_gmt":"2019-03-13T07:46:17","slug":"20180423-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20180423-00\/?p=98575","title":{"rendered":"The early history of redundant function pointer casts: MakeProcInstance"},"content":{"rendered":"<p>If you <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/05\/06\/10161590.aspx#10161846\">look through old code<\/a>, you see a lot of redundant function pointer casts. (If you&#8217;re writing new code, you should get rid of as many function pointer casts as possible, because <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/05\/06\/10161590.aspx#10161846\">a function pointer cast is a bug waiting to happen<\/a>.) Why does old code have so many redundant function pointer casts? <\/p>\n<p>Because back in the old days, they weren&#8217;t redundant. <\/p>\n<p>In the days of 16-bit Windows, function prologues were required to take very specific forms in order to make <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2012\/06\/29\/10325295.aspx\">stack walking<\/a> work, and stack walking was necessary in order to simulate an MMU on a CPU that didn&#8217;t have one. <\/p>\n<p>Another rule for prologues has to do with state management. The full prologue for a far function looks like this: <\/p>\n<pre>\n    mov     ax, ds\n    nop\n    inc     bp\n    push    bp\n    mov     bp, sp\n    push    ds\n    mov     ds, ax\n<\/pre>\n<p>Before we can dig into those instructions, we need to know a bit about how code segments worked in real-mode 16-bit Windows. In real-mode 16-bit Windows, there was a single address space for all applications because the CPU had no concept of per-process address spaces. The kernel simulated separate address spaces by managing <i>instances<\/i>. The instance (represented by an <i>instance handle<\/i>) specified the location of the data segment the code should operate on. If you have two copies of a program running, the code is shared, but each program has its own data. The instance handle tells you where that data is. <\/p>\n<p>And the instance handle is kept in the <code>ds<\/code> register. <\/p>\n<p>Therefore, it is essential that every function have its <code>ds<\/code> register set to the instance handle that describes where the code should find its data. You can think of it as a &#8220;global <code>this<\/code> pointer for the process.&#8221; <\/p>\n<p>Okay, so let&#8217;s look at the function prologue again. First, it copies <code>ds<\/code> to <code>ax<\/code> via a two-byte <code>mov ax, ds<\/code> instruction. Then there is a <code>nop<\/code>. This pads the prologue size to three bytes. <\/p>\n<p>The next four instructions build the stack frame: The <code>inc bp<\/code> <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/03\/16\/10141735.aspx\">marks the stack frame as a far frame<\/a>. The <code>push bp<\/code> and <code>mov bp, sp<\/code> build the <code>bp<\/code> chain. And the <code>push ds<\/code> saves the original <code>ds<\/code> register, <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2012\/06\/29\/10325295.aspx\">which also provides breathing room for return address patching<\/a>. <\/p>\n<p>And then we move <code>ax<\/code> back into <code>ds<\/code>. The instance handle just took a little tour of the <code>ax<\/code> register and then returned back home. What was the point of that? <\/p>\n<p>Recall that in 16-bit Windows, <a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2012\/06\/22\/10322767.aspx\">every far function called from another segment was listed in the module&#8217;s Entry Table<\/a>. <\/p>\n<p>When a far function is placed in the exported function table, the loader patches the first three bytes of the function to three <code>nop<\/code> instructions. Non-exported functions remain unchanged. This means that non-exported functions do the redundant <code>ds<\/code> rigamarole. It&#8217;s a little extra work, but it&#8217;s ultimately harmless. <\/p>\n<p>The effect of patching out the initial <code>mov ax, ds<\/code> is that the function ends up doing this: <\/p>\n<ul>\n<li>Build a far stack frame,     which includes saving the original <code>ds<\/code>. \n<li>Set <code>ds<\/code> to whatever was passed in the <code>ax<\/code> register. <\/ul>\n<p>The second step means that the code, when it executes, operates on the data associated with the handle passed in the <code>ax<\/code> register. <\/p>\n<p>Okay, great, but this means that you can&#8217;t call an exported function directly, because it will set the <code>ds<\/code> register to whatever value is passed in the <code>ax<\/code> register. Since the <code>ax<\/code> register is not part of the calling convention, its value is garbage. <\/p>\n<p>But that&#8217;s okay. We made things worse so we can make them better. <\/p>\n<p><a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20080207-00\/?p=23533\">The <code>Make&shy;Proc&shy;Instance<\/code> function<\/a> creates a stub function that loads the <code>ax<\/code> register with the instance handle you provide, and then jumps to the function you provide. Really. That&#8217;s all it did. (When you&#8217;re done, you call <code>Free&shy;Proc&shy;Instance<\/code> to free the memory back to the system.) <\/p>\n<p>This stub function was known as a <i>procedure instance thunk<\/i>, or a <i>proc instance<\/i> for short. Hence the name <code>Make&shy;Proc&shy;Instance<\/code>. <\/p>\n<p>Okay, finally the punch line. The <code>Make&shy;Proc&shy;Instance<\/code> function didn&#8217;t care what kind of function pointer you passed it. Whatever you passed in, it returned the same kind of pointer back out, because all the stub did was twiddle the <code>ax<\/code> register and then jump to the real function. The parameters on the stack didn&#8217;t change, the cleanup convention didn&#8217;t change, nothing else changed. <\/p>\n<p>The <code>Make&shy;Proc&shy;Instance<\/code> function was declared as returning a <code>FARPROC<\/code>, which is a typedef for a far function that takes no parameters and returns nothing. The parameters and return value are irrelevant; it just had to be <i>something<\/i>. <\/p>\n<p>But what this means is that when you take your function, like a window enumeration callback, and create a procedure instance for it, the thing you get back has been type-erased to a generic function pointer. To make it useful again, you need to cast it back to what it was originally. <\/p>\n<p>For example, if what you passed was a <code>WNDENUMPROC<\/code>, then you need to cast the procedure instance back to a <code>WNDENUMPROC<\/code>. If you passed a <code>TIMERPROC<\/code>, then you need to cast the procedure instance back to a <code>TIMERPROC<\/code>. You could anachronistically express this as <\/p>\n<pre>\ntemplate&lt;typename R, typename ...Args&gt;\nauto MakeProcInstanceT(R (FAR *func)(Args...), HINSTANCE inst)\n{\n  return (decltype(func))MakeProcInstance((FARPROC)func, inst);\n}\n<\/pre>\n<p>Of course, you didn&#8217;t have this fancy template deduction in 1983-era C, so you had to cast the return value manually. <\/p>\n<p>And that brings us to today. Even though <code>Make&shy;Proc&shy;Instance<\/code> has been obsolete for decades, some people imprinted on the &#8220;gotta cast your function pointers to get them to compile&#8221; pattern, either because they wrote code when the cast was required and fell into the habit, or or (more likely) they learned from code that was written by someone who inherited this habit from somebody else. And yes, this inherited folk wisdom <a HREF=\"https:\/\/msdn.microsoft.com\/ms644996\">can even be found in MSDN<\/a>. <\/p>\n<p>The redundant function pointer cast is now a type of folklore, passed down from developer to developer, even though it&#8217;s no longer needed and in fact <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20110506-00\/?p=10723\">will mask problems caused by mismatched prototypes<\/a>. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>The generic function pointer.<\/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-98575","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>The generic function pointer.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/98575","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=98575"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/98575\/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=98575"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=98575"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=98575"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}