[NTGDI][GDI32] AddFontResource: Support multiple files (#7833)

JIRA issue: CORE-17684
- Add HEAP_strdupA2W_buf and HEAP_strdupA2W_buf_free
  helper functions for quick string conversion.
- Optimize HEAP_... functions.
- Add IntConvertFontPaths helper function.
- Support multiple files in AddFontResource function.
- Add cFiles parameter to some internal font addition/
  removal functions.
- Half-implement NtGdiRemoveFontResourceW and
  RemoveFontResourceExW functions.
This commit is contained in:
Katayama Hirofumi MZ 2025-04-04 19:30:18 +09:00 committed by GitHub
parent 72bd9ef29a
commit 1890ad20f8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 506 additions and 232 deletions

View file

@ -1179,23 +1179,6 @@ NtGdiGetStringBitmapW(
return 0;
}
/*
* @unimplemented
*/
BOOL
APIENTRY
NtGdiRemoveFontResourceW(
IN WCHAR *pwszFiles,
IN ULONG cwc,
IN ULONG cFiles,
IN ULONG fl,
IN DWORD dwPidTid,
IN OPTIONAL DESIGNVECTOR *pdv)
{
UNIMPLEMENTED;
return FALSE;
}
/*
* @unimplemented
*/

View file

@ -208,20 +208,46 @@ typedef DWORD (WINAPI *QUERYREMOTEFONTS) (DWORD,DWORD,DWORD);
extern CLOSEPRINTER fpClosePrinter;
extern OPENPRINTERW fpOpenPrinterW;
extern HANDLE hProcessHeap;
/* FUNCTIONS *****************************************************************/
PVOID
HEAP_alloc(DWORD len);
static inline
_Ret_maybenull_
__drv_allocatesMem(Mem)
PVOID FASTCALL
HEAP_alloc(_In_ SIZE_T len)
{
ASSERT(hProcessHeap);
return RtlAllocateHeap(hProcessHeap, 0, len);
}
NTSTATUS
HEAP_strdupA2W(
LPWSTR* ppszW,
LPCSTR lpszA
);
static inline VOID FASTCALL
HEAP_free(_In_ __drv_freesMem(Mem) PVOID memory)
{
ASSERT(hProcessHeap);
RtlFreeHeap(hProcessHeap, 0, memory);
}
VOID
HEAP_free(LPVOID memory);
NTSTATUS FASTCALL
HEAP_strdupA2W(_Outptr_ PWSTR* ppszW, _In_ PCSTR lpszA);
/* Buffered string conversion (quicker) */
PWSTR FASTCALL
HEAP_strdupA2W_buf(
_In_ PCSTR lpszA,
_In_ PWSTR pszStaticBuff,
_In_ SIZE_T cchStaticBuff);
/* Free memory allocated by HEAP_strdupA2W_buf */
static inline VOID FASTCALL
HEAP_strdupA2W_buf_free(
_In_opt_ PWSTR pszDynamicBuff,
_In_ PWSTR pszStaticBuff)
{
if (pszDynamicBuff && pszDynamicBuff != pszStaticBuff)
HEAP_free(pszDynamicBuff);
}
VOID
FASTCALL

View file

@ -30,17 +30,8 @@
// global variables in a dll are process-global
HANDLE hProcessHeap = NULL;
PVOID
HEAP_alloc ( DWORD len )
{
/* make sure hProcessHeap gets initialized by GdiProcessSetup before we get here */
assert(hProcessHeap);
return RtlAllocateHeap ( hProcessHeap, 0, len );
}
NTSTATUS
HEAP_strdupA2W ( LPWSTR* ppszW, LPCSTR lpszA )
NTSTATUS FASTCALL
HEAP_strdupA2W(_Outptr_ PWSTR* ppszW, _In_ PCSTR lpszA)
{
ULONG len;
NTSTATUS Status;
@ -54,16 +45,24 @@ HEAP_strdupA2W ( LPWSTR* ppszW, LPCSTR lpszA )
if ( !*ppszW )
return STATUS_NO_MEMORY;
Status = RtlMultiByteToUnicodeN ( *ppszW, len*sizeof(WCHAR), NULL, (PCHAR)lpszA, len );
(*ppszW)[len] = L'\0';
(*ppszW)[len] = UNICODE_NULL;
return Status;
}
VOID
HEAP_free ( LPVOID memory )
PWSTR FASTCALL
HEAP_strdupA2W_buf(
_In_ PCSTR lpszA,
_In_ PWSTR pszStaticBuff,
_In_ SIZE_T cchStaticBuff)
{
/* make sure hProcessHeap gets initialized by GdiProcessSetup before we get here */
assert(hProcessHeap);
if (!lpszA)
return NULL;
RtlFreeHeap ( hProcessHeap, 0, memory );
SIZE_T size = strlen(lpszA) + 1;
PWSTR pszW = (size < cchStaticBuff) ? pszStaticBuff : HEAP_alloc(size * sizeof(WCHAR));
if (!pszW)
return NULL;
RtlMultiByteToUnicodeN(pszW, size * sizeof(WCHAR), NULL, lpszA, size);
return pszW;
}

View file

@ -1,10 +1,12 @@
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS system libraries
* FILE: win32ss/gdi/gdi32/objects/font.c
* PURPOSE:
* PROGRAMMER:
*
* PROJECT: ReactOS GDI32
* LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Font manipulation API
* COPYRIGHT: Copyright 2019 James Tabor
* Copyright 2019 Pierre Schweitzer (heis_spiter@hotmail.com)
* Copyright 2019-2021 Hermes Belusca-Maito (hermes.belusca-maito@reactos.org)
* Copyright 2018 Baruch Rutman (peterooch@gmail.com)
* Copyright 2025 Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
*/
#include <precomp.h>
@ -1939,6 +1941,144 @@ CreateFontW(
return CreateFontIndirectW(&logfont);
}
// Convert single or multiple font path(s)
PWSTR
FASTCALL
IntConvertFontPaths(
_In_ PCWSTR pszFiles,
_Out_ PDWORD pcFiles,
_Out_ PDWORD pcwc,
_Inout_ PDWORD pfl,
_In_ BOOL bFlag)
{
// FIXME: pfl
// FIXME: bFlag
*pcwc = *pcFiles = 0;
if (!*pszFiles)
{
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
// Build "Fonts" path
WCHAR szFontsDir[MAX_PATH];
GetWindowsDirectoryW(szFontsDir, _countof(szFontsDir));
StringCchCatW(szFontsDir, _countof(szFontsDir), L"\\Fonts");
// Count the number of paths separated by '|'.
ULONG pathCount = 1;
for (PCWSTR pch1 = pszFiles; *pch1; ++pch1)
{
if (*pch1 == L'|')
pathCount++;
}
// Allocate memory for the paths.
SIZE_T cchBuff = pathCount * MAX_PATH;
PWSTR pszBuff = HEAP_alloc(cchBuff * sizeof(WCHAR));
if (!pszBuff)
return NULL;
pszBuff[0] = UNICODE_NULL;
*pcFiles = pathCount;
// Convert paths
DWORD dwError = ERROR_SUCCESS;
PCWSTR pch1, pch1Prev;
BOOL bFirst = TRUE;
for (pch1 = pch1Prev = pszFiles;; ++pch1)
{
if (*pch1 && *pch1 != L'|')
continue;
UINT_PTR spanLen = pch1 - pch1Prev;
if (spanLen < _countof(L".ttf") || spanLen >= MAX_PATH)
{
dwError = ERROR_INVALID_FUNCTION;
break;
}
WCHAR szFileName[MAX_PATH], szFullPath[MAX_PATH];
StringCchCopyNW(szFileName, _countof(szFileName), pch1Prev, spanLen);
// Search file
if (!SearchPathW(L".", szFileName, NULL, _countof(szFullPath), szFullPath, NULL) &&
!SearchPathW(szFontsDir, szFileName, NULL, _countof(szFullPath), szFullPath, NULL))
{
dwError = ERROR_FILE_NOT_FOUND;
break;
}
if (bFirst)
{
bFirst = FALSE;
}
else
{
SIZE_T cch = wcslen(szFullPath);
if (cch < _countof(L".pfb"))
{
dwError = ERROR_INVALID_FUNCTION;
break;
}
// Check filename extension
PCWSTR pchDotExt = &szFullPath[cch - 4];
if (_wcsicmp(pchDotExt, L".pfb") != 0 &&
_wcsicmp(pchDotExt, L".mmm") != 0)
{
dwError = ERROR_INVALID_FUNCTION;
break;
}
}
// Convert to an NT path
UNICODE_STRING NtAbsPath;
if (!RtlDosPathNameToNtPathName_U(szFullPath, &NtAbsPath, NULL, NULL))
{
dwError = ERROR_OUTOFMEMORY;
break;
}
// Append a path and '|' to pszBuff
if (StringCchCatW(pszBuff, cchBuff, NtAbsPath.Buffer) != S_OK ||
StringCchCatW(pszBuff, cchBuff, L"|") != S_OK)
{
RtlFreeUnicodeString(&NtAbsPath);
dwError = ERROR_INVALID_FUNCTION;
break;
}
RtlFreeUnicodeString(&NtAbsPath);
if (!*pch1)
break;
pch1Prev = pch1 + 1;
}
if (dwError != ERROR_SUCCESS)
{
HEAP_free(pszBuff);
*pcwc = *pcFiles = 0;
if (dwError != ERROR_INVALID_FUNCTION)
SetLastError(dwError);
return NULL;
}
*pcwc = (DWORD)wcslen(pszBuff);
// Convert '|' to '\0'
for (PWSTR pch2 = pszBuff; *pch2; ++pch2)
{
if (*pch2 == L'|')
*pch2 = UNICODE_NULL;
}
return pszBuff;
}
/*
* @unimplemented
@ -1955,124 +2095,146 @@ CreateScalableFontResourceA(
return FALSE;
}
/*
* @implemented
*/
int
/* @implemented */
INT
WINAPI
AddFontResourceExW ( LPCWSTR lpszFilename, DWORD fl, PVOID pvReserved )
AddFontResourceExW(
_In_ LPCWSTR lpszFilename,
_In_ DWORD fl,
_In_opt_ PVOID pvReserved)
{
if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
{
SetLastError( ERROR_INVALID_PARAMETER );
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
return GdiAddFontResourceW(lpszFilename, fl,0);
return GdiAddFontResourceW(lpszFilename, fl, NULL);
}
/*
* @implemented
*/
int
/* @implemented */
INT
WINAPI
AddFontResourceExA ( LPCSTR lpszFilename, DWORD fl, PVOID pvReserved )
AddFontResourceExA(
_In_ LPCSTR lpszFilename,
_In_ DWORD fl,
_In_opt_ PVOID pvReserved)
{
NTSTATUS Status;
PWSTR FilenameW;
int rc;
if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
{
SetLastError( ERROR_INVALID_PARAMETER );
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
if ( !NT_SUCCESS (Status) )
{
SetLastError (RtlNtStatusToDosError(Status));
if (!lpszFilename)
return 0;
}
rc = GdiAddFontResourceW ( FilenameW, fl, 0 );
HEAP_free ( FilenameW );
return rc;
}
/*
* @implemented
*/
int
WINAPI
AddFontResourceA ( LPCSTR lpszFilename )
{
NTSTATUS Status;
PWSTR FilenameW;
int rc = 0;
WCHAR szBuff[MAX_PATH];
Status = HEAP_strdupA2W ( &FilenameW, lpszFilename );
if ( !NT_SUCCESS (Status) )
_SEH2_TRY
{
SetLastError (RtlNtStatusToDosError(Status));
FilenameW = HEAP_strdupA2W_buf(lpszFilename, szBuff, _countof(szBuff));
}
else
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
rc = GdiAddFontResourceW ( FilenameW, 0, 0);
HEAP_free ( FilenameW );
_SEH2_YIELD(return 0);
}
return rc;
_SEH2_END;
if (!FilenameW)
{
SetLastError(ERROR_OUTOFMEMORY);
return 0;
}
INT ret = GdiAddFontResourceW(FilenameW, fl, NULL);
HEAP_strdupA2W_buf_free(FilenameW, szBuff);
return ret;
}
/*
* @implemented
*/
int
/* @implemented */
INT
WINAPI
AddFontResourceW ( LPCWSTR lpszFilename )
AddFontResourceA(_In_ LPCSTR lpszFilename)
{
return GdiAddFontResourceW ( lpszFilename, 0, 0 );
return AddFontResourceExA(lpszFilename, 0, NULL);
}
/* @implemented */
INT
WINAPI
AddFontResourceW(_In_ LPCWSTR lpszFilename)
{
return GdiAddFontResourceW(lpszFilename, 0, NULL);
}
/*
* @implemented
*/
/* @implemented */
BOOL
WINAPI
RemoveFontResourceW(LPCWSTR lpFileName)
RemoveFontResourceW(_In_ LPCWSTR lpFileName)
{
return RemoveFontResourceExW(lpFileName,0,0);
return RemoveFontResourceExW(lpFileName, 0, NULL);
}
/*
* @implemented
*/
/* @implemented */
BOOL
WINAPI
RemoveFontResourceA(LPCSTR lpFileName)
RemoveFontResourceA(_In_ LPCSTR lpFileName)
{
return RemoveFontResourceExA(lpFileName,0,0);
return RemoveFontResourceExA(lpFileName, 0, NULL);
}
/*
* @implemented
*/
/* @implemented */
BOOL
WINAPI
RemoveFontResourceExA(LPCSTR lpFileName,
DWORD fl,
PVOID pdv)
RemoveFontResourceExA(
_In_ LPCSTR lpFileName,
_In_ DWORD fl,
_In_opt_ PVOID pdv)
{
NTSTATUS Status;
LPWSTR lpFileNameW;
BOOL result;
if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
if (!lpFileName)
return FALSE;
WCHAR szBuff[MAX_PATH];
PWSTR FilenameW;
_SEH2_TRY
{
FilenameW = HEAP_strdupA2W_buf(lpFileName, szBuff, _countof(szBuff));
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
FilenameW = NULL;
}
_SEH2_END;
if (!FilenameW)
{
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
BOOL result = RemoveFontResourceExW(FilenameW, fl, pdv);
HEAP_strdupA2W_buf_free(FilenameW, szBuff);
return result;
}
/* @implemented */
BOOL
WINAPI
RemoveFontResourceExW(
_In_ LPCWSTR lpFileName,
_In_ DWORD fl,
_In_opt_ PVOID pdv)
{
DPRINT("RemoveFontResourceExW\n");
if (fl & ~(FR_PRIVATE | FR_NOT_ENUM))
{
@ -2080,44 +2242,19 @@ RemoveFontResourceExA(LPCSTR lpFileName,
return FALSE;
}
_SEH2_TRY
{
Status = HEAP_strdupA2W(&lpFileNameW, lpFileName);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
if (!NT_SUCCESS(Status))
{
SetLastError(RtlNtStatusToDosError(Status));
if (!lpFileName)
return FALSE;
}
result = RemoveFontResourceExW(lpFileNameW, fl, pdv);
HEAP_free(lpFileNameW);
return result;
ULONG cFiles, cwc;
PWSTR pszConverted = IntConvertFontPaths(lpFileName, &cFiles, &cwc, &fl, TRUE);
if (!pszConverted)
return FALSE;
BOOL ret = NtGdiRemoveFontResourceW(pszConverted, cwc, cFiles, fl, 0, NULL);
HEAP_free(pszConverted);
return ret;
}
/*
* @unimplemented
*/
BOOL
WINAPI
RemoveFontResourceExW(LPCWSTR lpFileName,
DWORD fl,
PVOID pdv)
{
/* FIXME the flags */
/* FIXME the pdv */
/* FIXME NtGdiRemoveFontResource handle flags and pdv */
DPRINT("RemoveFontResourceExW\n");
return 0;
}
/***********************************************************************
* GdiGetCharDimensions
*
@ -2407,55 +2544,33 @@ NewEnumFontFamiliesExW(
return ret;
}
/*
* @implemented
*/
int
/* @implemented */
INT
WINAPI
GdiAddFontResourceW(
LPCWSTR lpszFilename,
FLONG fl,
DESIGNVECTOR *pdv)
{
INT Ret;
WCHAR lpszBuffer[MAX_PATH];
WCHAR lpszAbsPath[MAX_PATH];
UNICODE_STRING NtAbsPath;
/* FIXME: We don't support multiple files passed in lpszFilename
* as L"abcxxxxx.pfm|abcxxxxx.pfb"
*/
/* Does the file exist in CurrentDirectory or in the Absolute Path passed? */
GetCurrentDirectoryW(MAX_PATH, lpszBuffer);
if (!SearchPathW(lpszBuffer, lpszFilename, NULL, MAX_PATH, lpszAbsPath, NULL))
{
/* Nope. Then let's check Fonts folder */
GetWindowsDirectoryW(lpszBuffer, MAX_PATH);
StringCbCatW(lpszBuffer, sizeof(lpszBuffer), L"\\Fonts");
if (!SearchPathW(lpszBuffer, lpszFilename, NULL, MAX_PATH, lpszAbsPath, NULL))
{
DPRINT1("Font not found. The Buffer is: %ls, the FileName is: %S\n", lpszBuffer, lpszFilename);
return 0;
}
}
/* We found the font file so: */
if (!RtlDosPathNameToNtPathName_U(lpszAbsPath, &NtAbsPath, NULL, NULL))
{
DPRINT1("Can't convert Path! Path: %ls\n", lpszAbsPath);
ULONG cFiles, cwc;
PWSTR pszConverted = IntConvertFontPaths(lpszFilename, &cFiles, &cwc, &fl, FALSE);
if (!pszConverted)
return 0;
}
/* The Nt call expects a null-terminator included in cwc param. */
ASSERT(NtAbsPath.Buffer[NtAbsPath.Length / sizeof(WCHAR)] == UNICODE_NULL);
Ret = NtGdiAddFontResourceW(NtAbsPath.Buffer, NtAbsPath.Length / sizeof(WCHAR) + 1, 1, fl, 0, pdv);
INT ret = NtGdiAddFontResourceW(pszConverted, cwc, cFiles, fl, 0, pdv);
HEAP_free(pszConverted);
if (ret)
return ret;
RtlFreeUnicodeString(&NtAbsPath);
pszConverted = IntConvertFontPaths(lpszFilename, &cFiles, &cwc, &fl, TRUE);
if (!pszConverted)
return 0;
return Ret;
ret = NtGdiAddFontResourceW(pszConverted, cwc, cFiles, fl, 0, pdv);
HEAP_free(pszConverted);
if (!ret)
SetLastError(ERROR_INVALID_PARAMETER);
return ret;
}
/*
@ -2683,4 +2798,3 @@ cGetTTFFromFOT(DWORD x1 ,DWORD x2 ,DWORD x3, DWORD x4, DWORD x5, DWORD x6, DWORD
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}

View file

@ -438,23 +438,41 @@ RealizeFontInit(HFONT hFont)
return pTextObj;
}
static BOOL
IntCheckFontPathNames(
_In_reads_(cwc) WCHAR *pwcFiles,
_In_ ULONG cFiles,
_In_ ULONG cwc)
{
ULONG ich, cRealFiles;
if (pwcFiles[cwc - 1] != UNICODE_NULL)
return FALSE;
for (ich = cRealFiles = 0; ich < cwc; ++ich)
{
if (!pwcFiles[ich])
++cRealFiles;
}
return cRealFiles >= cFiles;
}
/** Functions ******************************************************************/
INT
APIENTRY
NtGdiAddFontResourceW(
IN WCHAR *pwcFiles,
IN ULONG cwc,
IN ULONG cFiles,
IN FLONG fl,
IN DWORD dwPidTid,
IN OPTIONAL DESIGNVECTOR *pdv)
_In_reads_(cwc) WCHAR *pwcFiles,
_In_ ULONG cwc,
_In_ ULONG cFiles,
_In_ FLONG fl,
_In_ DWORD dwPidTid,
_In_opt_ DESIGNVECTOR *pdv)
{
UNICODE_STRING SafeFileName;
INT Ret;
DBG_UNREFERENCED_PARAMETER(cFiles);
DBG_UNREFERENCED_PARAMETER(dwPidTid);
DBG_UNREFERENCED_PARAMETER(pdv);
@ -464,19 +482,21 @@ NtGdiAddFontResourceW(
if ((cwc <= 1) || (cwc > UNICODE_STRING_MAX_CHARS))
return 0;
SafeFileName.MaximumLength = (USHORT)(cwc * sizeof(WCHAR));
SafeFileName.Length = SafeFileName.MaximumLength - sizeof(UNICODE_NULL);
SafeFileName.Length = (USHORT)((cwc - 1) * sizeof(WCHAR));
SafeFileName.MaximumLength = SafeFileName.Length + sizeof(UNICODE_NULL);
SafeFileName.Buffer = ExAllocatePoolWithTag(PagedPool,
SafeFileName.MaximumLength,
TAG_STRING);
if (!SafeFileName.Buffer)
{
return 0;
}
_SEH2_TRY
{
ProbeForRead(pwcFiles, cwc * sizeof(WCHAR), sizeof(WCHAR));
if (!IntCheckFontPathNames(pwcFiles, cFiles, cwc))
return 0;
RtlCopyMemory(SafeFileName.Buffer, pwcFiles, SafeFileName.Length);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
@ -487,7 +507,62 @@ NtGdiAddFontResourceW(
_SEH2_END;
SafeFileName.Buffer[SafeFileName.Length / sizeof(WCHAR)] = UNICODE_NULL;
Ret = IntGdiAddFontResource(&SafeFileName, fl);
Ret = IntGdiAddFontResourceEx(&SafeFileName, cFiles, fl, 0);
ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
return Ret;
}
BOOL
APIENTRY
NtGdiRemoveFontResourceW(
_In_reads_(cwc) WCHAR *pwszFiles,
_In_ ULONG cwc,
_In_ ULONG cFiles,
_In_ ULONG fl,
_In_ DWORD dwPidTid,
_In_opt_ DESIGNVECTOR *pdv)
{
UNICODE_STRING SafeFileName;
BOOL Ret;
DBG_UNREFERENCED_PARAMETER(dwPidTid);
DBG_UNREFERENCED_PARAMETER(pdv);
DPRINT("NtGdiRemoveFontResourceW\n");
/* cwc = Length + trailing zero. */
if ((cwc <= 1) || (cwc > UNICODE_STRING_MAX_CHARS))
return FALSE;
SafeFileName.Length = (USHORT)((cwc - 1) * sizeof(WCHAR));
SafeFileName.MaximumLength = SafeFileName.Length + sizeof(UNICODE_NULL);
SafeFileName.Buffer = ExAllocatePoolWithTag(PagedPool,
SafeFileName.MaximumLength,
TAG_STRING);
if (!SafeFileName.Buffer)
return FALSE;
_SEH2_TRY
{
ProbeForRead(pwszFiles, cwc * sizeof(WCHAR), sizeof(WCHAR));
if (!IntCheckFontPathNames(pwszFiles, cFiles, cwc))
return FALSE;
RtlCopyMemory(SafeFileName.Buffer, pwszFiles, SafeFileName.Length);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
_SEH2_YIELD(return FALSE);
}
_SEH2_END;
SafeFileName.Buffer[SafeFileName.Length / sizeof(WCHAR)] = UNICODE_NULL;
Ret = IntGdiRemoveFontResource(&SafeFileName, cFiles, fl);
ExFreePoolWithTag(SafeFileName.Buffer, TAG_STRING);
return Ret;

View file

@ -1233,7 +1233,9 @@ IntUnicodeStringToBuffer(LPWSTR pszBuffer, SIZE_T cbBuffer, const UNICODE_STRING
}
static NTSTATUS
DuplicateUnicodeString(PUNICODE_STRING Source, PUNICODE_STRING Destination)
DuplicateUnicodeString(
_In_ PCUNICODE_STRING Source,
_Out_ PUNICODE_STRING Destination)
{
NTSTATUS Status = STATUS_NO_MEMORY;
UNICODE_STRING Tmp;
@ -1664,10 +1666,8 @@ IntLoadSystemFonts(VOID)
{
RtlCopyUnicodeString(&FileName, &Directory);
RtlAppendUnicodeStringToString(&FileName, &TempString);
if (!IntGdiAddFontResourceEx(&FileName, 0, AFRX_WRITE_REGISTRY))
{
if (!IntGdiAddFontResourceEx(&FileName, 1, 0, AFRX_WRITE_REGISTRY))
DPRINT1("ERR: Failed to load %wZ\n", &FileName);
}
}
if (DirInfo->NextEntryOffset == 0)
@ -2086,15 +2086,12 @@ NameFromCharSet(BYTE CharSet)
}
}
/*
* IntGdiAddFontResource
*
* Adds the font resource from the specified file to the system.
*/
INT FASTCALL
IntGdiAddFontResourceEx(PUNICODE_STRING FileName, DWORD Characteristics,
DWORD dwFlags)
/* Adds the font resource from the specified file to the system */
static INT FASTCALL
IntGdiAddFontResourceSingle(
_In_ PCUNICODE_STRING FileName,
_In_ DWORD Characteristics,
_In_ DWORD dwFlags)
{
NTSTATUS Status;
HANDLE FileHandle;
@ -2291,9 +2288,86 @@ IntGdiAddFontResourceEx(PUNICODE_STRING FileName, DWORD Characteristics,
}
INT FASTCALL
IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
IntGdiAddFontResourceEx(
_In_ PCUNICODE_STRING FileName,
_In_ DWORD cFiles,
_In_ DWORD Characteristics,
_In_ DWORD dwFlags)
{
return IntGdiAddFontResourceEx(FileName, Characteristics, 0);
PWSTR pchFile = FileName->Buffer;
SIZE_T cchFile;
INT ret = 0;
while (cFiles--)
{
_SEH2_TRY
{
cchFile = wcslen(pchFile);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_YIELD(return FALSE);
}
_SEH2_END;
UNICODE_STRING ustrPathName;
ustrPathName.Length = (USHORT)(cchFile * sizeof(WCHAR));
ustrPathName.MaximumLength = ustrPathName.Length + sizeof(WCHAR);
ustrPathName.Buffer = pchFile;
INT count = IntGdiAddFontResourceSingle(&ustrPathName, Characteristics, dwFlags);
if (!count)
return 0;
ret += count;
pchFile += cchFile + 1;
}
return ret;
}
static BOOL FASTCALL
IntGdiRemoveFontResourceSingle(
_In_ PCUNICODE_STRING FileName,
_In_ DWORD dwFlags)
{
return FALSE; // FIXME
}
BOOL FASTCALL
IntGdiRemoveFontResource(
_In_ PCUNICODE_STRING FileName,
_In_ DWORD cFiles,
_In_ DWORD dwFlags)
{
PWSTR pchFile = FileName->Buffer;
SIZE_T cchFile;
while (cFiles--)
{
_SEH2_TRY
{
cchFile = wcslen(pchFile);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_YIELD(return FALSE);
}
_SEH2_END;
UNICODE_STRING ustrPathName;
ustrPathName.Length = (USHORT)(cchFile * sizeof(WCHAR));
ustrPathName.MaximumLength = ustrPathName.Length + sizeof(WCHAR);
ustrPathName.Buffer = pchFile;
BOOL ret = IntGdiRemoveFontResourceSingle(&ustrPathName, dwFlags);
if (!ret)
return FALSE;
pchFile += cchFile + 1;
}
return TRUE;
}
/* Borrowed from shlwapi!PathIsRelativeW */
@ -2439,7 +2513,7 @@ IntLoadFontsInRegistry(VOID)
if (NT_SUCCESS(Status))
{
RtlCreateUnicodeString(&FileNameW, szPath);
nFontCount += IntGdiAddFontResourceEx(&FileNameW, 0, dwFlags);
nFontCount += IntGdiAddFontResourceEx(&FileNameW, 1, 0, dwFlags);
RtlFreeUnicodeString(&FileNameW);
}
@ -2508,8 +2582,6 @@ IntGdiAddFontMemResource(PVOID Buffer, DWORD dwSize, PDWORD pNumAdded)
return Ret;
}
// FIXME: Add RemoveFontResource
VOID FASTCALL
IntGdiCleanupMemEntry(PFONT_ENTRY_MEM Head)
{
@ -4131,7 +4203,6 @@ IntRequestFontSize(PDC dc, PFONTGDI FontGDI, LONG lfWidth, LONG lfHeight)
if (error)
{
DPRINT1("%s: Failed to request font size.\n", face->family_name);
ASSERT(FALSE);
return error;
}

View file

@ -118,9 +118,15 @@ ULONG FASTCALL FontGetObject(PTEXTOBJ TextObj, ULONG Count, PVOID Buffer);
VOID FASTCALL IntLoadSystemFonts(VOID);
BOOL FASTCALL IntLoadFontsInRegistry(VOID);
VOID FASTCALL IntGdiCleanupPrivateFontsForProcess(VOID);
INT FASTCALL IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics);
INT FASTCALL IntGdiAddFontResourceEx(PUNICODE_STRING FileName, DWORD Characteristics,
DWORD dwFlags);
INT FASTCALL IntGdiAddFontResourceEx(
_In_ PCUNICODE_STRING FileName,
_In_ DWORD cFiles,
_In_ DWORD Characteristics,
_In_ DWORD dwFlags);
BOOL FASTCALL IntGdiRemoveFontResource(
_In_ PCUNICODE_STRING FileName,
_In_ DWORD cFiles,
_In_ DWORD dwFlags);
HANDLE FASTCALL IntGdiAddFontMemResource(PVOID Buffer, DWORD dwSize, PDWORD pNumAdded);
BOOL FASTCALL IntGdiRemoveFontMemResource(HANDLE hMMFont);
ULONG FASTCALL ftGdiGetGlyphOutline(PDC,WCHAR,UINT,LPGLYPHMETRICS,ULONG,PVOID,LPMAT2,BOOL);