From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/unix/virtual.c | 146 +++++++++++++++++++++----------------- 1 file changed, 82 insertions(+), 64 deletions(-)
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index e733e3ffdd6..a57da1b5d09 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -5407,105 +5407,123 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T }
-static unsigned int fill_basic_memory_info( const void *addr, MEMORY_BASIC_INFORMATION *info ) +static struct file_view *get_memory_region_size( char *base, char **region_start, char **region_end, + BOOL *fake_reserved ) { - char *base, *alloc_base = 0, *alloc_end = working_set_limit; struct wine_rb_entry *ptr; struct file_view *view; - sigset_t sigset;
- base = ROUND_ADDR( addr, page_mask ); - - if (is_beyond_limit( base, 1, working_set_limit )) return STATUS_INVALID_PARAMETER; + *fake_reserved = FALSE; + *region_start = NULL; + *region_end = working_set_limit;
- /* Find the view containing the address */ - - server_enter_uninterrupted_section( &virtual_mutex, &sigset ); ptr = views_tree.root; while (ptr) { view = WINE_RB_ENTRY_VALUE( ptr, struct file_view, entry ); if ((char *)view->base > base) { - alloc_end = view->base; + *region_end = view->base; ptr = ptr->left; } else if ((char *)view->base + view->size <= base) { - alloc_base = (char *)view->base + view->size; + *region_start = (char *)view->base + view->size; ptr = ptr->right; } else { - alloc_base = view->base; - alloc_end = (char *)view->base + view->size; + *region_start = view->base; + *region_end = (char *)view->base + view->size; break; } } - - /* Fill the info structure */ - - info->BaseAddress = base; - info->RegionSize = alloc_end - base; - - if (!ptr) +#ifdef __i386__ { - info->State = MEM_FREE; - info->Protect = PAGE_NOACCESS; - info->AllocationBase = 0; - info->AllocationProtect = 0; - info->Type = 0; + struct reserved_area *area;
-#ifdef __i386__ + if (ptr) return view; /* on i386, pretend that space outside of a reserved area is allocated, * so that the app doesn't believe it's fully available */ + LIST_FOR_EACH_ENTRY( area, &reserved_areas, struct reserved_area, entry ) { - struct reserved_area *area; - BOOL in_reserved = FALSE; + char *area_start = area->base; + char *area_end = area_start + area->size;
- LIST_FOR_EACH_ENTRY( area, &reserved_areas, struct reserved_area, entry ) + if (area_end <= base) { - char *area_start = area->base; - char *area_end = area_start + area->size; + if (*region_start < area_end) *region_start = area_end; + continue; + } + if (area_start <= base || area_start <= (char *)address_space_start) + { + if (area_end < *region_end) *region_end = area_end; + return NULL; + } + /* report the remaining part of the 64K after the view as free */ + if ((UINT_PTR)*region_start & granularity_mask) + { + char *next = (char *)ROUND_ADDR( *region_start, granularity_mask ) + granularity_mask + 1;
- if (area_end <= base) - { - if (alloc_base < area_end) alloc_base = area_end; - continue; - } - if (area_start <= base || area_start <= (char *)address_space_start) + if (base < next) { - if (area_end < alloc_end) info->RegionSize = area_end - base; - in_reserved = TRUE; - break; - } - /* report the remaining part of the 64K after the view as free */ - if ((UINT_PTR)alloc_base & granularity_mask) - { - char *next = (char *)ROUND_ADDR( alloc_base, granularity_mask ) + granularity_mask + 1; - - if (base < next) - { - info->RegionSize = min( next, alloc_end ) - base; - in_reserved = TRUE; - break; - } - else alloc_base = base; + *region_end = min( next, *region_end ); + return NULL; } - /* pretend it's allocated */ - if (area_start < alloc_end) info->RegionSize = area_start - base; - break; - } - if (!in_reserved) - { - info->State = MEM_RESERVE; - info->Protect = PAGE_NOACCESS; - info->AllocationBase = alloc_base; - info->AllocationProtect = PAGE_NOACCESS; - info->Type = MEM_PRIVATE; + else *region_start = base; } + /* pretend it's allocated */ + if (area_start < *region_end) *region_end = area_start; + break; } + *fake_reserved = TRUE; + return NULL; + } +#else + return ptr ? view : NULL; #endif +} + + +static unsigned int fill_basic_memory_info( const void *addr, MEMORY_BASIC_INFORMATION *info ) +{ + char *base, *alloc_base, *alloc_end; + struct file_view *view; + BOOL fake_reserved; + sigset_t sigset; + + base = ROUND_ADDR( addr, page_mask ); + + if (is_beyond_limit( base, 1, working_set_limit )) return STATUS_INVALID_PARAMETER; + + /* Find the view containing the address */ + + server_enter_uninterrupted_section( &virtual_mutex, &sigset ); + view = get_memory_region_size( base, &alloc_base, &alloc_end, &fake_reserved ); + + /* Fill the info structure */ + + info->BaseAddress = base; + info->RegionSize = alloc_end - base; + + if (!view) + { + if (fake_reserved) + { + info->State = MEM_RESERVE; + info->Protect = PAGE_NOACCESS; + info->AllocationBase = alloc_base; + info->AllocationProtect = PAGE_NOACCESS; + info->Type = MEM_PRIVATE; + } + else + { + info->State = MEM_FREE; + info->Protect = PAGE_NOACCESS; + info->AllocationBase = 0; + info->AllocationProtect = 0; + info->Type = 0; + } } else {