Module: wine Branch: master Commit: 228c52de57623de52c00142d3eb7765bf489365f URL: http://source.winehq.org/git/wine.git/?a=commit;h=228c52de57623de52c00142d3e...
Author: Dmitry Timoshkov dmitry@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)