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.
 
 
 
 
 
 

776 lines
24 KiB

/***********************************************************************************
* Module Name: fntassoc.cxx
*
* Font association routines.
*
* History
*
* 4-8-96 Gerrit van Wingerden Moved code from flinkgdi.cxx
*
* Copyright (c) 1996-1999 Microsoft Corporation
**********************************************************************************/
#include "precomp.hxx"
#ifdef FE_SB
#define FONT_ASSOCIATION_CHARSET_KEY \
L"FontAssoc\\Associated CharSet"
#define FONT_ASSOCIATION_DEFAULT_KEY \
L"FontAssoc\\Associated DefaultFonts"
#define FONT_ASSOCIATION_FONTS_KEY \
L"FontAssoc\\Associated Fonts"
// Font Association configuration value
UINT fFontAssocStatus = 0x0;
//
// Fontfile path for AssocSystemFont in
// KEY : HKL\\SYSTEM\\CurrentControlSet\\Control\\FontAssoc\\Associated DefaultFonts
// VALUE : AssocSystemFont
//
// This font is loaded at system initialization stage. and will be used to provide
// DBCS glyphs for System/Terminal/FixedSys/... This font should have all glyphs that
// will be used on current system locale
//
// This hehavior is described in ...
// "Font Association for Far East implementation for Windows 95"
// Revision : 1.02
// Author : WJPark,ShusukeU.
//
// Holds the path of the font the font used to provide glyphs to system,terminal,
// and fixedsys fonts.
WCHAR gawcSystemDBCSFontPath[MAX_PATH];
// Identifies the facename to use for DBCS glyphs. This value comes out of the
// "FontPackage" value in AssociatedDefaultFonts key
static WCHAR gawcSystemDBCSFontFaceName[LF_FACESIZE+1];
// Holds the pfe's (vertical and non-vertical) for the system DBCS font face name
PFE *gappfeSystemDBCS[2] = { PPFENULL , PPFENULL };
// set to TRUE if SystemDBCS font is enabled.
BOOL gbSystemDBCSFontEnabled = FALSE;
//
// Font association default link initialization value.
//
// This value never be TRUE, if FontAssociation features are disabled.
// And this value will be TRUE, if we suceed to read "Associated DefaultFonts"
// key and fill up FontAssocDefaultTable.
//
BOOL bReadyToInitializeFontAssocDefault = FALSE;
//
// This value never be TRUE, if FontAssociation features are disabled.
// And this value also never be TRUE, no-user logged-on this window station.
// This value become TRUE at first time that GreEnableEUDC() is called.
// and this value is turned off when user logout.
//
BOOL bFinallyInitializeFontAssocDefault = FALSE;
//
// Font Association default link configuration table
//
#define NUMBER_OF_FONTASSOC_DEFAULT 7
#define FF_DEFAULT 0xFF
FONT_DEFAULTASSOC FontAssocDefaultTable[NUMBER_OF_FONTASSOC_DEFAULT] = {
{FALSE, FF_DONTCARE, L"FontPackageDontCare", L"\0", L"\0", {PPFENULL,PPFENULL}},
{FALSE, FF_ROMAN, L"FontPackageRoman", L"\0", L"\0" , {PPFENULL,PPFENULL}},
{FALSE, FF_SWISS, L"FontPackageSwiss", L"\0", L"\0", {PPFENULL,PPFENULL}},
{FALSE, FF_MODERN, L"FontPackageModern", L"\0", L"\0", {PPFENULL,PPFENULL}},
{FALSE, FF_SCRIPT, L"FontPackageScript", L"\0", L"\0", {PPFENULL,PPFENULL}},
{FALSE, FF_DECORATIVE, L"FontPackageDecorative", L"\0", L"\0", {PPFENULL,PPFENULL}},
{FALSE, FF_DEFAULT, L"FontPackage", L"\0", L"\0", {PPFENULL,PPFENULL}}
};
// Is font association substitition turned on?
static BOOL bEnableFontAssocSubstitutes = FALSE;
// Pointer to Substitution table for font association.
static ULONG ulNumFontAssocSubs = 0L;
PFONT_ASSOC_SUB pFontAssocSubs = (PFONT_ASSOC_SUB) NULL;
// definition is in flinkgdi.cxx
extern RTL_QUERY_REGISTRY_TABLE SharedQueryTable[2];
extern BOOL bAppendSysDirectory( WCHAR *pwcTarget, const WCHAR *pwcSource, UINT cchBufferSize );
extern BOOL bComputeQuickLookup(QUICKLOOKUP *pql, PFE *pPFE, BOOL bSystemEUDC);
/******************************Public*Routine******************************\
* NTSTATUS CountRegistryEntryCoutine(PWSTR,ULONG,PVOID,ULONG,PVOID,PVOID)
*
* History:
* 19-Jan-1996 -by- Hideyuki Nagase [hideyukn]
* Wrote it.
\**************************************************************************/
extern "C"
NTSTATUS
CountRegistryEntryRoutine
(
PWSTR ValueName,
ULONG ValueType,
PVOID ValueData,
ULONG ValueLength,
PVOID Context,
PVOID EntryContext
)
{
(*(ULONG *)EntryContext) += 1L;
return( STATUS_SUCCESS );
}
/******************************Public*Routine******************************\
* NTSTATUS FontAssocCharsetRoutine(PWSTR,ULONG,PVOID,ULONG,PVOID,PVOID)
*
* History:
* 28-Aug-1995 -by- Hideyuki Nagase [hideyukn]
* Wrote it.
\**************************************************************************/
extern "C"
NTSTATUS
FontAssocCharsetRoutine
(
PWSTR ValueName,
ULONG ValueType,
PVOID ValueData,
ULONG ValueLength,
PVOID Context,
PVOID EntryContext
)
{
//
// Only process follows if the data value is "YES"
//
if( _wcsicmp((LPWSTR) ValueData, L"YES" ) == 0)
{
//
// Check ANSI charset association is enabled
//
if( _wcsicmp(ValueName, L"ANSI(00)") == 0)
{
#if DBG
DbgPrint("GDISRV:FONTASSOC CHARSET:Enable ANSI association\n");
#endif
fFontAssocStatus |= ANSI_ASSOC;
return(STATUS_SUCCESS);
}
//
// Check SYMBOL charset association is enabled
//
else if( _wcsicmp(ValueName, L"SYMBOL(02)") == 0)
{
#if DBG
DbgPrint("GDISRV:FONTASSOC CHARSET:Enable SYMBOL association\n");
#endif
fFontAssocStatus |= SYMBOL_ASSOC;
return(STATUS_SUCCESS);
}
//
// Check OEM charset association is enabled
//
else if( _wcsicmp(ValueName, L"OEM(FF)") == 0)
{
#if DBG
DbgPrint("GDISRV:FONTASSOC CHARSET:Enable OEM association\n");
#endif
fFontAssocStatus |= OEM_ASSOC;
return(STATUS_SUCCESS);
}
}
//
// return STATUS_SUCCESS everytime,even we got error from above call, to
// get next enumuration.
//
return(STATUS_SUCCESS);
}
/******************************Public*Routine******************************\
* NTSTATUS FontAssocDefaultRoutine(PWSTR,ULONG,PVOID,ULONG,PVOID,PVOID)
*
* History:
* 14-Jan-1996 -by- Hideyuki Nagase [hideyukn]
* Wrote it.
\**************************************************************************/
extern "C"
NTSTATUS
FontAssocDefaultRoutine
(
PWSTR ValueName,
ULONG ValueType,
PVOID ValueData,
ULONG ValueLength,
PVOID Context,
PVOID EntryContext
)
{
UINT iIndex;
if(_wcsicmp(ValueName,L"AssocSystemFont") == 0)
{
bAppendSysDirectory(gawcSystemDBCSFontPath,(const WCHAR *)ValueData, MAX_PATH);
return(STATUS_SUCCESS);
}
else
if(_wcsicmp(ValueName,L"FontPackage") == 0)
{
cCapString(gawcSystemDBCSFontFaceName,(const WCHAR*)ValueData,LF_FACESIZE);
return(STATUS_SUCCESS);
}
for( iIndex = 0; iIndex < NUMBER_OF_FONTASSOC_DEFAULT; iIndex++ )
{
if(_wcsicmp(ValueName,
FontAssocDefaultTable[iIndex].DefaultFontTypeID) == 0)
{
// Check if the registry has some data.
if( *(LPWSTR)ValueData != L'\0' )
{
if (FAILED(StringCchCopyW(FontAssocDefaultTable[iIndex].DefaultFontFaceName, LF_FACESIZE+1, (const WCHAR *)ValueData)))
{
WARNING("FontAssocDefaultRoutine: not enough space in DefaultFontFaceName buffer\n");
return STATUS_SUCCESS;
}
FontAssocDefaultTable[iIndex].ValidRegData = TRUE;
#if DBG
DbgPrint("GDISRV:FONTASSOC DEFAULT:%ws -> %ws\n",
FontAssocDefaultTable[iIndex].DefaultFontTypeID,
FontAssocDefaultTable[iIndex].DefaultFontFaceName);
#endif
}
return(STATUS_SUCCESS);
}
}
#if DBG
DbgPrint("GDISRV:FONTASSOC DEFAULT:%ws is invalid registry key\n",(LPWSTR)ValueName);
#endif
//
// return STATUS_SUCCESS everytime,even we got error to do next enumuration.
//
return(STATUS_SUCCESS);
}
/******************************Public*Routine******************************\
* NTSTATUS FontAssocFontsRoutine(PWSTR,ULONG,PVOID,ULONG,PVOID,PVOID)
*
* History:
* 19-Jan-1996 -by- Hideyuki Nagase [hideyukn]
* Wrote it.
\**************************************************************************/
extern "C"
NTSTATUS
FontAssocFontsRoutine
(
PWSTR ValueName,
ULONG ValueType,
PVOID ValueData,
ULONG ValueLength,
PVOID Context,
PVOID EntryContext
)
{
UINT iIndex = (*(UINT *)EntryContext);
PFONT_ASSOC_SUB pfas = pFontAssocSubs + iIndex;
ASSERTGDI(iIndex < ulNumFontAssocSubs,
"GDIOSRV:FONTASSOC iIndex >= ulNumFontAssocSubs\n");
//
// Copy the registry data to local buffer..
//
cCapString(pfas->AssociatedName,(const WCHAR*)ValueData,LF_FACESIZE+1);
cCapString(pfas->OriginalName ,ValueName,LF_FACESIZE+1);
#if DBG
pfas->UniqNo = iIndex;
DbgPrint("GDISRV:FONTASSOC FontSubs %d %ws -> %ws\n",iIndex,
pfas->OriginalName,
pfas->AssociatedName);
#endif
//
// for Next entry....
//
(*(UINT *)EntryContext) = ++iIndex;
return (STATUS_SUCCESS);
}
/******************************Public*Routine******************************\
* VOID vInitializeFontAssocStatus()
*
* History:
* 28-Aug-1995 -by- Hideyuki Nagase [hideyukn]
* Wrote it.
\**************************************************************************/
VOID vInitializeFontAssocStatus(VOID)
{
NTSTATUS NtStatus;
// Read Font Association configuration value.
// Initialize "FontAssoc\Association CharSet" related.
SharedQueryTable[0].QueryRoutine = FontAssocCharsetRoutine;
SharedQueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
SharedQueryTable[0].Name = (PWSTR)NULL;
SharedQueryTable[0].EntryContext = (PVOID)NULL;
SharedQueryTable[0].DefaultType = REG_NONE;
SharedQueryTable[0].DefaultData = NULL;
SharedQueryTable[0].DefaultLength = 0;
SharedQueryTable[1].QueryRoutine = NULL;
SharedQueryTable[1].Flags = 0;
SharedQueryTable[1].Name = (PWSTR)NULL;
fFontAssocStatus = 0;
gawcSystemDBCSFontPath[0] = L'\0';
// Enumurate registry values
NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL|RTL_REGISTRY_OPTIONAL,
FONT_ASSOCIATION_CHARSET_KEY,
SharedQueryTable,
NULL,
NULL);
if(!NT_SUCCESS(NtStatus))
{
WARNING1("GDISRV:FontAssociation is disabled\n");
fFontAssocStatus = 0;
}
gawcSystemDBCSFontFaceName[0] = 0;
// Initialize "FontAssoc\Association DefaultFonts" related.
SharedQueryTable[0].QueryRoutine = FontAssocDefaultRoutine;
// Enumurate registry values
NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL|RTL_REGISTRY_OPTIONAL,
FONT_ASSOCIATION_DEFAULT_KEY,
SharedQueryTable,
NULL,
NULL);
if( !NT_SUCCESS(NtStatus) )
{
WARNING1("GDISRV:FontAssociation:Default table is not presented\n");
bReadyToInitializeFontAssocDefault = FALSE;
}
else
{
// We succeeded to read registry and fill up FontAssocDefaultTable.
bReadyToInitializeFontAssocDefault = TRUE;
// try to load the system DBCS font if we detected the appropriate registry
// entries
if(gawcSystemDBCSFontPath[0] && gawcSystemDBCSFontFaceName[0])
{
PUBLIC_PFTOBJ pfto;
LONG cFonts;
EUDCLOAD EudcLoadData;
PFF *placeHolder;
EudcLoadData.pppfeData = gappfeSystemDBCS;
EudcLoadData.LinkedFace = gawcSystemDBCSFontFaceName;
if(pfto.bLoadAFont(gawcSystemDBCSFontPath,
(PULONG) &cFonts,
PFF_STATE_EUDC_FONT,
&placeHolder,
&EudcLoadData ))
{
// initialize quick lookup table if we successfully loaded the font
// this must be NULL for bComputeQuickLookup
gqlTTSystem.puiBits = NULL;
if(bComputeQuickLookup(&gqlTTSystem, gappfeSystemDBCS[PFE_NORMAL], FALSE))
{
// now try the vertical face if one is provided
FLINKMESSAGE2(DEBUG_FONTLINK_INIT,
"Loaded SystemDBCSFont %ws\n",
gawcSystemDBCSFontPath);
gbSystemDBCSFontEnabled = TRUE;
gbAnyLinkedFonts = TRUE;
}
if(!gbSystemDBCSFontEnabled)
{
WARNING("vInitializeFontAssocStatus: error creating \
quick lookup tables for SystemDBCSFont\n");
pfto.bUnloadEUDCFont(gawcSystemDBCSFontPath);
}
}
else
{
WARNING("vInitializeFontAssocStatus: error loading SystemDBCSFont\n");
}
}
}
// Initialize "Font Association\Fonts" related.
bEnableFontAssocSubstitutes = FALSE;
SharedQueryTable[0].QueryRoutine = CountRegistryEntryRoutine;
SharedQueryTable[0].EntryContext = (PVOID)(&ulNumFontAssocSubs);
// Count the number of the registry entries.
// NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL|RTL_REGISTRY_OPTIONAL,
// FONT_ASSOCIATION_FONTS_KEY,
// SharedQueryTable,
// NULL,
// NULL);
ulNumFontAssocSubs = 0;
if( NT_SUCCESS(NtStatus) && (ulNumFontAssocSubs != 0) )
{
#if DBG
DbgPrint("GDISRV:FONTASSOC %d FontAssoc Substitution is found\n",
ulNumFontAssocSubs);
#endif
// Allocate lookaside table for fontassociation's substitution.
pFontAssocSubs = (PFONT_ASSOC_SUB)
PALLOCMEM(sizeof(FONT_ASSOC_SUB)*ulNumFontAssocSubs,'flnk');
if( pFontAssocSubs != NULL )
{
UINT iCount = 0; // This will be used as Current Table Index.
SharedQueryTable[0].QueryRoutine = FontAssocFontsRoutine;
SharedQueryTable[0].EntryContext = (PVOID)(&iCount);
NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL|RTL_REGISTRY_OPTIONAL,
FONT_ASSOCIATION_FONTS_KEY,
SharedQueryTable,
NULL,
NULL);
if( !NT_SUCCESS(NtStatus) )
{
VFREEMEM( pFontAssocSubs );
ulNumFontAssocSubs = 0L;
}
else
{
bEnableFontAssocSubstitutes = TRUE;
gbAnyLinkedFonts = TRUE;
}
}
else
{
ulNumFontAssocSubs = 0L;
}
}
return;
}
/*****************************************************************************\
* GreGetFontAssocStatus( BOOL bEnable )
*
* History:
* 28-Aug-1995 -by- Hideyuki Nagase [hideyukn]
* Wrote it.
*****************************************************************************/
UINT GreGetFontAssocStatus(VOID)
{
return(fFontAssocStatus);
}
/*****************************************************************************
* BOOL bSetupDefaultFlEntry(BOOL,BOOL,INT)
*
* This function load font and build link for eudc font according to
* the default link table.
*
* History
* 1-15-96 Hideyuki Nagase
* Wrote it.
*****************************************************************************/
BOOL bSetupDefaultFlEntry(VOID)
{
UINT iIndex;
UINT bRet = FALSE;
//
// get and validate PFT user object
//
PUBLIC_PFTOBJ pfto; // access the public font table
ASSERTGDI(
pfto.bValid(),
"gdisrv!bSetupDefaultFlEntry(): could not access the public font table\n"
);
for( iIndex = 0; iIndex < NUMBER_OF_FONTASSOC_DEFAULT; iIndex++ )
{
//
// Check the registry data and fontpath is valid ,and
// this font is not loaded, yet.
//
if( (FontAssocDefaultTable[iIndex].ValidRegData) &&
(FontAssocDefaultTable[iIndex].DefaultFontPathName[0] != L'\0') &&
(FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_NORMAL] == PPFENULL) )
{
PPFE appfeLink[2]; // temporary buffer
LONG cFonts; // count of fonts
EUDCLOAD EudcLoadData; // eudc load data
PFF *placeHolder;
PWSZ FontPathName = FontAssocDefaultTable[iIndex].DefaultFontPathName;
//
// Fill up EudcLoadData structure
//
EudcLoadData.pppfeData = appfeLink;
EudcLoadData.LinkedFace = FontAssocDefaultTable[iIndex].DefaultFontFaceName;
//
// Load the linked font.
//
if( pfto.bLoadAFont( FontPathName,
(PULONG) &cFonts,
(PFF_STATE_EUDC_FONT | PFF_STATE_PERMANENT_FONT),
&placeHolder,
&EudcLoadData ) )
{
//
// Check we really succeed to load requested facename font.
//
//
// Compute table for normal face
//
if(!bComputeQuickLookup(NULL, appfeLink[PFE_NORMAL], FALSE ))
{
WARNING("Unable to compute QuickLookUp for default link\n");
//
// Unload the fonts.
//
pfto.bUnloadEUDCFont(FontPathName);
//
// we got error during load, maybe font itself might be invalid,
// just invalidate the pathname the default table.
//
FontAssocDefaultTable[iIndex].DefaultFontPathName[0] = L'\0';
//
// Do next entry in default table.
//
continue;
}
//
// Compute table for vertical face, if vertical face font is provided,
//
if( !bComputeQuickLookup(NULL, appfeLink[PFE_VERTICAL], FALSE ))
{
WARNING("Unable to compute QuickLookUp for default link\n");
// Unload the fonts.
pfto.bUnloadEUDCFont(FontPathName);
// we got error during load, maybe font itself might be invalid,
// just invalidate the pathname the default table.
FontAssocDefaultTable[iIndex].DefaultFontPathName[0] = L'\0';
// Do next entry in default table.
continue;
}
//
// Finally, we keeps the PFEs in default array.
//
FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_NORMAL] =
appfeLink[PFE_NORMAL];
FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_VERTICAL] =
appfeLink[PFE_VERTICAL];
#if DBG
DbgPrint("GDISRV:FONTASSOC DEFAULT:Load %ws for %ws\n",
FontAssocDefaultTable[iIndex].DefaultFontPathName,
FontAssocDefaultTable[iIndex].DefaultFontTypeID);
#endif
// We can load Associated font.
bRet = TRUE;
}
else
{
#if DBG
DbgPrint("Failed to load default link font. (%ws)\n",FontPathName);
#endif
//
// we got error during load, maybe font itself might be invalid,
// just invalidate the pathname the default table.
//
FontAssocDefaultTable[iIndex].DefaultFontPathName[0] = L'\0';
//
// Make sure the PFEs are invalid.
//
FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_NORMAL] = PPFENULL;
FontAssocDefaultTable[iIndex].DefaultFontPFEs[PFE_VERTICAL] = PPFENULL;
}
}
}
return(bRet);
}
/*****************************************************************************
* ULONG NtGdiQueryFontAssocInfo
*
* Shared kernel mode entry point for QueryFontAssocStatus and
* GetFontAssocStatus
*
* History
* 6-12-96 Gerrit van Wingerden [gerritv]
* Wrote it.
****************************************************************************/
#define GFA_NOT_SUPPORTED 0
#define GFA_SUPPORTED 1
#define GFA_DBCSFONT 2
extern "C" ULONG NtGdiQueryFontAssocInfo(HDC hdc)
{
// if hdc is NULL then just return fFontAssocStatus
if(hdc == NULL)
{
return(fFontAssocStatus);
}
else
{
// for now eventually merge/share with NtGdiGetCharSet
FLONG flSim;
POINTL ptlSim;
FLONG flAboutMatch;
PFE *ppfe;
DCOBJ dco (hdc);
if (!dco.bValid())
{
SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
return(GFA_NOT_SUPPORTED);
}
PDEVOBJ pdo(dco.hdev());
ASSERTGDI(pdo.bValid(), "gdisrv!GetCharSet: bad pdev in dc\n");
if (!pdo.bGotFonts())
pdo.bGetDeviceFonts();
LFONTOBJ lfo(dco.pdc->hlfntNew(), &pdo);
if (dco.ulDirty() & DIRTY_CHARSET)
{
// force mapping
if (!lfo.bValid())
{
WARNING("gdisrv!RFONTOBJ(dco): bad LFONT handle\n");
return(GFA_NOT_SUPPORTED);
}
// Stabilize the public PFT for mapping.
SEMOBJ so(ghsemPublicPFT);
// LFONTOBJ::ppfeMapFont returns a pointer to the physical font face and
// a simulation type (ist)
// also store charset to the DC
ppfe = lfo.ppfeMapFont(dco, &flSim, &ptlSim, &flAboutMatch);
ASSERTGDI(!(dco.ulDirty() & DIRTY_CHARSET),
"NtGdiGetCharSet, charset is dirty\n");
}
UINT Charset = (dco.pdc->iCS_CP() >> 16) & 0xFF;
if (IS_ANY_DBCS_CHARSET( Charset ))
{
return GFA_DBCSFONT;
}
if (((Charset == ANSI_CHARSET) && (fFontAssocStatus & ANSI_ASSOC)) ||
((Charset == OEM_CHARSET) && (fFontAssocStatus & OEM_ASSOC)) ||
((Charset == SYMBOL_CHARSET) && (fFontAssocStatus & SYMBOL_ASSOC)) )
{
if(!(lfo.plfw()->lfClipPrecision & CLIP_DFA_DISABLE))
{
return(GFA_SUPPORTED);
}
}
return(GFA_NOT_SUPPORTED);
}
}
#endif