ntdll: Implementation of inter-process VirtualAllocEx and VirtualFreeEx.

This commit is contained in:
Alexandre Julliard 2007-01-15 22:27:40 +01:00
parent 6ca1d1b081
commit 7a00142bc1
4 changed files with 65 additions and 25 deletions

View File

@ -1311,7 +1311,6 @@ static void test_OpenProcess(void)
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
addr1 = pVirtualAllocEx(hproc, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS); addr1 = pVirtualAllocEx(hproc, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
todo_wine {
ok(!addr1, "VirtualAllocEx should fail\n"); ok(!addr1, "VirtualAllocEx should fail\n");
if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
{ /* Win9x */ { /* Win9x */
@ -1320,7 +1319,6 @@ todo_wine {
return; return;
} }
ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError()); ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
}
read_bytes = 0xdeadbeef; read_bytes = 0xdeadbeef;
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
@ -1334,11 +1332,7 @@ todo_wine {
ok(hproc != NULL, "OpenProcess error %d\n", GetLastError()); ok(hproc != NULL, "OpenProcess error %d\n", GetLastError());
addr1 = pVirtualAllocEx(hproc, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS); addr1 = pVirtualAllocEx(hproc, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
todo_wine {
ok(addr1 != NULL, "VirtualAllocEx error %d\n", GetLastError()); ok(addr1 != NULL, "VirtualAllocEx error %d\n", GetLastError());
}
if (addr1 == NULL) /* FIXME: remove once Wine is fixed */
addr1 = pVirtualAllocEx(GetCurrentProcess(), 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
/* without PROCESS_QUERY_INFORMATION */ /* without PROCESS_QUERY_INFORMATION */
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
@ -1374,18 +1368,14 @@ todo_wine {
ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type); ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
todo_wine {
ok(!pVirtualFreeEx(hproc, addr1, 0, MEM_RELEASE), ok(!pVirtualFreeEx(hproc, addr1, 0, MEM_RELEASE),
"VirtualFreeEx without PROCESS_VM_OPERATION rights should fail\n"); "VirtualFreeEx without PROCESS_VM_OPERATION rights should fail\n");
ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError()); ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
}
CloseHandle(hproc); CloseHandle(hproc);
todo_wine {
ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n"); ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
} }
}
START_TEST(process) START_TEST(process)
{ {

View File

@ -74,7 +74,7 @@ static void test_VirtualAllocEx(void)
for (i = 0; i < alloc_size; i++) for (i = 0; i < alloc_size; i++)
src[i] = 0xcafedead + i; src[i] = 0xcafedead + i;
todo_wine ok(addr1 != NULL, "VirtualAllocEx error %u\n", GetLastError()); ok(addr1 != NULL, "VirtualAllocEx error %u\n", GetLastError());
b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written); b = WriteProcessMemory(hProcess, addr1, src, alloc_size, &bytes_written);
ok(b && (bytes_written == alloc_size), "%lu bytes written\n", ok(b && (bytes_written == alloc_size), "%lu bytes written\n",
bytes_written); bytes_written);
@ -82,7 +82,7 @@ static void test_VirtualAllocEx(void)
ok(b && (bytes_read == alloc_size), "%lu bytes read\n", bytes_read); ok(b && (bytes_read == alloc_size), "%lu bytes read\n", bytes_read);
ok(!memcmp(src, dst, alloc_size), "Data from remote process differs\n"); ok(!memcmp(src, dst, alloc_size), "Data from remote process differs\n");
b = VirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE); b = VirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE);
todo_wine ok(b != 0, "VirtualFreeEx, error %u\n", GetLastError()); ok(b != 0, "VirtualFreeEx, error %u\n", GetLastError());
HeapFree( GetProcessHeap(), 0, src ); HeapFree( GetProcessHeap(), 0, src );
HeapFree( GetProcessHeap(), 0, dst ); HeapFree( GetProcessHeap(), 0, dst );
@ -99,7 +99,7 @@ static void test_VirtualAllocEx(void)
"got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError()); "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
addr1 = VirtualAllocEx(hProcess, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS); addr1 = VirtualAllocEx(hProcess, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
todo_wine ok(addr1 != NULL, "VirtualAllocEx failed\n"); ok(addr1 != NULL, "VirtualAllocEx failed\n");
/* test a not committed memory */ /* test a not committed memory */
memset(&info, 'q', sizeof(info)); memset(&info, 'q', sizeof(info));
@ -154,11 +154,13 @@ static void test_VirtualAllocEx(void)
GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */ GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */
"got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError()); "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
old_prot = 0;
todo_wine ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READONLY, todo_wine ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READONLY,
&old_prot), "VirtualProtectEx failed\n"); &old_prot), "VirtualProtectEx failed\n");
todo_wine ok(old_prot == PAGE_NOACCESS, todo_wine ok(old_prot == PAGE_NOACCESS,
"wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot); "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
old_prot = 0;
todo_wine ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READWRITE, todo_wine ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READWRITE,
&old_prot), "VirtualProtectEx failed\n"); &old_prot), "VirtualProtectEx failed\n");
todo_wine ok(old_prot == PAGE_READONLY, todo_wine ok(old_prot == PAGE_READONLY,
@ -166,20 +168,18 @@ static void test_VirtualAllocEx(void)
ok(!VirtualFreeEx(hProcess, addr1, 0x10000, 0), ok(!VirtualFreeEx(hProcess, addr1, 0x10000, 0),
"VirtualFreeEx should fail with type 0\n"); "VirtualFreeEx should fail with type 0\n");
todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, ok(GetLastError() == ERROR_INVALID_PARAMETER,
"got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError()); "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
todo_wine ok(VirtualFreeEx(hProcess, addr1, 0x10000, MEM_DECOMMIT), ok(VirtualFreeEx(hProcess, addr1, 0x10000, MEM_DECOMMIT), "VirtualFreeEx failed\n");
"VirtualFreeEx failed\n");
/* if the type is MEM_RELEASE, size must be 0 */ /* if the type is MEM_RELEASE, size must be 0 */
ok(!VirtualFreeEx(hProcess, addr1, 1, MEM_RELEASE), ok(!VirtualFreeEx(hProcess, addr1, 1, MEM_RELEASE),
"VirtualFreeEx should fail\n"); "VirtualFreeEx should fail\n");
todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, ok(GetLastError() == ERROR_INVALID_PARAMETER,
"got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError()); "got %u, expected ERROR_INVALID_PARAMETER\n", GetLastError());
todo_wine ok(VirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE), ok(VirtualFreeEx(hProcess, addr1, 0, MEM_RELEASE), "VirtualFreeEx failed\n");
"VirtualFreeEx failed\n");
TerminateProcess(hProcess, 0); TerminateProcess(hProcess, 0);
CloseHandle(hProcess); CloseHandle(hProcess);

View File

@ -706,6 +706,26 @@ static BOOL call_apcs( BOOL alertable )
NtCurrentTeb()->num_async_io--; NtCurrentTeb()->num_async_io--;
call.async_io.func( call.async_io.user, call.async_io.sb, call.async_io.status ); call.async_io.func( call.async_io.user, call.async_io.sb, call.async_io.status );
break; break;
case APC_VIRTUAL_ALLOC:
result.type = call.type;
result.virtual_alloc.addr = call.virtual_alloc.addr;
result.virtual_alloc.size = call.virtual_alloc.size;
result.virtual_alloc.status = NtAllocateVirtualMemory( NtCurrentProcess(),
&result.virtual_alloc.addr,
call.virtual_alloc.zero_bits,
&result.virtual_alloc.size,
call.virtual_alloc.op_type,
call.virtual_alloc.prot );
break;
case APC_VIRTUAL_FREE:
result.type = call.type;
result.virtual_free.addr = call.virtual_free.addr;
result.virtual_free.size = call.virtual_free.size;
result.virtual_free.status = NtFreeVirtualMemory( NtCurrentProcess(),
&result.virtual_free.addr,
&result.virtual_free.size,
call.virtual_free.op_type );
break;
default: default:
server_protocol_error( "get_apc_request: bad type %d\n", call.type ); server_protocol_error( "get_apc_request: bad type %d\n", call.type );
break; break;

View File

@ -1380,10 +1380,26 @@ NTSTATUS WINAPI NtAllocateVirtualMemory( HANDLE process, PVOID *ret, ULONG zero_
if (!size) return STATUS_INVALID_PARAMETER; if (!size) return STATUS_INVALID_PARAMETER;
if (!is_current_process( process )) if (process != NtCurrentProcess())
{ {
ERR("Unsupported on other process\n"); apc_call_t call;
return STATUS_ACCESS_DENIED; apc_result_t result;
call.virtual_alloc.type = APC_VIRTUAL_ALLOC;
call.virtual_alloc.addr = *ret;
call.virtual_alloc.size = *size_ptr;
call.virtual_alloc.zero_bits = zero_bits;
call.virtual_alloc.op_type = type;
call.virtual_alloc.prot = protect;
status = NTDLL_queue_process_apc( process, &call, &result );
if (status != STATUS_SUCCESS) return status;
if (result.virtual_alloc.status == STATUS_SUCCESS)
{
*ret = result.virtual_alloc.addr;
*size_ptr = result.virtual_alloc.size;
}
return result.virtual_alloc.status;
} }
/* Round parameters to a page boundary */ /* Round parameters to a page boundary */
@ -1485,10 +1501,24 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
TRACE("%p %p %08lx %x\n", process, addr, size, type ); TRACE("%p %p %08lx %x\n", process, addr, size, type );
if (!is_current_process( process )) if (process != NtCurrentProcess())
{ {
ERR("Unsupported on other process\n"); apc_call_t call;
return STATUS_ACCESS_DENIED; apc_result_t result;
call.virtual_free.type = APC_VIRTUAL_FREE;
call.virtual_free.addr = addr;
call.virtual_free.size = size;
call.virtual_free.op_type = type;
status = NTDLL_queue_process_apc( process, &call, &result );
if (status != STATUS_SUCCESS) return status;
if (result.virtual_free.status == STATUS_SUCCESS)
{
*addr_ptr = result.virtual_free.addr;
*size_ptr = result.virtual_free.size;
}
return result.virtual_free.status;
} }
/* Fix the parameters */ /* Fix the parameters */