Implemented adaptive 'Lookaside' init by init-code-search algorithm
authorshort <>
Sun, 9 Feb 2003 11:40:33 +0000 (11:40 +0000)
committershort <>
Sun, 9 Feb 2003 11:40:33 +0000 (11:40 +0000)
 - old code was broken for a different init code of W32 XP-SP1 ntoskrnl.exe

src/libcaptive/ex/lookas.c

index 93b63a0..9ce308d 100644 (file)
 
 #include "reactos/ddk/exfuncs.h"
 #include <glib/gmessages.h>
+#include "reactos/internal/module.h"   /* for MODULE_OBJECT */
+#include "reactos/internal/ldr.h"      /* for LdrGetModuleObject() */
+#include "captive/unicode.h"
+#include "captive/ldr_exports.h"       /* for captive_ModuleList_patchpoint */
+
+
+static G_CONST_RETURN guint8 *binary_defined_find(gconstpointer binary_base,gsize binary_length,
+               const guint8 *code,const guint8 *code_defined,gsize code_length,gssize call_offset)
+{
+const guint8 *base,*r;
+guint resti;
+
+       g_return_val_if_fail(binary_base!=NULL,NULL);
+       g_return_val_if_fail(binary_length>=code_length,NULL);
+       g_return_val_if_fail(code!=NULL,NULL);
+       g_return_val_if_fail(code_defined!=NULL,NULL);
+       g_return_val_if_fail(code_length>0,NULL);
+
+       g_return_val_if_fail(code_defined[0],NULL);     /* NOT SUPPORTED */
+
+       r=NULL;
+       for (base=binary_base;(char *)base<((char *)binary_base)+binary_length-code_length;base++) {
+gpointer call_orig=NULL;       /* Prevent: ... might be used uninitialized in this function */
+
+               base=memchr(base,code[0],(((char *)binary_base)+binary_length-code_length)-((char *)base));
+               if (!base)
+                       break;
+               if (call_offset>=0) {
+                       g_assert(call_offset+1+4<=(gssize)code_length);
+                       g_assert(code[call_offset]==0xE8);      /* call $quad-immediate */
+                       g_assert(code_defined[call_offset+0]
+                                       && code_defined[call_offset+1]
+                                       && code_defined[call_offset+2]
+                                       && code_defined[call_offset+3]
+                                       && code_defined[call_offset+4]);
+                       call_orig=*(gpointer *)(code+call_offset+1);
+                       *(gint32 *)(code+call_offset+1)=((char *)call_orig)-(((char *)base)+call_offset+1+4);   /* make it relative */
+                       }
+               for (resti=1;resti<code_length;resti++) {
+                       if (code_defined[resti] && code[resti]!=base[resti])
+                               break;
+                       }
+               if (call_offset>=0)
+                       *(gpointer *)(code+call_offset+1)=call_orig;
+               if (resti<code_length)
+                       continue;
+               g_return_val_if_fail(r==NULL,NULL);     /* FATAL: found a duplicate */
+               r=base;
+               }
+       /* 'r' may be NULL */
+
+       return r;
+}
+
+
+/* Declared only inside ntoskrnl/ldr/loader.c scope. */
+PVOID LdrGetExportAddress(PMODULE_OBJECT ModuleObject,char *Name,unsigned short Hint);
+
+/* Declared only inside libcaptive/ke/exports.c scope. */
+extern struct captive_ModuleList_patchpoint ExInitializeNPagedLookasideList_patchpoint;
+extern struct captive_ModuleList_patchpoint ExInitializePagedLookasideList_patchpoint;
+
+
+
+static gboolean ExAllocateFromPagedLookasideList_findinit
+               (gpointer Lookaside,const struct captive_ModuleList_patchpoint *patchpoint)
+{
+#define D 0xFF
+guint8 initcode[]={
+               /* + 0 */ 0x6A,D,       /* push $guint8  ;Depth                    */
+               /* + 2 */ 0x68,D,D,D,D, /* push $guint32 ;Tag                      */
+               /* + 7 */ 0x6A,D,       /* push $guint8  ;Size                     */
+               /* + 9 */ 0x6A,D,       /* push $guint8  ;Flags                    */
+               /* +11 */ 0x6A,0,       /* push $guint8  ;Free (gpointer size)     */
+               /* +13 */ 0x6A,0,       /* push $guint8  ;Allocate (gpointer size) */
+               /* +15 */ 0x68,D,D,D,D, /* push $guint32 ;Lookaside                */
+               /* +20 */ 0xE8,D,D,D,D, /* call $ExInitializeNPagedLookasideList   */
+               /* +25 */
+               };
+#undef D
+guint8 initcode_defined[]={
+               /* + 0 */ 1,0,       /* push $guint8  ;Depth                  */
+               /* + 2 */ 1,0,0,0,0, /* push $guint32 ;Tag                    */
+               /* + 7 */ 1,0,       /* push $guint8  ;Size                   */
+               /* + 9 */ 1,0,       /* push $guint8  ;Flags                  */
+               /* +11 */ 1,1,       /* push $guint8  ;Free                   */
+               /* +13 */ 1,1,       /* push $guint8  ;Allocate               */
+               /* +15 */ 1,1,1,1,1, /* push $guint32 ;Lookaside              */
+               /* +20 */ 1,1,1,1,1, /* call $ExInitializeNPagedLookasideList */
+               /* +25 */
+               };
+const guint8 *initcode_found;
+MODULE_OBJECT *ntoskrnl_exe_ModuleObject;
+
+       g_return_val_if_fail(Lookaside!=NULL,FALSE);
+
+       g_assert(sizeof(initcode)==25);
+       g_assert(sizeof(initcode)==sizeof(initcode_defined));
+
+       g_assert(initcode[15]==0x68); *(void **)(initcode+15+1)=Lookaside;
+
+       ntoskrnl_exe_ModuleObject=LdrGetModuleObject(captive_utf8_to_UnicodeString_alloca("ntoskrnl.exe"));
+       g_assert(ntoskrnl_exe_ModuleObject!=NULL);
+       g_assert(ntoskrnl_exe_ModuleObject->TextSection!=NULL);
+
+       g_assert(patchpoint->orig_w32_func!=NULL);
+       g_assert(initcode[20]==0xE8); *(void **)(initcode+20+1)=patchpoint->orig_w32_func;
+
+       if (!(initcode_found=binary_defined_find(
+                       (void *)ntoskrnl_exe_ModuleObject->TextSection->Base,   /* binary_base */
+                       ntoskrnl_exe_ModuleObject->TextSection->Length, /* binary_length */
+                       initcode,       /* code */
+                       initcode_defined,       /* code_defined */
+                       sizeof(initcode),       /* code_length */
+                       20)))   /* call_offset */
+               return FALSE;
+
+       g_assert(Lookaside==*(gpointer *)(initcode_found+15+1));
+
+       /**/ if (patchpoint==&ExInitializeNPagedLookasideList_patchpoint)
+               ExInitializeNPagedLookasideList(
+                               (NPAGED_LOOKASIDE_LIST *)Lookaside,     /* Lookaside */
+                               NULL,   /* Allocate; NULL as there is only guint8 in the code */
+                               NULL,   /* Free; NULL as there is only guint8 in the code */
+                               *(guint8  *)(initcode_found+9+1),       /* Flags; undocumented by W32 doc (reserved) */
+                               *(guint8  *)(initcode_found+7+1),       /* Size; FIXME: ? node size */
+                               *(guint32 *)(initcode_found+2+1),       /* Tag; 'FSfm' */
+                               *(guint8  *)(initcode_found+0+1));      /* Depth; undocumented by W32 doc (reserved) */
+       else if (patchpoint==&ExInitializePagedLookasideList_patchpoint)
+               ExInitializePagedLookasideList(
+                               (PAGED_LOOKASIDE_LIST *)Lookaside,      /* Lookaside */
+                               NULL,   /* Allocate; NULL as there is only guint8 in the code */
+                               NULL,   /* Free; NULL as there is only guint8 in the code */
+                               *(guint8  *)(initcode_found+9+1),       /* Flags; undocumented by W32 doc (reserved) */
+                               *(guint8  *)(initcode_found+7+1),       /* Size; FIXME: ? node size */
+                               *(guint32 *)(initcode_found+2+1),       /* Tag; 'FSfm' */
+                               *(guint8  *)(initcode_found+0+1));      /* Depth; undocumented by W32 doc (reserved) */
+       else g_assert_not_reached();
+
+       return TRUE;
+}
 
 
 PVOID ExAllocateFromPagedLookasideList_orig(PPAGED_LOOKASIDE_LIST Lookaside);
