C/C++ 使用API实现数据压缩与解压缩
在Windows编程中,经常会遇到需要对数据进行压缩和解压缩的情况,数据压缩是一种常见的优化手段,能够减小数据的存储空间并提高传输效率。Windows提供了这些API函数,本文将深入探讨使用Windows API进行数据压缩与解压缩的过程,主要使用ntdll.dll
库中的相关函数。
RtlGetCompressionWorkSpaceSize
RtlGetCompressionWorkSpaceSize 函数,位于ntdll.dll
库中。该函数用于获取数据压缩所需的工作空间大小。CompressionFormatAndEngine
参数指定压缩格式和引擎,CompressBufferWorkSpaceSize
和CompressFragmentWorkSpaceSize
分别用于输出缓冲区和片段的工作空间大小。
以下是该函数的声明:
typedef NTSTATUS(WINAPI *typedef_RtlGetCompressionWorkSpaceSize)(
_In_ USHORT CompressionFormatAndEngine,
_Out_ PULONG CompressBufferWorkSpaceSize,
_Out_ PULONG CompressFragmentWorkSpaceSize
);
该函数有以下参数:
- CompressionFormatAndEngine:指定压缩格式和引擎的参数。
- CompressBufferWorkSpaceSize:用于输出压缩缓冲区工作空间大小的指针。
- CompressFragmentWorkSpaceSize:用于输出压缩片段工作空间大小的指针。
函数返回NTSTATUS
类型的状态码,其中STATUS_SUCCESS
表示成功执行。
在使用这个函数时,你需要提供足够大的缓冲区来存储工作空间大小。可以按照以下步骤使用该函数:
- 加载 ntdll.dll 库。
- 获取 RtlGetCompressionWorkSpaceSize 函数地址。
- 定义变量用于存储工作空间大小。
- 调用 RtlGetCompressionWorkSpaceSize 函数,获取工作空间大小。
RtlCompressBuffer
RtlCompressBuffer 同样位于ntdll.dll
库中。该函数用于将数据进行压缩。CompressionFormatAndEngine
参数指定压缩格式和引擎,UncompressedBuffer
和UncompressedBufferSize
表示输入的未压缩数据,CompressedBuffer
和CompressedBufferSize
表示输出的压缩数据,UncompressedChunkSize
表示未压缩数据的块大小,FinalCompressedSize
表示最终压缩后的大小,WorkSpace
表示用于工作的缓冲区。
以下是该函数的声明:
typedef NTSTATUS(WINAPI *typedef_RtlCompressBuffer)(
_In_ USHORT CompressionFormatAndEngine,
_In_ PUCHAR UncompressedBuffer,
_In_ ULONG UncompressedBufferSize,
_Out_ PUCHAR CompressedBuffer,
_In_ ULONG CompressedBufferSize,
_In_ ULONG UncompressedChunkSize,
_Out_ PULONG FinalCompressedSize,
_In_ PVOID WorkSpace
);
该函数的参数包括:
- CompressionFormatAndEngine:指定压缩格式和引擎的参数。
- UncompressedBuffer:指向待压缩数据的指针。
- UncompressedBufferSize:待压缩数据的大小。
- CompressedBuffer:指向存储压缩数据的缓冲区的指针。
- CompressedBufferSize:存储压缩数据的缓冲区的大小。
- UncompressedChunkSize:未压缩的数据块的大小。
- FinalCompressedSize:用于输出最终压缩数据的大小的指针。
- WorkSpace:用于提供工作空间的指针。
函数返回NTSTATUS
类型的状态码,其中STATUS_SUCCESS
表示成功执行。
在使用这个函数时,你需要提供足够大的缓冲区来存储压缩后的数据。可以按照以下步骤使用该函数:
- 加载
ntdll.dll
库。 - 获取
RtlCompressBuffer
函数地址。 - 定义变量并分配内存用于存储未压缩的数据和压缩后的数据。
- 定义变量用于存储工作空间。
- 调用
RtlCompressBuffer
函数,将数据进行压缩。 - 处理压缩后的数据。
RtlDecompressBuffer
RtlDecompressBuffer 同样位于ntdll.dll
库中。该函数用于将压缩数据进行解压缩。CompressionFormat
参数指定压缩格式,UncompressedBuffer
和UncompressedBufferSize
表示输出的未压缩数据,CompressedBuffer
和CompressedBufferSize
表示输入的压缩数据,FinalUncompressedSize
表示最终解压缩后的大小。
以下是该函数的声明:
typedef NTSTATUS(WINAPI *typedef_RtlDecompressBuffer)(
_In_ USHORT CompressionFormat,
_Out_ PUCHAR UncompressedBuffer,
_In_ ULONG UncompressedBufferSize,
_In_ PUCHAR CompressedBuffer,
_In_ ULONG CompressedBufferSize,
_Out_ PULONG FinalUncompressedSize
);
该函数的参数包括:
- CompressionFormat:指定解压缩的格式。
- UncompressedBuffer:指向存储解压后数据的缓冲区的指针。
- UncompressedBufferSize:存储解压后数据的缓冲区的大小。
- CompressedBuffer:指向待解压数据的指针。
- CompressedBufferSize:待解压数据的大小。
- FinalUncompressedSize:用于输出最终解压后数据的大小的指针。
函数返回NTSTATUS
类型的状态码,其中STATUS_SUCCESS
表示成功执行。
在使用这个函数时,你需要提供足够大的缓冲区来存储解压后的数据。可以按照以下步骤使用该函数:
- 加载
ntdll.dll
库。 - 获取
RtlDecompressBuffer
函数地址。 - 定义变量并分配内存用于存储待解压的数据和解压后的数据。
- 调用
RtlDecompressBuffer
函数,将数据进行解压。 - 处理解压后的数据。
// 代码来源 《WINDOWS黑客编程技术详解》
// 作者:甘迪文
#include <Windows.h>
#include <iostream>
#include <windef.h>
typedef NTSTATUS(WINAPI *typedef_RtlGetCompressionWorkSpaceSize)(
_In_ USHORT CompressionFormatAndEngine,
_Out_ PULONG CompressBufferWorkSpaceSize,
_Out_ PULONG CompressFragmentWorkSpaceSize
);
typedef NTSTATUS(WINAPI *typedef_RtlCompressBuffer)(
_In_ USHORT CompressionFormatAndEngine,
_In_ PUCHAR UncompressedBuffer,
_In_ ULONG UncompressedBufferSize,
_Out_ PUCHAR CompressedBuffer,
_In_ ULONG CompressedBufferSize,
_In_ ULONG UncompressedChunkSize,
_Out_ PULONG FinalCompressedSize,
_In_ PVOID WorkSpace
);
typedef NTSTATUS(WINAPI *typedef_RtlDecompressBuffer)(
_In_ USHORT CompressionFormat,
_Out_ PUCHAR UncompressedBuffer,
_In_ ULONG UncompressedBufferSize,
_In_ PUCHAR CompressedBuffer,
_In_ ULONG CompressedBufferSize,
_Out_ PULONG FinalUncompressedSize
);
// 数据压缩
BOOL CompressData(BYTE *pUncompressData, DWORD dwUncompressDataLength, BYTE **ppCompressData, DWORD *pdwCompressDataLength)
{
BOOL bRet = FALSE;
NTSTATUS status = 0;
HMODULE hModule = NULL;
typedef_RtlGetCompressionWorkSpaceSize RtlGetCompressionWorkSpaceSize = NULL;
typedef_RtlCompressBuffer RtlCompressBuffer = NULL;
DWORD dwWorkSpaceSize = 0, dwFragmentWorkSpaceSize = 0;
BYTE *pWorkSpace = NULL;
BYTE *pCompressData = NULL;
DWORD dwCompressDataLength = 4096;
DWORD dwFinalCompressSize = 0;
do
{
// 加载 ntdll.dll
hModule = ::LoadLibrary("ntdll.dll");
if (NULL == hModule)
{
ShowError("LoadLibrary");
break;
}
// 获取 RtlGetCompressionWorkSpaceSize 函数地址
RtlGetCompressionWorkSpaceSize = (typedef_RtlGetCompressionWorkSpaceSize)::GetProcAddress(hModule, "RtlGetCompressionWorkSpaceSize");
if (NULL == RtlGetCompressionWorkSpaceSize)
{
ShowError("GetProcAddress");
break;
}
// 获取 RtlCompressBuffer 函数地址
RtlCompressBuffer = (typedef_RtlCompressBuffer)::GetProcAddress(hModule, "RtlCompressBuffer");
if (NULL == RtlCompressBuffer)
{
ShowError("GetProcAddress");
break;
}
// 获取WorkSpqce大小
status = RtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_STANDARD, &dwWorkSpaceSize, &dwFragmentWorkSpaceSize);
if (0 != status)
{
break;
}
// 申请动态内存
pWorkSpace = new BYTE[dwWorkSpaceSize];
if (NULL == pWorkSpace)
{
break;
}
::RtlZeroMemory(pWorkSpace, dwWorkSpaceSize);
while (TRUE)
{
// 申请动态内存
pCompressData = new BYTE[dwCompressDataLength];
if (NULL == pCompressData)
{
break;
}
::RtlZeroMemory(pCompressData, dwCompressDataLength);
// 调用RtlCompressBuffer压缩数据
RtlCompressBuffer(COMPRESSION_FORMAT_LZNT1, pUncompressData, dwUncompressDataLength, pCompressData, dwCompressDataLength, 4096, &dwFinalCompressSize, (PVOID)pWorkSpace);
if (dwCompressDataLength < dwFinalCompressSize)
{
// 释放内存
if (pCompressData)
{
delete[]pCompressData;
pCompressData = NULL;
}
dwCompressDataLength = dwFinalCompressSize;
}
else
{
break;
}
}
// 返回
*ppCompressData = pCompressData;
*pdwCompressDataLength = dwFinalCompressSize;
bRet = TRUE;
} while (FALSE);
// 释放
if (pWorkSpace)
{
delete[]pWorkSpace;
pWorkSpace = NULL;
}
if (hModule)
{
::FreeLibrary(hModule);
}
return bRet;
}
// 数据解压缩
BOOL UncompressData(BYTE *pCompressData, DWORD dwCompressDataLength, BYTE **ppUncompressData, DWORD *pdwUncompressDataLength)
{
BOOL bRet = FALSE;
HMODULE hModule = NULL;
typedef_RtlDecompressBuffer RtlDecompressBuffer = NULL;
BYTE *pUncompressData = NULL;
DWORD dwUncompressDataLength = 4096;
DWORD dwFinalUncompressSize = 0;
do
{
// 加载 ntdll.dll
hModule = ::LoadLibrary("ntdll.dll");
if (NULL == hModule)
{
break;
}
// 获取 RtlDecompressBuffer 函数地址
RtlDecompressBuffer = (typedef_RtlDecompressBuffer)::GetProcAddress(hModule, "RtlDecompressBuffer");
if (NULL == RtlDecompressBuffer)
{
break;
}
while (TRUE)
{
// 申请动态内存
pUncompressData = new BYTE[dwUncompressDataLength];
if (NULL == pUncompressData)
{
break;
}
::RtlZeroMemory(pUncompressData, dwUncompressDataLength);
// 调用RtlCompressBuffer压缩数据
RtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1, pUncompressData, dwUncompressDataLength, pCompressData, dwCompressDataLength, &dwFinalUncompressSize);
if (dwUncompressDataLength < dwFinalUncompressSize)
{
// 释放内存
if (pUncompressData)
{
delete[]pUncompressData;
pUncompressData = NULL;
}
dwUncompressDataLength = dwFinalUncompressSize;
}
else
{
break;
}
}
// 返回
*ppUncompressData = pUncompressData;
*pdwUncompressDataLength = dwFinalUncompressSize;
bRet = TRUE;
} while (FALSE);
// 释放
if (hModule)
{
::FreeLibrary(hModule);
}
return bRet;
}
int main(int argc, char *argv[])
{
DWORD i = 0;
BOOL bRet = FALSE;
char szBuffer[] = "DDDDDDDDDDGGGGGGGGGGGG";
DWORD dwBufferLength = ::lstrlen(szBuffer);
BYTE *pCompressData = NULL;
DWORD dwCompressDataLength = 0;
BYTE *pUncompressData = NULL;
DWORD dwUncompressDataLength = 0;
// 压缩数据
CompressData((BYTE *)szBuffer, dwBufferLength, &pCompressData, &dwCompressDataLength);
// 解压数据
UncompressData(pCompressData, dwCompressDataLength, &pUncompressData, &dwUncompressDataLength);
// 显示
printf("原数据为:\n");
for (i = 0; i < dwBufferLength; i++)
{
printf("%X ", szBuffer[i]);
}
printf("\n\n压缩数据为:\n");
for (i = 0; i < dwCompressDataLength; i++)
{
printf("%X ", pCompressData[i]);
}
printf("\n\n解压缩数据为:\n");
for (i = 0; i < dwUncompressDataLength; i++)
{
printf("%X ", pUncompressData[i]);
}
printf("\n");
// 释放
if (pUncompressData)
{
delete[]pUncompressData;
pUncompressData = NULL;
}
if (pCompressData)
{
delete[]pCompressData;
pCompressData = NULL;
}
system("pause");
return 0;
}
C/C++ 使用API实现数据压缩与解压缩的更多相关文章
- iOS/MAC 数据压缩与解压缩及常用算法 LZMA、ZLIB
苹果提供的常用的数据压缩算法LZMA.ZLIB.LZ4等: 这三种算法也是苹果建议的,可跨平台使用: 定义如下: /* Commonly-available encoders */ COMPRESSI ...
- 利用JAVA API函数实现数据的压缩与解压缩
综述 许多信息资料都或多或少的包含一些多余的数据.通常会导致在客户端与服务器之间,应用程序与计算机之间极大的数据传输量.最常见的解决数据存储和信息传送的方法是安装额外的存储设备和扩展现有的通讯能力 ...
- hadoop2.2编程: 数据压缩
本文主要讨论hadoop的数据压缩与解压缩代码的书写 Compressing and decompressing streams with CompressionCodec import org.ap ...
- JavaMail API 1.4.7邮件发送
下载oracle javaMail API: http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive- ...
- 【VC++技术杂谈008】使用zlib解压zip压缩文件
最近因为项目的需要,要对zip压缩文件进行批量解压.在网上查阅了相关的资料后,最终使用zlib开源库实现了该功能.本文将对zlib开源库进行简单介绍,并给出一个使用zlib开源库对zip压缩文件进行解 ...
- C/C++ 程序库
C/C++ 程序库 // --------------------------------------------- 来几个不常见但是很变态的库吧: bundle: 把几乎所有常见的压缩库封装成了一个 ...
- 转: 工作中用的C++库
转:https://www.mhftz.com/archives/42.html 个人学习C/C++的开源代码: 0.STL 1.osmium 2.leveldb 3.glog 4.redis 个人使 ...
- 网络基础 : OSI参考模型
Overview OSI规范的作用之一就是帮助在不同的主机之间传输数据. OSI模型包含7层,它们分为两组. 上面3层指定了终端中的应用程序如何彼此通信以及如何与用户交流: 下面4层指定了如何进行端到 ...
- Linux - 文件的压缩与归档
文件压缩 常用的压缩命令有 gzip.bzip2 等. gzip 命令 命令格式 gzip [ -acdfhlLnNrtvV19 ] [-S suffix] [ name ... ] 命令参数 -c ...
- c# 搭建服务端 byte[] 处理(3)
数据的传输中,为防止数据传输过程中被获取解析 造成数据的不安全,一般都会采取各类的方式对数据进行加密.压缩等操作,在客户端或服务端以相同的算法解析即可获得数据,一定程度上减小了数据在中间过程被获取数据 ...
随机推荐
- python 线程池 ThreadPoolExecutor
从Python3.2开始,标准库为我们提供了concurrent.futures 模块,它提供了 ThreadPoolExecutor (线程池)和 ProcessPoolExecutor (进程池) ...
- 接口文档 token发展史 jwt介绍和原理 drf-jwt快速使用
目录 昨日回顾 认证 权限 频率 全局异常处理 接口文档 接口文档编写 drf自动生成接口文档 cookies-session-token发展史 jwt介绍和原理 jwt的构成 base64的编码和解 ...
- WCF 使用动态代理精简代码架构 (WCF动态调用)
使用Castle.Core.dll实现,核心代码是使用Castle.DynamicProxy.ProxyGenerator类的CreateInterfaceProxyWithoutTarget方法动态 ...
- HDU 4027 Can you answer these queries?(线段树 区间不等更新)
https://vjudge.net/problem/HDU-4027#author=SUDA2019 题意 输入n个数 然后有两种操作 输入0时将给定区间所有数都变为自己的开方 输入1输出给定区间所 ...
- 入门篇-其之七-Java运算符(下)
一.三元运算符的使用 三元运算符(也称作三目运算符),使用:和?表示,其格式为:布尔表达式 ? 表达式1 : 表达式2 如果布尔表达式的计算结果是true,那么执行表达式1:否则,如果布尔表达式的计算 ...
- 深度 | 新兴软件研发范式崛起,云计算全面走向 Serverless 化
11月3日,2022 杭州 · 云栖大会上,阿里云智能总裁张建锋表示,以云为核心的新型计算体系正在形成,软件研发范式正在发生新的变革,Serverless 是其中最重要的趋势之一,阿里云将坚定推进核心 ...
- 6、SpringBoot-mybatis分页实现pagehelper
系列导航 springBoot项目打jar包 1.springboot工程新建(单模块) 2.springboot创建多模块工程 3.springboot连接数据库 4.SpringBoot连接数据库 ...
- 报错:for..in loops iterate over the entire prototype chain, which is virtually never what you want.
for..in loops iterate over the entire prototype chain, which is virtually never what you want. 意思是使用 ...
- Kubernetes security context capability
注:以下内容基于经验主义,不一定对. Linux capability Linux 中,root 作为特权用户,具有执行所有应用的能力.而普通用户只能执行普通应用.如果普通用户需要执行特权应用,需要进 ...
- 08-避免Latch的产生
1.Latch简介 Latch就是锁存器,是一种在异步电路系统中,对输入信号电平敏感的单元,用来存储信息 锁存器在数据未锁存时,输出端的信号随输入信号变化,就像信号通过一个缓冲器,一旦锁存信号有效,数 ...