Pour référence ultérieure ici, je poste ce script qui met en lumière les erreurs de conversion entre jeux de caractères OEM et ANSI ou Unicode (chaînes AutoIt) produites par la fonction OemToChar (W ou A).
Unicode impératif au niveau du source ET de la console Scite, sinon on n'y comprend plus rien !
Je cross-poste dans le post d'exemple. Euh, non, je ne retrouve pas le post qui était de notre Tlem je crois...
Code : Tout sélectionner
Func _OemToStr($sOEM, $iCodepage = Default)
If $iCodepage = Default Then $iCodepage = Int(RegRead("HKLM\SYSTEM\CurrentControlSet\Control\Nls\Codepage", "OEMCP"))
Local $tText = DllStructCreate("byte[" & StringLen($sOEM) & "]")
DllStructSetData($tText, 1, $sOEM)
$aResult = DllCall("kernel32.dll", "int", "MultiByteToWideChar", "uint", $iCodepage, "dword", 0, "struct*", $tText, "int", StringLen($sOEM), _
"ptr", 0, "int", 0)
Local $tWstr = DllStructCreate("wchar[" & $aResult[0] & "]")
$aResult = DllCall("kernel32.dll", "int", "MultiByteToWideChar", "uint", $iCodepage, "dword", 0, "struct*", $tText, "int", StringLen($sOEM), _
"struct*", $tWstr, "int", $aResult[0])
Return DllStructGetData($tWstr, 1)
EndFunc ;==>_OemToStr
Func _StrToOem($sStr, $iCodepage = Default)
If $iCodepage = Default Then $iCodepage = Int(RegRead("HKLM\SYSTEM\CurrentControlSet\Control\Nls\Codepage", "OEMCP"))
$aResult = DllCall("kernel32.dll", "int", "WideCharToMultiByte", "uint", $iCodepage, "dword", 0, "wstr", $sStr, "int", StringLen($sStr), _
"ptr", 0, "int", 0, "ptr", 0, "ptr", 0)
Local $tOem = DllStructCreate("byte[" & $aResult[0] & "]")
$aResult = DllCall("Kernel32.dll", "int", "WideCharToMultiByte", "uint", $iCodepage, "dword", 0, "wstr", $sStr, "int", StringLen($sStr), _
"struct*", $tOem, "int", $aResult[0], "ptr", 0, "ptr", 0)
Return DllStructGetData($tOem, 1)
EndFunc ;==>_StrToOem
Func _OemToCharW($sOEM)
Local $aStr = DllCall('user32.dll', 'Int', 'OemToCharW', 'str', $sOEM, 'wstr', '')
If Not @error Then Return $aStr[2]
EndFunc ;==>_OemToCharW
Func _OemToCharA($sOEM)
Local $aAnsi = DllCall('user32.dll', 'Int', 'OemToCharA', 'str', $sOEM, 'str', '')
If Not @error Then Return $aAnsi[2]
EndFunc ;==>_OemToCharA
; Unicode-aware ConsoleWrite
Func __ConsoleWrite($s)
ConsoleWrite(BinaryToString(StringToBinary($s, 4), 1))
EndFunc ;==>__ConsoleWrite
ConsoleWrite("Diff Oem _OemStr _OemToCharW _OemToCharA" & @LF)
_ConsoleWrite("━━━━ ━━━━━━━━ ━━━━━━━━━━ ━━━━━━━━━━━ ━━━━━━━━━━━" & @LF)
Local $a, $c, $w, $s
For $i = 0x01 To 0xFF
$c = Chr($i)
$a = _OemToCharA($c)
$w = _OemToCharW($c)
$s = _OemToStr($c)
_ConsoleWrite(' ' & ($w <> $s ? "W" : " ") & ($a <> $s ? "A" : " ") & _
" 0x" & Hex($i, 2) & " " & _
((AscW($c) < 0x20 Or AscW($c) = 0x7F Or AscW($c) = 0xF0) ? "CTRL" : "‷" & $s & "‴ ") & _
" 0x" & Hex(AscW($s), 4) & " " & _
((AscW($s) < 0x20 Or (AscW($s) > 0x7E And AscW($s) < 0x90) Or AscW($s) = 0xAD) ? "CTRL" : "‷" & $s & "‴ ") & _
" 0x" & Hex(AscW($w), 4) & " " & _
((AscW($w) < 0x20 Or (AscW($w) > 0x7E And AscW($w) < 0x90) Or AscW($w) = 0xAD) ? "CTRL" : "‷" & $w & "‴ ") & _
" 0x" & Hex(AscW($a), 2) & " " & _
((Asc($a) < 0x20 Or Asc($a) = 0x7F Or Asc($a) = 0xAD) ? "CTRL" : "‷" & $a & "‴") & @LF)
Next
Dans la colonne Diff de différences, un W signifie que le code obtenu par OemToCharW ne correspond pas à la conversion correcte entre OEM et Unicode, un A signifie que le code ANSI produit est distinct du code Unicode correct (ce qui n'est pas surprenant pour certains caractères OEM qui n'ont pas d'équivalence ANSI).
Outre les caractères de bordure de tableau, simples, doubles ou mixtes, on voit que le gros problème réside dans une conversion fantaisiste des caractères de contrôle, qui perdent alors tout leur sens.
La morale est de n'utiliser que des fonctions basées sur MultiByteToWideChar et WideCharToMultiByte et de ne surtout pas utiliser OemToChar(A ou W).
Edit : légères améliorations
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.