C/C++ 使用API实现数据压缩与解压缩

在Windows编程中,经常会遇到需要对数据进行压缩和解压缩的情况,数据压缩是一种常见的优化手段,能够减小数据的存储空间并提高传输效率。Windows提供了这些API函数,本文将深入探讨使用Windows API进行数据压缩与解压缩的过程,主要使用ntdll.dll库中的相关函数。

RtlGetCompressionWorkSpaceSize

RtlGetCompressionWorkSpaceSize 函数,位于ntdll.dll库中。该函数用于获取数据压缩所需的工作空间大小。CompressionFormatAndEngine参数指定压缩格式和引擎,CompressBufferWorkSpaceSizeCompressFragmentWorkSpaceSize分别用于输出缓冲区和片段的工作空间大小。

以下是该函数的声明:

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参数指定压缩格式和引擎,UncompressedBufferUncompressedBufferSize表示输入的未压缩数据,CompressedBufferCompressedBufferSize表示输出的压缩数据,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参数指定压缩格式,UncompressedBufferUncompressedBufferSize表示输出的未压缩数据,CompressedBufferCompressedBufferSize表示输入的压缩数据,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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/161353.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Rust日报】2023-11-21 如何将 Rust 的编译效率提高 75%

这是一篇来自 https://benw.is/posts/how-i-improved-my-rust-compile-times-by-seventy-five-percent 的总结和翻译&#xff0c;我去掉了一些不太重要的章节&#xff0c;保留了所有关键技术点。 Rust经常被提到的一个痛点是编译时间较慢。为了享受借用检查器、安全性和零成本抽…

pikachu靶场Table pikachu.member doesn’t exist:解决

背景&#xff1a; 第一次搭建pikachu靶场&#xff0c;搭建好后访问index.php后&#xff0c;尝试练习&#xff0c;发现界面显示Table pikachu.member doesn t exist&#xff0c;后来找了很多教程&#xff0c;没有解决&#xff0c;后来发现是自己没有进行初始化&#xff0c;给大家…

VMware 系列:ESXI6.7升级7.0

ESXI6.7升级7.0 一、下载补丁二、上传文件三 启用Shell四、登录Shell后台五、删除不兼容驱动六、正常升级最近,将一台使用ESXI6.7的虚拟机升级到了7.0版本,下面记录一下自己的升级过程。 升级条件 首先确保硬件是否能升级到7.0版本,物理网卡驱动为e1000e不能升级,如果是ig…

不到十个例题带你拿下c++双指针算法(leetcode)

移动零问题 https://leetcode.cn/problems/move-zeroes/submissions/ 1.题目解析 必须在原数组进行修改&#xff0c;不可以新建一个数组 非零元素相对顺序不变 2.算法原理 【数组划分】【数组分块】 这一类题会给我们一个数组&#xff0c;让我们划分区间&#xff0c;比如…

【机器学习】Nonlinear Independent Component Analysis - Aapo Hyvärinen

Linear independent component analysis (ICA) x i ( k ) ∑ j 1 n a i j s j ( k ) for all i 1 … n , k 1 … K ( ) x_i(k) \sum_{j1}^{n} a_{ij}s_j(k) \quad \text{for all } i 1 \ldots n, k 1 \ldots K \tag{} xi​(k)j1∑n​aij​sj​(k)for all i1…n,k1…K()…

VUE语法-$refs和ref属性的使用

1、$refs和ref属性的使用 1、$refs:一个包含 DOM 元素和组件实例的对象&#xff0c;通过模板引用注册。 2、ref实际上获取元素的DOM节点 3、如果需要在Vue中操作DOM我们可以通过ref和$refs这两个来实现 总结:$refs可以获取被ref属性修饰的元素的相关信息。 1.1、$refs和re…

PS_魔幻

首先打开一个背景图片 然后ctrl j复制一层背景 在调整中将图片改成黑白颜色 点击调整中的 色相/饱和度 调整明度 点击画笔工具&#xff0c;并且设置画笔模板 调节画笔大小&#xff0c;将笔记本电脑涂个概况 然后再新建色相/饱和度 勾选着色 调节背景颜色至喜欢 右键混合选项 …

04-React脚手架 集成Axios

初始化React脚手架 前期准备 1.脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目 1.包含了所有需要的配置&#xff08;语法检查、jsx编译、devServer…&#xff09;2.下载好了所有相关的依赖3.可以直接运行一个简单效果 2.react提供了一个用于创建react项目的脚手架库…

【华为OD机试python】分糖果【2023 B卷|100分】

