Holy cow, I wrote a book!
Now that we've learned what the dllimport
declaration specifier does, what if you get it wrong?
If you forget to declare a function as dllimport,
then you're basically making the compiler act like a naive compiler
that doesn't understand dllimport.
When the linker goes to resolve the external reference for
the function, it will use the stub from the import library,
and everything will work as before.
You do miss out on the optimization that dllimport
enables, but the code will still run.
You're just running in naive mode.
(There are still some header files in the Platform SDK that
neglect to use the dllimport declaration specifier.
As a result, anybody who uses those header files to import functions
from the corresponding DLL will be operating in "naive mode".
Hopefully the people responsible for those header files will
recognize themselves in this parenthetical and fix the problem for
a future release of the Platform SDK.)
Now, what about the reverse problem?
What if you declare a function as dllimport when it
The linker detects this since it sees an attempt to import a
__imp__FunctionName symbol and can't find one, though it
can find the normal FunctionName symbol.
When this happens, the linker raises
It recovers from this error by simply manufacturing a fake
__imp__FunctionName variable and initializing it with
the address of the FunctionName function.
In effect, you've imported the function from yourself.
Your code now goes through all the gyrations associated with
calling an imported function unnecessarily; it could have just
called FunctionName directly.
(There are cases where the linker can be a little smarter.
if it sees a call [__imp__FunctionName], it can change
it to call FunctionName + nop.
The nop is necessary because the
call [__imp__FunctionName] instruction is six bytes
long, whereas call FunctionName is only five.
The extra nop gets everything back in sync.)
call FunctionName + nop
Thus, in both cases where you mess up the dllimport
declaration specifier, the linker manages to recover from your mistake,
and your program does run fine, though the patching up did cost you
in code size and efficiency.
(All this discussion is for x86, by the way.
Other architectures have different quirks.)
Next time, more on import libraries, and exposing some "little
white lies" I've been telling.