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.
1640 lines
44 KiB
1640 lines
44 KiB
/****************************Module*Header******************************\
|
|
* Module Name: FIUTILS.C
|
|
*
|
|
* Module Descripton:
|
|
* This file has utility functions that handle NT5 Unidrv font files.
|
|
*
|
|
* Warnings:
|
|
*
|
|
* Issues:
|
|
*
|
|
* Created: 11 November 1997
|
|
* Author: Srinivasan Chandrasekar [srinivac]
|
|
*
|
|
* Copyright (c) 1996, 1997 Microsoft Corporation
|
|
\***********************************************************************/
|
|
|
|
#include "precomp.h"
|
|
|
|
//
|
|
// External functions
|
|
//
|
|
|
|
BOOL WINAPI GetPrinterDriverDirectoryW(LPWSTR, LPWSTR, DWORD, LPBYTE, DWORD, LPDWORD);
|
|
BOOL WINAPI GetPrinterW(HANDLE, DWORD, LPBYTE, DWORD, LPDWORD);;
|
|
|
|
//
|
|
// Internal data structures
|
|
//
|
|
|
|
//
|
|
// Structure used to remember which glyph set data's have been written to file
|
|
//
|
|
|
|
typedef struct _FI_GLYPHDATA {
|
|
SHORT sGlyphID; // unique glyph ID
|
|
WORD wPadding; // set to zero
|
|
DWORD gdPos; // position of glyph data inside file
|
|
} FI_GLYPHDATA, *PFI_GLYPHDATA;
|
|
|
|
//
|
|
// The handle we pass out is a pointer to this structure
|
|
//
|
|
|
|
typedef struct tagFI_FILE
|
|
{
|
|
DWORD dwSignature; // Signature of data structure
|
|
HANDLE hPrinter; // Handle of printer for using spooler funcs
|
|
HANDLE hHeap; // Handle to heap to use
|
|
|
|
WCHAR wchFileName[MAX_PATH]; // Name of font file
|
|
|
|
HANDLE hFile; // Handle of open file
|
|
|
|
PUFF_FILEHEADER pFileHdr; // Pointer to file header
|
|
PUFF_FONTDIRECTORY pFontDir; // Pointer to font directory
|
|
DWORD dwCurPos; // Current position of write in file
|
|
|
|
DWORD dwFlags; // Miscellaneous flags
|
|
|
|
//
|
|
// The following are used only if read access is present
|
|
//
|
|
|
|
PBYTE pView; // Pointer to view of file
|
|
|
|
//
|
|
// The following are used only if write access is present
|
|
//
|
|
|
|
PFI_GLYPHDATA pGlyphData; // Pointer to glyphs that have been written
|
|
DWORD nGlyphs; // Number of glyphs written
|
|
|
|
} FI_FILE, *PFI_FILE;
|
|
|
|
|
|
//
|
|
// Internal functions
|
|
//
|
|
|
|
#ifdef KERNEL_MODE
|
|
HANDLE OpenFontFile(HANDLE, HANDLE, HANDLE, PWSTR);
|
|
#else
|
|
HANDLE OpenFontFile(HANDLE, HANDLE, PWSTR);
|
|
#endif
|
|
BOOL WriteData(PFI_FILE, PDATA_HEADER);
|
|
void Qsort(PUFF_FONTDIRECTORY, int, int);
|
|
void Exchange(PUFF_FONTDIRECTORY, DWORD, DWORD);
|
|
BOOL GetFontCartridgeFile(HANDLE, HANDLE);
|
|
|
|
#define FONT_INFO_SIGNATURE 'fnti'
|
|
|
|
#define FI_FLAG_READ 0x00000001
|
|
#define FI_FLAG_WRITE 0x00000002
|
|
|
|
#define IsValidFontInfo(pfi) ((pfi) && (pfi)->dwSignature == FONT_INFO_SIGNATURE)
|
|
|
|
#ifdef KERNEL_MODE
|
|
#define ALLOC(hHeap, dwSize) MemAlloc(dwSize)
|
|
#define FREE(hHeap, pBuf) MemFree(pBuf)
|
|
#else
|
|
#define ALLOC(hHeap, dwSize) HeapAlloc((hHeap), HEAP_ZERO_MEMORY, (dwSize))
|
|
#define FREE(hHeap, pBuf) HeapFree((hHeap), 0, (pBuf))
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
* Functions that handle files that have been opened with read privileges
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FIOpenFontFile
|
|
*
|
|
* Function:
|
|
* This function opens the font file associated with the specified printer
|
|
* for read access.
|
|
*
|
|
* Arguments:
|
|
* hPrinter - Handle identifying printer
|
|
* hHeap - Handle of heap to use for memory allocations
|
|
* bCartridgeFile - Specifies if the font cartridge file is to be opened
|
|
* or the currently installed fonts file
|
|
*
|
|
* Returns:
|
|
* Handle to use in subsequent calls if successful, NULL otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
HANDLE
|
|
FIOpenFontFile(
|
|
HANDLE hPrinter,
|
|
#ifdef KERNEL_MODE
|
|
HANDLE hdev,
|
|
#endif
|
|
HANDLE hHeap
|
|
)
|
|
{
|
|
#ifdef KERNEL_MODE
|
|
return OpenFontFile(hPrinter, hdev, hHeap, REGVAL_FONTFILENAME);
|
|
#else
|
|
return OpenFontFile(hPrinter, hHeap, REGVAL_FONTFILENAME);
|
|
#endif
|
|
}
|
|
|
|
|
|
HANDLE
|
|
FIOpenCartridgeFile(
|
|
HANDLE hPrinter,
|
|
#ifdef KERNEL_MODE
|
|
HANDLE hdev,
|
|
#endif
|
|
HANDLE hHeap
|
|
)
|
|
{
|
|
#ifdef KERNEL_MODE
|
|
return OpenFontFile(hPrinter, hdev, hHeap, REGVAL_CARTRIDGEFILENAME);
|
|
#else
|
|
return OpenFontFile(hPrinter, hHeap, REGVAL_CARTRIDGEFILENAME);
|
|
#endif
|
|
}
|
|
|
|
HANDLE
|
|
OpenFontFile(
|
|
HANDLE hPrinter,
|
|
#ifdef KERNEL_MODE
|
|
HANDLE hdev,
|
|
#endif
|
|
HANDLE hHeap,
|
|
PWSTR pwstrRegVal
|
|
)
|
|
{
|
|
FI_FILE *pFIFile = NULL;
|
|
DWORD dwSize, dwStatus, dwType;
|
|
BOOL bRc = FALSE;
|
|
|
|
//
|
|
// Allocate FI_FILE structure
|
|
//
|
|
|
|
if (!(pFIFile = (FI_FILE *)ALLOC(hHeap, sizeof(FI_FILE))))
|
|
{
|
|
WARNING(("Could not allocate memory for opening Font File\n"));
|
|
return NULL;
|
|
}
|
|
pFIFile->dwSignature = FONT_INFO_SIGNATURE;
|
|
pFIFile->hPrinter = hPrinter;
|
|
pFIFile->hHeap = hHeap;
|
|
pFIFile->pView = NULL;
|
|
pFIFile->dwFlags = 0;
|
|
|
|
//
|
|
// If we are opening the cartridge file, and we are on the client, get it
|
|
// from the server
|
|
//
|
|
|
|
#ifndef KERNEL_MODE
|
|
if (wcscmp(pwstrRegVal, REGVAL_CARTRIDGEFILENAME) == 0)
|
|
{
|
|
if (!BGetFontCartridgeFile(hPrinter, hHeap))
|
|
goto EndOpenRead;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// Get the name of the font file - strip off the directory path as it may have the
|
|
// server path - generate the local path instead
|
|
//
|
|
|
|
{
|
|
WCHAR wchFileName[MAX_PATH];
|
|
PWSTR pName;
|
|
|
|
#ifdef KERNEL_MODE
|
|
|
|
PDRIVER_INFO_3 pdi3;
|
|
|
|
if (!(pdi3 = MyGetPrinterDriver(hPrinter, hdev, 3)))
|
|
goto EndOpenRead;
|
|
|
|
StringCchCopyW(pFIFile->wchFileName, CCHOF(pFIFile->wchFileName), pdi3->pDriverPath);
|
|
|
|
MemFree(pdi3);
|
|
|
|
//
|
|
// We have something like "c:\nt\system32\spool\drivers\w32x86\3\unidrv.dll".
|
|
// We need only till drivers, so we search backwards for the 3rd '\\'.
|
|
//
|
|
|
|
if (pName = wcsrchr(pFIFile->wchFileName, '\\'))
|
|
{
|
|
*pName = '\0';
|
|
|
|
if (pName = wcsrchr(pFIFile->wchFileName, '\\'))
|
|
{
|
|
*pName = '\0';
|
|
|
|
if (pName = wcsrchr(pFIFile->wchFileName, '\\'))
|
|
*pName = '\0';
|
|
}
|
|
}
|
|
|
|
if (!pName)
|
|
goto EndOpenRead;
|
|
|
|
#else
|
|
|
|
dwSize = sizeof(pFIFile->wchFileName);
|
|
if (!GetPrinterDriverDirectoryW(NULL, NULL, 1, (PBYTE)pFIFile->wchFileName, dwSize, &dwSize))
|
|
goto EndOpenRead;
|
|
|
|
//
|
|
// Get rid of the processor architecture part
|
|
//
|
|
|
|
if (pName = wcsrchr(pFIFile->wchFileName, '\\'))
|
|
*pName = '\0';
|
|
|
|
#endif
|
|
|
|
//
|
|
// Add "unifont"
|
|
//
|
|
|
|
StringCchCatW(pFIFile->wchFileName, CCHOF(pFIFile->wchFileName), FONTDIR);
|
|
|
|
//
|
|
// Get font file name from registry
|
|
//
|
|
|
|
dwSize = sizeof(wchFileName);
|
|
dwStatus = GetPrinterData(hPrinter, pwstrRegVal, &dwType, (PBYTE)wchFileName, dwSize, &dwSize);
|
|
|
|
if (dwStatus != ERROR_MORE_DATA && dwStatus != ERROR_SUCCESS)
|
|
goto EndOpenRead; // No font file is available
|
|
|
|
//
|
|
// Strip any directory prefix from the font filename
|
|
//
|
|
|
|
if (pName = wcsrchr(wchFileName, '\\'))
|
|
pName++;
|
|
else
|
|
pName = wchFileName;
|
|
|
|
StringCchCatW(pFIFile->wchFileName, CCHOF(pFIFile->wchFileName), pName);
|
|
}
|
|
|
|
//
|
|
// Memory map the file
|
|
//
|
|
|
|
#if defined(KERNEL_MODE) && !defined(USERMODE_DRIVER)
|
|
{
|
|
PBYTE pTemp = NULL;
|
|
DWORD dwSize;
|
|
HANDLE hFile;
|
|
|
|
hFile = MapFileIntoMemory(pFIFile->wchFileName, &pTemp, &dwSize);
|
|
if (!pTemp)
|
|
{
|
|
goto EndOpenRead;
|
|
}
|
|
pFIFile->pView = ALLOC(hHeap, dwSize);
|
|
if (pFIFile->pView)
|
|
{
|
|
memcpy(pFIFile->pView, pTemp, dwSize);
|
|
}
|
|
UnmapFileFromMemory((HFILEMAP)hFile);
|
|
}
|
|
#else
|
|
pFIFile->hFile = MapFileIntoMemory(pFIFile->wchFileName, &pFIFile->pView, NULL);
|
|
#endif
|
|
|
|
if (!pFIFile->pView)
|
|
{
|
|
WARNING(("Err %ld, could not create view of profile %s\n",
|
|
GetLastError(), pFIFile->wchFileName));
|
|
goto EndOpenRead;
|
|
}
|
|
|
|
//
|
|
// Check validity of font file
|
|
//
|
|
|
|
pFIFile->pFileHdr = (PUFF_FILEHEADER)pFIFile->pView;
|
|
|
|
if (pFIFile->pFileHdr->dwSignature != UFF_FILE_MAGIC ||
|
|
pFIFile->pFileHdr->dwVersion != UFF_VERSION_NUMBER ||
|
|
pFIFile->pFileHdr->dwSize != sizeof(UFF_FILEHEADER))
|
|
{
|
|
WARNING(("Invalid font file %s\n", pFIFile->wchFileName));
|
|
goto EndOpenRead;
|
|
}
|
|
|
|
//
|
|
// Set other fields
|
|
//
|
|
|
|
if (pFIFile->pFileHdr->offFontDir)
|
|
{
|
|
pFIFile->pFontDir = (PUFF_FONTDIRECTORY)(pFIFile->pView + pFIFile->pFileHdr->offFontDir);
|
|
}
|
|
|
|
pFIFile->dwCurPos = 0;
|
|
pFIFile->dwFlags = FI_FLAG_READ;
|
|
pFIFile->pGlyphData = NULL;
|
|
pFIFile->nGlyphs = 0;
|
|
|
|
bRc = TRUE;
|
|
|
|
EndOpenRead:
|
|
|
|
if (!bRc)
|
|
{
|
|
FICloseFontFile((HANDLE)pFIFile);
|
|
pFIFile = NULL;
|
|
}
|
|
|
|
return (HANDLE)pFIFile;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FICloseFontFile
|
|
*
|
|
* Function:
|
|
* This function closes the given font file and frees all memory
|
|
* associated with it
|
|
*
|
|
* Arguments:
|
|
* hFontFile - Handle identifying font file to close
|
|
*
|
|
* Returns:
|
|
* Nothing
|
|
*
|
|
******************************************************************************/
|
|
|
|
VOID
|
|
FICloseFontFile(
|
|
HANDLE hFontFile
|
|
)
|
|
{
|
|
FI_FILE *pFIFile = (FI_FILE*)hFontFile;
|
|
|
|
if (IsValidFontInfo(pFIFile))
|
|
{
|
|
if (pFIFile->dwFlags & FI_FLAG_READ)
|
|
{
|
|
//
|
|
// Memory mapped file was opened, close it
|
|
//
|
|
|
|
if (pFIFile->pView)
|
|
{
|
|
#if defined(KERNEL_MODE) && !defined(USERMODE_DRIVER)
|
|
FREE(pFIFile->hHeap, pFIFile->pView);
|
|
#else
|
|
UnmapFileFromMemory((HFILEMAP)pFIFile->hFile);
|
|
#endif
|
|
}
|
|
}
|
|
#ifndef KERNEL_MODE
|
|
else
|
|
{
|
|
//
|
|
// New file was created, free all allocated memory
|
|
//
|
|
|
|
if (pFIFile->pFileHdr)
|
|
{
|
|
FREE(pFIFile->hHeap, pFIFile->pFileHdr);
|
|
}
|
|
|
|
if (pFIFile->pFontDir)
|
|
{
|
|
FREE(pFIFile->hHeap, pFIFile->pFontDir);
|
|
}
|
|
|
|
if (pFIFile->hFile != INVALID_HANDLE_VALUE)
|
|
{
|
|
CloseHandle(pFIFile->hFile);
|
|
}
|
|
|
|
if (pFIFile->pGlyphData)
|
|
{
|
|
FREE(pFIFile->hHeap, pFIFile->pGlyphData);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
FREE(pFIFile->hHeap, pFIFile);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FIGetNumFonts
|
|
*
|
|
* Function:
|
|
* This function retrieves the number of fonts present in the given
|
|
* font file
|
|
*
|
|
* Arguments:
|
|
* hFontFile - Handle identifying font file
|
|
*
|
|
* Returns:
|
|
* Number of font present if successful, 0 otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
DWORD
|
|
FIGetNumFonts(
|
|
HANDLE hFontFile
|
|
)
|
|
{
|
|
FI_FILE *pFIFile = (FI_FILE*)hFontFile;
|
|
|
|
return IsValidFontInfo(pFIFile) ? pFIFile->pFileHdr->nFonts : 0;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FIGetFontDir
|
|
*
|
|
* Function:
|
|
* This function retrieves a pointer to the font directory of the
|
|
* given font file
|
|
*
|
|
* Arguments:
|
|
* hFontFile - Handle identifying font file
|
|
*
|
|
* Returns:
|
|
* Pointer to font directory if successful, NULL otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
PUFF_FONTDIRECTORY
|
|
FIGetFontDir(
|
|
HANDLE hFontFile
|
|
)
|
|
{
|
|
FI_FILE *pFIFile = (FI_FILE*)hFontFile;
|
|
|
|
return IsValidFontInfo(pFIFile) ? pFIFile->pFontDir : NULL;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FIGetFontName
|
|
*
|
|
* Function:
|
|
* This function retrieves a pointer to the name of the iFontIndex'th font
|
|
* in the given font file
|
|
*
|
|
* Arguments:
|
|
* hFontFile - Handle identifying font file
|
|
* iFontIndex - Index of the font whose name is to be retrieved
|
|
*
|
|
* Returns:
|
|
* Pointer to font name if successful, NULL otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
PWSTR
|
|
FIGetFontName(
|
|
HANDLE hFontFile,
|
|
DWORD iFontIndex
|
|
)
|
|
{
|
|
FI_FILE *pFIFile = (FI_FILE*)hFontFile;
|
|
PWSTR pwstrFontName = NULL;
|
|
|
|
if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_READ))
|
|
{
|
|
if (iFontIndex < pFIFile->pFileHdr->nFonts)
|
|
{
|
|
pwstrFontName = (PWSTR)(pFIFile->pView + pFIFile->pFontDir[iFontIndex].offFontName);
|
|
}
|
|
}
|
|
|
|
return pwstrFontName;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FIGetFontCartridgeName
|
|
*
|
|
* Function:
|
|
* This function retrieves a pointer to the name of the iFontIndex'th font
|
|
* cartridge in the given font file
|
|
*
|
|
* Arguments:
|
|
* hFontFile - Handle identifying font file
|
|
* iFontIndex - Index of the font whose cartridge name is to be retrieved
|
|
*
|
|
* Returns:
|
|
* Pointer to font cartridge name if present, NULL otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
PWSTR
|
|
FIGetFontCartridgeName(
|
|
HANDLE hFontFile,
|
|
DWORD iFontIndex
|
|
)
|
|
{
|
|
FI_FILE *pFIFile = (FI_FILE*)hFontFile;
|
|
PWSTR pwstrCartridgeName = NULL;
|
|
|
|
if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_READ))
|
|
{
|
|
if (iFontIndex < pFIFile->pFileHdr->nFonts)
|
|
{
|
|
pwstrCartridgeName = pFIFile->pFontDir[iFontIndex].offCartridgeName ?
|
|
(PWSTR)(pFIFile->pView + pFIFile->pFontDir[iFontIndex].offCartridgeName) : NULL;
|
|
}
|
|
}
|
|
|
|
return pwstrCartridgeName;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FIGetFontData
|
|
*
|
|
* Function:
|
|
* This function retrieves a pointer to the font data for the
|
|
* iFontIndex'th font in the given font file
|
|
*
|
|
* Arguments:
|
|
* hFontFile - Handle identifying font file
|
|
* iFontIndex - Index of the font whose font data is to be retrieved
|
|
*
|
|
* Returns:
|
|
* Pointer to font data if successful, NULL otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
PDATA_HEADER
|
|
FIGetFontData(
|
|
HANDLE hFontFile,
|
|
DWORD iFontIndex
|
|
)
|
|
{
|
|
FI_FILE *pFIFile = (FI_FILE*)hFontFile;
|
|
PDATA_HEADER pData = NULL;
|
|
|
|
if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_READ))
|
|
{
|
|
|
|
if (iFontIndex < pFIFile->pFileHdr->nFonts)
|
|
{
|
|
pData = (PDATA_HEADER)(pFIFile->pView + pFIFile->pFontDir[iFontIndex].offFontData);
|
|
}
|
|
}
|
|
|
|
return pData;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FIGetGlyphData
|
|
*
|
|
* Function:
|
|
* This function retrieves a pointer to the glyph data for the
|
|
* iFontIndex'th font in the given font file
|
|
*
|
|
* Arguments:
|
|
* hFontFile - Handle identifying font file
|
|
* iFontIndex - Index of the font whose glyph data is to be retrieved
|
|
*
|
|
* Returns:
|
|
* Pointer to glyph data if successful, NULL otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
PDATA_HEADER
|
|
FIGetGlyphData(
|
|
HANDLE hFontFile,
|
|
DWORD iFontIndex
|
|
)
|
|
{
|
|
FI_FILE *pFIFile = (FI_FILE*)hFontFile;
|
|
PDATA_HEADER pData = NULL;
|
|
|
|
if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_READ))
|
|
{
|
|
if (iFontIndex < pFIFile->pFileHdr->nFonts)
|
|
{
|
|
pData = pFIFile->pFontDir[iFontIndex].offGlyphData ?
|
|
(PDATA_HEADER)(pFIFile->pView + pFIFile->pFontDir[iFontIndex].offGlyphData) : NULL;
|
|
}
|
|
}
|
|
|
|
return pData;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FIGetVarData
|
|
*
|
|
* Function:
|
|
* This function retrieves a pointer to the variable data for the
|
|
* iFontIndex'th font in the given font file
|
|
*
|
|
* Arguments:
|
|
* hFontFile - Handle identifying font file
|
|
* iFontIndex - Index of the font whose variable data is to be retrieved
|
|
*
|
|
* Returns:
|
|
* Pointer to variable data if present, NULL otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
PDATA_HEADER
|
|
FIGetVarData(
|
|
HANDLE hFontFile,
|
|
DWORD iFontIndex
|
|
)
|
|
{
|
|
FI_FILE *pFIFile = (FI_FILE*)hFontFile;
|
|
PDATA_HEADER pData = NULL;
|
|
|
|
if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_READ))
|
|
{
|
|
|
|
if (iFontIndex < pFIFile->pFileHdr->nFonts)
|
|
{
|
|
pData = pFIFile->pFontDir[iFontIndex].offVarData ?
|
|
(PDATA_HEADER)(pFIFile->pView + pFIFile->pFontDir[iFontIndex].offVarData) : NULL;
|
|
}
|
|
}
|
|
|
|
return pData;
|
|
}
|
|
|
|
#ifndef KERNEL_MODE
|
|
|
|
/******************************************************************************
|
|
* Functions that handle files that have been opened with write privileges
|
|
******************************************************************************/
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FICreateFontFile
|
|
*
|
|
* Function:
|
|
* This function creates a new font file with only write access.
|
|
*
|
|
* Arguments:
|
|
* hPrinter - Handle identifying printer
|
|
* hHeap - Handle of heap to use for memory allocations
|
|
*
|
|
* Returns:
|
|
* Handle to use in subsequent calls if successful, NULL otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
HANDLE
|
|
FICreateFontFile(
|
|
HANDLE hPrinter,
|
|
HANDLE hHeap,
|
|
DWORD cFonts
|
|
)
|
|
{
|
|
FI_FILE *pFIFile = NULL;
|
|
PWSTR pName, pstrGuid;
|
|
DWORD dwSize;
|
|
UUID guid;
|
|
BOOL bRc = FALSE;
|
|
|
|
//
|
|
// Allocate FI_FILE structure
|
|
//
|
|
|
|
if (!(pFIFile = (FI_FILE *)ALLOC(hHeap, sizeof(FI_FILE))))
|
|
{
|
|
WARNING(("Could not allocate memory for creating Font File\n"));
|
|
return NULL;
|
|
}
|
|
pFIFile->dwSignature = FONT_INFO_SIGNATURE;
|
|
pFIFile->hPrinter = hPrinter;
|
|
pFIFile->hHeap = hHeap;
|
|
|
|
//
|
|
// Generate file name for font file
|
|
//
|
|
|
|
dwSize = sizeof(pFIFile->wchFileName);
|
|
if (!GetPrinterDriverDirectoryW(NULL, NULL, 1, (PBYTE)pFIFile->wchFileName, dwSize, &dwSize))
|
|
{
|
|
WARNING(("Error getting printer driver directory"));
|
|
goto EndCreateNew;
|
|
}
|
|
|
|
//
|
|
// Get rid of the processor architecture part
|
|
//
|
|
|
|
if (pName = wcsrchr(pFIFile->wchFileName, '\\'))
|
|
*pName = '\0';
|
|
|
|
//
|
|
// Add "unifont"
|
|
//
|
|
|
|
StringCchCatW(pFIFile->wchFileName, CCHOF(pFIFile->wchFileName), FONTDIR);
|
|
|
|
//
|
|
// Make sure the local directory is created
|
|
//
|
|
|
|
if ( ! CreateDirectory(pFIFile->wchFileName, NULL) )
|
|
{
|
|
WARNING(("Error creating directory %s", pFIFile->wchFileName));
|
|
goto EndCreateNew;
|
|
}
|
|
|
|
if ((UuidCreate(&guid) != RPC_S_OK) ||
|
|
(UuidToString(&guid, &pstrGuid) != RPC_S_OK))
|
|
{
|
|
WARNING(("Error getting a guid string\n"));
|
|
goto EndCreateNew;
|
|
}
|
|
StringCchCatW(pFIFile->wchFileName, CCHOF(pFIFile->wchFileName), pstrGuid);
|
|
StringCchCatW(pFIFile->wchFileName, CCHOF(pFIFile->wchFileName), L".UFF");
|
|
|
|
RpcStringFree(&pstrGuid);
|
|
|
|
pFIFile->hFile = CreateFile(pFIFile->wchFileName,
|
|
GENERIC_WRITE,
|
|
0,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_FLAG_RANDOM_ACCESS | SECURITY_SQOS_PRESENT | SECURITY_ANONYMOUS,
|
|
NULL);
|
|
|
|
if (pFIFile->hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
WARNING(("Error creating file %s", pFIFile->wchFileName));
|
|
goto EndCreateNew;
|
|
}
|
|
|
|
|
|
//
|
|
// Set other fields
|
|
//
|
|
|
|
pFIFile->dwFlags = FI_FLAG_WRITE; // Give write access alone
|
|
pFIFile->dwCurPos = 0;
|
|
|
|
//
|
|
// Allocate memory for remembering glyph datas that have been written.
|
|
// Max memory needed is if each font has a different glyph data.
|
|
//
|
|
|
|
pFIFile->pGlyphData = (PFI_GLYPHDATA)ALLOC(hHeap, cFonts * sizeof(FI_GLYPHDATA));
|
|
if (!pFIFile->pGlyphData)
|
|
{
|
|
WARNING(("Error allocating memory for tracking glyph data\n"));
|
|
goto EndCreateNew;
|
|
}
|
|
pFIFile->nGlyphs = 0;
|
|
|
|
//
|
|
// Allocate memory for the file header and font directory
|
|
//
|
|
|
|
pFIFile->pFileHdr = (PUFF_FILEHEADER)ALLOC(hHeap, sizeof(UFF_FILEHEADER));
|
|
pFIFile->pFontDir = (PUFF_FONTDIRECTORY)ALLOC(hHeap, cFonts * sizeof(UFF_FONTDIRECTORY));
|
|
if (!pFIFile->pFileHdr || !pFIFile->pFontDir)
|
|
{
|
|
WARNING(("Error allocating memory for file header or font directory\n"));
|
|
goto EndCreateNew;
|
|
}
|
|
|
|
//
|
|
// Initialize file header
|
|
//
|
|
|
|
pFIFile->pFileHdr->dwSignature = UFF_FILE_MAGIC;
|
|
pFIFile->pFileHdr->dwVersion = UFF_VERSION_NUMBER;
|
|
pFIFile->pFileHdr->dwSize = sizeof(UFF_FILEHEADER);
|
|
pFIFile->pFileHdr->nFonts = cFonts;
|
|
if (cFonts)
|
|
{
|
|
pFIFile->pFileHdr->offFontDir = sizeof(UFF_FILEHEADER);
|
|
}
|
|
|
|
bRc = TRUE;
|
|
|
|
EndCreateNew:
|
|
if (!bRc)
|
|
{
|
|
FICloseFontFile((HANDLE)pFIFile);
|
|
pFIFile = NULL;
|
|
}
|
|
|
|
return (HANDLE)pFIFile;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FIWriteFileHeader
|
|
*
|
|
* Function:
|
|
* This function seeks to the beginning of the file and writes the
|
|
* file header
|
|
*
|
|
* Arguments:
|
|
* hFontFile - Handle identifying font file
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL
|
|
FIWriteFileHeader(
|
|
HANDLE hFontFile
|
|
)
|
|
{
|
|
FI_FILE *pFIFile = (FI_FILE*)hFontFile;
|
|
DWORD dwSize;
|
|
|
|
if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_WRITE))
|
|
{
|
|
if (pFIFile->dwCurPos != 0)
|
|
{
|
|
pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, 0, 0, FILE_BEGIN);
|
|
}
|
|
|
|
if (!WriteFile(pFIFile->hFile, (PVOID)pFIFile->pFileHdr, sizeof(UFF_FILEHEADER), &dwSize, NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
pFIFile->dwCurPos += dwSize;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FIWriteFontDirectory
|
|
*
|
|
* Function:
|
|
* This function seeks to the right place in the file and writes the
|
|
* font directory. It sorts it by font ID if it is not already sorted.
|
|
*
|
|
* Arguments:
|
|
* hFontFile - Handle identifying font file
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL
|
|
FIWriteFontDirectory(
|
|
HANDLE hFontFile
|
|
)
|
|
{
|
|
FI_FILE *pFIFile = (FI_FILE*)hFontFile;
|
|
DWORD dwSize;
|
|
|
|
if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_WRITE))
|
|
{
|
|
//
|
|
// If there are no fonts, there is nothing to write
|
|
//
|
|
|
|
if (pFIFile->pFileHdr->offFontDir == 0)
|
|
return TRUE;
|
|
|
|
//
|
|
// Seek to right place
|
|
//
|
|
|
|
if (pFIFile->dwCurPos != pFIFile->pFileHdr->offFontDir)
|
|
{
|
|
pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, pFIFile->pFileHdr->offFontDir, 0, FILE_BEGIN);
|
|
}
|
|
|
|
//
|
|
// Sort the font directory
|
|
//
|
|
|
|
Qsort(pFIFile->pFontDir, (int)0, (int)pFIFile->pFileHdr->nFonts-1);
|
|
pFIFile->pFileHdr->dwFlags |= FONT_DIR_SORTED;
|
|
|
|
if (!WriteFile(pFIFile->hFile, (PVOID)pFIFile->pFontDir, pFIFile->pFileHdr->nFonts*sizeof(UFF_FONTDIRECTORY), &dwSize, NULL))
|
|
{
|
|
return FALSE;
|
|
}
|
|
pFIFile->dwCurPos += dwSize;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FIAlignedSeek
|
|
*
|
|
* Function:
|
|
* This function seeks forward by the specified amount and then some if
|
|
* required so you end up DWORD aligned
|
|
*
|
|
* Arguments:
|
|
* hFontFile - Handle identifying font file
|
|
* lSeekDist - Amount to seek forward by
|
|
*
|
|
* Returns:
|
|
* Handle to use in subsequent calls if successful, NULL otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
VOID
|
|
FIAlignedSeek(
|
|
HANDLE hFontFile,
|
|
DWORD dwSeekDist
|
|
)
|
|
{
|
|
FI_FILE *pFIFile = (FI_FILE*)hFontFile;
|
|
|
|
if (IsValidFontInfo(pFIFile) && (pFIFile->dwFlags & FI_FLAG_WRITE))
|
|
{
|
|
pFIFile->dwCurPos += dwSeekDist;
|
|
pFIFile->dwCurPos = (pFIFile->dwCurPos + 3) & ~3; // DWORD align
|
|
pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, pFIFile->dwCurPos, 0, FILE_BEGIN);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FICopyFontRecord
|
|
*
|
|
* Function:
|
|
* This function copies a font record including the directory entry,
|
|
* font meetrics, glyph data and variable data from one font file
|
|
* to another.
|
|
*
|
|
* Arguments:
|
|
* hWriteFile - Handle identifying font file to write into
|
|
* hReadFile - Handle identifying font file to read from
|
|
* dwWrIndex - Index of font to write into in write file
|
|
* dwRdIndex - Index of font to read from in read file
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL
|
|
FICopyFontRecord(
|
|
HANDLE hWriteFile,
|
|
HANDLE hReadFile,
|
|
DWORD dwWrIndex,
|
|
DWORD dwRdIndex
|
|
)
|
|
{
|
|
FI_FILE *pFIWrFile = (FI_FILE*)hWriteFile;
|
|
FI_FILE *pFIRdFile = (FI_FILE*)hReadFile;
|
|
PDATA_HEADER pData;
|
|
PWSTR pName;
|
|
DWORD dwSize;
|
|
DWORD j, gdPos;
|
|
|
|
if (!IsValidFontInfo(pFIWrFile) ||
|
|
!IsValidFontInfo(pFIRdFile) ||
|
|
!(pFIWrFile->dwFlags & FI_FLAG_WRITE) ||
|
|
!(pFIRdFile->dwFlags & FI_FLAG_READ))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Copy the font directory entry
|
|
//
|
|
|
|
pFIWrFile->pFontDir[dwWrIndex].dwSignature = FONT_REC_SIG;
|
|
pFIWrFile->pFontDir[dwWrIndex].wSize = (WORD)sizeof(UFF_FONTDIRECTORY);
|
|
pFIWrFile->pFontDir[dwWrIndex].wFontID = (WORD)dwWrIndex;
|
|
pFIWrFile->pFontDir[dwWrIndex].sGlyphID = pFIRdFile->pFontDir[dwRdIndex].sGlyphID;
|
|
pFIWrFile->pFontDir[dwWrIndex].wFlags = pFIRdFile->pFontDir[dwRdIndex].wFlags;
|
|
pFIWrFile->pFontDir[dwWrIndex].dwInstallerSig = pFIRdFile->pFontDir[dwRdIndex].dwInstallerSig;
|
|
|
|
//
|
|
// Write font name
|
|
//
|
|
|
|
pName = FIGetFontName(hReadFile, dwRdIndex);
|
|
|
|
ASSERT(pName != NULL); // Can't have NULL font name
|
|
if (NULL == pName)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pFIWrFile->pFontDir[dwWrIndex].offFontName = pFIWrFile->dwCurPos;
|
|
if (!WriteFile(pFIWrFile->hFile, (PVOID)pName, (lstrlen(pName)+1) * sizeof(TCHAR), &dwSize, NULL))
|
|
{
|
|
WARNING(("Error writing font name\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
pFIWrFile->dwCurPos += dwSize;
|
|
pFIWrFile->dwCurPos = (pFIWrFile->dwCurPos + 3) & ~3;
|
|
pFIWrFile->dwCurPos = SetFilePointer(pFIWrFile->hFile, pFIWrFile->dwCurPos, 0, FILE_BEGIN);
|
|
|
|
//
|
|
// Write font cartridge name
|
|
//
|
|
|
|
pName = FIGetFontCartridgeName(hReadFile, dwRdIndex);
|
|
|
|
if (pName == NULL)
|
|
{
|
|
pFIWrFile->pFontDir[dwRdIndex].offCartridgeName = 0;
|
|
}
|
|
else
|
|
{
|
|
pFIWrFile->pFontDir[dwWrIndex].offCartridgeName = pFIWrFile->dwCurPos;
|
|
if (!WriteFile(pFIWrFile->hFile, (PVOID)pName, (lstrlen(pName)+1) * sizeof(TCHAR), &dwSize, NULL))
|
|
{
|
|
WARNING(("Error writing font cartridge name\n"));
|
|
return FALSE;
|
|
}
|
|
pFIWrFile->dwCurPos += dwSize;
|
|
pFIWrFile->dwCurPos = (pFIWrFile->dwCurPos + 3) & ~3;
|
|
pFIWrFile->dwCurPos = SetFilePointer(pFIWrFile->hFile, pFIWrFile->dwCurPos, 0, FILE_BEGIN);
|
|
}
|
|
|
|
//
|
|
// Write font data
|
|
//
|
|
|
|
pData = FIGetFontData(hReadFile, dwRdIndex);
|
|
|
|
ASSERT(pData != NULL); // Can't have NULL font data
|
|
|
|
pFIWrFile->pFontDir[dwWrIndex].offFontData = pFIWrFile->dwCurPos;
|
|
if (!WriteData(pFIWrFile, pData))
|
|
return FALSE;
|
|
|
|
//
|
|
// Get glyph data from read file
|
|
//
|
|
|
|
pData = FIGetGlyphData(pFIRdFile, dwRdIndex);
|
|
if (pData)
|
|
{
|
|
//
|
|
// Check if it is already in write file
|
|
//
|
|
|
|
gdPos = 0;
|
|
for (j=0; j<pFIWrFile->nGlyphs; j++)
|
|
{
|
|
if (pFIWrFile->pGlyphData[j].sGlyphID == pFIWrFile->pFontDir[dwWrIndex].sGlyphID)
|
|
{
|
|
gdPos = pFIWrFile->pGlyphData[j].gdPos;
|
|
}
|
|
}
|
|
|
|
|
|
if (gdPos == 0)
|
|
{
|
|
//
|
|
// Not there yet - add to set of glyph data's that have been
|
|
// added to file, and write it into write file
|
|
//
|
|
|
|
pFIWrFile->pGlyphData[pFIWrFile->nGlyphs].sGlyphID = pFIWrFile->pFontDir[dwWrIndex].sGlyphID;
|
|
pFIWrFile->pGlyphData[pFIWrFile->nGlyphs].gdPos = pFIWrFile->dwCurPos;
|
|
pFIWrFile->nGlyphs++;
|
|
|
|
|
|
pFIWrFile->pFontDir[dwWrIndex].offGlyphData = pFIWrFile->dwCurPos;
|
|
if (!WriteData(pFIWrFile, pData))
|
|
return FALSE;
|
|
|
|
pFIWrFile->pFileHdr->nGlyphSets++;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Already in file, just update location
|
|
//
|
|
|
|
pFIWrFile->pFontDir[dwWrIndex].offGlyphData = gdPos;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Glyph data not present
|
|
//
|
|
|
|
pFIWrFile->pFontDir[dwWrIndex].offGlyphData = 0;
|
|
}
|
|
|
|
//
|
|
// Write var data
|
|
//
|
|
|
|
pData = FIGetVarData(pFIRdFile, dwRdIndex);
|
|
if (pData)
|
|
{
|
|
pFIWrFile->pFontDir[dwWrIndex].offVarData = pFIWrFile->dwCurPos;
|
|
if (!WriteData(pFIWrFile, pData))
|
|
return FALSE;
|
|
|
|
pFIWrFile->pFileHdr->nVarData++;
|
|
}
|
|
else
|
|
pFIWrFile->pFontDir[dwWrIndex].offVarData = 0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FIAddFontRecord
|
|
*
|
|
* Function:
|
|
* This function adds a font record including the directory entry,
|
|
* font meetrics, glyph data and variable data
|
|
*
|
|
* Arguments:
|
|
* hFontFile - Handle identifying font file to write
|
|
* dwIndex - Index of font to write
|
|
* pFntDat - Information about font to add
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL
|
|
FIAddFontRecord(
|
|
HANDLE hFontFile,
|
|
DWORD dwIndex,
|
|
FNTDAT *pFntDat
|
|
)
|
|
{
|
|
FI_FILE *pFIFile = (FI_FILE*)hFontFile;
|
|
PDATA_HEADER pData;
|
|
PWSTR pName;
|
|
DWORD dwSize;
|
|
DWORD j, gdPos;
|
|
|
|
if (!IsValidFontInfo(pFIFile) ||
|
|
!(pFIFile->dwFlags & FI_FLAG_WRITE))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Initialize the font directory entry
|
|
//
|
|
|
|
pFIFile->pFontDir[dwIndex].dwSignature = FONT_REC_SIG;
|
|
pFIFile->pFontDir[dwIndex].wSize = sizeof(UFF_FONTDIRECTORY);
|
|
pFIFile->pFontDir[dwIndex].wFontID = (WORD)dwIndex;
|
|
pFIFile->pFontDir[dwIndex].sGlyphID = (short)pFntDat->fid.dsCTT.cBytes;
|
|
pFIFile->pFontDir[dwIndex].wFlags = FONT_FL_SOFTFONT | FONT_FL_IFI | FONT_FL_GLYPHSET_RLE;
|
|
pFIFile->pFontDir[dwIndex].dwInstallerSig = WINNT_INSTALLER_SIG;
|
|
|
|
//
|
|
// Write font name
|
|
//
|
|
|
|
pName = pFntDat->fid.dsIdentStr.pvData;
|
|
|
|
ASSERT(pName != NULL); // Can't have NULL font name
|
|
|
|
pFIFile->pFontDir[dwIndex].offFontName = pFIFile->dwCurPos;
|
|
if (!WriteFile(pFIFile->hFile, (PVOID)pName, (lstrlen(pName)+1) * sizeof(TCHAR), &dwSize, NULL))
|
|
{
|
|
WARNING(("Error writing font name\n"));
|
|
return FALSE;
|
|
}
|
|
pFIFile->dwCurPos += dwSize;
|
|
pFIFile->dwCurPos = (pFIFile->dwCurPos + 3) & ~3;
|
|
pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, pFIFile->dwCurPos, 0, FILE_BEGIN);
|
|
|
|
//
|
|
// No font cartridge name
|
|
//
|
|
|
|
pFIFile->pFontDir[dwIndex].offCartridgeName = 0;
|
|
|
|
//
|
|
// Write font data
|
|
//
|
|
|
|
pFIFile->pFontDir[dwIndex].offFontData = pFIFile->dwCurPos;
|
|
|
|
if ((dwSize = FIWriteFix(pFIFile->hFile, (WORD)dwIndex, &pFntDat->fid)) == 0)
|
|
{
|
|
WARNING(("Error writing fixed part of font data\n"));
|
|
return FALSE;
|
|
}
|
|
pFIFile->dwCurPos += dwSize;
|
|
pFIFile->dwCurPos = (pFIFile->dwCurPos + 3) & ~3;
|
|
pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, pFIFile->dwCurPos, 0, FILE_BEGIN);
|
|
|
|
//
|
|
// Check if glyph data is already in new file
|
|
//
|
|
|
|
gdPos = 0;
|
|
for (j=0; j<pFIFile->nGlyphs; j++)
|
|
{
|
|
if (pFIFile->pGlyphData[j].sGlyphID == pFIFile->pFontDir[dwIndex].sGlyphID)
|
|
{
|
|
gdPos = pFIFile->pGlyphData[j].gdPos;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if (gdPos == 0)
|
|
{
|
|
HRSRC hrsrc;
|
|
|
|
//
|
|
// Get resource from our file
|
|
//
|
|
|
|
if (pFIFile->pFontDir[dwIndex].sGlyphID > 0)
|
|
{
|
|
hrsrc = FindResource(ghInstance, MAKEINTRESOURCE(pFIFile->pFontDir[dwIndex].sGlyphID), (LPWSTR)RC_TRANSTAB);
|
|
|
|
if (!hrsrc)
|
|
{
|
|
WARNING(("Unable to find RLE resource %d in unidrvui\n", pFIFile->pFontDir[dwIndex].sGlyphID));
|
|
return FALSE;
|
|
}
|
|
|
|
pData = (PDATA_HEADER)LockResource(LoadResource(ghInstance, hrsrc));
|
|
}
|
|
else
|
|
pData = NULL;
|
|
|
|
if (pData)
|
|
{
|
|
DATA_HEADER dh;
|
|
|
|
dh.dwSignature = DATA_CTT_SIG;
|
|
dh.wSize = (WORD)sizeof(DATA_HEADER);
|
|
dh.wDataID = (WORD)pFIFile->pFontDir[dwIndex].sGlyphID;
|
|
dh.dwDataSize = SizeofResource(ghInstance, hrsrc);
|
|
dh.dwReserved = 0;
|
|
|
|
pFIFile->pFontDir[dwIndex].offGlyphData = pFIFile->dwCurPos;
|
|
|
|
if (!WriteFile(pFIFile->hFile, (PVOID)&dh, sizeof(DATA_HEADER), &dwSize, NULL) ||
|
|
!WriteFile(pFIFile->hFile, (PVOID)pData, dh.dwDataSize, &dwSize, NULL))
|
|
{
|
|
WARNING(("Error writing glyph data to font file\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Add to set of glyph data's that have been added to file
|
|
//
|
|
|
|
pFIFile->pGlyphData[pFIFile->nGlyphs].sGlyphID = pFIFile->pFontDir[dwIndex].sGlyphID;
|
|
pFIFile->pGlyphData[pFIFile->nGlyphs].gdPos = pFIFile->dwCurPos;
|
|
pFIFile->nGlyphs++;
|
|
|
|
//
|
|
// Increment number of glyph sets written
|
|
//
|
|
|
|
pFIFile->pFileHdr->nGlyphSets++;
|
|
|
|
//
|
|
// Update file position
|
|
//
|
|
|
|
pFIFile->dwCurPos += sizeof(DATA_HEADER) + dwSize;
|
|
pFIFile->dwCurPos = (pFIFile->dwCurPos + 3) & ~3;
|
|
pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, pFIFile->dwCurPos, 0, FILE_BEGIN);
|
|
}
|
|
else
|
|
{
|
|
pFIFile->pFontDir[dwIndex].offGlyphData = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Already in file, just update location
|
|
//
|
|
|
|
pFIFile->pFontDir[dwIndex].offGlyphData = gdPos;
|
|
}
|
|
|
|
//
|
|
// Write var data
|
|
//
|
|
|
|
pFIFile->pFontDir[dwIndex].offVarData = pFIFile->dwCurPos;
|
|
|
|
if (!pFntDat->pVarData)
|
|
{
|
|
dwSize = FIWriteVar(pFIFile->hFile, pFntDat->wchFileName);
|
|
}
|
|
else
|
|
{
|
|
dwSize = FIWriteRawVar(pFIFile->hFile, pFntDat->pVarData, pFntDat->dwSize);
|
|
}
|
|
|
|
if (dwSize == 0)
|
|
{
|
|
WARNING(("Error writing variable part of font data\n"));
|
|
return FALSE;
|
|
}
|
|
|
|
pFIFile->dwCurPos += dwSize;
|
|
pFIFile->dwCurPos = (pFIFile->dwCurPos + 3) & ~3;
|
|
pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, pFIFile->dwCurPos, 0, FILE_BEGIN);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* FIUpdateFontFile
|
|
*
|
|
* Function:
|
|
* This function closes both files, and if bReplace, it deletes the current
|
|
* file,and sets the new file as the current font installer file in the
|
|
* registry. In !bReplace, it closes both files and deletes the new file.
|
|
*
|
|
* Arguments:
|
|
* hCurFile - Handle identifying current font file
|
|
* hNewFile - Handle identifying new font file
|
|
* bReplace - Whether the new file should replace the current file
|
|
*
|
|
* Returns:
|
|
* TRUE if successful, FALSE otherwise
|
|
*
|
|
******************************************************************************/
|
|
|
|
BOOL
|
|
FIUpdateFontFile(
|
|
HANDLE hCurFile,
|
|
HANDLE hNewFile,
|
|
BOOL bReplace
|
|
)
|
|
{
|
|
FI_FILE *pFICurFile = (FI_FILE*)hCurFile;
|
|
FI_FILE *pFINewFile = (FI_FILE*)hNewFile;
|
|
WCHAR wchCurFileName[MAX_PATH];
|
|
WCHAR wchNewFileName[MAX_PATH];
|
|
HANDLE hPrinter;
|
|
DWORD dwSize;
|
|
|
|
//
|
|
// Validate pFINewFile
|
|
// Validate pFINewFile->wchFileName is valid.
|
|
// Validate pFINewFile->hPrinter is valid as well.
|
|
//
|
|
// IsValidFontInfo checks if pFI is not NULL and the signature is valid.
|
|
//
|
|
// pFICurFile could be NULL. In this case this is the first time to install soft fonts.
|
|
//
|
|
if ((pFICurFile && !IsValidFontInfo(pFICurFile)) ||
|
|
(pFINewFile && !IsValidFontInfo(pFINewFile)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Initialize local variables
|
|
//
|
|
wchCurFileName[0] = '\0';
|
|
wchNewFileName[0] = '\0';
|
|
|
|
//
|
|
// Remember name of the current & new files. We check for non-NULL value
|
|
// because
|
|
// this function can be called in a failure situation with bReplace set
|
|
// to FALSE, and we need to handle all possible faillure cases.
|
|
// If bReplace is TRUE, pFINewFile must be non NULL, so we get hPrinter
|
|
// there
|
|
//
|
|
|
|
if (pFINewFile)
|
|
{
|
|
StringCchCopyW(wchNewFileName, CCHOF(wchNewFileName), pFINewFile->wchFileName);
|
|
|
|
hPrinter = pFINewFile->hPrinter;
|
|
}
|
|
else
|
|
{
|
|
hPrinter = NULL;
|
|
}
|
|
|
|
|
|
if (pFICurFile)
|
|
{
|
|
StringCchCopyW(wchCurFileName, CCHOF(wchCurFileName), pFICurFile->wchFileName);
|
|
}
|
|
|
|
//
|
|
// Close both files
|
|
//
|
|
|
|
FICloseFontFile(hCurFile);
|
|
FICloseFontFile(hNewFile);
|
|
|
|
if (bReplace)
|
|
{
|
|
//
|
|
// Copy new file to current file
|
|
//
|
|
|
|
if (wchCurFileName[0])
|
|
{
|
|
if (CopyFile(wchNewFileName, wchCurFileName, FALSE))
|
|
{
|
|
//
|
|
// Set printer data so client side caches get updated
|
|
//
|
|
|
|
dwSize = (lstrlen(wchCurFileName) + 1) * sizeof(TCHAR);
|
|
if (hPrinter)
|
|
{
|
|
SetPrinterData(hPrinter, REGVAL_FONTFILENAME, REG_SZ, (PBYTE)wchCurFileName, dwSize);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Set new file as font file and return (do not delete it!)
|
|
//
|
|
|
|
dwSize = (lstrlen(wchNewFileName) + 1) * sizeof(TCHAR);
|
|
if (hPrinter)
|
|
{
|
|
SetPrinterData(hPrinter, REGVAL_FONTFILENAME, REG_SZ, (PBYTE)wchNewFileName, dwSize);
|
|
}
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Delete the new file
|
|
//
|
|
|
|
if (wchNewFileName[0])
|
|
{
|
|
DeleteFile(wchNewFileName);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* Internal helper functions
|
|
******************************************************************************/
|
|
|
|
BOOL
|
|
WriteData(
|
|
PFI_FILE pFIFile,
|
|
PDATA_HEADER pData
|
|
)
|
|
{
|
|
DWORD dwSize;
|
|
|
|
if (!WriteFile(pFIFile->hFile, (PVOID)pData, (DWORD)(pData->wSize + pData->dwDataSize), &dwSize, NULL))
|
|
return FALSE;
|
|
|
|
pFIFile->dwCurPos += dwSize;
|
|
pFIFile->dwCurPos = (pFIFile->dwCurPos + 3) & ~3;
|
|
pFIFile->dwCurPos = SetFilePointer(pFIFile->hFile, pFIFile->dwCurPos, 0, FILE_BEGIN);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Qsort
|
|
*
|
|
* Function:
|
|
* This function sorts the given font directory array based on the
|
|
* wFontID field. It used quick sort.
|
|
*
|
|
* Arguments:
|
|
* lpData - Pointer to the font directory array to sort
|
|
* start - Starting index of array
|
|
* end - Ending index of array
|
|
*
|
|
* Returns:
|
|
* Nothing
|
|
*
|
|
******************************************************************************/
|
|
|
|
void
|
|
Qsort(
|
|
PUFF_FONTDIRECTORY lpData,
|
|
int start,
|
|
int end
|
|
)
|
|
{
|
|
int i, j;
|
|
|
|
if (start < end) {
|
|
i = start;
|
|
j = end + 1;
|
|
|
|
while (1) {
|
|
while (i < j) {
|
|
i++;
|
|
if (lpData[i].wFontID >= lpData[start].wFontID)
|
|
break;
|
|
}
|
|
|
|
while(1) {
|
|
j--;
|
|
if (lpData[j].wFontID <= lpData[start].wFontID)
|
|
break;
|
|
}
|
|
|
|
if (i < j)
|
|
Exchange(lpData, i, j);
|
|
else
|
|
break;
|
|
}
|
|
|
|
Exchange(lpData, start, j);
|
|
Qsort(lpData, start, j-1);
|
|
Qsort(lpData, j+1, end);
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Exchange
|
|
*
|
|
* Function:
|
|
* This function exchanges two entries in the font directory array
|
|
*
|
|
* Arguments:
|
|
* lpData - Pointer to the font directory array
|
|
* i, j - Indices of the two entries to exchange
|
|
*
|
|
* Returns:
|
|
* Nothing
|
|
*
|
|
******************************************************************************/
|
|
|
|
void
|
|
Exchange(
|
|
PUFF_FONTDIRECTORY lpData,
|
|
DWORD i,
|
|
DWORD j
|
|
)
|
|
{
|
|
UFF_FONTDIRECTORY fd;
|
|
|
|
if ( i != j) {
|
|
memcpy((LPSTR)&fd, (LPSTR)&lpData[i], sizeof(UFF_FONTDIRECTORY));
|
|
memcpy((LPSTR)&lpData[i], (LPSTR)&lpData[j], sizeof(UFF_FONTDIRECTORY));
|
|
memcpy((LPSTR)&lpData[j], (LPSTR)&fd, sizeof(UFF_FONTDIRECTORY));
|
|
}
|
|
}
|
|
|
|
#endif // #ifndef KERNEL_MODE
|
|
|
|
|
|
|