Alexandre Julliard : kernel32: Reserve the low 64Kb area separately from the rest of the DOS memory.

Alexandre Julliard julliard at winehq.org
Mon Apr 14 17:20:49 CDT 2008


Module: wine
Branch: master
Commit: f02ef19fdbf5d7396f71433bd26b904577e09fe4
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=f02ef19fdbf5d7396f71433bd26b904577e09fe4

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Apr 14 20:39:27 2008 +0200

kernel32: Reserve the low 64Kb area separately from the rest of the DOS memory.

---

 dlls/kernel32/dosmem.c |   72 +++++++++++++++++++++++++++++------------------
 1 files changed, 44 insertions(+), 28 deletions(-)

diff --git a/dlls/kernel32/dosmem.c b/dlls/kernel32/dosmem.c
index a976cba..f3aad4c 100644
--- a/dlls/kernel32/dosmem.c
+++ b/dlls/kernel32/dosmem.c
@@ -142,9 +142,8 @@ static LONG WINAPI dosmem_handler(EXCEPTION_POINTERS* except)
 {
     if (except->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
     {
-        DWORD   addr = except->ExceptionRecord->ExceptionInformation[1];
-        if (addr >= (ULONG_PTR)DOSMEM_dosmem + DOSMEM_protect &&
-            addr < (ULONG_PTR)DOSMEM_dosmem + DOSMEM_SIZE)
+        char *addr = (char *)except->ExceptionRecord->ExceptionInformation[1];
+        if (addr >= DOSMEM_dosmem + DOSMEM_protect && addr < DOSMEM_dosmem + DOSMEM_SIZE)
         {
             if (load_winedos()) return EXCEPTION_CONTINUE_EXECUTION;
         }
@@ -159,42 +158,58 @@ static LONG WINAPI dosmem_handler(EXCEPTION_POINTERS* except)
  */
 static char* setup_dos_mem(void)
 {
-    int sys_offset = 0;
+    size_t size;
     int page_size = getpagesize();
     void *addr = NULL;
+    void * const low_64k = (void *)DOSMEM_64KB;
 
-    if (wine_mmap_is_in_reserved_area( NULL, DOSMEM_SIZE ) != 1)
+    /* check without the first 64K */
+
+    if (wine_mmap_is_in_reserved_area( low_64k, DOSMEM_SIZE - DOSMEM_64KB ) != 1)
     {
-        addr = wine_anon_mmap( (void *)page_size, DOSMEM_SIZE-page_size,
-                               PROT_READ | PROT_WRITE, 0 );
-        if (addr == (void *)page_size) addr = NULL; /* we got what we wanted */
-        else munmap( addr, DOSMEM_SIZE - page_size );
+        addr = wine_anon_mmap( low_64k, DOSMEM_SIZE - DOSMEM_64KB, PROT_READ | PROT_WRITE, 0 );
+        if (addr != low_64k)
+        {
+            if (addr != MAP_FAILED) munmap( addr, DOSMEM_SIZE - DOSMEM_64KB );
+            ERR("Cannot use first megabyte for DOS address space, please report\n" );
+            /* allocate the DOS area somewhere else */
+            if (!(DOSMEM_dosmem = VirtualAlloc( NULL, DOSMEM_SIZE, MEM_RESERVE, PAGE_NOACCESS )))
+            {
+                ERR( "Cannot allocate DOS memory\n" );
+                ExitProcess(1);
+            }
+            return DOSMEM_dosmem;
+        }
     }
 
-    if (!addr)
-    {
-        /* now reserve from address 0 */
-        wine_anon_mmap( NULL, DOSMEM_SIZE, PROT_NONE, MAP_FIXED );
+    /* now try to allocate the low 64K too */
 
-        /* inform the memory manager that there is a mapping here, but don't commit yet */
-        VirtualAlloc( NULL, DOSMEM_SIZE, MEM_RESERVE | MEM_SYSTEM, PAGE_NOACCESS );
-        sys_offset = 0xf0000;
-        DOSMEM_protect = DOSMEM_64KB;
-    }
-    else
+    if (wine_mmap_is_in_reserved_area( NULL, DOSMEM_64KB ) != 1)
     {
-        ERR("Cannot use first megabyte for DOS address space, please report\n" );
-        /* allocate the DOS area somewhere else */
-        addr = VirtualAlloc( NULL, DOSMEM_SIZE, MEM_RESERVE, PAGE_NOACCESS );
-        if (!addr)
+        addr = wine_anon_mmap( (void *)page_size, DOSMEM_64KB - page_size, PROT_READ | PROT_WRITE, 0 );
+        if (addr == (void *)page_size)
         {
-            ERR( "Cannot allocate DOS memory\n" );
-            ExitProcess(1);
+            addr = NULL;
+            TRACE( "successfully mapped low 64K range\n" );
+        }
+        else
+        {
+            if (addr != MAP_FAILED) munmap( addr, DOSMEM_64KB - page_size );
+            addr = low_64k;
+            TRACE( "failed to map low 64K range\n" );
         }
     }
-    DOSMEM_dosmem = addr;
-    RtlAddVectoredExceptionHandler(FALSE, dosmem_handler);
-    return (char*)addr + sys_offset;
+    else addr = NULL;
+
+    /* now reserve the whole range */
+    size = (char *)DOSMEM_SIZE - (char *)addr;
+    wine_anon_mmap( addr, size, PROT_NONE, MAP_FIXED );
+
+    /* inform the memory manager that there is a mapping here, but don't commit yet */
+    VirtualAlloc( addr, size, MEM_RESERVE | MEM_SYSTEM, PAGE_NOACCESS );
+    DOSMEM_protect = DOSMEM_64KB;
+    DOSMEM_dosmem = NULL;
+    return (char *)0xf0000;  /* store sysmem in high addresses for now */
 }
 
 
@@ -208,6 +223,7 @@ BOOL DOSMEM_Init(void)
 {
     char*       sysmem = setup_dos_mem();
 
+    RtlAddVectoredExceptionHandler(FALSE, dosmem_handler);
     DOSMEM_0000H = GLOBAL_CreateBlock( GMEM_FIXED, sysmem,
                                        DOSMEM_64KB, 0, WINE_LDT_FLAGS_DATA );
     DOSMEM_BiosDataSeg = GLOBAL_CreateBlock( GMEM_FIXED, sysmem + 0x400,




More information about the wine-cvs mailing list