From f4eaa15aecdef19160a5f57fc7e21e62f5b7b69b Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 18 Nov 2008 20:11:49 +0100 Subject: [PATCH] kernel32: Moved allocation of the DOS memory area to ntdll. --- dlls/kernel32/dosmem.c | 86 +++++++++++------------------------------- dlls/ntdll/virtual.c | 79 +++++++++++++++++++++++++++++++++++++- 2 files changed, 100 insertions(+), 65 deletions(-) diff --git a/dlls/kernel32/dosmem.c b/dlls/kernel32/dosmem.c index f3aad4c938b..a1bff4dc68c 100644 --- a/dlls/kernel32/dosmem.c +++ b/dlls/kernel32/dosmem.c @@ -151,68 +151,6 @@ static LONG WINAPI dosmem_handler(EXCEPTION_POINTERS* except) return EXCEPTION_CONTINUE_SEARCH; } -/********************************************************************** - * setup_dos_mem - * - * Setup the first megabyte for DOS memory access - */ -static char* setup_dos_mem(void) -{ - size_t size; - int page_size = getpagesize(); - void *addr = NULL; - void * const low_64k = (void *)DOSMEM_64KB; - - /* check without the first 64K */ - - if (wine_mmap_is_in_reserved_area( low_64k, DOSMEM_SIZE - DOSMEM_64KB ) != 1) - { - 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; - } - } - - /* now try to allocate the low 64K too */ - - if (wine_mmap_is_in_reserved_area( NULL, DOSMEM_64KB ) != 1) - { - 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" ); - } - } - 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 * @@ -221,7 +159,29 @@ static char* setup_dos_mem(void) */ BOOL DOSMEM_Init(void) { - char* sysmem = setup_dos_mem(); + char *sysmem; + void *addr = (void *)1; + SIZE_T size = DOSMEM_SIZE - 1; + + if (NtAllocateVirtualMemory( GetCurrentProcess(), &addr, 0, &size, + MEM_RESERVE | MEM_COMMIT, PAGE_NOACCESS )) + { + ERR( "Cannot allocate DOS memory\n" ); + ExitProcess(1); + } + + DOSMEM_dosmem = addr; + if (!addr) + { + 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; + } RtlAddVectoredExceptionHandler(FALSE, dosmem_handler); DOSMEM_0000H = GLOBAL_CreateBlock( GMEM_FIXED, sysmem, diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 80cd32f5090..12424f0dad8 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -860,6 +860,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 * @@ -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 */