diff --git a/modules/rostests/apitests/CMakeLists.txt b/modules/rostests/apitests/CMakeLists.txt index 18dfedb9538..17a36e94d23 100644 --- a/modules/rostests/apitests/CMakeLists.txt +++ b/modules/rostests/apitests/CMakeLists.txt @@ -56,6 +56,7 @@ add_subdirectory(user32_dynamic) add_subdirectory(userenv) add_subdirectory(utildll) add_subdirectory(uxtheme) +add_subdirectory(version) if(NOT CMAKE_BUILD_TYPE STREQUAL "Release") add_subdirectory(win32u) add_subdirectory(win32nt) diff --git a/modules/rostests/apitests/version/CMakeLists.txt b/modules/rostests/apitests/version/CMakeLists.txt new file mode 100644 index 00000000000..b0ced710e5d --- /dev/null +++ b/modules/rostests/apitests/version/CMakeLists.txt @@ -0,0 +1,18 @@ + +list(APPEND SOURCE + VerQueryValue.c + precomp.h) + +list(APPEND PCH_SKIP_SOURCE + testlist.c) + +add_executable(version_apitest + ${SOURCE} + ${PCH_SKIP_SOURCE}) + +target_link_libraries(version_apitest wine uuid ${PSEH_LIB}) +set_module_type(version_apitest win32cui) +add_importlibs(version_apitest version msvcrt kernel32 ntdll) +add_pch(version_apitest precomp.h "${PCH_SKIP_SOURCE}") + +add_rostests_file(TARGET version_apitest) diff --git a/modules/rostests/apitests/version/VerQueryValue.c b/modules/rostests/apitests/version/VerQueryValue.c new file mode 100644 index 00000000000..215faf4a543 --- /dev/null +++ b/modules/rostests/apitests/version/VerQueryValue.c @@ -0,0 +1,302 @@ +/* + * PROJECT: ReactOS API Tests + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Tests for VerQueryValue[A/W] + * COPYRIGHT: Copyright 2024 Timo Kreuzer + */ + +#include "precomp.h" + +typedef struct +{ + WORD wLength; + WORD wValueLength; + WORD wType; + WCHAR szKey[16]; // L"VS_VERSION_INFO" + WORD Padding1; + VS_FIXEDFILEINFO Value; + + struct _StringFileInfo + { + WORD wLength; + WORD wValueLength; + WORD wType; + WCHAR szKey[15]; // L"StringFileInfo" + + struct _StringTable + { + WORD wLength; + WORD wValueLength; + WORD wType; + WCHAR szKey[9]; // L"000004B" + + struct _String_CompanyName + { + WORD wLength; + WORD wValueLength; + WORD wType; + WCHAR szKey[12]; // L"CompanyName" + WORD Padding1; + WCHAR Value[16]; // L"ReactOS Project" + } CompanyName; + + struct _String_Comments + { + WORD wLength; + WORD wValueLength; // 0 + WORD wType; + WCHAR szKey[9]; // L"Comments" + } Comments; + + struct _String_Comments2 + { + WORD wLength; + WORD wValueLength; // 0 + WORD wType; + WCHAR szKey[10]; // L"Comments2" + WORD Padding; + } Comments2; + + struct _String_FooBar + { + WORD wLength; + WORD wValueLength; + WORD wType; + WCHAR szKey[7]; // L"FooBar" + WCHAR Value[4]; // L"Bar" + } FooBar; + + } StringTable; + } StringFileInfo; +} TEST_VERSIONINFO; + +static const TEST_VERSIONINFO g_VersionInfo = +{ + .wLength = 298, // Header: 40, Value: 54, StringFileInfo: 204 + .wValueLength = sizeof(VS_FIXEDFILEINFO), + .wType = 0, + .szKey = L"VS_VERSION_INFO", + .Padding1 = 0, + .Value = + { + .dwSignature = VS_FFI_SIGNATURE, + .dwStrucVersion = VS_FFI_STRUCVERSION, + .dwFileVersionMS = 0x00050002, + .dwFileVersionLS = 0x0ECE0000, + .dwProductVersionMS = 0x00050002, + .dwProductVersionLS = 0x0ECE0000, + .dwFileFlagsMask = 0x00000002, + .dwFileFlags = 0x00000000, + .dwFileOS = VOS__WINDOWS32, + .dwFileType = VFT_APP, + .dwFileSubtype = VFT2_UNKNOWN, + .dwFileDateMS = 0x00020074, + .dwFileDateLS = 0x00000000, + }, + .StringFileInfo = + { + .wLength = 204, // Header: 36, StringTable: 168 + .wValueLength = 0, + .wType = 1, + .szKey = L"StringFileInfo", + .StringTable = + { + .wLength = 168, //Header: 24, Children: 144 + .wValueLength = 0, + .wType = 1, + .szKey = L"000004B0", + + .CompanyName = + { + .wLength = 64, + .wValueLength = 16, + .wType = 1, + .szKey = L"CompanyName", + .Padding1 = 0, + .Value = L"ReactOS Project", + }, + .Comments = + { + .wLength = 24, + .wValueLength = 0, + .wType = 1, + .szKey = L"Comments", + }, + .Comments2 = + { + .wLength = 28, + .wValueLength = 0, + .wType = 1, + .szKey = L"Comments2", + .Padding = 0xCC, + }, + .FooBar = + { + .wLength = 28, + .wValueLength = 4, + .wType = 1, + .szKey = L"FooBar", + .Value = L"Bar", + }, + }, + }, +}; + +void +Test_VerQueryValueA(void) +{ + DWORD dwVersionInfoSizeW, dwVersionInfoSizeA; + PVOID pvVersionInfoA, pvData = NULL; + CHAR szSubBlock[256]; + USHORT uLanguage, uCodePage; + UINT cbLen; + BOOL result; + + /* Get the size for the unicode version info */ + dwVersionInfoSizeW = GetFileVersionInfoSizeW(L"kernel32.dll", NULL); + ok(dwVersionInfoSizeW > 0, "GetFileVersionInfoSizeW failed\n"); + + /* Get the size for the ANSI version info */ + dwVersionInfoSizeA = GetFileVersionInfoSizeA("kernel32.dll", NULL); + ok(dwVersionInfoSizeA > 0, "GetFileVersionInfoSizeA failed\n"); + ok(dwVersionInfoSizeA == dwVersionInfoSizeW, "Unexpected size\n"); + + /* Get the ANSI version info from kernel32 */ + pvVersionInfoA = malloc(dwVersionInfoSizeA); + memset(pvVersionInfoA, 0xCC, dwVersionInfoSizeA); + result = GetFileVersionInfoA("kernel32.dll", 0, dwVersionInfoSizeA, pvVersionInfoA); + ok(result, "GetFileVersionInfoA failed\n"); + + /* Query available translations */ + result = VerQueryValueA(pvVersionInfoA, + "\\VarFileInfo\\Translation", + &pvData, + &cbLen); + ok(result, "VerQueryValueA failed\n"); + ok(cbLen >= 4, "Unexpected value\n"); + ok((cbLen & 0x3) == 0, "Unexpected value\n"); + uLanguage = ((USHORT*)pvData)[0]; + uCodePage = ((USHORT*)pvData)[1]; + + /* Query sublock */ + sprintf(szSubBlock, "\\StringFileInfo\\%04X%04X\\CompanyName", uLanguage, uCodePage); + result = VerQueryValueA(pvVersionInfoA, + szSubBlock, + &pvData, + &cbLen); + ok(result, "VerQueryValueA failed\n"); + ok(cbLen >= 2, "Unexpected value\n"); + ok((cbLen & 0x1) == 0, "Unexpected value\n"); + + free(pvVersionInfoA); +} + +void +Test_VerQueryValueW(void) +{ + DWORD dwVersionInfoSizeW; + PVOID pvVersionInfoW, pvData = NULL; + WCHAR szSubBlock[256]; + USHORT uLanguage, uCodePage; + UINT cbLen; + BOOL result; + + /* Get the size for the unicode version info */ + dwVersionInfoSizeW = GetFileVersionInfoSizeW(L"kernel32.dll", NULL); + ok(dwVersionInfoSizeW > 0, "GetFileVersionInfoSizeW failed\n"); + + /* Get the unicode version info from kernel32 */ + pvVersionInfoW = malloc(dwVersionInfoSizeW); + result = GetFileVersionInfoW(L"kernel32.dll", 0, dwVersionInfoSizeW, pvVersionInfoW); + ok(result, "GetFileVersionInfoW failed\n"); + + /* Query available translations */ + result = VerQueryValueW(pvVersionInfoW, + L"\\VarFileInfo\\Translation", + &pvData, + &cbLen); + ok(result, "VerQueryValueA failed\n"); + ok(cbLen >= 4, "Unexpected value\n"); + ok((cbLen & 0x3) == 0, "Unexpected value\n"); + uLanguage = ((USHORT*)pvData)[0]; + uCodePage = ((USHORT*)pvData)[1]; + + /* Query sublock */ + _swprintf(szSubBlock, L"\\StringFileInfo\\%04X%04X\\CompanyName", uLanguage, uCodePage); + result = VerQueryValueW(pvVersionInfoW, + szSubBlock, + &pvData, + &cbLen); + ok(result, "VerQueryValueA failed\n"); + ok(cbLen >= 2, "Unexpected value\n"); + ok((cbLen & 0x1) == 0, "Unexpected value\n"); + + free(pvVersionInfoW); +} + +void +Test_StaticVersionInfo(void) +{ + PVOID pVersionInfo; + PVOID pvData = NULL; + SIZE_T ExpectedOffset; + UINT cbLen; + BOOL result; + + /* Make a copy of the version info. Windows actually writes to it! + We make the buffer twice as big to account for the ANSI copy, + even if we don't use it. */ + pVersionInfo = malloc(2 * sizeof(g_VersionInfo)); + memset(pVersionInfo, 0, 2 * sizeof(g_VersionInfo)); + memcpy(pVersionInfo, &g_VersionInfo, sizeof(g_VersionInfo)); + + /* Test a special static version */ + result = VerQueryValueW(pVersionInfo, + L"\\StringFileInfo\\000004B0\\CompanyName", + &pvData, + &cbLen); + ok(result, "VerQueryValueW failed\n"); + ok_eq_int(cbLen, 16); + ok_eq_wstr((WCHAR*)pvData, L"ReactOS Project"); + ExpectedOffset = FIELD_OFFSET(TEST_VERSIONINFO, StringFileInfo.StringTable.CompanyName.Value); + ok(pvData == (PVOID)((ULONG_PTR)pVersionInfo + ExpectedOffset), "Unexpected offset\n"); + + result = VerQueryValueW(pVersionInfo, + L"\\StringFileInfo\\000004B0\\Comments", + &pvData, + &cbLen); + ok(result, "VerQueryValueW failed\n"); + ok_eq_int(cbLen, 0); + ok_eq_wstr((WCHAR*)pvData, L""); + ExpectedOffset = FIELD_OFFSET(TEST_VERSIONINFO, StringFileInfo.StringTable.Comments.szKey[8]); + ok(pvData == (PVOID)((ULONG_PTR)pVersionInfo + ExpectedOffset), "Unexpected offset\n"); + + result = VerQueryValueW(pVersionInfo, + L"\\StringFileInfo\\000004B0\\Comments2", + &pvData, + &cbLen); + ok(result, "VerQueryValueW failed\n"); + ok_eq_int(cbLen, 0); + ok_eq_wstr((WCHAR*)pvData, L""); + ExpectedOffset = FIELD_OFFSET(TEST_VERSIONINFO, StringFileInfo.StringTable.Comments2.szKey[9]); + ok(pvData == (PVOID)((ULONG_PTR)pVersionInfo + ExpectedOffset), "Unexpected offset\n"); + + result = VerQueryValueW(pVersionInfo, + L"\\StringFileInfo\\000004B0\\FooBar", + &pvData, + &cbLen); + ok(result, "VerQueryValueW failed\n"); + ok_eq_int(cbLen, 4); + ok(wcscmp((WCHAR*)pvData, L"Bar") == 0, "Bar\n"); + ExpectedOffset = FIELD_OFFSET(TEST_VERSIONINFO, StringFileInfo.StringTable.FooBar.Value); + ok(pvData == (PVOID)((ULONG_PTR)pVersionInfo + ExpectedOffset), "Unexpected offset\n"); + + free(pVersionInfo); +} + +START_TEST(VerQueryValue) +{ + Test_VerQueryValueA(); + Test_VerQueryValueW(); + Test_StaticVersionInfo(); +} diff --git a/modules/rostests/apitests/version/precomp.h b/modules/rostests/apitests/version/precomp.h new file mode 100644 index 00000000000..9d04b3bc6c5 --- /dev/null +++ b/modules/rostests/apitests/version/precomp.h @@ -0,0 +1,15 @@ +#pragma once + +#include + +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H + +#include +#include +#include +#include +#include +#include +#include diff --git a/modules/rostests/apitests/version/testlist.c b/modules/rostests/apitests/version/testlist.c new file mode 100644 index 00000000000..9e421f0afdf --- /dev/null +++ b/modules/rostests/apitests/version/testlist.c @@ -0,0 +1,18 @@ +/* + * PROJECT: ReactOS API Tests + * LICENSE: MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Tests for version.dll + * COPYRIGHT: Copyright 2024 Timo Kreuzer + */ + +#define STANDALONE +#include + +extern void func_VerQueryValue(void); + +const struct test winetest_testlist[] = +{ + { "VerQueryValue", func_VerQueryValue }, + + { 0, 0 } +};