|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
/* ntapi: Native API core library */
|
|
|
64e606 |
/* Copyright (C) 2013--2021 SysDeer Technologies, LLC */
|
|
|
dd89bb |
/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
|
|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
#include <psxtypes/psxtypes.h>
|
|
|
dd89bb |
#include <pemagine/pemagine.h>
|
|
|
dd89bb |
#include <dalist/dalist.h>
|
|
|
dd89bb |
#include <ntapi/ntapi.h>
|
|
|
dd89bb |
#include "ntapi_impl.h"
|
|
|
dd89bb |
|
|
|
dd89bb |
struct callback_ctx {
|
|
|
dd89bb |
struct dalist_ex * ldr_state_snapshot;
|
|
|
dd89bb |
struct pe_ldr_tbl_entry * ldr_tbl_entry;
|
|
|
dd89bb |
void * image_base;
|
|
|
dd89bb |
uint32_t load_count;
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
};
|
|
|
dd89bb |
|
|
|
dd89bb |
static int __cdecl __find_next_module_to_unload(
|
|
|
dd89bb |
struct pe_ldr_tbl_entry * ldr_tbl_entry,
|
|
|
dd89bb |
enum pe_callback_reason int_callback_reason,
|
|
|
dd89bb |
void * context)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
struct dalist_node * node;
|
|
|
dd89bb |
struct callback_ctx * ctx;
|
|
|
dd89bb |
|
|
|
dd89bb |
ctx = (struct callback_ctx *)context;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (int_callback_reason == PE_CALLBACK_REASON_ERROR) {
|
|
|
dd89bb |
ctx->status = NT_STATUS_UNSUCCESSFUL;
|
|
|
dd89bb |
return ctx->status;
|
|
|
dd89bb |
} else if (int_callback_reason != PE_CALLBACK_REASON_ITEM) {
|
|
|
dd89bb |
ctx->status = NT_STATUS_SUCCESS;
|
|
|
dd89bb |
return 1;
|
|
|
dd89bb |
} else if (!ldr_tbl_entry->dll_base) {
|
|
|
dd89bb |
ctx->status = NT_STATUS_SUCCESS;
|
|
|
dd89bb |
return 1;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
ctx->status = dalist_get_node_by_key(
|
|
|
dd89bb |
ctx->ldr_state_snapshot,
|
|
|
dd89bb |
(struct dalist_node_ex **)&node,
|
|
|
dd89bb |
(uintptr_t)ldr_tbl_entry->dll_base,
|
|
|
dd89bb |
DALIST_NODE_TYPE_EXISTING,
|
|
|
dd89bb |
0);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (ctx->status != DALIST_OK)
|
|
|
dd89bb |
return -1;
|
|
|
dd89bb |
else if (node)
|
|
|
dd89bb |
return 1;
|
|
|
dd89bb |
else if (!ctx->image_base || (ldr_tbl_entry->load_count < ctx->load_count)) {
|
|
|
dd89bb |
ctx->image_base = ldr_tbl_entry->dll_base;
|
|
|
dd89bb |
ctx->load_count = ldr_tbl_entry->load_count;
|
|
|
dd89bb |
ctx->ldr_tbl_entry = ldr_tbl_entry;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
return 1;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int __cdecl __ntapi_ldr_revert_state_to_snapshot(
|
|
|
dd89bb |
__in struct dalist_ex * ldr_state_snapshot)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
struct callback_ctx ctx;
|
|
|
dd89bb |
uint32_t i;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (!ldr_state_snapshot->free && !ldr_state_snapshot->memfn_ptr)
|
|
|
dd89bb |
return NT_STATUS_BUFFER_TOO_SMALL;
|
|
|
dd89bb |
|
|
|
dd89bb |
ctx.ldr_state_snapshot = ldr_state_snapshot;
|
|
|
dd89bb |
ctx.image_base = (void *)0;
|
|
|
dd89bb |
ctx.load_count = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
pe_enum_modules_in_load_order(
|
|
|
dd89bb |
__find_next_module_to_unload,
|
|
|
dd89bb |
&ctx;;
|
|
|
dd89bb |
|
|
|
dd89bb |
while ((ctx.image_base) && (ctx.status == NT_STATUS_SUCCESS)) {
|
|
|
dd89bb |
if (ctx.load_count == 0xffff) {
|
|
|
dd89bb |
ctx.load_count = 1;
|
|
|
dd89bb |
ctx.ldr_tbl_entry->load_count = 1;
|
|
|
dd89bb |
ctx.ldr_tbl_entry->entry_point = (void *)0;
|
|
|
dd89bb |
ctx.ldr_tbl_entry->flags = 0;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
for (i=0; i
|
|
|
dd89bb |
__ntapi->ldr_unload_dll(ctx.image_base);
|
|
|
dd89bb |
|
|
|
dd89bb |
__ntapi->zw_unmap_view_of_section(
|
|
|
dd89bb |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
dd89bb |
ctx.image_base);
|
|
|
dd89bb |
ctx.image_base = (void *)0;
|
|
|
dd89bb |
ctx.load_count = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
pe_enum_modules_in_load_order(
|
|
|
dd89bb |
__find_next_module_to_unload,
|
|
|
dd89bb |
&ctx;;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
return ctx.status;
|
|
|
dd89bb |
}
|