Holy cow, I wrote a book!
In the documentation for delay-loading,
there's a remark that says that
the call to GetProcAddress can be avoided if
there is binding information.
A customer who received the explanation of
why you can't delay-load kernel32
pointed out that paragraph and asked whether
this means that you can
delay-load kernel32 if you bind to it.
(Getting around to answering this question
was the point of
Let's take another look at what that GetProcAddress-avoidance
Actually, it's just another look at what the module loader does when
it's time to resolve imports to a bound DLL:
At build time,
the actual function pointers are precomputed and cached,
along with the timestamp of the DLL those precomputed values
At run time,
the delay-load stubs check the timestamp of the target DLL
and compare it against the timestamp that it had cached.
If they are the same, then they skip the call to
GetProcAddress and use the cached value.
In other words, the delay-load stubs use binding information
in exactly the same way the module loader does.
Does this mean that you can now delay-load kernel32?
First of all, if the timestamps don't match or if the target
DLL was not loaded at its preferred address, then the binding
information is of no use—you have a cache miss.
In that case, the module loader (and the delay-load stubs)
must obtain the function pointers the old-fashioned way.
You can't assume that your binding information will always
after your module was bound to
there may have been a security update which modified
kernel32, which invalidates your binding information.)
And besides, even if the binding information were used,
you still have to call LoadLibrary to get
the target DLL loaded in the first place.
Even though binding may have optimized away one call to kernel32,
you still have that LoadLibrary to deal with.