mirror of
https://github.com/reactos/reactos.git
synced 2025-04-25 08:00:24 +00:00
[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:
parent
72bd9ef29a
commit
1890ad20f8
7 changed files with 506 additions and 232 deletions
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue