Unicode API

H

Howard Kaikow

Are the following equivalent?

<DllImport("kernel32", CharSet:=CharSet.Unicode, SetLastError:=True)> _
Private Shared Function FindFirstFile _
(ByVal lpFileName As String, ByVal lpFindFileData As WIN32_FIND_DATA) As
Integer
End Function

<DllImport("kernel32", CharSet:=CharSet.Unicode, SetLastError:=True)> _
Private Shared Function FindFirstFileW _
(ByVal lpFileName As String, ByVal lpFindFileData As WIN32_FIND_DATA) As
Integer
End Function

<DllImport("kernel32", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function FindFirstFileW _
(ByVal lpFileName As String, ByVal lpFindFileData As WIN32_FIND_DATA) As
Integer
End Function
 
C

Claes Bergefall

No they are not

Howard Kaikow said:
Are the following equivalent?

<DllImport("kernel32", CharSet:=CharSet.Unicode, SetLastError:=True)> _
Private Shared Function FindFirstFile _
(ByVal lpFileName As String, ByVal lpFindFileData As WIN32_FIND_DATA) As
Integer
End Function

In this case ExactSpelling (a property of DllImportAttribute) is true
causing the runtime to *only* look for the method FindFirstFile. This fails
since there is no such method in kernel32

<DllImport("kernel32", CharSet:=CharSet.Unicode, SetLastError:=True)> _
Private Shared Function FindFirstFileW _
(ByVal lpFileName As String, ByVal lpFindFileData As WIN32_FIND_DATA) As
Integer
End Function

Here too ExactSpelling is true causing the runtime to *only* look for the
method FindFirstFileW. This works fine since that's actually one of the
methods exported from kernel32

<DllImport("kernel32", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function FindFirstFileW _
(ByVal lpFileName As String, ByVal lpFindFileData As WIN32_FIND_DATA) As
Integer
End Function

When using CharSet.Auto, VB defaults ExactSpelling to False and in this case
the behavior depends on the platform.
On ANSI platforms it will first look for the method FindFirstFileW (i.e. the
exact spelling you used) and if not found it will try FindFirstFileWA (i.e.
appending an A to the name you specified). I don't remember if the
FindFirstFileW method exists on ANSI systems so I don't know if this
succeeds or not. You'll have to try it
On Unicode platforms it will first look for the method FindFirstFileWW (i.e.
appending a W to the name you specified) and if not found it will try
FindFirstFileW (i.e. the exact spelling you used). All Unicode systems
exports FindFirstFileW som this will succeed.


Unless you have compelling reason not to, I suggest you stick with this:
<DllImport("kernel32", CharSet:=CharSet.Auto, SetLastError:=True)> _
Private Shared Function FindFirstFile (ByVal lpFileName As String, ByVal
lpFindFileData As WIN32_FIND_DATA) As Integer
End Function


/claes
 
M

Mattias Sjögren

Hej Claes,
In this case ExactSpelling (a property of DllImportAttribute) is true

No, ExactSpelling defaults to False and it's not set to anything else
in the code.


Mattias
 
C

Claes Bergefall

Hej Mattias :)

This is what it says in my documentation (2005):

"CharSet.Unicode
String marshaling
Platform invoke copies strings from their managed format (Unicode) to
Unicode format.
Name matching
When the ExactSpelling field is true, as it is by default in Visual Basic
2005, platform invoke searches only for the name you specify. For example,
if you specify MessageBox, platform invoke searches for MessageBox and fails
if it cannot locate the exact spelling.
When the ExactSpelling field is false, as it is by default in C++ and C#,
platform invoke searches for the mangled name first (MessageBoxW), then the
unmangled alias (MessageBox) if the mangled name is not found. Notice that
Unicode name-matching behavior differs from ANSI name-matching behavior."

Since we're using VB.NET it defaults to True when specifying
CharSet.Unicode. In C# though it would default to False.

/claes
 
C

Claes Bergefall

Here is the doc btw:
http://msdn2.microsoft.com/en-us/library/7b93s42f.aspx

Claes Bergefall said:
Hej Mattias :)

This is what it says in my documentation (2005):

"CharSet.Unicode
String marshaling
Platform invoke copies strings from their managed format (Unicode) to
Unicode format.
Name matching
When the ExactSpelling field is true, as it is by default in Visual Basic
2005, platform invoke searches only for the name you specify. For example,
if you specify MessageBox, platform invoke searches for MessageBox and
fails if it cannot locate the exact spelling.
When the ExactSpelling field is false, as it is by default in C++ and C#,
platform invoke searches for the mangled name first (MessageBoxW), then
the unmangled alias (MessageBox) if the mangled name is not found. Notice
that Unicode name-matching behavior differs from ANSI name-matching
behavior."

Since we're using VB.NET it defaults to True when specifying
CharSet.Unicode. In C# though it would default to False.

/claes
 
M

Mattias Sjögren

When the ExactSpelling field is true, as it is by default in Visual Basic 2005,

This is wrong, or at least over simplified. It's only the default
(i.e. set automatically by the compiler) if you use the Declare
statement with the Ansi or Unicode modifier. If you use Declare Auto,
or the DllImport attribute as in the original poster's code, the
default is ExactSpelling=false.


Trevlig midsommar...


Mattias
 
C

Claes Bergefall

Mattias Sjögren said:
This is wrong, or at least over simplified. It's only the default
(i.e. set automatically by the compiler) if you use the Declare
statement with the Ansi or Unicode modifier. If you use Declare Auto,
or the DllImport attribute as in the original poster's code, the
default is ExactSpelling=false.

Yes, it looks like you are correct (and it makes sense too since the
DllImport constructor doesn't set this value)

This works...
<DllImport("user32", CharSet:=CharSet.Unicode)> _
Private Shared Function SetWindowText(ByVal hwnd As IntPtr, ByVal lpString
As String) As Integer
End Function

....but this doesn't (although it looks fundamentally the same)
Private Declare Unicode Function SetWindowText Lib "user32" (ByVal hwnd As
IntPtr, ByVal lpString As String) As Integer

So I guess the documentation is incorrect (or at least incomplete) in this
case.

Trevlig midsommar...

Detsamma

/claes
 
H

Howard Kaikow

So, if I want to use Unicode, the following is guaranteed to work on systems
supporting FindFirstFileW and Unicode?

<DllImport("kernel32", CharSet:=CharSet.Unicode, SetLastError:=True)> _
Private Shared Function FindFirstFileW _
(ByVal lpFileName As String, ByVal lpFindFileData As WIN32_FIND_DATA) As
Integer
End Function
 
C

Claes Bergefall

Yes. You should pass lpFindFileData ByRef though (unless you defined
WIN32_FIND_DATA as a class) since it's an out parameter

/claes
 

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