ntdll: Implementation of inter-process VirtualQueryEx.

This commit is contained in:
Alexandre Julliard 2007-01-15 22:28:42 +01:00
parent 7a00142bc1
commit 3d00239586
7 changed files with 112 additions and 32 deletions

View File

@ -103,22 +103,17 @@ static void test_VirtualAllocEx(void)
/* test a not committed memory */
memset(&info, 'q', sizeof(info));
todo_wine ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info))
== sizeof(info), "VirtualQueryEx failed\n");
todo_wine ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress,
addr1);
todo_wine ok(info.AllocationBase == addr1, "%p != %p\n",
info.AllocationBase, addr1);
todo_wine ok(info.AllocationProtect == PAGE_NOACCESS,
"%x != PAGE_NOACCESS\n", info.AllocationProtect);
todo_wine ok(info.RegionSize == 0x10000, "%lx != 0x10000\n",
info.RegionSize);
todo_wine ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) == sizeof(info), "VirtualQueryEx failed\n");
ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
/* NT reports Protect == 0 for a not committed memory block */
todo_wine ok(info.Protect == 0 /* NT */ ||
ok(info.Protect == 0 /* NT */ ||
info.Protect == PAGE_NOACCESS, /* Win9x */
"%x != PAGE_NOACCESS\n", info.Protect);
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);
ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
@ -131,20 +126,16 @@ static void test_VirtualAllocEx(void)
ok(addr1 == addr2, "VirtualAllocEx failed\n");
/* test a committed memory */
todo_wine ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info))
== sizeof(info),
ok(VirtualQueryEx(hProcess, addr1, &info, sizeof(info)) == sizeof(info),
"VirtualQueryEx failed\n");
todo_wine ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress,
addr1);
todo_wine ok(info.AllocationBase == addr1, "%p != %p\n",
info.AllocationBase, addr1);
todo_wine ok(info.AllocationProtect == PAGE_NOACCESS,
"%x != PAGE_NOACCESS\n", info.AllocationProtect);
todo_wine ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
todo_wine ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
ok(info.RegionSize == 0x1000, "%lx != 0x1000\n", info.RegionSize);
ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
/* this time NT reports PAGE_NOACCESS as well */
todo_wine ok(info.Protect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.Protect);
todo_wine ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
ok(info.Protect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.Protect);
ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
/* this should fail, since not the whole range is committed yet */
SetLastError(0xdeadbeef);

View File

@ -726,6 +726,26 @@ static BOOL call_apcs( BOOL alertable )
&result.virtual_free.size,
call.virtual_free.op_type );
break;
case APC_VIRTUAL_QUERY:
{
MEMORY_BASIC_INFORMATION info;
result.type = call.type;
result.virtual_query.status = NtQueryVirtualMemory( NtCurrentProcess(),
call.virtual_query.addr,
MemoryBasicInformation, &info,
sizeof(info), NULL );
if (result.virtual_query.status == STATUS_SUCCESS)
{
result.virtual_query.base = info.BaseAddress;
result.virtual_query.alloc_base = info.AllocationBase;
result.virtual_query.size = info.RegionSize;
result.virtual_query.state = info.State;
result.virtual_query.prot = info.Protect;
result.virtual_query.alloc_prot = info.AllocationProtect;
result.virtual_query.alloc_type = info.Type;
}
break;
}
default:
server_protocol_error( "get_apc_request: bad type %d\n", call.type );
break;

View File

@ -1682,10 +1682,29 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
if (ADDRESS_SPACE_LIMIT && addr >= ADDRESS_SPACE_LIMIT)
return STATUS_WORKING_SET_LIMIT_RANGE;
if (!is_current_process( process ))
if (process != NtCurrentProcess())
{
ERR("Unsupported on other process\n");
return STATUS_ACCESS_DENIED;
NTSTATUS status;
apc_call_t call;
apc_result_t result;
call.virtual_query.type = APC_VIRTUAL_QUERY;
call.virtual_query.addr = addr;
status = NTDLL_queue_process_apc( process, &call, &result );
if (status != STATUS_SUCCESS) return status;
if (result.virtual_query.status == STATUS_SUCCESS)
{
info->BaseAddress = result.virtual_query.base;
info->AllocationBase = result.virtual_query.alloc_base;
info->RegionSize = result.virtual_query.size;
info->State = result.virtual_query.state;
info->Protect = result.virtual_query.prot;
info->AllocationProtect = result.virtual_query.alloc_prot;
info->Type = result.virtual_query.alloc_type;
if (res_len) *res_len = sizeof(*info);
}
return result.virtual_query.status;
}
base = ROUND_ADDR( addr, page_mask );

