Alexandre Julliard : kernel32: Moved allocation of the DOS memory area to ntdll.

Alexandre Julliard julliard at winehq.org
Wed Nov 19 08:34:41 CST 2008


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Nov 18 20:11:49 2008 +0100

kernel32: Moved allocation of the DOS memory area to ntdll.

---

 dlls/kernel32/dosmem.c |   84 ++++++++++++-----------------------------------
 dlls/ntdll/virtual.c   |   79 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 99 insertions(+), 64 deletions(-)

diff --git a/dlls/kernel32/dosmem.c b/dlls/kernel32/dosmem.c
index f3aad4c..a1bff4d 100644
--- a/dlls/kernel32/dosmem.c
+++ b/dlls/kernel32/dosmem.c
@@ -151,77 +151,37 @@ static LONG WINAPI dosmem_handler(EXCEPTION_POINTERS* except)
     return EXCEPTION_CONTINUE_SEARCH;
 }
 
-/**********************************************************************
- *		setup_dos_mem
+/***********************************************************************
+ *           DOSMEM_Init
  *
- * Setup the first megabyte for DOS memory access
+ * Create the dos memory segments, and store them into the KERNEL
+ * exported values.
  */
-static char* setup_dos_mem(void)
+BOOL DOSMEM_Init(void)
 {
-    size_t size;
-    int page_size = getpagesize();
-    void *addr = NULL;
-    void * const low_64k = (void *)DOSMEM_64KB;
-
-    /* check without the first 64K */
+    char *sysmem;
+    void *addr = (void *)1;
+    SIZE_T size = DOSMEM_SIZE - 1;
 
-    if (wine_mmap_is_in_reserved_area( low_64k, DOSMEM_SIZE - DOSMEM_64KB ) != 1)
+    if (NtAllocateVirtualMemory( GetCurrentProcess(), &addr, 0, &size,
+                                 MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS ))
     {
-        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;
-        }
+        ERR( "Cannot allocate DOS memory\n" );
+        ExitProcess(1);
     }
 
-    /* now try to allocate the low 64K too */
-
-    if (wine_mmap_is_in_reserved_area( NULL, DOSMEM_64KB ) != 1)
+    DOSMEM_dosmem = addr;
+    if (!addr)
     {
-        addr = wine_anon_mmap( (void *)page_size, DOSMEM_64KB - page_size, PROT_READ | PROT_WRITE, 0 );
-        if (addr == (void *)page_size)
-        {
-            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_protect = DOSMEM_64KB;
+        sysmem = (char *)0xf0000;  /* store sysmem in high addresses for now */
+    }
+    else
+    {
+        WARN( "First megabyte not available for DOS address space.\n" );
+        DOSMEM_protect = 0;
+        sysmem = DOSMEM_dosmem;
     }
-    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 */
-}
-
-
-/***********************************************************************
- *           DOSMEM_Init
- *
- * Create the dos memory segments, and store them into the KERNEL
- * exported values.
- */
-BOOL DOSMEM_Init(void)
-{
-    char*       sysmem = setup_dos_mem();
 
     RtlAddVectoredExceptionHandler(FALSE, dosmem_handler);
     DOSMEM_0000H = GLOBAL_CreateBlock( GMEM_FIXED, sysmem,
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 80cd32f..12424f0 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -861,6 +861,66 @@ static NTSTATUS decommit_pages( struct file_view *view, size_t start, size_t siz
 
 
 /***********************************************************************
+ *           allocate_dos_memory
+ *
+ * Allocate the DOS memory range.
+ */
+static NTSTATUS allocate_dos_memory( struct file_view **view, unsigned int vprot )
+{
+    size_t size;
+    void *addr = NULL;
+    void * const low_64k = (void *)0x10000;
+    const size_t dosmem_size = 0x110000;
+    int unix_prot = VIRTUAL_GetUnixProt( vprot );
+    struct list *ptr;
+
+    /* check for existing view */
+
+    if ((ptr = list_head( &views_list )))
+    {
+        struct file_view *first_view = LIST_ENTRY( ptr, struct file_view, entry );
+        if (first_view->base < (void *)dosmem_size) return STATUS_CONFLICTING_ADDRESSES;
+    }
+
+    /* check without the first 64K */
+
+    if (wine_mmap_is_in_reserved_area( low_64k, dosmem_size - 0x10000 ) != 1)
+    {
+        addr = wine_anon_mmap( low_64k, dosmem_size - 0x10000, unix_prot, 0 );
+        if (addr != low_64k)
+        {
+            if (addr != (void *)-1) munmap( addr, dosmem_size - 0x10000 );
+            return map_view( view, NULL, dosmem_size, 0xffff, 0, vprot );
+        }
+    }
+
+    /* now try to allocate the low 64K too */
+
+    if (wine_mmap_is_in_reserved_area( NULL, 0x10000 ) != 1)
+    {
+        addr = wine_anon_mmap( (void *)page_size, 0x10000 - page_size, unix_prot, 0 );
+        if (addr == (void *)page_size)
+        {
+            addr = NULL;
+            TRACE( "successfully mapped low 64K range\n" );
+        }
+        else
+        {
+            if (addr != (void *)-1) munmap( addr, 0x10000 - page_size );
+            addr = low_64k;
+            TRACE( "failed to map low 64K range\n" );
+        }
+    }
+
+    /* now reserve the whole range */
+
+    size = (char *)dosmem_size - (char *)addr;
+    wine_anon_mmap( addr, size, unix_prot, MAP_FIXED );
+    return create_view( view, addr, size, vprot );
+}
+
+
+/***********************************************************************
  *           map_image
  *
  * Map an executable (PE format) image into memory.
@@ -1506,6 +1566,9 @@ NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG zero_
 
     if (is_beyond_limit( 0, size, working_set_limit )) return STATUS_WORKING_SET_LIMIT_RANGE;
 
+    vprot = VIRTUAL_GetProt( protect ) | VPROT_VALLOC;
+    if (type & MEM_COMMIT) vprot |= VPROT_COMMITTED;
+
     if (*ret)
     {
         if (type & MEM_RESERVE) /* Round down to 64k boundary */
@@ -1514,6 +1577,20 @@ NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG zero_
             base = ROUND_ADDR( *ret, page_mask );
         size = (((UINT_PTR)*ret + size + page_mask) & ~page_mask) - (UINT_PTR)base;
 
+        /* address 1 is magic to mean DOS area */
+        if (!base && *ret == (void *)1 && size == 0x110000)
+        {
+            server_enter_uninterrupted_section( &csVirtual, &sigset );
+            status = allocate_dos_memory( &view, vprot );
+            if (status == STATUS_SUCCESS)
+            {
+                *ret = view->base;
+                *size_ptr = view->size;
+            }
+            server_leave_uninterrupted_section( &csVirtual, &sigset );
+            return status;
+        }
+
         /* disallow low 64k, wrap-around and kernel space */
         if (((char *)base < (char *)0x10000) ||
             ((char *)base + size < (char *)base) ||
@@ -1542,8 +1619,6 @@ NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG zero_
             return STATUS_INVALID_PARAMETER;
         }
     }
-    vprot = VIRTUAL_GetProt( protect ) | VPROT_VALLOC;
-    if (type & MEM_COMMIT) vprot |= VPROT_COMMITTED;
 
     /* Reserve the memory */
 




More information about the wine-cvs mailing list