在64位办公室中调用MultiByteToWideChar()会产生错误的结果 [英] Call to MultiByteToWideChar() in 64-bit office gives wrong result
问题描述
我有一个Excel VBA项目,我正在适应64位Office.在一部分中,我使用20个左右的不同代码页中的任何一个来调用 MultiByteToWideChar()
.(因此StrConv不能替代.)
I have an Excel VBA project I'm in the process of adapting for 64-bit Office. In one part, I make calls to MultiByteToWideChar()
using any of 20 or so different code pages. (So StrConv is not an alternative.)
使用以下 declare
:
Declare Function MultiByteToWideChar Lib "kernel32" ( _
ByVal codepage As Long, _
ByVal dwFlags As Long, _
lpMultiByteStr As Any, _
ByVal cbMultiByte As Long, _
ByVal lpWideCharStr As Long, _
ByVal cchWideChar As Long _
) As Long
'params: UINT, DWORD, LPCSTR, int, LPWSTR, int
'return: int
但是我对64位的适应却不是:我得到了错误的结果(例如,一个空字符串,其中期望有一个非空字符串),并且经常崩溃.我正在使用从
But my adaptation to 64-bit is not: I get wrong results (e.g. an empty string where a non-empty string is expected), and frequent crashes. I'm using a declare
that I got from the Microsoft-provided Win32API_PtrSafe.TXT file. (Of course, it could have bugs.)
所以,我猜想在clarify语句中或在我进行呼叫的方式中有不正确的地方.
So, I'm guessing something is not right in the declare statement or in how I'm making the call.
以下是可复制的最小样本:
Here's a minimal sample that repro's:
'Windows API declarations
Public Const MB_PRECOMPOSED = &H1 'use precomposed chars
Declare PtrSafe Function MultiByteToWideChar Lib "kernel32" ( _
ByVal CodePage As Long, _
ByVal dwFlags As Long, _
ByVal lpMultiByteStr As String, _
ByVal cchMultiByte As Long, _
ByVal lpWideCharStr As String, _
ByVal cchWideChar As Long _
) As Long
'params: UINT, DWORD, LPCSTR, int, LPWSTR, int
'return: int
' My function that calls MultiByteToWideChar
Private Function EncodedStringByteArrayToString(abStringData() As Byte, lngArrLen As Long, CodePage As Long) As String
Dim lngStrLen As Long, str As String
lngStrLen = MultiByteToWideChar(CodePage, MB_PRECOMPOSED, ByVal VarPtr(abStringData(1)), lngArrLen, 0&, 0)
str = String(lngStrLen, " ")
lngStrLen = MultiByteToWideChar(CodePage, MB_PRECOMPOSED, ByVal VarPtr(abStringData(1)), lngArrLen, StrPtr(str), lngStrLen)
EncodedStringByteArrayToString = str
End Function
' Sample routine to produce repro
Private Sub TestMB2WCBug()
Dim abStringData(1 To 9) As Byte
Dim resultString As String
abStringData(1) = 67
abStringData(2) = 111
abStringData(3) = 112
abStringData(4) = 121
abStringData(5) = 114
abStringData(6) = 105
abStringData(7) = 103
abStringData(8) = 104
abStringData(9) = 116
resultString = EncodedStringByteArrayToString(abStringData(), 9, 10000)
End Sub
推荐答案
这已经在32位Office中为我服务了多年
This has been working for me for years in 32-bit Office
它可能无法与您显示的 Declare
一起使用.
It could not possibly work with the Declare
that you have shown.
MultiByteToWideChar
需要一个 LPWSTR
作为输出缓冲区.当将字符串传递到 Declare
d函数时,VB执行从Unicode到ANSI的自动转换,因此当 lpWideCharStr
是声明为 As String
.充其量,它会收到一个足够大的缓冲区,因此不会发生缓冲区溢出,然后从函数返回时,VB将执行转换回Unicode的操作,因此您将得到一个双unicode字符串.
MultiByteToWideChar
expects an LPWSTR
as the output buffer. VB performs automatic conversion from Unicode to ANSI when passing strings into Declare
d functions, so there is no way that the function would receive a pointer to a wide string buffer when lpWideCharStr
is declared As String
. At best, it would receive a buffer that is large enough so no buffer overflow would occur, and then VB would perform conversion back to Unicode when returning from the function, so you will end up with a double-unicode string.
lpMultiByteStr
也不是字符串,而是一些编码.
lpMultiByteStr
is not a string either, it's an array of bytes in some encoding.
EncodedStringByteArrayToString
内部的代码似乎知道所有这些,因为它正确地传递了 lpMultiByteStr
的字节数组和 Strcodetr
的lpWideCharStr
.当前的 MultiByteToWideChar
声明可能不会发生这种情况.
The code inside EncodedStringByteArrayToString
seems to know all that, because it correctly passes a byte array for lpMultiByteStr
and an StrPtr
for lpWideCharStr
. This could have not happened with the current declaration of MultiByteToWideChar
.
EncodedStringByteArrayToString
中的代码所假定的声明为:
The declaration that is assumed by the code in EncodedStringByteArrayToString
is:
Declare PtrSafe Function MultiByteToWideChar Lib "kernel32" ( _
ByVal CodePage As Long, _
ByVal dwFlags As Long, _
ByVal lpMultiByteStr As LongPtr, _
ByVal cchMultiByte As Long, _
ByVal lpWideCharStr As LongPtr, _
ByVal cchWideChar As Long _
) As Long
显然你以前有过,所以就把它放回去.
Apparently you had that before, so just put it back.
这篇关于在64位办公室中调用MultiByteToWideChar()会产生错误的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!