Alexandre Julliard : ntdll: Implemented NtLockVirtualMemory and NtUnlockVirtualMemory.

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


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

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Jan 16 09:50:08 2007 +0100

ntdll: Implemented NtLockVirtualMemory and NtUnlockVirtualMemory.

---

 dlls/ntdll/virtual.c           |   56 ++++++++++++++++++++++++++++++++++-----
 include/wine/server_protocol.h |   32 +++++++++++++++++++++-
 server/protocol.def            |   30 ++++++++++++++++++++-
 server/thread.c                |    2 +
 server/trace.c                 |   18 +++++++++++++
 5 files changed, 127 insertions(+), 11 deletions(-)

diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index fe92383..ce8b500 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -1802,12 +1802,32 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HA
  */
 NTSTATUS WINAPI NtLockVirtualMemory( HANDLE process, PVOID *addr, SIZE_T *size, ULONG unknown )
 {
-    if (!is_current_process( process ))
+    NTSTATUS status = STATUS_SUCCESS;
+
+    if (process != NtCurrentProcess())
     {
-        ERR("Unsupported on other process\n");
-        return STATUS_ACCESS_DENIED;
+        apc_call_t call;
+        apc_result_t result;
+
+        call.virtual_lock.type = APC_VIRTUAL_LOCK;
+        call.virtual_lock.addr = *addr;
+        call.virtual_lock.size = *size;
+        status = NTDLL_queue_process_apc( process, &call, &result );
+        if (status != STATUS_SUCCESS) return status;
+
+        if (result.virtual_lock.status == STATUS_SUCCESS)
+        {
+            *addr = result.virtual_lock.addr;
+            *size = result.virtual_lock.size;
+        }
+        return result.virtual_lock.status;
     }
-    return STATUS_SUCCESS;
+
+    *size = ROUND_SIZE( *addr, *size );
+    *addr = ROUND_ADDR( *addr, page_mask );
+
+    if (mlock( *addr, *size )) status = STATUS_ACCESS_DENIED;
+    return status;
 }
 
 
@@ -1817,12 +1837,32 @@ NTSTATUS WINAPI NtLockVirtualMemory( HAN
  */
 NTSTATUS WINAPI NtUnlockVirtualMemory( HANDLE process, PVOID *addr, SIZE_T *size, ULONG unknown )
 {
-    if (!is_current_process( process ))
+    NTSTATUS status = STATUS_SUCCESS;
+
+    if (process != NtCurrentProcess())
     {
-        ERR("Unsupported on other process\n");
-        return STATUS_ACCESS_DENIED;
+        apc_call_t call;
+        apc_result_t result;
+
+        call.virtual_unlock.type = APC_VIRTUAL_UNLOCK;
+        call.virtual_unlock.addr = *addr;
+        call.virtual_unlock.size = *size;
+        status = NTDLL_queue_process_apc( process, &call, &result );
+        if (status != STATUS_SUCCESS) return status;
+
+        if (result.virtual_unlock.status == STATUS_SUCCESS)
+        {
+            *addr = result.virtual_unlock.addr;
+            *size = result.virtual_unlock.size;
+        }
+        return result.virtual_unlock.status;
     }
-    return STATUS_SUCCESS;
+
+    *size = ROUND_SIZE( *addr, *size );
+    *addr = ROUND_ADDR( *addr, page_mask );
+
+    if (munlock( *addr, *size )) status = STATUS_ACCESS_DENIED;
+    return status;
 }
 
 
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index 0f4d3f2..ca98f28 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -219,7 +219,9 @@ enum apc_type
     APC_VIRTUAL_FREE,
     APC_VIRTUAL_QUERY,
     APC_VIRTUAL_PROTECT,
-    APC_VIRTUAL_FLUSH
+    APC_VIRTUAL_FLUSH,
+    APC_VIRTUAL_LOCK,
+    APC_VIRTUAL_UNLOCK
 };
 
 typedef union
@@ -280,6 +282,18 @@ typedef union
         const void      *addr;
         unsigned long    size;
     } virtual_flush;
+    struct
+    {
+        enum apc_type    type;
+        void            *addr;
+        unsigned long    size;
+    } virtual_lock;
+    struct
+    {
+        enum apc_type    type;
+        void            *addr;
+        unsigned long    size;
+    } virtual_unlock;
 } apc_call_t;
 
 typedef union
@@ -326,6 +340,20 @@ typedef union
         const void      *addr;
         unsigned long    size;
     } virtual_flush;
