About VirtualQueryEx hack

Eric Pouech eric.pouech at wanadoo.fr
Mon Jul 15 14:03:31 CDT 2002


> > 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+
-------------- next part --------------
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 */
+ at REQ(query_virtual_memory_info)
+    obj_handle_t handle;        /* handle to the process */
+    void*        addr;          /* address where to look at */
+ at REPLY
+    int          state;
+    int          protect;
+    int          protect_other;
+    int          type;
+    void*        base_address;
+    void*        alloc_base;
+    int          size;
+ at 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);
+}


More information about the wine-devel mailing list