instruction_length(): Extended for 0xF0 (lock prefix).
[captive.git] / src / libcaptive / ldr / loader.c
index fe73f4d..48fe811 100644 (file)
@@ -121,9 +121,9 @@ gboolean errbool;
 
 /**
  * captive_LdrLoadModule:
- * @Filename: 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.
- * @ModuleObject: Returns initialized module object.
+ * @ModuleObjectp: Returns initialized module object.
  *
  * Load and initialize module to reactos using host OS functions.
  *
@@ -186,7 +186,7 @@ NTSTATUS LdrLoadModule(PUNICODE_STRING Filename,PMODULE_OBJECT *ModuleObject)
 /**
  * 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.
@@ -220,7 +220,9 @@ NTSTATUS 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;
 
@@ -374,6 +376,8 @@ static gsize instruction_length(const guint8 *instr)
                        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:
@@ -382,6 +386,8 @@ static gsize instruction_length(const guint8 *instr)
                                        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 ??,?? */
@@ -425,6 +431,8 @@ static gsize instruction_length(const guint8 *instr)
                        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 */
@@ -499,7 +507,7 @@ USHORT Idx;
 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;
 
@@ -544,10 +552,11 @@ CHAR *funcname=MODULEOBJECT_BASE_OFFSET_PLUS(NameList[Idx]);
                captive_va_arg(sym_val ,ap);
                /* '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);
@@ -563,24 +572,26 @@ CHAR *funcname=MODULEOBJECT_BASE_OFFSET_PLUS(NameList[Idx]);
                if (!patchpoint) /* 'data' type && !"pass"ed => do not corrupt it by 0xF4 */
                        continue;
                patchpoint->orig_w32_func=ExportAddress;
-               if (0xF4 /* hlt */ ==*patchpoint->orig_w32_func)        /* Already patched by name-aliased function? */
+               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 */ !=*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));
+               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);