{"id":3245,"date":"2020-11-24T16:18:10","date_gmt":"2020-11-24T08:18:10","guid":{"rendered":"https:\/\/www.aoisnow.net\/blog\/?p=3245"},"modified":"2020-11-24T16:18:10","modified_gmt":"2020-11-24T08:18:10","slug":"tont-32723-%e5%bd%93%e5%ba%94%e7%94%a8%e7%a8%8b%e5%ba%8f%e8%ae%a4%e4%b8%ba%e7%b3%bb%e7%bb%9f%e6%b0%b8%e8%bf%9c%e9%83%bd%e4%b8%8d%e4%bc%9a%e5%8f%98%e7%9a%84%e6%97%b6%e5%80%99%ef%bc%9a%e7%ac%ac3","status":"publish","type":"post","link":"https:\/\/www.aoisnow.net\/blog\/archives\/3245","title":{"rendered":"TONT 32723 \u5f53\u5e94\u7528\u7a0b\u5e8f\u8ba4\u4e3a\u7cfb\u7edf\u6c38\u8fdc\u90fd\u4e0d\u4f1a\u53d8\u7684\u65f6\u5019\uff1a\u7b2c3\u7ae0"},"content":{"rendered":"<p>\u539f\u6587\u94fe\u63a5\uff1a<a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20060109-27\/?p=32723\" target=\"_blank\" rel=\"noopener\">https:\/\/devblogs.microsoft.com\/oldnewthing\/20060109-27\/?p=32723<\/a><\/p>\n<p>\uff08\u8bd1\u6ce8\uff1a\u7b2c2\u7ae0\u5728\u539fBlog\u4e2d\u4e0d\u5b58\u5728\uff0c\u539f\u56e0\u672a\u77e5\uff09<\/p>\n<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\u2019t 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\u2019s \u201cFile\u201d menu and extracted the strings from that menu looking for an item that contained the word \u201cPrinter\u201d. It then posted a WM_COMMAND message to the Control Panel window with the menu identifier it found, thereby simulating the user clicking on the \u201cPrinters\u201d menu option.<\/p>\n<p>\u6211\u7684\u4e00\u4f4d\u540c\u4e8b\u66fe\u89e3\u51b3\u8fc7\u7684\u4e00\u6869\u8be1\u5f02\u7684\u5e94\u7528\u7a0b\u5e8f\u517c\u5bb9\u6027\u95ee\u9898\uff0c\u662f\u627e\u51fa\u4e3a\u4ec0\u4e48\u67d0\u4e2a\u7a0b\u5e8f\u65e0\u6cd5\u6253\u5f00\u6253\u5370\u673a\u63a7\u5236\u9762\u677f\u7684\u539f\u56e0\u3002\u5728\u6df1\u5165\u8c03\u67e5\u540e\uff0c\u539f\u56e0\u53d8\u5f97\u660e\u6717\u8d77\u6765\u3002\u8fd9\u4e2a\u7a0b\u5e8f\u4f1a\u6253\u5f00\u63a7\u5236\u9762\u677f\uff0c\u7528 FindWindow \u627e\u5230\u63a7\u5236\u9762\u677f\u7684\u7a97\u53e3\uff0c\u7136\u540e\u53bb\u8bbf\u95ee\u8fd9\u4e2a\u7a97\u53e3\u7684 File\uff08\u6587\u4ef6\uff09\u83dc\u5355\uff0c\u628a\u8fd9\u4e2a\u83dc\u5355\u91cc\u7684\u83dc\u5355\u9879\u5b57\u7b26\u4e32\u89e3\u6790\u51fa\u6765\uff0c\u7136\u540e\u5728\u5176\u4e2d\u627e\u5230\u5e26\u6709 Printer\uff08\u6253\u5370\u673a\uff09\u8fd9\u4e2a\u8bcd\u7684\u9879\u76ee\uff0c\u7136\u540e\u5411\u63a7\u5236\u9762\u677f\u7a97\u53e3\u53d1\u9001 WM_COMMAND \u7a97\u4f53\u6d88\u606f\uff0c\u4ee5\u521a\u624d\u627e\u5230\u7684\u83dc\u5355\u9879\u4e3a\u53c2\u6570\u3002\u7ecf\u8fc7\u4ee5\u4e0a\u4e00\u901a\u64cd\u4f5c\uff0c\u4fbf\u5b8c\u6210\u4e86\u6a21\u62df\u7528\u6237\u5355\u51fb\u300e\u6253\u5370\u673a\u300f\u83dc\u5355\u9879\u8fd9\u4e2a\u64cd\u4f5c\u3002\uff08\u8bd1\u6ce8\uff1a\u53ef\u81ea\u884c\u53c2\u8003 Windows 3.x \u7684\u63a7\u5236\u9762\u677f\u957f\u4ec0\u4e48\u6837\u5b50\uff0c\u4ee5\u4fbf\u66f4\u597d\u7406\u89e3\u4e0a\u6587\u63cf\u8ff0\u7684\u64cd\u4f5c\uff09<\/p>\n<p>With Windows 95\u2019s Control Panel, this method fell apart pretty badly. There is no \u201cPrinters\u201d option on the Control Panel\u2019s File menu. It never occurred to the authors of the program that this was a possibility. (Mind you, it was a possibility even in Windows 3.1: If you were running a non-English version of Windows, the name of the Printers option will be something like \u201cSkrivare\u201d or \u201cDrucker\u201d. Not that it mattered, because the \u201cFile\u201d menu will be called something like \u201cArkiv\u201d or \u201cDatei\u201d! The developers of this program simply assumed that everyone in the world speaks English.)<\/p>\n<p>\u5230\u4e86 Windows 95 \u7684\u63a7\u5236\u9762\u677f\u91cc\uff0c\u8fd9\u79cd\u64cd\u4f5c\u53ef\u8c13\u4e00\u8d25\u6d82\u5730\u3002\u63a7\u5236\u9762\u677f\u7684\u300e\u6587\u4ef6\u300f\u83dc\u5355\u91cc\u5e76\u6ca1\u6709\u300e\u6253\u5370\u673a\u300f\u8fd9\u4e00\u9879\uff0c\u5bf9\u8f6f\u4ef6\u7684\u7f16\u5199\u8005\u6765\u8bf4\uff0c\u8fd9\u662f\u6839\u672c\u4e0d\u53ef\u80fd\u53d1\u751f\u7684\u4e8b\u60c5\u3002\uff08\u9700\u8981\u63d0\u9192\u7684\u662f\uff0c\u5373\u4fbf\u5728 Windows 3.1 \u4e2d\uff0c\u8fd9\u4e5f\u662f\u4e00\u4ef6\u6709\u53ef\u80fd\u53d1\u751f\u7684\u4e8b\uff1a\u5982\u679c\u4f60\u8fd0\u884c\u7684 Windows \u4e0d\u662f\u82f1\u8bed\u7248\u672c\uff0c\u90a3\u4e48\u300e\u6253\u5370\u673a\u300f\u4e00\u9879\u7684\u540d\u5b57\u53ef\u80fd\u53eb\u505a Skrivare\uff08\u8bd1\u6ce8\uff1a\u745e\u5178\u8bed\u7684\u300e\u6253\u5370\u673a\u300f\uff09\u6216\u8005\u00a0Drucker\uff08\u8bd1\u6ce8\uff1a\u5fb7\u8bed\u7684\u300e\u6253\u5370\u673a\u300f\uff09\uff0c\u4f46\u8fd9\u5176\u5b9e\u4e5f\u4e0d\u662f\u6700\u5927\u7684\u95ee\u9898\uff0c\u56e0\u4e3a\u4e0e\u6b64\u540c\u65f6\u300e\u6587\u4ef6\u300f\u83dc\u5355\u7684\u540d\u5b57\u53ef\u662f\u4f1a\u53eb\u505a Arkiv \u6216\u8005 Datei\uff08\u8bd1\u6ce8\uff1a\u5206\u522b\u4e3a\u745e\u5178\u8bed\u548c\u5fb7\u8bed\u7684\u300e\u6587\u4ef6\u300f\uff09\u5462\uff01\u7f16\u5199\u8fd9\u4e2a\u8f6f\u4ef6\u7684\u5f00\u53d1\u8005\u4f30\u8ba1\u7b80\u5355\u7684\u8ba4\u4e3a\u8fd9\u4e2a\u4e16\u754c\u4e0a\u7684\u6240\u6709\u4eba\u90fd\u662f\u8bb2\u82f1\u8bed\u7684\u5427\u3002\uff09\uff08\u8bd1\u6ce8\uff1a\u4e5f\u53ef\u80fd\u4eba\u5bb6\u6839\u672c\u5c31\u6ca1\u60f3\u5728\u82f1\u8bed\u533a\u4e4b\u5916\u53d1\u884c\uff1f\uff09<\/p>\n<p>The code never checked for errors; it plowed ahead on the assumption that everything was going according to plan. The code eventually completed its rounds and sent a garbage WM_COMMAND message to the Control Panel window, which was of course ignored since it didn\u2019t match any of the valid commands on that window\u2019s menu.<\/p>\n<p>\u7a0b\u5e8f\u7684\u4ee3\u7801\u4ece\u6765\u90fd\u6ca1\u6709\u5bf9\u9519\u8bef\u8fdb\u884c\u8fc7\u68c0\u67e5\uff0c\u53ea\u662f\u4e00\u5473\u5730\u52c7\u5f80\u76f4\u524d\uff0c\u5047\u5b9a\u4e00\u5207\u90fd\u4f1a\u6309\u8ba1\u5212\u8fdb\u884c\u800c\u5df2\u3002\u4ee3\u7801\u505a\u5b8c\u4e86\u5b83\u7684\u5de5\u4f5c\uff0c\u5411\u63a7\u5236\u9762\u677f\u7a97\u53e3\u53d1\u9001\u4e86\u4e00\u4e2a\u65e0\u6548\u7684 WM_COMMAND \u7a97\u4f53\u6d88\u606f\uff0c\u800c\u8fd9\u4e2a\u6d88\u606f\u7531\u4e8e\u6ca1\u6709\u5305\u542b\u9488\u5bf9\u7a97\u4f53\u83dc\u5355\u7684\u4efb\u4f55\u6709\u6548\u6307\u4ee4\uff0c\u7406\u6240\u5f53\u7136\u5730\u88ab\u7cfb\u7edf\u5ffd\u7565\u4e86\u3002<\/p>\n<p>The punch line is that the mechanism for opening the Printers Control Panel was rather clearly spelled out on the very first page of the \u201cControl Panel\u201d chapter of the Windows 3.1 SDK:<\/p>\n<p>\u7b11\u70b9\u5728\u4e8e\uff0c\u6253\u5f00\u6253\u5370\u673a\u63a7\u5236\u9762\u677f\u7684\u65b9\u5f0f\uff0c\u5b9e\u9645\u4e0a\u5728 Windows 3.1 SDK\u300e\u63a7\u5236\u9762\u677f\u300f\u7ae0\u8282\u7684\u7b2c\u4e00\u9875\u5c31\u6e05\u6e05\u695a\u695a\u5730\u5199\u7740\uff1a<\/p>\n<blockquote><p>The following example shows how an application can start Control Panel and the Printers application from the command line by using the WinExec function:<\/p>\n<p>\u4ee5\u4e0b\u6848\u4f8b\u8bf4\u660e\u5982\u4f55\u4f7f\u5e94\u7528\u7a0b\u5e8f\u901a\u8fc7\u8c03\u7528 WinExec \u51fd\u6570\u6765\u6253\u5f00\u63a7\u5236\u9762\u677f\u4ee5\u53ca\u6253\u5370\u673a\u8bbe\u7f6e\u754c\u9762\uff1a<\/p>\n<p>WinExec(&#8220;control.exe printers&#8221;, SW_SHOWNORMAL);<\/p><\/blockquote>\n<p>In other words, they didn\u2019t even read past the first page.<\/p>\n<p>\u6362\u53e5\u8bdd\u8bf4\uff0c\u8fd9\u4e2a\u8f6f\u4ef6\u7684\u5f00\u53d1\u8005\u8fde\u7b2c\u4e00\u9875\u90fd\u6ca1\u8bfb\u8fc7\u53bb\u3002<\/p>\n<p>The solution: Create a \u201cdecoy\u201d Control Panel window with the same class name as Windows 3.1, so that this program would find it. The purpose of these \u201cdecoys\u201d is to draw the attention of the offending program, taking the brunt of the mistreatment and doing what they can to mimic the original behavior enough to keep that program happy. In this case, it waited patiently for the garbage WM_COMMAND message to arrive and dutifully launched the Printers Control Panel.<\/p>\n<p>\u81f3\u4e8e\u89e3\u51b3\u65b9\u6848\uff0c\u5219\u662f\u521b\u5efa\u4e86\u4e00\u4e2a\u7528\u4f5c\u300e\u8bf1\u9975\u300f\u7684\u63a7\u5236\u9762\u677f\u7a97\u53e3\uff0c\u8fd9\u4e2a\u7a97\u53e3\u7684\u7c7b\u540d\u4e0e Windows 3.1 \u7684\u63a7\u5236\u9762\u677f\u7a97\u53e3\u4e00\u81f4\uff0c\u4ee5\u4fbf\u8ba9\u8fd9\u4e2a\u7a0b\u5e8f\u80fd\u627e\u5230\u5b83\u3002\u8fd9\u4e2a\u8bf1\u9975\u7684\u4f5c\u7528\u662f\u5438\u5f15\u8fd9\u4e2a\u65e0\u793c\u7684\u5e94\u7528\u7a0b\u5e8f\u7684\u6ce8\u610f\u529b\uff0c\u9996\u5f53\u5176\u51b2\u5730\u6a21\u4eff\u65e7\u5f0f\u63a7\u5236\u9762\u677f\u7684\u884c\u4e3a\uff0c\u6765\u8ba9\u8fd9\u7c7b\u5e94\u7528\u7a0b\u5e8f\u5fc3\u6ee1\u610f\u8db3\u3002\u5728\u8fd9\u4e2a\u6848\u4f8b\u4e2d\uff0c\u5b83\u7684\u4f5c\u7528\u662f\u8010\u5fc3\u7b49\u5f85\u90a3\u4e2a\u65e0\u6548\u7684 WM_COMMAND \u7a97\u4f53\u6d88\u606f\u7684\u6765\u4e34\uff0c\u7136\u540e\u5c3d\u804c\u5c3d\u8d23\u5730\u6253\u5f00\u300e\u6253\u5370\u673a\u300f\u63a7\u5236\u9762\u677f\u3002<\/p>\n<p>Nowadays, this sort of problem would probably have been solved with the use of a shim. But this was back in Windows 95, where application compatibility technology was still comparatively immature. All that was available at the time were application compatibility flags and hot-patching of binaries, wherein the values are modified as they are loaded into memory. Using hot-patching technology was reserved for only the most extreme compatibility cases, because getting permission from the vendor to patch their program was a comparatively lengthy legal process. Patching was considered a \u201clast resort\u201d compatibility mechanism not only for the legal machinery necessary to permit it, but also because patching a program fixes only the versions of the program the patch was developed to address. If the vendor shipped ten versions of a program, ten different patches would have to be developed. And if the vendor shipped another version after Windows 95 was delivered to duplication, that version would be broken when Windows 95 hit the shelves.<\/p>\n<p>\u73b0\u5982\u4eca\uff0c\u8fd9\u7c7b\u95ee\u9898\u4e00\u822c\u4f1a\u901a\u8fc7\u4f7f\u7528\u300e\u6954\u5b50\u300f\u4e00\u7c7b\u7684\u65b9\u5f0f\u89e3\u51b3\uff0c\u4f46\u8fd9\u4e2a\u6848\u4f8b\u662f\u5728 Windows 95 \u7684\u5e74\u4ee3\u53d1\u751f\u7684\uff0c\u90a3\u65f6\u5e94\u7528\u7a0b\u5e8f\u517c\u5bb9\u6027\u6280\u672f\u76f8\u5bf9\u6765\u8bf4\u8fd8\u4e0d\u591f\u6210\u719f\uff0c\u800c\u90a3\u65f6\u80fd\u7528\u7684\u529e\u6cd5\u5c31\u662f\u5e94\u7528\u7a0b\u5e8f\u517c\u5bb9\u6027\u6807\u7b7e\uff0c\u4ee5\u53ca\u5bf9\u4e8c\u8fdb\u5236\u6587\u4ef6\u5e94\u7528\u70ed\u4fee\u590d\u8865\u4e01\uff0c\u5728\u5176\u52a0\u8f7d\u5165\u5185\u5b58\u65f6\u5bf9\u4e8c\u8fdb\u5236\u6570\u636e\u8fdb\u884c\u4fee\u6539\u3002\u70ed\u4fee\u590d\u8865\u4e01\u8fd9\u4e00\u62db\u53ea\u4f1a\u88ab\u7559\u5f85\u9047\u5230\u6700\u68d8\u624b\u7684\u517c\u5bb9\u6027\u95ee\u9898\u65f6\u624d\u4f1a\u4f7f\u7528\uff0c\u56e0\u4e3a\u4ece\u8f6f\u4ef6\u53d1\u884c\u5546\u54ea\u91cc\u83b7\u5f97\u5bf9\u5176\u7a0b\u5e8f\u8fdb\u884c\u4fee\u6539\u7684\u8bb8\u53ef\uff0c\u662f\u4e00\u4e2a\u5197\u957f\u7684\u6cd5\u5f8b\u8fc7\u7a0b\u3002\u6253\u8865\u4e01\u88ab\u89c6\u4e3a\u662f\u5b9e\u73b0\u517c\u5bb9\u6027\u95ee\u9898\u89e3\u51b3\u7684\u300e\u6700\u7ec8\u624b\u6bb5\u300f\uff0c\u4e0d\u4ec5\u4ec5\u56e0\u4e3a\u83b7\u5f97\u8bb8\u53ef\u8981\u7ecf\u8fc7\u673a\u68b0\u7e41\u590d\u7684\u6cd5\u5f8b\u6d41\u7a0b\uff0c\u540c\u65f6\u4e5f\u662f\u56e0\u4e3a\u8fd9\u6837\u53ea\u80fd\u4fee\u590d\u517c\u5bb9\u6027\u8865\u4e01\u6240\u9488\u5bf9\u7684\u8be5\u8f6f\u4ef6\u7279\u5b9a\u7248\u672c\u7684\u95ee\u9898\u3002\u5982\u679c\u8f6f\u4ef6\u53d1\u884c\u5546\u53d1\u5e03\u4e8610\u4e2a\u7248\u672c\u7684\u5e94\u7528\u7a0b\u5e8f\uff0c\u90a3\u5c31\u8981\u5f00\u53d110\u4e2a\u4e0d\u540c\u7684\u8865\u4e01\u3002\u800c\u5982\u679c\u8f6f\u4ef6\u53d1\u884c\u5546\u5728 Windows 95 \u9001\u5382\u4e4b\u540e\u53c8\u53d1\u5e03\u4e86\u65b0\u7248\u672c\uff0c\u90a3\u4e48\u8fd9\u4e2a\u65b0\u7248\u672c\u5728 Windows 95 \u4e0a\u67b6\u9500\u552e\u4e4b\u540e\u4fbf\u4ecd\u5b58\u5728\u517c\u5bb9\u6027\u95ee\u9898\u3002<\/p>\n<p>It is important to understand the distinction between what is a documented and supported feature and what is an implementation detail. Documented and supported features are contracts between Windows and your program. Windows will uphold its end of the contract for as long as that feature exists. Implementation details, on the other hand, are ephemeral; they can change at any time, be it at the next major operating system release, at the next service pack, even with the next security hotfix. If your program relies on implementation details, you\u2019re contributing to the compatibility cruft that Windows carries around from release to release.<\/p>\n<p>\u7406\u89e3\u6587\u6863\u4e2d\u53d7\u652f\u6301\u7684\u529f\u80fd\u548c\u90e8\u7f72\u7ec6\u8282\u7684\u533a\u522b\u5f88\u91cd\u8981\u3002\u6587\u6863\u4e2d\u53d7\u652f\u6301\u7684\u529f\u80fd\u662f Windows \u548c\u4f60\u7684\u7a0b\u5e8f\u4e4b\u95f4\u7684\u5951\u7ea6\uff0cWindows \u5728\u8fd9\u4e2a\u529f\u80fd\u7684\u5b58\u7eed\u671f\u95f4\u4f1a\u4fe1\u5b88\u627f\u8bfa\u3002\u800c\u53e6\u4e00\u65b9\u9762\uff0c\u90e8\u7f72\u7ec6\u8282\u5219\u662f\u7a0d\u7eb5\u5373\u901d\u7684\uff0c\u53ef\u80fd\u968f\u65f6\u53d1\u751f\u53d8\u5316\uff0c\u53d8\u5316\u53ef\u80fd\u53d1\u751f\u5728\u4e0b\u4e00\u4e2a\u7cfb\u7edf\u5927\u7248\u672c\uff0c\u4e0b\u4e00\u4e2a Service Pack\uff0c\u751a\u81f3\u662f\u4e0b\u4e00\u4e2a\u5b89\u5168\u66f4\u65b0\u8865\u4e01\u3002\u5982\u679c\u4f60\u7684\u7a0b\u5e8f\u4f9d\u8d56\u90e8\u7f72\u7ec6\u8282\uff0c\u90a3\u4f60\u4e0d\u8fc7\u662f\u5728\u4e3a Windows \u4ee3\u4ee3\u76f8\u4f20\u7684\u3001\u6c89\u91cd\u7684\u517c\u5bb9\u6027\u5305\u88b1\u6dfb\u7816\u52a0\u74e6\u7f62\u4e86\u3002<\/p>\n<p>Over the next few days, I\u2019ll talk about other decoys that have been used in Windows.<\/p>\n<p>\u63a5\u4e0b\u6765\u7684\u51e0\u5929\u91cc\uff0c\u6211\u4f1a\u8bb2\u4e00\u8bb2 Windows \u4e2d\u5176\u5b83\u7684\u4e00\u4e9b\u517c\u5bb9\u6027\u300e\u8bf1\u9975\u300f\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u539f\u6587\u94fe\u63a5\uff1ahttps:\/\/devblogs.microsoft.com\/oldnewthing\/2006010 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-3245","post","type-post","status-publish","format-standard","hentry","category-tont_history"],"_links":{"self":[{"href":"https:\/\/www.aoisnow.net\/blog\/wp-json\/wp\/v2\/posts\/3245","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.aoisnow.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.aoisnow.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.aoisnow.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.aoisnow.net\/blog\/wp-json\/wp\/v2\/comments?post=3245"}],"version-history":[{"count":0,"href":"https:\/\/www.aoisnow.net\/blog\/wp-json\/wp\/v2\/posts\/3245\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.aoisnow.net\/blog\/wp-json\/wp\/v2\/media?parent=3245"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.aoisnow.net\/blog\/wp-json\/wp\/v2\/categories?post=3245"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.aoisnow.net\/blog\/wp-json\/wp\/v2\/tags?post=3245"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}