ntdll-NtQueryVirtualMemory: Update patchset and return proper Nt paths.

This commit is contained in:
Sebastian Lackner 2017-05-28 11:20:01 +02:00
parent 70d09b1977
commit 43973275f2
13 changed files with 928 additions and 303 deletions

View File

@ -1,4 +1,4 @@
From 02109af7e131fe02a3d7d467210a0ea6f64a334a Mon Sep 17 00:00:00 2001
From ed78d7dd56fe29c5a310dc228576ce683730727a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Fri, 26 May 2017 05:17:17 +0200
Subject: ntdll: Implement opening files through nt device paths.
@ -9,10 +9,10 @@ Subject: ntdll: Implement opening files through nt device paths.
2 files changed, 149 insertions(+), 10 deletions(-)
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index 5f3c2dfc31a..fc2b1f63752 100644
index 32699fe3cc4..97b42398bb0 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -2806,16 +2806,10 @@ NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_STRING *
@@ -2811,16 +2811,10 @@ NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_STRING *
/******************************************************************************
@ -32,7 +32,7 @@ index 5f3c2dfc31a..fc2b1f63752 100644
{
static const WCHAR unixW[] = {'u','n','i','x'};
static const WCHAR pipeW[] = {'p','i','p','e'};
@@ -2932,6 +2926,128 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRI
@@ -2937,6 +2931,128 @@ NTSTATUS CDECL wine_nt_to_unix_file_name( const UNICODE_STRING *nameW, ANSI_STRI
return status;
}
@ -67,7 +67,7 @@ index 5f3c2dfc31a..fc2b1f63752 100644
+{
+ static const WCHAR dosdevicesW[] = {'\\','D','o','s','D','e','v','i','c','e','s',0};
+ UNICODE_STRING dosdevW;
+ WCHAR symlinkW[MAX_PATH];
+ WCHAR symlinkW[MAX_DIR_ENTRY_LEN];
+ OBJECT_ATTRIBUTES attr;
+ NTSTATUS status;
+ char data[1024];
@ -89,7 +89,7 @@ index 5f3c2dfc31a..fc2b1f63752 100644
+
+ while (!NtQueryDirectoryObject( handle, info, sizeof(data), TRUE, FALSE, &ctx, NULL ))
+ {
+ if (read_nt_symlink( handle, &info->ObjectName, symlinkW, MAX_PATH )) continue;
+ if (read_nt_symlink( handle, &info->ObjectName, symlinkW, MAX_DIR_ENTRY_LEN )) continue;
+ if (strlenW( symlinkW ) != length || memicmpW( symlinkW, name, length )) continue;
+ if (info->ObjectName.Length != 2 * sizeof(WCHAR) || info->ObjectName.Buffer[1] != ':') continue;
+
@ -162,10 +162,10 @@ index 5f3c2dfc31a..fc2b1f63752 100644
/******************************************************************
* RtlWow64EnableFsRedirection (NTDLL.@)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c
index 53504286366..43f56a7a40f 100644
index 9de9009b10e..1751865a682 100644
--- a/dlls/ntdll/tests/file.c
+++ b/dlls/ntdll/tests/file.c
@@ -161,18 +161,22 @@ static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
@@ -159,18 +159,22 @@ static void WINAPI apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserved )
static void create_file_test(void)
{
@ -189,7 +189,7 @@ index 53504286366..43f56a7a40f 100644
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
UNICODE_STRING nameW;
@@ -352,6 +356,25 @@ static void create_file_test(void)
@@ -351,6 +355,25 @@ static void create_file_test(void)
status = pNtQueryFullAttributesFile( &attr, &info );
ok( status == STATUS_OBJECT_NAME_INVALID,
"query %s failed %x\n", wine_dbgstr_w(nameW.Buffer), status );

View File

@ -1,275 +0,0 @@
From 805c61e62ca54cb4b7240c2313bd0fc4c97a902f Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Wed, 1 Feb 2017 19:22:56 +0800
Subject: ntdll: Implement NtQueryVirtualMemory(MemorySectionName). (v2)
---
dlls/ntdll/tests/info.c | 35 ++++++++++
dlls/ntdll/virtual.c | 156 ++++++++++++++++++++++++++++++++++--------
dlls/psapi/tests/psapi_main.c | 8 +--
3 files changed, 164 insertions(+), 35 deletions(-)
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index 448bc64c28a..90eb5bea015 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -1714,6 +1714,8 @@ static void test_queryvirtualmemory(void)
MEMORY_BASIC_INFORMATION mbi;
char stackbuf[42];
HMODULE module;
+ char buffer_name[sizeof(MEMORY_SECTION_NAME) + MAX_PATH * sizeof(WCHAR)];
+ MEMORY_SECTION_NAME *msn = (MEMORY_SECTION_NAME *)buffer_name;
module = GetModuleHandleA( "ntdll.dll" );
trace("Check flags of the PE header of NTDLL.DLL at %p\n", module);
@@ -1787,6 +1789,39 @@ static void test_queryvirtualmemory(void)
"mbi.Protect is 0x%x\n", mbi.Protect);
}
else skip( "bss is outside of module\n" ); /* this can happen on Mac OS */
+
+ trace("Check section name of NTDLL.DLL with invalid size\n");
+ module = GetModuleHandleA( "ntdll.dll" );
+ memset(msn, 0, sizeof(*msn));
+ readcount = 0;
+ status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemorySectionName, msn, sizeof(*msn), &readcount);
+ ok( status == STATUS_BUFFER_OVERFLOW, "Expected STATUS_BUFFER_OVERFLOW, got %08x\n", status);
+ ok( readcount > 0, "Expected readcount to be > 0\n");
+
+ trace("Check section name of NTDLL.DLL with invalid size\n");
+ module = GetModuleHandleA( "ntdll.dll" );
+ memset(msn, 0, sizeof(*msn));
+ readcount = 0;
+ status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemorySectionName, msn, sizeof(*msn) - 1, &readcount);
+ ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
+ ok( readcount > 0, "Expected readcount to be > 0\n");
+
+ trace("Check section name of NTDLL.DLL\n");
+ module = GetModuleHandleA( "ntdll.dll" );
+ memset(msn, 0x55, sizeof(*msn));
+ memset(buffer_name, 0x77, sizeof(buffer_name));
+ readcount = 0;
+ status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemorySectionName, msn, sizeof(buffer_name), &readcount);
+ ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+ ok( readcount > 0, "Expected readcount to be > 0\n");
+ trace ("Section Name: %s\n", wine_dbgstr_w(msn->SectionFileName.Buffer));
+
+ trace("Check section name of non mapped memory\n");
+ memset(msn, 0, sizeof(*msn));
+ readcount = 0;
+ status = pNtQueryVirtualMemory(NtCurrentProcess(), &buffer_name, MemorySectionName, msn, sizeof(buffer_name), &readcount);
+ ok( status == STATUS_INVALID_ADDRESS, "Expected STATUS_INVALID_ADDRESS, got %08x\n", status);
+ ok( readcount == 0 || broken(readcount != 0) /* wow64 */, "Expected readcount to be 0\n");
}
static void test_affinity(void)
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index e826fa03c0c..fcf7733b5a1 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -2240,41 +2240,17 @@ static int get_free_mem_state_callback( void *start, size_t size, void *arg )
return 1;
}
-#define UNIMPLEMENTED_INFO_CLASS(c) \
- case c: \
- FIXME("(process=%p,addr=%p) Unimplemented information class: " #c "\n", process, addr); \
- return STATUS_INVALID_INFO_CLASS
-
-/***********************************************************************
- * NtQueryVirtualMemory (NTDLL.@)
- * ZwQueryVirtualMemory (NTDLL.@)
- */
-NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
- MEMORY_INFORMATION_CLASS info_class, PVOID buffer,
- SIZE_T len, SIZE_T *res_len )
+/* get basic information about a memory block */
+static NTSTATUS get_basic_memory_info( HANDLE process, LPCVOID addr,
+ MEMORY_BASIC_INFORMATION *info,
+ SIZE_T len, SIZE_T *res_len )
{
struct file_view *view;
char *base, *alloc_base = 0;
struct list *ptr;
SIZE_T size = 0;
- MEMORY_BASIC_INFORMATION *info = buffer;
sigset_t sigset;
- if (info_class != MemoryBasicInformation)
- {
- switch(info_class)
- {
- UNIMPLEMENTED_INFO_CLASS(MemoryWorkingSetList);
- UNIMPLEMENTED_INFO_CLASS(MemorySectionName);
- UNIMPLEMENTED_INFO_CLASS(MemoryBasicVlmInformation);
-
- default:
- FIXME("(%p,%p,info_class=%d,%p,%ld,%p) Unknown information class\n",
- process, addr, info_class, buffer, len, res_len);
- return STATUS_INVALID_INFO_CLASS;
- }
- }
-
if (process != NtCurrentProcess())
{
NTSTATUS status;
@@ -2389,6 +2365,130 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
return STATUS_SUCCESS;
}
+/* get file name for mapped section */
+static NTSTATUS get_section_name( HANDLE process, LPCVOID addr,
+ MEMORY_SECTION_NAME *info,
+ SIZE_T len, SIZE_T *res_len )
+{
+ NTSTATUS status;
+ char *base;
+ struct file_view *view;
+ sigset_t sigset;
+
+ if (!addr || !info || !res_len) return STATUS_INVALID_PARAMETER;
+
+ if (process != NtCurrentProcess())
+ {
+ FIXME("(%p,%p,%p,%ld,%p): semi-stub\n", process, addr, info, len, res_len);
+ goto query_dll_name;
+ }
+
+ status = STATUS_INVALID_ADDRESS;
+
+ base = ROUND_ADDR( addr, page_mask );
+
+ server_enter_uninterrupted_section( &csVirtual, &sigset );
+ if ((view = VIRTUAL_FindView( base, 0 )))
+ {
+ if (view->mapping)
+ {
+ ANSI_STRING unix_filename;
+ UNICODE_STRING nt_name;
+
+ status = server_get_unix_name( view->mapping, &unix_filename );
+ if (status)
+ {
+ status = STATUS_FILE_INVALID;
+ }
+ else
+ {
+ status = wine_unix_to_nt_file_name( &unix_filename, &nt_name );
+ RtlFreeAnsiString( &unix_filename );
+ if (status == STATUS_SUCCESS)
+ {
+ *res_len = sizeof(MEMORY_SECTION_NAME) + nt_name.MaximumLength;
+ if (len >= *res_len)
+ {
+ info->SectionFileName.Length = nt_name.Length;
+ info->SectionFileName.MaximumLength = nt_name.MaximumLength;
+ info->SectionFileName.Buffer = (WCHAR *)(info + 1);
+ memcpy(info->SectionFileName.Buffer, nt_name.Buffer, nt_name.MaximumLength);
+ }
+ else
+ status = (len < sizeof(MEMORY_SECTION_NAME)) ? STATUS_INFO_LENGTH_MISMATCH : STATUS_BUFFER_OVERFLOW;
+
+ RtlFreeUnicodeString( &nt_name );
+ }
+ }
+ }
+ }
+ server_leave_uninterrupted_section( &csVirtual, &sigset );
+ if (status != STATUS_INVALID_ADDRESS) return status;
+
+query_dll_name:
+ /* FIXME: this will return a DOS path. Windows returns an NT path. */
+ SERVER_START_REQ(get_dll_info)
+ {
+ req->handle = wine_server_obj_handle( process );
+ req->base_address = (ULONG_PTR)addr;
+ wine_server_set_reply( req, info + 1,
+ len > sizeof(MEMORY_SECTION_NAME) ? len - sizeof(MEMORY_SECTION_NAME) : 0 );
+ status = wine_server_call( req );
+
+ if (status != STATUS_DLL_NOT_FOUND)
+ {
+ *res_len = sizeof(MEMORY_SECTION_NAME) + reply->filename_len + sizeof(WCHAR);
+ if (status == STATUS_SUCCESS && len >= *res_len)
+ {
+ info->SectionFileName.Length = reply->filename_len;
+ info->SectionFileName.MaximumLength = reply->filename_len + sizeof(WCHAR);
+ info->SectionFileName.Buffer = (WCHAR *)(info + 1);
+ *(WCHAR *)((char *)(info + 1) + reply->filename_len) = 0;
+ }
+ else if (status == STATUS_BUFFER_TOO_SMALL)
+ status = (len < sizeof(MEMORY_SECTION_NAME)) ? STATUS_INFO_LENGTH_MISMATCH : STATUS_BUFFER_OVERFLOW;
+ }
+ else
+ status = STATUS_INVALID_ADDRESS;
+ }
+ SERVER_END_REQ;
+ return status;
+}
+
+#define UNIMPLEMENTED_INFO_CLASS(c) \
+ case c: \
+ FIXME("(process=%p,addr=%p) Unimplemented information class: " #c "\n", process, addr); \
+ return STATUS_INVALID_INFO_CLASS
+
+/***********************************************************************
+ * NtQueryVirtualMemory (NTDLL.@)
+ * ZwQueryVirtualMemory (NTDLL.@)
+ */
+NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
+ MEMORY_INFORMATION_CLASS info_class,
+ PVOID buffer, SIZE_T len, SIZE_T *res_len )
+{
+ TRACE("(%p, %p, info_class=%d, %p, %ld, %p)\n",
+ process, addr, info_class, buffer, len, res_len);
+
+ switch(info_class)
+ {
+ case MemoryBasicInformation:
+ return get_basic_memory_info( process, addr, buffer, len, res_len );
+
+ case MemorySectionName:
+ return get_section_name( process, addr, buffer, len, res_len );
+
+ UNIMPLEMENTED_INFO_CLASS(MemoryWorkingSetList);
+ UNIMPLEMENTED_INFO_CLASS(MemoryBasicVlmInformation);
+
+ default:
+ FIXME("(%p,%p,info_class=%d,%p,%ld,%p) Unknown information class\n",
+ process, addr, info_class, buffer, len, res_len);
+ return STATUS_INVALID_INFO_CLASS;
+ }
+}
+
/***********************************************************************
* NtLockVirtualMemory (NTDLL.@)
diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c
index 7bc26fe8de9..ebb4e453e61 100644
--- a/dlls/psapi/tests/psapi_main.c
+++ b/dlls/psapi/tests/psapi_main.c
@@ -332,14 +332,7 @@ static BOOL nt_get_mapped_file_name(HANDLE process, LPVOID addr, LPWSTR name, DW
ret_len = 0xdeadbeef;
status = pNtQueryVirtualMemory(process, addr, MemorySectionName, buf, buf_len, &ret_len);
-todo_wine
ok(!status, "NtQueryVirtualMemory error %x\n", status);
- /* FIXME: remove once Wine is fixed */
- if (status)
- {
- HeapFree(GetProcessHeap(), 0, buf);
- return FALSE;
- }
section_name = (MEMORY_SECTION_NAME *)buf;
ok(ret_len == section_name->SectionFileName.MaximumLength + sizeof(*section_name), "got %lu, %u\n",
@@ -461,6 +454,7 @@ todo_wine {
{
ok(memcmp(map_nameW, nt_map_name, lstrlenW(map_nameW)) == 0, "map name does not start with a device name: %s\n", map_name);
WideCharToMultiByte(CP_ACP, 0, map_nameW, -1, map_name, MAX_PATH, NULL, NULL);
+todo_wine
ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name);
}
--
2.11.0

View File

@ -0,0 +1,91 @@
From d3932f7ec92691aa77a75840883597a1c652f8c9 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 28 May 2017 09:04:10 +0200
Subject: server: Store full path for ntdll/kernel32 dll.
---
dlls/ntdll/loader.c | 8 ++++++++
server/process.c | 23 +++++++++++++++++++++++
server/protocol.def | 6 ++++++
3 files changed, 37 insertions(+)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 518a99f5900..76d399a6cc6 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -3309,6 +3309,14 @@ void CDECL __wine_init_windows_dir( const WCHAR *windir, const WCHAR *sysdir )
RtlInitUnicodeString( &mod->FullDllName, buffer );
RtlInitUnicodeString( &mod->BaseDllName, p );
}
+
+ /* do the same for the wineserver dll list */
+ SERVER_START_REQ( init_system_dir )
+ {
+ wine_server_add_data( req, system_dir.Buffer, system_dir.Length );
+ wine_server_call( req );
+ }
+ SERVER_END_REQ;
}
diff --git a/server/process.c b/server/process.c
index 5eabbbef8ef..9204c8954c7 100644
--- a/server/process.c
+++ b/server/process.c
@@ -49,6 +49,8 @@
#include "user.h"
#include "security.h"
+#include "wine/unicode.h"
+
/* process structure */
static struct list process_list = LIST_INIT(process_list);
@@ -1502,6 +1504,27 @@ DECL_HANDLER(load_dll)
if (mapping) release_object( mapping );
}
+/* prepend the system dir to the name of the already created modules */
+DECL_HANDLER(init_system_dir)
+{
+ struct process *process = current->process;
+ struct process_dll *dll;
+ WCHAR *filename, *p;
+
+ LIST_FOR_EACH_ENTRY( dll, &process->dlls, struct process_dll, entry )
+ {
+ if (memchrW( dll->filename, '\\', dll->namelen / sizeof(WCHAR) )) continue;
+ if (!(filename = mem_alloc( get_req_data_size() + dll->namelen + sizeof(WCHAR) ))) continue;
+ memcpy( filename, get_req_data(), get_req_data_size() );
+ p = filename + get_req_data_size() / sizeof(WCHAR);
+ if (p > filename && p[-1] != '\\') *p++ = '\\';
+ memcpy( p, dll->filename, dll->namelen );
+ free( dll->filename );
+ dll->namelen += (p - filename) * sizeof(WCHAR);
+ dll->filename = filename;
+ }
+}
+
/* notify the server that a dll is being unloaded */
DECL_HANDLER(unload_dll)
{
diff --git a/server/protocol.def b/server/protocol.def
index 7eaaec2b823..2f043bef50d 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -949,6 +949,12 @@ struct rawinput_device
@END
+/* Prepend the system directory to already loaded modules */
+@REQ(init_system_dir)
+ VARARG(sysdir,unicode_str); /* system directory */
+@END
+
+
/* Notify the server that a dll is being unloaded */
@REQ(unload_dll)
mod_handle_t base; /* base address */
--
2.12.2

View File

@ -0,0 +1,103 @@
From 0da9b9bdc6862bd2ebe58f64798f55dd1f83cf1b Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Sun, 28 May 2017 04:19:06 +0200
Subject: ntdll: Split logic for MemoryBasicInformation into a separate
function.
---
dlls/ntdll/virtual.c | 64 ++++++++++++++++++++++++++++++----------------------
1 file changed, 37 insertions(+), 27 deletions(-)
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index e826fa03c0c..9f9ed6bfe7e 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -2240,41 +2240,18 @@ static int get_free_mem_state_callback( void *start, size_t size, void *arg )
return 1;
}
-#define UNIMPLEMENTED_INFO_CLASS(c) \
- case c: \
- FIXME("(process=%p,addr=%p) Unimplemented information class: " #c "\n", process, addr); \
- return STATUS_INVALID_INFO_CLASS
-/***********************************************************************
- * NtQueryVirtualMemory (NTDLL.@)
- * ZwQueryVirtualMemory (NTDLL.@)
- */
-NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
- MEMORY_INFORMATION_CLASS info_class, PVOID buffer,
- SIZE_T len, SIZE_T *res_len )
+/* get basic information about a memory block */
+static NTSTATUS get_basic_memory_info( HANDLE process, LPCVOID addr,
+ MEMORY_BASIC_INFORMATION *info,
+ SIZE_T len, SIZE_T *res_len )
{
struct file_view *view;
char *base, *alloc_base = 0;
struct list *ptr;
SIZE_T size = 0;
- MEMORY_BASIC_INFORMATION *info = buffer;
sigset_t sigset;
- if (info_class != MemoryBasicInformation)
- {
- switch(info_class)
- {
- UNIMPLEMENTED_INFO_CLASS(MemoryWorkingSetList);
- UNIMPLEMENTED_INFO_CLASS(MemorySectionName);
- UNIMPLEMENTED_INFO_CLASS(MemoryBasicVlmInformation);
-
- default:
- FIXME("(%p,%p,info_class=%d,%p,%ld,%p) Unknown information class\n",
- process, addr, info_class, buffer, len, res_len);
- return STATUS_INVALID_INFO_CLASS;
- }
- }
-
if (process != NtCurrentProcess())
{
NTSTATUS status;
@@ -2390,6 +2367,39 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
}
+#define UNIMPLEMENTED_INFO_CLASS(c) \
+ case c: \
+ FIXME("(process=%p,addr=%p) Unimplemented information class: " #c "\n", process, addr); \
+ return STATUS_INVALID_INFO_CLASS
+
+/***********************************************************************
+ * NtQueryVirtualMemory (NTDLL.@)
+ * ZwQueryVirtualMemory (NTDLL.@)
+ */
+NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
+ MEMORY_INFORMATION_CLASS info_class,
+ PVOID buffer, SIZE_T len, SIZE_T *res_len )
+{
+ TRACE("(%p, %p, info_class=%d, %p, %ld, %p)\n",
+ process, addr, info_class, buffer, len, res_len);
+
+ switch(info_class)
+ {
+ case MemoryBasicInformation:
+ return get_basic_memory_info( process, addr, buffer, len, res_len );
+
+ UNIMPLEMENTED_INFO_CLASS(MemoryWorkingSetList);
+ UNIMPLEMENTED_INFO_CLASS(MemorySectionName);
+ UNIMPLEMENTED_INFO_CLASS(MemoryBasicVlmInformation);
+
+ default:
+ FIXME("(%p,%p,info_class=%d,%p,%ld,%p) Unknown information class\n",
+ process, addr, info_class, buffer, len, res_len);
+ return STATUS_INVALID_INFO_CLASS;
+ }
+}
+
+
/***********************************************************************
* NtLockVirtualMemory (NTDLL.@)
* ZwLockVirtualMemory (NTDLL.@)
--
2.12.2

View File

@ -0,0 +1,176 @@
From 60d3299d2e2924023542dcb7245ddfd2f901b319 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Sun, 28 May 2017 05:19:30 +0200
Subject: ntdll: Implement NtQueryVirtualMemory(MemorySectionName). (v3)
Contains several improvements by Sebastian Lackner <sebastian@fds-team.de>.
---
dlls/ntdll/virtual.c | 109 +++++++++++++++++++++++++++++++++++++++++-
dlls/psapi/tests/psapi_main.c | 8 +---
2 files changed, 109 insertions(+), 8 deletions(-)
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 9f9ed6bfe7e..7d419de07b8 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -2241,6 +2241,33 @@ static int get_free_mem_state_callback( void *start, size_t size, void *arg )
}
+/* get the section mapping handle */
+static NTSTATUS get_section_mapping( HANDLE process, LPCVOID addr, HANDLE *mapping )
+{
+ struct file_view *view;
+ NTSTATUS status = STATUS_INVALID_ADDRESS;
+ sigset_t sigset;
+ char *base;
+
+ if (process != NtCurrentProcess())
+ {
+ FIXME( "query section mapping from other process not implemented yet\n" );
+ return STATUS_NOT_IMPLEMENTED;
+ }
+
+ base = ROUND_ADDR( addr, page_mask );
+
+ server_enter_uninterrupted_section( &csVirtual, &sigset );
+ if ((view = VIRTUAL_FindView( base, 0 )) && view->mapping)
+ {
+ status = NtDuplicateObject( NtCurrentProcess(), view->mapping, NtCurrentProcess(),
+ mapping, 0, 0, DUP_HANDLE_SAME_ACCESS );
+ }
+ server_leave_uninterrupted_section( &csVirtual, &sigset );
+ return status;
+}
+
+
/* get basic information about a memory block */
static NTSTATUS get_basic_memory_info( HANDLE process, LPCVOID addr,
MEMORY_BASIC_INFORMATION *info,
@@ -2367,6 +2394,84 @@ static NTSTATUS get_basic_memory_info( HANDLE process, LPCVOID addr,
}
+/* get file name for mapped section */
+static NTSTATUS get_section_name( HANDLE process, LPCVOID addr,
+ MEMORY_SECTION_NAME *info,
+ SIZE_T len, SIZE_T *res_len )
+{
+ UNICODE_STRING nt_name;
+ ANSI_STRING unix_name;
+ data_size_t size = 1024;
+ WCHAR *name = NULL;
+ NTSTATUS status;
+ HANDLE mapping;
+
+ if (!addr || !info || !res_len) return STATUS_INVALID_PARAMETER;
+
+ if (!(status = get_section_mapping( process, addr, &mapping )))
+ {
+ status = server_get_unix_name( mapping, &unix_name );
+ close_handle( mapping );
+ if (!status)
+ {
+ status = wine_unix_to_nt_file_name( &unix_name, &nt_name );
+ RtlFreeAnsiString( &unix_name );
+ }
+ if (!status) goto found;
+ if (status == STATUS_OBJECT_TYPE_MISMATCH) status = STATUS_FILE_INVALID;
+ return status;
+ }
+
+ for (;;)
+ {
+ if (!(name = RtlAllocateHeap( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR) )))
+ return STATUS_NO_MEMORY;
+
+ SERVER_START_REQ( get_dll_info )
+ {
+ req->handle = wine_server_obj_handle( process );
+ req->base_address = (ULONG_PTR)addr;
+ wine_server_set_reply( req, name, size * sizeof(WCHAR) );
+ status = wine_server_call( req );
+ size = reply->filename_len / sizeof(WCHAR);
+ }
+ SERVER_END_REQ;
+
+ if (!status)
+ {
+ name[size] = 0;
+ break;
+ }
+ RtlFreeHeap( GetProcessHeap(), 0, name );
+ if (status == STATUS_DLL_NOT_FOUND) return STATUS_INVALID_ADDRESS;
+ if (status != STATUS_BUFFER_TOO_SMALL) return status;
+ }
+
+ if (!RtlDosPathNameToNtPathName_U( name, &nt_name, NULL, NULL ))
+ {
+ RtlFreeHeap( GetProcessHeap(), 0, name );
+ return STATUS_INVALID_PARAMETER;
+ }
+
+found:
+ *res_len = sizeof(MEMORY_SECTION_NAME) + nt_name.Length + sizeof(WCHAR);
+ if (len >= *res_len)
+ {
+ info->SectionFileName.Length = nt_name.Length;
+ info->SectionFileName.MaximumLength = nt_name.Length + sizeof(WCHAR);
+ info->SectionFileName.Buffer = (WCHAR *)(info + 1);
+ memcpy(info->SectionFileName.Buffer, nt_name.Buffer, nt_name.Length);
+ info->SectionFileName.Buffer[ nt_name.Length / sizeof(WCHAR) ] = 0;
+ }
+ else
+ status = (len < sizeof(MEMORY_SECTION_NAME)) ? STATUS_INFO_LENGTH_MISMATCH : STATUS_BUFFER_OVERFLOW;
+
+ RtlFreeHeap( GetProcessHeap(), 0, name );
+ RtlFreeUnicodeString( &nt_name );
+ return status;
+}
+
+
#define UNIMPLEMENTED_INFO_CLASS(c) \
case c: \
FIXME("(process=%p,addr=%p) Unimplemented information class: " #c "\n", process, addr); \
@@ -2388,8 +2493,10 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr,
case MemoryBasicInformation:
return get_basic_memory_info( process, addr, buffer, len, res_len );
+ case MemorySectionName:
+ return get_section_name( process, addr, buffer, len, res_len );
+
UNIMPLEMENTED_INFO_CLASS(MemoryWorkingSetList);
- UNIMPLEMENTED_INFO_CLASS(MemorySectionName);
UNIMPLEMENTED_INFO_CLASS(MemoryBasicVlmInformation);
default:
diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c
index e35a7b694cb..56bf11a9a85 100644
--- a/dlls/psapi/tests/psapi_main.c
+++ b/dlls/psapi/tests/psapi_main.c
@@ -330,14 +330,7 @@ static BOOL nt_get_mapped_file_name(HANDLE process, LPVOID addr, LPWSTR name, DW
ret_len = 0xdeadbeef;
status = pNtQueryVirtualMemory(process, addr, MemorySectionName, buf, buf_len, &ret_len);
-todo_wine
ok(!status, "NtQueryVirtualMemory error %x\n", status);
- /* FIXME: remove once Wine is fixed */
- if (status)
- {
- HeapFree(GetProcessHeap(), 0, buf);
- return FALSE;
- }
section_name = (MEMORY_SECTION_NAME *)buf;
ok(ret_len == section_name->SectionFileName.MaximumLength + sizeof(*section_name), "got %lu, %u\n",
@@ -459,6 +452,7 @@ todo_wine {
{
ok(memcmp(map_nameW, nt_map_name, lstrlenW(map_nameW)) == 0, "map name does not start with a device name: %s\n", map_name);
WideCharToMultiByte(CP_ACP, 0, map_nameW, -1, map_name, MAX_PATH, NULL, NULL);
+todo_wine
ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name);
}
--
2.12.2

View File

@ -0,0 +1,65 @@
From f16058fd2551d42166df18a9d2dd784f57b35144 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Sun, 28 May 2017 10:30:43 +0200
Subject: ntdll/tests: Add tests for NtQueryVirtualMemory(MemorySectionName).
---
dlls/ntdll/tests/info.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index f1de20698a5..1b54bd41320 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -1751,6 +1751,8 @@ static void test_queryvirtualmemory(void)
MEMORY_BASIC_INFORMATION mbi;
char stackbuf[42];
HMODULE module;
+ char buffer_name[sizeof(MEMORY_SECTION_NAME) + MAX_PATH * sizeof(WCHAR)];
+ MEMORY_SECTION_NAME *msn = (MEMORY_SECTION_NAME *)buffer_name;
module = GetModuleHandleA( "ntdll.dll" );
trace("Check flags of the PE header of NTDLL.DLL at %p\n", module);
@@ -1824,6 +1826,39 @@ static void test_queryvirtualmemory(void)
"mbi.Protect is 0x%x\n", mbi.Protect);
}
else skip( "bss is outside of module\n" ); /* this can happen on Mac OS */
+
+ trace("Check section name of NTDLL.DLL with invalid size\n");
+ module = GetModuleHandleA( "ntdll.dll" );
+ memset(msn, 0, sizeof(*msn));
+ readcount = 0;
+ status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemorySectionName, msn, sizeof(*msn), &readcount);
+ ok( status == STATUS_BUFFER_OVERFLOW, "Expected STATUS_BUFFER_OVERFLOW, got %08x\n", status);
+ ok( readcount > 0, "Expected readcount to be > 0\n");
+
+ trace("Check section name of NTDLL.DLL with invalid size\n");
+ module = GetModuleHandleA( "ntdll.dll" );
+ memset(msn, 0, sizeof(*msn));
+ readcount = 0;
+ status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemorySectionName, msn, sizeof(*msn) - 1, &readcount);
+ ok( status == STATUS_INFO_LENGTH_MISMATCH, "Expected STATUS_INFO_LENGTH_MISMATCH, got %08x\n", status);
+ ok( readcount > 0, "Expected readcount to be > 0\n");
+
+ trace("Check section name of NTDLL.DLL\n");
+ module = GetModuleHandleA( "ntdll.dll" );
+ memset(msn, 0x55, sizeof(*msn));
+ memset(buffer_name, 0x77, sizeof(buffer_name));
+ readcount = 0;
+ status = pNtQueryVirtualMemory(NtCurrentProcess(), module, MemorySectionName, msn, sizeof(buffer_name), &readcount);
+ ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
+ ok( readcount > 0, "Expected readcount to be > 0\n");
+ trace ("Section Name: %s\n", wine_dbgstr_w(msn->SectionFileName.Buffer));
+
+ trace("Check section name of non mapped memory\n");
+ memset(msn, 0, sizeof(*msn));
+ readcount = 0;
+ status = pNtQueryVirtualMemory(NtCurrentProcess(), &buffer_name, MemorySectionName, msn, sizeof(buffer_name), &readcount);
+ ok( status == STATUS_INVALID_ADDRESS, "Expected STATUS_INVALID_ADDRESS, got %08x\n", status);
+ ok( readcount == 0 || broken(readcount != 0) /* wow64 */, "Expected readcount to be 0\n");
}
static void test_affinity(void)
--
2.12.2