【华为OD机试】-真题 !!点这里!! 【华为OD机试】真题考点分类 !!点这里 !! 题目描述 小明从糖果盒中随意抓一把糖果,每次小明会取出一半的糖果分给同学们。 当糖果不能平均分配时,小明可以选择从糖果盒中(假设盒中糖果足够) 取出一个糖果或放回一个糖果。 小明最少需要多…

【喵叔闲扯】---小谈静态类和单例模式

静态类&#xff08;Static Class&#xff09;和单例&#xff08;Singleton&#xff09;都是在编程中用于实现特定类型的设计模式或代码组织方式。它们在不同的情境下有不同的用途和特点。 静态类&#xff08;Static Class&#xff09; 静态类是一种类&#xff0c;它的方法和属性…

一键去水印免费网站快速无痕处理图片、视频水印

水印问题往往是一个大麻烦。即使我们只想将这些照片保留在我们的个人相册中以供怀旧&#xff0c;水印也可能像顽固的符号一样刺激我们的眼睛。为了解决这个问题&#xff0c;我们需要不断探索创新的解决方案&#xff0c;让我们深入研究一款强大的一键去水印免费网站“水印云”。…

Rust并发编程:理解线程与并发

大家好&#xff01;我是lincyang。 今天我们来深入探讨Rust中的并发编程&#xff0c;特别是线程的使用和并发的基本概念。 Rust中的线程 Rust使用线程来实现并发。线程是操作系统可以同时运行的最小指令集。在Rust中&#xff0c;创建线程非常简单&#xff0c;但与此同时&…

ubuntu 系统 怎么判断系统有没有GPU

在 Ubuntu 系统中&#xff0c;您可以通过几种方式来检查系统是否包含显卡&#xff0c;以及显卡的详细信息。以下是一些常用的方法&#xff1a; lspci 命令&#xff1a; 打开终端。输入 lspci | grep VGA 命令。这将显示系统中所有的 VGA 兼容设备&#xff0c;通常是您的显卡。 …

二叉搜索树java实现

顾名思义&#xff0c;二叉搜索树是一棵二叉树&#xff0c;每个节点就是一个对象&#xff0c;这个对象包含属性left、right和parent。left指向节点的左孩子&#xff0c;right指向节点的右孩子&#xff0c;parent指向节点的父节点&#xff08;双亲&#xff09;。如果某个孩子节点…

scala的类介绍

scala的类、抽象类、接口、对象 class :类&#xff0c; 通过new关键字来实例化&#xff0c;每次实例化都会创建一个新的对象&#xff1b;用来定义普通的类。object&#xff1a;对象&#xff0c;用来定义一个单例对象的&#xff0c;它只有一个实例&#xff0c;且在程序运行期间…

黑马点评笔记 redis实现缓存

文章目录 什么是缓存?为什么要使用缓存 如何使用缓存功能实现缓存模型和思路代码实现 缓存更新策略数据库缓存不一致解决方案代码实现 什么是缓存? 缓存(Cache),就是数据交换的缓冲区,俗称的缓存就是缓冲区内的数据,一般从数据库中获取,存储于本地代码(例如: 例1:Static fi…

vr小鼠虚拟解剖实验教学平台减少了受感染风险

家畜解剖实验教学是培养畜牧兽医专业学生实际操作能力的专业教学活动中的核心手段。采取新型教学方式与手段&#xff0c;合理设置实验教学内容&#xff0c;有助于激发学生的操作积极性&#xff0c;促进实践教学的改革。 家畜解剖VR仿真教学是一种借助VR虚拟现实制作和web3d开发…

常用通信接口、协议:SCCB

一、概述 SCCB(串行摄像头控制总线)是由欧姆尼图像技术公司&#xff08;OmniVision&#xff09;开发的一种类IIC的总线&#xff0c;主要用于其OV系列的图像传感器上&#xff08;但目前有很多家的图像传感器都有采用该控制总线&#xff09;。相对于IIC总线来说SCCB与之最主要的差…

java基础-集合

1、集合 在java中&#xff0c;集合&#xff08;Collection&#xff09;指的是一组数据容器&#xff0c;它可以存储多个对象&#xff0c;并且允许用户通过一些方法来访问与操作这些对象。j 集合的实现原理都基于数据结构和算法&#xff0c;如下&#xff1a; 数据结构&#xff1…

振南技术干货集:制冷设备大型IoT监测项目研发纪实(2)

注解目录 1.制冷设备的监测迫在眉睫 1.1 冷食的利润贡献 1.2 冷设监测系统的困难 &#xff08;制冷设备对于便利店为何如何重要&#xff1f;了解一下你所不知道的便利店和新零售行业。关于电力线载波通信的论战。&#xff09; 2、电路设计 2.1 防护电路 2.1.1 强电防护 …