Alexandre Julliard : ntdll: Implementation of inter-process VirtualProtectEx.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Jan 16 05:22:15 CST 2007


Module: wine
Branch: master
Commit: 1ea968016f1eaa9fada60a328e6f310fa0d5d7e3
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=1ea968016f1eaa9fada60a328e6f310fa0d5d7e3

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Jan 15 22:30:04 2007 +0100

ntdll: Implementation of inter-process VirtualProtectEx.

---

 dlls/kernel32/tests/virtual.c  |   16 ++++++----------
 dlls/ntdll/sync.c              |   10 ++++++++++
 dlls/ntdll/virtual.c           |   21 ++++++++++++++++++---
 include/wine/server_protocol.h |   20 ++++++++++++++++++--
 server/protocol.def            |   18 +++++++++++++++++-
 server/thread.c                |    1 +
 server/trace.c                 |   11 +++++++++++
 7 files changed, 81 insertions(+), 16 deletions(-)

diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
index 3c64a06..d19818c 100644
--- a/dlls/kernel32/tests/virtual.c
+++ b/dlls/kernel32/tests/virtual.c
@@ -118,7 +118,7 @@ static void test_VirtualAllocEx(void)
     SetLastError(0xdeadbeef);
     ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
        "VirtualProtectEx should fail on a not committed memory\n");
-    todo_wine ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
+    ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */
         "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
 
@@ -141,21 +141,17 @@ static void test_VirtualAllocEx(void)
     SetLastError(0xdeadbeef);
     ok(!VirtualProtectEx(hProcess, addr1, 0xFFFC, PAGE_READONLY, &old_prot),
         "VirtualProtectEx should fail on a not committed memory\n");
-    todo_wine ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
+    ok(GetLastError() == ERROR_INVALID_ADDRESS /* NT */ ||
        GetLastError() == ERROR_INVALID_PARAMETER, /* Win9x */
         "got %u, expected ERROR_INVALID_ADDRESS\n", GetLastError());
 
     old_prot = 0;
-    todo_wine ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READONLY,
-                                  &old_prot), "VirtualProtectEx failed\n");
-    todo_wine ok(old_prot == PAGE_NOACCESS,
-        "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
+    ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READONLY, &old_prot), "VirtualProtectEx failed\n");
+    ok(old_prot == PAGE_NOACCESS, "wrong old protection: got %04x instead of PAGE_NOACCESS\n", old_prot);
 
     old_prot = 0;
-    todo_wine ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READWRITE,
-                                  &old_prot), "VirtualProtectEx failed\n");
-    todo_wine ok(old_prot == PAGE_READONLY,
-        "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
+    ok(VirtualProtectEx(hProcess, addr1, 0x1000, PAGE_READWRITE, &old_prot), "VirtualProtectEx failed\n");
+    ok(old_prot == PAGE_READONLY, "wrong old protection: got %04x instead of PAGE_READONLY\n", old_prot);
 
     ok(!VirtualFreeEx(hProcess, addr1, 0x10000, 0),
        "VirtualFreeEx should fail with type 0\n");
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index e0eb2d4..8cfd1e5 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -746,6 +746,16 @@ static BOOL call_apcs( BOOL alertable )
             }
             break;
         }
+        case APC_VIRTUAL_PROTECT:
+            result.type = call.type;
+            result.virtual_protect.addr = call.virtual_protect.addr;
+            result.virtual_protect.size = call.virtual_protect.size;
+            result.virtual_protect.status = NtProtectVirtualMemory( NtCurrentProcess(),
+                                                                    &result.virtual_protect.addr,
+                                                                    &result.virtual_protect.size,
+                                                                    call.virtual_protect.prot,
+                                                                    &result.virtual_protect.prot );
+            break;
         default:
             server_protocol_error( "get_apc_request: bad type %d\n", call.type );
             break;
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 0407a21..57cbb20 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -1597,10 +1597,25 @@ NTSTATUS WINAPI NtProtectVirtualMemory(
 
     TRACE("%p %p %08lx %08x\n", process, addr, size, new_prot );
 
-    if (!is_current_process( process ))
+    if (process != NtCurrentProcess())
     {
-        ERR("Unsupported on other process\n");
-        return STATUS_ACCESS_DENIED;
+        apc_call_t call;
+        apc_result_t result;
+
+        call.virtual_protect.type = APC_VIRTUAL_PROTECT;
+        call.virtual_protect.addr = addr;
+        call.virtual_protect.size = size;
+        call.virtual_protect.prot = new_prot;
+        status = NTDLL_queue_process_apc( process, &call, &result );
+        if (status != STATUS_SUCCESS) return status;
+
+        if (result.virtual_protect.status == STATUS_SUCCESS)
+        {
+            *addr_ptr = result.virtual_protect.addr;
+            *size_ptr = result.virtual_protect.size;
+            if (old_prot) *old_prot = result.virtual_protect.prot;
+        }
+        return result.virtual_protect.status;
     }
 
     /* Fix the parameters */
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 60715ff..890dabd 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -217,7 +217,8 @@ enum apc_type
     APC_ASYNC_IO,
     APC_VIRTUAL_ALLOC,
     APC_VIRTUAL_FREE,
-    APC_VIRTUAL_QUERY
+    APC_VIRTUAL_QUERY,
+    APC_VIRTUAL_PROTECT
 };
 
 typedef union
