1
0
mirror of https://github.com/UzixLS/KernelEx.git synced 2025-07-18 23:11:19 +03:00
Files
KernelEx/core/apiconfmgr.cpp
2018-11-03 16:23:17 +03:00

432 lines
9.7 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 <stdio.h>
#include <malloc.h>
#include "debug.h"
#include "SettingsDB.h"
#include "internals.h"
#include "resolver.h"
#include "apiconfmgr.h"
#define ALLOC_CAPACITY 10
ApiConfigurationManager apiconfmgr;
ApiConfigurationManager::ApiConfigurationManager()
{
apiconf_ptrs = NULL;
apiconf_cnt = 0;
default_apiconf = NULL;
disable_extensions = false;
}
ApiConfigurationManager::~ApiConfigurationManager()
{
for (int i = 0 ; i < apiconf_cnt ; i++)
delete apiconf_ptrs[i];
if (apiconf_ptrs)
free(apiconf_ptrs);
}
bool ApiConfigurationManager::add_apiconf(ApiConfiguration* ac)
{
//allocate space for new ApiConfigurations
if (apiconf_cnt % ALLOC_CAPACITY == 0)
{
void* new_block = realloc(apiconf_ptrs,
(apiconf_cnt + ALLOC_CAPACITY) * sizeof(ApiConfiguration*));
if (!new_block)
{
DBGPRINTF(("Failed to add api configuration to list of new ACs\n"));
return false;
}
apiconf_ptrs = (ApiConfiguration**) new_block;
}
//add to table of new ApiConfigurations
apiconf_ptrs[apiconf_cnt++] = ac;
return true;
}
ApiConfiguration* ApiConfigurationManager::get_api_configuration(const char* conf_name)
{
for (int i = 0 ; i < apiconf_cnt ; i++)
if (!strcmp(apiconf_ptrs[i]->conf_name, conf_name))
return apiconf_ptrs[i];
return NULL;
}
bool ApiConfigurationManager::load_api_configurations()
{
strcpy(core_conf_file, kernelex_dir);
strcat(core_conf_file, "core.ini");
DBGPRINTF(("Loading api configurations\n"));
HKEY key;
LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
"Software\\KernelEx", 0, KEY_WRITE, &key);
if (result == ERROR_SUCCESS)
{
DWORD type, data, size = sizeof(data);
RegQueryValueEx(key, "DisableExtensions", NULL, &type, (BYTE*) &data, &size);
if (result == ERROR_SUCCESS && type == REG_DWORD && size == sizeof(data) && data == 1)
disable_extensions = true;
RegCloseKey(key);
}
int default_apiconf_index = GetPrivateProfileInt(
"ApiConfigurations", "default", 0, core_conf_file);
for (int i = 0 ; i < 65536 ; i++)
{
char num[6];
char apiconf_name[256];
ApiConfiguration* apiconf = NULL;
sprintf(num, "%d", i);
if (!GetPrivateProfileString("ApiConfigurations", num, "",
apiconf_name, sizeof(apiconf_name), core_conf_file))
{
//no more entries
if (i <= default_apiconf_index)
{
DBGPRINTF(("Failed to load default api configuration - aborting\n"));
return false;
}
break;
}
DBGPRINTF(("Processing api configuration #%s: %s\n", num, apiconf_name));
char buf[256];
if (!GetPrivateProfileString(apiconf_name, "inherit", "", buf,
sizeof(buf), core_conf_file) || !strcmpi(buf, "none"))
{
//no inherit
apiconf = new ApiConfiguration(apiconf_name);
}
else
{
ApiConfiguration* src_conf = get_api_configuration(buf);
if (!src_conf)
{
DBGPRINTF(("Cannot inherit: %s. Configuration not found\n", buf));
goto __error;
}
apiconf = new ApiConfiguration(apiconf_name, *src_conf);
}
if (!apiconf || !apiconf->is_initialized())
{
DBGPRINTF(("Failed to create new api configuration object\n"));
goto __error;
}
if (!join_apilibs(apiconf) || !parse_overrides(apiconf) || !add_apiconf(apiconf))
goto __error;
continue;
__error:
if (apiconf)
delete apiconf;
if (i == default_apiconf_index)
{
DBGPRINTF(("Failed to load default api configuration - aborting\n"));
return false;
}
} //for loop
DBGPRINTF(("No more api configurations\n"));
//set default apiconf
if (default_apiconf_index >= 0)
default_apiconf = apiconf_ptrs[default_apiconf_index];
else
{
DBGPRINTF(("Failed to load default api configuration - aborting\n"));
return false;
}
DBGPRINTF(("Default api configuration is: %s\n", default_apiconf->get_name()));
DBGPRINTF(("API extensions are by default: %s\n",
disable_extensions ? "disabled" : "enabled"));
SettingsDB::instance.flush_all();
return true;
}
bool ApiConfigurationManager::join_apilibs(ApiConfiguration* apiconf)
{
char buf[256];
if (GetPrivateProfileString(apiconf->get_name(), "contents", "",
buf, sizeof(buf), core_conf_file) && strcmpi(buf, "none") != 0)
{
char buf2[256];
strupr(buf);
strcpy(buf2, buf);
char* lib = strtok(buf, ",");
while (lib)
{
if (!apilibmgr.load_apilib(lib))
{
DBGPRINTF(("Failed to load api library: %s\n", lib));
return false;
}
lib = strtok(NULL, ",");
}
//merge has to be done in a separate loop because STD
//api library is based on other loaded api libraries
lib = strtok(buf2, ",");
while (lib)
{
if (!apiconf->merge(apilibmgr.get_apilib(lib)))
{
DBGPRINTF(("Failed to merge api library: %s\n", lib));
return false;
}
lib = strtok(NULL, ",");
}
}
return true;
}
bool ApiConfigurationManager::parse_overrides(ApiConfiguration* apiconf)
{
//parse names and ordinal overrides
char buf[MAX_PATH];
char section_data[32767];
DWORD res;
//first try [conf.names.xx]
strcpy(buf, apiconf->get_name());
strcat(buf, ".names");
if (isWinMe())
strcat(buf, ".me");
else
strcat(buf, ".98");
res = GetPrivateProfileSection(buf, section_data, sizeof(section_data),
core_conf_file);
//else try [conf.names]
if (!res)
{
strcpy(buf, apiconf->get_name());
strcat(buf, ".names");
res = GetPrivateProfileSection(buf, section_data, sizeof(section_data),
core_conf_file);
}
if (res)
{
DBGPRINTF(("Parsing named api overrides\n"));
char* line = section_data;
while (*line)
{
char* module;
char* api_name;
char* apilib_name;
int id;
char* p = line;
char* oldline = line;
line += strlen(line) + 1;
module = p;
p = strchr(p, '.');
if (!p)
{
DBGPRINTF(("Error parsing line: %s\n", oldline));
continue;
}
*p++ = '\0';
strcpy(buf, module);
strcat(buf, ".DLL");
module = buf;
api_name = p;
p = strchr(p, '=');
if (!p)
{
DBGPRINTF(("Error parsing line: %s\n", oldline));
continue;
}
*p++ = '\0';
apilib_name = p;
p = strchr(p, '.');
if (!p)
id = 0;
else
{
*p++ = '\0';
id = atoi(p);
if (id < 0)
{
DBGPRINTF(("Error parsing line: %s\n", oldline));
continue;
}
}
strupr(apilib_name);
if (!strcmp(apilib_name, "NONE"))
{
if (!apiconf->erase(module, api_name))
{
DBGPRINTF(("Failed to merge named api overrides\n"));
return false;
}
}
else
{
if (!apiconf->merge(module, api_name,
apilibmgr.get_apilib(apilib_name), id))
{
DBGPRINTF(("Failed to merge named api overrides\n"));
return false;
}
}
}
}
//first try [conf.ordinals.xx]
strcpy(buf, apiconf->get_name());
strcat(buf, ".ordinals");
if (isWinMe())
strcat(buf, ".me");
else
strcat(buf, ".98");
//else try [conf.ordinals]
res = GetPrivateProfileSection(buf, section_data, sizeof(section_data),
core_conf_file);
if (!res)
{
strcpy(buf, apiconf->get_name());
strcat(buf, ".ordinals");
res = GetPrivateProfileSection(buf, section_data, sizeof(section_data),
core_conf_file);
}
if (res)
{
DBGPRINTF(("Parsing ordinal api overrides\n"));
char* line = section_data;
while (*line)
{
char* module;
char* ordinal_s;
int ordinal;
char* apilib_name;
int id;
char* p = line;
char* oldline = line;
line += strlen(line) + 1;
module = p;
p = strchr(p, '.');
if (!p)
{
DBGPRINTF(("Error parsing line: %s\n", oldline));
continue;
}
*p++ = '\0';
strcpy(buf, module);
strcat(buf, ".DLL");
module = buf;
ordinal_s = p;
p = strchr(p, '=');
if (!p)
{
DBGPRINTF(("Error parsing line: %s\n", oldline));
continue;
}
*p++ = '\0';
ordinal = atoi(ordinal_s);
if (ordinal < 1 || ordinal > 65535)
{
DBGPRINTF(("Error parsing line: %s\n", oldline));
continue;
}
apilib_name = p;
p = strchr(p, '.');
if (!p)
id = 0;
else
{
*p++ = '\0';
id = atoi(p);
if (id < 0)
{
DBGPRINTF(("Error parsing line: %s\n", oldline));
continue;
}
}
strupr(apilib_name);
if (!strcmp(apilib_name, "NONE"))
{
if (!apiconf->erase(module, (WORD) ordinal))
{
DBGPRINTF(("Failed to merge ordinal api overrides\n"));
return false;
}
}
else
{
if (!apiconf->merge(module, (WORD) ordinal,
apilibmgr.get_apilib(apilib_name), id))
{
DBGPRINTF(("Failed to merge ordinal api overrides\n"));
return false;
}
}
}
}
return true;
}
#ifdef _DEBUG
void ApiConfigurationManager::dump_configurations()
{
printf("Dumping all api configurations (count = %d) ...\n\n", apiconf_cnt);
for (int i = 0 ; i < apiconf_cnt ; i++)
{
apiconf_ptrs[i]->dump();
}
printf("End dump\n\n");
}
#endif