Source code of Windows XP (NT5)
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.

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