简述
在 Windows 环境下,使用 Windows API 可以进行文件的压缩和解压操作。这提供了一种有效的方式来
处理文件,减小存储空间,并在需要时快速解压。以下是一个使用 Windows API 进行压缩与解压的简单
示例,使用了 ntdll.dll 中的 RtlCompressBuffer 和 RtlDecompressBuffer 函数。
# include <iostream>
# include <windows.h>
using namespace std;
# 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;
ULONG fragWorkspaceSize;
NTSTATUS ret = RtlGetCompressionWorkSpaceSize (
COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_STANDARD,
& bufWorkspaceSize,
& fragWorkspaceSize
) ;
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,
( UCHAR* ) buffer,
bufferLen,
compBuffer,
compBufferLen,
4096 ,
compBufferSize,
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,
uncompBuffer,
uncompBufferLen,
( UCHAR* ) buffer,
bufferLen,
uncompBufferSize
) ;
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) ;
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 ;
}