Module: wine Branch: master Commit: c122260b9d2f60f78fac610775d3bd767e38680b URL: http://source.winehq.org/git/wine.git/?a=commit;h=c122260b9d2f60f78fac610775...
Author: Alexandre Julliard julliard@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;