mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-05 18:01:34 +00:00
ntdll: Support MEM_COALESCE_PLACEHOLDERS in NtFreeVirtualMemory().
This commit is contained in:
parent
d5f23441ad
commit
03096546c9
2 changed files with 125 additions and 3 deletions
|
@ -295,9 +295,9 @@ static void test_NtAllocateVirtualMemoryEx(void)
|
|||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
MEM_EXTENDED_PARAMETER ext[2];
|
||||
char *p, *p1, *p2, *p3;
|
||||
void *addresses[16];
|
||||
SIZE_T size, size2;
|
||||
char *p, *p1, *p2;
|
||||
ULONG granularity;
|
||||
NTSTATUS status;
|
||||
ULONG_PTR count;
|
||||
|
@ -510,6 +510,7 @@ static void test_NtAllocateVirtualMemoryEx(void)
|
|||
|
||||
p1 = addr1;
|
||||
p2 = p1 + size / 4;
|
||||
p3 = p2 + size / 4;
|
||||
size2 = size / 4;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER);
|
||||
ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
|
@ -517,12 +518,79 @@ static void test_NtAllocateVirtualMemoryEx(void)
|
|||
ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2);
|
||||
ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1);
|
||||
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER);
|
||||
ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
|
||||
check_region_size(p1, p2 - p1);
|
||||
check_region_size(p2, p3 - p2);
|
||||
check_region_size(p3, size - (p3 - p1));
|
||||
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
|
||||
ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status);
|
||||
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_COALESCE_PLACEHOLDERS);
|
||||
ok(status == STATUS_INVALID_PARAMETER_4, "Unexpected status %08lx.\n", status);
|
||||
|
||||
size2 = size + 0x1000;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
|
||||
ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status);
|
||||
|
||||
size2 = size - 0x1000;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
|
||||
ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status);
|
||||
|
||||
p1 = (char *)addr1 + 0x1000;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
|
||||
ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status);
|
||||
p1 = addr1;
|
||||
|
||||
size2 = 0;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
|
||||
ok(status == STATUS_INVALID_PARAMETER_3, "Unexpected status %08lx.\n", status);
|
||||
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE);
|
||||
ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
|
||||
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
|
||||
ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
ok(size == 0x10000, "Unexpected size %#Ix.\n", size);
|
||||
ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1);
|
||||
check_region_size(p1, size);
|
||||
|
||||
size2 = size / 4;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER);
|
||||
ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2);
|
||||
ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1);
|
||||
check_region_size(p1, size / 4);
|
||||
check_region_size(p2, size - size / 4);
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE);
|
||||
|
||||
size2 = size - size / 4;
|
||||
status = pNtAllocateVirtualMemoryEx(NtCurrentProcess(), (void **)&p2, &size2, MEM_RESERVE | MEM_REPLACE_PLACEHOLDER,
|
||||
PAGE_READWRITE, NULL, 0);
|
||||
ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
|
||||
ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status);
|
||||
|
||||
size2 = size - size / 4;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p2, &size2, MEM_RELEASE);
|
||||
ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
ok(size2 == 0xc000, "Unexpected size %#Ix.\n", size2);
|
||||
ok(p2 == p1 + size / 4, "Unexpected addr %p, expected %p.\n", p2, p1 + size / 4);
|
||||
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size, MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS);
|
||||
ok(status == STATUS_CONFLICTING_ADDRESSES, "Unexpected status %08lx.\n", status);
|
||||
|
||||
size2 = size / 4;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p1, &size2, MEM_RELEASE);
|
||||
ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status);
|
||||
ok(size2 == 0x4000, "Unexpected size %#Ix.\n", size2);
|
||||
ok(p1 == addr1, "Unexpected addr %p, expected %p.\n", p1, addr1);
|
||||
|
||||
size2 = 0;
|
||||
status = NtFreeVirtualMemory(NtCurrentProcess(), (void **)&p3, &size2, MEM_RELEASE);
|
||||
ok(status == STATUS_MEMORY_NOT_ALLOCATED, "Unexpected status %08lx.\n", status);
|
||||
|
||||
/* Split in two regions, specifying second half. */
|
||||
addr1 = NULL;
|
||||
|
|
|
@ -2294,6 +2294,53 @@ static NTSTATUS free_pages( struct file_view *view, char *base, size_t size )
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* coalesce_placeholders
|
||||
*
|
||||
* Coalesce placeholder views.
|
||||
* virtual_mutex must be held by caller.
|
||||
*/
|
||||
static NTSTATUS coalesce_placeholders( struct file_view *view, char *base, size_t size )
|
||||
{
|
||||
struct rb_entry *next;
|
||||
struct file_view *curr_view, *next_view;
|
||||
unsigned int i, view_count = 0;
|
||||
size_t views_size = 0;
|
||||
|
||||
if (!size) return STATUS_INVALID_PARAMETER_3;
|
||||
if (base != view->base) return STATUS_CONFLICTING_ADDRESSES;
|
||||
|
||||
curr_view = view;
|
||||
while (curr_view->protect & VPROT_FREE_PLACEHOLDER)
|
||||
{
|
||||
++view_count;
|
||||
views_size += curr_view->size;
|
||||
if (views_size >= size) break;
|
||||
if (!(next = rb_next( &curr_view->entry ))) break;
|
||||
next_view = RB_ENTRY_VALUE( next, struct file_view, entry );
|
||||
if ((char *)curr_view->base + curr_view->size != next_view->base) break;
|
||||
curr_view = next_view;
|
||||
}
|
||||
|
||||
if (view_count < 2 || size != views_size) return STATUS_CONFLICTING_ADDRESSES;
|
||||
|
||||
for (i = 1; i < view_count; ++i)
|
||||
{
|
||||
curr_view = RB_ENTRY_VALUE( rb_next( &view->entry ), struct file_view, entry );
|
||||
unregister_view( curr_view );
|
||||
free_view( curr_view );
|
||||
}
|
||||
|
||||
unregister_view( view );
|
||||
view->size = views_size;
|
||||
register_view( view );
|
||||
|
||||
VIRTUAL_DEBUG_DUMP_VIEW( view );
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* allocate_dos_memory
|
||||
*
|
||||
|
@ -4445,7 +4492,8 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
|
|||
else if (!(view = find_view( base, 0 ))) status = STATUS_MEMORY_NOT_ALLOCATED;
|
||||
else if (!is_view_valloc( view )) status = STATUS_INVALID_PARAMETER;
|
||||
else if (!size && base != view->base) status = STATUS_FREE_VM_NOT_AT_BASE;
|
||||
else if ((char *)view->base + view->size - base < size) status = STATUS_UNABLE_TO_FREE_VM;
|
||||
else if ((char *)view->base + view->size - base < size && !(type & MEM_COALESCE_PLACEHOLDERS))
|
||||
status = STATUS_UNABLE_TO_FREE_VM;
|
||||
else switch (type)
|
||||
{
|
||||
case MEM_DECOMMIT:
|
||||
|
@ -4458,6 +4506,12 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
|
|||
case MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER:
|
||||
status = free_pages_preserve_placeholder( view, base, size );
|
||||
break;
|
||||
case MEM_RELEASE | MEM_COALESCE_PLACEHOLDERS:
|
||||
status = coalesce_placeholders( view, base, size );
|
||||
break;
|
||||
case MEM_COALESCE_PLACEHOLDERS:
|
||||
status = STATUS_INVALID_PARAMETER_4;
|
||||
break;
|
||||
default:
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue