mirror of
https://github.com/UzixLS/KernelEx.git
synced 2025-07-18 23:11:19 +03:00
562 lines
14 KiB
C++
Executable File
562 lines
14 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 <algorithm>
|
|
#include "apilib.h"
|
|
#include "apiconf.h"
|
|
#include "resolver.h"
|
|
#include "internals.h"
|
|
#include "debug.h"
|
|
|
|
using namespace std;
|
|
|
|
ApiConfiguration::ApiConfiguration(const char* name)
|
|
{
|
|
initialized = prepare(name);
|
|
}
|
|
|
|
ApiConfiguration::ApiConfiguration(const char* new_name, const ApiConfiguration& src)
|
|
{
|
|
if (!prepare(new_name))
|
|
goto __error;
|
|
|
|
for (int i = 0 ; i < src.api_tables_count ; i++)
|
|
{
|
|
void* mem;
|
|
const ModuleApi& stab = src.api_tables[i];
|
|
ModuleApi& dtab = api_tables[i];
|
|
|
|
mem = malloc(stab.named_apis_count * sizeof(NamedApi));
|
|
if (!mem)
|
|
goto __error;
|
|
|
|
dtab.named_apis = (NamedApi*) mem;
|
|
dtab.named_apis_count = stab.named_apis_count;
|
|
copy(stab.named_apis, stab.named_apis + stab.named_apis_count,
|
|
dtab.named_apis);
|
|
|
|
mem = malloc(stab.unnamed_apis_count * sizeof(PROC));
|
|
if (!mem)
|
|
goto __error;
|
|
|
|
dtab.unnamed_apis = (PDWORD) mem;
|
|
dtab.unnamed_apis_count = stab.unnamed_apis_count;
|
|
copy(stab.unnamed_apis, stab.unnamed_apis + stab.unnamed_apis_count,
|
|
dtab.unnamed_apis);
|
|
}
|
|
|
|
initialized = true;
|
|
return;
|
|
|
|
__error:
|
|
initialized = false;
|
|
}
|
|
|
|
ApiConfiguration::~ApiConfiguration()
|
|
{
|
|
for (int i = 0 ; i < api_tables_count ; i++)
|
|
{
|
|
free(api_tables[i].named_apis);
|
|
free(api_tables[i].unnamed_apis);
|
|
}
|
|
free(conf_name);
|
|
free(api_tables);
|
|
}
|
|
|
|
bool ApiConfiguration::prepare(const char* name)
|
|
{
|
|
int size = strlen(name) + 1;
|
|
conf_name = (char*) malloc(size);
|
|
if (!conf_name)
|
|
return false;
|
|
|
|
strcpy(conf_name, name);
|
|
|
|
api_tables = (ModuleApi*) calloc(overridden_module_count, sizeof(ModuleApi));
|
|
if (!api_tables)
|
|
return false;
|
|
|
|
api_tables_count = overridden_module_count;
|
|
return true;
|
|
}
|
|
|
|
bool ApiConfiguration::merge(const ApiLibrary* apilib)
|
|
{
|
|
if (!apilib)
|
|
return false;
|
|
|
|
for (int i = 0 ; i < overridden_module_count ; i++)
|
|
{
|
|
const apilib_api_table* psrc = apilib->api_tables;
|
|
while (psrc->target_library)
|
|
{
|
|
if (!strcmpi(psrc->target_library, overridden_module_names[i]))
|
|
{
|
|
if (i >= api_tables_count)
|
|
{
|
|
void* mem = recalloc(api_tables, overridden_module_count * sizeof(ModuleApi));
|
|
if (!mem)
|
|
return false;
|
|
api_tables = (ModuleApi*) mem;
|
|
api_tables_count = overridden_module_count;
|
|
}
|
|
ModuleApi* pdst = api_tables + i;
|
|
|
|
//join ordinal apis
|
|
|
|
unsigned short max_ord;
|
|
if (psrc->ordinal_apis_count)
|
|
max_ord = psrc->ordinal_apis[psrc->ordinal_apis_count - 1].ord;
|
|
else
|
|
max_ord = 0;
|
|
|
|
if (pdst->unnamed_apis_count < max_ord)
|
|
{
|
|
void* mem = recalloc(pdst->unnamed_apis, max_ord * sizeof(PROC));
|
|
if (!mem)
|
|
return false;
|
|
pdst->unnamed_apis = (PDWORD) mem;
|
|
pdst->unnamed_apis_count = max_ord;
|
|
}
|
|
|
|
//join tables
|
|
for (int i = psrc->ordinal_apis_count - 1 ; i >= 0 ; i--)
|
|
{
|
|
const apilib_unnamed_api& pua = psrc->ordinal_apis[i];
|
|
pdst->unnamed_apis[pua.ord - 1] = encode_address(pua.addr, apilib);
|
|
}
|
|
|
|
//join named apis
|
|
|
|
const apilib_named_api* sfirst = psrc->named_apis;
|
|
const apilib_named_api* slast = sfirst + psrc->named_apis_count;
|
|
NamedApi* dfirst = pdst->named_apis;
|
|
NamedApi* dlast = dfirst + pdst->named_apis_count;
|
|
|
|
//check how much space is needed first
|
|
int space = 0;
|
|
while (sfirst != slast && dfirst != dlast)
|
|
{
|
|
int cmp_result = strcmp(dfirst->api_name, sfirst->name);
|
|
if (cmp_result < 0)
|
|
{
|
|
dfirst++;
|
|
}
|
|
else if (cmp_result == 0)
|
|
{
|
|
dfirst++;
|
|
sfirst++;
|
|
while (sfirst != slast && !strcmp(sfirst->name, (sfirst - 1)->name))
|
|
sfirst++;
|
|
}
|
|
else
|
|
{
|
|
space++;
|
|
sfirst++;
|
|
while (sfirst != slast && !strcmp(sfirst->name, (sfirst - 1)->name))
|
|
sfirst++;
|
|
}
|
|
}
|
|
|
|
//entries after end of dest
|
|
while (sfirst != slast)
|
|
{
|
|
sfirst++;
|
|
space++;
|
|
while (sfirst != slast && !strcmp(sfirst->name, (sfirst - 1)->name))
|
|
sfirst++;
|
|
}
|
|
|
|
//allocate new mem
|
|
if (space)
|
|
{
|
|
void* mem = realloc(pdst->named_apis,
|
|
(pdst->named_apis_count + space) * sizeof(NamedApi));
|
|
if (!mem)
|
|
return false;
|
|
|
|
pdst->named_apis = (NamedApi*) mem;
|
|
}
|
|
|
|
sfirst = psrc->named_apis;
|
|
dfirst = pdst->named_apis;
|
|
dlast = dfirst + pdst->named_apis_count;
|
|
pdst->named_apis_count += space;
|
|
|
|
//join tables
|
|
while (sfirst != slast && dfirst != dlast)
|
|
{
|
|
int cmp_result = strcmp(dfirst->api_name, sfirst->name);
|
|
if (cmp_result < 0)
|
|
dfirst++;
|
|
else if (cmp_result == 0)
|
|
{
|
|
//same apis => update address
|
|
(dfirst++)->address = encode_address((sfirst++)->addr, apilib);
|
|
while (sfirst != slast && !strcmp(sfirst->name, (sfirst - 1)->name))
|
|
sfirst++;
|
|
}
|
|
else //cmp_result > 0
|
|
{
|
|
//insert new api
|
|
copy_backward(dfirst, dlast, dlast + 1);
|
|
dlast++;
|
|
dfirst->api_name = sfirst->name;
|
|
dfirst->address = encode_address(sfirst->addr, apilib);
|
|
dfirst++;
|
|
sfirst++;
|
|
while (sfirst != slast && !strcmp(sfirst->name, (sfirst - 1)->name))
|
|
sfirst++;
|
|
}
|
|
}
|
|
|
|
//entries after end of dest
|
|
while (sfirst != slast)
|
|
{
|
|
dfirst->api_name = sfirst->name;
|
|
dfirst->address = encode_address(sfirst->addr, apilib);
|
|
dfirst++;
|
|
sfirst++;
|
|
while (sfirst != slast && !strcmp(sfirst->name, (sfirst - 1)->name))
|
|
sfirst++;
|
|
}
|
|
|
|
break;
|
|
}
|
|
psrc++;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ApiConfiguration::merge(const char* module, unsigned short ordinal,
|
|
const ApiLibrary* apilib, int id)
|
|
{
|
|
if (!apilib)
|
|
return false;
|
|
|
|
const apilib_api_table* psrc = apilib->api_tables;
|
|
|
|
while (psrc->target_library)
|
|
{
|
|
if (!strcmpi(module, psrc->target_library))
|
|
break;
|
|
psrc++;
|
|
}
|
|
|
|
if (!psrc->target_library)
|
|
return false;
|
|
|
|
apilib_unnamed_api to_find;
|
|
to_find.ord = ordinal;
|
|
|
|
const apilib_unnamed_api* first = psrc->ordinal_apis;
|
|
const apilib_unnamed_api* last = first + psrc->ordinal_apis_count;
|
|
|
|
const apilib_unnamed_api* low = lower_bound(first, last, to_find);
|
|
|
|
if (low == last || to_find < *low)
|
|
return false;
|
|
|
|
low += id;
|
|
|
|
if (low >= last || to_find < *low)
|
|
return false;
|
|
|
|
int i;
|
|
for (i = 0 ; i < overridden_module_count ; i++)
|
|
if (!strcmpi(module, overridden_module_names[i]))
|
|
break;
|
|
|
|
if (i == overridden_module_count)
|
|
return false;
|
|
|
|
if (api_tables_count <= i)
|
|
{
|
|
void* mem = recalloc(api_tables, overridden_module_count * sizeof(ModuleApi));
|
|
if (!mem)
|
|
return false;
|
|
api_tables = (ModuleApi*) mem;
|
|
api_tables_count = overridden_module_count;
|
|
}
|
|
|
|
ModuleApi* pdst = api_tables + i;
|
|
if (pdst->unnamed_apis_count < ordinal)
|
|
{
|
|
void* mem = recalloc(pdst->unnamed_apis, ordinal * sizeof(PROC));
|
|
if (!mem)
|
|
return false;
|
|
pdst->unnamed_apis = (PDWORD) mem;
|
|
pdst->unnamed_apis_count = ordinal;
|
|
}
|
|
|
|
pdst->unnamed_apis[ordinal - 1] = encode_address(low->addr, apilib);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ApiConfiguration::merge(const char* module, const char* api_name,
|
|
const ApiLibrary* apilib, int id)
|
|
{
|
|
if (!apilib)
|
|
return false;
|
|
|
|
const apilib_api_table* psrc = apilib->api_tables;
|
|
|
|
while (psrc->target_library)
|
|
{
|
|
if (!strcmpi(module, psrc->target_library))
|
|
break;
|
|
psrc++;
|
|
}
|
|
|
|
if (!psrc->target_library)
|
|
return false;
|
|
|
|
apilib_named_api to_find;
|
|
to_find.name = api_name;
|
|
|
|
const apilib_named_api* first = psrc->named_apis;
|
|
const apilib_named_api* last = first + psrc->named_apis_count;
|
|
|
|
const apilib_named_api* low = lower_bound(first, last, to_find);
|
|
|
|
if (low == last || to_find < *low)
|
|
return false;
|
|
|
|
low += id;
|
|
|
|
if (low >= last || to_find < *low)
|
|
return false;
|
|
|
|
int i;
|
|
for (i = 0 ; i < overridden_module_count ; i++)
|
|
if (!strcmpi(module, overridden_module_names[i]))
|
|
break;
|
|
|
|
if (i == overridden_module_count)
|
|
return false;
|
|
|
|
if (api_tables_count <= i)
|
|
{
|
|
void* mem = recalloc(api_tables, overridden_module_count * sizeof(ModuleApi));
|
|
if (!mem)
|
|
return false;
|
|
api_tables = (ModuleApi*) mem;
|
|
api_tables_count = overridden_module_count;
|
|
}
|
|
|
|
ModuleApi* pdst = api_tables + i;
|
|
NamedApi* dfirst = pdst->named_apis;
|
|
NamedApi* dlast = dfirst + pdst->named_apis_count;
|
|
|
|
NamedApi dto_find;
|
|
dto_find.api_name = api_name;
|
|
|
|
NamedApi* dlow = lower_bound(dfirst, dlast, dto_find);
|
|
|
|
//scenario 1: existing entry
|
|
if (dlow < dlast && !(dto_find < *dlow))
|
|
{
|
|
dlow->address = encode_address(low->addr, apilib);
|
|
}
|
|
//scenario 2: no matching entry
|
|
else
|
|
{
|
|
void* mem = realloc(pdst->named_apis,
|
|
(pdst->named_apis_count + 1) * sizeof(NamedApi));
|
|
if (!mem)
|
|
return false;
|
|
|
|
pdst->named_apis = (NamedApi*) mem;
|
|
pdst->named_apis_count++;
|
|
|
|
dlow = (NamedApi*)((DWORD) dlow - (DWORD) dfirst + (DWORD) pdst->named_apis);
|
|
dfirst = pdst->named_apis;
|
|
dlast = dfirst + pdst->named_apis_count;
|
|
copy_backward(dlow, dlast - 1, dlast);
|
|
dlow->api_name = low->name;
|
|
dlow->address = encode_address(low->addr, apilib);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ApiConfiguration::erase(const char* module, unsigned short ordinal)
|
|
{
|
|
int i;
|
|
for (i = 0 ; i < overridden_module_count ; i++)
|
|
if (!strcmpi(module, overridden_module_names[i]))
|
|
break;
|
|
|
|
if (i == overridden_module_count || i >= api_tables_count)
|
|
return false;
|
|
|
|
ModuleApi* pdst = api_tables + i;
|
|
if (pdst->unnamed_apis_count < ordinal)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
pdst->unnamed_apis[ordinal - 1] = 0;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ApiConfiguration::erase(const char* module, const char* api_name)
|
|
{
|
|
int i;
|
|
for (i = 0 ; i < overridden_module_count ; i++)
|
|
if (!strcmpi(module, overridden_module_names[i]))
|
|
break;
|
|
|
|
if (i == overridden_module_count || i >= api_tables_count)
|
|
return false;
|
|
|
|
ModuleApi* pdst = api_tables + i;
|
|
NamedApi* dfirst = pdst->named_apis;
|
|
NamedApi* dlast = dfirst + pdst->named_apis_count;
|
|
|
|
NamedApi dto_find;
|
|
dto_find.api_name = api_name;
|
|
|
|
NamedApi* dlow = lower_bound(dfirst, dlast, dto_find);
|
|
|
|
if (dlow >= dlast || dto_find < *dlow)
|
|
return false;
|
|
|
|
copy(dlow + 1, dlast, dlow);
|
|
pdst->named_apis_count--;
|
|
//should I realloc memory after deleting entry?
|
|
|
|
return true;
|
|
}
|
|
|
|
/** Get api address given api table number and api name.
|
|
* @param table_id Valid api table number.
|
|
* @param hint Loader hint.
|
|
* @param api_name Api name.
|
|
* @return Api address or 0 if api address not found.
|
|
*/
|
|
unsigned long ApiConfiguration::get(unsigned short table_id,
|
|
unsigned short hint, const char* api_name)
|
|
{
|
|
NamedApi* named_apis;
|
|
unsigned short named_apis_count;
|
|
int lo, hi, curr;
|
|
|
|
named_apis = api_tables[table_id].named_apis;
|
|
named_apis_count = api_tables[table_id].named_apis_count;
|
|
|
|
if (hint < named_apis_count)
|
|
{
|
|
int res = strcmp(api_name, named_apis[hint].api_name);
|
|
if (res > 0)
|
|
{
|
|
lo = hint + 1;
|
|
hi = named_apis_count - 1;
|
|
}
|
|
else if (res < 0)
|
|
{
|
|
lo = 0;
|
|
hi = hint - 1;
|
|
}
|
|
else
|
|
{
|
|
return named_apis[hint].address;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lo = 0;
|
|
hi = named_apis_count - 1;
|
|
}
|
|
curr = (hi + lo) >> 1;
|
|
|
|
while (lo <= hi)
|
|
{
|
|
int res = strcmp(api_name, named_apis[curr].api_name);
|
|
if (res > 0)
|
|
{
|
|
lo = curr + 1;
|
|
}
|
|
else if (res < 0)
|
|
{
|
|
hi = curr - 1;
|
|
}
|
|
else
|
|
{
|
|
return named_apis[curr].address;
|
|
}
|
|
curr = (hi + lo) >> 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/** Get api address given api table number and api ordinal.
|
|
* @param table_id Valid api table number.
|
|
* @param api_ordinal Api ordinal number.
|
|
* @return Api address or 0 if api address not found.
|
|
*/
|
|
unsigned long ApiConfiguration::get(unsigned short table_id,
|
|
unsigned short api_ordinal)
|
|
{
|
|
unsigned long* unnamed_apis;
|
|
unsigned short unnamed_apis_count;
|
|
|
|
unnamed_apis = api_tables[table_id].unnamed_apis;
|
|
unnamed_apis_count = api_tables[table_id].unnamed_apis_count;
|
|
|
|
if (api_ordinal > unnamed_apis_count)
|
|
return 0;
|
|
|
|
return unnamed_apis[api_ordinal - 1];
|
|
}
|
|
|
|
bool ApiConfiguration::is_initialized()
|
|
{
|
|
return initialized;
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
|
|
void ApiConfiguration::dump()
|
|
{
|
|
printf("ApiConfiguration %s\n", get_name());
|
|
for (int i = 0 ; i < api_tables_count ; i++)
|
|
{
|
|
printf("Covered module #%d: %s\n", i, overridden_module_names[i]);
|
|
printf("Named apis (count = %d)\n", api_tables[i].named_apis_count);
|
|
for (int j = 0 ; j < api_tables[i].named_apis_count ; j++)
|
|
printf("\t%-32s %08x\n", api_tables[i].named_apis[j].api_name,
|
|
api_tables[i].named_apis[j].address);
|
|
printf("Unnamed apis (count = %d)\n", api_tables[i].unnamed_apis_count);
|
|
for (int j = 0 ; j < api_tables[i].unnamed_apis_count ; j++)
|
|
printf("\t%-5d %08x\n", j, api_tables[i].unnamed_apis[j]);
|
|
printf("\n");
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
#endif
|