Module: wine Branch: master Commit: f4eaa15aecdef19160a5f57fc7e21e62f5b7b69b URL: http://source.winehq.org/git/wine.git/?a=commit;h=f4eaa15aecdef19160a5f57fc7...
Author: Alexandre Julliard julliard@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 */