#include <iostream>
#include <Windows.h>
#include <fstream>
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
);
void get_ntstatus_err(NTSTATUS ntstatus)
{
switch (ntstatus) {
case STATUS_BUFFER_ALL_ZEROS:
std::cout << "Error: STATUS_BUFFER_ALL_ZEROS";
break;
case STATUS_INVALID_PARAMETER:
std::cout << "Error: STATUS_INVALID_PARAMETER";
break;
case STATUS_UNSUPPORTED_COMPRESSION:
std::cout << "Error: STATUS_UNSUPPORTED_COMPRESSION";
break;
case STATUS_NOT_SUPPORTED_ON_SBS:
std::cout << "Error: STATUS_NOT_SUPPORTED_ON_SBS";
break;
case STATUS_BUFFER_TOO_SMALL:
std::cout << "Error: STATUS_BUFFER_TOO_SMALL";
break;
case STATUS_BAD_COMPRESSION_BUFFER:
std::cout << "Error: STATUS_BAD_COMPRESSION_BUFFER";
break;
default:
std::cout << "(Unknown Error)";
}
std::endl(std::cout);
}
// ----------------------------------------------------------------------------------------------------
char *get_file_buffer(const char *filepath, int &buffer_len)
{
std::ifstream ifs(filepath, std::ofstream::binary);
if (!ifs.is_open()) return 0;
ifs.seekg(0, ifs.end);
buffer_len = ifs.tellg();
ifs.seekg(0, ifs.beg);
char *buffer = new char[buffer_len];
ifs.read(buffer, buffer_len);
return buffer;
}
// ----------------------------------------------------------------------------------------------------
int write_file_buffer(const char *filepath, char *buffer, int buffer_len)
{
std::ofstream ofs(filepath, std::ofstream::binary);
if (!ofs.is_open()) return 1;
ofs.write(buffer, buffer_len);
ofs.close();
return 0;
}
// ----------------------------------------------------------------------------------------------------
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) {
std::cout << "An error ocurred while trying to calculate the compression workspace size." << std::endl;
get_ntstatus_err(ret);
return 0;
}
std::cout << "Compression Workspace Size: 0x" << std::hex << bufWorkspaceSize
<< std::dec << " (" << bufWorkspaceSize << ")" << std::endl;
VOID *workspace = (VOID *)LocalAlloc(LMEM_FIXED, bufWorkspaceSize);
if (workspace == NULL) {
std::cout << "Failed to allocate space for workspace" << std::endl;
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) {
get_ntstatus_err(result);
return 0;
}
// std::cout << "Compressed DATA: " << compBuffer << std::endl;
std::cout << "Compressed Length: " << compBufferSize << std::endl;
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) {
get_ntstatus_err(result);
return 0;
}
// std::cout << "Uncompressed DATA: " << uncompBuffer << std::endl;
std::cout << "Uncompressed Length: " << uncompBufferSize << std::endl;
return uncompBuffer;
}
// ----------------------------------------------------------------------------------------------------
// #define COMPRESS
int main()
{
#ifdef COMPRESS
const char originalFile[] = "Z:\\ai.gif";
#endif
const char compressedFile[] = "Z:\\ai-compressed.gif";
#ifndef COMPRESS
const char decompressedFile[] = "Z:\\ai-decompressed.gif";
#endif
#ifdef COMPRESS
int bufferLen;
char *buffer = get_file_buffer(originalFile, bufferLen);
if (buffer == 0) {
std::cout << "An error ocurred while trying to read the bytes of the specified file into the buffer." << std::endl;
return 1;
}
ULONG realCompSize;
UCHAR *compressed_buffer = compress_buffer(buffer, bufferLen, bufferLen + 512, &realCompSize);
if (compressed_buffer == 0) return 1;
if (write_file_buffer(compressedFile, (char *)compressed_buffer, (int)realCompSize) != 0) {
std::cout << "An error ocurred while trying to write the bytes of the compressed buffer to a file." << std::endl;
return 1;
}
std::cout << compressed_buffer << std::endl;
#else
int bufferLen;
char *buffer = get_file_buffer(compressedFile, bufferLen);
if (buffer == 0) {
std::cout << "An error ocurred while trying to read the bytes of the specified file into the buffer." << std::endl;
return 1;
}
ULONG realDecompSize;
UCHAR *decompressed_buffer = decompress_buffer(buffer, bufferLen, bufferLen * 100, &realDecompSize);
if (decompressed_buffer == 0) return 1;
if (write_file_buffer(decompressedFile, (char *)decompressed_buffer, (int)realDecompSize) != 0) {
std::cout << "An error ocurred while trying to write the bytes of the compressed buffer to a file." << std::endl;
return 1;
}
#endif
return 0;
}