mirror of
https://github.com/reactos/reactos.git
synced 2025-08-02 05:25:48 +00:00
[NTGDI][NTUSER] Initial support of NtGdiRemoveFontResourceW (#7877)
Enable the users to delete fonts. JIRA issue: CORE-17684 - Add IntDeleteRegFontEntry helper function. - Add RegDeleteValueW and RegEnumValueW helper functions in win32ss/user/ntuser/misc/registry.c. - Add some code to IntGdiRemoveFontResourceSingle function.
This commit is contained in:
parent
2c475add8c
commit
530d26a1f4
3 changed files with 246 additions and 2 deletions
|
@ -2086,6 +2086,8 @@ NameFromCharSet(BYTE CharSet)
|
|||
}
|
||||
}
|
||||
|
||||
static const UNICODE_STRING DosPathPrefix = RTL_CONSTANT_STRING(L"\\??\\");
|
||||
|
||||
/* Adds the font resource from the specified file to the system */
|
||||
static INT FASTCALL
|
||||
IntGdiAddFontResourceSingle(
|
||||
|
@ -2108,7 +2110,6 @@ IntGdiAddFontResourceSingle(
|
|||
LPWSTR pszBuffer;
|
||||
PFILE_OBJECT FileObject;
|
||||
static const UNICODE_STRING TrueTypePostfix = RTL_CONSTANT_STRING(L" (TrueType)");
|
||||
static const UNICODE_STRING DosPathPrefix = RTL_CONSTANT_STRING(L"\\??\\");
|
||||
|
||||
/* Build PathName */
|
||||
if (dwFlags & AFRX_DOS_DEVICE_PATH)
|
||||
|
@ -2326,12 +2327,126 @@ IntGdiAddFontResourceEx(
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Borrowed from shlwapi */
|
||||
static PWSTR
|
||||
PathFindFileNameW(_In_ PCWSTR pszPath)
|
||||
{
|
||||
PCWSTR lastSlash = pszPath;
|
||||
while (*pszPath)
|
||||
{
|
||||
if ((*pszPath == L'\\' || *pszPath == L'/' || *pszPath == L':') &&
|
||||
pszPath[1] && pszPath[1] != '\\' && pszPath[1] != L'/')
|
||||
{
|
||||
lastSlash = pszPath + 1;
|
||||
}
|
||||
pszPath++;
|
||||
}
|
||||
return (PWSTR)lastSlash;
|
||||
}
|
||||
|
||||
/* Delete registry font entries */
|
||||
static VOID
|
||||
IntDeleteRegFontEntries(_In_ PCWSTR pszFileName, _In_ DWORD dwFlags)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HKEY hKey;
|
||||
WCHAR szName[MAX_PATH], szValue[MAX_PATH];
|
||||
ULONG dwIndex, NameLength, ValueSize, dwType;
|
||||
|
||||
Status = RegOpenKey(g_FontRegPath.Buffer, &hKey);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return;
|
||||
|
||||
for (dwIndex = 0;;)
|
||||
{
|
||||
NameLength = RTL_NUMBER_OF(szName);
|
||||
ValueSize = sizeof(szValue);
|
||||
Status = RegEnumValueW(hKey, dwIndex, szName, &NameLength, &dwType, szValue, &ValueSize);
|
||||
if (!NT_SUCCESS(Status))
|
||||
break;
|
||||
|
||||
if (dwType != REG_SZ || _wcsicmp(szValue, pszFileName) != 0)
|
||||
{
|
||||
++dwIndex;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Delete the found value */
|
||||
Status = RegDeleteValueW(hKey, szName);
|
||||
if (!NT_SUCCESS(Status))
|
||||
break;
|
||||
}
|
||||
|
||||
ZwClose(hKey);
|
||||
}
|
||||
|
||||
static BOOL FASTCALL
|
||||
IntGdiRemoveFontResourceSingle(
|
||||
_In_ PCUNICODE_STRING FileName,
|
||||
_In_ DWORD dwFlags)
|
||||
{
|
||||
return FALSE; // FIXME
|
||||
BOOL ret = FALSE;
|
||||
UNICODE_STRING PathName;
|
||||
PLIST_ENTRY CurrentEntry, NextEntry;
|
||||
PFONT_ENTRY FontEntry;
|
||||
PFONTGDI FontGDI;
|
||||
PWSTR pszBuffer, pszFileTitle;
|
||||
SIZE_T Length;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Build PathName */
|
||||
if (dwFlags & AFRX_DOS_DEVICE_PATH)
|
||||
{
|
||||
Length = DosPathPrefix.Length + FileName->Length + sizeof(UNICODE_NULL);
|
||||
pszBuffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_USTR);
|
||||
if (!pszBuffer)
|
||||
return FALSE; /* Failure */
|
||||
|
||||
RtlInitEmptyUnicodeString(&PathName, pszBuffer, Length);
|
||||
RtlAppendUnicodeStringToString(&PathName, &DosPathPrefix);
|
||||
RtlAppendUnicodeStringToString(&PathName, FileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = DuplicateUnicodeString(FileName, &PathName);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return FALSE; /* Failure */
|
||||
}
|
||||
|
||||
pszFileTitle = PathName.Buffer;
|
||||
if (!(dwFlags & AFRX_ALTERNATIVE_PATH))
|
||||
pszFileTitle = PathFindFileNameW(PathName.Buffer);
|
||||
|
||||
if (!pszFileTitle || !*pszFileTitle)
|
||||
{
|
||||
RtlFreeUnicodeString(&PathName);
|
||||
return FALSE; /* Failure */
|
||||
}
|
||||
|
||||
/* Delete font entries that matches PathName */
|
||||
IntLockFreeType();
|
||||
for (CurrentEntry = g_FontListHead.Flink;
|
||||
CurrentEntry != &g_FontListHead;
|
||||
CurrentEntry = NextEntry)
|
||||
{
|
||||
FontEntry = CONTAINING_RECORD(CurrentEntry, FONT_ENTRY, ListEntry);
|
||||
NextEntry = CurrentEntry->Flink;
|
||||
|
||||
FontGDI = FontEntry->Font;
|
||||
ASSERT(FontGDI);
|
||||
if (FontGDI->Filename && _wcsicmp(FontGDI->Filename, pszFileTitle) == 0)
|
||||
{
|
||||
RemoveEntryList(&FontEntry->ListEntry);
|
||||
CleanupFontEntry(FontEntry);
|
||||
if (dwFlags & AFRX_WRITE_REGISTRY)
|
||||
IntDeleteRegFontEntries(pszFileTitle, dwFlags);
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
IntUnLockFreeType();
|
||||
|
||||
RtlFreeUnicodeString(&PathName);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL FASTCALL
|
||||
|
|
|
@ -60,6 +60,19 @@ DWORD
|
|||
NTAPI
|
||||
RegGetSectionDWORD(LPCWSTR pszSection, PCWSTR pszValue, DWORD dwDefault);
|
||||
|
||||
NTSTATUS NTAPI
|
||||
RegDeleteValueW(_In_ HKEY hKey, _In_ LPCWSTR pszValueName);
|
||||
|
||||
NTSTATUS NTAPI
|
||||
RegEnumValueW(
|
||||
_In_ HKEY hKey,
|
||||
_In_ ULONG Index,
|
||||
_Out_opt_ LPWSTR Name,
|
||||
_Out_opt_ PULONG NameLength,
|
||||
_Out_opt_ PULONG Type,
|
||||
_Out_opt_ PVOID Data,
|
||||
_Out_opt_ PULONG DataLength);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
SetLastNtError(_In_ NTSTATUS Status);
|
||||
|
|
|
@ -380,3 +380,119 @@ RegWriteUserSetting(
|
|||
return NT_SUCCESS(Status);
|
||||
}
|
||||
|
||||
static inline BOOL
|
||||
IsStringType(ULONG Type)
|
||||
{
|
||||
return (Type == REG_SZ) || (Type == REG_EXPAND_SZ) || (Type == REG_MULTI_SZ);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
RegEnumValueW(
|
||||
_In_ HKEY hKey,
|
||||
_In_ ULONG Index,
|
||||
_Out_opt_ LPWSTR Name,
|
||||
_Out_opt_ PULONG NameLength,
|
||||
_Out_opt_ PULONG Type,
|
||||
_Out_opt_ PVOID Data,
|
||||
_Out_opt_ PULONG DataLength)
|
||||
{
|
||||
PKEY_VALUE_FULL_INFORMATION ValueInfo = NULL;
|
||||
ULONG BufferLength = 0;
|
||||
ULONG ReturnedLength;
|
||||
NTSTATUS Status;
|
||||
|
||||
/* Calculate the required buffer length */
|
||||
BufferLength = FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name);
|
||||
BufferLength += (MAX_PATH + 1) * sizeof(WCHAR);
|
||||
if (Data != NULL)
|
||||
BufferLength += *DataLength;
|
||||
|
||||
/* Allocate the value buffer */
|
||||
ValueInfo = ExAllocatePoolWithTag(PagedPool, BufferLength, TAG_TEMP);
|
||||
if (ValueInfo == NULL)
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
/* Enumerate the value*/
|
||||
Status = ZwEnumerateValueKey(hKey,
|
||||
Index,
|
||||
KeyValueFullInformation,
|
||||
ValueInfo,
|
||||
BufferLength,
|
||||
&ReturnedLength);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
if (Name)
|
||||
{
|
||||
/* Check if the name fits */
|
||||
if ((ValueInfo->NameLength + sizeof(WCHAR)) <= (*NameLength * sizeof(WCHAR)))
|
||||
{
|
||||
/* Copy it */
|
||||
RtlMoveMemory(Name, ValueInfo->Name, ValueInfo->NameLength);
|
||||
|
||||
/* Terminate the string */
|
||||
Name[ValueInfo->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Otherwise, we ran out of buffer space */
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (Data)
|
||||
{
|
||||
/* Check if the data fits */
|
||||
if (ValueInfo->DataLength <= *DataLength)
|
||||
{
|
||||
/* Copy it */
|
||||
RtlMoveMemory(Data,
|
||||
(PVOID)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset),
|
||||
ValueInfo->DataLength);
|
||||
|
||||
/* if the type is REG_SZ and data is not 0-terminated
|
||||
* and there is enough space in the buffer NT appends a \0 */
|
||||
if (IsStringType(ValueInfo->Type) &&
|
||||
ValueInfo->DataLength <= *DataLength - sizeof(WCHAR))
|
||||
{
|
||||
WCHAR *ptr = (WCHAR *)((ULONG_PTR)Data + ValueInfo->DataLength);
|
||||
if ((ptr > (WCHAR *)Data) && ptr[-1])
|
||||
*ptr = UNICODE_NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Status = STATUS_BUFFER_OVERFLOW;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
|
||||
{
|
||||
if (Type)
|
||||
*Type = ValueInfo->Type;
|
||||
|
||||
if (NameLength)
|
||||
*NameLength = ValueInfo->NameLength;
|
||||
|
||||
if (DataLength)
|
||||
*DataLength = ValueInfo->DataLength;
|
||||
}
|
||||
|
||||
/* Free the buffer and return status */
|
||||
if (ValueInfo)
|
||||
ExFreePoolWithTag(ValueInfo, TAG_TEMP);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS NTAPI
|
||||
RegDeleteValueW(_In_ HKEY hKey, _In_ LPCWSTR pszValueName)
|
||||
{
|
||||
UNICODE_STRING ustrName;
|
||||
RtlInitUnicodeString(&ustrName, pszValueName);
|
||||
return ZwDeleteValueKey(hKey, &ustrName);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue