kernel32: Add basic OpenProcess test, make it pass under Wine

Dmitry Timoshkov dmitry at codeweavers.com
Mon Nov 6 08:24:02 CST 2006


Hello,

Changelog:
    kernel32: Add basic OpenProcess test, make it pass under Wine.

diff -up a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
--- a/dlls/kernel32/tests/process.c	2006-10-11 12:34:26.000000000 +0900
+++ b/dlls/kernel32/tests/process.c	2006-11-06 22:10:54.000000000 +0800
@@ -2,6 +2,7 @@
  * Unit test suite for CreateProcess function.
  *
  * Copyright 2002 Eric Pouech
+ * Copyright 2006 Dmitry Timoshkov
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -1265,6 +1266,79 @@ static  void    test_ExitCode(void)
     assert(DeleteFileA(resfile) != 0);
 }
 
+static void test_OpenProcess(void)
+{
+    HANDLE hproc;
+    void *addr1;
+    MEMORY_BASIC_INFORMATION info;
+    SIZE_T dummy, read_bytes;
+
+    /* without PROCESS_VM_OPERATION */
+    hproc = OpenProcess(PROCESS_ALL_ACCESS & ~PROCESS_VM_OPERATION, FALSE, GetCurrentProcessId());
+    ok(hproc != NULL, "OpenProcess error %d\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    addr1 = VirtualAllocEx(hproc, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
+    ok(!addr1, "VirtualAllocEx should fail\n");
+    ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
+
+    read_bytes = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ok(ReadProcessMemory(hproc, test_OpenProcess, &dummy, sizeof(dummy), &read_bytes),
+       "ReadProcessMemory error %d\n", GetLastError());
+    ok(read_bytes == sizeof(dummy), "wrong read bytes %ld\n", read_bytes);
+
+    CloseHandle(hproc);
+
+    hproc = OpenProcess(PROCESS_VM_OPERATION, FALSE, GetCurrentProcessId());
+    ok(hproc != NULL, "OpenProcess error %d\n", GetLastError());
+
+    addr1 = VirtualAllocEx(hproc, 0, 0xFFFC, MEM_RESERVE, PAGE_NOACCESS);
+    ok(addr1 != NULL, "VirtualAllocEx error %d\n", GetLastError());
+
+    /* without PROCESS_QUERY_INFORMATION */
+    SetLastError(0xdeadbeef);
+    ok(!VirtualQueryEx(hproc, addr1, &info, sizeof(info)),
+       "VirtualQueryEx without PROCESS_QUERY_INFORMATION rights should fail\n");
+    ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
+
+    /* without PROCESS_VM_READ */
+    read_bytes = 0xdeadbeef;
+    SetLastError(0xdeadbeef);
+    ok(!ReadProcessMemory(hproc, addr1, &dummy, sizeof(dummy), &read_bytes),
+       "ReadProcessMemory without PROCESS_VM_READ rights should fail\n");
+    ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
+    ok(read_bytes == 0, "wrong read bytes %ld\n", read_bytes);
+
+    CloseHandle(hproc);
+
+    hproc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());
+
+    memset(&info, 0xaa, sizeof(info));
+    ok(VirtualQueryEx(hproc, addr1, &info, sizeof(info)) == sizeof(info),
+       "VirtualQueryEx error %d\n", GetLastError());
+
+    ok(info.BaseAddress == addr1, "%p != %p\n", info.BaseAddress, addr1);
+    ok(info.AllocationBase == addr1, "%p != %p\n", info.AllocationBase, addr1);
+    ok(info.AllocationProtect == PAGE_NOACCESS, "%x != PAGE_NOACCESS\n", info.AllocationProtect);
+    ok(info.RegionSize == 0x10000, "%lx != 0x10000\n", info.RegionSize);
+    ok(info.State == MEM_RESERVE, "%x != MEM_RESERVE\n", info.State);
+    /* NT reports Protect == 0 for a not committed memory block */
+    ok(info.Protect == 0 /* NT */ ||
+       info.Protect == PAGE_NOACCESS, /* Win9x */
+        "%x != PAGE_NOACCESS\n", info.Protect);
+    ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
+
+    SetLastError(0xdeadbeef);
+    ok(!VirtualFreeEx(hproc, addr1, 0, MEM_RELEASE),
+       "VirtualFreeEx without PROCESS_VM_OPERATION rights should fail\n");
+    ok(GetLastError() == ERROR_ACCESS_DENIED, "wrong error %d\n", GetLastError());
+
+    CloseHandle(hproc);
+
+    ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
+}
+
 START_TEST(process)
 {
     int b = init();
@@ -1284,6 +1358,7 @@ START_TEST(process)
     test_DebuggingFlag();
     test_Console();
     test_ExitCode();
+    test_OpenProcess();
     /* things that can be tested:
      *  lookup:         check the way program to be executed is searched
      *  handles:        check the handle inheritance stuff (+sec options)
diff -up a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
--- a/dlls/ntdll/ntdll_misc.h	2006-11-06 18:35:24.000000000 +0800
+++ b/dlls/ntdll/ntdll_misc.h	2006-11-06 22:07:21.000000000 +0800
@@ -114,7 +114,7 @@ extern NTSTATUS VIRTUAL_HandleFault(LPCV
 extern BOOL VIRTUAL_HasMapping( LPCVOID addr );
 extern void VIRTUAL_UseLargeAddressSpace(void);
 
-extern BOOL is_current_process( HANDLE handle );
+extern BOOL is_current_process( HANDLE handle, UINT access );
 
 /* code pages */
 extern int ntdll_umbstowcs(DWORD flags, const char* src, int srclen, WCHAR* dst, int dstlen);
diff -up a/dlls/ntdll/process.c b/dlls/ntdll/process.c
--- a/dlls/ntdll/process.c	2006-10-19 12:41:25.000000000 +0900
+++ b/dlls/ntdll/process.c	2006-11-06 21:52:23.000000000 +0800
@@ -141,6 +141,7 @@ NTSTATUS WINAPI NtQueryInformationProces
                     SERVER_START_REQ(get_process_info)
                     {
                         req->handle = ProcessHandle;
+                        req->access = PROCESS_QUERY_INFORMATION;
                         if ((ret = wine_server_call( req )) == STATUS_SUCCESS)
                         {
                             pbi.ExitStatus = reply->exit_code;
@@ -234,6 +235,7 @@ NTSTATUS WINAPI NtQueryInformationProces
                     SERVER_START_REQ(get_process_info)
                     {
                       req->handle = ProcessHandle;
+                      req->access = PROCESS_QUERY_INFORMATION;
                       if ((ret = wine_server_call( req )) == STATUS_SUCCESS)
                       {
                           NTDLL_from_server_abstime(&pti.CreateTime, &reply->start_time);
diff -up a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
--- a/dlls/ntdll/thread.c	2006-10-04 16:28:20.000000000 +0900
+++ b/dlls/ntdll/thread.c	2006-11-06 22:06:47.000000000 +0800
@@ -406,7 +406,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HAN
     NTSTATUS status;
     SIZE_T size, page_size = getpagesize();
 
-    if( ! is_current_process( process ) )
+    if( !is_current_process( process, PROCESS_CREATE_THREAD ) )
     {
         ERR("Unsupported on other process\n");
         return STATUS_ACCESS_DENIED;
diff -up a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
--- a/dlls/ntdll/virtual.c	2006-11-06 18:35:25.000000000 +0800
+++ b/dlls/ntdll/virtual.c	2006-11-06 22:15:48.000000000 +0800
@@ -1193,7 +1193,7 @@ static NTSTATUS map_image( HANDLE hmappi
  *
  * Check whether a process handle is for the current process.
  */
-BOOL is_current_process( HANDLE handle )
+BOOL is_current_process( HANDLE handle, UINT access )
 {
     BOOL ret = FALSE;
 
@@ -1201,6 +1201,7 @@ BOOL is_current_process( HANDLE handle )
     SERVER_START_REQ( get_process_info )
     {
         req->handle = handle;
+        req->access = access;
         if (!wine_server_call( req ))
             ret = ((DWORD)reply->pid == GetCurrentProcessId());
     }
@@ -1315,7 +1316,7 @@ NTSTATUS WINAPI NtAllocateVirtualMemory(
 
     if (!size) return STATUS_INVALID_PARAMETER;
 
-    if (!is_current_process( process ))
+    if (!is_current_process( process, PROCESS_VM_OPERATION ))
     {
         ERR("Unsupported on other process\n");
         return STATUS_ACCESS_DENIED;
@@ -1419,7 +1420,7 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HAN
 
     TRACE("%p %p %08lx %x\n", process, addr, size, type );
 
-    if (!is_current_process( process ))
+    if (!is_current_process( process, PROCESS_VM_OPERATION ))
     {
         ERR("Unsupported on other process\n");
         return STATUS_ACCESS_DENIED;
@@ -1497,7 +1498,7 @@ NTSTATUS WINAPI NtProtectVirtualMemory( 
 
     TRACE("%p %p %08lx %08x\n", process, addr, size, new_prot );
 
-    if (!is_current_process( process ))
+    if (!is_current_process( process, PROCESS_VM_OPERATION ))
     {
         ERR("Unsupported on other process\n");
         return STATUS_ACCESS_DENIED;
@@ -1581,7 +1582,7 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HA
     if (ADDRESS_SPACE_LIMIT && addr >= ADDRESS_SPACE_LIMIT)
         return STATUS_WORKING_SET_LIMIT_RANGE;
 
-    if (!is_current_process( process ))
+    if (!is_current_process( process, PROCESS_QUERY_INFORMATION ))
     {
         ERR("Unsupported on other process\n");
         return STATUS_ACCESS_DENIED;
@@ -1666,7 +1667,7 @@ NTSTATUS WINAPI NtQueryVirtualMemory( HA
  */
 NTSTATUS WINAPI NtLockVirtualMemory( HANDLE process, PVOID *addr, SIZE_T *size, ULONG unknown )
 {
-    if (!is_current_process( process ))
+    if (!is_current_process( process, PROCESS_VM_OPERATION ))
     {
         ERR("Unsupported on other process\n");
         return STATUS_ACCESS_DENIED;
@@ -1681,7 +1682,7 @@ NTSTATUS WINAPI NtLockVirtualMemory( HAN
  */
 NTSTATUS WINAPI NtUnlockVirtualMemory( HANDLE process, PVOID *addr, SIZE_T *size, ULONG unknown )
 {
-    if (!is_current_process( process ))
+    if (!is_current_process( process, PROCESS_VM_OPERATION ))
     {
         ERR("Unsupported on other process\n");
         return STATUS_ACCESS_DENIED;
@@ -1784,7 +1785,7 @@ NTSTATUS WINAPI NtMapViewOfSection( HAND
     TRACE("handle=%p process=%p addr=%p off=%x%08x size=%lx access=%x\n",
           handle, process, *addr_ptr, offset.u.HighPart, offset.u.LowPart, size, protect );
 
-    if (!is_current_process( process ))
+    if (!is_current_process( process, PROCESS_VM_OPERATION ))
     {
         ERR("Unsupported on other process\n");
         return STATUS_ACCESS_DENIED;
@@ -1933,7 +1934,7 @@ NTSTATUS WINAPI NtUnmapViewOfSection( HA
     NTSTATUS status = STATUS_INVALID_PARAMETER;
     void *base = ROUND_ADDR( addr, page_mask );
 
-    if (!is_current_process( process ))
+    if (!is_current_process( process, PROCESS_VM_OPERATION ))
     {
         ERR("Unsupported on other process\n");
         return STATUS_ACCESS_DENIED;
@@ -1960,7 +1961,7 @@ NTSTATUS WINAPI NtFlushVirtualMemory( HA
     NTSTATUS status = STATUS_SUCCESS;
     void *addr = ROUND_ADDR( *addr_ptr, page_mask );
 
-    if (!is_current_process( process ))
+    if (!is_current_process( process, PROCESS_VM_OPERATION ))
     {
         ERR("Unsupported on other process\n");
         return STATUS_ACCESS_DENIED;
diff -up a/include/winnt.h b/include/winnt.h
--- a/include/winnt.h	2006-11-03 21:34:19.000000000 +0800
+++ b/include/winnt.h	2006-11-06 19:24:53.000000000 +0800
@@ -3826,6 +3826,7 @@ typedef enum tagSID_NAME_USE {
 #define PROCESS_SET_QUOTA          0x0100
 #define PROCESS_SET_INFORMATION    0x0200
 #define PROCESS_QUERY_INFORMATION  0x0400
+#define PROCESS_SUSPEND_RESUME     0x0800
 #define PROCESS_ALL_ACCESS         (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0xfff)
 
 #define THREAD_TERMINATE           0x0001
diff -up a/server/process.c b/server/process.c
--- a/server/process.c	2006-10-11 12:34:29.000000000 +0900
+++ b/server/process.c	2006-11-06 21:50:01.000000000 +0800
@@ -986,7 +986,7 @@ DECL_HANDLER(get_process_info)
 {
     struct process *process;
 
-    if ((process = get_process_from_handle( req->handle, PROCESS_QUERY_INFORMATION )))
+    if ((process = get_process_from_handle( req->handle, req->access )))
     {
         reply->pid              = get_process_id( process );
         reply->ppid             = process->parent ? get_process_id( process->parent ) : 0;
diff -up a/server/protocol.def b/server/protocol.def
--- a/server/protocol.def	2006-11-06 18:35:52.000000000 +0800
+++ b/server/protocol.def	2006-11-06 21:57:22.000000000 +0800
@@ -335,6 +335,7 @@ struct token_groups
 /* Retrieve information about a process */
 @REQ(get_process_info)
     obj_handle_t handle;           /* process handle */
+    unsigned int access;           /* wanted access rights */
 @REPLY
     process_id_t pid;              /* server process id */
     process_id_t ppid;             /* server process id of parent */





More information about the wine-patches mailing list