mirror of https://github.com/lianthony/NT4.0
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.
951 lines
30 KiB
951 lines
30 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: fntsweep.c
|
|
*
|
|
* Created: 23-Oct-1995 12:48:42
|
|
* 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
|
|
|
|
WCHAR pwszType1Key[] = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Type 1 Installer\\Type 1 Fonts";
|
|
WCHAR pwszSweepType1Key[] = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Type 1 Installer\\LastType1Sweep";
|
|
|
|
WCHAR pwszFontsKey[] = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
|
|
WCHAR pwszSweepKey[] = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontCache\\LastFontSweep";
|
|
WCHAR pwszFontDrivers[] = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Font Drivers";
|
|
|
|
#define LAST_SWEEP_TIME L"LastSweepTime"
|
|
|
|
#define DWORDALIGN(X) (((X) + 3) & ~3)
|
|
|
|
WCHAR *gpwcSystemDir = NULL;
|
|
WCHAR *gpwcFontsDir = NULL;
|
|
BOOL gbWin31Upgrade = FALSE;
|
|
|
|
|
|
BOOL bCheckIfDualBootingWithWin31()
|
|
{
|
|
WCHAR Buffer[32];
|
|
WCHAR awcWindowsDir[MAX_PATH];
|
|
DWORD dwRet;
|
|
UINT cwchWinPath = GetWindowsDirectoryW(awcWindowsDir, MAX_PATH);
|
|
|
|
// 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 DBG
|
|
DbgPrint("\n dwRet = %ld, win31upgrade = %ws\n\n", dwRet, Buffer);
|
|
#endif
|
|
|
|
return (BOOL)(dwRet ? (!lstrcmpiW(Buffer,WINNT_A_YES)) : 0);
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* BOOL bCheckFontEntry(WCHAR *pwcName, WCHAR *pwcExtension)
|
|
*
|
|
* 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,
|
|
WCHAR *pwcFileName
|
|
)
|
|
{
|
|
BOOL bFot = FALSE;
|
|
WCHAR awcTTF[MAX_PATH];
|
|
WCHAR awcTmpBuf[MAX_PATH];
|
|
WCHAR *pwcTTF;
|
|
FLONG fl, fl2;
|
|
FLONG flEmbed;
|
|
DWORD dwPidTid;
|
|
|
|
if (bCheckFontEntry(pwcValueName, EXT_TRUETYPE))
|
|
{
|
|
// This is a tt entry, either .fot or .ttf
|
|
|
|
if (bFot = bCheckFontEntry(pwcFileName,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, pwcFileName,NULL, &fl2))
|
|
{
|
|
if (cGetTTFFromFOT(awcTmpBuf, MAX_PATH, awcTTF, &fl, &flEmbed, &dwPidTid) &&
|
|
!(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);
|
|
UserVerify(ERROR_SUCCESS ==
|
|
RegSetValueExW(
|
|
hkey, // here is the key
|
|
pwcValueName,
|
|
0,
|
|
REG_SZ,
|
|
(CONST BYTE*) pwcTTF,
|
|
(DWORD)((wcslen(pwcTTF)+1) * sizeof(WCHAR))));
|
|
}
|
|
#ifdef DEBUG
|
|
else
|
|
{
|
|
RIPMSG1(RIP_WARNING, "Could not locate ttf pointed to by %ws", awcTmpBuf);
|
|
}
|
|
#endif
|
|
}
|
|
#ifdef DEBUG
|
|
else
|
|
{
|
|
RIPMSG1(RIP_WARNING, "Could not locate .fot: %ws", pwcFileName);
|
|
}
|
|
#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, pwcFileName,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);
|
|
UserVerify(ERROR_SUCCESS ==
|
|
RegSetValueExW(
|
|
hkey, // here is the key
|
|
pwcValueName,
|
|
0,
|
|
REG_SZ,
|
|
(CONST BYTE*) pwcTTF,
|
|
(DWORD)((wcslen(pwcTTF)+1) * sizeof(WCHAR))));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/******************************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,
|
|
WCHAR *pwcValueData
|
|
)
|
|
{
|
|
WCHAR *pwcPFM, *pwcPFB;
|
|
|
|
// 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);
|
|
|
|
#if DBG
|
|
DbgPrint("%ld = GdiAddFontResourceW(%ws, 0x%lx);\n",
|
|
iRet, pwcPFM, dwFlags);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
VOID vAddRemoteType1Font(
|
|
HKEY hkey,
|
|
WCHAR *pwcValueName,
|
|
WCHAR *pwcValueData
|
|
)
|
|
{
|
|
hkey;
|
|
pwcValueName;
|
|
vAddType1Font(pwcValueData, AFRW_ADD_REMOTE_FONT);
|
|
}
|
|
|
|
VOID vAddLocalType1Font(
|
|
HKEY hkey,
|
|
WCHAR *pwcValueName,
|
|
WCHAR *pwcValueData
|
|
)
|
|
{
|
|
hkey;
|
|
pwcValueName;
|
|
vAddType1Font(pwcValueData, AFRW_ADD_LOCAL_FONT);
|
|
}
|
|
|
|
|
|
typedef VOID (*PFNENTRY)(HKEY hkey, WCHAR *, WCHAR *);
|
|
|
|
|
|
/******************************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(
|
|
WCHAR *pwszFontListKey, // font list key
|
|
WCHAR *pwszFontSweepKey, // the corresponding sweep key
|
|
PFNENTRY pfnProcessFontEntry, // function that processes individual entry
|
|
BOOL bForceEnum // force enumeration
|
|
)
|
|
{
|
|
LONG lRet;
|
|
WCHAR awcClass[MAX_PATH] = L"";
|
|
DWORD cwcClassName = MAX_PATH;
|
|
DWORD cSubKeys;
|
|
DWORD cjMaxSubKey;
|
|
DWORD cwcMaxClass;
|
|
DWORD cValues = 0;
|
|
DWORD cwcMaxValueName, cjMaxValueName;
|
|
DWORD cjMaxValueData;
|
|
DWORD cjSecurityDescriptor;
|
|
DWORD iFont;
|
|
|
|
WCHAR *pwcValueName;
|
|
BYTE *pjValueData;
|
|
DWORD cwcValueName, cjValueData;
|
|
|
|
HKEY hkey = NULL;
|
|
FILETIME ftLastWriteTime;
|
|
FILETIME ftLastSweepTime;
|
|
BOOL bSweep = FALSE;
|
|
|
|
HKEY hkeyLastSweep;
|
|
DWORD dwType;
|
|
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:
|
|
|
|
lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, // Root key
|
|
pwszFontSweepKey, // Subkey to open
|
|
0L, // Reserved
|
|
KEY_READ|KEY_WRITE, // SAM
|
|
&hkeyLastSweep); // return handle
|
|
|
|
if (lRet != ERROR_SUCCESS)
|
|
{
|
|
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
|
|
|
|
lRet = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
|
|
pwszFontSweepKey,
|
|
0,
|
|
REG_OPTION_NON_VOLATILE,
|
|
0,
|
|
KEY_WRITE,
|
|
NULL,
|
|
&hkeyLastSweep,
|
|
&dwDisposition
|
|
);
|
|
|
|
if (lRet != ERROR_SUCCESS)
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
lRet = RegQueryValueExW(hkeyLastSweep,
|
|
LAST_SWEEP_TIME,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)&ftLastSweepTime,
|
|
&cjData
|
|
);
|
|
if (lRet != ERROR_SUCCESS)
|
|
{
|
|
bSweep = TRUE; // force sweep, something is suspicious
|
|
}
|
|
#if DBG
|
|
else
|
|
{
|
|
UserAssert(dwType == REG_BINARY);
|
|
UserAssert(cjData == sizeof(ftLastSweepTime));
|
|
}
|
|
#endif // DBG
|
|
}
|
|
}
|
|
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:
|
|
|
|
lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, // Root key
|
|
pwszFontListKey, // Subkey to open
|
|
0L, // Reserved
|
|
KEY_READ|KEY_WRITE, // SAM
|
|
&hkey); // return handle
|
|
|
|
if (lRet == ERROR_SUCCESS)
|
|
{
|
|
// get the number of entries in the [Fonts] section
|
|
|
|
lRet = RegQueryInfoKeyW(
|
|
hkey,
|
|
awcClass, // "" on return
|
|
&cwcClassName, // 0 on return
|
|
NULL,
|
|
&cSubKeys, // 0 on return
|
|
&cjMaxSubKey, // 0 on return
|
|
&cwcMaxClass, // 0 on return
|
|
&cValues, // == cFonts, if all of them are present
|
|
&cwcMaxValueName, // longest value name
|
|
&cjMaxValueData, // longest value data
|
|
&cjSecurityDescriptor, // security descriptor,
|
|
&ftLastWriteTime
|
|
);
|
|
|
|
if ((lRet == ERROR_SUCCESS) && cValues)
|
|
{
|
|
UserAssert(!(cwcClassName | cSubKeys | cjMaxSubKey | cwcMaxClass | awcClass[0]));
|
|
|
|
// 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)
|
|
{
|
|
switch(CompareFileTime(&ftLastWriteTime, &ftLastSweepTime))
|
|
{
|
|
case 1:
|
|
bSweep = TRUE;
|
|
break;
|
|
case 0:
|
|
bSweep = FALSE;
|
|
break;
|
|
case -1:
|
|
|
|
// Error condition, this should not have happened,
|
|
// we will sweep just to be safe.
|
|
|
|
bSweep = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// 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((cwcMaxValueName+1) * sizeof(WCHAR));
|
|
|
|
// allocate temporary buffer into which we are going to suck the contents
|
|
// of the registry
|
|
|
|
cjMaxValueData = DWORDALIGN(cjMaxValueData);
|
|
cjData = cjMaxValueName + // space for the value name
|
|
cjMaxValueData ; // space for the value data
|
|
|
|
#if DBG
|
|
{
|
|
dwType = sizeof(WCHAR) * MAX_PATH;
|
|
UserAssert((dwType & 3) == 0);
|
|
}
|
|
#endif
|
|
|
|
if (pwcValueName = LocalAlloc(LMEM_FIXED,cjData))
|
|
{
|
|
// data goes into the second half of the buffer
|
|
|
|
pjValueData = (BYTE *)pwcValueName + cjMaxValueName;
|
|
|
|
for (iFont = 0; iFont < cValues; iFont++)
|
|
{
|
|
// make sure to let RegEnumValueW the size of buffers
|
|
|
|
// Note that this is bizzare, on input RegEnumValueW expects
|
|
// the size in BYTE's of the ValueName buffer
|
|
// (including the terminating zero),
|
|
// on return RegEnumValueW returns the number of WCHAR's
|
|
// NOT including the terminating zero.
|
|
|
|
cwcValueName = cjMaxValueName; // bizzare
|
|
cjValueData = cjMaxValueData;
|
|
|
|
lRet = RegEnumValueW(
|
|
hkey,
|
|
iFont,
|
|
pwcValueName,
|
|
&cwcValueName,
|
|
NULL, // reserved
|
|
&dwType,
|
|
pjValueData,
|
|
&cjValueData
|
|
);
|
|
|
|
if (lRet == ERROR_SUCCESS)
|
|
{
|
|
UserAssert(cwcValueName <= cwcMaxValueName);
|
|
UserAssert(cjValueData <= cjMaxValueData);
|
|
UserAssert((dwType == REG_SZ) || (dwType == REG_MULTI_SZ));
|
|
|
|
// 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, pwcValueName, (WCHAR *)pjValueData);
|
|
}
|
|
}
|
|
|
|
if (!bForceEnum)
|
|
{
|
|
// now that the sweep is completed, get the last write time
|
|
// and store it as the LastSweepTime at the appropriate location
|
|
|
|
lRet = RegQueryInfoKeyW(
|
|
hkey,
|
|
awcClass, // "" on return
|
|
&cwcClassName, // 0 on return
|
|
NULL,
|
|
&cSubKeys, // 0 on return
|
|
&cjMaxSubKey, // 0 on return
|
|
&cwcMaxClass, // 0 on return
|
|
&cValues, // == cFonts, if all of them are present
|
|
&cwcMaxValueName, // longest value name
|
|
&cjMaxValueData, // longest value data
|
|
&cjSecurityDescriptor, // security descriptor,
|
|
&ftLastWriteTime
|
|
);
|
|
UserAssert(lRet == ERROR_SUCCESS);
|
|
|
|
// now remember the result
|
|
|
|
lRet = RegSetValueExW(
|
|
hkeyLastSweep, // here is the key
|
|
LAST_SWEEP_TIME,
|
|
0,
|
|
REG_BINARY,
|
|
(CONST BYTE*)&ftLastWriteTime,
|
|
sizeof(ftLastWriteTime));
|
|
UserAssert(lRet == ERROR_SUCCESS);
|
|
}
|
|
|
|
// free the memory that will be no longer needed
|
|
|
|
LocalFree(pwcValueName);
|
|
}
|
|
}
|
|
}
|
|
RegCloseKey(hkey);
|
|
}
|
|
|
|
if (!bForceEnum)
|
|
{
|
|
RegCloseKey(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()
|
|
{
|
|
LONG lRet;
|
|
WCHAR awcClass[MAX_PATH] = L"";
|
|
DWORD cwcClassName = MAX_PATH;
|
|
DWORD cSubKeys;
|
|
DWORD cjMaxSubKey;
|
|
DWORD cwcMaxClass;
|
|
DWORD cValues = 0;
|
|
DWORD cwcMaxValueName;
|
|
DWORD cjMaxValueData;
|
|
DWORD cjSecurityDescriptor;
|
|
|
|
HKEY hkey = NULL;
|
|
FILETIME ftLastWriteTime;
|
|
|
|
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.
|
|
|
|
lRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, // Root key
|
|
pwszFontDrivers, // Subkey to open
|
|
0L, // Reserved
|
|
KEY_READ, // SAM
|
|
&hkey); // return handle
|
|
|
|
if (lRet == ERROR_SUCCESS)
|
|
{
|
|
// get the number of entries in the [Fonts] section
|
|
|
|
lRet = RegQueryInfoKeyW(
|
|
hkey,
|
|
awcClass, // "" on return
|
|
&cwcClassName, // 0 on return
|
|
NULL,
|
|
&cSubKeys, // 0 on return
|
|
&cjMaxSubKey, // 0 on return
|
|
&cwcMaxClass, // 0 on return
|
|
&cValues, // == cExternalDrivers
|
|
&cwcMaxValueName, // longest value name
|
|
&cjMaxValueData, // longest value data
|
|
&cjSecurityDescriptor, // security descriptor,
|
|
&ftLastWriteTime
|
|
);
|
|
|
|
if ((lRet == ERROR_SUCCESS) && cValues)
|
|
{
|
|
UserAssert(!(cwcClassName | cSubKeys | cjMaxSubKey | cwcMaxClass | awcClass[0]));
|
|
|
|
// externally loadable drivers are present, force sweep
|
|
|
|
bRet = TRUE;
|
|
}
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
return bRet;
|
|
}
|
|
|
|
/******************************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()
|
|
{
|
|
// check if shared windows directory installation:
|
|
|
|
gbWin31Upgrade = bCheckIfDualBootingWithWin31();
|
|
|
|
// sweep fonts in the [Fonts] key
|
|
|
|
vSweepFonts(pwszFontsKey, pwszSweepKey, vProcessFontEntry, FALSE);
|
|
|
|
// now sweep type 1 fonts, if any
|
|
|
|
vSweepFonts(pwszType1Key, pwszSweepType1Key, vProcessType1FontEntry, FALSE);
|
|
|
|
// one of the two routines above may have initialized %windir%\system
|
|
// and %windir%\fonts directories. Free the memory associated with this
|
|
|
|
if (gpwcSystemDir)
|
|
{
|
|
LocalFree(gpwcSystemDir);
|
|
gpwcSystemDir = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* VOID vLoadLocal/RemoteT1Fonts()
|
|
*
|
|
* History:
|
|
* 30-Apr-1996 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID vLoadT1Fonts(PFNENTRY pfnProcessFontEntry)
|
|
{
|
|
|
|
if (bLoadableFontDrivers())
|
|
{
|
|
#if DBG
|
|
DbgPrint("vLoadT1Fonts(0x%lx) was called\n", pfnProcessFontEntry);
|
|
#endif
|
|
// now enum and add remote type1 fonts if any
|
|
|
|
vSweepFonts(pwszType1Key, pwszSweepType1Key, pfnProcessFontEntry, TRUE);
|
|
|
|
// if the routines above initialized %windir%\system
|
|
// and %windir%\fonts directories. Free the memory associated with this
|
|
|
|
if (gpwcSystemDir)
|
|
{
|
|
LocalFree(gpwcSystemDir);
|
|
gpwcSystemDir = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID vLoadLocalT1Fonts()
|
|
{
|
|
vLoadT1Fonts(vAddLocalType1Font);
|
|
}
|
|
|
|
VOID vLoadRemoteT1Fonts()
|
|
{
|
|
vLoadT1Fonts(vAddRemoteType1Font);
|
|
}
|