Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

MASM: How to statically import a DLL function by ordical?

226 views
Skip to first unread message

JJ

unread,
May 29, 2018, 4:03:36 PM5/29/18
to
Instead of by function name.

If it's not possible using ML or LINK, is there a tool to convert name
imports to ordinal imports?

R.Wieser

unread,
May 30, 2018, 3:39:36 AM5/30/18
to
JJ,

> How to statically import a DLL function by ordical?

The way I found it to be done is provide a .DEF file to the linker , in
which you mention which names are supposed to be bound to which ordinal
positions. Like this:

WS2_32.DEF
- - - - - - - -
LIBRARY WS2_32.dll

EXPORTS
accept @1
bind @2
closesocket @3
(etcetera)
- - - - - - - -

I'm not sure if it works the same for ML or LINK though.

Regards,
Rudy Wieser


JJ

unread,
May 30, 2018, 8:54:05 AM5/30/18
to
The only related LINK option I've found is the /DEF:file.def option, but
it's for defining what functions are exported by the main module.

R.Wieser

unread,
May 30, 2018, 9:24:19 AM5/30/18
to
JJ,

> The only related LINK option I've found is the /DEF:file.def option,
> but it's for defining what functions are exported by the main module.

Although I thought that was what you wanted to do (I misread), AFAIK you can
do the above as well. It than supplements the "by name" imports a LIB file
offers (but can also fully replace it) (it also allows you create alternate
names for existing "by name" entries).

Another (better im(ns)ho) solution would be to create a new LIB file, by
using (something like) IMPLIB.EXE provinding it the DLL as well as the DEF
file. With that new LIB file you than can refer to the (erstwhile) "by
ordinal only" entries by the names as specified in that DEF file.

Ofcourse, you can also retrieve the address for an ordinal entry dynamically
(using GetProcAddress). But I would not advice that for normal usage
(cumbersome).

Regards,
Rudy Wieser


JJ

unread,
May 31, 2018, 2:56:15 PM5/31/18
to
On Wed, 30 May 2018 15:24:02 +0200, R.Wieser wrote:
>
> Another (better im(ns)ho) solution would be to create a new LIB file, by
> using (something like) IMPLIB.EXE provinding it the DLL as well as the DEF
> file. With that new LIB file you than can refer to the (erstwhile) "by
> ordinal only" entries by the names as specified in that DEF file.

OK. I've managed to get the program to import the functions by ordinal.

I noticed that the Microsoft SDK import library files have the function
names appended with the argument size. e.g. "ExitProcess@4". I know that DLL
files don't have the information that specifies the size of function
arguments. So, how did Microsoft made those LIB files? Did they typed them
manually into the DEF files? Or is there a Microsoft equivalent of Borland's
IMPDEF? Which does more such as accepting a C header file in order to
retrieve function argument sizes.

> Ofcourse, you can also retrieve the address for an ordinal entry dynamically
> (using GetProcAddress). But I would not advice that for normal usage
> (cumbersome).

That's true. Moreover, I needed to import by ordinal in order to minimize
the file size. It's for tiny programs which are not bigger than 4KB, so
every byte matters. Without using any EXE compressor.

Kaz Kylheku

unread,
May 31, 2018, 3:51:06 PM5/31/18
to
On 2018-05-31, JJ <jj4p...@vfemail.net> wrote:
> the file size. It's for tiny programs which are not bigger than 4KB, so
> every byte matters. Without using any EXE compressor.

So it goes without saying that the only place you can get help is Usnenet.

R.Wieser

unread,
May 31, 2018, 4:30:20 PM5/31/18
to
JJ,

> I noticed that the Microsoft SDK import library files have the
> function names appended with the argument size. e.g.
> "ExitProcess@4".

Yep. The so-called "mangled (function) names".

> I know that DLL files don't have the information that specifies
> the size of function arguments.

No, not as a seperate section. But if you look in such DLLs (exported
functions) you can see that those mangled names are being used for the
functions themselves.

> So, how did Microsoft made those LIB files? Did they typed them
> manually into the DEF files?

Probably exactly the same way you make yours: by providing the DLL as an
argument to IMPLIB (or an MS equivalent), and let it extract the mangled
names from there and subsequently stuff them into the LIB file.

At least, that is what IMPLIB does for me (but which I can't use, because my
assembler does not accept the mangled function names, and I have to create a
DEF file to "rename" them, and from that generate a new LIB)

> Or is there a Microsoft equivalent of Borland's IMPDEF?

