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.

835 lines
28 KiB

  1. /*++
  2. Copyright (c) 1996-1997 Microsoft Corporation
  3. Module Name:
  4. ppdcheck.c
  5. Abstract:
  6. PPD parser test program
  7. Environment:
  8. PostScript driver, PPD parser, Check build only
  9. Revision History:
  10. 09/17/96 -davidx-
  11. Implement PpdDump.
  12. 03/27/96 -davidx-
  13. Created it.
  14. --*/
  15. #include "lib.h"
  16. #include "ppd.h"
  17. #include "pass2.h"
  18. INT giDebugLevel;
  19. HINSTANCE ghInstance;
  20. PSTR gstrProgName;
  21. PRAWBINARYDATA gpRawData;
  22. PINFOHEADER gpInfoHdr;
  23. PUIINFO gpUIInfo;
  24. PPPDDATA gpPpdData;
  25. DWORD gdwTotalSize, gdwNumFiles, gdwMaxFileSize;
  26. extern const CHAR gstrFalseKwd[];
  27. extern const CHAR gstrNoneKwd[];
  28. #define DumpInt(label, n) DbgPrint("%s: %d\n", label, n)
  29. #define DumpHex(label, n) DbgPrint("%s: 0x%x\n", label, n)
  30. #define DumpStrW(label, offset) DbgPrint("%s: %ws\n", label, OFFSET_TO_POINTER(gpRawData, offset))
  31. #define DumpStrA(label, offset) DbgPrint("%s: %s\n", label, OFFSET_TO_POINTER(gpRawData, offset))
  32. #define DumpFix(label, n) DbgPrint("%s: %f\n", label, (FLOAT) (n) / FIX_24_8_SCALE)
  33. #define DumpInvo(label, p) DbgPrint("%s: %d bytes\n", label, (p)->dwCount)
  34. #define DumpSize(label, p) DbgPrint("%s: %d x %d\n", label, (p)->cx, (p)->cy)
  35. #define DumpRect(label, p) DbgPrint("%s: (%d, %d) - (%d, %d)\n", label, \
  36. (p)->left, (p)->top, (p)->right, (p)->bottom)
  37. VOID
  38. PpdDump(
  39. VOID
  40. )
  41. {
  42. DWORD index, dwFeatures;
  43. PFEATURE pFeature;
  44. POPTION pOption;
  45. LPTSTR ptstrTable;
  46. PUICONSTRAINT pUIConstraint;
  47. PORDERDEPEND pOrderDep;
  48. PFILEDATEINFO pFileDateInfo;
  49. DbgPrint("\nRAWBINARYDATA:\n");
  50. DumpInt (" dwFileSize", gpRawData->dwFileSize);
  51. DumpHex (" dwParserSignature", gpRawData->dwParserSignature);
  52. DumpHex (" dwParserVersion", gpRawData->dwParserVersion);
  53. DumpHex (" dwChecksum32", gpRawData->dwChecksum32);
  54. DumpInt (" dwDocumentFeatures", gpRawData->dwDocumentFeatures);
  55. DumpInt (" dwPrinterFeatures", gpRawData->dwPrinterFeatures);
  56. DumpInt (" Source PPD files", gpRawData->FileDateInfo.dwCount);
  57. pFileDateInfo = OFFSET_TO_POINTER(gpRawData, gpRawData->FileDateInfo.loOffset);
  58. ASSERT(gpRawData->FileDateInfo.dwCount == 0 || pFileDateInfo != NULL);
  59. for (index=0; index < gpRawData->FileDateInfo.dwCount; index++, pFileDateInfo++)
  60. {
  61. FILETIME FileTime;
  62. SYSTEMTIME SystemTime;
  63. TCHAR TimeDateString[64];
  64. DumpStrW(" loFileName", pFileDateInfo->loFileName);
  65. FileTimeToLocalFileTime(&pFileDateInfo->FileTime, &FileTime);
  66. FileTimeToSystemTime(&FileTime, &SystemTime);
  67. GetDateFormat(LOCALE_USER_DEFAULT, 0, &SystemTime, NULL, TimeDateString, 64);
  68. DbgPrint(" FileTime: %ws ", TimeDateString);
  69. GetTimeFormat(LOCALE_USER_DEFAULT, 0, &SystemTime, NULL, TimeDateString, 64);
  70. DbgPrint("%ws\n", TimeDateString);
  71. }
  72. DbgPrint("\nUIINFO:\n");
  73. DumpInt (" dwSize", gpUIInfo->dwSize);
  74. DumpStrW(" loNickName", gpUIInfo->loNickName);
  75. DumpHex (" dwSpecVersion", gpUIInfo->dwSpecVersion);
  76. DumpHex (" dwTechnology", gpUIInfo->dwTechnology);
  77. DumpInt (" dwDocumentFeatures", gpUIInfo->dwDocumentFeatures);
  78. DumpInt (" dwPrinterFeatures", gpUIInfo->dwPrinterFeatures);
  79. DumpInt (" UIConstraints.dwCount", gpUIInfo->UIConstraints.dwCount);
  80. DumpInt (" dwMaxCopies", gpUIInfo->dwMaxCopies);
  81. DumpInt (" dwMinScale", gpUIInfo->dwMinScale);
  82. DumpInt (" dwMaxScale", gpUIInfo->dwMaxScale);
  83. DumpInt (" dwLangEncoding", gpUIInfo->dwLangEncoding);
  84. DumpInt (" dwLangLevel", gpUIInfo->dwLangLevel);
  85. if (gpUIInfo->dwLangLevel >= 2 && gpPpdData->dwPSVersion < 2000)
  86. DbgPrint(" *** Level 2 clone\n");
  87. DumpInvo(" Password", &gpUIInfo->Password);
  88. DumpInvo(" ExitServer", &gpUIInfo->ExitServer);
  89. DumpHex (" dwProtocols", gpUIInfo->dwProtocols);
  90. DumpInt (" dwJobTimeout", gpUIInfo->dwJobTimeout);
  91. DumpInt (" dwWaitTimeout", gpUIInfo->dwWaitTimeout);
  92. DumpInt (" dwTTRasterizer", gpUIInfo->dwTTRasterizer);
  93. DumpInt (" dwFreeMem", gpUIInfo->dwFreeMem);
  94. DumpInt (" dwPrintRate", gpUIInfo->dwPrintRate);
  95. DumpInt (" dwPrintRateUnit", gpUIInfo->dwPrintRateUnit);
  96. DumpFix (" fxScreenAngle", gpUIInfo->fxScreenAngle);
  97. DumpFix (" fxScreenFreq", gpUIInfo->fxScreenFreq);
  98. DumpHex (" dwFlags", gpUIInfo->dwFlags);
  99. DumpInt (" dwCustomSizeOptIndex", gpUIInfo->dwCustomSizeOptIndex);
  100. DumpInt (" ptMasterUnits.x", gpUIInfo->ptMasterUnits.x);
  101. DumpInt (" ptMasterUnits.y", gpUIInfo->ptMasterUnits.y);
  102. dwFeatures = gpUIInfo->dwDocumentFeatures + gpUIInfo->dwPrinterFeatures;
  103. pFeature = OFFSET_TO_POINTER(gpRawData, gpUIInfo->loFeatureList);
  104. pUIConstraint = OFFSET_TO_POINTER(gpRawData, gpUIInfo->UIConstraints.loOffset);
  105. DbgPrint("\n FEATURES: count = %d\n", dwFeatures);
  106. for (index = 0; index < dwFeatures; index++, pFeature++)
  107. {
  108. DWORD dwConstIndex, dwFeatureIndex, dwOptionIndex, dwOptionCount;
  109. PFEATURE pConstFeature;
  110. POPTION pConstOption;
  111. DumpStrA("\n loKeywordName", pFeature->loKeywordName);
  112. DumpStrW(" loDisplayName", pFeature->loDisplayName);
  113. DumpHex (" dwFlags", pFeature->dwFlags);
  114. DumpInt (" dwDefaultOptIndex", pFeature->dwDefaultOptIndex);
  115. DumpInt (" dwNoneFalseOptIndex", pFeature->dwNoneFalseOptIndex);
  116. DumpInt (" dwFeatureID", pFeature->dwFeatureID);
  117. DumpInt (" dwUIType", pFeature->dwUIType);
  118. DumpInt (" dwPriority", pFeature->dwPriority);
  119. DumpInt (" dwFeatureType", pFeature->dwFeatureType);
  120. DumpInt (" dwOptionSize", pFeature->dwOptionSize);
  121. if (dwOptionCount = pFeature->Options.dwCount)
  122. {
  123. pOption = OFFSET_TO_POINTER(gpRawData, pFeature->Options.loOffset);
  124. DbgPrint("\n OPTIONS: count = %d\n", dwOptionCount);
  125. while (dwOptionCount--)
  126. {
  127. DumpStrA("\n loKeywordName", pOption->loKeywordName);
  128. DumpStrW(" loDisplayName", pOption->loDisplayName);
  129. DumpInvo(" Invocation", &pOption->Invocation);
  130. switch (pFeature->dwFeatureID)
  131. {
  132. case GID_PAGESIZE:
  133. { PPAGESIZE pPaper = (PPAGESIZE) pOption;
  134. DumpSize(" szPaperSize", &pPaper->szPaperSize);
  135. DumpRect(" rcImgArea", &pPaper->rcImgArea);
  136. DumpInt (" dwPaperSizeID", pPaper->dwPaperSizeID);
  137. DumpHex (" dwFlags", pPaper->dwFlags);
  138. }
  139. break;
  140. case GID_RESOLUTION:
  141. { PRESOLUTION pRes = (PRESOLUTION) pOption;
  142. DumpInt (" iXdpi", pRes->iXdpi);
  143. DumpInt (" iYdpi", pRes->iYdpi);
  144. DumpFix (" fxScreenAngle", pRes->fxScreenAngle);
  145. DumpFix (" fxScreenFreq", pRes->fxScreenFreq);
  146. }
  147. break;
  148. case GID_DUPLEX:
  149. DumpInt (" dwDuplexID", ((PDUPLEX) pOption)->dwDuplexID);
  150. break;
  151. case GID_COLLATE:
  152. DumpInt (" dwCollateID", ((PCOLLATE) pOption)->dwCollateID);
  153. break;
  154. case GID_MEDIATYPE:
  155. DumpInt (" dwMediaTypeID", ((PMEDIATYPE) pOption)->dwMediaTypeID);
  156. break;
  157. case GID_OUTPUTBIN:
  158. DumpInt (" bOutputOrderReversed", ((POUTPUTBIN) pOption)->bOutputOrderReversed);
  159. break;
  160. case GID_INPUTSLOT:
  161. { PINPUTSLOT pTray = (PINPUTSLOT) pOption;
  162. DumpHex (" dwFlags", pTray->dwFlags);
  163. DumpInt (" dwPaperSourceID", pTray->dwPaperSourceID);
  164. }
  165. break;
  166. case GID_MEMOPTION:
  167. { PMEMOPTION pMemOption = (PMEMOPTION) pOption;
  168. DumpInt (" dwInstalledMem", pMemOption->dwInstalledMem);
  169. DumpInt (" dwFreeMem", pMemOption->dwFreeMem);
  170. DumpInt (" dwFreeFontMem", pMemOption->dwFreeFontMem);
  171. }
  172. break;
  173. }
  174. if ((dwConstIndex = pOption->dwUIConstraintList) != NULL_CONSTRAINT)
  175. {
  176. ASSERT(pUIConstraint != NULL);
  177. DbgPrint("\n UICONSTRAINTS:\n");
  178. while (dwConstIndex != NULL_CONSTRAINT)
  179. {
  180. ASSERT(dwConstIndex < gpUIInfo->UIConstraints.dwCount);
  181. dwFeatureIndex = pUIConstraint[dwConstIndex].dwFeatureIndex;
  182. dwOptionIndex = pUIConstraint[dwConstIndex].dwOptionIndex;
  183. dwConstIndex = pUIConstraint[dwConstIndex].dwNextConstraint;
  184. ASSERT(dwFeatureIndex < dwFeatures);
  185. pConstFeature = PGetIndexedFeature(gpUIInfo, dwFeatureIndex);
  186. DbgPrint(" %s", OFFSET_TO_POINTER(gpRawData, pConstFeature->loKeywordName));
  187. if (dwOptionIndex != OPTION_INDEX_ANY)
  188. {
  189. ASSERT(dwOptionIndex < pConstFeature->Options.dwCount);
  190. pConstOption = PGetIndexedOption(gpUIInfo, pConstFeature, dwOptionIndex);
  191. DbgPrint(" %s", OFFSET_TO_POINTER(gpRawData, pConstOption->loKeywordName));
  192. }
  193. DbgPrint("\n");
  194. }
  195. }
  196. pOption = (POPTION) ((PBYTE) pOption + pFeature->dwOptionSize);
  197. }
  198. }
  199. if ((dwConstIndex = pFeature->dwUIConstraintList) != NULL_CONSTRAINT)
  200. {
  201. ASSERT(pUIConstraint != NULL);
  202. DbgPrint("\n UICONSTRAINTS:\n");
  203. while (dwConstIndex != NULL_CONSTRAINT)
  204. {
  205. ASSERT(dwConstIndex < gpUIInfo->UIConstraints.dwCount);
  206. dwFeatureIndex = pUIConstraint[dwConstIndex].dwFeatureIndex;
  207. dwOptionIndex = pUIConstraint[dwConstIndex].dwOptionIndex;
  208. dwConstIndex = pUIConstraint[dwConstIndex].dwNextConstraint;
  209. ASSERT(dwFeatureIndex < dwFeatures);
  210. pConstFeature = PGetIndexedFeature(gpUIInfo, dwFeatureIndex);
  211. DbgPrint(" %s", OFFSET_TO_POINTER(gpRawData, pConstFeature->loKeywordName));
  212. if (dwOptionIndex != OPTION_INDEX_ANY)
  213. {
  214. ASSERT(dwOptionIndex < pConstFeature->Options.dwCount);
  215. pConstOption = PGetIndexedOption(gpUIInfo, pConstFeature, dwOptionIndex);
  216. DbgPrint(" %s", OFFSET_TO_POINTER(gpRawData, pConstOption->loKeywordName));
  217. }
  218. DbgPrint("\n");
  219. }
  220. }
  221. }
  222. DbgPrint("\n PREDEFINED FEATURES:\n");
  223. for (index = 0; index < MAX_GID; index++)
  224. {
  225. if (pFeature = GET_PREDEFINED_FEATURE(gpUIInfo, index))
  226. DbgPrint(" %s\n", OFFSET_TO_POINTER(gpRawData, pFeature->loKeywordName));
  227. }
  228. DbgPrint("\n DEFAULT FONT SUBSTITUTION TABLE: %d bytes\n", gpUIInfo->dwFontSubCount);
  229. ptstrTable = OFFSET_TO_POINTER(gpRawData, gpUIInfo->loFontSubstTable);
  230. if (ptstrTable) {
  231. while (*ptstrTable) {
  232. DbgPrint(" %ws => ", ptstrTable);
  233. ptstrTable += _tcslen(ptstrTable) + 1;
  234. DbgPrint("%ws\n", ptstrTable);
  235. ptstrTable += _tcslen(ptstrTable) + 1;
  236. }
  237. }
  238. DbgPrint("\nPPDDATA:\n");
  239. #ifndef WINNT_40
  240. DumpHex (" GetUserDefaultUILanguage() returns", GetUserDefaultUILanguage());
  241. #endif
  242. DumpHex (" dwUserDefUILangID", gpPpdData->dwUserDefUILangID);
  243. DumpHex (" dwPpdFilever", gpPpdData->dwPpdFilever);
  244. DumpHex (" dwFlags", gpPpdData->dwFlags);
  245. DumpHex (" dwExtensions", gpPpdData->dwExtensions);
  246. DumpInt (" dwSetResType", gpPpdData->dwSetResType);
  247. DumpInt (" dwPSVersion", gpPpdData->dwPSVersion);
  248. DumpInvo(" PSVersion", &gpPpdData->PSVersion);
  249. DumpInvo(" Product", &gpPpdData->Product);
  250. DumpHex (" dwOutputOrderIndex", gpPpdData->dwOutputOrderIndex);
  251. DumpHex (" dwCustomSizeFlags", gpPpdData->dwCustomSizeFlags);
  252. DumpInt (" dwLeadingEdgeLong", gpPpdData->dwLeadingEdgeLong);
  253. DumpInt (" dwLeadingEdgeShort", gpPpdData->dwLeadingEdgeShort);
  254. DumpInt (" dwUseHWMarginsTrue", gpPpdData->dwUseHWMarginsTrue);
  255. DumpInt (" dwUseHWMarginsFalse", gpPpdData->dwUseHWMarginsFalse);
  256. for (index = 0; index < CUSTOMPARAM_MAX; index++)
  257. {
  258. DbgPrint(" param %d: dwOrder = %d, lMinVal = %d, lMaxVal = %d\n", index,
  259. gpPpdData->CustomSizeParams[index].dwOrder,
  260. gpPpdData->CustomSizeParams[index].lMinVal,
  261. gpPpdData->CustomSizeParams[index].lMaxVal);
  262. }
  263. DumpInvo(" PatchFile", &gpPpdData->PatchFile);
  264. DumpInvo(" JclBegin", &gpPpdData->JclBegin);
  265. DumpInvo(" JclEnterPS", &gpPpdData->JclEnterPS);
  266. DumpInvo(" JclEnd", &gpPpdData->JclEnd);
  267. DumpInvo(" ManualFeedFalse", &gpPpdData->ManualFeedFalse);
  268. DumpHex (" dwNt4Checksum", gpPpdData->dwNt4Checksum);
  269. DumpInt (" dwNt4DocFeatures", gpPpdData->dwNt4DocFeatures);
  270. DumpInt (" dwNt4PrnFeatures", gpPpdData->dwNt4PrnFeatures);
  271. if (gpPpdData->Nt4Mapping.dwCount)
  272. {
  273. PBYTE pubNt4Mapping;
  274. pubNt4Mapping = OFFSET_TO_POINTER(gpRawData, gpPpdData->Nt4Mapping.loOffset);
  275. ASSERT(pubNt4Mapping != NULL);
  276. for (index=0; index < gpPpdData->Nt4Mapping.dwCount; index++)
  277. DbgPrint(" %2d => %d\n", index, pubNt4Mapping[index]);
  278. }
  279. if (gpPpdData->DeviceFonts.dwCount)
  280. {
  281. PDEVFONT pDevFont;
  282. DbgPrint("\n DEVICE FONTS:\n");
  283. if (pDevFont = OFFSET_TO_POINTER(gpRawData, gpPpdData->loDefaultFont))
  284. DumpStrA(" default", pDevFont->loFontName);
  285. pDevFont = OFFSET_TO_POINTER(gpRawData, gpPpdData->DeviceFonts.loOffset);
  286. for (index = 0; index < gpPpdData->DeviceFonts.dwCount; index++, pDevFont++)
  287. {
  288. DumpStrA("\n loFontName", pDevFont->loFontName);
  289. DumpStrW(" loDisplayName", pDevFont->loDisplayName);
  290. DumpStrA(" loEncoding", pDevFont->loEncoding);
  291. DumpStrA(" loCharset", pDevFont->loCharset);
  292. DumpStrA(" loVersion", pDevFont->loVersion);
  293. DumpInt (" dwStatus", pDevFont->dwStatus);
  294. }
  295. }
  296. if (gpPpdData->OrderDeps.dwCount)
  297. {
  298. pOrderDep = OFFSET_TO_POINTER(gpRawData, gpPpdData->OrderDeps.loOffset);
  299. ASSERT(pOrderDep != NULL);
  300. DbgPrint("\n ORDER DEPENDENCIES:\n");
  301. for (index=0; index < gpPpdData->OrderDeps.dwCount; index++, pOrderDep++)
  302. {
  303. DbgPrint(" %d: order = %d section = 0x%x (in PPD: 0x%x) ",
  304. index, pOrderDep->lOrder, pOrderDep->dwSection, pOrderDep->dwPPDSection);
  305. pFeature = PGetIndexedFeature(gpUIInfo, pOrderDep->dwFeatureIndex);
  306. ASSERT(pFeature != NULL);
  307. DbgPrint("%s", OFFSET_TO_POINTER(gpRawData, pFeature->loKeywordName));
  308. if (pOrderDep->dwOptionIndex != OPTION_INDEX_ANY)
  309. {
  310. pOption = PGetIndexedOption(gpUIInfo, pFeature, pOrderDep->dwOptionIndex);
  311. ASSERT(pOption != NULL);
  312. DbgPrint(" %s", OFFSET_TO_POINTER(gpRawData, pOption->loKeywordName));
  313. }
  314. DbgPrint(", next = %d\n", pOrderDep->dwNextOrderDep);
  315. }
  316. }
  317. if (gpPpdData->QueryOrderDeps.dwCount)
  318. {
  319. pOrderDep = OFFSET_TO_POINTER(gpRawData, gpPpdData->QueryOrderDeps.loOffset);
  320. ASSERT(pOrderDep != NULL);
  321. DbgPrint("\n QUERY ORDER DEPENDENCIES:\n");
  322. for (index=0; index < gpPpdData->QueryOrderDeps.dwCount; index++, pOrderDep++)
  323. {
  324. DbgPrint(" %d: order = %d section = 0x%x (in PPD: 0x%x) ",
  325. index, pOrderDep->lOrder, pOrderDep->dwSection, pOrderDep->dwPPDSection);
  326. pFeature = PGetIndexedFeature(gpUIInfo, pOrderDep->dwFeatureIndex);
  327. ASSERT(pFeature != NULL);
  328. DbgPrint("%s", OFFSET_TO_POINTER(gpRawData, pFeature->loKeywordName));
  329. if (pOrderDep->dwOptionIndex != OPTION_INDEX_ANY)
  330. {
  331. pOption = PGetIndexedOption(gpUIInfo, pFeature, pOrderDep->dwOptionIndex);
  332. ASSERT(pOption != NULL);
  333. DbgPrint(" %s", OFFSET_TO_POINTER(gpRawData, pOption->loKeywordName));
  334. }
  335. DbgPrint(", next = %d\n", pOrderDep->dwNextOrderDep);
  336. }
  337. }
  338. if (gpPpdData->JobPatchFiles.dwCount)
  339. {
  340. PJOBPATCHFILE pJobPatchFiles;
  341. pJobPatchFiles = OFFSET_TO_POINTER(gpRawData, gpPpdData->JobPatchFiles.loOffset);
  342. ASSERT(pJobPatchFiles);
  343. DbgPrint("\n JOB PATCH FILES:\n");
  344. for (index = 0; index < gpPpdData->JobPatchFiles.dwCount; index++, pJobPatchFiles++)
  345. {
  346. DbgPrint(" %2d No %li", index, pJobPatchFiles->lJobPatchNo);
  347. DbgPrint(": '%s'\n", OFFSET_TO_POINTER(gpRawData, pJobPatchFiles->loOffset));
  348. }
  349. }
  350. }
  351. VOID
  352. DumpNt4Mapping(
  353. VOID
  354. )
  355. {
  356. PFEATURE pFeatures;
  357. PBYTE pubNt4Mapping;
  358. DWORD iNt4, iNt5, cNt4, cNt5;
  359. PSTR pName;
  360. DbgPrint("checksum: 0x%x\n", gpPpdData->dwNt4Checksum);
  361. DbgPrint("number of doc-sticky features: %d\n", gpPpdData->dwNt4DocFeatures);
  362. DbgPrint("number of printer-sticky features: %d\n", gpPpdData->dwNt4PrnFeatures);
  363. pubNt4Mapping = OFFSET_TO_POINTER(gpRawData, gpPpdData->Nt4Mapping.loOffset);
  364. pFeatures = OFFSET_TO_POINTER(gpRawData, gpUIInfo->loFeatureList);
  365. ASSERT(pubNt4Mapping != NULL);
  366. cNt4 = gpPpdData->dwNt4DocFeatures + gpPpdData->dwNt4PrnFeatures;
  367. cNt5 = gpPpdData->Nt4Mapping.dwCount;
  368. ASSERT(cNt5 == 0 || pFeatures != NULL);
  369. for (iNt4=0; iNt4 < cNt4; iNt4++)
  370. {
  371. for (iNt5=0; iNt5 < cNt5; iNt5++)
  372. {
  373. if (pubNt4Mapping[iNt5] == iNt4)
  374. {
  375. pName = OFFSET_TO_POINTER(gpRawData, pFeatures[iNt5].loKeywordName);
  376. ASSERT(pName != NULL);
  377. if (strcmp(pName, "JCLResolution") == EQUAL_STRING ||
  378. strcmp(pName, "SetResolution") == EQUAL_STRING)
  379. {
  380. pName = "Resolution";
  381. }
  382. DbgPrint(" %2d: %s\n", pubNt4Mapping[iNt5], pName);
  383. break;
  384. }
  385. }
  386. }
  387. }
  388. ULONG _cdecl
  389. DbgPrint(
  390. PCSTR pstrFormat,
  391. ...
  392. )
  393. {
  394. va_list ap;
  395. va_start(ap, pstrFormat);
  396. vprintf(pstrFormat, ap);
  397. va_end(ap);
  398. return 0;
  399. }
  400. typedef enum {
  401. Free,
  402. InBracket,
  403. InHexDigitOdd,
  404. InHexDigitEven
  405. } eInvState;
  406. static void CheckInvocationValue(POPTION pOption, LPSTR pstrFeatureName)
  407. {
  408. eInvState State = Free;
  409. DWORD i;
  410. LPSTR pInv = OFFSET_TO_POINTER(gpRawData, pOption->Invocation.loOffset);
  411. ASSERT(pOption->Invocation.dwCount == 0 || pInv != NULL);
  412. for (i=0; i< pOption->Invocation.dwCount; i++)
  413. {
  414. switch (State)
  415. {
  416. case Free:
  417. if (*(pInv + i) == '<')
  418. State = InBracket;
  419. break;
  420. case InBracket:
  421. if (isxdigit(*(pInv + i)))
  422. State = InHexDigitOdd;
  423. else
  424. State = Free;
  425. break;
  426. case InHexDigitOdd:
  427. if (isxdigit(*(pInv + i)))
  428. State = InHexDigitEven;
  429. else
  430. State = Free;
  431. break;
  432. case InHexDigitEven:
  433. if (isxdigit(*(pInv + i)))
  434. State = InHexDigitOdd;
  435. else if (*(pInv + i) == '>')
  436. {
  437. LPSTR pstrOptionName = OFFSET_TO_POINTER(gpRawData, pOption->loKeywordName);
  438. DbgPrint("Warning: invocation value of feature '%s', option '%s' contains hex digits\n - possibly forgotten to use 'JCL' as start of keyword ?\n",
  439. pstrFeatureName, pstrOptionName);
  440. return;
  441. }
  442. else
  443. State = Free;
  444. break;
  445. }
  446. }
  447. }
  448. VOID
  449. PpdVerify(
  450. VOID
  451. )
  452. {
  453. DWORD index, dwFeatures;
  454. PFEATURE pFeature;
  455. POPTION pOption;
  456. PSTR pstrFeatureName, pstrOptionName;
  457. BOOL bNoneOption, bFalseOption;
  458. PUICONSTRAINT pConstraint;
  459. DWORD NoOfConstraints = gpUIInfo->UIConstraints.dwCount;
  460. dwFeatures = gpUIInfo->dwDocumentFeatures + gpUIInfo->dwPrinterFeatures;
  461. pFeature = OFFSET_TO_POINTER(gpRawData, gpUIInfo->loFeatureList);
  462. pConstraint = OFFSET_TO_POINTER(gpRawData, gpUIInfo->UIConstraints.loOffset);
  463. ASSERT(dwFeatures == 0 || pFeature != NULL);
  464. for (index = 0; index < dwFeatures; index++, pFeature++)
  465. {
  466. DWORD dwOptionCount, dwOptionIndex = 0;
  467. pstrFeatureName = OFFSET_TO_POINTER(gpRawData, pFeature->loKeywordName);
  468. if (dwOptionCount = pFeature->Options.dwCount)
  469. {
  470. pOption = OFFSET_TO_POINTER(gpRawData, pFeature->Options.loOffset);
  471. bNoneOption = bFalseOption = FALSE;
  472. ASSERT(dwOptionCount == 0 || pOption != NULL);
  473. while (dwOptionCount--)
  474. {
  475. pstrOptionName = OFFSET_TO_POINTER(gpRawData, pOption->loKeywordName);
  476. ASSERT(pstrOptionName);
  477. if (!strcmp(pstrOptionName, gstrNoneKwd))
  478. bNoneOption = TRUE;
  479. else if (!strcmp(pstrOptionName, gstrFalseKwd))
  480. bFalseOption = TRUE;
  481. if (giDebugLevel <= 2)
  482. {
  483. CheckInvocationValue(pOption, pstrFeatureName);
  484. //
  485. // check self constraining constraints
  486. //
  487. if (pOption->dwUIConstraintList != NULL_CONSTRAINT)
  488. {
  489. DWORD dwConstIndex = pOption->dwUIConstraintList;
  490. do
  491. {
  492. if ((pConstraint[dwConstIndex].dwFeatureIndex == index) &&
  493. ((pConstraint[dwConstIndex].dwOptionIndex == dwOptionIndex) ||
  494. (pConstraint[dwConstIndex].dwOptionIndex == OPTION_INDEX_ANY)))
  495. DbgPrint("Warning : self constraining constraint found for feature '%s', Option '%s'\n", pstrFeatureName, pstrOptionName);
  496. dwConstIndex = pConstraint[dwConstIndex].dwNextConstraint;
  497. } while (dwConstIndex != NULL_CONSTRAINT);
  498. }
  499. }
  500. pOption = (POPTION) ((PBYTE) pOption + pFeature->dwOptionSize);
  501. dwOptionIndex++;
  502. }
  503. if (bNoneOption && bFalseOption)
  504. DbgPrint("Error: Feature '%s' has both None and False options!\n",pstrFeatureName);
  505. }
  506. }
  507. }
  508. VOID
  509. usage(
  510. VOID
  511. )
  512. {
  513. DbgPrint("usage: %s [-options] filenames ...\n", gstrProgName);
  514. DbgPrint("where options are:\n");
  515. DbgPrint(" -b attempt to read cached binary PPD data first\n");
  516. DbgPrint(" -k keep the binary PPD data\n");
  517. DbgPrint(" -wN set warning level to N\n");
  518. DbgPrint(" -h display help information\n");
  519. exit(-1);
  520. }
  521. INT _cdecl
  522. main(
  523. INT argc,
  524. CHAR **argv
  525. )
  526. {
  527. BOOL bUseCache, bKeepBPD;
  528. DWORD dwTime;
  529. //
  530. // Go through the command line arguments
  531. //
  532. ghInstance = GetModuleHandle(NULL);
  533. bUseCache = bKeepBPD = FALSE;
  534. giDebugLevel = DBG_TERSE;
  535. gdwTotalSize = gdwNumFiles = gdwMaxFileSize;
  536. gstrProgName = *argv++;
  537. argc--;
  538. if (argc == 0)
  539. usage();
  540. dwTime = GetTickCount();
  541. for ( ; argc--; argv++)
  542. {
  543. PSTR pArg = *argv;
  544. if (*pArg == '-' || *pArg == '/')
  545. {
  546. //
  547. // The argument is an option flag
  548. //
  549. switch (*++pArg) {
  550. case 'b':
  551. case 'B':
  552. bUseCache = bKeepBPD = TRUE;
  553. break;
  554. case 'k':
  555. case 'K':
  556. bKeepBPD = TRUE;
  557. break;
  558. case 'w':
  559. case 'W':
  560. if (*++pArg >= '0' && *pArg <= '9')
  561. {
  562. giDebugLevel = *pArg - '0';
  563. break;
  564. }
  565. default:
  566. usage();
  567. break;
  568. }
  569. }
  570. else
  571. {
  572. WCHAR wstrFilename[MAX_PATH];
  573. PTSTR ptstrBpdFilename;
  574. //
  575. // Convert ANSI filename to Unicode filename
  576. //
  577. MultiByteToWideChar(CP_ACP, 0, pArg, -1, wstrFilename, MAX_PATH);
  578. TERSE(("\n*** %ws\n", wstrFilename));
  579. //
  580. // If -b option is given, try to read cached binary data first
  581. //
  582. if (bUseCache)
  583. gpRawData = PpdLoadCachedBinaryData(wstrFilename);
  584. else
  585. {
  586. gpRawData = PpdParseTextFile(wstrFilename);
  587. if (giDebugLevel <= 2)
  588. CheckOptionIntegrity(wstrFilename);
  589. }
  590. if (gpRawData)
  591. {
  592. gpInfoHdr = (PINFOHEADER) gpRawData;
  593. gpUIInfo = (PUIINFO) ((PBYTE) gpInfoHdr + gpInfoHdr->loUIInfoOffset);
  594. gpPpdData = (PPPDDATA) ((PBYTE) gpInfoHdr + gpInfoHdr->loDriverOffset);
  595. gpUIInfo->pInfoHeader = gpInfoHdr;
  596. if (giDebugLevel == 8)
  597. {
  598. DbgPrint("*** PPD file: %s\n", StripDirPrefixA(pArg));
  599. DumpNt4Mapping();
  600. }
  601. else if (giDebugLevel == 9)
  602. PpdDump();
  603. //
  604. // extra error checking
  605. //
  606. PpdVerify();
  607. gdwTotalSize += gpRawData->dwFileSize;
  608. gdwNumFiles++;
  609. if (gpRawData->dwFileSize > gdwMaxFileSize)
  610. gdwMaxFileSize = gpRawData->dwFileSize;
  611. MemFree(gpRawData);
  612. //
  613. // If -k option is not given, get rid of the BPD file after we're done
  614. //
  615. if (! bKeepBPD && (ptstrBpdFilename = GenerateBpdFilename(wstrFilename)))
  616. {
  617. DeleteFile(ptstrBpdFilename);
  618. MemFree(ptstrBpdFilename);
  619. }
  620. }
  621. }
  622. }
  623. #ifdef COLLECT_STATS
  624. if (gdwNumFiles > 0)
  625. {
  626. dwTime = GetTickCount() - dwTime;
  627. TERSE(("Number of files parsed: %d\n", gdwNumFiles));
  628. TERSE(("Average binary file size: %d\n", gdwTotalSize / gdwNumFiles));
  629. TERSE(("Maximum binary file size: %d\n", gdwMaxFileSize));
  630. TERSE(("Average parsing time per file (ms): %d\n", dwTime / gdwNumFiles));
  631. }
  632. #endif // COLLECT_STATS
  633. return 0;
  634. }