@@ -265,6 +266,13 @@ typedef union
         enum apc_type    type;
         const void      *addr;
     } virtual_query;
+    struct
+    {
+        enum apc_type    type;
+        void            *addr;
+        unsigned long    size;
+        unsigned int     prot;
+    } virtual_protect;
 } apc_call_t;
 
 typedef union
@@ -296,6 +304,14 @@ typedef union
         unsigned int     alloc_prot;
         unsigned int     alloc_type;
     } virtual_query;
+    struct
+    {
+        enum apc_type    type;
+        unsigned int     status;
+        void            *addr;
+        unsigned long    size;
+        unsigned int     prot;
+    } virtual_protect;
 } apc_result_t;
 
 
@@ -4517,6 +4533,6 @@ union generic_reply
     struct query_symlink_reply query_symlink_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 267
+#define SERVER_PROTOCOL_VERSION 268
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index b24e275..8c40e10 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -233,7 +233,8 @@ enum apc_type
     APC_ASYNC_IO,
     APC_VIRTUAL_ALLOC,
     APC_VIRTUAL_FREE,
-    APC_VIRTUAL_QUERY
+    APC_VIRTUAL_QUERY,
+    APC_VIRTUAL_PROTECT
 };
 
 typedef union
@@ -281,6 +282,13 @@ typedef union
         enum apc_type    type;      /* APC_VIRTUAL_QUERY */
         const void      *addr;      /* requested address */
     } virtual_query;
+    struct
+    {
+        enum apc_type    type;      /* APC_VIRTUAL_PROTECT */
+        void            *addr;      /* requested address */
+        unsigned long    size;      /* requested address */
+        unsigned int     prot;      /* new protection flags */
+    } virtual_protect;
 } apc_call_t;
 
 typedef union
@@ -312,6 +320,14 @@ typedef union
         unsigned int     alloc_prot;/* resulting allocation protection */
         unsigned int     alloc_type;/* resulting region allocation type */
     } virtual_query;
+    struct
+    {
+        enum apc_type    type;      /* APC_VIRTUAL_PROTECT */
+        unsigned int     status;    /* status returned by call */
+        void            *addr;      /* resulting address */
+        unsigned long    size;      /* resulting size */
+        unsigned int     prot;      /* old protection flags */
+    } virtual_protect;
 } apc_result_t;
 
 /****************************************************************/
diff --git a/server/thread.c b/server/thread.c
index 62bd559..35484a4 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -1157,6 +1157,7 @@ DECL_HANDLER(queue_apc)
     case APC_VIRTUAL_ALLOC:
     case APC_VIRTUAL_FREE:
     case APC_VIRTUAL_QUERY:
+    case APC_VIRTUAL_PROTECT:
         access = (apc->call.type == APC_VIRTUAL_QUERY) ? PROCESS_QUERY_INFORMATION : PROCESS_VM_OPERATION;
         if ((process = get_process_from_handle( req->process, access )))
         {
diff --git a/server/trace.c b/server/trace.c
index 2b9ee8c..b878c02 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -133,6 +133,11 @@ static void dump_apc_call( const apc_cal
     case APC_VIRTUAL_QUERY:
         fprintf( stderr, "APC_VIRTUAL_QUERY,addr=%p", call->virtual_query.addr );
         break;
+    case APC_VIRTUAL_PROTECT:
+        fprintf( stderr, "APC_VIRTUAL_PROTECT,addr=%p,size=%lu,prot=%x",
+                 call->virtual_protect.addr, call->virtual_protect.size,
+                 call->virtual_protect.prot );
+        break;
     default:
         fprintf( stderr, "type=%u", call->type );
         break;
@@ -165,6 +170,12 @@ static void dump_apc_result( const apc_r
                  result->virtual_query.prot, result->virtual_query.alloc_prot,
                  result->virtual_query.alloc_type );
         break;
+    case APC_VIRTUAL_PROTECT:
+        fprintf( stderr, "APC_VIRTUAL_PROTECT,status=%s,addr=%p,size=%lu,prot=%x",
+                 get_status_name( result->virtual_protect.status ),
+                 result->virtual_protect.addr, result->virtual_protect.size,
+                 result->virtual_protect.prot );
+        break;
     default:
         fprintf( stderr, "type=%u", result->type );
         break;




More information about the wine-cvs mailing list