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
GetSystemFontDirectory(LPWSTR pszDir)92 GetSystemFontDirectory(LPWSTR pszDir)
93 {
94 GetWindowsDirectoryW(pszDir, MAX_PATH);
95 lstrcatW(pszDir, L"\\Fonts");
96 }
97
98 static void
GetSystemFontPath(LPWSTR pszPath,LPCWSTR pszFile)99 GetSystemFontPath(LPWSTR pszPath, LPCWSTR pszFile)
100 {
101 GetSystemFontDirectory(pszPath);
102 lstrcatW(pszPath, L"\\");
103 lstrcatW(pszPath, pszFile);
104 }
105
106 static INT
GetMultiSzLength(const WCHAR * pszz)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
ReplaceChars(WCHAR * pch,INT Len,WCHAR From,WCHAR To)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
SzFromMultiSz(WCHAR * pszz)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
Test_GetFontResourceInfoW_case0(LPCWSTR pszFilePath,const GFRI_ENTRY * Entry)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
Test_GetFontResourceInfoW_case1(LPCWSTR pszFilePath,const GFRI_ENTRY * Entry)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
Test_GetFontResourceInfoW_case2(LPCWSTR pszFilePath,const GFRI_ENTRY * Entry)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
Test_GetFontResourceInfoW_case3(LPCWSTR pszFilePath,const GFRI_ENTRY * Entry)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
Test_GetFontResourceInfoW_case4(LPCWSTR pszFilePath,const GFRI_ENTRY * Entry)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
Test_GetFontResourceInfoW_case5(LPCWSTR pszFilePath,const GFRI_ENTRY * Entry)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
DoEntry(const GFRI_ENTRY * Entry)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
START_TEST(GetFontResourceInfoW)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