Why do these DLLs have two apparently identical entry points?

非 Y 不嫁゛ 提交于 2021-02-11 07:58:39

问题


Today, working on some VB.NET code I had to access two external DLLs in order to use some methods. The help topics that I found told me to use the following external methods:

  • shlwapi.dll → PathIsNetworkPath (Reference 1)
  • mpr.dll → WNetAddConnection2 and WNetCancelConnection2 (Reference 2)

However, when I tried to call these methods from my code, I got an error saying that the entry point did not exist. So I did some research and I found out that the DLLs in my operative System (Windows 7 enterprise 32 bits) do not include these methods exactly, but instead, I got:

  • PathIsNetworkPath → PathIsNetworkPathA / PathIsNetworkPathW
  • WNetAddConnection2 → WNetAddConnection2A / WNetAddConnection2W
  • WNetCancelConnection2 → WNetCancelConnection2A / WNetCancelConnection2W

So, I tested their behaviour: * Methods finishing with "A" work just as expected. * Methods finishing with "W" do not work as expected, they raise errors or return wrong results (g.i. "false" when it should be "true"). And yet however, nobody in the help topics mentions having a similar problem.

So I did a little research and in the MSDN documentation I found that the DLLs contain only the methods that finish with "A" and "W", and both of them, in the three cases that I use, the documentation pages are identical as far as I can see. As a matter of fact all along the page, they don't use the name of the method that ends with A/W but without it.

So my questions are: *why do I have methods "A" and "W" instead of the one without A/W in my DLLs? What's the difference between both of them? Why do methods "A" work for me while methods "W" don't?


回答1:


Since Windows NT 4 / 2000 / XP, WinAPI functions come in ANSI (A) and Unicode (W) variants. See also What is the difference between the `A` and `W` functions in the Win32 API?.

When using P/Invoke, there's a difference between C# and VB.NET. See Specifying a Character Set on MS Docs, specifically "String Marshaling and Name Matching" and "Specifying a Character Set in Visual Basic":

When the DllImportAttribute.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 when it cannot locate the exact spelling.

Given the default for the DllImportAttribute.CharSet field is "ANSI" for C# and VB.NET, the rules for Visual Basic determine that the runtime doesn't search for the A or W entry point, see Docs: DllImportAttribute.ExactSpelling Field. This is for backwards compatibility with Visual Basic I guess.

So you have three options:

  1. Explicitly specify the "W" entry point and CharSet.Unicode:

    <DllImport("shlwapi.dll", EntryPoint:="PathIsNetworkPathW", SetLastError:=True, CharSet:=CharSet.Unicode)> _
    Public Function PathIsNetworkPath(<MarshalAs(UnmanagedType.LPTStr)>pszPath As String) As <MarshalAs(UnmanagedType.Bool)>Boolean
    End Function
    
  2. Disable exact spelling, causing the runtime to search for the "A" entry point (given the default charset, when not specified, is ANSI):

    <DllImport("shlwapi.dll", EntryPoint:="PathIsNetworkPath", SetLastError:=True, ExactSpelling:=False)> _
    Public Function PathIsNetworkPath(<MarshalAs(UnmanagedType.LPTStr)>pszPath As String) As <MarshalAs(UnmanagedType.Bool)>Boolean
    End Function
    
  3. Set the CharSet to Auto, implying a platform-specific character set (Unicode for most OSes) and ExactSpelling False:

    <DllImport("shlwapi.dll", EntryPoint:="PathIsNetworkPath", SetLastError:=True, CharSet:=CharSet.Auto)> _
    Public Function PathIsNetworkPath(<MarshalAs(UnmanagedType.LPTStr)>pszPath As String) As <MarshalAs(UnmanagedType.Bool)>Boolean
    End Function
    

I'd prefer option 3, as it eliminates useless (or even dangerous, as it might lead to data loss) Unicode -> ANSI -> Unicode conversion of the strings, and doesn't require you to explicitly specify the "W" variants of the functions.



来源:https://stackoverflow.com/questions/52643817/why-do-these-dlls-have-two-apparently-identical-entry-points

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!