View File

@ -216,7 +216,8 @@ enum apc_type
APC_TIMER,
APC_ASYNC_IO,
APC_VIRTUAL_ALLOC,
APC_VIRTUAL_FREE
APC_VIRTUAL_FREE,
APC_VIRTUAL_QUERY
};
typedef union
@ -259,6 +260,11 @@ typedef union
unsigned long size;
unsigned int op_type;
} virtual_free;
struct
{
enum apc_type type;
const void *addr;
} virtual_query;
} apc_call_t;
typedef union
@ -278,6 +284,18 @@ typedef union
void *addr;
unsigned long size;
} virtual_free;
struct
{
enum apc_type type;
unsigned int status;
void *base;
void *alloc_base;
unsigned long size;
unsigned int state;
unsigned int prot;
unsigned int alloc_prot;
unsigned int alloc_type;
} virtual_query;
} apc_result_t;
@ -4499,6 +4517,6 @@ union generic_reply
struct query_symlink_reply query_symlink_reply;
};
#define SERVER_PROTOCOL_VERSION 266
#define SERVER_PROTOCOL_VERSION 267
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -232,7 +232,8 @@ enum apc_type
APC_TIMER,
APC_ASYNC_IO,
APC_VIRTUAL_ALLOC,
APC_VIRTUAL_FREE
APC_VIRTUAL_FREE,
APC_VIRTUAL_QUERY
};
typedef union
@ -275,6 +276,11 @@ typedef union
unsigned long size; /* allocation size */
unsigned int op_type; /* type of operation */
} virtual_free;
struct
{
enum apc_type type; /* APC_VIRTUAL_QUERY */
const void *addr; /* requested address */
} virtual_query;
} apc_call_t;
typedef union
@ -294,6 +300,18 @@ typedef union
void *addr; /* resulting address */
unsigned long size; /* resulting size */
} virtual_free;
struct
{
enum apc_type type; /* APC_VIRTUAL_QUERY */
unsigned int status; /* status returned by call */
void *base; /* resulting base address */
void *alloc_base;/* resulting allocation base */
unsigned long size; /* resulting region size */
unsigned int state; /* resulting region state */
unsigned int prot; /* resulting region protection */
unsigned int alloc_prot;/* resulting allocation protection */
unsigned int alloc_type;/* resulting region allocation type */
} virtual_query;
} apc_result_t;
/****************************************************************/

View File

@ -1140,6 +1140,7 @@ DECL_HANDLER(queue_apc)
struct thread *thread;
struct process *process;
struct thread_apc *apc;
unsigned int access;
if (!(apc = create_apc( NULL, &req->call ))) return;
@ -1155,7 +1156,9 @@ DECL_HANDLER(queue_apc)
break;
case APC_VIRTUAL_ALLOC:
case APC_VIRTUAL_FREE:
if ((process = get_process_from_handle( req->process, PROCESS_VM_OPERATION )))
case APC_VIRTUAL_QUERY:
access = (apc->call.type == APC_VIRTUAL_QUERY) ? PROCESS_QUERY_INFORMATION : PROCESS_VM_OPERATION;
if ((process = get_process_from_handle( req->process, access )))
{
obj_handle_t handle = alloc_handle( current->process, apc, SYNCHRONIZE, 0 );
if (handle)

View File

@ -130,6 +130,9 @@ static void dump_apc_call( const apc_call_t *call )
call->virtual_free.addr, call->virtual_free.size,
call->virtual_free.op_type );
break;
case APC_VIRTUAL_QUERY:
fprintf( stderr, "APC_VIRTUAL_QUERY,addr=%p", call->virtual_query.addr );
break;
default:
fprintf( stderr, "type=%u", call->type );
break;
@ -154,6 +157,14 @@ static void dump_apc_result( const apc_result_t *result )
get_status_name( result->virtual_free.status ),
result->virtual_free.addr, result->virtual_free.size );
break;
case APC_VIRTUAL_QUERY:
fprintf( stderr, "APC_VIRTUAL_QUERY,status=%s,base=%p,alloc_base=%p,size=%lu,state=%x,prot=%x,alloc_prot=%x,alloc_type=%x",
get_status_name( result->virtual_query.status ),
result->virtual_query.base, result->virtual_query.alloc_base,
result->virtual_query.size, result->virtual_query.state,
result->virtual_query.prot, result->virtual_query.alloc_prot,
result->virtual_query.alloc_type );
break;
default:
fprintf( stderr, "type=%u", result->type );
break;