From: Nikolay Sivov nsivov@codeweavers.com
--- dlls/ntdll/tests/file.c | 4 ---- dlls/ntdll/unix/virtual.c | 5 ++--- server/mapping.c | 28 +++++++++++++++++++++++++--- 3 files changed, 27 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 8c06babde1a..cd7deda7c5b 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -6089,7 +6089,6 @@ static void test_file_map_large_size(void)
status = NtMapViewOfSection(hmapfile, GetCurrentProcess(), &addr, 0, 0, NULL, &size, ViewUnmap, MEM_RESERVE, PAGE_READONLY); - todo_wine ok(!status, "Failed to map the section %#lx.\n", status);
ret = GetFileSize(hfile, NULL); @@ -6099,15 +6098,12 @@ static void test_file_map_large_size(void) ok(!!addr, "Failed to resize, error %ld.\n", GetLastError());
ret = GetFileSize(hfile, NULL); - todo_wine ok(ret == 0x1000, "Unexpected size %lu.\n", ret);
addr = VirtualAlloc(addr, 0x1100, MEM_COMMIT, PAGE_READONLY); - todo_wine ok(!!addr, "Failed to resize, error %ld.\n", GetLastError());
ret = GetFileSize(hfile, NULL); - todo_wine ok(ret == 0x2000, "Unexpected size %lu.\n", ret);
CloseHandle(hmapfile); diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index e733e3ffdd6..cd5dcb0465a 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -3541,7 +3541,7 @@ static unsigned int virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG_P if (*size_ptr) { size = *size_ptr; - if (size > full_size - offset.QuadPart) return STATUS_INVALID_VIEW_SIZE; + if (!(alloc_type & MEM_RESERVE) && (size > full_size - offset.QuadPart)) return STATUS_INVALID_VIEW_SIZE; } else { @@ -5003,9 +5003,8 @@ static NTSTATUS allocate_virtual_memory( void **ret, SIZE_T *size_ptr, ULONG typ else /* commit the pages */ { if (!(view = find_view( base, size ))) status = STATUS_NOT_MAPPED_VIEW; - else if (view->protect & SEC_FILE) status = STATUS_ALREADY_COMMITTED; else if (view->protect & VPROT_FREE_PLACEHOLDER) status = STATUS_CONFLICTING_ADDRESSES; - else if (!(status = set_protection( view, base, size, protect )) && (view->protect & SEC_RESERVE)) + else if (!(status = set_protection( view, base, size, protect )) && (view->protect & (SEC_FILE|SEC_RESERVE))) { SERVER_START_REQ( add_mapping_committed_range ) { diff --git a/server/mapping.c b/server/mapping.c index c3f57b6394c..bfd1e0d70be 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -1564,8 +1564,7 @@ DECL_HANDLER(map_view)
if ((mapping->flags & SEC_IMAGE) || req->start >= mapping->size || - req->start + req->size < req->start || - req->start + req->size > round_size( mapping->size, page_mask )) + req->start + req->size < req->start) { set_error( STATUS_INVALID_PARAMETER ); goto done; @@ -1712,7 +1711,30 @@ DECL_HANDLER(add_mapping_committed_range) { struct memory_view *view = find_mapped_view( current->process, req->base );
- if (view) add_committed_range( view, req->offset, req->offset + req->size ); + if (view) + { + if (view->flags & SEC_FILE) + { + struct stat st; + int unix_fd; + + if ((unix_fd = get_unix_fd( view->fd )) == -1) return; + if (fstat( unix_fd, &st ) == -1) + { + file_set_error(); + return; + } + + if ((req->offset + req->size) <= st.st_size) + set_error( STATUS_ALREADY_COMMITTED ); + else + grow_file( unix_fd, req->offset + req->size ); + } + else + { + add_committed_range( view, req->offset, req->offset + req->size ); + } + } }
/* check if two memory maps are for the same file */