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)
数据的传输中,为防止数据传输过程中被获取解析 造成数据的不安全,一般都会采取各类的方式对数据进行加密.压缩等操作,在客户端或服务端以相同的算法解析即可获得数据,一定程度上减小了数据在中间过程被获取数据 ...
随机推荐
- esp8266 水墨屏显示中文之大号字体
想要显示更大的字体,操作流程如下: 一.下载ESP8266文字显示相关库 链接: https://pan.baidu.com/s/1q9m0K2_egAmiMmD5IBfQ4Q 提取码: wtr2 二 ...
- Nginx--upstream健康检查
nginx 判断节点失效状态: Nginx 默认判断失败节点状态以connect refuse和time out状态为准,不以HTTP错误状态进行判断失败,因为HTTP只要能返回状态说明该节点还可以正 ...
- OJ中的语言选项里G++ 与 C++的区别
概念上: C++是一门计算机编程语言,而G++则是C++的编译器. GCC和G++都是GUN的编译器,cc是Unix系统的C Compiler,而gcc则是GNU Compiler Collectio ...
- HHKB Programming Contest 2020 补题记录(D题投影,E题预处理节省时间)
补题链接:Here A - Keyboard 签到,S 为 Y 则输出大写 T,不然则原样输出 T int main() { ios_base::sync_with_stdio(false), cin ...
- 一些 Codeforce Content 补题记录
Codeforces Round #651 (Div. 2) 1370A. Maximum GCD 给定一个 n,求(1~n)中任意组合对的最大的公约数. 思路:如果 \(n\) 是偶数,那么最大公约 ...
- OKR之剑·实战篇06:OKR致胜法宝-氛围&业绩双轮驱动(下)
作者:vivo 互联网平台产品研发团队 本文是<OKR 之剑>系列之实战第 6 篇-- 本文介绍团队营造氛围的方法与实践.在业绩方面的探索与输出,在两方面分别总结了一些经验分享给大家. 一 ...
- 阿里云蝉联 FaaS 领导者,产品能力获最高分
日前,权威咨询机构 Forrester 发布 The Forrester Wave: Functions-As-A-Service Platforms, Q2 2023.阿里云凭借函数计算的产品能力在 ...
- Shell 脚本编程学习
本文为博主原创,转载请注明出处: 目录: 1. shell 变量 2. 运算符 3. if 语句 4.for 循环 5.while 语句 6. case 语法 7.跳出循环:continue 与 br ...
- 基于Java 的商城网站系统设计与实现(8000字论文)
摘要 随着我国经济活力的不断提升和互联网的快速发展,信息的重要性正在显现出来.电子商务作为经济发展的重要一环取得了突飞猛进的发展.由于具有高效便捷的优点,网上购物已经成为一种不可或缺的新型生活方式,近 ...
- 【FreeRTOS】任务调度
启动调度器接口,主要是创建空闲任务和定时器任务以及执行特定架构的启动调度器接口 // FreeRTOS\Source\tasks.c void vTaskStartScheduler( void ) ...