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.
 
 
 
 
 
 

503 lines
13 KiB

/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
pass2.cpp
Abstract:
Functions for additional checking of a PPD file
Environment:
PostScript driver, PPD parser
Revision History:
09/15/98 -rorleth-
Created it.
--*/
#include <lib.h>
#include <iostream.h>
#include "pass2.h"
enum FeatureId
{
FID_PAGE_SIZE,
FID_PAGE_REGION,
FID_INPUT_SLOT,
FID_SMOOTHING,
FID_MEDIA_COLOR,
FID_MEDIA_TYPE,
FID_MEDIA_WEIGHT,
FID_OUTPUT_MODE,
FID_PAPER_DIMENSION,
FID_IMAGE_AREA,
FID_OUTPUT_ORDER,
NO_OF_FEATURES
};
typedef struct _PPD_FEATURE
{
FeatureId eId;
LPSTR lpszName;
} PPD_FEATURE, *PPPD_FEATURE;
//
// features whose options we have to check
//
static PPD_FEATURE aCheckFeat[] =
{
{ FID_PAGE_SIZE, "PageSize" },
{ FID_PAGE_REGION, "PageRegion" },
{ FID_INPUT_SLOT, "InputSlot" },
{ FID_SMOOTHING, "Smoothing" },
{ FID_MEDIA_COLOR, "MediaColor" },
{ FID_MEDIA_TYPE, "MediaType" },
{ FID_MEDIA_WEIGHT, "MediaWeight" },
{ FID_OUTPUT_MODE, "OutputMode" },
{ FID_PAPER_DIMENSION, "PaperDimension" },
{ FID_IMAGE_AREA, "ImageableArea" },
{ FID_OUTPUT_ORDER, "OutputOrder" },
{ NO_OF_FEATURES, NULL}
};
typedef struct _PPD_OPTION
{
FeatureId eId;
LPSTR lpszName;
} PPD_OPTION, *PPPD_OPTION;
//
// keywords that require defined feature options
//
static PPD_OPTION gaCheckKeyword[] =
{
{ FID_INPUT_SLOT, "RequiresPageRegion"},
{ NO_OF_FEATURES, NULL }
};
//
// special option names
//
static PPD_OPTION gaSpecialOptions[] =
{
{ NO_OF_FEATURES, "None" }, // NO_OF_FEATURES means valid for all features in that case
{ NO_OF_FEATURES, "All" },
{ NO_OF_FEATURES, "Unknown" },
{ FID_OUTPUT_ORDER, "Normal" }, // Normal and Reverse are predefined options for OutputOrder
{ FID_OUTPUT_ORDER, "Reverse" },
{ NO_OF_FEATURES, NULL},
};
//
// keywords that have a length limitation for the UI
//
typedef struct _PPD_LENGTH_CHECK
{
FeatureId eId;
size_t iMaxLen;
} PPD_LENGTH_CHECK, *PPPD_LENGTH_CHECK;
static PPD_LENGTH_CHECK gaCheckLength[] =
{
{ FID_INPUT_SLOT, 23},
{ NO_OF_FEATURES, 0 }
};
const char *pDefaultKeyword = "Default";
const int MaxOptionNameLen = 40;
const int MaxTranslationNameLen = 128;
typedef struct _OPTION_LIST
{
char aName[MaxOptionNameLen+1];
char aTransName[MaxTranslationNameLen+1];
_OPTION_LIST *pNext;
} OPTION_LIST, *POPTION_LIST;
static POPTION_LIST gaOptionList[NO_OF_FEATURES]; // stores all defined options
/*++
Routine Description:
checks whether a references option is defined
Arguments:
char **ppString : Pointer to pointer to option, is advanced by the option name length
FeatureId FeatId : ID of the feature, which should have the option
char *pOptionName: pointer to buffer, where the option name shall be stored for error messages
Return Value:
TRUE if the identified feature has that option, FALSE if not
--*/
static BOOL IsOptionDefined(char **ppString, FeatureId FeatId, char *pOptionName)
{
char *pEndName, *pName = *ppString;
while (isspace(*pName))
pName++;
pEndName = strpbrk(pName, "/: \t\n\r\0");
*ppString = pEndName; // advance current pointer
strncpy(pOptionName, pName, min((DWORD)(pEndName - pName), MaxOptionNameLen));
pOptionName[pEndName-pName] = 0;
//
// check special cases that do not have to be defined
//
int i=0;
while (gaSpecialOptions[i].lpszName != NULL)
{
if ((gaSpecialOptions[i].eId == NO_OF_FEATURES) ||
(gaSpecialOptions[i].eId == FeatId))
{
if (!strcmp(gaSpecialOptions[i].lpszName, pOptionName))
return TRUE;
}
i++;
}
POPTION_LIST pList = gaOptionList[FeatId], pNew;
while (pList != NULL)
{
if (!strcmp(pList->aName, pOptionName))
return TRUE; // found it, it's defined
pList = pList->pNext;
}
return FALSE;
}
/*++
Routine Description:
checks a whole PPD-file, whether all referenced options are defined
Arguments:
PTSTR FileName: Name of the PPD-file to check
--*/
extern "C" void CheckOptionIntegrity(PTSTR ptstrPpdFilename)
{
ZeroMemory(gaOptionList, sizeof(gaOptionList)); // initialise the list header
_flushall(); // to avoid sync problems with the DbgPrint output
//
// create the file mapping
//
HANDLE hFile = CreateFile(ptstrPpdFilename, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
return;
}
DWORD dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize == 0xffffffff)
{
CloseHandle(hFile);
return;
}
HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY,0, 0,NULL);
if (hMap == NULL)
{
CloseHandle(hFile);
return;
}
LPCVOID pView = MapViewOfFile(hMap, FILE_MAP_READ, 0,0,0);
if (pView == NULL)
{
CloseHandle(hMap);
CloseHandle(hFile);
return;
}
//
// copy the whole file into an allocated buffer just to get zero-termination
//
LPSTR pFile, pFileStart;
pFileStart = (LPSTR) VirtualAlloc(NULL, dwFileSize+1, MEM_COMMIT, PAGE_READWRITE);
if (pFileStart != NULL)
{
CopyMemory(pFileStart, pView, dwFileSize);
*(pFileStart + dwFileSize) = 0;
}
UnmapViewOfFile(pView);
CloseHandle(hMap);
CloseHandle(hFile);
if (pFileStart == NULL)
{
cout << "ppdcheck.exe out of memory" << endl;
return;
}
pFile = pFileStart;
//
// now the whole PPD-file is a giant string
// extract all the features/options
//
char *pCurOption = (char *) pFileStart;
char OptionName[MaxOptionNameLen+1];
//
// step 1 : extract all valid feature options
//
while ((pFile != NULL) &&
(pCurOption = strchr(pFile, '*')) != NULL)
{
pCurOption++;
char *pNextLine = strpbrk(pCurOption, "\n\r");
pFile = pNextLine;
if (*pCurOption == '%') // skip comments
continue;
//
// scan whether this is one of the features to look for
//
int Index = 0;
while (aCheckFeat[Index].eId != NO_OF_FEATURES)
{
if (strncmp(aCheckFeat[Index].lpszName, pCurOption, strlen(aCheckFeat[Index].lpszName)))
{
Index++;
continue;
}
//
// this is one of the monitored features: make entry in list
//
POPTION_LIST pList = gaOptionList[aCheckFeat[Index].eId], pNew;
pNew = new OPTION_LIST;
pNew->pNext = gaOptionList[aCheckFeat[Index].eId];
gaOptionList[aCheckFeat[Index].eId] = pNew;
char *pName = pCurOption + strlen(aCheckFeat[Index].lpszName), *pEndName;
while (isspace(*pName))
pName++;
pEndName = strpbrk(pName, "/: \0");
DWORD dwNameLen = min((DWORD)(pEndName - pName), MaxOptionNameLen);
strncpy(pNew->aName, pName, dwNameLen);
pNew->aName[dwNameLen] = 0;
dwNameLen = 0;
if (*pEndName == '/') // there is a translation string
{
pName = pEndName +1;
pEndName = strpbrk(pName, ":\n\r\0");
dwNameLen = min((DWORD) (pEndName - pName), MaxTranslationNameLen);
strncpy(pNew->aTransName, pName, dwNameLen);
}
pNew->aTransName[dwNameLen] = 0;
break;
}
}
//
// step 2: check whether all referenced options are featured
//
pFile = pFileStart;
pCurOption = (char *) pFile;
while ((pFile != NULL) &&
(pCurOption = strchr(pFile, '*')) != NULL)
{
pCurOption++;
char *pNextLine = strpbrk(pCurOption, "\n\r");
pFile = pNextLine;
//
// skip comments
//
if (*pCurOption == '%')
continue;
//
// check whether it starts with "Default", if yes, check that feature option
//
if (!strncmp(pDefaultKeyword, pCurOption, strlen(pDefaultKeyword)))
{
pCurOption += strlen(pDefaultKeyword);
int Index = 0;
while (aCheckFeat[Index].eId != NO_OF_FEATURES)
{
if (strncmp(aCheckFeat[Index].lpszName, pCurOption, strlen(aCheckFeat[Index].lpszName)))
{
Index++;
continue;
}
//
// it's one of the checked featurs
//
pCurOption += strlen(aCheckFeat[Index].lpszName);
char *pOption = strpbrk(pCurOption, ":");
if (pOption == NULL)
{
cout << "Warning: default option for '" << aCheckFeat[Index].lpszName << "' is not completed !" << endl;
break;
}
pCurOption = pOption + 1;
if (!IsOptionDefined(&pCurOption, aCheckFeat[Index].eId, OptionName))
cout << "Warning: default option '" << OptionName << "' for feature '*" << aCheckFeat[Index].lpszName <<"' is not defined!" << endl;
break;
}
}
else
{
//
// scan whether this is one of the keywords to look for
//
int Index = 0;
while (gaCheckKeyword[Index].eId != NO_OF_FEATURES)
{
if (strncmp(gaCheckKeyword[Index].lpszName, pCurOption, strlen(gaCheckKeyword[Index].lpszName)))
{
Index++;
continue;
}
//
// this is one of the monitored features: get the option it references
//
pCurOption += strlen(gaCheckKeyword[Index].lpszName);
if (!IsOptionDefined(&pCurOption, gaCheckKeyword[Index].eId, OptionName))
cout << "Warning: option '" << OptionName << "' for keyword '*" << gaCheckKeyword[Index].lpszName <<"' is not defined!" << endl;
break;
}
Index++;
}
}
//
// step 3: check that all option names are different and don't have trailing or leading spaces
//
for (int i = 0; i < NO_OF_FEATURES;i++)
{
POPTION_LIST pCheck = gaOptionList[i], pCur;
while (pCheck != NULL)
{
pCur = pCheck->pNext;
while (pCur != NULL)
{
if (strlen(pCheck->aName) &&
!strcmp(pCheck->aName, pCur->aName))
cout << "Warning: option name '" << pCheck->aName << "' used twice" << endl;
if (strlen(pCheck->aTransName) &&
!strcmp(pCheck->aTransName, pCur->aTransName))
cout << "Warning: translation name '" << pCheck->aTransName << "' used twice" << endl;
pCur = pCur->pNext;
}
size_t TransNameLen = strlen(pCheck->aTransName);
if (isspace(pCheck->aTransName[0]))
cout << "Warning: translation name '" << pCheck->aTransName << "' has leading whitespace" << endl;
if ((TransNameLen > 1) &&
isspace(pCheck->aTransName[TransNameLen-1]))
cout << "Warning: translation name '" << pCheck->aTransName << "' has trailing whitespace" << endl;
pCheck = pCheck->pNext;
}
}
//
// step 4: warn if the string that is used for the display is too long
//
i = 0;
while (gaCheckLength[i].eId != NO_OF_FEATURES)
{
POPTION_LIST pCheck = gaOptionList[gaCheckLength[i].eId], pCur;
while (pCheck != NULL)
{
size_t TransNameLen = strlen(pCheck->aTransName);
if (TransNameLen > gaCheckLength[i].iMaxLen)
cout << "Warning: translation name '" << pCheck->aTransName << "' will be truncated to "<< (unsigned int) gaCheckLength[i].iMaxLen << " characters"<< endl;
else if ((TransNameLen == 0) && (strlen(pCheck->aName) > gaCheckLength[i].iMaxLen))
cout << "Warning: option name '" << pCheck->aName << "' will be truncated to "<< (unsigned int) gaCheckLength[i].iMaxLen << " characters"<< endl;
pCheck = pCheck->pNext;
}
i++;
}
//
// clean up
//
for (i = 0; i < NO_OF_FEATURES;i++)
{
POPTION_LIST pTmp = gaOptionList[i], pCur;
while (pTmp != NULL)
{
pCur = pTmp->pNext;
delete pTmp;
pTmp = pCur;
}
gaOptionList[i] = NULL;
}
_flushall(); // to avoid sync problems with the DbgPrint output
VirtualFree((LPVOID) pFileStart, 0, MEM_RELEASE);
}