1 /*
2  * PROJECT:         ReactOS API tests
3  * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
4  * PURPOSE:         Test for EnumFontFamilies[Ex]
5  * PROGRAMMERS:     Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include "precomp.h"
9 
10 static BYTE ContextContinue;
11 static BYTE ContextStop;
12 
13 static int EnumProcCalls;
14 static ENUMLOGFONTA LastFontA;
15 static ENUMLOGFONTW LastFontW;
16 
17 typedef int WRAP_ENUM_FONT_FAMILIES(_In_ HDC, _In_ PCWSTR, _In_ PVOID, _In_ LPARAM);
18 typedef WRAP_ENUM_FONT_FAMILIES *PWRAP_ENUM_FONT_FAMILIES;
19 
20 static
21 int
22 WrapEnumFontFamiliesA(
23     _In_ HDC hdc,
24     _In_ PCWSTR Family,
25     _In_ PVOID EnumProc,
26     _In_ LPARAM lParam)
27 {
28     char FamilyA[100];
29     WideCharToMultiByte(CP_ACP, 0, Family, -1, FamilyA, sizeof(FamilyA), NULL, NULL);
30     return EnumFontFamiliesA(hdc, FamilyA, EnumProc, lParam);
31 }
32 
33 static
34 int
35 WrapEnumFontFamiliesW(
36     _In_ HDC hdc,
37     _In_ PCWSTR Family,
38     _In_ PVOID EnumProc,
39     _In_ LPARAM lParam)
40 {
41     return EnumFontFamiliesW(hdc, Family, EnumProc, lParam);
42 }
43 
44 static
45 int
46 WrapEnumFontFamiliesExA(
47     _In_ HDC hdc,
48     _In_ PCWSTR Family,
49     _In_ PVOID EnumProc,
50     _In_ LPARAM lParam)
51 {
52     LOGFONTA lf;
53 
54     ZeroMemory(&lf, sizeof(lf));
55     lf.lfCharSet = DEFAULT_CHARSET;
56     lf.lfPitchAndFamily = 0;
57     WideCharToMultiByte(CP_ACP, 0, Family, -1, lf.lfFaceName, sizeof(lf.lfFaceName), NULL, NULL);
58     return EnumFontFamiliesExA(hdc, &lf, EnumProc, lParam, 0);
59 }
60 
61 static
62 int
63 WrapEnumFontFamiliesExW(
64     _In_ HDC hdc,
65     _In_ PCWSTR Family,
66     _In_ PVOID EnumProc,
67     _In_ LPARAM lParam)
68 {
69     LOGFONTW lf;
70 
71     ZeroMemory(&lf, sizeof(lf));
72     lf.lfCharSet = DEFAULT_CHARSET;
73     lf.lfPitchAndFamily = 0;
74     StringCbCopyW(lf.lfFaceName, sizeof(lf.lfFaceName), Family);
75     return EnumFontFamiliesExW(hdc, &lf, EnumProc, lParam, 0);
76 }
77 
78 static
79 int
80 CALLBACK
81 EnumProcA(
82     _In_ const LOGFONTA *elf,
83     _In_ const TEXTMETRICA *ntm,
84     _In_ DWORD FontType,
85     _In_ LPARAM lParam)
86 {
87     EnumProcCalls++;
88 
89     ok(lParam == (LPARAM)&ContextContinue ||
90        lParam == (LPARAM)&ContextStop,
91        "Context is %p, expected %p or %p\n",
92        (PVOID)lParam, &ContextContinue, &ContextStop);
93 
94     LastFontA = *(ENUMLOGFONTA *)elf;
95     return lParam == (LPARAM)&ContextContinue ? 7 : 0;
96 }
97 
98 static
99 int
100 CALLBACK
101 EnumProcW(
102     _In_ const LOGFONTW *elf,
103     _In_ const TEXTMETRICW *ntm,
104     _In_ DWORD FontType,
105     _In_ LPARAM lParam)
106 {
107     EnumProcCalls++;
108 
109     ok(lParam == (LPARAM)&ContextContinue ||
110        lParam == (LPARAM)&ContextStop,
111        "Context is %p, expected %p or %p\n",
112        (PVOID)lParam, &ContextContinue, &ContextStop);
113 
114     LastFontW = *(ENUMLOGFONTW *)elf;
115     return lParam == (LPARAM)&ContextContinue ? 7 : 0;
116 }
117 
118 static
119 void
120 TestEnumFontFamilies(
121     _In_ HDC hdc,
122     _In_ PCWSTR FontName,
123     _In_ BOOLEAN ExpectToFind)
124 {
125     const struct
126     {
127         PWRAP_ENUM_FONT_FAMILIES Wrapper;
128         PCSTR Name;
129         BOOLEAN Wide;
130     } *fun, functions[] =
131     {
132         { WrapEnumFontFamiliesA,    "EnumFontFamiliesA",    FALSE },
133         { WrapEnumFontFamiliesW,    "EnumFontFamiliesW",    TRUE },
134         { WrapEnumFontFamiliesExA,  "EnumFontFamiliesExA",  FALSE },
135         { WrapEnumFontFamiliesExW,  "EnumFontFamiliesExW",  TRUE },
136     };
137     const struct
138     {
139         PVOID Context;
140         PCSTR Description;
141     } *ctx, contexts[] =
142     {
143         { &ContextContinue, "Continue" },
144         { &ContextStop,     "Stop" },
145     };
146     int ret;
147     DWORD error;
148     unsigned iFunction;
149     unsigned iContext;
150 
151     for (iContext = 0; iContext < _countof(contexts); iContext++)
152     {
153         ctx = &contexts[iContext];
154         for (iFunction = 0; iFunction < _countof(functions); iFunction++)
155         {
156             fun = &functions[iFunction];
157             EnumProcCalls = 0;
158             SetLastError(0xdeadbeef);
159             ret = fun->Wrapper(hdc,
160                                FontName,
161                                fun->Wide ? (PVOID)EnumProcW : (PVOID)EnumProcA,
162                                (LPARAM)ctx->Context);
163             error = GetLastError();
164             ok(error == 0xdeadbeef, "[%s, %s, '%ls'] error is %lu\n", fun->Name, ctx->Description, FontName, error);
165             if (ExpectToFind)
166             {
167                 if (ctx->Context == &ContextContinue)
168                 {
169                     ok(ret == 7, "[%s, %s, '%ls'] ret is %d, expected 7\n", fun->Name, ctx->Description, FontName, ret);
170                     ok(EnumProcCalls >= 1, "[%s, %s, '%ls'] EnumProcCalls is %d\n", fun->Name, ctx->Description, FontName, EnumProcCalls);
171                 }
172                 else
173                 {
174                     ok(ret == 0, "[%s, %s, '%ls'] ret is %d, expected 0\n", fun->Name, ctx->Description, FontName, ret);
175                     ok(EnumProcCalls == 1, "[%s, %s, '%ls'] EnumProcCalls is %d\n", fun->Name, ctx->Description, FontName, EnumProcCalls);
176                 }
177             }
178             else
179             {
180                 ok(ret == 1, "[%s, %s, '%ls'] ret is %d, expected 1\n", fun->Name, ctx->Description, FontName, ret);
181                 ok(EnumProcCalls == 0, "[%s, %s, '%ls'] EnumProcCalls is %d\n", fun->Name, ctx->Description, FontName, EnumProcCalls);
182             }
183         }
184     }
185 }
186 
187 START_TEST(EnumFontFamilies)
188 {
189     HDC hdc;
190 
191     hdc = CreateCompatibleDC(NULL);
192     if (!hdc)
193     {
194         skip("No DC\n");
195         return;
196     }
197 
198     TestEnumFontFamilies(hdc, L"ThisFontDoesNotExist", FALSE);
199     /* Basic fonts that should be installed */
200     TestEnumFontFamilies(hdc, L"MS Sans Serif", TRUE);
201     TestEnumFontFamilies(hdc, L"Tahoma", TRUE);
202     TestEnumFontFamilies(hdc, L"System", TRUE);
203     /* Show case insensitivity */
204     TestEnumFontFamilies(hdc, L"tahOmA", TRUE);
205     /* Special fonts that we have a hack for in win32k ;) */
206     TestEnumFontFamilies(hdc, L"Marlett", TRUE);
207     TestEnumFontFamilies(hdc, L"Symbol", TRUE);
208     TestEnumFontFamilies(hdc, L"VGA", FALSE);
209 
210     DeleteDC(hdc);
211 }
212 
213