ntdll: Implementation of inter-process VirtualProtectEx.
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 @@
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 @@
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 @@
}
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 @@
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 @@
APC_ASYNC_IO,
APC_VIRTUAL_ALLOC,
APC_VIRTUAL_FREE,
- APC_VIRTUAL_QUERY
+ APC_VIRTUAL_QUERY,
+ APC_VIRTUAL_PROTECT
};
typedef union
@@ -265,6 +266,13 @@
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 @@
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 @@
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 @@
APC_ASYNC_IO,
APC_VIRTUAL_ALLOC,
APC_VIRTUAL_FREE,
- APC_VIRTUAL_QUERY
+ APC_VIRTUAL_QUERY,
+ APC_VIRTUAL_PROTECT
};
typedef union
@@ -281,6 +282,13 @@
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 @@
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 @@
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 @@
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 @@
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;