From 9b178146c45a1b459ab6225194125f0187c219e4 Mon Sep 17 00:00:00 2001 From: Nemirtingas Date: Mon, 26 Aug 2019 19:36:07 +0200 Subject: [PATCH] Cleaned a bit hooks and added sanity checks. --- generate_game_infos/generate_game_infos.cpp | 241 +++++++++++++++ generate_items_infos/generate_items_infos.cpp | 157 ++++++++++ overlay_experimental/DX10_Hook.cpp | 13 +- overlay_experimental/DX10_Hook.h | 2 +- overlay_experimental/DX11_Hook.cpp | 13 +- overlay_experimental/DX11_Hook.h | 2 +- overlay_experimental/DX12_Hook.cpp | 24 +- overlay_experimental/DX12_Hook.h | 2 +- overlay_experimental/Hook_Manager.cpp | 276 +++++++++++------- overlay_experimental/Hook_Manager.h | 2 +- overlay_experimental/steam_overlay.cpp | 12 + overlay_experimental/steam_overlay.h | 3 +- 12 files changed, 600 insertions(+), 147 deletions(-) create mode 100644 generate_game_infos/generate_game_infos.cpp create mode 100644 generate_items_infos/generate_items_infos.cpp diff --git a/generate_game_infos/generate_game_infos.cpp b/generate_game_infos/generate_game_infos.cpp new file mode 100644 index 0000000..2b74a3f --- /dev/null +++ b/generate_game_infos/generate_game_infos.cpp @@ -0,0 +1,241 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +class CurlGlobal +{ + bool _init; + + CurlGlobal() :_init(false) {} + + ~CurlGlobal() { cleanup(); } + +public: + static CurlGlobal& Inst() + { + static CurlGlobal _this; + return _this; + } + + CURLcode init(long flags = CURL_GLOBAL_DEFAULT) { return curl_global_init(flags); } + void cleanup() + { + if (_init) + { + curl_global_cleanup(); + _init = false; + } + } +}; + +class CurlEasy +{ + CURL* _me; + bool _init; + std::string _buffer; + + static int writer(char* data, size_t size, size_t nmemb, + CurlEasy* _this) + { + if (_this == nullptr) + return 0; + + _this->_buffer.append(data, size * nmemb); + + return size * nmemb; + } + +public: + CurlEasy() :_me(nullptr), _init(false) {} + ~CurlEasy() { cleanup(); } + + bool init() + { + _init = (_me = curl_easy_init()) != nullptr; + if (_init) + { + if (curl_easy_setopt(_me, CURLOPT_WRITEFUNCTION, writer) != CURLE_OK) + { + cleanup(); + return false; + } + + if (curl_easy_setopt(_me, CURLOPT_WRITEDATA, this) != CURLE_OK) + { + cleanup(); + return false; + } + } + return _init; + } + + void cleanup() + { + if (_init) + { + curl_easy_cleanup(_me); + } + } + + CURLcode set_url(const std::string& url) + { + return curl_easy_setopt(_me, CURLOPT_URL, url.c_str()); + } + + CURLcode skip_verifypeer(bool skip = true) + { + return curl_easy_setopt(_me, CURLOPT_SSL_VERIFYPEER, skip ? 0L : 1L); + } + + CURLcode skip_verifhost(bool skip = true) + { + return curl_easy_setopt(_me, CURLOPT_SSL_VERIFYHOST, skip ? 0L : 1L); + } + + CURLcode connect_only(bool connect = true) + { + return curl_easy_setopt(_me, CURLOPT_CONNECT_ONLY, connect ? 1L : 0L); + } + + CURLcode perform() + { + _buffer.clear(); + return curl_easy_perform(_me); + } + + CURLcode recv(void* buffer, size_t buflen, size_t* read_len) + { + return curl_easy_recv(_me, buffer, buflen, read_len); + } + + CURLcode get_html_code(long& code) + { + return curl_easy_getinfo(_me, CURLINFO_RESPONSE_CODE, &code); + } + + std::string const& get_answer() const { return _buffer; } +}; + +// Get all steam appid with their name: http://api.steampowered.com/ISteamApps/GetAppList/v2/ +// Steam storefront webapi: https://wiki.teamfortress.com/wiki/User:RJackson/StorefrontAPI +// http://api.steampowered.com/ISteamUserStats/GetSchemaForGame/v2/?key=&appid= +/* +{ + "game" : { + "gameName" : "", + "availableGameStats" : { + "achievements" : { + ("" : { + "name" : "achievement_name", + "displayName" : "achievement name on screen", + "hidden" : (0|1), + ["description" : "",] + "icon" : "", + "icongray" : "" + }, + ...) + } + } + } +} +*/ +// Get appid infos: http://store.steampowered.com/api/appdetails/?appids=218620 +/* +"appid" : { + "success" : (true|false), + (success == true "data" : { + ... + "name" : "", + "steam_appid" : , + (OPT "dlc" : [, ]), + "header_image" : "" <-- Use this in the overlay ? + (OPT "achievements" : { + "total" : + }), + "background" : "" <-- Use this as the overlay background ? + (OPT "packages" : [, ]) + }) +} +*/ + +#ifdef max +#undef max +#endif +//232090 +int main() +{ + CurlGlobal& cglobal = CurlGlobal::Inst(); + cglobal.init(); + + CurlEasy easy; + if (easy.init()) + { + std::string url; + std::string steam_apikey; + std::string app_id; + + std::cout << "Enter the game appid: "; + std::cin >> app_id; + std::cout << "Enter your webapi key: "; + std::cin.clear(); + std::cin.ignore(std::numeric_limits::max(), '\n'); + std::cin >> steam_apikey; + + url = "http://api.steampowered.com/ISteamUserStats/GetSchemaForGame/v2/?key="; + url += steam_apikey; + url += "&appid="; + url += app_id; + easy.set_url(url); + easy.perform(); + try + { + std::ofstream ach_file("achievements.json", std::ios::trunc | std::ios::out); + nlohmann::json json = nlohmann::json::parse(easy.get_answer()); + nlohmann::json output_json = nlohmann::json::array(); + + bool first = true; + int i = 0; + for (auto& item : json["game"]["availableGameStats"]["achievements"].items()) + { + output_json[i]["name"] = item.value()["name"]; + output_json[i]["displayName"] = item.value()["displayName"]; + output_json[i]["hidden"] = item.value()["hidden"]; + try + { + output_json[i]["description"] = item.value()["description"]; + } + catch (...) + { + output_json[i]["description"] = ""; + } + output_json[i]["icon"] = item.value()["icon"]; + output_json[i]["icongray"] = item.value()["icongray"]; + output_json[i]["time_earned"] = 0; + output_json[i]["earned"] = 0; + ++i; + } + ach_file << std::setw(2) << output_json; + } + catch (std::exception& e) + { + std::cerr << "Failed to get infos: "; + long code; + if (easy.get_html_code(code) == CURLE_OK && code == 403) + { + std::cerr << "Error in webapi key"; + } + else + { + std::cerr << "Error while parsing json. Try to go at " << url << " and see what you can do to build your achivements.json"; + } + std::cerr << std::endl; + } + } +} diff --git a/generate_items_infos/generate_items_infos.cpp b/generate_items_infos/generate_items_infos.cpp new file mode 100644 index 0000000..4def7b9 --- /dev/null +++ b/generate_items_infos/generate_items_infos.cpp @@ -0,0 +1,157 @@ +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +struct ClientCBS +{ + STEAM_CALLBACK(ClientCBS, OnSteamInventoryDefinitionUpdate, SteamInventoryDefinitionUpdate_t); + STEAM_CALLBACK(ClientCBS, OnSteamInventoryResultReady , SteamInventoryResultReady_t); +}; + +bool definition_update = false; + +std::vector split(const std::string& s, char delimiter) +{ + std::vector tokens; + std::string token; + std::istringstream tokenStream(s); + while (std::getline(tokenStream, token, delimiter)) + { + tokens.push_back(token); + } + return tokens; +} + +void ClientCBS::OnSteamInventoryResultReady(SteamInventoryResultReady_t* param) +{ + switch (param->m_result) + { + case k_EResultOK: break; + case k_EResultPending: break; + } + + if (param->m_handle) + { + SteamInventory()->DestroyResult(param->m_handle); + } +} + +void ClientCBS::OnSteamInventoryDefinitionUpdate(SteamInventoryDefinitionUpdate_t* param) +{ + std::ofstream out("items.json", std::ios::out | std::ios::trunc); + nlohmann::json json = nlohmann::json::object(); + SteamItemDef_t* items; + uint32 size = 0; + SteamInventory()->GetItemDefinitionIDs(nullptr, &size); + items = new SteamItemDef_t[size]; + SteamInventory()->GetItemDefinitionIDs(items, &size); + + definition_update = true; + + std::cerr << "Creating json, please wait..." << std::endl; + + for (int i = 0; i < size; ++i) + { + uint32 len; + len = 0; + if (SteamInventory()->GetItemDefinitionProperty(items[i], nullptr, nullptr, &len)) + { + std::string buffer(len, '\0'); + if (SteamInventory()->GetItemDefinitionProperty(items[i], nullptr, &buffer[0], &len)) + { + buffer.pop_back(); + std::vector strs(std::move(split(buffer, ','))); + + std::string key = std::to_string(items[i]); + + for (auto j = strs.begin(); j != strs.end(); ++j) + { + len = 0; + if (SteamInventory()->GetItemDefinitionProperty(items[i], j->c_str(), nullptr, &len)) + { + std::string buffer(len, '\0'); + if (SteamInventory()->GetItemDefinitionProperty(items[i], j->c_str(), &buffer[0], &len)) + { + buffer.pop_back(); + if( *j == "quantity") + json[key][*j] = "0"; + else + json[key][*j] = buffer; + } + } + } + } + } + } + + out << std::setw(2) << json; + + delete[]items; +} + +int main(int argc, char *argv[]) +{ + uint32_t appid; + + if (argc == 2) + { + appid = std::stoi(argv[1]); + } + else + { + std::cout << "Enter the game appid: "; + std::cin >> appid; + } + + std::ofstream steam_api("steam_appid.txt", std::ios::out | std::ios::trunc); + steam_api << appid; + steam_api.close(); + + if (SteamAPI_RestartAppIfNecessary(0)) + { + std::cerr << "This app needs restart" << std::endl; + return EXIT_FAILURE; + } + + if (!SteamAPI_Init()) + { + std::cerr << "SteamAPI_Init() failed" << std::endl; + return EXIT_FAILURE; + } + + auto SUser = SteamUser(); + + if (!SUser->BLoggedOn()) + { + std::cerr << "Steam user is not logged in" << std::endl; + return EXIT_FAILURE; + } + + ClientCBS cbs; + + int max_retry = 10; + while (!definition_update && max_retry-- > 0) + { + std::cerr << "Running LoadItemDefinitions" << std::endl; + bool ret = SteamInventory()->LoadItemDefinitions(); + int retry = 0; + while (retry++ <= 100 && !definition_update) + { + SteamAPI_RunCallbacks(); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + } + + SteamAPI_Shutdown(); + + return 0; +} \ No newline at end of file diff --git a/overlay_experimental/DX10_Hook.cpp b/overlay_experimental/DX10_Hook.cpp index 6f5db63..fe0726a 100644 --- a/overlay_experimental/DX10_Hook.cpp +++ b/overlay_experimental/DX10_Hook.cpp @@ -139,7 +139,10 @@ HRESULT STDMETHODCALLTYPE DX10_Hook::MyResizeBuffers(IDXGISwapChain* _this, UINT DX10_Hook::DX10_Hook(): initialized(false), pDevice(nullptr), - mainRenderTargetView(nullptr) + mainRenderTargetView(nullptr), + Present(nullptr), + ResizeBuffers(nullptr), + ResizeTarget(nullptr) { _library = LoadLibrary(DLL_NAME); @@ -190,13 +193,9 @@ const char* DX10_Hook::get_lib_name() const return DLL_NAME; } -void DX10_Hook::loadFunctions(ID3D10Device *pDevice, IDXGISwapChain *pSwapChain) +void DX10_Hook::loadFunctions(IDXGISwapChain *pSwapChain) { - void** vTable = *reinterpret_cast(pDevice); - -#define LOAD_FUNC(X) (void*&)X = vTable[(int)ID3D10DeviceVTable::X] - -#undef LOAD_FUNC + void** vTable; vTable = *reinterpret_cast(pSwapChain); #define LOAD_FUNC(X) (void*&)X = vTable[(int)IDXGISwapChainVTable::X] diff --git a/overlay_experimental/DX10_Hook.h b/overlay_experimental/DX10_Hook.h index 4979e74..63bb974 100644 --- a/overlay_experimental/DX10_Hook.h +++ b/overlay_experimental/DX10_Hook.h @@ -48,7 +48,7 @@ public: static DX10_Hook* Inst(); virtual const char* get_lib_name() const; - void loadFunctions(ID3D10Device *pDevice, IDXGISwapChain *pSwapChain); + void loadFunctions(IDXGISwapChain *pSwapChain); }; #endif//NO_OVERLAY diff --git a/overlay_experimental/DX11_Hook.cpp b/overlay_experimental/DX11_Hook.cpp index 9cda270..81c4afa 100644 --- a/overlay_experimental/DX11_Hook.cpp +++ b/overlay_experimental/DX11_Hook.cpp @@ -156,7 +156,10 @@ HRESULT STDMETHODCALLTYPE DX11_Hook::MyResizeBuffers(IDXGISwapChain* _this, UINT DX11_Hook::DX11_Hook(): initialized(false), pContext(nullptr), - mainRenderTargetView(nullptr) + mainRenderTargetView(nullptr), + Present(nullptr), + ResizeBuffers(nullptr), + ResizeTarget(nullptr) { _library = LoadLibrary(DLL_NAME); @@ -208,13 +211,9 @@ const char* DX11_Hook::get_lib_name() const return DLL_NAME; } -void DX11_Hook::loadFunctions(ID3D11Device *pDevice, IDXGISwapChain *pSwapChain) +void DX11_Hook::loadFunctions(IDXGISwapChain *pSwapChain) { - void** vTable = *reinterpret_cast(pDevice); - -#define LOAD_FUNC(X) (void*&)X = vTable[(int)ID3D11DeviceVTable::X] - -#undef LOAD_FUNC + void** vTable; vTable = *reinterpret_cast(pSwapChain); #define LOAD_FUNC(X) (void*&)X = vTable[(int)IDXGISwapChainVTable::X] diff --git a/overlay_experimental/DX11_Hook.h b/overlay_experimental/DX11_Hook.h index 83de88d..c0ceea3 100644 --- a/overlay_experimental/DX11_Hook.h +++ b/overlay_experimental/DX11_Hook.h @@ -48,7 +48,7 @@ public: static DX11_Hook* Inst(); virtual const char* get_lib_name() const; - void loadFunctions(ID3D11Device *pDevice, IDXGISwapChain *pSwapChain); + void loadFunctions(IDXGISwapChain *pSwapChain); }; #endif//NO_OVERLAY diff --git a/overlay_experimental/DX12_Hook.cpp b/overlay_experimental/DX12_Hook.cpp index 7b9f09b..2665170 100644 --- a/overlay_experimental/DX12_Hook.cpp +++ b/overlay_experimental/DX12_Hook.cpp @@ -178,7 +178,7 @@ DX12_Hook::DX12_Hook(): { _library = LoadLibrary(DLL_NAME); - PRINT_DEBUG("Trying to hook DX12 but DX12_Hook is not implemented yet, please report to DEV with the game name.\n"); + PRINT_DEBUG("DX12 support is experimental, don't complain if it doesn't work as expected.\n"); // Hook to D3D12CreateDevice and D3D12CreateDeviceAndSwapChain so we know when it gets called. // If its called, then DX12 will be used to render the overlay. @@ -223,25 +223,10 @@ const char* DX12_Hook::get_lib_name() const return DLL_NAME; } -void DX12_Hook::loadFunctions(ID3D12Device* pDevice, ID3D12CommandQueue* pCommandQueue, IDXGISwapChain *pSwapChain) +void DX12_Hook::loadFunctions(ID3D12CommandList* pCommandList, IDXGISwapChain *pSwapChain) { - void** vTable = *reinterpret_cast(pDevice); -#define LOAD_FUNC(X) (void*&)X = vTable[(int)ID3D12DeviceVTable::X] + void** vTable; -#undef LOAD_FUNC - - vTable = *reinterpret_cast(pCommandQueue); -#define LOAD_FUNC(X) (void*&)X = vTable[(int)ID3D12CommandQueueVTable::X] - LOAD_FUNC(ExecuteCommandLists); -#undef LOAD_FUNC - - - ID3D12CommandAllocator* pCommandAllocator; - ID3D12CommandList* pCommandList; - - pDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&pCommandAllocator)); - pDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, pCommandAllocator, NULL, IID_PPV_ARGS(&pCommandList)); - vTable = *reinterpret_cast(pCommandList); #define LOAD_FUNC(X) (void*&)X = vTable[(int)ID3D12GraphicsCommandListVTable::X] LOAD_FUNC(Close); @@ -253,9 +238,6 @@ void DX12_Hook::loadFunctions(ID3D12Device* pDevice, ID3D12CommandQueue* pComman LOAD_FUNC(ResizeBuffers); LOAD_FUNC(ResizeTarget); #undef LOAD_FUNC - - pCommandList->Release(); - pCommandAllocator->Release(); } #endif//NO_OVERLAY \ No newline at end of file diff --git a/overlay_experimental/DX12_Hook.h b/overlay_experimental/DX12_Hook.h index 0889ce0..4556c52 100644 --- a/overlay_experimental/DX12_Hook.h +++ b/overlay_experimental/DX12_Hook.h @@ -52,7 +52,7 @@ public: static DX12_Hook* Inst(); virtual const char* get_lib_name() const; - void loadFunctions(ID3D12Device *pDevice, ID3D12CommandQueue *pCommandQueue, IDXGISwapChain *pSwapChain); + void loadFunctions(ID3D12CommandList *pCommandList, IDXGISwapChain *pSwapChain); }; #endif//NO_OVERLAY diff --git a/overlay_experimental/Hook_Manager.cpp b/overlay_experimental/Hook_Manager.cpp index 4b18fa6..aaa4e82 100644 --- a/overlay_experimental/Hook_Manager.cpp +++ b/overlay_experimental/Hook_Manager.cpp @@ -49,13 +49,13 @@ HRESULT STDMETHODCALLTYPE Hook_Manager::MyIDXGISwapChain_Present(IDXGISwapChain* } else { - _this->GetDevice(__uuidof(ID3D12Device), (void**)& pDevice); - if (pDevice) - { + //_this->GetDevice(__uuidof(ID3D12Device), (void**)& pDevice); + //if (pDevice) + //{ // DX12_Hook* hook = DX12_Hook::Inst(); // if (hook->start_hook()) // inst.AddHook(hook); - } + //} } } if (pDevice) pDevice->Release(); @@ -142,11 +142,14 @@ void Hook_Manager::HookDX9Present(IDirect3DDevice9* pDevice, bool ex) } } -void Hook_Manager::HookwglMakeCurrent() +void Hook_Manager::HookwglMakeCurrent(BOOL(WINAPI* wglMakeCurrent)(HDC, HGLRC)) { if (!_ogl_hooked) { _ogl_hooked = true; + + _wglMakeCurrent = wglMakeCurrent; + rendererdetect_hook->BeginHook(); rendererdetect_hook->HookFuncs( @@ -167,28 +170,32 @@ void Hook_Manager::hook_dx9() IDirect3D9Ex* pD3D = nullptr; IUnknown* pDevice = nullptr; - - D3DPRESENT_PARAMETERS params = {}; - params.BackBufferWidth = 1; - params.BackBufferHeight = 1; - params.hDeviceWindow = hWnd; - params.BackBufferCount = 1; - params.Windowed = TRUE; - params.SwapEffect = D3DSWAPEFFECT_DISCARD; - - decltype(Direct3DCreate9Ex)* Direct3DCreate9Ex = (decltype(Direct3DCreate9Ex))GetProcAddress(GetModuleHandle(DX9_Hook::DLL_NAME), "Direct3DCreate9Ex"); - if (Direct3DCreate9Ex != nullptr) + HMODULE library = GetModuleHandle(DX9_Hook::DLL_NAME); + decltype(Direct3DCreate9Ex)* Direct3DCreate9Ex = nullptr; + if (library != nullptr) { - Direct3DCreate9Ex(D3D_SDK_VERSION, &pD3D); - pD3D->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, ¶ms, NULL, reinterpret_cast(&pDevice)); - } - else - { - decltype(Direct3DCreate9)* Direct3DCreate9 = (decltype(Direct3DCreate9))GetProcAddress(GetModuleHandle(DX9_Hook::DLL_NAME), "Direct3DCreate9"); - if (Direct3DCreate9) + Direct3DCreate9Ex = (decltype(Direct3DCreate9Ex))GetProcAddress(library, "Direct3DCreate9Ex"); + D3DPRESENT_PARAMETERS params = {}; + params.BackBufferWidth = 1; + params.BackBufferHeight = 1; + params.hDeviceWindow = hWnd; + params.BackBufferCount = 1; + params.Windowed = TRUE; + params.SwapEffect = D3DSWAPEFFECT_DISCARD; + + if (Direct3DCreate9Ex != nullptr) { - pD3D = reinterpret_cast(Direct3DCreate9(D3D_SDK_VERSION)); - pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, ¶ms, reinterpret_cast(&pDevice)); + Direct3DCreate9Ex(D3D_SDK_VERSION, &pD3D); + pD3D->CreateDeviceEx(D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, ¶ms, NULL, reinterpret_cast(&pDevice)); + } + else + { + decltype(Direct3DCreate9)* Direct3DCreate9 = (decltype(Direct3DCreate9))GetProcAddress(library, "Direct3DCreate9"); + if (Direct3DCreate9 != nullptr) + { + pD3D = reinterpret_cast(Direct3DCreate9(D3D_SDK_VERSION)); + pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_NULLREF, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, ¶ms, reinterpret_cast(&pDevice)); + } } } @@ -218,30 +225,37 @@ void Hook_Manager::hook_dx10() if (!hWnd) return; - IDXGISwapChain* pSwapChain; - ID3D10Device* pDevice; - DXGI_SWAP_CHAIN_DESC SwapChainDesc = {}; - decltype(D3D10CreateDeviceAndSwapChain)* D3D10CreateDeviceAndSwapChain = - (decltype(D3D10CreateDeviceAndSwapChain))GetProcAddress(GetModuleHandle(DX10_Hook::DLL_NAME), "D3D10CreateDeviceAndSwapChain"); - SwapChainDesc.BufferCount = 1; - SwapChainDesc.BufferDesc.Width = 1; - SwapChainDesc.BufferDesc.Height = 1; - SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - SwapChainDesc.BufferDesc.RefreshRate.Numerator = 0; - SwapChainDesc.BufferDesc.RefreshRate.Denominator = 0; - SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - SwapChainDesc.OutputWindow = hWnd; - SwapChainDesc.SampleDesc.Count = 1; - SwapChainDesc.SampleDesc.Quality = 0; - SwapChainDesc.Windowed = TRUE; - - D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_NULL, NULL, 0, D3D10_SDK_VERSION, &SwapChainDesc, &pSwapChain, &pDevice); - - if (pDevice != nullptr && pSwapChain != nullptr) + IDXGISwapChain* pSwapChain = nullptr; + ID3D10Device* pDevice = nullptr; + HMODULE library = GetModuleHandle(DX10_Hook::DLL_NAME); + if (library != nullptr) + { + decltype(D3D10CreateDeviceAndSwapChain)* D3D10CreateDeviceAndSwapChain = + (decltype(D3D10CreateDeviceAndSwapChain))GetProcAddress(library, "D3D10CreateDeviceAndSwapChain"); + if (D3D10CreateDeviceAndSwapChain != nullptr) + { + DXGI_SWAP_CHAIN_DESC SwapChainDesc = {}; + + SwapChainDesc.BufferCount = 1; + SwapChainDesc.BufferDesc.Width = 1; + SwapChainDesc.BufferDesc.Height = 1; + SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + SwapChainDesc.BufferDesc.RefreshRate.Numerator = 0; + SwapChainDesc.BufferDesc.RefreshRate.Denominator = 0; + SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + SwapChainDesc.OutputWindow = hWnd; + SwapChainDesc.SampleDesc.Count = 1; + SwapChainDesc.SampleDesc.Quality = 0; + SwapChainDesc.Windowed = TRUE; + + D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_NULL, NULL, 0, D3D10_SDK_VERSION, &SwapChainDesc, &pSwapChain, &pDevice); + } + } + if (pSwapChain != nullptr) { PRINT_DEBUG("Hooked IDXGISwapChain::Present to detect DX Version\n"); auto h = DX10_Hook::Inst(); - h->loadFunctions(pDevice, pSwapChain); + h->loadFunctions(pSwapChain); _hooks.insert(h); HookDXGIPresent(pSwapChain); } @@ -262,30 +276,37 @@ void Hook_Manager::hook_dx11() if (!hWnd) return; - IDXGISwapChain* pSwapChain; - ID3D11Device* pDevice; - DXGI_SWAP_CHAIN_DESC SwapChainDesc = {}; - decltype(D3D11CreateDeviceAndSwapChain)* D3D11CreateDeviceAndSwapChain = - (decltype(D3D11CreateDeviceAndSwapChain))GetProcAddress(GetModuleHandle(DX11_Hook::DLL_NAME), "D3D11CreateDeviceAndSwapChain"); - SwapChainDesc.BufferCount = 1; - SwapChainDesc.BufferDesc.Width = 1; - SwapChainDesc.BufferDesc.Height = 1; - SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - SwapChainDesc.BufferDesc.RefreshRate.Numerator = 0; - SwapChainDesc.BufferDesc.RefreshRate.Denominator = 0; - SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - SwapChainDesc.OutputWindow = hWnd; - SwapChainDesc.SampleDesc.Count = 1; - SwapChainDesc.SampleDesc.Quality = 0; - SwapChainDesc.Windowed = TRUE; - - D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, NULL, D3D11_SDK_VERSION, &SwapChainDesc, &pSwapChain, &pDevice, NULL, NULL); - - if (pDevice != nullptr && pSwapChain != nullptr) + IDXGISwapChain* pSwapChain = nullptr; + ID3D11Device* pDevice = nullptr; + HMODULE library = GetModuleHandle(DX11_Hook::DLL_NAME); + if (library != nullptr) + { + decltype(D3D11CreateDeviceAndSwapChain)* D3D11CreateDeviceAndSwapChain = + (decltype(D3D11CreateDeviceAndSwapChain))GetProcAddress(library, "D3D11CreateDeviceAndSwapChain"); + if (D3D11CreateDeviceAndSwapChain != nullptr) + { + DXGI_SWAP_CHAIN_DESC SwapChainDesc = {}; + + SwapChainDesc.BufferCount = 1; + SwapChainDesc.BufferDesc.Width = 1; + SwapChainDesc.BufferDesc.Height = 1; + SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + SwapChainDesc.BufferDesc.RefreshRate.Numerator = 0; + SwapChainDesc.BufferDesc.RefreshRate.Denominator = 0; + SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + SwapChainDesc.OutputWindow = hWnd; + SwapChainDesc.SampleDesc.Count = 1; + SwapChainDesc.SampleDesc.Quality = 0; + SwapChainDesc.Windowed = TRUE; + + D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, NULL, D3D11_SDK_VERSION, &SwapChainDesc, &pSwapChain, &pDevice, NULL, NULL); + } + } + if (pSwapChain != nullptr) { PRINT_DEBUG("Hooked IDXGISwapChain::Present to detect DX Version\n"); auto h = DX11_Hook::Inst(); - h->loadFunctions(pDevice, pSwapChain); + h->loadFunctions(pSwapChain); _hooks.insert(h); HookDXGIPresent(pSwapChain); } @@ -309,53 +330,81 @@ void Hook_Manager::hook_dx12() IDXGIFactory4* pDXGIFactory = nullptr; IDXGISwapChain1* pSwapChain = nullptr; - D3D12_COMMAND_QUEUE_DESC queueDesc = {}; ID3D12CommandQueue* pCommandQueue = nullptr; ID3D12Device* pDevice = nullptr; + ID3D12CommandAllocator* pCommandAllocator = nullptr; + ID3D12CommandList* pCommandList = nullptr; - decltype(D3D12CreateDevice)* D3D12CreateDevice = - (decltype(D3D12CreateDevice))GetProcAddress(GetModuleHandle(DX12_Hook::DLL_NAME), "D3D12CreateDevice"); - - D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&pDevice)); - - if (pDevice) + HMODULE library = GetModuleHandle(DX12_Hook::DLL_NAME); + if (library != nullptr) { - DXGI_SWAP_CHAIN_DESC1 SwapChainDesc = {}; - SwapChainDesc.BufferCount = 2; - SwapChainDesc.Width = 1; - SwapChainDesc.Height = 1; - SwapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - SwapChainDesc.Stereo = FALSE; - SwapChainDesc.SampleDesc = { 1, 0 }; - SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - SwapChainDesc.Scaling = DXGI_SCALING_NONE; - SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; - - queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; - queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; - pDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&pCommandQueue)); - - if (pCommandQueue) + decltype(D3D12CreateDevice)* D3D12CreateDevice = + (decltype(D3D12CreateDevice))GetProcAddress(library, "D3D12CreateDevice"); + + if (D3D12CreateDevice != nullptr) { - reinterpret_cast(GetProcAddress(GetModuleHandle("dxgi.dll"), "CreateDXGIFactory1"))(IID_PPV_ARGS(&pDXGIFactory)); - pDXGIFactory->CreateSwapChainForHwnd(pCommandQueue, hWnd, &SwapChainDesc, NULL, NULL, &pSwapChain); - if (pSwapChain != nullptr) - { - PRINT_DEBUG("Hooked IDXGISwapChain::Present to detect DX Version\n"); + D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&pDevice)); - auto h = DX12_Hook::Inst(); - h->loadFunctions(pDevice, pCommandQueue, pSwapChain); - _hooks.insert(h); - HookDXGIPresent(pSwapChain); - } - else + if (pDevice != nullptr) { - PRINT_DEBUG("Failed to Hook IDXGISwapChain::Present to detect DX Version\n"); - } - } + DXGI_SWAP_CHAIN_DESC1 SwapChainDesc = {}; + SwapChainDesc.BufferCount = 2; + SwapChainDesc.Width = 1; + SwapChainDesc.Height = 1; + SwapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + SwapChainDesc.Stereo = FALSE; + SwapChainDesc.SampleDesc = { 1, 0 }; + SwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + SwapChainDesc.Scaling = DXGI_SCALING_NONE; + SwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; + + D3D12_COMMAND_QUEUE_DESC queueDesc = {}; + queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + pDevice->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(&pCommandQueue)); + + if (pCommandQueue != nullptr) + { + HMODULE dxgi = GetModuleHandle("dxgi.dll"); + if (dxgi != nullptr) + { + decltype(CreateDXGIFactory1)* CreateDXGIFactory1 = (decltype(CreateDXGIFactory1))GetProcAddress(dxgi, "CreateDXGIFactory1"); + if (CreateDXGIFactory1 != nullptr) + { + CreateDXGIFactory1(IID_PPV_ARGS(&pDXGIFactory)); + if (pDXGIFactory != nullptr) + { + pDXGIFactory->CreateSwapChainForHwnd(pCommandQueue, hWnd, &SwapChainDesc, NULL, NULL, &pSwapChain); + + pDevice->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&pCommandAllocator)); + if (pCommandAllocator != nullptr) + { + pDevice->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, pCommandAllocator, NULL, IID_PPV_ARGS(&pCommandList)); + } + } + } + } + } + }//if (pDevice != nullptr) + }//if (D3D12CreateDevice != nullptr) + }//if (library != nullptr) + if (pSwapChain != nullptr && pCommandList != nullptr) + { + PRINT_DEBUG("Hooked IDXGISwapChain::Present to detect DX Version\n"); + + auto h = DX12_Hook::Inst(); + h->loadFunctions(pCommandList, pSwapChain); + _hooks.insert(h); + HookDXGIPresent(pSwapChain); + } + else + { + PRINT_DEBUG("Failed to Hook IDXGISwapChain::Present to detect DX Version\n"); } + if (pCommandList) pCommandList->Release(); + if (pCommandAllocator) pCommandAllocator->Release(); if (pSwapChain) pSwapChain->Release(); if (pDXGIFactory) pDXGIFactory->Release(); if (pCommandQueue) pCommandQueue->Release(); @@ -367,8 +416,21 @@ void Hook_Manager::hook_opengl() { if (!_ogl_hooked && !_renderer_found) { - _wglMakeCurrent = (decltype(_wglMakeCurrent))GetProcAddress(GetModuleHandle(OpenGL_Hook::DLL_NAME), "wglMakeCurrent"); - HookwglMakeCurrent(); + HMODULE library = GetModuleHandle(OpenGL_Hook::DLL_NAME); + decltype(wglMakeCurrent)* wglMakeCurrent = nullptr; + if (library != nullptr) + { + _wglMakeCurrent = (decltype(_wglMakeCurrent))GetProcAddress(library, "wglMakeCurrent"); + } + if (wglMakeCurrent != nullptr) + { + PRINT_DEBUG("Hooked wglMakeCurrent to detect OpenGL\n"); + HookwglMakeCurrent(wglMakeCurrent); + } + else + { + PRINT_DEBUG("Failed to Hook wglMakeCurrent to detect OpenGL\n"); + } } } diff --git a/overlay_experimental/Hook_Manager.h b/overlay_experimental/Hook_Manager.h index 8f1e367..0722cbf 100644 --- a/overlay_experimental/Hook_Manager.h +++ b/overlay_experimental/Hook_Manager.h @@ -59,7 +59,7 @@ protected: // DX9 Present and PresentEx will be used to detect if DX9 should be used for overlay void HookDX9Present(IDirect3DDevice9* pDevice, bool ex); // wglMakeCurrent will be used to detect if OpenGL3 should be used for overlay - void HookwglMakeCurrent(); + void HookwglMakeCurrent(BOOL (WINAPI *wglMakeCurrent)(HDC, HGLRC)); // Setup DX9 Device and get vtable void hook_dx9(); // Setup DX10 Device and get vtable diff --git a/overlay_experimental/steam_overlay.cpp b/overlay_experimental/steam_overlay.cpp index f22712d..ab8b3e5 100644 --- a/overlay_experimental/steam_overlay.cpp +++ b/overlay_experimental/steam_overlay.cpp @@ -369,6 +369,17 @@ void Steam_Overlay::BuildFriendWindow(Friend const& frd, friend_window_state& st ImGui::End(); } +void Steam_Overlay::BuildNotifications() +{ + //ImGui::SetNextWindowPos(ImVec2{ (float)width - 300, (float)height - 80 }); + //ImGui::SetNextWindowSize(ImVec2{ 300.0, 80.0 }); + //ImGui::Begin("##notification", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse + // | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoFocusOnAppearing + // | ImGuiWindowFlags_NoDecoration); + // + //ImGui::End(); +} + // Try to make this function as short as possible or it might affect game's fps. void Steam_Overlay::OverlayProc( int width, int height ) { @@ -430,6 +441,7 @@ void Steam_Overlay::OverlayProc( int width, int height ) ImGui::End(); }// if(show_overlay) + BuildNotifications(); } void Steam_Overlay::Callback(Common_Message *msg) diff --git a/overlay_experimental/steam_overlay.h b/overlay_experimental/steam_overlay.h index c3337f5..45fd514 100644 --- a/overlay_experimental/steam_overlay.h +++ b/overlay_experimental/steam_overlay.h @@ -80,7 +80,8 @@ class Steam_Overlay void BuildContextMenu(Friend const& frd, friend_window_state &state); // Double click on friend void BuildFriendWindow(Friend const& frd, friend_window_state &state); - + // Notifications like achievements, chat and invitations + void BuildNotifications(); public: Steam_Overlay(Settings* settings, SteamCallResults* callback_results, SteamCallBacks* callbacks, RunEveryRunCB* run_every_runcb, Networking *network);