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