Hello,

I came across interesting linker behavior while trying to include a function
forwarder into my DLL (I use Visual C++ 6.0 SP 5).

Suppose I have mydll.dll and I want MyHtonl in this DLL to be forwarded to
wsock32.htonl. Also I want to link implicitly (that is, using the import
library) with mydll.dll. So I include the following lines into the .def
file:

EXPORTS
MyHtonl = wsock32.htonl

I get MyHtonl exported from mydll.dll and mydll.lib contains two symbols:
MyHtonl and __imp_MyHtonl. Looks reasonable, but this is not what I want.
Since I want to link implicitly and the original htonl uses __stdcall
calling convention, I need _MyHtonl@4 and __imp__MyHtonl@4 symbols in the
import library.

Now when I try to fix it by specifying the decorated name in the .def file

EXPORTS
_MyHtonl@4 = wsock32.htonl

I get pretty interesing results: the name that appears in the export table
is _MyHtonl, and the import library contains __MyHtonl@4@4 and
__imp___MyHtonl@4@4. Weird. The linker seems to be triggered by '@'
character in the function name, so if I write

EXPORTS
@MyHtonl = wsock32.htonl

I get _@MyHtonl@4 and __imp__@MyHtonl@4 in the import library and empty
(I never thought this is ever possible) function name in the export table.

So, the question is, how it is possible to create a forwarder so that
1) the export table contains the undecorated function name;
2) the import library contains the properly decorated function name for
__stdcall calling convention.

I know that such forwarders exist in the system images. For example,
kernel32.dll forwards EnterCriticalSection to ntdll.RtlEnterCriticalSection
and both 1) and 2) are met. I wonder how Microsoft builds it. Do they use a
special in-house tool or is it possible to achieve with publicly available
tools?

-- Alex Fedotov

P.S. Of course there is a plenty of ways how to solve my original problem,
but now I'm just curious about that linker behavior and if it is possible to
forward functions the way I want.

Re: Function forwarding by Jeff

Jeff
Sun Aug 17 09:41:41 CDT 2003

"Alex Fedotov" <me@alexfedotov.com> wrote in message
news:%23lLPkNJZDHA.2620@TK2MSFTNGP09.phx.gbl...
> Hello,
>
> I came across interesting linker behavior while trying to include a
function
> forwarder into my DLL (I use Visual C++ 6.0 SP 5).
>
> Suppose I have mydll.dll and I want MyHtonl in this DLL to be
forwarded to
> wsock32.htonl. Also I want to link implicitly (that is, using the
import
> library) with mydll.dll. So I include the following lines into the
.def
> file:
>
> EXPORTS
> MyHtonl = wsock32.htonl
>
> I get MyHtonl exported from mydll.dll and mydll.lib contains two
symbols:
> MyHtonl and __imp_MyHtonl. Looks reasonable, but this is not what I
want.
> Since I want to link implicitly and the original htonl uses __stdcall
> calling convention, I need _MyHtonl@4 and __imp__MyHtonl@4 symbols in
the
> import library.

Alex,

Given this *.c file...

// htonl.c
#include <Windows.h>

BOOL WINAPI DllMain(
HINSTANCE hinstDLL,
DWORD fdwReason,
LPVOID lpvReserved)
{
return TRUE;
}

...and compiling it at the command line using this...

cl /c htonl.c

...and this *.def file...

// htonl.def
LIBRARY HTONL
EXPORTS
MyHtonl = wsock32.htonl

...and linking at the command line using this...

link /DLL /DEF:htonl.def htonl.obj wsock32.lib

I get an 'htonl.dll' with the single export that dumpbin /exports
reports as...

ordinal hint RVA name
1 0 MyHtonl (forwarded to wsock32.htonl)

...and an 'htonl.lib' import lib for which dumpbin /linkermember reports
the following exports...

5 public symbols
4 _MyHtonl@4
1 __IMPORT_DESCRIPTOR_HTONL
2 __NULL_IMPORT_DESCRIPTOR
4 __imp__MyHtonl@4
3 HTONL_NULL_THUNK_DATA

...seems to be exactly what you're after, but I can't explain the
reasons for our differences.

--
Jeff Partch [VC++ MVP]



Re: Function forwarding by Alex

Alex
Sun Aug 17 12:50:00 CDT 2003

Jeff Partch wrote:

> Given this *.c file...
> [...]
> ...seems to be exactly what you're after, but I can't explain the
> reasons for our differences.

Thanks Jeff,

I did the same and... got the same results. Now when I included those lines
into my project, it worked as well.

Initially I tried to use /export linker option as an easy way to achieve
conditional exports:

#ifndef _WINCE
#pragma comment(linker, "/export:MyHtonl=wsock32.htonl")
#else
#pragma comment(linker, "/export:MyHtonl=winsock.htonl")
#endif

And _this_ gives the results I described before. I did try using a .def file
instead and I remember it didn't work yesterday, but it was probably too
late so I didn't see the difference ;).

-- Alex Fedotov