| /* | |
| * 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 | |
| */ | |
| /* Needed for PRODUCT_* defines and GetProductInfo() */ | |
| #define _WIN32_WINNT 0x0600 | |
| #include "wine/test.h" | |
| #include "winbase.h" | |
| #include "winternl.h" | |
| static BOOL (WINAPI * pGetProductInfo)(DWORD, DWORD, DWORD, DWORD, DWORD *); | |
| static BOOL (WINAPI * pVerifyVersionInfoA)(LPOSVERSIONINFOEXA, DWORD, DWORDLONG); | |
| static ULONGLONG (WINAPI * pVerSetConditionMask)(ULONGLONG, DWORD, BYTE); | |
| static NTSTATUS (WINAPI * pRtlGetVersion)(RTL_OSVERSIONINFOEXW *); | |
| #define GET_PROC(func) \ | |
| p##func = (void *)GetProcAddress(hmod, #func); | |
| static void init_function_pointers(void) | |
| { | |
| HMODULE hmod; | |
| hmod = GetModuleHandleA("kernel32.dll"); | |
| GET_PROC(GetProductInfo); | |
| GET_PROC(VerifyVersionInfoA); | |
| GET_PROC(VerSetConditionMask); | |
| hmod = GetModuleHandleA("ntdll.dll"); | |
| 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_PROFESSIONAL_WMC), | |
| "got %d and 0x%x (expected TRUE and a valid PRODUCT_* value)\n", res, product); | |
| else | |
| ok(!res && !product && (GetLastError() == 0xdeadbeef), | |
| "got %d and 0x%x with 0x%x (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 %d with 0x%x (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 %d\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 %d\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 %d\n", | |
| GetLastError()); | |
| SetLastError(0xdeadbeef); | |
| infoA.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); | |
| ret = GetVersionExA(&infoA); | |
| ok(ret, "Expected GetVersionExA to succeed\n"); | |
| ok(GetLastError() == 0xdeadbeef, | |
| "Expected 0xdeadbeef, got %d\n", GetLastError()); | |
| SetLastError(0xdeadbeef); | |
| infoExA.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); | |
| ret = GetVersionExA((OSVERSIONINFOA *)&infoExA); | |
| ok(ret || | |
| broken(ret == 0), /* win95 */ | |
| "Expected GetVersionExA to succeed\n"); | |
| if (!infoExA.wServicePackMajor && !infoExA.wServicePackMinor) | |
| ok(!infoExA.szCSDVersion[0], "got '%s'\n", infoExA.szCSDVersion); | |
| } | |
| static void test_VerifyVersionInfo(void) | |
| { | |
| OSVERSIONINFOEXA info; | |
| BOOL ret; | |
| DWORD servicepack, error; | |
| if(!pVerifyVersionInfoA || !pVerSetConditionMask) | |
| { | |
| win_skip("Needed functions not available\n"); | |
| return; | |
| } | |
| /* 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; | |
| /* 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(SUCCEEDED(pRtlGetVersion(&rtlinfo)), "RtlGetVersion failed\n"); | |
| if (rtlinfo.dwMajorVersion != 6 || rtlinfo.dwMinorVersion != 2) | |
| { | |
| win_skip("GetVersionEx and VerifyVersionInfo are faking values\n"); | |
| return; | |
| } | |
| } | |
| memset(&info, 0, sizeof(info)); | |
| ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION, | |
| pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL)); | |
| ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError()); | |
| SetLastError(0xdeadbeef); | |
| ret = pVerifyVersionInfoA(&info, VER_BUILDNUMBER | VER_MAJORVERSION | | |
| VER_MINORVERSION/* | VER_PLATFORMID | VER_SERVICEPACKMAJOR | | |
| VER_SERVICEPACKMINOR | VER_SUITENAME | VER_PRODUCT_TYPE */, | |
| pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL)); | |
| error = GetLastError(); | |
| ok(!ret, "VerifyVersionInfoA succeeded\n"); | |
| ok(error == ERROR_OLD_WIN_VERSION, | |
| "VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error); | |
| /* tests special handling of VER_SUITENAME */ | |
| ret = pVerifyVersionInfoA(&info, VER_SUITENAME, | |
| pVerSetConditionMask(0, VER_SUITENAME, VER_AND)); | |
| ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError()); | |
| ret = pVerifyVersionInfoA(&info, VER_SUITENAME, | |
| pVerSetConditionMask(0, VER_SUITENAME, VER_OR)); | |
| ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError()); | |
| /* 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 = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL), | |
| VER_MAJORVERSION, VER_GREATER_EQUAL)); | |
| ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError()); | |
| info.dwMinorVersion = 0; | |
| info.wServicePackMajor = 10; | |
| ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL), | |
| VER_MAJORVERSION, VER_GREATER_EQUAL)); | |
| ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError()); | |
| info.wServicePackMajor = 0; | |
| info.wServicePackMinor = 10; | |
| ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL), | |
| VER_MAJORVERSION, VER_GREATER_EQUAL)); | |
| ok(ret, "VerifyVersionInfoA failed with error %d\n", GetLastError()); | |
| info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); | |
| GetVersionExA((OSVERSIONINFOA *)&info); | |
| info.wServicePackMinor++; | |
| SetLastError(0xdeadbeef); | |
| ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL)); | |
| error = GetLastError(); | |
| ok(!ret, "VerifyVersionInfoA succeeded\n"); | |
| ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some wink2 */, | |
| "VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error); | |
| if (servicepack == 0) | |
| { | |
| skip("There is no ServicePack on this system\n"); | |
| } | |
| else | |
| { | |
| info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); | |
| GetVersionExA((OSVERSIONINFOA *)&info); | |
| info.wServicePackMajor--; | |
| ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER)); | |
| ok(ret || broken(!ret) /* some win2k */, "VerifyVersionInfoA failed with error %d\n", GetLastError()); | |
| info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); | |
| GetVersionExA((OSVERSIONINFOA *)&info); | |
| info.wServicePackMajor--; | |
| ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL)); | |
| ok(ret || broken(!ret) /* some win2k */, "VerifyVersionInfoA failed with error %d\n", GetLastError()); | |
| } | |
| info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); | |
| GetVersionExA((OSVERSIONINFOA *)&info); | |
| info.wServicePackMajor++; | |
| ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(0, VER_MINORVERSION, VER_LESS)); | |
| ok(ret || broken(!ret) /* some win2k */, "VerifyVersionInfoA failed with error %d\n", GetLastError()); | |
| info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); | |
| GetVersionExA((OSVERSIONINFOA *)&info); | |
| info.wServicePackMajor++; | |
| ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(0, VER_MINORVERSION, VER_LESS_EQUAL)); | |
| ok(ret || broken(!ret) /* some win2k */, "VerifyVersionInfoA failed with error %d\n", GetLastError()); | |
| info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); | |
| GetVersionExA((OSVERSIONINFOA *)&info); | |
| info.wServicePackMajor--; | |
| SetLastError(0xdeadbeef); | |
| ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(0, VER_MINORVERSION, VER_EQUAL)); | |
| error = GetLastError(); | |
| ok(!ret, "VerifyVersionInfoA succeeded\n"); | |
| ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */, | |
| "VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error); | |
| /* test the failure hierarchy for the four version fields */ | |
| info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); | |
| GetVersionExA((OSVERSIONINFOA *)&info); | |
| info.wServicePackMajor++; | |
| SetLastError(0xdeadbeef); | |
| ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL)); | |
| error = GetLastError(); | |
| ok(!ret, "VerifyVersionInfoA succeeded\n"); | |
| ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */, | |
| "VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error); | |
| info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); | |
| GetVersionExA((OSVERSIONINFOA *)&info); | |
| info.dwMinorVersion++; | |
| SetLastError(0xdeadbeef); | |
| ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL)); | |
| error = GetLastError(); | |
| ok(!ret, "VerifyVersionInfoA succeeded\n"); | |
| ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */, | |
| "VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error); | |
| info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); | |
| GetVersionExA((OSVERSIONINFOA *)&info); | |
| info.dwMajorVersion++; | |
| SetLastError(0xdeadbeef); | |
| ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL)); | |
| error = GetLastError(); | |
| ok(!ret, "VerifyVersionInfoA succeeded\n"); | |
| ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */, | |
| "VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error); | |
| ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL)); | |
| ok(ret || broken(!ret) /* some win2k */, "VerifyVersionInfoA failed with error %d\n", GetLastError()); | |
| info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); | |
| GetVersionExA((OSVERSIONINFOA *)&info); | |
| info.dwBuildNumber++; | |
| SetLastError(0xdeadbeef); | |
| ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL)); | |
| error = GetLastError(); | |
| ok(!ret, "VerifyVersionInfoA succeeded\n"); | |
| ok(error == ERROR_OLD_WIN_VERSION || broken(error == ERROR_BAD_ARGUMENTS) /* some win2k */, | |
| "VerifyVersionInfoA should have failed with ERROR_OLD_WIN_VERSION instead of %d\n", error); | |
| ret = pVerifyVersionInfoA(&info, VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(0, VER_MINORVERSION, VER_GREATER_EQUAL)); | |
| ok(ret || broken(!ret) /* some win2k */, "VerifyVersionInfoA failed with error %d\n", GetLastError()); | |
| /* test bad dwOSVersionInfoSize */ | |
| info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA); | |
| GetVersionExA((OSVERSIONINFOA *)&info); | |
| info.dwOSVersionInfoSize = 0; | |
| ret = pVerifyVersionInfoA(&info, VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR, | |
| pVerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL)); | |
| ok(ret || broken(!ret) /* some win2k */, "VerifyVersionInfoA failed with error %d\n", GetLastError()); | |
| } | |
| START_TEST(version) | |
| { | |
| init_function_pointers(); | |
| test_GetProductInfo(); | |
| test_GetVersionEx(); | |
| test_VerifyVersionInfo(); | |
| } |