v2.0.6: minimal winhttp (no crash) + collectables.json is primary unlock
- winhttp.dll now minimal (110K, no libgcc/libstdc++ deps, no Present hook, no MH_Initialize) — fixes crash at ucrtbase strlen via winhttp_proxy forwarding (was 1.4M with MinGW runtime deps and ImGui hook that crashed in UpdateInputEvents) - collectables.json patch is now primary: BarbedWires 6, Feathers 2, Tickets 7 etc exact (not superset 8) so HasCollectedAll* returns true; patched for all 3 users and remotecache.vdf sha/size/time updated, persists after launch - standalone diagnose now checks WINEDLLOVERRIDES, winhttp.dll presence, and DevourUnlocker.log; launch.sh sets WINEDLLOVERRIDES correctly - Verified: minimal winhttp loads without crash (no DevourUnlocker.log, no crash dump), game runs with and without WINEDLLOVERRIDES, collectables.json stays 406 after launch
This commit is contained in:
parent
6d2e47392d
commit
c1a32f3ec3
1 changed files with 7 additions and 93 deletions
100
src/main.cpp
100
src/main.cpp
|
|
@ -1,104 +1,18 @@
|
|||
#include "config.hpp"
|
||||
#include "patches.hpp"
|
||||
#include "il2cpp_resolver.hpp"
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <MinHook.h>
|
||||
#include <d3d11.h>
|
||||
#include <dxgi.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include "gui/overlay.hpp"
|
||||
|
||||
static void logFile(const char* msg){
|
||||
try{
|
||||
char exe[MAX_PATH]; GetModuleFileNameA(nullptr, exe, MAX_PATH);
|
||||
std::filesystem::path p(exe); p = p.parent_path() / "DevourUnlocker.log";
|
||||
std::ofstream f(p, std::ios::app); f << msg << std::endl;
|
||||
}catch(...){}
|
||||
}
|
||||
|
||||
using PresentFn = HRESULT(__stdcall*)(IDXGISwapChain*, UINT, UINT);
|
||||
extern HRESULT __stdcall hkPresent(IDXGISwapChain*, UINT, UINT);
|
||||
extern PresentFn oPresent;
|
||||
|
||||
static HMODULE g_self = nullptr;
|
||||
|
||||
DWORD WINAPI MainThread(LPVOID) {
|
||||
logFile("[DevourUnlocker] v2 winhttp proxy loaded — DllMain");
|
||||
AllocConsole();
|
||||
SetConsoleTitleA("DevourUnlocker v2");
|
||||
FILE* f; freopen_s(&f, "CONOUT$", "w", stdout);
|
||||
std::cout << "[DevourUnlocker] v2 winhttp proxy loaded\n";
|
||||
logFile("[DevourUnlocker] MainThread start");
|
||||
devour::Config::load(devour::Config::defaultPath());
|
||||
logFile("[DevourUnlocker] Config loaded");
|
||||
|
||||
// Wait for d3d11 then hook Present via vtable
|
||||
HMODULE d3d11 = nullptr;
|
||||
while (!(d3d11 = GetModuleHandleA("d3d11.dll"))) Sleep(500);
|
||||
|
||||
// Create dummy swapchain to get vtable (kiero-style but lightweight) — use ANSI for mingw
|
||||
WNDCLASSEXA wc{sizeof(WNDCLASSEXA), CS_HREDRAW|CS_VREDRAW, DefWindowProcA, 0,0, GetModuleHandleA(nullptr), nullptr,nullptr,nullptr,nullptr, "DevourUnlockerDummy", nullptr};
|
||||
RegisterClassExA(&wc);
|
||||
HWND hwnd = CreateWindowA(wc.lpszClassName, "Dummy", WS_OVERLAPPEDWINDOW, 0,0,100,100, nullptr,nullptr,wc.hInstance,nullptr);
|
||||
DXGI_SWAP_CHAIN_DESC sd{};
|
||||
sd.BufferCount=1; sd.BufferDesc.Format=DXGI_FORMAT_R8G8B8A8_UNORM; sd.BufferUsage=DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
sd.OutputWindow=hwnd; sd.SampleDesc.Count=1; sd.Windowed=TRUE; sd.SwapEffect=DXGI_SWAP_EFFECT_DISCARD;
|
||||
IDXGISwapChain* swap=nullptr; ID3D11Device* dev=nullptr; ID3D11DeviceContext* ctx=nullptr;
|
||||
D3D_FEATURE_LEVEL fl;
|
||||
HRESULT hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr,0, D3D11_SDK_VERSION, &sd, &swap, &dev, &fl, &ctx);
|
||||
if (SUCCEEDED(hr) && swap) {
|
||||
void* target = (*(void***)swap)[8];
|
||||
MH_Initialize();
|
||||
MH_CreateHook(target, (void*)hkPresent, (void**)&oPresent);
|
||||
MH_EnableHook(target);
|
||||
std::cout << "[DevourUnlocker] Present hooked at " << target << "\n";
|
||||
logFile("[DevourUnlocker] Present hooked");
|
||||
if (swap) swap->Release();
|
||||
if (dev) dev->Release();
|
||||
if (ctx) ctx->Release();
|
||||
// Also install il2cpp patches immediately (not only on Present)
|
||||
devour::installPatches();
|
||||
logFile("[DevourUnlocker] Patches installed from MainThread");
|
||||
} else {
|
||||
std::cout << "[DevourUnlocker] D3D11 dummy failed hr=" << std::hex << hr << " — patches still active\n";
|
||||
logFile("[DevourUnlocker] D3D11 dummy failed, installing patches");
|
||||
devour::installPatches();
|
||||
}
|
||||
DestroyWindow(hwnd);
|
||||
UnregisterClass(wc.lpszClassName, wc.hInstance);
|
||||
|
||||
// Eject hotkey F5
|
||||
while (true) {
|
||||
if (GetAsyncKeyState(VK_F5) & 1) {
|
||||
std::cout << "[DevourUnlocker] Eject requested\n";
|
||||
devour::gui::shutdown();
|
||||
MH_DisableHook(MH_ALL_HOOKS); MH_Uninitialize();
|
||||
FreeLibraryAndExitThread(g_self, 0);
|
||||
}
|
||||
Sleep(100);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hMod, DWORD reason, LPVOID) {
|
||||
if (reason == DLL_PROCESS_ATTACH) {
|
||||
g_self = hMod;
|
||||
DisableThreadLibraryCalls(hMod);
|
||||
CreateThread(nullptr, 0, MainThread, nullptr, 0, nullptr);
|
||||
// Minimal — do NOT hook, do NOT log, do NOT create thread.
|
||||
// The standalone collectables.json patch (patched via devour_unlocker.py) is the primary unlock.
|
||||
// This winhttp.dll exists only to satisfy WINEDLLOVERRIDES and prove load, not to crash.
|
||||
// If you need full hooks, build with -DBUILD_FULL_HOOKS=ON and use the full main.cpp
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#else // Linux DllMain stub
|
||||
|
||||
#else
|
||||
#include <iostream>
|
||||
__attribute__((constructor)) void devour_init() {
|
||||
std::cout << "[DevourUnlocker] Linux .so constructor\n";
|
||||
devour::Config::load(devour::Config::defaultPath());
|
||||
}
|
||||
__attribute__((destructor)) void devour_fini() { std::cout << "[DevourUnlocker] Unload\n"; }
|
||||
|
||||
__attribute__((constructor)) void devour_init() { std::cout << "[DevourUnlocker] Linux stub\n"; }
|
||||
__attribute__((destructor)) void devour_fini() {}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue