ntdll: Implementation of inter-process VirtualProtectEx.

This commit is contained in:
Alexandre Julliard 2007-01-15 22:30:04 +01:00
parent 3d00239586
commit 1ea968016f
7 changed files with 81 additions and 16 deletions

View File

@ -118,7 +118,7 @@ static void test_VirtualAllocEx(void)
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot), ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
"VirtualProtectEx should fail on a not committed memory\n"); "VirtualProtectEx should fail on a not committed memory\n");
todo_wine ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ || ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
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());
@ -141,21 +141,17 @@ static void test_VirtualAllocEx(void)
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot), ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
"VirtualProtectEx should fail on a not committed memory\n"); "VirtualProtectEx should fail on a not committed memory\n");
todo_wine ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ || ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
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; old_prot = 0;
todo_wine ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READONLY, ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtectEx failed\n");
&old_prot), "VirtualProtectEx failed\n"); ok(old_prot == PAGE_NOACCESS, "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
todo_wine ok(old_prot == PAGE_NOACCESS,
"wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
old_prot = 0; old_prot = 0;
todo_wine ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READWRITE, ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtectEx failed\n");
&old_prot), "VirtualProtectEx failed\n"); ok(old_prot == PAGE_READONLY, "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
todo_wine ok(old_prot == PAGE_READONLY,
"wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
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");

View File

@ -746,6 +746,16 @@ static BOOL call_apcs( BOOL alertable )
} }
break; break;
} }
case APC_VIRTUAL_PROTECT:
result.type = call.type;
result.virtual_protect.addr = call.virtual_protect.addr;
result.virtual_protect.size = call.virtual_protect.size;
result.virtual_protect.status = NtProtectVirtualMemory( NtCurrentProcess(),
&result.virtual_protect.addr,
&result.virtual_protect.size,
call.virtual_protect.prot,
&result.virtual_protect.prot );
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

@ -1597,10 +1597,25 @@ NTSTATUS WINAPI NtProtectVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T
TRACE("%p %p %08lx %08x\n", process, addr, size, new_prot ); TRACE("%p %p %08lx %08x\n", process, addr, size, new_prot );
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_protect.type = APC_VIRTUAL_PROTECT;
call.virtual_protect.addr = addr;
call.virtual_protect.size = size;
call.virtual_protect.prot = new_prot;
status = NTDLL_queue_process_apc( process, &call, &result );
if (status != STATUS_SUCCESS) return status;
if (result.virtual_protect.status == STATUS_SUCCESS)
{
*addr_ptr = result.virtual_protect.addr;
*size_ptr = result.virtual_protect.size;
if (old_prot) *old_prot = result.virtual_protect.prot;
}
return result.virtual_protect.status;
} }
/* Fix the parameters */ /* Fix the parameters */

View File

