PATCH: virtual fixes for native mode

Marcus Meissner marcus at jet.franken.de
Thu Feb 5 21:30:35 CST 2004


Hi,

This is the next try for assisting loading NT native dlls.

We need non-page aligned access for those drvs, which have sections
that are not page aligned.

Also some bad magic tries to write the import thunks into thefirst 
page, so we need to map the header r/w too.

Ciao, Marcus

Changelog:
	Added possibility to map native mode dlls which have sections
	that are not page aligned.

Index: virtual.c
===================================================================
RCS file: /home/wine/wine/dlls/ntdll/virtual.c,v
retrieving revision 1.24
diff -u -r1.24 virtual.c
--- virtual.c	30 Jan 2004 22:59:34 -0000	1.24
+++ virtual.c	6 Feb 2004 01:58:10 -0000
@@ -131,11 +131,15 @@
 #define ROUND_SIZE(addr,size) \
    (((UINT)(size) + ((UINT_PTR)(addr) & page_mask) + page_mask) & ~page_mask)
 
+#define ROUND_SIZE_MASK(addr,size,mask) \
+   (((UINT)(size) + ((UINT_PTR)(addr) & (mask)) + (mask)) & ~(mask))
+
 #define VIRTUAL_DEBUG_DUMP_VIEW(view) \
    if (!TRACE_ON(virtual)); else VIRTUAL_DumpView(view)
 
 static LPVOID VIRTUAL_mmap( int fd, LPVOID start, DWORD size, DWORD offset_low,
-                            DWORD offset_high, int prot, int flags, BOOL *removable );
+                            DWORD offset_high, int prot, int flags,
+			    BOOL *removable, BOOL usepagemask );
 
 
 /***********************************************************************
@@ -585,6 +589,8 @@
     int i, pos;
     FILE_VIEW *view;
     char *ptr;
+    BOOL native = FALSE;
+    DWORD secmask = page_mask;
 
     /* zero-map the whole range */
 
@@ -605,11 +611,20 @@
     /* map the header */
 
     if (VIRTUAL_mmap( fd, ptr, header_size, 0, 0, PROT_READ,
-                      MAP_PRIVATE | MAP_FIXED, &removable ) == (char *)-1) goto error;
+                      MAP_PRIVATE | MAP_FIXED, &removable, TRUE ) == (char *)-1) goto error;
     dos = (IMAGE_DOS_HEADER *)ptr;
     nt = (IMAGE_NT_HEADERS *)(ptr + dos->e_lfanew);
     if ((char *)(nt + 1) > ptr + header_size) goto error;
 
+    /* Check if we are loading a native mode driver / dll */
+    if ((nt->FileHeader.SizeOfOptionalHeader >= 0x44) &&
+    	(nt->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_NATIVE)
+    ) {
+	if ( nt->OptionalHeader.SectionAlignment)
+	    secmask = nt->OptionalHeader.SectionAlignment-1;
+	native = TRUE;
+    }
+
     sec = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
     if ((char *)(sec + nt->FileHeader.NumberOfSections) > ptr + header_size) goto error;
 
@@ -643,7 +658,7 @@
         DWORD size;
 
         /* a few sanity checks */
