在64位办公室中调用MultiByteToWideChar()会产生错误的结果 [英] Call to MultiByteToWideChar() in 64-bit office gives wrong result

查看:40
本文介绍了在64位办公室中调用MultiByteToWideChar()会产生错误的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个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 Declared 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