198 lines
5.8 KiB
C++
198 lines
5.8 KiB
C++
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT license.
|
|
|
|
#include "precomp.h"
|
|
|
|
#include "TrueTypeFontList.hpp"
|
|
|
|
#include "RegistrySerialization.hpp"
|
|
|
|
#pragma hdrstop
|
|
|
|
#define DEFAULT_NON_DBCS_FONTFACE L"Consolas"
|
|
|
|
SINGLE_LIST_ENTRY TrueTypeFontList::s_ttFontList;
|
|
|
|
WORD ConvertStringToDec(
|
|
__in LPTSTR lpch)
|
|
{
|
|
TCHAR ch;
|
|
WORD val = 0;
|
|
|
|
while ((ch = *lpch) != TEXT('\0'))
|
|
{
|
|
if (TEXT('0') <= ch && ch <= TEXT('9'))
|
|
val = (val * 10) + (ch - TEXT('0'));
|
|
else
|
|
break;
|
|
|
|
lpch++;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
[[nodiscard]] NTSTATUS TrueTypeFontList::s_Initialize()
|
|
{
|
|
HKEY hkRegistry;
|
|
WCHAR awchValue[512];
|
|
WCHAR awchData[512];
|
|
DWORD dwIndex;
|
|
LPWSTR pwsz;
|
|
|
|
// Prevent memory leak. Delete if it's already allocated before refilling it.
|
|
LOG_IF_FAILED(s_Destroy());
|
|
|
|
NTSTATUS Status = RegistrySerialization::s_OpenKey(HKEY_LOCAL_MACHINE,
|
|
MACHINE_REGISTRY_CONSOLE_TTFONT_WIN32_PATH,
|
|
&hkRegistry);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
LPTTFONTLIST pTTFontList;
|
|
|
|
for (dwIndex = 0;; dwIndex++)
|
|
{
|
|
Status = RegistrySerialization::s_EnumValue(hkRegistry,
|
|
dwIndex,
|
|
sizeof(awchValue),
|
|
(LPWSTR)awchValue,
|
|
sizeof(awchData),
|
|
(PBYTE)awchData);
|
|
|
|
if (Status == ERROR_NO_MORE_ITEMS)
|
|
{
|
|
Status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pTTFontList = (TTFONTLIST*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TTFONTLIST));
|
|
if (pTTFontList == nullptr)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pTTFontList->List.Next = nullptr;
|
|
pTTFontList->CodePage = ConvertStringToDec(awchValue);
|
|
pwsz = awchData;
|
|
if (*pwsz == BOLD_MARK)
|
|
{
|
|
pTTFontList->fDisableBold = TRUE;
|
|
pwsz++;
|
|
}
|
|
else
|
|
{
|
|
pTTFontList->fDisableBold = FALSE;
|
|
}
|
|
|
|
StringCchCopyW(pTTFontList->FaceName1,
|
|
ARRAYSIZE(pTTFontList->FaceName1),
|
|
pwsz);
|
|
|
|
// wcslen is only valid on non-null pointers.
|
|
if (pwsz != nullptr)
|
|
{
|
|
pwsz += wcslen(pwsz) + 1;
|
|
|
|
// Validate that pwsz must be pointing to a position in awchData array after the movement.
|
|
if (pwsz >= awchData && pwsz < (awchData + ARRAYSIZE(awchData)))
|
|
{
|
|
if (*pwsz == BOLD_MARK)
|
|
{
|
|
pTTFontList->fDisableBold = TRUE;
|
|
pwsz++;
|
|
}
|
|
StringCchCopyW(pTTFontList->FaceName2,
|
|
ARRAYSIZE(pTTFontList->FaceName2),
|
|
pwsz);
|
|
}
|
|
}
|
|
|
|
PushEntryList(&s_ttFontList, &(pTTFontList->List));
|
|
}
|
|
|
|
RegCloseKey(hkRegistry);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
[[nodiscard]] NTSTATUS TrueTypeFontList::s_Destroy()
|
|
{
|
|
while (s_ttFontList.Next != nullptr)
|
|
{
|
|
LPTTFONTLIST pTTFontList = (LPTTFONTLIST)PopEntryList(&s_ttFontList);
|
|
|
|
if (pTTFontList != nullptr)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, pTTFontList);
|
|
}
|
|
}
|
|
|
|
s_ttFontList.Next = nullptr;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
LPTTFONTLIST TrueTypeFontList::s_SearchByName(_In_opt_ LPCWSTR pwszFace,
|
|
_In_ BOOL fCodePage,
|
|
_In_ UINT CodePage)
|
|
{
|
|
PSINGLE_LIST_ENTRY pTemp = s_ttFontList.Next;
|
|
|
|
if (pwszFace)
|
|
{
|
|
while (pTemp != nullptr)
|
|
{
|
|
LPTTFONTLIST pTTFontList = (LPTTFONTLIST)pTemp;
|
|
|
|
if (wcscmp(pwszFace, pTTFontList->FaceName1) == 0 ||
|
|
wcscmp(pwszFace, pTTFontList->FaceName2) == 0)
|
|
{
|
|
if (fCodePage)
|
|
if (pTTFontList->CodePage == CodePage)
|
|
return pTTFontList;
|
|
else
|
|
return nullptr;
|
|
else
|
|
return pTTFontList;
|
|
}
|
|
|
|
pTemp = pTemp->Next;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
[[nodiscard]] NTSTATUS TrueTypeFontList::s_SearchByCodePage(const UINT uiCodePage,
|
|
_Out_writes_(cchFaceName) PWSTR pwszFaceName,
|
|
const size_t cchFaceName)
|
|
{
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
BOOL fFontFound = FALSE;
|
|
|
|
// Look through our list entries to see if we can find a corresponding truetype font for this codepage
|
|
for (PSINGLE_LIST_ENTRY pListEntry = s_ttFontList.Next; pListEntry != nullptr && !fFontFound; pListEntry = pListEntry->Next)
|
|
{
|
|
LPTTFONTLIST pTTFontEntry = (LPTTFONTLIST)pListEntry;
|
|
if (pTTFontEntry->CodePage == uiCodePage)
|
|
{
|
|
// found a match, use this font's primary facename
|
|
status = StringCchCopyW(pwszFaceName, cchFaceName, pTTFontEntry->FaceName1);
|
|
fFontFound = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!fFontFound)
|
|
{
|
|
status = StringCchCopyW(pwszFaceName, cchFaceName, DEFAULT_NON_DBCS_FONTFACE);
|
|
}
|
|
|
|
return status;
|
|
}
|