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.

814 lines
19 KiB

  1. /*++
  2. Copyright (c) 1990-2003 Microsoft Corporation
  3. Module Name:
  4. devcaps.c
  5. Abstract:
  6. This module contains API function DrvDeviceCapabilities and other support
  7. functions
  8. Author:
  9. 02-Dec-1993 Thu 16:49:08 created
  10. 22-Mar-1994 Tue 13:00:04 updated
  11. Update RESOLUTION caps so it return as not supported, this way the
  12. application will not used to setup the DMRES_xxx fields
  13. [Environment:]
  14. GDI Device Driver - Plotter.
  15. [Notes:]
  16. Revision History:
  17. --*/
  18. #include "precomp.h"
  19. #pragma hdrstop
  20. #define DBG_PLOTFILENAME DbgDevCaps
  21. extern HMODULE hPlotUIModule;
  22. #define DBG_DEVCAPS_0 0x00000001
  23. #define DBG_DEVCAPS_1 0x00000002
  24. DEFINE_DBGVAR(0);
  25. //
  26. // Local defines only used in this module
  27. //
  28. // The following sizes are copied from the Win 3.1 driver. They do not appear
  29. // to be defined in any public place, although it looks like they should be.
  30. //
  31. #define CCHBINNAME 24 // Characters allowed for bin names
  32. #define CCHPAPERNAME 64 // Max length of paper size names
  33. #define DC_SPL_PAPERNAMES 0xFFFF
  34. #define DC_SPL_MEDIAREADY 0xFFFE
  35. #ifdef DBG
  36. LPSTR pDCCaps[] = {
  37. "FIELDS",
  38. "PAPERS",
  39. "PAPERSIZE",
  40. "MINEXTENT",
  41. "MAXEXTENT",
  42. "BINS",
  43. "DUPLEX",
  44. "SIZE",
  45. "EXTRA",
  46. "VERSION",
  47. "DRIVER",
  48. "BINNAMES",
  49. "ENUMRESOLUTIONS",
  50. "FILEDEPENDENCIES",
  51. "TRUETYPE",
  52. "PAPERNAMES",
  53. "ORIENTATION",
  54. "COPIES",
  55. //
  56. // 4.00
  57. //
  58. "BINADJUST",
  59. "EMF_COMPLIANT",
  60. "DATATYPE_PRODUCED",
  61. "COLLATE",
  62. "MANUFACTURER",
  63. "MODEL",
  64. //
  65. // 5.00
  66. //
  67. "PERSONALITY",
  68. "PRINTRATE",
  69. "PRINTRATEUNIT",
  70. "PRINTERMEM",
  71. "MEDIAREADY",
  72. "STAPLE",
  73. "PRINTRATEPPM",
  74. "COLORDEVICE",
  75. "NUP",
  76. "NULL"
  77. };
  78. #endif
  79. INT
  80. CALLBACK
  81. DevCapEnumFormProc(
  82. PFORM_INFO_1 pFI1,
  83. DWORD Index,
  84. PENUMFORMPARAM pEFP
  85. )
  86. /*++
  87. Routine Description:
  88. This is callback function from PlotEnumForm()
  89. Arguments:
  90. pFI1 - pointer to the current FORM_INFO_1 data structure passed
  91. Index - pFI1 index related to the pFI1Base (0 based)
  92. pEFP - Pointer to the EnumFormParam
  93. Return Value:
  94. > 0: Continue enumerate the next
  95. = 0: Stop enumerate, but keep the pFI1Base when return from PlotEnumForms
  96. < 0: Stop enumerate, and free pFI1Base memory
  97. the form enumerate will only the one has FI1F_VALID_SIZE bit set in the
  98. flag field, it also call one more time with pFI1 NULL to give the callback
  99. function a chance to free the memory (by return < 0)
  100. Author:
  101. 03-Dec-1993 Fri 23:00:25 created
  102. 27-Jan-1994 Thu 16:06:00 updated
  103. Fixed the pptOutput which we did not increment the pointer
  104. 12-Jul-1994 Tue 12:47:22 updated
  105. Move paper tray checking into the PlotEnumForms() itselft
  106. Revision History:
  107. --*/
  108. {
  109. #define pwOutput ((WORD *)pEFP->pCurForm)
  110. #define pptOutput ((POINT *)pEFP->pCurForm)
  111. #define pwchOutput ((WCHAR *)pEFP->pCurForm)
  112. #define DeviceCap (pEFP->ReqIndex)
  113. if (!pwOutput) {
  114. PLOTASSERT(0, "DevCapEnumFormProc(DevCaps=%ld) pvOutput=NULL",
  115. pwOutput, DeviceCap);
  116. return(0);
  117. }
  118. if (!pFI1) {
  119. //
  120. // extra call, or no pvOutput, return a -1 to free memory for pFI1Base
  121. // We want to add the custom paper size so that application know we
  122. // supports that
  123. //
  124. switch (DeviceCap) {
  125. case DC_PAPERNAMES:
  126. LoadString(hPlotUIModule,
  127. IDS_USERFORM,
  128. pwchOutput,
  129. CCHPAPERNAME);
  130. PLOTDBG(DBG_DEVCAPS_1, ("!!! Extra FormName = %s", pwchOutput));
  131. break;
  132. case DC_PAPERS:
  133. *pwOutput = (WORD)DMPAPER_USER;
  134. PLOTDBG(DBG_DEVCAPS_1, ("!!! Extra FormID = %ld", *pwOutput));
  135. break;
  136. case DC_PAPERSIZE:
  137. //
  138. // I'm not sure we should return POINT or POINTS structure here, what
  139. // is Window 3.1 do, because at here we return as dmPaperWidth and
  140. // dmPaperLength, these fields only as a SHORT (16 bits), we will do
  141. // win32 documentation said, POINT (32-bit version)
  142. //
  143. //
  144. // Return custom paper sizes as 8.5" x 11"
  145. //
  146. pptOutput->x = (LONG)2159;
  147. pptOutput->y = (LONG)2794;
  148. PLOTDBG(DBG_DEVCAPS_1, ("!!! Extra FormSize = %ld x %ld",
  149. pptOutput->x, pptOutput->y));
  150. break;
  151. }
  152. return(-1);
  153. }
  154. switch (DeviceCap) {
  155. case DC_PAPERNAMES:
  156. case DC_MEDIAREADY:
  157. _WCPYSTR(pwchOutput, pFI1->pName, CCHPAPERNAME);
  158. pwchOutput += CCHPAPERNAME;
  159. break;
  160. case DC_PAPERS:
  161. *pwOutput++ = (WORD)(Index + DMPAPER_FIRST);
  162. break;
  163. case DC_PAPERSIZE:
  164. //
  165. // I'm not sure we should return POINT or POINTS structure here, what
  166. // is Window 3.1 do, because at here we return as dmPaperWidth and
  167. // dmPaperLength, these fields only as a SHORT (16 bits), we will do
  168. // win32 documentation said, POINT (32-bit version)
  169. //
  170. pptOutput->x = (LONG)SPLTODM(pFI1->Size.cx);
  171. pptOutput->y = (LONG)SPLTODM(pFI1->Size.cy);
  172. pptOutput++;
  173. break;
  174. }
  175. return(1);
  176. #undef DeviceCap
  177. #undef pwOutput
  178. #undef pptOutput
  179. #undef pwchOutput
  180. }
  181. DWORD
  182. WINAPI
  183. DrvDeviceCapabilities(
  184. HANDLE hPrinter,
  185. LPWSTR pwDeviceName,
  186. WORD DeviceCap,
  187. VOID *pvOutput,
  188. DEVMODE *pDM
  189. )
  190. /*++
  191. Routine Description:
  192. Arguments:
  193. hPrinter - handle the to specific printer.
  194. pwDeviceName - pointer to the device name
  195. DeviceCap - specific capability to get.
  196. pvOutput - Pointer to the output buffer
  197. pDM - Ponter to the input DEVMODE
  198. Return Value:
  199. DWORD depends on the DeviceCap
  200. Author:
  201. 02-Dec-1993 Thu 16:50:36 created
  202. 05-Jan-1994 Wed 23:35:19 updated
  203. Replace PLOTTER_UNIT_DPI with pPlotGPC->PlotXDPI, pPlotGPC->PlotYDPI,
  204. 06-Jan-1994 Thu 13:10:11 updated
  205. Change RasterDPI always be the resoluton reports back to the apps
  206. Revision History:
  207. --*/
  208. {
  209. #define pbOutput ((BYTE *)pvOutput)
  210. #define psOutput ((SHORT *)pvOutput)
  211. #define pwOutput ((WORD *)pvOutput)
  212. #define pptOutput ((POINT *)pvOutput)
  213. #define pwchOutput ((WCHAR *)pvOutput)
  214. #define pdwOutput ((DWORD *)pvOutput)
  215. #define plOutput ((LONG *)pvOutput)
  216. #define pptsdwRet ((POINTS *)&dwRet)
  217. PPRINTERINFO pPI;
  218. ENUMFORMPARAM EnumFormParam;
  219. DWORD dwRet;
  220. ZeroMemory(&EnumFormParam, sizeof(ENUMFORMPARAM));
  221. //
  222. // The MapPrinter will allocate memory, set default devmode, reading and
  223. // validating the GPC then update from current pritner registry, it also
  224. // will cached the PlotGPC.
  225. //
  226. if (!(pPI = MapPrinter(hPrinter,
  227. (PPLOTDEVMODE)pDM,
  228. NULL,
  229. (DeviceCap == DC_MEDIAREADY) ?
  230. MPF_DEVICEDATA : 0))) {
  231. PLOTERR(("DrvDeviceCapabilities: MapPrinter() failed"));
  232. return(GDI_ERROR);
  233. }
  234. //
  235. // Start checking DeviceCap now, set dwRet to 0 first for anything we do
  236. // not support. We can do return() at any point in this function because
  237. // we use cached PI, and it will get destroy when the this module
  238. // get unloaded.
  239. //
  240. EnumFormParam.cMaxOut = 0x7FFFFFFF;
  241. dwRet = 0;
  242. switch (DeviceCap) {
  243. case DC_BINNAMES:
  244. case DC_BINS:
  245. //
  246. // For current plotter, it always only have ONE bin
  247. //
  248. if (pvOutput) {
  249. if (DeviceCap == DC_BINS) {
  250. *pwOutput = DMBIN_ONLYONE;
  251. } else {
  252. if (pPI->pPlotGPC->Flags & PLOTF_ROLLFEED) {
  253. dwRet = IDS_ROLLFEED;
  254. } else {
  255. dwRet = IDS_MAINFEED;
  256. }
  257. LoadString(hPlotUIModule, dwRet, pwchOutput, CCHBINNAME);
  258. }
  259. }
  260. dwRet = 1;
  261. break;
  262. case DC_COPIES:
  263. dwRet = (DWORD)pPI->pPlotGPC->MaxCopies;
  264. break;
  265. case DC_DRIVER:
  266. dwRet = (DWORD)pPI->PlotDM.dm.dmDriverVersion;
  267. break;
  268. case DC_COLLATE:
  269. case DC_DUPLEX:
  270. //
  271. // plotter now have no duplex support or collation support
  272. //
  273. break;
  274. case DC_ENUMRESOLUTIONS:
  275. //
  276. // We only have one resolution setting which will be RasterXDPI and
  277. // RasterYDPI in the GPC data for the raster able plotter, for pen
  278. // plotter now we returned pPlotGPC->PlotXDPI, pPlotGPC->PlotYDPI
  279. //
  280. // The RasterDPI will be used for raster printer resolution, for pen
  281. // plotter this is the GPC's ideal resolution
  282. //
  283. //
  284. // We will return not supported (dwRet=0) so that application will not
  285. // use this to set the DEVMODE's print quality and use the DMRES_XXXX
  286. // as print qualities which is use by us to send to the plotter
  287. //
  288. //
  289. // 26-Mar-1999 Fri 09:43:38 updated
  290. // We will return one pair of current PlotXDPI, PlotYDPI for DS
  291. //
  292. if (pdwOutput) {
  293. if (pPI->pPlotGPC->Flags & PLOTF_RASTER) {
  294. pdwOutput[0] = (DWORD)pPI->pPlotGPC->RasterXDPI;
  295. pdwOutput[1] = (DWORD)pPI->pPlotGPC->RasterYDPI;
  296. } else {
  297. pdwOutput[0] = (DWORD)pPI->pPlotGPC->PlotXDPI;
  298. pdwOutput[1] = (DWORD)pPI->pPlotGPC->PlotYDPI;
  299. }
  300. }
  301. dwRet = 1;
  302. break;
  303. case DC_EXTRA:
  304. dwRet = (DWORD)pPI->PlotDM.dm.dmDriverExtra;
  305. break;
  306. case DC_FIELDS:
  307. dwRet = (DWORD)pPI->PlotDM.dm.dmFields;
  308. break;
  309. case DC_FILEDEPENDENCIES:
  310. //
  311. // we are supposed to fill in an array of 64 character filenames,
  312. // this will include the DataFileName, HelpFileName and UIFileName
  313. // but, if we are to be of any use, we would need to use the
  314. // fully qualified pathnames, and 64 characters is probably not
  315. // enough
  316. if (pwchOutput) {
  317. *pwchOutput = (WCHAR)0;
  318. }
  319. break;
  320. case DC_MAXEXTENT:
  321. //
  322. // This is real problem, the document said that we return a POINT
  323. // structure but a POINT structure here contains 2 LONGs, so for
  324. // Windows 3.1 compatibility reason we return a POINTS structure, if device have
  325. // variable length paper support then return 0x7fff as Window 3.1
  326. // because a maximum positive number in POINTS is 0x7fff, this number
  327. // will actually only allowed us to support the paper length up to
  328. // 10.75 feet.
  329. //
  330. pptsdwRet->x = SPLTODM(pPI->pPlotGPC->DeviceSize.cx);
  331. if (pPI->pPlotGPC->DeviceSize.cy >= 3276700) {
  332. pptsdwRet->y = 0x7fff; // 10.75" maximum.
  333. } else {
  334. pptsdwRet->y = SPLTODM(pPI->pPlotGPC->DeviceSize.cy);
  335. }
  336. break;
  337. case DC_MINEXTENT:
  338. //
  339. // This is real problem, the document said that we return a POINT
  340. // structure but a POINT structure here contains 2 LONGs, so for Win3.1
  341. // compatibility reason we return a POINTS structure
  342. //
  343. pptsdwRet->x = MIN_DM_FORM_CX;
  344. pptsdwRet->y = MIN_DM_FORM_CY;
  345. break;
  346. case DC_ORIENTATION:
  347. //
  348. // We always rotate the page to the left 90 degree from the user's
  349. // perspective
  350. //
  351. dwRet = 90;
  352. break;
  353. case DC_SPL_PAPERNAMES:
  354. if (!pvOutput) {
  355. PLOTERR(("DrvDeviceCapabilities: Spool's DC_PAPERNAMES, pvOutput=NULL"));
  356. dwRet = (DWORD)GDI_ERROR;
  357. break;
  358. }
  359. EnumFormParam.cMaxOut = pdwOutput[0];
  360. DeviceCap = DC_PAPERNAMES;
  361. //
  362. // Fall through
  363. //
  364. case DC_PAPERNAMES:
  365. case DC_PAPERS:
  366. case DC_PAPERSIZE:
  367. //
  368. // One of the problem here is we can cached the FORM_INFO_1 which
  369. // enum through spooler, because in between calls the data could
  370. // changed, such as someone add/delete form through the printman, so
  371. // at here we always free (LocalAlloc() used in PlotEnumForms) the
  372. // memory afterward
  373. //
  374. EnumFormParam.pPlotDM = &(pPI->PlotDM);
  375. EnumFormParam.pPlotGPC = pPI->pPlotGPC;
  376. EnumFormParam.ReqIndex = DeviceCap;
  377. EnumFormParam.pCurForm = (PFORMSIZE)pvOutput;
  378. if (!PlotEnumForms(hPrinter, DevCapEnumFormProc, &EnumFormParam)) {
  379. PLOTERR(("DrvDeviceCapabilities: PlotEnumForms() failed"));
  380. dwRet = GDI_ERROR;
  381. } else {
  382. dwRet = EnumFormParam.ValidCount;
  383. }
  384. break;
  385. case DC_SIZE:
  386. dwRet = (DWORD)pPI->PlotDM.dm.dmSize;
  387. break;
  388. case DC_TRUETYPE:
  389. //
  390. // For now we do not return anything, because we draw truetype font
  391. // as truetype (ie. line/curve segment), if we eventually doing ATM or
  392. // bitmap truetype download then we will return DCFF_BITMAP but for
  393. // now return 0
  394. //
  395. break;
  396. case DC_VERSION:
  397. dwRet = (DWORD)pPI->PlotDM.dm.dmSpecVersion;
  398. break;
  399. case DC_PERSONALITY:
  400. if (pwchOutput) {
  401. //
  402. // DDK says an array of string buffers, each 32 characters in length.
  403. //
  404. _WCPYSTR(pwchOutput, L"HP-GL/2", 32);
  405. }
  406. dwRet = 1;
  407. break;
  408. case DC_COLORDEVICE:
  409. dwRet = (pPI->pPlotGPC->Flags & PLOTF_COLOR) ? 1 : 0;
  410. break;
  411. case DC_SPL_MEDIAREADY:
  412. if (!pwchOutput) {
  413. PLOTERR(("DrvDeviceCapabilities: Spool's DC_MEDIAREADY, pwchOutput=NULL"));
  414. dwRet = (DWORD)GDI_ERROR;
  415. break;
  416. }
  417. EnumFormParam.cMaxOut = pdwOutput[0];
  418. //
  419. // Fall through for DC_MEDIAREADY
  420. //
  421. case DC_MEDIAREADY:
  422. PLOTDBG(DBG_DEVCAPS_0,
  423. ("DevCaps(DC_MEDIAREADY:pvOut=%p): CurPaper=%ws, %ldx%ld",
  424. pwchOutput, pPI->CurPaper.Name,
  425. pPI->CurPaper.Size.cx, pPI->CurPaper.Size.cy));
  426. if (pPI->CurPaper.Size.cy) {
  427. //
  428. // Non Roll Paper
  429. //
  430. dwRet = 1;
  431. if (pwchOutput) {
  432. if (EnumFormParam.cMaxOut >= 1) {
  433. _WCPYSTR(pwchOutput, pPI->CurPaper.Name, CCHPAPERNAME);
  434. } else {
  435. dwRet = 0;
  436. }
  437. }
  438. } else {
  439. //
  440. // Roll Paper Installed
  441. //
  442. EnumFormParam.pPlotDM = &(pPI->PlotDM);
  443. EnumFormParam.pPlotGPC = pPI->pPlotGPC;
  444. EnumFormParam.ReqIndex = DC_MEDIAREADY;
  445. EnumFormParam.pCurForm = (PFORMSIZE)pvOutput;
  446. if (!PlotEnumForms(hPrinter, DevCapEnumFormProc, &EnumFormParam)) {
  447. PLOTERR(("DrvDeviceCapabilities: PlotEnumForms() failed"));
  448. dwRet = GDI_ERROR;
  449. } else {
  450. //
  451. // Remove Custom paper size
  452. //
  453. dwRet = EnumFormParam.ValidCount - 1;
  454. }
  455. }
  456. break;
  457. case DC_STAPLE:
  458. case DC_NUP:
  459. break;
  460. default:
  461. //
  462. // something is wrong here
  463. //
  464. PLOTERR(("DrvDeviceCapabilities: Invalid DeviceCap (%ld) passed.",
  465. DeviceCap));
  466. dwRet = (DWORD)GDI_ERROR;
  467. }
  468. PLOTDBG(DBG_DEVCAPS_0,
  469. ("DrvDeviceCapabilities: DC_%hs, pvOut=%p, dwRet=%ld",
  470. pDCCaps[DeviceCap-1], (DWORD_PTR)pvOutput, dwRet));
  471. UnMapPrinter(pPI);
  472. return(dwRet);
  473. #undef pbOutput
  474. #undef psOutput
  475. #undef pwOutput
  476. #undef pptOutput
  477. #undef pwchOutput
  478. #undef pdwOutput
  479. #undef plOutput
  480. #undef pptsdwRet
  481. }
  482. DWORD
  483. DrvSplDeviceCaps(
  484. HANDLE hPrinter,
  485. LPWSTR pwDeviceName,
  486. WORD DeviceCap,
  487. VOID *pvOutput,
  488. DWORD cchBuf,
  489. DEVMODE *pDM
  490. )
  491. /*++
  492. Routine Description:
  493. This function supports the querrying of device capabilities.
  494. Arguments:
  495. hPrinter - handle the to specific printer.
  496. pwDeviceName - pointer to the device name
  497. DeviceCap - specific capability to get.
  498. pvOutput - Pointer to the output buffer
  499. cchBuf - Count of character for the pvOutput
  500. pDM - Ponter to the input DEVMODE
  501. Return Value:
  502. DWORD depends on the DeviceCap
  503. Revision History:
  504. --*/
  505. {
  506. switch (DeviceCap) {
  507. case DC_PAPERNAMES:
  508. case DC_MEDIAREADY:
  509. if (pvOutput) {
  510. if (cchBuf >= CCHPAPERNAME) {
  511. DeviceCap = (DeviceCap == DC_PAPERNAMES) ?
  512. DC_SPL_PAPERNAMES :
  513. DC_SPL_MEDIAREADY;
  514. *((LPDWORD)pvOutput) = (DWORD)(cchBuf / CCHPAPERNAME);
  515. PLOTDBG(DBG_DEVCAPS_0,
  516. ("SplDeviceCap: DC_SPL_MEDIAREADY, cchBuf=%ld (%ld)",
  517. cchBuf, *((LPDWORD)pvOutput)));
  518. } else {
  519. return(GDI_ERROR);
  520. }
  521. }
  522. return(DrvDeviceCapabilities(hPrinter,
  523. pwDeviceName,
  524. DeviceCap,
  525. pvOutput,
  526. pDM));
  527. break;
  528. default:
  529. return(GDI_ERROR);
  530. }
  531. }