#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);
{
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);
}