{"id":23533,"date":"2008-02-07T10:00:00","date_gmt":"2008-02-07T10:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2008\/02\/07\/what-did-makeprocinstance-do\/"},"modified":"2008-02-07T10:00:00","modified_gmt":"2008-02-07T10:00:00","slug":"what-did-makeprocinstance-do","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20080207-00\/?p=23533","title":{"rendered":"What did MakeProcInstance do?"},"content":{"rendered":"<p>\n<code>MakeProcInstance<\/code> doesn&#8217;t do anything.\n<\/p>\n<pre>\n#define MakeProcInstance(lpProc,hInstance) (lpProc)\n<\/pre>\n<p>\nWhat&#8217;s the point of a macro that doesn&#8217;t do anything?\n<\/p>\n<p>\nIt did something back in 16-bit Windows.\n<\/p>\n<p>\nRecall that in 16-bit Windows, the <code>HINSTANCE<\/code>\nwas the mechanism for identifying a data segment;\ni.e., a bunch of memory that represents the set of variables\nin use by a module.\nIf you had two copies of Notepad running, there was one copy of\nthe code but two sets of variables (one for each copy).\nIt is the second set of variables that establishes the second\ncopy of Notepad.\n<\/p>\n<p>\nWhen you set up a callback function, such as a window procedure,\nthe callback function needs to know which set of variables it&#8217;s\nbeing called for.\nFor example, if one copy of Notepad calls\n<code>EnumFonts<\/code> and passes a callback function,\nthe function needs to know which copy of Notepad it is running in\nso that it can access the correct set of variables.\nThat&#8217;s what the <code>MakeProcInstance<\/code> function was for.\n<\/p>\n<p>\nThe parameters to <code>MakeProcInstance<\/code> are a function pointer\nand an instance handle.\nthe <code>MakeProcInstance<\/code> function generated code on the fly\nwhich set the data segment register equal to the\ninstance handle and then jumped to the original function pointer.\nThe return value of <code>MakeProcInstance<\/code> is a pointer to that\ndynamically-generated code fragment\n(known as a <i>thunk<\/i>),\nand you used that code fragment as the function pointer whenever\nyou needed another function to call you back.\nThat way, when your function was called, its variables were properly\nset up.\nWhen you no longer needed the code fragment,\nyou freed it with the <code>FreeProcInstance<\/code> function.\n<\/p>\n<p>\nThose who have worked with ATL have seen this sort of code fragment\ngeneration already in the <code>CStdCallThunk<\/code> class.\nThe operation is entirely analogous with <code>MakeProcInstance<\/code>.\nYou initialize the <code>CStdCallThunk<\/code> with a function pointer\nand a <code>this<\/code> parameter, and it generates code on the fly\nwhich converts a static function into a C++ member function\nby setting the <code>this<\/code> pointer before calling the function\nyou used to initialize the thunk.\n<\/p>\n<p>\nThe creation of these code fragments on 16-bit Windows had to be\ndone by the kernel because the 8086 processor did not have\na memory management unit.\nThere was no indirection through a translation table;\nall addresses were physical.\nAs a result, if the memory manager had to move memory around,\nit also had to know where all the references to the moved memory\nwere kept so it can update the pointers.\nIf a data segment moved, the kernel had to go fix up all the\n<code>MakeProcInstance<\/code> thunks so that they used the new\ninstance handle instead of the old one.\n<\/p>\n<p>\nIt was\n<a HREF=\"http:\/\/mg.to\/\">\nMichael Geary<\/a>\nwho discovered that all this\n<code>MakeProcInstance<\/code> work was unnecessary.\nIf the callback function resided in a DLL,\nthen the function could hard-code its instance handle\nand just load it at the start of the function;\nthis technique ultimately became known as <i>__loadds<\/i>.\nSince DLLs were single-instance, the DLL already knew\nwhich set of variables it was supposed to use since there\nwas only one set of DLL variables to begin with!\n(Of course, the hard-coded value had to be recorded as a fix-up\nsince the instance handle is determined at run time.\nPlus the kernel needed to know which values to update if the instance\nhandle changed values.)\nOn the other hand, if the callback function resided in an executable,\nthen it could obtain its instance handle from the stack selector;\nthis technique ultimately became known as <i>__export<\/i>.\nEach program ran on a single stack (no multi-threading here),\nand the stack, data segment, and local heap all resided in the same\nselector by convention.\nAnd in a strange bit of coming full circle which I discovered as I wrote\nup this reminiscence,\nMichael Geary&#8217;s copy of\n<a HREF=\"http:\/\/www.geary.com\/fixds.html\">\nthe original readme for his FixDS program that brought this technique\nto the public<\/a> contains an introduction which links back to me&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>MakeProcInstance doesn&#8217;t do anything. #define MakeProcInstance(lpProc,hInstance) (lpProc) What&#8217;s the point of a macro that doesn&#8217;t do anything? It did something back in 16-bit Windows. Recall that in 16-bit Windows, the HINSTANCE was the mechanism for identifying a data segment; i.e., a bunch of memory that represents the set of variables in use by a module. [&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-23533","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>MakeProcInstance doesn&#8217;t do anything. #define MakeProcInstance(lpProc,hInstance) (lpProc) What&#8217;s the point of a macro that doesn&#8217;t do anything? It did something back in 16-bit Windows. Recall that in 16-bit Windows, the HINSTANCE was the mechanism for identifying a data segment; i.e., a bunch of memory that represents the set of variables in use by a module. [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/23533","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=23533"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/23533\/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=23533"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=23533"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=23533"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}