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.

1503 lines
36 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. devcaps.c
  5. Abstract:
  6. This file handles the DrvDeviceCapabilities spooler API.
  7. Environment:
  8. Win32 subsystem, DriverUI module, user mode
  9. Revision History:
  10. 02/13/97 -davidx-
  11. Implement OEM plugin support.
  12. 02/10/97 -davidx-
  13. Consistent handling of common printer info.
  14. 02/04/97 -davidx-
  15. Reorganize driver UI to separate ps and uni DLLs.
  16. 07/17/96 -amandan-
  17. Created it.
  18. --*/
  19. #include "precomp.h"
  20. DWORD
  21. DwDeviceCapabilities(
  22. HANDLE hPrinter,
  23. PWSTR pDeviceName,
  24. WORD wCapability,
  25. PVOID pOutput,
  26. LONG cchBufSize,
  27. PDEVMODE pdmSrc
  28. )
  29. /*++
  30. Routine Description:
  31. This function support the querrying of device capabilities
  32. It gets the binary data (UIINFO) from the parser and return
  33. the requested capability to the caller.
  34. Arguments:
  35. hPrinter handle to printer object
  36. pDeviceName pointer to device name
  37. wCapability specifies the requested capability
  38. pOutput pointer to output buffer
  39. cchBufSize Size of output buffer in number of characters
  40. pdmSrc pointer to input devmode
  41. Return Value:
  42. The capabilities supported and relevant information in pOutput
  43. --*/
  44. {
  45. DWORD dwOld,dwDrv,dwRet = GDI_ERROR;
  46. PDEVMODE pdm;
  47. PCOMMONINFO pci;
  48. FORM_TRAY_TABLE pFormTrayTable;
  49. PFN_OEMDeviceCapabilities pfnOEMDeviceCapabilities;
  50. BOOL bEMFSpooling, bNup;
  51. #if defined(ADOBE) && defined(PSCRIPT)
  52. PDEVMODE pdmPrinter = NULL;
  53. PPRINTER_INFO_2 pPrinterInfo2 = NULL;
  54. #endif // ADOBE && PSCRIPT
  55. //
  56. // Load basic printer info
  57. // Process devmode information: driver default + input devmode
  58. // Fix up options array with public devmode information
  59. // Get an updated printer description data instance
  60. //
  61. #if defined(ADOBE) && defined(PSCRIPT)
  62. if (!(pci = PLoadCommonInfo(hPrinter, pDeviceName, 0)))
  63. {
  64. goto devcaps_exit;
  65. }
  66. //
  67. // Fix bug #25547: PS custom paper size problem with Word.
  68. // Word is calling DeviceCapabilities with pdmSrc=NULL. The fix
  69. // is limited to the cases of PS driver and NULL pdmSrc in order
  70. // to minimize possible app-compat problems.
  71. //
  72. if (pdmSrc == NULL)
  73. {
  74. if (!(pPrinterInfo2 = MyGetPrinter(pci->hPrinter, 2)))
  75. {
  76. goto devcaps_exit;
  77. }
  78. pdmPrinter = pPrinterInfo2->pDevMode;
  79. }
  80. if (
  81. #ifndef WINNT_40
  82. ! ( (wCapability != DC_PRINTERMEM &&
  83. wCapability != DC_DUPLEX &&
  84. wCapability != DC_COLLATE &&
  85. wCapability != DC_STAPLE)||
  86. (BFillCommonInfoPrinterData(pci)) ) ||
  87. #endif
  88. ! BFillCommonInfoDevmode(pci, (pdmSrc == NULL) ? pdmPrinter : NULL, pdmSrc) ||
  89. ! BCombineCommonInfoOptionsArray(pci))
  90. {
  91. goto devcaps_exit;
  92. }
  93. #else
  94. if (! (pci = PLoadCommonInfo(hPrinter, pDeviceName, 0)) ||
  95. #ifndef WINNT_40
  96. ! ( (wCapability != DC_PRINTERMEM &&
  97. wCapability != DC_DUPLEX &&
  98. wCapability != DC_COLLATE &&
  99. wCapability != DC_STAPLE)||
  100. (BFillCommonInfoPrinterData(pci)) ) ||
  101. #endif
  102. ! BFillCommonInfoDevmode(pci, NULL, pdmSrc) ||
  103. ! BCombineCommonInfoOptionsArray(pci))
  104. {
  105. goto devcaps_exit;
  106. }
  107. #endif // ADOBE && PSCRIPT
  108. VFixOptionsArrayWithDevmode(pci);
  109. (VOID) ResolveUIConflicts(pci->pRawData,
  110. pci->pCombinedOptions,
  111. MAX_COMBINED_OPTIONS,
  112. MODE_DOCUMENT_STICKY);
  113. VOptionsToDevmodeFields(pci, TRUE);
  114. if (! BUpdateUIInfo(pci))
  115. goto devcaps_exit;
  116. pdm = pci->pdm;
  117. //
  118. // Get spooler EMF cap so that we can report COLLATE and COPIES correctly
  119. //
  120. VGetSpoolerEmfCaps(pci->hPrinter, &bNup, &bEMFSpooling, 0, NULL);
  121. switch (wCapability)
  122. {
  123. case DC_VERSION:
  124. dwRet = pdm->dmSpecVersion;
  125. break;
  126. case DC_DRIVER:
  127. dwRet = pdm->dmDriverVersion;
  128. break;
  129. case DC_SIZE:
  130. dwRet = pdm->dmSize;
  131. break;
  132. case DC_EXTRA:
  133. dwRet = pdm->dmDriverExtra;
  134. break;
  135. case DC_FIELDS:
  136. dwRet = pdm->dmFields;
  137. break;
  138. case DC_FILEDEPENDENCIES:
  139. if (pOutput != NULL)
  140. *((PWSTR) pOutput) = NUL;
  141. dwRet = 0;
  142. break;
  143. case DC_COPIES:
  144. if (bEMFSpooling && ISSET_MFSPOOL_FLAG(pci->pdmPrivate))
  145. dwRet = max(MAX_COPIES, (SHORT)pci->pUIInfo->dwMaxCopies);
  146. else
  147. dwRet = pci->pUIInfo->dwMaxCopies;
  148. break;
  149. case DC_DUPLEX:
  150. dwRet = SUPPORTS_DUPLEX(pci) ? 1: 0;
  151. break;
  152. case DC_TRUETYPE:
  153. if (! (pdm->dmFields & DM_TTOPTION))
  154. dwRet = 0;
  155. else
  156. dwRet = _DwGetFontCap(pci->pUIInfo);
  157. break;
  158. case DC_ORIENTATION:
  159. dwRet = _DwGetOrientationAngle(pci->pUIInfo, pdm);
  160. break;
  161. case DC_PAPERNAMES:
  162. dwRet = DwEnumPaperSizes(pci, pOutput, NULL, NULL, NULL, cchBufSize);
  163. break;
  164. case DC_PAPERS:
  165. dwRet = DwEnumPaperSizes(pci, NULL, pOutput, NULL, NULL, cchBufSize);
  166. break;
  167. case DC_PAPERSIZE:
  168. dwRet = DwEnumPaperSizes(pci, NULL, NULL, pOutput, NULL, cchBufSize);
  169. break;
  170. case DC_MINEXTENT:
  171. case DC_MAXEXTENT:
  172. dwRet = DwCalcMinMaxExtent(pci, pOutput, wCapability);
  173. break;
  174. case DC_BINNAMES:
  175. dwRet = DwEnumBinNames(pci, pOutput);
  176. break;
  177. case DC_BINS:
  178. dwRet = DwEnumBins(pci, pOutput);
  179. break;
  180. case DC_ENUMRESOLUTIONS:
  181. dwRet = DwEnumResolutions( pci, pOutput);
  182. break;
  183. case DC_COLLATE:
  184. if (bEMFSpooling && ISSET_MFSPOOL_FLAG(pci->pdmPrivate))
  185. dwRet = DRIVER_SUPPORTS_COLLATE(pci);
  186. else
  187. dwRet = PRINTER_SUPPORTS_COLLATE(pci);
  188. break;
  189. //
  190. // Following device capabilities are not available on NT4
  191. //
  192. #ifndef WINNT_40
  193. case DC_COLORDEVICE:
  194. dwRet = IS_COLOR_DEVICE(pci->pUIInfo) ? 1 : 0;
  195. break;
  196. case DC_NUP:
  197. dwRet = DwEnumNupOptions(pci, pOutput);
  198. break;
  199. case DC_PERSONALITY:
  200. dwRet = _DwEnumPersonalities(pci, pOutput);
  201. break;
  202. case DC_PRINTRATE:
  203. if ((dwRet = pci->pUIInfo->dwPrintRate) == 0)
  204. dwRet = GDI_ERROR;
  205. break;
  206. case DC_PRINTRATEUNIT:
  207. if ((dwRet = pci->pUIInfo->dwPrintRateUnit) == 0)
  208. dwRet = GDI_ERROR;
  209. break;
  210. case DC_PRINTRATEPPM:
  211. if ((dwRet = pci->pUIInfo->dwPrintRatePPM) == 0)
  212. dwRet = GDI_ERROR;
  213. break;
  214. case DC_PRINTERMEM:
  215. dwRet = DwGetAvailablePrinterMem(pci);
  216. break;
  217. case DC_MEDIAREADY:
  218. //
  219. // Get current form-tray assignment table
  220. //
  221. if (pFormTrayTable = PGetFormTrayTable(pci->hPrinter, NULL))
  222. {
  223. PWSTR pwstr;
  224. //
  225. // Get list of currently assigned forms.
  226. // Notice that DwEnumMediaReady returns currently
  227. // form names in place of the original form-tray table.
  228. //
  229. dwRet = DwEnumMediaReady(pFormTrayTable, NULL);
  230. if (dwRet > 0 && pOutput != NULL)
  231. {
  232. DWORD dwCount;
  233. pwstr = pFormTrayTable;
  234. dwCount = 0;
  235. while (*pwstr)
  236. {
  237. if ((cchBufSize == UNUSED_PARAM) ||
  238. (cchBufSize >= CCHPAPERNAME))
  239. {
  240. CopyString(pOutput, pwstr, CCHPAPERNAME);
  241. pOutput = (PWSTR) pOutput + CCHPAPERNAME;
  242. pwstr += wcslen(pwstr) + 1;
  243. if (cchBufSize != UNUSED_PARAM)
  244. {
  245. cchBufSize -= CCHPAPERNAME;
  246. }
  247. dwCount++;
  248. }
  249. else
  250. {
  251. //
  252. // Output buffer is not big enough to hold more form names,
  253. // so we will just return the number of forms we have filled
  254. // into the output buffer so far.
  255. //
  256. break;
  257. }
  258. }
  259. dwRet = dwCount;
  260. }
  261. MemFree(pFormTrayTable);
  262. }
  263. else
  264. {
  265. PCWSTR pwstrDefault = IsMetricCountry() ? A4_FORMNAME : LETTER_FORMNAME;
  266. dwRet = 1;
  267. if (pOutput)
  268. {
  269. if ((cchBufSize == UNUSED_PARAM) ||
  270. (cchBufSize >= CCHPAPERNAME))
  271. {
  272. CopyString(pOutput, pwstrDefault, CCHPAPERNAME);
  273. }
  274. else
  275. {
  276. //
  277. // Output buffer is not big enough to hold CCHPAPERNAME WCHARs.
  278. //
  279. dwRet = 0;
  280. }
  281. }
  282. }
  283. break;
  284. case DC_STAPLE:
  285. dwRet = _BSupportStapling(pci);
  286. break;
  287. case DC_MEDIATYPENAMES:
  288. dwRet = DwEnumMediaTypes(pci, pOutput, NULL);
  289. break;
  290. case DC_MEDIATYPES:
  291. dwRet = DwEnumMediaTypes(pci, NULL, pOutput);
  292. break;
  293. #endif // !WINNT_40
  294. default:
  295. SetLastError(ERROR_NOT_SUPPORTED);
  296. break;
  297. }
  298. //
  299. // Call OEMDeviceCapabilities entrypoint for each plugin.
  300. // If dwRet is GDI_ERROR at this point, it means the system driver
  301. // doesn't support the requested device capability or an error
  302. // prevented the system driver from handling it.
  303. //
  304. dwDrv = dwRet;
  305. FOREACH_OEMPLUGIN_LOOP(pci)
  306. dwOld = dwRet;
  307. if (HAS_COM_INTERFACE(pOemEntry))
  308. {
  309. if (HComOEMDeviceCapabilities(
  310. pOemEntry,
  311. &pci->oemuiobj,
  312. hPrinter,
  313. pDeviceName,
  314. wCapability,
  315. pOutput,
  316. pdm,
  317. pOemEntry->pOEMDM,
  318. dwOld,
  319. &dwRet) == E_NOTIMPL)
  320. continue;
  321. }
  322. else
  323. {
  324. if (pfnOEMDeviceCapabilities = GET_OEM_ENTRYPOINT(pOemEntry, OEMDeviceCapabilities))
  325. {
  326. dwRet = pfnOEMDeviceCapabilities(
  327. &pci->oemuiobj,
  328. hPrinter,
  329. pDeviceName,
  330. wCapability,
  331. pOutput,
  332. pdm,
  333. pOemEntry->pOEMDM,
  334. dwOld);
  335. }
  336. }
  337. if (dwRet == GDI_ERROR && dwOld != GDI_ERROR)
  338. {
  339. ERR(("OEMDeviceCapabilities failed for '%ws': %d\n",
  340. CURRENT_OEM_MODULE_NAME(pOemEntry),
  341. GetLastError()));
  342. }
  343. END_OEMPLUGIN_LOOP
  344. //
  345. // The flaw of this API is there is no size associated with the input buffer.
  346. // We have to assume that the app is doing the right thing and allocate enough
  347. // buffer to hold our values. However, the values can change if the OEM plugins
  348. // choose to change the value. We have no way of determine that.
  349. // To err on the safe side, we will always ask the app to allocate the larger
  350. // of the two values (Unidrv and OEM). When asked the second time to fill out
  351. // the buffer, OEM can return the correct values.
  352. //
  353. if ((pOutput == NULL && dwRet != GDI_ERROR &&
  354. dwDrv !=GDI_ERROR && dwRet < dwDrv) &&
  355. (wCapability == DC_PAPERNAMES || wCapability == DC_PAPERS ||
  356. wCapability == DC_PAPERSIZE || wCapability == DC_BINNAMES ||
  357. wCapability == DC_BINS ||
  358. #ifndef WINNT_40
  359. wCapability == DC_NUP || wCapability == DC_PERSONALITY ||
  360. wCapability == DC_MEDIAREADY || wCapability == DC_MEDIATYPENAMES ||
  361. wCapability == DC_MEDIATYPES ||
  362. #endif
  363. wCapability == DC_ENUMRESOLUTIONS) )
  364. {
  365. //
  366. // The size returned by OEM is smaller than what Unidrv needs, so modifies it
  367. //
  368. if (dwRet == 0)
  369. dwRet = GDI_ERROR;
  370. else
  371. dwRet = dwDrv;
  372. }
  373. devcaps_exit:
  374. if (dwRet == GDI_ERROR)
  375. TERSE(("DrvDeviceCapabilities(%d) failed: %d\n", wCapability, GetLastError()));
  376. #if defined(ADOBE) && defined(PSCRIPT)
  377. if (!pPrinterInfo2)
  378. MemFree(pPrinterInfo2);
  379. #endif // ADOBE && PSCRIPT
  380. VFreeCommonInfo(pci);
  381. return dwRet;
  382. }
  383. DWORD
  384. DrvSplDeviceCaps(
  385. HANDLE hPrinter,
  386. PWSTR pDeviceName,
  387. WORD wCapability,
  388. PVOID pOutput,
  389. DWORD cchBufSize,
  390. PDEVMODE pdmSrc
  391. )
  392. /*++
  393. Routine Description:
  394. This function support the querrying of device capabilities
  395. It gets the binary data (UIINFO) from the parser and return
  396. the requested capability to the caller.
  397. Arguments:
  398. hPrinter handle to printer object
  399. pDeviceName pointer to device name
  400. wCapability specifies the requested capability
  401. pOutput pointer to output buffer
  402. cchBufSize output buffer size in count of chars
  403. pdmSrc pointer to input devmode
  404. Return Value:
  405. The capabilities supported and relevant information in pOutput
  406. --*/
  407. {
  408. switch (wCapability) {
  409. case DC_PAPERNAMES:
  410. #ifndef WINNT_40
  411. case DC_MEDIAREADY:
  412. #endif
  413. return (DwDeviceCapabilities(hPrinter,
  414. pDeviceName,
  415. wCapability,
  416. pOutput,
  417. (LONG)cchBufSize,
  418. pdmSrc));
  419. default:
  420. return GDI_ERROR;
  421. }
  422. }
  423. DWORD
  424. DrvDeviceCapabilities(
  425. HANDLE hPrinter,
  426. PWSTR pDeviceName,
  427. WORD wCapability,
  428. PVOID pOutput,
  429. PDEVMODE pdmSrc
  430. )
  431. /*++
  432. Routine Description:
  433. This function support the querrying of device capabilities
  434. It gets the binary data (UIINFO) from the parser and return
  435. the requested capability to the caller.
  436. Arguments:
  437. hPrinter handle to printer object
  438. pDeviceName pointer to device name
  439. wCapability specifies the requested capability
  440. pOutput pointer to output buffer
  441. pdmSrc pointer to input devmode
  442. Return Value:
  443. The capabilities supported and relevant information in pOutput
  444. --*/
  445. {
  446. return (DwDeviceCapabilities(hPrinter,
  447. pDeviceName,
  448. wCapability,
  449. pOutput,
  450. UNUSED_PARAM,
  451. pdmSrc));
  452. }
  453. DWORD
  454. DwEnumPaperSizes(
  455. PCOMMONINFO pci,
  456. PWSTR pPaperNames,
  457. PWORD pPapers,
  458. PPOINT pPaperSizes,
  459. PWORD pPaperFeatures,
  460. LONG cchPaperNamesBufSize
  461. )
  462. /*++
  463. Routine Description:
  464. This function retrieves a list of supported paper sizes
  465. Arguments:
  466. pci - Points to basic printer information
  467. pForms - List of spooler forms
  468. dwForms - Number of spooler forms
  469. pPaperNames - Buffer for returning supported paper size names
  470. pPapers - Buffer for returning supported paper size indices
  471. pPaperSizes - Buffer for returning supported paper size dimensions
  472. pPaperFeatures - Buffer for returning supported paper size option indices
  473. cchPaperNamesBufSize - Size of buffer holding paper names in characters
  474. Return Value:
  475. Number of paper sizes supported, GDI_ERROR if there is an error.
  476. --*/
  477. {
  478. PFORM_INFO_1 pForms;
  479. DWORD dwCount, dwIndex, dwOptionIndex = 0;
  480. #ifdef UNIDRV
  481. PFEATURE pFeature;
  482. PPAGESIZE pPageSize;
  483. PPAGESIZEEX pPageSizeEx;
  484. #endif
  485. //
  486. // Get the list of spooler forms if we haven't done so already
  487. //
  488. if (pci->pSplForms == NULL)
  489. pci->pSplForms = MyEnumForms(pci->hPrinter, 1, &pci->dwSplForms);
  490. if (pci->pSplForms == NULL)
  491. {
  492. ERR(("No spooler forms.\n"));
  493. return GDI_ERROR;
  494. }
  495. //
  496. // Go through each form in the forms database
  497. //
  498. dwCount = 0;
  499. pForms = pci->pSplForms;
  500. #ifdef UNIDRV
  501. pFeature = GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_PAGESIZE);
  502. #endif
  503. for (dwIndex=0; dwIndex < pci->dwSplForms; dwIndex++, pForms++)
  504. {
  505. //
  506. // If the form is supported on the printer, then
  507. // increment the paper size count and collect
  508. // requested information
  509. //
  510. if (! BFormSupportedOnPrinter(pci, pForms, &dwOptionIndex))
  511. continue;
  512. dwCount++;
  513. //
  514. // Return the size of the form in 0.1mm units.
  515. // The unit used in FORM_INFO_1 is 0.001mm.
  516. // Fill pPaperSizes with the form info supported by the printer
  517. //
  518. if (pPaperSizes)
  519. {
  520. pPaperSizes->x = pForms->Size.cx / DEVMODE_PAPER_UNIT;
  521. pPaperSizes->y = pForms->Size.cy / DEVMODE_PAPER_UNIT;
  522. #ifdef UNIDRV
  523. if (pFeature &&
  524. (pPageSize = PGetIndexedOption(pci->pUIInfo, pFeature, dwOptionIndex)) &&
  525. (pPageSizeEx = OFFSET_TO_POINTER(pci->pInfoHeader, pPageSize->GenericOption.loRenderOffset)) &&
  526. (pPageSizeEx->bRotateSize))
  527. {
  528. LONG lTemp;
  529. lTemp = pPaperSizes->x;
  530. pPaperSizes->x = pPaperSizes->y;
  531. pPaperSizes->y = lTemp;
  532. }
  533. #endif // UNIDRV
  534. pPaperSizes++;
  535. }
  536. //
  537. // Return the formname.
  538. //
  539. if (pPaperNames)
  540. {
  541. if (cchPaperNamesBufSize == UNUSED_PARAM)
  542. {
  543. CopyString(pPaperNames, pForms->pName, CCHPAPERNAME);
  544. pPaperNames += CCHPAPERNAME;
  545. }
  546. else if (cchPaperNamesBufSize >= CCHPAPERNAME)
  547. {
  548. CopyString(pPaperNames, pForms->pName, CCHPAPERNAME);
  549. pPaperNames += CCHPAPERNAME;
  550. cchPaperNamesBufSize -= CCHPAPERNAME;
  551. }
  552. else
  553. {
  554. dwCount--;
  555. break;
  556. }
  557. }
  558. //
  559. // Return one-based index of the form.
  560. //
  561. if (pPapers)
  562. *pPapers++ = (WORD) (dwIndex + DMPAPER_FIRST);
  563. //
  564. // Return page size feature index
  565. //
  566. if (pPaperFeatures)
  567. *pPaperFeatures++ = (WORD) dwOptionIndex;
  568. }
  569. #ifdef PSCRIPT
  570. {
  571. PPPDDATA pPpdData;
  572. PPAGESIZE pPageSize;
  573. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pci->pRawData);
  574. ASSERT(pPpdData != NULL);
  575. if (SUPPORT_FULL_CUSTOMSIZE_FEATURES(pci->pUIInfo, pPpdData) &&
  576. (pPageSize = PGetCustomPageSizeOption(pci->pUIInfo)))
  577. {
  578. ASSERT(pPageSize->dwPaperSizeID == DMPAPER_CUSTOMSIZE);
  579. dwCount++;
  580. if (pPaperSizes)
  581. {
  582. pPaperSizes->x = pci->pdmPrivate->csdata.dwX / DEVMODE_PAPER_UNIT;
  583. pPaperSizes->y = pci->pdmPrivate->csdata.dwY / DEVMODE_PAPER_UNIT;
  584. pPaperSizes++;
  585. }
  586. if (pPaperNames)
  587. {
  588. if (cchPaperNamesBufSize == UNUSED_PARAM)
  589. {
  590. LOAD_STRING_PAGESIZE_NAME(pci, pPageSize, pPaperNames, CCHPAPERNAME);
  591. pPaperNames += CCHPAPERNAME;
  592. }
  593. else if (cchPaperNamesBufSize >= CCHPAPERNAME)
  594. {
  595. LOAD_STRING_PAGESIZE_NAME(pci, pPageSize, pPaperNames, CCHPAPERNAME);
  596. pPaperNames += CCHPAPERNAME;
  597. cchPaperNamesBufSize -= CCHPAPERNAME;
  598. }
  599. else
  600. dwCount--;
  601. }
  602. if (pPapers)
  603. *pPapers++ = DMPAPER_CUSTOMSIZE;
  604. if (pPaperFeatures)
  605. *pPaperFeatures++ = (WORD) pci->pUIInfo->dwCustomSizeOptIndex;
  606. }
  607. }
  608. #endif // PSCRIPT
  609. return dwCount;
  610. }
  611. DWORD
  612. DwCalcMinMaxExtent(
  613. PCOMMONINFO pci,
  614. PPOINT pptOutput,
  615. WORD wCapability
  616. )
  617. /*++
  618. Routine Description:
  619. This function retrieves the min and max paper size.
  620. Arguments:
  621. pci - Points to basic printer information
  622. wCapability - What the caller is interested in:
  623. DC_MAXEXTENT or DC_MINEXTENT
  624. Return Value:
  625. Number of paper sizes supported, GDI_ERROR if there is an error.
  626. --*/
  627. {
  628. PFORM_INFO_1 pForms;
  629. DWORD dwCount, dwLoopCnt, dwOptionIndex;
  630. LONG lMinX, lMinY, lMaxX, lMaxY, lcx, lcy;
  631. #ifdef UNIDRV
  632. PFEATURE pFeature;
  633. PPAGESIZE pPageSize;
  634. PPAGESIZEEX pPageSizeEx;
  635. #endif
  636. //
  637. // Get the list of spooler forms if we haven't done so already
  638. //
  639. if (pci->pSplForms == NULL)
  640. pci->pSplForms = MyEnumForms(pci->hPrinter, 1, &pci->dwSplForms);
  641. if (pci->pSplForms == NULL)
  642. {
  643. ERR(("No spooler forms.\n"));
  644. return GDI_ERROR;
  645. }
  646. //
  647. // Go through each form in the forms database
  648. //
  649. lMinX = lMinY = MAX_LONG;
  650. lMaxX = lMaxY = 0;
  651. dwCount = 0;
  652. pForms = pci->pSplForms;
  653. dwLoopCnt = pci->dwSplForms;
  654. #ifdef UNIDRV
  655. pFeature = GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_PAGESIZE);
  656. #endif
  657. for ( ; dwLoopCnt--; pForms++)
  658. {
  659. //
  660. // If the form is supported on the printer, then
  661. // increment the paper size count and collect
  662. // requested information
  663. //
  664. if (! BFormSupportedOnPrinter(pci, pForms, &dwOptionIndex))
  665. continue;
  666. dwCount++;
  667. lcx = pForms->Size.cx;
  668. lcy = pForms->Size.cy;
  669. #ifdef UNIDRV
  670. //
  671. // Need to swap x, y as we do in DwEnumPaperSizes() if bRotateSize is True.
  672. //
  673. if (pFeature &&
  674. (pPageSize = PGetIndexedOption(pci->pUIInfo, pFeature, dwOptionIndex)) &&
  675. (pPageSizeEx = OFFSET_TO_POINTER(pci->pInfoHeader, pPageSize->GenericOption.loRenderOffset)) &&
  676. (pPageSizeEx->bRotateSize))
  677. {
  678. LONG lTemp;
  679. lTemp = lcx;
  680. lcx = lcy;
  681. lcy = lTemp;
  682. }
  683. #endif // UNIDRV
  684. if (lMinX > lcx)
  685. lMinX = lcx;
  686. if (lMinY > lcy)
  687. lMinY = lcy;
  688. if (lMaxX < lcx)
  689. lMaxX = lcx;
  690. if (lMaxY < lcy)
  691. lMaxY = lcy;
  692. }
  693. #ifdef PSCRIPT
  694. //
  695. // If the printer supports custom page size, we should
  696. // take that into consideration as well.
  697. //
  698. if (SUPPORT_CUSTOMSIZE(pci->pUIInfo))
  699. {
  700. PPPDDATA pPpdData;
  701. pPpdData = GET_DRIVER_INFO_FROM_INFOHEADER((PINFOHEADER) pci->pRawData);
  702. ASSERT(pPpdData != NULL);
  703. if (lMinX > MINCUSTOMPARAM_WIDTH(pPpdData))
  704. lMinX = MINCUSTOMPARAM_WIDTH(pPpdData);
  705. if (lMinY > MINCUSTOMPARAM_HEIGHT(pPpdData))
  706. lMinY = MINCUSTOMPARAM_HEIGHT(pPpdData);
  707. if (lMaxX < MAXCUSTOMPARAM_WIDTH(pPpdData))
  708. lMaxX = MAXCUSTOMPARAM_WIDTH(pPpdData);
  709. if (lMaxY < MAXCUSTOMPARAM_HEIGHT(pPpdData))
  710. lMaxY = MAXCUSTOMPARAM_HEIGHT(pPpdData);
  711. }
  712. #endif // PSCRIPT
  713. //
  714. // Convert from micron to 0.1mm
  715. //
  716. lMinX /= DEVMODE_PAPER_UNIT;
  717. lMinY /= DEVMODE_PAPER_UNIT;
  718. lMaxX /= DEVMODE_PAPER_UNIT;
  719. lMaxY /= DEVMODE_PAPER_UNIT;
  720. //
  721. // Return the result as a POINTS structure
  722. //
  723. if (wCapability == DC_MINEXTENT)
  724. {
  725. lMinX = min(lMinX, 0x7fff);
  726. lMinY = min(lMinY, 0x7fff);
  727. return MAKELONG(lMinX, lMinY);
  728. }
  729. else
  730. {
  731. lMaxX = min(lMaxX, 0x7fff);
  732. lMaxY = min(lMaxY, 0x7fff);
  733. return MAKELONG(lMaxX, lMaxY);
  734. }
  735. }
  736. DWORD
  737. DwEnumBinNames(
  738. PCOMMONINFO pci,
  739. PWSTR pBinNames
  740. )
  741. /*++
  742. Routine Description:
  743. This function retrieves a list of supported paper bins
  744. Arguments:
  745. pci - Points to basic printer information
  746. pBinNames - Buffer for returning paper bin names.
  747. It can be NULL if the caller is only interested
  748. the number of paper bins supported.
  749. Return Value:
  750. Number of paper bins supported.
  751. --*/
  752. {
  753. PFEATURE pFeature;
  754. PINPUTSLOT pInputSlot;
  755. DWORD dwIndex, dwCount = 0;
  756. //
  757. // Go through the list of input slots supported by the printer
  758. //
  759. pFeature = GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_INPUTSLOT);
  760. if ((pFeature != NULL) &&
  761. (dwCount = pFeature->Options.dwCount) > 0 &&
  762. (pBinNames != NULL))
  763. {
  764. for (dwIndex=0; dwIndex < dwCount; dwIndex++)
  765. {
  766. pInputSlot = PGetIndexedOption(pci->pUIInfo, pFeature, dwIndex);
  767. ASSERT(pInputSlot != NULL);
  768. //
  769. // If the first tray is "*UseFormTrayTable", change its
  770. // display name here to be consistent.
  771. //
  772. if (dwIndex == 0 && pInputSlot->dwPaperSourceID == DMBIN_FORMSOURCE)
  773. {
  774. LoadString(ghInstance, IDS_TRAY_FORMSOURCE, pBinNames, CCHBINNAME);
  775. }
  776. else
  777. {
  778. LOAD_STRING_OPTION_NAME(pci, pInputSlot, pBinNames, CCHBINNAME);
  779. }
  780. pBinNames += CCHBINNAME;
  781. }
  782. }
  783. return dwCount;
  784. }
  785. DWORD
  786. DwEnumBins(
  787. PCOMMONINFO pci,
  788. PWORD pBins
  789. )
  790. /*++
  791. Routine Description:
  792. This function retrieves the number of supported paper bins
  793. Arguments:
  794. pci - Points to basic printer information
  795. pBins - Output buffer for returning paper bin indices.
  796. It can be NULL if the caller is only interested
  797. the number of paper bins supported.
  798. Return Value:
  799. Number of paper bins supported.
  800. --*/
  801. {
  802. PFEATURE pFeature;
  803. PINPUTSLOT pInputSlot;
  804. DWORD dwIndex, dwCount = 0;
  805. //
  806. // Go through the list of input slots supported by the printer
  807. //
  808. pFeature = GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_INPUTSLOT);
  809. if ((pFeature != NULL) &&
  810. (dwCount = pFeature->Options.dwCount) > 0 &&
  811. (pBins != NULL))
  812. {
  813. for (dwIndex=0; dwIndex < dwCount; dwIndex++)
  814. {
  815. pInputSlot = PGetIndexedOption(pci->pUIInfo, pFeature, dwIndex);
  816. ASSERT(pInputSlot != NULL);
  817. *pBins++ = (WORD)pInputSlot->dwPaperSourceID;
  818. }
  819. }
  820. return dwCount;
  821. }
  822. DWORD
  823. DwEnumResolutions(
  824. PCOMMONINFO pci,
  825. PLONG pResolutions
  826. )
  827. /*++
  828. Routine Description:
  829. This function retrieves a list of supported resolutions.
  830. Arguments:
  831. pci - Points to basic printer information
  832. pResolutions - Returns information about supported resolutions.
  833. Two numbers are returned for each resolution option:
  834. one for horizontal and the other for vertical.
  835. Note that this can be NULL if the caller is only interested
  836. in the number of resolutions supported.
  837. Return Value:
  838. Number of resolutions supported.
  839. --*/
  840. {
  841. DWORD dwCount, dwIndex;
  842. PFEATURE pFeature;
  843. PRESOLUTION pResOption;
  844. //
  845. // Go throught the list of resolutions supported by the printer
  846. //
  847. pFeature = GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_RESOLUTION);
  848. if (pFeature && pFeature->Options.dwCount > 0)
  849. {
  850. //
  851. // Enumerate all options of the resolution feature
  852. //
  853. dwCount = pFeature->Options.dwCount;
  854. for (dwIndex=0; dwIndex < dwCount; dwIndex++)
  855. {
  856. pResOption = PGetIndexedOption(pci->pUIInfo, pFeature, dwIndex);
  857. ASSERT(pResOption != NULL);
  858. if (pResolutions != NULL)
  859. {
  860. *pResolutions++ = pResOption->iXdpi;
  861. *pResolutions++ = pResOption->iYdpi;
  862. }
  863. }
  864. }
  865. else
  866. {
  867. //
  868. // If no resolution option is available,
  869. // return at least one default resolution
  870. //
  871. dwCount = 1;
  872. if (pResolutions != NULL)
  873. {
  874. pResolutions[0] =
  875. pResolutions[1] = _DwGetDefaultResolution();
  876. }
  877. }
  878. return dwCount;
  879. }
  880. DWORD
  881. DwGetAvailablePrinterMem(
  882. PCOMMONINFO pci
  883. )
  884. /*++
  885. Routine Description:
  886. Find out how much memory is available in the printer
  887. Arguments:
  888. pci - Points to base printer information
  889. Return Value:
  890. Amount of memory available in the printer (in KBytes)
  891. --*/
  892. {
  893. DWORD dwFreeMem;
  894. ASSERT(pci->pPrinterData && pci->pCombinedOptions);
  895. //
  896. // For PSCRIPT, the amount of free memory is stored in
  897. // PRINTERDATA.dwFreeMem field.
  898. //
  899. #ifdef PSCRIPT
  900. dwFreeMem = pci->pPrinterData->dwFreeMem;
  901. #endif
  902. //
  903. // For UNIDRV, we need to find out the currently selected
  904. // option for GID_MEMOPTION feature.
  905. //
  906. #ifdef UNIDRV
  907. {
  908. PFEATURE pFeature;
  909. PMEMOPTION pMemOption;
  910. DWORD dwIndex;
  911. if (! (pFeature = GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_MEMOPTION)))
  912. return GDI_ERROR;
  913. dwIndex = GET_INDEX_FROM_FEATURE(pci->pUIInfo, pFeature);
  914. dwIndex = pci->pCombinedOptions[dwIndex].ubCurOptIndex;
  915. if (! (pMemOption = PGetIndexedOption(pci->pUIInfo, pFeature, dwIndex)))
  916. return GDI_ERROR;
  917. dwFreeMem = pMemOption->dwInstalledMem;
  918. }
  919. #endif
  920. return dwFreeMem / KBYTES;
  921. }
  922. DWORD
  923. DwEnumMediaReady(
  924. FORM_TRAY_TABLE pFormTrayTable,
  925. PDWORD pdwResultSize
  926. )
  927. /*++
  928. Routine Description:
  929. Find the list of forms currently available in the printer
  930. Arguments:
  931. pFormTrayTable - Points to current form-tray assignment table
  932. pdwResultSize - Return the size of the resulting MULTI_SZ (in bytes)
  933. Return Value:
  934. Number of forms currently available
  935. Note:
  936. List of supported form names are returned in place of
  937. the original form-tray assignment table.
  938. Format for form-tray assignment table is:
  939. tray-name form-name
  940. ...
  941. NUL
  942. Returned form names are in the form of:
  943. form-name
  944. ...
  945. NUL
  946. Duplicate form names are filtered out.
  947. --*/
  948. {
  949. PWSTR pwstrOutput, pwstrNext, pwstr;
  950. DWORD dwCount, dwIndex, dwLen;
  951. dwCount = 0;
  952. pwstrNext = pwstrOutput = pFormTrayTable;
  953. //
  954. // Enumerate through each entry of form-tray assignment table
  955. //
  956. while (*pwstrNext)
  957. {
  958. //
  959. // skip tray name field
  960. //
  961. pwstrNext += wcslen(pwstrNext) + 1;
  962. //
  963. // make sure the form name is not a duplicate
  964. //
  965. pwstr = pFormTrayTable;
  966. for (dwIndex=0; dwIndex < dwCount; dwIndex++)
  967. {
  968. if (_wcsicmp(pwstr, pwstrNext) == EQUAL_STRING)
  969. break;
  970. pwstr += wcslen(pwstr) + 1;
  971. }
  972. dwLen = wcslen(pwstrNext) + 1;
  973. if (dwIndex == dwCount)
  974. {
  975. //
  976. // if the form name is not a duplicate, nor Not Available, count it
  977. //
  978. if (*pwstrNext != NUL && *pwstrNext != L'0' && dwLen > 1)
  979. {
  980. MoveMemory(pwstrOutput, pwstrNext, dwLen * sizeof(WCHAR));
  981. pwstrOutput += dwLen;
  982. dwCount++;
  983. }
  984. }
  985. //
  986. // go past the form name field
  987. //
  988. pwstrNext += dwLen;
  989. }
  990. *pwstrOutput++ = NUL;
  991. if (pdwResultSize != NULL)
  992. *pdwResultSize = (DWORD)(pwstrOutput - pFormTrayTable) * sizeof(WCHAR);
  993. return dwCount;
  994. }
  995. DWORD
  996. DwEnumNupOptions(
  997. PCOMMONINFO pci,
  998. PDWORD pdwOutput
  999. )
  1000. /*++
  1001. Routine Description:
  1002. Enumerate the list of supported printer description languages
  1003. Arguments:
  1004. pci - Points to common printer info
  1005. pdwOutput - Points to output buffer
  1006. Return Value:
  1007. Number of N-up options supported
  1008. GDI_ERROR if there is an error
  1009. --*/
  1010. {
  1011. static CONST DWORD adwNupOptions[] = { 1, 2, 4, 6, 9, 16 };
  1012. if (pdwOutput)
  1013. CopyMemory(pdwOutput, adwNupOptions, sizeof(adwNupOptions));
  1014. return sizeof(adwNupOptions) / sizeof(DWORD);
  1015. }
  1016. DWORD
  1017. DwEnumMediaTypes(
  1018. IN PCOMMONINFO pci,
  1019. OUT PTSTR pMediaTypeNames,
  1020. OUT PDWORD pMediaTypes
  1021. )
  1022. /*++
  1023. Routine Description:
  1024. Retrieves the display names and indices of supported media types
  1025. Arguments:
  1026. pci - points to common printer information
  1027. pMediaTypeNames - output buffer for returning supported media type names
  1028. pMediaTypes - output buffer for returning supported media type indices
  1029. (Both pMediaTypeNames and pMediaTypes will be NULL if caller if only
  1030. asking for the number of supported media types.)
  1031. Return Value:
  1032. Number of media types supported.
  1033. --*/
  1034. {
  1035. PFEATURE pFeature;
  1036. DWORD dwIndex, dwCount;
  1037. //
  1038. // This function is used to support both DC_MEDIATYPENAMES and DC_MEDIATYPES.
  1039. // pMediaTypeNames or pMediaTypes should not both be non-NULL.
  1040. //
  1041. ASSERT(pMediaTypeNames == NULL || pMediaTypes == NULL);
  1042. //
  1043. // Go through the list of media types supported by the printer
  1044. //
  1045. pFeature = GET_PREDEFINED_FEATURE(pci->pUIInfo, GID_MEDIATYPE);
  1046. if (pFeature == NULL)
  1047. {
  1048. //
  1049. // Media type feature is not supported by the printer.
  1050. //
  1051. return 0;
  1052. }
  1053. if (pMediaTypeNames == NULL && pMediaTypes == NULL)
  1054. {
  1055. //
  1056. // caller is only asking for the number of supported media types
  1057. //
  1058. return pFeature->Options.dwCount;
  1059. }
  1060. dwCount = 0;
  1061. for (dwIndex = 0; dwIndex < pFeature->Options.dwCount; dwIndex++)
  1062. {
  1063. PMEDIATYPE pMediaType;
  1064. pMediaType = PGetIndexedOption(pci->pUIInfo, pFeature, dwIndex);
  1065. ASSERT(pMediaType != NULL);
  1066. if (pMediaTypeNames)
  1067. {
  1068. if (LOAD_STRING_OPTION_NAME(pci, pMediaType, pMediaTypeNames, CCHMEDIATYPENAME))
  1069. {
  1070. dwCount++;
  1071. pMediaTypeNames += CCHMEDIATYPENAME;
  1072. }
  1073. else
  1074. {
  1075. ERR(("LOAD_STRING_OPTION_NAME failed for MediaType option %d\n", dwIndex));
  1076. }
  1077. }
  1078. else if (pMediaTypes)
  1079. {
  1080. *pMediaTypes++ = pMediaType->dwMediaTypeID;
  1081. dwCount++;
  1082. }
  1083. }
  1084. return dwCount;
  1085. }