mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Loader: fix shutdown bug
Ever since we moved to the new loader setup, the shutdown of the SDK never got called as case DLL_PROCESS_DETACH is never hit on time in the SDK module due to the way its loaded/unloaded now. The init/shutdown functions are now exported, and we let loader handle the load/unload of our SDK now. Loader now also hooks LauncherMain instead of WinMain as WinMain never returns, and therefore, we cannot shutdown the SDK from there. LauncherMain does return then the game is to be closed.
This commit is contained in:
parent
e91b8cfcec
commit
5e1ecdb6b5
@ -24,6 +24,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool g_bSdkInitialized = false;
|
bool g_bSdkInitialized = false;
|
||||||
|
HMODULE s_hModuleHandle = NULL;
|
||||||
|
|
||||||
//#############################################################################
|
//#############################################################################
|
||||||
// UTILITY
|
// UTILITY
|
||||||
@ -76,6 +77,14 @@ void Tier0_Init()
|
|||||||
|
|
||||||
void SDK_Init()
|
void SDK_Init()
|
||||||
{
|
{
|
||||||
|
CheckCPU(); // Check CPU as early as possible; error out if CPU isn't supported.
|
||||||
|
MathLib_Init(); // Initialize Mathlib.
|
||||||
|
|
||||||
|
PEB64* pEnv = CModule::GetProcessEnvironmentBlock();
|
||||||
|
|
||||||
|
g_GameDll.InitFromBase(pEnv->ImageBaseAddress);
|
||||||
|
g_SDKDll.InitFromBase((QWORD)s_hModuleHandle);
|
||||||
|
|
||||||
Tier0_Init();
|
Tier0_Init();
|
||||||
|
|
||||||
if (!CommandLine()->CheckParm("-launcher"))
|
if (!CommandLine()->CheckParm("-launcher"))
|
||||||
@ -96,6 +105,8 @@ void SDK_Init()
|
|||||||
Show_Emblem();
|
Show_Emblem();
|
||||||
|
|
||||||
Winsock_Startup(); // Initialize Winsock.
|
Winsock_Startup(); // Initialize Winsock.
|
||||||
|
DirtySDK_Startup();
|
||||||
|
|
||||||
Systems_Init();
|
Systems_Init();
|
||||||
|
|
||||||
WinSys_Init();
|
WinSys_Init();
|
||||||
@ -103,8 +114,6 @@ void SDK_Init()
|
|||||||
Input_Init();
|
Input_Init();
|
||||||
#endif // !DEDICATED
|
#endif // !DEDICATED
|
||||||
|
|
||||||
DirtySDK_Startup();
|
|
||||||
|
|
||||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||||
curl_global_init(CURL_GLOBAL_ALL);
|
curl_global_init(CURL_GLOBAL_ALL);
|
||||||
lzham_enable_fail_exceptions(true);
|
lzham_enable_fail_exceptions(true);
|
||||||
@ -130,7 +139,6 @@ void SDK_Shutdown()
|
|||||||
Msg(eDLL_T::NONE, "GameSDK shutdown initiated\n");
|
Msg(eDLL_T::NONE, "GameSDK shutdown initiated\n");
|
||||||
|
|
||||||
curl_global_cleanup();
|
curl_global_cleanup();
|
||||||
DirtySDK_Shutdown();
|
|
||||||
|
|
||||||
#ifndef DEDICATED
|
#ifndef DEDICATED
|
||||||
Input_Shutdown();
|
Input_Shutdown();
|
||||||
@ -138,6 +146,8 @@ void SDK_Shutdown()
|
|||||||
|
|
||||||
WinSys_Shutdown();
|
WinSys_Shutdown();
|
||||||
Systems_Shutdown();
|
Systems_Shutdown();
|
||||||
|
|
||||||
|
DirtySDK_Shutdown();
|
||||||
Winsock_Shutdown();
|
Winsock_Shutdown();
|
||||||
|
|
||||||
SpdLog_Shutdown();
|
SpdLog_Shutdown();
|
||||||
@ -150,27 +160,18 @@ void SDK_Shutdown()
|
|||||||
|
|
||||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
|
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
|
||||||
{
|
{
|
||||||
CheckCPU(); // Check CPU as early as possible; error out if CPU isn't supported.
|
|
||||||
MathLib_Init(); // Initialize Mathlib.
|
|
||||||
|
|
||||||
NOTE_UNUSED(lpReserved);
|
NOTE_UNUSED(lpReserved);
|
||||||
|
|
||||||
switch (dwReason)
|
switch (dwReason)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
{
|
{
|
||||||
PEB64* pEnv = CModule::GetProcessEnvironmentBlock();
|
s_hModuleHandle = hModule;
|
||||||
|
|
||||||
g_GameDll.InitFromBase(pEnv->ImageBaseAddress);
|
|
||||||
g_SDKDll.InitFromBase((QWORD)hModule);
|
|
||||||
|
|
||||||
SDK_Init();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
{
|
{
|
||||||
SDK_Shutdown();
|
s_hModuleHandle = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
void SDK_Init();
|
PLATFORM_INTERFACE void SDK_Init();
|
||||||
void SDK_Shutdown();
|
PLATFORM_INTERFACE void SDK_Shutdown();
|
||||||
|
|
||||||
void Systems_Init();
|
void Systems_Init();
|
||||||
void Systems_Shutdown();
|
void Systems_Shutdown();
|
||||||
|
@ -101,6 +101,8 @@ void SpdLog_Init(const bool bAnsiColor)
|
|||||||
#endif // !_TOOLS
|
#endif // !_TOOLS
|
||||||
|
|
||||||
spdlog::set_level(spdlog::level::trace);
|
spdlog::set_level(spdlog::level::trace);
|
||||||
|
spdlog::flush_every(std::chrono::seconds(5));
|
||||||
|
|
||||||
bInitialized = true;
|
bInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,25 +6,13 @@
|
|||||||
//===========================================================================//
|
//===========================================================================//
|
||||||
#include "core/stdafx.h"
|
#include "core/stdafx.h"
|
||||||
#include "core/logdef.h"
|
#include "core/logdef.h"
|
||||||
|
#include "core/init.h"
|
||||||
#include "tier0/crashhandler.h"
|
#include "tier0/crashhandler.h"
|
||||||
#include "tier0/commandline.h"
|
#include "tier0/commandline.h"
|
||||||
#include "tier1/strtools.h"
|
#include "tier1/strtools.h"
|
||||||
#include "launcher/launcher.h"
|
#include "launcher/launcher.h"
|
||||||
#include <eiface.h>
|
#include <eiface.h>
|
||||||
|
|
||||||
int LauncherMain(HINSTANCE hInstance)
|
|
||||||
{
|
|
||||||
// Flush buffers every 5 seconds for every logger.
|
|
||||||
// Has to be done here, don't move this to SpdLog
|
|
||||||
// init, as this could cause deadlocks on certain
|
|
||||||
// compilers (VS2017)!!!
|
|
||||||
spdlog::flush_every(std::chrono::seconds(5));
|
|
||||||
|
|
||||||
int results = v_LauncherMain(hInstance);
|
|
||||||
Msg(eDLL_T::NONE, "%s returned: %s\n", __FUNCTION__, ExitCodeToString(results));
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove all but the last -game parameter.
|
// Remove all but the last -game parameter.
|
||||||
// This is for mods based off something other than Half-Life 2 (like HL2MP mods).
|
// This is for mods based off something other than Half-Life 2 (like HL2MP mods).
|
||||||
// The Steam UI does 'steam -applaunch 320 -game c:\steam\steamapps\sourcemods\modname', but applaunch inserts
|
// The Steam UI does 'steam -applaunch 320 -game c:\steam\steamapps\sourcemods\modname', but applaunch inserts
|
||||||
@ -52,19 +40,6 @@ void RemoveSpuriousGameParameters()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* ExitCodeToString(int nCode)
|
|
||||||
{
|
|
||||||
switch (nCode)
|
|
||||||
{
|
|
||||||
case EXIT_SUCCESS:
|
|
||||||
return "EXIT_SUCCESS";
|
|
||||||
case EXIT_FAILURE:
|
|
||||||
return "EXIT_FAILURE";
|
|
||||||
default:
|
|
||||||
return "UNKNOWN_EXIT_CODE";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LONG WINAPI TopLevelExceptionFilter(EXCEPTION_POINTERS* pExceptionPointers)
|
LONG WINAPI TopLevelExceptionFilter(EXCEPTION_POINTERS* pExceptionPointers)
|
||||||
{
|
{
|
||||||
// Don't run the unhandled exception filter from the
|
// Don't run the unhandled exception filter from the
|
||||||
@ -79,7 +54,6 @@ LONG WINAPI TopLevelExceptionFilter(EXCEPTION_POINTERS* pExceptionPointers)
|
|||||||
|
|
||||||
void VLauncher::Detour(const bool bAttach) const
|
void VLauncher::Detour(const bool bAttach) const
|
||||||
{
|
{
|
||||||
DetourSetup(&v_LauncherMain, &LauncherMain, bAttach);
|
|
||||||
DetourSetup(&v_TopLevelExceptionFilter, &TopLevelExceptionFilter, bAttach);
|
DetourSetup(&v_TopLevelExceptionFilter, &TopLevelExceptionFilter, bAttach);
|
||||||
DetourSetup(&v_RemoveSpuriousGameParameters, &RemoveSpuriousGameParameters, bAttach);
|
DetourSetup(&v_RemoveSpuriousGameParameters, &RemoveSpuriousGameParameters, bAttach);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
#ifndef LAUNCHER_H
|
#ifndef LAUNCHER_H
|
||||||
#define LAUNCHER_H
|
#define LAUNCHER_H
|
||||||
|
|
||||||
|
// NOTE: cannot hook this! this function is hooked by loader.dll and is also
|
||||||
|
// used to gracefully shutdown the SDK.
|
||||||
inline int(*v_LauncherMain)(HINSTANCE hInstance);
|
inline int(*v_LauncherMain)(HINSTANCE hInstance);
|
||||||
|
|
||||||
inline LONG(*v_TopLevelExceptionFilter)(EXCEPTION_POINTERS* pExceptionPointer);
|
inline LONG(*v_TopLevelExceptionFilter)(EXCEPTION_POINTERS* pExceptionPointer);
|
||||||
inline void(*v_RemoveSpuriousGameParameters)(void);
|
inline void(*v_RemoveSpuriousGameParameters)(void);
|
||||||
|
|
||||||
const char* ExitCodeToString(int nCode);
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
class VLauncher : public IDetour
|
class VLauncher : public IDetour
|
||||||
{
|
{
|
||||||
|
@ -39,10 +39,14 @@ static const IMAGE_DOS_HEADER* s_DosHeader = nullptr;
|
|||||||
static const IMAGE_NT_HEADERS64* s_NtHeaders = nullptr;
|
static const IMAGE_NT_HEADERS64* s_NtHeaders = nullptr;
|
||||||
static HMODULE s_SdkModule = NULL;
|
static HMODULE s_SdkModule = NULL;
|
||||||
|
|
||||||
|
typedef void (*InitFunc)(void);
|
||||||
|
static InitFunc s_SdkInitFunc = NULL;
|
||||||
|
static InitFunc s_SdkShutdownFunc = NULL;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// WinMain function pointer
|
// LauncherMain function pointer
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
static int (*v_WinMain)(HINSTANCE, HINSTANCE, LPSTR, int) = nullptr;
|
static int (*v_LauncherMain)(HINSTANCE, HINSTANCE, LPSTR, int) = nullptr;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: Terminates the process with an error when called
|
// Purpose: Terminates the process with an error when called
|
||||||
@ -100,16 +104,49 @@ static void InitGameSDK(const LPSTR lpCmdLine)
|
|||||||
{
|
{
|
||||||
Assert(0);
|
Assert(0);
|
||||||
FatalError("Failed to load SDK: error code = %08x\n", GetLastError());
|
FatalError("Failed to load SDK: error code = %08x\n", GetLastError());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_SdkInitFunc = (InitFunc)GetProcAddress(s_SdkModule, "SDK_Init");
|
||||||
|
if (s_SdkInitFunc)
|
||||||
|
s_SdkShutdownFunc = (InitFunc)GetProcAddress(s_SdkModule, "SDK_Shutdown");
|
||||||
|
|
||||||
|
if (!s_SdkInitFunc || !s_SdkShutdownFunc)
|
||||||
|
{
|
||||||
|
Assert(0);
|
||||||
|
FatalError("Loaded SDK is invalid: error code = %08x\n", GetLastError());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_SdkInitFunc();
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Purpose: Unloads the SDK module
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
static void ShutdownGameSDK()
|
||||||
|
{
|
||||||
|
if (s_SdkModule)
|
||||||
|
{
|
||||||
|
s_SdkShutdownFunc();
|
||||||
|
|
||||||
|
FreeLibrary(s_SdkModule);
|
||||||
|
s_SdkModule = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Purpose: WinMain hook; loads the SDK before LauncherMain
|
// Purpose: LauncherMain hook; loads the SDK before the game inits
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
int WINAPI hWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
int WINAPI hLauncherMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||||
{
|
{
|
||||||
InitGameSDK(lpCmdLine); // Init GameSDK, internal function calls LauncherMain.
|
InitGameSDK(lpCmdLine); // Init GameSDK, internal function calls LauncherMain.
|
||||||
return v_WinMain(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
|
const int ret = v_LauncherMain(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
|
||||||
|
ShutdownGameSDK();
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@ -120,7 +157,7 @@ static void AttachEP()
|
|||||||
DetourTransactionBegin();
|
DetourTransactionBegin();
|
||||||
DetourUpdateThread(GetCurrentThread());
|
DetourUpdateThread(GetCurrentThread());
|
||||||
|
|
||||||
DetourAttach(&v_WinMain, &hWinMain);
|
DetourAttach(&v_LauncherMain, &hLauncherMain);
|
||||||
|
|
||||||
HRESULT hr = DetourTransactionCommit();
|
HRESULT hr = DetourTransactionCommit();
|
||||||
if (hr != NO_ERROR) // Failed to hook into the process, terminate...
|
if (hr != NO_ERROR) // Failed to hook into the process, terminate...
|
||||||
@ -138,7 +175,7 @@ static void DetachEP()
|
|||||||
DetourTransactionBegin();
|
DetourTransactionBegin();
|
||||||
DetourUpdateThread(GetCurrentThread());
|
DetourUpdateThread(GetCurrentThread());
|
||||||
|
|
||||||
DetourDetach(&v_WinMain, &hWinMain);
|
DetourDetach(&v_LauncherMain, &hLauncherMain);
|
||||||
HRESULT hr = DetourTransactionCommit();
|
HRESULT hr = DetourTransactionCommit();
|
||||||
|
|
||||||
Assert(hr != NO_ERROR);
|
Assert(hr != NO_ERROR);
|
||||||
@ -159,7 +196,7 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
|
|||||||
s_NtHeaders = (IMAGE_NT_HEADERS64*)((uintptr_t)s_DosHeader
|
s_NtHeaders = (IMAGE_NT_HEADERS64*)((uintptr_t)s_DosHeader
|
||||||
+ (uintptr_t)s_DosHeader->e_lfanew);
|
+ (uintptr_t)s_DosHeader->e_lfanew);
|
||||||
|
|
||||||
v_WinMain = CModule::GetExportedSymbol((QWORD)s_DosHeader, "WinMain")
|
v_LauncherMain = CModule::GetExportedSymbol((QWORD)s_DosHeader, "LauncherMain")
|
||||||
.RCast<int (*)(HINSTANCE, HINSTANCE, LPSTR, int)>();
|
.RCast<int (*)(HINSTANCE, HINSTANCE, LPSTR, int)>();
|
||||||
|
|
||||||
AttachEP();
|
AttachEP();
|
||||||
@ -168,9 +205,6 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
|
|||||||
|
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
{
|
{
|
||||||
if (s_SdkModule)
|
|
||||||
FreeLibrary(s_SdkModule);
|
|
||||||
|
|
||||||
DetachEP();
|
DetachEP();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user