* dlfcn.cc (dlopen): Reimplement RTLD_NODELETE for Windows 2000 using
internal datastructures. Explain the code. * ntdll.h (struct _LDR_DATA_TABLE_ENTRY): Define. (struct _PEB_LDR_DATA): Define. (struct _PEB): Change PVOID LoaderData to PPEB_LDR_DATA Ldr. * fhandler_process.cc (format_process_maps): Call NtQueryVirtualMemory with valid return length pointer. Explain why.
This commit is contained in:
		| @@ -1,3 +1,14 @@ | ||||
| 2011-08-16  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* dlfcn.cc (dlopen): Reimplement RTLD_NODELETE for Windows 2000 using | ||||
| 	internal datastructures.  Explain the code. | ||||
| 	* ntdll.h (struct _LDR_DATA_TABLE_ENTRY): Define. | ||||
| 	(struct _PEB_LDR_DATA): Define. | ||||
| 	(struct _PEB): Change PVOID LoaderData to PPEB_LDR_DATA Ldr. | ||||
|  | ||||
| 	* fhandler_process.cc (format_process_maps): Call NtQueryVirtualMemory | ||||
| 	with valid return length pointer.  Explain why. | ||||
|  | ||||
| 2011-08-16  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* include/cygwin/version.h (CYGWIN_VERSION_API_MINOR): Bump. | ||||
|   | ||||
| @@ -120,12 +120,27 @@ dlopen (const char *name, int flags) | ||||
| 					  (HMODULE *) &ret)) | ||||
| 		{ | ||||
| 		  /* Windows 2000 is missing the GetModuleHandleEx call, so we | ||||
| 		     just use a trick.  Call LoadLibrary 10 times more if the | ||||
| 		     RTLD_NODELETE flag has been specified.  That makes it | ||||
| 		     unlikely (but not impossible) that dlclose will actually | ||||
| 		     free the library. */ | ||||
| 		  for (int i = 0; i < 10; ++i) | ||||
| 		    LoadLibraryW (path); | ||||
| 		     use a non-documented way to set the DLL to "don't free". | ||||
| 		     This is how it works:  Fetch the Windows Loader data from | ||||
| 		     the PEB.  Iterate backwards through the list of loaded | ||||
| 		     DLLs and compare the DllBase address with the address | ||||
| 		     returned by LoadLibrary.  If they are equal we found the | ||||
| 		     right entry.  Now set the LoadCount to -1, which is the | ||||
| 		     marker for a DLL which should never be free'd. */ | ||||
| 		  PPEB_LDR_DATA ldr = NtCurrentTeb ()->Peb->Ldr; | ||||
|  | ||||
| 		  for (PLDR_DATA_TABLE_ENTRY entry = (PLDR_DATA_TABLE_ENTRY) | ||||
| 					     ldr->InLoadOrderModuleList.Blink; | ||||
| 		       entry && entry->DllBase; | ||||
| 		       entry = (PLDR_DATA_TABLE_ENTRY) | ||||
| 			       entry->InLoadOrderLinks.Blink) | ||||
| 		    { | ||||
| 		      if (entry->DllBase == ret) | ||||
| 			{ | ||||
| 			  entry->LoadCount = (WORD) -1; | ||||
| 			  break; | ||||
| 			} | ||||
| 		    } | ||||
| 		} | ||||
| 	    } | ||||
|  | ||||
|   | ||||
| @@ -960,12 +960,16 @@ format_process_maps (void *data, char *&destbuf) | ||||
| 	  // if a new allocation, figure out what kind it is | ||||
| 	  if (newbase && !last_pass && mb.State != MEM_FREE) | ||||
| 	    { | ||||
| 	      /* If the return length pointer is missing, NtQueryVirtualMemory | ||||
| 		 returns with STATUS_ACCESS_VIOLATION on Windows 2000. */ | ||||
| 	      ULONG ret_len = 0; | ||||
|  | ||||
| 	      st.st_dev = 0; | ||||
| 	      st.st_ino = 0; | ||||
| 	      if ((mb.Type & (MEM_MAPPED | MEM_IMAGE)) | ||||
| 		  && NT_SUCCESS (NtQueryVirtualMemory (proc, cur.abase, | ||||
| 		  && NT_SUCCESS (status = NtQueryVirtualMemory (proc, cur.abase, | ||||
| 						       MemorySectionName, | ||||
| 						       msi, 65536, NULL))) | ||||
| 						       msi, 65536, &ret_len))) | ||||
| 		{ | ||||
| 		  PWCHAR dosname = | ||||
| 		      drive_maps.fixup_if_match (msi->SectionFileName.Buffer); | ||||
|   | ||||
| @@ -579,6 +579,34 @@ typedef struct _KERNEL_USER_TIMES | ||||
|   LARGE_INTEGER UserTime; | ||||
| } KERNEL_USER_TIMES, *PKERNEL_USER_TIMES; | ||||
|  | ||||
| typedef struct _LDR_DATA_TABLE_ENTRY | ||||
| { | ||||
|   LIST_ENTRY InLoadOrderLinks; | ||||
|   LIST_ENTRY InMemoryOrderLinks; | ||||
|   LIST_ENTRY InInitializationOrderLinks; | ||||
|   PVOID DllBase; | ||||
|   PVOID EntryPoint; | ||||
|   ULONG SizeOfImage; | ||||
|   UNICODE_STRING FullDllName; | ||||
|   UNICODE_STRING BaseDllName; | ||||
|   ULONG Flags; | ||||
|   WORD LoadCount; | ||||
|   /* More follows.  Left out since it's just not used.  The aforementioned | ||||
|      part of the structure is stable from at least NT4 up to Windows 7, | ||||
|      including WOW64. */ | ||||
| } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; | ||||
|  | ||||
| typedef struct _PEB_LDR_DATA | ||||
| { | ||||
|   ULONG Length; | ||||
|   UCHAR Initialized; | ||||
|   PVOID SsHandle; | ||||
|   LIST_ENTRY InLoadOrderModuleList; | ||||
|   LIST_ENTRY InMemoryOrderModuleList; | ||||
|   LIST_ENTRY InInitializationOrderModuleList; | ||||
|   PVOID EntryInProgress; | ||||
| } PEB_LDR_DATA, *PPEB_LDR_DATA; | ||||
|  | ||||
| typedef struct _RTL_USER_PROCESS_PARAMETERS | ||||
| { | ||||
|   ULONG AllocationSize; | ||||
| @@ -616,7 +644,7 @@ typedef struct _PEB | ||||
|   BYTE Reserved1[2]; | ||||
|   BYTE BeingDebugged; | ||||
|   BYTE Reserved2[9]; | ||||
|   PVOID LoaderData; | ||||
|   PPEB_LDR_DATA Ldr; | ||||
|   PRTL_USER_PROCESS_PARAMETERS ProcessParameters; | ||||
|   BYTE Reserved3[4]; | ||||
|   PVOID ProcessHeap; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user