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.pswp.cn/news/161353.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/161353.shtml
英文地址,請注明出處:http://en.pswp.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 強電防護 …