Probably (never looked for it though, so I'm not sure). But you do not
need to go the DEF file way. IMPLIB can generate a LIB directly from the
DLL. And IIRC you can even tell the importing process to return ordinals
only (doing a translation from function name to ordinal by way of the LIB
file)

> Which does more such as accepting a C header file in order
> to retrieve function argument sizes.

You give MS to much credit I'm afraid. :-)

You *cannot* retrieve that argument data (type, size) from anywhere else
than the sourcefile the program (DLL) is created from. After that (in the
resulting machine code - the DLL) all that info is gone. But for in the
mangled function names ofcourse.

Though there might be a possibility that a program/DLL is created with
simple (non-mangled) function names, and that a preparser generates the
actually used mangled ones from the simple names and what it can parse from
the functions argument declaration. Who knows (I don't) :-)

> It's for tiny programs which are not bigger than 4KB, so every byte
> matters.

:-)

If that is what you want to do, why don't you come over to the dark side and
write some Assembly, instead of that foul white-wizzards (rather wastefull)
C{something} ? :-D

By the way, I just thought of something: IIRC I can force my linker to
import everything by ordinal. Maybe your compiler can do the same ? That
way you do not even need to bother with recreating LIBs ...

Though I hope you are aware that you would bump into problems when DLLs on
different versions of Windows carry the functions with the same names, but
at different ordinals (as I've seen with W98se and XP).

Regards,
Rudy Wieser


JJ

unread,
Jun 1, 2018, 5:15:37 AM6/1/18
to
On Thu, 31 May 2018 22:30:13 +0200, R.Wieser wrote:
> JJ,
>
>> I noticed that the Microsoft SDK import library files have the
>> function names appended with the argument size. e.g.
>> "ExitProcess@4".
>
> Yep. The so-called "mangled (function) names".
>
>> I know that DLL files don't have the information that specifies
>> the size of function arguments.
>
> No, not as a seperate section. But if you look in such DLLs (exported
> functions) you can see that those mangled names are being used for the
> functions themselves.

Most Windows API (flat) function names (such as ExitProcess) in the DLL are
not mangled. And since I use the INVOKE directive to call the imported
function, that directive uses function names appended with argument size -
as defined by the PROTO directive. I could use the primitive CALL
instruction to call the function so that I don't have to use mangled
function names in the DEF/LIB file, but I'll have to PUSH the function
arguments manually. I was just hoping that INVOKE is a better way to call a
function, but things suggest that I was wrong.

> At least, that is what IMPLIB does for me (but which I can't use, because my
> assembler does not accept the mangled function names, and I have to create a
> DEF file to "rename" them, and from that generate a new LIB)
>
> Probably (never looked for it though, so I'm not sure). But you do not
> need to go the DEF file way. IMPLIB can generate a LIB directly from the
> DLL. And IIRC you can even tell the importing process to return ordinals
> only (doing a translation from function name to ordinal by way of the LIB
> file)

What compiler are using? Cause IIRC, IMPLIB is available only for Borland
compiler.

> You give MS to much credit I'm afraid. :-)
>
> You *cannot* retrieve that argument data (type, size) from anywhere else
> than the sourcefile the program (DLL) is created from. After that (in the
> resulting machine code - the DLL) all that info is gone. But for in the
> mangled function names ofcourse.
>
> Though there might be a possibility that a program/DLL is created with
> simple (non-mangled) function names, and that a preparser generates the
> actually used mangled ones from the simple names and what it can parse from
> the functions argument declaration. Who knows (I don't) :-)

Perhaps it would be easier to create a "builder" script that tries to
compiles a project to retrieve "unsatisfied external symbol" errors and use
that information to create the DEF file and make the LIB file. Then compiles
the project again.

> If that is what you want to do, why don't you come over to the dark side and
> write some Assembly, instead of that foul white-wizzards (rather wastefull)
> C{something} ? :-D

Too late. I've gone to the dark side before I see the bright side - almost 3
decades ago. >8D

> By the way, I just thought of something: IIRC I can force my linker to
> import everything by ordinal. Maybe your compiler can do the same ? That
> way you do not even need to bother with recreating LIBs ...

Please do tell. Maybe it's time I stop trying to use what most people use,
and use anything to achieve what I need.

> Though I hope you are aware that you would bump into problems when DLLs on
> different versions of Windows carry the functions with the same names, but
> at different ordinals (as I've seen with W98se and XP).

I know. I'm being careful of this case.

... and this leads me to another question.
How would you do if you want to mix both by name and by ordinal function
importing? I know that it's possible, because I've seen some applications
linking to (mostly) WSOCK32.DLL functions by both name and ordinal.

R.Wieser

unread,
Jun 1, 2018, 7:37:40 AM6/1/18
to
JJ,

> Most Windows API (flat) function names (such as ExitProcess) in
> the DLL are not mangled.

Correct. (I, wrongly, assumed you where talking about C{something}
libraries)

> And since I use the INVOKE directive to call the imported function,
> that directive uses function names appended with argument size -
> as defined by the PROTO directive.

And that is what the .H (or .INC) files are for: they describe *how* the
functions have to be called (and what kind of result you can expect).

> I could use the primitive CALL instruction to call the function so
> that I don't have to use mangled function names in the DEF/LIB
> file, but I'll have to PUSH the function arguments manually.

I wanted to go for a plain "no", but I guess it depends on the used
compiler/assembler itself.

For instance, I can call functions (inside my own program or DLLs) without a
PROTO (or in my case, a PROCDESC) in sight anywhere (and have done so for
many years). Though having them means that a compile/assemble time check
on the number and type of arguments can be performed.

But you could always create a .H file yourself for the DLL/LIB in question.
The only problem will than be where you get that "how many arguments does
this function take, what types are they" info from (welcome to my world by
the way. Its what I need to do for every DLL I want to use ...).

Luckily the MSDN has got a wealth of of information in that regard.

> I was just hoping that INVOKE is a better way to call a function,
> but things suggest that I was wrong.

No, you're right, it is (see above). It just needs a bit more work to be
able to keep using them.

> What compiler are using? Cause IIRC, IMPLIB is available only for
> Borland compiler.

I'm not. I'm using Borlands TASM32 v5 assembler, which was long ago used as
the backend for their C compiler. I bought it as a stand-alone package
though (which includes both IMPLIB and IMPDEF as well as a resource compiler
and other tools - it even included a few books. You know, real paper. :-) )

> Perhaps it would be easier to create a "builder" script that tries to
> compiles a project to retrieve "unsatisfied external symbol" errors
> and use that information to create the DEF file and make the LIB file.

I don't think that that will be possible. Although you will probably be
able to filter the "huh? I don't recognise this function name" entries from
the error listing, it won't include information to which DLL it expects the
name to be in. And you really need that for the DEF file.

Personally I would, for a "plain" DLL, opt to just generate the LIB file
from the DLL, and than either define the way the function needs to be called
(PROTO / PROCDESC) in the sourcefile itself, or in a (new) .H / .INC file.

But please do remember that the DEF vs LIB is an "or" thing. You can use
both at the same time, but you only *need* one of them (at least, with
Tasm32. YMMV).

> Too late. I've gone to the dark side before I see the bright side -
> almost 3 decades ago. >8D

Shucks. Thats what happened to me too (4 decades ago). :-)

>> IIRC I can force my linker to import everything by ordinal.
>
> Please do tell. Maybe it's time I stop trying to use what most people
> use, and use anything to achieve what I need.

I'm sorry. I just went back and checked. And although the TLINK32 "o" flag
is defined as "Import by ordinals" I could still see, when doing a hexdump,
the DLL function names in all their glory. I must have misunderstood (or
simply forgotten) something there. :-\

> How would you do if you want to mix both by name and by ordinal
> function importing?

I don't think its something you can control - from within the sourcecode I
mean. AFAIK its gouverned by the LIB and/or DEF file: if the function name
symbol is linked to a "by ordinal" import that will be used, if its linked
to a "by name" import, than it will be used.

Hmmm ... That makes me wonder: is the above "o" switch maybe ment for a LIB
entry where both a symbol as well as an ordinal entry are available. I'll
have to check that out some day.

> I know that it's possible, because I've seen some applications linking
> to (mostly) WSOCK32.DLL functions by both name and ordinal.

True. But thats than caused by the LIB file for WS2_32 than containing
both "by name" and "by ordinal" entries (and your function symbols
referencing them).

Do you have something like TDUMP - to "dump" the contents of a LIB (or DLL)
file with ? You can than see the different entries yourself.

Though I must say that WS2_32.DLL on my machine (XPsp3) does not seem to
contain any "by ordinal only" entries. But that does not mean the LIB could
not be constructed with both though.

Regards,
Rudy Wieser


JJ

unread,
Jun 2, 2018, 2:10:53 AM6/2/18
to
On Fri, 1 Jun 2018 13:37:33 +0200, R.Wieser wrote:
>
> Luckily the MSDN has got a wealth of of information in that regard.

You wish... They only have minimum documentations on MASM. C/C++ on the
other hand, is abundant.

> No, you're right, it is (see above). It just needs a bit more work to be
> able to keep using them.

But the fact that it can only use mangled function name, is a restriction.

> I don't think that that will be possible. Although you will probably be
> able to filter the "huh? I don't recognise this function name" entries from
> the error listing, it won't include information to which DLL it expects the
> name to be in. And you really need that for the DEF file.

Ah, you're right.

> But please do remember that the DEF vs LIB is an "or" thing. You can use
> both at the same time, but you only *need* one of them (at least, with
> Tasm32. YMMV).

Unfortunately, Microsoft LINK can't use DEF files, in place of LIB files.

> I'm sorry. I just went back and checked. And although the TLINK32 "o" flag
> is defined as "Import by ordinals" I could still see, when doing a hexdump,
> the DLL function names in all their glory. I must have misunderstood (or
> simply forgotten) something there. :-\

I know. I've been there too.

> I don't think its something you can control - from within the sourcecode I
> mean. AFAIK its gouverned by the LIB and/or DEF file: if the function name
> symbol is linked to a "by ordinal" import that will be used, if its linked
> to a "by name" import, than it will be used.

Yes, I've just noticed that.

> Hmmm ... That makes me wonder: is the above "o" switch maybe ment for a LIB
> entry where both a symbol as well as an ordinal entry are available. I'll
> have to check that out some day.
>
> Do you have something like TDUMP - to "dump" the contents of a LIB (or DLL)
> file with ? You can than see the different entries yourself.

For Microsoft import LIB files, each function exports always have both the
function name and ordinal, but there's a flag which indicates whether it's
available by name or ordinal. Not both.

R.Wieser

unread,
Jun 2, 2018, 4:55:11 AM6/2/18
to
JJ,

>> Luckily the MSDN has got a wealth of of information in that regard.
>
> You wish... They only have minimum documentations on MASM. C/C++
> on the other hand, is abundant.

I know. They also have zero info in regard to my Borlands Tasm32. :-)

But when given the choice between MSDN pages and pretty-much nothing else
than I think I may call MSDN info rather abundant - especially in regard to
description for functions in the common Windows DLLs.

But yes, I always have to extract information from the available C/C++/other
examples and than re-implement them in Assembly (no simple copy-paste).
I've been doing that for so long that I do not even register that anymore.

Than again, most of my information searches are about how to use a certain
DLL function, and much less about how to solve a problem.

> But the fact that it can only use mangled function name, is a restriction.

I'm not sure from which direction you mean that ...

- Yes, you cannot change the names in the DLL (well, you can. But its
certainly not advicable :-) ).

