ImGui Window doesn’t show on DLL Injection

  c++, directx, directx-11, imgui
  • Current Goal: Trying to inject custom code into DirectX11 Games to display windows.
  • Expected Result: ImGui Demo Window should show up after injection but should not be interactable
  • Result Got: ImGui Demo Window doesn’t show up or display anything on injection.

Things I have tried: Making a custom Imgui window and reinjecting, debugging the code to make sure it’s being run and is called every frame, making sure nothing is NULL, searching up my problem on google, ImGui GitHub, stack overflow.

D3D11 Init (Called First thing after injection)

    LRESULT CALLBACK DXGIMsgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { return DefWindowProc(hwnd, uMsg, wParam, lParam); }
    DWORD __stdcall D3D11Init() {
        // Create Dummy Window
        WNDCLASSEXA wc = { sizeof(WNDCLASSEX), CS_CLASSDC, DXGIMsgProc, 0L, 0L, GetModuleHandleA(NULL), NULL, NULL, NULL, NULL, "DX", NULL };
        RegisterClassExA(&wc);
        HWND hWnd = CreateWindowA("DX", NULL, WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, wc.hInstance, NULL);

        D3D_FEATURE_LEVEL levels[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1 };
        D3D_FEATURE_LEVEL obtainedLevel;
        DXGI_SWAP_CHAIN_DESC sd;
        {
            ZeroMemory(&sd, sizeof(sd));
            sd.BufferCount = 1;
            sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
            sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
            sd.OutputWindow = hWnd;
            sd.Windowed = TRUE;
            sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
            sd.SampleDesc.Count = 1;
        }

        HRESULT hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, levels, sizeof(levels) / sizeof(D3D_FEATURE_LEVEL), D3D11_SDK_VERSION, &sd, &d3dSwapChain, &d3dDevice, &obtainedLevel, &d3dContext);
        if (FAILED(hr))
        {
            return E_FAIL;
        }

        pSwapChainVTable = (DWORD_PTR*)(d3dSwapChain);
        pSwapChainVTable = (DWORD_PTR*)(pSwapChainVTable[0]);

        pDeviceVTable = (DWORD_PTR*)(d3dDevice);
        pDeviceVTable = (DWORD_PTR*)pDeviceVTable[0];

        pDeviceContextVTable = (DWORD_PTR*)(d3dContext);
        pDeviceContextVTable = (DWORD_PTR*)(pDeviceContextVTable[0]);

        SAFE_RELEASE(d3dSwapChain);
        SAFE_RELEASE(d3dDevice);
        SAFE_RELEASE(d3dContext);
        UnregisterClassA(wc.lpszClassName, wc.hInstance);

        if (MH_Initialize() != MH_OK) { return 1; }
        if (MH_CreateHook((DWORD_PTR*)pSwapChainVTable[8], PresentHook, reinterpret_cast<void**>(&pHookD3D11Present)) != MH_OK) { return 1; }
        if (MH_EnableHook((DWORD_PTR*)pSwapChainVTable[8]) != MH_OK) { return 1; }

        DWORD old_protect;
        VirtualProtect(pHookD3D11Present, 2, PAGE_EXECUTE_READWRITE, &old_protect);
    }

PresentHook (Called everytime the game calls Present Function)

    HRESULT __stdcall PresentHook(IDXGISwapChain* pSwapChain, UINT SyncInterval, UINT Flags) {
        if(!init) {
            std::cout << "t[+] Present Hook called First Time!" << std::endl;
            if (FAILED(GetDeviceAndCtxFromSwapChain(pSwapChain, &d3dDevice, &d3dContext)))
                return pHookD3D11Present(pSwapChain, SyncInterval, Flags);

            // Get Game Window Handle
            DXGI_SWAP_CHAIN_DESC sd;
            pSwapChain->GetDesc(&sd);
            window = sd.OutputWindow;

            ImGui::CreateContext();
            ImGuiIO& io = ImGui::GetIO(); (void) io;
            io.IniFilename = NULL;
            io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
            io.DisplaySize = ImVec2(1280, 720);
            
            ImGui_ImplWin32_Init(window);
            ImGui_ImplDX11_Init(d3dDevice, d3dContext);
            init = true;
        };

        ImGui_ImplDX11_NewFrame();
        ImGui_ImplWin32_NewFrame();
        ImGui::NewFrame();
        ImGui::ShowDemoWindow();
        ImGui::EndFrame();
        ImGui::Render();
        ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
        return pHookD3D11Present(pSwapChain, SyncInterval, Flags);
    }

Source: Windows Questions C++

LEAVE A COMMENT