{"id":32723,"date":"2006-01-09T09:57:27","date_gmt":"2006-01-09T09:57:27","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2006\/01\/09\/when-programs-assume-that-the-system-will-never-change-episode-3\/"},"modified":"2006-01-09T09:57:27","modified_gmt":"2006-01-09T09:57:27","slug":"when-programs-assume-that-the-system-will-never-change-episode-3","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20060109-27\/?p=32723","title":{"rendered":"When programs assume that the system will never change, episode 3"},"content":{"rendered":"<p>\nOne of the stranger application compatibility puzzles\nwas solved by a colleague of mine who was trying to figure\nout why a particular program couldn&#8217;t open the Printers\nControl Panel.\nUpon closer investigation, the reason became clear.\nThe program launched the Control Panel,\nused <code>FindWindow<\/code> to locate the window,\nthen accessed that window&#8217;s &#8220;File&#8221; menu and extracted the strings from\nthat menu looking for an item that contained the word &#8220;Printer&#8221;.\nIt then posted a <code>WM_COMMAND<\/code> message to the Control Panel\nwindow with the menu identifier it found, thereby simulating the\nuser clicking on the &#8220;Printers&#8221; menu option.\n<\/p>\n<p>\nWith Windows&nbsp;95&#8217;s Control Panel, this method fell apart\npretty badly.\nThere is no &#8220;Printers&#8221; option on the Control Panel&#8217;s File menu.\nIt never occurred to the authors of the program that this was\na possibility.\n(Mind you, it was a possibility even in Windows&nbsp;3.1:\nIf you were running a non-English version of Windows, the\nname of the Printers option will be something like\n&#8220;Skrivare&#8221; or &#8220;Drucker&#8221;.\nNot that it mattered, because the &#8220;File&#8221; menu will be called\nsomething like &#8220;Arkiv&#8221; or &#8220;Datei&#8221;!\nThe developers of this program\nsimply assumed that everyone in the world speaks English.)\n<\/p>\n<p>\nThe code never checked for errors; it plowed ahead on the\nassumption that everything was going according to plan.\nThe code eventually completed its rounds and sent a\ngarbage <code>WM_COMMAND<\/code> message to the Control Panel window,\nwhich was of course ignored since it didn&#8217;t match any of the\nvalid commands on that window&#8217;s menu.\n<\/p>\n<p>\nThe punch line is that\nthe mechanism for opening the Printers Control Panel\nwas rather clearly spelled out\non the very first page of the &#8220;Control Panel&#8221; chapter of\nthe Windows&nbsp;3.1 SDK:\n<\/p>\n<blockquote CLASS=\"q\">\n<p>\nThe following example shows how an application can start Control Panel\nand the Printers application from the command line by using the WinExec\nfunction:\n<\/p>\n<pre>\n    WinExec(\"control.exe printers\", SW_SHOWNORMAL);\n<\/pre>\n<\/blockquote>\n<p>\nIn other words, they didn&#8217;t even read past the first page.\n<\/p>\n<p>\nThe solution:\nCreate a &#8220;decoy&#8221; Control Panel window with the same class name\nas Windows&nbsp;3.1, so that this program would find it.\nThe purpose of these &#8220;decoys&#8221; is to draw the attention of the\noffending program,\ntaking the brunt of the mistreatment and doing what they can to\nmimic the original behavior enough to keep that program happy.\nIn this case, it waited patiently for the garbage\n<code>WM_COMMAND<\/code> message to arrive and dutifully launched\nthe Printers Control Panel.\n<\/p>\n<p>\nNowadays, this sort of problem would probably have been solved with the\nuse of a shim.\nBut this was back in Windows&nbsp;95, where application compatibility\ntechnology was still comparatively immature.\nAll that was available at the time were application compatibility flags\nand hot-patching of binaries,\nwherein the values are modified as they are loaded into memory.\nUsing hot-patching technology was reserved for only the most extreme\ncompatibility cases, because getting permission from the vendor\nto patch their program was a comparatively lengthy legal process.\nPatching was considered a &#8220;last resort&#8221; compatibility mechanism\nnot only for the legal machinery necessary to permit it,\nbut also because patching a program fixes only the versions of\nthe program the patch was developed to address.\nIf the vendor shipped ten versions of a program,\nten different patches would have to be developed.\nAnd if the vendor shipped another version after Windows&nbsp;95\nwas delivered to duplication, that version would be broken when\nWindows&nbsp;95 hit the shelves.\n<\/p>\n<p>\nIt is important to understand the distinction between what is\na documented and supported feature and what is an implementation detail.\nDocumented and supported features are contracts between Windows and\nyour program.\nWindows will uphold its end of the contract for as long as that feature\nexists.\nImplementation details, on the other hand, are ephemeral;\nthey can change at any time,\nbe it at the next major operating system release,\nat the next service pack,\neven with the next security hotfix.\nIf your program relies on implementation details,\nyou&#8217;re contributing to the compatibility cruft\nthat Windows carries around from release to release.\n<\/p>\n<p>\nOver the next few days, I&#8217;ll talk about other decoys\nthat have been used in Windows.\n<\/p>\n<p>\n[Somebody caught my misspelling of &#8220;Drucker&#8221; while I was fixing it! &#8211; 7:45am]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the stranger application compatibility puzzles was solved by a colleague of mine who was trying to figure out why a particular program couldn&#8217;t open the Printers Control Panel. Upon closer investigation, the reason became clear. The program launched the Control Panel, used FindWindow to locate the window, then accessed that window&#8217;s &#8220;File&#8221; menu [&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-32723","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-history"],"acf":[],"blog_post_summary":"<p>One of the stranger application compatibility puzzles was solved by a colleague of mine who was trying to figure out why a particular program couldn&#8217;t open the Printers Control Panel. Upon closer investigation, the reason became clear. The program launched the Control Panel, used FindWindow to locate the window, then accessed that window&#8217;s &#8220;File&#8221; menu [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/32723","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=32723"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/32723\/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=32723"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=32723"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=32723"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}