數據壓縮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\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;
}
***********************************

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM