| | #include <windows.h> |
| | #include <stdio.h> |
| | #include <stdarg.h> |
| | #include <wchar.h> |
| |
|
| | #include "../src/shared/OsModule.h" |
| | #include "../src/shared/StringUtil.h" |
| |
|
| | #include "TestUtil.cc" |
| | #include "../src/shared/StringUtil.cc" |
| |
|
| | #define COUNT_OF(x) (sizeof(x) / sizeof((x)[0])) |
| |
|
| | |
| | |
| |
|
| | struct AGENT_CONSOLE_FONT_INFO { |
| | DWORD nFont; |
| | COORD dwFontSize; |
| | }; |
| |
|
| | struct AGENT_CONSOLE_FONT_INFOEX { |
| | ULONG cbSize; |
| | DWORD nFont; |
| | COORD dwFontSize; |
| | UINT FontFamily; |
| | UINT FontWeight; |
| | WCHAR FaceName[LF_FACESIZE]; |
| | }; |
| |
|
| | |
| | typedef BOOL WINAPI SetConsoleFont_t( |
| | HANDLE hOutput, |
| | DWORD dwFontIndex); |
| |
|
| | |
| | typedef DWORD WINAPI GetNumberOfConsoleFonts_t(); |
| |
|
| | |
| | typedef BOOL WINAPI GetCurrentConsoleFont_t( |
| | HANDLE hOutput, |
| | BOOL bMaximumWindow, |
| | AGENT_CONSOLE_FONT_INFO *lpConsoleCurrentFont); |
| |
|
| | |
| | typedef COORD WINAPI GetConsoleFontSize_t( |
| | HANDLE hConsoleOutput, |
| | DWORD nFont); |
| |
|
| | |
| | typedef BOOL WINAPI GetCurrentConsoleFontEx_t( |
| | HANDLE hConsoleOutput, |
| | BOOL bMaximumWindow, |
| | AGENT_CONSOLE_FONT_INFOEX *lpConsoleCurrentFontEx); |
| |
|
| | |
| | typedef BOOL WINAPI SetCurrentConsoleFontEx_t( |
| | HANDLE hConsoleOutput, |
| | BOOL bMaximumWindow, |
| | AGENT_CONSOLE_FONT_INFOEX *lpConsoleCurrentFontEx); |
| |
|
| | #define GET_MODULE_PROC(mod, funcName) \ |
| | m_##funcName = reinterpret_cast<funcName##_t*>((mod).proc(#funcName)); \ |
| | |
| | #define DEFINE_ACCESSOR(funcName) \ |
| | funcName##_t &funcName() const { \ |
| | ASSERT(valid()); \ |
| | return *m_##funcName; \ |
| | } |
| |
|
| | class XPFontAPI { |
| | public: |
| | XPFontAPI() : m_kernel32(L"kernel32.dll") { |
| | GET_MODULE_PROC(m_kernel32, GetCurrentConsoleFont); |
| | GET_MODULE_PROC(m_kernel32, GetConsoleFontSize); |
| | } |
| |
|
| | bool valid() const { |
| | return m_GetCurrentConsoleFont != NULL && |
| | m_GetConsoleFontSize != NULL; |
| | } |
| |
|
| | DEFINE_ACCESSOR(GetCurrentConsoleFont) |
| | DEFINE_ACCESSOR(GetConsoleFontSize) |
| |
|
| | private: |
| | OsModule m_kernel32; |
| | GetCurrentConsoleFont_t *m_GetCurrentConsoleFont; |
| | GetConsoleFontSize_t *m_GetConsoleFontSize; |
| | }; |
| |
|
| | class UndocumentedXPFontAPI : public XPFontAPI { |
| | public: |
| | UndocumentedXPFontAPI() : m_kernel32(L"kernel32.dll") { |
| | GET_MODULE_PROC(m_kernel32, SetConsoleFont); |
| | GET_MODULE_PROC(m_kernel32, GetNumberOfConsoleFonts); |
| | } |
| |
|
| | bool valid() const { |
| | return this->XPFontAPI::valid() && |
| | m_SetConsoleFont != NULL && |
| | m_GetNumberOfConsoleFonts != NULL; |
| | } |
| |
|
| | DEFINE_ACCESSOR(SetConsoleFont) |
| | DEFINE_ACCESSOR(GetNumberOfConsoleFonts) |
| |
|
| | private: |
| | OsModule m_kernel32; |
| | SetConsoleFont_t *m_SetConsoleFont; |
| | GetNumberOfConsoleFonts_t *m_GetNumberOfConsoleFonts; |
| | }; |
| |
|
| | class VistaFontAPI : public XPFontAPI { |
| | public: |
| | VistaFontAPI() : m_kernel32(L"kernel32.dll") { |
| | GET_MODULE_PROC(m_kernel32, GetCurrentConsoleFontEx); |
| | GET_MODULE_PROC(m_kernel32, SetCurrentConsoleFontEx); |
| | } |
| |
|
| | bool valid() const { |
| | return this->XPFontAPI::valid() && |
| | m_GetCurrentConsoleFontEx != NULL && |
| | m_SetCurrentConsoleFontEx != NULL; |
| | } |
| |
|
| | DEFINE_ACCESSOR(GetCurrentConsoleFontEx) |
| | DEFINE_ACCESSOR(SetCurrentConsoleFontEx) |
| |
|
| | private: |
| | OsModule m_kernel32; |
| | GetCurrentConsoleFontEx_t *m_GetCurrentConsoleFontEx; |
| | SetCurrentConsoleFontEx_t *m_SetCurrentConsoleFontEx; |
| | }; |
| |
|
| | static std::vector<std::pair<DWORD, COORD> > readFontTable( |
| | XPFontAPI &api, HANDLE conout, DWORD maxCount) { |
| | std::vector<std::pair<DWORD, COORD> > ret; |
| | for (DWORD i = 0; i < maxCount; ++i) { |
| | COORD size = api.GetConsoleFontSize()(conout, i); |
| | if (size.X == 0 && size.Y == 0) { |
| | break; |
| | } |
| | ret.push_back(std::make_pair(i, size)); |
| | } |
| | return ret; |
| | } |
| |
|
| | static void dumpFontTable(HANDLE conout) { |
| | const int kMaxCount = 1000; |
| | XPFontAPI api; |
| | if (!api.valid()) { |
| | printf("dumpFontTable: cannot dump font table -- missing APIs\n"); |
| | return; |
| | } |
| | std::vector<std::pair<DWORD, COORD> > table = |
| | readFontTable(api, conout, kMaxCount); |
| | std::string line; |
| | char tmp[128]; |
| | size_t first = 0; |
| | while (first < table.size()) { |
| | size_t last = std::min(table.size() - 1, first + 10 - 1); |
| | winpty_snprintf(tmp, "%02u-%02u:", |
| | static_cast<unsigned>(first), static_cast<unsigned>(last)); |
| | line = tmp; |
| | for (size_t i = first; i <= last; ++i) { |
| | if (i % 10 == 5) { |
| | line += " - "; |
| | } |
| | winpty_snprintf(tmp, " %2dx%-2d", |
| | table[i].second.X, table[i].second.Y); |
| | line += tmp; |
| | } |
| | printf("%s\n", line.c_str()); |
| | first = last + 1; |
| | } |
| | if (table.size() == kMaxCount) { |
| | printf("... stopped reading at %d fonts ...\n", kMaxCount); |
| | } |
| | } |
| |
|
| | static std::string stringToCodePoints(const std::wstring &str) { |
| | std::string ret = "("; |
| | for (size_t i = 0; i < str.size(); ++i) { |
| | char tmp[32]; |
| | winpty_snprintf(tmp, "%X", str[i]); |
| | if (ret.size() > 1) { |
| | ret.push_back(' '); |
| | } |
| | ret += tmp; |
| | } |
| | ret.push_back(')'); |
| | return ret; |
| | } |
| |
|
| | static void dumpFontInfoEx( |
| | const AGENT_CONSOLE_FONT_INFOEX &infoex) { |
| | std::wstring faceName(infoex.FaceName, |
| | winpty_wcsnlen(infoex.FaceName, COUNT_OF(infoex.FaceName))); |
| | cprintf(L"nFont=%u dwFontSize=(%d,%d) " |
| | "FontFamily=0x%x FontWeight=%u FaceName=%ls %hs\n", |
| | static_cast<unsigned>(infoex.nFont), |
| | infoex.dwFontSize.X, infoex.dwFontSize.Y, |
| | infoex.FontFamily, infoex.FontWeight, faceName.c_str(), |
| | stringToCodePoints(faceName).c_str()); |
| | } |
| |
|
| | static void dumpVistaFont(VistaFontAPI &api, HANDLE conout, BOOL maxWindow) { |
| | AGENT_CONSOLE_FONT_INFOEX infoex = {0}; |
| | infoex.cbSize = sizeof(infoex); |
| | if (!api.GetCurrentConsoleFontEx()(conout, maxWindow, &infoex)) { |
| | printf("GetCurrentConsoleFontEx call failed\n"); |
| | return; |
| | } |
| | dumpFontInfoEx(infoex); |
| | } |
| |
|
| | static void dumpXPFont(XPFontAPI &api, HANDLE conout, BOOL maxWindow) { |
| | AGENT_CONSOLE_FONT_INFO info = {0}; |
| | if (!api.GetCurrentConsoleFont()(conout, maxWindow, &info)) { |
| | printf("GetCurrentConsoleFont call failed\n"); |
| | return; |
| | } |
| | printf("nFont=%u dwFontSize=(%d,%d)\n", |
| | static_cast<unsigned>(info.nFont), |
| | info.dwFontSize.X, info.dwFontSize.Y); |
| | } |
| |
|
| | static void dumpFontAndTable(HANDLE conout) { |
| | VistaFontAPI vista; |
| | if (vista.valid()) { |
| | printf("maxWnd=0: "); dumpVistaFont(vista, conout, FALSE); |
| | printf("maxWnd=1: "); dumpVistaFont(vista, conout, TRUE); |
| | dumpFontTable(conout); |
| | return; |
| | } |
| | UndocumentedXPFontAPI xp; |
| | if (xp.valid()) { |
| | printf("maxWnd=0: "); dumpXPFont(xp, conout, FALSE); |
| | printf("maxWnd=1: "); dumpXPFont(xp, conout, TRUE); |
| | dumpFontTable(conout); |
| | return; |
| | } |
| | printf("setSmallFont: neither Vista nor XP APIs detected -- giving up\n"); |
| | dumpFontTable(conout); |
| | } |
| |
|
| | int main() { |
| | const HANDLE conout = openConout(); |
| | const COORD largest = GetLargestConsoleWindowSize(conout); |
| | printf("largestConsoleWindowSize=(%d,%d)\n", largest.X, largest.Y); |
| | dumpFontAndTable(conout); |
| | UndocumentedXPFontAPI xp; |
| | if (xp.valid()) { |
| | printf("GetNumberOfConsoleFonts returned %u\n", xp.GetNumberOfConsoleFonts()()); |
| | } else { |
| | printf("The GetNumberOfConsoleFonts API was missing\n"); |
| | } |
| | printf("CP=%u OutputCP=%u\n", GetConsoleCP(), GetConsoleOutputCP()); |
| | return 0; |
| | } |
| |
|