5959typedef BOOL (WINAPI * DllEntryProc )(HINSTANCE hinstDLL , DWORD fdwReason , LPVOID lpReserved );
6060typedef int (WINAPI * ExeEntryProc )(void );
6161
62+ #ifdef _WIN64
63+ // simple linked list to store memory blocks that span the 4GB boundary
64+ // (which can't be used as memory for memorymodule)
65+ typedef struct tagPOINTER_LIST {
66+ tagPOINTER_LIST * next ;
67+ unsigned char * address ;
68+ }POINTER_LIST ;
69+ #endif
70+
6271typedef struct {
6372 PIMAGE_NT_HEADERS headers ;
6473 unsigned char * codeBase ;
@@ -75,6 +84,9 @@ typedef struct {
7584 void * userdata ;
7685 ExeEntryProc exeEntry ;
7786 DWORD pageSize ;
87+ #ifdef _WIN64
88+ POINTER_LIST * blockedMemory ;
89+ #endif
7890} MEMORYMODULE , * PMEMORYMODULE ;
7991
8092typedef struct {
@@ -125,6 +137,18 @@ OutputLastError(const char *msg)
125137#endif
126138}
127139
140+ #ifdef _WIN64
141+ static void FreePointerList (POINTER_LIST * head , CustomFreeFunc freeMemory , void * userdata ) {
142+ POINTER_LIST * node = head ;
143+ while (node != NULL ) {
144+ POINTER_LIST * current = node ;
145+ freeMemory (current -> address , 0 , MEM_RELEASE , userdata );
146+ current = current -> next ;
147+ free (node );
148+ }
149+ }
150+ #endif
151+
128152static BOOL
129153CheckSize (size_t size , size_t expected ) {
130154 if (size < expected ) {
@@ -523,6 +547,9 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
523547 size_t optionalSectionSize ;
524548 size_t lastSectionEnd = 0 ;
525549 size_t alignedImageSize ;
550+ #ifdef _WIN64
551+ POINTER_LIST * blockedMemory = NULL ;
552+ #endif
526553
527554 if (!CheckSize (size , sizeof (IMAGE_DOS_HEADER ))) {
528555 return NULL ;
@@ -598,9 +625,41 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
598625 }
599626 }
600627
628+ #ifdef _WIN64
629+ // check that memory-block does not span over the 4GB border
630+ if ((unsigned long long )(code ) / 0x100000000 < (unsigned long long )(code + alignedImageSize ) / 0x100000000 )
631+ {
632+ POINTER_LIST * * current_node_ptr = & blockedMemory ;
633+
634+ do
635+ {
636+ // store code to keep bad address blocked
637+ * current_node_ptr = (POINTER_LIST * )malloc (sizeof (POINTER_LIST ));
638+ (* current_node_ptr )-> next = NULL ;
639+ (* current_node_ptr )-> address = code ;
640+ current_node_ptr = & (* current_node_ptr )-> next ;
641+
642+ code = (unsigned char * )allocMemory (NULL ,
643+ alignedImageSize ,
644+ MEM_RESERVE | MEM_COMMIT ,
645+ PAGE_READWRITE ,
646+ userdata );
647+
648+ if (code == NULL ) {
649+ FreePointerList (blockedMemory , freeMemory , userdata );
650+ SetLastError (ERROR_OUTOFMEMORY );
651+ return NULL ;
652+ }
653+ } while ((unsigned long long )(code ) / 0x100000000 < (unsigned long long )(code + alignedImageSize ) / 0x100000000 );
654+ }
655+ #endif
656+
601657 result = (PMEMORYMODULE )HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY , sizeof (MEMORYMODULE ));
602658 if (result == NULL ) {
603659 freeMemory (code , 0 , MEM_RELEASE , userdata );
660+ #ifdef _WIN64
661+ FreePointerList (blockedMemory , freeMemory , userdata );
662+ #endif
604663 SetLastError (ERROR_OUTOFMEMORY );
605664 return NULL ;
606665 }
@@ -614,6 +673,9 @@ HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
614673 result -> freeLibrary = freeLibrary ;
615674 result -> userdata = userdata ;
616675 result -> pageSize = sysInfo .dwPageSize ;
676+ #ifdef _WIN64
677+ result -> blockedMemory = blockedMemory ;
678+ #endif
617679
618680 if (!CheckSize (size , old_header -> OptionalHeader .SizeOfHeaders )) {
619681 goto error ;
@@ -776,6 +838,11 @@ void MemoryFreeLibrary(HMEMORYMODULE mod)
776838 module -> free (module -> codeBase , 0 , MEM_RELEASE , module -> userdata );
777839 }
778840
841+ #ifdef _WIN64
842+ // release blockeded memory
843+ FreePointerList (module -> blockedMemory , module -> free , module -> userdata );
844+ #endif
845+
779846 HeapFree (GetProcessHeap (), 0 , module );
780847}
781848
0 commit comments