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); +}