Blob Blame History Raw
/********************************************************/
/*  ntapi: Native API core library                      */
/*  Copyright (C) 2013--2017  Z. Gilboa                 */
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
/********************************************************/

#include <psxtypes/psxtypes.h>
#include <pemagine/pemagine.h>
#include <dalist/dalist.h>
#include <ntapi/ntapi.h>

struct callback_ctx {
	struct dalist_ex *	ldr_state_snapshot;
	int32_t			status;
};

static int __cdecl __add_module_base_address_to_list(
	struct pe_ldr_tbl_entry *	ldr_tbl_entry,
	enum pe_callback_reason		int_callback_reason,
	void *				context)
{
	struct dalist_node *	node;
	struct callback_ctx *	ctx;

	ctx = (struct callback_ctx *)context;

	if (int_callback_reason == PE_CALLBACK_REASON_ERROR) {
		ctx->status = NT_STATUS_UNSUCCESSFUL;
		return ctx->status;
	} else if (int_callback_reason != PE_CALLBACK_REASON_ITEM) {
		ctx->status = NT_STATUS_SUCCESS;
		return 1;
	} else if (!ldr_tbl_entry->dll_base) {
		ctx->status = NT_STATUS_SUCCESS;
		return 1;
	}

	ctx->status = dalist_get_node_by_key(
		ctx->ldr_state_snapshot,
		(struct dalist_node_ex **)&node,
		(uintptr_t)ldr_tbl_entry->dll_base,
		DALIST_NODE_TYPE_NEW,
		0);

	if (ctx->status != DALIST_OK)
		return -1;
	else
		return 1;
}


int __cdecl __ntapi_ldr_create_state_snapshot(
	__out	struct dalist_ex * ldr_state_snapshot)
{
	struct callback_ctx ctx;

	if (!ldr_state_snapshot->free && !ldr_state_snapshot->memfn_ptr)
		return NT_STATUS_BUFFER_TOO_SMALL;
	else if (ldr_state_snapshot->info.list_nodes)
		return NT_STATUS_INVALID_USER_BUFFER;

	ctx.ldr_state_snapshot = ldr_state_snapshot;

	pe_enum_modules_in_load_order(
		__add_module_base_address_to_list,
		&ctx);

	return ctx.status;
}