// deLZ.cpp
#include <iostream>
#include <windows.h>
using namespace std;
//typedef unsigned long NTSTATUS;
#define STATUS_SUCCESS ((NTSTATUS)0x00000000UL)
#define STATUS_BUFFER_ALL_ZEROS ((NTSTATUS)0x00000117UL)
#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DUL)
#define STATUS_UNSUPPORTED_COMPRESSION ((NTSTATUS)0xC000025FUL)
#define STATUS_NOT_SUPPORTED_ON_SBS ((NTSTATUS)0xC0000300UL)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023UL)
#define STATUS_BAD_COMPRESSION_BUFFER ((NTSTATUS)0xC0000242UL)
HMODULE ntdll = GetModuleHandle("ntdll.dll");
typedef NTSTATUS(__stdcall *_RtlCompressBuffer)(
USHORT CompressionFormatAndEngine,
PUCHAR UncompressedBuffer,
ULONG UncompressedBufferSize,
PUCHAR CompressedBuffer,
ULONG CompressedBufferSize,
ULONG UncompressedChunkSize,
PULONG FinalCompressedSize,
PVOID WorkSpace
);
typedef NTSTATUS(__stdcall *_RtlDecompressBuffer)(
USHORT CompressionFormat,
PUCHAR UncompressedBuffer,
ULONG UncompressedBufferSize,
PUCHAR CompressedBuffer,
ULONG CompressedBufferSize,
PULONG FinalUncompressedSize
);
typedef NTSTATUS(__stdcall *_RtlGetCompressionWorkSpaceSize)(
USHORT CompressionFormatAndEngine,
PULONG CompressBufferWorkSpaceSize,
PULONG CompressFragmentWorkSpaceSize
);
char *ReadFileWs(const char *FilePath,DWORD &bufferLen){
HANDLE File=CreateFileA(FilePath,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
if(File==INVALID_HANDLE_VALUE){
return NULL;
}
DWORD _size=GetFileSize(File,0);
char *Buffer=new char[_size+1];
bool result=ReadFile(File,Buffer,_size,&bufferLen,0);
CloseHandle(File);
if(result)return Buffer;
else return NULL;
}
bool WriteFileWs(const char *FilePath,char *Buffer,DWORD bufferLen,DWORD &numberBytesRead){
HANDLE File=CreateFileA(FilePath,GENERIC_WRITE,FILE_SHARE_WRITE,0,CREATE_ALWAYS,0,0);
if(File==INVALID_HANDLE_VALUE){
return false;
}
bool result=WriteFile(File,Buffer,bufferLen,&numberBytesRead,NULL);
CloseHandle(File);
return result;
}
UCHAR *compress_buffer(const char *buffer, const ULONG bufferLen, ULONG compBufferLen, ULONG *compBufferSize)
{
_RtlCompressBuffer RtlCompressBuffer = (_RtlCompressBuffer) GetProcAddress(ntdll, "RtlCompressBuffer");
_RtlGetCompressionWorkSpaceSize RtlGetCompressionWorkSpaceSize = (_RtlGetCompressionWorkSpaceSize) GetProcAddress(ntdll, "RtlGetCompressionWorkSpaceSize");
ULONG bufWorkspaceSize; // Workspace Size
ULONG fragWorkspaceSize; // Fragmented Workspace Size (Unused)
NTSTATUS ret = RtlGetCompressionWorkSpaceSize(
COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM, // CompressionFormatAndEngine
&bufWorkspaceSize, // CompressBufferWorkSpaceSize
&fragWorkspaceSize // CompressFragmentWorkSpaceSize
);
if (ret != STATUS_SUCCESS) return 0;
VOID *workspace = (VOID *)LocalAlloc(LMEM_FIXED, bufWorkspaceSize);
if (workspace == NULL) return 0;
UCHAR *compBuffer = new UCHAR[compBufferLen];
NTSTATUS result = RtlCompressBuffer(
COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM, // CompressionFormatAndEngine
(UCHAR *)buffer, // UncompressedBuffer
bufferLen, // UncompressedBufferSize
compBuffer, // CompressedBuffer
compBufferLen, // CompressedBufferSize
4096, // UncompressedChunkSize
compBufferSize, // FinalCompressedSize
workspace // WorkSpace
);
LocalFree(workspace);
if (result != STATUS_SUCCESS) {
return 0;
}
return compBuffer;
}
UCHAR *decompress_buffer(const char *buffer, const int bufferLen, const int uncompBufferLen, ULONG *uncompBufferSize)
{
_RtlDecompressBuffer RtlDecompressBuffer = (_RtlDecompressBuffer) GetProcAddress(ntdll, "RtlDecompressBuffer");
UCHAR *uncompBuffer = new UCHAR[uncompBufferLen];
NTSTATUS result = RtlDecompressBuffer(
COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_MAXIMUM, // CompressionFormat
uncompBuffer, // UncompressedBuffer
uncompBufferLen, // UncompressedBufferSize
(UCHAR *)buffer, // CompressedBuffer
bufferLen, // CompressedBufferSize
uncompBufferSize // FinalUncompressedSize
);
if (result != STATUS_SUCCESS) {
printf("result: %x\n", result);
return 0;
}
return uncompBuffer;
}
int main(int argc, char *argv[])
{
if (argc != 3) {
cout << "lose input path and output path" << endl;
return 1;
}
char *compressDataPath = argv[1];
char *DecompressStorePath = argv[2];
DWORD bufferLen, numberBytesRead, realDecompSize;
char *data = ReadFileWs(compressDataPath, bufferLen);
cout << compressDataPath << " Length: " << bufferLen << endl;
UCHAR *bufferDescomprimido = decompress_buffer(data, bufferLen, 4096 * 5000, &realDecompSize);
WriteFileWs(DecompressStorePath, (char*)bufferDescomprimido, realDecompSize, numberBytesRead);
cout << DecompressStorePath << " Length: " << numberBytesRead << endl;
cout << "Success" << endl;
delete[] data;
delete[] bufferDescomprimido;
return 0;
}