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.
1608 lines
57 KiB
1608 lines
57 KiB
// Copyright (c) 1996-1999 Microsoft Corporation
|
|
/*
|
|
* postproc.c - postprocessing functions
|
|
|
|
|
|
|
|
History of Changes
|
|
9/30/98 --hsingh--
|
|
Added three functions BsetUQMFlag(), BRecurseNodes(), BsetUQMTrue()
|
|
to enable making the UpdateQualityMacro? keyword optional in
|
|
.gpd file.
|
|
Bug Report 225088
|
|
*/
|
|
|
|
|
|
#include "gpdparse.h"
|
|
|
|
|
|
// ---- functions defined in postproc.c ---- //
|
|
|
|
|
|
DWORD dwFindLastNode(
|
|
DWORD dwFirstNode,
|
|
PGLOBL pglobl) ;
|
|
|
|
BOOL BappendCommonFontsToPortAndLandscape(
|
|
PGLOBL pglobl) ;
|
|
|
|
BOOL BinitSpecialFeatureOptionFields(
|
|
PGLOBL pglobl) ;
|
|
|
|
BOOL BIdentifyConstantString(
|
|
IN PARRAYREF parString,
|
|
OUT PDWORD pdwDest, // write dword value here.
|
|
IN DWORD dwClassIndex, // which class of constant is this?
|
|
BOOL bCustomOptOK,
|
|
PGLOBL pglobl
|
|
) ;
|
|
|
|
|
|
|
|
BOOL BReadDataInGlobalNode(
|
|
PATREEREF patr, // address of field in GlobalAttrib struct
|
|
PDWORD pdwHeapOffset,
|
|
PGLOBL pglobl
|
|
) ;
|
|
|
|
|
|
BOOL BsetUQMFlag(PGLOBL pglobl);
|
|
BOOL BRecurseNodes(
|
|
IN DWORD dwNodeIndex,
|
|
PGLOBL pglobl);
|
|
BOOL BsetUQMTrue(
|
|
IN DWORD dwFeature,
|
|
PGLOBL pglobl);
|
|
|
|
|
|
VOID VCountPrinterDocStickyFeatures(
|
|
PGLOBL pglobl) ;
|
|
|
|
BOOL BConvertSpecVersionToDWORD (
|
|
PWSTR pwstrFileName ,
|
|
PGLOBL pglobl) ;
|
|
|
|
|
|
|
|
|
|
|
|
BOOL BinitMiniRawBinaryData(
|
|
PGLOBL pglobl) ;
|
|
|
|
BOOL BexchangeArbDataInFOATNode(
|
|
DWORD dwFeature,
|
|
DWORD dwOption,
|
|
DWORD dwFieldOff, // offset of field in FeatureOption struct
|
|
DWORD dwCount, // number bytes to copy.
|
|
OUT PBYTE pubOut, // previous contents of attribute node
|
|
IN PBYTE pubIn, // new contents of attribute node.
|
|
PBOOL pbPrevsExists, // previous contents existed.
|
|
BOOL bSynthetic, // access synthetic features
|
|
PGLOBL pglobl
|
|
) ;
|
|
|
|
BOOL BInitPriorityArray(
|
|
PGLOBL pglobl) ;
|
|
|
|
|
|
|
|
// ---------------------------------------------------- //
|
|
|
|
|
|
|
|
typedef struct
|
|
{
|
|
DWORD paperID ;
|
|
DWORD x ;
|
|
DWORD y ;
|
|
} PAPERDIM ;
|
|
|
|
CONST PAPERDIM aPaperDimensions[] = {
|
|
DMPAPER_LETTER, 215900, 279400,
|
|
DMPAPER_LETTERSMALL, 215900, 279400,
|
|
DMPAPER_TABLOID, 279400, 431800,
|
|
DMPAPER_LEDGER, 431800, 279400,
|
|
DMPAPER_LEGAL, 215900, 355600,
|
|
DMPAPER_STATEMENT, 139700, 215900,
|
|
DMPAPER_EXECUTIVE, 184150, 266700,
|
|
DMPAPER_A3, 297000, 420000,
|
|
DMPAPER_A4, 210000, 297000,
|
|
DMPAPER_A4SMALL, 210000, 297000,
|
|
DMPAPER_A5, 148000, 210000,
|
|
DMPAPER_B4, 257000, 364000,
|
|
DMPAPER_B5, 182000, 257000,
|
|
DMPAPER_FOLIO, 215900, 330200,
|
|
DMPAPER_QUARTO, 215000, 275000,
|
|
DMPAPER_10X14, 254000, 355600,
|
|
DMPAPER_11X17, 279400, 431800,
|
|
DMPAPER_NOTE, 215900, 279400,
|
|
DMPAPER_ENV_9, 98425, 225425,
|
|
DMPAPER_ENV_10, 104775, 241300,
|
|
DMPAPER_ENV_11, 114300, 263525,
|
|
DMPAPER_ENV_12, 120650, 279400,
|
|
DMPAPER_ENV_14, 127000, 292100,
|
|
DMPAPER_CSHEET, 431800, 558800,
|
|
DMPAPER_DSHEET, 558800, 863600,
|
|
DMPAPER_ESHEET, 863600,1117600,
|
|
DMPAPER_ENV_DL, 110000, 220000,
|
|
DMPAPER_ENV_C5, 162000, 229000,
|
|
DMPAPER_ENV_C3, 324000, 458000,
|
|
DMPAPER_ENV_C4, 229000, 324000,
|
|
DMPAPER_ENV_C6, 114000, 162000,
|
|
DMPAPER_ENV_C65, 114000, 229000,
|
|
DMPAPER_ENV_B4, 250000, 353000,
|
|
DMPAPER_ENV_B5, 176000, 250000,
|
|
DMPAPER_ENV_B6, 176000, 125000,
|
|
DMPAPER_ENV_ITALY, 110000, 230000,
|
|
DMPAPER_ENV_MONARCH, 98425, 190500,
|
|
DMPAPER_ENV_PERSONAL, 92075, 165100,
|
|
DMPAPER_FANFOLD_US, 377825, 279400,
|
|
DMPAPER_FANFOLD_STD_GERMAN, 215900, 304800,
|
|
DMPAPER_FANFOLD_LGL_GERMAN, 215900, 330200,
|
|
|
|
DMPAPER_ISO_B4, 250000, 353000,
|
|
DMPAPER_JAPANESE_POSTCARD, 100000, 148000,
|
|
DMPAPER_9X11, 228600, 279400,
|
|
DMPAPER_10X11, 254000, 279400,
|
|
DMPAPER_15X11, 381000, 279400,
|
|
DMPAPER_ENV_INVITE, 220000, 220000,
|
|
DMPAPER_LETTER_EXTRA, 241300, 304800,
|
|
|
|
DMPAPER_LEGAL_EXTRA, 241300, 381000,
|
|
DMPAPER_TABLOID_EXTRA, 296926, 457200,
|
|
DMPAPER_A4_EXTRA, 235458, 322326,
|
|
DMPAPER_LETTER_TRANSVERSE, 215900, 279400,
|
|
DMPAPER_A4_TRANSVERSE, 210000, 297000,
|
|
DMPAPER_LETTER_EXTRA_TRANSVERSE, 241300, 304800,
|
|
DMPAPER_A_PLUS, 227000, 356000,
|
|
DMPAPER_B_PLUS, 305000, 487000,
|
|
DMPAPER_LETTER_PLUS, 215900, 322326,
|
|
DMPAPER_A4_PLUS, 210000, 330000,
|
|
DMPAPER_A5_TRANSVERSE, 148000, 210000,
|
|
DMPAPER_B5_TRANSVERSE, 182000, 257000,
|
|
DMPAPER_A3_EXTRA, 322000, 445000,
|
|
DMPAPER_A5_EXTRA, 174000, 235000,
|
|
DMPAPER_B5_EXTRA, 201000, 276000,
|
|
DMPAPER_A2, 420000, 594000,
|
|
DMPAPER_A3_TRANSVERSE, 297000, 420000,
|
|
DMPAPER_A3_EXTRA_TRANSVERSE, 322000, 445000,
|
|
|
|
// Predefined forms currently availble only in Win95. Included here
|
|
// for compatibility.
|
|
|
|
// FE-only predefined forms.
|
|
#ifndef WINNT_40
|
|
DMPAPER_DBL_JAPANESE_POSTCARD, 200000, 148000,
|
|
DMPAPER_A6, 105000, 148000,
|
|
DMPAPER_JENV_KAKU2, 240000, 332000,
|
|
DMPAPER_JENV_KAKU3, 216000, 277000,
|
|
DMPAPER_JENV_CHOU3, 120000, 235000,
|
|
DMPAPER_JENV_CHOU4, 90000, 205000,
|
|
DMPAPER_LETTER_ROTATED, 279400, 215900,
|
|
DMPAPER_A3_ROTATED, 420000, 297000,
|
|
DMPAPER_A4_ROTATED, 297000, 210000,
|
|
DMPAPER_A5_ROTATED, 210000, 148000,
|
|
DMPAPER_B4_JIS_ROTATED, 364000, 257000,
|
|
DMPAPER_B5_JIS_ROTATED, 257000, 182000,
|
|
DMPAPER_JAPANESE_POSTCARD_ROTATED, 148000, 100000,
|
|
DMPAPER_DBL_JAPANESE_POSTCARD_ROTATED, 148000, 200000,
|
|
DMPAPER_A6_ROTATED, 148000, 105000,
|
|
DMPAPER_JENV_KAKU2_ROTATED, 332000, 240000,
|
|
DMPAPER_JENV_KAKU3_ROTATED, 277000, 216000,
|
|
DMPAPER_JENV_CHOU3_ROTATED, 235000, 120000,
|
|
DMPAPER_JENV_CHOU4_ROTATED, 205000, 90000,
|
|
DMPAPER_B6_JIS, 128000, 182000,
|
|
DMPAPER_B6_JIS_ROTATED, 182000, 128000,
|
|
DMPAPER_12X11, 304932, 279521,
|
|
DMPAPER_JENV_YOU4, 105000, 235000,
|
|
DMPAPER_JENV_YOU4_ROTATED, 235000, 105000,
|
|
DMPAPER_P16K, 146000, 215000,
|
|
DMPAPER_P32K, 970000, 151000,
|
|
DMPAPER_P32KBIG, 101000, 160000,
|
|
DMPAPER_PENV_1, 102000, 165000,
|
|
DMPAPER_PENV_2, 110000, 176000,
|
|
DMPAPER_PENV_3, 125000, 176000,
|
|
DMPAPER_PENV_4, 110000, 208000,
|
|
DMPAPER_PENV_5, 110000, 220000,
|
|
DMPAPER_PENV_6, 120000, 230000,
|
|
DMPAPER_PENV_7, 160000, 230000,
|
|
DMPAPER_PENV_8, 120000, 309000,
|
|
DMPAPER_PENV_9, 229000, 324000,
|
|
DMPAPER_PENV_10, 324000, 458000,
|
|
DMPAPER_P16K_ROTATED, 215000, 146000,
|
|
DMPAPER_P32K_ROTATED, 151000, 970000,
|
|
DMPAPER_P32KBIG_ROTATED, 160000, 101000,
|
|
DMPAPER_PENV_1_ROTATED, 165000, 102000,
|
|
DMPAPER_PENV_2_ROTATED, 176000, 110000,
|
|
DMPAPER_PENV_3_ROTATED, 176000, 125000,
|
|
DMPAPER_PENV_4_ROTATED, 208000, 110000,
|
|
DMPAPER_PENV_5_ROTATED, 220000, 110000,
|
|
DMPAPER_PENV_6_ROTATED, 230000, 120000,
|
|
DMPAPER_PENV_7_ROTATED, 230000, 160000,
|
|
DMPAPER_PENV_8_ROTATED, 309000, 120000,
|
|
DMPAPER_PENV_9_ROTATED, 324000, 229000,
|
|
DMPAPER_PENV_10_ROTATED, 458000, 324000,
|
|
#endif
|
|
0, 0, 0
|
|
};
|
|
|
|
|
|
|
|
|
|
DWORD dwFindLastNode(
|
|
DWORD dwFirstNode,
|
|
PGLOBL pglobl)
|
|
// assume dwFirstNode != END_OF_LIST
|
|
{
|
|
PLISTNODE plstRoot ; // start of LIST array
|
|
|
|
plstRoot = (PLISTNODE) gMasterTable[MTI_LISTNODES].pubStruct ;
|
|
|
|
while(plstRoot[dwFirstNode].dwNextItem != END_OF_LIST)
|
|
dwFirstNode = plstRoot[dwFirstNode].dwNextItem ;
|
|
return(dwFirstNode);
|
|
} // dwFindLastNode(...)
|
|
|
|
|
|
BOOL BappendCommonFontsToPortAndLandscape(
|
|
PGLOBL pglobl)
|
|
// append dwFontLst to dwPortFontLst and dwLandFontLst
|
|
// in the FontCart structure.
|
|
{
|
|
DWORD dwNumFontCarts , dwI, dwNodeIndex;
|
|
PFONTCART pfc ;
|
|
PLISTNODE plstRoot ; // start of LIST array
|
|
|
|
dwNumFontCarts = gMasterTable[MTI_FONTCART].dwArraySize ;
|
|
|
|
if(!dwNumFontCarts)
|
|
return (TRUE); // no fontcart structs to process.
|
|
|
|
pfc = (PFONTCART)gMasterTable[MTI_FONTCART].pubStruct ;
|
|
plstRoot = (PLISTNODE) gMasterTable[MTI_LISTNODES].pubStruct ;
|
|
|
|
for(dwI = 0 ; dwI < dwNumFontCarts ; dwI++)
|
|
{
|
|
if(pfc[dwI].dwFontLst == END_OF_LIST)
|
|
continue; // nothing to append.
|
|
|
|
if(pfc[dwI].dwPortFontLst == END_OF_LIST)
|
|
pfc[dwI].dwPortFontLst = pfc[dwI].dwFontLst ;
|
|
else
|
|
{
|
|
dwNodeIndex = dwFindLastNode(pfc[dwI].dwPortFontLst, pglobl) ;
|
|
plstRoot[dwNodeIndex].dwNextItem = pfc[dwI].dwFontLst ;
|
|
}
|
|
if(pfc[dwI].dwLandFontLst == END_OF_LIST)
|
|
pfc[dwI].dwLandFontLst = pfc[dwI].dwFontLst ;
|
|
else
|
|
{
|
|
dwNodeIndex = dwFindLastNode(pfc[dwI].dwLandFontLst, pglobl) ;
|
|
plstRoot[dwNodeIndex].dwNextItem = pfc[dwI].dwFontLst ;
|
|
}
|
|
} //for dwI
|
|
return (TRUE); //
|
|
} //BappendCommonFontsToPortAndLandscape()
|
|
|
|
|
|
BOOL BinitSpecialFeatureOptionFields(
|
|
PGLOBL pglobl)
|
|
// determine num options and Unicode names for feature and
|
|
// option keywords.
|
|
{
|
|
DWORD dwOptionID , dwOptionIndex , dwHeapOffset,
|
|
dwFeatureIndex, dwFeatureID, dwLargestString ,
|
|
dwAccumulator ; // tracks amount of buffer needed to store
|
|
// Feature/Option keyword strings in devmode.
|
|
|
|
PSYMBOLNODE psn ;
|
|
PDFEATURE_OPTIONS pfo ;
|
|
ARRAYREF arSymbolName, arUnicodeName;
|
|
|
|
BOOL bPickMany, // can user select multiple options?
|
|
bExists ; // dummy
|
|
|
|
PBYTE pubFeaDelim = " NewFeature " ,
|
|
pubTrue = " TRUE ",
|
|
pubFalse = " FALSE ";
|
|
|
|
// do this just for non-synthesized features.
|
|
// write atrFeaKeyWord directly as heap offset.
|
|
// write atrOptKeyWord as single level tree
|
|
// using BexchangeArbDataInFOATNode().
|
|
|
|
gmrbd.dwMaxPrnKeywordSize = gmrbd.dwMaxDocKeywordSize = 0 ;
|
|
// tell amanda how much room to reserve in devmode or registry
|
|
// to store feature/option keywords.
|
|
gmrbd.rbd.dwChecksum32 = 0 ; // seed
|
|
|
|
|
|
pfo = (PDFEATURE_OPTIONS) gMasterTable[MTI_DFEATURE_OPTIONS].pubStruct ;
|
|
|
|
psn = (PSYMBOLNODE) gMasterTable[MTI_SYMBOLTREE].pubStruct ;
|
|
|
|
dwFeatureIndex = mdwFeatureSymbols ;
|
|
|
|
while(dwFeatureIndex != INVALID_INDEX)
|
|
{
|
|
DWORD dwRootOptions ,
|
|
dwNonStandardSizeID = FIRST_NON_STANDARD_ID ;
|
|
|
|
dwFeatureID = psn[dwFeatureIndex].dwSymbolID ;
|
|
arSymbolName = psn[dwFeatureIndex].arSymbolName ;
|
|
|
|
// ----- special checks for Feature describing multiple Resource DLLs.
|
|
|
|
if(dwFeatureID && (dwFeatureID == gdwResDLL_ID) )
|
|
{
|
|
// does feature have correct symbolname?
|
|
PBYTE pubResName = "RESDLL" ;
|
|
DWORD dwLen ;
|
|
|
|
dwLen = strlen(pubResName);
|
|
|
|
if((dwLen != arSymbolName.dwCount) ||
|
|
strncmp(mpubOffRef + arSymbolName.loOffset,
|
|
pubResName, dwLen) )
|
|
{
|
|
ERR(("References to ResourceDLLs must be placed in the feature with symbolname: %s.\n", pubResName));
|
|
return(FALSE);
|
|
}
|
|
|
|
// has atrOptRcNameID been defined?
|
|
|
|
if(pfo[dwFeatureID].atrOptRcNameID != ATTRIB_UNINITIALIZED)
|
|
{
|
|
ERR(("ResourceDLL names must be declared explicitly using *Name not *rcNameID.\n"));
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// ----- compute BUD checksum
|
|
|
|
gmrbd.rbd.dwChecksum32 = ComputeCrc32Checksum (
|
|
pubFeaDelim,
|
|
strlen(pubFeaDelim),
|
|
gmrbd.rbd.dwChecksum32 ) ;
|
|
|
|
// perform checksum on arSymbolName
|
|
|
|
gmrbd.rbd.dwChecksum32 = ComputeCrc32Checksum(
|
|
mpubOffRef + arSymbolName.loOffset,
|
|
arSymbolName.dwCount,
|
|
gmrbd.rbd.dwChecksum32 ) ;
|
|
|
|
|
|
// extract value for atrFeaInstallable using
|
|
if(!BReadDataInGlobalNode(&pfo[dwFeatureID].atrFeaInstallable , &dwHeapOffset, pglobl)
|
|
|| *(PDWORD)(mpubOffRef + dwHeapOffset) != BT_TRUE)
|
|
gmrbd.rbd.dwChecksum32 = // no synthesized feature associated
|
|
ComputeCrc32Checksum(
|
|
pubFalse,
|
|
strlen(pubFalse),
|
|
gmrbd.rbd.dwChecksum32 ) ;
|
|
else
|
|
gmrbd.rbd.dwChecksum32 = // associated with synthesized feature
|
|
ComputeCrc32Checksum(
|
|
pubTrue,
|
|
strlen(pubTrue),
|
|
gmrbd.rbd.dwChecksum32 ) ;
|
|
|
|
// ----- end part I compute BUD checksum
|
|
|
|
dwRootOptions = psn[dwFeatureIndex].dwSubSpaceIndex ;
|
|
|
|
pfo[dwFeatureID].dwNumOptions =
|
|
psn[dwRootOptions].dwSymbolID + 1 ;
|
|
|
|
|
|
|
|
#if 0
|
|
Don't convert symbol values to Unicode.
|
|
if(!BwriteUnicodeToHeap(&arSymbolName, &arUnicodeName,
|
|
iCodepage = 0))
|
|
return(FALSE) ;
|
|
#endif
|
|
if(!BwriteToHeap(&(pfo[dwFeatureID].atrFeaKeyWord),
|
|
(PBYTE)&arSymbolName, sizeof(ARRAYREF), 4, pglobl))
|
|
return(FALSE);
|
|
|
|
dwAccumulator = arSymbolName.dwCount + 2 ;
|
|
|
|
|
|
pfo[dwFeatureID].atrFeaKeyWord |= ATTRIB_HEAP_VALUE ;
|
|
|
|
{ // !!! new stuff
|
|
DWORD dwHeapOffset ;
|
|
|
|
dwLargestString = 0 ; // track the largest option string
|
|
|
|
if(!BReadDataInGlobalNode(&pfo[dwFeatureID].atrUIType , &dwHeapOffset, pglobl)
|
|
|| *(PDWORD)(mpubOffRef + dwHeapOffset) != UIT_PICKMANY)
|
|
bPickMany = FALSE ;
|
|
// accumulator += the largest option string;
|
|
else
|
|
bPickMany = TRUE ;
|
|
// accumulator = sum of all option strings;
|
|
}
|
|
|
|
|
|
if(!BIdentifyConstantString(&arSymbolName,
|
|
&(pfo[dwFeatureID].dwGID), CL_CONS_FEATURES, TRUE, pglobl) )
|
|
{
|
|
pfo[dwFeatureID].dwGID = GID_UNKNOWN ;
|
|
}
|
|
|
|
if((pfo[dwFeatureID].dwGID == GID_MEMOPTION) ||
|
|
(pfo[dwFeatureID].dwGID == GID_PAGEPROTECTION))
|
|
{
|
|
DWORD dwHeapOffset, dwValue ;
|
|
PATREEREF patr ;
|
|
|
|
// set only if not explictly initialized in GPD file.
|
|
|
|
if(!BReadDataInGlobalNode(&pfo[dwFeatureID].atrFeatureType , &dwHeapOffset, pglobl) )
|
|
{
|
|
// label this FeatureType as PrinterSticky
|
|
dwValue = FT_PRINTERPROPERTY ;
|
|
patr = &pfo[dwFeatureID].atrFeatureType ;
|
|
|
|
if(!BwriteToHeap(patr, (PBYTE)&dwValue ,
|
|
sizeof(DWORD), 4, pglobl) )
|
|
{
|
|
return(FALSE) ; // heap overflow start over.
|
|
}
|
|
*patr |= ATTRIB_HEAP_VALUE ;
|
|
}
|
|
}
|
|
|
|
dwOptionIndex = dwRootOptions ;
|
|
|
|
while(dwOptionIndex != INVALID_INDEX)
|
|
{
|
|
DWORD dwDevmodeID, dwConsClass, dwInstallable ;
|
|
BOOL bCustomOptOK ;
|
|
|
|
dwOptionID = psn[dwOptionIndex].dwSymbolID ;
|
|
arSymbolName = psn[dwOptionIndex].arSymbolName ;
|
|
|
|
|
|
|
|
// ----- part II compute BUD checksum
|
|
// perform checksum on arSymbolName
|
|
|
|
gmrbd.rbd.dwChecksum32 =
|
|
ComputeCrc32Checksum(
|
|
mpubOffRef + arSymbolName.loOffset,
|
|
arSymbolName.dwCount,
|
|
gmrbd.rbd.dwChecksum32 ) ;
|
|
|
|
|
|
// extract value for atrOptInstallable using
|
|
if( BexchangeArbDataInFOATNode(dwFeatureID, dwOptionID,
|
|
offsetof(DFEATURE_OPTIONS, atrOptInstallable) ,
|
|
sizeof(DWORD),
|
|
(PBYTE)&dwInstallable, NULL, &bExists, FALSE , pglobl) &&
|
|
bExists && dwInstallable == BT_TRUE)
|
|
gmrbd.rbd.dwChecksum32 = // associated with synthesized feature
|
|
ComputeCrc32Checksum(
|
|
pubTrue,
|
|
strlen(pubTrue),
|
|
gmrbd.rbd.dwChecksum32 ) ;
|
|
else
|
|
gmrbd.rbd.dwChecksum32 = // no synthesized feature associated
|
|
ComputeCrc32Checksum(
|
|
pubFalse,
|
|
strlen(pubFalse),
|
|
gmrbd.rbd.dwChecksum32 ) ;
|
|
// ----- end part II compute BUD checksum
|
|
|
|
|
|
#if 0
|
|
if(!BwriteUnicodeToHeap(&arSymbolName, &arUnicodeName,
|
|
iCodepage = 0))
|
|
return(FALSE) ;
|
|
// if this is ever used, must use &arUnicodeName
|
|
// as the 2nd argument to BwriteToHeap.
|
|
#endif
|
|
|
|
if(! BexchangeArbDataInFOATNode(
|
|
dwFeatureID, dwOptionID,
|
|
offsetof(DFEATURE_OPTIONS, atrOptKeyWord),
|
|
sizeof(ARRAYREF),
|
|
NULL, (PBYTE)&arSymbolName, &bExists, FALSE , pglobl))
|
|
return(FALSE); // this is a fatal error.
|
|
|
|
if(bPickMany)
|
|
dwAccumulator += arSymbolName.dwCount + 1 ;
|
|
else
|
|
{
|
|
// track largest option string
|
|
if(dwLargestString < arSymbolName.dwCount + 1 )
|
|
dwLargestString = arSymbolName.dwCount + 1 ;
|
|
}
|
|
|
|
|
|
switch(pfo[dwFeatureID].dwGID)
|
|
{
|
|
case GID_PAGESIZE:
|
|
dwConsClass = CL_CONS_PAPERSIZE ;
|
|
bCustomOptOK = TRUE ;
|
|
break ;
|
|
case GID_MEDIATYPE:
|
|
dwConsClass = CL_CONS_MEDIATYPE ;
|
|
bCustomOptOK = TRUE ;
|
|
break ;
|
|
case GID_INPUTSLOT:
|
|
dwConsClass = CL_CONS_INPUTSLOT ;
|
|
bCustomOptOK = TRUE ;
|
|
break ;
|
|
case GID_HALFTONING:
|
|
dwConsClass = CL_CONS_HALFTONE ;
|
|
bCustomOptOK = TRUE ;
|
|
break ;
|
|
case GID_DUPLEX:
|
|
dwConsClass = CL_CONS_DUPLEX ;
|
|
bCustomOptOK = FALSE ;
|
|
break ;
|
|
case GID_ORIENTATION:
|
|
dwConsClass = CL_CONS_ORIENTATION ;
|
|
bCustomOptOK = FALSE ;
|
|
break ;
|
|
case GID_PAGEPROTECTION:
|
|
dwConsClass = CL_CONS_PAGEPROTECT ;
|
|
bCustomOptOK = FALSE ;
|
|
break ;
|
|
case GID_COLLATE:
|
|
dwConsClass = CL_CONS_COLLATE ;
|
|
bCustomOptOK = FALSE ;
|
|
break ;
|
|
|
|
default:
|
|
dwConsClass = CL_NUMCLASSES ;
|
|
bCustomOptOK = TRUE ; // Irrelavent.
|
|
break ;
|
|
} //switch
|
|
|
|
if(dwConsClass != CL_NUMCLASSES)
|
|
{
|
|
if(BIdentifyConstantString(&arSymbolName,
|
|
&dwDevmodeID, dwConsClass, bCustomOptOK, pglobl) )
|
|
{
|
|
if(! BexchangeArbDataInFOATNode(
|
|
dwFeatureID, dwOptionID,
|
|
offsetof(DFEATURE_OPTIONS, atrOptIDvalue),
|
|
sizeof(DWORD),
|
|
NULL, (PBYTE)&dwDevmodeID, &bExists, FALSE , pglobl))
|
|
return(FALSE); // this is a fatal error.
|
|
|
|
|
|
if(dwConsClass == CL_CONS_PAPERSIZE &&
|
|
dwDevmodeID < DMPAPER_USER)
|
|
{
|
|
// fill in the page dimensions.
|
|
POINT ptDim ;
|
|
DWORD dwI ;
|
|
PGLOBALATTRIB pga ;
|
|
BOOL bTRUE = TRUE ;
|
|
PBYTE pub ;
|
|
|
|
if(dwDevmodeID == DMPAPER_LETTER)
|
|
{
|
|
// pointer to dword containing heapoffset
|
|
PATREEREF patrAttribRoot ;
|
|
|
|
pub = gMasterTable[MTI_GLOBALATTRIB].pubStruct ;
|
|
patrAttribRoot = &(((PGLOBALATTRIB)pub)->atrLetterSizeExists) ;
|
|
BwriteToHeap((PDWORD) patrAttribRoot, (PBYTE)&bTRUE, 4 , 4 , pglobl);
|
|
*patrAttribRoot |= ATTRIB_HEAP_VALUE ;
|
|
}
|
|
else if(dwDevmodeID == DMPAPER_A4)
|
|
{
|
|
PATREEREF patrAttribRoot ; // pointer to dword containing heapoffset
|
|
|
|
pub = gMasterTable[MTI_GLOBALATTRIB].pubStruct ;
|
|
patrAttribRoot = &(((PGLOBALATTRIB)pub)->atrA4SizeExists) ;
|
|
BwriteToHeap((PDWORD) patrAttribRoot, (PBYTE)&bTRUE, 4 , 4 , pglobl);
|
|
*patrAttribRoot |= ATTRIB_HEAP_VALUE ;
|
|
}
|
|
|
|
for(dwI = 0 ; aPaperDimensions[dwI].x ; dwI++)
|
|
{
|
|
if(aPaperDimensions[dwI].paperID == dwDevmodeID)
|
|
break ;
|
|
}
|
|
// worst case causes (0,0) to be assigned.
|
|
|
|
ptDim.x = aPaperDimensions[dwI].x ;
|
|
ptDim.y = aPaperDimensions[dwI].y ;
|
|
|
|
// convert from microns to master units
|
|
|
|
ptDim.x /= 100 ; // microns to tenths of mm
|
|
ptDim.y /= 100 ;
|
|
|
|
pga = (PGLOBALATTRIB)gMasterTable[
|
|
MTI_GLOBALATTRIB].pubStruct ;
|
|
|
|
if(!BReadDataInGlobalNode(&pga->atrMasterUnits,
|
|
&dwHeapOffset, pglobl) )
|
|
return(FALSE);
|
|
|
|
ptDim.x *= ((PPOINT)(mpubOffRef + dwHeapOffset))->x ;
|
|
ptDim.y *= ((PPOINT)(mpubOffRef + dwHeapOffset))->y ;
|
|
|
|
ptDim.x /= 254 ;
|
|
ptDim.y /= 254 ;
|
|
|
|
|
|
if(! BexchangeArbDataInFOATNode(
|
|
dwFeatureID, dwOptionID,
|
|
offsetof(DFEATURE_OPTIONS, atrPageDimensions),
|
|
sizeof(POINT),
|
|
NULL, (PBYTE)&ptDim, &bExists, FALSE , pglobl))
|
|
return(FALSE); // this is a fatal error.
|
|
}
|
|
}
|
|
else if(bCustomOptOK)
|
|
// feature permits GPD defined options
|
|
{
|
|
DWORD dwID , // pattern size ID used by GDI
|
|
dwOldID, // user specified ID value if any.
|
|
dwRcPatID;
|
|
POINT ptSize ;
|
|
|
|
// Option Symbolvalue not found in tables.
|
|
// assume its a user-defined value.
|
|
|
|
#ifndef WINNT_40
|
|
if((pfo[dwFeatureID].dwGID == GID_HALFTONING) &&
|
|
BexchangeArbDataInFOATNode(
|
|
dwFeatureID, dwOptionID,
|
|
offsetof(DFEATURE_OPTIONS, atrRcHTPatternID),
|
|
sizeof(DWORD),
|
|
(PBYTE)&dwRcPatID, NULL, &bExists, FALSE , pglobl) &&
|
|
bExists && dwRcPatID &&
|
|
BexchangeArbDataInFOATNode(
|
|
dwFeatureID, dwOptionID,
|
|
offsetof(DFEATURE_OPTIONS, atrHTPatternSize),
|
|
sizeof(POINT),
|
|
(PBYTE)&ptSize, NULL, &bExists, FALSE, pglobl ) &&
|
|
bExists &&
|
|
(ptSize.x >= HT_USERPAT_CX_MIN) &&
|
|
(ptSize.x <= HT_USERPAT_CX_MAX) &&
|
|
(ptSize.y >= HT_USERPAT_CY_MIN) &&
|
|
(ptSize.y <= HT_USERPAT_CY_MAX)
|
|
)
|
|
{
|
|
dwID = HT_PATSIZE_USER ;
|
|
// GID halftone code is to use
|
|
// the user defined halftone matrix.
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
dwID = dwNonStandardSizeID ;
|
|
dwNonStandardSizeID++ ;
|
|
// OEM will supply a halftone function.
|
|
}
|
|
|
|
if(! BexchangeArbDataInFOATNode(
|
|
dwFeatureID, dwOptionID,
|
|
offsetof(DFEATURE_OPTIONS, atrOptIDvalue),
|
|
sizeof(DWORD),
|
|
(PBYTE)&dwOldID, (PBYTE)NULL, &bExists, FALSE , pglobl ))
|
|
return(FALSE); // this is a fatal error.
|
|
|
|
if(!bExists && ! BexchangeArbDataInFOATNode(
|
|
dwFeatureID, dwOptionID,
|
|
offsetof(DFEATURE_OPTIONS, atrOptIDvalue),
|
|
sizeof(DWORD),
|
|
NULL, (PBYTE)&dwID, &bExists, FALSE , pglobl))
|
|
return(FALSE); // this is a fatal error.
|
|
}
|
|
} // if(dwConsClass != CL_NUMCLASSES)
|
|
|
|
// otherwise leave optionID uninitialized.
|
|
|
|
dwOptionIndex = psn[dwOptionIndex].dwNextSymbol ;
|
|
|
|
} //while
|
|
|
|
|
|
|
|
|
|
{ // !!! new stuff
|
|
DWORD dwHeapOffset ;
|
|
|
|
dwAccumulator += dwLargestString ; // is zero if not needed.
|
|
|
|
if(!BReadDataInGlobalNode(&pfo[dwFeatureID].atrFeatureType , &dwHeapOffset, pglobl)
|
|
|| *(PDWORD)(mpubOffRef + dwHeapOffset) != FT_PRINTERPROPERTY)
|
|
gmrbd.dwMaxDocKeywordSize += dwAccumulator;
|
|
else
|
|
gmrbd.dwMaxPrnKeywordSize += dwAccumulator;
|
|
|
|
}
|
|
|
|
|
|
dwFeatureIndex = psn[dwFeatureIndex].dwNextSymbol ;
|
|
}
|
|
return(TRUE) ;
|
|
} // BinitSpecialFeatureOptionFields()
|
|
|
|
|
|
|
|
|
|
BOOL BIdentifyConstantString(
|
|
IN PARRAYREF parString,
|
|
OUT PDWORD pdwDest, // write dword value here.
|
|
IN DWORD dwClassIndex, // which class of constant is this?
|
|
BOOL bCustomOptOK,
|
|
IN PGLOBL pglobl
|
|
)
|
|
{
|
|
DWORD dwI, dwCount, dwStart , dwLen;
|
|
|
|
dwStart = gcieTable[dwClassIndex].dwStart ;
|
|
dwCount = gcieTable[dwClassIndex].dwCount ;
|
|
|
|
|
|
for(dwI = 0 ; dwI < dwCount ; dwI++)
|
|
{
|
|
dwLen = strlen(gConstantsTable[dwStart + dwI].pubName);
|
|
|
|
if((dwLen == parString->dwCount) &&
|
|
!strncmp(mpubOffRef + parString->loOffset,
|
|
gConstantsTable[dwStart + dwI].pubName,
|
|
dwLen) )
|
|
{
|
|
*pdwDest = gConstantsTable[dwStart + dwI].dwValue ;
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
if(bCustomOptOK)
|
|
{
|
|
if(gdwVerbosity >= 4)
|
|
{
|
|
#if defined(DEVSTUDIO) // This needs to be a one-liner
|
|
ERR(("Note: '%0.*s' is not a predefined member of enumeration class %s\n",
|
|
parString->dwCount , mpubOffRef + parString->loOffset,
|
|
gConstantsTable[dwStart - 1]));
|
|
#else
|
|
ERR(("Note: Feature/Option name not a predefined member of enumeration class %s\n",
|
|
gConstantsTable[dwStart - 1]));
|
|
ERR(("\t%0.*s\n", parString->dwCount , mpubOffRef + parString->loOffset )) ;
|
|
#endif
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if defined(DEVSTUDIO) // Same with this one...
|
|
ERR(("Error: '%0.*s'- user defined Option names not permitted for enumeration class %s\n",
|
|
parString->dwCount , mpubOffRef + parString->loOffset, gConstantsTable[dwStart - 1]));
|
|
#else
|
|
ERR(("Error: user defined Option names not permitted for enumeration class %s\n",
|
|
gConstantsTable[dwStart - 1]));
|
|
ERR(("\t%0.*s\n", parString->dwCount , mpubOffRef + parString->loOffset )) ;
|
|
#endif
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
|
|
BOOL BReadDataInGlobalNode(
|
|
PATREEREF patr, // address of field in GlobalAttrib struct
|
|
PDWORD pdwHeapOffset, // contents of attribute node.
|
|
PGLOBL pglobl
|
|
)
|
|
|
|
/*
|
|
this function will grab the first heap offset value it
|
|
encounters from the specified attribute tree root.
|
|
If the tree is multivalued, it selects the first
|
|
option of each level.
|
|
The high bit (if set) is cleared before the value is returned.
|
|
If root is uninitialized, returns FALSE, not an error condition
|
|
since GPD file is not required to initialize all fields.
|
|
*/
|
|
|
|
{
|
|
PATTRIB_TREE patt ; // start of ATTRIBUTE tree array.
|
|
DWORD dwNodeIndex ;
|
|
|
|
patt = (PATTRIB_TREE) gMasterTable[MTI_ATTRIBTREE].pubStruct ;
|
|
|
|
if(*patr == ATTRIB_UNINITIALIZED)
|
|
return(FALSE);
|
|
|
|
if(*patr & ATTRIB_HEAP_VALUE)
|
|
{
|
|
*pdwHeapOffset = *patr & ~ATTRIB_HEAP_VALUE ;
|
|
return(TRUE) ;
|
|
}
|
|
|
|
dwNodeIndex = *patr ;
|
|
if(patt[dwNodeIndex].dwFeature == DEFAULT_INIT)
|
|
{
|
|
*pdwHeapOffset = patt[dwNodeIndex].dwOffset ;
|
|
return(TRUE) ;
|
|
}
|
|
while(patt[dwNodeIndex].eOffsetMeans == NEXT_FEATURE)
|
|
{
|
|
// Down to the next level we go.
|
|
dwNodeIndex = patt[dwNodeIndex].dwOffset ;
|
|
}
|
|
if(patt[dwNodeIndex].eOffsetMeans == VALUE_AT_HEAP)
|
|
{
|
|
*pdwHeapOffset = patt[dwNodeIndex].dwOffset ;
|
|
return(TRUE) ;
|
|
}
|
|
else
|
|
return(FALSE) ;
|
|
} // BReadDataInGlobalNode(...)
|
|
|
|
|
|
// Following three functions
|
|
// Added on 9/30/98 in response to bug report 225088
|
|
|
|
// BsetUQMFlag() goes through the attrib trees rooted at
|
|
// atrDraftQualitySettings, atrBetterQualitySettings, atrBestQualitySettings,
|
|
// & atrDefaultQuality and checks for a feature dependency. If found,
|
|
// it updates the UpdateQualityMacro flag for that feature to TRUE.
|
|
|
|
BOOL BsetUQMFlag(
|
|
PGLOBL pglobl)
|
|
{
|
|
DWORD i; // Loop Counter.
|
|
PATTRIB_TREE patt;
|
|
ATREEREF atrAttribRoot;
|
|
BOOL bStatus = TRUE;
|
|
|
|
PGLOBALATTRIB pga =
|
|
(PGLOBALATTRIB)gMasterTable[MTI_GLOBALATTRIB].pubStruct ;
|
|
|
|
// List of features whose UQM flag needs to be updated.
|
|
ATREEREF patr[] = { pga->atrDraftQualitySettings,
|
|
pga->atrBetterQualitySettings,
|
|
pga->atrBestQualitySettings,
|
|
pga->atrDefaultQuality,
|
|
};
|
|
|
|
DWORD dwNumAttrib = sizeof(patr)/sizeof(ATREEREF);
|
|
|
|
patt = (PATTRIB_TREE) gMasterTable[MTI_ATTRIBTREE].pubStruct ;
|
|
|
|
|
|
// for the four quality settings
|
|
for ( i = 0; bStatus && (i < dwNumAttrib); i++)
|
|
{
|
|
atrAttribRoot = patr[i] ;
|
|
|
|
// It may be possible that only some of the four settings
|
|
// may occur. In that case, atrAttribRoot == ATTRIB_UNINITIALIZED
|
|
// only for those that dont occur.
|
|
if(atrAttribRoot == ATTRIB_UNINITIALIZED)
|
|
{
|
|
// Occurs probably because patr[i] e.g. DraftQualityMacro keyword
|
|
// appears no where in the .gpd. Continue and check whether other
|
|
// patr[i] occur.
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (atrAttribRoot & ATTRIB_HEAP_VALUE)
|
|
{
|
|
// Indicates there is no dependency
|
|
// of any feature. So we can safely
|
|
// ignore and continue with the
|
|
// next attribute.
|
|
continue;
|
|
}
|
|
|
|
|
|
// If the above two are not true, it means atrAttribRoot points
|
|
// to a valid node (in the attrib tree).
|
|
|
|
// In the tree, at most
|
|
// the first node can be the global default initializer:
|
|
// (as stated (in treewalk.c line 351) and interpreted (from
|
|
// state2.c function - BaddBranchToTree (...) ) )
|
|
// Therefore it is safe check for this condition only once,
|
|
// just before we start
|
|
// recursing down the tree. No need to check once within the tree.
|
|
|
|
|
|
// In a global default initializer!
|
|
// it may be assumed dwOffset contains heap offset.
|
|
// But we are concerned not with the heap value, but
|
|
// the next Node.
|
|
|
|
if(patt[atrAttribRoot].dwFeature == DEFAULT_INIT)
|
|
{
|
|
if ( patt[atrAttribRoot].dwNext == END_OF_LIST)
|
|
continue;
|
|
|
|
atrAttribRoot = patt[atrAttribRoot].dwNext ; // to the next node.
|
|
} //if
|
|
|
|
|
|
// Walk thru the tree and retrieve the features that are children
|
|
// of the tree rooted at atrAttribRoot.
|
|
|
|
bStatus = BRecurseNodes(atrAttribRoot, pglobl);
|
|
|
|
} //for
|
|
|
|
return bStatus;
|
|
} //BsetUQMFlag
|
|
|
|
|
|
// Recurse down the attribute tree. When we reach a feature we
|
|
// set its UQM flag to true by calling the function BsetUQMTrue(..)
|
|
// It is reasonable to assume that the dwFeature attribute in the
|
|
// structure pointed to by atrAttribNode contains a valid feature ID.
|
|
// The other special cases are handled in the previous function -
|
|
// BsetUQMFlag()
|
|
|
|
BOOL BRecurseNodes(
|
|
IN ATREEREF atrAttribNode,
|
|
IN OUT PGLOBL pglobl
|
|
)
|
|
{
|
|
PATTRIB_TREE patt;
|
|
BOOL bStatus = TRUE;
|
|
|
|
PDFEATURE_OPTIONS pfo =
|
|
(PDFEATURE_OPTIONS) (gMasterTable[MTI_DFEATURE_OPTIONS].pubStruct);
|
|
|
|
patt = (PATTRIB_TREE) gMasterTable[MTI_ATTRIBTREE].pubStruct ;
|
|
|
|
// Is it safe to assume that a new feature is encountered only
|
|
// when we go one level down the tree.
|
|
// Yes. Because the nodes at the same level have the SAME feature
|
|
// but DIFFERENT options.
|
|
|
|
|
|
// Hack. Since ColorMode is handled in a special way in the UI, the
|
|
// Quality Macro should not be executed for Color Mode.
|
|
if ((*(pfo + patt[atrAttribNode].dwFeature)).dwGID != GID_COLORMODE)
|
|
{
|
|
bStatus = BsetUQMTrue(patt[atrAttribNode].dwFeature, pglobl);
|
|
}
|
|
|
|
// Even though the trees of some gpd's (e.g. cnb5500.gpd) appear very
|
|
// uniform (i.e. most of the branches look similar), we cannot assume it
|
|
// to be true for all .gpd Therefore we have to go through
|
|
// all the branches of the tree.
|
|
|
|
for(; bStatus && atrAttribNode != END_OF_LIST;
|
|
atrAttribNode = patt[atrAttribNode].dwNext)
|
|
{
|
|
|
|
// This is what we are really interested in.
|
|
// Check if the node has a sublevel. Yes means another feature.
|
|
|
|
if( patt[atrAttribNode].eOffsetMeans == NEXT_FEATURE)
|
|
{
|
|
bStatus = BRecurseNodes(patt[atrAttribNode].dwOffset, pglobl);
|
|
|
|
}
|
|
} // for
|
|
|
|
return bStatus;
|
|
} // End of function BRecurseNodes(...)
|
|
|
|
|
|
|
|
BOOL BsetUQMTrue(
|
|
IN DWORD dwFeature,
|
|
IN OUT PGLOBL pglobl)
|
|
|
|
// For the feature dwFeature
|
|
// Set the UpdateQualityMacro Flag to true;
|
|
|
|
{
|
|
|
|
BOOL bStatus = TRUE;
|
|
DWORD dwTrue = BT_TRUE;
|
|
|
|
PDFEATURE_OPTIONS pfo =
|
|
(PDFEATURE_OPTIONS) (gMasterTable[MTI_DFEATURE_OPTIONS].pubStruct);
|
|
|
|
|
|
PATREEREF patrAttribRoot = &((*(pfo + dwFeature)).atrUpdateQualityMacro);
|
|
|
|
|
|
// The tree rooted at atrAttribRoot can either be uninitilized or
|
|
// have a pointer to a heap value.
|
|
// Any other case is a violation of the semantics.
|
|
|
|
|
|
if(*patrAttribRoot == ATTRIB_UNINITIALIZED)
|
|
{
|
|
// Put BT_TRUE in the heap and make *patrAttribRoot point to it.
|
|
// i.e. have *patrAttribRoot hold a dword that is an offset into
|
|
// the heap. It is then ORed with ATTRIB_HEAP_VALUE(which has
|
|
// MSB set to 1). The MSB indicates that the DWORD is a
|
|
// Heap Offset and not a ATTRIB_UNINITIALIZED, node index or any
|
|
// other value.
|
|
|
|
if((bStatus = BwriteToHeap((PDWORD)patrAttribRoot, (PBYTE)&dwTrue,
|
|
gValueToSize[VALUE_CONSTANT_BOOLEANTYPE], 4, pglobl) ) )
|
|
{
|
|
*patrAttribRoot |= ATTRIB_HEAP_VALUE ;
|
|
}
|
|
else {
|
|
*patrAttribRoot = ATTRIB_UNINITIALIZED ;
|
|
|
|
// The global Error variables have been set in BwriteToHeap().
|
|
}
|
|
|
|
|
|
return bStatus;
|
|
} //if(*patrAttribRoot == ATTRIB_UNINITIALIZED)
|
|
|
|
|
|
/*
|
|
Now comes the case when the user has specified the value of
|
|
UpdateQualityMacro to be TRUE or FALSE. If the value is TRUE
|
|
we still overwrite it with TRUE. If FALSE, we update it according
|
|
to the dependencies in the .gpd file.
|
|
Since we have reached here in the program, the dependencies
|
|
indicate that the UQM needs to be set to TRUE.
|
|
*/
|
|
|
|
else if (*patrAttribRoot & ATTRIB_HEAP_VALUE)
|
|
{
|
|
// The value should be a DWORD because UpdateQualityMacro's
|
|
// mMainKeywordTable[dwI].flAgs = 0 ; (file framwrk1.c line 1566)
|
|
// Therefore not checking for a list.
|
|
|
|
PDWORD pdwValue = (PDWORD) ( (PBYTE) mpubOffRef +
|
|
(*patrAttribRoot & ~ATTRIB_HEAP_VALUE) );
|
|
|
|
//Change to TRUE irrespective of its previous value.
|
|
*pdwValue = BT_TRUE; //Value in the heap changed to TRUE
|
|
}
|
|
|
|
// Since UpdateQualityMacro's
|
|
// mMainKeywordTable[dwI].dwSubType = ATT_LOCAL_FEATURE_ONLY
|
|
// (file framwrk1.c line 1574)
|
|
// (i.e. it is not a free-float type), it cannot have a
|
|
// sub-tree. So it should not point to another node.
|
|
//
|
|
// The following condition should never be true because UQM cannot
|
|
// have a DEFAULT_INIT
|
|
// if(patt[*patrAttribRoot].dwFeature == DEFAULT_INIT)
|
|
// Reason : It cannot form a tree (reason as explained above).
|
|
//
|
|
//Thus control should never reach here.
|
|
else {
|
|
PATTRIB_TREE patt =
|
|
(PATTRIB_TREE) gMasterTable[MTI_ATTRIBTREE].pubStruct ;
|
|
|
|
if(patt[*patrAttribRoot].dwFeature == DEFAULT_INIT) {
|
|
ERR(("Warning: unexpected value atrUpdateQualityMacro ATREEREF\n"));
|
|
}
|
|
else {
|
|
ERR(("Warning: atrUpdateQualityMacro ATREEREF points to a tree. \
|
|
Unexpected Condition\n"));
|
|
}
|
|
ERR(("Unexpected condition encountered while processing Quality Macros\n "));
|
|
|
|
geErrorType = ERRTY_SYNTAX ;
|
|
geErrorSev = ERRSEV_FATAL ;
|
|
bStatus = FALSE;
|
|
}
|
|
|
|
return bStatus;
|
|
} //BsetUQMTrue(...)
|
|
|
|
// End of 3 functions added on 9/30/98 in response to
|
|
// bug report no. 225088
|
|
|
|
|
|
|
|
|
|
|
|
VOID VCountPrinterDocStickyFeatures(
|
|
PGLOBL pglobl)
|
|
{
|
|
PDFEATURE_OPTIONS pfo ;
|
|
DWORD dwHeapOffset, dwCount, dwI ;
|
|
|
|
// extern MINIRAWBINARYDATA gmrbd ;
|
|
// Not required now as it is part of the PGLOBL structure.
|
|
|
|
|
|
pfo = (PDFEATURE_OPTIONS) gMasterTable[MTI_DFEATURE_OPTIONS].pubStruct ;
|
|
dwCount = gMasterTable[MTI_DFEATURE_OPTIONS].dwArraySize ;
|
|
|
|
gmrbd.rbd.dwDocumentFeatures = 0 ;
|
|
gmrbd.rbd.dwPrinterFeatures =
|
|
gMasterTable[MTI_SYNTHESIZED_FEATURES].dwArraySize ;
|
|
|
|
for(dwI = 0 ; dwI < dwCount ; dwI++)
|
|
{
|
|
if(BReadDataInGlobalNode(&pfo[dwI].atrFeatureType,
|
|
&dwHeapOffset, pglobl) &&
|
|
*(PDWORD)(mpubOffRef + dwHeapOffset) == FT_PRINTERPROPERTY)
|
|
gmrbd.rbd.dwPrinterFeatures++ ;
|
|
else
|
|
gmrbd.rbd.dwDocumentFeatures++ ;
|
|
}
|
|
} // VCountPrinterDocStickyFeatures()
|
|
|
|
|
|
BOOL BConvertSpecVersionToDWORD(
|
|
PWSTR pwstrFileName,
|
|
PGLOBL pglobl
|
|
)
|
|
// also used to prepend absolute path to resource Dll name.
|
|
{
|
|
BOOL bStatus ;
|
|
DWORD dwMajor, dwMinor, dwHeapOffset, dwDelim, dwDummy, dwByteCount;
|
|
// WCHAR awchDLLQualifiedName[MAX_PATH];
|
|
PWSTR pwstrLastBackSlash, pwstrDLLName,
|
|
pwstrDataFileName = NULL;
|
|
ABSARRAYREF aarValue, aarToken ;
|
|
PGLOBALATTRIB pga ;
|
|
DWORD pathlen = 0 ;
|
|
DWORD namelen = 0 ;
|
|
WCHAR * pwDLLQualifiedName = NULL ;
|
|
|
|
// extern MINIRAWBINARYDATA gmrbd ;
|
|
// Not required now as it is part of the PGLOBL structure.
|
|
|
|
|
|
pga = (PGLOBALATTRIB)gMasterTable[MTI_GLOBALATTRIB].pubStruct ;
|
|
|
|
|
|
if(!BReadDataInGlobalNode(&pga->atrGPDSpecVersion ,
|
|
&dwHeapOffset, pglobl) )
|
|
{
|
|
ERR(("Missing required keyword: *GPDSpecVersion.\n"));
|
|
return(FALSE);
|
|
}
|
|
|
|
aarValue.dw = ((PARRAYREF)(mpubOffRef + dwHeapOffset))->dwCount ;
|
|
aarValue.pub = mpubOffRef +
|
|
((PARRAYREF)(mpubOffRef + dwHeapOffset))->loOffset ;
|
|
|
|
bStatus = BdelimitToken(&aarValue, ".", &aarToken, &dwDelim) ;
|
|
|
|
if(bStatus)
|
|
bStatus = BparseInteger(&aarToken, &dwMajor, VALUE_INTEGER, pglobl) ;
|
|
|
|
if(bStatus)
|
|
bStatus = BparseInteger(&aarValue, &dwMinor, VALUE_INTEGER, pglobl) ;
|
|
|
|
if(bStatus)
|
|
{
|
|
gmrbd.dwSpecVersion = dwMajor << 16; // place in HiWord
|
|
gmrbd.dwSpecVersion |= dwMinor & 0xffff; // place in LoWord
|
|
}
|
|
else
|
|
{
|
|
ERR(("BConvertSpecVersionToDWORD: syntax error in *GPDSpecVersion value. unknown version.\n"));
|
|
}
|
|
|
|
|
|
// -------- now to fix up the helpfile name. ------ //
|
|
|
|
if(!BReadDataInGlobalNode(&pga->atrHelpFile ,
|
|
&dwHeapOffset, pglobl) )
|
|
{
|
|
goto FIX_RESDLLNAME; // GPD doesn't have this keyword
|
|
}
|
|
|
|
pwstrDLLName = (PWSTR)(mpubOffRef +
|
|
((PARRAYREF)(mpubOffRef + dwHeapOffset))->loOffset) ;
|
|
|
|
|
|
// how large should pwDLLQualifiedName be???
|
|
|
|
pathlen = wcslen(pwstrFileName) ;
|
|
namelen = pathlen + wcslen(pwstrDLLName) + 1;
|
|
|
|
if(!(pwDLLQualifiedName = (PWSTR)MemAllocZ(namelen * sizeof(WCHAR)) ))
|
|
{
|
|
ERR(("Fatal: unable to alloc memory for pwDLLQualifiedName: %d WCHARs.\n",
|
|
namelen));
|
|
geErrorType = ERRTY_MEMORY_ALLOCATION ;
|
|
geErrorSev = ERRSEV_FATAL ;
|
|
return(FALSE) ; // This is unrecoverable
|
|
}
|
|
|
|
|
|
wcsncpy(pwDLLQualifiedName, pwstrFileName , namelen);
|
|
|
|
if (pwstrLastBackSlash = wcsrchr(pwDLLQualifiedName,TEXT('\\')))
|
|
{
|
|
*(pwstrLastBackSlash + 1) = NUL;
|
|
|
|
//Find a BackSlash in the Source DLL Name.
|
|
pwstrDataFileName = wcsrchr( pwstrDLLName, TEXT('\\') );
|
|
|
|
//Increment the pointer to first char of the DLL Name.
|
|
if (pwstrDataFileName)
|
|
pwstrDataFileName++;
|
|
else
|
|
pwstrDataFileName = pwstrDLLName;
|
|
|
|
// wcscat(pwDLLQualifiedName, pwstrDataFileName) ;
|
|
StringCchCatW(pwDLLQualifiedName, namelen, pwstrDataFileName);
|
|
|
|
((PARRAYREF)(mpubOffRef + dwHeapOffset))->dwCount =
|
|
dwByteCount =
|
|
wcslen(pwDLLQualifiedName) * sizeof(WCHAR) ;
|
|
|
|
|
|
if(BwriteToHeap(&((PARRAYREF)(mpubOffRef + dwHeapOffset))->loOffset,
|
|
// Store heap offset of dest string here.
|
|
(PBYTE) pwDLLQualifiedName, dwByteCount, 2, pglobl) )
|
|
{
|
|
// add NUL terminator.
|
|
BwriteToHeap(&dwDummy, "\0\0", 2, 1, pglobl) ;
|
|
goto FIX_RESDLLNAME;
|
|
}
|
|
|
|
bStatus = FALSE ;
|
|
}
|
|
|
|
|
|
|
|
|
|
// -------- now to fix up the resource Dll name. ------ //
|
|
|
|
FIX_RESDLLNAME:
|
|
|
|
if(pwDLLQualifiedName)
|
|
MemFree(pwDLLQualifiedName) ;
|
|
|
|
#if 0 // fix for bug 34042
|
|
if(!BReadDataInGlobalNode(&pga->atrResourceDLL ,
|
|
&dwHeapOffset, pglobl) )
|
|
{
|
|
// return(bStatus); // GPD doesn't have this keyword
|
|
// create a dummy filename!
|
|
|
|
PATREEREF patr ;
|
|
ARRAYREF arDummyName ;
|
|
|
|
arDummyName.dwCount = wcslen(TEXT("No_Res")) * sizeof(WCHAR) ;
|
|
if(!BwriteToHeap(&arDummyName.loOffset,
|
|
(PBYTE)TEXT("No_Res\0"), arDummyName.dwCount + sizeof(WCHAR), 2, pglobl) )
|
|
// note: add null terminator or strcat will derail.
|
|
{
|
|
bStatus = FALSE ; // heap overflow start over.
|
|
}
|
|
|
|
patr = &pga->atrResourceDLL ;
|
|
if(!BwriteToHeap(patr, (PBYTE)(&arDummyName) , sizeof(ARRAYREF), 4, pglobl) )
|
|
{
|
|
bStatus = FALSE ; // heap overflow start over.
|
|
}
|
|
dwHeapOffset = *patr ;
|
|
*patr |= ATTRIB_HEAP_VALUE ;
|
|
}
|
|
// #if 0 move this to new location 25 lines up. fix for bug 34042
|
|
// ganesh's winres lib will take care of prepending fully qualified path...
|
|
|
|
pwstrDLLName = (PWSTR)(mpubOffRef +
|
|
((PARRAYREF)(mpubOffRef + dwHeapOffset))->loOffset) ;
|
|
|
|
|
|
wcsncpy(awchDLLQualifiedName, pwstrFileName , MAX_PATH -1);
|
|
|
|
if (pwstrLastBackSlash = wcsrchr(awchDLLQualifiedName,TEXT('\\')))
|
|
{
|
|
*(pwstrLastBackSlash + 1) = NUL;
|
|
|
|
//Find a BackSlash in the Source DLL Name.
|
|
pwstrDataFileName = wcsrchr( pwstrDLLName, TEXT('\\') );
|
|
|
|
//Increment the pointer to first char of the DLL Name.
|
|
if (pwstrDataFileName)
|
|
pwstrDataFileName++;
|
|
else
|
|
pwstrDataFileName = pwstrDLLName;
|
|
|
|
wcscat(awchDLLQualifiedName, pwstrDataFileName) ;
|
|
|
|
((PARRAYREF)(mpubOffRef + dwHeapOffset))->dwCount =
|
|
dwByteCount =
|
|
wcslen(awchDLLQualifiedName) * sizeof(WCHAR) ;
|
|
|
|
|
|
if(BwriteToHeap(&((PARRAYREF)(mpubOffRef + dwHeapOffset))->loOffset,
|
|
// Store heap offset of dest string here.
|
|
(PBYTE) awchDLLQualifiedName, dwByteCount, 2, pglobl) )
|
|
{
|
|
// add NUL terminator.
|
|
BwriteToHeap(&dwDummy, "\0\0", 2, 1, pglobl) ;
|
|
return(bStatus) ;
|
|
}
|
|
|
|
return(FALSE) ;
|
|
}
|
|
#endif
|
|
return(bStatus) ;
|
|
} // BConvertSpecVersionToDWORD(...)
|
|
|
|
|
|
BOOL BinitMiniRawBinaryData(
|
|
PGLOBL pglobl)
|
|
{
|
|
gmrbd.rbd.dwParserSignature = GPD_PARSER_SIGNATURE ;
|
|
gmrbd.rbd.dwParserVersion = GPD_PARSER_VERSION ;
|
|
gmrbd.rbd.pvReserved = NULL;
|
|
return(TRUE) ;
|
|
} //BinitMiniRawBinaryData()
|
|
|
|
|
|
BOOL BexchangeArbDataInFOATNode(
|
|
DWORD dwFeature,
|
|
DWORD dwOption,
|
|
DWORD dwFieldOff, // offset of field in FeatureOption struct
|
|
DWORD dwCount, // number bytes to copy.
|
|
OUT PBYTE pubOut, // previous contents of attribute node
|
|
IN PBYTE pubIn, // new contents of attribute node.
|
|
PBOOL pbPrevsExists, // previous contents existed.
|
|
BOOL bSynthetic, // access synthetic features
|
|
PGLOBL pglobl
|
|
)
|
|
/*
|
|
'FOAT' means FeatureOption AttributeTree.
|
|
this function writes or overwrites the byte string specified by
|
|
pubIn into the heap at the location indicated by the attribute tree
|
|
HeapOffset field. The previous contents at HeapOffset is saved to
|
|
pubOut and pbPrevsExists is set to TRUE. If pubIn is NULL,
|
|
the current attribute tree is not altered.
|
|
|
|
The parameters dwFeature, dwOption, dwFieldOffset specify
|
|
the structure, field, and branch of the attribute tree.
|
|
If the specified option branch does not exist, one will be created,
|
|
pubOut may be set to NULL if the previous content is unimportant.
|
|
Assumptions:
|
|
The tree being accessed is strictly one level deep. That is the
|
|
node is fully specified by just Feature, Option. No default initializers.
|
|
*/
|
|
{
|
|
PATTRIB_TREE patt ; // start of ATTRIBUTE tree array.
|
|
PATREEREF patr ;
|
|
ATREEREF atrCur ; // contains index of currently used attribute node.
|
|
|
|
DWORD dwFeaOffset ; // Start numbering features from this
|
|
// starting point. This gives synthetic
|
|
// features a separate non-overlapping number
|
|
// space from normal features.
|
|
|
|
PDFEATURE_OPTIONS pfo ;
|
|
|
|
|
|
if(bSynthetic)
|
|
{
|
|
pfo = (PDFEATURE_OPTIONS) gMasterTable[MTI_SYNTHESIZED_FEATURES].pubStruct +
|
|
dwFeature ;
|
|
dwFeaOffset = gMasterTable[MTI_DFEATURE_OPTIONS].dwArraySize ;
|
|
}
|
|
else
|
|
{
|
|
pfo = (PDFEATURE_OPTIONS) gMasterTable[MTI_DFEATURE_OPTIONS].pubStruct +
|
|
dwFeature ;
|
|
dwFeaOffset = 0 ;
|
|
}
|
|
|
|
patt = (PATTRIB_TREE) gMasterTable[MTI_ATTRIBTREE].pubStruct ;
|
|
|
|
patr = (PATREEREF)((PBYTE)pfo + dwFieldOff) ;
|
|
atrCur = *patr ;
|
|
|
|
if(atrCur == ATTRIB_UNINITIALIZED)
|
|
{
|
|
if(pubIn)
|
|
{
|
|
if(!BcreateEndNode(patr, dwFeature + dwFeaOffset , dwOption, pglobl) )
|
|
return(FALSE) ; // resource exhaustion
|
|
if(!BwriteToHeap(&(patt[*patr].dwOffset), pubIn,
|
|
dwCount, 4, pglobl) )
|
|
return(FALSE) ; // A fatal error.
|
|
patt[*patr].eOffsetMeans = VALUE_AT_HEAP ;
|
|
}
|
|
*pbPrevsExists = FALSE ;
|
|
return(TRUE) ;
|
|
}
|
|
|
|
if(atrCur & ATTRIB_HEAP_VALUE)
|
|
{
|
|
ERR(("Internal error. BexchangeArbDataInFOATNode should never create a branchless node.\n"));
|
|
return(FALSE) ;
|
|
}
|
|
|
|
// offset field contains index to another node
|
|
// but we will tack the new node (if any) after
|
|
// the existing node. Don't change patr.
|
|
|
|
if(pubIn)
|
|
{
|
|
if(!BfindOrCreateMatchingNode(atrCur, &atrCur, dwFeature + dwFeaOffset , dwOption, pglobl))
|
|
return(FALSE) ; // Tree inconsistency error or resource exhaustion
|
|
|
|
if(patt[atrCur].eOffsetMeans != VALUE_AT_HEAP)
|
|
{
|
|
// just created a new node.
|
|
if(!BwriteToHeap(&(patt[atrCur].dwOffset), pubIn, dwCount, 4, pglobl) )
|
|
return(FALSE) ; // A fatal error.
|
|
patt[atrCur].eOffsetMeans = VALUE_AT_HEAP ;
|
|
*pbPrevsExists = FALSE ;
|
|
return(TRUE) ;
|
|
}
|
|
|
|
if(pubOut)
|
|
memcpy(pubOut, mpubOffRef + patt[atrCur].dwOffset, dwCount) ;
|
|
memcpy(mpubOffRef + patt[atrCur].dwOffset, pubIn, dwCount) ;
|
|
}
|
|
else
|
|
{
|
|
if(!BfindMatchingNode(atrCur, &atrCur, dwFeature + dwFeaOffset , dwOption, pglobl))
|
|
{
|
|
*pbPrevsExists = FALSE ; // nothing found, don't create.
|
|
return(TRUE) ;
|
|
}
|
|
if(pubOut)
|
|
memcpy(pubOut, mpubOffRef + patt[atrCur].dwOffset, dwCount) ;
|
|
}
|
|
*pbPrevsExists = TRUE ;
|
|
return(TRUE) ;
|
|
} // BexchangeArbDataInFOATNode(...)
|
|
|
|
|
|
|
|
|
|
typedef struct
|
|
{
|
|
DWORD dwUserPriority ;
|
|
DWORD dwNext ; // index of feature with a equal or greater
|
|
// numerical value for dwUserPriority .
|
|
} PRIORITY_NODE, *PPRIORITY_NODE ; // the prefix tag shall be 'pn'
|
|
|
|
|
|
BOOL BInitPriorityArray(
|
|
PGLOBL pglobl)
|
|
{
|
|
|
|
DWORD dwNumFea, dwFea, dwPrnStickyroot, dwDocStickyroot,
|
|
dwPrevsNode, dwCurNode, dwNumSyn, dwIndex, dwHeapOffset,
|
|
adwDefaultPriority[MAX_GID];
|
|
PDWORD pdwRoot, pdwPriority ;
|
|
|
|
PDFEATURE_OPTIONS pfo ;
|
|
PPRIORITY_NODE pnPri ;
|
|
BOOL bPrinterSticky ;
|
|
|
|
|
|
|
|
// init adwDefaultPriority[], the default priorities
|
|
// are very low compared to any value a user may
|
|
// explicitly assign.
|
|
// The last term is the priority starting from 0 = highest.
|
|
|
|
for(dwIndex = 0 ; dwIndex < MAX_GID ; dwIndex++)
|
|
{
|
|
adwDefaultPriority[dwIndex] = 0xffffffff ; // default if not enum below.
|
|
}
|
|
|
|
adwDefaultPriority[GID_PAGESIZE] = 0xffffffff - MAX_GID + 0 ;
|
|
adwDefaultPriority[GID_INPUTSLOT] = 0xffffffff - MAX_GID + 1 ;
|
|
adwDefaultPriority[GID_ORIENTATION] = 0xffffffff - MAX_GID + 2 ;
|
|
adwDefaultPriority[GID_COLORMODE] = 0xffffffff - MAX_GID + 3 ;
|
|
adwDefaultPriority[GID_DUPLEX] = 0xffffffff - MAX_GID + 4 ;
|
|
adwDefaultPriority[GID_MEDIATYPE] = 0xffffffff - MAX_GID + 5 ;
|
|
adwDefaultPriority[GID_RESOLUTION] = 0xffffffff - MAX_GID + 6 ;
|
|
adwDefaultPriority[GID_HALFTONING] = 0xffffffff - MAX_GID + 7 ;
|
|
|
|
dwPrnStickyroot = dwDocStickyroot = INVALID_INDEX ;
|
|
|
|
pfo = (PDFEATURE_OPTIONS) gMasterTable[MTI_DFEATURE_OPTIONS].pubStruct;
|
|
dwNumFea = gMasterTable[MTI_DFEATURE_OPTIONS].dwArraySize ;
|
|
|
|
if(!(pnPri = MemAllocZ(dwNumFea * sizeof(PRIORITY_NODE)) ))
|
|
{
|
|
ERR(("Fatal: BInitPriorityArray - unable to alloc %d bytes.\n",
|
|
dwNumFea * sizeof(PRIORITY_NODE)));
|
|
|
|
geErrorType = ERRTY_MEMORY_ALLOCATION ;
|
|
geErrorSev = ERRSEV_FATAL ;
|
|
gdwMasterTabIndex = 0xffff ;
|
|
|
|
return(FALSE) ; // This is unrecoverable
|
|
}
|
|
|
|
for(dwFea = 0 ; dwFea < dwNumFea ; dwFea++)
|
|
{
|
|
if(BReadDataInGlobalNode(&pfo[dwFea].atrFeatureType , &dwHeapOffset, pglobl)
|
|
&& *(PDWORD)(mpubOffRef + dwHeapOffset) == FT_PRINTERPROPERTY)
|
|
bPrinterSticky = TRUE ;
|
|
else
|
|
bPrinterSticky = FALSE ;
|
|
|
|
if(BReadDataInGlobalNode(&pfo[dwFea].atrPriority , &dwHeapOffset, pglobl))
|
|
{
|
|
pnPri[dwFea].dwUserPriority =
|
|
*(PDWORD)(mpubOffRef + dwHeapOffset) ;
|
|
}
|
|
else
|
|
{
|
|
pnPri[dwFea].dwUserPriority = 0xffffffff; // lowest priority
|
|
if(pfo[dwFea].dwGID != GID_UNKNOWN)
|
|
{
|
|
pnPri[dwFea].dwUserPriority = adwDefaultPriority[pfo[dwFea].dwGID] ;
|
|
}
|
|
}
|
|
|
|
pdwRoot = (bPrinterSticky ) ? &dwPrnStickyroot : &dwDocStickyroot ;
|
|
|
|
dwCurNode = *pdwRoot ;
|
|
dwPrevsNode = INVALID_INDEX ;
|
|
while(dwCurNode != INVALID_INDEX)
|
|
{
|
|
if(pnPri[dwFea].dwUserPriority <= pnPri[dwCurNode].dwUserPriority)
|
|
break ;
|
|
dwPrevsNode = dwCurNode ;
|
|
dwCurNode = pnPri[dwCurNode].dwNext ;
|
|
}
|
|
|
|
if(dwPrevsNode == INVALID_INDEX)
|
|
*pdwRoot = dwFea ; // first on the list.
|
|
else
|
|
pnPri[dwPrevsNode].dwNext = dwFea ;
|
|
|
|
pnPri[dwFea].dwNext = dwCurNode ;
|
|
}
|
|
|
|
// pdwPriority array holds index of all features
|
|
// including synthesized - which are assigned indicies
|
|
// dwFea >= dwNumFea. The feature indicies are ordered
|
|
// with the highest priority feature index occupying
|
|
// pdwPriority[0].
|
|
|
|
dwNumSyn = gMasterTable[MTI_SYNTHESIZED_FEATURES].dwArraySize ;
|
|
|
|
pdwPriority = (PDWORD)gMasterTable[MTI_PRIORITYARRAY].pubStruct ;
|
|
|
|
for(dwIndex = 0 ; dwIndex < dwNumSyn ; dwIndex++)
|
|
{
|
|
pdwPriority[dwIndex] = dwIndex + dwNumFea ;
|
|
// take all synthesized features and assign them
|
|
// the highest pri.
|
|
}
|
|
|
|
for(dwCurNode = dwPrnStickyroot ; dwCurNode != INVALID_INDEX ;
|
|
dwIndex++ )
|
|
{
|
|
pdwPriority[dwIndex] = dwCurNode ;
|
|
dwCurNode = pnPri[dwCurNode].dwNext ;
|
|
}
|
|
|
|
for(dwCurNode = dwDocStickyroot ; dwCurNode != INVALID_INDEX ;
|
|
dwIndex++ )
|
|
{
|
|
pdwPriority[dwIndex] = dwCurNode ;
|
|
dwCurNode = pnPri[dwCurNode].dwNext ;
|
|
}
|
|
|
|
ASSERT(dwIndex == gMasterTable[MTI_PRIORITYARRAY].dwArraySize) ;
|
|
|
|
MemFree(pnPri) ;
|
|
return(TRUE);
|
|
|
|
} //BInitPriorityArray ()
|
|
|
|
|
|
|