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.

502 lines
13 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. pass2.cpp
  5. Abstract:
  6. Functions for additional checking of a PPD file
  7. Environment:
  8. PostScript driver, PPD parser
  9. Revision History:
  10. 09/15/98 -rorleth-
  11. Created it.
  12. --*/
  13. #include <lib.h>
  14. #include <iostream.h>
  15. #include "pass2.h"
  16. enum FeatureId
  17. {
  18. FID_PAGE_SIZE,
  19. FID_PAGE_REGION,
  20. FID_INPUT_SLOT,
  21. FID_SMOOTHING,
  22. FID_MEDIA_COLOR,
  23. FID_MEDIA_TYPE,
  24. FID_MEDIA_WEIGHT,
  25. FID_OUTPUT_MODE,
  26. FID_PAPER_DIMENSION,
  27. FID_IMAGE_AREA,
  28. FID_OUTPUT_ORDER,
  29. NO_OF_FEATURES
  30. };
  31. typedef struct _PPD_FEATURE
  32. {
  33. FeatureId eId;
  34. LPSTR lpszName;
  35. } PPD_FEATURE, *PPPD_FEATURE;
  36. //
  37. // features whose options we have to check
  38. //
  39. static PPD_FEATURE aCheckFeat[] =
  40. {
  41. { FID_PAGE_SIZE, "PageSize" },
  42. { FID_PAGE_REGION, "PageRegion" },
  43. { FID_INPUT_SLOT, "InputSlot" },
  44. { FID_SMOOTHING, "Smoothing" },
  45. { FID_MEDIA_COLOR, "MediaColor" },
  46. { FID_MEDIA_TYPE, "MediaType" },
  47. { FID_MEDIA_WEIGHT, "MediaWeight" },
  48. { FID_OUTPUT_MODE, "OutputMode" },
  49. { FID_PAPER_DIMENSION, "PaperDimension" },
  50. { FID_IMAGE_AREA, "ImageableArea" },
  51. { FID_OUTPUT_ORDER, "OutputOrder" },
  52. { NO_OF_FEATURES, NULL}
  53. };
  54. typedef struct _PPD_OPTION
  55. {
  56. FeatureId eId;
  57. LPSTR lpszName;
  58. } PPD_OPTION, *PPPD_OPTION;
  59. //
  60. // keywords that require defined feature options
  61. //
  62. static PPD_OPTION gaCheckKeyword[] =
  63. {
  64. { FID_INPUT_SLOT, "RequiresPageRegion"},
  65. { NO_OF_FEATURES, NULL }
  66. };
  67. //
  68. // special option names
  69. //
  70. static PPD_OPTION gaSpecialOptions[] =
  71. {
  72. { NO_OF_FEATURES, "None" }, // NO_OF_FEATURES means valid for all features in that case
  73. { NO_OF_FEATURES, "All" },
  74. { NO_OF_FEATURES, "Unknown" },
  75. { FID_OUTPUT_ORDER, "Normal" }, // Normal and Reverse are predefined options for OutputOrder
  76. { FID_OUTPUT_ORDER, "Reverse" },
  77. { NO_OF_FEATURES, NULL},
  78. };
  79. //
  80. // keywords that have a length limitation for the UI
  81. //
  82. typedef struct _PPD_LENGTH_CHECK
  83. {
  84. FeatureId eId;
  85. size_t iMaxLen;
  86. } PPD_LENGTH_CHECK, *PPPD_LENGTH_CHECK;
  87. static PPD_LENGTH_CHECK gaCheckLength[] =
  88. {
  89. { FID_INPUT_SLOT, 23},
  90. { NO_OF_FEATURES, 0 }
  91. };
  92. const char *pDefaultKeyword = "Default";
  93. const int MaxOptionNameLen = 40;
  94. const int MaxTranslationNameLen = 128;
  95. typedef struct _OPTION_LIST
  96. {
  97. char aName[MaxOptionNameLen+1];
  98. char aTransName[MaxTranslationNameLen+1];
  99. _OPTION_LIST *pNext;
  100. } OPTION_LIST, *POPTION_LIST;
  101. static POPTION_LIST gaOptionList[NO_OF_FEATURES]; // stores all defined options
  102. /*++
  103. Routine Description:
  104. checks whether a references option is defined
  105. Arguments:
  106. char **ppString : Pointer to pointer to option, is advanced by the option name length
  107. FeatureId FeatId : ID of the feature, which should have the option
  108. char *pOptionName: pointer to buffer, where the option name shall be stored for error messages
  109. Return Value:
  110. TRUE if the identified feature has that option, FALSE if not
  111. --*/
  112. static BOOL IsOptionDefined(char **ppString, FeatureId FeatId, char *pOptionName)
  113. {
  114. char *pEndName, *pName = *ppString;
  115. while (isspace(*pName))
  116. pName++;
  117. pEndName = strpbrk(pName, "/: \t\n\r\0");
  118. *ppString = pEndName; // advance current pointer
  119. strncpy(pOptionName, pName, min((DWORD)(pEndName - pName), MaxOptionNameLen));
  120. pOptionName[pEndName-pName] = 0;
  121. //
  122. // check special cases that do not have to be defined
  123. //
  124. int i=0;
  125. while (gaSpecialOptions[i].lpszName != NULL)
  126. {
  127. if ((gaSpecialOptions[i].eId == NO_OF_FEATURES) ||
  128. (gaSpecialOptions[i].eId == FeatId))
  129. {
  130. if (!strcmp(gaSpecialOptions[i].lpszName, pOptionName))
  131. return TRUE;
  132. }
  133. i++;
  134. }
  135. POPTION_LIST pList = gaOptionList[FeatId], pNew;
  136. while (pList != NULL)
  137. {
  138. if (!strcmp(pList->aName, pOptionName))
  139. return TRUE; // found it, it's defined
  140. pList = pList->pNext;
  141. }
  142. return FALSE;
  143. }
  144. /*++
  145. Routine Description:
  146. checks a whole PPD-file, whether all referenced options are defined
  147. Arguments:
  148. PTSTR FileName: Name of the PPD-file to check
  149. --*/
  150. extern "C" void CheckOptionIntegrity(PTSTR ptstrPpdFilename)
  151. {
  152. ZeroMemory(gaOptionList, sizeof(gaOptionList)); // initialise the list header
  153. _flushall(); // to avoid sync problems with the DbgPrint output
  154. //
  155. // create the file mapping
  156. //
  157. HANDLE hFile = CreateFile(ptstrPpdFilename, GENERIC_READ, FILE_SHARE_READ,
  158. NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);
  159. if (hFile == INVALID_HANDLE_VALUE)
  160. {
  161. return;
  162. }
  163. DWORD dwFileSize = GetFileSize(hFile, NULL);
  164. if (dwFileSize == 0xffffffff)
  165. {
  166. CloseHandle(hFile);
  167. return;
  168. }
  169. HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY,0, 0,NULL);
  170. if (hMap == NULL)
  171. {
  172. CloseHandle(hFile);
  173. return;
  174. }
  175. LPCVOID pView = MapViewOfFile(hMap, FILE_MAP_READ, 0,0,0);
  176. if (pView == NULL)
  177. {
  178. CloseHandle(hMap);
  179. CloseHandle(hFile);
  180. return;
  181. }
  182. //
  183. // copy the whole file into an allocated buffer just to get zero-termination
  184. //
  185. LPSTR pFile, pFileStart;
  186. pFileStart = (LPSTR) VirtualAlloc(NULL, dwFileSize+1, MEM_COMMIT, PAGE_READWRITE);
  187. if (pFileStart != NULL)
  188. {
  189. CopyMemory(pFileStart, pView, dwFileSize);
  190. *(pFileStart + dwFileSize) = 0;
  191. }
  192. UnmapViewOfFile(pView);
  193. CloseHandle(hMap);
  194. CloseHandle(hFile);
  195. if (pFileStart == NULL)
  196. {
  197. cout << "ppdcheck.exe out of memory" << endl;
  198. return;
  199. }
  200. pFile = pFileStart;
  201. //
  202. // now the whole PPD-file is a giant string
  203. // extract all the features/options
  204. //
  205. char *pCurOption = (char *) pFileStart;
  206. char OptionName[MaxOptionNameLen+1];
  207. //
  208. // step 1 : extract all valid feature options
  209. //
  210. while ((pFile != NULL) &&
  211. (pCurOption = strchr(pFile, '*')) != NULL)
  212. {
  213. pCurOption++;
  214. char *pNextLine = strpbrk(pCurOption, "\n\r");
  215. pFile = pNextLine;
  216. if (*pCurOption == '%') // skip comments
  217. continue;
  218. //
  219. // scan whether this is one of the features to look for
  220. //
  221. int Index = 0;
  222. while (aCheckFeat[Index].eId != NO_OF_FEATURES)
  223. {
  224. if (strncmp(aCheckFeat[Index].lpszName, pCurOption, strlen(aCheckFeat[Index].lpszName)))
  225. {
  226. Index++;
  227. continue;
  228. }
  229. //
  230. // this is one of the monitored features: make entry in list
  231. //
  232. POPTION_LIST pList = gaOptionList[aCheckFeat[Index].eId], pNew;
  233. pNew = new OPTION_LIST;
  234. pNew->pNext = gaOptionList[aCheckFeat[Index].eId];
  235. gaOptionList[aCheckFeat[Index].eId] = pNew;
  236. char *pName = pCurOption + strlen(aCheckFeat[Index].lpszName), *pEndName;
  237. while (isspace(*pName))
  238. pName++;
  239. pEndName = strpbrk(pName, "/: \0");
  240. DWORD dwNameLen = min((DWORD)(pEndName - pName), MaxOptionNameLen);
  241. strncpy(pNew->aName, pName, dwNameLen);
  242. pNew->aName[dwNameLen] = 0;
  243. dwNameLen = 0;
  244. if (*pEndName == '/') // there is a translation string
  245. {
  246. pName = pEndName +1;
  247. pEndName = strpbrk(pName, ":\n\r\0");
  248. dwNameLen = min((DWORD) (pEndName - pName), MaxTranslationNameLen);
  249. strncpy(pNew->aTransName, pName, dwNameLen);
  250. }
  251. pNew->aTransName[dwNameLen] = 0;
  252. break;
  253. }
  254. }
  255. //
  256. // step 2: check whether all referenced options are featured
  257. //
  258. pFile = pFileStart;
  259. pCurOption = (char *) pFile;
  260. while ((pFile != NULL) &&
  261. (pCurOption = strchr(pFile, '*')) != NULL)
  262. {
  263. pCurOption++;
  264. char *pNextLine = strpbrk(pCurOption, "\n\r");
  265. pFile = pNextLine;
  266. //
  267. // skip comments
  268. //
  269. if (*pCurOption == '%')
  270. continue;
  271. //
  272. // check whether it starts with "Default", if yes, check that feature option
  273. //
  274. if (!strncmp(pDefaultKeyword, pCurOption, strlen(pDefaultKeyword)))
  275. {
  276. pCurOption += strlen(pDefaultKeyword);
  277. int Index = 0;
  278. while (aCheckFeat[Index].eId != NO_OF_FEATURES)
  279. {
  280. if (strncmp(aCheckFeat[Index].lpszName, pCurOption, strlen(aCheckFeat[Index].lpszName)))
  281. {
  282. Index++;
  283. continue;
  284. }
  285. //
  286. // it's one of the checked featurs
  287. //
  288. pCurOption += strlen(aCheckFeat[Index].lpszName);
  289. char *pOption = strpbrk(pCurOption, ":");
  290. if (pOption == NULL)
  291. {
  292. cout << "Warning: default option for '" << aCheckFeat[Index].lpszName << "' is not completed !" << endl;
  293. break;
  294. }
  295. pCurOption = pOption + 1;
  296. if (!IsOptionDefined(&pCurOption, aCheckFeat[Index].eId, OptionName))
  297. cout << "Warning: default option '" << OptionName << "' for feature '*" << aCheckFeat[Index].lpszName <<"' is not defined!" << endl;
  298. break;
  299. }
  300. }
  301. else
  302. {
  303. //
  304. // scan whether this is one of the keywords to look for
  305. //
  306. int Index = 0;
  307. while (gaCheckKeyword[Index].eId != NO_OF_FEATURES)
  308. {
  309. if (strncmp(gaCheckKeyword[Index].lpszName, pCurOption, strlen(gaCheckKeyword[Index].lpszName)))
  310. {
  311. Index++;
  312. continue;
  313. }
  314. //
  315. // this is one of the monitored features: get the option it references
  316. //
  317. pCurOption += strlen(gaCheckKeyword[Index].lpszName);
  318. if (!IsOptionDefined(&pCurOption, gaCheckKeyword[Index].eId, OptionName))
  319. cout << "Warning: option '" << OptionName << "' for keyword '*" << gaCheckKeyword[Index].lpszName <<"' is not defined!" << endl;
  320. break;
  321. }
  322. Index++;
  323. }
  324. }
  325. //
  326. // step 3: check that all option names are different and don't have trailing or leading spaces
  327. //
  328. for (int i = 0; i < NO_OF_FEATURES;i++)
  329. {
  330. POPTION_LIST pCheck = gaOptionList[i], pCur;
  331. while (pCheck != NULL)
  332. {
  333. pCur = pCheck->pNext;
  334. while (pCur != NULL)
  335. {
  336. if (strlen(pCheck->aName) &&
  337. !strcmp(pCheck->aName, pCur->aName))
  338. cout << "Warning: option name '" << pCheck->aName << "' used twice" << endl;
  339. if (strlen(pCheck->aTransName) &&
  340. !strcmp(pCheck->aTransName, pCur->aTransName))
  341. cout << "Warning: translation name '" << pCheck->aTransName << "' used twice" << endl;
  342. pCur = pCur->pNext;
  343. }
  344. size_t TransNameLen = strlen(pCheck->aTransName);
  345. if (isspace(pCheck->aTransName[0]))
  346. cout << "Warning: translation name '" << pCheck->aTransName << "' has leading whitespace" << endl;
  347. if ((TransNameLen > 1) &&
  348. isspace(pCheck->aTransName[TransNameLen-1]))
  349. cout << "Warning: translation name '" << pCheck->aTransName << "' has trailing whitespace" << endl;
  350. pCheck = pCheck->pNext;
  351. }
  352. }
  353. //
  354. // step 4: warn if the string that is used for the display is too long
  355. //
  356. i = 0;
  357. while (gaCheckLength[i].eId != NO_OF_FEATURES)
  358. {
  359. POPTION_LIST pCheck = gaOptionList[gaCheckLength[i].eId], pCur;
  360. while (pCheck != NULL)
  361. {
  362. size_t TransNameLen = strlen(pCheck->aTransName);
  363. if (TransNameLen > gaCheckLength[i].iMaxLen)
  364. cout << "Warning: translation name '" << pCheck->aTransName << "' will be truncated to "<< (unsigned int) gaCheckLength[i].iMaxLen << " characters"<< endl;
  365. else if ((TransNameLen == 0) && (strlen(pCheck->aName) > gaCheckLength[i].iMaxLen))
  366. cout << "Warning: option name '" << pCheck->aName << "' will be truncated to "<< (unsigned int) gaCheckLength[i].iMaxLen << " characters"<< endl;
  367. pCheck = pCheck->pNext;
  368. }
  369. i++;
  370. }
  371. //
  372. // clean up
  373. //
  374. for (i = 0; i < NO_OF_FEATURES;i++)
  375. {
  376. POPTION_LIST pTmp = gaOptionList[i], pCur;
  377. while (pTmp != NULL)
  378. {
  379. pCur = pTmp->pNext;
  380. delete pTmp;
  381. pTmp = pCur;
  382. }
  383. gaOptionList[i] = NULL;
  384. }
  385. _flushall(); // to avoid sync problems with the DbgPrint output
  386. VirtualFree((LPVOID) pFileStart, 0, MEM_RELEASE);
  387. }
  388.