Windows API压缩与解压

发布时间:2023年12月29日
简述
在 Windows 环境下,使用 Windows API 可以进行文件的压缩和解压操作。这提供了一种有效的方式来
处理文件,减小存储空间,并在需要时快速解压。以下是一个使用 Windows API 进行压缩与解压的简单
示例,使用了 ntdll.dll 中的 RtlCompressBuffer 和 RtlDecompressBuffer 函数。	
#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 = GetModuleHandleA("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_STANDARD, // 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_STANDARD, // 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_STANDARD, // CompressionFormat
        uncompBuffer,                                           // UncompressedBuffer
        uncompBufferLen,                                        // UncompressedBufferSize
        (UCHAR*)buffer,                                         // CompressedBuffer
        bufferLen,                                              // CompressedBufferSize
        uncompBufferSize                                        // FinalUncompressedSize
    );
 
    if (result != STATUS_SUCCESS) {
        ;
        return 0;
    }
 
 
    return uncompBuffer;
}
 
 
int main(void)
{
    char* path = (char*)"D:\\Utest\\TestDll.dll";//源文件
    char* NewPath = (char*)"D:\\Utest\\TestDllYY.dll";                // 压缩后
    char* DecompressPath = (char*)"D:\\Utest\\TestDllJJ.dll";// 解压
    DWORD bufferLen, numberBytesRead, compBufferSize, realDecompSize;
 
    char* data = ReadFileWs(path, bufferLen); 
    UCHAR* bufferComprimido = compress_buffer(data, bufferLen, bufferLen + 512, &compBufferSize);//necesitara ser liberado
    cout << "读取和压缩文件" << endl;
 
    WriteFileWs(NewPath, (char*)bufferComprimido, compBufferSize, numberBytesRead);
    cout << "在指定路径写入压缩后的文件" << endl;
 
    UCHAR* bufferDescomprimido = decompress_buffer((char*)bufferComprimido, bufferLen, compBufferSize * 100, &realDecompSize);
    WriteFileWs(DecompressPath, (char*)bufferDescomprimido, bufferLen, numberBytesRead);
    cout << "在指定路径写入解压后的文件 " << endl;
 
    delete[] data; 
    delete[] bufferComprimido;
    delete[] bufferDescomprimido;
 
 
 
    cin.get();
    return 0;
}
文章来源:https://blog.csdn.net/qq_18811919/article/details/131045146
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。