mirror of
https://github.com/UzixLS/KernelEx.git
synced 2025-07-19 07:21:20 +03:00
218 lines
4.9 KiB
C++
218 lines
4.9 KiB
C++
/*
|
|
* KernelEx
|
|
* Copyright (C) 2008-2009, Xeno86
|
|
*
|
|
* This file is part of KernelEx source code.
|
|
*
|
|
* KernelEx is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published
|
|
* by the Free Software Foundation; version 2 of the License.
|
|
*
|
|
* KernelEx is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with GNU Make; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#include "version.h"
|
|
#include "kexcoresdk.h"
|
|
#include "debug.h"
|
|
#include "apiconfmgr.h"
|
|
#include "internals.h"
|
|
|
|
extern int internals_init();
|
|
extern void internals_uninit();
|
|
extern int resolver_init();
|
|
extern void resolver_uninit();
|
|
extern void resolver_hook();
|
|
extern void resolver_unhook();
|
|
|
|
static int init_count = 0;
|
|
|
|
static void prepare()
|
|
{
|
|
ApiConfigurationManager acm;
|
|
acm.reload_api_configurations();
|
|
}
|
|
|
|
//these should be visible only in debug builds
|
|
#ifdef _DEBUG
|
|
extern "C" _KEXCOREIMP
|
|
#endif
|
|
int kexInit()
|
|
{
|
|
if (init_count > 0)
|
|
return ++init_count;
|
|
|
|
DBGPRINTF(("KernelEx Core v%s by Xeno86\n", VERSION_STR));
|
|
DBGPRINTF(("Initializing...\n"));
|
|
|
|
if (!internals_init())
|
|
goto __error1;
|
|
|
|
prepare();
|
|
|
|
if (!resolver_init())
|
|
goto __error2;
|
|
|
|
resolver_hook();
|
|
|
|
DBGPRINTF(("Initialized successfully\n"));
|
|
return ++init_count;
|
|
|
|
__error2:
|
|
internals_uninit();
|
|
__error1:
|
|
DBGPRINTF(("Initialization failure\n"));
|
|
return 0;
|
|
}
|
|
|
|
//these should be visible only in debug builds
|
|
#ifdef _DEBUG
|
|
extern "C" _KEXCOREIMP
|
|
#endif
|
|
int kexUninit()
|
|
{
|
|
if (init_count == 0)
|
|
return 0;
|
|
if (init_count > 1)
|
|
return --init_count;
|
|
|
|
DBGPRINTF(("Uninitializing\n"));
|
|
resolver_unhook();
|
|
resolver_uninit();
|
|
internals_uninit();
|
|
return --init_count;
|
|
}
|
|
|
|
extern "C" _KEXCOREIMP
|
|
DWORD WINAPI MprStart(LPVOID)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/** Check if loaded into shared memory area.
|
|
* @param addr Address to which loaded.
|
|
* @return TRUE if loaded to shared memory, FALSE otherwise.
|
|
*/
|
|
static bool ensure_shared_memory(DWORD addr)
|
|
{
|
|
if (addr < 0x80000000)
|
|
{
|
|
MessageBox(NULL, "KernelEx not loaded into shared memory!",
|
|
"Critical Error", MB_ICONERROR | MB_OK);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool is_failsafe_mode()
|
|
{
|
|
return GetSystemMetrics(SM_CLEANBOOT) != 0;
|
|
}
|
|
|
|
static int load_count(DWORD addr)
|
|
{
|
|
if (!ppmteModTable)
|
|
return 1;
|
|
IMTE** pmteModTable = *ppmteModTable;
|
|
return pmteModTable[MRfromCallerAddr(addr)->mteIndex]->cUsage;
|
|
}
|
|
|
|
static void get_own_path(HMODULE base)
|
|
{
|
|
char path[MAX_PATH];
|
|
GetModuleFileName(base, path, sizeof(path));
|
|
own_path = path;
|
|
}
|
|
|
|
static bool detect_old_version()
|
|
{
|
|
typedef void (WINAPI *KV_t)(char *);
|
|
KV_t h_KVersion;
|
|
char buf[32];
|
|
|
|
h_KVersion = (KV_t)GetProcAddress(GetModuleHandle("kernel32"), "KUPVersion");
|
|
if (!h_KVersion)
|
|
h_KVersion = (KV_t)GetProcAddress(GetModuleHandle("kernel32"), "KEXVersion");
|
|
if (!h_KVersion)
|
|
return false;
|
|
h_KVersion(buf);
|
|
ShowError(IDS_OLDVER, buf);
|
|
return true;
|
|
}
|
|
|
|
/** CRT startup routine declaration. */
|
|
extern "C"
|
|
BOOL WINAPI _DllMainCRTStartup(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
|
|
|
|
/** Pre-init code executed before CRT startup code. */
|
|
extern "C"
|
|
BOOL APIENTRY PreDllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
|
|
{
|
|
BOOL ret = TRUE;
|
|
|
|
if (reason == DLL_PROCESS_ATTACH)
|
|
{
|
|
if (!ensure_shared_memory((DWORD)instance))
|
|
return FALSE;
|
|
|
|
if (is_failsafe_mode())
|
|
return FALSE;
|
|
|
|
DisableThreadLibraryCalls(instance);
|
|
|
|
if (load_count((DWORD) instance) == 1)
|
|
{
|
|
if (detect_old_version())
|
|
return FALSE;
|
|
|
|
//very important - without this memory allocation won't work
|
|
if (!create_shared_heap())
|
|
return FALSE;
|
|
|
|
//we are in shared memory so CRT init code should be called only once
|
|
//globally (by default it would be called on every process attach)
|
|
ret = _DllMainCRTStartup(instance, reason, reserved);
|
|
|
|
get_own_path(instance);
|
|
}
|
|
}
|
|
else if (reason == DLL_PROCESS_DETACH)
|
|
{
|
|
if (load_count((DWORD) instance) == 1)
|
|
{
|
|
ret = _DllMainCRTStartup(instance, reason, reserved);
|
|
destroy_shared_heap();
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/** Entry point. Called by CRT startup code. */
|
|
extern "C"
|
|
BOOL APIENTRY DllMain(HINSTANCE instance, DWORD reason, BOOL load_static)
|
|
{
|
|
if (reason == DLL_PROCESS_ATTACH && GetModuleHandle("MPREXE.EXE"))
|
|
{
|
|
return kexInit();
|
|
}
|
|
|
|
//for additional safety - auto uninit on core unload
|
|
if (reason == DLL_PROCESS_DETACH
|
|
&& load_count((DWORD) instance) == 1 && init_count > 0)
|
|
{
|
|
init_count = 1;
|
|
kexUninit();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|