You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1302 lines
44 KiB
1302 lines
44 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: fntsweep.c
|
|
*
|
|
* Copyright (c) 1985 - 1999, Microsoft Corporation
|
|
* Author: Bodin Dresevic [BodinD]
|
|
*
|
|
* Copyright (c) 1990 Microsoft Corporation
|
|
*
|
|
* This file contains font sweeper related stuff.
|
|
* On the boot of ths system, i.e. initialization of userk, the
|
|
* [Fonts] section of win.ini is checked to
|
|
* find out if any new fonts have been added by any font installers.
|
|
* If third party installers have installed fonts in the system directory
|
|
* those are copied to fonts directory. Any fot entries are replaced
|
|
* by appropriate *.ttf entries, any fot files are deleted if they were
|
|
* ever installed.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include <setupbat.h> // in sdkinc
|
|
|
|
CONST WCHAR pwszType1Key[] = L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Type 1 Installer\\Type 1 Fonts";
|
|
CONST WCHAR pwszSweepType1Key[] = L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Type 1 Installer\\LastType1Sweep";
|
|
CONST WCHAR pwszUpdType1Key[] = L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Type 1 Installer\\Upgraded Type1";
|
|
|
|
CONST WCHAR pwszFontsKey[] = L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
|
|
CONST WCHAR pwszSweepKey[] = L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\LastFontSweep";
|
|
CONST WCHAR pwszFontDrivers[] = L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Font Drivers";
|
|
|
|
#define LAST_SWEEP_TIME L"LastSweepTime"
|
|
#define UPGRADED_TYPE1 L"UpgradedType1"
|
|
|
|
#define DWORDALIGN(X) (((X) + 3) & ~3)
|
|
|
|
WCHAR *gpwcSystemDir;
|
|
WCHAR *gpwcFontsDir;
|
|
BOOL gbWin31Upgrade;
|
|
|
|
|
|
BOOL bCheckIfDualBootingWithWin31()
|
|
{
|
|
WCHAR Buffer[32];
|
|
WCHAR awcWindowsDir[MAX_PATH];
|
|
DWORD dwRet;
|
|
UINT cwchWinPath;
|
|
|
|
awcWindowsDir[0] = L'\0'; // prefix:make sure to zero terminated
|
|
cwchWinPath = GetSystemWindowsDirectoryW(awcWindowsDir, MAX_PATH);
|
|
|
|
if ((cwchWinPath == 0) || (cwchWinPath > MAX_PATH))
|
|
return FALSE;
|
|
|
|
// the cwchWinPath value does not include the terminating zero
|
|
|
|
if (awcWindowsDir[cwchWinPath - 1] == L'\\')
|
|
{
|
|
cwchWinPath -= 1;
|
|
}
|
|
awcWindowsDir[cwchWinPath] = L'\0'; // make sure to zero terminated
|
|
|
|
lstrcatW(awcWindowsDir, L"\\system32\\");
|
|
lstrcatW(awcWindowsDir, WINNT_GUI_FILE_W);
|
|
|
|
dwRet = GetPrivateProfileStringW(
|
|
WINNT_DATA_W,
|
|
WINNT_D_WIN31UPGRADE_W,
|
|
WINNT_A_NO_W,
|
|
Buffer,
|
|
sizeof(Buffer)/sizeof(WCHAR),
|
|
awcWindowsDir
|
|
);
|
|
|
|
#if DBGSWEEP
|
|
DbgPrint("\n dwRet = %ld, win31upgrade = %ws\n\n", dwRet, Buffer);
|
|
#endif
|
|
|
|
return (BOOL)(dwRet ? (!lstrcmpiW(Buffer,WINNT_A_YES)) : 0);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* VOID vNullTermWideString (WCHAR *pwcDest, WCHAR *pwcSrc, ULONG ulLength)
|
|
*
|
|
* Given pwcSrc, which is not necessarily null-terminated, copy ulLength characters
|
|
* the into pwcDest and place a null character after it.
|
|
*
|
|
* History:
|
|
* 03-Feb-99 -by- Donald Chinn [dchinn]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
VOID vNullTermWideString (WCHAR *pwcDest, WCHAR *pwcSrc, ULONG ulLength)
|
|
{
|
|
ULONG index;
|
|
|
|
for (index = 0; index < ulLength; index++) {
|
|
*pwcDest++ = *pwcSrc++;
|
|
}
|
|
*pwcDest = '\0';
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* BOOL bCheckFontEntry(WCHAR *pwcName, WCHAR *pwcExtension)
|
|
*
|
|
* This function assumes that both pwcName and pwcExtension are null-terminated.
|
|
*
|
|
* History:
|
|
* 25-Oct-1995 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
|
|
BOOL bCheckFontEntry(WCHAR *pwcName, WCHAR *pwcExtension)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
LONG cwc = (LONG)wcslen(pwcName) - (LONG)wcslen(pwcExtension);
|
|
if (cwc > 0)
|
|
{
|
|
bRet = !_wcsicmp(&pwcName[cwc], pwcExtension);
|
|
}
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* Process win.ini line
|
|
*
|
|
* History:
|
|
* 24-Oct-1995 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
#define EXT_TRUETYPE L"(TrueType)"
|
|
#define EXT_FOT L".FOT"
|
|
|
|
|
|
VOID vProcessFontEntry(
|
|
HKEY hkey,
|
|
WCHAR *pwcValueName,
|
|
ULONG ulValueNameLength,
|
|
WCHAR *pwcFileName,
|
|
ULONG ulFileNameLength
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING UnicodeString;
|
|
BOOL bFot = FALSE;
|
|
WCHAR awcTTF[MAX_PATH];
|
|
WCHAR awcTmpBuf[MAX_PATH];
|
|
WCHAR *pwcTTF;
|
|
FLONG fl, fl2;
|
|
FLONG flEmbed;
|
|
DWORD dwPidTid;
|
|
WCHAR awcValueName[MAX_PATH]; // null-terminated pwcValueName
|
|
WCHAR awcFileName[MAX_PATH]; // null-terminated pwcFileName
|
|
|
|
|
|
// Make sure the ValueName is null-terminated
|
|
ulValueNameLength = min(MAX_PATH - 1, ulValueNameLength);
|
|
vNullTermWideString (awcValueName, pwcValueName, ulValueNameLength);
|
|
|
|
// Make sure the FileName is null-terminated
|
|
ulFileNameLength = min(MAX_PATH - 1, ulFileNameLength);
|
|
vNullTermWideString (awcFileName, pwcFileName, ulFileNameLength);
|
|
|
|
if (bCheckFontEntry(awcValueName, EXT_TRUETYPE))
|
|
{
|
|
// This is a tt entry, either .fot or .ttf
|
|
|
|
if (bFot = bCheckFontEntry(awcFileName, EXT_FOT))
|
|
{
|
|
// this is an .fot entry, must find ttf pointed to by .fot,
|
|
// but first must get the full path to the .fot file
|
|
// for cGetTTFFromFOT routine expects it. We will also need
|
|
// the full path to the .fot file so that we can delete it
|
|
// eventually.
|
|
|
|
if (bMakePathNameW(awcTmpBuf, awcFileName, NULL, &fl2))
|
|
{
|
|
if (cGetTTFFromFOT(awcTmpBuf, MAX_PATH, awcTTF, &fl, &flEmbed, &dwPidTid, TRUE) &&
|
|
!(fl & FONT_ISNOT_FOT))
|
|
{
|
|
// fix the entry to point to .ttf file. At this point
|
|
// awcTTF points to the FULL path to the .ttf file.
|
|
// However, we will only need a relative path to the
|
|
// .ttf file, when the .ttf file is in the %windir%\system
|
|
// or %windir%\fonts directories. In case the file is in the
|
|
// %windir%\system directory we shall copy it to %windir%\fonts
|
|
// directory and write the relative path to the registry.
|
|
// In case it is in the %windir%\fonts directory we do not
|
|
// touch the file and also just write the relative path to the
|
|
// registry. In any other case we just write the full .ttf
|
|
// path to the registry.
|
|
|
|
// first delete the .fot file, it is no longer needed
|
|
|
|
if (bFot && !gbWin31Upgrade)
|
|
{
|
|
UserVerify(DeleteFileW(awcTmpBuf));
|
|
}
|
|
|
|
if ((fl & (FONT_IN_FONTS_DIR | FONT_IN_SYSTEM_DIR)) == 0)
|
|
{
|
|
// if ttf file is not in either the system or the fonts
|
|
// directories, just write the full path to the registry
|
|
|
|
pwcTTF = awcTTF;
|
|
}
|
|
else
|
|
{
|
|
// find the bare file part, this is what will be written
|
|
// in the registry
|
|
|
|
pwcTTF = &awcTTF[wcslen(awcTTF) - 1];
|
|
while ((pwcTTF >= awcTTF) && (*pwcTTF != L'\\') && (*pwcTTF != L':'))
|
|
pwcTTF--;
|
|
pwcTTF++;
|
|
|
|
if (fl & FONT_IN_SYSTEM_DIR)
|
|
{
|
|
// need to move the ttf to fonts dir, can reuse the
|
|
// buffer on the stack:
|
|
|
|
wcscpy(awcTmpBuf, gpwcFontsDir);
|
|
lstrcatW(awcTmpBuf, L"\\");
|
|
lstrcatW(awcTmpBuf, pwcTTF);
|
|
|
|
// note that MoveFile should succeed, for if there was
|
|
// a ttf file of the same file name in %windir%\fonts dir
|
|
// we would not have been in this code path.
|
|
|
|
RIPMSG2(RIP_VERBOSE, "Moving %ws to %ws", awcTTF, awcTmpBuf);
|
|
if (!gbWin31Upgrade)
|
|
{
|
|
UserVerify(MoveFileW(awcTTF, awcTmpBuf));
|
|
}
|
|
else
|
|
{
|
|
// Boolean value TRUE means "do not copy if target exists"
|
|
|
|
UserVerify(CopyFileW(awcTTF, awcTmpBuf, TRUE));
|
|
}
|
|
}
|
|
}
|
|
|
|
RIPMSG2(RIP_VERBOSE, "writing to the registry:\n %ws=%ws", pwcValueName, pwcTTF);
|
|
RtlInitUnicodeString(&UnicodeString, awcValueName);
|
|
Status = NtSetValueKey(hkey,
|
|
&UnicodeString,
|
|
0,
|
|
REG_SZ,
|
|
pwcTTF,
|
|
(wcslen(pwcTTF)+1) * sizeof(WCHAR));
|
|
UserAssert(NT_SUCCESS(Status));
|
|
}
|
|
#if DBG
|
|
else
|
|
{
|
|
RIPMSG1(RIP_WARNING, "Could not locate ttf pointed to by %ws", awcTmpBuf);
|
|
}
|
|
#endif
|
|
}
|
|
#if DBG
|
|
else
|
|
{
|
|
RIPMSG1(RIP_WARNING, "Could not locate .fot: %ws", awcFileName);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// not a true type case. little bit simpler,
|
|
// we will use awcTTF buffer for the full path name, and pwcTTF
|
|
// as local variable even though these TTF names are misnomer
|
|
// for these are not tt fonts
|
|
|
|
if (bMakePathNameW(awcTTF, awcFileName,NULL, &fl))
|
|
{
|
|
// At this point
|
|
// awcTTF points to the FULL path to the font file.
|
|
|
|
// If the font is in the system subdirectory we will just move it
|
|
// to the fonts subdirectory. If the path in the registry is relative
|
|
// we will leave it alone. If it is an absolute path, we shall
|
|
// fix the registry entry to only contain relative path, the
|
|
// absolute path is redundant.
|
|
|
|
if (fl & (FONT_IN_SYSTEM_DIR | FONT_IN_FONTS_DIR))
|
|
{
|
|
// find the bare file part, this is what will be written
|
|
// in the registry
|
|
|
|
pwcTTF = &awcTTF[wcslen(awcTTF) - 1];
|
|
while ((pwcTTF >= awcTTF) && (*pwcTTF != L'\\') && (*pwcTTF != L':'))
|
|
pwcTTF--;
|
|
pwcTTF++;
|
|
|
|
if (fl & FONT_IN_SYSTEM_DIR)
|
|
{
|
|
// need to move the font to fonts dir, can reuse the
|
|
// buffer on the stack to build the full destination path
|
|
|
|
wcscpy(awcTmpBuf, gpwcFontsDir);
|
|
lstrcatW(awcTmpBuf, L"\\");
|
|
lstrcatW(awcTmpBuf, pwcTTF);
|
|
|
|
// note that MoveFile should succeed, for if there was
|
|
// a font file of the same file name in %windir%\fonts dir
|
|
// we would not have been in this code path. The only time
|
|
// it could fail if the path in the registry is absolute.
|
|
|
|
RIPMSG2(RIP_VERBOSE, "Moving %ws to %ws", awcTTF, awcTmpBuf);
|
|
if (!gbWin31Upgrade)
|
|
{
|
|
UserVerify(MoveFileW(awcTTF, awcTmpBuf));
|
|
}
|
|
else
|
|
{
|
|
// Boolean value TRUE means "do not copy if target exists"
|
|
|
|
UserVerify(CopyFileW(awcTTF, awcTmpBuf, TRUE));
|
|
}
|
|
}
|
|
|
|
// check if the file path in the registry is absolute,
|
|
// if so make it relative:
|
|
|
|
if (!(fl & FONT_RELATIVE_PATH))
|
|
{
|
|
RIPMSG2(RIP_VERBOSE, "writing to the registry:\n %ws=%ws", pwcValueName, pwcTTF);
|
|
RtlInitUnicodeString(&UnicodeString, awcValueName);
|
|
Status = NtSetValueKey(hkey,
|
|
&UnicodeString,
|
|
0,
|
|
REG_SZ,
|
|
pwcTTF,
|
|
(wcslen(pwcTTF)+1) * sizeof(WCHAR));
|
|
UserAssert(NT_SUCCESS(Status));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* VOID vMoveFileFromSystemToFontsDir(WCHAR *pwcFile)
|
|
*
|
|
* History:
|
|
* 24-Apr-1996 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
|
|
|
|
|
|
VOID vMoveFileFromSystemToFontsDir(WCHAR *pwcFile)
|
|
{
|
|
WCHAR awcTmpBuf[MAX_PATH];
|
|
WCHAR awcTmp[MAX_PATH];
|
|
FLONG fl;
|
|
WCHAR *pwcTmp;
|
|
|
|
#if DBG
|
|
BOOL bOk;
|
|
#endif
|
|
|
|
if (bMakePathNameW(awcTmp, pwcFile,NULL, &fl))
|
|
{
|
|
// If the font is in the system subdirectory we will just move it
|
|
// to the fonts subdirectory. The path in the registry is relative
|
|
// and we will leave it alone.
|
|
|
|
if
|
|
(
|
|
(fl & (FONT_IN_SYSTEM_DIR | FONT_RELATIVE_PATH)) ==
|
|
(FONT_IN_SYSTEM_DIR | FONT_RELATIVE_PATH)
|
|
)
|
|
{
|
|
// find the bare file part, this is what will be written
|
|
// in the registry
|
|
|
|
pwcTmp = &awcTmp[wcslen(awcTmp) - 1];
|
|
while ((pwcTmp >= awcTmp) && (*pwcTmp != L'\\') && (*pwcTmp != L':'))
|
|
pwcTmp--;
|
|
|
|
if (pwcTmp > awcTmp)
|
|
pwcTmp++;
|
|
|
|
// need to move the font to fonts dir, can reuse the
|
|
// buffer on the stack to build the full destination path
|
|
|
|
wcscpy(awcTmpBuf, gpwcFontsDir);
|
|
lstrcatW(awcTmpBuf, L"\\");
|
|
lstrcatW(awcTmpBuf, pwcTmp);
|
|
|
|
// note that MoveFile should succeed, for if there was
|
|
// a font file of the same file name in %windir%\fonts dir
|
|
// we would not have been in this code path.
|
|
|
|
#if DBG
|
|
bOk =
|
|
#endif
|
|
MoveFileW(awcTmp, awcTmpBuf);
|
|
|
|
RIPMSG3(RIP_VERBOSE,
|
|
"move %ws to %ws %s",
|
|
awcTmp,
|
|
awcTmpBuf,
|
|
(bOk) ? "succeeded" : "failed");
|
|
}
|
|
#if DBG
|
|
else
|
|
{
|
|
RIPMSG2(RIP_WARNING,
|
|
"File %ws not in system directory, fl = 0x%lx\n",
|
|
awcTmp, fl);
|
|
}
|
|
#endif
|
|
|
|
}
|
|
#if DBG
|
|
else
|
|
{
|
|
RIPMSG1(RIP_WARNING, "Could not locate %ws", pwcFile);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* VOID vProcessType1FontEntry
|
|
*
|
|
*
|
|
* Effects: All this routine does is to check if pwcPFM and pwcPFB pointed to
|
|
* by pwcValueData point to files in the %windir%system directory
|
|
* and if so copies these type 1 files to %windir%\fonts directory
|
|
*
|
|
* History:
|
|
* 20-Nov-1995 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
|
|
VOID vProcessType1FontEntry(
|
|
HKEY hkey,
|
|
WCHAR *pwcValueName,
|
|
ULONG ulValueNameLength,
|
|
WCHAR *pwcValueData,
|
|
ULONG ulValueDataLength
|
|
)
|
|
{
|
|
WCHAR *pwcPFM, *pwcPFB;
|
|
|
|
UNREFERENCED_PARAMETER(hkey);
|
|
UNREFERENCED_PARAMETER(pwcValueName);
|
|
UNREFERENCED_PARAMETER(ulValueNameLength);
|
|
UNREFERENCED_PARAMETER(ulValueDataLength);
|
|
|
|
// skip unused boolean value in this multi reg_sz string:
|
|
|
|
if ((pwcValueData[0] != L'\0') && (pwcValueData[1] == L'\0'))
|
|
{
|
|
pwcPFM = &pwcValueData[2];
|
|
pwcPFB = pwcPFM + wcslen(pwcPFM) + 1; // add 1 for zero separator
|
|
|
|
vMoveFileFromSystemToFontsDir(pwcPFM);
|
|
vMoveFileFromSystemToFontsDir(pwcPFB);
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* VOID vAddRemote/LocalType1Font
|
|
*
|
|
* History:
|
|
* 25-Apr-1996 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
|
|
|
|
VOID vAddType1Font(
|
|
WCHAR *pwcValueData,
|
|
DWORD dwFlags
|
|
)
|
|
{
|
|
WCHAR *pwcPFM, *pwcPFB, *pwcMMM;
|
|
|
|
#if DBG
|
|
int iRet;
|
|
#endif
|
|
|
|
// skip unused boolean value in this multi reg_sz string:
|
|
|
|
if ((pwcValueData[0] != L'\0') && (pwcValueData[1] == L'\0'))
|
|
{
|
|
pwcPFM = &pwcValueData[2];
|
|
pwcPFB = pwcPFM + wcslen(pwcPFM) + 1; // add 1 for zero separator
|
|
pwcMMM = pwcPFB + wcslen(pwcPFB) + 1; // may of may not be there.
|
|
|
|
// replace space by separator and call addfontresourcew
|
|
|
|
pwcPFB[-1] = PATH_SEPARATOR;
|
|
|
|
// if this is a multiple master font, need one more separator:
|
|
|
|
if (pwcMMM[0] != L'\0')
|
|
pwcMMM[-1] = PATH_SEPARATOR;
|
|
|
|
#if DBG
|
|
iRet =
|
|
#endif
|
|
|
|
GdiAddFontResourceW(pwcPFM, dwFlags, NULL);
|
|
|
|
#if DBGSWEEP
|
|
DbgPrint("%ld = GdiAddFontResourceW(%ws, 0x%lx);\n",
|
|
iRet, pwcPFM, dwFlags);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
VOID vAddRemoteType1Font(
|
|
HKEY hkey,
|
|
WCHAR *pwcValueName,
|
|
ULONG ulValueNameLength,
|
|
WCHAR *pwcValueData,
|
|
ULONG ulValueDataLength
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(hkey);
|
|
UNREFERENCED_PARAMETER(pwcValueName);
|
|
UNREFERENCED_PARAMETER(ulValueNameLength);
|
|
UNREFERENCED_PARAMETER(ulValueDataLength);
|
|
vAddType1Font(pwcValueData, AFRW_ADD_REMOTE_FONT);
|
|
}
|
|
|
|
VOID vAddLocalType1Font(
|
|
HKEY hkey,
|
|
WCHAR *pwcValueName,
|
|
ULONG ulValueNameLength,
|
|
WCHAR *pwcValueData,
|
|
ULONG ulValueDataLength
|
|
)
|
|
{
|
|
UNREFERENCED_PARAMETER(hkey);
|
|
UNREFERENCED_PARAMETER(pwcValueName);
|
|
UNREFERENCED_PARAMETER(ulValueNameLength);
|
|
UNREFERENCED_PARAMETER(ulValueDataLength);
|
|
vAddType1Font(pwcValueData, AFRW_ADD_LOCAL_FONT);
|
|
}
|
|
|
|
|
|
typedef VOID (*PFNENTRY)(HKEY hkey, WCHAR *, ULONG, WCHAR *, ULONG);
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* VOID vFontSweep()
|
|
*
|
|
* This is the main routine in this module. Checks if the fonts need to be
|
|
* "sweeped" and does so if need be.
|
|
*
|
|
* History:
|
|
* 27-Oct-1995 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID vSweepFonts(
|
|
PCWSTR pwszFontListKey, // font list key
|
|
PCWSTR pwszFontSweepKey, // the corresponding sweep key
|
|
PFNENTRY pfnProcessFontEntry, // function that processes individual entry
|
|
BOOL bForceEnum // force enumeration
|
|
)
|
|
{
|
|
DWORD cjMaxValueName;
|
|
DWORD iFont;
|
|
NTSTATUS Status;
|
|
UNICODE_STRING UnicodeString;
|
|
OBJECT_ATTRIBUTES ObjA;
|
|
KEY_FULL_INFORMATION KeyInfo;
|
|
DWORD dwReturnLength;
|
|
|
|
PKEY_VALUE_FULL_INFORMATION KeyValueInfo;
|
|
BYTE *pjValueData;
|
|
|
|
HKEY hkey = NULL;
|
|
struct {
|
|
KEY_VALUE_PARTIAL_INFORMATION;
|
|
LARGE_INTEGER;
|
|
} SweepValueInfo;
|
|
LARGE_INTEGER LastSweepTime;
|
|
BOOL bSweep = FALSE;
|
|
|
|
HKEY hkeyLastSweep;
|
|
DWORD cjData;
|
|
|
|
if (!bForceEnum)
|
|
{
|
|
// first check if anything needs to be done, that is, if anybody
|
|
// touched the [Fonts] section of the registry since the last time we sweeped it.
|
|
// get the time of the last sweep of the fonts section of the registry:
|
|
|
|
RtlInitUnicodeString(&UnicodeString, pwszFontSweepKey);
|
|
InitializeObjectAttributes(&ObjA,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
Status = NtOpenKey(&hkeyLastSweep,
|
|
KEY_READ | KEY_WRITE,
|
|
&ObjA);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DWORD dwDisposition;
|
|
|
|
// We are running for the first time, we need to create the key
|
|
// for it does not exist as yet at this time
|
|
|
|
bSweep = TRUE;
|
|
|
|
// Create the key, open it for writing, since we will have to
|
|
// store the time when the [Fonts] section of the registry was last swept
|
|
|
|
Status = NtCreateKey(&hkeyLastSweep,
|
|
KEY_WRITE,
|
|
&ObjA,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
&dwDisposition);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
RtlInitUnicodeString(&UnicodeString, LAST_SWEEP_TIME);
|
|
Status = NtQueryValueKey(hkeyLastSweep,
|
|
&UnicodeString,
|
|
KeyValuePartialInformation,
|
|
&SweepValueInfo,
|
|
sizeof(SweepValueInfo),
|
|
&dwReturnLength);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
bSweep = TRUE; // force sweep, something is suspicious
|
|
}
|
|
else
|
|
{
|
|
UserAssert(SweepValueInfo.Type == REG_BINARY);
|
|
UserAssert(SweepValueInfo.DataLength == sizeof(LastSweepTime));
|
|
RtlCopyMemory(&LastSweepTime, &SweepValueInfo.Data, sizeof(LastSweepTime));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bSweep = TRUE;
|
|
}
|
|
|
|
// now open the Fonts key and get the time the key last changed:
|
|
// now get the time of the time of the last change is bigger than
|
|
// the time of last sweep, must sweep again:
|
|
|
|
RtlInitUnicodeString(&UnicodeString, pwszFontListKey);
|
|
InitializeObjectAttributes(&ObjA,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
Status = NtOpenKey(&hkey,
|
|
KEY_READ | KEY_WRITE,
|
|
&ObjA);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
// get the number of entries in the [Fonts] section
|
|
|
|
Status = NtQueryKey(hkey,
|
|
KeyFullInformation,
|
|
&KeyInfo,
|
|
sizeof(KeyInfo),
|
|
&dwReturnLength);
|
|
|
|
if (NT_SUCCESS(Status) && KeyInfo.Values)
|
|
{
|
|
UserAssert(!(KeyInfo.ClassLength | KeyInfo.SubKeys | KeyInfo.MaxNameLen | KeyInfo.MaxClassLen));
|
|
|
|
// now let us check if the fonts need to be sweeped. This is the case
|
|
// when the registry last write time is bigger than the last sweep time
|
|
|
|
if (!bSweep)
|
|
{
|
|
if (KeyInfo.LastWriteTime.QuadPart != LastSweepTime.QuadPart ) {
|
|
bSweep = TRUE;
|
|
}
|
|
}
|
|
|
|
// init system dir, we will need it:
|
|
|
|
if (bSweep &&
|
|
bInitSystemAndFontsDirectoriesW(&gpwcSystemDir, &gpwcFontsDir))
|
|
{
|
|
// alloc buffer big enough to hold the biggest ValueName and ValueData
|
|
|
|
cjMaxValueName = DWORDALIGN(KeyInfo.MaxValueNameLen + sizeof(WCHAR));
|
|
|
|
// allocate temporary buffer into which we are going to pull the contents
|
|
// of the registry
|
|
|
|
KeyInfo.MaxValueDataLen = DWORDALIGN(KeyInfo.MaxValueDataLen);
|
|
cjData = cjMaxValueName + // space for the value name
|
|
KeyInfo.MaxValueDataLen ; // space for the value data
|
|
|
|
if (KeyValueInfo = UserLocalAlloc(0, sizeof(*KeyValueInfo) + cjData))
|
|
{
|
|
for (iFont = 0; iFont < KeyInfo.Values; iFont++)
|
|
{
|
|
Status = NtEnumerateValueKey(
|
|
hkey,
|
|
iFont,
|
|
KeyValueFullInformation,
|
|
KeyValueInfo,
|
|
sizeof(*KeyValueInfo) + cjData,
|
|
&dwReturnLength);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
UserAssert(KeyValueInfo->NameLength <= KeyInfo.MaxValueNameLen);
|
|
UserAssert(KeyValueInfo->DataLength <= KeyInfo.MaxValueDataLen);
|
|
UserAssert((KeyValueInfo->Type == REG_SZ) || (KeyValueInfo->Type == REG_MULTI_SZ));
|
|
|
|
// data goes into the second half of the buffer
|
|
|
|
pjValueData = (BYTE *)KeyValueInfo + KeyValueInfo->DataOffset;
|
|
|
|
// see if the font files are where the registry claims they are.
|
|
// It is unfortunate we have to do this because SearchPathW
|
|
// is slow because it touches the disk.
|
|
|
|
(*pfnProcessFontEntry)(hkey,
|
|
KeyValueInfo->Name,
|
|
KeyValueInfo->NameLength / sizeof(WCHAR),
|
|
(WCHAR *)pjValueData,
|
|
KeyValueInfo->DataLength / sizeof(WCHAR));
|
|
}
|
|
}
|
|
|
|
if (!bForceEnum)
|
|
{
|
|
// now that the sweep is completed, get the last write time
|
|
// and store it as the LastSweepTime at the appropriate location
|
|
|
|
Status = NtQueryKey(hkey,
|
|
KeyFullInformation,
|
|
&KeyInfo,
|
|
sizeof(KeyInfo),
|
|
&dwReturnLength);
|
|
UserAssert(NT_SUCCESS(Status));
|
|
|
|
// now remember the result
|
|
|
|
RtlInitUnicodeString(&UnicodeString, LAST_SWEEP_TIME);
|
|
Status = NtSetValueKey(hkeyLastSweep,
|
|
&UnicodeString,
|
|
0,
|
|
REG_BINARY,
|
|
&KeyInfo.LastWriteTime,
|
|
sizeof(KeyInfo.LastWriteTime));
|
|
UserAssert(NT_SUCCESS(Status));
|
|
}
|
|
|
|
// free the memory that will be no longer needed
|
|
|
|
UserLocalFree(KeyValueInfo);
|
|
}
|
|
}
|
|
}
|
|
NtClose(hkey);
|
|
}
|
|
|
|
if (!bForceEnum)
|
|
{
|
|
NtClose(hkeyLastSweep);
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* BOOL bLoadableFontDrivers()
|
|
*
|
|
* open the font drivers key and check if there are any entries, if so
|
|
* return true. If that is the case we will call AddFontResourceW on
|
|
* Type 1 fonts at boot time, right after user had logged on
|
|
* PostScript printer drivers are not initialized at this time yet,
|
|
* it is safe to do it at this time.
|
|
* Effects:
|
|
*
|
|
* Warnings:
|
|
*
|
|
* History:
|
|
* 24-Apr-1996 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
|
|
BOOL bLoadableFontDrivers()
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING UnicodeString;
|
|
OBJECT_ATTRIBUTES ObjA;
|
|
KEY_FULL_INFORMATION KeyInfo;
|
|
DWORD dwReturnLength;
|
|
HKEY hkey = NULL;
|
|
BOOL bRet = FALSE;
|
|
|
|
// open the font drivers key and check if there are any entries, if so
|
|
// return true. If that is the case we will call AddFontResourceW on
|
|
// Type 1 fonts at boot time, right after user had logged on
|
|
// PostScript printer drivers are not initialized at this time yet,
|
|
// it is safe to do it at this time.
|
|
|
|
RtlInitUnicodeString(&UnicodeString, pwszFontDrivers);
|
|
InitializeObjectAttributes(&ObjA,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
Status = NtOpenKey(&hkey,
|
|
KEY_READ,
|
|
&ObjA);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
// get the number of entries in the [Fonts] section
|
|
|
|
Status = NtQueryKey(hkey,
|
|
KeyFullInformation,
|
|
&KeyInfo,
|
|
sizeof(KeyInfo),
|
|
&dwReturnLength);
|
|
|
|
if (NT_SUCCESS(Status) && KeyInfo.Values)
|
|
{
|
|
UserAssert(!(KeyInfo.ClassLength | KeyInfo.SubKeys | KeyInfo.MaxNameLen | KeyInfo.MaxClassLen));
|
|
|
|
// externally loadable drivers are present, force sweep
|
|
|
|
bRet = TRUE;
|
|
}
|
|
|
|
NtClose(hkey);
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
|
|
|
|
/***********************Public*Routine******************************\
|
|
*
|
|
* BOOL bCheckAndDeleteTTF()
|
|
*
|
|
* Checks whether there is a converted TTF corresponding to
|
|
* a Type1 font. Delete the TTF file and the reg entry if there is.
|
|
*
|
|
* History:
|
|
* 29-Jan-1998 -by- Xudong Wu [TessieW]
|
|
* Wrote it.
|
|
\*******************************************************************/
|
|
BOOL bCheckAndDeleteTTF
|
|
(
|
|
HKEY hkey,
|
|
PKEY_FULL_INFORMATION pKeyInfo,
|
|
PKEY_VALUE_FULL_INFORMATION KeyValueInfo,
|
|
PKEY_VALUE_BASIC_INFORMATION KeyValueBasicInfo,
|
|
DWORD cjData
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING UnicodeString;
|
|
DWORD dwReturnLength;
|
|
ULONG iFont;
|
|
WCHAR awcTmp[MAX_PATH], *pFontName, *pType1Name, *pwcFile;
|
|
BOOL bDelTTFfile, bRet = TRUE;
|
|
FLONG fl;
|
|
WCHAR awcType1Name[MAX_PATH]; // null-terminated pType1Name
|
|
WCHAR awcFontName[MAX_PATH]; // null-terminated pFontName
|
|
WCHAR awcFile[MAX_PATH]; // null-terminated pwcFile
|
|
|
|
// pKeyInfo holds the full info on the key "Fonts"
|
|
for (iFont = 0; iFont < pKeyInfo->Values; iFont++)
|
|
{
|
|
RtlZeroMemory(KeyValueInfo->Name, cjData);
|
|
Status = NtEnumerateValueKey(
|
|
hkey,
|
|
iFont,
|
|
KeyValueFullInformation,
|
|
KeyValueInfo,
|
|
sizeof(*KeyValueInfo) + cjData,
|
|
&dwReturnLength);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
UserAssert(KeyValueInfo->NameLength <= pKeyInfo->MaxValueNameLen);
|
|
UserAssert(KeyValueInfo->DataLength <= pKeyInfo->MaxValueDataLen);
|
|
UserAssert(KeyValueInfo->Type == REG_SZ);
|
|
|
|
bDelTTFfile = FALSE;
|
|
|
|
// Make sure we use null-terminated strings
|
|
vNullTermWideString (awcType1Name,
|
|
KeyValueBasicInfo->Name,
|
|
KeyValueBasicInfo->NameLength / sizeof(WCHAR));
|
|
vNullTermWideString (awcFontName,
|
|
KeyValueInfo->Name,
|
|
KeyValueInfo->NameLength / sizeof(WCHAR));
|
|
vNullTermWideString (awcFile,
|
|
(WCHAR *) ((BYTE *)KeyValueInfo + KeyValueInfo->DataOffset),
|
|
KeyValueInfo->DataLength / sizeof(WCHAR));
|
|
pType1Name = awcType1Name;
|
|
pFontName = awcFontName;
|
|
pwcFile = awcFile;
|
|
|
|
while((*pType1Name) && (*pType1Name++ == *pFontName++))
|
|
;
|
|
|
|
// if the font name match the type1 name
|
|
// check whether this is a ttf font
|
|
if ((*pType1Name == 0) && (*pFontName++ == L' '))
|
|
{
|
|
WCHAR *pTrueType = L"(TrueType)";
|
|
|
|
while(*pTrueType && (*pTrueType++ == *pFontName++))
|
|
;
|
|
if (*pTrueType == 0)
|
|
{
|
|
bDelTTFfile = TRUE;
|
|
}
|
|
}
|
|
|
|
if (bDelTTFfile)
|
|
{
|
|
// delete the converted TTF file
|
|
if (bRet = bMakePathNameW(awcTmp, pwcFile, NULL, &fl))
|
|
{
|
|
UserVerify((bRet = DeleteFileW(awcTmp)));
|
|
}
|
|
|
|
// remove the reg entry
|
|
*pFontName = 0;
|
|
RtlInitUnicodeString(&UnicodeString, awcFontName);
|
|
Status = NtDeleteValueKey(hkey, (PUNICODE_STRING)&UnicodeString);
|
|
|
|
// decrement the number of values under [Fonts]
|
|
if (NT_SUCCESS(Status))
|
|
pKeyInfo->Values--;
|
|
else
|
|
bRet = FALSE;
|
|
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
/***********************Public*Routine**************************\
|
|
*
|
|
* BOOL bCleanConvertedTTFs()
|
|
*
|
|
* Enumerate each entry under "Upgrade Type1" key, call
|
|
* bCheckAndDeleteTTF() to remove the coverted TTFs.
|
|
*
|
|
* History:
|
|
* 29-Jan-1998 -by- Xudong Wu [TessieW]
|
|
* Wrote it.
|
|
\***************************************************************/
|
|
BOOL bCleanConvertedTTFs()
|
|
{
|
|
UNICODE_STRING UnicodeString;
|
|
OBJECT_ATTRIBUTES ObjA;
|
|
NTSTATUS Status;
|
|
HKEY hkeyFonts = NULL, hkeyType1 = NULL;
|
|
DWORD dwReturnLength;
|
|
DWORD iFontT1, cjData;
|
|
DWORD cjMaxValueNameT1, cjMaxValueNameFonts;
|
|
BOOL bRet = FALSE, bError = FALSE;
|
|
|
|
KEY_FULL_INFORMATION KeyInfoType1, KeyInfoFonts;
|
|
PKEY_VALUE_BASIC_INFORMATION KeyValueBasicInfo;
|
|
PKEY_VALUE_FULL_INFORMATION KeyValueInfo;
|
|
|
|
// Open and query the value from the "Type1 Fonts" key
|
|
// No need to continue if not succeed or no Type1 font listed
|
|
RtlInitUnicodeString(&UnicodeString, pwszType1Key);
|
|
InitializeObjectAttributes(&ObjA,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = NtOpenKey(&hkeyType1,
|
|
KEY_READ | KEY_WRITE,
|
|
&ObjA);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
Status = NtQueryKey(hkeyType1,
|
|
KeyFullInformation,
|
|
&KeyInfoType1,
|
|
sizeof(KeyInfoType1),
|
|
&dwReturnLength);
|
|
|
|
if (NT_SUCCESS(Status) && KeyInfoType1.Values)
|
|
{
|
|
UserAssert(!(KeyInfoType1.ClassLength | KeyInfoType1.SubKeys |
|
|
KeyInfoType1.MaxNameLen | KeyInfoType1.MaxClassLen));
|
|
|
|
cjMaxValueNameT1 = DWORDALIGN(KeyInfoType1.MaxValueNameLen + sizeof(WCHAR));
|
|
|
|
// Alloc buffer big enough to hold the longest Name
|
|
if (KeyValueBasicInfo = UserLocalAlloc(0, sizeof(*KeyValueBasicInfo) + cjMaxValueNameT1))
|
|
{
|
|
RtlInitUnicodeString(&UnicodeString, pwszFontsKey);
|
|
InitializeObjectAttributes(&ObjA,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
Status = NtOpenKey(&hkeyFonts,
|
|
KEY_READ | KEY_WRITE,
|
|
&ObjA);
|
|
if (NT_SUCCESS(Status)) {
|
|
Status = NtQueryKey(hkeyFonts,
|
|
KeyFullInformation,
|
|
&KeyInfoFonts,
|
|
sizeof(KeyInfoFonts),
|
|
&dwReturnLength);
|
|
if (NT_SUCCESS(Status) && KeyInfoFonts.Values) {
|
|
UserAssert(!(KeyInfoFonts.ClassLength | KeyInfoFonts.SubKeys |
|
|
KeyInfoFonts.MaxNameLen | KeyInfoFonts.MaxClassLen));
|
|
|
|
cjMaxValueNameFonts = DWORDALIGN(KeyInfoFonts.MaxValueNameLen + sizeof(WCHAR));
|
|
KeyInfoFonts.MaxValueDataLen = DWORDALIGN(KeyInfoFonts.MaxValueDataLen);
|
|
cjData = cjMaxValueNameFonts + KeyInfoFonts.MaxValueDataLen;
|
|
|
|
// Alloc buffer big enough to hold the longest Name and Value
|
|
if (KeyValueInfo = UserLocalAlloc(0, sizeof(*KeyValueInfo) + cjData))
|
|
{
|
|
// Enum the "Type1 Fonts" key
|
|
for (iFontT1 = 0; iFontT1 < KeyInfoType1.Values; iFontT1++)
|
|
{
|
|
RtlZeroMemory(KeyValueBasicInfo->Name, cjMaxValueNameT1);
|
|
Status = NtEnumerateValueKey(
|
|
hkeyType1,
|
|
iFontT1,
|
|
KeyValueBasicInformation,
|
|
KeyValueBasicInfo,
|
|
sizeof(*KeyValueBasicInfo) + cjMaxValueNameT1,
|
|
&dwReturnLength);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
UserAssert(KeyValueBasicInfo->NameLength <= KeyInfoType1.MaxValueNameLen);
|
|
UserAssert(KeyValueBasicInfo->Type == REG_MULTI_SZ);
|
|
|
|
// For each Type1 font, check to see whether
|
|
// there is corresponding converted TTF
|
|
// Delete the TTF file and reg entry if any
|
|
|
|
bRet = bCheckAndDeleteTTF(hkeyFonts, &KeyInfoFonts, KeyValueInfo,
|
|
KeyValueBasicInfo, cjData);
|
|
if (!bRet)
|
|
{
|
|
bError = TRUE;
|
|
}
|
|
}
|
|
}
|
|
UserLocalFree(KeyValueInfo);
|
|
// no type1 fonts installed
|
|
if (KeyInfoType1.Values == 0)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
NtClose(hkeyFonts);
|
|
} // NtOpenKey (hkeyFonts)
|
|
UserLocalFree(KeyValueBasicInfo);
|
|
}
|
|
} // NtQueryKey (hkeyType1)
|
|
NtClose(hkeyType1);
|
|
}
|
|
|
|
return (bRet && !bError);
|
|
}
|
|
|
|
|
|
/***********************Public*Routine******************************\
|
|
*
|
|
* VOID vCleanConvertedTTFs()
|
|
*
|
|
* Delete the converted TTFs and clean the registry if there is any
|
|
* TTFs generated from Type1 fonts.
|
|
*
|
|
* History:
|
|
* 29-Jan-1998 -by- Xudong Wu [TessieW]
|
|
* Wrote it.
|
|
\*******************************************************************/
|
|
VOID vCleanConvertedTTFs()
|
|
{
|
|
BOOL bNeedUpgrade = FALSE;
|
|
UNICODE_STRING UnicodeString;
|
|
OBJECT_ATTRIBUTES ObjA;
|
|
DWORD dwReturnLength;
|
|
NTSTATUS Status;
|
|
HKEY hkeyUpgradeType1 = NULL;
|
|
|
|
struct {
|
|
KEY_VALUE_PARTIAL_INFORMATION;
|
|
LARGE_INTEGER;
|
|
} UpgradeValueInfo;
|
|
DWORD UpgradeValue = 0;
|
|
|
|
RtlInitUnicodeString(&UnicodeString, pwszUpdType1Key);
|
|
InitializeObjectAttributes(&ObjA,
|
|
&UnicodeString,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = NtOpenKey(&hkeyUpgradeType1,
|
|
KEY_READ | KEY_WRITE,
|
|
&ObjA);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
// Key doesn't exist, run for the first time
|
|
// Create the key, open it for writing
|
|
|
|
DWORD dwDisposition;
|
|
|
|
Status = NtCreateKey(&hkeyUpgradeType1,
|
|
KEY_WRITE,
|
|
&ObjA,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
&dwDisposition);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
bNeedUpgrade = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
RtlInitUnicodeString(&UnicodeString, UPGRADED_TYPE1);
|
|
Status = NtQueryValueKey(hkeyUpgradeType1,
|
|
&UnicodeString,
|
|
KeyValuePartialInformation,
|
|
&UpgradeValueInfo,
|
|
sizeof(UpgradeValueInfo),
|
|
&dwReturnLength);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
UserAssert(UpgradeValueInfo.Type == REG_DWORD);
|
|
UserAssert(UpgradeValueInfo.DataLength == sizeof(UpgradeValue));
|
|
RtlCopyMemory(&UpgradeValue, &UpgradeValueInfo.Data, sizeof(UpgradeValue));
|
|
|
|
// Done if the value is non-zero.
|
|
if (UpgradeValue == 0)
|
|
{
|
|
bNeedUpgrade = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bNeedUpgrade)
|
|
{
|
|
if (bCleanConvertedTTFs())
|
|
{
|
|
UpgradeValue = 1;
|
|
}
|
|
|
|
RtlInitUnicodeString(&UnicodeString, UPGRADED_TYPE1);
|
|
Status = NtSetValueKey(hkeyUpgradeType1,
|
|
&UnicodeString,
|
|
0,
|
|
REG_DWORD,
|
|
&UpgradeValue,
|
|
sizeof(UpgradeValue));
|
|
UserAssert(NT_SUCCESS(Status));
|
|
}
|
|
|
|
if (hkeyUpgradeType1)
|
|
{
|
|
NtClose(hkeyUpgradeType1);
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* VOID vFontSweep()
|
|
*
|
|
* Effects: The main routine, calls vSweepFonts to sweep "regular" fonts
|
|
* and then to sweep type 1 fonts
|
|
*
|
|
* History:
|
|
* 20-Nov-1995 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
VOID vFontSweep(
|
|
VOID)
|
|
{
|
|
/*
|
|
* Check if shared windows directory installation.
|
|
*/
|
|
gbWin31Upgrade = bCheckIfDualBootingWithWin31();
|
|
|
|
/*
|
|
* Before we sweep the files to the Fonts directory, check whether the
|
|
* 'converted' TTFs have been removed.
|
|
*/
|
|
vCleanConvertedTTFs();
|
|
|
|
/*
|
|
* Sweep fonts in the [Fonts] key.
|
|
*/
|
|
vSweepFonts(pwszFontsKey, pwszSweepKey, vProcessFontEntry, FALSE);
|
|
|
|
/*
|
|
* Now sweep type 1 fonts, if any.
|
|
*/
|
|
vSweepFonts(pwszType1Key, pwszSweepType1Key, vProcessType1FontEntry, FALSE);
|
|
|
|
if (gpwcSystemDir) {
|
|
UserLocalFree(gpwcSystemDir);
|
|
gpwcSystemDir = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* vLoadLT1Fonts
|
|
*
|
|
* History:
|
|
* 30-Apr-1996 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
VOID vLoadT1Fonts(
|
|
PFNENTRY pfnProcessFontEntry)
|
|
{
|
|
if (bLoadableFontDrivers()) {
|
|
/*
|
|
* Now enum and add remote type1 fonts if any.
|
|
*/
|
|
vSweepFonts(pwszType1Key, pwszSweepType1Key, pfnProcessFontEntry, TRUE);
|
|
|
|
if (gpwcSystemDir) {
|
|
UserLocalFree(gpwcSystemDir);
|
|
gpwcSystemDir = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID vLoadLocalT1Fonts(
|
|
VOID)
|
|
{
|
|
vLoadT1Fonts(vAddLocalType1Font);
|
|
}
|
|
|
|
VOID vLoadRemoteT1Fonts(
|
|
VOID)
|
|
{
|
|
vLoadT1Fonts(vAddRemoteType1Font);
|
|
}
|