Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1030 lines
30 KiB

#include "precomp.hpp"
#include <shlobj.h>
#include <strsafe.h>
#define FONTFILECACHEPATH_W TEXT("\\GDIPFONTCACHEV1.DAT")
#define FONTFILECACHEPATH_A "\\GDIPFONTCACHEV1.DAT"
#define FONTFILECACHEREGLOC_W TEXT("Software\\Microsoft\\GDIPlus")
#define FONTFILECACHEREGKEY_W TEXT("FontCachePath")
#define FONTLOADCACHE_NAMEOBJ "GdiplusFontCacheFileV1"
#define FONT_CACHE_EXTRA_SIZE (8 * 1024)
// Just for tempary use
#define FONTFILECACHE_VER 0x185
//--------------------------------------------------------------------------
// Unicode wrappers for win9x - defined in imgutils.hpp (include file conflict)
//--------------------------------------------------------------------------
LONG
_RegCreateKey(
HKEY rootKey,
const WCHAR* keyname,
REGSAM samDesired,
HKEY* hkeyResult
);
LONG
_RegSetString(
HKEY hkey,
const WCHAR* name,
const WCHAR* value
);
// todo: this should replace _RegGetString and go away to better place (mikhaill 2/14/2002)
LONG
_RegGetStringSafe(
HKEY hkey,
const WCHAR* name,
WCHAR* buf,
DWORD size
)
{
LONG status;
DWORD regtype;
DWORD regsize;
if (OSInfo::IsNT)
{ // Windows NT - Unicode
regsize = size;
status = RegQueryValueExW(
hkey,
name,
NULL,
&regtype,
(BYTE*) buf,
&regsize);
if (status != ERROR_SUCCESS) return status;
if (regtype != REG_SZ) return ERROR_INVALID_DATA;
DWORD wregsize = regsize/sizeof(WCHAR);
if (wregsize == 0 || buf[wregsize-1] != 0) return ERROR_INVALID_DATA;
return ERROR_SUCCESS;
}
else
{ // Windows 9x - non-Unicode
CHAR ansibuf[MAX_PATH];
AnsiStrFromUnicode nameStr(name);
if (!nameStr.IsValid())
return ERROR_INVALID_DATA;
regsize = MAX_PATH;
status = RegQueryValueExA(
hkey,
nameStr,
NULL,
&regtype,
(BYTE*) ansibuf,
&regsize);
if (status != ERROR_SUCCESS) return status;
if (regtype != REG_SZ) return ERROR_INVALID_DATA;
if (regsize == 0 || ansibuf[regsize-1] != 0
|| regsize*sizeof(WCHAR) > size) return ERROR_INVALID_DATA;
BOOL ok = AnsiToUnicodeStr(ansibuf, buf, regsize);
return ok ? ERROR_SUCCESS : ERROR_INVALID_DATA;
}
}
#define SIZED(x) x, sizeof(x)
#define STRCPY_W(dst, src, fail) if ( FAILED( StringCbCopyW ( SIZED(dst), src ) ) ) goto fail
#define STRCAT_W(dst, src, fail) if ( FAILED( StringCbCatW ( SIZED(dst), src ) ) ) goto fail
#define STRCPY_A(dst, src, fail) if ( FAILED( StringCbCopyA ( SIZED(dst), src ) ) ) goto fail
#define STRCAT_A(dst, src, fail) if ( FAILED( StringCbCatA ( SIZED(dst), src ) ) ) goto fail
#define STRCHK_W( src, fail) if ( FAILED( StringCbLengthW( SIZED(src), 0 ) ) ) goto fail
// There are 2 levels synchronization mechanism need to take care
// First level: The lock for GDIPFONTCACHEV1.DAT
// GDIPFONTCACHEV1.DAT is a gloabl file and will be share by different process
// Second level: The lock fof gflFontCacheState and gFontFileCache
// They should be shared by different thread in the same process.
// We define a CriticalSec in gFontFileCache.
// mikhaill 02/15/02: at this time there is no separate critical section for cache file;
// instead the common Globals::TextCriticalSection is used - see comments by claudebe in globals.hpp.
FLONG gflFontCacheState;
FONTFILECACHE gFontFileCache;
HANDLE ghsemFontFileCache = NULL;
ULONG CalcFontFileCacheCheckSum(PVOID pvFile, ULONG cjFileSize);
VOID vReleaseFontCacheFile(VOID);
typedef HRESULT (* PSHGETFOLDERPATHA) (HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPSTR pszPath);
typedef HRESULT (* PSHGETFOLDERPATHW) (HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPWSTR pszPath);
/*****************************************************************************
* VOID vReleaseFontCacheFile(VOID)
*
* Unmap the view of the file
*
* History
* 11-09-99 Yung-Jen Tony Tsai [YungT]
* Wrote it.
*****************************************************************************/
VOID vReleaseFontCacheFile(VOID)
{
if (gFontFileCache.pFile)
{
UnmapViewOfFile(gFontFileCache.pFile);
gFontFileCache.pFile = NULL;
}
if (gFontFileCache.hFileMapping)
{
CloseHandle(gFontFileCache.hFileMapping);
gFontFileCache.hFileMapping = 0;
}
if (gFontFileCache.hFile)
{
CloseHandle(gFontFileCache.hFile);
gFontFileCache.hFile = 0;
}
}
/*****************************************************************************
* BOOL bOpenFontFileCache()
*
* Initialize font file cache, open the cacheplus.dat file and create hash table
*
* History
* 11-09-99 Yung-Jen Tony Tsai [YungT]
* Wrote it.
*****************************************************************************/
BOOL bOpenFontCacheFile(BOOL bOpenOnly, ULONG cjFileSize, BOOL bReAlloc)
{
HANDLE hFile = INVALID_HANDLE_VALUE;
PBYTE pFile = NULL;
BOOL bOK = FALSE;
DWORD dwCreation = 0;
#if DBG
DWORD dwError = 0;
#endif
WCHAR wszFilePath[MAX_PATH];
WCHAR wszPathOnly[MAX_PATH];
CHAR szFilePath[MAX_PATH];
CHAR szPathOnly[MAX_PATH];
BOOL bRegValid = FALSE;
// initialize strings...
wszFilePath[0] = 0;
wszPathOnly[0] = 0;
szFilePath[0] = 0;
szPathOnly[0] = 0;
if (bOpenOnly)
{
dwCreation = OPEN_EXISTING;
}
else
{
dwCreation = CREATE_ALWAYS;
}
// First check the registry to see if we can bypass loading SHFolder
HKEY hkey = (HKEY)NULL;
const WCHAR wchLocation[] = FONTFILECACHEREGLOC_W;
const WCHAR wchValue[] = FONTFILECACHEREGKEY_W;
DWORD valueLength = sizeof(wszFilePath);
// If this fails, we cannot access the registry key...
if (_RegCreateKey(HKEY_CURRENT_USER, wchLocation, KEY_ALL_ACCESS, &hkey) != ERROR_SUCCESS)
hkey = NULL;
if (hkey && _RegGetStringSafe(hkey, wchValue, wszFilePath, valueLength) == ERROR_SUCCESS)
{
// The key exists, so we should read the location of the font file
// from there instead of loading the SHFolder.DLL...
STRCPY_W(wszPathOnly, wszFilePath, fail_1);
// Append the name of cache file
STRCAT_W(wszFilePath, FONTFILECACHEPATH_W, fail_1);
if (Globals::IsNt)
{
hFile = CreateFileW(
wszFilePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
dwCreation,
FILE_ATTRIBUTE_NORMAL,
NULL);
}
else
{
AnsiStrFromUnicode ansiStr(wszFilePath);
if (ansiStr.IsValid())
{
hFile = CreateFileA(
ansiStr,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
dwCreation,
FILE_ATTRIBUTE_NORMAL,
NULL);
}
}
if (hFile != INVALID_HANDLE_VALUE)
bRegValid = TRUE;
fail_1:;
}
if (hFile == INVALID_HANDLE_VALUE)
{
// Use SHFolder.DLL to find the proper location for the file if the
// registry key is not present or is incorrect.
if (Globals::IsNt)
{
// Two steps to get the cache file
// If SHFolder.DLL is existed then we will put the cache file in CSIDL_LOCAL_APPDATA
// Or put it on %SystemRoot%\system32 for WINNT
PSHGETFOLDERPATHW pfnSHGetFolderPathW = NULL;
// Load SHFolder.DLL
if (!gFontFileCache.hShFolder)
gFontFileCache.hShFolder = LoadLibraryW(L"ShFolder.DLL");
// If SHFolder.DLL is existed then we will put the cache file in CSIDL_LOCAL_APPDATA
if (gFontFileCache.hShFolder)
{
// Get the function SHGetFolderPath
pfnSHGetFolderPathW = (PSHGETFOLDERPATHW) GetProcAddress(gFontFileCache.hShFolder, "SHGetFolderPathW");
if (pfnSHGetFolderPathW)
{
// On NT and higher we should use the CSIDL_LOCAL_APPDATA so that this data
// does not roam...
if ((*pfnSHGetFolderPathW) (NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE,
NULL, 0, wszFilePath) == E_INVALIDARG)
{
// CSIDL_LOCAL_APPDATA not understood, use CSIDL_APPDATA (IE 5.0 not present)
(*pfnSHGetFolderPathW) (NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE,
NULL, 0, wszFilePath);
}
// Check whether ShFolder.DLL generated good string
STRCHK_W(wszFilePath, fail_2);
// Keep a copy of the path for registry update...
STRCPY_W(wszPathOnly, wszFilePath, fail_2);
// Append the name of cache file
STRCAT_W(wszFilePath, FONTFILECACHEPATH_W, fail_2);
hFile = CreateFileW(wszFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, dwCreation, FILE_ATTRIBUTE_NORMAL, NULL);
fail_2:;
}
}
// Try to put it on %SystemRoot%\system32 for WINNT
if (hFile == INVALID_HANDLE_VALUE)
{
// Get path for system Dircectory
UINT size = GetSystemDirectoryW(wszFilePath, MAX_PATH);
if (size >= MAX_PATH) goto fail_3;
// Keep a copy of the path for registry update...
STRCPY_W(wszPathOnly, wszFilePath, fail_3);
// Append the name of the cache file
STRCAT_W(wszFilePath, FONTFILECACHEPATH_W, fail_3);
hFile = CreateFileW(wszFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, dwCreation, FILE_ATTRIBUTE_NORMAL, NULL);
fail_3:;
}
}
else
{
// Windows 9x - non-Unicode
// Two steps to get the cache file
// If SHFolder.DLL is existed then we will put the cache file in CSIDL_APPDATA
// Or put it on %SystemRoot%\system for Win9x
if (!gFontFileCache.hShFolder)
gFontFileCache.hShFolder = LoadLibraryA("ShFolder.DLL");
if (gFontFileCache.hShFolder)
{
PSHGETFOLDERPATHA pfnSHGetFolderPathA;
pfnSHGetFolderPathA = (PSHGETFOLDERPATHA) GetProcAddress(gFontFileCache.hShFolder, "SHGetFolderPathA");
if (pfnSHGetFolderPathA)
{
(*pfnSHGetFolderPathA) (NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE,
NULL, 0, szFilePath);
// Keep a copy of the path for registry update...
STRCPY_A(szPathOnly, szFilePath, fail_4);
STRCAT_A(szFilePath, FONTFILECACHEPATH_A, fail_4);
hFile = CreateFileA(szFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, dwCreation, FILE_ATTRIBUTE_NORMAL, NULL);
fail_4:;
}
}
if (hFile == INVALID_HANDLE_VALUE)
{
UINT size = GetSystemDirectoryA(szFilePath, MAX_PATH);
if (size >= MAX_PATH) goto fail_5;
// Keep a copy of the path for registry update...
STRCPY_A(szPathOnly, szFilePath, fail_5);
STRCAT_A(szFilePath, FONTFILECACHEPATH_A, fail_5);
hFile = CreateFileA(szFilePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, dwCreation, FILE_ATTRIBUTE_NORMAL, NULL);
fail_5:;
}
if (hFile != INVALID_HANDLE_VALUE)
{
// szFilePath contains the ANSI full path, convert to unicode...
AnsiToUnicodeStr(szPathOnly, wszPathOnly, sizeof(wszPathOnly)/sizeof(wszPathOnly[0]));
}
}
}
if (hkey)
{
if (hFile != INVALID_HANDLE_VALUE && !bRegValid)
{
// wszPathOnly contains the full path to the font cache file
// so write it out to the registry key...
_RegSetString(hkey, wchValue, wszPathOnly);
}
RegCloseKey(hkey);
}
if (hFile != INVALID_HANDLE_VALUE)
{
if ((dwCreation == OPEN_EXISTING) && !bReAlloc)
{
cjFileSize = GetFileSize(hFile, NULL);
}
if (cjFileSize != 0xffffffff)
{
HANDLE hFileMapping;
if (Globals::IsNt)
{
hFileMapping = CreateFileMappingW(hFile, 0, PAGE_READWRITE, 0, cjFileSize, NULL);
}
else
{
hFileMapping = CreateFileMappingA(hFile, 0, PAGE_READWRITE, 0, cjFileSize, NULL);
}
if (hFileMapping)
{
pFile = (PBYTE)MapViewOfFile(hFileMapping, FILE_MAP_ALL_ACCESS, 0, 0, cjFileSize);
// It should not be NULL if it is then we must know something wrong
if (pFile)
{
gFontFileCache.cjFileSize = cjFileSize;
gFontFileCache.hFile = hFile;
gFontFileCache.hFileMapping = hFileMapping;
gFontFileCache.pFile = (FONTFILECACHEHEADER *) pFile;
bOK = TRUE;
}
else
{
CloseHandle(hFile);
#if DBG
dwError = GetLastError();
TERSE(("Error to map a view of a file %x", dwError));
#endif
}
}
else
{
CloseHandle(hFile);
#if DBG
dwError = GetLastError();
TERSE(("Error to map a file %x", dwError));
#endif
}
}
}
#if DBG
else
{
if (!bOpenOnly)
{
dwError = GetLastError();
TERSE(("Error to create a file %x", dwError));
}
}
#endif
if (!bOK)
{
vReleaseFontCacheFile();
}
return bOK;
}
/*****************************************************************************
* BOOL bReAllocCacheFile(ULONG ulSize)
*
* ReAlloc font cache buffer
*
* History
* 11/16/99 YungT create it
* Wrote it.
*****************************************************************************/
BOOL bReAllocCacheFile(ULONG ulSize)
{
BOOL bOK = FALSE;
ULONG ulFileSizeOrg;
ULONG ulSizeExtra;
ULONG ulFileSize;
ulFileSizeOrg = gFontFileCache.pFile->ulFileSize;
ASSERT(ulSize > gFontFileCache.pFile->ulDataSize);
// Calculate the extra cache we need
ulSizeExtra = QWORD_ALIGN(ulSize - gFontFileCache.pFile->ulDataSize);
ulFileSize = ulFileSizeOrg + ulSizeExtra;
if (gFontFileCache.pFile)
{
vReleaseFontCacheFile();
}
if (bOpenFontCacheFile(TRUE, ulFileSize, TRUE))
{
gFontFileCache.pFile->ulFileSize = ulFileSize;
gFontFileCache.pFile->ulDataSize = ulSize;
gFontFileCache.pCacheBuf = (PBYTE) gFontFileCache.pFile + SZ_FONTCACHE_HEADER();
bOK = TRUE;
}
return bOK;
}
/*****************************************************************************
* BOOL FontFileCacheReadRegistry()
*
* Decide we need to open registry or not when load from cache
*
* History
* 07-28-2k Yung-Jen Tony Tsai [YungT]
* Wrote it.
*****************************************************************************/
BOOL FontFileCacheReadRegistry()
{
return gFontFileCache.bReadFromRegistry;
}
/*****************************************************************************
* VOID FontFileCacheFault()
*
* Fault reprot for Engine font cache.
*
* History
* 11-15-99 Yung-Jen Tony Tsai [YungT]
* Wrote it.
*****************************************************************************/
VOID FontFileCacheFault()
{
gflFontCacheState = FONT_CACHE_ERROR_MODE;
}
/*****************************************************************************
* PVOID FontFileCacheAlloc(ULONG ulFastCheckSum, ULONG ulSize)
*
* Alloc the cached buffer for font driver
*
* History
* 11-15-99 Yung-Jen Tony Tsai [YungT]
* Wrote it.
*****************************************************************************/
PVOID FontFileCacheAlloc(ULONG ulSize)
{
PVOID pvIfi = NULL;
{
ASSERT(gflFontCacheState & FONT_CACHE_CREATE_MODE);
if (ghsemFontFileCache == NULL)
return pvIfi;
if (gflFontCacheState & FONT_CACHE_CREATE_MODE)
{
if ( (QWORD_ALIGN(ulSize) < gFontFileCache.pFile->ulDataSize)
|| bReAllocCacheFile(ulSize))
{
pvIfi = (PVOID) gFontFileCache.pCacheBuf;
// Gaurantee the cache pointer is at 8 byte boundary
gFontFileCache.pFile->ulDataSize = ulSize;
}
else
{
gflFontCacheState = FONT_CACHE_ERROR_MODE;
}
}
}
return pvIfi;
}
/*****************************************************************************
* PVOID FontFileCacheLookUp(ULONG FastCheckSum, ULONG *pcjData)
*
* Lookup font cache
*
* History
* 11-15-99 Yung-Jen Tony Tsai [YungT]
* Wrote it.
*****************************************************************************/
PVOID FontFileCacheLookUp(ULONG *pcjData)
{
PBYTE pCache = NULL;
*pcjData = 0;
ASSERT(ghsemFontFileCache);
if (ghsemFontFileCache == NULL)
return pCache;
if (gflFontCacheState & FONT_CACHE_LOOKUP_MODE)
{
ASSERT(gFontFileCache.pFile);
ASSERT(gFontFileCache.pCacheBuf == ((PBYTE) gFontFileCache.pFile +
SZ_FONTCACHE_HEADER()));
*pcjData = gFontFileCache.pFile->ulDataSize;
pCache = gFontFileCache.pCacheBuf;
gFontFileCache.pCacheBuf += QWORD_ALIGN(*pcjData);
}
return (PVOID) pCache;
}
/*****************************************************************************
* VOID GetFontFileCacheState()
*
* Clean font file cache after load or update the cache file.
*
* History
* 11-12-99 Yung-Jen Tony Tsai [YungT]
* Wrote it.
*****************************************************************************/
FLONG GetFontFileCacheState()
{
return gflFontCacheState;
}
/*****************************************************************************
* VOID vCloseFontFileCache()
*
* Clean font file cache after load or update the cache file.
*
* History
* 11-12-99 Yung-Jen Tony Tsai [YungT]
* Wrote it.
*****************************************************************************/
VOID vCloseFontFileCache()
{
// do paranoid check
if (!ghsemFontFileCache)
return;
if (gflFontCacheState & FONT_CACHE_MASK)
{
if (gflFontCacheState & FONT_CACHE_CREATE_MODE)
{
// Close the file, we are done recreating it
if (gFontFileCache.pFile)
{
gFontFileCache.pFile->CheckSum = CalcFontFileCacheCheckSum((PVOID) ((PBYTE) gFontFileCache.pFile + 4), (gFontFileCache.cjFileSize - 4));
}
}
}
if (gFontFileCache.hShFolder)
{
FreeLibrary(gFontFileCache.hShFolder);
gFontFileCache.hShFolder = NULL;
}
vReleaseFontCacheFile();
ReleaseSemaphore(ghsemFontFileCache, 1, NULL);
CloseHandle(ghsemFontFileCache);
ghsemFontFileCache = NULL;
gflFontCacheState = 0;
}
/*****************************************************************************
* ULONG CalcFontFileCacheCheckSum(PVOID pvFile, ULONG cjFileSize)
*
* Helper function for query fonts information from font registry
*
* History
* 11-11-99 Yung-Jen Tony Tsai [YungT]
* Wrote it.
*****************************************************************************/
ULONG CalcFontFileCacheCheckSum(PVOID pvFile, ULONG cjFileSize)
{
ULONG sum;
PULONG pulCur,pulEnd;
pulCur = (PULONG) pvFile;
__try
{
for (sum = 0, pulEnd = pulCur + cjFileSize / sizeof(ULONG); pulCur < pulEnd; pulCur += 1)
{
sum += 256 * sum + *pulCur;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
sum = 0; // oh well, not very unique.
}
return ( sum < 2 ) ? 2 : sum; // 0 is reserved for device fonts
// 1 is reserved for TYPE1 fonts
}
/*****************************************************************************
* ULONG QueryFontReg(ULARGE_INTEGER *pFontRegLastWriteTime, ULONG *pulFonts)
*
* Helper function for query fonts information from font registry
*
* History
* 11-15-99 Yung-Jen Tony Tsai [YungT]
* Wrote it.
*****************************************************************************/
BOOL QueryFontReg(ULARGE_INTEGER *pFontRegLastWriteTime)
{
BOOL bOK = FALSE;
ULONG ulFonts;
HKEY hkey;
LONG error = (Globals::IsNt) ? RegOpenKeyExW(HKEY_LOCAL_MACHINE, Globals::FontsKeyW, 0, KEY_QUERY_VALUE, &hkey)
: RegOpenKeyExA(HKEY_LOCAL_MACHINE, Globals::FontsKeyA, 0, KEY_QUERY_VALUE, &hkey);
if (error == ERROR_SUCCESS)
{
// There is no difference between A or W APIs at this case.
error = RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, &ulFonts, NULL, NULL, NULL,
(FILETIME *)pFontRegLastWriteTime);
if (error == ERROR_SUCCESS)
{
bOK = TRUE;
}
RegCloseKey(hkey);
}
return bOK;
}
/*****************************************************************************
* BOOL bCreateFontFileCache()
*
* Initialize font file cache, open the cacheplus.dat file and create hash table
*
* History
* 11-09-99 Yung-Jen Tony Tsai [YungT]
* Wrote it.
*****************************************************************************/
BOOL bCreateFontCacheFile(ULARGE_INTEGER FntRegLWT)
{
ULONG ulSize;
BOOL bOk = FALSE;
ulSize = SZ_FONTCACHE_HEADER() + FONT_CACHE_EXTRA_SIZE;
if (gFontFileCache.pFile)
{
vReleaseFontCacheFile();
}
if(bOpenFontCacheFile(FALSE, ulSize, FALSE))
{
gFontFileCache.pFile->ulLanguageID = (ULONG) Globals::LanguageID;
gFontFileCache.pFile->CheckSum = 0;
gFontFileCache.pFile->ulMajorVersionNumber = FONTFILECACHE_VER;
gFontFileCache.pFile->FntRegLWT.QuadPart = FntRegLWT.QuadPart;
gFontFileCache.pFile->ulFileSize = ulSize;
gFontFileCache.pFile->ulDataSize = FONT_CACHE_EXTRA_SIZE;
bOk = TRUE;
}
return bOk;
}
#if DBG
/*****************************************************************************
* BOOL bFontFileCacheDisabled()
*
* Tempary routine for performance evaluation
*
* History
* 11-29-99 Yung-Jen Tony Tsai [YungT]
* Wrote it.
*****************************************************************************/
BOOL bFontFileCacheDisabled()
{
return FALSE;
}
#endif
BOOL bScanRegistry()
{
ASSERT(!Globals::IsNt);
BOOL bOK = TRUE;
ULONG index = 0;
ULONG registrySize = 0;
ULONG numExpected;
// Open the key
HKEY hkey;
PBYTE pCached = (PBYTE) gFontFileCache.pFile + SZ_FONTCACHE_HEADER();
if (*((ULONG *) pCached) != 0xBFBFBFBF)
return FALSE;
LONG error = RegOpenKeyExA(HKEY_LOCAL_MACHINE, Globals::FontsKeyA, 0, KEY_QUERY_VALUE, &hkey);
if (error == ERROR_SUCCESS)
{
DWORD allDataSize = 0;
error = RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, NULL, NULL, &numExpected, NULL, NULL, NULL, NULL);
if (error != ERROR_SUCCESS)
{
RegCloseKey(hkey);
return FALSE;
}
PBYTE pRegistryData;
registrySize = *((ULONG *) (pCached + 4)) ;
pRegistryData = pCached + 8;
while (index < numExpected)
{
DWORD regType = 0;
DWORD labelSize = MAX_PATH;
DWORD dataSize = MAX_PATH;
CHAR label[MAX_PATH];
BYTE data[MAX_PATH];
error = RegEnumValueA(hkey, index, label, &labelSize, NULL, &regType, data, &dataSize);
if (error == ERROR_NO_MORE_ITEMS)
{
bOK = FALSE;
break;
}
if (allDataSize >= registrySize)
{
bOK = FALSE;
break;
}
if (memcmp(pRegistryData, data, dataSize))
{
bOK = FALSE;
break;
}
pRegistryData += dataSize;
allDataSize += dataSize;
index ++;
}
RegCloseKey(hkey);
if (bOK && (allDataSize == registrySize))
return TRUE;
}
return FALSE;
}
/*****************************************************************************
* VOID InitFontFileCache()
*
* Initialize font file cache, open the cacheplus.dat file and create hash table
*
* History
* 11-09-99 Yung-Jen Tony Tsai [YungT]
* Wrote it.
*****************************************************************************/
VOID InitFontFileCache()
{
ULARGE_INTEGER FntRegLWT = { 0, 0};
if (gflFontCacheState)
{
return;
}
#if DBG
// Only for performance evaluation.
if (bFontFileCacheDisabled())
{
goto CleanUp;
}
#endif
// If the named semaphore object existed before the function call,
// the function returns a handle to the existing object and
// GetLastError returns ERROR_ALREADY_EXISTS.
ghsemFontFileCache = CreateSemaphoreA( NULL, 1, 1, FONTLOADCACHE_NAMEOBJ);
// Something wrong, we can not go with font file cache
if (ghsemFontFileCache == NULL)
{
goto CleanUp;
}
else
{
// Wait 5 seconds until the semaphore released.
// No further attempts to create font file cache on timeout.
// This does not mean deial of service - just will work
// slower using GpFontTable::LoadAllFontsFromRegistry(FALSE).
DWORD dwr = WaitForSingleObject(ghsemFontFileCache, 5000);
if (dwr == WAIT_TIMEOUT) goto CleanUp;
}
gFontFileCache.pFile = NULL;
// now open the TT Fonts key :
if (!QueryFontReg(&FntRegLWT))
{
goto CleanUp;
}
if (bOpenFontCacheFile(TRUE, 0, FALSE))
{
// File did not change from last time boot.
if (gFontFileCache.pFile->CheckSum && gFontFileCache.cjFileSize == gFontFileCache.pFile->ulFileSize &&
gFontFileCache.pFile->CheckSum == CalcFontFileCacheCheckSum((PVOID) ((PBYTE) gFontFileCache.pFile + 4), (gFontFileCache.cjFileSize - 4)) &&
gFontFileCache.pFile->ulMajorVersionNumber == FONTFILECACHE_VER &&
gFontFileCache.pFile->ulLanguageID == (ULONG) Globals::LanguageID && // If locale changed, we need to re-create the cache
gFontFileCache.pFile->FntRegLWT.QuadPart == FntRegLWT.QuadPart && // If registry has been updated we need to re-create the cache file
(FntRegLWT.QuadPart != 0 || bScanRegistry())
)
{
gflFontCacheState = FONT_CACHE_LOOKUP_MODE;
}
else
{
if(bCreateFontCacheFile(FntRegLWT))
{
// If something will not match, then it means we need to create FNTCACHE again
gflFontCacheState = FONT_CACHE_CREATE_MODE;
}
}
}
else
{
// If there is no GDIPFONTCACHE.DAT file
// Then we need to create it.
if(bCreateFontCacheFile(FntRegLWT))
{
gflFontCacheState = FONT_CACHE_CREATE_MODE;
}
}
CleanUp:
// Semaphore initialized
if (gflFontCacheState & FONT_CACHE_MASK)
{
// Initialize the start pointer of current Cache table
gFontFileCache.pCacheBuf = (PBYTE) gFontFileCache.pFile + SZ_FONTCACHE_HEADER();
if (FntRegLWT.QuadPart == (ULONGLONG) 0)
gFontFileCache.bReadFromRegistry = TRUE;
else
gFontFileCache.bReadFromRegistry = FALSE;
}
else
{
gflFontCacheState = 0;
// Clean up the memory
if (gFontFileCache.pFile)
{
vReleaseFontCacheFile();
}
if (ghsemFontFileCache)
{
ReleaseSemaphore(ghsemFontFileCache, 1, NULL);
CloseHandle( ghsemFontFileCache);
ghsemFontFileCache = NULL;
}
}
}