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

This commit is contained in:
Alexandre Julliard 2008-04-14 20:39:27 +02:00
parent 195ca1e85f
commit f02ef19fdb
1 changed files with 47 additions and 31 deletions

View File

@ -142,9 +142,8 @@ static LONG WINAPI dosmem_handler(EXCEPTION_POINTERS* except)
{ {
if (except->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) if (except->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)
{ {
DWORD addr = except->ExceptionRecord->ExceptionInformation[1]; char *addr = (char *)except->ExceptionRecord->ExceptionInformation[1];
if (addr >= (ULONG_PTR)DOSMEM_dosmem + DOSMEM_protect && if (addr >= DOSMEM_dosmem + DOSMEM_protect && addr < DOSMEM_dosmem + DOSMEM_SIZE)
addr < (ULONG_PTR)DOSMEM_dosmem + DOSMEM_SIZE)
{ {
if (load_winedos()) return EXCEPTION_CONTINUE_EXECUTION; 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) static char* setup_dos_mem(void)
{ {
int sys_offset = 0; size_t size;
int page_size = getpagesize(); int page_size = getpagesize();
void *addr = NULL; 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 */
{
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 );
}
if (!addr) if (wine_mmap_is_in_reserved_area( low_64k, DOSMEM_SIZE - DOSMEM_64KB ) != 1)
{ {
/* now reserve from address 0 */ addr = wine_anon_mmap( low_64k, DOSMEM_SIZE - DOSMEM_64KB, PROT_READ | PROT_WRITE, 0 );
wine_anon_mmap( NULL, DOSMEM_SIZE, PROT_NONE, MAP_FIXED ); if (addr != low_64k)
/* 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 (addr != MAP_FAILED) munmap( addr, DOSMEM_SIZE - DOSMEM_64KB );
ERR("Cannot use first megabyte for DOS address space, please report\n" ); ERR("Cannot use first megabyte for DOS address space, please report\n" );
/* allocate the DOS area somewhere else */ /* allocate the DOS area somewhere else */
addr = VirtualAlloc( NULL, DOSMEM_SIZE, MEM_RESERVE, PAGE_NOACCESS ); if (!(DOSMEM_dosmem = VirtualAlloc( NULL, DOSMEM_SIZE, MEM_RESERVE, PAGE_NOACCESS )))
if (!addr)
{ {
ERR( "Cannot allocate DOS memory\n" ); ERR( "Cannot allocate DOS memory\n" );
ExitProcess(1); ExitProcess(1);
} }
return DOSMEM_dosmem;
} }
DOSMEM_dosmem = addr; }
RtlAddVectoredExceptionHandler(FALSE, dosmem_handler);
return (char*)addr + sys_offset; /* 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 */
} }
@ -208,6 +223,7 @@ BOOL DOSMEM_Init(void)
{ {
char* sysmem = setup_dos_mem(); char* sysmem = setup_dos_mem();
RtlAddVectoredExceptionHandler(FALSE, dosmem_handler);
DOSMEM_0000H = GLOBAL_CreateBlock( GMEM_FIXED, sysmem, DOSMEM_0000H = GLOBAL_CreateBlock( GMEM_FIXED, sysmem,
DOSMEM_64KB, 0, WINE_LDT_FLAGS_DATA ); DOSMEM_64KB, 0, WINE_LDT_FLAGS_DATA );
DOSMEM_BiosDataSeg = GLOBAL_CreateBlock( GMEM_FIXED, sysmem + 0x400, DOSMEM_BiosDataSeg = GLOBAL_CreateBlock( GMEM_FIXED, sysmem + 0x400,