Opened 10 hours ago
#4064 new Bug
_WinAPI_DecompressBuffer does not work for $COMPRESSION_FORMAT_XPRESS_HUFF
| Reported by: | andybiochem | Owned by: | |
|---|---|---|---|
| Milestone: | Component: | AutoIt | |
| Version: | 3.3.14.0 | Severity: | None |
| Keywords: | Cc: |
Description
Hi,
The _WinAPI_DecompressBuffer UDF does not work when using the $COMPRESSION_FORMAT_XPRESS_HUFF compression format.
_WinAPI_CompressBuffer works correctly to compress data with XPRESS_HUFF, but the Decompression UDF fails.
Reproducing script...
(this is the help file example script with the compression format specified as XPRESS_HUFF)
#include <WinAPIMem.au3> #include <WinAPISys.au3> ; Create compressed and uncompressed buffers Local $a_pBuffer[2] For $i = 0 To 1 $a_pBuffer[$i] = _WinAPI_CreateBuffer(1024) Next ; Compress binary data Local $dData = Binary('0x00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF') Local $iSize = BinaryLen($dData) DllStructSetData(DllStructCreate('byte[' & $iSize & ']', $a_pBuffer[0]), 1, $dData) $iSize = _WinAPI_CompressBuffer($a_pBuffer[0], $iSize, $a_pBuffer[1], 1024, BitOR($COMPRESSION_FORMAT_XPRESS_HUFF, $COMPRESSION_ENGINE_MAXIMUM)) If Not @error Then ConsoleWrite('Compressed: ' & DllStructGetData(DllStructCreate('byte[' & $iSize & ']', $a_pBuffer[1]), 1) & @CRLF) EndIf ; Decompress data $iSize = _WinAPI_DecompressBuffer($a_pBuffer[0], 1024, $a_pBuffer[1], $iSize, $COMPRESSION_FORMAT_XPRESS_HUFF) If Not @error Then ConsoleWrite('Uncompressed: ' & DllStructGetData(DllStructCreate('byte[' & $iSize & ']', $a_pBuffer[0]), 1) & @CRLF) EndIf ; Free memory For $i = 0 To 1 _WinAPI_FreeMemory($a_pBuffer[$i]) Next
The decompression fails due to the direct call on ntdll's RtlDecompressBuffer in WinAPISys.au3, and passing in $COMPRESSION_FORMAT_XPRESS_HUFF...
; #FUNCTION# ==================================================================================================================== ; Author.........: Yashied ; Modified.......: jpm ; =============================================================================================================================== Func _WinAPI_DecompressBuffer($pUncompressedBuffer, $iUncompressedSize, $pCompressedBuffer, $iCompressedSize, $iFormat = $COMPRESSION_FORMAT_LZNT1) Local $aCall = DllCall('ntdll.dll', 'long', 'RtlDecompressBuffer', 'ushort', $iFormat, 'struct*', $pUncompressedBuffer, _ 'ulong', $iUncompressedSize, 'struct*', $pCompressedBuffer, 'ulong', $iCompressedSize, 'ulong*', 0) If @error Then Return SetError(@error, @extended, 0) If $aCall[0] Then Return SetError(10, $aCall[0], 0) Return $aCall[6] EndFunc ;==>_WinAPI_DecompressBuffer
RtlDecompressBuffer does not support XPRESS_HUFF format. It looks like this came later in RtlDecompressBufferEx.
Working example of a RtlDecompressBufferEx UDF using XPRESS_HUFF...
(again, this is the help file example script updated)
#include <WinAPIMem.au3> #include <WinAPISys.au3> ; Create compressed and uncompressed buffers Local $a_pBuffer[2] For $i = 0 To 1 $a_pBuffer[$i] = _WinAPI_CreateBuffer(1024) Next ; Compress binary data Local $dData = Binary('0x00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF') $dData &= $dData ;XPRESS_HUFF looks to struggle with short data $dData &= $dData $dData &= $dData $dData &= $dData Local $iSize = BinaryLen($dData) DllStructSetData(DllStructCreate('byte[' & $iSize & ']', $a_pBuffer[0]), 1, $dData) $iSize = _WinAPI_CompressBuffer($a_pBuffer[0], $iSize, $a_pBuffer[1], 1024, BitOR($COMPRESSION_FORMAT_XPRESS_HUFF, $COMPRESSION_ENGINE_MAXIMUM)) If Not @error Then ConsoleWrite('Compressed: ' & DllStructGetData(DllStructCreate('byte[' & $iSize & ']', $a_pBuffer[1]), 1) & @CRLF) EndIf ; Decompress data $iSize = _WinAPI_DecompressBufferEx($a_pBuffer[0], 1024, $a_pBuffer[1], $iSize, BitOR($COMPRESSION_FORMAT_XPRESS_HUFF, $COMPRESSION_ENGINE_MAXIMUM)) If Not @error Then ConsoleWrite('Uncompressed: ' & DllStructGetData(DllStructCreate('byte[' & $iSize & ']', $a_pBuffer[0]), 1) & @CRLF) EndIf ; Free memory For $i = 0 To 1 _WinAPI_FreeMemory($a_pBuffer[$i]) Next Func _WinAPI_DecompressBufferEx($pUncompressedBuffer, $iUncompressedSize, $pCompressedBuffer, $iCompressedSize, $iFormat = 0x0002) Local $iSize_Workspace = DllCall('ntdll.dll', 'uint', 'RtlGetCompressionWorkSpaceSize', 'ushort', $iFormat, 'ulong*', 0, 'ulong*', 0)[2] ;get workspace size Local $tWorkSpace = DllStructCreate("byte["&$iSize_Workspace&"]") Local $pWorkSpace = DllStructGetPtr($tWorkSpace) Local $aCall = DllCall('ntdll.dll', 'long', 'RtlDecompressBufferEx', 'ushort', $iFormat, 'struct*', $pUncompressedBuffer, _ 'ulong', $iUncompressedSize, 'struct*', $pCompressedBuffer, 'ulong', $iCompressedSize, 'ulong*', 0,"ptr",$pWorkSpace) If @error Then Return SetError(@error, @extended, 0) If $aCall[0] Then Return SetError(10, $aCall[0], 0) Return $aCall[6] EndFunc ;==>_WinAPI_DecompressBuffer
Note that XPRESS_HUFF is very sensitive to short data, not sure why. Some reading suggests that the first 256 (?) bytes are reserved for the 'huff table' and so if data is so short it compresses to around 256 bytes, the compression fails with buffer errors.
In the working example above, I've had to pad out ($dData &= $dData) the input binary multiple times to a length that successfully compresses & uncompresses.
Best regards,
Andybiochem
Attachments (0)
Guidelines for posting comments:
- You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
- In-depth discussions should take place on the forum.
For more information see the full version of the ticket guidelines here.