+    struct
+    {
+        enum apc_type    type;
+        unsigned int     status;
+        void            *addr;
+        unsigned long    size;
+    } virtual_lock;
+    struct
+    {
+        enum apc_type    type;
+        unsigned int     status;
+        void            *addr;
+        unsigned long    size;
+    } virtual_unlock;
 } apc_result_t;
 
 
@@ -4547,6 +4575,6 @@ union generic_reply
     struct query_symlink_reply query_symlink_reply;
 };
 
-#define SERVER_PROTOCOL_VERSION 269
+#define SERVER_PROTOCOL_VERSION 270
 
 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */
diff --git a/server/protocol.def b/server/protocol.def
index 9987fd4..343fbbb 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -235,7 +235,9 @@ enum apc_type
     APC_VIRTUAL_FREE,
     APC_VIRTUAL_QUERY,
     APC_VIRTUAL_PROTECT,
-    APC_VIRTUAL_FLUSH
+    APC_VIRTUAL_FLUSH,
+    APC_VIRTUAL_LOCK,
+    APC_VIRTUAL_UNLOCK
 };
 
 typedef union
@@ -296,6 +298,18 @@ typedef union
         const void      *addr;      /* requested address */
         unsigned long    size;      /* requested address */
     } virtual_flush;
+    struct
+    {
+        enum apc_type    type;      /* APC_VIRTUAL_LOCK */
+        void            *addr;      /* requested address */
+        unsigned long    size;      /* requested address */
+    } virtual_lock;
+    struct
+    {
+        enum apc_type    type;      /* APC_VIRTUAL_UNLOCK */
+        void            *addr;      /* requested address */
+        unsigned long    size;      /* requested address */
+    } virtual_unlock;
 } apc_call_t;
 
 typedef union
@@ -342,6 +356,20 @@ typedef union
         const void      *addr;      /* resulting address */
         unsigned long    size;      /* resulting size */
     } virtual_flush;
+    struct
+    {
+        enum apc_type    type;      /* APC_VIRTUAL_LOCK */
+        unsigned int     status;    /* status returned by call */
+        void            *addr;      /* resulting address */
+        unsigned long    size;      /* resulting size */
+    } virtual_lock;
+    struct
+    {
+        enum apc_type    type;      /* APC_VIRTUAL_UNLOCK */
+        unsigned int     status;    /* status returned by call */
+        void            *addr;      /* resulting address */
+        unsigned long    size;      /* resulting size */
+    } virtual_unlock;
 } apc_result_t;
 
 /****************************************************************/
diff --git a/server/thread.c b/server/thread.c
index 6c53e5c..5b0268a 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -1159,6 +1159,8 @@ DECL_HANDLER(queue_apc)
     case APC_VIRTUAL_QUERY:
     case APC_VIRTUAL_PROTECT:
     case APC_VIRTUAL_FLUSH:
+    case APC_VIRTUAL_LOCK:
+    case APC_VIRTUAL_UNLOCK:
         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 7422912..6766faf 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -142,6 +142,14 @@ static void dump_apc_call( const apc_cal
         fprintf( stderr, "APC_VIRTUAL_FLUSH,addr=%p,size=%lu",
                  call->virtual_flush.addr, call->virtual_flush.size );
         break;
+    case APC_VIRTUAL_LOCK:
+        fprintf( stderr, "APC_VIRTUAL_LOCK,addr=%p,size=%lu",
+                 call->virtual_lock.addr, call->virtual_lock.size );
+        break;
+    case APC_VIRTUAL_UNLOCK:
+        fprintf( stderr, "APC_VIRTUAL_UNLOCK,addr=%p,size=%lu",
+                 call->virtual_unlock.addr, call->virtual_unlock.size );
+        break;
     default:
         fprintf( stderr, "type=%u", call->type );
         break;
@@ -185,6 +193,16 @@ static void dump_apc_result( const apc_r
                  get_status_name( result->virtual_flush.status ),
                  result->virtual_flush.addr, result->virtual_flush.size );
         break;
+    case APC_VIRTUAL_LOCK:
+        fprintf( stderr, "APC_VIRTUAL_LOCK,status=%s,addr=%p,size=%lu",
+                 get_status_name( result->virtual_lock.status ),
+                 result->virtual_lock.addr, result->virtual_lock.size );
+        break;
+    case APC_VIRTUAL_UNLOCK:
+        fprintf( stderr, "APC_VIRTUAL_UNLOCK,status=%s,addr=%p,size=%lu",
+                 get_status_name( result->virtual_unlock.status ),
+                 result->virtual_unlock.addr, result->virtual_unlock.size );
+        break;
     default:
         fprintf( stderr, "type=%u", result->type );
         break;




More information about the wine-cvs mailing list