mirror of
https://github.com/UzixLS/KernelEx.git
synced 2025-07-19 07:21:20 +03:00
267 lines
6.1 KiB
C++
Executable File
267 lines
6.1 KiB
C++
Executable File
/*
|
|
* 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"
|
|
#include "DebugWindow.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();
|
|
|
|
extern BOOL resolver_process_attach();
|
|
|
|
static int init_count = 0;
|
|
|
|
//these should be visible externally 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;
|
|
|
|
if (!apiconfmgr.load_api_configurations())
|
|
goto __error2;
|
|
|
|
if (!resolver_init())
|
|
goto __error2;
|
|
|
|
resolver_hook();
|
|
|
|
#ifdef _DEBUG
|
|
DebugWindow::create();
|
|
#endif
|
|
|
|
DBGPRINTF(("Initialized successfully\n"));
|
|
return ++init_count;
|
|
|
|
__error2:
|
|
internals_uninit();
|
|
__error1:
|
|
DBGPRINTF(("Initialization failure\n"));
|
|
return 0;
|
|
}
|
|
|
|
//these should be visible externally 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();
|
|
#ifdef _DEBUG
|
|
DebugWindow::destroy();
|
|
#endif
|
|
internals_uninit();
|
|
return --init_count;
|
|
}
|
|
|
|
extern "C" _KEXCOREIMP
|
|
DWORD WINAPI MprStart(LPVOID)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
void load_MPRServices()
|
|
{
|
|
char subkey[200];
|
|
char dllname[MAX_PATH];
|
|
HKEY hk_serv;
|
|
HKEY hk_this;
|
|
DWORD size;
|
|
DWORD index = 0;
|
|
|
|
if (RegOpenKey(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\MPRServices",
|
|
&hk_serv) != ERROR_SUCCESS)
|
|
return;
|
|
while (RegEnumKey(hk_serv, index, subkey, sizeof(subkey)) == ERROR_SUCCESS)
|
|
{
|
|
RegOpenKey(hk_serv, subkey, &hk_this);
|
|
size = sizeof(dllname);
|
|
if (RegQueryValueEx(hk_this, "DllName", NULL, NULL, (BYTE*)dllname, &size)
|
|
== ERROR_SUCCESS)
|
|
{
|
|
LoadLibrary(dllname);
|
|
}
|
|
RegCloseKey(hk_this);
|
|
index++;
|
|
}
|
|
RegCloseKey(hk_serv);
|
|
}
|
|
|
|
/** 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 (!IS_SHARED(addr))
|
|
{
|
|
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()
|
|
{
|
|
char path[MAX_PATH];
|
|
GetModuleFileName(hInstance, 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)
|
|
{
|
|
DisableThreadLibraryCalls(instance);
|
|
|
|
if (load_count((DWORD) instance) == 1)
|
|
{
|
|
//first reference => do init
|
|
hInstance = instance;
|
|
|
|
if (!ensure_shared_memory((DWORD)instance))
|
|
return FALSE;
|
|
|
|
if (is_failsafe_mode())
|
|
return FALSE;
|
|
|
|
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();
|
|
}
|
|
else
|
|
{
|
|
//referenced by other module => call resolver
|
|
ret = resolver_process_attach();
|
|
}
|
|
}
|
|
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"))
|
|
{
|
|
//auto start if loaded by MPREXE
|
|
|
|
//load all other MPR services before further execution
|
|
load_MPRServices();
|
|
|
|
//initialize
|
|
if (!kexInit())
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//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;
|
|
}
|
|
|