Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/ntdll/unix/virtual.c | 40 ++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-)
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 984af2d4a21..41d878546bb 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -943,6 +943,24 @@ static BYTE get_page_vprot( const void *addr ) }
+/*********************************************************************** + * get_vprot_range_size + * + * Return the size of the region with equal masked vprot byte. + * Also return the protections for the first page. + * The function assumes that base and size are page aligned and + * base + size does not wrap around. */ +static SIZE_T get_vprot_range_size( char *base, SIZE_T size, BYTE mask, BYTE *vprot ) +{ + char *addr; + + *vprot = get_page_vprot( base ); + for (addr = base + page_size; addr != base + size; addr += page_size) + if ((*vprot ^ get_page_vprot( addr )) & mask) break; + + return addr - base; +} + /*********************************************************************** * set_page_vprot * @@ -2047,18 +2065,21 @@ done: */ static SIZE_T get_committed_size( struct file_view *view, void *base, BYTE *vprot ) { - SIZE_T i, start; + SIZE_T offset;
- start = ((char *)base - (char *)view->base) >> page_shift; - *vprot = get_page_vprot( base ); + base = ROUND_ADDR( base, page_mask ); + offset = (char *)base - (char *)view->base;
if (view->protect & SEC_RESERVE) { SIZE_T ret = 0; + + *vprot = get_page_vprot( base ); + SERVER_START_REQ( get_mapping_committed_range ) { req->base = wine_server_client_ptr( view->base ); - req->offset = start << page_shift; + req->offset = offset; if (!wine_server_call( req )) { ret = reply->size; @@ -2072,9 +2093,8 @@ static SIZE_T get_committed_size( struct file_view *view, void *base, BYTE *vpro SERVER_END_REQ; return ret; } - for (i = start + 1; i < view->size >> page_shift; i++) - if ((*vprot ^ get_page_vprot( (char *)view->base + (i << page_shift) )) & VPROT_COMMITTED) break; - return (i - start) << page_shift; + + return get_vprot_range_size( base, view->size - offset, VPROT_COMMITTED, vprot ); }
@@ -4196,7 +4216,6 @@ static NTSTATUS get_basic_memory_info( HANDLE process, LPCVOID addr, else { BYTE vprot; - char *ptr; SIZE_T range_size = get_committed_size( view, base, &vprot );
info->State = (vprot & VPROT_COMMITTED) ? MEM_COMMIT : MEM_RESERVE; @@ -4205,9 +4224,8 @@ static NTSTATUS get_basic_memory_info( HANDLE process, LPCVOID addr, if (view->protect & SEC_IMAGE) info->Type = MEM_IMAGE; else if (view->protect & (SEC_FILE | SEC_RESERVE | SEC_COMMIT)) info->Type = MEM_MAPPED; else info->Type = MEM_PRIVATE; - for (ptr = base; ptr < base + range_size; ptr += page_size) - if ((get_page_vprot( ptr ) ^ vprot) & ~VPROT_WRITEWATCH) break; - info->RegionSize = ptr - base; + + info->RegionSize = get_vprot_range_size( base, range_size, ~VPROT_WRITEWATCH, &vprot ); } server_leave_uninterrupted_section( &virtual_mutex, &sigset );