kernel32: Add support for foreign process handles in GetProcessVersion.
Dmitry Timoshkov
dmitry at codeweavers.com
Wed Oct 15 09:44:54 CDT 2008
This patch should fix the problem reported in the bug 15608.
---
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)
--
1.6.0.2
More information about the wine-patches
mailing list