1 /* 2 * PROJECT: ReactOS API Tests 3 * LICENSE: MIT (https://spdx.org/licenses/MIT) 4 * PURPOSE: Tests for VerQueryValue[A/W] 5 * COPYRIGHT: Copyright 2024 Timo Kreuzer <timo.kreuzer@reactos.org> 6 */ 7 8 #include "precomp.h" 9 10 typedef struct 11 { 12 WORD wLength; 13 WORD wValueLength; 14 WORD wType; 15 WCHAR szKey[16]; // L"VS_VERSION_INFO" 16 WORD Padding1; 17 VS_FIXEDFILEINFO Value; 18 19 struct _StringFileInfo 20 { 21 WORD wLength; 22 WORD wValueLength; 23 WORD wType; 24 WCHAR szKey[15]; // L"StringFileInfo" 25 26 struct _StringTable 27 { 28 WORD wLength; 29 WORD wValueLength; 30 WORD wType; 31 WCHAR szKey[9]; // L"000004B" 32 33 struct _String_CompanyName 34 { 35 WORD wLength; 36 WORD wValueLength; 37 WORD wType; 38 WCHAR szKey[12]; // L"CompanyName" 39 WORD Padding1; 40 WCHAR Value[16]; // L"ReactOS Project" 41 } CompanyName; 42 43 struct _String_Comments 44 { 45 WORD wLength; 46 WORD wValueLength; // 0 47 WORD wType; 48 WCHAR szKey[9]; // L"Comments" 49 } Comments; 50 51 struct _String_Comments2 52 { 53 WORD wLength; 54 WORD wValueLength; // 0 55 WORD wType; 56 WCHAR szKey[10]; // L"Comments2" 57 WORD Padding; 58 } Comments2; 59 60 struct _String_FooBar 61 { 62 WORD wLength; 63 WORD wValueLength; 64 WORD wType; 65 WCHAR szKey[7]; // L"FooBar" 66 WCHAR Value[4]; // L"Bar" 67 } FooBar; 68 69 } StringTable; 70 } StringFileInfo; 71 } TEST_VERSIONINFO; 72 73 static const TEST_VERSIONINFO g_VersionInfo = 74 { 75 .wLength = 298, // Header: 40, Value: 54, StringFileInfo: 204 76 .wValueLength = sizeof(VS_FIXEDFILEINFO), 77 .wType = 0, 78 .szKey = L"VS_VERSION_INFO", 79 .Padding1 = 0, 80 .Value = 81 { 82 .dwSignature = VS_FFI_SIGNATURE, 83 .dwStrucVersion = VS_FFI_STRUCVERSION, 84 .dwFileVersionMS = 0x00050002, 85 .dwFileVersionLS = 0x0ECE0000, 86 .dwProductVersionMS = 0x00050002, 87 .dwProductVersionLS = 0x0ECE0000, 88 .dwFileFlagsMask = 0x00000002, 89 .dwFileFlags = 0x00000000, 90 .dwFileOS = VOS__WINDOWS32, 91 .dwFileType = VFT_APP, 92 .dwFileSubtype = VFT2_UNKNOWN, 93 .dwFileDateMS = 0x00020074, 94 .dwFileDateLS = 0x00000000, 95 }, 96 .StringFileInfo = 97 { 98 .wLength = 204, // Header: 36, StringTable: 168 99 .wValueLength = 0, 100 .wType = 1, 101 .szKey = L"StringFileInfo", 102 .StringTable = 103 { 104 .wLength = 168, //Header: 24, Children: 144 105 .wValueLength = 0, 106 .wType = 1, 107 .szKey = L"000004B0", 108 109 .CompanyName = 110 { 111 .wLength = 64, 112 .wValueLength = 16, 113 .wType = 1, 114 .szKey = L"CompanyName", 115 .Padding1 = 0, 116 .Value = L"ReactOS Project", 117 }, 118 .Comments = 119 { 120 .wLength = 24, 121 .wValueLength = 0, 122 .wType = 1, 123 .szKey = L"Comments", 124 }, 125 .Comments2 = 126 { 127 .wLength = 28, 128 .wValueLength = 0, 129 .wType = 1, 130 .szKey = L"Comments2", 131 .Padding = 0xCC, 132 }, 133 .FooBar = 134 { 135 .wLength = 28, 136 .wValueLength = 4, 137 .wType = 1, 138 .szKey = L"FooBar", 139 .Value = L"Bar", 140 }, 141 }, 142 }, 143 }; 144 145 void 146 Test_VerQueryValueA(void) 147 { 148 DWORD dwVersionInfoSizeW, dwVersionInfoSizeA; 149 PVOID pvVersionInfoA, pvData = NULL; 150 CHAR szSubBlock[256]; 151 USHORT uLanguage, uCodePage; 152 UINT cbLen; 153 BOOL result; 154 155 /* Get the size for the unicode version info */ 156 dwVersionInfoSizeW = GetFileVersionInfoSizeW(L"kernel32.dll", NULL); 157 ok(dwVersionInfoSizeW > 0, "GetFileVersionInfoSizeW failed\n"); 158 159 /* Get the size for the ANSI version info */ 160 dwVersionInfoSizeA = GetFileVersionInfoSizeA("kernel32.dll", NULL); 161 ok(dwVersionInfoSizeA > 0, "GetFileVersionInfoSizeA failed\n"); 162 ok(dwVersionInfoSizeA == dwVersionInfoSizeW, "Unexpected size\n"); 163 164 /* Get the ANSI version info from kernel32 */ 165 pvVersionInfoA = malloc(dwVersionInfoSizeA); 166 memset(pvVersionInfoA, 0xCC, dwVersionInfoSizeA); 167 result = GetFileVersionInfoA("kernel32.dll", 0, dwVersionInfoSizeA, pvVersionInfoA); 168 ok(result, "GetFileVersionInfoA failed\n"); 169 170 /* Query available translations */ 171 result = VerQueryValueA(pvVersionInfoA, 172 "\\VarFileInfo\\Translation", 173 &pvData, 174 &cbLen); 175 ok(result, "VerQueryValueA failed\n"); 176 ok(cbLen >= 4, "Unexpected value\n"); 177 ok((cbLen & 0x3) == 0, "Unexpected value\n"); 178 uLanguage = ((USHORT*)pvData)[0]; 179 uCodePage = ((USHORT*)pvData)[1]; 180 181 /* Query sublock */ 182 sprintf(szSubBlock, "\\StringFileInfo\\%04X%04X\\CompanyName", uLanguage, uCodePage); 183 result = VerQueryValueA(pvVersionInfoA, 184 szSubBlock, 185 &pvData, 186 &cbLen); 187 ok(result, "VerQueryValueA failed\n"); 188 ok(cbLen >= 2, "Unexpected value\n"); 189 ok((cbLen & 0x1) == 0, "Unexpected value\n"); 190 191 free(pvVersionInfoA); 192 } 193 194 void 195 Test_VerQueryValueW(void) 196 { 197 DWORD dwVersionInfoSizeW; 198 PVOID pvVersionInfoW, pvData = NULL; 199 WCHAR szSubBlock[256]; 200 USHORT uLanguage, uCodePage; 201 UINT cbLen; 202 BOOL result; 203 204 /* Get the size for the unicode version info */ 205 dwVersionInfoSizeW = GetFileVersionInfoSizeW(L"kernel32.dll", NULL); 206 ok(dwVersionInfoSizeW > 0, "GetFileVersionInfoSizeW failed\n"); 207 208 /* Get the unicode version info from kernel32 */ 209 pvVersionInfoW = malloc(dwVersionInfoSizeW); 210 result = GetFileVersionInfoW(L"kernel32.dll", 0, dwVersionInfoSizeW, pvVersionInfoW); 211 ok(result, "GetFileVersionInfoW failed\n"); 212 213 /* Query available translations */ 214 result = VerQueryValueW(pvVersionInfoW, 215 L"\\VarFileInfo\\Translation", 216 &pvData, 217 &cbLen); 218 ok(result, "VerQueryValueA failed\n"); 219 ok(cbLen >= 4, "Unexpected value\n"); 220 ok((cbLen & 0x3) == 0, "Unexpected value\n"); 221 uLanguage = ((USHORT*)pvData)[0]; 222 uCodePage = ((USHORT*)pvData)[1]; 223 224 /* Query sublock */ 225 _swprintf(szSubBlock, L"\\StringFileInfo\\%04X%04X\\CompanyName", uLanguage, uCodePage); 226 result = VerQueryValueW(pvVersionInfoW, 227 szSubBlock, 228 &pvData, 229 &cbLen); 230 ok(result, "VerQueryValueA failed\n"); 231 ok(cbLen >= 2, "Unexpected value\n"); 232 ok((cbLen & 0x1) == 0, "Unexpected value\n"); 233 234 free(pvVersionInfoW); 235 } 236 237 void 238 Test_StaticVersionInfo(void) 239 { 240 PVOID pVersionInfo; 241 PVOID pvData = NULL; 242 SIZE_T ExpectedOffset; 243 UINT cbLen; 244 BOOL result; 245 246 /* Make a copy of the version info. Windows actually writes to it! 247 We make the buffer twice as big to account for the ANSI copy, 248 even if we don't use it. */ 249 pVersionInfo = malloc(2 * sizeof(g_VersionInfo)); 250 memset(pVersionInfo, 0, 2 * sizeof(g_VersionInfo)); 251 memcpy(pVersionInfo, &g_VersionInfo, sizeof(g_VersionInfo)); 252 253 /* Test a special static version */ 254 result = VerQueryValueW(pVersionInfo, 255 L"\\StringFileInfo\\000004B0\\CompanyName", 256 &pvData, 257 &cbLen); 258 ok(result, "VerQueryValueW failed\n"); 259 ok_eq_int(cbLen, 16); 260 ok_eq_wstr((WCHAR*)pvData, L"ReactOS Project"); 261 ExpectedOffset = FIELD_OFFSET(TEST_VERSIONINFO, StringFileInfo.StringTable.CompanyName.Value); 262 ok(pvData == (PVOID)((ULONG_PTR)pVersionInfo + ExpectedOffset), "Unexpected offset\n"); 263 264 result = VerQueryValueW(pVersionInfo, 265 L"\\StringFileInfo\\000004B0\\Comments", 266 &pvData, 267 &cbLen); 268 ok(result, "VerQueryValueW failed\n"); 269 ok_eq_int(cbLen, 0); 270 ok_eq_wstr((WCHAR*)pvData, L""); 271 ExpectedOffset = FIELD_OFFSET(TEST_VERSIONINFO, StringFileInfo.StringTable.Comments.szKey[8]); 272 ok(pvData == (PVOID)((ULONG_PTR)pVersionInfo + ExpectedOffset), "Unexpected offset\n"); 273 274 result = VerQueryValueW(pVersionInfo, 275 L"\\StringFileInfo\\000004B0\\Comments2", 276 &pvData, 277 &cbLen); 278 ok(result, "VerQueryValueW failed\n"); 279 ok_eq_int(cbLen, 0); 280 ok_eq_wstr((WCHAR*)pvData, L""); 281 ExpectedOffset = FIELD_OFFSET(TEST_VERSIONINFO, StringFileInfo.StringTable.Comments2.szKey[9]); 282 ok(pvData == (PVOID)((ULONG_PTR)pVersionInfo + ExpectedOffset), "Unexpected offset\n"); 283 284 result = VerQueryValueW(pVersionInfo, 285 L"\\StringFileInfo\\000004B0\\FooBar", 286 &pvData, 287 &cbLen); 288 ok(result, "VerQueryValueW failed\n"); 289 ok_eq_int(cbLen, 4); 290 ok(wcscmp((WCHAR*)pvData, L"Bar") == 0, "Bar\n"); 291 ExpectedOffset = FIELD_OFFSET(TEST_VERSIONINFO, StringFileInfo.StringTable.FooBar.Value); 292 ok(pvData == (PVOID)((ULONG_PTR)pVersionInfo + ExpectedOffset), "Unexpected offset\n"); 293 294 free(pVersionInfo); 295 } 296 297 START_TEST(VerQueryValue) 298 { 299 Test_VerQueryValueA(); 300 Test_VerQueryValueW(); 301 Test_StaticVersionInfo(); 302 } 303