前言:
为了实现windows上的数据压缩和解压缩,最方便的方法就是直接调用WIN32 API函数,windows系统的ntdll.dll专门提供了RtlCompressBuffer函数和RtlDecompressBuffer函数来负责数据压缩和解压缩操作,这两个函数并未公开,需要通过ntdll.dll来动态调用。
实现过程:
一、数据压缩:
(1).调用LoadLibrary函数加载ntdll.dll,获取ntdll.dll加载模块的句柄
(2).调用GetProcAddress函数获取RtlGetCompressionWorkSpaceSize函数与RtlCompressBuffer函数的地址
(3).调用RtlGetCompressionWorkSpaceSize函数来获取RtlCompressBuffer函数的工作空间缓冲区的大小(压缩格式和引擎类型设置为COMPRESSION_FORMAT_LZNT1和COMPRESSION_ENGINE_STANDARD)
(4).根据工作空间缓冲区的大小申请内存给压缩数据使用
(5).调用RtlCompressBuffer函数来压缩数据。数据压缩缓冲区的大小为4096字节
注意:需要将实际的压缩数据大小和数据压缩缓冲区的大小进行比较,如果数据压缩缓冲区太小,则需要释放原来的缓冲区,按照实际压缩数据的大小重新申请一个新的数据压缩缓冲区,并且重新压缩数据
二、数据解压缩
(1).调用LoadLibrary函数加载ntdll.dll,并获取ntdll.dll加载模块的句柄
(2).调用GetProcAddress函数来获取RtlDecompressBuffer函数
(3).申请一块内存,大小为4096字节,存放解压缩后的数据
(4).调用RtlDecompressBuffer函数来解压缩数据(压缩格式和引擎类型必须设置为COMPRESSION_FORMAT_LZNT1)
注意:需要将实际的解压数据大小和数据解压缓冲区的大小进行比较,如果数据解压缓冲区太小,则需要释放原来的缓冲区,按照实际解压数据的大小重新申请一个新的数据解压缓冲区,并且重新解压缩数据
实现代码:
//************************************ // 函数名:CCondenseDlg::DataCompress // 返回类型:BOOL // 功能: 数据压缩 // 参数1:BYTE* pUncompressData 未压缩的数据 // 参数2:DWORD dwUncompressDataLength 未压缩的数据的数据大小 // 参数3:BYTE** ppCompressData 压缩后的数据 // 参数4:DWORD* pdwCompressDataLength 压缩后的数据大小 //************************************ BOOL CCondenseDlg::DataCompress(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; DWORD dwFragmentWorkSpaceSize = 0; BYTE* pWorkSpace = NULL; BYTE* pCompressData = NULL; DWORD dwCompressDataLength = 4096; DWORD dwFinalCompressSize = 0; //加载ntdll.dll hModule = LoadLibrary(_T("ntdll.dll")); if (hModule == NULL) { m_Tip += _T("LoadLibrary Error\r\n"); return bRet; } //获取函数地址 RtlGetCompressionWorkSpaceSize = (typedef_RtlGetCompressionWorkSpaceSize)::GetProcAddress(hModule, "RtlGetCompressionWorkSpaceSize"); if (NULL == RtlGetCompressionWorkSpaceSize) { m_Tip += _T("GetProcAddress Error\r\n"); FreeLibrary(hModule); return bRet; } RtlCompressBuffer = (typedef_RtlCompressBuffer)::GetProcAddress(hModule, "RtlCompressBuffer"); if (NULL == RtlCompressBuffer) { m_Tip += _T("GetProcAddress Error\r\n"); FreeLibrary(hModule); return bRet; } //获取WorkSpace大小 status = RtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_STANDARD, &dwWorkSpaceSize, &dwFragmentWorkSpaceSize); if (0 != status) { m_Tip += _T("RtlGetCompressionWorkSpaceSize Error\r\n"); FreeLibrary(hModule); return bRet; } //申请动态内存 pWorkSpace = new BYTE[dwWorkSpaceSize]{ 0 }; if (pWorkSpace == NULL) { m_Tip += _T("new Error\r\n"); FreeLibrary(hModule); return bRet; } while (TRUE) { //申请动态内存存储压缩后的数据 pCompressData = new BYTE[dwCompressDataLength]; if (pCompressData == NULL) { m_Tip += _T("new Error\r\n"); delete[] pWorkSpace; FreeLibrary(hModule); return bRet; } //开始压缩数据 RtlCompressBuffer(COMPRESSION_FORMAT_LZNT1, pUncompressData, dwUncompressDataLength, (PUCHAR)pCompressData, dwCompressDataLength, 4096, &dwFinalCompressSize, (PVOID)pWorkSpace); //如果压缩数据的缓冲区小于最终的压缩大小 说明压缩失败 需要重新压缩 if (dwCompressDataLength < dwFinalCompressSize) { //释放内存 if (pCompressData) { delete[] pCompressData; } dwCompressDataLength = dwFinalCompressSize; } else { //否则说明压缩成功 退出循环 break; } } //返回压缩后的数据和长度 *ppCompressData = pCompressData; *pdwCompressDataLength = dwFinalCompressSize; bRet = TRUE; //释放资源 if (pWorkSpace) { delete[] pWorkSpace; } if (hModule) { FreeLibrary(hModule); } return bRet; }
//************************************ // 函数名:CCondenseDlg::UncompressData // 返回类型:BOOL // 功能: 数据解压缩 // 参数1:BYTE *pCompressData 压缩的数据 // 参数2:DWORD dwCompressDataLength 压缩的数据大小 // 参数3:BYTE **ppUncompressData 解压缩的数据 // 参数4:DWORD *pdwUncompressDataLength 解压缩的数据大小 //*BOOL CCondenseDlg::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; // 加载 ntdll.dll hModule = ::LoadLibrary(_T("ntdll.dll")); if (NULL == hModule) { m_Tip += _T("LoadLibrary Error\r\n"); return bRet; } // 获取 RtlDecompressBuffer 函数地址 RtlDecompressBuffer = (typedef_RtlDecompressBuffer)::GetProcAddress(hModule, "RtlDecompressBuffer"); if (NULL == RtlDecompressBuffer) { m_Tip += _T("GetProcAddress Error\r\n"); FreeLibrary(hModule); return bRet; } while (TRUE) { // 申请动态内存 pUncompressData = new BYTE[dwUncompressDataLength]; if (NULL == pUncompressData) { m_Tip += _T("new Error\r\n"); FreeLibrary(hModule); return bRet; } ::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; //释放资源 if (hModule) { ::FreeLibrary(hModule); } return bRet; } ***********************************