1 | #include <windows.h>
|
2 | #include <stdio.h>
|
3 | #include <stdarg.h>
|
4 | #include <wchar.h>
|
5 |
|
6 | #include "../src/shared/OsModule.h"
|
7 | #include "../src/shared/StringUtil.h"
|
8 |
|
9 | #include "TestUtil.cc"
|
10 | #include "../src/shared/StringUtil.cc"
|
11 |
|
12 | #define COUNT_OF(x) (sizeof(x) / sizeof((x)[0]))
|
13 |
|
14 |
|
15 |
|
16 |
|
17 | struct AGENT_CONSOLE_FONT_INFO {
|
18 | DWORD nFont;
|
19 | COORD dwFontSize;
|
20 | };
|
21 |
|
22 | struct AGENT_CONSOLE_FONT_INFOEX {
|
23 | ULONG cbSize;
|
24 | DWORD nFont;
|
25 | COORD dwFontSize;
|
26 | UINT FontFamily;
|
27 | UINT FontWeight;
|
28 | WCHAR FaceName[LF_FACESIZE];
|
29 | };
|
30 |
|
31 |
|
32 | typedef BOOL WINAPI SetConsoleFont_t(
|
33 | HANDLE hOutput,
|
34 | DWORD dwFontIndex);
|
35 |
|
36 |
|
37 | typedef DWORD WINAPI GetNumberOfConsoleFonts_t();
|
38 |
|
39 |
|
40 | typedef BOOL WINAPI GetCurrentConsoleFont_t(
|
41 | HANDLE hOutput,
|
42 | BOOL bMaximumWindow,
|
43 | AGENT_CONSOLE_FONT_INFO *lpConsoleCurrentFont);
|
44 |
|
45 |
|
46 | typedef COORD WINAPI GetConsoleFontSize_t(
|
47 | HANDLE hConsoleOutput,
|
48 | DWORD nFont);
|
49 |
|
50 |
|
51 | typedef BOOL WINAPI GetCurrentConsoleFontEx_t(
|
52 | HANDLE hConsoleOutput,
|
53 | BOOL bMaximumWindow,
|
54 | AGENT_CONSOLE_FONT_INFOEX *lpConsoleCurrentFontEx);
|
55 |
|
56 |
|
57 | typedef BOOL WINAPI SetCurrentConsoleFontEx_t(
|
58 | HANDLE hConsoleOutput,
|
59 | BOOL bMaximumWindow,
|
60 | AGENT_CONSOLE_FONT_INFOEX *lpConsoleCurrentFontEx);
|
61 |
|
62 | #define GET_MODULE_PROC(mod, funcName) \
|
63 | m_##funcName = reinterpret_cast<funcName##_t*>((mod).proc(#funcName)); \
|
64 |
|
65 | #define DEFINE_ACCESSOR(funcName) \
|
66 | funcName##_t &funcName() const { \
|
67 | ASSERT(valid()); \
|
68 | return *m_##funcName; \
|
69 | }
|
70 |
|
71 | class XPFontAPI {
|
72 | public:
|
73 | XPFontAPI() : m_kernel32(L"kernel32.dll") {
|
74 | GET_MODULE_PROC(m_kernel32, GetCurrentConsoleFont);
|
75 | GET_MODULE_PROC(m_kernel32, GetConsoleFontSize);
|
76 | }
|
77 |
|
78 | bool valid() const {
|
79 | return m_GetCurrentConsoleFont != NULL &&
|
80 | m_GetConsoleFontSize != NULL;
|
81 | }
|
82 |
|
83 | DEFINE_ACCESSOR(GetCurrentConsoleFont)
|
84 | DEFINE_ACCESSOR(GetConsoleFontSize)
|
85 |
|
86 | private:
|
87 | OsModule m_kernel32;
|
88 | GetCurrentConsoleFont_t *m_GetCurrentConsoleFont;
|
89 | GetConsoleFontSize_t *m_GetConsoleFontSize;
|
90 | };
|
91 |
|
92 | class UndocumentedXPFontAPI : public XPFontAPI {
|
93 | public:
|
94 | UndocumentedXPFontAPI() : m_kernel32(L"kernel32.dll") {
|
95 | GET_MODULE_PROC(m_kernel32, SetConsoleFont);
|
96 | GET_MODULE_PROC(m_kernel32, GetNumberOfConsoleFonts);
|
97 | }
|
98 |
|
99 | bool valid() const {
|
100 | return this->XPFontAPI::valid() &&
|
101 | m_SetConsoleFont != NULL &&
|
102 | m_GetNumberOfConsoleFonts != NULL;
|
103 | }
|
104 |
|
105 | DEFINE_ACCESSOR(SetConsoleFont)
|
106 | DEFINE_ACCESSOR(GetNumberOfConsoleFonts)
|
107 |
|
108 | private:
|
109 | OsModule m_kernel32;
|
110 | SetConsoleFont_t *m_SetConsoleFont;
|
111 | GetNumberOfConsoleFonts_t *m_GetNumberOfConsoleFonts;
|
112 | };
|
113 |
|
114 | class VistaFontAPI : public XPFontAPI {
|
115 | public:
|
116 | VistaFontAPI() : m_kernel32(L"kernel32.dll") {
|
117 | GET_MODULE_PROC(m_kernel32, GetCurrentConsoleFontEx);
|
118 | GET_MODULE_PROC(m_kernel32, SetCurrentConsoleFontEx);
|
119 | }
|
120 |
|
121 | bool valid() const {
|
122 | return this->XPFontAPI::valid() &&
|
123 | m_GetCurrentConsoleFontEx != NULL &&
|
124 | m_SetCurrentConsoleFontEx != NULL;
|
125 | }
|
126 |
|
127 | DEFINE_ACCESSOR(GetCurrentConsoleFontEx)
|
128 | DEFINE_ACCESSOR(SetCurrentConsoleFontEx)
|
129 |
|
130 | private:
|
131 | OsModule m_kernel32;
|
132 | GetCurrentConsoleFontEx_t *m_GetCurrentConsoleFontEx;
|
133 | SetCurrentConsoleFontEx_t *m_SetCurrentConsoleFontEx;
|
134 | };
|
135 |
|
136 | static std::vector<std::pair<DWORD, COORD> > readFontTable(
|
137 | XPFontAPI &api, HANDLE conout, DWORD maxCount) {
|
138 | std::vector<std::pair<DWORD, COORD> > ret;
|
139 | for (DWORD i = 0; i < maxCount; ++i) {
|
140 | COORD size = api.GetConsoleFontSize()(conout, i);
|
141 | if (size.X == 0 && size.Y == 0) {
|
142 | break;
|
143 | }
|
144 | ret.push_back(std::make_pair(i, size));
|
145 | }
|
146 | return ret;
|
147 | }
|
148 |
|
149 | static void dumpFontTable(HANDLE conout) {
|
150 | const int kMaxCount = 1000;
|
151 | XPFontAPI api;
|
152 | if (!api.valid()) {
|
153 | printf("dumpFontTable: cannot dump font table -- missing APIs\n");
|
154 | return;
|
155 | }
|
156 | std::vector<std::pair<DWORD, COORD> > table =
|
157 | readFontTable(api, conout, kMaxCount);
|
158 | std::string line;
|
159 | char tmp[128];
|
160 | size_t first = 0;
|
161 | while (first < table.size()) {
|
162 | size_t last = std::min(table.size() - 1, first + 10 - 1);
|
163 | winpty_snprintf(tmp, "%02u-%02u:",
|
164 | static_cast<unsigned>(first), static_cast<unsigned>(last));
|
165 | line = tmp;
|
166 | for (size_t i = first; i <= last; ++i) {
|
167 | if (i % 10 == 5) {
|
168 | line += " - ";
|
169 | }
|
170 | winpty_snprintf(tmp, " %2dx%-2d",
|
171 | table[i].second.X, table[i].second.Y);
|
172 | line += tmp;
|
173 | }
|
174 | printf("%s\n", line.c_str());
|
175 | first = last + 1;
|
176 | }
|
177 | if (table.size() == kMaxCount) {
|
178 | printf("... stopped reading at %d fonts ...\n", kMaxCount);
|
179 | }
|
180 | }
|
181 |
|
182 | static std::string stringToCodePoints(const std::wstring &str) {
|
183 | std::string ret = "(";
|
184 | for (size_t i = 0; i < str.size(); ++i) {
|
185 | char tmp[32];
|
186 | winpty_snprintf(tmp, "%X", str[i]);
|
187 | if (ret.size() > 1) {
|
188 | ret.push_back(' ');
|
189 | }
|
190 | ret += tmp;
|
191 | }
|
192 | ret.push_back(')');
|
193 | return ret;
|
194 | }
|
195 |
|
196 | static void dumpFontInfoEx(
|
197 | const AGENT_CONSOLE_FONT_INFOEX &infoex) {
|
198 | std::wstring faceName(infoex.FaceName,
|
199 | winpty_wcsnlen(infoex.FaceName, COUNT_OF(infoex.FaceName)));
|
200 | cprintf(L"nFont=%u dwFontSize=(%d,%d) "
|
201 | "FontFamily=0x%x FontWeight=%u FaceName=%ls %hs\n",
|
202 | static_cast<unsigned>(infoex.nFont),
|
203 | infoex.dwFontSize.X, infoex.dwFontSize.Y,
|
204 | infoex.FontFamily, infoex.FontWeight, faceName.c_str(),
|
205 | stringToCodePoints(faceName).c_str());
|
206 | }
|
207 |
|
208 | static void dumpVistaFont(VistaFontAPI &api, HANDLE conout, BOOL maxWindow) {
|
209 | AGENT_CONSOLE_FONT_INFOEX infoex = {0};
|
210 | infoex.cbSize = sizeof(infoex);
|
211 | if (!api.GetCurrentConsoleFontEx()(conout, maxWindow, &infoex)) {
|
212 | printf("GetCurrentConsoleFontEx call failed\n");
|
213 | return;
|
214 | }
|
215 | dumpFontInfoEx(infoex);
|
216 | }
|
217 |
|
218 | static void dumpXPFont(XPFontAPI &api, HANDLE conout, BOOL maxWindow) {
|
219 | AGENT_CONSOLE_FONT_INFO info = {0};
|
220 | if (!api.GetCurrentConsoleFont()(conout, maxWindow, &info)) {
|
221 | printf("GetCurrentConsoleFont call failed\n");
|
222 | return;
|
223 | }
|
224 | printf("nFont=%u dwFontSize=(%d,%d)\n",
|
225 | static_cast<unsigned>(info.nFont),
|
226 | info.dwFontSize.X, info.dwFontSize.Y);
|
227 | }
|
228 |
|
229 | static void dumpFontAndTable(HANDLE conout) {
|
230 | VistaFontAPI vista;
|
231 | if (vista.valid()) {
|
232 | printf("maxWnd=0: "); dumpVistaFont(vista, conout, FALSE);
|
233 | printf("maxWnd=1: "); dumpVistaFont(vista, conout, TRUE);
|
234 | dumpFontTable(conout);
|
235 | return;
|
236 | }
|
237 | UndocumentedXPFontAPI xp;
|
238 | if (xp.valid()) {
|
239 | printf("maxWnd=0: "); dumpXPFont(xp, conout, FALSE);
|
240 | printf("maxWnd=1: "); dumpXPFont(xp, conout, TRUE);
|
241 | dumpFontTable(conout);
|
242 | return;
|
243 | }
|
244 | printf("setSmallFont: neither Vista nor XP APIs detected -- giving up\n");
|
245 | dumpFontTable(conout);
|
246 | }
|
247 |
|
248 | int main() {
|
249 | const HANDLE conout = openConout();
|
250 | const COORD largest = GetLargestConsoleWindowSize(conout);
|
251 | printf("largestConsoleWindowSize=(%d,%d)\n", largest.X, largest.Y);
|
252 | dumpFontAndTable(conout);
|
253 | UndocumentedXPFontAPI xp;
|
254 | if (xp.valid()) {
|
255 | printf("GetNumberOfConsoleFonts returned %u\n", xp.GetNumberOfConsoleFonts()());
|
256 | } else {
|
257 | printf("The GetNumberOfConsoleFonts API was missing\n");
|
258 | }
|
259 | printf("CP=%u OutputCP=%u\n", GetConsoleCP(), GetConsoleOutputCP());
|
260 | return 0;
|
261 | }
|