Generic AutoHotkey 32bit
27-Sep-2012
Usage example:
Data =
(
The Quick Brown Fox The Quick Brown Fox The Quick Brown Fox The Quick Brown Fox
The Quick Brown Fox The Quick Brown Fox The Quick Brown Fox The Quick Brown Fox
The Quick Brown Fox The Quick Brown Fox The Quick Brown Fox The Quick Brown Fox
The Quick Brown Fox The Quick Brown Fox The Quick Brown Fox The Quick Brown Fox
The Quick Brown Fox The Quick Brown Fox The Quick Brown Fox The Quick Brown Fox
)
DataSize := StrLen( Data ) * ( A_IsUnicode ? 2 : 1 )
CompressedDataSize := VarZ_Compress( Data, DataSize )
VarZ_Save( Data, CompressedDataSize, "tqbf.txt.lz_" )
VarZ_Load( Data, "tqbf.txt.lz_" )
VarZ_Decompress( Data )
MsgBox % "Orignal size:`t" DataSize "`n"
. "Compressed:`t" CompressedDataSize "`n`n"
. "[" Data "]"
Wrapper
[color=#225599]/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - __ __ ______ \ \ / / |___ / V A R Z >>> N A T I V E D A T A C O M P R E S S I O N \ \ / /_ _ _ __ / / http://www.autohotkey.com/community/viewtopic.php?t=45559 \ \/ / _` | '__/ / Author: Suresh Kumar A N (email: [email protected]) \ / (_| | | / /__ Ver 2.0 | Created 19-Jun-2009 | Last Modified 27-Sep-2012 \/ \__,_|_|/_____| > http://tinyurl.com/skanbox/AutoHotkey/VarZ/2.0/VarZ.ahk | - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */[/color] [color=#FF0000]VarZ_Compress([/color] ByRef Data, DataSize, CompressionMode = 0x102 [color=#FF0000])[/color] { Static STATUS_SUCCESS := 0x0, HdrSz := 18 If ( NumGet( Data ) = 0x005F5A4C ) ; "LZ_" + Chr(0) Return 0, ErrorLevel := -1 ; already compressed DllCall( "ntdll\RtlGetCompressionWorkSpaceSize" , UInt, CompressionMode , UIntP, CompressBufferWorkSpaceSize , UIntP, CompressFragmentWorkSpaceSize ) VarSetCapacity( CompressBufferWorkSpace, CompressBufferWorkSpaceSize ) TempSize := VarSetCapacity( TempData, DataSize ) ; Workspace for Compress NTSTATUS := DllCall( "ntdll\RtlCompressBuffer" , UInt, CompressionMode , UInt, &Data ; Uncompressed data , UInt, DataSize , UInt, &TempData ; Compressed data , UInt, TempSize , UInt, CompressFragmentWorkSpaceSize , UIntP, FinalCompressedSize ; Compressed data size , UInt, &CompressBufferWorkSpace , UInt ) If ( NTSTATUS <> STATUS_SUCCESS || FinalCompressedSize + HdrSz > DataSize ) Return 0, ErrorLevel := ( NTSTATUS ? NTSTATUS : -2 ) ; unable to compress data VarSetCapacity( Data, FinalCompressedSize + HdrSz, 0 ) ; Renew variable capacity NumPut( 0x005F5A4C, Data ) ; "LZ_" + Chr(0) Numput( CompressionMode, Data, 8 ) ; actually "UShort" NumPut( DataSize, Data, 10 ) ; Uncompressed data size NumPut( FinalCompressedSize, Data, 14 ) ; Compressed data size DllCall( "RtlMoveMemory", UInt, &Data + HdrSz ; Target pointer , UInt, &TempData ; Source pointer , UInt, FinalCompressedSize ) ; Data length in bytes DllCall( "shlwapi\HashData", UInt, &Data + 8 ; Read data pointer , UInt, FinalCompressedSize + 10 ; Read data size , UInt, &Data + 4 ; Write data pointer , UInt, 4 ) ; Write data length in bytes Return FinalCompressedSize + HdrSz } ;- -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- [color=#FF0000]VarZ_Decompress([/color] ByRef Data [color=#FF0000])[/color] { Static STATUS_SUCCESS := 0x0, HdrSz := 18 If ( NumGet( Data ) <> 0x005F5A4C ) ; "LZ_" + Chr(0) Return 0, ErrorLevel := -1 ; not natively compressed DataSize := NumGet( Data, 14 ) ; Compressed data size DllCall( "shlwapi\HashData", UInt, &Data + 8 ; Read data pointer , UInt, DataSize + 10 ; Read data size , UIntP, Hash ; Write data pointer , UInt, 4 ) ; Write data length in bytes If ( Hash <> NumGet( Data, 4 ) ) ; Hash vs Saved hash Return 0, ErrorLevel := -2 ; Hash failed = Data corrupt TempSize := NumGet( Data, 10 ) ; Decompressed data size VarSetCapacity( TempData, TempSize, 0 ) ; Workspace for Decompress NTSTATUS := DllCall( "ntdll\RtlDecompressBuffer" , UInt, NumGet( Data, 8, "UShort" ) ; Compression mode , UInt, &TempData ; Decompressed data , UInt, TempSize , UInt, &Data + HdrSz ; Compressed data , UInt, DataSize , UIntP, FinalUncompressedSize ; Decompressed data size , UInt ) If ( NTSTATUS <> STATUS_SUCCESS ) Return 0, ErrorLevel := NTSTATUS ; Unable to decompress data VarSetCapacity( Data, FinalUncompressedSize, 0 ) ; Renew variable capacity DllCall( "RtlMoveMemory", UInt, &Data ; Target pointer , UInt, &TempData ; Source pointer , UInt, FinalUncompressedSize ) ; Data length in bytes Return FinalUncompressedSize, VarSetCapacity( Data, -1 ) } ;- -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- [color=#FF0000]VarZ_Load([/color] ByRef Data, SrcFile [color=#FF0000])[/color] { FileGetSize, DataSize, %SrcFile% IfNotEqual, ErrorLevel, 0, Return FileRead, Data, *c %SrcFile% Return DataSize } ;- -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- [color=#FF0000]VarZ_Save([/color] ByRef Data, DataSize, TrgFile [color=#FF0000])[/color] { hFile := DllCall( "_lcreat", ( A_IsUnicode ? "AStr" : "Str" ),TrgFile, UInt,0 ) IfLess, hFile, 1, Return "", ErrorLevel := 1 nBytes := DllCall( "_lwrite", UInt,hFile, UInt,&Data, UInt,DataSize, UInt ) DllCall( "_lclose", UInt,hFile ) Return nBytes } ;- -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- - -- End of VarZ wrapper
Extra
[color=#FF0000]VarZ_Uncompress([/color] ByRef D [color=#FF0000])[/color] { [color=#008000]; Shortcode version of VarZ_Decompress() of VarZ 2.0 wrapper[/color] ; VarZ 2.0 by SKAN, 27-Sep-2012. http://www.autohotkey.com/community/viewtopic.php?t=45559 IfNotEqual, A_Tab, % ID:=NumGet(D), IfNotEqual, ID, 0x5F5A4C, Return 0, ErrorLevel := -1 savedHash := NumGet(D,4), TZ := NumGet(D,10), DZ := NumGet(D,14) DllCall( "shlwapi\HashData", UInt,&D+8, UInt,DZ+10, UIntP,Hash, UInt,4 ) IfNotEqual, Hash, %savedHash%, Return 0, ErrorLevel := -2 VarSetCapacity( TD,TZ,0 ), NTSTATUS := DllCall( "ntdll\RtlDecompressBuffer", UInt , NumGet(D,8,"UShort"), UInt, &TD, UInt,TZ, UInt,&D+18, UInt,DZ, UIntP,Final, UInt ) IfNotEqual, NTSTATUS, 0, Return 0, ErrorLevel := NTSTATUS VarSetCapacity( D,Final,0 ), DllCall( "RtlMoveMemory", UInt,&D, UInt,&TD, UInt,Final ) Return Final, VarSetCapacity( D,-1 ) }
Notes:
[*:37pxdbk4] When VarZ_Compress() fails, AHK errorlevel is set to either of the most probable NTSTATUS values
[*:37pxdbk4]0x00000117 - STATUS_BUFFER_ALL_ZEROS
The specified buffer contains all zeros.
[*:37pxdbk4]0xC0000023 - STATUS_BUFFER_TOO_SMALL
The buffer is too small to contain the entry. No information has been written to the buffer.
For simple understanding, the former error occurs when you pass an empty variable and the latter error will occur when compressed data is larger than the source. RtlCompressBuffer() will actually bloat the data, when you try to :
[*:37pxdbk4]Compress a short string
[*:37pxdbk4]Compress a string that has already been compressed with a better compression technology[/list][*:37pxdbk4]By default COMPRESSION_ENGINE_MAXIMUM ( 0x100 ) is enabled and is 5 times slower than the normal compression. To turn it off, pass 0x2 as the third parameter
like:
VarZ_Compress( Data, DataSize, 0x2 )
[*:37pxdbk4]Compressed data will be prefixed with an info header sized 18 bytes. If Compression was successful but Compressed Data+Header exceeds the size of Uncompressed Data, then VarZ_Compress() will ignore Compression and return 0
[*:37pxdbk4] MSDN Reference: RtlCompressBuffer, RtlDecompressBuffer, RtlGetCompressionWorkSpaceSize[/list][/list]
[*:37pxdbk4]Discussion on 'double compression' and an alternate version supporting double compression by HotKeyIt
[*:37pxdbk4]I have also written a small sized Win32 console utility, LZ_.exe v1.1 - 64KiB ( Source code ) which can toggle Compression & Decompression for a given file.