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.
 
 
 
 
 
 

1358 lines
42 KiB

/******************************Module*Header*******************************\
* Module Name: enumgdi.cxx
*
* Enumeration routines.
* hefs
* Created: 28-Mar-1992 16:18:45
* Author: Gilman Wong [gilmanw]
*
* Copyright (c) 1992-199 Microsoft Corporation
*
\**************************************************************************/
#include "precomp.hxx"
// gaclrEnumColorTable
//
// Colors used for GreEnumPens and GreEnumBrushes. This color table is
// set up so that:
//
// - the first 2 entries are for monochrome devices
//
// - the first 8 entries are for 8-color devices
//
// - the first 16 are for 4 BPP color devices
//
// - the first 20 are for 8 BPP and up color devices
static COLORREF
gaclrEnumColorTable[] = { 0x00000000, // black
0x00ffffff, // white (monochrome)
0x000000ff, // red
0x0000ff00, // green
0x0000ffff, // yellow
0x00ff0000, // blue
0x00ff00ff, // magenta
0x00ffff00, // cyan (EGA hi-intensity)
0x00808080, // dark grey
0x00c0c0c0, // light grey
0x00000080, // red
0x00008000, // green
0x00008080, // yellow
0x00800000, // blue
0x00800080, // magenta
0x00808000, // cyan (EGA lo-intensity)
0x00c0dcc0, // money green
0x00f0c8a4, // cool blue
0x00f0fbff, // off white
0x00a4a0a0 // med grey (extra colors)
};
static ULONG gulEnumColorTableSize = sizeof(gaclrEnumColorTable) / sizeof(COLORREF);
#define ECT_1BPP 2 // use this many colors for 1 BPP
#define ECT_EGA 8 // use this many colors for EGA
#define ECT_4BPP 16 // use this many colors for 4 BPP
#define ECT_8BPP min(gulEnumColorTableSize, 256) // use this many colors for 8 BPP
#define ENUM_FILTER_NONE 0
#define ENUM_FILTER_TT 1
#define ENUM_FILTER_NONTT 2
// gaulEnumPenStyles
//
// Pen styles used for GreEnumPens.
static ULONG
gaulPenStyles[] = { PS_SOLID,
PS_DASH,
PS_DOT,
PS_DASHDOT,
PS_DASHDOTDOT
};
static ULONG gulPenStylesTableSize = sizeof(gaulPenStyles) / sizeof(ULONG);
// gaulEnumBrushStyles
//
// Brush hatch styles used for GreEnumBrushes.
ULONG
gaulHatchStyles[] = { HS_HORIZONTAL,
HS_VERTICAL,
HS_FDIAGONAL,
HS_BDIAGONAL,
HS_CROSS,
HS_DIAGCROSS
};
static ULONG gulHatchStylesTableSize = sizeof(gaulHatchStyles) / sizeof(ULONG);
/******************************Public*Routine******************************\
* NtGdiEnumObjects()
*
*
* Returns:
* Number of objects copied into the return buffer. If buffer is NULL,
* then the object capacity needed for the buffer is returned. If an
* error occurs, then ERROR is returned.
*
\**************************************************************************/
ULONG
APIENTRY
NtGdiEnumObjects(
HDC hdc,
int iObjectType,
ULONG cjBuf,
PVOID pvBuf
)
{
ULONG cRet = ERROR;
if ( (cjBuf == 0) == (pvBuf == (PVOID) NULL) )
{
// Create and validate DC user object.
DCOBJ dco(hdc);
if (dco.bValid())
{
PDEVOBJ pdo(dco.hdev());
// For color devices, we grab the colors out of the
// gaclrEnumColorTable color table. For better results, a
// driver should implement DrvEnumObj.
ULONG cclrDevice = pdo.GdiInfoNotDynamic()->ulNumColors;
ULONG cObjects;
//
// Determine the number of colors to grab out of the table.
//
if ( cclrDevice >= ECT_8BPP )
cclrDevice = ECT_8BPP;
else if ( cclrDevice >= ECT_4BPP )
cclrDevice = ECT_4BPP;
else if ( cclrDevice >= ECT_EGA )
cclrDevice = ECT_EGA;
else if ( cclrDevice >= ECT_1BPP )
cclrDevice = ECT_1BPP;
switch (iObjectType)
{
case OBJ_PEN:
cObjects = cjBuf / sizeof(LOGPEN);
cRet = cclrDevice * gulPenStylesTableSize;
break;
case OBJ_BRUSH:
cObjects = cjBuf / sizeof(LOGBRUSH);
cRet = cclrDevice * (gulHatchStylesTableSize + 1); // the "1" is the solid brush
break;
default:
WARNING("NtGdiEnumObjects(): bad object type\n");
return cRet;
}
//
// If the buffer is big enough, return the data
//
if (cObjects >= cRet)
{
__try
{
ProbeForWrite(pvBuf, cjBuf, sizeof(DWORD));
COLORREF *pclr;
COLORREF *pclrEnd = gaclrEnumColorTable + cclrDevice;
PULONG pulPenStyle;
PULONG pulPenStyleEnd = gaulPenStyles + gulPenStylesTableSize;
PULONG pulHatchStyle;
PULONG pulHatchStyleEnd = gaulHatchStyles + gulHatchStylesTableSize;
PLOGPEN plpBuf = ((PLOGPEN)pvBuf);
PLOGBRUSH plbBuf = ((PLOGBRUSH)pvBuf);
switch (iObjectType)
{
case OBJ_PEN:
//
// Fill buffer will LOGPENs of all styles, in all colors.
//
for (pulPenStyle = gaulPenStyles; pulPenStyle < pulPenStyleEnd; pulPenStyle += 1)
{
for (pclr = gaclrEnumColorTable;
pclr < pclrEnd;
pclr += 1)
{
// Fill in the LOGPEN fields.
plpBuf->lopnWidth.x = 0; // nominal width
plpBuf->lopnWidth.y = 0; // ignored
plpBuf->lopnStyle = (UINT) *pulPenStyle;
plpBuf->lopnColor = *pclr;
// Next LOGPEN.
plpBuf += 1;
}
}
break;
case OBJ_BRUSH:
//
// Fill buffer will LOGBRUSHs of BS_SOLID style, in all colors.
//
for (pclr = gaclrEnumColorTable; pclr < pclrEnd; pclr += 1)
{
// Fill in the LOGBRUSH fields.
plbBuf->lbStyle = BS_SOLID;
plbBuf->lbColor = *pclr;
plbBuf->lbHatch = 0;
// Next LOGBRUSH.
plbBuf += 1;
}
//
// Now fill the buffer with LOGBRUSHs of BS_HATCH, in all
// hatch styles and colors.
//
for (pulHatchStyle = gaulHatchStyles; pulHatchStyle < pulHatchStyleEnd; pulHatchStyle += 1)
{
for (pclr = gaclrEnumColorTable;
pclr < pclrEnd;
pclr += 1)
{
// Fill in the LOGBRUSH fields.
plbBuf->lbStyle = BS_HATCHED;
plbBuf->lbColor = *pclr;
plbBuf->lbHatch = *pulHatchStyle;
// Next LOGBRUSH.
plbBuf += 1;
}
}
break;
default:
WARNING("NtGdiEnumObjects(): bad object type 2\n");
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
// SetLastError(GetExceptionCode());
cRet = ERROR;
}
}
else if (cObjects)
{
//
// If the buffer is not large enough (and it is not zero)
// then return an error,
//
cRet = ERROR;
}
}
}
return cRet;
}
BOOL bScanFamily(
FHOBJ *pfho1, ULONG ulFilter1,
FHOBJ *pfho2, ULONG ulFilter2,
FHOBJ *pfho3, ULONG ulFilter3,
EFSOBJ *pefsmo,
ULONG iEnumType,
EFFILTER_INFO *peffi,
PWSZ pwszName
);
BOOL bScanFamilyAndFace(
FHOBJ *pfhoEngFamily,
FHOBJ *pfhoEngFace,
FHOBJ *pfhoDevFamily,
FHOBJ *pfhoDevFace,
EFSOBJ *pefsmo,
ULONG iEnumType,
EFFILTER_INFO *peffi,
PWSZ pwszName
);
#define EFS_DEFAULT 32
/******************************Public*Routine******************************\
* HEFS hefsEngineOnly
*
* Enumerates engine fonts only.
*
* PFEs are accumulated in an EFSTATE (EnumFont State) object. If a non-NULL
* pwszName is specified, then only fonts that match the given name are added
* to the EFS. If a NULL pwszFace is specified, then one font of each name is
* added to the EFS.
*
* If any of the filtering flags in the EFFILTER_INFO structure are specified,
* then PFEs are tested in additional filtering stages before they are added
* to the EFS.
*
* The EFS is allocated by this function. It is the responsibility of the
* caller to ensure that the EFS is eventually freed.
*
* Returns:
* Handle to allocated EFS object, HEFS_INVALID if an error occurs.
*
* History:
*
* 19-Aug-1996 -by- Xudong Wu [TessieW]
* Add enumeration for Private PFT.
*
* 07-Aug-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
HEFS hefsEngineOnly (
PWSZ pwszName, // enumerate this font family
ULONG lfCharSet,
ULONG iEnumType, // TRUE if processing EnumFonts()
EFFILTER_INFO *peffi, // filtering information
PUBLIC_PFTOBJ &pfto, // public PFT user object
PUBLIC_PFTOBJ &pftop, // private PFT user object
ULONG *pulCount
)
{
// ulEnumFontOpen, the caller, has already grabbed the ghsemPublicPFT,
// so the font hash tables are stable.
// Create and validate FHOBJ for engine (family list).
FHOBJ fhoEngineFamily(&pfto.pPFT->pfhFamily);
if ( !fhoEngineFamily.bValid() )
{
WARNING("gdisrv!hefsEnumFontsState(): cannot lock engine font hash (family)\n");
return HEFS_INVALID;
}
// Create and validate FHOBJ for engine (face list).
FHOBJ fhoEngineFace(&pfto.pPFT->pfhFace);
if ( !fhoEngineFace.bValid() )
{
WARNING("gdisrv!hefsEnumFontsState(): cannot lock engine font hash (face)\n");
return HEFS_INVALID;
}
// For NULL pwszName, an example of each family needs to be enumerated. In
// other words, we scan ACROSS the names.
if (pwszName == (PWSZ) NULL)
{
// Allocate a new EFSTATE for the enumeration. Use total number
// of lists as a hint for the initial size. This is reasonable
// since we will probably enumerate back all of the list heads.
EFSMEMOBJ efsmo(fhoEngineFamily.cLists(), iEnumType);
if ( !efsmo.bValid() )
{
WARNING("win32k!GreEnumFontOpen(): could not allocate enumeration state\n");
return HEFS_INVALID;
}
// Enumerate engine fonts in public PFT.
// For Win3.1 compatability Non-TT,TT.
if ( !bScanFamily(&fhoEngineFamily, ENUM_FILTER_NONTT, &fhoEngineFamily, ENUM_FILTER_TT,
(FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) )
{
return HEFS_INVALID;
}
// Scan through private PFT if gpPFTPrivate!=NULL
if (pftop.pPFT != NULL)
{
FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
if ( !fhoPrivateFamily.bValid() )
{
WARNING("win32k!hefsEngineOnly(): cannot lock private font hash (family)\n");
return HEFS_INVALID;
}
if ( !bScanFamily(&fhoPrivateFamily, ENUM_FILTER_NONTT, &fhoPrivateFamily, ENUM_FILTER_TT,
(FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) )
{
return HEFS_INVALID;
}
}
*pulCount = efsmo.cjEfdwTotal();
// Keep the EFSTATE around.
efsmo.vKeepIt();
// Return the EFSOBJ handle.
return efsmo.hefs();
}
// For non-NULL pwszName, all the fonts of a particular family are enumerated.
// In other words, we scan DOWN a name.
else
{
// Allocate a new EFSTATE. Use a default size.
EFSMEMOBJ efsmo(EFS_DEFAULT, iEnumType);
if ( !efsmo.bValid() )
{
WARNING("gdisrv!hefsEnumFontsState(): could not allocate enumeration state\n");
return HEFS_INVALID;
}
if (!bScanFamilyAndFace(&fhoEngineFamily, &fhoEngineFace, (FHOBJ*)NULL, (FHOBJ*)NULL,
&efsmo, iEnumType, peffi, pwszName))
{
return HEFS_INVALID;
}
// Scan through the Privat PFT with family name lists.
if (pftop.pPFT != NULL)
{
FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
FHOBJ fhoPrivateFace(&pftop.pPFT->pfhFace);
if (!fhoPrivateFamily.bValid() || !fhoPrivateFace.bValid())
{
WARNING("win32k!hefsEngineOnly(): cannot lock private font hash\n");
return HEFS_INVALID;
}
if (!bScanFamilyAndFace(&fhoPrivateFamily, &fhoPrivateFace, (FHOBJ*)NULL, (FHOBJ*)NULL,
&efsmo, iEnumType, peffi, pwszName))
{
return HEFS_INVALID;
}
}
// Repeat with the alternate facename (if any). Since a LOGFONT can
// map via the alternate facenames, it is appropriate to enumerate the
// alternate facename fonts as if they really had this face name.
PFONTSUB pfsub = pfsubAlternateFacename(pwszName);
PWSZ pwszAlt = pfsub ? (PWSZ)pfsub->fcsAltFace.awch : NULL;
if ( pwszAlt != (PWSZ) NULL )
{
// Enumerate engine fonts.
if (!bScanFamilyAndFace(&fhoEngineFamily, &fhoEngineFace, (FHOBJ*)NULL, (FHOBJ*)NULL,
&efsmo, iEnumType, peffi, pwszAlt))
{
return HEFS_INVALID;
}
// Enumerate the private fonts.
if (pftop.pPFT != NULL)
{
FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
FHOBJ fhoPrivateFace(&pftop.pPFT->pfhFace);
if (!fhoPrivateFamily.bValid() || !fhoPrivateFace.bValid())
{
WARNING("win32k!hefsEngineOnly(): cannot lock private font hash\n");
return HEFS_INVALID;
}
if (!bScanFamilyAndFace(&fhoPrivateFamily, &fhoPrivateFace, (FHOBJ*)NULL, (FHOBJ*)NULL,
&efsmo, iEnumType, peffi, pwszAlt))
{
return HEFS_INVALID;
}
}
// Inform the enumeration state that an alternate name was used.
efsmo.vUsedAltName(pfsub);
}
*pulCount = efsmo.cjEfdwTotal();
// Keep the EFSTATE around.
efsmo.vKeepIt();
// Return the EFSOBJ handle.
return efsmo.hefs();
}
}
/******************************Public*Routine******************************\
* HEFS hefsDeviceAndEngine
*
* Enumerates device and engine fonts.
*
* PFEs are accumulated in an EFSTATE (EnumFont State) object. If a non-NULL
* pwszName is specified, then only fonts that match the given name are added
* to the EFS. If a NULL pwszFace is specified, then one font of each name is
* added to the EFS.
*
* If any of the filtering flags in the EFFILTER_INFO structure are specified,
* then PFEs are tested in additional filtering stages before they are added
* to the EFS.
*
* The EFS is allocated by this function. It is the responsibility of the
* caller to ensure that the EFS is eventually freed.
*
* Returns:
* Handle to allocated EFS object, HEFS_INVALID if an error occurs.
*
*
* History:
*
* 18-Sept-1996 -by- Xudong Wu [TessieW]
* Add the enumeration for private PFT.
*
* 07-Aug-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
HEFS hefsDeviceAndEngine (
PWSZ pwszName, // enumerate this font family
ULONG lfCharSet,
ULONG iEnumType,
EFFILTER_INFO *peffi, // filtering information
PUBLIC_PFTOBJ &pfto, // public PFT user object
PUBLIC_PFTOBJ &pftop, // private PFT user object
PFFOBJ &pffoDevice, // PFFOBJ for device fonts
PDEVOBJ &pdo, // PDEVOBJ for device
ULONG *pulCount
)
{
// ulEnumFontOpen, the caller, has already grabbed the ghsemPublicPFT,
// so the font hash tables are stable.
// Create and validate FHOBJ for device (family list).
FHOBJ fhoDeviceFamily(&pffoDevice.pPFF->pfhFamily);
if ( !fhoDeviceFamily.bValid() )
{
WARNING("gdisrv!hefsEnumFontsState(): cannot lock device font hash (family)\n");
return HEFS_INVALID;
}
// Create and validate FHOBJ for engine (family list).
FHOBJ fhoEngineFamily(&pfto.pPFT->pfhFamily);
if ( !fhoEngineFamily.bValid() )
{
WARNING("gdisrv!hefsEnumFontsState(): cannot lock engine font hash (family)\n");
return HEFS_INVALID;
}
// Create and validate FHOBJ for device (face list).
FHOBJ fhoDeviceFace(&pffoDevice.pPFF->pfhFace);
if ( !fhoDeviceFace.bValid() )
{
WARNING("gdisrv!hefsEnumFontsState(): cannot lock device font hash (face)\n");
return HEFS_INVALID;
}
// Create and validate FHOBJ for engine (face list).
FHOBJ fhoEngineFace(&pfto.pPFT->pfhFace);
if ( !fhoEngineFace.bValid() )
{
WARNING("gdisrv!hefsEnumFontsState(): cannot lock engine font hash (face)\n");
return HEFS_INVALID;
}
// For NULL pwszName, an example of each family needs to be enumerated. In
// other words, we scan ACROSS the names.
if (pwszName == (PWSZ) NULL)
{
// Allocate a new EFSTATE for the enumeration. Use total number of lists
// as a hint for the initial size. This is reasonable since we will probably
// enumerate back all of the list heads.
ASSERTGDI(peffi->bNonTrueTypeFilter == FALSE, "ERROR not FALSE");
EFSMEMOBJ efsmo(fhoDeviceFamily.cLists() + fhoEngineFamily.cLists(), iEnumType);
if ( !efsmo.bValid() )
{
WARNING("gdisrv!hefsEnumFontsState(): could not allocate enumeration state\n");
return HEFS_INVALID;
}
//
// Enumerate device and engine fonts.
//
if (pdo.flTextCaps() & TC_RA_ABLE)
{
//
// For Win3.1 compatability Enum Device,Non-TT,TT
// This is for Displays and PaintJets under 3.1
//
if ( !bScanFamily(&fhoDeviceFamily, ENUM_FILTER_NONE, &fhoEngineFamily, ENUM_FILTER_NONTT,
&fhoEngineFamily, ENUM_FILTER_TT, &efsmo, iEnumType, peffi, NULL) )
{
return HEFS_INVALID;
}
// scan through private PFT if gpPFTPrivate!=NULL
if (pftop.pPFT != NULL)
{
FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
if ( !fhoPrivateFamily.bValid() )
{
WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash (family)\n");
return HEFS_INVALID;
}
if ( !bScanFamily(&fhoPrivateFamily, ENUM_FILTER_NONTT, &fhoPrivateFamily, ENUM_FILTER_TT,
(FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) )
{
return HEFS_INVALID;
}
}
}
#if 0
// If we ever need this, this is how Postscript should do it. We would
// need to call the driver at Enable Printer time to see if it's Postscript
// and set a bit for quick checking here.
else if (pdo.bPostScript())
{
//
// For Win3.1 compatability Enum TT,Device,Non-TT,
//
if (!bScanFamily(&fhoEngineFamily, ENUM_FILTER_TT, &fhoDeviceFamily, ENUM_FILTER_NONE,
&fhoEngineFamily, ENUM_FILTER_NONTT, &efsmo, iEnumType, peffi, NULL) )
{
return HEFS_INVALID;
}
// scan throught private PFT if gpPFTPrivate!=NULL
if (pftop.pPFT != NULL)
{
FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
if ( !fhoPrivateFamily.bValid() )
{
WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash (family)\n");
return HEFS_INVALID;
}
if ( !bScanFamily(&fhoPrivateFamily, ENUM_FILTER_TT, &fhoPrivateFamily, ENUM_FILTER_NONTT,
(FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) )
{
return HEFS_INVALID;
}
}
}
#endif
else
{
//
// Win3.1 compatability.
// Enum Device, TT, Non-TT.
//
if ( !bScanFamily(&fhoDeviceFamily, ENUM_FILTER_NONE, &fhoEngineFamily, ENUM_FILTER_TT,
&fhoEngineFamily, ENUM_FILTER_NONTT, &efsmo, iEnumType, peffi, NULL) )
{
return HEFS_INVALID;
}
if (pftop.pPFT != NULL)
{
FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
if ( !fhoPrivateFamily.bValid() )
{
WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash (family)\n");
return HEFS_INVALID;
}
if ( !bScanFamily(&fhoPrivateFamily, ENUM_FILTER_TT, &fhoPrivateFamily, ENUM_FILTER_NONTT,
(FHOBJ*)NULL, 0, &efsmo, iEnumType, peffi, NULL) )
{
return HEFS_INVALID;
}
}
}
*pulCount = efsmo.cjEfdwTotal();
// Keep the EFSTATE around.
efsmo.vKeepIt();
// Return the EFSOBJ handle.
return efsmo.hefs();
}
else
{
// For non-NULL pwszName, all the fonts of a particular family are enumerated.
// In other words, we scan DOWN a name.
// Allocate a new EFSTATE. Use a default size.
EFSMEMOBJ efsmo(EFS_DEFAULT, iEnumType);
if ( !efsmo.bValid() )
{
WARNING("gdisrv!hefsEnumFontsState(): could not allocate enumeration state\n");
return HEFS_INVALID;
}
// Enumerate device and engine fonts.
if (!bScanFamilyAndFace(&fhoEngineFamily, &fhoEngineFace, &fhoDeviceFamily, &fhoDeviceFace,
&efsmo, iEnumType, peffi, pwszName))
{
return HEFS_INVALID;
}
// Enumerate the private fonts if any
if (pftop.pPFT != NULL)
{
FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
FHOBJ fhoPrivateFace(&pftop.pPFT->pfhFace);
if (!fhoPrivateFamily.bValid() || !fhoPrivateFace.bValid())
{
WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash\n");
return HEFS_INVALID;
}
if (!bScanFamilyAndFace(&fhoPrivateFamily, &fhoPrivateFace, (FHOBJ*)NULL, (FHOBJ*)NULL,
&efsmo, iEnumType, peffi, pwszName))
{
return HEFS_INVALID;
}
}
// Repeat with the alternate facename (if any). Since a LOGFONT can
// map via the alternate facenames, it is appropriate to enumerate the
// alternate facename fonts as if they really had this face name.
//
// However, to be Win 3.1 compatible, we will NOT do this if the device
// is a non-display device.
//
// It appears that Windows 95 no longer does this. Additionally, we need
// to enumerate manufactured EE names (i.e. Arial Cyr, Arial Grk, etc)
// on printer DC's as well now. If we don't we break Word Perfect 94 a 16 bit
// winstone application.
//
//
// if ( pdo.bDisplayPDEV() )
{
PFONTSUB pfsub = pfsubAlternateFacename(pwszName);
PWSZ pwszAlt = pfsub ? (PWSZ)pfsub->fcsAltFace.awch : NULL;
if ( pwszAlt != (PWSZ) NULL )
{
// Enumerate device and engine fonts.
if (!bScanFamilyAndFace(&fhoEngineFamily, &fhoEngineFace, &fhoDeviceFamily, &fhoDeviceFace,
&efsmo, iEnumType, peffi, pwszAlt))
{
return HEFS_INVALID;
}
// Enumerate private fonts if any
if (pftop.pPFT != NULL)
{
FHOBJ fhoPrivateFamily(&pftop.pPFT->pfhFamily);
FHOBJ fhoPrivateFace(&pftop.pPFT->pfhFace);
if (!fhoPrivateFamily.bValid() || !fhoPrivateFace.bValid())
{
WARNING("win32k!hefsDeviceAndEngine(): cannot lock private font hash\n");
return HEFS_INVALID;
}
if (!bScanFamilyAndFace(&fhoPrivateFamily, &fhoPrivateFace, (FHOBJ*)NULL, (FHOBJ*)NULL,
&efsmo, iEnumType, peffi, pwszAlt))
{
return HEFS_INVALID;
}
}
// Inform the enumeration state that an alternate name was used.
efsmo.vUsedAltName(pfsub);
}
}
*pulCount = efsmo.cjEfdwTotal();
// Keep the EFSTATE around.
efsmo.vKeepIt();
// Return the EFSOBJ handle.
return efsmo.hefs();
}
}
/******************************Public*Routine******************************\
* ULONG ulEnumFontOpen
*
* First phase of the enumeration. Fonts from the engine and device are
* chosen and saved in a EFSTATE (font enumeration state) object. A handle
* to this object is passed back. The caller can use this handle to
* initiate the second pass in which the data is sent back over the client
* server interface in chunks.
*
* This function is also responsible for determining what types of filters
* will be applied in choosing fonts for the enumeration. Filters which
* are controllable are:
*
* TrueType filtering non-TrueType fonts are discarded
*
* Raster filering raster fonts are discarded
*
* Aspect ratio filtering fonts not matching resolution are discarded
*
* Returns:
* EFS handle (as a ULONG) if successful, HEFS_INVALID (0) otherwise.
*
* Note:
* The function may still return valid HEFS even if the EFSTATE is empty.
*
* History:
* 08-Aug-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
ULONG_PTR GreEnumFontOpen (
HDC hdc, // device to enumerate on
ULONG iEnumType, // EnumFonts, EnumFontFamilies or EnumFontFamiliesEx
FLONG flWin31Compat, // Win 3.1 compatibility flags
ULONG cwchMax, // maximum name length (for paranoid CSR code)
PWSZ pwszName, // font name to enumerate
ULONG lfCharSet,
ULONG *pulCount
)
{
DONTUSE(cwchMax);
HEFS hefsRet = HEFS_INVALID;
//
// Create and validate user object for DC.
//
DCOBJ dco(hdc);
if(!dco.bValid())
{
WARNING("gdisrv!ulEnumFontOpen(): cannot access DC\n");
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
return ((ULONG_PTR) hefsRet);
}
//
// Get PDEV user object. We also need to make
// sure that we have loaded device fonts before we go off to the font mapper.
// This must be done before the semaphore is locked.
//
PDEVOBJ pdo(dco.hdev());
ASSERTGDI (
pdo.bValid(),
"gdisrv!ulEnumFontOpen(): cannot access PDEV\n");
if (!pdo.bGotFonts())
pdo.bGetDeviceFonts();
// Stabilize public PFT.
SEMOBJ so(ghsemPublicPFT);
// Compute font enumeration filter info.
EFFILTER_INFO effi;
effi.lfCharSetFilter = lfCharSet;
effi.bNonTrueTypeFilter = FALSE;
//
// If not raster capable, then use raster font filtering.
//
//
// If it weren't hacked, we might be able to get this info
// from GetDeviceCaps(). As it is, we will assume only
// plotters are non-raster capable.
//
effi.bRasterFilter = (pdo.ulTechnology() == DT_PLOTTER);
effi.bEngineFilter = (pdo.ulTechnology() == DT_CHARSTREAM);
//
// Aspect ratio filter (use device's logical x and y resolutions).
//
// Note: [Windows 3.1 compatiblity] Aspect ratio filtering is turned ON for
// non-display devices. This is because most printers in Win 3.1
// do aspect ratio filtering. And since the Win 3.1 DDI gives
// enumeration to the drivers, display bitmap fonts usually are not
// enumerated on these devices. The NT DDI, however, gives the graphics
// engine control over enumeration. So we need to provide this
// compatibility here. Hopefully, all devices in Win3.1 do this
// filtering, because we do now.
//
// Note that we check the PDEV directly rather than the DC because
// DCOBJ::bDisplay() is not TRUE for display ICs (just display DCs
// which are DCTYPE_DIRECT).
//
effi.bAspectFilter = (BOOL) ( (dco.pdc->flFontMapper() & ASPECT_FILTERING)
|| !pdo.bDisplayPDEV() );
effi.ptlDeviceAspect.x = pdo.ulLogPixelsX();
effi.ptlDeviceAspect.y = pdo.ulLogPixelsY();
//
// If set for TrueType only, use TrueType filtering.
//
effi.bTrueTypeFilter = ((gulFontInformation & FE_FILTER_TRUETYPE) != 0);
//
// Set the Win3.1 compatibility flag.
//
effi.bTrueTypeDupeFilter = (BOOL) (flWin31Compat & GACF_TTIGNORERASTERDUPE);
// assume failure
hefsRet = 0;
{
// Find the device PFF
DEVICE_PFTOBJ pftoDevice;
PFF *pPFF;
if (pPFF = pftoDevice.pPFFGet(dco.hdev()))
{
PFFOBJ pffoDev(pPFF);
if (pffoDev.bValid())
{
PUBLIC_PFTOBJ pftoPublic;
PUBLIC_PFTOBJ pftoPrivate(gpPFTPrivate);
hefsRet =
hefsDeviceAndEngine(
pwszName
, lfCharSet
, iEnumType
, &effi
, pftoPublic
, pftoPrivate
, pffoDev
, pdo
, pulCount
);
}
else
{
WARNING("ulEnumFontOpen: invalid pffoDev\n");
}
}
}
if (!hefsRet)
{
PUBLIC_PFTOBJ pftoPublic;
PUBLIC_PFTOBJ pftoPrivate(gpPFTPrivate);
// If no device font PFFOBJ was found, do enumeration without a PFFOBJ.
// pulls all the fonts into an enumeration state.
hefsRet = hefsEngineOnly(pwszName,
lfCharSet,
iEnumType,
&effi,
pftoPublic,
pftoPrivate,
pulCount);
}
return ((ULONG_PTR) hefsRet);
}
/******************************Public*Routine******************************\
* BOOL bEnumFontChunk
*
* Second phase of the enumeration. HPFEs are pulled out of the enumeration
* state one-by-one, converted into an ENUMFONTDATA structure, and put into
* the return buffer. The size of the return buffer is determined by the
* client side and determines the granularity of the "chunking".
*
* This function signals the client side that the enumeration data has been
* exhausted by returning FALSE. Note that it is possible that in the pass
* pass through here that the EFSTATE may already be empty. The caller must
* check both the function return value and the pcefdw value.
*
* Note:
* Caller should set *pcefd to the capacity of the pefp buffer.
* Upon return, iEnumType will set pefb.cefp to the number of
* ENUMFONTDATA structures copied into the pefb.aefd array.
*
* Also, pefdw is user memory, which might be asynchronously changed
* at any time. So, we cannot trust any values read from that buffer.
*
* Returns:
* TRUE if there are more to go, FALSE otherwise,
*
* History:
* 08-Aug-1992 -by- Gilman Wong [gilmanw]
* Wrote it.
\**************************************************************************/
BOOL bEnumFontChunk(
HDC hdc, // device to enumerate on
ULONG_PTR idEnum,
COUNT cjEfdwTotal, // (in) capacity of buffer
COUNT *pcjEfdw, // (out) number of ENUMFONTDATAs returned
PENUMFONTDATAW pefdw // return buffer
)
{
// Initialize position in buffer in which to copy data
PENUMFONTDATAW pefdwCur = pefdw;
*pcjEfdw = 0;
// Validate DC and EnumFontState. If either fail lock bug out.
DCOBJ dco(hdc);
EFSOBJ efso((HEFS) idEnum);
if ((!efso.bValid()) || (!dco.bValid()))
{
WARNING("gdisrv!bEnumFontChunk(): bad HEFS or DC handle\n");
return FALSE;
}
// since as of 4.0 we do not go through this a chunk at the time
// we must have
if (cjEfdwTotal != efso.cjEfdwTotal())
{
WARNING("gdisrv!bEnumFontChunk(): efso.cjEfdwTotal() problem\n");
return FALSE;
}
ASSERTGDI(cjEfdwTotal >= efso.cefe() * CJ_EFDW0,
"cjEfdwTotal NOT BIG enough \n");
// Counter to track number of ENUMFONTDATAW structures copied into buffer.
COUNT cjEfdwCopied = 0;
EFENTRY *pefe;
// Before we access PFEs, grab the ghsemPublicPFT so no one can delete
// PFE while we are in the loop (note that PFEs can get deleted
// once we are outside of this--like between chunks!).
SEMOBJ so(ghsemPublicPFT);
// In each font file, try each font face
// We are sure that we will not overwrite the buffer because
// the size of buffer is big enough to take all the enumfont data.
while((pefe = efso.pefeEnumNext()))
{
// Create a PFE Collect user object. We're using real handle instead of
// pointers because someone may have deleted by the time we get
// around to enumerating.
// Get the PFE through PFE Collect object.
HPFECOBJ pfeco(pefe->hpfec);
PFEOBJ pfeo(pfeco.GetPFE(pefe->iFont));
SIZE_T cjEfdwCur = 0;
// Validate user object and copy data into buffer. Because PFE
// may have been deleted between chunks, we need to check validity.
PWSZ pwszFamilyOverride = NULL;
BOOL bCharSetOverride = FALSE;
ULONG lfCharSetOverride = DEFAULT_CHARSET;
if (efso.pwszFamilyOverride())
{
pwszFamilyOverride = efso.pwszFamilyOverride();
if (pefe->fjOverride & FJ_CHARSETOVERRIDE)
{
bCharSetOverride = TRUE;
lfCharSetOverride = pefe->jCharSetOverride;
}
else
{
bCharSetOverride = efso.bCharSetOverride();
lfCharSetOverride = (ULONG)efso.jCharSetOverride();
}
}
else
{
if (pefe->fjOverride & FJ_FAMILYOVERRIDE)
{
pwszFamilyOverride = gpfsTable[pefe->iOverride].awchOriginal;
}
if (pefe->fjOverride & FJ_CHARSETOVERRIDE)
{
bCharSetOverride = TRUE;
lfCharSetOverride = pefe->jCharSetOverride;
}
}
if
(
pfeo.bValid() &&
(cjEfdwCur = cjCopyFontDataW(
dco,
pefdwCur,
pfeo,
pefe->efsty,
pwszFamilyOverride,
lfCharSetOverride,
bCharSetOverride,
efso.iEnumType()
))
)
{
cjEfdwCopied += (ULONG) cjEfdwCur;
pefdwCur = (ENUMFONTDATAW *)((BYTE*)pefdwCur + cjEfdwCur);
}
}
*pcjEfdw = cjEfdwCopied;
// we are done: pefe has to be zero:
ASSERTGDI(!pefe, "not all fonts are enumerated yet\n");
ASSERTGDI(cjEfdwCopied <= cjEfdwTotal, "cjEfdwCopied > cjEfdwTotal\n");
// true means success, it used to mean that there are more fonts to come for
// enumeration. Now, we do not do "chunking" any more. Assert above makes sure
// that this is the case [bodind]
return TRUE;
}
/*************************Public*Routine********************************\
* BOOL bScanTheList()
*
* Scan through the font hash table using the given filter mode
*
* History:
*
* 07-Nov-1996 -by- Xudong Wu [TessieW]
* Wrote it.
*
************************************************************************/
BOOL bScanTheList(
FHOBJ *pfho,
ULONG ulFilter,
EFSOBJ *pefsmo,
ULONG iEnumType,
EFFILTER_INFO *peffi,
PWSZ pwszName
)
{
BOOL bRet;
if (pwszName)
{
bRet = pfho->bScanLists(pefsmo, pwszName, iEnumType, peffi);
}
else
{
BOOL bTempFilter;
if (ulFilter == ENUM_FILTER_TT)
{
bTempFilter = peffi->bTrueTypeFilter;
peffi->bTrueTypeFilter = TRUE;
}
else if (ulFilter == ENUM_FILTER_NONTT)
{
peffi->bNonTrueTypeFilter = TRUE;
}
bRet = pfho->bScanLists(pefsmo, iEnumType, peffi);
if (ulFilter == ENUM_FILTER_TT)
{
peffi->bTrueTypeFilter = bTempFilter;
}
else if (ulFilter == ENUM_FILTER_NONTT)
{
peffi->bNonTrueTypeFilter = FALSE;
}
}
return bRet;
}
/*************************Public*Routine********************************\
* BOOL bScanFamily()
*
* Scan through the family font hash table in the different filter
* order given by the input flag.
*
* History:
*
* 23-Oct-1996 -by- Xudong Wu [TessieW]
* Wrote it.
*
************************************************************************/
BOOL bScanFamily(
FHOBJ *pfho1, ULONG ulFilter1,
FHOBJ *pfho2, ULONG ulFilter2,
FHOBJ *pfho3, ULONG ulFilter3,
EFSOBJ *pefsmo,
ULONG iEnumType,
EFFILTER_INFO *peffi,
PWSZ pwszName
)
{
return
(
(!pfho1 || bScanTheList(pfho1, ulFilter1, pefsmo, iEnumType, peffi, pwszName))
&&
(!pfho2 || bScanTheList(pfho2, ulFilter2, pefsmo, iEnumType, peffi, pwszName))
&&
(!pfho3 || bScanTheList(pfho3, ulFilter3, pefsmo, iEnumType, peffi, pwszName))
);
}
/*************************Public*Routine********************************\
* BOOL bScanFamilyAndFace()
*
* Frist scan through the family font hash table. If no match is found,
* scan through the face font hash table.
*
* History:
*
* 23-Oct-1996 -by- Xudong Wu [TessieW]
* Wrote it.
*
************************************************************************/
BOOL bScanFamilyAndFace(
FHOBJ *pfhoEngFamily,
FHOBJ *pfhoEngFace,
FHOBJ *pfhoDevFamily,
FHOBJ *pfhoDevFace,
EFSOBJ *pefsmo,
ULONG iEnumType,
EFFILTER_INFO *peffi,
PWSZ pwszName
)
{
BOOL bRet = FALSE;
if (bScanFamily(pfhoDevFamily, ENUM_FILTER_NONE,
pfhoEngFamily, ENUM_FILTER_NONE,
(FHOBJ *) NULL,
0, pefsmo, iEnumType, peffi, pwszName))
{
// If list is empty, try the face name lists, else we are done
if (pefsmo->bEmpty() )
{
bRet = bScanFamily(pfhoDevFace, ENUM_FILTER_NONE,
pfhoEngFace, ENUM_FILTER_NONE,
(FHOBJ*) NULL,
0, pefsmo, iEnumType, peffi, pwszName);
#if DBG
if (!bRet)
WARNING("win32k!bScanFamilyAndFace(): scan face failed\n");
#endif
}
else
{
bRet = TRUE;
}
}
#if DBG
else
{
WARNING("win32k!bScanFamilyAndFace(): scan family failed\n");
}
#endif
return bRet;
}