1 /* 2 * PROJECT: ReactOS api tests 3 * LICENSE: GPL - See COPYING in the top level directory 4 * PURPOSE: Test for GetFontResourceInfoW 5 * PROGRAMMERS: Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 6 */ 7 8 #include "precomp.h" 9 10 /* GetFontResourceInfoW is undocumented */ 11 BOOL WINAPI GetFontResourceInfoW(LPCWSTR lpFileName, DWORD *pdwBufSize, void* lpBuffer, DWORD dwType); 12 13 /* structure of test entry */ 14 typedef struct GFRI_ENTRY 15 { 16 LPCWSTR File; 17 BOOL Preinstalled; 18 WCHAR FontInfo[64]; 19 INT FontCount; 20 WCHAR FaceNames[10][64]; 21 } GFRI_ENTRY; 22 23 /* test entries */ 24 static const GFRI_ENTRY TestEntries[] = 25 { 26 { L"symbol.ttf", TRUE, L"Symbol|", 1, { L"Symbol" } }, 27 { L"tahoma.ttf", TRUE, L"Tahoma|", 1, { L"Tahoma" } }, 28 { L"tahomabd.ttf", TRUE, L"Tahoma Bold|", 1, { L"Tahoma" } } 29 }; 30 31 /* Japanese */ 32 static const GFRI_ENTRY AdditionalTestEntriesJapanese[] = 33 { 34 { 35 /* MS Gothic & MS UI Gothic & MS PGothic */ 36 L"msgothic.ttc", TRUE, 37 { 38 0xFF2D, 0xFF33, 0x0020, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0x0020, 39 0x0026, 0x0020, 0x004D, 0x0053, 0x0020, 0x0055, 0x0049, 0x0020, 40 0x0047, 0x006F, 0x0074, 0x0068, 0x0069, 0x0063, 0x0020, 0x0026, 41 0x0020, 0xFF2D, 0xFF33, 0x0020, 0xFF30, 0x30B4, 0x30B7, 0x30C3, 42 0x30AF, L'|', 0 43 }, 44 6, 45 { 46 { 0xFF2D, 0xFF33, 0x0020, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0 }, 47 { L'@', 0xFF2D, 0xFF33, 0x0020, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0 }, 48 L"MS UI Gothic", 49 L"@MS UI Gothic", 50 { 0xFF2D, 0xFF33, 0x0020, 0xFF30, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0 }, 51 { L'@', 0xFF2D, 0xFF33, 0x0020, 0xFF30, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0 } 52 } 53 }, 54 { 55 L"ExampleFont.ttf", FALSE, 56 L"JapaneseDisplayName|", 57 1, 58 { 59 L"JapaneseFamilyName" 60 } 61 } 62 }; 63 64 /* English */ 65 static const GFRI_ENTRY AdditionalTestEntriesEnglish[] = 66 { 67 { 68 /* MS Gothic & MS UI Gothic & MS PGothic */ 69 L"msgothic.ttc", TRUE, 70 L"MS Gothic & MS UI Gothic & MS PGothic|", 71 6, 72 { 73 L"MS Gothic", 74 L"@MS Gothic", 75 L"MS UI Gothic", 76 L"@MS UI Gothic", 77 L"MS PGothic", 78 L"@MS PGothic" 79 } 80 }, 81 { 82 L"ExampleFont.ttf", FALSE, 83 L"EnglishDisplayName|", 84 1, 85 { 86 L"EnglishFamilyName" 87 } 88 } 89 }; 90 91 static void 92 GetSystemFontDirectory(LPWSTR pszDir) 93 { 94 GetWindowsDirectoryW(pszDir, MAX_PATH); 95 lstrcatW(pszDir, L"\\Fonts"); 96 } 97 98 static void 99 GetSystemFontPath(LPWSTR pszPath, LPCWSTR pszFile) 100 { 101 GetSystemFontDirectory(pszPath); 102 lstrcatW(pszPath, L"\\"); 103 lstrcatW(pszPath, pszFile); 104 } 105 106 static INT 107 GetMultiSzLength(const WCHAR *pszz) 108 { 109 INT Len, TotalLen = 0; 110 for (;;) 111 { 112 Len = lstrlenW(pszz); 113 TotalLen += Len + 1; 114 pszz += Len + 1; 115 if (*pszz == 0) 116 break; 117 } 118 ++TotalLen; 119 return TotalLen; 120 } 121 122 static void 123 ReplaceChars(WCHAR *pch, INT Len, WCHAR From, WCHAR To) 124 { 125 while (Len > 0) 126 { 127 if (*pch == From) 128 { 129 *pch = To; 130 } 131 //printf("0x%04X, ", *pch); 132 ++pch; 133 --Len; 134 } 135 } 136 137 static void 138 SzFromMultiSz(WCHAR *pszz) 139 { 140 INT Length = GetMultiSzLength(pszz); 141 //printf("Length: %d\n", Length); 142 if (Length > 0) 143 { 144 ReplaceChars(pszz, Length - 1, L'\0', L'|'); 145 pszz[Length - 1] = 0; 146 } 147 else 148 { 149 pszz[0] = 0; 150 } 151 //printf("pszz: %S\n", pszz); 152 } 153 154 static void 155 Test_GetFontResourceInfoW_case0(LPCWSTR pszFilePath, const GFRI_ENTRY *Entry) 156 { 157 BOOL Ret; 158 DWORD Size, Case = 0; 159 DWORD Data; 160 161 /* data NULL, size zero */ 162 Size = 0; 163 Ret = GetFontResourceInfoW(pszFilePath, &Size, NULL, Case); 164 ok_int(Ret, 1); 165 ok_int(Size, 4); 166 167 /* data NULL, size non-zero */ 168 Size = 1024; 169 Ret = GetFontResourceInfoW(pszFilePath, &Size, NULL, Case); 170 ok_int(Ret, 0); 171 ok_int(Size, 1024); 172 173 /* size zero */ 174 Data = 0xDEADFACE; 175 Size = 0; 176 Ret = GetFontResourceInfoW(pszFilePath, &Size, &Data, Case); 177 ok_int(Ret, 1); 178 ok_int(Data, 0xDEADFACE); 179 ok_int(Size, 4); 180 181 /* size non-zero */ 182 Data = 0xDEADFACE; 183 Size = sizeof(Data); 184 Ret = GetFontResourceInfoW(pszFilePath, &Size, &Data, Case); 185 ok_int(Ret, 1); 186 ok_int(Data, Entry->FontCount); 187 ok_int(Size, 4); 188 } 189 190 static void 191 Test_GetFontResourceInfoW_case1(LPCWSTR pszFilePath, const GFRI_ENTRY *Entry) 192 { 193 BOOL Ret; 194 DWORD Size, Case = 1; 195 static WCHAR Data[1024 / sizeof(WCHAR)]; 196 197 /* data NULL, size zero */ 198 Size = 0; 199 Ret = GetFontResourceInfoW(pszFilePath, &Size, NULL, Case); 200 ok_int(Ret, 1); 201 /* FIXME: What's the result of Size? */ 202 ok(Size != 0, "Size expected non-zero but zero\n"); 203 204 /* data NULL, size non-zero */ 205 Size = 1024; 206 Ret = GetFontResourceInfoW(pszFilePath, &Size, NULL, Case); 207 ok_int(Ret, 0); 208 ok_int(Size, 1024); 209 210 /* size zero */ 211 Size = 0; 212 CopyMemory(Data, L"ABC\0", sizeof(L"ABC\0")); 213 Ret = GetFontResourceInfoW(pszFilePath, &Size, Data, Case); 214 ok_int(Ret, 1); 215 /* FIXME: What's the result of Size? */ 216 ok(Size != 0, "Size expected non-zero but zero\n"); 217 ok(lstrcmpiW(Data, L"ABC") == 0, "data mismatched: \"%S\"\n", Data); 218 219 /* size non-zero */ 220 Size = 1024; 221 CopyMemory(Data, L"ABC\0", sizeof(L"ABC\0")); 222 Ret = GetFontResourceInfoW(pszFilePath, &Size, Data, Case); 223 ok_int(Ret, 1); 224 /* FIXME: What's the result of Size? */ 225 ok(Size != 0, "Size expected non-zero but zero\n"); 226 227 SzFromMultiSz(Data); 228 ok(lstrcmpiW(Data, Entry->FontInfo) == 0, "data mismatched: \"%S\" and \"%S\"\n", 229 Data, Entry->FontInfo); 230 #if 0 231 if (lstrcmpiW(Data, Entry->FontInfo) != 0) 232 { 233 int i, len = lstrlenW(Data) + 1; 234 for (i = 0; i < len; ++i) 235 { 236 printf("0x%04X <=> 0x%04X\n", Data[i], Entry->FontInfo[i]); 237 } 238 } 239 #endif 240 } 241 242 static void 243 Test_GetFontResourceInfoW_case2(LPCWSTR pszFilePath, const GFRI_ENTRY *Entry) 244 { 245 BOOL Ret; 246 DWORD i, Size, Case = 2; 247 static LOGFONTW Data[100]; 248 249 /* data NULL, size zero */ 250 Size = 0; 251 Ret = GetFontResourceInfoW(pszFilePath, &Size, NULL, Case); 252 ok_int(Ret, 1); 253 ok_int(Size, Entry->FontCount * sizeof(LOGFONTW)); 254 255 /* data NULL, size non-zero */ 256 Size = 1024; 257 Ret = GetFontResourceInfoW(pszFilePath, &Size, NULL, Case); 258 ok_int(Ret, 0); 259 ok_int(Size, 1024); 260 261 /* size zero */ 262 Size = 0; 263 ZeroMemory(Data, sizeof(Data)); 264 Ret = GetFontResourceInfoW(pszFilePath, &Size, Data, Case); 265 ok_int(Ret, 1); 266 ok_int(Size, Entry->FontCount * sizeof(LOGFONTW)); 267 268 /* size non-zero */ 269 Size = sizeof(Data); 270 ZeroMemory(Data, sizeof(Data)); 271 Ret = GetFontResourceInfoW(pszFilePath, &Size, Data, Case); 272 ok_int(Ret, 1); 273 ok_int(Size, Entry->FontCount * sizeof(LOGFONTW)); 274 for (i = 0; i < Entry->FontCount; ++i) 275 { 276 ok(lstrcmpiW(Data[i].lfFaceName, Entry->FaceNames[i]) == 0, 277 "face name #%d mismatched: \"%S\" and \"%S\"\n", (int)i, Data[i].lfFaceName, Entry->FaceNames[i]); 278 #if 0 279 if (lstrcmpiW(Data[i].lfFaceName, Entry->FaceNames[i]) != 0) 280 { 281 int k, len = lstrlenW(Data[i].lfFaceName); 282 for (k = 0; k < len; ++k) 283 { 284 printf("0x%04X <=> 0x%04X\n", Entry->FaceNames[i][k], Data[i].lfFaceName[k]); 285 } 286 } 287 #endif 288 } 289 } 290 291 static void 292 Test_GetFontResourceInfoW_case3(LPCWSTR pszFilePath, const GFRI_ENTRY *Entry) 293 { 294 BOOL Ret; 295 DWORD Size, Case = 3; 296 DWORD Data[2]; 297 298 /* data NULL, size zero */ 299 Size = 0; 300 Ret = GetFontResourceInfoW(pszFilePath, &Size, NULL, Case); 301 ok_int(Ret, 1); 302 ok_int(Size, 4); 303 304 /* data NULL, size non-zero */ 305 Size = sizeof(Data); 306 Ret = GetFontResourceInfoW(pszFilePath, &Size, NULL, Case); 307 ok_int(Ret, 0); 308 ok_int(Size, 8); 309 310 /* size zero */ 311 Size = 0; 312 Data[0] = 0xDEADFACE; 313 Ret = GetFontResourceInfoW(pszFilePath, &Size, Data, Case); 314 ok_int(Ret, 1); 315 ok_int(Size, 4); 316 ok_int(Data[0], 0xDEADFACE); 317 318 /* size non-zero */ 319 Size = sizeof(Data); 320 Data[0] = 0xDEADFACE; 321 Ret = GetFontResourceInfoW(pszFilePath, &Size, Data, Case); 322 ok_int(Ret, 1); 323 ok_int(Size, 4); 324 ok_int(Data[0], 1); 325 } 326 327 static void 328 Test_GetFontResourceInfoW_case4(LPCWSTR pszFilePath, const GFRI_ENTRY *Entry) 329 { 330 BOOL Ret; 331 DWORD Size, Case = 4; 332 WCHAR Data[MAX_PATH]; 333 334 /* data NULL, size zero */ 335 Size = 0; 336 Ret = GetFontResourceInfoW(pszFilePath, &Size, NULL, Case); 337 ok_int(Ret, 1); 338 ok_int(Size, (lstrlenW(pszFilePath) + 1) * sizeof(WCHAR)); 339 340 /* data NULL, size non-zero */ 341 Size = MAX_PATH; 342 Ret = GetFontResourceInfoW(pszFilePath, &Size, NULL, Case); 343 ok_int(Ret, 0); 344 ok_int(Size, MAX_PATH); 345 346 /* size zero */ 347 Size = 0; 348 Ret = GetFontResourceInfoW(pszFilePath, &Size, Data, Case); 349 ok_int(Ret, 1); 350 ok_int(Size, (lstrlenW(pszFilePath) + 1) * sizeof(WCHAR)); 351 352 /* size non-zero */ 353 Size = MAX_PATH; 354 Ret = GetFontResourceInfoW(pszFilePath, &Size, Data, Case); 355 ok_int(Ret, 1); 356 ok_int(Size, (lstrlenW(pszFilePath) + 1) * sizeof(WCHAR)); 357 ok(lstrcmpiW(pszFilePath, Data) == 0, "data mismatched: \"%S\"\n", Data); 358 } 359 360 static void 361 Test_GetFontResourceInfoW_case5(LPCWSTR pszFilePath, const GFRI_ENTRY *Entry) 362 { 363 BOOL Ret; 364 DWORD Size, Case = 5; 365 DWORD Data; 366 367 /* data NULL, size zero */ 368 Size = 0; 369 Ret = GetFontResourceInfoW(pszFilePath, &Size, NULL, Case); 370 ok_int(Ret, 1); 371 ok_int(Size, 4); 372 373 /* data NULL, size non-zero */ 374 Size = sizeof(Data); 375 Ret = GetFontResourceInfoW(pszFilePath, &Size, NULL, Case); 376 ok_int(Ret, 0); 377 ok_int(Size, 4); 378 379 /* size zero */ 380 Size = 0; 381 Data = 0xDEADFACE; 382 Ret = GetFontResourceInfoW(pszFilePath, &Size, &Data, Case); 383 ok_int(Ret, 1); 384 ok_int(Size, 4); 385 ok_int(Data, 0xDEADFACE); 386 387 /* size non-zero */ 388 Size = sizeof(Data); 389 Data = 0xDEADFACE; 390 Ret = GetFontResourceInfoW(pszFilePath, &Size, &Data, Case); 391 ok_int(Ret, 1); 392 ok_int(Size, 4); 393 ok_int(Data, 0); 394 } 395 396 static void 397 DoEntry(const GFRI_ENTRY *Entry) 398 { 399 WCHAR szPath[MAX_PATH], szTempPath[MAX_PATH]; 400 BOOL Installed = FALSE; 401 402 if (Entry->Preinstalled) 403 { 404 GetSystemFontPath(szPath, Entry->File); 405 printf("GetSystemFontPath: %S\n", szPath); 406 if (GetFileAttributesW(szPath) == INVALID_FILE_ATTRIBUTES) 407 { 408 skip("Font file \"%S\" was not found\n", szPath); 409 return; 410 } 411 } 412 else 413 { 414 /* load font data from resource */ 415 HANDLE hFile; 416 HMODULE hMod = GetModuleHandleW(NULL); 417 HRSRC hRsrc = FindResourceW(hMod, Entry->File, (LPCWSTR)RT_RCDATA); 418 HGLOBAL hGlobal = LoadResource(hMod, hRsrc); 419 DWORD Size = SizeofResource(hMod, hRsrc); 420 LPVOID pFont = LockResource(hGlobal); 421 422 /* get temporary file name */ 423 GetTempPathW(_countof(szTempPath), szTempPath); 424 GetTempFileNameW(szTempPath, L"FNT", 0, szPath); 425 printf("GetTempFileNameW: %S\n", szPath); 426 427 /* write to file */ 428 hFile = CreateFileW(szPath, GENERIC_WRITE, FILE_SHARE_READ, NULL, 429 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 430 WriteFile(hFile, pFont, Size, &Size, NULL); 431 CloseHandle(hFile); 432 433 /* check existence */ 434 if (GetFileAttributesW(szPath) == INVALID_FILE_ATTRIBUTES) 435 { 436 skip("Font file \"%S\" was not stored\n", szPath); 437 return; 438 } 439 440 /* install */ 441 Installed = !!AddFontResourceW(szPath); 442 if (!Installed) 443 { 444 skip("Font file \"%S\" was not installed\n", szPath); 445 RemoveFontResourceW(szPath); 446 DeleteFileW(szPath); 447 return; 448 } 449 } 450 451 Test_GetFontResourceInfoW_case0(szPath, Entry); 452 Test_GetFontResourceInfoW_case1(szPath, Entry); 453 Test_GetFontResourceInfoW_case2(szPath, Entry); 454 Test_GetFontResourceInfoW_case3(szPath, Entry); 455 Test_GetFontResourceInfoW_case4(szPath, Entry); 456 Test_GetFontResourceInfoW_case5(szPath, Entry); 457 458 if (!Entry->Preinstalled) 459 { 460 if (Installed) 461 { 462 RemoveFontResourceW(szPath); 463 DeleteFileW(szPath); 464 } 465 } 466 } 467 468 START_TEST(GetFontResourceInfoW) 469 { 470 INT i; 471 const GFRI_ENTRY *Entry; 472 473 printf("sizeof(LOGFONTW) == %u\n", (int)sizeof(LOGFONTW)); 474 475 for (i = 0; i < _countof(TestEntries); ++i) 476 { 477 Entry = &TestEntries[i]; 478 DoEntry(Entry); 479 } 480 481 if (PRIMARYLANGID(GetSystemDefaultLangID()) == LANG_JAPANESE) 482 { 483 /* Japanese */ 484 for (i = 0; i < _countof(AdditionalTestEntriesJapanese); ++i) 485 { 486 Entry = &AdditionalTestEntriesJapanese[i]; 487 DoEntry(Entry); 488 } 489 } 490 else 491 { 492 /* non-Japanese */ 493 for (i = 0; i < _countof(AdditionalTestEntriesEnglish); ++i) 494 { 495 Entry = &AdditionalTestEntriesEnglish[i]; 496 DoEntry(Entry); 497 } 498 } 499 } 500