Commit a5ff427a authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Implement NtQueryVirtualMemory(MemoryImageInformation).

parent 884cff82
...@@ -2483,7 +2483,6 @@ static void test_query_image_information(void) ...@@ -2483,7 +2483,6 @@ static void test_query_image_information(void)
&info, sizeof(info), &len ); &info, sizeof(info), &len );
if (status == STATUS_INVALID_INFO_CLASS) if (status == STATUS_INVALID_INFO_CLASS)
{ {
todo_wine
win_skip( "MemoryImageInformation not supported\n" ); win_skip( "MemoryImageInformation not supported\n" );
NtUnmapViewOfSection( NtCurrentProcess(), ptr ); NtUnmapViewOfSection( NtCurrentProcess(), ptr );
return; return;
...@@ -2578,6 +2577,7 @@ static void test_query_image_information(void) ...@@ -2578,6 +2577,7 @@ static void test_query_image_information(void)
offset.QuadPart = 0; offset.QuadPart = 0;
status = NtMapViewOfSection( mapping, NtCurrentProcess(), &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READONLY ); status = NtMapViewOfSection( mapping, NtCurrentProcess(), &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READONLY );
ok( status == STATUS_IMAGE_NOT_AT_BASE, "Unexpected status %08lx\n", status ); ok( status == STATUS_IMAGE_NOT_AT_BASE, "Unexpected status %08lx\n", status );
todo_wine
ok( size == 0x4000, "wrong size %Ix\n", size ); ok( size == 0x4000, "wrong size %Ix\n", size );
NtClose( mapping ); NtClose( mapping );
...@@ -2589,6 +2589,7 @@ static void test_query_image_information(void) ...@@ -2589,6 +2589,7 @@ static void test_query_image_information(void)
ok( info.ImageBase == ptr, "wrong image base %p/%p\n", info.ImageBase, ptr ); ok( info.ImageBase == ptr, "wrong image base %p/%p\n", info.ImageBase, ptr );
ok( info.SizeOfImage == nt->OptionalHeader.SizeOfImage, "wrong size %Ix/%x\n", ok( info.SizeOfImage == nt->OptionalHeader.SizeOfImage, "wrong size %Ix/%x\n",
info.SizeOfImage, (UINT)nt->OptionalHeader.SizeOfImage ); info.SizeOfImage, (UINT)nt->OptionalHeader.SizeOfImage );
todo_wine
ok( info.ImagePartialMap, "wrong partial map\n" ); ok( info.ImagePartialMap, "wrong partial map\n" );
ok( !info.ImageNotExecutable, "wrong not executable\n" ); ok( !info.ImageNotExecutable, "wrong not executable\n" );
ok( info.ImageSigningLevel == 0 || info.ImageSigningLevel == 12, ok( info.ImageSigningLevel == 0 || info.ImageSigningLevel == 12,
...@@ -2606,6 +2607,7 @@ static void test_query_image_information(void) ...@@ -2606,6 +2607,7 @@ static void test_query_image_information(void)
offset.QuadPart = 0; offset.QuadPart = 0;
status = NtMapViewOfSection( mapping, NtCurrentProcess(), &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READONLY ); status = NtMapViewOfSection( mapping, NtCurrentProcess(), &ptr, 0, 0, &offset, &size, 1, 0, PAGE_READONLY );
ok( status == STATUS_IMAGE_NOT_AT_BASE, "Unexpected status %08lx\n", status ); ok( status == STATUS_IMAGE_NOT_AT_BASE, "Unexpected status %08lx\n", status );
todo_wine
ok( size == 0x5000, "wrong size %Ix\n", size ); ok( size == 0x5000, "wrong size %Ix\n", size );
NtClose( mapping ); NtClose( mapping );
...@@ -2617,6 +2619,7 @@ static void test_query_image_information(void) ...@@ -2617,6 +2619,7 @@ static void test_query_image_information(void)
ok( info.ImageBase == ptr, "wrong image base %p/%p\n", info.ImageBase, ptr ); ok( info.ImageBase == ptr, "wrong image base %p/%p\n", info.ImageBase, ptr );
ok( info.SizeOfImage == nt->OptionalHeader.SizeOfImage, "wrong size %Ix/%x\n", ok( info.SizeOfImage == nt->OptionalHeader.SizeOfImage, "wrong size %Ix/%x\n",
info.SizeOfImage, (UINT)nt->OptionalHeader.SizeOfImage ); info.SizeOfImage, (UINT)nt->OptionalHeader.SizeOfImage );
todo_wine
ok( info.ImagePartialMap, "wrong partial map\n" ); ok( info.ImagePartialMap, "wrong partial map\n" );
ok( !info.ImageNotExecutable, "wrong not executable\n" ); ok( !info.ImageNotExecutable, "wrong not executable\n" );
ok( info.ImageSigningLevel == 0 || info.ImageSigningLevel == 12, ok( info.ImageSigningLevel == 0 || info.ImageSigningLevel == 12,
......
...@@ -4967,6 +4967,40 @@ static unsigned int get_memory_section_name( HANDLE process, LPCVOID addr, ...@@ -4967,6 +4967,40 @@ static unsigned int get_memory_section_name( HANDLE process, LPCVOID addr,
return status; return status;
} }
static unsigned int get_memory_image_info( HANDLE process, LPCVOID addr, MEMORY_IMAGE_INFORMATION *info,
SIZE_T len, SIZE_T *res_len )
{
unsigned int status;
if (len < sizeof(*info)) return STATUS_INFO_LENGTH_MISMATCH;
memset( info, 0, sizeof(*info) );
SERVER_START_REQ( get_image_view_info )
{
req->process = wine_server_obj_handle( process );
req->addr = wine_server_client_ptr( addr );
status = wine_server_call( req );
if (!status && reply->base)
{
info->ImageBase = wine_server_get_ptr( reply->base );
info->SizeOfImage = reply->size;
info->ImageSigningLevel = 12;
}
}
SERVER_END_REQ;
if (status == STATUS_NOT_MAPPED_VIEW)
{
MEMORY_BASIC_INFORMATION basic_info;
status = get_basic_memory_info( process, addr, &basic_info, sizeof(basic_info), NULL );
if (status || basic_info.State == MEM_FREE) status = STATUS_INVALID_ADDRESS;
}
if (!status && res_len) *res_len = sizeof(*info);
return status;
}
/*********************************************************************** /***********************************************************************
* NtQueryVirtualMemory (NTDLL.@) * NtQueryVirtualMemory (NTDLL.@)
...@@ -4995,6 +5029,9 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr, ...@@ -4995,6 +5029,9 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
case MemoryRegionInformation: case MemoryRegionInformation:
return get_memory_region_info( process, addr, buffer, len, res_len ); return get_memory_region_info( process, addr, buffer, len, res_len );
case MemoryImageInformation:
return get_memory_image_info( process, addr, buffer, len, res_len );
case MemoryWineUnixFuncs: case MemoryWineUnixFuncs:
case MemoryWineUnixWow64Funcs: case MemoryWineUnixWow64Funcs:
if (len != sizeof(unixlib_handle_t)) return STATUS_INFO_LENGTH_MISMATCH; if (len != sizeof(unixlib_handle_t)) return STATUS_INFO_LENGTH_MISMATCH;
......
...@@ -192,6 +192,23 @@ typedef struct ...@@ -192,6 +192,23 @@ typedef struct
typedef struct typedef struct
{ {
ULONG ImageBase;
ULONG SizeOfImage;
union
{
ULONG ImageFlags;
struct
{
ULONG ImagePartialMap : 1;
ULONG ImageNotExecutable : 1;
ULONG ImageSigningLevel : 4;
ULONG Reserved : 26;
};
};
} MEMORY_IMAGE_INFORMATION32;
typedef struct
{
NTSTATUS ExitStatus; NTSTATUS ExitStatus;
ULONG PebBaseAddress; ULONG PebBaseAddress;
ULONG AffinityMask; ULONG AffinityMask;
......
...@@ -493,7 +493,7 @@ NTSTATUS WINAPI wow64_NtQueryVirtualMemory( UINT *args ) ...@@ -493,7 +493,7 @@ NTSTATUS WINAPI wow64_NtQueryVirtualMemory( UINT *args )
{ {
if (len < sizeof(MEMORY_REGION_INFORMATION32)) if (len < sizeof(MEMORY_REGION_INFORMATION32))
status = STATUS_INFO_LENGTH_MISMATCH; status = STATUS_INFO_LENGTH_MISMATCH;
if ((ULONG_PTR)addr > highest_user_address) else if ((ULONG_PTR)addr > highest_user_address)
status = STATUS_INVALID_PARAMETER; status = STATUS_INVALID_PARAMETER;
else else
{ {
...@@ -534,6 +534,27 @@ NTSTATUS WINAPI wow64_NtQueryVirtualMemory( UINT *args ) ...@@ -534,6 +534,27 @@ NTSTATUS WINAPI wow64_NtQueryVirtualMemory( UINT *args )
break; break;
} }
case MemoryImageInformation: /* MEMORY_IMAEG_INFORMATION */
{
if (len < sizeof(MEMORY_IMAGE_INFORMATION32)) return STATUS_INFO_LENGTH_MISMATCH;
if ((ULONG_PTR)addr > highest_user_address) status = STATUS_INVALID_PARAMETER;
else
{
MEMORY_IMAGE_INFORMATION info;
MEMORY_IMAGE_INFORMATION32 *info32 = ptr;
if (!(status = NtQueryVirtualMemory( handle, addr, class, &info, sizeof(info), &res_len )))
{
info32->ImageBase = PtrToUlong( info.ImageBase );
info32->SizeOfImage = info.SizeOfImage;
info32->ImageFlags = info.ImageFlags;
}
}
res_len = sizeof(MEMORY_IMAGE_INFORMATION32);
break;
}
case MemoryWineUnixWow64Funcs: case MemoryWineUnixWow64Funcs:
return STATUS_INVALID_INFO_CLASS; return STATUS_INVALID_INFO_CLASS;
......
...@@ -2027,6 +2027,21 @@ struct map_builtin_view_reply ...@@ -2027,6 +2027,21 @@ struct map_builtin_view_reply
struct get_image_view_info_request
{
struct request_header __header;
obj_handle_t process;
client_ptr_t addr;
};
struct get_image_view_info_reply
{
struct reply_header __header;
client_ptr_t base;
mem_size_t size;
};
struct unmap_view_request struct unmap_view_request
{ {
struct request_header __header; struct request_header __header;
...@@ -5629,6 +5644,7 @@ enum request ...@@ -5629,6 +5644,7 @@ enum request
REQ_map_view, REQ_map_view,
REQ_map_image_view, REQ_map_image_view,
REQ_map_builtin_view, REQ_map_builtin_view,
REQ_get_image_view_info,
REQ_unmap_view, REQ_unmap_view,
REQ_get_mapping_committed_range, REQ_get_mapping_committed_range,
REQ_add_mapping_committed_range, REQ_add_mapping_committed_range,
...@@ -5916,6 +5932,7 @@ union generic_request ...@@ -5916,6 +5932,7 @@ union generic_request
struct map_view_request map_view_request; struct map_view_request map_view_request;
struct map_image_view_request map_image_view_request; struct map_image_view_request map_image_view_request;
struct map_builtin_view_request map_builtin_view_request; struct map_builtin_view_request map_builtin_view_request;
struct get_image_view_info_request get_image_view_info_request;
struct unmap_view_request unmap_view_request; struct unmap_view_request unmap_view_request;
struct get_mapping_committed_range_request get_mapping_committed_range_request; struct get_mapping_committed_range_request get_mapping_committed_range_request;
struct add_mapping_committed_range_request add_mapping_committed_range_request; struct add_mapping_committed_range_request add_mapping_committed_range_request;
...@@ -6201,6 +6218,7 @@ union generic_reply ...@@ -6201,6 +6218,7 @@ union generic_reply
struct map_view_reply map_view_reply; struct map_view_reply map_view_reply;
struct map_image_view_reply map_image_view_reply; struct map_image_view_reply map_image_view_reply;
struct map_builtin_view_reply map_builtin_view_reply; struct map_builtin_view_reply map_builtin_view_reply;
struct get_image_view_info_reply get_image_view_info_reply;
struct unmap_view_reply unmap_view_reply; struct unmap_view_reply unmap_view_reply;
struct get_mapping_committed_range_reply get_mapping_committed_range_reply; struct get_mapping_committed_range_reply get_mapping_committed_range_reply;
struct add_mapping_committed_range_reply add_mapping_committed_range_reply; struct add_mapping_committed_range_reply add_mapping_committed_range_reply;
...@@ -6418,7 +6436,7 @@ union generic_reply ...@@ -6418,7 +6436,7 @@ union generic_reply
/* ### protocol_version begin ### */ /* ### protocol_version begin ### */
#define SERVER_PROTOCOL_VERSION 778 #define SERVER_PROTOCOL_VERSION 779
/* ### protocol_version end ### */ /* ### protocol_version end ### */
......
...@@ -1325,6 +1325,23 @@ DECL_HANDLER(unmap_view) ...@@ -1325,6 +1325,23 @@ DECL_HANDLER(unmap_view)
free_memory_view( view ); free_memory_view( view );
} }
/* get information about a mapped image view */
DECL_HANDLER(get_image_view_info)
{
struct process *process;
struct memory_view *view;
if (!(process = get_process_from_handle( req->process, PROCESS_QUERY_INFORMATION ))) return;
if ((view = find_mapped_addr( process, req->addr )) && (view->flags & SEC_IMAGE))
{
reply->base = view->base;
reply->size = view->size;
}
release_object( process );
}
/* get a range of committed pages in a file mapping */ /* get a range of committed pages in a file mapping */
DECL_HANDLER(get_mapping_committed_range) DECL_HANDLER(get_mapping_committed_range)
{ {
......
...@@ -1628,6 +1628,16 @@ enum server_fd_type ...@@ -1628,6 +1628,16 @@ enum server_fd_type
@END @END
/* Get information about a mapped image view */
@REQ(get_image_view_info)
obj_handle_t process; /* process handle */
client_ptr_t addr; /* address inside mapped view (in process address space) */
@REPLY
client_ptr_t base; /* view base address */
mem_size_t size; /* view size */
@END
/* Unmap a memory view from the current process */ /* Unmap a memory view from the current process */
@REQ(unmap_view) @REQ(unmap_view)
client_ptr_t base; /* view base address */ client_ptr_t base; /* view base address */
......
...@@ -186,6 +186,7 @@ DECL_HANDLER(get_mapping_info); ...@@ -186,6 +186,7 @@ DECL_HANDLER(get_mapping_info);
DECL_HANDLER(map_view); DECL_HANDLER(map_view);
DECL_HANDLER(map_image_view); DECL_HANDLER(map_image_view);
DECL_HANDLER(map_builtin_view); DECL_HANDLER(map_builtin_view);
DECL_HANDLER(get_image_view_info);
DECL_HANDLER(unmap_view); DECL_HANDLER(unmap_view);
DECL_HANDLER(get_mapping_committed_range); DECL_HANDLER(get_mapping_committed_range);
DECL_HANDLER(add_mapping_committed_range); DECL_HANDLER(add_mapping_committed_range);
...@@ -472,6 +473,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = ...@@ -472,6 +473,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_map_view, (req_handler)req_map_view,
(req_handler)req_map_image_view, (req_handler)req_map_image_view,
(req_handler)req_map_builtin_view, (req_handler)req_map_builtin_view,
(req_handler)req_get_image_view_info,
(req_handler)req_unmap_view, (req_handler)req_unmap_view,
(req_handler)req_get_mapping_committed_range, (req_handler)req_get_mapping_committed_range,
(req_handler)req_add_mapping_committed_range, (req_handler)req_add_mapping_committed_range,
...@@ -1145,6 +1147,12 @@ C_ASSERT( FIELD_OFFSET(struct map_image_view_request, entry) == 32 ); ...@@ -1145,6 +1147,12 @@ C_ASSERT( FIELD_OFFSET(struct map_image_view_request, entry) == 32 );
C_ASSERT( FIELD_OFFSET(struct map_image_view_request, machine) == 36 ); C_ASSERT( FIELD_OFFSET(struct map_image_view_request, machine) == 36 );
C_ASSERT( sizeof(struct map_image_view_request) == 40 ); C_ASSERT( sizeof(struct map_image_view_request) == 40 );
C_ASSERT( sizeof(struct map_builtin_view_request) == 16 ); C_ASSERT( sizeof(struct map_builtin_view_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_image_view_info_request, process) == 12 );
C_ASSERT( FIELD_OFFSET(struct get_image_view_info_request, addr) == 16 );
C_ASSERT( sizeof(struct get_image_view_info_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_image_view_info_reply, base) == 8 );
C_ASSERT( FIELD_OFFSET(struct get_image_view_info_reply, size) == 16 );
C_ASSERT( sizeof(struct get_image_view_info_reply) == 24 );
C_ASSERT( FIELD_OFFSET(struct unmap_view_request, base) == 16 ); C_ASSERT( FIELD_OFFSET(struct unmap_view_request, base) == 16 );
C_ASSERT( sizeof(struct unmap_view_request) == 24 ); C_ASSERT( sizeof(struct unmap_view_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_mapping_committed_range_request, base) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_mapping_committed_range_request, base) == 16 );
......
...@@ -2210,6 +2210,18 @@ static void dump_map_builtin_view_request( const struct map_builtin_view_request ...@@ -2210,6 +2210,18 @@ static void dump_map_builtin_view_request( const struct map_builtin_view_request
dump_varargs_unicode_str( ", name=", cur_size ); dump_varargs_unicode_str( ", name=", cur_size );
} }
static void dump_get_image_view_info_request( const struct get_image_view_info_request *req )
{
fprintf( stderr, " process=%04x", req->process );
dump_uint64( ", addr=", &req->addr );
}
static void dump_get_image_view_info_reply( const struct get_image_view_info_reply *req )
{
dump_uint64( " base=", &req->base );
dump_uint64( ", size=", &req->size );
}
static void dump_unmap_view_request( const struct unmap_view_request *req ) static void dump_unmap_view_request( const struct unmap_view_request *req )
{ {
dump_uint64( " base=", &req->base ); dump_uint64( " base=", &req->base );
...@@ -4622,6 +4634,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { ...@@ -4622,6 +4634,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_map_view_request, (dump_func)dump_map_view_request,
(dump_func)dump_map_image_view_request, (dump_func)dump_map_image_view_request,
(dump_func)dump_map_builtin_view_request, (dump_func)dump_map_builtin_view_request,
(dump_func)dump_get_image_view_info_request,
(dump_func)dump_unmap_view_request, (dump_func)dump_unmap_view_request,
(dump_func)dump_get_mapping_committed_range_request, (dump_func)dump_get_mapping_committed_range_request,
(dump_func)dump_add_mapping_committed_range_request, (dump_func)dump_add_mapping_committed_range_request,
...@@ -4905,6 +4918,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { ...@@ -4905,6 +4918,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
(dump_func)dump_get_image_view_info_reply,
NULL, NULL,
(dump_func)dump_get_mapping_committed_range_reply, (dump_func)dump_get_mapping_committed_range_reply,
NULL, NULL,
...@@ -5188,6 +5202,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { ...@@ -5188,6 +5202,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"map_view", "map_view",
"map_image_view", "map_image_view",
"map_builtin_view", "map_builtin_view",
"get_image_view_info",
"unmap_view", "unmap_view",
"get_mapping_committed_range", "get_mapping_committed_range",
"add_mapping_committed_range", "add_mapping_committed_range",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment