22
22
* Portions created by Joachim Bauch are Copyright (C) 2004-2015
23
23
* Joachim Bauch. All Rights Reserved.
24
24
*
25
+ *
26
+ * THeller: Added binary search in MemoryGetProcAddress function
27
+ * (#define USE_BINARY_SEARCH to enable it). This gives a very large
28
+ * speedup for libraries that exports lots of functions.
29
+ *
30
+ * These portions are Copyright (C) 2013 Thomas Heller.
25
31
*/
26
32
27
33
#include <windows.h>
56
62
57
63
#include "MemoryModule.h"
58
64
65
+ struct ExportNameEntry {
66
+ LPCSTR name ;
67
+ WORD idx ;
68
+ };
69
+
59
70
typedef BOOL (WINAPI * DllEntryProc )(HINSTANCE hinstDLL , DWORD fdwReason , LPVOID lpReserved );
60
71
typedef int (WINAPI * ExeEntryProc )(void );
61
72
@@ -72,6 +83,7 @@ typedef struct {
72
83
CustomLoadLibraryFunc loadLibrary ;
73
84
CustomGetProcAddressFunc getProcAddress ;
74
85
CustomFreeLibraryFunc freeLibrary ;
86
+ struct ExportNameEntry * nameExportsTable ;
75
87
void * userdata ;
76
88
ExeEntryProc exeEntry ;
77
89
DWORD pageSize ;
@@ -688,12 +700,27 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
688
700
return NULL ;
689
701
}
690
702
691
- FARPROC MemoryGetProcAddress (HMEMORYMODULE module , LPCSTR name )
703
+ static int _compare (const void * a , const void * b )
704
+ {
705
+ const struct ExportNameEntry * p1 = (const struct ExportNameEntry * ) a ;
706
+ const struct ExportNameEntry * p2 = (const struct ExportNameEntry * ) b ;
707
+ return _stricmp (p1 -> name , p2 -> name );
708
+ }
709
+
710
+ static int _find (const void * a , const void * b )
711
+ {
712
+ LPCSTR * name = (LPCSTR * ) a ;
713
+ const struct ExportNameEntry * p = (const struct ExportNameEntry * ) b ;
714
+ return _stricmp (* name , p -> name );
715
+ }
716
+
717
+ FARPROC MemoryGetProcAddress (HMEMORYMODULE mod , LPCSTR name )
692
718
{
693
- unsigned char * codeBase = ((PMEMORYMODULE )module )-> codeBase ;
719
+ PMEMORYMODULE module = (PMEMORYMODULE )mod ;
720
+ unsigned char * codeBase = module -> codeBase ;
694
721
DWORD idx = 0 ;
695
722
PIMAGE_EXPORT_DIRECTORY exports ;
696
- PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY (( PMEMORYMODULE ) module , IMAGE_DIRECTORY_ENTRY_EXPORT );
723
+ PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY (module , IMAGE_DIRECTORY_ENTRY_EXPORT );
697
724
if (directory -> Size == 0 ) {
698
725
// no export table found
699
726
SetLastError (ERROR_PROC_NOT_FOUND );
@@ -715,25 +742,44 @@ FARPROC MemoryGetProcAddress(HMEMORYMODULE module, LPCSTR name)
715
742
}
716
743
717
744
idx = LOWORD (name ) - exports -> Base ;
745
+ } else if (!exports -> NumberOfNames ) {
746
+ SetLastError (ERROR_PROC_NOT_FOUND );
747
+ return NULL ;
718
748
} else {
719
- // search function name in list of exported names
720
- DWORD i ;
721
- DWORD * nameRef = (DWORD * ) (codeBase + exports -> AddressOfNames );
722
- WORD * ordinal = (WORD * ) (codeBase + exports -> AddressOfNameOrdinals );
723
- BOOL found = FALSE;
724
- for (i = 0 ; i < exports -> NumberOfNames ; i ++ , nameRef ++ , ordinal ++ ) {
725
- if (_stricmp (name , (const char * ) (codeBase + (* nameRef ))) == 0 ) {
726
- idx = * ordinal ;
727
- found = TRUE;
728
- break ;
749
+ const struct ExportNameEntry * found ;
750
+
751
+ // Lazily build name table and sort it by names
752
+ if (!module -> nameExportsTable ) {
753
+ DWORD i ;
754
+ DWORD * nameRef = (DWORD * ) (codeBase + exports -> AddressOfNames );
755
+ WORD * ordinal = (WORD * ) (codeBase + exports -> AddressOfNameOrdinals );
756
+ struct ExportNameEntry * entry = (struct ExportNameEntry * ) malloc (exports -> NumberOfNames * sizeof (struct ExportNameEntry ));
757
+ module -> nameExportsTable = entry ;
758
+ if (!entry ) {
759
+ SetLastError (ERROR_OUTOFMEMORY );
760
+ return NULL ;
729
761
}
762
+ for (i = 0 ; i < exports -> NumberOfNames ; i ++ , nameRef ++ , ordinal ++ , entry ++ ) {
763
+ entry -> name = (const char * ) (codeBase + (* nameRef ));
764
+ entry -> idx = * ordinal ;
765
+ }
766
+ qsort (module -> nameExportsTable ,
767
+ exports -> NumberOfNames ,
768
+ sizeof (struct ExportNameEntry ), _compare );
730
769
}
731
770
771
+ // search function name in list of exported names with binary search
772
+ found = (const struct ExportNameEntry * ) bsearch (& name ,
773
+ module -> nameExportsTable ,
774
+ exports -> NumberOfNames ,
775
+ sizeof (struct ExportNameEntry ), _find );
732
776
if (!found ) {
733
777
// exported symbol not found
734
778
SetLastError (ERROR_PROC_NOT_FOUND );
735
779
return NULL ;
736
780
}
781
+
782
+ idx = found -> idx ;
737
783
}
738
784
739
785
if (idx > exports -> NumberOfFunctions ) {
@@ -759,6 +805,7 @@ void MemoryFreeLibrary(HMEMORYMODULE mod)
759
805
(* DllEntry )((HINSTANCE )module -> codeBase , DLL_PROCESS_DETACH , 0 );
760
806
}
761
807
808
+ free (module -> nameExportsTable );
762
809
if (module -> modules != NULL ) {
763
810
// free previously opened libraries
764
811
int i ;
0 commit comments