#include <sys/mman.h> /* for PROT_READ, MAP_SHARED */
#include "captive/macros.h"
#include <stdarg.h>
-#include "reactos/ddk/rtl.h" /* for InsertTailList() */
+#include "reactos/ntos/rtl.h" /* for InsertTailList() */
#include "reactos/internal/debug.h" /* for assert() */
#include <glib/gutils.h> /* for g_path_get_basename() */
#include <gmodule.h>
+#include "captive/options-module.h"
/* map: ExportAddress -> (struct captive_ModuleList_patchpoint *) */
/* reactos/ntoskrnl/ldr/loader.c file-scope global declaration: */
NTSTATUS LdrProcessModule(PVOID ModuleLoadBase,PUNICODE_STRING ModuleName,PMODULE_OBJECT *ModuleObject);
+PVOID LdrGetExportAddress(PMODULE_OBJECT ModuleObject,char *Name,unsigned short Hint);
/* 'ntoskrnl/ldr/loader.c' file-scoped declaration: */
/**
- * LdrLoadModule:
- * @Filename: Filename of module to load based on host OS disk.
+ * captive_LdrLoadModule:
+ * @options_module: #captive_options_module structure describing the module to load.
* Loading of already loaded module is forbidden.
- * @ModuleObject: Returns initialized module object.
+ * @ModuleObjectp: Returns initialized module object.
*
* Load and initialize module to reactos using host OS functions.
*
* Returns: STATUS_SUCCESS if the module was loaded successfuly during the call.
*/
-NTSTATUS LdrLoadModule(PUNICODE_STRING Filename,PMODULE_OBJECT *ModuleObjectp)
+NTSTATUS captive_LdrLoadModule(struct captive_options_module *options_module,PMODULE_OBJECT *ModuleObjectp)
{
-PVOID ModuleLoadBase;
PMODULE_OBJECT Module;
NTSTATUS err;
-gchar *Filename_utf8=(/* de-const */ gchar *)captive_UnicodeString_to_utf8_alloca(Filename);
+gchar *Filename_utf8=options_module->pathname_utf8;
gchar *Filename_bslash_utf8,*s;
UNICODE_STRING *Filename_bslash;
*ModuleObjectp=NULL;
- /* Open the Module */
- ModuleLoadBase=captive_rtl_file_mmap(
- NULL, /* lenp */
- Filename_utf8, /* path */
- O_RDONLY, /* open_flags */
- PROT_READ, /* mmap_prot */
- MAP_SHARED); /* mmap_flags */
- /* FIXME: convert errno instead of STATUS_INSUFFICIENT_RESOURCES */
- g_return_val_if_fail(ModuleLoadBase!=NULL,STATUS_INSUFFICIENT_RESOURCES);
-
/* Filename=~s#/#\\#g -> Filename_bslash to satisfy basename-derivations by reactos. */
- Filename_bslash_utf8=g_strdup(Filename_utf8);
+ Filename_bslash_utf8=(/* de-const as we do not change the length */ gchar *)captive_strdup_alloca(Filename_utf8);
for (s=Filename_bslash_utf8;(s=strchr(s,'/'));s++)
*s='\\';
Filename_bslash=captive_utf8_to_UnicodeString_alloca(Filename_bslash_utf8);
- if ((('M'<<8U)|('Z'<<0U))==GUINT16_FROM_BE(*(const guint16 *)ModuleLoadBase)) {
- g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: Loading module format: %s",G_STRLOC,"MZ/PE-32");
- /* examine/relocate the module */
- err=LdrProcessModule(ModuleLoadBase,Filename_bslash,&Module);
- if (!NT_SUCCESS(err)) {
- g_error("LdrLoadModule(): LdrProcessModule()=0x%08lX",err);
- goto err_captive_rtl_file_munmap;
- }
- }
- else {
- g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: Loading module format: %s",G_STRLOC,"native .so");
- Module=captive_LdrLoadModule_gmodule(Filename_utf8,Filename_bslash_utf8);
- g_assert(Module!=NULL);
+ switch (options_module->type) {
+ case CAPTIVE_OPTIONS_MODULE_TYPE_EMPTY: g_assert_not_reached();
+
+ case CAPTIVE_OPTIONS_MODULE_TYPE_PE32:
+ g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: Loading module format: %s",G_STRLOC,"MZ/PE-32");
+ /* examine/relocate the module */
+ err=LdrProcessModule(options_module->u.pe32.base,Filename_bslash,&Module);
+ if (!NT_SUCCESS(err)) {
+ g_error("LdrLoadModule(): LdrProcessModule()=0x%08lX",(gulong)err);
+ goto err;
+ }
+ break;
+
+ case CAPTIVE_OPTIONS_MODULE_TYPE_GMODULE:
+ g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: Loading module format: %s",G_STRLOC,"native .so");
+ Module=captive_LdrLoadModule_gmodule(Filename_utf8,Filename_bslash_utf8);
+ g_assert(Module!=NULL);
}
/* we were successful */
- captive_rtl_file_munmap(ModuleLoadBase);
*ModuleObjectp=Module;
/* Hook for KDB on loading a driver. */
return STATUS_SUCCESS;
- /* Error recoveries */
-err_captive_rtl_file_munmap:
- captive_rtl_file_munmap(ModuleLoadBase);
-
+err:
g_return_val_if_reached(err);
}
+NTSTATUS LdrLoadModule(PUNICODE_STRING Filename,PMODULE_OBJECT *ModuleObject)
+{
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+}
+
+
/**
* captive_LdrpLoadAndCallImage:
* @ModuleObjectp: Returns PMODULE_OBJECT successfuly loaded.
- * @ModuleName: Filename of module to load based on host OS disk.
+ * @options_module: #captive_options_module structure describing the module to load.
* Loading of already loaded module is forbidden despite original
* LdrpLoadAndCallImage().
* @DriverEntry_DriverObject: argument #DriverObject of #PDRIVER_INITIALIZE call.
* Returns: STATUS_SUCCESS if the driver module was loaded and initialized
* successfuly during this call. Ignore returned @ModuleObjectp if function failed.
*/
-NTSTATUS captive_LdrpLoadAndCallImage(PMODULE_OBJECT *ModuleObjectp,PUNICODE_STRING ModuleName,
+NTSTATUS captive_LdrpLoadAndCallImage(PMODULE_OBJECT *ModuleObjectp,struct captive_options_module *options_module,
PDRIVER_OBJECT DriverEntry_DriverObject,PUNICODE_STRING DriverEntry_RegistryPath)
{
PDRIVER_INITIALIZE DriverEntry;
PMODULE_OBJECT ModuleObject_tmp;
NTSTATUS err;
+#if 0 /* TODO */
/* check for duplicity */
g_return_val_if_fail(LdrGetModuleObject(ModuleName)==NULL,STATUS_IMAGE_ALREADY_LOADED);
+#endif
/* provide our temporary storage if the caller doesn't want to know ModuleObject address */
if (!ModuleObjectp)
ModuleObjectp=&ModuleObject_tmp;
/* load the module */
- err=LdrLoadModule(ModuleName,ModuleObjectp);
+ err=captive_LdrLoadModule(options_module,ModuleObjectp);
g_return_val_if_fail(NT_SUCCESS(err),err);
/* initialize the module */
DriverEntry=(PDRIVER_INITIALIZE)(*ModuleObjectp)->EntryPoint;
- err=(*DriverEntry)(DriverEntry_DriverObject,DriverEntry_RegistryPath);
+ err=(NTSTATUS)captive_stdcall_call_8((CaptiveStdCallFunc8)DriverEntry,
+ DriverEntry_DriverObject,
+ DriverEntry_RegistryPath);
if (!NT_SUCCESS(err))
goto err_LdrUnloadModule;
return 1+4;
case 0x6A: /* push $single-byte */
return 1+1;
+ case 0x80:
+ switch (instr[1]) {
+ case 0x3D: /* cmpb $byte,immediate-quad-indirect */
+ return 1+1+4+1; /* 80 3D immediate-quad-indirect byte */
+ case 0x7C: /* cmpb $byte,#immediate(%reg,1) */
+ return 1+1+1+1+1; /* 80 7C address-mode immediate byte */
+ default: g_assert_not_reached();
+ }
case 0x83:
switch (instr[1]) {
case 0x01: /* addl $byte,(%ecx) */
return 1+1+1;
case 0x3D: /* cmpl $byte,immediate-quad-indirect */
return 1+1+4+1; /* 83 3D immediate-quad-indirect byte */
+ case 0x7C: /* cmpl $byte,#immediate(%reg,1) */
+ return 1+1+1+1+1; /* 80 7C address-mode immediate byte */
default: g_assert_not_reached();
}
case 0x8A: /* mov ??,?? */
return 4; /* 8B 44 address-mode offset */
default: g_assert_not_reached();
}
+ case 0x8F: /* lea Gb,M */
+ switch (instr[1]) {
+ case 0x04:
+ switch (instr[2]) {
+ case 0x24: /* popl (%esp,1) */
+ return 3;
+ default: g_assert_not_reached();
+ }
+ default: g_assert_not_reached();
+ }
case 0x9C: /* pushf */
return 1;
case 0x9D: /* popf */
return 1+2;
case 0xCC: /* int $0x3 */
return 1;
+ case 0xF0: /* lock prefix */
+ return 1+instruction_length(instr+1);
case 0xFA: /* cli */
return 1;
case 0xFB: /* sti */
PVOID ExportAddress,*ExportAddressp;
const gchar *sym_name;
void (*sym_val)(void);
-struct captive_ModuleList_patchpoint *patchpoint;
+struct captive_ModuleList_patchpoint *patchpoint,*patchpointpatch;
GHashTable *exportdir_hash;
gboolean errbool;
va_start(ap,FullName_utf8);
while (captive_va_arg(sym_name,ap)) {
captive_va_arg(sym_val ,ap);
- g_assert(sym_val!=NULL);
+ /* 'sym_val' may be NULL if 'data' type && "pass"ed */
captive_va_arg(patchpoint,ap); /* 'data' type if ==NULL */
+ captive_va_arg(patchpointpatch,ap); /* 'data' type or 'pass' in non-debug mode if ==NULL */
ExportAddressp=g_hash_table_lookup(exportdir_hash,sym_name);
if (ExportAddressp==NULL) {
- g_error("%s: Function not found for patchpoint: %s",G_STRLOC,sym_name);
- g_assert_not_reached();
+ g_message("%s: Function not found for patchpoint (ignoring): %s",G_STRLOC,sym_name);
+ continue;
}
errbool=g_hash_table_remove(exportdir_hash,sym_name);
g_assert(errbool==TRUE);
+ if (!sym_val) { /* 'data' type && "pass"ed => do not corrupt it by 0xF4 */
+ g_assert(!patchpoint);
+ continue;
+ }
ExportAddress=(PVOID)MODULEOBJECT_BASE_OFFSET_PLUS(*ExportAddressp);
*ExportAddressp=(PVOID)MODULEOBJECT_BASE_OFFSET_MINUS(sym_val);
if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
g_assert_not_reached(); /* LdrPEFixupForward() needed */
- if (!patchpoint) /* 'data' type */
+ if (!patchpoint) /* 'data' type && !"pass"ed => do not corrupt it by 0xF4 */
continue;
patchpoint->orig_w32_func=ExportAddress;
- g_assert(0xF4 /* hlt */ !=*patchpoint->orig_w32_func);
- patchpoint->orig_w32_2ndinstr=patchpoint->orig_w32_func
- +instruction_length((guint8 *)patchpoint->orig_w32_func);
- g_assert(0xF4 /* hlt */ !=*patchpoint->orig_w32_2ndinstr);
- patchpoint->wrap_wrap_func=sym_val;
- patchpoint->orig_w32_func_byte=*patchpoint->orig_w32_func;
- patchpoint->orig_w32_2ndinstr_byte=*patchpoint->orig_w32_2ndinstr;
- patchpoint->through_w32_func=FALSE;
- g_assert(NULL==g_hash_table_lookup(captive_ModuleList_patchpoint_hash,patchpoint->orig_w32_func));
+ if (!patchpointpatch) /* 'pass' in non-debug mode */
+ continue;
+ if (0xF4 /* hlt */ ==*patchpointpatch->orig_w32_func) /* Already patched by name-aliased function? */
+ continue;
+ g_assert(0xF4 /* hlt */ !=*patchpointpatch->orig_w32_func);
+ patchpointpatch->orig_w32_2ndinstr=patchpointpatch->orig_w32_func
+ +instruction_length((guint8 *)patchpointpatch->orig_w32_func);
+ g_assert(0xF4 /* hlt */ !=*patchpointpatch->orig_w32_2ndinstr);
+ patchpointpatch->wrap_wrap_func=sym_val;
+ patchpointpatch->orig_w32_func_byte=*patchpointpatch->orig_w32_func;
+ patchpointpatch->orig_w32_2ndinstr_byte=*patchpointpatch->orig_w32_2ndinstr;
+ patchpointpatch->through_w32_func=FALSE;
+ g_assert(NULL==g_hash_table_lookup(captive_ModuleList_patchpoint_hash,patchpointpatch->orig_w32_func));
g_hash_table_insert(captive_ModuleList_patchpoint_hash,
- patchpoint->orig_w32_func, /* key */
- patchpoint); /* value */
- g_assert(NULL==g_hash_table_lookup(captive_ModuleList_patchpoint_hash,patchpoint->orig_w32_2ndinstr));
+ patchpointpatch->orig_w32_func, /* key */
+ patchpointpatch); /* value */
+ g_assert(NULL==g_hash_table_lookup(captive_ModuleList_patchpoint_hash,patchpointpatch->orig_w32_2ndinstr));
g_hash_table_insert(captive_ModuleList_patchpoint_hash,
- patchpoint->orig_w32_2ndinstr, /* key */
- patchpoint); /* value */
+ patchpointpatch->orig_w32_2ndinstr, /* key */
+ patchpointpatch); /* value */
*(guint8 *)ExportAddress=0xF4; /* hlt */
}
va_end(ap);
return g_hash_table_lookup(captive_ModuleList_function_disable_hash,ExportAddress); /* funcname */
}
+
+
+void *captive_Module_GetExportAddress(const gchar *ModuleName_utf8,const gchar *FunctionName)
+{
+MODULE_OBJECT *ModuleObject;
+void *r;
+
+ g_return_val_if_fail(ModuleName_utf8!=NULL,NULL);
+ g_return_val_if_fail(FunctionName!=NULL,NULL);
+
+ ModuleObject=LdrGetModuleObject(captive_utf8_to_UnicodeString_alloca(g_path_get_basename(ModuleName_utf8)));
+ g_return_val_if_fail(ModuleObject!=NULL,NULL);
+
+ r=LdrGetExportAddress(
+ ModuleObject, /* ModuleObject */
+ (/* de-const */char *)FunctionName, /* Name */
+ -1); /*Hint*/
+ g_return_val_if_fail(r!=NULL,NULL);
+
+ return r;
+}