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