|
|
/******************************Module*Header*******************************\
* Module Name: pffobj.cxx * * Non-inline methods for physical font file objects. * * Copyright (c) 1991-1999 Microsoft Corporation \**************************************************************************/
#include "precomp.hxx"
extern PW32PROCESS gpidSpool;
// Define the global PFT semaphore. This must be held to access any of the
// physical font information.
#if DBG
extern FLONG gflFontDebug; #endif
extern "C" void FreeFileView(PFONTFILEVIEW *ppfv, ULONG cFiles); extern "C" ULONG ComputeFileviewCheckSum(PVOID, ULONG);
ULONG ComputeFileviewCheckSum(PVOID pvView, ULONG cjView) { ULONG sum; PULONG pulCur,pulEnd;
pulCur = (PULONG) pvView;
__try { for (sum = 0, pulEnd = pulCur + cjView / sizeof(ULONG); pulCur < pulEnd; pulCur += 1) { sum += 256 * sum + *pulCur; } } __except (EXCEPTION_EXECUTE_HANDLER) { WARNING("win32k: exception while computing font check sum\n"); sum = 0; // oh well, not very unique.
}
return ( sum < 2 ) ? 2 : sum; // 0 is reserved for device fonts
// 1 is reserved for TYPE1 fonts
}
PFFMEMOBJ::PFFMEMOBJ( PFF *pPFFCloned, FLONG fl, // indicates if a permanent font
FLONG flEmbed, // embedding flag
PFT *pPFTParent // contains this pff
) { if ( pPFF = (PFF *) PALLOCMEM((size_t)pPFFCloned->sizeofThis, 'ffpG')) { RtlCopyMemory((PBYTE) pPFF, (PBYTE) pPFFCloned, offsetof(PFF,aulData));
pPFF->pPFFPrev = 0; pPFF->pPFFNext = 0;
// Wet the implicit stuff.
pPFF->cFonts = 0; // faces not loaded into table yet
pPFF->cRFONT = 0; // nothing realized from this file yet
pPFF->flState = fl; pPFF->pfhFace = 0; pPFF->pfhFamily = 0; pPFF->pfhUFI = 0; pPFF->prfntList = 0; // initialize to NULL list
pPFF->pPFT = pPFTParent;
pPFF->pPvtDataHead = NULL; // initialize to NULL link list
// loaded with FR_PRIVATE, FR_PRIVATE | FR_NOT_ENUM, FRW_EMB_PID, FRW_EMB_TID
// the load count (cPirvate or cNotEnum) is initialized in PvtData structure per process
if (flEmbed & (FR_PRIVATE | FRW_EMB_PID | FRW_EMB_TID)) { pPFF->cLoaded = 0; pPFF->cNotEnum = 0; bAddPvtData(flEmbed); }
// file is loaded as NOT_ENUM only
else if ( flEmbed & FR_NOT_ENUM ) { pPFF->cLoaded = 0; pPFF->cNotEnum = 1; }
// file is loaded as public
else { pPFF->cLoaded = 1; pPFF->cNotEnum = 0; }
// Mark this PFF as cloned
pPFFCloned->pPFFClone = pPFF; pPFF->pPFFClone = pPFFCloned;
} else { WARNING("invalid PFFMEMOBJ\n"); } }
/******************************Public*Routine******************************\
* PFFMEMOBJ::PFFMEMOBJ * * Constructor for default sized physical font file memory object. * * cFonts = # fonts in file or device * pwsz = pointer to upper case Unicode string containing the full * path to the font file. This pointer is set to zero, by * default for fonts loaded from a device. * * History: * Thu 01-Sep-1994 06:29:47 by Kirk Olynyk [kirko] * Put the size calculation logic in the constructor thereby modularizing * and shrinking the code. * Tue 09-Nov-1993 -by- Patrick Haluptzok [patrickh] * Remove from handle manager * 02-Jan-1991 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
PFFMEMOBJ::PFFMEMOBJ( unsigned cFonts // number of fonts in file|device
, PWSZ pwsz // if font file this is an upper case path
, ULONG cwc // number of characters in the mul path above
, ULONG cFiles // number of files
, DESIGNVECTOR *pdv // design vector, only present for mm instances
, ULONG cjDV // size of design vector
, HFF hffFontFile // IFI driver's handle to file
, HDEV hdevDevice // physical device handle
, DHPDEV dhpdevDevice // driver's pdev handle
, PFT *pPFTParent // contains this pff
, FLONG fl // indicates if a permanent font
, FLONG flEmbed // embedding flag
, PFNTCHECKSUM pFntCheckSum , PFONTFILEVIEW *ppfv // ptr to FILEVIEW structure
, PUNIVERSAL_FONT_ID pufi // ptr to original UFI used in remote printing
) { ULONG size = offsetof(PFF,aulData) + cFonts * sizeof(PFE*); ULONG dpDV = 0; ULONG dpPathName = 0;
ASSERTGDI(hdevDevice, "PFFMEMOBJ passed NULL hdevDevice\n"); ASSERTGDI(pFntCheckSum, "pFntCheckSum is NULL\n");
fs = 0;
if (pwsz) { dpPathName = size; size += ALIGN4(cwc*sizeof(WCHAR)); }
if (cjDV) { dpDV = size; size += cjDV; }
if (pPFF = (PFF *) PALLOCMEM(size, 'ffpG')) { pPFF->sizeofThis = size; pPFF->pPFFPrev = 0; pPFF->pPFFNext = 0; pPFF->hff = hffFontFile; pPFF->hdev = hdevDevice; pPFF->dhpdev = dhpdevDevice; pPFF->pPFT = pPFTParent; pPFF->cFiles = cFiles;
pPFF->cwc = cwc; if (cwc) { pPFF->pwszPathname_ = (PWSZ)((BYTE *)pPFF + dpPathName); RtlCopyMemory(pPFF->pwszPathname_, pwsz, cwc * sizeof(WCHAR)); } else { pPFF->pwszPathname_ = 0; }
pPFF->cjDV_ = cjDV; if (cjDV) { pPFF->pdv_ = (DESIGNVECTOR *)((BYTE *)pPFF + dpDV); RtlCopyMemory(pPFF->pdv_, pdv, cjDV); } else { pPFF->pdv_ = NULL; }
pPFF->ppfv = ppfv;
// Wet the implicit stuff.
pPFF->cFonts = 0; // faces not loaded into table yet
pPFF->cRFONT = 0; // nothing realized from this file yet
pPFF->flState = fl; pPFF->pfhFace = 0; pPFF->pfhFamily = 0; pPFF->pfhUFI = 0; pPFF->prfntList = 0; // initialize to NULL list
pPFF->pPvtDataHead = NULL; // initialize to NULL link list
// loaded with FR_PRIVATE, FR_PRIVATE | FR_NOT_ENUM, FRW_EMB_PID, FRW_EMB_TID
// the load count (cPirvate or cNotEnum) is initialized in PvtData structure per process
if (flEmbed & (FR_PRIVATE | FRW_EMB_PID | FRW_EMB_TID)) { pPFF->cLoaded = 0; pPFF->cNotEnum = 0; bAddPvtData(flEmbed); }
// file is loaded as NOT_ENUM only
else if ( flEmbed & FR_NOT_ENUM ) { pPFF->cLoaded = 0; pPFF->cNotEnum = 1; }
// file is loaded as public
else { pPFF->cLoaded = 1; pPFF->cNotEnum = 0; }
// Mark this PFF as not cloned
pPFF->pPFFClone = NULL;
pPFF->ulCheckSum = 0; // for device fonts it is zero
if(pufi != NULL) { pPFF->ulCheckSum = pufi->CheckSum; } else { if (ppfv != NULL) {
pPFF->ulCheckSum = pFntCheckSum->ulCheckSum;
if (!pPFF->ulCheckSum) { // not in the boot, or could not find it in the ttfcache for some reason
// Now compute the UFI
KeAttachProcess(PsGetProcessPcb(gpepCSRSS)); for (ULONG iFile = 0; iFile < cFiles; iFile ++) { pPFF->ulCheckSum += ComputeFileviewCheckSum(ppfv[iFile]->fv.pvViewFD, ppfv[iFile]->fv.cjView); } KeDetachProcess();
PutFNTCacheCheckSum(pFntCheckSum->ulFastCheckSum, pPFF->ulCheckSum); }
ASSERTGDI(pPFF->ulCheckSum, "pPFF->ulCheckSum must not be zero\n");
if (pPFF->cjDV_) { pPFF->ulCheckSum += ComputeFileviewCheckSum(pdv, cjDV); } }
#if 0
// do it old way, and compare values in DBG mode
if (ppfv != NULL) { ULONG ulCheckSumTest = 0;
// Now compute the UFI
KeAttachProcess(PsGetProcessPcb(gpepCSRSS)); for (ULONG iFile = 0; iFile < cFiles; iFile ++) { ulCheckSumTest += ComputeFileviewCheckSum(ppfv[iFile]->fv.pvViewFD, ppfv[iFile]->fv.cjView); } KeDetachProcess();
if (pPFF->cjDV_) { ulCheckSumTest += ComputeFileviewCheckSum(pdv, cjDV); }
if (ulCheckSumTest != pPFF->ulCheckSum) { DbgPrint(" TrueType font cache failed, if you see these message \n"); DbgPrint(" Please contact YungT or NTFonts \n"); DbgPrint(" it is ok to hit 'g' \n"); DbgBreakPoint(); } } #endif
} } else { WARNING("invalid PFFMEMOBJ\n"); } }
/******************************Public*Routine******************************\
* PFFMEMOBJ::~PFFMEMOBJ() * * Destructor for physical font file memory object. * * History: * Tue 09-Nov-1993 -by- Patrick Haluptzok [patrickh] * Remove from handle manager * * 02-Jan-1991 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
PFFMEMOBJ::~PFFMEMOBJ() { if ((fs & PFFMO_KEEPIT) == 0) { if (pPFF) { VFREEMEM(pPFF); } } }
/******************************Public*Routine******************************\
* BOOL PFFOBJ::bCreatePFEC(ULONG cFonts) * * Create the handle of PFE collect, a object to reduce the consumption of object handle * * Returns: * TRUE means we create successfully * * History: * * 2-June-1996 -by- Yung-Jen Tony Tsai [YungT] * Wrote it. \**************************************************************************/
BOOL PFFOBJ::bCreatePFEC(ULONG cFonts) { BOOL bRet = FALSE;
ASSERTGDI(cFonts, "PFFOBJ::bCreateHPFE cFonts is zero \n"); pPFF->pPFEC = (PFEC *) HmgAlloc(sizeof(PFEC), PFE_TYPE, HMGR_ALLOC_ALT_LOCK | HMGR_MAKE_PUBLIC);
if (pPFF->pPFEC) { pPFF->pPFEC->pvPFE = (PVOID) PALLOCMEM(SZ_PFE(gcfsCharSetTable) * cFonts, 'efpG'); pPFF->pPFEC->cjPFE = SZ_PFE(gcfsCharSetTable); if (pPFF->pPFEC->pvPFE) bRet = TRUE; else { HmgFree((HOBJ)pPFF->pPFEC->hGet()); pPFF->pPFEC = NULL; } }
return bRet; }
/******************************Public*Routine******************************\
* VOID PFFOBJ::vDeletePFEC(PVOID *ppvPFE) * * Delete the handle of PFE collect, a object to reduce the consumption of object handle * * Returns: * None * * History: * * 2-June-1996 -by- Yung-Jen Tony Tsai [YungT] * Wrote it. \**************************************************************************/
VOID PFFOBJ::vDeletePFEC(PVOID *ppvPFE) { *ppvPFE = NULL; if (pPFF->pPFEC != NULL) { *ppvPFE = pPFF->pPFEC->pvPFE; HmgFree((HOBJ)pPFF->pPFEC->hGet()); pPFF->pPFEC = NULL; } }
/******************************Public*Routine******************************\
* PFFOBJ::bAddHash * * Adds the PFF and all its PFEs to the font hashing table. The font * hashing tabled modified is in the PFT if a font driver managed font; * otherwise, the font hashing table is in the PFF itself. * * The caller should hold the ghsemPublicPFT while calling this function. * * Returns: * TRUE if successful, FALSE otherwise. * * History: * 11-Mar-1993 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
BOOL PFFOBJ::bAddHash(BOOL bEUDC) { // Caller must hold the ghsemPublicPFT semaphore to protect access to
// the hash tables.
//
// Add the entry to the appropriate font hash tables
//
FONTHASH **ppfhFace, **ppfhFamily,**ppfhUFI;
if (!bDeviceFonts()) { //
// Hash tables for the font driver loaded fonts exist off of
// the font table.
//
PUBLIC_PFTOBJ pfto( bInPrivatePFT() ? gpPFTPrivate : gpPFTPublic ); ASSERTGDI(pfto.bValid(),"PFFOBJ::vAddHash -- invalid Public PFTOBJ\n");
ppfhFace = &(pfto.pPFT->pfhFace); ppfhFamily = &(pfto.pPFT->pfhFamily); ppfhUFI = &(pfto.pPFT->pfhUFI);
//
// If this is a TrueType font, increment the count.
//
if ( pPFF->hdev == (HDEV) gppdevTrueType ) { gcTrueTypeFonts++; // protected by ghsemPublicPFT
} } else { //
// Hash tables for device fonts exist off of the PFF that
// encapsulates them.
//
#if DBG
if (gflFontDebug & DEBUG_FONTTABLE) { RIP("\n\n[kirko] PFFMEMOBJ::vAddHash -- Adding to the Driver's font hash table\n\n"); } #endif
ppfhFace = &pPFF->pfhFace; ppfhFamily = &pPFF->pfhFamily; ppfhUFI = &pPFF->pfhUFI; }
//
// Now that we have figured out where the tables are, add the PFEs to them.
//
FHOBJ fhoFamily(ppfhFamily); FHOBJ fhoFace(ppfhFace); FHOBJ fhoUFI(ppfhUFI);
ASSERTGDI(fhoFamily.bValid(), "bAddHashPFFOBJ(): fhoFamily not valid\n"); ASSERTGDI(fhoFace.bValid(), "bAddHashPFFOBJ(): fhoFace not valid\n"); ASSERTGDI(fhoUFI.bValid(), "bAddHashPFFOBJ(): fhoUFI not valid\n");
if (! (fhoUFI.bValid() && fhoFamily.bValid() && fhoFace.bValid())) return FALSE; for (COUNT c = 0; c < pPFF->cFonts; c++) { PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]); ASSERTGDI(pfeo.bValid(), "bAddHashPFFOBJ(): bad HPFE\n");
if(!fhoUFI.bInsert(pfeo) ) { WARNING("PFFOBJ::bAddHash -- fhoUFI.bInsert failed\n"); return FALSE; }
// If we only need to add it to the UFI hash table (we need to add it there
// so that the remote printing code can request the bits of it needs to).
if(bEUDC) { continue; }
if (!fhoFamily.bInsert(pfeo)) { WARNING("PFFOBJ::bAddHash -- fhoFamily.bInsert failed\n"); return FALSE; }
#if DBG
if (gflFontDebug & DEBUG_FONTTABLE) { DbgPrint("PFFMEMOBJ::vAddHash(\"%ws\")\n",pfeo.pwszFamilyName()); } // Need level 2 checking to see this.
if (gflFontDebug & DEBUG_FONTTABLE_EXTRA) { fhoFamily.vPrint((VPRINT) DbgPrint); } #endif
#if DBG
if (gflFontDebug & DEBUG_FONTTABLE) { UNIVERSAL_FONT_ID ufi; pfeo.vUFI(&ufi); DbgPrint("PFFMEMOBJ::vAddHash(\"%x\")\n",ufi.CheckSum); } // Need level 2 checking to see this.
if (gflFontDebug & DEBUG_FONTTABLE_EXTRA) { fhoUFI.vPrint((VPRINT) DbgPrint); } #endif
if(!fhoFace.bInsert(pfeo)) { WARNING("PFFMEMOBJ::vAddHash -- fhoFace.bInsert failed\n"); return FALSE; }
#if DBG
if (gflFontDebug & DEBUG_FONTTABLE) { DbgPrint("gdisrv!PFFMEMOBJ::vAddHash(\"%ws\")\n",pfeo.pwszFaceName()); } if (gflFontDebug & DEBUG_FONTTABLE_EXTRA) { fhoFace.vPrint((VPRINT) DbgPrint); } #endif
}
return TRUE; }
/******************************Public*Routine******************************\
* PFFOBJ::vRemoveHash * * Removes the PFF and all its PFEs from the font hashing table, preventing * the font from being enumerated or mapped. * * The caller should hold the ghsemPublicPFT while calling this function. * * History: * 10-Mar-1993 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
VOID PFFOBJ::vRemoveHash () { // Caller must hold the ghsemPublicPFT semaphore to protect access to
// the hash tables.
if (bDeviceFonts()) { //
// Hash tables for device fonts exist off of the PFF that
// encapsulates the device fonts. Font driver loaded fonts
// are handled later while deleting the PFEs.
//
//
// Kill the entire table for the device. No more processing
// of font hash table stuff is necssary for device fonts
// after we leave this scope.
//
FHOBJ fhoFace(&(pPFF->pfhFace)); if (fhoFace.bValid()) { fhoFace.vFree(); }
FHOBJ fhoFamily(&(pPFF->pfhFamily)); if (fhoFamily.bValid()) { fhoFamily.vFree(); }
FHOBJ fhoUFI(&(pPFF->pfhUFI)); if (fhoUFI.bValid()) { fhoUFI.vFree(); } }
else { PUBLIC_PFTOBJ pfto( bInPrivatePFT() ? gpPFTPrivate : gpPFTPublic ); ASSERTGDI(pfto.bValid(),"vRemoveHashPFFOBJ(): invalid PFTOBJ\n");
//
// Hash tables for the font driver managed fonts exist off of
// the font table (PFT).
//
FHOBJ fhoFace(&(pfto.pPFT->pfhFace)); FHOBJ fhoFamily(&(pfto.pPFT->pfhFamily)); FHOBJ fhoUFI(&(pfto.pPFT->pfhUFI));
for (COUNT c = 0; c < pPFF->cFonts; c++) { PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]); ASSERTGDI(pfeo.bValid(), "vRemoveHashPFFOBJ(): bad HPFE\n");
//
// Remove PFE from hash tables.
//
if( !pfeo.bEUDC() ) { // EUDC fonts arent added to these two tables
if (fhoFace.bValid()) fhoFace.vDelete(pfeo);
if (fhoFamily.bValid()) fhoFamily.vDelete(pfeo); }
if (fhoUFI.bValid()) fhoUFI.vDelete(pfeo);
#if DBG
if (gflFontDebug & DEBUG_FONTTABLE) { DbgPrint("gdisrv!vRemoveHashPFFOBJ() hpfe 0x%lx (\"%ws\")\n", pfeo.ppfeGet(), pfeo.pwszFamilyName()); } // Need level 2 checking to see this extra detail.
if (gflFontDebug & DEBUG_FONTTABLE_EXTRA) { fhoFamily.vPrint((VPRINT) DbgPrint); } #endif
}
//
// If this is a TrueType font, decrement the count.
//
if ( pPFF->hdev == (HDEV) gppdevTrueType ) { gcTrueTypeFonts--; // protected by ghsemPublicPFT
} } }
/******************************Public*Routine******************************\
* * BOOL PFFOBJ::bPermanent() * * * Effects: * * Warnings: * * History: * 06-Dec-1993 -by- Bodin Dresevic [BodinD] * Wrote it. \**************************************************************************/
BOOL PFFOBJ::bPermanent() { // in the new version of the code every remote font is flagged at
// AddFontResourceTime. The difference in behavior from 3.51
// is that now fonts added by the applicaitons, if local, will not
// be removed at log on time.
if (pPFF->flState & PFF_STATE_NETREMOTE_FONT) return FALSE; else return TRUE;
}
/******************************Public*Routine******************************\
* PFFOBJ::vPFFC_Delete * * Deletes the PFF and its PFEs. Information needed to call the driver * to unload the font file and release driver allocated data is stored * in the PFFCLEANUP structure. The PFFCLEANUP structure is allocated * within this routine. It is the caller's responsibility to release * the PFFCLEANUP structure (calling vCleanupFontFile() calls the drivers * AND releases the structure). * * Changed so that it does not return a pointer to a PFFCLEANUP * structure. Instead, it takes a pointer to a PFFCLEANUP * structure as an argument. Thus, the caller must allocate * and free the memory to the PFFCLEANUP structure. [dchinn 11/24/98] * * Returns: * void. The contents of the PFFCLEANUP structure passed in will be altered * as appropriate. * * History: * 10-Mar-1993 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
VOID PFFOBJ::vPFFC_Delete(PFFCLEANUP *pPFFC) {
PVOID pvPFE; TRACE_FONT(("Entering PFFOBJ::vPFFC_Delete()\n\tpPFF=%-#x\n", pPFF));
// check to see if a NULL pointer to a PFFCLEANUP structure was passed in
ASSERTGDI(pPFFC, "vPFFC_Delete(): passed in a NULL\n");
vDeletePFEC(&pvPFE); //
// Delete all the PFE entries.
//
for (COUNT c = 0; c < pPFF->cFonts; c++) { PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]); ASSERTGDI(pfeo.bValid(), "vPFFC_DeletePFFOBJ(): bad HPFE (device font)\n");
//
// Delete the PFE. The vDelete function will copy the driver allocated
// resource information from the PFE into the PFECLEANUP structure.
// We will call DrvFree for these resources later (when we're not under
// semaphore).
//
pfeo.vDelete(); }
//
// Save stuff about the PFF also.
//
pPFFC->hff = pPFF->hff; pPFFC->hdev = pPFF->hdev; pPFFC->pPFFClone = pPFF->pPFFClone;
//
// Free object memory and invalidate pointer.
//
TRACE_FONT(("Freeing pPFF=%-#x\n",pPFF));
// If this was a remote font then we must delete the memory for the file.
// If this is a normal font then we must still delete the view.
if (!pPFF->pPFFClone) { if (pPFF->ppfv && pPFF->cFiles) { FreeFileView(pPFF->ppfv, pPFF->cFiles); } } else {
// We release the pPFFClone.
pPFF->pPFFClone->pPFFClone = NULL; }
if (pvPFE) VFREEMEM(pvPFE); VFREEMEM(pPFF);
pPFF = 0; TRACE_FONT(("Exiting PFFOBJ::vPFFC_Delete\n\treturn value = %x\n", pPFFC)); return; }
/******************************Public*Routine******************************\
* PFFOBJ::vPFFC_DeleteAndCleanup * * This function creates a pointer to a PFFCLEANUP structure, calls vPFFC_Delete(), * and then calls vCleanupFontFile(). This is the recommended way to handle * unloading a font file, because it avoids the possibility (when a font file * contains fewer than CFONTS_PFFCLEANUP fonts) that under a Hydra scenario * it will fail to free up all the memory. * * (The old way of doing the cleanup was to call vPFFC_Delete() and then * vCleanupFontFile(). However, the old vPFFC_Delete() allocated a PFFCLEANUP * structure. If that allocation failed, then the rest of the cleanup would * not occur, and so memory would leak from a Hydra session. This new way of * doing the cleanup does not allocate memory from the heap. Instead, it allocates * it on the stack.) * * If for some reason the two calls (vPFFC_Delete() and vCleanupFontFile() ) need * to be done separately (for example, if one of the calls is protected by a * semaphore), then one must wrap code similar to that below around the two calls. * * Returns: * void. * * History: * 24-Nov-1998 -by- Donald Chinn [dchinn] * Wrote it. \**************************************************************************/
VOID PFFOBJ::vPFFC_DeleteAndCleanup() { PFFCLEANUP pffc;
// now call vPFFC_Delete() and vCleanupFontFile()
vPFFC_Delete (&pffc); vCleanupFontFile (&pffc); }
/******************************Public*Routine******************************\
* BOOL PFFOBJ::bDeleteLoadRef () * * Remove a load reference. Caller must hold the ghsemPublicPFT semaphore. * * Returns: * TRUE if caller should delete, FALSE if caller shouldn't delete. * * History: * 23-Feb-1991 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
BOOL PFFOBJ::bDeleteLoadRef(ULONG fl, PVTDATA *pPvtData, BOOL *pbWrongFlags) { // ghsemPublicPFT protects the ref counts (cLoaded and cRFONT). Caller
// must grab the semaphore before calling this function.
// Decrement the load count. Must prevent underflow. Who knows if some
// app might not randomly go around doing extra RemoveFont calls. Isn't
// it too bad that we have to run APPS on our nice clean OS? :-)
BOOL bRet = FALSE; *pbWrongFlags = FALSE;
TRACE_FONT(("Enterning PFFOBJ::bDeleteLoadRef\n" "\tpPFF=%-#x\n" "\tcLoaded=%d\n", "\tcNotEnum=%d\n",pPFF ,pPFF->cLoaded ,pPFF->cNotEnum));
// Embedded/Private fonts
if (bInPrivatePFT()) { ASSERTGDI(pPvtData, "bDeleteLoadRef: pPvtData is NULL\n");
if (pPvtData == NULL) { return bRet; } // called by cleanup routine when the process terminates
if (fl == FRW_PVT_CLEANUP) { pPvtData->cPrivate = 0; pPvtData->cNotEnum = 0; }
// decreament cNotEnum for Embedded or FR_NOT_ENUM set font
else if (fl & (FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID | FR_PRINT_EMB_FONT)) { if (pPvtData->fl & fl) { if ( pPvtData->cNotEnum ) { pPvtData->cNotEnum--; if (fl == FR_PRINT_EMB_FONT) { pPvtData->fl &= ~FR_PRINT_EMB_FONT; } } } else { *pbWrongFlags = TRUE; } }
// decreament cPrivate for FR_PRIVATE set only font
else { if (pPvtData->fl & fl) { if ( pPvtData->cPrivate ) { pPvtData->cPrivate--; } else { *pbWrongFlags = TRUE; } } }
// Remove the PvtData block if both cPrivate and cNotEnum counts are zero.
if ((pPvtData->cPrivate | pPvtData->cNotEnum) == 0) { bRemovePvtData(pPvtData); }
// Mark it to Ready2Die if the PvtData list is NULL.
if (pPvtDataHeadGet() == NULL) { ASSERTGDI( (pPFF->cLoaded | pPFF->cNotEnum) == 0, "win32k!bDeleteLoadRef(): global (cLoaded | cNotEnum) in private PFF is not 0\n");
vKill(); bRet = TRUE; } } else { // remove a public font
if (fl == 0) { if (pPFF->cLoaded) { pPFF->cLoaded--; } }
// remove a FR_NOT_ENUM font in the public PFT
else { ASSERTGDI(fl == FR_NOT_ENUM, "win32k!bDeletLoadRef(): attempt to delete a font in public PFT with fl!=FR_NOT_ENUM \n");
if (pPFF->cNotEnum) { pPFF->cNotEnum--; } }
if ((pPFF->cLoaded | pPFF->cNotEnum) == 0) { ASSERTGDI(pPFF->pPvtDataHead == NULL, "win32k!bDeleteLoadRef(): pPvtDataHead in public PFF is not NULL\n");
vKill(); // mark as "dead"
bRet = TRUE; } }
TRACE_FONT(("Exiting PFFOBJ::bDeleteLoadRef\n\treturn value = %d\n",bRet)); return( bRet ); }
/******************************Public*Routine******************************\
* BOOL PFFOBJ::bDeleteRFONTRef () * * Destroy the PFF physical font file object (message from a RFONT). * * Conditions that need to be met before deletion: * * must delete all RFONTs before PFF can be deleted (cRFONT must be zero) * must delete all PFEs before deleting PFF * * After decrementing the cRFONT: * * If cRFONT != 0 OR flState != PFF_STATE_READY2DIE, just exit. * * If cRFONT == 0 and flState == PFF_STATE_READY2DIE, delete the PFF. * * Note: * This function has the side effect of decrementing the RFONT count. * * Returns: * TRUE if successful, FALSE if error occurs (which means PFF still lives!) * * Warning: * This should only be called from RFONTOBJ::bDelete() * * History: * 23-Feb-1991 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
BOOL PFFOBJ::bDeleteRFONTRef() { PFFCLEANUP pffc; BOOL bCleanUp = FALSE;
{ // Need to stabilize table to access cRFONT and to modify font table.
SEMOBJ so(ghsemPublicPFT);
// Decrement the RFONT count.
ASSERTGDI(pPFF->cRFONT > 0,"bDeleteRFONTRefPFFOBJ(): bad ref count in PFF\n"); pPFF->cRFONT--;
// If load count is zero and no more RFONTs for this PFF, OK to delete.
if ( (pPFF->cLoaded == 0) && (pPFF->cNotEnum == 0) && (pPFF->pPvtDataHead == NULL) && (pPFF->cRFONT == 0) ) { // If the load count is zero, the PFF is already out of the PFT.
// It is now safe to delete the PFF.
vPFFC_Delete(&pffc); bCleanUp = TRUE; } }
// Call the driver outside of the semaphore.
if (bCleanUp) vCleanupFontFile(&pffc); // function can handle NULL case
return TRUE; }
/******************************Public*Routine******************************\
* vKill * * Puts the PFF and its PFEs to death. In other words, the PFF and PFEs are * put in a dead state that prevents them from being mapped to or enumerated. * It also means that the font file is in a state in which the system wants * to delete it (load count is zero), but the deletion is delayed because * RFONTs still exist which reference this PFF. * * History: * 29-May-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
VOID PFFOBJ::vKill() { // Put into a dead state if not already there.
TRACE_FONT(("Entering PFFOBJ::vKill\n\tpPFF=%-#x\n", pPFF)); if ( !bDead() ) { // Set state.
pPFF->flState |= PFF_STATE_READY2DIE;
// Run the list of PFEs and set each to death.
for (COUNT c = 0; c < pPFF->cFonts; c++) { PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]);
if (pfeo.bValid()) { // Mark PFE as dead state.
pfeo.vKill(); } else { WARNING("vDiePFFOBJ(): cannot make PFEOBJ\n"); } } } TRACE_FONT(("Exiting PFFOBJ::vKill\n")); }
/******************************Public*Routine******************************\
* vRevive * * Restores the PFF and its PFEs to life. In other words, the states are * cleared so that the PFF and PFEs are available for mapping and enumeration. * * History: * 29-May-1992 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
VOID PFFOBJ::vRevive () { // If dead, then revive.
if ( bDead() ) { // Reset state.
pPFF->flState &= ~PFF_STATE_READY2DIE;
// Run the list of PFEs and revive each one.
for (COUNT c = 0; c < pPFF->cFonts; c++) { PFEOBJ pfeo(((PFE **) (pPFF->aulData))[c]);
if (pfeo.bValid()) { // Mark PFE as dead state.
pfeo.vRevive(); } else { WARNING("vRevivePFFOBJ(): cannot make PFEOBJ\n"); } } } }
/******************************Public*Routine******************************\
* BOOL PFFMEMOBJ::bLoadFontFileTable * * Creates a PFE for each of the faces in a font file and loads the IFI * metrics and mapping tables into each of the PFEs. The font file is * uniquely identified by the driver, hoDriver, and IFI font file handle, * hff, stored in the PFF object. However, rather than hitting the handle * manager an extra time, a PFDEVOBJ is passed into this function. * * After all the PFE entries are added, the font files pathname is added * to the end of the data buffer. * * It is assumed that the PFF ahpfe table has enough room for cFontsToLoad * new HPFE handles as well as the font files pathname. * * Returns: * TRUE if successful, FALSE if error. * * History: * 16-Jan-1991 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
BOOL PFFMEMOBJ::bLoadFontFileTable ( PWSZ pwszPathname, // upper case
COUNT cFontsToLoad, HANDLE hdc, PUNIVERSAL_FONT_ID pufi #ifdef FE_SB
,PEUDCLOAD pEudcLoadData #endif
) { ULONG iFont; // font face index
// Create PFE's for each of the fonts in the font file.
// (Note: iFont indices for IFI fonts are 1-based, not 0-based)
PDEVOBJ ppdo(hdev());
if (!bCreatePFEC(cFontsToLoad)) return FALSE;
for (iFont = 1; iFont <= cFontsToLoad; iFont++) { FD_GLYPHSET *pfdg; PIFIMETRICS pifi; // storage for the pointer to ifi
ULONG_PTR idMetrics;
// Grab the IFIMETRICS pointer.
if ( (pifi = ppdo.QueryFont( pPFF->dhpdev, pPFF->hff, iFont, &idMetrics)) == (PIFIMETRICS) NULL ) { WARNING("bLoadFontFileTablePFFMEMOBJ(): error getting metrics\n"); return (FALSE); }
// Put into a new PFE.
#ifdef FE_SB
BOOL bRet = TRUE; if( bReadyToInitializeFontAssocDefault ) { // This should be Base font, not be EUDC.
//
if ( pEudcLoadData == NULL ) { // check this base font should be RE-load as default linked font ?
// if so, the pathname for this font will be registerd as default linked font.
bRet = FindDefaultLinkedFontEntry( (const WCHAR *)(((BYTE*) pifi) + pifi->dpwszFamilyName),pwszPathname); } }
if (!bRet || !bAddEntry(iFont, NULL, 0, pifi, idMetrics, (HANDLE)0, pufi, pEudcLoadData)) { // Failed to get the FD_GLYPHSET information. The entry is
// partially valid (IFIMETRICS), so lets invalidate the good part.
if (PPFNVALID(ppdo,Free)) { ppdo.Free(pifi, idMetrics); }
WARNING("bLoadFontFileTablePFFMEMOBJ(): error getting glyphset\n");
return (FALSE); }
#endif
}
return (TRUE); }
/*************************Public*Routine**************************\
* BOOL bExtendGlyphset * Check the glyph set returned by the printer driver. Tack on the * f0xx unicode range if missing for symbol font. * * History: * Oct-10-97 Xudong Wu [TessieW] * Wrote it. * \*****************************************************************/ BOOL bExtendGlyphSet(FD_GLYPHSET **ppfdgIn, FD_GLYPHSET **ppfdgOut) { WCHAR awch[256], *pwsz = awch, wcLow, wcHigh; UCHAR ach[256]; USHORT AnsiCodePage, OemCodePage; INT cjWChar, cjChar;
ULONG cjSize, iRun, jRun, i, j; FD_GLYPHSET *pfdgNew, *pfdg; ULONG cRuns; BOOL bRet = FALSE, bNeedExt = FALSE;
pfdg = *ppfdgIn; cRuns = pfdg->cRuns; if (cRuns == 0) { WARNING("bExtendGlyphSet - empty glyphset\n"); return FALSE; }
wcLow = pfdg->awcrun[0].wcLow; wcHigh = pfdg->awcrun[cRuns-1].wcLow + (WCHAR)pfdg->awcrun[cRuns-1].cGlyphs - 1 ;
// mixing CP_SYMBOL mapping
// e0 is the number of glyphs in f020-f0ff range in symbol CP
// We shall extend the glypset if [f020,f0ff] does not intersect any
// of the runs specified in the old pfdg. We check that by making sure that
// [f020,f0ff] is entirely contained in the complement of the old glyphset.
if (pfdg->cGlyphsSupported <= 256) { if ((wcHigh < 0xf020) || (wcLow > 0xf0ff)) { bNeedExt = TRUE; } else { // bNeedExt = FALSE; // already initialized
for (iRun = 0; iRun < (cRuns - 1); iRun++) { wcLow = pfdg->awcrun[iRun].wcLow + pfdg->awcrun[iRun].cGlyphs - 1; wcHigh = pfdg->awcrun[iRun+1].wcLow;
if ((wcLow < 0xf020) && (wcHigh > 0xf0ff)) { bNeedExt = TRUE; break; } } } }
if (bNeedExt) { cjSize = SZ_GLYPHSET(cRuns + 1, pfdg->cGlyphsSupported + 0x00e0); pfdgNew = (FD_GLYPHSET*) PALLOCMEM(cjSize,'slgG');
if (pfdgNew) { HGLYPH *phgS, *phgD;
cjWChar = sizeof(WCHAR) * pfdg->cGlyphsSupported; cjChar = 256;
for (iRun = 0; iRun < cRuns; iRun++) { for (i = 0; i < pfdg->awcrun[iRun].cGlyphs; i++) { *pwsz++ = pfdg->awcrun[iRun].wcLow + (WCHAR)i; } }
RtlGetDefaultCodePage(&AnsiCodePage, &OemCodePage); if(IS_ANY_DBCS_CODEPAGE(AnsiCodePage)) { AnsiCodePage = 1252; } if(EngWideCharToMultiByte(AnsiCodePage, awch, cjWChar, (CHAR*)ach, cjChar) == -1) { VFREEMEM(pfdgNew); return bRet; }
pfdgNew->cjThis = cjSize; pfdgNew->flAccel = pfdg->flAccel | GS_EXTENDED;
pfdgNew->cGlyphsSupported = pfdg->cGlyphsSupported + 0x00e0; pfdgNew->cRuns = cRuns + 1;
phgS = phgD = (HGLYPH*) &pfdgNew->awcrun[cRuns+1];
for ( iRun = 0; (iRun < cRuns) && (pfdg->awcrun[iRun].wcLow < 0xf020); iRun++) { pfdgNew->awcrun[iRun].wcLow = pfdg->awcrun[iRun].wcLow; pfdgNew->awcrun[iRun].cGlyphs = pfdg->awcrun[iRun].cGlyphs; pfdgNew->awcrun[iRun].phg = phgD;
RtlCopyMemory(phgD, pfdg->awcrun[iRun].phg, sizeof(HGLYPH) * pfdg->awcrun[iRun].cGlyphs);
phgD += pfdg->awcrun[iRun].cGlyphs; }
// fill in the f0xx range
pfdgNew->awcrun[iRun].wcLow = 0xf020; pfdgNew->awcrun[iRun].cGlyphs = 0x00e0; pfdgNew->awcrun[iRun].phg = phgD;
RtlZeroMemory((PVOID)phgD, 0x00e0 * sizeof(HGLYPH));
j = 0; for (jRun = 0; jRun < cRuns; jRun++) { for (i = 0; i < pfdg->awcrun[jRun].cGlyphs; i++) { if (ach[j] >= 0x20) { phgD[ach[j] - 0x20] = pfdg->awcrun[jRun].phg[i]; } j++; } }
phgD += 0x00e0; for (; iRun < cRuns; iRun++) { pfdgNew->awcrun[iRun+1].wcLow = pfdg->awcrun[iRun].wcLow; pfdgNew->awcrun[iRun+1].cGlyphs = pfdg->awcrun[iRun].cGlyphs; pfdgNew->awcrun[iRun+1].phg = phgD;
RtlCopyMemory(phgD, pfdg->awcrun[iRun].phg, sizeof(HGLYPH) * pfdg->awcrun[iRun].cGlyphs);
phgD += pfdg->awcrun[iRun].cGlyphs; }
*ppfdgOut = pfdgNew; bRet = TRUE; } else { WARNING("bExtentGlyphSet(): failed to allocate pGlyphset\n"); } }
return bRet; }
/******************************Public*Routine******************************\
* BOOL PFFMEMOBJ::bLoadDeviceFontTable ( * * Creates a PFE object for each device font and stores the IFIMETRICS and * FD_MAPPINGS (UNICODE->HGLYPH) structures of that font. The device is * identified by the pair (ppdo, dhpdev). There are cFonts number of device * fonts to load. * * Note: * It is assumed that there is enough storage in the PFF for the number * of device fonts requested. * * History: * 18-Mar-1991 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
BOOL PFFMEMOBJ::bLoadDeviceFontTable ( PDEVOBJ *ppdo // physical device
) { ULONG iFont; // font face index
ULONG cFonts = ppdo->cFonts(); BOOL bUMPD = ppdo->bUMPD(); BOOL bRet = FALSE;
PIFIMETRICS pifi; // pointer to font's IFIMETRICS
FD_GLYPHSET *pfdg; // pointer to font's GLYPHSETs
ULONG_PTR idifi; // driver id's
ULONG_PTR idfdg;
if (cFonts) {
if (!bCreatePFEC(cFonts)) return bRet;
//
// If the device has some fonts, allocate two FONTHASH strcutures
// and save the addresses of the tables on the PFF
//
FHMEMOBJ fhmoFace( &pPFF->pfhFace, FHT_FACE , cFonts); FHMEMOBJ fhmoFamily(&pPFF->pfhFamily, FHT_FAMILY, cFonts); FHMEMOBJ fhmoUFI(&pPFF->pfhUFI, FHT_UFI, cFonts); }
// Create PFE's for each of the fonts in the font file
// (Note: iFont indices for device fonts are 1-based, not 0-based)
for (iFont = 1; iFont<=cFonts; iFont++) {
// Set as NULL before we start to allocate ifi and fd_glyphset
pfdg = NULL; pifi = NULL; // Get pointer to metrics
if (( pifi = ppdo->QueryFont(pPFF->dhpdev, 0, iFont, &idifi )) == NULL ) { SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE); #if DBG
DbgPrint("gdisrv!PFFMEMOBJ::bLoadDeviceFontTable(): error getting metrics \
for iFace = %ld\n", iFont); #endif
goto CleanUp; }
// Get pointer to the UNICODE->HGLYPH mappings
if (bUMPD) { pfdg = NULL; } else { if ( (pfdg = (FD_GLYPHSET *) ppdo->QueryFontTree( pPFF->dhpdev, 0, iFont, QFT_GLYPHSET, &idfdg)) == NULL ) { // Failed to get the FD_GLYPHSET information. The entry is
// partially valid (IFIMETRICS), so lets invalidate the good part.
SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE); goto CleanUp; }
// extend the glyph set,
// it may not contain [f020,f0ff] range for the older drivers
if (pifi->jWinCharSet == SYMBOL_CHARSET) { FD_GLYPHSET *pfdgNew = NULL;
if (bExtendGlyphSet(&pfdg, &pfdgNew)) { if (PPFNVALID(*ppdo,Free)) { ppdo->Free(pfdg, idfdg); } pfdg = pfdgNew; } } } // Put into a new PFE
// add entry logs error
if (bAddEntry(iFont, pfdg, idfdg, pifi, idifi,(HANDLE)0,NULL) == FALSE) { WARNING("bLoadDeviceFontTable():adding PFE\n"); goto CleanUp; } }
bRet = TRUE; CleanUp:
if (!bRet) { // Free font hash
FHOBJ fhoFace(&(pPFF->pfhFace)); if (fhoFace.bValid()) { fhoFace.vFree(); }
FHOBJ fhoFamily(&(pPFF->pfhFamily)); if (fhoFamily.bValid()) { fhoFamily.vFree(); }
FHOBJ fhoUFI(&(pPFF->pfhUFI)); if (fhoUFI.bValid()) { fhoUFI.vFree(); }
// Free pfdg
if ( (pifi != NULL) && (pifi->jWinCharSet == SYMBOL_CHARSET) && (pfdg != NULL) && (pfdg->flAccel & GS_EXTENDED)) { VFREEMEM(pfdg); } else { if ((pfdg != NULL) && PPFNVALID(*ppdo,Free)) { ppdo->Free(pfdg, idfdg); } }
// Free pifi
if (pifi) { if (PPFNVALID(*ppdo,Free)) { ppdo->Free(pifi, idifi); } } } return bRet; }
/******************************Public*Routine******************************\
* BOOL PFFMEMOBJ::bAddEntry * * * * This function creates a new physical font entry object and adds it to the* * end of the table. The iFont parameter identifies the font within this * * file. The cjSize and pjMetrics identify a buffer containing face * * information including the IFI metrics and the mapping structures * * (defining the UNICODE->HGLYPH mapping). * * * * Returns FALSE if the function fails. * * * * History: * * 02-Jan-1991 -by- Gilman Wong [gilmanw] * * Wrote it. * \**************************************************************************/
BOOL PFFMEMOBJ::bAddEntry ( ULONG iFont, // index of the font (IFI or device)
FD_GLYPHSET *pfdg, // pointer to UNICODE->HGLYPH map
ULONG_PTR idfdg, // driver id for FD_GLYPHSET
PIFIMETRICS pifi, // pointer to IFIMETRICS
ULONG_PTR idifi, // driver id for IFIMETRICS
HANDLE hdc, // handle of DC if this is a remote font
PUNIVERSAL_FONT_ID pufi, // used when adding remote fonts
PEUDCLOAD pEudcLoadData // pointer to EUDCLOAD
) {
// Allocate memory for a new PFE
PFECOBJ pfeco(pPFF->pPFEC); PFEMEMOBJ pfemo(pfeco.GetPFE(iFont));
// Validate new object, hmgr logs error if needed
if (!pfemo.bValid()) return (FALSE);
// Initialize the new PFE
#ifdef FE_SB
BOOL bEUDC = ( pEudcLoadData != NULL ); PPFE *pppfeEUDC = ((bEUDC) ? pEudcLoadData->pppfeData : NULL);
if( !pfemo.bInit(pPFFGet(), iFont, pfdg, idfdg, pifi, idifi, bDeviceFonts(), pufi, bEUDC )) { return(FALSE); }
if( bEUDC ) { //
// This font file is loaded as EUDC font.
//
if( pEudcLoadData->LinkedFace == NULL ) { //
// No face name is specified.
//
switch( iFont ) { case 1: pppfeEUDC[PFE_NORMAL] = pfemo.ppfeGet(); pppfeEUDC[PFE_VERTICAL] = pppfeEUDC[PFE_NORMAL]; break;
case 2: //
// if more than one face name the second face must be an @face
//
if( pfemo.pwszFaceName()[0] == (WCHAR) '@' ) { pppfeEUDC[PFE_VERTICAL] = pfemo.ppfeGet();
#if DBG
if( gflEUDCDebug & (DEBUG_FONTLINK_LOAD|DEBUG_FONTLINK_INIT) ) { DbgPrint("EUDC font has vertical face %ws %x\n", pfemo.pwszFaceName(), pppfeEUDC[PFE_VERTICAL] ); } #endif
} else { WARNING("bAddEntryPFFMEMOBJ -- second face not a @face.\n"); } break;
default: WARNING("bAddEntryPFFMEMOBJ -- too many faces in EUDC font.\n"); } } else { if( iFont == 1 ) { //
// link first face as default, because this font file might not
// contains user's specified face name, but the user want to link
// this font file. I don't know which is better link it as default
// or fail link.
//
pppfeEUDC[PFE_NORMAL] = pfemo.ppfeGet(); pppfeEUDC[PFE_VERTICAL] = pppfeEUDC[PFE_NORMAL]; } else { ULONG iPfeOffset = PFE_NORMAL; PWSTR pwszEudcFace = pfemo.pwszFaceName();
//
// Is this a vertical face ?
//
if( pwszEudcFace[0] == (WCHAR) '@' ) { iPfeOffset = PFE_VERTICAL; }
//
// Is this a face that we want ?
//
if( pfemo.bCheckFamilyName(pEudcLoadData->LinkedFace,1) ) { //
// Yes....., keep it.
//
pppfeEUDC[iPfeOffset] = pfemo.ppfeGet();
//
// if this is a PFE for Normal face, also keep it for Vertical face.
// after this, this value might be over-written by CORRRCT vertical
// face's PFE.
//
// NOTE :
// This code assume Normal face come faster than Vertical face...
//
if( iPfeOffset == PFE_NORMAL ) pppfeEUDC[PFE_VERTICAL] = pfemo.ppfeGet(); } } }
// mark the FaceNameEUDC pfe list as NULL
pfemo.vSetLinkedFontEntry( NULL ); } else {
PWSZ pwszAlias = NULL; BOOL bIsFamilyNameAlias = FALSE; PFLENTRY pFlEntry = NULL;
// Here we see if there is an EUDC font for this family name.
pwszAlias = pfemo.pwszFamilyNameAlias(&bIsFamilyNameAlias);
pFlEntry = FindBaseFontEntry(pwszAlias);
if (!pFlEntry && bIsFamilyNameAlias) {
pwszAlias += (wcslen(pwszAlias) + 1);
if (bIsFamilyNameAlias) { pFlEntry = FindBaseFontEntry(pwszAlias); } }
if( pFlEntry != NULL ) { //
// set eudc list..
//
pfemo.vSetLinkedFontEntry( pFlEntry );
#if DBG
if( gflEUDCDebug & DEBUG_FACENAME_EUDC ) { PLIST_ENTRY p = pfemo.pGetLinkedFontList()->Flink;
DbgPrint("Found FaceName EUDC for %ws is ",pfemo.pwszFamilyName());
while( p != &(pFlEntry->linkedFontListHead) ) { PPFEDATA ppfeData = CONTAINING_RECORD(p,PFEDATA,linkedFontList); PFEOBJ pfeo( ppfeData->appfe[PFE_NORMAL] ); PFFOBJ pffo( pfeo.pPFF() );
DbgPrint(" %ws ",pffo.pwszPathname());
p = p->Flink; }
DbgPrint("\n"); } #endif
} else { // mark the FaceNameEUDC pfe as NULL
pfemo.vSetLinkedFontEntry( NULL ); }
} #endif
// Put PFE pointer into the PFF's table
((PFE **) (pPFF->aulData))[pPFF->cFonts++] = pfemo.ppfeGet();
return (TRUE); }
#if DBG
/******************************Public*Routine******************************\
* VOID PFFOBJ::vDump () * * Debugging code. * * History: * Thu 02-Apr-1992 12:10:28 by Kirk Olynyk [kirko] * DbgPrint supports %ws * * 25-Feb-1991 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
VOID PFFOBJ::vDump () { DbgPrint("\nContents of PFF, pPFF = 0x%lx\n", pPFFGet()); if (*(WCHAR *)pwszPathname()) { DbgPrint("Filename = %ws\n", pwszPathname()); } DbgPrint("flState = 0x%lx\n", pPFF->flState); DbgPrint("cLoaded = %ld\n", pPFF->cLoaded); DbgPrint("cNotEnum = %ld\n", pPFF->cNotEnum); DbgPrint("pPvtDataHead = 0x%lx\n", pPFF->pPvtDataHead); DbgPrint("cRFONT = %ld\n", pPFF->cRFONT); DbgPrint("hff = 0x%lx\n", pPFF->hff); DbgPrint("cFonts = %ld\n", pPFF->cFonts); DbgPrint("HPFE table\n"); for (ULONG i=0; i<pPFF->cFonts; i++) DbgPrint(" 0x%lx\n", ((PFE **) (pPFF->aulData))[i]); DbgPrint("\n"); } #endif
/******************************Public*Routine******************************\
* vCleanupFontFile * * Parses the PFFCLEANUP structure and calls the driver to release * its resources and to unload the font file. * * History: * 10-Mar-1993 -by- Gilman Wong [gilmanw] * Wrote it. \**************************************************************************/
VOID vCleanupFontFile(PFFCLEANUP *pPFFC) { // Create PDEV user object so we can call driver functions.
PDEVOBJ pdo(pPFFC->hdev);
//
// If font driver loaded font, call to unload font file.
//
if (pPFFC->hff != HFF_INVALID && pPFFC->pPFFClone == NULL) { BOOL bOK = pdo.UnloadFontFile( pPFFC->hff ); ASSERTGDI(bOK, "PFFOBJ::vCleanupFontFile(): DrvUnloadFontFile failed\n");
#if DBG
if(bOK == -1){ RIP("PFFOBJ::vCleanupFontFile(): DrvUnloadFontFile failed2\n"); } #endif
} }
/******************************Public*Routine******************************\
* pPvtDataMatch() * * * * Search for existing PvtData for the current process * * * * Return * * if found, return the address of the pPvtData block * * * * otherwise, return NULL * * * History: * * 11-Aug-1996 -by- Xudong Wu [TessieW] * * Wrote it. * \**************************************************************************/
PVTDATA *PFFOBJ::pPvtDataMatch() { PVTDATA *pPvtDataCur;
for (pPvtDataCur = pPvtDataHeadGet(); pPvtDataCur; pPvtDataCur = pPvtDataCur->pPvtDataNext) { if ((pPvtDataCur->fl & FRW_EMB_TID) && (pPvtDataCur->dwID == (DWORD) W32GetCurrentTID())) { break; }
if (pPvtDataCur->dwID == (DWORD) W32GetCurrentPID()) { break; }
// spooler has the right of using any fonts
if ((gpidSpool == (PW32PROCESS)W32GetCurrentProcess()) && (pPvtDataCur->fl & FR_PRINT_EMB_FONT)) break; }
return (pPvtDataCur); }
/******************************Public*Routine******************************\
* bAddPvtData(ULONG flEmbed) * * * * Add PvtData data block to the tail of pPvtDataHead link list * * * * Return FALSE if function fails * * * * History: * * 11-Aug-1996 -by- Xudong Wu [TessieW] * * Wrote it. * \**************************************************************************/
BOOL PFFOBJ::bAddPvtData(ULONG flEmbed) { PVTDATA *pPvtData;
// Search for the existing PvtData block for the current process
pPvtData = pPvtDataMatch();
// PvtData exists for the calling process
if (pPvtData) { if (flEmbed & (FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID)) { pPvtData->cNotEnum++; } else { pPvtData->cPrivate++; }
pPvtData->fl |= flEmbed & (FR_PRIVATE | FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID);
return TRUE; }
// no PvtData exists for the current process
else { if (pPvtData = (PVTDATA *) PALLOCMEM(sizeof(PVTDATA), 'pvtG')) { pPvtData->fl = flEmbed & (FR_PRIVATE | FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID);
// Embedded fonts can't be enumed, so we set cNotEnum to 1
if (flEmbed & (FR_NOT_ENUM | FRW_EMB_PID | FRW_EMB_TID)) { pPvtData->cPrivate = 0; pPvtData->cNotEnum = 1; } else { pPvtData->cPrivate = 1; pPvtData->cNotEnum = 0; } pPvtData->dwID = (flEmbed & FRW_EMB_TID) ? (DWORD)W32GetCurrentTID() : (DWORD)W32GetCurrentPID() ;
pPvtData->pPvtDataNext = pPFF->pPvtDataHead; pPFF->pPvtDataHead = pPvtData;
return TRUE; } else { WARNING("PFFOBJ::bAddPvtData(): memory allocation failed\n"); return FALSE; } } }
/******************************Public*Routine******************************\
* bRemovePvtData(PVTDATA *pPvtData) * * * * Rmove the PvtData data block from the pPvtDataHead link list * * * * Return FALSE if function fails * * * * History: * * 27-Set-1996 -by- Xudong Wu [TessieW] * * Wrote it. * \**************************************************************************/
BOOL PFFOBJ::bRemovePvtData(PVTDATA *pPvtData) { PVTDATA *pPrev, *pCur;
pPrev = pPvtDataHeadGet();
if (!pPrev) { WARNING("PFFOBJ::bRemovePvtData: try to remove PvtData block from NULL list\n"); return FALSE; }
// remove the PvtData block from the head of the list
if ( pPrev == pPvtData) { pPFF->pPvtDataHead = pPvtData->pPvtDataNext;
VFREEMEM(pPvtData); return TRUE; }
while (pCur = pPrev->pPvtDataNext) { if (pCur == pPvtData) { pPrev->pPvtDataNext = pPvtData->pPvtDataNext;
VFREEMEM(pPvtData); return TRUE; }
pPrev = pCur; }
return FALSE; }
|