HeathHowren / CSGO-ImGui-DX9-Kiero-Hook

Using Kiero to Hook DirectX9 and draw with Dear ImGui
13 stars 10 forks source link

Proper way of unloading #10

Open HAWGT opened 2 years ago

HAWGT commented 2 years ago

I'm trying to make an unload routine, but unfortunately it freezes the game, here is what I'm trying:

DWORD WINAPI UnloadThread(LPVOID lpReserved)

{

    SetWindowLongPtr(window, GWL_WNDPROC, (LONG_PTR)WndProc);

    kiero::shutdown();

    Sleep(5000); //Maybe there are some hooks still being used

    FreeLibraryAndExitThread(module, 0);

    return TRUE;

}
HeathHowren commented 2 years ago

Please add breakpoints to see what line is causing the crash and let me know which one. From the looks of it the thread is closing properly. Not much I can do without access to full code.

Recommendations: make sure the module variable is not null move the code to the kiero::shutdown() func what is the reason for SetWindowLongPtr(... ...) func?

HAWGT commented 2 years ago

The crash happens when I call FreeLibraryAndExitThread, the module being null wouldn't make any sense since I'm setting it once the dll is attached as a global variable, the SetWindowLongPtr was me restoring the original value thinking it could be the cause, here is the code:

// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <cstdio>
#include "skCrypter.h"
#include "imgui_kiero_minhook_dx9.h"
#include "memory.h"
#include "offsets.h"

//---------------------------------------------------------------------------------------

EndScene oEndScene = NULL;
WNDPROC oWndProc;
static HWND window = NULL;

//---------------------------------------------------------------------------------------

extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

//---------------------------------------------------------------------------------------

long __stdcall hkEndScene(LPDIRECT3DDEVICE9 pDevice);
LRESULT __stdcall WndProc(const HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void InitImGui(LPDIRECT3DDEVICE9 pDevice);
HWND GetProcessWindow();
BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam);
void OpenDebugConsole();
void CloseDebugConsole();
DWORD WINAPI MainThread(LPVOID lpReserved);
long __stdcall hkEndScene(LPDIRECT3DDEVICE9 pDevice);
DWORD WINAPI UnloadThread(LPVOID lpReserved);

//---------------------------------------------------------------------------------------

LRESULT __stdcall WndProc(const HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {

    if (true && ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam))
        return true;

    return CallWindowProc(oWndProc, hWnd, uMsg, wParam, lParam);
}

//---------------------------------------------------------------------------------------

void InitImGui(LPDIRECT3DDEVICE9 pDevice)
{
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    io.ConfigFlags = ImGuiConfigFlags_NoMouseCursorChange;
    ImGui_ImplWin32_Init(window);
    ImGui_ImplDX9_Init(pDevice);
}

//---------------------------------------------------------------------------------------

HWND GetProcessWindow()
{
    window = NULL;
    EnumWindows(EnumWindowsCallback, NULL);
    return window;
}

BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam)
{
    DWORD wndProcId;
    GetWindowThreadProcessId(handle, &wndProcId);

    if (GetCurrentProcessId() != wndProcId)
        return TRUE; // skip to next window

    window = handle;
    return FALSE; // window found abort search
}

//---------------------------------------------------------------------------------------

HMODULE module;
FILE* f = nullptr;

void OpenDebugConsole()
{
    AllocConsole();
    freopen_s(&f, skCrypt("CONIN$"), skCrypt("r"), stdin);
    freopen_s(&f, skCrypt("CONOUT$"), skCrypt("w"), stdout);
    freopen_s(&f, skCrypt("CONOUT$"), skCrypt("w"), stderr);
    ShowWindow(GetConsoleWindow(), SW_SHOW);
}

void CloseDebugConsole()
{
    CloseWindow(GetConsoleWindow());
    fclose(f);
    FreeConsole();
    FreeLibraryAndExitThread(module, 0);
}

//---------------------------------------------------------------------------------------

bool init = false;
bool show = true;
static int fov = 90;
DWORD gameModule = NULL;

//---------------------------------------------------------------------------------------

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        module = hModule;
        DisableThreadLibraryCalls(hModule);
        //OpenDebugConsole();
        CreateThread(nullptr, 0, MainThread, module, 0, nullptr);
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        //CloseDebugConsole();
        kiero::shutdown();
        break;
    }
    return TRUE;
}

DWORD WINAPI MainThread(LPVOID lpReserved)
{
    bool attached = false;
    do
    {
        if (kiero::init(kiero::RenderType::D3D9) == kiero::Status::Success)
        {
            kiero::bind(42, (void**)&oEndScene, hkEndScene);
            do
                window = GetProcessWindow();
            while (window == NULL);
            oWndProc = (WNDPROC)SetWindowLongPtr(window, GWL_WNDPROC, (LONG_PTR)WndProc);
            attached = true;
        }
    } while (!attached);
    return TRUE;
}

long __stdcall hkEndScene(LPDIRECT3DDEVICE9 pDevice)
{

    //dwMouseEnable

    if (!init)
    {
       gameModule = (DWORD)GetModuleHandle("client.dll");
        InitImGui(pDevice);
        init = true;
    }

    if (GetAsyncKeyState(VK_DELETE)) {
        CreateThread(nullptr, 0, UnloadThread, module, 0, nullptr);
        //CloseDebugConsole();
        return 0;
    }

    if (GetAsyncKeyState(VK_INSERT) & 1)
    {
        show = !show;
    }

    if (show) {
        ImGui_ImplDX9_NewFrame();
        ImGui_ImplWin32_NewFrame();
        ImGui::NewFrame();

        ImGui::Begin("internal test");

        ImGui::SliderInt("FOV Changer", &fov, -180, 180);
        const auto LocalPlayer = RPM<uintptr_t>(gameModule + hazedumper::signatures::dwLocalPlayer);
        if (LocalPlayer)
            WPM<int>(LocalPlayer + hazedumper::netvars::m_iDefaultFOV, fov);

        if (ImGui::Button("Unload", ImVec2(100, 40)))
        {
            //CloseDebugConsole();
            CreateThread(nullptr, 0, UnloadThread, module, 0, nullptr);
        }

        ImGui::End();

        ImGui::EndFrame();
        ImGui::Render();
        ImGui_ImplDX9_RenderDrawData(ImGui::GetDrawData());
    }
    return oEndScene(pDevice);
}

DWORD WINAPI UnloadThread(LPVOID lpReserved)
{
    SetWindowLongPtr(window, GWL_WNDPROC, (LONG_PTR)WndProc);
    kiero::shutdown();
    Sleep(5000); //Maybe there are some hooks still being used
    FreeLibraryAndExitThread(module, 0);
    return TRUE;
}