数据压缩API

前言:

  为了实现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
");
        return bRet;
    }

    //获取函数地址
    RtlGetCompressionWorkSpaceSize = (typedef_RtlGetCompressionWorkSpaceSize)::GetProcAddress(hModule, "RtlGetCompressionWorkSpaceSize");
    if (NULL == RtlGetCompressionWorkSpaceSize)
    {
        m_Tip += _T("GetProcAddress Error
");
        FreeLibrary(hModule);
        return bRet;
    }

    RtlCompressBuffer = (typedef_RtlCompressBuffer)::GetProcAddress(hModule, "RtlCompressBuffer");
    if (NULL == RtlCompressBuffer)
    {
        m_Tip += _T("GetProcAddress Error
");
        FreeLibrary(hModule);
        return bRet;
    }

    //获取WorkSpace大小
    status = RtlGetCompressionWorkSpaceSize(COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE_STANDARD,
        &dwWorkSpaceSize, &dwFragmentWorkSpaceSize);
    if (0 != status)
    {
        m_Tip += _T("RtlGetCompressionWorkSpaceSize Error
");
        FreeLibrary(hModule);
        return bRet;
    }

    //申请动态内存
    pWorkSpace = new BYTE[dwWorkSpaceSize]{ 0 };
    if (pWorkSpace == NULL)
    {
        m_Tip += _T("new Error
");
        FreeLibrary(hModule);
        return bRet;
    }

    while (TRUE)
    {
        //申请动态内存存储压缩后的数据
        pCompressData = new BYTE[dwCompressDataLength];
        if (pCompressData == NULL)
        {
            m_Tip += _T("new Error
");
            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
");
        return bRet;
    }

    // 获取 RtlDecompressBuffer 函数地址
    RtlDecompressBuffer = (typedef_RtlDecompressBuffer)::GetProcAddress(hModule, "RtlDecompressBuffer");
    if (NULL == RtlDecompressBuffer)
    {
        m_Tip += _T("GetProcAddress Error
");
        FreeLibrary(hModule);
        return bRet;
    }

    while (TRUE)
    {
        // 申请动态内存
        pUncompressData = new BYTE[dwUncompressDataLength];
        if (NULL == pUncompressData)
        {
            m_Tip += _T("new Error
");
            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;
}
***********************************
原文地址:https://www.cnblogs.com/ndyxb/p/12910398.html