読者です 読者をやめる 読者になる 読者になる

めいくりぷとのブログ

技術的なことやゲームのことやら・・・

WDDM Hook

DirectX C++

Windows Display Driver Model (WDDM) hook について適当に書きます。

前記事でOpenGL ICD hookについて書きましたが、ほとんど同じです。
今回も大雑把に説明します。


まずは、各ディスプレイドライバのエクスポート関数 "OpenAdapter" をフックしします。

NVIDIA GeForce => nvd3dum.dll
Radeon => aticfx32.dll
Intel Graphics => igdumd32.dll

OpenAdapterの第一引数の D3DDDIARG_OPENADAPTER 構造体から pOpenData->pAdapterFuncs->pfnCreateDevice のアドレスを取得し、そのアドレスを元に pfnCreateDevice をフックします。

pfnCreateDevice(HANDLE hDevice, D3DDDIARG_CREATEDEVICE *pDeviceData);

第二引数の D3DDDIARG_CREATEDEVICE 構造体の D3DDDI_DEVICEFUNS *pDeviceFuncs がvtableへのポインタになりますので、
pfnCreateDevice のフックコード内で取得し、vtable内の各関数をフックします。
以下にサンプルソースを貼っておきます。

BOOL Detour_CreateDevice()
{
    typedef HRESULT(APIENTRY *pfnCreateDevice)(
        __in HANDLE hAdapter,
        __inout D3DDDIARG_CREATEDEVICE *pDeviceData);
 
    static pfnCreateDevice _CreateDevice =
        reinterpret_cast<pfnCreateDevice>(D3DManager::GetInstance()->m_pfnCreateDevice);
    pfnCreateDevice CreateDevice_Hook = [](
        __in HANDLE hAdapter,
        __inout D3DDDIARG_CREATEDEVICE *pDeviceData) -> HRESULT
    {
        HRESULT hResult = _CreateDevice(hAdapter, pDeviceData);
 
        if (hResult == S_OK && pDeviceData->pDeviceFuncs)
        {
            DirectX *pDirectX = DirectX::GetInstance();
           
            if (!pDirectX->m_pDeviceFuncs)
            {
                pDirectX->Init(pDeviceData->pDeviceFuncs);
            }
        }
 
        return hResult;
    };
 
    return DetourFunction(TRUE, reinterpret_cast<LPVOID*>(&_CreateDevice), CreateDevice_Hook);
}
 
BOOL Detour_OpenAdapter()
{
    typedef HRESULT(APIENTRY *pfnOpenAdapter)(
        __inout D3DDDIARG_OPENADAPTER *pOpenData);
 
    static pfnOpenAdapter _OpenAdapter =
        reinterpret_cast<pfnOpenAdapter>(GetProcAddress(D3DManager::GetInstance()->GetDispDrv(), "OpenAdapter"));
    pfnOpenAdapter OpenAdapter_Hook = [](
        __inout D3DDDIARG_OPENADAPTER *pOpenData) -> HRESULT
    {
        HRESULT hResult = _OpenAdapter(pOpenData);
 
        if (hResult == S_OK && pOpenData->pAdapterFuncs->pfnCreateDevice)
        {
            D3DManager *pManager = D3DManager::GetInstance();
 
            if (!pManager->m_pfnCreateDevice)
            {
                pManager->m_pfnCreateDevice = pOpenData->pAdapterFuncs->pfnCreateDevice;
 
                if (pManager->m_pfnCreateDevice)
                {
                    Detour_CreateDevice();
                }
            }
        }
 
        return hResult;
    };
 
    return DetourFunction(TRUE, reinterpret_cast<LPVOID*>(&_OpenAdapter), OpenAdapter_Hook);
}


以上。