Dmitry Timoshkov : kernel32: Add support for foreign process handles in GetProcessVersion.

Alexandre Julliard julliard at winehq.org
Thu Oct 16 06:07:04 CDT 2008


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

Author: Dmitry Timoshkov <dmitry at codeweavers.com>
Date:   Wed Oct 15 23:44:54 2008 +0900

kernel32: Add support for foreign process handles in GetProcessVersion.

---

 dlls/kernel32/process.c       |   52 ++++++++++++++++++++++++++++++++++------
 dlls/kernel32/tests/process.c |   42 ++++++++++++++++++++++++++++++++-
 2 files changed, 85 insertions(+), 9 deletions(-)

diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index 1d68462..72d829b 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -2860,19 +2860,55 @@ BOOL WINAPI GetProcessAffinityMask( HANDLE hProcess,
 /***********************************************************************
  *           GetProcessVersion    (KERNEL32.@)
  */
-DWORD WINAPI GetProcessVersion( DWORD processid )
+DWORD WINAPI GetProcessVersion( DWORD pid )
 {
-    IMAGE_NT_HEADERS *nt;
+    HANDLE process;
+    NTSTATUS status;
+    PROCESS_BASIC_INFORMATION pbi;
+    SIZE_T count;
+    PEB peb;
+    IMAGE_DOS_HEADER dos;
+    IMAGE_NT_HEADERS nt;
+    DWORD ver = 0;
 
-    if (processid && processid != GetCurrentProcessId())
+    if (!pid || pid == GetCurrentProcessId())
     {
-        FIXME("should use ReadProcessMemory\n");
+        IMAGE_NT_HEADERS *nt;
+
+        if ((nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress )))
+            return ((nt->OptionalHeader.MajorSubsystemVersion << 16) |
+                    nt->OptionalHeader.MinorSubsystemVersion);
         return 0;
     }
-    if ((nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress )))
-        return ((nt->OptionalHeader.MajorSubsystemVersion << 16) |
-                nt->OptionalHeader.MinorSubsystemVersion);
-    return 0;
+
+    process = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, pid);
+    if (!process) return 0;
+
+    status = NtQueryInformationProcess(process, ProcessBasicInformation, &pbi, sizeof(pbi), NULL);
+    if (status) goto err;
+
+    status = NtReadVirtualMemory(process, pbi.PebBaseAddress, &peb, sizeof(peb), &count);
+    if (status || count != sizeof(peb)) goto err;
+
+    memset(&dos, 0, sizeof(dos));
+    status = NtReadVirtualMemory(process, peb.ImageBaseAddress, &dos, sizeof(dos), &count);
+    if (status || count != sizeof(dos)) goto err;
+    if (dos.e_magic != IMAGE_DOS_SIGNATURE) goto err;
+
+    memset(&nt, 0, sizeof(nt));
+    status = NtReadVirtualMemory(process, (char *)peb.ImageBaseAddress + dos.e_lfanew, &nt, sizeof(nt), &count);
+    if (status || count != sizeof(nt)) goto err;
+    if (nt.Signature != IMAGE_NT_SIGNATURE) goto err;
+
+    ver = MAKELONG(nt.OptionalHeader.MinorSubsystemVersion, nt.OptionalHeader.MajorSubsystemVersion);
+
+err:
+    CloseHandle(process);
+
+    if (status != STATUS_SUCCESS)
+        SetLastError(RtlNtStatusToDosError(status));
+
+    return ver;
 }
 
 
diff --git a/dlls/kernel32/tests/process.c b/dlls/kernel32/tests/process.c
index 321053f..f7ca2f8 100644
--- a/dlls/kernel32/tests/process.c
+++ b/dlls/kernel32/tests/process.c
@@ -24,12 +24,16 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-#include "wine/test.h"
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
 #include "windef.h"
 #include "winbase.h"
 #include "winuser.h"
 #include "wincon.h"
 #include "winnls.h"
+#include "winternl.h"
+
+#include "wine/test.h"
 
 static HINSTANCE hkernel32;
 static LPVOID (WINAPI *pVirtualAllocEx)(HANDLE, LPVOID, SIZE_T, DWORD, DWORD);
@@ -1419,6 +1423,41 @@ static void test_OpenProcess(void)
     ok(VirtualFree(addr1, 0, MEM_RELEASE), "VirtualFree failed\n");
 }
 
+static void test_GetProcessVersion(void)
+{
+    static char cmdline[] = "winver.exe";
+    PROCESS_INFORMATION pi;
+    STARTUPINFOA si;
+    DWORD ret;
+
+    SetLastError(0xdeadbeef);
+    ret = GetProcessVersion(0);
+    ok(ret, "GetProcessVersion error %u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ret = GetProcessVersion(GetCurrentProcessId());
+    ok(ret, "GetProcessVersion error %u\n", GetLastError());
+
+    memset(&si, 0, sizeof(si));
+    si.cb = sizeof(si);
+    si.dwFlags = STARTF_USESHOWWINDOW;
+    si.wShowWindow = SW_HIDE;
+    ret = CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+    SetLastError(0xdeadbeef);
+    ok(ret, "CreateProcess error %u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ret = GetProcessVersion(pi.dwProcessId);
+    ok(ret, "GetProcessVersion error %u\n", GetLastError());
+
+    SetLastError(0xdeadbeef);
+    ret = TerminateProcess(pi.hProcess, 0);
+    ok(ret, "TerminateProcess error %u\n", GetLastError());
+
+    CloseHandle(pi.hProcess);
+    CloseHandle(pi.hThread);
+}
+
 START_TEST(process)
 {
     int b = init();
@@ -1439,6 +1478,7 @@ START_TEST(process)
     test_Console();
     test_ExitCode();
     test_OpenProcess();
+    test_GetProcessVersion();
     /* things that can be tested:
      *  lookup:         check the way program to be executed is searched
      *  handles:        check the handle inheritance stuff (+sec options)




More information about the wine-cvs mailing list