Modify

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)

Change History (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.

Add Comment

Modify Ticket

Action
as new The ticket will remain with no owner.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.