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.

3801 lines
98 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. All rights reserved.
  4. Module Name:
  5. getsetop.c
  6. Abstract:
  7. PostScript helper functions for OEM plugins
  8. HGetOptions
  9. Author:
  10. Feng Yue (fengy)
  11. 8/24/2000 fengy Completed with support of both PPD and driver features.
  12. 8/1/2000 fengy Created it with function framework.
  13. --*/
  14. #include "lib.h"
  15. #include "ppd.h"
  16. #include "pslib.h"
  17. //
  18. // PS driver's helper functions for OEM plugins
  19. //
  20. //
  21. // synthesized PS driver features
  22. //
  23. const CHAR kstrPSFAddEuro[] = "%AddEuro";
  24. const CHAR kstrPSFCtrlDAfter[] = "%CtrlDAfter";
  25. const CHAR kstrPSFCtrlDBefore[] = "%CtrlDBefore";
  26. const CHAR kstrPSFCustomPS[] = "%CustomPageSize";
  27. const CHAR kstrPSFTrueGrayG[] = "%GraphicsTrueGray";
  28. const CHAR kstrPSFJobTimeout[] = "%JobTimeout";
  29. const CHAR kstrPSFMaxBitmap[] = "%MaxFontSizeAsBitmap";
  30. const CHAR kstrPSFEMF[] = "%MetafileSpooling";
  31. const CHAR kstrPSFMinOutline[] = "%MinFontSizeAsOutline";
  32. const CHAR kstrPSFMirroring[] = "%Mirroring";
  33. const CHAR kstrPSFNegative[] = "%Negative";
  34. const CHAR kstrPSFPageOrder[] = "%PageOrder";
  35. const CHAR kstrPSFNup[] = "%PagePerSheet";
  36. const CHAR kstrPSFErrHandler[] = "%PSErrorHandler";
  37. const CHAR kstrPSFPSMemory[] = "%PSMemory";
  38. const CHAR kstrPSFOrientation[] = "%Orientation";
  39. const CHAR kstrPSFOutFormat[] = "%OutputFormat";
  40. const CHAR kstrPSFOutProtocol[] = "%OutputProtocol";
  41. const CHAR kstrPSFOutPSLevel[] = "%OutputPSLevel";
  42. const CHAR kstrPSFTrueGrayT[] = "%TextTrueGray";
  43. const CHAR kstrPSFTTFormat[] = "%TTDownloadFormat";
  44. const CHAR kstrPSFWaitTimeout[] = "%WaitTimeout";
  45. //
  46. // commonly used keyword strings
  47. //
  48. const CHAR kstrKwdTrue[] = "True";
  49. const CHAR kstrKwdFalse[] = "False";
  50. #define MAX_WORD_VALUE 0x7fff
  51. #define MAX_DWORD_VALUE 0x7fffffff
  52. #define RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode) \
  53. if ((dwMode) == PSFPROC_ENUMOPTION_MODE) \
  54. { \
  55. SetLastError(ERROR_NOT_SUPPORTED); \
  56. return FALSE; \
  57. }
  58. /*++
  59. Routine Name:
  60. BOutputFeatureOption
  61. Routine Description:
  62. output one pair of feature keyword and option keyword names
  63. Arguments:
  64. pszFeature - feature keyword name
  65. pszOption - option keyword name
  66. pmszOutBuf - pointer to output data buffer
  67. cbRemain - remaining output data buffer size in bytes
  68. pcbNeeded - buffer size in bytes needed to output the keyword pair
  69. Return Value:
  70. TRUE if succeeds
  71. FALSE if output data buffer size is not big enough
  72. Last Error:
  73. ERROR_INSUFFICIENT_BUFFER if FALSE is returned
  74. --*/
  75. BOOL
  76. BOutputFeatureOption(
  77. IN PCSTR pszFeature,
  78. IN PCSTR pszOption,
  79. OUT PSTR pmszOutBuf,
  80. IN INT cbRemain,
  81. OUT PDWORD pcbNeeded
  82. )
  83. {
  84. DWORD cbFeatureSize, cbOptionSize;
  85. ASSERT(pszFeature && pszOption);
  86. cbFeatureSize = strlen(pszFeature) + 1;
  87. cbOptionSize = strlen(pszOption) + 1;
  88. if (pcbNeeded)
  89. {
  90. *pcbNeeded = cbFeatureSize + cbOptionSize;
  91. }
  92. if (!pmszOutBuf || cbRemain < (INT)(cbFeatureSize + cbOptionSize))
  93. {
  94. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  95. return FALSE;
  96. }
  97. CopyMemory(pmszOutBuf, pszFeature, cbFeatureSize);
  98. pmszOutBuf += cbFeatureSize;
  99. CopyMemory(pmszOutBuf, pszOption, cbOptionSize);
  100. return TRUE;
  101. }
  102. /*++
  103. Routine Name:
  104. BReadBooleanOption
  105. Routine Description:
  106. return boolean value specified by the option keyword name
  107. Arguments:
  108. pszOption - option keyword name
  109. pbValue - pointer to the variable to store returned boolean value
  110. Return Value:
  111. TRUE if the read operation succeeds
  112. FALSE otherwise
  113. Last Error:
  114. None
  115. --*/
  116. BOOL
  117. BReadBooleanOption(
  118. IN PCSTR pszOption,
  119. OUT PBOOL pbValue
  120. )
  121. {
  122. BOOL bReadOK = TRUE;
  123. ASSERT(pszOption && pbValue);
  124. if (strcmp(pszOption, kstrKwdTrue) == EQUAL_STRING)
  125. {
  126. *pbValue = TRUE;
  127. }
  128. else if (strcmp(pszOption, kstrKwdFalse) == EQUAL_STRING)
  129. {
  130. *pbValue = FALSE;
  131. }
  132. else
  133. {
  134. bReadOK = FALSE;
  135. }
  136. return bReadOK;
  137. }
  138. /*++
  139. Routine Name:
  140. BGetSetBoolFlag
  141. Routine Description:
  142. get or set a feature's boolean setting
  143. Arguments:
  144. pszFeature - feature keyword name
  145. pszOption - (set only) option keyword name
  146. pdwValue - pointer to DWORD data that stores the feature's setting
  147. dwFlagBit - flag bit value to indicate the feature's setting is TRUE
  148. bValid - TRUE if get/set on the feature's setting is supported. FALSE otherwise.
  149. pmszOutBuf - (get only) pointer to output data buffer
  150. cbRemain - (get only) remaining output data buffer size in bytes
  151. pcbNeeded - (get only) buffer size in bytes needed to output the boolean setting
  152. bSetMode - TRUE for set operation, FALSE for get operation
  153. Return Value:
  154. TRUE if the get or set operation succeeds
  155. FALSE otherwise
  156. Last Error:
  157. ERROR_INVALID_PARAMETER (set only) if FALSE is returned because set operation
  158. is not supported, or set operation found invalid argument
  159. ERROR_INSUFFICIENT_BUFFER (get only) see BOutputFeatureOption
  160. --*/
  161. BOOL
  162. BGetSetBoolFlag(
  163. IN PCSTR pszFeature,
  164. IN PCSTR pszOption,
  165. IN PDWORD pdwValue,
  166. IN DWORD dwFlagBit,
  167. IN BOOL bValid,
  168. OUT PSTR pmszOutBuf,
  169. IN INT cbRemain,
  170. OUT PDWORD pcbNeeded,
  171. IN BOOL bSetMode
  172. )
  173. {
  174. BOOL bFlagSet;
  175. ASSERT(pdwValue);
  176. #ifndef KERNEL_MODE
  177. //
  178. // set is only supported for UI plugins
  179. //
  180. if (bSetMode)
  181. {
  182. if (!bValid ||
  183. !BReadBooleanOption(pszOption, &bFlagSet))
  184. {
  185. SetLastError(ERROR_INVALID_PARAMETER);
  186. return FALSE;
  187. }
  188. if (bFlagSet)
  189. {
  190. *pdwValue |= dwFlagBit;
  191. }
  192. else
  193. {
  194. *pdwValue &= ~dwFlagBit;
  195. }
  196. return TRUE;
  197. }
  198. #else
  199. ASSERT(bSetMode == FALSE);
  200. #endif // !KERNEL_MODE
  201. //
  202. // get is supported for both UI and render plugins
  203. //
  204. {
  205. if (bValid && (*pdwValue & dwFlagBit))
  206. {
  207. bFlagSet = TRUE;
  208. }
  209. else
  210. {
  211. bFlagSet = FALSE;
  212. }
  213. return BOutputFeatureOption(pszFeature,
  214. bFlagSet ? kstrKwdTrue : kstrKwdFalse,
  215. pmszOutBuf,
  216. cbRemain,
  217. pcbNeeded);
  218. }
  219. }
  220. /*++
  221. Routine Name:
  222. BReadUnsignedInt
  223. Routine Description:
  224. return unsigned integer value specified in the input data buffer
  225. Arguments:
  226. pcstrArgument - pointer to the input data buffer, where UINT value(s) are
  227. represented as string of digit characters
  228. bSingleArgument - TRUE if only one UINT should be read from the input data
  229. FALSE if multiple UINTs can be read from the input data
  230. pdwValue - pointer to the variable to store returned unsigned integer value
  231. Return Value:
  232. NULL read failed due to invalid characters in the digit string
  233. non-NULL read succeeds. The new pointer position in the input data buffer
  234. after one UINT is read will be returned.
  235. Last Error:
  236. None
  237. --*/
  238. PCSTR
  239. PReadUnsignedInt(
  240. IN PCSTR pcstrArgument,
  241. IN BOOL bSingleArgument,
  242. OUT PDWORD pdwValue
  243. )
  244. {
  245. DWORD dwTemp = 0;
  246. ASSERT(pcstrArgument && pdwValue);
  247. //
  248. // skip any preceding white spaces
  249. //
  250. while (*pcstrArgument == ' ' || *pcstrArgument == '\t')
  251. {
  252. pcstrArgument++;
  253. }
  254. //
  255. // the first non-white space character must be a digit
  256. //
  257. if (!(*pcstrArgument >= '0' && *pcstrArgument <= '9'))
  258. {
  259. ERR(("first non-white space character is not a digit\n"));
  260. return NULL;
  261. }
  262. //
  263. // read in the digits
  264. //
  265. while (*pcstrArgument >= '0' && *pcstrArgument <= '9')
  266. {
  267. dwTemp = dwTemp * 10 + *pcstrArgument - '0';
  268. pcstrArgument++;
  269. }
  270. if (bSingleArgument)
  271. {
  272. //
  273. // any remaing characters must be white spaces
  274. //
  275. while (*pcstrArgument)
  276. {
  277. if (*pcstrArgument != ' ' && *pcstrArgument != '\t')
  278. {
  279. ERR(("character after digits is not white space\n"));
  280. return NULL;
  281. }
  282. pcstrArgument++;
  283. }
  284. }
  285. else
  286. {
  287. //
  288. // skip any remaining white spaces
  289. //
  290. while (*pcstrArgument == ' ' || *pcstrArgument == '\t')
  291. {
  292. pcstrArgument++;
  293. }
  294. }
  295. *pdwValue = dwTemp;
  296. return pcstrArgument;
  297. }
  298. /*++
  299. Routine Name:
  300. BGetSetUnsignedInt
  301. Routine Description:
  302. get or set a feature's unsigned integer setting
  303. Arguments:
  304. pszFeature - feature keyword name
  305. pszOption - (set only) option keyword name
  306. pdwValue - pointer to DWORD data that stores the feature's setting
  307. dwMaxVal - maximum valid UINT value for the feature's setting
  308. pmszOutBuf - (get only) pointer to output data buffer
  309. cbRemain - (get only) remaining output data buffer size in bytes
  310. pcbNeeded - (get only) buffer size in bytes needed to output the UINT setting
  311. bSetMode - TRUE for set operation, FALSE for get operation
  312. Return Value:
  313. TRUE if the get or set operation succeeds
  314. FALSE otherwise
  315. Last Error:
  316. ERROR_INVALID_PARAMETER (set only) if set operation failed because of
  317. invalid character(s) in the digit character string
  318. ERROR_INSUFFICIENT_BUFFER (get only) see BOutputFeatureOption
  319. --*/
  320. BOOL
  321. BGetSetUnsignedInt(
  322. IN PCSTR pszFeature,
  323. IN PCSTR pszOption,
  324. IN OUT PDWORD pdwValue,
  325. IN DWORD dwMaxVal,
  326. OUT PSTR pmszOutBuf,
  327. IN INT cbRemain,
  328. OUT PDWORD pcbNeeded,
  329. IN BOOL bSetMode
  330. )
  331. {
  332. ASSERT(pdwValue);
  333. #ifndef KERNEL_MODE
  334. //
  335. // set is only supported for UI plugins
  336. //
  337. if (bSetMode)
  338. {
  339. DWORD dwTemp;
  340. if (!PReadUnsignedInt(pszOption, TRUE, &dwTemp) ||
  341. dwTemp > dwMaxVal)
  342. {
  343. SetLastError(ERROR_INVALID_PARAMETER);
  344. return FALSE;
  345. }
  346. *pdwValue = dwTemp;
  347. return TRUE;
  348. }
  349. #else
  350. ASSERT(bSetMode == FALSE);
  351. #endif // !KERNEL_MODE
  352. //
  353. // get is supported for both UI and render plugins
  354. //
  355. {
  356. CHAR pszValue[16];
  357. _ultoa(*pdwValue, pszValue, 10);
  358. return BOutputFeatureOption(pszFeature,
  359. pszValue,
  360. pmszOutBuf,
  361. cbRemain,
  362. pcbNeeded);
  363. }
  364. }
  365. /*++
  366. Routine Name:
  367. BPSFProc_AddEuro
  368. Routine Description:
  369. %-feature enum/get/set operation handler
  370. Arguments:
  371. hPrinter - printer handle
  372. pUIInfo - pointer to driver's UIINFO structure
  373. pPpdData - pointer to driver's PPDDATA structure
  374. pdm - pointer to public DEVMODE
  375. pPrinterData - pointer to driver's PRINTERDATA structure
  376. pszFeature - feature keyword name
  377. pszOption - (set only) option keyword name
  378. pmszOutBuf - (get only) pointer to output data buffer
  379. cbRemain - (get only) remaining output data buffer size in bytes
  380. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  381. dwMode - indicate one of three operations: enum, get, set
  382. Return Value:
  383. TRUE if the requested operation succeeds
  384. FALSE otherwise
  385. Last Error:
  386. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  387. ERROR_INVALID_PARAMETER
  388. ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
  389. --*/
  390. BOOL
  391. BPSFProc_AddEuro(
  392. IN HANDLE hPrinter,
  393. IN PUIINFO pUIInfo,
  394. IN PPPDDATA pPpdData,
  395. IN PDEVMODE pdm,
  396. IN PPRINTERDATA pPrinterData,
  397. IN PCSTR pszFeature,
  398. IN PCSTR pszOption,
  399. OUT PSTR pmszOutBuf,
  400. IN INT cbRemain,
  401. OUT PDWORD pcbNeeded,
  402. IN DWORD dwMode
  403. )
  404. {
  405. BOOL bValid, bResult;
  406. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  407. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  408. //
  409. // refer to _VUnpackDriverPrnPropItem and _BPackPrinterOptions in ps.c
  410. //
  411. bValid = pUIInfo->dwLangLevel >= 2;
  412. bResult = BGetSetBoolFlag(pszFeature,
  413. pszOption,
  414. &(pPrinterData->dwFlags),
  415. PFLAGS_ADD_EURO,
  416. bValid,
  417. pmszOutBuf,
  418. cbRemain,
  419. pcbNeeded,
  420. bSetMode);
  421. #ifndef KERNEL_MODE
  422. //
  423. // set is only supported for UI plugins
  424. //
  425. if (bSetMode && bResult)
  426. {
  427. pPrinterData->dwFlags |= PFLAGS_EURO_SET;
  428. }
  429. #endif // !KERNEL_MODE
  430. return bResult;
  431. }
  432. /*++
  433. Routine Name:
  434. BPSFProc_CtrlDA
  435. Routine Description:
  436. %-feature enum/get/set operation handler
  437. Arguments:
  438. hPrinter - printer handle
  439. pUIInfo - pointer to driver's UIINFO structure
  440. pPpdData - pointer to driver's PPDDATA structure
  441. pdm - pointer to public DEVMODE
  442. pPrinterData - pointer to driver's PRINTERDATA structure
  443. pszFeature - feature keyword name
  444. pszOption - (set only) option keyword name
  445. pmszOutBuf - (get only) pointer to output data buffer
  446. cbRemain - (get only) remaining output data buffer size in bytes
  447. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  448. dwMode - indicate one of three operations: enum, get, set
  449. Return Value:
  450. TRUE if the requested operation succeeds
  451. FALSE otherwise
  452. Last Error:
  453. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  454. ERROR_INVALID_PARAMETER
  455. ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
  456. --*/
  457. BOOL
  458. BPSFProc_CtrlDA(
  459. IN HANDLE hPrinter,
  460. IN PUIINFO pUIInfo,
  461. IN PPPDDATA pPpdData,
  462. IN PDEVMODE pdm,
  463. IN PPRINTERDATA pPrinterData,
  464. IN PCSTR pszFeature,
  465. IN PCSTR pszOption,
  466. OUT PSTR pmszOutBuf,
  467. IN INT cbRemain,
  468. OUT PDWORD pcbNeeded,
  469. IN DWORD dwMode
  470. )
  471. {
  472. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  473. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  474. //
  475. // refer to _VUnpackDriverPrnPropItem and _BPackPrinterOptions in ps.c
  476. //
  477. return BGetSetBoolFlag(pszFeature,
  478. pszOption,
  479. &(pPrinterData->dwFlags),
  480. PFLAGS_CTRLD_AFTER,
  481. TRUE,
  482. pmszOutBuf,
  483. cbRemain,
  484. pcbNeeded,
  485. bSetMode);
  486. }
  487. /*++
  488. Routine Name:
  489. BPSFProc_CtrlDB
  490. Routine Description:
  491. %-feature enum/get/set operation handler
  492. Arguments:
  493. hPrinter - printer handle
  494. pUIInfo - pointer to driver's UIINFO structure
  495. pPpdData - pointer to driver's PPDDATA structure
  496. pdm - pointer to public DEVMODE
  497. pPrinterData - pointer to driver's PRINTERDATA structure
  498. pszFeature - feature keyword name
  499. pszOption - (set only) option keyword name
  500. pmszOutBuf - (get only) pointer to output data buffer
  501. cbRemain - (get only) remaining output data buffer size in bytes
  502. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  503. dwMode - indicate one of three operations: enum, get, set
  504. Return Value:
  505. TRUE if the requested operation succeeds
  506. FALSE otherwise
  507. Last Error:
  508. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  509. ERROR_INVALID_PARAMETER
  510. ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
  511. --*/
  512. BOOL
  513. BPSFProc_CtrlDB(
  514. IN HANDLE hPrinter,
  515. IN PUIINFO pUIInfo,
  516. IN PPPDDATA pPpdData,
  517. IN PDEVMODE pdm,
  518. IN PPRINTERDATA pPrinterData,
  519. IN PCSTR pszFeature,
  520. IN PCSTR pszOption,
  521. OUT PSTR pmszOutBuf,
  522. IN INT cbRemain,
  523. OUT PDWORD pcbNeeded,
  524. IN DWORD dwMode
  525. )
  526. {
  527. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  528. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  529. //
  530. // refer to _VUnpackDriverPrnPropItem and _BPackPrinterOptions in ps.c
  531. //
  532. return BGetSetBoolFlag(pszFeature,
  533. pszOption,
  534. &(pPrinterData->dwFlags),
  535. PFLAGS_CTRLD_BEFORE,
  536. TRUE,
  537. pmszOutBuf,
  538. cbRemain,
  539. pcbNeeded,
  540. bSetMode);
  541. }
  542. /*++
  543. Routine Name:
  544. BPSFProc_CustomPS
  545. Routine Description:
  546. %-feature enum/get/set operation handler
  547. Arguments:
  548. hPrinter - printer handle
  549. pUIInfo - pointer to driver's UIINFO structure
  550. pPpdData - pointer to driver's PPDDATA structure
  551. pdm - pointer to public DEVMODE
  552. pPrinterData - pointer to driver's PRINTERDATA structure
  553. pszFeature - feature keyword name
  554. pszOption - (set only) option keyword name
  555. pmszOutBuf - (get only) pointer to output data buffer
  556. cbRemain - (get only) remaining output data buffer size in bytes
  557. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  558. dwMode - indicate one of three operations: enum, get, set
  559. Return Value:
  560. TRUE if the requested operation succeeds
  561. FALSE otherwise
  562. Last Error:
  563. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  564. ERROR_INVALID_PARAMETER if get/set of the feature setting is not supported,
  565. or set operation found invalid arguments
  566. ERROR_INSUFFICIENT_BUFFER (get only) if output data buffer size is not big enough
  567. --*/
  568. BOOL
  569. BPSFProc_CustomPS(
  570. IN HANDLE hPrinter,
  571. IN PUIINFO pUIInfo,
  572. IN PPPDDATA pPpdData,
  573. IN PDEVMODE pdm,
  574. IN PPRINTERDATA pPrinterData,
  575. IN PCSTR pszFeature,
  576. IN PCSTR pszOption,
  577. OUT PSTR pmszOutBuf,
  578. IN INT cbRemain,
  579. OUT PDWORD pcbNeeded,
  580. IN DWORD dwMode
  581. )
  582. {
  583. typedef struct _PSF_CUSTOMFEED_ENTRY {
  584. PCSTR pszFeedName; // feed direction name
  585. DWORD dwFeedDirection; // feed direction code
  586. } PSF_CUSTOMFEED_ENTRY, *PPSF_CUSTOMFEED_ENTRY;
  587. static const PSF_CUSTOMFEED_ENTRY kPSF_CustomFeedTable[] =
  588. {
  589. {"LongEdge", LONGEDGEFIRST},
  590. {"ShortEdge", SHORTEDGEFIRST},
  591. {"LongEdgeFlip", LONGEDGEFIRST_FLIPPED},
  592. {"ShortEdgeFlip", SHORTEDGEFIRST_FLIPPED},
  593. {NULL, 0},
  594. };
  595. PPSF_CUSTOMFEED_ENTRY pEntry, pMatchEntry;
  596. PPSDRVEXTRA pdmPrivate;
  597. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  598. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  599. ASSERT(pdm);
  600. pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
  601. //
  602. // This feature is supported when the printer supports custom
  603. // page size AND current custom page size is currently selected
  604. //
  605. // For reason of following check, refer to BPackItemFormName in
  606. // docprop.c and BDisplayPSCustomPageSizeDialog in custsize.c.
  607. //
  608. if (!SUPPORT_CUSTOMSIZE(pUIInfo) ||
  609. !SUPPORT_FULL_CUSTOMSIZE_FEATURES(pUIInfo, pPpdData) ||
  610. pdm->dmPaperSize != DMPAPER_CUSTOMSIZE)
  611. {
  612. ERR(("custom size not supported/selected: dmPaperSize=%d, mode=%d\n", pdm->dmPaperSize, bSetMode));
  613. SetLastError(ERROR_INVALID_PARAMETER);
  614. return FALSE;
  615. }
  616. pMatchEntry = NULL;
  617. pEntry = (PPSF_CUSTOMFEED_ENTRY)&(kPSF_CustomFeedTable[0]);
  618. #ifndef KERNEL_MODE
  619. //
  620. // set is only supported for UI plugins
  621. //
  622. if (bSetMode)
  623. {
  624. PCSTR pcstrArgument = pszOption;
  625. CUSTOMSIZEDATA csdata;
  626. BOOL bResult;
  627. if ((pcstrArgument = PReadUnsignedInt(pcstrArgument,
  628. FALSE,
  629. &(csdata.dwX))) &&
  630. (pcstrArgument = PReadUnsignedInt(pcstrArgument,
  631. FALSE,
  632. &(csdata.dwY))) &&
  633. (pcstrArgument = PReadUnsignedInt(pcstrArgument,
  634. FALSE,
  635. &(csdata.dwWidthOffset))) &&
  636. (pcstrArgument = PReadUnsignedInt(pcstrArgument,
  637. FALSE,
  638. &(csdata.dwHeightOffset))))
  639. {
  640. while (pEntry->pszFeedName)
  641. {
  642. if ((*pcstrArgument == *(pEntry->pszFeedName)) &&
  643. (strcmp(pcstrArgument, pEntry->pszFeedName) == EQUAL_STRING))
  644. {
  645. pMatchEntry = pEntry;
  646. break;
  647. }
  648. pEntry++;
  649. }
  650. if (!pMatchEntry)
  651. {
  652. //
  653. // unrecognized feed direction name
  654. //
  655. SetLastError(ERROR_INVALID_PARAMETER);
  656. return FALSE;
  657. }
  658. //
  659. // All arguments are recognized. Save into private devmode and do validation.
  660. //
  661. pdmPrivate->csdata.wFeedDirection = (WORD)pMatchEntry->dwFeedDirection;
  662. pdmPrivate->csdata.dwX = POINT_TO_MICRON(csdata.dwX);
  663. pdmPrivate->csdata.dwY = POINT_TO_MICRON(csdata.dwY);
  664. pdmPrivate->csdata.dwWidthOffset = POINT_TO_MICRON(csdata.dwWidthOffset);
  665. pdmPrivate->csdata.dwHeightOffset = POINT_TO_MICRON(csdata.dwHeightOffset);
  666. }
  667. else
  668. {
  669. SetLastError(ERROR_INVALID_PARAMETER);
  670. return FALSE;
  671. }
  672. bResult = BValidateCustomPageSizeData((PRAWBINARYDATA)(pUIInfo->pInfoHeader),
  673. &(pdmPrivate->csdata));
  674. if (!bResult)
  675. {
  676. VERBOSE(("Set: custom page size input arguments are adjusted\n"));
  677. }
  678. return TRUE;
  679. }
  680. #else
  681. ASSERT(bSetMode == FALSE);
  682. #endif // !KERNEL_MODE
  683. //
  684. // get is supported for both UI and render plugins
  685. //
  686. {
  687. DWORD cbFeatureSize, cbNeeded, cbFeedNameSize;
  688. INT iIndex;
  689. ASSERT(pszFeature);
  690. cbNeeded = 0;
  691. //
  692. // frist output the feature keyword
  693. //
  694. cbFeatureSize = strlen(pszFeature) + 1;
  695. if (pmszOutBuf && (cbRemain >= (INT)cbFeatureSize))
  696. {
  697. CopyMemory(pmszOutBuf, pszFeature, cbFeatureSize);
  698. pmszOutBuf += cbFeatureSize;
  699. }
  700. cbRemain -= cbFeatureSize;
  701. cbNeeded += cbFeatureSize;
  702. //
  703. // then output the 4 custom page size parameters
  704. //
  705. for (iIndex = 0; iIndex < 4; iIndex++)
  706. {
  707. DWORD dwValue, cbValueSize;
  708. CHAR pszValue[16];
  709. switch (iIndex)
  710. {
  711. case 0:
  712. {
  713. dwValue = pdmPrivate->csdata.dwX;
  714. break;
  715. }
  716. case 1:
  717. {
  718. dwValue = pdmPrivate->csdata.dwY;
  719. break;
  720. }
  721. case 2:
  722. {
  723. dwValue = pdmPrivate->csdata.dwWidthOffset;
  724. break;
  725. }
  726. case 3:
  727. {
  728. dwValue = pdmPrivate->csdata.dwWidthOffset;
  729. break;
  730. }
  731. default:
  732. {
  733. RIP(("hit bad iIndex %d\n", iIndex));
  734. break;
  735. }
  736. }
  737. dwValue = MICRON_TO_POINT(dwValue);
  738. _ultoa(dwValue, pszValue, 10);
  739. cbValueSize = strlen(pszValue) + 1;
  740. if (pmszOutBuf && (cbRemain >= (INT)cbValueSize))
  741. {
  742. //
  743. // output the decimal value string
  744. //
  745. CopyMemory(pmszOutBuf, pszValue, cbValueSize);
  746. //
  747. // replace NUL with space as the separator between decimal value strings
  748. //
  749. pmszOutBuf += cbValueSize - 1;
  750. *pmszOutBuf = ' ';
  751. pmszOutBuf++;
  752. }
  753. cbRemain -= cbValueSize;
  754. cbNeeded += cbValueSize;
  755. }
  756. //
  757. // lastly output the feed direction name
  758. //
  759. while (pEntry->pszFeedName)
  760. {
  761. if (pdmPrivate->csdata.wFeedDirection == pEntry->dwFeedDirection)
  762. {
  763. pMatchEntry = pEntry;
  764. break;
  765. }
  766. pEntry++;
  767. }
  768. if (!pMatchEntry)
  769. {
  770. RIP(("unknown wFeedDirection %d\n", pdmPrivate->csdata.wFeedDirection));
  771. pMatchEntry = (PPSF_CUSTOMFEED_ENTRY)&(kPSF_CustomFeedTable[0]);
  772. }
  773. cbFeedNameSize = strlen(pMatchEntry->pszFeedName) + 1;
  774. if (pmszOutBuf && (cbRemain >= (INT)cbFeedNameSize))
  775. {
  776. CopyMemory(pmszOutBuf, pMatchEntry->pszFeedName, cbFeedNameSize);
  777. pmszOutBuf += cbFeedNameSize;
  778. }
  779. cbRemain -= cbFeedNameSize;
  780. cbNeeded += cbFeedNameSize;
  781. if (pcbNeeded)
  782. {
  783. *pcbNeeded = cbNeeded;
  784. }
  785. //
  786. // check if output buffer is big enough for all of the 5 parameters
  787. //
  788. if (!pmszOutBuf || cbRemain < 0)
  789. {
  790. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  791. return FALSE;
  792. }
  793. return TRUE;
  794. }
  795. }
  796. /*++
  797. Routine Name:
  798. BPSFProc_TrueGrayG
  799. Routine Description:
  800. %-feature enum/get/set operation handler
  801. Arguments:
  802. hPrinter - printer handle
  803. pUIInfo - pointer to driver's UIINFO structure
  804. pPpdData - pointer to driver's PPDDATA structure
  805. pdm - pointer to public DEVMODE
  806. pPrinterData - pointer to driver's PRINTERDATA structure
  807. pszFeature - feature keyword name
  808. pszOption - (set only) option keyword name
  809. pmszOutBuf - (get only) pointer to output data buffer
  810. cbRemain - (get only) remaining output data buffer size in bytes
  811. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  812. dwMode - indicate one of three operations: enum, get, set
  813. Return Value:
  814. TRUE if the requested operation succeeds
  815. FALSE otherwise
  816. Last Error:
  817. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  818. ERROR_INVALID_PARAMETER
  819. ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
  820. --*/
  821. BOOL
  822. BPSFProc_TrueGrayG(
  823. IN HANDLE hPrinter,
  824. IN PUIINFO pUIInfo,
  825. IN PPPDDATA pPpdData,
  826. IN PDEVMODE pdm,
  827. IN PPRINTERDATA pPrinterData,
  828. IN PCSTR pszFeature,
  829. IN PCSTR pszOption,
  830. OUT PSTR pmszOutBuf,
  831. IN INT cbRemain,
  832. OUT PDWORD pcbNeeded,
  833. IN DWORD dwMode
  834. )
  835. {
  836. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  837. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  838. //
  839. // refer to _VUnpackDriverPrnPropItem and _BPackPrinterOptions in ps.c
  840. //
  841. return BGetSetBoolFlag(pszFeature,
  842. pszOption,
  843. &(pPrinterData->dwFlags),
  844. PFLAGS_TRUE_GRAY_GRAPH,
  845. TRUE,
  846. pmszOutBuf,
  847. cbRemain,
  848. pcbNeeded,
  849. bSetMode);
  850. }
  851. /*++
  852. Routine Name:
  853. BPSFProc_JobTimeout
  854. Routine Description:
  855. %-feature enum/get/set operation handler
  856. Arguments:
  857. hPrinter - printer handle
  858. pUIInfo - pointer to driver's UIINFO structure
  859. pPpdData - pointer to driver's PPDDATA structure
  860. pdm - pointer to public DEVMODE
  861. pPrinterData - pointer to driver's PRINTERDATA structure
  862. pszFeature - feature keyword name
  863. pszOption - (set only) option keyword name
  864. pmszOutBuf - (get only) pointer to output data buffer
  865. cbRemain - (get only) remaining output data buffer size in bytes
  866. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  867. dwMode - indicate one of three operations: enum, get, set
  868. Return Value:
  869. TRUE if the requested operation succeeds
  870. FALSE otherwise
  871. Last Error:
  872. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  873. ERROR_INVALID_PARAMETER
  874. ERROR_INSUFFICIENT_BUFFER see BGetSetUnsignedInt
  875. --*/
  876. BOOL
  877. BPSFProc_JobTimeout(
  878. IN HANDLE hPrinter,
  879. IN PUIINFO pUIInfo,
  880. IN PPPDDATA pPpdData,
  881. IN PDEVMODE pdm,
  882. IN PPRINTERDATA pPrinterData,
  883. IN PCSTR pszFeature,
  884. IN PCSTR pszOption,
  885. OUT PSTR pmszOutBuf,
  886. IN INT cbRemain,
  887. OUT PDWORD pcbNeeded,
  888. IN DWORD dwMode
  889. )
  890. {
  891. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  892. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  893. //
  894. // refer to VUnpackPrinterPropertiesItems in prnprop.c
  895. // and _BPackPrinterOptions in ps.c
  896. //
  897. return BGetSetUnsignedInt(pszFeature,
  898. pszOption,
  899. &(pPrinterData->dwJobTimeout),
  900. MAX_DWORD_VALUE,
  901. pmszOutBuf,
  902. cbRemain,
  903. pcbNeeded,
  904. bSetMode);
  905. }
  906. /*++
  907. Routine Name:
  908. BPSFProc_MaxBitmap
  909. Routine Description:
  910. %-feature enum/get/set operation handler
  911. Arguments:
  912. hPrinter - printer handle
  913. pUIInfo - pointer to driver's UIINFO structure
  914. pPpdData - pointer to driver's PPDDATA structure
  915. pdm - pointer to public DEVMODE
  916. pPrinterData - pointer to driver's PRINTERDATA structure
  917. pszFeature - feature keyword name
  918. pszOption - (set only) option keyword name
  919. pmszOutBuf - (get only) pointer to output data buffer
  920. cbRemain - (get only) remaining output data buffer size in bytes
  921. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  922. dwMode - indicate one of three operations: enum, get, set
  923. Return Value:
  924. TRUE if the requested operation succeeds
  925. FALSE otherwise
  926. Last Error:
  927. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  928. ERROR_INVALID_PARAMETER
  929. ERROR_INSUFFICIENT_BUFFER see BGetSetUnsignedInt
  930. --*/
  931. BOOL
  932. BPSFProc_MaxBitmap(
  933. IN HANDLE hPrinter,
  934. IN PUIINFO pUIInfo,
  935. IN PPPDDATA pPpdData,
  936. IN PDEVMODE pdm,
  937. IN PPRINTERDATA pPrinterData,
  938. IN PCSTR pszFeature,
  939. IN PCSTR pszOption,
  940. OUT PSTR pmszOutBuf,
  941. IN INT cbRemain,
  942. OUT PDWORD pcbNeeded,
  943. IN DWORD dwMode
  944. )
  945. {
  946. DWORD dwValue;
  947. BOOL bResult;
  948. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  949. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  950. //
  951. // refer to _VUnpackDriverPrnPropItem and _BPackPrinterOptions in ps.c
  952. //
  953. dwValue = pPrinterData->wMaxbitmapPPEM;
  954. bResult = BGetSetUnsignedInt(pszFeature,
  955. pszOption,
  956. &dwValue,
  957. MAX_WORD_VALUE,
  958. pmszOutBuf,
  959. cbRemain,
  960. pcbNeeded,
  961. bSetMode);
  962. #ifndef KERNEL_MODE
  963. //
  964. // set is only supported for UI plugins
  965. //
  966. if (bSetMode && bResult)
  967. {
  968. pPrinterData->wMaxbitmapPPEM = (WORD)dwValue;
  969. }
  970. #endif // !KERNEL_MODE
  971. return bResult;
  972. }
  973. /*++
  974. Routine Name:
  975. BPSFProc_EMF
  976. Routine Description:
  977. %-feature enum/get/set operation handler
  978. Arguments:
  979. hPrinter - printer handle
  980. pUIInfo - pointer to driver's UIINFO structure
  981. pPpdData - pointer to driver's PPDDATA structure
  982. pdm - pointer to public DEVMODE
  983. pPrinterData - pointer to driver's PRINTERDATA structure
  984. pszFeature - feature keyword name
  985. pszOption - (set only) option keyword name
  986. pmszOutBuf - (get only) pointer to output data buffer
  987. cbRemain - (get only) remaining output data buffer size in bytes
  988. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  989. dwMode - indicate one of three operations: enum, get, set
  990. Return Value:
  991. TRUE if the requested operation succeeds
  992. FALSE otherwise
  993. Last Error:
  994. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  995. ERROR_INVALID_PARAMETER if get/set of the feature setting is not supported,
  996. or set operation found invalid arguments
  997. ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
  998. --*/
  999. BOOL
  1000. BPSFProc_EMF(
  1001. IN HANDLE hPrinter,
  1002. IN PUIINFO pUIInfo,
  1003. IN PPPDDATA pPpdData,
  1004. IN PDEVMODE pdm,
  1005. IN PPRINTERDATA pPrinterData,
  1006. IN PCSTR pszFeature,
  1007. IN PCSTR pszOption,
  1008. OUT PSTR pmszOutBuf,
  1009. IN INT cbRemain,
  1010. OUT PDWORD pcbNeeded,
  1011. IN DWORD dwMode
  1012. )
  1013. {
  1014. PPSDRVEXTRA pdmPrivate;
  1015. BOOL bResult;
  1016. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  1017. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  1018. ASSERT(pdm);
  1019. pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
  1020. //
  1021. // refer to BPackItemEmfFeatures and VUnpackDocumentPropertiesItems
  1022. //
  1023. // We assume spooler EMF is enabled if reverse printing is supported.
  1024. // (refer to PFillUiData for how it sets pUiData->bEMFSpooling)
  1025. //
  1026. //
  1027. // On Win2K+, this feature is not supported if spooler EMF is disabled.
  1028. // On NT4, spooler doesn't support the EMF capability query, so we
  1029. // always support our driver's EMF on/off feature.
  1030. //
  1031. #ifndef WINNT_40
  1032. {
  1033. BOOL bEMFSpooling;
  1034. VGetSpoolerEmfCaps(hPrinter, NULL, &bEMFSpooling, 0, NULL);
  1035. if (!bEMFSpooling)
  1036. {
  1037. ERR(("%s not supported when spooler EMF is disabled, mode=%d", pszFeature, bSetMode));
  1038. SetLastError(ERROR_INVALID_PARAMETER);
  1039. return FALSE;
  1040. }
  1041. }
  1042. #endif // !WINNT_40
  1043. return BGetSetBoolFlag(pszFeature,
  1044. pszOption,
  1045. &(pdmPrivate->dwFlags),
  1046. PSDEVMODE_METAFILE_SPOOL,
  1047. TRUE,
  1048. pmszOutBuf,
  1049. cbRemain,
  1050. pcbNeeded,
  1051. bSetMode);
  1052. }
  1053. /*++
  1054. Routine Name:
  1055. BPSFProc_MinOutline
  1056. Routine Description:
  1057. %-feature enum/get/set operation handler
  1058. Arguments:
  1059. hPrinter - printer handle
  1060. pUIInfo - pointer to driver's UIINFO structure
  1061. pPpdData - pointer to driver's PPDDATA structure
  1062. pdm - pointer to public DEVMODE
  1063. pPrinterData - pointer to driver's PRINTERDATA structure
  1064. pszFeature - feature keyword name
  1065. pszOption - (set only) option keyword name
  1066. pmszOutBuf - (get only) pointer to output data buffer
  1067. cbRemain - (get only) remaining output data buffer size in bytes
  1068. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  1069. dwMode - indicate one of three operations: enum, get, set
  1070. Return Value:
  1071. TRUE if the requested operation succeeds
  1072. FALSE otherwise
  1073. Last Error:
  1074. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  1075. ERROR_INVALID_PARAMETER
  1076. ERROR_INSUFFICIENT_BUFFER see BGetSetUnsignedInt
  1077. --*/
  1078. BOOL
  1079. BPSFProc_MinOutline(
  1080. IN HANDLE hPrinter,
  1081. IN PUIINFO pUIInfo,
  1082. IN PPPDDATA pPpdData,
  1083. IN PDEVMODE pdm,
  1084. IN PPRINTERDATA pPrinterData,
  1085. IN PCSTR pszFeature,
  1086. IN PCSTR pszOption,
  1087. OUT PSTR pmszOutBuf,
  1088. IN INT cbRemain,
  1089. OUT PDWORD pcbNeeded,
  1090. IN DWORD dwMode
  1091. )
  1092. {
  1093. DWORD dwValue;
  1094. BOOL bResult;
  1095. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  1096. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  1097. //
  1098. // refer to _VUnpackDriverPrnPropItem and _BPackPrinterOptions in ps.c
  1099. //
  1100. dwValue = pPrinterData->wMinoutlinePPEM;
  1101. bResult = BGetSetUnsignedInt(pszFeature,
  1102. pszOption,
  1103. &dwValue,
  1104. MAX_WORD_VALUE,
  1105. pmszOutBuf,
  1106. cbRemain,
  1107. pcbNeeded,
  1108. bSetMode);
  1109. #ifndef KERNEL_MODE
  1110. //
  1111. // set is only supported for UI plugins
  1112. //
  1113. if (bSetMode && bResult)
  1114. {
  1115. pPrinterData->wMinoutlinePPEM = (WORD)dwValue;
  1116. }
  1117. #endif // !KERNEL_MODE
  1118. return bResult;
  1119. }
  1120. /*++
  1121. Routine Name:
  1122. BPSFProc_Mirroring
  1123. Routine Description:
  1124. %-feature enum/get/set operation handler
  1125. Arguments:
  1126. hPrinter - printer handle
  1127. pUIInfo - pointer to driver's UIINFO structure
  1128. pPpdData - pointer to driver's PPDDATA structure
  1129. pdm - pointer to public DEVMODE
  1130. pPrinterData - pointer to driver's PRINTERDATA structure
  1131. pszFeature - feature keyword name
  1132. pszOption - (set only) option keyword name
  1133. pmszOutBuf - (get only) pointer to output data buffer
  1134. cbRemain - (get only) remaining output data buffer size in bytes
  1135. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  1136. dwMode - indicate one of three operations: enum, get, set
  1137. Return Value:
  1138. TRUE if the requested operation succeeds
  1139. FALSE otherwise
  1140. Last Error:
  1141. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  1142. ERROR_INVALID_PARAMETER
  1143. ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
  1144. --*/
  1145. BOOL
  1146. BPSFProc_Mirroring(
  1147. IN HANDLE hPrinter,
  1148. IN PUIINFO pUIInfo,
  1149. IN PPPDDATA pPpdData,
  1150. IN PDEVMODE pdm,
  1151. IN PPRINTERDATA pPrinterData,
  1152. IN PCSTR pszFeature,
  1153. IN PCSTR pszOption,
  1154. OUT PSTR pmszOutBuf,
  1155. IN INT cbRemain,
  1156. OUT PDWORD pcbNeeded,
  1157. IN DWORD dwMode
  1158. )
  1159. {
  1160. PPSDRVEXTRA pdmPrivate;
  1161. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  1162. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  1163. ASSERT(pdm);
  1164. pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
  1165. //
  1166. // refer to _BPackDocumentOptions and _VUnpackDocumentOptions in ps.c
  1167. //
  1168. return BGetSetBoolFlag(pszFeature,
  1169. pszOption,
  1170. &(pdmPrivate->dwFlags),
  1171. PSDEVMODE_MIRROR,
  1172. TRUE,
  1173. pmszOutBuf,
  1174. cbRemain,
  1175. pcbNeeded,
  1176. bSetMode);
  1177. }
  1178. /*++
  1179. Routine Name:
  1180. BPSFProc_Negative
  1181. Routine Description:
  1182. %-feature enum/get/set operation handler
  1183. Arguments:
  1184. hPrinter - printer handle
  1185. pUIInfo - pointer to driver's UIINFO structure
  1186. pPpdData - pointer to driver's PPDDATA structure
  1187. pdm - pointer to public DEVMODE
  1188. pPrinterData - pointer to driver's PRINTERDATA structure
  1189. pszFeature - feature keyword name
  1190. pszOption - (set only) option keyword name
  1191. pmszOutBuf - (get only) pointer to output data buffer
  1192. cbRemain - (get only) remaining output data buffer size in bytes
  1193. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  1194. dwMode - indicate one of three operations: enum, get, set
  1195. Return Value:
  1196. TRUE if the requested operation succeeds
  1197. FALSE otherwise
  1198. Last Error:
  1199. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  1200. ERROR_INVALID_PARAMETER
  1201. ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
  1202. --*/
  1203. BOOL
  1204. BPSFProc_Negative(
  1205. IN HANDLE hPrinter,
  1206. IN PUIINFO pUIInfo,
  1207. IN PPPDDATA pPpdData,
  1208. IN PDEVMODE pdm,
  1209. IN PPRINTERDATA pPrinterData,
  1210. IN PCSTR pszFeature,
  1211. IN PCSTR pszOption,
  1212. OUT PSTR pmszOutBuf,
  1213. IN INT cbRemain,
  1214. OUT PDWORD pcbNeeded,
  1215. IN DWORD dwMode
  1216. )
  1217. {
  1218. PPSDRVEXTRA pdmPrivate;
  1219. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  1220. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  1221. ASSERT(pdm);
  1222. pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
  1223. //
  1224. // refer to _BPackDocumentOptions and _VUnpackDocumentOptions in ps.c
  1225. //
  1226. return BGetSetBoolFlag(pszFeature,
  1227. pszOption,
  1228. &(pdmPrivate->dwFlags),
  1229. PSDEVMODE_NEG,
  1230. !IS_COLOR_DEVICE(pUIInfo),
  1231. pmszOutBuf,
  1232. cbRemain,
  1233. pcbNeeded,
  1234. bSetMode);
  1235. }
  1236. /*++
  1237. Routine Name:
  1238. BPSFProc_PageOrder
  1239. Routine Description:
  1240. %-feature enum/get/set operation handler
  1241. Arguments:
  1242. hPrinter - printer handle
  1243. pUIInfo - pointer to driver's UIINFO structure
  1244. pPpdData - pointer to driver's PPDDATA structure
  1245. pdm - pointer to public DEVMODE
  1246. pPrinterData - pointer to driver's PRINTERDATA structure
  1247. pszFeature - feature keyword name
  1248. pszOption - (set only) option keyword name
  1249. pmszOutBuf - (get only) pointer to output data buffer
  1250. cbRemain - (get only) remaining output data buffer size in bytes
  1251. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  1252. dwMode - indicate one of three operations: enum, get, set
  1253. Return Value:
  1254. TRUE if the requested operation succeeds
  1255. FALSE otherwise
  1256. Last Error:
  1257. ERROR_INVALID_PARAMETER if get/set of the feature setting is not supported,
  1258. or set operation found invalid argument
  1259. ERROR_INSUFFICIENT_BUFFER if output data buffer size is not big enough for
  1260. enum or get operation
  1261. --*/
  1262. BOOL
  1263. BPSFProc_PageOrder(
  1264. IN HANDLE hPrinter,
  1265. IN PUIINFO pUIInfo,
  1266. IN PPPDDATA pPpdData,
  1267. IN PDEVMODE pdm,
  1268. IN PPRINTERDATA pPrinterData,
  1269. IN PCSTR pszFeature,
  1270. IN PCSTR pszOption,
  1271. OUT PSTR pmszOutBuf,
  1272. IN INT cbRemain,
  1273. OUT PDWORD pcbNeeded,
  1274. IN DWORD dwMode
  1275. )
  1276. {
  1277. static const CHAR pstrPageOrder[][16] =
  1278. {
  1279. "FrontToBack",
  1280. "BackToFront",
  1281. };
  1282. PPSDRVEXTRA pdmPrivate;
  1283. INT iIndex;
  1284. BOOL bReversePrint;
  1285. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  1286. //
  1287. // option enumeration handling
  1288. //
  1289. if (dwMode == PSFPROC_ENUMOPTION_MODE)
  1290. {
  1291. DWORD cbNeeded = 0;
  1292. for (iIndex = 0; iIndex < 2; iIndex++)
  1293. {
  1294. DWORD cbOptionNameSize;
  1295. cbOptionNameSize = strlen(pstrPageOrder[iIndex]) + 1;
  1296. if (pmszOutBuf && cbRemain >= (INT)cbOptionNameSize)
  1297. {
  1298. CopyMemory(pmszOutBuf, pstrPageOrder[iIndex], cbOptionNameSize);
  1299. pmszOutBuf += cbOptionNameSize;
  1300. }
  1301. cbRemain -= cbOptionNameSize;
  1302. cbNeeded += cbOptionNameSize;
  1303. }
  1304. if (pcbNeeded)
  1305. {
  1306. *pcbNeeded = cbNeeded;
  1307. }
  1308. if (!pmszOutBuf || cbRemain < 0)
  1309. {
  1310. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1311. return FALSE;
  1312. }
  1313. return TRUE;
  1314. }
  1315. //
  1316. // option get/set handling
  1317. //
  1318. ASSERT(pdm);
  1319. pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
  1320. VGetSpoolerEmfCaps(hPrinter, NULL, &bReversePrint, 0, NULL);
  1321. if (!bReversePrint)
  1322. {
  1323. ERR(("%s not supported when spooler EMF is disabled, mode=%d", pszFeature, bSetMode));
  1324. SetLastError(ERROR_INVALID_PARAMETER);
  1325. return FALSE;
  1326. }
  1327. #ifndef KERNEL_MODE
  1328. //
  1329. // set is only supported for UI plugins
  1330. //
  1331. if (bSetMode)
  1332. {
  1333. for (iIndex = 0; iIndex < 2; iIndex++)
  1334. {
  1335. if ((*pszOption == pstrPageOrder[iIndex][0]) &&
  1336. (strcmp(pszOption, pstrPageOrder[iIndex]) == EQUAL_STRING))
  1337. {
  1338. break;
  1339. }
  1340. }
  1341. if (iIndex >= 2)
  1342. {
  1343. //
  1344. // unrecognized page order name
  1345. //
  1346. SetLastError(ERROR_INVALID_PARAMETER);
  1347. return FALSE;
  1348. }
  1349. //
  1350. // refer to VUnpackDocumentPropertiesItems
  1351. //
  1352. pdmPrivate->bReversePrint = iIndex != 0;
  1353. return TRUE;
  1354. }
  1355. #else
  1356. ASSERT(bSetMode == FALSE);
  1357. #endif // !KERNEL_MODE
  1358. //
  1359. // get is supported for both UI and render plugins
  1360. //
  1361. {
  1362. INT iSelection;
  1363. //
  1364. // refer to BPackItemEmfFeatures
  1365. //
  1366. iSelection = pdmPrivate->bReversePrint ? 1 : 0;
  1367. return BOutputFeatureOption(pszFeature,
  1368. pstrPageOrder[iSelection],
  1369. pmszOutBuf,
  1370. cbRemain,
  1371. pcbNeeded);
  1372. }
  1373. }
  1374. /*++
  1375. Routine Name:
  1376. BPSFProc_Nup
  1377. Routine Description:
  1378. %-feature enum/get/set operation handler
  1379. Arguments:
  1380. hPrinter - printer handle
  1381. pUIInfo - pointer to driver's UIINFO structure
  1382. pPpdData - pointer to driver's PPDDATA structure
  1383. pdm - pointer to public DEVMODE
  1384. pPrinterData - pointer to driver's PRINTERDATA structure
  1385. pszFeature - feature keyword name
  1386. pszOption - (set only) option keyword name
  1387. pmszOutBuf - (get only) pointer to output data buffer
  1388. cbRemain - (get only) remaining output data buffer size in bytes
  1389. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  1390. dwMode - indicate one of three operations: enum, get, set
  1391. Return Value:
  1392. TRUE if the requested operation succeeds
  1393. FALSE otherwise
  1394. Last Error:
  1395. ERROR_INVALID_PARAMETER (set only) if set operation found invalid argument
  1396. ERROR_INSUFFICIENT_BUFFER if output data buffer size is not big enough for
  1397. enum or get operation
  1398. --*/
  1399. BOOL
  1400. BPSFProc_Nup(
  1401. IN HANDLE hPrinter,
  1402. IN PUIINFO pUIInfo,
  1403. IN PPPDDATA pPpdData,
  1404. IN PDEVMODE pdm,
  1405. IN PPRINTERDATA pPrinterData,
  1406. IN PCSTR pszFeature,
  1407. IN PCSTR pszOption,
  1408. OUT PSTR pmszOutBuf,
  1409. IN INT cbRemain,
  1410. OUT PDWORD pcbNeeded,
  1411. IN DWORD dwMode
  1412. )
  1413. {
  1414. typedef struct _PSF_NUP_ENTRY {
  1415. PCSTR pszNupName; // Nup name
  1416. LAYOUT iLayout; // Nup code
  1417. } PSF_NUP_ENTRY, *PPSF_NUP_ENTRY;
  1418. static const PSF_NUP_ENTRY kPSF_NupTable[] =
  1419. {
  1420. "1", ONE_UP,
  1421. "2", TWO_UP,
  1422. "4", FOUR_UP,
  1423. "6", SIX_UP,
  1424. "9", NINE_UP,
  1425. "16", SIXTEEN_UP,
  1426. "Booklet", BOOKLET_UP,
  1427. NULL, 0,
  1428. };
  1429. PPSF_NUP_ENTRY pEntry, pMatchEntry;
  1430. PPSDRVEXTRA pdmPrivate;
  1431. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  1432. pMatchEntry = NULL;
  1433. pEntry = (PPSF_NUP_ENTRY)&(kPSF_NupTable[0]);
  1434. //
  1435. // option enumeration handling
  1436. //
  1437. if (dwMode == PSFPROC_ENUMOPTION_MODE)
  1438. {
  1439. BOOL bEMFSpooling;
  1440. DWORD cbNeeded = 0;
  1441. VGetSpoolerEmfCaps(hPrinter, NULL, &bEMFSpooling, 0, NULL);
  1442. while (pEntry->pszNupName)
  1443. {
  1444. //
  1445. // Booklet is not supported on NT4 and only supported when
  1446. // spooler EMF is enabled on Win2K+.
  1447. //
  1448. if ((pEntry->iLayout != BOOKLET_UP) ||
  1449. bEMFSpooling)
  1450. {
  1451. DWORD cbOptionNameSize;
  1452. cbOptionNameSize = strlen(pEntry->pszNupName) + 1;
  1453. if (pmszOutBuf && cbRemain >= (INT)cbOptionNameSize)
  1454. {
  1455. CopyMemory(pmszOutBuf, pEntry->pszNupName, cbOptionNameSize);
  1456. pmszOutBuf += cbOptionNameSize;
  1457. }
  1458. cbRemain -= cbOptionNameSize;
  1459. cbNeeded += cbOptionNameSize;
  1460. }
  1461. pEntry++;
  1462. }
  1463. if (pcbNeeded)
  1464. {
  1465. *pcbNeeded = cbNeeded;
  1466. }
  1467. if (!pmszOutBuf || cbRemain < 0)
  1468. {
  1469. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1470. return FALSE;
  1471. }
  1472. return TRUE;
  1473. }
  1474. //
  1475. // option get/set handling
  1476. //
  1477. ASSERT(pdm);
  1478. pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
  1479. #ifndef KERNEL_MODE
  1480. //
  1481. // set is only supported for UI plugins
  1482. //
  1483. if (bSetMode)
  1484. {
  1485. while (pEntry->pszNupName)
  1486. {
  1487. if ((*pszOption == *(pEntry->pszNupName)) &&
  1488. (strcmp(pszOption, pEntry->pszNupName) == EQUAL_STRING))
  1489. {
  1490. pMatchEntry = pEntry;
  1491. break;
  1492. }
  1493. pEntry++;
  1494. }
  1495. //
  1496. // refer to VUnpackDocumentPropertiesItems
  1497. //
  1498. if (!pMatchEntry)
  1499. {
  1500. //
  1501. // unrecognized Nup name
  1502. //
  1503. SetLastError(ERROR_INVALID_PARAMETER);
  1504. return FALSE;
  1505. }
  1506. pdmPrivate->iLayout = pMatchEntry->iLayout;
  1507. return TRUE;
  1508. }
  1509. #else
  1510. ASSERT(bSetMode == FALSE);
  1511. #endif // !KERNEL_MODE
  1512. //
  1513. // get is supported for both UI and render plugins
  1514. //
  1515. {
  1516. while (pEntry->pszNupName)
  1517. {
  1518. if (pdmPrivate->iLayout == pEntry->iLayout)
  1519. {
  1520. pMatchEntry = pEntry;
  1521. break;
  1522. }
  1523. pEntry++;
  1524. }
  1525. //
  1526. // If no match, default to 1-up.
  1527. //
  1528. if (!pMatchEntry)
  1529. {
  1530. RIP(("unknown iLayout value: %d\n", pdmPrivate->iLayout));
  1531. pMatchEntry = (PPSF_NUP_ENTRY)&(kPSF_NupTable[0]);
  1532. }
  1533. //
  1534. // refer to BPackItemEmfFeatures
  1535. //
  1536. return BOutputFeatureOption(pszFeature,
  1537. pMatchEntry->pszNupName,
  1538. pmszOutBuf,
  1539. cbRemain,
  1540. pcbNeeded);
  1541. }
  1542. }
  1543. /*++
  1544. Routine Name:
  1545. BPSFProc_PSErrHandler
  1546. Routine Description:
  1547. %-feature enum/get/set operation handler
  1548. Arguments:
  1549. hPrinter - printer handle
  1550. pUIInfo - pointer to driver's UIINFO structure
  1551. pPpdData - pointer to driver's PPDDATA structure
  1552. pdm - pointer to public DEVMODE
  1553. pPrinterData - pointer to driver's PRINTERDATA structure
  1554. pszFeature - feature keyword name
  1555. pszOption - (set only) option keyword name
  1556. pmszOutBuf - (get only) pointer to output data buffer
  1557. cbRemain - (get only) remaining output data buffer size in bytes
  1558. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  1559. dwMode - indicate one of three operations: enum, get, set
  1560. Return Value:
  1561. TRUE if the requested operation succeeds
  1562. FALSE otherwise
  1563. Last Error:
  1564. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  1565. ERROR_INVALID_PARAMETER
  1566. ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
  1567. --*/
  1568. BOOL
  1569. BPSFProc_PSErrHandler(
  1570. IN HANDLE hPrinter,
  1571. IN PUIINFO pUIInfo,
  1572. IN PPPDDATA pPpdData,
  1573. IN PDEVMODE pdm,
  1574. IN PPRINTERDATA pPrinterData,
  1575. IN PCSTR pszFeature,
  1576. IN PCSTR pszOption,
  1577. OUT PSTR pmszOutBuf,
  1578. IN INT cbRemain,
  1579. OUT PDWORD pcbNeeded,
  1580. IN DWORD dwMode
  1581. )
  1582. {
  1583. PPSDRVEXTRA pdmPrivate;
  1584. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  1585. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  1586. ASSERT(pdm);
  1587. pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
  1588. //
  1589. // refer to _BPackDocumentOptions and _VUnpackDocumentOptions in ps.c
  1590. //
  1591. return BGetSetBoolFlag(pszFeature,
  1592. pszOption,
  1593. &(pdmPrivate->dwFlags),
  1594. PSDEVMODE_EHANDLER,
  1595. TRUE,
  1596. pmszOutBuf,
  1597. cbRemain,
  1598. pcbNeeded,
  1599. bSetMode);
  1600. }
  1601. /*++
  1602. Routine Name:
  1603. BPSFProc_PSMemory
  1604. Routine Description:
  1605. %-feature enum/get/set operation handler
  1606. Arguments:
  1607. hPrinter - printer handle
  1608. pUIInfo - pointer to driver's UIINFO structure
  1609. pPpdData - pointer to driver's PPDDATA structure
  1610. pdm - pointer to public DEVMODE
  1611. pPrinterData - pointer to driver's PRINTERDATA structure
  1612. pszFeature - feature keyword name
  1613. pszOption - (set only) option keyword name
  1614. pmszOutBuf - (get only) pointer to output data buffer
  1615. cbRemain - (get only) remaining output data buffer size in bytes
  1616. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  1617. dwMode - indicate one of three operations: enum, get, set
  1618. Return Value:
  1619. TRUE if the requested operation succeeds
  1620. FALSE otherwise
  1621. Last Error:
  1622. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  1623. ERROR_INVALID_PARAMETER
  1624. ERROR_INSUFFICIENT_BUFFER see BGetSetUnsignedInt
  1625. --*/
  1626. BOOL
  1627. BPSFProc_PSMemory(
  1628. IN HANDLE hPrinter,
  1629. IN PUIINFO pUIInfo,
  1630. IN PPPDDATA pPpdData,
  1631. IN PDEVMODE pdm,
  1632. IN PPRINTERDATA pPrinterData,
  1633. IN PCSTR pszFeature,
  1634. IN PCSTR pszOption,
  1635. OUT PSTR pmszOutBuf,
  1636. IN INT cbRemain,
  1637. OUT PDWORD pcbNeeded,
  1638. IN DWORD dwMode
  1639. )
  1640. {
  1641. DWORD dwFreeMem;
  1642. BOOL bResult;
  1643. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  1644. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  1645. //
  1646. // refer to _BPackPrinterOptions in ps.c and
  1647. // VUnpackPrinterPropertiesItems in prnprop.c
  1648. //
  1649. dwFreeMem = pPrinterData->dwFreeMem / KBYTES;
  1650. bResult = BGetSetUnsignedInt(pszFeature,
  1651. pszOption,
  1652. &dwFreeMem,
  1653. MAX_DWORD_VALUE,
  1654. pmszOutBuf,
  1655. cbRemain,
  1656. pcbNeeded,
  1657. bSetMode);
  1658. #ifndef KERNEL_MODE
  1659. //
  1660. // set is only supported for UI plugins
  1661. //
  1662. if (bResult && bSetMode)
  1663. {
  1664. DWORD dwMinimum;
  1665. //
  1666. // Make sure the PS memory is not set below the minimum required.
  1667. // (refer to _BPackPrinterOptions in ps.c)
  1668. //
  1669. dwMinimum = (pUIInfo->dwLangLevel <= 1 ? MIN_FREEMEM_L1 : MIN_FREEMEM_L2) / KBYTES;
  1670. pPrinterData->dwFreeMem = max(dwFreeMem, dwMinimum) * KBYTES;
  1671. }
  1672. #endif // !KERNEL_MODE
  1673. return bResult;
  1674. }
  1675. /*++
  1676. Routine Name:
  1677. BPSFProc_Orientation
  1678. Routine Description:
  1679. %-feature enum/get/set operation handler
  1680. Arguments:
  1681. hPrinter - printer handle
  1682. pUIInfo - pointer to driver's UIINFO structure
  1683. pPpdData - pointer to driver's PPDDATA structure
  1684. pdm - pointer to public DEVMODE
  1685. pPrinterData - pointer to driver's PRINTERDATA structure
  1686. pszFeature - feature keyword name
  1687. pszOption - (set only) option keyword name
  1688. pmszOutBuf - (get only) pointer to output data buffer
  1689. cbRemain - (get only) remaining output data buffer size in bytes
  1690. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  1691. dwMode - indicate one of three operations: enum, get, set
  1692. Return Value:
  1693. TRUE if the requested operation succeeds
  1694. FALSE otherwise
  1695. Last Error:
  1696. ERROR_INVALID_PARAMETER (set only) if set operation found invalid argument
  1697. ERROR_INSUFFICIENT_BUFFER if output data buffer size is not big enough for
  1698. enum or get operation
  1699. --*/
  1700. BOOL
  1701. BPSFProc_Orientation(
  1702. IN HANDLE hPrinter,
  1703. IN PUIINFO pUIInfo,
  1704. IN PPPDDATA pPpdData,
  1705. IN PDEVMODE pdm,
  1706. IN PPRINTERDATA pPrinterData,
  1707. IN PCSTR pszFeature,
  1708. IN PCSTR pszOption,
  1709. OUT PSTR pmszOutBuf,
  1710. IN INT cbRemain,
  1711. OUT PDWORD pcbNeeded,
  1712. IN DWORD dwMode
  1713. )
  1714. {
  1715. static const CHAR pstrOrient[][32] =
  1716. {
  1717. "Portrait",
  1718. "Landscape",
  1719. "RotatedLandscape",
  1720. };
  1721. PPSDRVEXTRA pdmPrivate;
  1722. INT iIndex;
  1723. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  1724. //
  1725. // option enumeration handling
  1726. //
  1727. if (dwMode == PSFPROC_ENUMOPTION_MODE)
  1728. {
  1729. DWORD cbNeeded = 0;
  1730. for (iIndex = 0; iIndex <= 2; iIndex++)
  1731. {
  1732. DWORD cbOptionNameSize;
  1733. cbOptionNameSize = strlen(pstrOrient[iIndex]) + 1;
  1734. if (pmszOutBuf && cbRemain >= (INT)cbOptionNameSize)
  1735. {
  1736. CopyMemory(pmszOutBuf, pstrOrient[iIndex], cbOptionNameSize);
  1737. pmszOutBuf += cbOptionNameSize;
  1738. }
  1739. cbRemain -= cbOptionNameSize;
  1740. cbNeeded += cbOptionNameSize;
  1741. }
  1742. if (pcbNeeded)
  1743. {
  1744. *pcbNeeded = cbNeeded;
  1745. }
  1746. if (!pmszOutBuf || cbRemain < 0)
  1747. {
  1748. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1749. return FALSE;
  1750. }
  1751. return TRUE;
  1752. }
  1753. //
  1754. // option get/set handling
  1755. //
  1756. ASSERT(pdm);
  1757. pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
  1758. #ifndef KERNEL_MODE
  1759. //
  1760. // set is only supported for UI plugins
  1761. //
  1762. if (bSetMode)
  1763. {
  1764. for (iIndex = 0; iIndex <= 2; iIndex++)
  1765. {
  1766. if ((*pszOption == pstrOrient[iIndex][0]) &&
  1767. (strcmp(pszOption, pstrOrient[iIndex]) == EQUAL_STRING))
  1768. {
  1769. break;
  1770. }
  1771. }
  1772. if (iIndex > 2)
  1773. {
  1774. //
  1775. // unrecognized orientation name
  1776. //
  1777. SetLastError(ERROR_INVALID_PARAMETER);
  1778. return FALSE;
  1779. }
  1780. //
  1781. // refer to _VUnpackDocumentOptions in ps.c
  1782. //
  1783. pdm->dmFields |= DM_ORIENTATION;
  1784. pdm->dmOrientation = (iIndex == 0) ? DMORIENT_PORTRAIT :
  1785. DMORIENT_LANDSCAPE;
  1786. if (iIndex != 2)
  1787. pdmPrivate->dwFlags &= ~PSDEVMODE_LSROTATE;
  1788. else
  1789. pdmPrivate->dwFlags |= PSDEVMODE_LSROTATE;
  1790. return TRUE;
  1791. }
  1792. #else
  1793. ASSERT(bSetMode == FALSE);
  1794. #endif // !KERNEL_MODE
  1795. //
  1796. // get is supported for both UI and render plugins
  1797. //
  1798. {
  1799. INT iSelection;
  1800. //
  1801. // refer to _BPackOrientationItem in ps.c
  1802. //
  1803. if ((pdm->dmFields & DM_ORIENTATION) &&
  1804. (pdm->dmOrientation == DMORIENT_LANDSCAPE))
  1805. {
  1806. iSelection = pdmPrivate->dwFlags & PSDEVMODE_LSROTATE ? 2 : 1;
  1807. }
  1808. else
  1809. iSelection = 0;
  1810. return BOutputFeatureOption(pszFeature,
  1811. pstrOrient[iSelection],
  1812. pmszOutBuf,
  1813. cbRemain,
  1814. pcbNeeded);
  1815. }
  1816. }
  1817. /*++
  1818. Routine Name:
  1819. BPSFProc_OutFormat
  1820. Routine Description:
  1821. %-feature enum/get/set operation handler
  1822. Arguments:
  1823. hPrinter - printer handle
  1824. pUIInfo - pointer to driver's UIINFO structure
  1825. pPpdData - pointer to driver's PPDDATA structure
  1826. pdm - pointer to public DEVMODE
  1827. pPrinterData - pointer to driver's PRINTERDATA structure
  1828. pszFeature - feature keyword name
  1829. pszOption - (set only) option keyword name
  1830. pmszOutBuf - (get only) pointer to output data buffer
  1831. cbRemain - (get only) remaining output data buffer size in bytes
  1832. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  1833. dwMode - indicate one of three operations: enum, get, set
  1834. Return Value:
  1835. TRUE if the requested operation succeeds
  1836. FALSE otherwise
  1837. Last Error:
  1838. ERROR_INVALID_PARAMETER (set only) if set operation found invalid argument
  1839. ERROR_INSUFFICIENT_BUFFER if output data buffer size is not big enough for
  1840. enum or get operation
  1841. --*/
  1842. BOOL
  1843. BPSFProc_OutFormat(
  1844. IN HANDLE hPrinter,
  1845. IN PUIINFO pUIInfo,
  1846. IN PPPDDATA pPpdData,
  1847. IN PDEVMODE pdm,
  1848. IN PPRINTERDATA pPrinterData,
  1849. IN PCSTR pszFeature,
  1850. IN PCSTR pszOption,
  1851. OUT PSTR pmszOutBuf,
  1852. IN INT cbRemain,
  1853. OUT PDWORD pcbNeeded,
  1854. IN DWORD dwMode
  1855. )
  1856. {
  1857. typedef struct _PSF_OUTFORMAT_ENTRY {
  1858. PCSTR pszFormatName; // output format name
  1859. DIALECT iDialect; // output format code
  1860. } PSF_OUTFORMAT_ENTRY, *PPSF_OUTFORMAT_ENTRY;
  1861. static const PSF_OUTFORMAT_ENTRY kPSF_OutFormatTable[] =
  1862. {
  1863. {"Speed", SPEED},
  1864. {"Portability", PORTABILITY},
  1865. {"EPS", EPS},
  1866. {"Archive", ARCHIVE},
  1867. {NULL, 0},
  1868. };
  1869. PPSF_OUTFORMAT_ENTRY pEntry, pMatchEntry;
  1870. PPSDRVEXTRA pdmPrivate;
  1871. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  1872. pMatchEntry = NULL;
  1873. pEntry = (PPSF_OUTFORMAT_ENTRY)&(kPSF_OutFormatTable[0]);
  1874. //
  1875. // option enumeration handling
  1876. //
  1877. if (dwMode == PSFPROC_ENUMOPTION_MODE)
  1878. {
  1879. DWORD cbNeeded = 0;
  1880. while (pEntry->pszFormatName)
  1881. {
  1882. DWORD cbOptionNameSize;
  1883. cbOptionNameSize = strlen(pEntry->pszFormatName) + 1;
  1884. if (pmszOutBuf && cbRemain >= (INT)cbOptionNameSize)
  1885. {
  1886. CopyMemory(pmszOutBuf, pEntry->pszFormatName, cbOptionNameSize);
  1887. pmszOutBuf += cbOptionNameSize;
  1888. }
  1889. cbRemain -= cbOptionNameSize;
  1890. cbNeeded += cbOptionNameSize;
  1891. pEntry++;
  1892. }
  1893. if (pcbNeeded)
  1894. {
  1895. *pcbNeeded = cbNeeded;
  1896. }
  1897. if (!pmszOutBuf || cbRemain < 0)
  1898. {
  1899. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  1900. return FALSE;
  1901. }
  1902. return TRUE;
  1903. }
  1904. //
  1905. // option get/set handling
  1906. //
  1907. ASSERT(pdm);
  1908. pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
  1909. #ifndef KERNEL_MODE
  1910. //
  1911. // set is only supported for UI plugins
  1912. //
  1913. if (bSetMode)
  1914. {
  1915. while (pEntry->pszFormatName)
  1916. {
  1917. if ((*pszOption == *(pEntry->pszFormatName)) &&
  1918. (strcmp(pszOption, pEntry->pszFormatName) == EQUAL_STRING))
  1919. {
  1920. pMatchEntry = pEntry;
  1921. break;
  1922. }
  1923. pEntry++;
  1924. }
  1925. //
  1926. // refer to _VUnpackDocumentOptions in ps.c
  1927. //
  1928. if (!pMatchEntry)
  1929. {
  1930. //
  1931. // unrecognized output format name
  1932. //
  1933. SetLastError(ERROR_INVALID_PARAMETER);
  1934. return FALSE;
  1935. }
  1936. pdmPrivate->iDialect = pMatchEntry->iDialect;
  1937. return TRUE;
  1938. }
  1939. #else
  1940. ASSERT(bSetMode == FALSE);
  1941. #endif // !KERNEL_MODE
  1942. //
  1943. // get is supported for both UI and render plugins
  1944. //
  1945. {
  1946. while (pEntry->pszFormatName)
  1947. {
  1948. if (pdmPrivate->iDialect == pEntry->iDialect)
  1949. {
  1950. pMatchEntry = pEntry;
  1951. break;
  1952. }
  1953. pEntry++;
  1954. }
  1955. //
  1956. // If no match, default to SPEED.
  1957. //
  1958. if (!pMatchEntry)
  1959. {
  1960. RIP(("unknown iDialect value: %d\n", pdmPrivate->iDialect));
  1961. pMatchEntry = (PPSF_OUTFORMAT_ENTRY)&(kPSF_OutFormatTable[0]);
  1962. }
  1963. //
  1964. // refer to BPackItemPSOutputOption in ps.c
  1965. //
  1966. return BOutputFeatureOption(pszFeature,
  1967. pMatchEntry->pszFormatName,
  1968. pmszOutBuf,
  1969. cbRemain,
  1970. pcbNeeded);
  1971. }
  1972. }
  1973. /*++
  1974. Routine Name:
  1975. BPSFProc_Protocol
  1976. Routine Description:
  1977. %-feature enum/get/set operation handler
  1978. Arguments:
  1979. hPrinter - printer handle
  1980. pUIInfo - pointer to driver's UIINFO structure
  1981. pPpdData - pointer to driver's PPDDATA structure
  1982. pdm - pointer to public DEVMODE
  1983. pPrinterData - pointer to driver's PRINTERDATA structure
  1984. pszFeature - feature keyword name
  1985. pszOption - (set only) option keyword name
  1986. pmszOutBuf - (get only) pointer to output data buffer
  1987. cbRemain - (get only) remaining output data buffer size in bytes
  1988. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  1989. dwMode - indicate one of three operations: enum, get, set
  1990. Return Value:
  1991. TRUE if the requested operation succeeds
  1992. FALSE otherwise
  1993. Last Error:
  1994. ERROR_INVALID_PARAMETER (set only) if set operation found invalid argument
  1995. ERROR_INSUFFICIENT_BUFFER if output data buffer size is not big enough for
  1996. enum or get operation
  1997. --*/
  1998. BOOL
  1999. BPSFProc_Protocol(
  2000. IN HANDLE hPrinter,
  2001. IN PUIINFO pUIInfo,
  2002. IN PPPDDATA pPpdData,
  2003. IN PDEVMODE pdm,
  2004. IN PPRINTERDATA pPrinterData,
  2005. IN PCSTR pszFeature,
  2006. IN PCSTR pszOption,
  2007. OUT PSTR pmszOutBuf,
  2008. IN INT cbRemain,
  2009. OUT PDWORD pcbNeeded,
  2010. IN DWORD dwMode
  2011. )
  2012. {
  2013. typedef struct _PSF_PROTOCOL_ENTRY {
  2014. PCSTR pszProtocolName; // output protocol name
  2015. DWORD dwProtocol; // output protocol code
  2016. } PSF_PROTOCOL_ENTRY, *PPSF_PROTOCOL_ENTRY;
  2017. static const PSF_PROTOCOL_ENTRY kPSF_ProtocolTable[] =
  2018. {
  2019. {"ASCII", PROTOCOL_ASCII},
  2020. {"BCP", PROTOCOL_BCP},
  2021. {"TBCP", PROTOCOL_TBCP},
  2022. {"Binary", PROTOCOL_BINARY},
  2023. {NULL, 0},
  2024. };
  2025. PPSF_PROTOCOL_ENTRY pEntry, pMatchEntry;
  2026. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  2027. pMatchEntry = NULL;
  2028. pEntry = (PPSF_PROTOCOL_ENTRY)&(kPSF_ProtocolTable[0]);
  2029. //
  2030. // option enumeration handling
  2031. //
  2032. if (dwMode == PSFPROC_ENUMOPTION_MODE)
  2033. {
  2034. DWORD cbNeeded = 0;
  2035. while (pEntry->pszProtocolName)
  2036. {
  2037. //
  2038. // ASCII is always supported.
  2039. //
  2040. if ((pEntry->dwProtocol == PROTOCOL_ASCII) ||
  2041. (pUIInfo->dwProtocols & pEntry->dwProtocol))
  2042. {
  2043. DWORD cbOptionNameSize;
  2044. cbOptionNameSize = strlen(pEntry->pszProtocolName) + 1;
  2045. if (pmszOutBuf && cbRemain >= (INT)cbOptionNameSize)
  2046. {
  2047. CopyMemory(pmszOutBuf, pEntry->pszProtocolName, cbOptionNameSize);
  2048. pmszOutBuf += cbOptionNameSize;
  2049. }
  2050. cbRemain -= cbOptionNameSize;
  2051. cbNeeded += cbOptionNameSize;
  2052. }
  2053. pEntry++;
  2054. }
  2055. if (pcbNeeded)
  2056. {
  2057. *pcbNeeded = cbNeeded;
  2058. }
  2059. if (!pmszOutBuf || cbRemain < 0)
  2060. {
  2061. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2062. return FALSE;
  2063. }
  2064. return TRUE;
  2065. }
  2066. //
  2067. // option get/set handling
  2068. //
  2069. #ifndef KERNEL_MODE
  2070. //
  2071. // set is only supported for UI plugins
  2072. //
  2073. if (bSetMode)
  2074. {
  2075. while (pEntry->pszProtocolName)
  2076. {
  2077. if ((*pszOption == *(pEntry->pszProtocolName)) &&
  2078. (strcmp(pszOption, pEntry->pszProtocolName) == EQUAL_STRING))
  2079. {
  2080. pMatchEntry = pEntry;
  2081. break;
  2082. }
  2083. pEntry++;
  2084. }
  2085. //
  2086. // refer to _VUnpackDriverPrnPropItem in ps.c
  2087. //
  2088. if (!pMatchEntry ||
  2089. (pMatchEntry->dwProtocol != PROTOCOL_ASCII &&
  2090. !(pUIInfo->dwProtocols & pMatchEntry->dwProtocol)))
  2091. {
  2092. //
  2093. // Either unrecognized protocol name, or the protocol is not supported.
  2094. // (ASCII is always supported.)
  2095. //
  2096. SetLastError(ERROR_INVALID_PARAMETER);
  2097. return FALSE;
  2098. }
  2099. pPrinterData->wProtocol = (WORD)pMatchEntry->dwProtocol;
  2100. return TRUE;
  2101. }
  2102. #else
  2103. ASSERT(bSetMode == FALSE);
  2104. #endif // !KERNEL_MODE
  2105. //
  2106. // get is supported for both UI and render plugins
  2107. //
  2108. {
  2109. while (pEntry->pszProtocolName)
  2110. {
  2111. if (pPrinterData->wProtocol == (WORD)pEntry->dwProtocol)
  2112. {
  2113. pMatchEntry = pEntry;
  2114. break;
  2115. }
  2116. pEntry++;
  2117. }
  2118. //
  2119. // If no match or matched protocol is not supported, default to PROTOCOL_ASCII.
  2120. //
  2121. if (!pMatchEntry)
  2122. {
  2123. RIP(("unknown wProtocol value: %d\n", pPrinterData->wProtocol));
  2124. pMatchEntry = (PPSF_PROTOCOL_ENTRY)&(kPSF_ProtocolTable[0]);
  2125. }
  2126. //
  2127. // refer to BPackPSProtocolItem in ps.c
  2128. //
  2129. if (pMatchEntry->dwProtocol != PROTOCOL_ASCII &&
  2130. !(pUIInfo->dwProtocols & pMatchEntry->dwProtocol))
  2131. {
  2132. ERR(("unsupported wProtocol value: %d\n", pPrinterData->wProtocol));
  2133. pMatchEntry = (PPSF_PROTOCOL_ENTRY)&(kPSF_ProtocolTable[0]);
  2134. }
  2135. return BOutputFeatureOption(pszFeature,
  2136. pMatchEntry->pszProtocolName,
  2137. pmszOutBuf,
  2138. cbRemain,
  2139. pcbNeeded);
  2140. }
  2141. }
  2142. /*++
  2143. Routine Name:
  2144. BPSFProc_PSLevel
  2145. Routine Description:
  2146. %-feature enum/get/set operation handler
  2147. Arguments:
  2148. hPrinter - printer handle
  2149. pUIInfo - pointer to driver's UIINFO structure
  2150. pPpdData - pointer to driver's PPDDATA structure
  2151. pdm - pointer to public DEVMODE
  2152. pPrinterData - pointer to driver's PRINTERDATA structure
  2153. pszFeature - feature keyword name
  2154. pszOption - (set only) option keyword name
  2155. pmszOutBuf - (get only) pointer to output data buffer
  2156. cbRemain - (get only) remaining output data buffer size in bytes
  2157. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  2158. dwMode - indicate one of three operations: enum, get, set
  2159. Return Value:
  2160. TRUE if the requested operation succeeds
  2161. FALSE otherwise
  2162. Last Error:
  2163. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  2164. ERROR_INVALID_PARAMETER if PSLevel is set to a negative value,
  2165. or see BGetSetUnsignedInt
  2166. ERROR_INSUFFICIENT_BUFFER see BGetSetUnsignedInt
  2167. --*/
  2168. BOOL
  2169. BPSFProc_PSLevel(
  2170. IN HANDLE hPrinter,
  2171. IN PUIINFO pUIInfo,
  2172. IN PPPDDATA pPpdData,
  2173. IN PDEVMODE pdm,
  2174. IN PPRINTERDATA pPrinterData,
  2175. IN PCSTR pszFeature,
  2176. IN PCSTR pszOption,
  2177. OUT PSTR pmszOutBuf,
  2178. IN INT cbRemain,
  2179. OUT PDWORD pcbNeeded,
  2180. IN DWORD dwMode
  2181. )
  2182. {
  2183. PPSDRVEXTRA pdmPrivate;
  2184. DWORD dwPSLevel;
  2185. BOOL bResult;
  2186. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  2187. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  2188. ASSERT(pdm);
  2189. pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
  2190. //
  2191. // refer to _VUnpackDocumentOptions and BPackItemPSLevel in ps.c
  2192. //
  2193. dwPSLevel = (DWORD)pdmPrivate->iPSLevel;
  2194. bResult = BGetSetUnsignedInt(pszFeature,
  2195. pszOption,
  2196. &dwPSLevel,
  2197. pUIInfo->dwLangLevel,
  2198. pmszOutBuf,
  2199. cbRemain,
  2200. pcbNeeded,
  2201. bSetMode);
  2202. #ifndef KERNEL_MODE
  2203. //
  2204. // set is only supported for UI plugins
  2205. //
  2206. if (bResult && bSetMode)
  2207. {
  2208. //
  2209. // set output PS level to 0 is not allowed
  2210. //
  2211. if (dwPSLevel > 0)
  2212. {
  2213. pdmPrivate->iPSLevel = (INT)dwPSLevel;
  2214. }
  2215. else
  2216. {
  2217. SetLastError(ERROR_INVALID_PARAMETER);
  2218. bResult = FALSE;
  2219. }
  2220. }
  2221. #endif // !KERNEL_MODE
  2222. return bResult;
  2223. }
  2224. /*++
  2225. Routine Name:
  2226. BPSFProc_TrueGrayT
  2227. Routine Description:
  2228. %-feature enum/get/set operation handler
  2229. Arguments:
  2230. hPrinter - printer handle
  2231. pUIInfo - pointer to driver's UIINFO structure
  2232. pPpdData - pointer to driver's PPDDATA structure
  2233. pdm - pointer to public DEVMODE
  2234. pPrinterData - pointer to driver's PRINTERDATA structure
  2235. pszFeature - feature keyword name
  2236. pszOption - (set only) option keyword name
  2237. pmszOutBuf - (get only) pointer to output data buffer
  2238. cbRemain - (get only) remaining output data buffer size in bytes
  2239. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  2240. dwMode - indicate one of three operations: enum, get, set
  2241. Return Value:
  2242. TRUE if the requested operation succeeds
  2243. FALSE otherwise
  2244. Last Error:
  2245. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  2246. ERROR_INVALID_PARAMETER
  2247. ERROR_INSUFFICIENT_BUFFER see BGetSetBoolFlag
  2248. --*/
  2249. BOOL
  2250. BPSFProc_TrueGrayT(
  2251. IN HANDLE hPrinter,
  2252. IN PUIINFO pUIInfo,
  2253. IN PPPDDATA pPpdData,
  2254. IN PDEVMODE pdm,
  2255. IN PPRINTERDATA pPrinterData,
  2256. IN PCSTR pszFeature,
  2257. IN PCSTR pszOption,
  2258. OUT PSTR pmszOutBuf,
  2259. IN INT cbRemain,
  2260. OUT PDWORD pcbNeeded,
  2261. IN DWORD dwMode
  2262. )
  2263. {
  2264. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  2265. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  2266. //
  2267. // refer to _VUnpackDriverPrnPropItem and _BPackPrinterOptions in ps.c
  2268. //
  2269. return BGetSetBoolFlag(pszFeature,
  2270. pszOption,
  2271. &(pPrinterData->dwFlags),
  2272. PFLAGS_TRUE_GRAY_TEXT,
  2273. TRUE,
  2274. pmszOutBuf,
  2275. cbRemain,
  2276. pcbNeeded,
  2277. bSetMode);
  2278. }
  2279. /*++
  2280. Routine Name:
  2281. BPSFProc_TTFormat
  2282. Routine Description:
  2283. %-feature enum/get/set operation handler
  2284. Arguments:
  2285. hPrinter - printer handle
  2286. pUIInfo - pointer to driver's UIINFO structure
  2287. pPpdData - pointer to driver's PPDDATA structure
  2288. pdm - pointer to public DEVMODE
  2289. pPrinterData - pointer to driver's PRINTERDATA structure
  2290. pszFeature - feature keyword name
  2291. pszOption - (set only) option keyword name
  2292. pmszOutBuf - (get only) pointer to output data buffer
  2293. cbRemain - (get only) remaining output data buffer size in bytes
  2294. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  2295. dwMode - indicate one of three operations: enum, get, set
  2296. Return Value:
  2297. TRUE if the requested operation succeeds
  2298. FALSE otherwise
  2299. Last Error:
  2300. ERROR_INVALID_PARAMETER (set only) if set operation found invalid argument
  2301. ERROR_INSUFFICIENT_BUFFER if output data buffer size is not big enough for
  2302. enum or get operation
  2303. --*/
  2304. BOOL
  2305. BPSFProc_TTFormat(
  2306. IN HANDLE hPrinter,
  2307. IN PUIINFO pUIInfo,
  2308. IN PPPDDATA pPpdData,
  2309. IN PDEVMODE pdm,
  2310. IN PPRINTERDATA pPrinterData,
  2311. IN PCSTR pszFeature,
  2312. IN PCSTR pszOption,
  2313. OUT PSTR pmszOutBuf,
  2314. IN INT cbRemain,
  2315. OUT PDWORD pcbNeeded,
  2316. IN DWORD dwMode
  2317. )
  2318. {
  2319. typedef struct _PSF_TTFORMAT_ENTRY {
  2320. PCSTR pszTTFmtName; // TT download format name
  2321. TTDLFMT iTTDLFmt; // TT download format enum code
  2322. } PSF_TTFORMAT_ENTRY, *PPSF_TTFORMAT_ENTRY;
  2323. static const PSF_TTFORMAT_ENTRY kPSF_TTFormatTable[] =
  2324. {
  2325. {"Automatic", TT_DEFAULT},
  2326. {"Outline", TYPE_1},
  2327. {"Bitmap", TYPE_3},
  2328. {"NativeTrueType", TYPE_42},
  2329. {NULL, 0},
  2330. };
  2331. PPSF_TTFORMAT_ENTRY pEntry, pMatchEntry;
  2332. PPSDRVEXTRA pdmPrivate;
  2333. BOOL bSupportType42;
  2334. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  2335. bSupportType42 = pUIInfo->dwTTRasterizer == TTRAS_TYPE42;
  2336. pMatchEntry = NULL;
  2337. pEntry = (PPSF_TTFORMAT_ENTRY)&(kPSF_TTFormatTable[0]);
  2338. //
  2339. // option enumeration handling
  2340. //
  2341. if (dwMode == PSFPROC_ENUMOPTION_MODE)
  2342. {
  2343. DWORD cbNeeded = 0;
  2344. while (pEntry->pszTTFmtName)
  2345. {
  2346. if ((pEntry->iTTDLFmt != TYPE_42) ||
  2347. bSupportType42)
  2348. {
  2349. DWORD cbOptionNameSize;
  2350. cbOptionNameSize = strlen(pEntry->pszTTFmtName) + 1;
  2351. if (pmszOutBuf && cbRemain >= (INT)cbOptionNameSize)
  2352. {
  2353. CopyMemory(pmszOutBuf, pEntry->pszTTFmtName, cbOptionNameSize);
  2354. pmszOutBuf += cbOptionNameSize;
  2355. }
  2356. cbRemain -= cbOptionNameSize;
  2357. cbNeeded += cbOptionNameSize;
  2358. }
  2359. pEntry++;
  2360. }
  2361. if (pcbNeeded)
  2362. {
  2363. *pcbNeeded = cbNeeded;
  2364. }
  2365. if (!pmszOutBuf || cbRemain < 0)
  2366. {
  2367. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  2368. return FALSE;
  2369. }
  2370. return TRUE;
  2371. }
  2372. //
  2373. // option get/set handling
  2374. //
  2375. ASSERT(pdm);
  2376. pdmPrivate = (PPSDRVEXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdm);
  2377. #ifndef KERNEL_MODE
  2378. //
  2379. // set is only supported for UI plugins
  2380. //
  2381. if (bSetMode)
  2382. {
  2383. while (pEntry->pszTTFmtName)
  2384. {
  2385. if ((*pszOption == *(pEntry->pszTTFmtName)) &&
  2386. (strcmp(pszOption, pEntry->pszTTFmtName) == EQUAL_STRING))
  2387. {
  2388. pMatchEntry = pEntry;
  2389. break;
  2390. }
  2391. pEntry++;
  2392. }
  2393. //
  2394. // refer to _VUnpackDocumentOptions in ps.c
  2395. //
  2396. if (!pMatchEntry ||
  2397. (!bSupportType42 && pMatchEntry->iTTDLFmt == TYPE_42))
  2398. {
  2399. //
  2400. // Either unrecognized TTFormat name, or the TTFormat is not supported.
  2401. //
  2402. SetLastError(ERROR_INVALID_PARAMETER);
  2403. return FALSE;
  2404. }
  2405. pdmPrivate->iTTDLFmt = pMatchEntry->iTTDLFmt;
  2406. return TRUE;
  2407. }
  2408. #else
  2409. ASSERT(bSetMode == FALSE);
  2410. #endif // !KERNEL_MODE
  2411. //
  2412. // get is supported for both UI and render plugins
  2413. //
  2414. {
  2415. while (pEntry->pszTTFmtName)
  2416. {
  2417. if (pdmPrivate->iTTDLFmt == pEntry->iTTDLFmt)
  2418. {
  2419. pMatchEntry = pEntry;
  2420. break;
  2421. }
  2422. pEntry++;
  2423. }
  2424. //
  2425. // If no match or matched format is not supported, default to Automatic format.
  2426. //
  2427. if (!pMatchEntry)
  2428. {
  2429. RIP(("unknown TTFormat value: %d\n", pdmPrivate->iTTDLFmt));
  2430. pMatchEntry = (PPSF_TTFORMAT_ENTRY)&(kPSF_TTFormatTable[0]);
  2431. }
  2432. //
  2433. // refer to BPackItemTTDownloadFormat in ps.c
  2434. //
  2435. if (!bSupportType42 && pMatchEntry->iTTDLFmt == TYPE_42)
  2436. {
  2437. ERR(("unsupported TTFormat value: %d\n", pdmPrivate->iTTDLFmt));
  2438. pMatchEntry = (PPSF_TTFORMAT_ENTRY)&(kPSF_TTFormatTable[0]);
  2439. }
  2440. return BOutputFeatureOption(pszFeature,
  2441. pMatchEntry->pszTTFmtName,
  2442. pmszOutBuf,
  2443. cbRemain,
  2444. pcbNeeded);
  2445. }
  2446. }
  2447. /*++
  2448. Routine Name:
  2449. BPSFProc_WaitTimeout
  2450. Routine Description:
  2451. %-feature enum/get/set operation handler
  2452. Arguments:
  2453. hPrinter - printer handle
  2454. pUIInfo - pointer to driver's UIINFO structure
  2455. pPpdData - pointer to driver's PPDDATA structure
  2456. pdm - pointer to public DEVMODE
  2457. pPrinterData - pointer to driver's PRINTERDATA structure
  2458. pszFeature - feature keyword name
  2459. pszOption - (set only) option keyword name
  2460. pmszOutBuf - (get only) pointer to output data buffer
  2461. cbRemain - (get only) remaining output data buffer size in bytes
  2462. pcbNeeded - (get only) buffer size in bytes needed to output the feature setting
  2463. dwMode - indicate one of three operations: enum, get, set
  2464. Return Value:
  2465. TRUE if the requested operation succeeds
  2466. FALSE otherwise
  2467. Last Error:
  2468. ERROR_NOT_SUPPORTED unsupported enum operation is requested
  2469. ERROR_INVALID_PARAMETER
  2470. ERROR_INSUFFICIENT_BUFFER see BGetSetUnsignedInt
  2471. --*/
  2472. BOOL
  2473. BPSFProc_WaitTimeout(
  2474. IN HANDLE hPrinter,
  2475. IN PUIINFO pUIInfo,
  2476. IN PPPDDATA pPpdData,
  2477. IN PDEVMODE pdm,
  2478. IN PPRINTERDATA pPrinterData,
  2479. IN PCSTR pszFeature,
  2480. IN PCSTR pszOption,
  2481. OUT PSTR pmszOutBuf,
  2482. IN INT cbRemain,
  2483. OUT PDWORD pcbNeeded,
  2484. IN DWORD dwMode
  2485. )
  2486. {
  2487. BOOL bSetMode = (dwMode == PSFPROC_SETOPTION_MODE) ? TRUE : FALSE;
  2488. RETURN_ON_UNSUPPORTED_ENUM_MODE(dwMode)
  2489. //
  2490. // refer to VUnpackPrinterPropertiesItems in prnprop.c
  2491. // and _BPackPrinterOptions in ps.c
  2492. //
  2493. return BGetSetUnsignedInt(pszFeature,
  2494. pszOption,
  2495. &(pPrinterData->dwWaitTimeout),
  2496. MAX_DWORD_VALUE,
  2497. pmszOutBuf,
  2498. cbRemain,
  2499. pcbNeeded,
  2500. bSetMode);
  2501. }
  2502. //
  2503. // Note: for pfnPSProc handlers whose bPrinterSticky is TRUE,
  2504. // the PDEVMODE will be NULL (see PFillUiData), so you should NOT
  2505. // access PDEVMODE.
  2506. //
  2507. const PSFEATURE_ENTRY kPSFeatureTable[] =
  2508. {
  2509. //
  2510. // pszPSFeatureName bPrinterSticky bEnumerableOptions bBooleanOptions pfnPSProc
  2511. //
  2512. {kstrPSFAddEuro, TRUE, TRUE, TRUE, BPSFProc_AddEuro},
  2513. {kstrPSFCtrlDAfter, TRUE, TRUE, TRUE, BPSFProc_CtrlDA},
  2514. {kstrPSFCtrlDBefore, TRUE, TRUE, TRUE, BPSFProc_CtrlDB},
  2515. {kstrPSFCustomPS, FALSE, FALSE, FALSE, BPSFProc_CustomPS},
  2516. {kstrPSFTrueGrayG, TRUE, TRUE, TRUE, BPSFProc_TrueGrayG},
  2517. {kstrPSFJobTimeout, TRUE, FALSE, FALSE, BPSFProc_JobTimeout},
  2518. {kstrPSFMaxBitmap, TRUE, FALSE, FALSE, BPSFProc_MaxBitmap},
  2519. {kstrPSFEMF, FALSE, TRUE, TRUE, BPSFProc_EMF},
  2520. {kstrPSFMinOutline, TRUE, FALSE, FALSE, BPSFProc_MinOutline},
  2521. {kstrPSFMirroring, FALSE, TRUE, TRUE, BPSFProc_Mirroring},
  2522. {kstrPSFNegative, FALSE, TRUE, TRUE, BPSFProc_Negative},
  2523. {kstrPSFPageOrder, FALSE, TRUE, FALSE, BPSFProc_PageOrder},
  2524. {kstrPSFNup, FALSE, TRUE, FALSE, BPSFProc_Nup},
  2525. {kstrPSFErrHandler, FALSE, TRUE, TRUE, BPSFProc_PSErrHandler},
  2526. {kstrPSFPSMemory, TRUE, FALSE, FALSE, BPSFProc_PSMemory},
  2527. {kstrPSFOrientation, FALSE, TRUE, FALSE, BPSFProc_Orientation},
  2528. {kstrPSFOutFormat, FALSE, TRUE, FALSE, BPSFProc_OutFormat},
  2529. {kstrPSFOutProtocol, TRUE, TRUE, FALSE, BPSFProc_Protocol},
  2530. {kstrPSFOutPSLevel, FALSE, FALSE, FALSE, BPSFProc_PSLevel},
  2531. {kstrPSFTrueGrayT, TRUE, TRUE, TRUE, BPSFProc_TrueGrayT},
  2532. {kstrPSFTTFormat, FALSE, TRUE, FALSE, BPSFProc_TTFormat},
  2533. {kstrPSFWaitTimeout, TRUE, FALSE, FALSE, BPSFProc_WaitTimeout},
  2534. {NULL, FALSE, FALSE, FALSE, NULL},
  2535. };
  2536. /*++
  2537. Routine Name:
  2538. PComposeFullFeatureList
  2539. Routine Description:
  2540. Allocate a buffer and fill the buffer with the full keyword list
  2541. of supported features.
  2542. Caller is responsible to free the buffer.
  2543. Arguments:
  2544. hPrinter - printer handle
  2545. pUIInfo - pointer to driver's UIINFO structure
  2546. Return Value:
  2547. NULL if failed to allocate and correctly fill the buffer
  2548. non-NULL succeeds. Pointer to the buffer containing full keyword list
  2549. of supported features will be returned.
  2550. Last Error:
  2551. None
  2552. --*/
  2553. PSTR
  2554. PComposeFullFeatureList(
  2555. IN HANDLE hPrinter,
  2556. IN PUIINFO pUIInfo
  2557. )
  2558. {
  2559. PSTR pmszFeatureList, pmszRet = NULL;
  2560. DWORD cbNeeded = 0;
  2561. HRESULT hr;
  2562. hr = HEnumFeaturesOrOptions(hPrinter,
  2563. pUIInfo->pInfoHeader,
  2564. 0,
  2565. NULL,
  2566. NULL,
  2567. 0,
  2568. &cbNeeded);
  2569. if (hr != E_OUTOFMEMORY || cbNeeded == 0)
  2570. {
  2571. ERR(("HEnumFeaturesOrOptions failed. hr=%X\n", hr));
  2572. goto exit;
  2573. }
  2574. if ((pmszFeatureList = MemAlloc(cbNeeded)) == NULL)
  2575. {
  2576. ERR(("memory allocation failed.\n"));
  2577. goto exit;
  2578. }
  2579. hr = HEnumFeaturesOrOptions(hPrinter,
  2580. pUIInfo->pInfoHeader,
  2581. 0,
  2582. NULL,
  2583. pmszFeatureList,
  2584. cbNeeded,
  2585. &cbNeeded);
  2586. if (FAILED(hr))
  2587. {
  2588. ERR(("HEnumFeaturesOrOptions failed. hr=%X\n", hr));
  2589. MemFree(pmszFeatureList);
  2590. goto exit;
  2591. }
  2592. //
  2593. // Succeeded
  2594. //
  2595. pmszRet = pmszFeatureList;
  2596. exit:
  2597. return pmszRet;
  2598. }
  2599. /*++
  2600. Routine Name:
  2601. BValidMultiSZString
  2602. Routine Description:
  2603. validate if a given ASCII string is in MULTI_SZ format
  2604. Arguments:
  2605. pmszString - the input ASCII string that needs validation
  2606. cbSize - size in bytes of the input ASCII string
  2607. bCheckPairs - TRUE if need to validate the MULTI_SZ
  2608. string contains pairs. FALSE otherwise.
  2609. Return Value:
  2610. TRUE if the input ASCII string is in valid MULTI_SZ format
  2611. FALSE if it's not
  2612. Last Error:
  2613. None
  2614. --*/
  2615. BOOL
  2616. BValidMultiSZString(
  2617. IN PCSTR pmszString,
  2618. IN DWORD cbSize,
  2619. IN BOOL bCheckPairs
  2620. )
  2621. {
  2622. PCSTR pszEnd;
  2623. INT cTokens = 0;
  2624. if (!pmszString || !cbSize)
  2625. {
  2626. return FALSE;
  2627. }
  2628. pszEnd = pmszString + cbSize - 1;
  2629. while (*pmszString && pmszString <= pszEnd)
  2630. {
  2631. while (*pmszString && pmszString <= pszEnd)
  2632. {
  2633. pmszString++;
  2634. }
  2635. if (pmszString > pszEnd)
  2636. {
  2637. ERR(("Missing single token's NUL terminator!\n"));
  2638. return FALSE;
  2639. }
  2640. cTokens++;
  2641. pmszString++;
  2642. }
  2643. if (pmszString > pszEnd)
  2644. {
  2645. ERR(("Missing MULTI_SZ string's last NUL terminator!\n"));
  2646. return FALSE;
  2647. }
  2648. if (!bCheckPairs)
  2649. {
  2650. return TRUE;
  2651. }
  2652. else
  2653. {
  2654. return (cTokens % 2) ? FALSE : TRUE;
  2655. }
  2656. }
  2657. /*++
  2658. Routine Name:
  2659. HGetOptions
  2660. Routine Description:
  2661. get the current setting for a specified feature
  2662. For UI plugin's GetOptions call during DrvDocumentPropertySheets, or for
  2663. render plugins's GetOptions call, both doc-sticky and printer-sticky features
  2664. are supported.
  2665. For UI plugin's GetOptions call during DrvDevicePropertySheets, only
  2666. printer-sticky features are supported.
  2667. Arguments:
  2668. hPrinter - printer handle
  2669. pInfoHeader - pointer to driver's INFOHEADER structure
  2670. pOptionsArray - pointer to driver's combined option array
  2671. pdm - pointer to public DEVMODE
  2672. pPrinterData - pointer to driver's PRINTERDATA structure
  2673. dwFlags - flags for the get operation
  2674. pmszFeaturesRequested - MULTI_SZ ASCII string containing feature keyword names
  2675. cbin - size in bytes of the pmszFeaturesRequested string
  2676. pmszFeatureOptionBuf - pointer to output data buffer to store feature settings
  2677. cbSize - size in bytes of pmszFeatureOptionBuf buffer
  2678. pcbNeeded - buffer size in bytes needed to output the feature settings
  2679. bPrinterSticky - TRUE if we are in printer-sticky mode, FALSE if we are in
  2680. doc-sticky mode
  2681. Return Value:
  2682. S_OK if the get operation succeeds
  2683. E_INVALIDARG if input pmszFeaturesRequested is not in valid MULTI_SZ format
  2684. E_OUTOFMEMORY if output data buffer size is not big enough
  2685. E_FAIL if other internal failures are encountered
  2686. Last Error:
  2687. None
  2688. --*/
  2689. HRESULT
  2690. HGetOptions(
  2691. IN HANDLE hPrinter,
  2692. IN PINFOHEADER pInfoHeader,
  2693. IN POPTSELECT pOptionsArray,
  2694. IN PDEVMODE pdm,
  2695. IN PPRINTERDATA pPrinterData,
  2696. IN DWORD dwFlags,
  2697. IN PCSTR pmszFeaturesRequested,
  2698. IN DWORD cbIn,
  2699. OUT PSTR pmszFeatureOptionBuf,
  2700. IN DWORD cbSize,
  2701. OUT PDWORD pcbNeeded,
  2702. IN BOOL bPrinterSticky
  2703. )
  2704. {
  2705. PUIINFO pUIInfo;
  2706. PPPDDATA pPpdData;
  2707. HRESULT hr;
  2708. PSTR pmszFeatureList = NULL, pCurrentOut;
  2709. PCSTR pszFeature;
  2710. DWORD cbNeeded;
  2711. INT cbRemain;
  2712. pUIInfo = GET_UIINFO_FROM_INFOHEADER(pInfoHeader);
  2713. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER(pInfoHeader);
  2714. ASSERT(pUIInfo != NULL && pUIInfo->dwSize == sizeof(UIINFO));
  2715. ASSERT(pPpdData != NULL && pPpdData->dwSizeOfStruct == sizeof(PPDDATA));
  2716. if (pUIInfo == NULL || pPpdData == NULL)
  2717. {
  2718. hr = E_FAIL;
  2719. goto exit;
  2720. }
  2721. if (!pmszFeaturesRequested)
  2722. {
  2723. //
  2724. // client is asking for settings of all features.
  2725. //
  2726. if (!(pmszFeatureList = PComposeFullFeatureList(hPrinter, pUIInfo)))
  2727. {
  2728. hr = E_FAIL;
  2729. goto exit;
  2730. }
  2731. pszFeature = pmszFeatureList;
  2732. }
  2733. else
  2734. {
  2735. //
  2736. // client provided its specific feature list.
  2737. //
  2738. // We need to verify the MULTI_SZ input buffer first.
  2739. //
  2740. if (!BValidMultiSZString(pmszFeaturesRequested, cbIn, FALSE))
  2741. {
  2742. ERR(("Get: invalid MULTI_SZ input param\n"));
  2743. hr = E_INVALIDARG;
  2744. goto exit;
  2745. }
  2746. pszFeature = pmszFeaturesRequested;
  2747. }
  2748. pCurrentOut = pmszFeatureOptionBuf;
  2749. cbNeeded = 0;
  2750. cbRemain = (INT)cbSize;
  2751. while (*pszFeature)
  2752. {
  2753. DWORD cbFeatureKeySize;
  2754. cbFeatureKeySize = strlen(pszFeature) + 1;
  2755. if (*pszFeature == PSFEATURE_PREFIX)
  2756. {
  2757. PPSFEATURE_ENTRY pEntry, pMatchEntry;
  2758. //
  2759. // synthesized PS driver feature
  2760. //
  2761. pMatchEntry = NULL;
  2762. pEntry = (PPSFEATURE_ENTRY)(&kPSFeatureTable[0]);
  2763. while (pEntry->pszPSFeatureName)
  2764. {
  2765. if ((*pszFeature == *(pEntry->pszPSFeatureName)) &&
  2766. (strcmp(pszFeature, pEntry->pszPSFeatureName) == EQUAL_STRING))
  2767. {
  2768. pMatchEntry = pEntry;
  2769. break;
  2770. }
  2771. pEntry++;
  2772. }
  2773. //
  2774. // Both doc-sticky and printer-sticky features are supported in DOC_STICKY_MODE,
  2775. // but only printer-sticky features are supported in PRINTER_STICKY_MODE.
  2776. // (refer to comments in HEnumConstrainedOptions)
  2777. //
  2778. if (!pMatchEntry ||
  2779. (bPrinterSticky && !pMatchEntry->bPrinterSticky))
  2780. {
  2781. VERBOSE(("Get: invalid or mode-mismatched feature %s\n", pszFeature));
  2782. goto next_feature;
  2783. }
  2784. if (pMatchEntry->pfnPSProc)
  2785. {
  2786. DWORD cbPSFSize = 0;
  2787. BOOL bResult;
  2788. bResult = (pMatchEntry->pfnPSProc)(hPrinter,
  2789. pUIInfo,
  2790. pPpdData,
  2791. pdm,
  2792. pPrinterData,
  2793. pszFeature,
  2794. NULL,
  2795. pCurrentOut,
  2796. cbRemain,
  2797. &cbPSFSize,
  2798. PSFPROC_GETOPTION_MODE);
  2799. if (bResult)
  2800. {
  2801. //
  2802. // If the handler succeeded, it should have filled in the output buffer
  2803. // with correct content and return the size of buffer consumption in cbPSFSize.
  2804. //
  2805. pCurrentOut += cbPSFSize;
  2806. }
  2807. else
  2808. {
  2809. //
  2810. // If the handler failed because of insufficent output buffer, it should return
  2811. // the needed buffer size in cbPSFSize.
  2812. //
  2813. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  2814. {
  2815. ERR(("Get: %%-feature handler failed on %s\n", pszFeature));
  2816. }
  2817. }
  2818. cbRemain -= cbPSFSize;
  2819. cbNeeded += cbPSFSize;
  2820. }
  2821. }
  2822. else
  2823. {
  2824. PFEATURE pFeature;
  2825. POPTION pOption;
  2826. PSTR pszOption;
  2827. DWORD dwFeatureIndex, cbOptionKeySize;
  2828. //
  2829. // PPD *OpenUI feature
  2830. //
  2831. pFeature = PGetNamedFeature(pUIInfo, pszFeature, &dwFeatureIndex);
  2832. //
  2833. // Both doc-sticky and printer-sticky features are supported in DOC_STICKY_MODE,
  2834. // but only printer-sticky features are supported in PRINTER_STICKY_MODE.
  2835. // (refer to comments in HEnumConstrainedOptions)
  2836. //
  2837. if (!pFeature ||
  2838. (bPrinterSticky && pFeature->dwFeatureType != FEATURETYPE_PRINTERPROPERTY))
  2839. {
  2840. VERBOSE(("Get: invalid or mode-mismatched feature %s\n", pszFeature));
  2841. goto next_feature;
  2842. }
  2843. //
  2844. // Skip GID_LEADINGEDGE, GID_USEHWMARGINS. They are not real PPD *OpenUI features.
  2845. //
  2846. if (pFeature->dwFeatureID == GID_LEADINGEDGE ||
  2847. pFeature->dwFeatureID == GID_USEHWMARGINS)
  2848. {
  2849. VERBOSE(("Get: skip feature %s\n", pszFeature));
  2850. goto next_feature;
  2851. }
  2852. pOption = PGetIndexedOption(pUIInfo, pFeature, pOptionsArray[dwFeatureIndex].ubCurOptIndex);
  2853. if (!pOption)
  2854. {
  2855. WARNING(("Get: invalid option selection for feature %s\n", pszFeature));
  2856. goto next_feature;
  2857. }
  2858. pszOption = OFFSET_TO_POINTER(pUIInfo->pubResourceData, pOption->loKeywordName);
  2859. ASSERT(pszOption);
  2860. cbOptionKeySize = strlen(pszOption) + 1;
  2861. //
  2862. // We don't support pick-many yet.
  2863. //
  2864. ASSERT(pOptionsArray[dwFeatureIndex].ubNext == NULL_OPTSELECT);
  2865. //
  2866. // At this point, we found a valid setting for the feature.
  2867. //
  2868. if (pCurrentOut && (cbRemain >= (INT)(cbFeatureKeySize + cbOptionKeySize)))
  2869. {
  2870. CopyMemory(pCurrentOut, pszFeature, cbFeatureKeySize);
  2871. pCurrentOut += cbFeatureKeySize;
  2872. CopyMemory(pCurrentOut, pszOption, cbOptionKeySize);
  2873. pCurrentOut += cbOptionKeySize;
  2874. }
  2875. cbRemain -= (cbFeatureKeySize + cbOptionKeySize);
  2876. cbNeeded += cbFeatureKeySize + cbOptionKeySize;
  2877. }
  2878. next_feature:
  2879. pszFeature += cbFeatureKeySize;
  2880. }
  2881. //
  2882. // remember the last NUL terminator for the MULTI_SZ output string
  2883. //
  2884. cbRemain--;
  2885. cbNeeded++;
  2886. if (pcbNeeded)
  2887. {
  2888. *pcbNeeded = cbNeeded;
  2889. }
  2890. if (!pCurrentOut || cbRemain < 0)
  2891. {
  2892. hr = E_OUTOFMEMORY;
  2893. goto exit;
  2894. }
  2895. *pCurrentOut = NUL;
  2896. hr = S_OK;
  2897. exit:
  2898. MemFree(pmszFeatureList);
  2899. return hr;
  2900. }