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.

1565 lines
41 KiB

  1. /*++
  2. Copyright (c) 1996-1997 Microsoft Corporation
  3. Module Name:
  4. psutil.c
  5. Abstract:
  6. PostScript utility functions
  7. BInitDriverDefaultDevmode
  8. BMergeDriverDevmode
  9. VCopyUnicodeStringToAnsi
  10. PGetAndConvertOldVersionFormTrayTable
  11. BSaveAsOldVersionFormTrayTable
  12. Environment:
  13. Windows NT printer drivers
  14. Revision History:
  15. 12/03/97 -fengy-
  16. Added VUpdatePrivatePrinterData to split fixed fields in PrinterData
  17. into Keyword/Value pairs in Registry.
  18. 04/17/97 -davidx-
  19. Provide OEM plugins access to driver private devmode settings.
  20. 02/04/97 -davidx-
  21. Devmode changes to support OEM plugins.
  22. 10/02/96 -davidx-
  23. Implement BPSMergeDevmode.
  24. 09/26/96 -davidx-
  25. Created it.
  26. --*/
  27. #include "lib.h"
  28. #include "ppd.h"
  29. #include "pslib.h"
  30. #include "oemutil.h"
  31. //
  32. // Information about PostScript driver private devmode
  33. //
  34. CONST DRIVER_DEVMODE_INFO gDriverDMInfo =
  35. {
  36. PSDRIVER_VERSION, sizeof(PSDRVEXTRA),
  37. PSDRIVER_VERSION_500, sizeof(PSDRVEXTRA500),
  38. PSDRIVER_VERSION_400, sizeof(PSDRVEXTRA400),
  39. PSDRIVER_VERSION_351, sizeof(PSDRVEXTRA351),
  40. };
  41. CONST DWORD gdwDriverDMSignature = PSDEVMODE_SIGNATURE;
  42. CONST WORD gwDriverVersion = PSDRIVER_VERSION;
  43. static VOID
  44. VInitNewPrivateFields(
  45. PRAWBINARYDATA pRawData,
  46. PUIINFO pUIInfo,
  47. PPSDRVEXTRA pdmPrivate,
  48. BOOL bInitAllFields
  49. )
  50. /*++
  51. Routine Description:
  52. Intialize the new private devmode fields for PS 5.0
  53. Arguments:
  54. pUIInfo - Points to a UIINFO structure
  55. pRawData - Points to raw binary printer description data
  56. pdmPrivate - Points to the private devmode fields to be initialized
  57. bInitAllFields - Whether to initialize all new private fields or
  58. initialize the options array only
  59. Return Value:
  60. NONE
  61. --*/
  62. {
  63. if (bInitAllFields)
  64. {
  65. pdmPrivate->wReserved1 = 0;
  66. pdmPrivate->wSize = sizeof(PSDRVEXTRA);
  67. pdmPrivate->fxScrFreq = 0;
  68. pdmPrivate->fxScrAngle = 0;
  69. pdmPrivate->iDialect = SPEED;
  70. pdmPrivate->iTTDLFmt = TT_DEFAULT;
  71. pdmPrivate->bReversePrint = FALSE;
  72. pdmPrivate->iLayout = ONE_UP;
  73. pdmPrivate->iPSLevel = pUIInfo->dwLangLevel;
  74. pdmPrivate->wOEMExtra = 0;
  75. pdmPrivate->wVer = PSDRVEXTRA_VERSION;
  76. pdmPrivate->dwReserved2 = 0;
  77. ZeroMemory(pdmPrivate->dwReserved3, sizeof(pdmPrivate->dwReserved3));
  78. }
  79. InitDefaultOptions(pRawData,
  80. pdmPrivate->aOptions,
  81. MAX_PRINTER_OPTIONS,
  82. MODE_DOCUMENT_STICKY);
  83. pdmPrivate->dwOptions = pRawData->dwDocumentFeatures;
  84. pdmPrivate->dwChecksum32 = pRawData->dwChecksum32;
  85. }
  86. BOOL
  87. BInitDriverDefaultDevmode(
  88. OUT PDEVMODE pdmOut,
  89. IN LPCTSTR ptstrPrinterName,
  90. IN PUIINFO pUIInfo,
  91. IN PRAWBINARYDATA pRawData,
  92. IN BOOL bMetric
  93. )
  94. /*++
  95. Routine Description:
  96. Return the driver default devmode
  97. Arguments:
  98. pdmOut - Points to the output devmode to be initialized
  99. ptstrPrinterName - Specifies the name of the printer
  100. pUIInfo - Points to a UIINFO structure
  101. pRawData - Points to raw binary printer description data
  102. bMetric - Whether the system is running in metric mode
  103. Return Value:
  104. TRUE if successful, FALSE if there is an error
  105. Note:
  106. This function should initialize both public devmode fields
  107. and driver private devmode fields. It's also assumed that
  108. output buffer has already been zero initialized by the caller.
  109. --*/
  110. {
  111. PPSDRVEXTRA pdmPrivate;
  112. PFEATURE pFeature;
  113. PPPDDATA pPpdData;
  114. //
  115. // Initialize public devmode fields
  116. //
  117. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
  118. ASSERT(pPpdData != NULL);
  119. pdmOut->dmDriverVersion = PSDRIVER_VERSION;
  120. pdmOut->dmSpecVersion = DM_SPECVERSION;
  121. pdmOut->dmSize = sizeof(DEVMODE);
  122. pdmOut->dmDriverExtra = sizeof(PSDRVEXTRA);
  123. pdmOut->dmFields = DM_ORIENTATION |
  124. DM_SCALE |
  125. DM_COPIES |
  126. DM_PRINTQUALITY |
  127. DM_YRESOLUTION |
  128. DM_TTOPTION |
  129. #ifndef WINNT_40
  130. DM_NUP |
  131. #endif
  132. DM_COLOR |
  133. DM_DEFAULTSOURCE;
  134. pdmOut->dmOrientation = DMORIENT_PORTRAIT;
  135. pdmOut->dmDuplex = DMDUP_SIMPLEX;
  136. pdmOut->dmCollate = DMCOLLATE_FALSE;
  137. pdmOut->dmMediaType = DMMEDIA_STANDARD;
  138. pdmOut->dmTTOption = DMTT_SUBDEV;
  139. pdmOut->dmColor = DMCOLOR_MONOCHROME;
  140. pdmOut->dmDefaultSource = DMBIN_FORMSOURCE;
  141. pdmOut->dmScale = 100;
  142. pdmOut->dmCopies = 1;
  143. pdmOut->dmPrintQuality =
  144. pdmOut->dmYResolution = DEFAULT_RESOLUTION;
  145. #ifndef WINNT_40
  146. pdmOut->dmNup = DMNUP_SYSTEM;
  147. #endif
  148. if (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_RESOLUTION))
  149. {
  150. PRESOLUTION pRes;
  151. //
  152. // Use the default resolution specified in the PPD file
  153. //
  154. if (pRes = PGetIndexedOption(pUIInfo, pFeature, pFeature->dwDefaultOptIndex))
  155. {
  156. pdmOut->dmPrintQuality = (short)pRes->iXdpi;
  157. pdmOut->dmYResolution = (short)pRes->iYdpi;
  158. }
  159. }
  160. if (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_DUPLEX))
  161. {
  162. PDUPLEX pDuplex;
  163. //
  164. // Use the default duplex option specified in the PPD file
  165. //
  166. pdmOut->dmFields |= DM_DUPLEX;
  167. if (pDuplex = PGetIndexedOption(pUIInfo, pFeature, pFeature->dwDefaultOptIndex))
  168. pdmOut->dmDuplex = (SHORT) pDuplex->dwDuplexID;
  169. }
  170. #ifdef WINNT_40
  171. if (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_COLLATE))
  172. {
  173. PCOLLATE pCollate;
  174. pdmOut->dmFields |= DM_COLLATE;
  175. if (pCollate = PGetIndexedOption(pUIInfo, pFeature, pFeature->dwDefaultOptIndex))
  176. pdmOut->dmCollate = (SHORT) pCollate->dwCollateID;
  177. }
  178. #else // !WINNT_40
  179. pdmOut->dmFields |= DM_COLLATE;
  180. pdmOut->dmCollate = DMCOLLATE_TRUE;
  181. #endif // !WINNT_40
  182. if (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_MEDIATYPE))
  183. {
  184. //
  185. // Use the default media type specified in the PPD file
  186. //
  187. pdmOut->dmFields |= DM_MEDIATYPE;
  188. if (pFeature->dwDefaultOptIndex != OPTION_INDEX_ANY)
  189. pdmOut->dmMediaType = DMMEDIA_USER + pFeature->dwDefaultOptIndex;
  190. }
  191. //
  192. // Adobe wants to preserve the color information even for b/w printers.
  193. // So for both b/w and color printers, turn color on by default for Adobe.
  194. //
  195. #ifndef ADOBE
  196. if (IS_COLOR_DEVICE(pUIInfo))
  197. {
  198. #endif // !ADOBE
  199. //
  200. // Turn color on by default
  201. //
  202. pdmOut->dmColor = DMCOLOR_COLOR;
  203. pdmOut->dmFields |= DM_COLOR;
  204. #ifndef ADOBE
  205. }
  206. #endif // !ADOBE
  207. //
  208. // We always set ICM off. The spooler will turn it on at install time
  209. // if there are color profiles installed with this printer
  210. //
  211. pdmOut->dmICMMethod = DMICMMETHOD_NONE;
  212. pdmOut->dmICMIntent = DMICM_CONTRAST;
  213. #ifndef WINNT_40
  214. #ifndef ADOBE
  215. if (IS_COLOR_DEVICE(pUIInfo))
  216. {
  217. #endif // !ADOBE
  218. pdmOut->dmFields |= (DM_ICMMETHOD | DM_ICMINTENT);
  219. #ifndef ADOBE
  220. }
  221. #endif // !ADOBE
  222. #endif // !WINNT_40
  223. //
  224. // dmDeviceName field will be filled elsewhere.
  225. // Use an arbitrary default value if the input parameter is NULL.
  226. //
  227. CopyString(pdmOut->dmDeviceName,
  228. ptstrPrinterName ? ptstrPrinterName : TEXT("PostScript"),
  229. CCHDEVICENAME);
  230. //
  231. // Initialize form-related fields
  232. //
  233. VDefaultDevmodeFormFields(pUIInfo, pdmOut, bMetric);
  234. //
  235. // Private devmode fields
  236. //
  237. pdmPrivate = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdmOut);
  238. pdmPrivate->dwSignature = PSDEVMODE_SIGNATURE;
  239. pdmPrivate->coloradj = gDefaultHTColorAdjustment;
  240. #ifndef WINNT_40
  241. pdmPrivate->dwFlags = PSDEVMODE_METAFILE_SPOOL;
  242. #endif
  243. if (pPpdData->dwFlags & PPDFLAG_PRINTPSERROR)
  244. pdmPrivate->dwFlags |= PSDEVMODE_EHANDLER;
  245. if (pUIInfo->dwLangLevel > 1)
  246. pdmPrivate->dwFlags |= PSDEVMODE_COMPRESSBMP;
  247. #ifndef KERNEL_MODE
  248. //
  249. // Set up some private devmode flag bits for compatibility
  250. // with previous versions of the driver.
  251. //
  252. pdmPrivate->dwFlags |= PSDEVMODE_CTRLD_AFTER;
  253. if (GetACP() == 1252)
  254. pdmPrivate->dwFlags |= (PSDEVMODE_FONTSUBST|PSDEVMODE_ENUMPRINTERFONTS);
  255. #endif
  256. //
  257. // Intialize the new private devmode fields for PS 5.0
  258. //
  259. VInitNewPrivateFields(pRawData, pUIInfo, pdmPrivate, TRUE);
  260. if (SUPPORT_CUSTOMSIZE(pUIInfo))
  261. {
  262. VFillDefaultCustomPageSizeData(pRawData, &pdmPrivate->csdata, bMetric);
  263. }
  264. else
  265. {
  266. ZeroMemory(&pdmPrivate->csdata, sizeof(pdmPrivate->csdata));
  267. pdmPrivate->csdata.dwX = pdmOut->dmPaperWidth * DEVMODE_PAPER_UNIT;
  268. pdmPrivate->csdata.dwY = pdmOut->dmPaperLength * DEVMODE_PAPER_UNIT;
  269. }
  270. return TRUE;
  271. }
  272. BOOL
  273. BMergeDriverDevmode(
  274. IN OUT PDEVMODE pdmOut,
  275. IN PUIINFO pUIInfo,
  276. IN PRAWBINARYDATA pRawData,
  277. IN PDEVMODE pdmIn
  278. )
  279. /*++
  280. Routine Description:
  281. Merge the input devmode with an existing devmode.
  282. Arguments:
  283. pdmOut - Points to a valid output devmode
  284. pUIInfo - Points to a UIINFO structure
  285. pRawData - Points to raw binary printer description data
  286. pdmIn - Points to the input devmode
  287. Return Value:
  288. TRUE if successful, FALSE if there is a fatal error
  289. Note:
  290. This function should take care of both public devmode fields
  291. and driver private devmode fields. It can assume the input
  292. devmode has already been convert to the current size.
  293. --*/
  294. {
  295. PPSDRVEXTRA pdmPrivateIn, pdmPrivateOut;
  296. PFEATURE pFeature;
  297. PPPDDATA pPpdData;
  298. ASSERT(pdmOut != NULL &&
  299. pdmOut->dmSize == sizeof(DEVMODE) &&
  300. pdmOut->dmDriverExtra >= sizeof(PSDRVEXTRA) &&
  301. pdmIn != NULL &&
  302. pdmIn->dmSize == sizeof(DEVMODE) &&
  303. pdmIn->dmDriverExtra >= sizeof(PSDRVEXTRA));
  304. pdmPrivateIn = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdmIn);
  305. pdmPrivateOut = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdmOut);
  306. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
  307. ASSERT(pPpdData != NULL);
  308. //
  309. // Merge the public devmode fields
  310. //
  311. #ifndef WINNT_40
  312. if ( (pdmIn->dmFields & DM_NUP) &&
  313. (pdmIn->dmNup == DMNUP_SYSTEM ||
  314. pdmIn->dmNup == DMNUP_ONEUP))
  315. {
  316. pdmOut->dmNup = pdmIn->dmNup;
  317. pdmOut->dmFields |= DM_NUP;
  318. }
  319. #endif // #ifndef WINNT_40
  320. if (pdmIn->dmFields & DM_DEFAULTSOURCE &&
  321. ((pdmIn->dmDefaultSource >= DMBIN_FIRST &&
  322. pdmIn->dmDefaultSource <= DMBIN_LAST) ||
  323. pdmIn->dmDefaultSource >= DMBIN_USER))
  324. {
  325. pdmOut->dmFields |= DM_DEFAULTSOURCE;
  326. pdmOut->dmDefaultSource = pdmIn->dmDefaultSource;
  327. }
  328. if ((pdmIn->dmFields & DM_ORIENTATION) &&
  329. (pdmIn->dmOrientation == DMORIENT_PORTRAIT ||
  330. pdmIn->dmOrientation == DMORIENT_LANDSCAPE))
  331. {
  332. pdmOut->dmFields |= DM_ORIENTATION;
  333. pdmOut->dmOrientation = pdmIn->dmOrientation;
  334. }
  335. //
  336. // If both DM_PAPERLENGTH and DM_PAPERWIDTH are set, copy
  337. // dmPaperLength and dmPaperWidth fields. If DM_PAPERSIZE
  338. // is set, copy dmPaperSize field. Otherwise, if DM_FORMNAME
  339. // is set, copy dmFormName field.
  340. //
  341. if ((pdmIn->dmFields & DM_PAPERWIDTH) &&
  342. (pdmIn->dmFields & DM_PAPERLENGTH) &&
  343. (pdmIn->dmPaperWidth > 0) &&
  344. (pdmIn->dmPaperLength > 0))
  345. {
  346. pdmOut->dmFields |= (DM_PAPERLENGTH | DM_PAPERWIDTH);
  347. pdmOut->dmFields &= ~(DM_PAPERSIZE | DM_FORMNAME);
  348. pdmOut->dmPaperWidth = pdmIn->dmPaperWidth;
  349. pdmOut->dmPaperLength = pdmIn->dmPaperLength;
  350. }
  351. else if (pdmIn->dmFields & DM_PAPERSIZE)
  352. {
  353. if ((pdmIn->dmPaperSize != DMPAPER_CUSTOMSIZE) ||
  354. SUPPORT_CUSTOMSIZE(pUIInfo) &&
  355. SUPPORT_FULL_CUSTOMSIZE_FEATURES(pUIInfo, pPpdData))
  356. {
  357. pdmOut->dmFields |= DM_PAPERSIZE;
  358. pdmOut->dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH | DM_FORMNAME);
  359. pdmOut->dmPaperSize = pdmIn->dmPaperSize;
  360. }
  361. }
  362. else if (pdmIn->dmFields & DM_FORMNAME)
  363. {
  364. pdmOut->dmFields |= DM_FORMNAME;
  365. pdmOut->dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH | DM_PAPERSIZE);
  366. CopyString(pdmOut->dmFormName, pdmIn->dmFormName, CCHFORMNAME);
  367. }
  368. if ((pdmIn->dmFields & DM_SCALE) &&
  369. (pdmIn->dmScale >= MIN_SCALE) &&
  370. (pdmIn->dmScale <= MAX_SCALE))
  371. {
  372. pdmOut->dmFields |= DM_SCALE;
  373. pdmOut->dmScale = pdmIn->dmScale;
  374. }
  375. if ((pdmIn->dmFields & DM_COPIES) &&
  376. (pdmIn->dmCopies >= 1) &&
  377. (pdmIn->dmCopies <= (SHORT) pUIInfo->dwMaxCopies))
  378. {
  379. pdmOut->dmFields |= DM_COPIES;
  380. pdmOut->dmCopies = pdmIn->dmCopies;
  381. }
  382. if ((pdmIn->dmFields & DM_DUPLEX) &&
  383. (GET_PREDEFINED_FEATURE(pUIInfo, GID_DUPLEX) != NULL) &&
  384. (pdmIn->dmDuplex == DMDUP_SIMPLEX ||
  385. pdmIn->dmDuplex == DMDUP_HORIZONTAL ||
  386. pdmIn->dmDuplex == DMDUP_VERTICAL))
  387. {
  388. pdmOut->dmFields |= DM_DUPLEX;
  389. pdmOut->dmDuplex = pdmIn->dmDuplex;
  390. }
  391. if ((pdmIn->dmFields & DM_COLLATE) &&
  392. #ifdef WINNT_40
  393. GET_PREDEFINED_FEATURE(pUIInfo, GID_COLLATE) != NULL &&
  394. #endif
  395. (pdmIn->dmCollate == DMCOLLATE_TRUE ||
  396. pdmIn->dmCollate == DMCOLLATE_FALSE))
  397. {
  398. pdmOut->dmFields |= DM_COLLATE;
  399. pdmOut->dmCollate = pdmIn->dmCollate;
  400. }
  401. if ((pdmIn->dmFields & DM_TTOPTION) &&
  402. (pdmIn->dmTTOption == DMTT_BITMAP ||
  403. pdmIn->dmTTOption == DMTT_DOWNLOAD ||
  404. pdmIn->dmTTOption == DMTT_SUBDEV))
  405. {
  406. pdmOut->dmFields |= DM_TTOPTION;
  407. pdmOut->dmTTOption = (pdmIn->dmTTOption == DMTT_SUBDEV) ? DMTT_SUBDEV : DMTT_DOWNLOAD;
  408. }
  409. //
  410. // Merge color and ICM fields.
  411. //
  412. #ifndef ADOBE
  413. if (IS_COLOR_DEVICE(pUIInfo))
  414. {
  415. #endif // !ADOBE
  416. if ((pdmIn->dmFields & DM_COLOR) &&
  417. (pdmIn->dmColor == DMCOLOR_COLOR ||
  418. pdmIn->dmColor == DMCOLOR_MONOCHROME))
  419. {
  420. pdmOut->dmFields |= DM_COLOR;
  421. pdmOut->dmColor = pdmIn->dmColor;
  422. }
  423. #ifndef WINNT_40
  424. if ((pdmIn->dmFields & DM_ICMMETHOD) &&
  425. (pdmIn->dmICMMethod == DMICMMETHOD_NONE ||
  426. pdmIn->dmICMMethod == DMICMMETHOD_SYSTEM ||
  427. pdmIn->dmICMMethod == DMICMMETHOD_DRIVER ||
  428. pdmIn->dmICMMethod == DMICMMETHOD_DEVICE))
  429. {
  430. pdmOut->dmFields |= DM_ICMMETHOD;
  431. pdmOut->dmICMMethod = pdmIn->dmICMMethod;
  432. }
  433. if ((pdmIn->dmFields & DM_ICMINTENT) &&
  434. (pdmIn->dmICMIntent == DMICM_SATURATE ||
  435. pdmIn->dmICMIntent == DMICM_CONTRAST ||
  436. pdmIn->dmICMIntent == DMICM_COLORIMETRIC ||
  437. pdmIn->dmICMIntent == DMICM_ABS_COLORIMETRIC))
  438. {
  439. pdmOut->dmFields |= DM_ICMINTENT;
  440. pdmOut->dmICMIntent = pdmIn->dmICMIntent;
  441. }
  442. #endif // !WINNT_40
  443. #ifndef ADOBE
  444. }
  445. #endif // !ADOBE
  446. //
  447. // Resolution
  448. //
  449. if ((pdmIn->dmFields & (DM_PRINTQUALITY|DM_YRESOLUTION)) &&
  450. (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_RESOLUTION)))
  451. {
  452. PRESOLUTION pRes;
  453. DWORD dwIndex;
  454. INT iXdpi, iYdpi;
  455. switch (pdmIn->dmFields & (DM_PRINTQUALITY|DM_YRESOLUTION))
  456. {
  457. case DM_PRINTQUALITY:
  458. iXdpi = iYdpi = pdmIn->dmPrintQuality;
  459. break;
  460. case DM_YRESOLUTION:
  461. iXdpi = iYdpi = pdmIn->dmYResolution;
  462. break;
  463. default:
  464. iXdpi = pdmIn->dmPrintQuality;
  465. iYdpi = pdmIn->dmYResolution;
  466. break;
  467. }
  468. dwIndex = MapToDeviceOptIndex(pUIInfo->pInfoHeader,
  469. GID_RESOLUTION,
  470. iXdpi,
  471. iYdpi,
  472. NULL);
  473. if (pRes = PGetIndexedOption(pUIInfo, pFeature, dwIndex))
  474. {
  475. pdmOut->dmFields |= (DM_PRINTQUALITY|DM_YRESOLUTION);
  476. pdmOut->dmPrintQuality = (short)pRes->iXdpi;
  477. pdmOut->dmYResolution = (short)pRes->iYdpi;
  478. }
  479. }
  480. //
  481. // Media type
  482. //
  483. if ((pdmIn->dmFields & DM_MEDIATYPE) &&
  484. (pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_MEDIATYPE)) &&
  485. (pdmIn->dmMediaType == DMMEDIA_STANDARD ||
  486. pdmIn->dmMediaType == DMMEDIA_TRANSPARENCY ||
  487. pdmIn->dmMediaType == DMMEDIA_GLOSSY ||
  488. ((pdmIn->dmMediaType >= DMMEDIA_USER) &&
  489. (pdmIn->dmMediaType < DMMEDIA_USER + pFeature->Options.dwCount))))
  490. {
  491. pdmOut->dmFields |= DM_MEDIATYPE;
  492. pdmOut->dmMediaType = pdmIn->dmMediaType;
  493. }
  494. //
  495. // Merge the private devmode fields
  496. //
  497. if (pdmPrivateIn->dwSignature == PSDEVMODE_SIGNATURE)
  498. {
  499. CopyMemory(pdmPrivateOut, pdmPrivateIn, sizeof(PSDRVEXTRA));
  500. if (pdmPrivateOut->dwChecksum32 != pRawData->dwChecksum32)
  501. {
  502. WARNING(("PSCRIPT5: Devmode checksum mismatch.\n"));
  503. //
  504. // Intialize the new private devmode fields for PS 5.0.
  505. // If wReserved1 field is not 0, then the devmode is of
  506. // a previous version. In that case, we should initialize
  507. // all new private fields instead of just the options array.
  508. //
  509. VInitNewPrivateFields(pRawData,
  510. pUIInfo,
  511. pdmPrivateOut,
  512. pdmPrivateOut->wReserved1 != 0);
  513. //
  514. // Convert PS4 feature/option selections to PS4 format
  515. //
  516. if (pdmPrivateIn->wReserved1 == pPpdData->dwNt4Checksum)
  517. {
  518. VConvertOptSelectArray(pRawData,
  519. pdmPrivateOut->aOptions,
  520. MAX_PRINTER_OPTIONS,
  521. ((PSDRVEXTRA400 *) pdmPrivateIn)->aubOptions,
  522. 64,
  523. MODE_DOCUMENT_STICKY);
  524. }
  525. }
  526. if (pdmPrivateOut->iPSLevel == 0 ||
  527. pdmPrivateOut->iPSLevel > (INT) pUIInfo->dwLangLevel)
  528. {
  529. pdmPrivateOut->iPSLevel = pUIInfo->dwLangLevel;
  530. }
  531. if (pdmPrivateOut->iTTDLFmt == TYPE_42 && pUIInfo->dwTTRasterizer != TTRAS_TYPE42)
  532. pdmPrivateOut->iTTDLFmt = TT_DEFAULT;
  533. if (IS_COLOR_DEVICE(pUIInfo))
  534. {
  535. pdmPrivateOut->dwFlags &= ~PSDEVMODE_NEG;
  536. }
  537. }
  538. //
  539. // If custom page size is supported, make sure the custom page
  540. // size parameters are valid.
  541. //
  542. if (SUPPORT_CUSTOMSIZE(pUIInfo))
  543. (VOID) BValidateCustomPageSizeData(pRawData, &pdmPrivateOut->csdata);
  544. return TRUE;
  545. }
  546. BOOL
  547. BValidateDevmodeCustomPageSizeFields(
  548. PRAWBINARYDATA pRawData,
  549. PUIINFO pUIInfo,
  550. PDEVMODE pdm,
  551. PRECTL prclImageArea
  552. )
  553. /*++
  554. Routine Description:
  555. Check if the devmode form fields are specifying PostScript custom page size
  556. Arguments:
  557. pRawData - Points to raw printer description data
  558. pUIInfo - Points to UIINFO structure
  559. pdm - Points to input devmode
  560. prclImageArea - Returns imageable area of the custom page size
  561. Return Value:
  562. TRUE if the devmode specifies PostScript custom page size
  563. FALSE otherwise
  564. --*/
  565. {
  566. PPPDDATA pPpdData;
  567. PPSDRVEXTRA pdmPrivate;
  568. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
  569. ASSERT(pPpdData != NULL);
  570. if ((pdm->dmFields & DM_PAPERSIZE) &&
  571. pdm->dmPaperSize == DMPAPER_CUSTOMSIZE &&
  572. SUPPORT_CUSTOMSIZE(pUIInfo) &&
  573. SUPPORT_FULL_CUSTOMSIZE_FEATURES(pUIInfo, pPpdData))
  574. {
  575. pdmPrivate = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdm);
  576. pdm->dmFields &= ~(DM_PAPERWIDTH|DM_PAPERLENGTH|DM_FORMNAME);
  577. pdm->dmPaperWidth = (SHORT) (pdmPrivate->csdata.dwX / DEVMODE_PAPER_UNIT);
  578. pdm->dmPaperLength = (SHORT) (pdmPrivate->csdata.dwY / DEVMODE_PAPER_UNIT);
  579. ZeroMemory(pdm->dmFormName, sizeof(pdm->dmFormName));
  580. if (prclImageArea)
  581. {
  582. prclImageArea->left =
  583. prclImageArea->top = 0;
  584. prclImageArea->right = pdmPrivate->csdata.dwX;
  585. prclImageArea->bottom = pdmPrivate->csdata.dwY;
  586. }
  587. return TRUE;
  588. }
  589. return FALSE;
  590. }
  591. VOID
  592. VCopyUnicodeStringToAnsi(
  593. PSTR pstr,
  594. PCWSTR pwstr,
  595. INT iMaxChars
  596. )
  597. /*++
  598. Routine Description:
  599. Convert an ANSI string to a UNICODE string (using the current ANSI codepage)
  600. Arguments:
  601. pstr - Pointer to buffer for holding ANSI string
  602. pwstr - Pointer to Unicode string
  603. iMaxChars - Maximum number of ANSI characters to copy
  604. Return Value:
  605. NONE
  606. Note:
  607. If iMaxChars is 0 or negative, we assume the caller has provided
  608. an ANSI buffer that's sufficiently large to do the conversion.
  609. --*/
  610. {
  611. INT iLen = wcslen(pwstr) + 1;
  612. if (iMaxChars <= 0)
  613. iMaxChars = iLen;
  614. #ifdef KERNEL_MODE
  615. (VOID) EngUnicodeToMultiByteN(pstr, iMaxChars, NULL, (PWSTR) pwstr, iLen*sizeof(WCHAR));
  616. #else // !KERNEL_MODE
  617. (VOID) WideCharToMultiByte(CP_ACP, 0, pwstr, iLen, pstr, iMaxChars, NULL, NULL);
  618. #endif
  619. pstr[iMaxChars - 1] = NUL;
  620. }
  621. FORM_TRAY_TABLE
  622. PGetAndConvertOldVersionFormTrayTable(
  623. IN HANDLE hPrinter,
  624. OUT PDWORD pdwSize
  625. )
  626. /*++
  627. Routine Description:
  628. Retrieve the old form-to-tray assignment table from registry and convert
  629. it to the new format for the caller.
  630. Arguments:
  631. hPrinter - Handle to the printer object
  632. pdwSize - Returns the form-to-tray assignment table size
  633. Return Value:
  634. Pointer to form-to-tray assignment table read from the registry
  635. NULL if there is an error
  636. --*/
  637. {
  638. PTSTR ptstrNewTable;
  639. PTSTR ptstrOld, ptstrEnd, ptstrNew, ptstrSave;
  640. DWORD dwTableSize, dwNewTableSize;
  641. FORM_TRAY_TABLE pFormTrayTable;
  642. //
  643. // Retrieve the form-to-tray assignment information from registry
  644. //
  645. pFormTrayTable = PvGetPrinterDataBinary(hPrinter,
  646. REGVAL_TRAY_FORM_SIZE_PS40,
  647. REGVAL_TRAY_FORM_TABLE_PS40,
  648. &dwTableSize);
  649. if (pFormTrayTable == NULL)
  650. return NULL;
  651. //
  652. // Simple validation to make sure the information is valid
  653. // Old format contains the table size as the first field in table
  654. //
  655. if (dwTableSize != *pFormTrayTable)
  656. {
  657. ERR(("Corrupted form-to-tray assignment table!\n"));
  658. SetLastError(ERROR_INVALID_DATA);
  659. MemFree(pFormTrayTable);
  660. return NULL;
  661. }
  662. //
  663. // Convert the old format form-to-tray assignment table to new format
  664. // OLD NEW
  665. // Tray Name Tray Name
  666. // Form Name Form Name
  667. // Printer Form
  668. // IsDefaultTray
  669. //
  670. //
  671. // The first WCHAR hold the size of the table
  672. //
  673. dwTableSize -= sizeof(WCHAR);
  674. ptstrOld = pFormTrayTable + 1;
  675. ptstrEnd = ptstrOld + (dwTableSize / sizeof(WCHAR) - 1);
  676. //
  677. // Figuring out the size of new table, the last entry in the table
  678. // is always a NUL so add the count for it here first
  679. //
  680. dwNewTableSize = 1;
  681. while (ptstrOld < ptstrEnd && *ptstrOld != NUL)
  682. {
  683. ptstrSave = ptstrOld;
  684. ptstrOld += _tcslen(ptstrOld) + 1;
  685. ptstrOld += _tcslen(ptstrOld) + 1;
  686. //
  687. // New format contain only TrayName and FormName
  688. //
  689. dwNewTableSize += (DWORD)(ptstrOld - ptstrSave);
  690. //
  691. // Skip printer form and IsDefaultTray flag
  692. //
  693. ptstrOld += _tcslen(ptstrOld) + 2;
  694. }
  695. dwNewTableSize *= sizeof(WCHAR);
  696. if ((ptstrOld != ptstrEnd) ||
  697. (*ptstrOld != NUL) ||
  698. (ptstrNewTable = MemAlloc(dwNewTableSize)) == NULL)
  699. {
  700. ERR(( "Couldn't convert form-to-tray assignment table.\n"));
  701. MemFree(pFormTrayTable);
  702. return NULL;
  703. }
  704. //
  705. // The first WCHAR contains the table size
  706. //
  707. ptstrOld = pFormTrayTable + 1;
  708. ptstrNew = ptstrNewTable;
  709. while (*ptstrOld != NUL)
  710. {
  711. //
  712. // Copy slot name, form name
  713. //
  714. ptstrSave = ptstrOld;
  715. ptstrOld += _tcslen(ptstrOld) + 1;
  716. ptstrOld += _tcslen(ptstrOld) + 1;
  717. CopyMemory(ptstrNew, ptstrSave, (ptstrOld - ptstrSave) * sizeof(WCHAR));
  718. ptstrNew += (ptstrOld - ptstrSave);
  719. //
  720. // skip printer form and IsDefaultTray flag
  721. //
  722. ptstrOld += _tcslen(ptstrOld) + 2;
  723. }
  724. //
  725. // The last WCHAR is a NUL-terminator
  726. //
  727. *ptstrNew = NUL;
  728. if (pdwSize)
  729. *pdwSize = dwNewTableSize;
  730. MemFree(pFormTrayTable);
  731. ASSERT(BVerifyMultiSZPair(ptstrNewTable, dwNewTableSize));
  732. return(ptstrNewTable);
  733. }
  734. #ifndef KERNEL_MODE
  735. BOOL
  736. BSaveAsOldVersionFormTrayTable(
  737. IN HANDLE hPrinter,
  738. IN FORM_TRAY_TABLE pFormTrayTable,
  739. IN DWORD dwSize
  740. )
  741. /*++
  742. Routine Description:
  743. Save form-to-tray assignment table in NT 4.0 compatible format
  744. Arguments:
  745. hPrinter - Handle to the current printer
  746. pFormTrayTable - Points to new format form-tray table
  747. dwSize - Size of form-tray table to be saved, in bytes
  748. Return Value:
  749. TRUE if successful, FALSE if there is an error
  750. --*/
  751. {
  752. DWORD dwOldTableSize;
  753. PTSTR ptstrNew, ptstrOld, ptstrOldTable;
  754. BOOL bResult;
  755. //
  756. // Find out how much memory to allocate for old format table
  757. // Old format table has size as its very first character
  758. //
  759. ASSERT((dwSize % sizeof(TCHAR)) == 0 && dwSize >= sizeof(TCHAR));
  760. dwOldTableSize = dwSize + sizeof(WCHAR);
  761. ptstrNew = pFormTrayTable;
  762. while (*ptstrNew != NUL)
  763. {
  764. //
  765. // Skip tray name and form name
  766. //
  767. ptstrNew += _tcslen(ptstrNew) + 1;
  768. ptstrNew += _tcslen(ptstrNew) + 1;
  769. //
  770. // Old format has two extra characters per entry
  771. // one for the empty PrinterForm field
  772. // another for IsDefaultTray flag
  773. //
  774. dwOldTableSize += 2 * sizeof(TCHAR);
  775. }
  776. if ((ptstrOldTable = MemAlloc(dwOldTableSize)) == NULL)
  777. {
  778. ERR(("Memory allocation failed\n"));
  779. return FALSE;
  780. }
  781. //
  782. // Convert new format table to old format
  783. // Be careful about the IsDefaultTray flag
  784. //
  785. ptstrNew = pFormTrayTable;
  786. ptstrOld = ptstrOldTable;
  787. *ptstrOld++ = (TCHAR) dwOldTableSize;
  788. while (*ptstrNew != NUL)
  789. {
  790. //
  791. // Copy slot name and form name
  792. //
  793. FINDFORMTRAY FindData;
  794. DWORD dwCount;
  795. PTSTR ptstrTrayName, ptstrFormName;
  796. ptstrTrayName = ptstrNew;
  797. ptstrNew += _tcslen(ptstrNew) + 1;
  798. ptstrFormName = ptstrNew;
  799. ptstrNew += _tcslen(ptstrNew) + 1;
  800. CopyMemory(ptstrOld, ptstrTrayName, (ptstrNew - ptstrTrayName) * sizeof(TCHAR));
  801. ptstrOld += (ptstrNew - ptstrTrayName);
  802. //
  803. // Set PrinterForm field to NUL
  804. //
  805. *ptstrOld++ = NUL;
  806. //
  807. // Set IsDefaultTray flag appropriately
  808. //
  809. dwCount = 0;
  810. RESET_FINDFORMTRAY(pFormTrayTable, &FindData);
  811. while (BSearchFormTrayTable(pFormTrayTable, NULL, ptstrFormName, &FindData))
  812. dwCount++;
  813. *ptstrOld++ = (dwCount == 1) ? TRUE : FALSE;
  814. }
  815. //
  816. // The last character is a NUL-terminator
  817. //
  818. *ptstrOld = NUL;
  819. bResult = BSetPrinterDataBinary(
  820. hPrinter,
  821. REGVAL_TRAY_FORM_SIZE_PS40,
  822. REGVAL_TRAY_FORM_TABLE_PS40,
  823. ptstrOldTable,
  824. dwOldTableSize);
  825. MemFree(ptstrOldTable);
  826. return bResult;
  827. }
  828. #endif // !KERNEL_MODE
  829. BOOL
  830. BGetDevmodeSettingForOEM(
  831. IN PDEVMODE pdm,
  832. IN DWORD dwIndex,
  833. OUT PVOID pOutput,
  834. IN DWORD cbSize,
  835. OUT PDWORD pcbNeeded
  836. )
  837. /*++
  838. Routine Description:
  839. Function to provide OEM plugins access to driver private devmode settings
  840. Arguments:
  841. pdm - Points to the devmode to be access
  842. dwIndex - Predefined index to specify which devmode the caller is interested in
  843. pOutput - Points to output buffer
  844. cbSize - Size of output buffer
  845. pcbNeeded - Returns the expected size of output buffer
  846. Return Value:
  847. TRUE if successful, FALSE if there is an error
  848. --*/
  849. #define MAPPSDEVMODEFIELD(index, field) \
  850. { index, offsetof(PSDRVEXTRA, field), sizeof(pdmPrivate->field) }
  851. {
  852. PPSDRVEXTRA pdmPrivate;
  853. INT i;
  854. static const struct {
  855. DWORD dwIndex;
  856. DWORD dwOffset;
  857. DWORD dwSize;
  858. } aIndexMap[] = {
  859. MAPPSDEVMODEFIELD(OEMGDS_PSDM_FLAGS, dwFlags),
  860. MAPPSDEVMODEFIELD(OEMGDS_PSDM_DIALECT, iDialect),
  861. MAPPSDEVMODEFIELD(OEMGDS_PSDM_TTDLFMT, iTTDLFmt),
  862. MAPPSDEVMODEFIELD(OEMGDS_PSDM_NUP, iLayout),
  863. MAPPSDEVMODEFIELD(OEMGDS_PSDM_PSLEVEL, iPSLevel),
  864. MAPPSDEVMODEFIELD(OEMGDS_PSDM_CUSTOMSIZE, csdata),
  865. { 0, 0, 0 }
  866. };
  867. pdmPrivate = (PPSDRVEXTRA) GET_DRIVER_PRIVATE_DEVMODE(pdm);
  868. i = 0;
  869. while (aIndexMap[i].dwSize != 0)
  870. {
  871. if (aIndexMap[i].dwIndex == dwIndex)
  872. {
  873. *pcbNeeded = aIndexMap[i].dwSize;
  874. if (cbSize < aIndexMap[i].dwSize || pOutput == NULL)
  875. {
  876. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  877. return FALSE;
  878. }
  879. CopyMemory(pOutput, (PBYTE) pdmPrivate + aIndexMap[i].dwOffset, aIndexMap[i].dwSize);
  880. return TRUE;
  881. }
  882. i++;
  883. }
  884. WARNING(("Unknown pscript devmode index: %d\n", dwIndex));
  885. SetLastError(ERROR_NOT_SUPPORTED);
  886. return FALSE;
  887. }
  888. BOOL
  889. BConvertPrinterPropertiesData(
  890. IN HANDLE hPrinter,
  891. IN PRAWBINARYDATA pRawData,
  892. OUT PPRINTERDATA pPrinterData,
  893. IN PVOID pvSrcData,
  894. IN DWORD dwSrcSize
  895. )
  896. /*++
  897. Routine Description:
  898. Convert an older or newer version PRINTERDATA structure to current version
  899. Arguments:
  900. hPrinter - Handle to the current printer
  901. pRawData - Points to raw printer description data
  902. pPrinterData - Points to destination buffer
  903. pvSrcData - Points to source data to be converted
  904. dwSrcSize - Size of the source data in bytes
  905. Return Value:
  906. TRUE if conversion was successful, FALSE otherwise
  907. Note:
  908. This function is called after the library function has already
  909. done a generic conversion.
  910. --*/
  911. {
  912. PPS4_PRINTERDATA pSrc = pvSrcData;
  913. PPPDDATA pPpdData;
  914. //
  915. // Check if the source PRINTERDATA was from NT4 PS driver
  916. //
  917. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pRawData);
  918. ASSERT(pPpdData != NULL);
  919. if (dwSrcSize != sizeof(PS4_PRINTERDATA) ||
  920. dwSrcSize != pSrc->wSize ||
  921. pSrc->wDriverVersion != PSDRIVER_VERSION_400 ||
  922. pSrc->wChecksum != pPpdData->dwNt4Checksum)
  923. {
  924. return FALSE;
  925. }
  926. //
  927. // Convert PS4 feature/option selections to PS4 format
  928. //
  929. VConvertOptSelectArray(pRawData,
  930. pPrinterData->aOptions,
  931. MAX_PRINTER_OPTIONS,
  932. pSrc->options,
  933. 64,
  934. MODE_PRINTER_STICKY);
  935. return TRUE;
  936. }
  937. VOID
  938. VUpdatePrivatePrinterData(
  939. IN HANDLE hPrinter,
  940. IN OUT PPRINTERDATA pPrinterData,
  941. IN DWORD dwMode,
  942. IN PUIINFO pUIInfo,
  943. IN POPTSELECT pCombineOptions
  944. )
  945. /*++
  946. Routine Description:
  947. Update the Registry with the keyword/value pairs
  948. of PRINTERDATA's fixed fields.
  949. Arguments:
  950. hPrinter - Handle to the current printer
  951. pPrinterData - Points to PRINTERDATA
  952. dwMode - MODE_READ/MODE_WRITE
  953. Return Value:
  954. None
  955. --*/
  956. {
  957. DWORD dwValue, dwMinFreeMem;
  958. #ifdef KERNEL_MODE
  959. ASSERT(dwMode == MODE_READ);
  960. #endif
  961. //
  962. // read/write PRINTERDATA fields from/to registry
  963. //
  964. if (dwMode == MODE_READ)
  965. {
  966. if (BGetPrinterDataDWord(hPrinter, REGVAL_FREEMEM, &dwValue))
  967. {
  968. //
  969. // REGVAL_FREEMEM is in unit of Kbyte, we need to convert it to byte.
  970. // Also make sure the value is not less than the minimum value we required.
  971. //
  972. dwMinFreeMem = pUIInfo->dwLangLevel < 2 ? MIN_FREEMEM_L1: MIN_FREEMEM_L2;
  973. pPrinterData->dwFreeMem = max(dwValue * KBYTES, dwMinFreeMem);
  974. }
  975. if (BGetPrinterDataDWord(hPrinter, REGVAL_JOBTIMEOUT, &dwValue))
  976. {
  977. pPrinterData->dwJobTimeout = dwValue;
  978. }
  979. if (BGetPrinterDataDWord(hPrinter, REGVAL_PROTOCOL, &dwValue))
  980. {
  981. pPrinterData->wProtocol = (WORD)dwValue;
  982. if (pPrinterData->wProtocol != PROTOCOL_ASCII &&
  983. pPrinterData->wProtocol != PROTOCOL_BCP &&
  984. pPrinterData->wProtocol != PROTOCOL_TBCP &&
  985. pPrinterData->wProtocol != PROTOCOL_BINARY)
  986. {
  987. pPrinterData->wProtocol = PROTOCOL_ASCII;
  988. }
  989. }
  990. }
  991. #ifndef KERNEL_MODE
  992. else
  993. {
  994. ASSERT(dwMode == MODE_WRITE);
  995. //
  996. // Remember to convert byte to Kbyte for REGVAL_FREEMEM
  997. //
  998. (VOID) BSetPrinterDataDWord(hPrinter, REGVAL_FREEMEM, pPrinterData->dwFreeMem / KBYTES);
  999. (VOID) BSetPrinterDataDWord(hPrinter, REGVAL_JOBTIMEOUT, pPrinterData->dwJobTimeout);
  1000. (VOID) BSetPrinterDataDWord(hPrinter, REGVAL_PROTOCOL, (DWORD)pPrinterData->wProtocol);
  1001. }
  1002. #endif // !KERNEL_MODE
  1003. }
  1004. VOID
  1005. VDefaultDevmodeFormFields(
  1006. PUIINFO pUIInfo,
  1007. PDEVMODE pDevmode,
  1008. BOOL bMetric
  1009. )
  1010. /*++
  1011. Routine Description:
  1012. Initialized the form-related devmode fields with their default values
  1013. Arguments:
  1014. pUIInfo - Points for UIINFO
  1015. pDevmode - Points to the DEVMODE whose form-related fields are to be initialized
  1016. bMetric - Specifies whether the system is running in metric mode
  1017. Return Value:
  1018. NONE
  1019. --*/
  1020. {
  1021. ASSERT(pUIInfo);
  1022. if (!(bMetric && (pUIInfo->dwFlags & FLAG_A4_SIZE_EXISTS)) &&
  1023. !(!bMetric && (pUIInfo->dwFlags & FLAG_LETTER_SIZE_EXISTS)))
  1024. {
  1025. PFEATURE pFeature;
  1026. PPAGESIZE pPageSize;
  1027. PCWSTR pDisplayName;
  1028. //
  1029. // A4 or Letter not available. Use the printer's default paper size.
  1030. //
  1031. if ((pFeature = GET_PREDEFINED_FEATURE(pUIInfo, GID_PAGESIZE)) &&
  1032. (pPageSize = PGetIndexedOption(pUIInfo, pFeature, pFeature->dwDefaultOptIndex)) &&
  1033. (pDisplayName = OFFSET_TO_POINTER(pUIInfo->pubResourceData, pPageSize->GenericOption.loDisplayName)))
  1034. {
  1035. CopyString(pDevmode->dmFormName, pDisplayName, CCHFORMNAME);
  1036. pDevmode->dmPaperSize = (short)(pPageSize->dwPaperSizeID);
  1037. pDevmode->dmPaperWidth = (short)(pPageSize->szPaperSize.cx / DEVMODE_PAPER_UNIT);
  1038. pDevmode->dmPaperLength = (short)(pPageSize->szPaperSize.cy / DEVMODE_PAPER_UNIT);
  1039. //
  1040. // PPD parser always assigns custom paper size values to dwPaperSizeID (see ppdparse.c), including for
  1041. // standard page sizes, so we need to use dmPaperSize/dmPaperWidth in devmode instead of dmPaperSize.
  1042. //
  1043. pDevmode->dmFields |= (DM_FORMNAME | DM_PAPERWIDTH | DM_PAPERLENGTH);
  1044. pDevmode->dmFields &= ~DM_PAPERSIZE;
  1045. //
  1046. // return when we succeeded, otherwise we will fall into the default A4 or Letter case
  1047. //
  1048. return;
  1049. }
  1050. else
  1051. {
  1052. ERR(("Failed to get default paper size from PPD\n"));
  1053. }
  1054. }
  1055. if (bMetric)
  1056. {
  1057. CopyString(pDevmode->dmFormName, A4_FORMNAME, CCHFORMNAME);
  1058. pDevmode->dmPaperSize = DMPAPER_A4;
  1059. pDevmode->dmPaperWidth = 2100; // 210mm measured in 0.1mm units
  1060. pDevmode->dmPaperLength = 2970; // 297mm
  1061. }
  1062. else
  1063. {
  1064. CopyString(pDevmode->dmFormName, LETTER_FORMNAME, CCHFORMNAME);
  1065. pDevmode->dmPaperSize = DMPAPER_LETTER;
  1066. pDevmode->dmPaperWidth = 2159; // 8.5"
  1067. pDevmode->dmPaperLength = 2794; // 11"
  1068. }
  1069. pDevmode->dmFields &= ~(DM_PAPERWIDTH | DM_PAPERLENGTH);
  1070. pDevmode->dmFields |= (DM_PAPERSIZE | DM_FORMNAME);
  1071. }
  1072. #if !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)
  1073. typedef struct _VMERRMSGIDTBL
  1074. {
  1075. LANGID lgid; // Language ID
  1076. DWORD resid; // VM error handler resource ID
  1077. }
  1078. VMERRMSGIDTBL, *PVMERRMSGIDTBL;
  1079. VMERRMSGIDTBL VMErrMsgIDTbl[] =
  1080. {
  1081. // Lang. ID Res. ID
  1082. { LANG_CHINESE, 0 }, // Chinense: use sub table below
  1083. { LANG_DANISH, PSPROC_vmerr_Danish_ps }, // Danish Adobe bug#342407
  1084. { LANG_DUTCH, PSPROC_vmerr_Dutch_ps }, // Dutch
  1085. { LANG_FINNISH, PSPROC_vmerr_Finnish_ps }, // Finnish Adobe bug#342407
  1086. { LANG_FRENCH, PSPROC_vmerr_French_ps }, // French
  1087. { LANG_GERMAN, PSPROC_vmerr_German_ps }, // German
  1088. { LANG_ITALIAN, PSPROC_vmerr_Italian_ps }, // Italian
  1089. { LANG_JAPANESE, PSPROC_vmerr_Japanese_ps }, // Japanese
  1090. { LANG_KOREAN, PSPROC_vmerr_Korean_ps }, // Korean
  1091. { LANG_NORWEGIAN, PSPROC_vmerr_Norwegian_ps }, // Norwegian Adobe bug#342407
  1092. { LANG_PORTUGUESE, PSPROC_vmerr_Portuguese_ps }, // Portuguese
  1093. { LANG_SPANISH, PSPROC_vmerr_Spanish_ps }, // Spanish
  1094. { LANG_SWEDISH, PSPROC_vmerr_Swedish_ps }, // Swedish
  1095. { 0, 0 } // Stopper. Don't remove this.
  1096. };
  1097. VMERRMSGIDTBL VMErrMsgIDTbl2[] =
  1098. {
  1099. // Sub lang. ID Res. ID
  1100. { SUBLANG_CHINESE_TRADITIONAL, PSPROC_vmerr_TraditionalChinese_ps }, // Taiwan
  1101. { SUBLANG_CHINESE_SIMPLIFIED, PSPROC_vmerr_SimplifiedChinese_ps }, // PRC
  1102. { SUBLANG_CHINESE_HONGKONG, PSPROC_vmerr_TraditionalChinese_ps }, // Hong Kong
  1103. { SUBLANG_CHINESE_SINGAPORE, PSPROC_vmerr_SimplifiedChinese_ps }, // Singapore
  1104. { 0, 0 } // Stopper. Don't remove this.
  1105. };
  1106. DWORD
  1107. DWGetVMErrorMessageID(
  1108. VOID
  1109. )
  1110. /*++
  1111. Routine Description:
  1112. Get the VM Error message ID calculated from the current user's locale.
  1113. Arguments:
  1114. None
  1115. Return Value:
  1116. The VM Error message ID.
  1117. --*/
  1118. {
  1119. LANGID lgid;
  1120. WORD wPrim, wSub;
  1121. DWORD dwVMErrorMessageID;
  1122. PVMERRMSGIDTBL pTbl, pTbl2;
  1123. dwVMErrorMessageID = 0;
  1124. lgid = GetSystemDefaultLangID();
  1125. wPrim = PRIMARYLANGID(lgid);
  1126. for (pTbl = VMErrMsgIDTbl; pTbl->lgid && !dwVMErrorMessageID; pTbl++)
  1127. {
  1128. if (pTbl->lgid == wPrim)
  1129. {
  1130. if (pTbl->resid)
  1131. {
  1132. dwVMErrorMessageID = pTbl->resid;
  1133. break;
  1134. }
  1135. else
  1136. {
  1137. wSub = SUBLANGID(lgid);
  1138. for (pTbl2 = VMErrMsgIDTbl2; pTbl2->lgid; pTbl2++)
  1139. {
  1140. if (pTbl2->lgid == wSub)
  1141. {
  1142. dwVMErrorMessageID = pTbl2->resid;
  1143. break;
  1144. }
  1145. }
  1146. }
  1147. }
  1148. }
  1149. return dwVMErrorMessageID;
  1150. }
  1151. #endif // !defined(KERNEL_MODE) || defined(USERMODE_DRIVER)