Code:
Compress proc lpInputFile:DWORD,lpOutputFile:DWORD
LOCAL hModule:DWORD
LOCAL RtlGetCompressionWorkspaceSize:DWORD
LOCAL RtlCompressBuffer:DWORD
LOCAL hFile:DWORD
LOCAL dwInputFileSize:DWORD
LOCAL lpBufferSource:DWORD
LOCAL lpBufferDest:DWORD
LOCAL dwTemp:DWORD
LOCAL lpWorkspace:DWORD
LOCAL dwBytesTouched:DWORD
mov hModule,FUNC(GetModuleHandle,SADD("ntdll.dll"))
;Get the address to the functions needed to compress a file
mov RtlGetCompressionWorkspaceSize,FUNC(GetProcAddress,hModule,SADD("RtlGetCompressionWorkSpaceSize"))
mov RtlCompressBuffer,FUNC(GetProcAddress,hModule,SADD("RtlCompressBuffer"))
mov hFile,FUNC(CreateFile,lpInputFile,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ or FILE_SHARE_WRITE,0,OPEN_ALWAYS,0,0)
.IF hFile!=INVALID_HANDLE_VALUE
mov dwInputFileSize,FUNC(GetFileSize,hFile,0)
mov lpBufferSource,FUNC(VirtualAlloc,0,dwInputFileSize,MEM_COMMIT,PAGE_READWRITE)
mov lpBufferDest,FUNC(VirtualAlloc,0,dwInputFileSize,MEM_COMMIT,PAGE_READWRITE)
.IF lpBufferSource==0 || lpBufferDest==0
invoke VirtualFree,[lpBufferSource],0,MEM_RELEASE
invoke VirtualFree,[lpBufferDest],0,MEM_RELEASE
mov eax,FALSE
ret
.ENDIF
invoke ReadFile,hFile,lpBufferSource,dwInputFileSize,ADDR dwBytesTouched,0
.IF dwBytesTouched!=0
;Create the workspace
lea eax,dwBytesTouched
push eax
lea eax,dwTemp
push eax
push 2 ;LZCompression
call RtlGetCompressionWorkspaceSize
mov lpWorkspace,FUNC(VirtualAlloc,0,dwTemp,MEM_COMMIT,PAGE_READWRITE)
.IF lpWorkspace==0
ret
mov eax,FALSE
.ENDIF
mov dwTemp,0
;Compress the buffer
push lpWorkspace
lea eax,dwTemp
push eax
push dwInputFileSize
push dwInputFileSize
push lpBufferDest
push dwInputFileSize
push lpBufferSource
push 2 ;LZCompression w/ normal engine
call RtlCompressBuffer
.IF dwTemp!=0
;Write the compressed buffer to output file
mov hFile,FUNC(CreateFile,lpOutputFile,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0)
;Write the original file size at the front of the file
invoke WriteFile,hFile,ADDR dwInputFileSize,4,ADDR dwBytesTouched,0
invoke WriteFile,hFile,lpBufferDest,dwTemp,ADDR dwBytesTouched,0
invoke CloseHandle,hFile
.ENDIF
.ENDIF
invoke VirtualFree,[lpBufferSource],0,MEM_RELEASE
invoke VirtualFree,[lpBufferDest],0,MEM_RELEASE
invoke VirtualFree,[lpWorkspace],0,MEM_RELEASE
mov eax,TRUE
.ELSE
invoke CloseHandle,hFile
mov eax,FALSE
.ENDIF
ret
Compress endp
Decompress proc lpInputFile:DWORD,lpOutputFile:DWORD
LOCAL hModule:DWORD
LOCAL RtlDecompressBuffer:DWORD
LOCAL hFile:DWORD
LOCAL dwInputFileSize:DWORD
LOCAL hHeap:DWORD
LOCAL lpBufferSource:DWORD
LOCAL dwBytesTouched:DWORD
LOCAL lpBufferDest:DWORD
LOCAL dwTemp:DWORD
LOCAL dwOriginalSize:DWORD
mov hModule,FUNC(GetModuleHandle,SADD("ntdll.dll"))
;Get the address to the decompression function
mov RtlDecompressBuffer,FUNC(GetProcAddress,hModule,SADD("RtlDecompressBuffer"))
mov hFile,FUNC(CreateFile,lpInputFile,GENERIC_READ,0,0,OPEN_EXISTING,0,0)
.IF hFile!=INVALID_HANDLE_VALUE
mov dwInputFileSize,FUNC(GetFileSize,hFile,0)
mov hHeap,FUNC(GetProcessHeap)
;First 4 bytes are the orignal file size, get them
invoke ReadFile,hFile,ADDR dwOriginalSize,4,ADDR dwBytesTouched,0
sub dwInputFileSize,4
mov lpBufferSource,FUNC(HeapAlloc,hHeap,HEAP_ZERO_MEMORY,dwInputFileSize)
.IF lpBufferSource==0
invoke CloseHandle,hFile
mov eax,FALSE
ret
.ENDIF
mov dwBytesTouched,0
;Read the contents of the compressed file
invoke ReadFile,hFile,lpBufferSource,dwInputFileSize,ADDR dwBytesTouched,0
invoke CloseHandle,hFile
.IF dwBytesTouched!=0
mov lpBufferDest,FUNC(HeapAlloc,hHeap,HEAP_ZERO_MEMORY,dwOriginalSize)
.IF lpBufferDest==0
invoke HeapFree,hModule,0,lpBufferSource
mov eax,FALSE
ret
.ENDIF
;Decompress the buffer we just read
mov dwTemp,0
lea eax,dwTemp
push eax
push dwBytesTouched
push lpBufferSource
push dwOriginalSize
push lpBufferDest
push 2 ;LZCompression w/ normal engine
call RtlDecompressBuffer
.IF dwTemp!=0
;Write the decompressed buffer to output file
mov hFile,FUNC(CreateFile,lpOutputFile,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0)
invoke WriteFile,hFile,lpBufferDest,dwTemp,ADDR dwBytesTouched,0
invoke CloseHandle,hFile
.ENDIF
invoke HeapFree,hHeap,0,lpBufferDest
.ENDIF
invoke HeapFree,hHeap,0,lpBufferSource
mov eax,TRUE
.ELSE
invoke CloseHandle,hFile
mov eax,FALSE
.ENDIF
ret
Decompress endp
I am working on a way to do this with memory mapped files instead of creating a bunch of buffers and using async file io api, which should make it insanely faster. I will of course post if I do.