Opened 6 weeks ago

Last modified 3 weeks ago

#4046 closed Feature Request

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

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

Description

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 (0)

Note: See TracTickets for help on using tickets.