@@ -29,15 +170,14 @@ PVOID ExAllocateFromPagedLookasideList_wrap(PAGED_LOOKASIDE_LIST *Lookaside)
 {
 static PAGED_LOOKASIDE_LIST Lookaside_zero;
 
-       if (!memcmp(Lookaside,&Lookaside_zero,sizeof(Lookaside_zero)))
-               ExInitializeNPagedLookasideList(
-                               (NPAGED_LOOKASIDE_LIST *)Lookaside,     /* Lookaside */
-                               NULL,   /* Allocate */
-                               NULL,   /* Free */
-                               0x10,   /* Flags; undocumented by W32 doc (reserved) */
-                               0x20,   /* Size; FIXME: ? node size */
-                               0x6D665346,     /* Tag; 'FSfm' */
-                               0x20);  /* Depth; undocumented by W32 doc (reserved) */
+       g_return_val_if_fail(Lookaside!=NULL,NULL);
+
+       if (!memcmp(Lookaside,&Lookaside_zero,sizeof(Lookaside_zero))) {
+               if (1
+                               && !ExAllocateFromPagedLookasideList_findinit(Lookaside,&ExInitializeNPagedLookasideList_patchpoint)
+                               && !ExAllocateFromPagedLookasideList_findinit(Lookaside,&ExInitializePagedLookasideList_patchpoint))
+               g_assert_not_reached(); /* failed to patch it */
+               }
 
        return ExAllocateFromPagedLookasideList_orig(Lookaside);
 }