From c122260b9d2f60f78fac610775d3bd767e38680b Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 16 Jan 2007 09:50:08 +0100 Subject: [PATCH] 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 fe92383a6e5..ce8b50045e4 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -1802,12 +1802,32 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HANDLE process, LPCVOID addr, */ 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( HANDLE process, PVOID *addr, SIZE_T *size, */ 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 0f4d3f21f67..ca98f28f83c 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 9987fd46dd4..343fbbbb42f 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 6c53e5c6274..5b0268ab7b1 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 7422912ccd3..6766faf8e73 100644 --- a/server/trace.c +++ b/server/trace.c @@ -142,6 +142,14 @@ static void dump_apc_call( const apc_call_t *call ) 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_result_t *result ) 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;