Declare AUTO function

A

Armin Zingler

Hi,

I'm wondering why this declaration works:

Declare Auto Function SetupDiGetClassDevs Lib _
"setupapi.dll" Alias "SetupDiGetClassDevsA" _
(...) As IntPtr

According to the documentation, related to the function name
resolution, the "Auto" modifier means that the runtime searches
for "SetupDiGetClassDevsA" first, then for the same name
with a "W" appended, which is "SetupDiGetClassDevsAW". Both
names don't exist on a Win7 system, yet it works.

Documentation says:

"On a Unicode platform, such as Windows NT, Windows 2000, or
Windows XP, first look up the external procedure with no name
modification. If that fails, append "W" to the end of the
external procedure name and look it up again."

(from http://msdn.microsoft.com/en-us/library/4zey12w5(VS.90).aspx )

To which name does "with no name modification" refer? The original
name "SetupDiGetClassDevs" or the alias name "SetupDiGetClassDevsA"?
It must be the former, otherwise the call should fail. If so, what's
the purpose of the alias name? I reason that it's ignored if the
Auto modifier is used. Am I right or wrong?
(BTW, I didn't write the declaration myself)
 
T

Tom Shelton

Armin Zingler formulated on Saturday :
Hi,

I'm wondering why this declaration works:

Declare Auto Function SetupDiGetClassDevs Lib _
"setupapi.dll" Alias "SetupDiGetClassDevsA" _
(...) As IntPtr

According to the documentation, related to the function name
resolution, the "Auto" modifier means that the runtime searches
for "SetupDiGetClassDevsA" first, then for the same name
with a "W" appended, which is "SetupDiGetClassDevsAW". Both
names don't exist on a Win7 system, yet it works.

Documentation says:

"On a Unicode platform, such as Windows NT, Windows 2000, or
Windows XP, first look up the external procedure with no name
modification. If that fails, append "W" to the end of the
external procedure name and look it up again."

(from http://msdn.microsoft.com/en-us/library/4zey12w5(VS.90).aspx )

To which name does "with no name modification" refer? The original
name "SetupDiGetClassDevs" or the alias name "SetupDiGetClassDevsA"?
It must be the former, otherwise the call should fail. If so, what's
the purpose of the alias name? I reason that it's ignored if the
Auto modifier is used. Am I right or wrong?
(BTW, I didn't write the declaration myself)

On win32 there are generally 2 entry points forevery function that
dealt with string parameters - one that takes Ansi strings
(FunctionNameA) and one that would take wide character strings
(FunctionNameW). For instance, there is no entry point SendMessage in
User32 - but, there are SendMessageA and SendMessageW.

On 9x platforms, the W function was usually unimplemented (there were a
few exceptions for functions used by com and it was also possilbe to
expand the number of availabe W functions using the Microsoft Layer for
Unicode) - in other words it wasn't there. On NT based platforms both
entry points were implemented, but the A functions would simply convert
the Ansi to Wide and then call the W function, converting any return
values back to Ansi for the return to the caller. The W functions were
the primary api for NT.

The function you are refering to, though is not part of the standard
win32 api - but was an NT only function was first included in Windows
2000. Therefore, it does not expose the A and the W entry points -
only the unqualified name.

In the bad old days of the ultra inferior VB.CLASSIC - the alias
feature was often used to avoid having to specify which version you
wanted to call. So for instance the declares:

Declare Function SendMessage Lib "user32" Alias "SendMessageA" (....)
As Long

and

Declare Function SendMessageA Lib "user32" (...) As Long

Are the same. And the call would work on both 9x and NT - though, it
would be distinctly slower on NT based systems because of all the
string conversions between Ansi and Wide the at had to occur.

What sucked were the cases where 1) you new you were going to be NT
only and wanted to call the W function for efficeincy or 2) you wanted
to use one of the W functions common to both systems. You couldn't use
a declare statement with As String - Vb6 always converted to ansi
before a call to an external method defined in a declare statement. So
your choices were, use a Long instead and StrPtr or a byte array and
handle the string covnersions your self. Or, you could step outside of
VB and create (or find) a type lib....

VB.NET introduced the abiltity to directly call the W functions from a
delcare statemetn and also introduced the Auto keyword so that the
runtime could select the most appropriate entry point based on the
current runtime environment.

So, lets take SendMessage for example. In VB.NET rather then specifiy
in the Alias SendMessageA or SendMessageW - you declare it Auto:

Declare Auto Function SendMessage Lib "user32" (...) As IntPtr

This basically allows the runtime to generate code that uses the most
appropriate version of the function. It will check:

does user32 contain and entry point named SendMessage?

Yes - call it
No - Is the current environment nt based?

Yes - append a W to SendMessage, and check for the SendMessageW entry
point.

No - append an A to SendMessage, and check for the SendMessageA entry
point.

If it can't resolve any of those versions then it of course throws an
error.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top