1
0
mirror of https://github.com/UzixLS/KernelEx.git synced 2025-07-19 07:21:20 +03:00
Files
KernelEx/core/main.cpp
2018-11-03 16:21:13 +03:00

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;
}