kernelbase: Mind OS version in the PE header when reporting OS version.
Signed-off-by: Paul Gofman <pgofman@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
1cddd8d571
commit
03c297b1c1
|
@ -918,13 +918,188 @@ static void test_PackageIdFromFullName(void)
|
|||
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %u.\n", ret);
|
||||
}
|
||||
|
||||
#define TEST_VERSION_WIN7 1
|
||||
#define TEST_VERSION_WIN8 2
|
||||
#define TEST_VERSION_WIN8_1 4
|
||||
#define TEST_VERSION_WIN10 8
|
||||
|
||||
static const struct
|
||||
{
|
||||
unsigned int pe_version_major, pe_version_minor;
|
||||
unsigned int manifest_versions;
|
||||
unsigned int expected_major, expected_minor;
|
||||
}
|
||||
test_pe_os_version_tests[] =
|
||||
{
|
||||
{ 4, 0, 0, 6, 2},
|
||||
{ 4, 0, TEST_VERSION_WIN10, 10, 0},
|
||||
{ 6, 3, TEST_VERSION_WIN8, 6, 2},
|
||||
{10, 0, 0, 10, 0},
|
||||
{ 6, 3, 0, 6, 3},
|
||||
{ 6, 4, 0, 6, 3},
|
||||
{ 9, 0, 0, 6, 3},
|
||||
{11, 0, 0, 10, 0},
|
||||
{10, 0,
|
||||
TEST_VERSION_WIN7 | TEST_VERSION_WIN8 | TEST_VERSION_WIN8_1,
|
||||
6, 3},
|
||||
};
|
||||
|
||||
static void test_pe_os_version_child(unsigned int test)
|
||||
{
|
||||
OSVERSIONINFOEXA info;
|
||||
BOOL ret;
|
||||
|
||||
info.dwOSVersionInfoSize = sizeof(info);
|
||||
ret = GetVersionExA((OSVERSIONINFOA *)&info);
|
||||
ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
|
||||
ok(info.dwMajorVersion == test_pe_os_version_tests[test].expected_major,
|
||||
"Test %u, expected major version %u, got %u.\n", test, test_pe_os_version_tests[test].expected_major,
|
||||
info.dwMajorVersion);
|
||||
ok(info.dwMinorVersion == test_pe_os_version_tests[test].expected_minor,
|
||||
"Test %u, expected minor version %u, got %u.\n", test, test_pe_os_version_tests[test].expected_minor,
|
||||
info.dwMinorVersion);
|
||||
}
|
||||
|
||||
static void test_pe_os_version(void)
|
||||
{
|
||||
static const char manifest_header[] =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
|
||||
"<assembly manifestVersion=\"1.0\" xmlns=\"urn:schemas-microsoft-com:asm.v1\""
|
||||
" xmlns:asmv3=\"urn:schemas-microsoft-com:asm.v3\">\n"
|
||||
"\t<compatibility xmlns=\"urn:schemas-microsoft-com:compatibility.v1\">\n"
|
||||
"\t\t<application>\n";
|
||||
static const char manifest_footer[] =
|
||||
"\t\t</application>\n"
|
||||
"\t</compatibility>\n"
|
||||
"</assembly>\n";
|
||||
static const char *version_guids[] =
|
||||
{
|
||||
"{35138b9a-5d96-4fbd-8e2d-a2440225f93a}",
|
||||
"{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}",
|
||||
"{1f676c76-80e1-4239-95bb-83d0f6d0da78}",
|
||||
"{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}",
|
||||
};
|
||||
LONG hdr_offset, offset_major, offset_minor;
|
||||
char str[MAX_PATH], tmp_exe_name[9];
|
||||
RTL_OSVERSIONINFOEXW rtlinfo;
|
||||
STARTUPINFOA si = { 0 };
|
||||
PROCESS_INFORMATION pi;
|
||||
DWORD result, code;
|
||||
unsigned int i, j;
|
||||
HANDLE file;
|
||||
char **argv;
|
||||
DWORD size;
|
||||
BOOL ret;
|
||||
|
||||
winetest_get_mainargs( &argv );
|
||||
|
||||
if (!pRtlGetVersion)
|
||||
{
|
||||
win_skip("RtlGetVersion is not supported, skipping tests.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
rtlinfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
|
||||
ok(!pRtlGetVersion(&rtlinfo), "RtlGetVersion failed.\n");
|
||||
if (rtlinfo.dwMajorVersion < 10)
|
||||
{
|
||||
skip("Too old Windows version %u.%u, skipping tests.\n", rtlinfo.dwMajorVersion, rtlinfo.dwMinorVersion);
|
||||
return;
|
||||
}
|
||||
|
||||
file = CreateFileA(argv[0], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
ok(file != INVALID_HANDLE_VALUE, "CreateFile failed, GetLastError() %u.\n", GetLastError());
|
||||
SetFilePointer(file, 0x3c, NULL, FILE_BEGIN);
|
||||
ReadFile(file, &hdr_offset, sizeof(hdr_offset), &size, NULL);
|
||||
CloseHandle(file);
|
||||
|
||||
offset_major = hdr_offset + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader)
|
||||
+ FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, MajorOperatingSystemVersion);
|
||||
offset_minor = hdr_offset + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader)
|
||||
+ FIELD_OFFSET(IMAGE_OPTIONAL_HEADER, MinorOperatingSystemVersion);
|
||||
|
||||
si.cb = sizeof(si);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(test_pe_os_version_tests); ++i)
|
||||
{
|
||||
sprintf(tmp_exe_name, "tmp%u.exe", i);
|
||||
ret = CopyFileA(argv[0], tmp_exe_name, FALSE);
|
||||
ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
|
||||
|
||||
file = CreateFileA(tmp_exe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
ok(file != INVALID_HANDLE_VALUE, "CreateFile failed, GetLastError() %u.\n", GetLastError());
|
||||
|
||||
SetFilePointer(file, offset_major, NULL, FILE_BEGIN);
|
||||
WriteFile(file, &test_pe_os_version_tests[i].pe_version_major,
|
||||
sizeof(test_pe_os_version_tests[i].pe_version_major), &size, NULL);
|
||||
SetFilePointer(file, offset_minor, NULL, FILE_BEGIN);
|
||||
WriteFile(file, &test_pe_os_version_tests[i].pe_version_minor,
|
||||
sizeof(test_pe_os_version_tests[i].pe_version_minor), &size, NULL);
|
||||
|
||||
CloseHandle(file);
|
||||
|
||||
sprintf(str, "%s.manifest", tmp_exe_name);
|
||||
file = CreateFileA(str, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
ok(file != INVALID_HANDLE_VALUE, "CreateFile failed, GetLastError() %u.\n", GetLastError());
|
||||
|
||||
WriteFile(file, manifest_header, strlen(manifest_header), &size, NULL);
|
||||
for (j = 0; j < ARRAY_SIZE(version_guids); ++j)
|
||||
{
|
||||
if (test_pe_os_version_tests[i].manifest_versions & (1 << j))
|
||||
{
|
||||
sprintf(str, "\t\t\t<supportedOS Id=\"%s\"/>\n", version_guids[j]);
|
||||
WriteFile(file, str, strlen(str), &size, NULL);
|
||||
}
|
||||
}
|
||||
WriteFile(file, manifest_footer, strlen(manifest_footer), &size, NULL);
|
||||
|
||||
CloseHandle(file);
|
||||
|
||||
sprintf(str, "%s version pe_os_version %u", tmp_exe_name, i);
|
||||
|
||||
ret = CreateProcessA(NULL, str, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
|
||||
ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
|
||||
CloseHandle(pi.hThread);
|
||||
result = WaitForSingleObject(pi.hProcess, 10000);
|
||||
ok(result == WAIT_OBJECT_0, "Got unexpected result %#x.\n", result);
|
||||
|
||||
ret = GetExitCodeProcess(pi.hProcess, &code);
|
||||
ok(ret, "Got unexpected ret %#x, GetLastError() %u.\n", ret, GetLastError());
|
||||
ok(!code, "Test %u failed.\n", i);
|
||||
|
||||
CloseHandle(pi.hProcess);
|
||||
|
||||
DeleteFileA(tmp_exe_name);
|
||||
sprintf(str, "%s.manifest", tmp_exe_name);
|
||||
DeleteFileA(str);
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(version)
|
||||
{
|
||||
char **argv;
|
||||
int argc;
|
||||
|
||||
argc = winetest_get_mainargs( &argv );
|
||||
|
||||
init_function_pointers();
|
||||
|
||||
if (argc >= 4)
|
||||
{
|
||||
if (!strcmp(argv[2], "pe_os_version"))
|
||||
{
|
||||
unsigned int test;
|
||||
|
||||
test = atoi(argv[3]);
|
||||
test_pe_os_version_child(test);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
test_GetProductInfo();
|
||||
test_GetVersionEx();
|
||||
test_VerifyVersionInfo();
|
||||
test_pe_os_version();
|
||||
test_GetSystemFirmwareTable();
|
||||
test_PackageIdFromFullName();
|
||||
}
|
||||
|
|
|
@ -127,10 +127,17 @@ typedef struct
|
|||
|
||||
|
||||
/***********************************************************************
|
||||
* Win8 info, reported if app doesn't provide compat GUID in manifest.
|
||||
* Win8 info, reported if the app doesn't provide compat GUID in the manifest and
|
||||
* doesn't have higher OS version in PE header.
|
||||
*/
|
||||
static const struct version_info windows8_version_info = { 6, 2, 0x23f0 };
|
||||
|
||||
/***********************************************************************
|
||||
* Win8.1 info, reported if the app doesn't provide compat GUID in the manifest and
|
||||
* OS version in PE header is 8.1 or higher but below 10.
|
||||
*/
|
||||
static const struct version_info windows8_1_version_info = { 6, 3, 0x2580 };
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Windows versions that need compatibility GUID specified in manifest
|
||||
|
@ -161,7 +168,8 @@ static const struct
|
|||
* Initialize the current_version variable.
|
||||
*
|
||||
* For compatibility, Windows 8.1 and later report Win8 version unless the app
|
||||
* has a manifest that confirms its compatibility with newer versions of Windows.
|
||||
* has a manifest or higher OS version in the PE optional header
|
||||
* that confirms its compatibility with newer versions of Windows.
|
||||
*
|
||||
*/
|
||||
static RTL_OSVERSIONINFOEXW current_version;
|
||||
|
@ -173,7 +181,9 @@ static BOOL CALLBACK init_current_version(PINIT_ONCE init_once, PVOID parameter,
|
|||
DWORD ElementCount;
|
||||
COMPATIBILITY_CONTEXT_ELEMENT Elements[1];
|
||||
} *acci;
|
||||
BOOL have_os_compat_elements = FALSE;
|
||||
const struct version_info *ver;
|
||||
IMAGE_NT_HEADERS *nt;
|
||||
SIZE_T req;
|
||||
int idx;
|
||||
|
||||
|
@ -209,8 +219,12 @@ static BOOL CALLBACK init_current_version(PINIT_ONCE init_once, PVOID parameter,
|
|||
|
||||
for (i = 0; i < acci->ElementCount; i++)
|
||||
{
|
||||
if (acci->Elements[i].Type == ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS &&
|
||||
IsEqualGUID(&acci->Elements[i].Id, &version_data[idx].guid))
|
||||
if (acci->Elements[i].Type != ACTCTX_COMPATIBILITY_ELEMENT_TYPE_OS)
|
||||
continue;
|
||||
|
||||
have_os_compat_elements = TRUE;
|
||||
|
||||
if (IsEqualGUID(&acci->Elements[i].Id, &version_data[idx].guid))
|
||||
{
|
||||
ver = &version_data[idx].info;
|
||||
|
||||
|
@ -227,6 +241,18 @@ static BOOL CALLBACK init_current_version(PINIT_ONCE init_once, PVOID parameter,
|
|||
HeapFree(GetProcessHeap(), 0, acci);
|
||||
|
||||
done:
|
||||
if (!have_os_compat_elements && current_version.dwMajorVersion >= 10
|
||||
&& (nt = RtlImageNtHeader(NtCurrentTeb()->Peb->ImageBaseAddress))
|
||||
&& (nt->OptionalHeader.MajorOperatingSystemVersion > 6
|
||||
|| (nt->OptionalHeader.MajorOperatingSystemVersion == 6
|
||||
&& nt->OptionalHeader.MinorOperatingSystemVersion >= 3)))
|
||||
{
|
||||
if (current_version.dwMajorVersion > 10)
|
||||
FIXME("Unsupported current_version.dwMajorVersion %u.\n", current_version.dwMajorVersion);
|
||||
|
||||
ver = nt->OptionalHeader.MajorOperatingSystemVersion >= 10 ? NULL : &windows8_1_version_info;
|
||||
}
|
||||
|
||||
if (ver)
|
||||
{
|
||||
current_version.dwMajorVersion = ver->major;
|
||||
|
|
Loading…
Reference in New Issue