1106 lines
39 KiB
C
1106 lines
39 KiB
C
/*
|
|
* Unit test suite for version functions
|
|
*
|
|
* Copyright 2006 Robert Shearman
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include "wine/test.h"
|
|
#include "winbase.h"
|
|
#include "winternl.h"
|
|
#include "appmodel.h"
|
|
|
|
static BOOL (WINAPI * pGetProductInfo)(DWORD, DWORD, DWORD, DWORD, DWORD *);
|
|
static UINT (WINAPI * pGetSystemFirmwareTable)(DWORD, DWORD, void *, DWORD);
|
|
static LONG (WINAPI * pPackageIdFromFullName)(const WCHAR *, UINT32, UINT32 *, BYTE *);
|
|
static NTSTATUS (WINAPI * pNtQuerySystemInformation)(SYSTEM_INFORMATION_CLASS, void *, ULONG, ULONG *);
|
|
static NTSTATUS (WINAPI * pRtlGetVersion)(RTL_OSVERSIONINFOEXW *);
|
|
|
|
#define GET_PROC(func) \
|
|
p##func = (void *)GetProcAddress(hmod, #func);
|
|
|
|
/* Firmware table providers */
|
|
#define ACPI 0x41435049
|
|
#define FIRM 0x4649524D
|
|
#define RSMB 0x52534D42
|
|
|
|
static void init_function_pointers(void)
|
|
{
|
|
HMODULE hmod;
|
|
|
|
hmod = GetModuleHandleA("kernel32.dll");
|
|
|
|
GET_PROC(GetProductInfo);
|
|
GET_PROC(GetSystemFirmwareTable);
|
|
GET_PROC(PackageIdFromFullName);
|
|
|
|
hmod = GetModuleHandleA("ntdll.dll");
|
|
|
|
GET_PROC(NtQuerySystemInformation);
|
|
GET_PROC(RtlGetVersion);
|
|
}
|
|
|
|
static void test_GetProductInfo(void)
|
|
{
|
|
DWORD product;
|
|
DWORD res;
|
|
DWORD table[] = {9,8,7,6,
|
|
7,0,0,0,
|
|
6,2,0,0,
|
|
6,1,2,0,
|
|
6,1,1,0,
|
|
6,1,0,2,
|
|
6,1,0,0,
|
|
6,0,3,0,
|
|
6,0,2,0,
|
|
6,0,1,5,
|
|
6,0,1,0,
|
|
6,0,0,0,
|
|
5,3,0,0,
|
|
5,2,0,0,
|
|
5,1,0,0,
|
|
5,0,0,0,
|
|
0};
|
|
|
|
DWORD *entry = table;
|
|
|
|
if (!pGetProductInfo)
|
|
{
|
|
/* Not present before Vista */
|
|
win_skip("GetProductInfo() not available\n");
|
|
return;
|
|
}
|
|
|
|
while (*entry)
|
|
{
|
|
/* SetLastError() / GetLastError(): value is untouched */
|
|
product = 0xdeadbeef;
|
|
SetLastError(0xdeadbeef);
|
|
res = pGetProductInfo(entry[0], entry[1], entry[2], entry[3], &product);
|
|
|
|
if (entry[0] >= 6)
|
|
ok(res && (product > PRODUCT_UNDEFINED) && (product <= PRODUCT_ENTERPRISE_S_N_EVALUATION),
|
|
"got %ld and 0x%lx (expected TRUE and a valid PRODUCT_* value)\n", res, product);
|
|
else
|
|
ok(!res && !product && (GetLastError() == 0xdeadbeef),
|
|
"got %ld and 0x%lx with 0x%lx (expected FALSE and PRODUCT_UNDEFINED with LastError untouched)\n",
|
|
res, product, GetLastError());
|
|
|
|
entry+= 4;
|
|
}
|
|
|
|
/* NULL pointer is not a problem */
|
|
SetLastError(0xdeadbeef);
|
|
res = pGetProductInfo(6, 1, 0, 0, NULL);
|
|
ok( (!res) && (GetLastError() == 0xdeadbeef),
|
|
"got %ld with 0x%lx (expected FALSE with LastError untouched\n", res, GetLastError());
|
|
}
|
|
|
|
static void test_GetVersionEx(void)
|
|
{
|
|
OSVERSIONINFOA infoA;
|
|
OSVERSIONINFOEXA infoExA;
|
|
BOOL ret;
|
|
|
|
if (0)
|
|
{
|
|
/* Silently crashes on XP */
|
|
GetVersionExA(NULL);
|
|
}
|
|
|
|
SetLastError(0xdeadbeef);
|
|
memset(&infoA,0,sizeof infoA);
|
|
ret = GetVersionExA(&infoA);
|
|
ok(!ret, "Expected GetVersionExA to fail\n");
|
|
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
|
|
GetLastError() == 0xdeadbeef /* Win9x */,
|
|
"Expected ERROR_INSUFFICIENT_BUFFER or 0xdeadbeef (Win9x), got %ld\n",
|
|
GetLastError());
|
|
|
|
SetLastError(0xdeadbeef);
|
|
infoA.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA) / 2;
|
|
ret = GetVersionExA(&infoA);
|
|
ok(!ret, "Expected GetVersionExA to fail\n");
|
|
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
|
|
GetLastError() == 0xdeadbeef /* Win9x */,
|
|
"Expected ERROR_INSUFFICIENT_BUFFER or 0xdeadbeef (Win9x), got %ld\n",
|
|
GetLastError());
|
|
|
|
SetLastError(0xdeadbeef);
|
|
infoA.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA) * 2;
|
|
ret = GetVersionExA(&infoA);
|
|
ok(!ret, "Expected GetVersionExA to fail\n");
|
|
ok(GetLastError() == ERROR_INSUFFICIENT_BUFFER ||
|
|
GetLastError() == 0xdeadbeef /* Win9x */,
|
|
"Expected ERROR_INSUFFICIENT_BUFFER or 0xdeadbeef (Win9x), got %ld\n",
|
|
GetLastError());
|
|
|
|
SetLastError(0xdeadbeef);
|
|
infoA.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA);
|
|
ret = GetVersionExA(&infoA);
|
|
ok(ret, "Expected GetVersionExA to succeed\n");
|
|
ok(GetLastError() == 0xdeadbeef,
|
|
"Expected 0xdeadbeef, got %ld\n", GetLastError());
|
|
|
|
SetLastError(0xdeadbeef);
|
|
infoExA.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
|
|
ret = GetVersionExA((OSVERSIONINFOA *)&infoExA);
|
|
ok(ret, "GetVersionExA failed.\n");
|
|
|
|
if (!infoExA.wServicePackMajor && !infoExA.wServicePackMinor)
|
|
ok(!infoExA.szCSDVersion[0], "got '%s'\n", infoExA.szCSDVersion);
|
|
}
|
|
|
|
static void test_VerifyVersionInfo(void)
|
|
{
|
|
enum srcversion_mode
|
|
{
|
|
SRCVERSION_ZERO = 0,
|
|
SRCVERSION_CURRENT = 1,
|
|
SRCVERSION_INC_MINOR = 2,
|
|
SRCVERSION_INC_SP_MINOR = 3,
|
|
SRCVERSION_INC_SP_MAJOR = 4,
|
|
SRCVERSION_DEC_SP_MAJOR = 5,
|
|
SRCVERSION_DEC_MAJOR = 6,
|
|
SRCVERSION_INC_BUILD = 7,
|
|
SRCVERSION_REQUIRES_SP = 0x1000,
|
|
};
|
|
|
|
struct verify_version_test
|
|
{
|
|
DWORD verifymask; /* Type mask for VerifyVersionInfo() */
|
|
DWORD srcinfo; /* The way current version info is modified. */
|
|
DWORD err; /* Error code on failure, 0 on success. */
|
|
|
|
DWORD typemask1;
|
|
DWORD condition1;
|
|
DWORD typemask2;
|
|
DWORD condition2;
|
|
DWORD typemask3;
|
|
DWORD condition3;
|
|
DWORD typemask4;
|
|
DWORD condition4;
|
|
} verify_version_tests[] =
|
|
{
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_MINOR,
|
|
0,
|
|
|
|
VER_MAJORVERSION, VER_EQUAL,
|
|
VER_MINORVERSION, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_MINOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL,
|
|
VER_MINORVERSION, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_CURRENT,
|
|
0,
|
|
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL,
|
|
VER_MINORVERSION, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_CURRENT,
|
|
0,
|
|
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL,
|
|
VER_MINORVERSION, VER_AND,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_MINOR,
|
|
0,
|
|
|
|
VER_MAJORVERSION, VER_LESS_EQUAL,
|
|
VER_MINORVERSION, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_MINOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MAJORVERSION, VER_AND,
|
|
VER_MINORVERSION, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_MINOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MAJORVERSION, VER_OR,
|
|
VER_MINORVERSION, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MINOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MINORVERSION, VER_EQUAL,
|
|
VER_SERVICEPACKMINOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MINOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MAJORVERSION, VER_EQUAL,
|
|
VER_SERVICEPACKMINOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MAJORVERSION, VER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_EQUAL,
|
|
},
|
|
{
|
|
VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MINOR,
|
|
0,
|
|
|
|
VER_SERVICEPACKMAJOR, VER_EQUAL,
|
|
VER_SERVICEPACKMINOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MINOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_SERVICEPACKMAJOR, VER_EQUAL,
|
|
VER_SERVICEPACKMINOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MINOR,
|
|
0,
|
|
|
|
VER_MINORVERSION, VER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_EQUAL,
|
|
VER_SERVICEPACKMINOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MINOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MINORVERSION, VER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_EQUAL,
|
|
VER_SERVICEPACKMINOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MINOR,
|
|
0,
|
|
|
|
VER_MAJORVERSION, VER_EQUAL,
|
|
VER_MINORVERSION, VER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_EQUAL,
|
|
VER_SERVICEPACKMINOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MINOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MAJORVERSION, VER_EQUAL,
|
|
VER_MINORVERSION, VER_GREATER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_EQUAL,
|
|
VER_SERVICEPACKMINOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
0,
|
|
|
|
VER_MAJORVERSION, VER_LESS_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_GREATER,
|
|
},
|
|
{
|
|
VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MAJORVERSION, VER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MINORVERSION, VER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
0,
|
|
|
|
VER_MAJORVERSION, VER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MAJORVERSION, VER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
0,
|
|
|
|
VER_MAJORVERSION, VER_EQUAL,
|
|
VER_MINORVERSION, VER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_DEC_MAJOR,
|
|
0,
|
|
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_CURRENT,
|
|
0,
|
|
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL,
|
|
VER_MINORVERSION, VER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_LESS,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL,
|
|
VER_MINORVERSION, VER_GREATER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_LESS_EQUAL,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_AND,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION,
|
|
SRCVERSION_ZERO,
|
|
0,
|
|
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER,
|
|
SRCVERSION_ZERO,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL,
|
|
},
|
|
{
|
|
VER_SUITENAME,
|
|
SRCVERSION_ZERO,
|
|
0,
|
|
|
|
VER_SUITENAME, VER_AND,
|
|
},
|
|
{
|
|
VER_SUITENAME,
|
|
SRCVERSION_ZERO,
|
|
0,
|
|
|
|
VER_SUITENAME, VER_OR,
|
|
},
|
|
{
|
|
VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MINOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MINORVERSION, VER_GREATER_EQUAL,
|
|
},
|
|
{
|
|
VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
0,
|
|
|
|
VER_MINORVERSION, VER_LESS,
|
|
},
|
|
{
|
|
VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
0,
|
|
|
|
VER_MINORVERSION, VER_LESS_EQUAL,
|
|
},
|
|
{
|
|
VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MINORVERSION, VER_EQUAL,
|
|
},
|
|
{
|
|
VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_SP_MAJOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MINORVERSION, VER_GREATER_EQUAL,
|
|
},
|
|
{
|
|
VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_MINOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MINORVERSION, VER_GREATER_EQUAL,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_MINOR,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MINORVERSION, VER_GREATER_EQUAL,
|
|
},
|
|
{
|
|
VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_CURRENT,
|
|
0,
|
|
|
|
VER_MINORVERSION, VER_GREATER_EQUAL,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_BUILD,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MINORVERSION, VER_GREATER_EQUAL,
|
|
},
|
|
{
|
|
VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_INC_BUILD,
|
|
0,
|
|
|
|
VER_MINORVERSION, VER_GREATER_EQUAL,
|
|
},
|
|
{
|
|
VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_DEC_SP_MAJOR | SRCVERSION_REQUIRES_SP,
|
|
0,
|
|
|
|
VER_MINORVERSION, VER_GREATER,
|
|
},
|
|
{
|
|
VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_DEC_SP_MAJOR | SRCVERSION_REQUIRES_SP,
|
|
0,
|
|
|
|
VER_MINORVERSION, VER_GREATER_EQUAL,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_DEC_SP_MAJOR | SRCVERSION_REQUIRES_SP,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_MAJORVERSION, VER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_GREATER,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_DEC_SP_MAJOR | SRCVERSION_REQUIRES_SP,
|
|
0,
|
|
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL,
|
|
VER_MINORVERSION, VER_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_GREATER,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_DEC_SP_MAJOR | SRCVERSION_REQUIRES_SP,
|
|
0,
|
|
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL,
|
|
VER_MINORVERSION, VER_LESS_EQUAL,
|
|
VER_SERVICEPACKMAJOR, VER_GREATER,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_DEC_SP_MAJOR | SRCVERSION_REQUIRES_SP,
|
|
0,
|
|
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL,
|
|
VER_MINORVERSION, VER_AND,
|
|
VER_SERVICEPACKMAJOR, VER_GREATER,
|
|
},
|
|
{
|
|
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
SRCVERSION_DEC_SP_MAJOR | SRCVERSION_REQUIRES_SP,
|
|
ERROR_OLD_WIN_VERSION,
|
|
|
|
VER_SERVICEPACKMAJOR, VER_GREATER,
|
|
VER_SERVICEPACKMINOR, VER_EQUAL,
|
|
},
|
|
};
|
|
|
|
OSVERSIONINFOEXA info;
|
|
DWORD servicepack;
|
|
unsigned int i;
|
|
BOOL ret;
|
|
|
|
/* Before we start doing some tests we should check what the version of
|
|
* the ServicePack is. Tests on a box with no ServicePack will fail otherwise.
|
|
*/
|
|
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
|
|
GetVersionExA((OSVERSIONINFOA *)&info);
|
|
servicepack = info.wServicePackMajor;
|
|
if (servicepack == 0)
|
|
skip("There is no ServicePack on this system. Some tests will be skipped.\n");
|
|
|
|
/* Win8.1+ returns Win8 version in GetVersionEx when there's no app manifest targeting 8.1 */
|
|
if (info.dwMajorVersion == 6 && info.dwMinorVersion == 2)
|
|
{
|
|
RTL_OSVERSIONINFOEXW rtlinfo;
|
|
rtlinfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
|
|
ok(!pRtlGetVersion(&rtlinfo), "RtlGetVersion failed\n");
|
|
|
|
if (rtlinfo.dwMajorVersion != 6 || rtlinfo.dwMinorVersion != 2)
|
|
{
|
|
skip("GetVersionEx and VerifyVersionInfo are faking values\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_SIZE(verify_version_tests); i++)
|
|
{
|
|
struct verify_version_test *test = &verify_version_tests[i];
|
|
DWORD srcinfo = test->srcinfo;
|
|
ULONGLONG mask;
|
|
|
|
if (servicepack == 0 && srcinfo & SRCVERSION_REQUIRES_SP)
|
|
continue;
|
|
srcinfo &= ~SRCVERSION_REQUIRES_SP;
|
|
|
|
info.dwOSVersionInfoSize = sizeof(info);
|
|
GetVersionExA((OSVERSIONINFOA *)&info);
|
|
|
|
switch (srcinfo)
|
|
{
|
|
case SRCVERSION_ZERO:
|
|
memset(&info, 0, sizeof(info));
|
|
break;
|
|
case SRCVERSION_INC_MINOR:
|
|
info.dwMinorVersion++;
|
|
break;
|
|
case SRCVERSION_INC_SP_MINOR:
|
|
info.wServicePackMinor++;
|
|
break;
|
|
case SRCVERSION_INC_SP_MAJOR:
|
|
info.wServicePackMajor++;
|
|
break;
|
|
case SRCVERSION_DEC_SP_MAJOR:
|
|
info.wServicePackMajor--;
|
|
break;
|
|
case SRCVERSION_DEC_MAJOR:
|
|
info.dwMajorVersion--;
|
|
break;
|
|
case SRCVERSION_INC_BUILD:
|
|
info.dwBuildNumber++;
|
|
break;
|
|
default:
|
|
;
|
|
}
|
|
|
|
mask = VerSetConditionMask(0, test->typemask1, test->condition1);
|
|
if (test->typemask2)
|
|
mask = VerSetConditionMask(mask, test->typemask2, test->condition2);
|
|
if (test->typemask3)
|
|
mask = VerSetConditionMask(mask, test->typemask3, test->condition3);
|
|
if (test->typemask4)
|
|
mask = VerSetConditionMask(mask, test->typemask4, test->condition4);
|
|
|
|
SetLastError(0xdeadbeef);
|
|
ret = VerifyVersionInfoA(&info, test->verifymask, mask);
|
|
ok(test->err ? !ret : ret, "%u: unexpected return value %d.\n", i, ret);
|
|
if (!ret)
|
|
ok(GetLastError() == test->err, "%u: unexpected error code %ld, expected %ld.\n", i, GetLastError(), test->err);
|
|
}
|
|
|
|
/* test handling of version numbers */
|
|
/* v3.10 is always less than v4.x even
|
|
* if the minor version is tested */
|
|
info.dwMajorVersion = 3;
|
|
info.dwMinorVersion = 10;
|
|
ret = VerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
VerSetConditionMask(VerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL),
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL));
|
|
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
|
|
|
|
info.dwMinorVersion = 0;
|
|
info.wServicePackMajor = 10;
|
|
ret = VerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
VerSetConditionMask(VerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL),
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL));
|
|
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
|
|
|
|
info.wServicePackMajor = 0;
|
|
info.wServicePackMinor = 10;
|
|
ret = VerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
VerSetConditionMask(VerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL),
|
|
VER_MAJORVERSION, VER_GREATER_EQUAL));
|
|
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
|
|
|
|
/* test bad dwOSVersionInfoSize */
|
|
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
|
|
GetVersionExA((OSVERSIONINFOA *)&info);
|
|
info.dwOSVersionInfoSize = 0;
|
|
ret = VerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR,
|
|
VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL));
|
|
ok(ret, "VerifyVersionInfoA failed with error %ld\n", GetLastError());
|
|
}
|
|
|
|
static void test_GetSystemFirmwareTable(void)
|
|
{
|
|
static const ULONG min_sfti_len = FIELD_OFFSET(SYSTEM_FIRMWARE_TABLE_INFORMATION, TableBuffer);
|
|
ULONG expected_len;
|
|
UINT len;
|
|
SYSTEM_FIRMWARE_TABLE_INFORMATION *sfti;
|
|
UCHAR *smbios_table;
|
|
|
|
if (!pGetSystemFirmwareTable)
|
|
{
|
|
win_skip("GetSystemFirmwareTable not available\n");
|
|
return;
|
|
}
|
|
|
|
sfti = HeapAlloc(GetProcessHeap(), 0, sizeof(*sfti));
|
|
ok(!!sfti, "Failed to allocate memory\n");
|
|
sfti->ProviderSignature = RSMB;
|
|
sfti->Action = SystemFirmwareTable_Get;
|
|
sfti->TableID = 0;
|
|
pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, min_sfti_len, &expected_len);
|
|
if (expected_len == 0) /* xp, 2003 */
|
|
{
|
|
win_skip("SystemFirmwareTableInformation is not available\n");
|
|
HeapFree(GetProcessHeap(), 0, sfti);
|
|
return;
|
|
}
|
|
sfti = HeapReAlloc(GetProcessHeap(), 0, sfti, expected_len);
|
|
ok(!!sfti, "Failed to allocate memory\n");
|
|
pNtQuerySystemInformation(SystemFirmwareTableInformation, sfti, expected_len, &expected_len);
|
|
|
|
expected_len -= min_sfti_len;
|
|
len = pGetSystemFirmwareTable(RSMB, 0, NULL, 0);
|
|
ok(len == expected_len, "Expected length %lu, got %u\n", expected_len, len);
|
|
|
|
smbios_table = HeapAlloc(GetProcessHeap(), 0, expected_len);
|
|
len = pGetSystemFirmwareTable(RSMB, 0, smbios_table, expected_len);
|
|
ok(len == expected_len, "Expected length %lu, got %u\n", expected_len, len);
|
|
ok(len == 0 || !memcmp(smbios_table, sfti->TableBuffer, 6),
|
|
"Expected prologue %02x %02x %02x %02x %02x %02x, got %02x %02x %02x %02x %02x %02x\n",
|
|
sfti->TableBuffer[0], sfti->TableBuffer[1], sfti->TableBuffer[2],
|
|
sfti->TableBuffer[3], sfti->TableBuffer[4], sfti->TableBuffer[5],
|
|
smbios_table[0], smbios_table[1], smbios_table[2],
|
|
smbios_table[3], smbios_table[4], smbios_table[5]);
|
|
|
|
HeapFree(GetProcessHeap(), 0, sfti);
|
|
HeapFree(GetProcessHeap(), 0, smbios_table);
|
|
}
|
|
|
|
static const struct
|
|
{
|
|
UINT32 code;
|
|
const WCHAR *name;
|
|
BOOL broken;
|
|
}
|
|
arch_data[] =
|
|
{
|
|
{PROCESSOR_ARCHITECTURE_INTEL, L"X86"},
|
|
{PROCESSOR_ARCHITECTURE_ARM, L"Arm"},
|
|
{PROCESSOR_ARCHITECTURE_AMD64, L"X64"},
|
|
{PROCESSOR_ARCHITECTURE_NEUTRAL, L"Neutral"},
|
|
{PROCESSOR_ARCHITECTURE_ARM64, L"Arm64", TRUE /* Before Win10. */},
|
|
{PROCESSOR_ARCHITECTURE_UNKNOWN, L"Unknown", TRUE /* Before Win10 1709. */},
|
|
};
|
|
|
|
static const WCHAR *arch_string_from_code(UINT32 arch)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < ARRAY_SIZE(arch_data); ++i)
|
|
if (arch_data[i].code == arch)
|
|
return arch_data[i].name;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static unsigned int get_package_str_size(const WCHAR *str)
|
|
{
|
|
return str ? (lstrlenW(str) + 1) * sizeof(*str) : 0;
|
|
}
|
|
|
|
static unsigned int get_package_id_size(const PACKAGE_ID *id)
|
|
{
|
|
return sizeof(*id) + get_package_str_size(id->name)
|
|
+ get_package_str_size(id->resourceId) + 14 * sizeof(WCHAR);
|
|
}
|
|
|
|
static void packagefullname_from_packageid(WCHAR *buffer, size_t count, const PACKAGE_ID *id)
|
|
{
|
|
swprintf(buffer, count, L"%s_%u.%u.%u.%u_%s_%s_%s", id->name, id->version.Major,
|
|
id->version.Minor, id->version.Build, id->version.Revision,
|
|
arch_string_from_code(id->processorArchitecture), id->resourceId,
|
|
id->publisherId);
|
|
}
|
|
|
|
static void test_PackageIdFromFullName(void)
|
|
{
|
|
static const PACKAGE_ID test_package_id =
|
|
{
|
|
0, PROCESSOR_ARCHITECTURE_INTEL,
|
|
{{.Major = 1, .Minor = 2, .Build = 3, .Revision = 4}},
|
|
(WCHAR *)L"TestPackage", NULL,
|
|
(WCHAR *)L"TestResourceId", (WCHAR *)L"0abcdefghjkme"
|
|
};
|
|
UINT32 size, expected_size;
|
|
PACKAGE_ID test_id;
|
|
WCHAR fullname[512];
|
|
BYTE id_buffer[512];
|
|
unsigned int i;
|
|
PACKAGE_ID *id;
|
|
LONG ret;
|
|
|
|
if (!pPackageIdFromFullName)
|
|
{
|
|
win_skip("PackageIdFromFullName not available.\n");
|
|
return;
|
|
}
|
|
|
|
packagefullname_from_packageid(fullname, ARRAY_SIZE(fullname), &test_package_id);
|
|
|
|
id = (PACKAGE_ID *)id_buffer;
|
|
|
|
memset(id_buffer, 0xcc, sizeof(id_buffer));
|
|
expected_size = get_package_id_size(&test_package_id);
|
|
size = sizeof(id_buffer);
|
|
ret = pPackageIdFromFullName(fullname, 0, &size, id_buffer);
|
|
ok(ret == ERROR_SUCCESS, "Got unexpected ret %lu.\n", ret);
|
|
ok(size == expected_size, "Got unexpected length %u, expected %u.\n", size, expected_size);
|
|
ok(!lstrcmpW(id->name, test_package_id.name), "Got unexpected name %s.\n", debugstr_w(id->name));
|
|
ok(!lstrcmpW(id->resourceId, test_package_id.resourceId), "Got unexpected resourceId %s.\n",
|
|
debugstr_w(id->resourceId));
|
|
ok(!lstrcmpW(id->publisherId, test_package_id.publisherId), "Got unexpected publisherId %s.\n",
|
|
debugstr_w(id->publisherId));
|
|
ok(!id->publisher, "Got unexpected publisher %s.\n", debugstr_w(id->publisher));
|
|
ok(id->processorArchitecture == PROCESSOR_ARCHITECTURE_INTEL, "Got unexpected processorArchitecture %u.\n",
|
|
id->processorArchitecture);
|
|
ok(id->version.Version == 0x0001000200030004, "Got unexpected Version %s.\n",
|
|
wine_dbgstr_longlong(id->version.Version));
|
|
ok((BYTE *)id->name == id_buffer + sizeof(*id), "Got unexpected name %p, buffer %p.\n", id->name, id_buffer);
|
|
ok((BYTE *)id->resourceId == (BYTE *)id->name + (lstrlenW(id->name) + 1) * 2,
|
|
"Got unexpected resourceId %p, buffer %p.\n", id->resourceId, id_buffer);
|
|
ok((BYTE *)id->publisherId == (BYTE *)id->resourceId + (lstrlenW(id->resourceId) + 1) * 2,
|
|
"Got unexpected publisherId %p, buffer %p.\n", id->resourceId, id_buffer);
|
|
|
|
ret = pPackageIdFromFullName(fullname, 0, NULL, id_buffer);
|
|
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %ld.\n", ret);
|
|
|
|
size = sizeof(id_buffer);
|
|
ret = pPackageIdFromFullName(NULL, 0, &size, id_buffer);
|
|
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %ld.\n", ret);
|
|
ok(size == sizeof(id_buffer), "Got unexpected size %u.\n", size);
|
|
|
|
size = sizeof(id_buffer);
|
|
ret = pPackageIdFromFullName(fullname, 0, &size, NULL);
|
|
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %ld.\n", ret);
|
|
ok(size == sizeof(id_buffer), "Got unexpected size %u.\n", size);
|
|
|
|
size = expected_size - 1;
|
|
ret = pPackageIdFromFullName(fullname, 0, &size, NULL);
|
|
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %ld.\n", ret);
|
|
ok(size == expected_size - 1, "Got unexpected size %u.\n", size);
|
|
|
|
size = expected_size - 1;
|
|
ret = pPackageIdFromFullName(fullname, 0, &size, id_buffer);
|
|
ok(ret == ERROR_INSUFFICIENT_BUFFER, "Got unexpected ret %ld.\n", ret);
|
|
ok(size == expected_size, "Got unexpected size %u.\n", size);
|
|
|
|
size = 0;
|
|
ret = pPackageIdFromFullName(fullname, 0, &size, NULL);
|
|
ok(ret == ERROR_INSUFFICIENT_BUFFER, "Got unexpected ret %ld.\n", ret);
|
|
ok(size == expected_size, "Got unexpected size %u.\n", size);
|
|
|
|
for (i = 0; i < ARRAY_SIZE(arch_data); ++i)
|
|
{
|
|
test_id = test_package_id;
|
|
test_id.processorArchitecture = arch_data[i].code;
|
|
packagefullname_from_packageid(fullname, ARRAY_SIZE(fullname), &test_id);
|
|
size = expected_size;
|
|
ret = pPackageIdFromFullName(fullname, 0, &size, id_buffer);
|
|
ok(ret == ERROR_SUCCESS || broken(arch_data[i].broken && ret == ERROR_INVALID_PARAMETER),
|
|
"Got unexpected ret %lu.\n", ret);
|
|
if (ret != ERROR_SUCCESS)
|
|
continue;
|
|
ok(size == expected_size, "Got unexpected length %u, expected %u.\n", size, expected_size);
|
|
ok(id->processorArchitecture == arch_data[i].code, "Got unexpected processorArchitecture %u, arch %S.\n",
|
|
id->processorArchitecture, arch_data[i].name);
|
|
}
|
|
|
|
size = sizeof(id_buffer);
|
|
ret = pPackageIdFromFullName(L"TestPackage_1.2.3.4_X86_TestResourceId_0abcdefghjkme", 0, &size, id_buffer);
|
|
ok(ret == ERROR_SUCCESS, "Got unexpected ret %lu.\n", ret);
|
|
|
|
size = sizeof(id_buffer);
|
|
ret = pPackageIdFromFullName(L"TestPackage_1.2.3.4_X86_TestResourceId_abcdefghjkme", 0, &size, id_buffer);
|
|
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret);
|
|
|
|
size = sizeof(id_buffer);
|
|
ret = pPackageIdFromFullName(L"TestPackage_1.2.3.4_X86_TestResourceId_0abcdefghjkmee", 0, &size, id_buffer);
|
|
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret);
|
|
|
|
size = sizeof(id_buffer);
|
|
ret = pPackageIdFromFullName(L"TestPackage_1.2.3_X86_TestResourceId_0abcdefghjkme", 0, &size, id_buffer);
|
|
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret);
|
|
|
|
size = sizeof(id_buffer);
|
|
ret = pPackageIdFromFullName(L"TestPackage_1.2.3.4_X86_TestResourceId_0abcdefghjkme_", 0, &size, id_buffer);
|
|
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\n", ret);
|
|
|
|
size = sizeof(id_buffer);
|
|
ret = pPackageIdFromFullName(L"TestPackage_1.2.3.4_X86__0abcdefghjkme", 0, &size, id_buffer);
|
|
ok(ret == ERROR_SUCCESS, "Got unexpected ret %lu.\n", ret);
|
|
ok(!lstrcmpW(id->resourceId, L""), "Got unexpected resourceId %s.\n", debugstr_w(id->resourceId));
|
|
|
|
size = sizeof(id_buffer);
|
|
ret = pPackageIdFromFullName(L"TestPackage_1.2.3.4_X86_0abcdefghjkme", 0, &size, id_buffer);
|
|
ok(ret == ERROR_INVALID_PARAMETER, "Got unexpected ret %lu.\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() %lu.\n", ret, GetLastError());
|
|
ok(info.dwMajorVersion == test_pe_os_version_tests[test].expected_major,
|
|
"Test %u, expected major version %u, got %lu.\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 %lu.\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 %lu.%lu, 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() %lu.\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() %lu.\n", ret, GetLastError());
|
|
|
|
file = CreateFileA(tmp_exe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
|
ok(file != INVALID_HANDLE_VALUE, "CreateFile failed, GetLastError() %lu.\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() %lu.\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() %lu.\n", ret, GetLastError());
|
|
CloseHandle(pi.hThread);
|
|
result = WaitForSingleObject(pi.hProcess, 10000);
|
|
ok(result == WAIT_OBJECT_0, "Got unexpected result %#lx.\n", result);
|
|
|
|
ret = GetExitCodeProcess(pi.hProcess, &code);
|
|
ok(ret, "Got unexpected ret %#x, GetLastError() %lu.\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();
|
|
}
|