2 * reactos ldr/ (loader) emulation of libcaptive
3 * Copyright (C) 2002 Jan Kratochvil <project-captive@jankratochvil.net>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; exactly version 2 of June 1991 is required
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "captive/ldr.h" /* self */
23 #include "captive/ldr_exports.h" /* self */
24 #include "reactos/internal/ldr.h" /* self */
25 #include "captive/unicode.h"
26 #include "captive/rtl-file.h"
27 #include <glib/gtypes.h>
28 #include <glib/gmessages.h>
29 #include <glib/gmem.h>
30 #include "reactos/napi/types.h"
31 #include "reactos/internal/kd.h" /* for KDB_LOADDRIVER_HOOK */
33 #include <sys/mman.h> /* for PROT_READ, MAP_SHARED */
34 #include "captive/macros.h"
36 #include "reactos/ddk/rtl.h" /* for InsertTailList() */
37 #include "reactos/internal/debug.h" /* for assert() */
38 #include <glib/gutils.h> /* for g_path_get_basename() */
42 /* map: ExportAddress -> (struct captive_ModuleList_patchpoint *) */
43 static GHashTable *captive_ModuleList_patchpoint_hash;
45 /* initialize 'captive_ModuleList_patchpoint_hash' */
46 static void captive_ModuleList_patchpoint_hash_init(void)
48 if (captive_ModuleList_patchpoint_hash)
50 captive_ModuleList_patchpoint_hash=g_hash_table_new(g_direct_hash,g_direct_equal);
54 /* map: ExportAddress -> (CHAR *)funcname */
55 static GHashTable *captive_ModuleList_function_disable_hash;
57 /* initialize 'captive_ModuleList_function_disable_hash' */
58 static void captive_ModuleList_function_disable_hash_init(void)
60 if (captive_ModuleList_function_disable_hash)
62 captive_ModuleList_function_disable_hash=g_hash_table_new(g_direct_hash,g_direct_equal);
66 /* reactos/ntoskrnl/ldr/loader.c file-scope global declaration: */
67 NTSTATUS LdrProcessModule(PVOID ModuleLoadBase,PUNICODE_STRING ModuleName,PMODULE_OBJECT *ModuleObject);
70 /* 'ntoskrnl/ldr/loader.c' file-scoped declaration: */
71 VOID LdrpBuildModuleBaseName(PUNICODE_STRING BaseName,PUNICODE_STRING FullName);
74 static MODULE_OBJECT *captive_LdrLoadModule_gmodule(const gchar *Filename_utf8,const gchar *Filename_bslash_utf8)
78 MODULE_TEXT_SECTION *ModuleTextSection;
81 g_return_val_if_fail(Filename_utf8!=NULL,NULL);
82 g_return_val_if_fail(Filename_bslash_utf8!=NULL,NULL);
83 g_return_val_if_fail(TRUE==g_module_supported(),NULL);
85 gmodule=g_module_open(Filename_utf8,
86 0); /* Flags; !LAZY */
88 g_message(g_module_error());
89 g_assert(gmodule!=NULL);
93 errbool=g_module_symbol(gmodule,"DriverEntry",&r->EntryPoint);
94 g_assert(errbool==TRUE);
96 r->Base=(PVOID)gmodule;
97 r->Flags=MODULE_FLAG_COFF; /* some weird value - reactos uses MODULE_FLAG_PE */
99 RtlCreateUnicodeString(&r->FullName,captive_utf8_to_UnicodeString_alloca(Filename_bslash_utf8)->Buffer);
100 LdrpBuildModuleBaseName(&r->BaseName,&r->FullName);
105 InsertTailList(&ModuleListHead,&r->ListEntry);
107 captive_new0(ModuleTextSection);
108 /* ModuleTextSection->Base=0; */
109 /* ModuleTextSection->Length=0; */
110 ModuleTextSection->Name=g_memdup(r->BaseName.Buffer,
111 (captive_ucs2_strlen(r->BaseName.Buffer)+1)*sizeof(captive_ucs2));
112 /* ModuleTextSection->OptionalHeader=NULL; */
113 InsertTailList(&ModuleTextListHead,&ModuleTextSection->ListEntry);
114 r->TextSection=ModuleTextSection;
122 * @Filename: Filename of module to load based on host OS disk.
123 * Loading of already loaded module is forbidden.
124 * @ModuleObject: Returns initialized module object.
126 * Load and initialize module to reactos using host OS functions.
128 * Returns: STATUS_SUCCESS if the module was loaded successfuly during the call.
130 NTSTATUS LdrLoadModule(PUNICODE_STRING Filename,PMODULE_OBJECT *ModuleObjectp)
132 PVOID ModuleLoadBase;
133 PMODULE_OBJECT Module;
135 gchar *Filename_utf8=(/* de-const */ gchar *)captive_UnicodeString_to_utf8_alloca(Filename);
136 gchar *Filename_bslash_utf8,*s;
137 UNICODE_STRING *Filename_bslash;
141 /* Open the Module */
142 ModuleLoadBase=captive_rtl_file_mmap(
144 Filename_utf8, /* path */
145 O_RDONLY, /* open_flags */
146 PROT_READ, /* mmap_prot */
147 MAP_SHARED); /* mmap_flags */
148 /* FIXME: convert errno instead of STATUS_INSUFFICIENT_RESOURCES */
149 g_return_val_if_fail(ModuleLoadBase!=NULL,STATUS_INSUFFICIENT_RESOURCES);
151 /* Filename=~s#/#\\#g -> Filename_bslash to satisfy basename-derivations by reactos. */
152 Filename_bslash_utf8=g_strdup(Filename_utf8);
153 for (s=Filename_bslash_utf8;(s=strchr(s,'/'));s++)
155 Filename_bslash=captive_utf8_to_UnicodeString_alloca(Filename_bslash_utf8);
157 if ((('M'<<8U)|('Z'<<0U))==GUINT16_FROM_BE(*(const guint16 *)ModuleLoadBase)) {
158 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: Loading module format: %s",G_STRLOC,"MZ/PE-32");
159 /* examine/relocate the module */
160 err=LdrProcessModule(ModuleLoadBase,Filename_bslash,&Module);
161 if (!NT_SUCCESS(err)) {
162 g_error("LdrLoadModule(): LdrProcessModule()=0x%08lX",err);
163 goto err_captive_rtl_file_munmap;
167 g_log(G_LOG_DOMAIN,G_LOG_LEVEL_DEBUG,"%s: Loading module format: %s",G_STRLOC,"native .so");
168 Module=captive_LdrLoadModule_gmodule(Filename_utf8,Filename_bslash_utf8);
169 g_assert(Module!=NULL);
172 /* we were successful */
173 captive_rtl_file_munmap(ModuleLoadBase);
174 *ModuleObjectp=Module;
176 /* Hook for KDB on loading a driver. */
177 KDB_LOADDRIVER_HOOK(Filename_bslash,Module);
179 return STATUS_SUCCESS;
181 /* Error recoveries */
182 err_captive_rtl_file_munmap:
183 captive_rtl_file_munmap(ModuleLoadBase);
185 g_return_val_if_reached(err);
190 * captive_LdrpLoadAndCallImage:
191 * @ModuleObjectp: Returns PMODULE_OBJECT successfuly loaded.
192 * @ModuleName: Filename of module to load based on host OS disk.
193 * Loading of already loaded module is forbidden despite original
194 * LdrpLoadAndCallImage().
195 * @DriverEntry_DriverObject: argument #DriverObject of #PDRIVER_INITIALIZE call.
196 * @DriverEntry_RegistryPath: argument #RegistryPath of #PDRIVER_INITIALIZE call.
198 * Corresponds to reactos LdrpLoadAndCallImage() but it also provides arguments
199 * to pass to #PDRIVER_INITIALIZE call of module driver initialization.
201 * Returns: STATUS_SUCCESS if the driver module was loaded and initialized
202 * successfuly during this call. Ignore returned @ModuleObjectp if function failed.
204 NTSTATUS captive_LdrpLoadAndCallImage(PMODULE_OBJECT *ModuleObjectp,PUNICODE_STRING ModuleName,
205 PDRIVER_OBJECT DriverEntry_DriverObject,PUNICODE_STRING DriverEntry_RegistryPath)
207 PDRIVER_INITIALIZE DriverEntry;
208 PMODULE_OBJECT ModuleObject_tmp;
211 /* check for duplicity */
212 g_return_val_if_fail(LdrGetModuleObject(ModuleName)==NULL,STATUS_IMAGE_ALREADY_LOADED);
214 /* provide our temporary storage if the caller doesn't want to know ModuleObject address */
216 ModuleObjectp=&ModuleObject_tmp;
218 /* load the module */
219 err=LdrLoadModule(ModuleName,ModuleObjectp);
220 g_return_val_if_fail(NT_SUCCESS(err),err);
222 /* initialize the module */
223 DriverEntry=(PDRIVER_INITIALIZE)(*ModuleObjectp)->EntryPoint;
224 err=(*DriverEntry)(DriverEntry_DriverObject,DriverEntry_RegistryPath);
225 if (!NT_SUCCESS(err))
226 goto err_LdrUnloadModule;
228 /* assumed STATUS_SUCCESS */
233 LdrUnloadModule(*ModuleObjectp);
236 g_return_val_if_reached(err);
241 * captive_ModuleList_add_builtin:
242 * @FullName_utf8: String to fill in #PMODULE_OBJECT->FullName.
243 * @...: (const gchar *sym_name,void *sym_val) symbol list terminated by %NULL.
245 * Adds simulated built-in module to #ModuleListHead module list.
246 * It can be used for the functionality of reactos/ntoskrnl/ldr/loader.c/LdrInitModuleManagement().
247 * libcaptive does not support Ordinals - we just pretend liner (%0-based)
248 * Ordinal numbers of the functions in given @... stdargs order.
250 * Returns: %TRUE if the module was successfuly added.
252 gboolean captive_ModuleList_add_builtin(const gchar *FullName_utf8,...)
254 MODULE_OBJECT *ModuleObject;
257 const gchar *sym_name;
259 gchar *basename_utf8;
260 IMAGE_DOS_HEADER *DosHeader;
261 IMAGE_NT_HEADERS *NTHeaders;
262 IMAGE_EXPORT_DIRECTORY *ExportDir;
263 guint symi,symN; /* index,number of passed stdarg sym_name/sym_val pairs */
264 ptrdiff_t *NameList; /* filled by sym_name; MODULEOBJECT_BASE_OFFSET_MINUS()ed */
265 WORD *OrdinalList; /* linear list - libcaptive doesn't support Ordinals */
266 ptrdiff_t *FunctionList; /* filled by sym_val; MODULEOBJECT_BASE_OFFSET_MINUS()ed */
268 g_return_val_if_fail(FullName_utf8!=NULL,FALSE);
270 captive_new0(ModuleObject);
271 /* A lot of offsets in the structures are relative to ModuleObject->Base */
272 #define MODULEOBJECT_BASE_OFFSET_MINUS(addr) ((ptrdiff_t)((char *)addr-(char *)ModuleObject->Base))
274 ModuleObject->Flags = MODULE_FLAG_PE;
276 /* fill ModuleObject->FullName
277 * ModuleObject->FullName should be probably "\\SYSTEM32\\..." style but
278 * we put there '/'-based UNIX filenames in libcaptive.
280 errbool=RtlCreateUnicodeString(&ModuleObject->FullName,captive_utf8_to_UnicodeString_alloca(FullName_utf8)->Buffer);
282 g_error("captive_ModuleList_add_builtin: RtlCreateUnicodeString()==FALSE");
283 goto err_g_free_ModuleObject;
286 /* fill ModuleObject->BaseName
287 * reactos/ntoskrnl/ldr/loader.c/LdrpBuildModuleBaseName() does this one
288 * but it is 'static' for that file and also it is stricly backslash based.
289 * ModuleObject->FullName should be probably "\\SYSTEM32\\..." style but
290 * we put there '/'-based UNIX filenames in libcaptive.
292 basename_utf8=g_path_get_basename(FullName_utf8);
293 errbool=RtlCreateUnicodeString(&ModuleObject->BaseName,captive_utf8_to_UnicodeString_alloca(basename_utf8)->Buffer);
294 g_free(basename_utf8);
296 g_error("captive_ModuleList_add_builtin: RtlCreateUnicodeString()==FALSE");
297 goto err_g_free_ModuleObject;
300 /* We must satisfy reactos/ntoskrnl/ldr/rtl.c/RtlImageDirectoryEntryToData(,,IMAGE_DIRECTORY_ENTRY_EXPORT)
301 * prepare module headers
303 captive_new0(DosHeader);
304 ModuleObject->Base=DosHeader; /* link DosHeader to ModuleObject */
305 DosHeader->e_magic=IMAGE_DOS_MAGIC;
306 captive_new0(NTHeaders);
307 DosHeader->e_lfanew=MODULEOBJECT_BASE_OFFSET_MINUS(NTHeaders); /* link NTHeaders to DosHeader */
308 NTHeaders->Signature=IMAGE_PE_MAGIC;
309 NTHeaders->OptionalHeader.NumberOfRvaAndSizes=IMAGE_DIRECTORY_ENTRY_EXPORT+1;
310 NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size
311 =sizeof(*ExportDir); /* in bytes; just prevent LdrPEFixupForward() invocation */
312 captive_new0(ExportDir);
313 NTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress
314 =MODULEOBJECT_BASE_OFFSET_MINUS(ExportDir); /* link ExportDir to NTHeaders */
315 ExportDir->Base=0; /* base Ordinal number; Ordinals are not supported by libcaptive */
317 /* count the number of symbols */
318 va_start(ap,FullName_utf8);
319 for (symN=0;captive_va_arg(sym_name,ap);symN++)
320 captive_va_arg(sym_val,ap);
322 ExportDir->NumberOfNames=symN;
323 ExportDir->NumberOfFunctions=symN;
325 /* allocate and link the symbol tables */
326 captive_newn(NameList,symN);
327 ExportDir->AddressOfNames=(PDWORD *)MODULEOBJECT_BASE_OFFSET_MINUS(NameList); /* link NameList to ExportDir */
328 captive_newn(OrdinalList,symN);
329 ExportDir->AddressOfNameOrdinals=(PWORD *)MODULEOBJECT_BASE_OFFSET_MINUS(OrdinalList); /* link OrdinalList to ExportDir */
330 captive_newn(FunctionList,symN);
331 ExportDir->AddressOfFunctions=(PDWORD *)MODULEOBJECT_BASE_OFFSET_MINUS(FunctionList); /* link FunctionList to ExportDir */
333 /* fill in symbol tables */
334 va_start(ap,FullName_utf8);
335 for (symi=0;symi<symN;symi++) {
336 captive_va_arg(sym_name,ap);
337 captive_va_arg(sym_val ,ap);
338 NameList[symi]=MODULEOBJECT_BASE_OFFSET_MINUS(sym_name);
339 OrdinalList[symi]=symi; /* Ordinals are not supported by libcaptive */
340 FunctionList[symi]=MODULEOBJECT_BASE_OFFSET_MINUS(sym_val);
344 /* successful module info build */
345 InsertTailList(&ModuleListHead,&ModuleObject->ListEntry);
348 err_g_free_ModuleObject:
349 g_free(ModuleObject);
351 g_return_val_if_reached(FALSE);
355 static gsize instruction_length(const guint8 *instr)
357 if ((instr[0] & 0xF8)==0x50) /* push %regular-register */
359 if ((instr[0] & 0xF8)==0x58) /* pop %regular-register */
361 if ((instr[0] & 0xE7)==0x06) /* push %segment-register */
363 if ((instr[0] & 0xE7)==0x07 && instr[0]!=0x0F) /* pop %segment-register */
366 case 0x33: /* xor GB,Ev */
368 case 0x64: /* prefix %fs */
369 return instruction_length(instr+1);
370 case 0x68: /* push $quad-byte */
372 case 0x6A: /* push $single-byte */
376 case 0x01: /* addl $byte,(%ecx) */
378 case 0x3D: /* cmpl $byte,immediate-quad-indirect */
379 return 1+1+4+1; /* 83 3D immediate-quad-indirect byte */
380 default: g_assert_not_reached();
382 case 0x8A: /* mov ??,?? */
383 case 0x8B: /* mov Gb,Eb */
385 case 0x0D: /* mov immediate-quad-indirect,%ecx */
387 case 0x44: /* mov #offset(%reg,%reg,#mult),%reg */
388 case 0x4C: /* mov #offset(%reg,#mult),%reg */
389 case 0x54: /* mov #offset(%reg,#mult),%reg */
390 return 1+1+1+1; /* 8B 44 address-mode offset */
391 default: g_assert_not_reached();
393 case 0x8D: /* lea Gb,M */
395 case 0x44: /* mov #offset(%reg,%reg,#mult),%reg */
396 return 4; /* 8B 44 address-mode offset */
397 default: g_assert_not_reached();
399 case 0x9C: /* pushf */
401 case 0x9D: /* popf */
403 case 0xA1: /* mov immediate-quad-indirect,%eax */
405 case 0xB8: /* mov $immediate-quad,%eax */
407 case 0xC2: /* ret $immediate-double */
409 case 0xCC: /* int $0x3 */
415 case 0xFF: /* inc/dec Ev */
417 default: g_assert_not_reached();
419 g_assert_not_reached(); /* TODO:fill the table */
425 /* A lot of offsets in the structures are relative to ModuleObject->Base */
426 #define MODULEOBJECT_BASE_OFFSET_PLUS(addr) ((gpointer)((char *)addr+(ptrdiff_t)ModuleObject->Base))
428 static void captive_ModuleList_patch_function_disable
429 (CHAR *funcname,PVOID *ExportAddressp,MODULE_OBJECT *ModuleObject /* user_data */)
433 g_return_if_fail(funcname!=NULL);
434 g_return_if_fail(ExportAddressp!=NULL);
435 g_return_if_fail(ModuleObject!=NULL);
437 ExportAddress=(PVOID)MODULEOBJECT_BASE_OFFSET_PLUS(*ExportAddressp);
438 g_return_if_fail(ExportAddress!=NULL);
440 /* Some alised name; safe to ignore as we checked for possible W32 binary 0xF4
441 * hits during our initialization in captive_ModuleList_patch().
443 if (0xF4 /* hlt */ ==*(guint8 *)ExportAddress)
446 captive_ModuleList_function_disable_hash_init();
448 *(guint8 *)ExportAddress=0xF4; /* hlt */
449 /* We may get aliased here; already existing entry is therefore allowed. */
450 g_hash_table_insert(captive_ModuleList_function_disable_hash,
451 ExportAddress, /* key */
452 funcname); /* value */
457 * captive_ModuleList_patch:
458 * @FullName_utf8: String to find #PMODULE_OBJECT by #FullName.
459 * @...: (const gchar *sym_name,void (*sym_val)(void),struct captive_ModuleList_patchpoint *patchpoint) symbol list terminated by %NULL.
461 * Patches existing @FullName_utf8 module to use for function named #sym_name
462 * pointer to the handler #sym_val. If #patchpoint is not %NULL it gets assigned the original
463 * pointer value (used for %pass keyword in #exports.captivesym).
465 * Put here 0xF4 'hlt' instead of 0xCC 'int $0x3; breakpoint'
466 * as 'hlt' will generate handled SIGSEGV instead of SIGTRAP which
467 * is used by gdb(1) during debugging.
468 * See also libcaptive/ps/signal.c/ sigaction_SIGSEGV().
470 * Returns: %TRUE if the module was successfuly added.
472 gboolean captive_ModuleList_patch(const gchar *FullName_utf8,...)
474 MODULE_OBJECT *ModuleObject;
476 IMAGE_EXPORT_DIRECTORY *ExportDir;
477 ptrdiff_t *NameList; /* filled by sym_name; MODULEOBJECT_BASE_OFFSET_PLUS()ed */
478 WORD *OrdinalList; /* linear list - libcaptive doesn't support Ordinals */
479 ptrdiff_t *FunctionList; /* filled by sym_val; MODULEOBJECT_BASE_OFFSET_PLUS()ed */
482 PVOID ExportAddress,*ExportAddressp;
483 const gchar *sym_name;
484 void (*sym_val)(void);
485 struct captive_ModuleList_patchpoint *patchpoint;
486 GHashTable *exportdir_hash;
489 g_return_val_if_fail(FullName_utf8!=NULL,FALSE);
491 captive_ModuleList_patchpoint_hash_init();
493 ModuleObject=LdrGetModuleObject(captive_utf8_to_UnicodeString_alloca(g_path_get_basename(FullName_utf8)));
494 g_return_val_if_fail(ModuleObject!=NULL,FALSE);
496 ExportDir=(PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(ModuleObject->Base,
497 TRUE,IMAGE_DIRECTORY_ENTRY_EXPORT,&ExportDirSize);
498 g_return_val_if_fail(ExportDir!=NULL,FALSE);
500 NameList =MODULEOBJECT_BASE_OFFSET_PLUS(ExportDir->AddressOfNames);
501 OrdinalList =MODULEOBJECT_BASE_OFFSET_PLUS(ExportDir->AddressOfNameOrdinals);
502 FunctionList=MODULEOBJECT_BASE_OFFSET_PLUS(ExportDir->AddressOfFunctions);
504 /* map (CHAR *)funcname->(PVOID *)ExportAddressp */
505 exportdir_hash=g_hash_table_new(g_str_hash,g_str_equal);
507 /* Initialize 'exportdir_hash' by all W32 exported functions. */
508 for (Idx=0;Idx<ExportDir->NumberOfNames;Idx++) {
509 CHAR *funcname=MODULEOBJECT_BASE_OFFSET_PLUS(NameList[Idx]);
511 ExportAddressp=(PVOID *)(FunctionList+OrdinalList[Idx]);
512 ExportAddress=(PVOID)MODULEOBJECT_BASE_OFFSET_PLUS(*ExportAddressp);
513 if (0xF4 /* hlt */ ==*(guint8 *)ExportAddress) {
514 g_error("%s: Function already patched although we did not touch it yet: %s",G_STRLOC,funcname);
515 g_assert_not_reached();
517 g_assert(NULL==g_hash_table_lookup(exportdir_hash,funcname));
518 g_hash_table_insert(exportdir_hash,
520 ExportAddressp); /* value */
523 /* Patch wished functions and remove them from 'exportdir_hash'. */
524 va_start(ap,FullName_utf8);
525 while (captive_va_arg(sym_name,ap)) {
526 captive_va_arg(sym_val ,ap);
527 g_assert(sym_val!=NULL);
528 captive_va_arg(patchpoint,ap);
529 g_assert(patchpoint!=NULL);
530 ExportAddressp=g_hash_table_lookup(exportdir_hash,sym_name);
531 if (ExportAddressp==NULL) {
532 g_error("%s: Function not found for patchpoint: %s",G_STRLOC,sym_name);
533 g_assert_not_reached();
535 errbool=g_hash_table_remove(exportdir_hash,sym_name);
536 g_assert(errbool==TRUE);
537 ExportAddress=(PVOID)MODULEOBJECT_BASE_OFFSET_PLUS(*ExportAddressp);
538 if (((ULONG)ExportAddress >= (ULONG)ExportDir) &&
539 ((ULONG)ExportAddress < (ULONG)ExportDir + ExportDirSize))
540 g_assert_not_reached(); /* LdrPEFixupForward() needed */
541 patchpoint->orig_w32_func=ExportAddress;
542 g_assert(0xF4 /* hlt */ !=*patchpoint->orig_w32_func);
543 patchpoint->orig_w32_2ndinstr=patchpoint->orig_w32_func
544 +instruction_length((guint8 *)patchpoint->orig_w32_func);
545 g_assert(0xF4 /* hlt */ !=*patchpoint->orig_w32_2ndinstr);
546 patchpoint->wrap_wrap_func=sym_val;
547 patchpoint->orig_w32_func_byte=*patchpoint->orig_w32_func;
548 patchpoint->orig_w32_2ndinstr_byte=*patchpoint->orig_w32_2ndinstr;
549 patchpoint->through_w32_func=FALSE;
550 g_assert(NULL==g_hash_table_lookup(captive_ModuleList_patchpoint_hash,patchpoint->orig_w32_func));
551 g_hash_table_insert(captive_ModuleList_patchpoint_hash,
552 patchpoint->orig_w32_func, /* key */
553 patchpoint); /* value */
554 g_assert(NULL==g_hash_table_lookup(captive_ModuleList_patchpoint_hash,patchpoint->orig_w32_2ndinstr));
555 g_hash_table_insert(captive_ModuleList_patchpoint_hash,
556 patchpoint->orig_w32_2ndinstr, /* key */
557 patchpoint); /* value */
558 *(guint8 *)ExportAddress=0xF4; /* hlt */
559 *ExportAddressp=(PVOID)MODULEOBJECT_BASE_OFFSET_MINUS(sym_val);
563 /* The remaining entries of 'exportdir_hash' are W32 native functions
564 * unspecified by .captivesym file; we patch them as not-implemented ones.
566 g_hash_table_foreach(exportdir_hash,
567 (GHFunc)captive_ModuleList_patch_function_disable, /* func */
568 ModuleObject); /* used_data; unused */
570 g_hash_table_destroy(exportdir_hash);
572 #undef MODULEOBJECT_BASE_OFFSET_PLUS /* no longer valid */
573 #undef MODULEOBJECT_BASE_OFFSET_MINUS /* no longer valid */
578 struct captive_ModuleList_patchpoint *captive_ModuleList_patchpoint_find(gconstpointer ExportAddress)
580 struct captive_ModuleList_patchpoint *r;
582 g_return_val_if_fail(ExportAddress!=NULL,NULL);
584 captive_ModuleList_patchpoint_hash_init();
586 r=g_hash_table_lookup(captive_ModuleList_patchpoint_hash,ExportAddress);
587 g_return_val_if_fail(r!=NULL,NULL);
588 g_assert(r->orig_w32_func==ExportAddress || r->orig_w32_2ndinstr==ExportAddress);
594 G_CONST_RETURN gchar *captive_ModuleList_function_disable_find(gconstpointer ExportAddress)
596 g_return_val_if_fail(ExportAddress!=NULL,NULL);
598 return g_hash_table_lookup(captive_ModuleList_function_disable_hash,ExportAddress); /* funcname */