-        size = sec->VirtualAddress + ROUND_SIZE( sec->VirtualAddress, sec->Misc.VirtualSize );
+        size = sec->VirtualAddress + ROUND_SIZE_MASK( sec->VirtualAddress, sec->Misc.VirtualSize, secmask );
         if (sec->VirtualAddress > total_size || size > total_size || size < sec->VirtualAddress)
         {
             ERR_(module)( "Section %.8s too large (%lx+%lx/%lx)\n",
@@ -654,14 +669,14 @@
         if ((sec->Characteristics & IMAGE_SCN_MEM_SHARED) &&
             (sec->Characteristics & IMAGE_SCN_MEM_WRITE))
         {
-            size = ROUND_SIZE( 0, sec->Misc.VirtualSize );
-            TRACE_(module)( "mapping shared section %.8s at %p off %lx (%x) size %lx (%lx) flags %lx\n",
+            size = ROUND_SIZE_MASK( 0, sec->Misc.VirtualSize, secmask );
+            TRACE_(module)( "mapping shared section %.8s at %p off 0x%lx (%x) size %lx (%lx) flags %lx\n",
                           sec->Name, ptr + sec->VirtualAddress,
                           sec->PointerToRawData, pos, sec->SizeOfRawData,
                           size, sec->Characteristics );
             if (VIRTUAL_mmap( shared_fd, ptr + sec->VirtualAddress, size,
                               pos, 0, PROT_READ|PROT_WRITE|PROT_EXEC,
-                              MAP_SHARED|MAP_FIXED, NULL ) == (void *)-1)
+                              MAP_SHARED|MAP_FIXED, NULL, !native ) == (void *)-1)
             {
                 ERR_(module)( "Could not map shared section %.8s\n", sec->Name );
                 goto error;
@@ -672,12 +687,12 @@
                 imports->VirtualAddress < sec->VirtualAddress + size)
             {
                 UINT_PTR base = imports->VirtualAddress & ~page_mask;
-                UINT_PTR end = base + ROUND_SIZE( imports->VirtualAddress, imports->Size );
+                UINT_PTR end = base + ROUND_SIZE_MASK( imports->VirtualAddress, imports->Size, secmask );
                 if (end > sec->VirtualAddress + size) end = sec->VirtualAddress + size;
                 if (end > base) VIRTUAL_mmap( shared_fd, ptr + base, end - base,
                                               pos + (base - sec->VirtualAddress), 0,
                                               PROT_READ|PROT_WRITE|PROT_EXEC,
-                                              MAP_PRIVATE|MAP_FIXED, NULL );
+                                              MAP_PRIVATE|MAP_FIXED, NULL, !native );
             }
             pos += size;
             continue;
@@ -697,7 +712,7 @@
          */
         if (VIRTUAL_mmap( fd, ptr + sec->VirtualAddress, sec->SizeOfRawData,
                           sec->PointerToRawData, 0, PROT_READ|PROT_WRITE|PROT_EXEC,
-                          MAP_PRIVATE | MAP_FIXED, &removable ) == (void *)-1)
+                          MAP_PRIVATE | MAP_FIXED, &removable, !native ) == (void *)-1)
         {
             ERR_(module)( "Could not map section %.8s, file probably truncated\n", sec->Name );
             goto error;
@@ -705,7 +720,7 @@
 
         if ((sec->SizeOfRawData < sec->Misc.VirtualSize) && (sec->SizeOfRawData & page_mask))
         {
-            DWORD end = ROUND_SIZE( 0, sec->SizeOfRawData );
+            DWORD end = ROUND_SIZE_MASK( 0, sec->SizeOfRawData, secmask );
             if (end > sec->Misc.VirtualSize) end = sec->Misc.VirtualSize;
             TRACE_(module)("clearing %p - %p\n",
                            ptr + sec->VirtualAddress + sec->SizeOfRawData,
@@ -757,7 +772,7 @@
 
     /* set the image protections */
 
-    VIRTUAL_SetProt( view, ptr, header_size, VPROT_COMMITTED | VPROT_READ );
+    VIRTUAL_SetProt( view, ptr, header_size, VPROT_COMMITTED | VPROT_READ | (native?VPROT_WRITE:0));
     sec = (IMAGE_SECTION_HEADER*)((char *)&nt->OptionalHeader+nt->FileHeader.SizeOfOptionalHeader);
     for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
     {
@@ -934,7 +949,8 @@
  */
 static LPVOID VIRTUAL_mmap( int fd, LPVOID start, DWORD size,
                             DWORD offset_low, DWORD offset_high,
-                            int prot, int flags, BOOL *removable )
+                            int prot, int flags, BOOL *removable,
+			    BOOL usepagemask )
 {
     LPVOID ret;
     off_t offset;
@@ -972,7 +988,28 @@
  fake_mmap:
     /* Reserve the memory with an anonymous mmap */
     ret = wine_anon_mmap( start, size, PROT_READ | PROT_WRITE, flags );
-    if (ret == (LPVOID)-1) return ret;
+    if (ret == (LPVOID)-1) {
+	if (!usepagemask) { /* Only used in NT native mode */
+	    /* This only happens for WDMs, where the sections are not page aligned.
+	     * The whole file however is. */
+	    if (((int)start & page_mask)) {
+		int xoff = (unsigned int)start & page_mask;
+
+		offset_low -= xoff;
+		start = (char*)start - xoff;
+		size += xoff;
+		ret = wine_anon_mmap( start, size, PROT_READ | PROT_WRITE, flags );
+		if (ret != (LPVOID)-1) {
+			/* Now read in the file */
+			offset = ((off_t)offset_high << 32) | offset_low;
+			pread( fd, ret, size, offset );
+			mprotect( ret, size, prot );  /* Set the right protection */
+			return (char*)ret + xoff;
+		}
+	    }
+	}
+	return ret;
+    }
     /* Now read in the file */
     offset = ((off_t)offset_high << 32) | offset_low;
     pread( fd, ret, size, offset );
@@ -1515,7 +1552,7 @@
     TRACE("handle=%p size=%x offset=%lx\n", handle, size, offset->u.LowPart );
 
     ret = VIRTUAL_mmap( unix_handle, ptr, size, offset->u.LowPart, offset->u.HighPart,
-                        VIRTUAL_GetUnixProt( prot ), flags | MAP_FIXED, &removable );
+                        VIRTUAL_GetUnixProt( prot ), flags | MAP_FIXED, &removable, TRUE );
     if (ret != ptr)
     {
         ERR( "VIRTUAL_mmap %p %x %lx%08lx failed\n",



More information about the wine-patches mailing list