Opened 6 weeks ago

Closed 6 weeks ago

Last modified 3 weeks ago

#4046 closed Feature Request (Completed)

_WinAPI_MultiByteToWideChar - trailing junk characters in edge case. — at Version 4

Reported by: anonymous Owned by:
Milestone: Component: Standard UDFs
Version: Severity: None
Keywords: Cc:

Description (last modified by mLipok)

Hi folks, just a quick suggestion for an improvement to _WinAPI_MultiByteToWideChar.

I've found its currently possible to receive some junk characters at the end of the outputted string. This happens when the input text is a struct, is NOT null-terminated, and there is other data in memory after the string.

The proposed fix would be to explicitly pass the struct length when IsDllStruct($vText) = True (at the moment this param is hard coded to -1).

#include <WinAPIConv.au3>

Global Const $CP_UTF8 = 65001

;Simulated struct already that's already in memory
Local $dUtf8 = Binary("0x48656C6C6F576F726C6421")
Local $iUtf8Len =  BinaryLen($dUtf8)
Local $tSomeStruct = DllStructCreate("byte utf8[" & $iUtf8Len & "];byte other_stuff[4]")
$tSomeStruct.utf8 = $dUtf8
$tSomeStruct.other_stuff = Binary("0xFFFFFFFF")

Local $tUTF8 = DllStructCreate("byte[" & $iUtf8Len & "]", DllStructGetPtr($tSomeStruct))

Local $tWstr = _WinAPI_MultiByteToWideChar($tUTF8, $CP_UTF8)
ConsoleWrite("Current Result:"  & @CRLF)
ConsoleWrite(DllStructGetData($tWstr, 1) & @CRLF & @CRLF)

Local $tWstr = _WinAPI_MultiByteToWideChar_Modified($tUTF8, $CP_UTF8)
ConsoleWrite("Modified Result:"  & @CRLF)
ConsoleWrite(DllStructGetData($tWstr, 1) & @CRLF)

Func _WinAPI_MultiByteToWideChar_Modified($vText, $iCodePage = 0, $iFlags = 0, $bRetString = False)
        Local $sTextType = ""
        If IsString($vText) Then $sTextType = "str"
        If (IsDllStruct($vText) Or IsPtr($vText)) Then $sTextType = "struct*"
        If $sTextType = "" Then Return SetError(1, 0, 0) ; invalid input parameter type
        Local $iTextLen = IsDllStruct($vText) ? DllStructGetSize($vText) : -1  ;--- ADDED LINE ----

        ; compute size for the output WideChar
        Local $aCall = DllCall("kernel32.dll", "int", "MultiByteToWideChar", "uint", $iCodePage, "dword", $iFlags, _
                        $sTextType, $vText, "int", $iTextLen, "ptr", 0, "int", 0)
        If @error Or Not $aCall[0] Then Return SetError(@error + 10, @extended, 0)

        ; allocate space for output WideChar
        Local $iOut = $aCall[0]
        Local $tOut = DllStructCreate("wchar[" & $iOut & "]")

        $aCall = DllCall("kernel32.dll", "int", "MultiByteToWideChar", "uint", $iCodePage, "dword", $iFlags, $sTextType, $vText, _
                        "int", $iTextLen, "struct*", $tOut, "int", $iOut)
        If @error Or Not $aCall[0] Then Return SetError(@error + 20, @extended, 0)

        If $bRetString Then Return DllStructGetData($tOut, 1)
        Return $tOut
EndFunc

Output:

Current Result:
HelloWorld!????

Modified Result:
HelloWorld!

Change History (4)

comment:1 Changed 6 weeks ago by Jpm

  • Type changed from Bug to Feature Request

comment:2 Changed 6 weeks ago by TicketCleanup

  • Version 3.3.16.1 deleted

Automatic ticket cleanup.

comment:3 Changed 6 weeks ago by Jpm

  • Resolution set to Completed
  • Status changed from new to closed

comment:4 Changed 3 weeks ago by mLipok

  • Description modified (diff)
Note: See TracTickets for help on using tickets.