- No, you are free to come up with your own names, make a DEF file to link
your names to the mangled ones, and than create a LIB file from the DEF.

Now I think of it, it would be best to create a LIB file with a different
name. (the LIB file still points to the right DLL, as it has been provided
at the top of the DEF file).

After that copy the origional .H file to match the above .LIB filename, and
rename the mangled names in it to match the ones in the DEF.

And as a last step import the new LIB and H file instead of, or even along
side the origional ones.

From this point on you have than nothing to do with the mangled function
names anymore.

... or am I missing something here ?

By the way, here is an example of such a "rename" I did (VSSAPI):

DEF file (all on a single line):
- - - - -
CreateVssBackupComponents =
?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z
- - - - -
TDUMP of the entry in the resulting LIB:
- - - - -
0002B0 THEADR CreateVssBackupComponents
0002CE COMENT Purge: Yes, List: Yes, Class: 160 (0A0h)
Dynamic link import (IMPDEF)
Imported by: name
Internal Name: CreateVssBackupComponents
Module Name: VSSAPI.DLL
Imported name:
?CreateVssBackupComponents@@YGJPAPAVIVssBackupComponents@@@Z
000338 MODEND
- - - - -

> Unfortunately, Microsoft LINK can't use DEF files, in place of LIB files.

Well, luckily a LIB is only a single implib step away from a DEF. :-)

> For Microsoft import LIB files, each function exports always have both
> the function name and ordinal, but there's a flag which indicates whether
> it's available by name or ordinal. Not both.

Bummer.

Although ... Now I think of it it would be a bit silly for a LIB entry to
have both the name as well as the ordinal: The first allows us to use
other versions of the DLL even if the order of the functions in them have
changed, and the latter makes sure we would *not* be able to do so. (also,
remember the warning I gave about using ordinals instead of names ? Yeah,
such a LIB would stumble into that pitfall, and possibly worse. :-( :-) )

Regards,
Rudy Wieser


0 new messages