{"id":95796,"date":"2017-03-22T07:00:00","date_gmt":"2017-03-22T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=95796"},"modified":"2019-03-13T01:08:24","modified_gmt":"2019-03-13T08:08:24","slug":"20170322-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170322-00\/?p=95796","title":{"rendered":"You can peek to see whether your delay-loaded function loaded successfully"},"content":{"rendered":"<p><a HREF=\"https:\/\/msdn.microsoft.com\/library\/windows\/desktop\/mt403328(v=vs.85).aspx\">The <code>Query&shy;Optional&shy;Delay&shy;Loaded&shy;API<\/code> function<\/a> lets you ask whether a function marked as delay-loaded was in fact found. Here&#8217;s a tiny demonstration: <\/p>\n<pre>\n#include &lt;windows.h&gt;\n#include &lt;commdlg.h&gt;\n#include &lt;libloaderapi2.h&gt;\n#include &lt;stdio.h&gt;\n\nEXTERN_C IMAGE_DOS_HEADER <a HREF=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/\">__ImageBase<\/a>;\n#define HMODULE_THISCOMPONENT reinterpret_cast&lt;HMODULE&gt;(&amp;__ImageBase)\n\nint __cdecl main(int argc, char** argv)\n{\n    if (QueryOptionalDelayLoadedAPI(HMODULE_THISCOMPONENT,\n          \"comdlg32.dll\", \"GetOpenFileNameW\", 0))\n    {\n        printf(\"GetOpenFileNameW can be called!\\n\");\n    }\n    return 0;\n}\n<\/pre>\n<p>This gives you function-by-function granularity on checking whether a delay-loaded function was successfully loaded, which is an improvement over <a HREF=\"https:\/\/msdn.microsoft.com\/library\/8yfshtha.aspx\">being told whether all the imports for a DLL were loaded<\/a>. <\/p>\n<p>Note also that the original problem with the Win16 model for weak linking wasn&#8217;t that <a HREF=\"https:\/\/twitter.com\/rosyna\/status\/710650988034568192\">developers built but never ran their programs<\/a>. Developers built their programs, and they ran fine on all the systems they tested because the function was present on all the systems they tested. <i>It never occurred to them that the function might not exist in the first place<\/i>. I mean, suppose you wrote a 16-bit program that called <code>Get&shy;Open&shy;File&shy;Name<\/code>. It runs great on all your systems! But oh no, you get a report from a customer that it crashes on their system. The reason: <code>COMMDLG.DLL<\/code> was not a mandatory OS component. Users had the option of installing Windows without it, at which point all the programs that called <code>Get&shy;Open&shy;File&shy;Name<\/code> would start crashing. <\/p>\n<p>Win32&#8217;s response to this was &#8220;If you want weak linking, <a HREF=\"http:\/\/catb.org\/jargon\/html\/I\/If-you-want-X--you-know-where-to-find-it-.html\">you know where to find it<\/a>.&#8221; Namely, <code>Get&shy;Proc&shy;Address<\/code>. The fact that you called a function to get an address will hopefully remind you to check whether the function actually succeeded. <\/p>\n<p>The introduction of the <code>Query&shy;Optional&shy;Delay&shy;Loaded&shy;API<\/code> function is to allow Store apps (which are not allowed by policy to call <code>Load&shy;Library<\/code>) to detect whether their delay-loaded function actually got loaded. The fact that the requested functions are in the delay-loaded function table means that a static analysis can still find all the functions that the program could potentially call. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Predicting the future.<\/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":[25],"class_list":["post-95796","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Predicting the future.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/95796","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=95796"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/95796\/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=95796"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=95796"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=95796"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}