{"id":3158,"date":"2020-09-08T16:20:31","date_gmt":"2020-09-08T08:20:31","guid":{"rendered":"https:\/\/www.aoisnow.net\/blog\/?p=3158"},"modified":"2020-09-08T16:20:31","modified_gmt":"2020-09-08T08:20:31","slug":"tont-34883-%e4%b8%ba%e4%bb%80%e4%b9%88-findfirstfile-%e4%bc%9a%e5%90%8c%e6%97%b6%e6%9f%a5%e6%89%be%e7%9f%ad%e6%96%87%e4%bb%b6%e5%90%8d%ef%bc%9f","status":"publish","type":"post","link":"https:\/\/www.aoisnow.net\/blog\/archives\/3158","title":{"rendered":"TONT 34883 \u4e3a\u4ec0\u4e48 FindFirstFile \u4f1a\u540c\u65f6\u67e5\u627e\u77ed\u6587\u4ef6\u540d\uff1f"},"content":{"rendered":"<p>\u539f\u6587\u94fe\u63a5\uff1a<a href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20050720-16\/?p=34883\" target=\"_blank\" rel=\"noopener\">https:\/\/devblogs.microsoft.com\/oldnewthing\/20050720-16\/?p=34883<\/a><\/p>\n<p>The FindFirstFile function matches both the short and long names. This can produce somewhat surprising results. For example, if you ask for \u201c*.htm\u201d, this also gives you the file \u201cx.html\u201d since its short name is \u201cX~1.HTM\u201d.<\/p>\n<p>FindFirstFile \u51fd\u6570\u4f1a\u540c\u65f6\u5339\u914d\u77ed\u6587\u4ef6\u540d\u548c\u957f\u6587\u4ef6\u540d\uff0c\u6709\u65f6\u8fd9\u79cd\u8bbe\u8ba1\u4f1a\u5e26\u6765\u4e00\u4e9b\u610f\u6599\u4e4b\u5916\u7684\u7ed3\u679c\u3002\u4f8b\u5982\uff0c\u5982\u679c\u4f60\u67e5\u627e\u300e*.htm\u300f\uff0cx.html\uff08\u8bd1\u6ce8\uff1a\u6ce8\u610f\u6b64\u5904\u7684\u6269\u5c55\u540d\u662fHTML\uff0c\u5176\u57288.3\u5f62\u5f0f\u4e0b\u4e3aHTM\uff0c\u611f\u8c22\u77f3\u6a31\u706f\u7b3c\u5728\u8bc4\u8bba\u4e2d\u6307\u51fa\uff09\u4e5f\u4f1a\u51fa\u73b0\u5728\u7ed3\u679c\u4e2d\uff0c\u56e0\u4e3a\u5b83\u7684\u77ed\u6587\u4ef6\u540d\u662fX~1.HTM\u3002<\/p>\n<p>Why does it bother matching short names? Shouldn\u2019t it match only long names? After all, only old 16-bit programs use short names.<\/p>\n<p>\u4e3a\u4ec0\u4e48\u8981\u53bb\u5339\u914d\u77ed\u6587\u4ef6\u540d\u5462\uff0c\u53ea\u5339\u914d\u957f\u6587\u4ef6\u540d\u4e0d\u5c31\u591f\u4e86\u5417\uff1f\u6bd5\u7adf\u53ea\u6709\u65e7\u5f0f\u768416\u4f4d\u5e94\u7528\u7a0b\u5e8f\u4f1a\u7528\u77ed\u6587\u4ef6\u540d\u4e86\u3002<\/p>\n<p>But that\u2019s the problem: 16-bit programs use short names.<\/p>\n<p>\u7136\u800c\u8fd9\u5374\u6b63\u89c6\u95ee\u9898\u6240\u5728\uff1a16\u4f4d\u5e94\u7528\u7a0b\u5e8f\u4f7f\u7528\u7684\u662f\u77ed\u6587\u4ef6\u540d\u3002<\/p>\n<p>Through a process known as generic thunks, a 16-bit program can load a 32-bit DLL and call into it. Windows 95 and the Windows 16-bit emulation layer in Windows NT rely heavily on generic thunks so that they don\u2019t have to write two versions of everything. Instead, the 16-bit version just thunks up to the 32-bit version.<\/p>\n<p>\u901a\u8fc7\u540d\u4e3a\u901a\u7528 Thunk \u7684\u8fc7\u7a0b\uff0c16\u4f4d\u5e94\u7528\u7a0b\u5e8f\u53ef\u4ee5\u52a0\u8f7d32\u4f4d\u7684DLL\u5e76\u8c03\u7528\u4e4b\u3002Windows 95 \u548c Windows NT \u4e2d\u7684 16 \u4f4d Windows \u6a21\u62df\u5c42\u5bf9\u4e8e\u901a\u7528 Thunk \u91cd\u5ea6\u4f9d\u8d56\uff0c\u8fd9\u6837\u624d\u4e0d\u5fc5\u4e3a\u5404\u79cd\u5404\u6837\u7684\u4e1c\u897f\u7f16\u51992\u4e2a\u7248\u672c\uff0c\u800c\u662f\u8ba9 16 \u4f4d\u7684\u8c03\u7528\u76f4\u63a5\u4e0e 32 \u4f4d\u7684\u76f8\u5173\u8c03\u7528\u8fdb\u884c\u8054\u52a8\u3002<\/p>\n<p>Note, however, that this would mean that 32-bit DLLs would see two different views of the file system, depending on whether they are hosted from a 16-bit process or a 32-bit process.<\/p>\n<p>\u7136\u800c\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u5982\u6b64\u4e00\u676532\u4f4d\u7684DLL\u4fbf\u5bf9\u6587\u4ef6\u7cfb\u7edf\u6709\u4e86\u4e24\u79cd\u89c2\u5bdf\u65b9\u5f0f\uff0c\u5177\u4f53\u53d6\u51b3\u4e8e\u5176\u5bbf\u4e3b\u8fdb\u7a0b\u662f16\u4f4d\u8fd8\u662f32\u4f4d\u3002<\/p>\n<p>\u201cThen make the FindFirstFile function check to see who its caller is and change its behavior accordingly,\u201d doesn\u2019t fly because you can\u2019t trust the return address.<\/p>\n<p>\u300e\u90a3\u5c31\u8ba9 FindFirstFile \u770b\u770b\u8c03\u7528\u65b9\u662f\u8c01\uff0c\u7136\u540e\u6267\u884c\u4e0d\u540c\u7684\u884c\u4e3a\u4e0d\u5c31\u597d\u4e86\u300f\uff0c\u8fd9\u79cd\u60f3\u6cd5\u662f\u4e0d\u73b0\u5b9e\u7684\uff0c\u56e0\u4e3a\u4f60\u65e0\u6cd5\u4fe1\u4efb\u8fd4\u56de\u5730\u5740\u3002<\/p>\n<p>Even if this problem were solved, you would still have the problem of 16\/32 interop across the process boundary.<\/p>\n<p>\u5c31\u7b97\u80fd\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u4f60\u8fd8\u662f\u8981\u9762\u5bf916\/32\u4f4d\u8fdb\u7a0b\u8fb9\u754c\u95f4\u4e92\u64cd\u4f5c\u7684\u95ee\u9898\u3002<\/p>\n<p>For example, suppose a 16-bit program calls WinExec(&#8220;notepad X~1.HTM&#8221;). The 32-bit Notepad program had better open the file X~1.HTM even though it\u2019s a short name. What\u2019s more, a common way to get properties of a file such as its last access time is to call FindFirstFile with the file name, since the WIN32_FIND_DATA structure returns that information as part of the find data. (Note: GetFileAttributesEx is a better choice, but that function is comparatively new.) If the FindFirstFile function did not work for short file names, then the above trick would fail for short names passed across the 16\/32 boundary.<\/p>\n<p>\u4f8b\u5982\uff0c\u5047\u8bbe\u67d0\u4e2a\u7a0b\u5e8f\u8c03\u7528\u4e86WinExec(&#8220;notepad X~1.HTM&#8221;)\uff0c\u90a3\u4e4832\u4f4d\u7684\u8bb0\u4e8b\u672c\u6700\u597d\u662f\u53bb\u6253\u5f00X~1.HTM\uff0c\u5373\u4fbf\u8fd9\u662f\u4e2a\u77ed\u6587\u4ef6\u540d\u3002\u6b64\u5916\uff0c\u83b7\u53d6\u6587\u4ef6\u5c5e\u6027\uff08\u4f8b\u5982\u6587\u4ef6\u7684\u6700\u540e\u8bbf\u95ee\u65f6\u95f4\uff09\u7684\u4e00\u79cd\u901a\u5e38\u65b9\u5f0f\u4fbf\u662f\u8c03\u7528 FindFirstFile \u5e76\u63d0\u4f9b\u6587\u4ef6\u540d\uff0c\u56e0\u4e3a WIN32_FIND_DATA \u7ed3\u6784\u4f1a\u5c06\u8fd9\u7c7b\u4fe1\u606f\u5305\u542b\u5728\u8fd4\u56de\u4e2d\u3002\uff08\u8bf7\u6ce8\u610f\uff1a\u4f7f\u7528 GetFileAttributesEx \u662f\u66f4\u597d\u7684\u505a\u6cd5\uff0c\u4e0d\u8fc7\u8fd9\u4e2a\u51fd\u6570\u76f8\u5bf9\u6765\u8bf4\u8fd8\u6bd4\u8f83\u65b0\u5c31\u662f\u4e86\u3002\uff09\u5982\u679c\u00a0FindFirstFile\uff08\u572832\u4f4d\u7a0b\u5e8f\u8c03\u7528\u5b83\u7684\u65f6\u5019\uff09\u4e0d\u80fd\u4f7f\u7528\u77ed\u6587\u4ef6\u540d\uff0c\u90a3\u4e48\u524d\u8ff0\u7684\u505a\u6cd5\u5c31\u4f1a\u5931\u6548\uff0c\u56e0\u4e3a\u6b64\u65f6\u77ed\u6587\u4ef6\u540d\u8de8\u8d8a\u4e8616\/32\u4f4d\u7684\u8fb9\u754c\u3002<\/p>\n<p>As another example, suppose the DLL saves the file name in a location external to the process, say a configuration file, the registry, or a shared memory block. If a 16-bit program program calls into this DLL, it would pass short names, whereas if a 32-bit program calls into the DLL, it would pass long names. If the file system functions returned only long names for 32-bit programs, then the copy of the DLL running in a 32-bit program would not be able to read the data written by the DLL running in a 16-bit program.<\/p>\n<p>\u53e6\u4e00\u4e2a\u4f8b\u5b50\u662f\uff0c\u5047\u8bbe\u67d0\u4e2aDLL\u5c06\u6587\u4ef6\u540d\u4fdd\u5b58\u5728\u8fdb\u7a0b\u4e4b\u5916\u7684\u67d0\u5904\uff0c\u4f8b\u5982\u914d\u7f6e\u6587\u4ef6\u4e2d\u3001\u6ce8\u518c\u8868\u4e2d\uff0c\u6216\u67d0\u4e2a\u5171\u4eab\u7684\u5185\u5b58\u533a\u57df\u91cc\u3002\u5982\u679c16\u4f4d\u5e94\u7528\u7a0b\u5e8f\u8c03\u7528\u4e86\u8fd9\u4e2aDLL\uff0c\u90a3\u4e48\u5b83\u4f20\u5165\u7684\u5c31\u662f\u77ed\u6587\u4ef6\u540d\uff0c\u800c32\u4f4d\u5e94\u7528\u7a0b\u5e8f\u8c03\u7528\u65f6\u5219\u4f1a\u4f20\u5165\u957f\u6587\u4ef6\u540d\u3002\u5982\u679c\u6587\u4ef6\u7cfb\u7edf\u51fd\u6570\u53ea\u4e3a32\u4f4d\u5e94\u7528\u7a0b\u5e8f\u8fd4\u56de\u957f\u6587\u4ef6\u540d\uff0c\u90a3\u4e48\u8fd0\u884c\u572832\u4f4d\u5e94\u7528\u7a0b\u5e8f\u4e0b\u7684\u8fd9\u4e2aDLL\u5c31\u65e0\u6cd5\u8bfb\u53d6\u753116\u4f4d\u5e94\u7528\u7a0b\u5e8f\u8c03\u7528\u5176\u65f6\u5199\u5165\u7684\u6570\u636e\u4e86\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u539f\u6587\u94fe\u63a5\uff1ahttps:\/\/devblogs.microsoft.com\/oldnewthing\/2005072 [&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-3158","post","type-post","status-publish","format-standard","hentry","category-tont_history"],"_links":{"self":[{"href":"https:\/\/www.aoisnow.net\/blog\/wp-json\/wp\/v2\/posts\/3158","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=3158"}],"version-history":[{"count":0,"href":"https:\/\/www.aoisnow.net\/blog\/wp-json\/wp\/v2\/posts\/3158\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.aoisnow.net\/blog\/wp-json\/wp\/v2\/media?parent=3158"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.aoisnow.net\/blog\/wp-json\/wp\/v2\/categories?post=3158"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.aoisnow.net\/blog\/wp-json\/wp\/v2\/tags?post=3158"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}