@ -217,7 +217,8 @@ enum apc_type
APC_ASYNC_IO, APC_ASYNC_IO,
APC_VIRTUAL_ALLOC, APC_VIRTUAL_ALLOC,
APC_VIRTUAL_FREE, APC_VIRTUAL_FREE,
APC_VIRTUAL_QUERY APC_VIRTUAL_QUERY,
APC_VIRTUAL_PROTECT
}; };
typedef union typedef union
@ -265,6 +266,13 @@ typedef union
enum apc_type type; enum apc_type type;
const void *addr; const void *addr;
} virtual_query; } virtual_query;
struct
{
enum apc_type type;
void *addr;
unsigned long size;
unsigned int prot;
} virtual_protect;
} apc_call_t; } apc_call_t;
typedef union typedef union
@ -296,6 +304,14 @@ typedef union
unsigned int alloc_prot; unsigned int alloc_prot;
unsigned int alloc_type; unsigned int alloc_type;
} virtual_query; } virtual_query;
struct
{
enum apc_type type;
unsigned int status;
void *addr;
unsigned long size;
unsigned int prot;
} virtual_protect;
} apc_result_t; } apc_result_t;
@ -4517,6 +4533,6 @@ union generic_reply
struct query_symlink_reply query_symlink_reply; struct query_symlink_reply query_symlink_reply;
}; };
#define SERVER_PROTOCOL_VERSION 267 #define SERVER_PROTOCOL_VERSION 268
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ #endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -233,7 +233,8 @@ enum apc_type
APC_ASYNC_IO, APC_ASYNC_IO,
APC_VIRTUAL_ALLOC, APC_VIRTUAL_ALLOC,
APC_VIRTUAL_FREE, APC_VIRTUAL_FREE,
APC_VIRTUAL_QUERY APC_VIRTUAL_QUERY,
APC_VIRTUAL_PROTECT
}; };
typedef union typedef union
@ -281,6 +282,13 @@ typedef union
enum apc_type type; /* APC_VIRTUAL_QUERY */ enum apc_type type; /* APC_VIRTUAL_QUERY */
const void *addr; /* requested address */ const void *addr; /* requested address */
} virtual_query; } virtual_query;
struct
{
enum apc_type type; /* APC_VIRTUAL_PROTECT */
void *addr; /* requested address */
unsigned long size; /* requested address */
unsigned int prot; /* new protection flags */
} virtual_protect;
} apc_call_t; } apc_call_t;
typedef union typedef union
@ -312,6 +320,14 @@ typedef union
unsigned int alloc_prot;/* resulting allocation protection */ unsigned int alloc_prot;/* resulting allocation protection */
unsigned int alloc_type;/* resulting region allocation type */ unsigned int alloc_type;/* resulting region allocation type */
} virtual_query; } virtual_query;
struct
{
enum apc_type type; /* APC_VIRTUAL_PROTECT */
unsigned int status; /* status returned by call */
void *addr; /* resulting address */
unsigned long size; /* resulting size */
unsigned int prot; /* old protection flags */
} virtual_protect;
} apc_result_t; } apc_result_t;
/****************************************************************/ /****************************************************************/

View File

@ -1157,6 +1157,7 @@ DECL_HANDLER(queue_apc)
case APC_VIRTUAL_ALLOC: case APC_VIRTUAL_ALLOC:
case APC_VIRTUAL_FREE: case APC_VIRTUAL_FREE:
case APC_VIRTUAL_QUERY: case APC_VIRTUAL_QUERY:
case APC_VIRTUAL_PROTECT:
access = (apc->call.type == APC_VIRTUAL_QUERY) ? PROCESS_QUERY_INFORMATION : PROCESS_VM_OPERATION; access = (apc->call.type == APC_VIRTUAL_QUERY) ? PROCESS_QUERY_INFORMATION : PROCESS_VM_OPERATION;
if ((process = get_process_from_handle( req->process, access ))) if ((process = get_process_from_handle( req->process, access )))
{ {

View File

@ -133,6 +133,11 @@ static void dump_apc_call( const apc_call_t *call )
case APC_VIRTUAL_QUERY: case APC_VIRTUAL_QUERY:
fprintf( stderr, "APC_VIRTUAL_QUERY,addr=%p", call->virtual_query.addr ); fprintf( stderr, "APC_VIRTUAL_QUERY,addr=%p", call->virtual_query.addr );
break; break;
case APC_VIRTUAL_PROTECT:
fprintf( stderr, "APC_VIRTUAL_PROTECT,addr=%p,size=%lu,prot=%x",
call->virtual_protect.addr, call->virtual_protect.size,
call->virtual_protect.prot );
break;
default: default:
fprintf( stderr, "type=%u", call->type ); fprintf( stderr, "type=%u", call->type );
break; break;
@ -165,6 +170,12 @@ static void dump_apc_result( const apc_result_t *result )
result->virtual_query.prot, result->virtual_query.alloc_prot, result->virtual_query.prot, result->virtual_query.alloc_prot,
result->virtual_query.alloc_type ); result->virtual_query.alloc_type );
break; break;
case APC_VIRTUAL_PROTECT:
fprintf( stderr, "APC_VIRTUAL_PROTECT,status=%s,addr=%p,size=%lu,prot=%x",
get_status_name( result->virtual_protect.status ),
result->virtual_protect.addr, result->virtual_protect.size,
result->virtual_protect.prot );
break;
default: default:
fprintf( stderr, "type=%u", result->type ); fprintf( stderr, "type=%u", result->type );
break; break;