> > I have a hack for VirtualQueryEx for Linux, but Alexandre will never
> > accept it (but if someone needs it, I can provide it)
>
> May you post it to me ?
cc'ing wine-devel if others are interested
of course, it'll only work on linux (but it wouldn't be too hard to make
it work on other OSes)
(you need to run tools/make_request after applying the patch and before
re-configuring and re-compiling)
A+
Name: vqex
ChangeLog: added implementation for VirtualQueryEx (linux only)
License: X11
GenDate: 2002/07/15 18:59:12 UTC
ModifiedFiles: memory/virtual.c server/Makefile.in server/protocol.def
AddedFiles: server/virtual.c
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/memory/virtual.c,v
retrieving revision 1.80
diff -u -u -r1.80 virtual.c
--- memory/virtual.c 3 Jul 2002 21:10:44 -0000 1.80
+++ memory/virtual.c 10 Jul 2002 21:46:31 -0000
@@ -1243,15 +1243,42 @@
* Number of bytes returned in information buffer
*/
DWORD WINAPI VirtualQueryEx(
- HANDLE handle, /* [in] Handle of process */
- LPCVOID addr, /* [in] Address of region */
- LPMEMORY_BASIC_INFORMATION info, /* [out] Address of info buffer */
- DWORD len /* [in] Size of buffer */ )
+ HANDLE handle, /* [in] Handle of process */
+ LPCVOID addr, /* [in] Address of region */
+ LPMEMORY_BASIC_INFORMATION pinfo, /* [out] Address of info buffer */
+ DWORD len /* [in] Size of buffer */ )
{
+ int res;
+ MEMORY_BASIC_INFORMATION info;
+
if (MapProcessHandle( handle ) == GetCurrentProcessId())
- return VirtualQuery( addr, info, len );
- ERR("Unsupported on other process\n");
- return 0;
+ return VirtualQuery( addr, pinfo, len );
+
+ if (addr >= (void*)0xc0000000) return 0;
+
+ SERVER_START_REQ( query_virtual_memory_info )
+ {
+ req->handle = handle;
+ req->addr = ROUND_ADDR( addr, page_mask );
+
+ res = wine_server_call_err( req );
+ if (!res)
+ {
+ info.State = reply->state;
+ info.Protect = VIRTUAL_Win32Flags[reply->protect];
+ info.AllocationProtect = VIRTUAL_Win32Flags[reply->protect_other];
+ info.Type = reply->type;
+ info.BaseAddress = reply->base_address;
+ info.AllocationBase = reply->alloc_base;
+ info.RegionSize = reply->size;
+ }
+ }
+ SERVER_END_REQ;
+ if (res) return 0;
+
+ len = min(len, sizeof(info));
+ memcpy(pinfo, &info, len);
+ return len;
}
Index: server/Makefile.in
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/server/Makefile.in,v
retrieving revision 1.33
diff -u -u -r1.33 Makefile.in
--- server/Makefile.in 9 May 2002 04:31:40 -0000 1.33
+++ server/Makefile.in 14 Jul 2002 17:00:22 -0000
@@ -39,6 +39,7 @@
trace.c \
unicode.c \
user.c \
+ virtual.c \
window.c
PROGRAMS = wineserver
Index: server/protocol.def
===================================================================
RCS file: /home/cvs/cvsroot/wine/wine/server/protocol.def,v
retrieving revision 1.39
diff -u -u -r1.39 protocol.def
--- server/protocol.def 2 Jun 2002 21:22:22 -0000 1.39
+++ server/protocol.def 10 Jul 2002 21:44:11 -0000
@@ -1038,6 +1038,21 @@
@END
+/* query a process virtual memory */
+@REQ(query_virtual_memory_info)
+ obj_handle_t handle; /* handle to the process */
+ void* addr; /* address where to look at */
+@REPLY
+ int state;
+ int protect;
+ int protect_other;
+ int type;
+ void* base_address;
+ void* alloc_base;
+ int size;
+@END
+
+
/* Create a file mapping */
@REQ(create_mapping)
int size_high; /* mapping size */
--- /dev/null Thu Jan 1 01:00:00 1970
+++ server/virtual.c Wed Jul 10 23:31:31 2002
@@ -0,0 +1,103 @@
+#include "config.h"
+#include "wine/port.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "process.h"
+#include "request.h"
+
+static void query_virtual_memory_info(struct process* process, unsigned base,
+ struct query_virtual_memory_info_reply* reply)
+{
+ char buffer[MAX_PATH];
+ FILE* file = NULL;
+ unsigned alloc_base = 0;
+ unsigned size = 0;
+ unsigned start, end;
+ unsigned vprot;
+
+#ifdef linux
+ if (process->thread_list)
+ {
+ sprintf(buffer, "/proc/%d/maps", process->thread_list->unix_pid);
+ file = fopen(buffer, "r");
+ }
+#endif
+ if (!file)
+ {
+ set_error(STATUS_NOT_SUPPORTED);
+ return;
+ }
+
+ while (fgets(buffer, sizeof(buffer) - 1, file))
+ {
+#ifdef linux
+ char prot[5];
+ unsigned shift, minor, major;
+ /* 407ac000-407ae000 rw-p 00007000 */
+
+ if (sscanf(buffer, "%x-%x %4s %08x %x:%x", &start, &end, prot, &shift, &major, &minor) != 6)
+ {
+ if (sscanf(buffer, "%x-%x %4s", &start, &end, prot) != 3) continue;
+ shift = 0;
+ major = minor = 0;
+ }
+
+ vprot = 0;
+ if (prot[0] == 'r') vprot |= VPROT_READ;
+ if (prot[1] == 'w') vprot |= VPROT_WRITE;
+ if (prot[2] == 'x') vprot |= VPROT_EXEC;
+ if (prot[3] == 'p') vprot |= VPROT_WRITECOPY;
+#endif
+
+ if (end <= base)
+ continue;
+ if (base < start)
+ {
+ size = start - alloc_base;
+ goto noMap;
+ }
+ if (base < end)
+ {
+ alloc_base = start;
+ size = end - start;
+
+ reply->state = MEM_COMMIT; /* FIXME: hard to tell MEM_RESERVE */
+ reply->protect = vprot;
+ reply->protect_other = reply->protect; /* FIXME: hard to guesss */
+
+ reply->type = (major && minor) ? MEM_MAPPED : 0; /* FIXME */
+ goto final;
+ }
+ alloc_base = end;
+ }
+
+ size = 0xffff0000 - alloc_base;
+
+ noMap:
+ reply->state = MEM_FREE;
+ reply->protect = 0;
+ reply->protect_other = 0;
+ reply->type = 0;
+ final:
+ reply->base_address = (LPVOID)base;
+ reply->alloc_base = (LPVOID)alloc_base;
+ reply->size = size - (base - alloc_base);
+
+ fclose(file);
+ return;
+}
+
+/* query information about a part of the memory */
+DECL_HANDLER(query_virtual_memory_info)
+{
+ struct process* process;
+
+ if (!(process = get_process_from_handle( req->handle, PROCESS_VM_READ )))
+ return;
+
+ query_virtual_memory_info(process, (unsigned)req->addr, reply);
+}