View File

@ -0,0 +1,60 @@
From ace7d4f4d6f6de1e2ba60c43d8e79d2b54d03523 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 28 May 2017 10:33:40 +0200
Subject: ntdll/tests: Add test to ensure section name is full path.
---
dlls/ntdll/tests/info.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/dlls/ntdll/tests/info.c b/dlls/ntdll/tests/info.c
index 1b54bd41320..4bd4b755de5 100644
--- a/dlls/ntdll/tests/info.c
+++ b/dlls/ntdll/tests/info.c
@@ -22,6 +22,7 @@
#include <winnls.h>
#include <stdio.h>
+static NTSTATUS (WINAPI * pRtlDowncaseUnicodeString)(UNICODE_STRING *, const UNICODE_STRING *, BOOLEAN);
static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
static NTSTATUS (WINAPI * pNtQuerySystemInformationEx)(SYSTEM_INFORMATION_CLASS, void*, ULONG, void*, ULONG, ULONG*);
static NTSTATUS (WINAPI * pNtPowerInformation)(POWER_INFORMATION_LEVEL, PVOID, ULONG, PVOID, ULONG);
@@ -66,6 +67,7 @@ static BOOL InitFunctionPtrs(void)
return FALSE;
}
+ NTDLL_GET_PROC(RtlDowncaseUnicodeString);
NTDLL_GET_PROC(NtQuerySystemInformation);
NTDLL_GET_PROC(NtPowerInformation);
NTDLL_GET_PROC(NtQueryInformationProcess);
@@ -1745,6 +1747,7 @@ static void test_queryvirtualmemory(void)
{
NTSTATUS status;
SIZE_T readcount;
+ static const WCHAR windowsW[] = {'w','i','n','d','o','w','s'};
static const char teststring[] = "test string";
static char datatestbuf[42] = "abc";
static char rwtestbuf[42];
@@ -1753,6 +1756,8 @@ static void test_queryvirtualmemory(void)
HMODULE module;
char buffer_name[sizeof(MEMORY_SECTION_NAME) + MAX_PATH * sizeof(WCHAR)];
MEMORY_SECTION_NAME *msn = (MEMORY_SECTION_NAME *)buffer_name;
+ BOOL found;
+ int i;
module = GetModuleHandleA( "ntdll.dll" );
trace("Check flags of the PE header of NTDLL.DLL at %p\n", module);
@@ -1852,6 +1857,10 @@ static void test_queryvirtualmemory(void)
ok( status == STATUS_SUCCESS, "Expected STATUS_SUCCESS, got %08x\n", status);
ok( readcount > 0, "Expected readcount to be > 0\n");
trace ("Section Name: %s\n", wine_dbgstr_w(msn->SectionFileName.Buffer));
+ pRtlDowncaseUnicodeString( &msn->SectionFileName, &msn->SectionFileName, FALSE );
+ for (found = FALSE, i = (msn->SectionFileName.Length - sizeof(windowsW)) / sizeof(WCHAR); i >= 0; i--)
+ found |= !memcmp( &msn->SectionFileName.Buffer[i], windowsW, sizeof(windowsW) );
+ ok( found, "Section name does not contain \"Windows\"\n");
trace("Check section name of non mapped memory\n");
memset(msn, 0, sizeof(*msn));
--
2.12.2

View File

@ -0,0 +1,204 @@
From d98c5a09b04c6082a085e313284379e70bb108b5 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 28 May 2017 05:44:38 +0200
Subject: ntdll: Allow to query section names from other processes.
---
dlls/ntdll/ntdll_misc.h | 1 +
dlls/ntdll/server.c | 12 ++++++++++++
dlls/ntdll/virtual.c | 18 ++++++++++++++----
dlls/psapi/tests/psapi_main.c | 19 +++++++++++++++++++
server/protocol.def | 13 +++++++++++++
server/thread.c | 9 +++++++++
6 files changed, 68 insertions(+), 4 deletions(-)
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 5e4c39e8bd6..0e7749af4c3 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -161,6 +161,7 @@ extern NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_S
UINT disposition ) DECLSPEC_HIDDEN;
/* virtual memory */
+extern NTSTATUS virtual_get_section_mapping( HANDLE process, LPCVOID addr, HANDLE *mapping ) DECLSPEC_HIDDEN;
extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_create_builtin_view( void *base ) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_alloc_thread_stack( TEB *teb, SIZE_T reserve_size, SIZE_T commit_size ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/server.c b/dlls/ntdll/server.c
index c02a12ab19a..fa2802beb6b 100644
--- a/dlls/ntdll/server.c
+++ b/dlls/ntdll/server.c
@@ -464,6 +464,18 @@ static BOOL invoke_apc( const apc_call_t *call, apc_result_t *result )
}
break;
}
+ case APC_VIRTUAL_SECTION:
+ {
+ HANDLE mapping;
+ addr = wine_server_get_ptr( call->virtual_section.addr );
+ if ((ULONG_PTR)addr == call->virtual_section.addr)
+ {
+ result->virtual_section.status = virtual_get_section_mapping( NtCurrentProcess(), addr, &mapping );
+ result->virtual_section.mapping = wine_server_obj_handle( mapping );
+ }
+ else result->virtual_section.status = STATUS_WORKING_SET_LIMIT_RANGE;
+ break;
+ }
case APC_VIRTUAL_PROTECT:
result->type = call->type;
addr = wine_server_get_ptr( call->virtual_protect.addr );
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 60f5f2946ba..80700437a45 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -2242,7 +2242,7 @@ static int get_free_mem_state_callback( void *start, size_t size, void *arg )
/* get the section mapping handle */
-static NTSTATUS get_section_mapping( HANDLE process, LPCVOID addr, HANDLE *mapping )
+NTSTATUS virtual_get_section_mapping( HANDLE process, LPCVOID addr, HANDLE *mapping )
{
struct file_view *view;
NTSTATUS status = STATUS_INVALID_ADDRESS;
@@ -2251,8 +2251,18 @@ static NTSTATUS get_section_mapping( HANDLE process, LPCVOID addr, HANDLE *mappi
if (process != NtCurrentProcess())
{
- FIXME( "query section mapping from other process not implemented yet\n" );
- return STATUS_NOT_IMPLEMENTED;
+ apc_call_t call;
+ apc_result_t result;
+
+ memset( &call, 0, sizeof(call) );
+
+ call.virtual_section.type = APC_VIRTUAL_SECTION;
+ call.virtual_section.addr = wine_server_client_ptr( addr );
+ status = server_queue_process_apc( process, &call, &result );
+ if (status != STATUS_SUCCESS) return status;
+
+ *mapping = wine_server_ptr_handle( result.virtual_section.mapping );
+ return result.virtual_section.status;
}
base = ROUND_ADDR( addr, page_mask );
@@ -2408,7 +2418,7 @@ static NTSTATUS get_section_name( HANDLE process, LPCVOID addr,
if (!addr || !info || !res_len) return STATUS_INVALID_PARAMETER;
- if (!(status = get_section_mapping( process, addr, &mapping )))
+ if (!(status = virtual_get_section_mapping( process, addr, &mapping )))
{
status = server_get_unix_name( mapping, &unix_name );
close_handle( mapping );
diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c
index 56bf11a9a85..23025eedab3 100644
--- a/dlls/psapi/tests/psapi_main.c
+++ b/dlls/psapi/tests/psapi_main.c
@@ -356,6 +356,10 @@ static void test_GetMappedFileName(void)
char temp_path[MAX_PATH], file_name[MAX_PATH], map_name[MAX_PATH], device_name[MAX_PATH], drive[3];
WCHAR map_nameW[MAX_PATH], nt_map_name[MAX_PATH];
HANDLE hfile, hmap;
+ HANDLE current_process;
+
+ DuplicateHandle( GetCurrentProcess(), GetCurrentProcess(),
+ GetCurrentProcess(), &current_process, 0, 0, DUPLICATE_SAME_ACCESS );
SetLastError(0xdeadbeef);
ret = pGetMappedFileNameA(NULL, hMod, szMapPath, sizeof(szMapPath));
@@ -457,6 +461,20 @@ todo_wine
}
SetLastError(0xdeadbeef);
+ ret = pGetMappedFileNameW(current_process, base, map_nameW, sizeof(map_nameW)/sizeof(map_nameW[0]));
+todo_wine {
+ ok(ret, "GetMappedFileNameW error %d\n", GetLastError());
+ ok(ret > strlen(device_name), "map_name should be longer than device_name\n");
+}
+ if (nt_get_mapped_file_name(current_process, base, nt_map_name, sizeof(nt_map_name)/sizeof(nt_map_name[0])))
+ {
+ ok(memcmp(map_nameW, nt_map_name, lstrlenW(map_nameW)) == 0, "map name does not start with a device name: %s\n", map_name);
+ WideCharToMultiByte(CP_ACP, 0, map_nameW, -1, map_name, MAX_PATH, NULL, NULL);
+todo_wine
+ ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name);
+ }
+
+ SetLastError(0xdeadbeef);
ret = pGetMappedFileNameA(GetCurrentProcess(), base + 0x2000, map_name, sizeof(map_name));
todo_wine {
ok(ret, "GetMappedFileName error %d\n", GetLastError());
@@ -501,6 +519,7 @@ todo_wine
todo_wine
ok(GetLastError() == ERROR_FILE_INVALID, "expected ERROR_FILE_INVALID, got %d\n", GetLastError());
+ CloseHandle(current_process);
UnmapViewOfFile(base);
CloseHandle(hmap);
}
diff --git a/server/protocol.def b/server/protocol.def
index 2f043bef50d..7f509dce29c 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -448,6 +448,7 @@ enum apc_type
APC_VIRTUAL_ALLOC,
APC_VIRTUAL_FREE,
APC_VIRTUAL_QUERY,
+ APC_VIRTUAL_SECTION,
APC_VIRTUAL_PROTECT,
APC_VIRTUAL_FLUSH,
APC_VIRTUAL_LOCK,
@@ -506,6 +507,12 @@ typedef union
} virtual_query;
struct
{
+ enum apc_type type; /* APC_VIRTUAL_SECTION */
+ int __pad;
+ client_ptr_t addr; /* requested address */
+ } virtual_section;
+ struct
+ {
enum apc_type type; /* APC_VIRTUAL_PROTECT */
unsigned int prot; /* new protection flags */
client_ptr_t addr; /* requested address */
@@ -597,6 +604,12 @@ typedef union
} virtual_query;
struct
{
+ enum apc_type type; /* APC_VIRTUAL_SECTION */
+ unsigned int status; /* status returned by call */
+ obj_handle_t mapping; /* resulting mapping */
+ } virtual_section;
+ struct
+ {
enum apc_type type; /* APC_VIRTUAL_PROTECT */
unsigned int status; /* status returned by call */
client_ptr_t addr; /* resulting address */
diff --git a/server/thread.c b/server/thread.c
index 10a5bf14b62..dc3323fe4dc 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -1481,6 +1481,14 @@ DECL_HANDLER(select)
apc->result.create_thread.handle = handle;
clear_error(); /* ignore errors from the above calls */
}
+ else if (apc->result.type == APC_VIRTUAL_SECTION) /* duplicate the handle to the caller process */
+ {
+ obj_handle_t mapping = duplicate_handle( current->process, apc->result.virtual_section.mapping,
+ apc->caller->process, 0, 0, DUP_HANDLE_SAME_ACCESS );
+ close_handle( current->process, apc->result.virtual_section.mapping );
+ apc->result.virtual_section.mapping = mapping;
+ clear_error(); /* ignore errors from the above calls */
+ }
else if (apc->result.type == APC_ASYNC_IO)
{
if (apc->owner)
@@ -1541,6 +1549,7 @@ DECL_HANDLER(queue_apc)
process = get_process_from_handle( req->handle, PROCESS_VM_OPERATION );
break;
case APC_VIRTUAL_QUERY:
+ case APC_VIRTUAL_SECTION:
process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION );
break;
case APC_MAP_VIEW:
--
2.12.2

View File

@ -1,12 +1,12 @@
From 2cd035059cfc7c77ca63c3e46fc85dde1a2a7ccc Mon Sep 17 00:00:00 2001
From d0f1010e925785febb306d0fd22b70165585b0a2 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Wed, 16 Mar 2016 20:23:28 +0800
Subject: kernel32: Implement K32GetMappedFileName. (v2)
---
dlls/kernel32/virtual.c | 67 +++++++++++++++++++++++++++++++++++--------
dlls/psapi/tests/psapi_main.c | 21 +++-----------
2 files changed, 59 insertions(+), 29 deletions(-)
dlls/psapi/tests/psapi_main.c | 25 ++++------------
2 files changed, 60 insertions(+), 32 deletions(-)
diff --git a/dlls/kernel32/virtual.c b/dlls/kernel32/virtual.c
index 5733a42bbf5..efdddfafc97 100644
@ -98,10 +98,10 @@ index 5733a42bbf5..efdddfafc97 100644
/***********************************************************************
diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c
index ebb4e453e61..375bffb9c4a 100644
index 23025eedab3..0751bb24fb8 100644
--- a/dlls/psapi/tests/psapi_main.c
+++ b/dlls/psapi/tests/psapi_main.c
@@ -362,18 +362,15 @@ static void test_GetMappedFileName(void)
@@ -364,27 +364,22 @@ static void test_GetMappedFileName(void)
SetLastError(0xdeadbeef);
ret = pGetMappedFileNameA(NULL, hMod, szMapPath, sizeof(szMapPath));
ok(!ret, "GetMappedFileName should fail\n");
@ -120,15 +120,16 @@ index ebb4e453e61..375bffb9c4a 100644
ok( ret || broken(GetLastError() == ERROR_UNEXP_NET_ERR), /* win2k */
"GetMappedFileNameA failed with error %u\n", GetLastError() );
if (ret)
@@ -382,7 +379,6 @@ todo_wine
todo_wine
{
ok(ret == strlen(szMapPath), "szMapPath=\"%s\" ret=%d\n", szMapPath, ret);
- todo_wine
ok(szMapPath[0] == '\\', "szMapPath=\"%s\"\n", szMapPath);
szMapBaseName = strrchr(szMapPath, '\\'); /* That's close enough for us */
- todo_wine
ok(szMapBaseName && *szMapBaseName, "szMapPath=\"%s\"\n", szMapPath);
if (szMapBaseName)
{
@@ -420,36 +416,31 @@ todo_wine
@@ -422,36 +417,31 @@ todo_wine
SetLastError(0xdeadbeef);
ret = pGetMappedFileNameA(GetCurrentProcess(), base, map_name, 0);
ok(!ret, "GetMappedFileName should fail\n");
@ -167,7 +168,19 @@ index ebb4e453e61..375bffb9c4a 100644
if (nt_get_mapped_file_name(GetCurrentProcess(), base, nt_map_name, sizeof(nt_map_name)/sizeof(nt_map_name[0])))
{
ok(memcmp(map_nameW, nt_map_name, lstrlenW(map_nameW)) == 0, "map name does not start with a device name: %s\n", map_name);
@@ -460,16 +451,14 @@ todo_wine
@@ -462,10 +452,9 @@ todo_wine
SetLastError(0xdeadbeef);
ret = pGetMappedFileNameW(current_process, base, map_nameW, sizeof(map_nameW)/sizeof(map_nameW[0]));
-todo_wine {
ok(ret, "GetMappedFileNameW error %d\n", GetLastError());
ok(ret > strlen(device_name), "map_name should be longer than device_name\n");
-}
+
if (nt_get_mapped_file_name(current_process, base, nt_map_name, sizeof(nt_map_name)/sizeof(nt_map_name[0])))
{
ok(memcmp(map_nameW, nt_map_name, lstrlenW(map_nameW)) == 0, "map name does not start with a device name: %s\n", map_name);
@@ -476,16 +465,14 @@ todo_wine
SetLastError(0xdeadbeef);
ret = pGetMappedFileNameA(GetCurrentProcess(), base + 0x2000, map_name, sizeof(map_name));
@ -185,7 +198,7 @@ index ebb4e453e61..375bffb9c4a 100644
ok(GetLastError() == ERROR_UNEXP_NET_ERR, "expected ERROR_UNEXP_NET_ERR, got %d\n", GetLastError());
SetLastError(0xdeadbeef);
@@ -481,7 +470,6 @@ todo_wine
@@ -497,7 +484,6 @@ todo_wine
SetLastError(0xdeadbeef);
ret = pGetMappedFileNameA(0, base, map_name, sizeof(map_name));
ok(!ret, "GetMappedFileName should fail\n");
@ -193,15 +206,15 @@ index ebb4e453e61..375bffb9c4a 100644
ok(GetLastError() == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", GetLastError());
UnmapViewOfFile(base);
@@ -500,7 +488,6 @@ todo_wine
@@ -516,7 +502,6 @@ todo_wine
SetLastError(0xdeadbeef);
ret = pGetMappedFileNameA(GetCurrentProcess(), base, map_name, sizeof(map_name));
ok(!ret, "GetMappedFileName should fail\n");
-todo_wine
ok(GetLastError() == ERROR_FILE_INVALID, "expected ERROR_FILE_INVALID, got %d\n", GetLastError());
UnmapViewOfFile(base);
@@ -549,7 +536,7 @@ static void test_GetProcessImageFileName(void)
CloseHandle(current_process);
@@ -566,7 +551,7 @@ static void test_GetProcessImageFileName(void)
if(ret && ret1)
{
/* Windows returns 2*strlen-1 */
@ -211,5 +224,5 @@ index ebb4e453e61..375bffb9c4a 100644
}
--
2.11.0
2.12.2

View File

@ -0,0 +1,163 @@
From 2ea8d5c16d9ab714f8cecde6cd6b2ff51738535a Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Sun, 28 May 2017 11:17:26 +0200
Subject: ntdll: Resolve drive symlinks before returning section name.
---
dlls/ntdll/directory.c | 2 +-
dlls/ntdll/ntdll_misc.h | 1 +
dlls/ntdll/virtual.c | 38 ++++++++++++++++++++++++++++++++------
dlls/psapi/tests/psapi_main.c | 6 +-----
4 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/dlls/ntdll/directory.c b/dlls/ntdll/directory.c
index 97b42398bb0..c0b2a1ea83e 100644
--- a/dlls/ntdll/directory.c
+++ b/dlls/ntdll/directory.c
@@ -2932,7 +2932,7 @@ static NTSTATUS nt_to_unix_file_name_internal( const UNICODE_STRING *nameW, ANSI
}
/* read the contents of an NT symlink object */
-static NTSTATUS read_nt_symlink( HANDLE root, UNICODE_STRING *name, WCHAR *target, size_t length )
+NTSTATUS read_nt_symlink( HANDLE root, UNICODE_STRING *name, WCHAR *target, size_t length )
{
OBJECT_ATTRIBUTES attr;
UNICODE_STRING targetW;
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 0e7749af4c3..e56a781fc29 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -161,6 +161,7 @@ extern NTSTATUS nt_to_unix_file_name_attr( const OBJECT_ATTRIBUTES *attr, ANSI_S
UINT disposition ) DECLSPEC_HIDDEN;
/* virtual memory */
+extern NTSTATUS read_nt_symlink( HANDLE root, UNICODE_STRING *name, WCHAR *target, size_t length ) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_get_section_mapping( HANDLE process, LPCVOID addr, HANDLE *mapping ) DECLSPEC_HIDDEN;
extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_create_builtin_view( void *base ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 80700437a45..1f3be783fb3 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -53,6 +53,7 @@
#include "wine/library.h"
#include "wine/server.h"
#include "wine/exception.h"
+#include "wine/unicode.h"
#include "wine/list.h"
#include "wine/debug.h"
#include "ntdll_misc.h"
@@ -146,6 +147,8 @@ static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
#define VIRTUAL_HEAP_SIZE (sizeof(void*)*1024*1024)
+#define MAX_DIR_ENTRY_LEN 255 /* max length of a directory entry in chars */
+
static HANDLE virtual_heap;
static void *preload_reserve_start;
static void *preload_reserve_end;
@@ -2409,12 +2412,15 @@ static NTSTATUS get_section_name( HANDLE process, LPCVOID addr,
MEMORY_SECTION_NAME *info,
SIZE_T len, SIZE_T *res_len )
{
+ static const WCHAR dosprefixW[] = {'\\','?','?','\\'};
+ WCHAR symlinkW[MAX_DIR_ENTRY_LEN] = {0};
UNICODE_STRING nt_name;
ANSI_STRING unix_name;
data_size_t size = 1024;
- WCHAR *name = NULL;
+ WCHAR *ptr, *name = NULL;
NTSTATUS status;
HANDLE mapping;
+ size_t offset = 0;
if (!addr || !info || !res_len) return STATUS_INVALID_PARAMETER;
@@ -2464,14 +2470,34 @@ static NTSTATUS get_section_name( HANDLE process, LPCVOID addr,
}
found:
- *res_len = sizeof(MEMORY_SECTION_NAME) + nt_name.Length + sizeof(WCHAR);
+ if (nt_name.Length >= sizeof(dosprefixW) &&
+ !memcmp( nt_name.Buffer, dosprefixW, sizeof(dosprefixW) ))
+ {
+ UNICODE_STRING device_name = nt_name;
+ offset = sizeof(dosprefixW) / sizeof(WCHAR);
+ while (offset * sizeof(WCHAR) < nt_name.Length && nt_name.Buffer[ offset ] != '\\') offset++;
+ device_name.Length = offset * sizeof(WCHAR);
+ if (read_nt_symlink( NULL, &device_name, symlinkW, MAX_DIR_ENTRY_LEN ))
+ {
+ symlinkW[0] = 0;
+ offset = 0;
+ }
+ }
+
+ *res_len = sizeof(MEMORY_SECTION_NAME) + strlenW(symlinkW) * sizeof(WCHAR) +
+ nt_name.Length - offset * sizeof(WCHAR) + sizeof(WCHAR);
if (len >= *res_len)
{
- info->SectionFileName.Length = nt_name.Length;
- info->SectionFileName.MaximumLength = nt_name.Length + sizeof(WCHAR);
+ info->SectionFileName.Length = strlenW(symlinkW) * sizeof(WCHAR) +
+ nt_name.Length - offset * sizeof(WCHAR);
+ info->SectionFileName.MaximumLength = info->SectionFileName.Length + sizeof(WCHAR);
info->SectionFileName.Buffer = (WCHAR *)(info + 1);
- memcpy(info->SectionFileName.Buffer, nt_name.Buffer, nt_name.Length);
- info->SectionFileName.Buffer[ nt_name.Length / sizeof(WCHAR) ] = 0;
+
+ ptr = (WCHAR *)(info + 1);
+ strcpyW( ptr, symlinkW );
+ ptr += strlenW(symlinkW);
+ memcpy( ptr, nt_name.Buffer + offset, nt_name.Length - offset * sizeof(WCHAR) );
+ ptr[ nt_name.Length / sizeof(WCHAR) - offset ] = 0;
}
else
status = (len < sizeof(MEMORY_SECTION_NAME)) ? STATUS_INFO_LENGTH_MISMATCH : STATUS_BUFFER_OVERFLOW;
diff --git a/dlls/psapi/tests/psapi_main.c b/dlls/psapi/tests/psapi_main.c
index 0751bb24fb8..dd592a9ab21 100644
--- a/dlls/psapi/tests/psapi_main.c
+++ b/dlls/psapi/tests/psapi_main.c
@@ -434,7 +434,6 @@ static void test_GetMappedFileName(void)
ret = pGetMappedFileNameA(GetCurrentProcess(), base, map_name, sizeof(map_name));
ok(ret, "GetMappedFileName error %d\n", GetLastError());
ok(ret > strlen(device_name), "map_name should be longer than device_name\n");
-todo_wine
ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name);
SetLastError(0xdeadbeef);
@@ -446,7 +445,6 @@ todo_wine
{
ok(memcmp(map_nameW, nt_map_name, lstrlenW(map_nameW)) == 0, "map name does not start with a device name: %s\n", map_name);
WideCharToMultiByte(CP_ACP, 0, map_nameW, -1, map_name, MAX_PATH, NULL, NULL);
-todo_wine
ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name);
}
@@ -459,7 +457,6 @@ todo_wine
{
ok(memcmp(map_nameW, nt_map_name, lstrlenW(map_nameW)) == 0, "map name does not start with a device name: %s\n", map_name);
WideCharToMultiByte(CP_ACP, 0, map_nameW, -1, map_name, MAX_PATH, NULL, NULL);
-todo_wine
ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name);
}
@@ -467,7 +464,6 @@ todo_wine
ret = pGetMappedFileNameA(GetCurrentProcess(), base + 0x2000, map_name, sizeof(map_name));
ok(ret, "GetMappedFileName error %d\n", GetLastError());
ok(ret > strlen(device_name), "map_name should be longer than device_name\n");
-todo_wine
ok(memcmp(map_name, device_name, strlen(device_name)) == 0, "map name does not start with a device name: %s\n", map_name);
SetLastError(0xdeadbeef);
@@ -552,7 +548,7 @@ static void test_GetProcessImageFileName(void)
{
/* Windows returns 2*strlen-1 */
ok(ret >= strlen(szImgPath), "szImgPath=\"%s\" ret=%d\n", szImgPath, ret);
- todo_wine ok(!strcmp(szImgPath, szMapPath), "szImgPath=\"%s\" szMapPath=\"%s\"\n", szImgPath, szMapPath);
+ ok(!strcmp(szImgPath, szMapPath), "szImgPath=\"%s\" szMapPath=\"%s\"\n", szImgPath, szMapPath);
}
SetLastError(0xdeadbeef);
--
2.12.2

View File

@ -1 +1,2 @@
Fixes: [23999] Implement MemorySectionName class in NtQueryVirtualMemory
Depends: ntdll-NtDevicePath

View File

@ -2373,6 +2373,13 @@ if test "$enable_ntdll_NtSuspendProcess" -eq 1; then
enable_kernel32_K32GetPerformanceInfo=1
fi
if test "$enable_ntdll_NtQueryVirtualMemory" -eq 1; then
if test "$enable_ntdll_NtDevicePath" -gt 1; then
abort "Patchset ntdll-NtDevicePath disabled, but ntdll-NtQueryVirtualMemory depends on that."
fi
enable_ntdll_NtDevicePath=1
fi
if test "$enable_ntdll_NtDevicePath" -eq 1; then
if test "$enable_ntdll_Pipe_SpecialCharacters" -gt 1; then
abort "Patchset ntdll-Pipe_SpecialCharacters disabled, but ntdll-NtDevicePath depends on that."
@ -5754,19 +5761,36 @@ fi
# Patchset ntdll-NtQueryVirtualMemory
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * ntdll-Pipe_SpecialCharacters, ntdll-NtDevicePath
# |
# | This patchset fixes the following Wine bugs:
# | * [#23999] Implement MemorySectionName class in NtQueryVirtualMemory
# |
# | Modified files:
# | * dlls/kernel32/virtual.c, dlls/ntdll/tests/info.c, dlls/ntdll/virtual.c, dlls/psapi/tests/psapi_main.c
# | * dlls/kernel32/virtual.c, dlls/ntdll/directory.c, dlls/ntdll/loader.c, dlls/ntdll/ntdll_misc.h, dlls/ntdll/server.c,
# | dlls/ntdll/tests/info.c, dlls/ntdll/virtual.c, dlls/psapi/tests/psapi_main.c, server/process.c, server/protocol.def,
# | server/thread.c
# |
if test "$enable_ntdll_NtQueryVirtualMemory" -eq 1; then
patch_apply ntdll-NtQueryVirtualMemory/0001-ntdll-Implement-NtQueryVirtualMemory-MemorySectionNa.patch
patch_apply ntdll-NtQueryVirtualMemory/0002-kernel32-Implement-K32GetMappedFileName.-v2.patch
patch_apply ntdll-NtQueryVirtualMemory/0003-ntdll-Fix-error-code-when-querying-too-large-memory-.patch
patch_apply ntdll-NtQueryVirtualMemory/0001-server-Store-full-path-for-ntdll-kernel32-dll.patch
patch_apply ntdll-NtQueryVirtualMemory/0002-ntdll-Split-logic-for-MemoryBasicInformation-into-a-.patch
patch_apply ntdll-NtQueryVirtualMemory/0003-ntdll-Implement-NtQueryVirtualMemory-MemorySectionNa.patch
patch_apply ntdll-NtQueryVirtualMemory/0004-ntdll-tests-Add-tests-for-NtQueryVirtualMemory-Memor.patch
patch_apply ntdll-NtQueryVirtualMemory/0005-ntdll-tests-Add-test-to-ensure-section-name-is-full-.patch
patch_apply ntdll-NtQueryVirtualMemory/0006-ntdll-Allow-to-query-section-names-from-other-proces.patch
patch_apply ntdll-NtQueryVirtualMemory/0007-kernel32-Implement-K32GetMappedFileName.-v2.patch
patch_apply ntdll-NtQueryVirtualMemory/0008-ntdll-Resolve-drive-symlinks-before-returning-sectio.patch
patch_apply ntdll-NtQueryVirtualMemory/0009-ntdll-Fix-error-code-when-querying-too-large-memory-.patch
(
printf '%s\n' '+ { "Dmitry Timoshkov", "ntdll: Implement NtQueryVirtualMemory(MemorySectionName).", 2 },';
printf '%s\n' '+ { "Sebastian Lackner", "server: Store full path for ntdll/kernel32 dll.", 1 },';
printf '%s\n' '+ { "Dmitry Timoshkov", "ntdll: Split logic for MemoryBasicInformation into a separate function.", 1 },';
printf '%s\n' '+ { "Dmitry Timoshkov", "ntdll: Implement NtQueryVirtualMemory(MemorySectionName).", 3 },';
printf '%s\n' '+ { "Dmitry Timoshkov", "ntdll/tests: Add tests for NtQueryVirtualMemory(MemorySectionName).", 1 },';
printf '%s\n' '+ { "Sebastian Lackner", "ntdll/tests: Add test to ensure section name is full path.", 1 },';
printf '%s\n' '+ { "Sebastian Lackner", "ntdll: Allow to query section names from other processes.", 1 },';
printf '%s\n' '+ { "Dmitry Timoshkov", "kernel32: Implement K32GetMappedFileName.", 2 },';
printf '%s\n' '+ { "Sebastian Lackner", "ntdll: Resolve drive symlinks before returning section name.", 1 },';
printf '%s\n' '+ { "Michael Müller", "ntdll: Fix error code when querying too large memory address.", 1 },';
) >> "$patchlist"
fi