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.

660 lines
17 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. dm.c
  5. Abstract:
  6. Devmode related functions used by the driver UI.
  7. Environment:
  8. Win32 subsystem, DriverUI module, user mode
  9. Revision History:
  10. 02/05/97 -davidx-
  11. Rewrote it to support OEM plugins among other things.
  12. 07/17/96 -amandan-
  13. Created it.
  14. --*/
  15. #include "precomp.h"
  16. //
  17. // This is the devmode version 320 (DM_SPECVERSION)
  18. //
  19. #define DM_SPECVERSION320 0x0320
  20. #define DM_SPECVERSION400 0x0400
  21. #define DM_SPECVERSION401 0x0401
  22. #define DM_SPECVER_BASE DM_SPECVERSION320
  23. #define CCHDEVICENAME320 32
  24. #define CCHFORMNAME320 32
  25. typedef struct _DEVMODE320 {
  26. WCHAR dmDeviceName[CCHDEVICENAME320];
  27. WORD dmSpecVersion;
  28. WORD dmDriverVersion;
  29. WORD dmSize;
  30. WORD dmDriverExtra;
  31. DWORD dmFields;
  32. short dmOrientation;
  33. short dmPaperSize;
  34. short dmPaperLength;
  35. short dmPaperWidth;
  36. short dmScale;
  37. short dmCopies;
  38. short dmDefaultSource;
  39. short dmPrintQuality;
  40. short dmColor;
  41. short dmDuplex;
  42. short dmYResolution;
  43. short dmTTOption;
  44. short dmCollate;
  45. WCHAR dmFormName[CCHFORMNAME320];
  46. WORD dmLogPixels;
  47. DWORD dmBitsPerPel;
  48. DWORD dmPelsWidth;
  49. DWORD dmPelsHeight;
  50. DWORD dmDisplayFlags;
  51. DWORD dmDisplayFrequency;
  52. } DEVMODE320, *PDEVMODE320;
  53. typedef struct _DMEXTRA400 {
  54. DWORD dmICMMethod;
  55. DWORD dmICMIntent;
  56. DWORD dmMediaType;
  57. DWORD dmDitherType;
  58. DWORD dmICCManufacturer;
  59. DWORD dmICCModel;
  60. } DMEXTRA400;
  61. typedef struct _DMEXTRA401 {
  62. DWORD dmPanningWidth;
  63. DWORD dmPanningHeight;
  64. } DMEXTRA401;
  65. #define DM_SIZE320 sizeof(DEVMODE320)
  66. #define DM_SIZE400 (DM_SIZE320 + sizeof(DMEXTRA400))
  67. #define DM_SIZE401 (DM_SIZE400 + sizeof(DMEXTRA401))
  68. VOID
  69. VPatchPublicDevmodeVersion(
  70. IN OUT PDEVMODE pdm
  71. )
  72. /*++
  73. Routine Description:
  74. Patch dmSpecVersion field of the input devmode
  75. based on its dmSize information
  76. Arguments:
  77. pdm - Specifies a devmode to be version-checked
  78. Return Value:
  79. NONE
  80. --*/
  81. {
  82. ASSERT(pdm != NULL);
  83. //
  84. // Check against known devmode sizes
  85. //
  86. switch (pdm->dmSize)
  87. {
  88. case DM_SIZE320:
  89. pdm->dmSpecVersion = DM_SPECVERSION320;
  90. break;
  91. case DM_SIZE400:
  92. pdm->dmSpecVersion = DM_SPECVERSION400;
  93. break;
  94. case DM_SIZE401:
  95. pdm->dmSpecVersion = DM_SPECVERSION401;
  96. break;
  97. }
  98. }
  99. VOID
  100. VSimpleConvertDevmode(
  101. IN PDEVMODE pdmIn,
  102. IN OUT PDEVMODE pdmOut
  103. )
  104. /*++
  105. Routine Description:
  106. Simple-minded devmode conversion function.
  107. Arguments:
  108. pdmIn - Points to an input devmode
  109. pdmOut - Points to an initialized and valid output devmode
  110. Return Value:
  111. NONE
  112. Notes:
  113. This function only relies on values of these 4 fields in pdmOut:
  114. dmSpecVersion
  115. dmDriverVersion
  116. dmSize
  117. dmDriverExtra
  118. All other fields in pdmOut are ignored and zero-filled before
  119. any memory copy occurs.
  120. --*/
  121. {
  122. WORD wSpecVersion, wDriverVersion;
  123. WORD wSize, wDriverExtra;
  124. ASSERT(pdmIn != NULL && pdmOut != NULL);
  125. //
  126. // Copy public devmode fields
  127. //
  128. wSpecVersion = pdmOut->dmSpecVersion;
  129. wDriverVersion = pdmOut->dmDriverVersion;
  130. wSize = pdmOut->dmSize;
  131. wDriverExtra = pdmOut->dmDriverExtra;
  132. ZeroMemory(pdmOut, wSize+wDriverExtra);
  133. CopyMemory(pdmOut, pdmIn, min(wSize, pdmIn->dmSize));
  134. pdmOut->dmSpecVersion = wSpecVersion;
  135. pdmOut->dmDriverVersion = wDriverVersion;
  136. pdmOut->dmSize = wSize;
  137. pdmOut->dmDriverExtra = wDriverExtra;
  138. //
  139. // Copy private devmode fields
  140. //
  141. CopyMemory((PBYTE) pdmOut + pdmOut->dmSize,
  142. (PBYTE) pdmIn + pdmIn->dmSize,
  143. min(wDriverExtra, pdmIn->dmDriverExtra));
  144. VPatchPublicDevmodeVersion(pdmOut);
  145. }
  146. /*++
  147. Routine Name:
  148. VSmartConvertDevmode
  149. Routine Description:
  150. Smart devmode conversion function for CDM_CONVERT. It strictly obeys
  151. the pdmOut's devmode framework (public, fixed-size core private, each
  152. plugin devmode), and do the best to convert data from pdmIn into that
  153. framework. It guarantees that pdmIn's data from a certain section only
  154. goes into the same section in pdmOut, i.e. pdmIn's core private devmode
  155. data won't overrun into pdmOut's plugin devmode section.
  156. Compared with VSimpleConvertDevmode, this function doesn't change the
  157. size of any private devmode section in the original pdmOut. This includes
  158. the sizes of: fixed-size core private devmode and each individual OEM
  159. plugin devmode.
  160. Arguments:
  161. pdmIn - Points to an input devmode
  162. pdmOut - Points to an initialized and valid output devmode
  163. Return Value:
  164. NONE
  165. Note:
  166. These size/version fields are preserved in pdmOut:
  167. dmSpecVersion
  168. dmDriverVersion
  169. dmSize
  170. dmDriverExtra
  171. wSize
  172. wOEMExtra
  173. wVer
  174. each individual OEM plugin's OEM_DMEXTRAHEADER
  175. dwSize
  176. dwSignature
  177. dwVersion
  178. --*/
  179. VOID
  180. VSmartConvertDevmode(
  181. IN PDEVMODE pdmIn,
  182. IN OUT PDEVMODE pdmOut
  183. )
  184. {
  185. PDRIVEREXTRA pdmPrivIn, pdmPrivOut;
  186. WORD wSpecVersion, wDriverVersion;
  187. WORD wSize, wDriverExtra;
  188. WORD wCoreFixIn, wOEMExtraIn;
  189. WORD wCoreFixOut, wOEMExtraOut, wVerOut;
  190. BOOL bMSdm500In = FALSE, bMSdm500Out = FALSE;
  191. ASSERT(pdmIn != NULL && pdmOut != NULL);
  192. //
  193. // First let's determine the version of pdmIn/pdmOut.
  194. //
  195. pdmPrivIn = (PDRIVEREXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdmIn);
  196. pdmPrivOut = (PDRIVEREXTRA)GET_DRIVER_PRIVATE_DEVMODE(pdmOut);
  197. if (pdmIn->dmDriverVersion >= gDriverDMInfo.dmDriverVersion500 &&
  198. pdmIn->dmDriverExtra >= gDriverDMInfo.dmDriverExtra500 &&
  199. pdmPrivIn->dwSignature == gdwDriverDMSignature)
  200. {
  201. wCoreFixIn = pdmPrivIn->wSize;
  202. wOEMExtraIn = pdmPrivIn->wOEMExtra;
  203. if ((wCoreFixIn >= gDriverDMInfo.dmDriverExtra500) &&
  204. ((wCoreFixIn + wOEMExtraIn) <= pdmIn->dmDriverExtra))
  205. {
  206. bMSdm500In = TRUE;
  207. }
  208. }
  209. if (pdmOut->dmDriverVersion >= gDriverDMInfo.dmDriverVersion500 &&
  210. pdmOut->dmDriverExtra >= gDriverDMInfo.dmDriverExtra500 &&
  211. pdmPrivOut->dwSignature == gdwDriverDMSignature)
  212. {
  213. wCoreFixOut = pdmPrivOut->wSize;
  214. wOEMExtraOut = pdmPrivOut->wOEMExtra;
  215. if ((wCoreFixOut >= gDriverDMInfo.dmDriverExtra500) &&
  216. ((wCoreFixOut + wOEMExtraOut) <= pdmOut->dmDriverExtra))
  217. {
  218. wVerOut = pdmPrivOut->wVer;
  219. bMSdm500Out = TRUE;
  220. }
  221. }
  222. if (!bMSdm500In || !bMSdm500Out)
  223. {
  224. //
  225. // For unknown devmode or MS pre-v5 devmode, there is no
  226. // complexity caused by plugin devmodes, so we will just
  227. // call the simple convert function.
  228. //
  229. VSimpleConvertDevmode(pdmIn, pdmOut);
  230. return;
  231. }
  232. //
  233. // Copy public devmode fields
  234. //
  235. wSpecVersion = pdmOut->dmSpecVersion;
  236. wDriverVersion = pdmOut->dmDriverVersion;
  237. wSize = pdmOut->dmSize;
  238. wDriverExtra = pdmOut->dmDriverExtra;
  239. ZeroMemory(pdmOut, wSize);
  240. CopyMemory(pdmOut, pdmIn, min(wSize, pdmIn->dmSize));
  241. pdmOut->dmSpecVersion = wSpecVersion;
  242. pdmOut->dmDriverVersion = wDriverVersion;
  243. pdmOut->dmSize = wSize;
  244. pdmOut->dmDriverExtra = wDriverExtra;
  245. VPatchPublicDevmodeVersion(pdmOut);
  246. //
  247. // Copy private devmode fields section by section
  248. //
  249. // 1. First copy the fixed-size core section
  250. //
  251. ZeroMemory(pdmPrivOut, wCoreFixOut);
  252. CopyMemory(pdmPrivOut, pdmPrivIn, min(wCoreFixIn, wCoreFixOut));
  253. //
  254. // Restore the size/version fields in core private devmode of pdmOut
  255. //
  256. pdmPrivOut->wSize = wCoreFixOut;
  257. pdmPrivOut->wOEMExtra = wOEMExtraOut;
  258. pdmPrivOut->wVer = wVerOut;
  259. //
  260. // 2. Then copy any OEM plugin devmodes
  261. //
  262. // If pdmOut has no plugin devmodes, then we have no room to copy pdmIn's.
  263. //
  264. // If pdmIn has no plugin devmode, then we have nothing to copy, so we will
  265. // just leave pdmOut's unchanged.
  266. //
  267. // So we only have work to do if both pdmIn and pdmOut have plugin devmodes.
  268. //
  269. if (wOEMExtraIn > 0 && wOEMExtraOut > 0)
  270. {
  271. POEM_DMEXTRAHEADER pOemDMIn, pOemDMOut;
  272. pOemDMIn = (POEM_DMEXTRAHEADER) ((PBYTE)pdmPrivIn + wCoreFixIn);
  273. pOemDMOut = (POEM_DMEXTRAHEADER) ((PBYTE)pdmPrivOut + wCoreFixOut);
  274. //
  275. // Make sure both in and out plugin devmodes blocks are valid before
  276. // we do the conversion. Otherwise, we will leave pdmOut plugin devmodes
  277. // unchanged.
  278. //
  279. if (bIsValidPluginDevmodes(pOemDMIn, (LONG)wOEMExtraIn) &&
  280. bIsValidPluginDevmodes(pOemDMOut, (LONG)wOEMExtraOut))
  281. {
  282. LONG cbInSize = (LONG)wOEMExtraIn;
  283. LONG cbOutSize = (LONG)wOEMExtraOut;
  284. while (cbInSize > 0 && cbOutSize > 0)
  285. {
  286. OEM_DMEXTRAHEADER OemDMHdrIn, OemDMHdrOut;
  287. //
  288. // Copy headers into local buffers
  289. //
  290. CopyMemory(&OemDMHdrIn, pOemDMIn, sizeof(OEM_DMEXTRAHEADER));
  291. CopyMemory(&OemDMHdrOut, pOemDMOut, sizeof(OEM_DMEXTRAHEADER));
  292. if (OemDMHdrIn.dwSize > sizeof(OEM_DMEXTRAHEADER) &&
  293. OemDMHdrOut.dwSize > sizeof(OEM_DMEXTRAHEADER))
  294. {
  295. //
  296. // Zero-fill, then copy over the plugin devmode portion after
  297. // the header structure. Notice that the header structure in
  298. // pOemDMOut is unchanged.
  299. //
  300. ZeroMemory((PBYTE)pOemDMOut + sizeof(OEM_DMEXTRAHEADER),
  301. OemDMHdrOut.dwSize - sizeof(OEM_DMEXTRAHEADER));
  302. CopyMemory((PBYTE)pOemDMOut + sizeof(OEM_DMEXTRAHEADER),
  303. (PBYTE)pOemDMIn + sizeof(OEM_DMEXTRAHEADER),
  304. min(OemDMHdrOut.dwSize - sizeof(OEM_DMEXTRAHEADER),
  305. OemDMHdrIn.dwSize - sizeof(OEM_DMEXTRAHEADER)));
  306. }
  307. cbInSize -= OemDMHdrIn.dwSize;
  308. pOemDMIn = (POEM_DMEXTRAHEADER) ((PBYTE)pOemDMIn + OemDMHdrIn.dwSize);
  309. cbOutSize -= OemDMHdrOut.dwSize;
  310. pOemDMOut = (POEM_DMEXTRAHEADER) ((PBYTE)pOemDMOut + OemDMHdrOut.dwSize);
  311. }
  312. }
  313. }
  314. }
  315. BOOL
  316. BConvertDevmodeOut(
  317. IN PDEVMODE pdmSrc,
  318. IN PDEVMODE pdmIn,
  319. OUT PDEVMODE pdmOut
  320. )
  321. /*++
  322. Routine Description:
  323. This function copy a source devmode to an output devmode buffer.
  324. It should be called by the driver just before the driver returns
  325. to the caller of DrvDocumentPropertySheets.
  326. Arguments:
  327. pdmSrc - pointer to current version of src DEVMODE
  328. pdmIn - pointer to input devmode passed in by the app
  329. pdmOut - pointer to output buffer passed in by the app
  330. Return Value:
  331. TRUE for success
  332. FALSE for failure.
  333. Note:
  334. pdmOut is only the output buffer allocated by the application. It
  335. doesn't necessarily contain any valid devmode content, so we should
  336. not look at any of its fields.
  337. --*/
  338. {
  339. if (pdmOut == NULL)
  340. {
  341. RIP(("Output buffer is NULL.\n"));
  342. return FALSE;
  343. }
  344. //
  345. // Without an input devmode, we'll have to assume the output
  346. // devmode is big enough to hold our current devmode.
  347. //
  348. if (pdmIn == NULL)
  349. {
  350. CopyMemory(pdmOut, pdmSrc, pdmSrc->dmSize + pdmSrc->dmDriverExtra);
  351. return TRUE;
  352. }
  353. //
  354. // If an input devmode is provided, we make sure we don't copy
  355. // anything larger than the input devmode to the output devmode buffer.
  356. // So the private devmode size dmDriverExtra of pdmOut can only shrink
  357. // (when Src private devmode size is smaller), but it will never grow.
  358. //
  359. // This is really dumb because we may end up chopping off tail end of
  360. // public and private devmode fields. But it's neccesary to work with
  361. // ill-behaving apps out there.
  362. //
  363. if (pdmIn->dmSize < pdmSrc->dmSize)
  364. {
  365. pdmOut->dmSpecVersion = pdmIn->dmSpecVersion;
  366. pdmOut->dmSize = pdmIn->dmSize;
  367. }
  368. else
  369. {
  370. pdmOut->dmSpecVersion = pdmSrc->dmSpecVersion;
  371. pdmOut->dmSize = pdmSrc->dmSize;
  372. }
  373. if (pdmIn->dmDriverExtra < pdmSrc->dmDriverExtra)
  374. {
  375. pdmOut->dmDriverVersion = pdmIn->dmDriverVersion;
  376. pdmOut->dmDriverExtra = pdmIn->dmDriverExtra;
  377. }
  378. else
  379. {
  380. pdmOut->dmDriverVersion = pdmSrc->dmDriverVersion;
  381. pdmOut->dmDriverExtra = pdmSrc->dmDriverExtra;
  382. }
  383. VSimpleConvertDevmode(pdmSrc, pdmOut);
  384. return TRUE;
  385. }
  386. BOOL
  387. DrvConvertDevMode(
  388. LPTSTR pPrinterName,
  389. PDEVMODE pdmIn,
  390. PDEVMODE pdmOut,
  391. PLONG pcbNeeded,
  392. DWORD fMode
  393. )
  394. /*++
  395. Routine Description:
  396. This function convert the devmode from previous version.
  397. Arguments:
  398. pPrinterName - pointer to printer name
  399. pdmIn - input devmode
  400. pdmOut - output devmode
  401. pcbNeeded - size of output buffer on input
  402. size of output devmode on output
  403. fMode - specifies functions to perform
  404. Return Value:
  405. TRUE for success and FALSE for failure
  406. --*/
  407. {
  408. PCOMMONINFO pci;
  409. DWORD dwSize, dwError;
  410. VERBOSE(("DrvConvertDevMode: fMode = 0x%x\n", fMode));
  411. //
  412. // Sanity check: make sure pcbNeeded parameter is not NULL
  413. //
  414. if (pcbNeeded == NULL)
  415. {
  416. RIP(("pcbNeeded is NULL.\n"));
  417. SetLastError(ERROR_INVALID_PARAMETER);
  418. return FALSE;
  419. }
  420. switch (fMode)
  421. {
  422. case CDM_CONVERT:
  423. //
  424. // Convert input devmode to output devmode
  425. // Note: OEM plugins are not involved here because
  426. // they can only convert input devmode to current
  427. // version, not between any versions.
  428. //
  429. if (pdmIn == NULL || pdmOut == NULL ||
  430. *pcbNeeded < pdmOut->dmSize + pdmOut->dmDriverExtra)
  431. {
  432. break;
  433. }
  434. VSmartConvertDevmode(pdmIn, pdmOut);
  435. *pcbNeeded = pdmOut->dmSize + pdmOut->dmDriverExtra;
  436. return TRUE;
  437. case CDM_CONVERT351:
  438. //
  439. // Convert input devmode to 3.51 version devmode
  440. // First check if the caller provided buffer is large enough
  441. //
  442. dwSize = DM_SIZE320 + gDriverDMInfo.dmDriverExtra351;
  443. if (*pcbNeeded < (LONG) dwSize || pdmOut == NULL)
  444. {
  445. *pcbNeeded = dwSize;
  446. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  447. return FALSE;
  448. }
  449. //
  450. // Do the conversion from input devmode to 3.51 devmode
  451. //
  452. pdmOut->dmSpecVersion = DM_SPECVERSION320;
  453. pdmOut->dmSize = DM_SIZE320;
  454. pdmOut->dmDriverVersion = gDriverDMInfo.dmDriverVersion351;
  455. pdmOut->dmDriverExtra = gDriverDMInfo.dmDriverExtra351;
  456. VSimpleConvertDevmode(pdmIn, pdmOut);
  457. *pcbNeeded = dwSize;
  458. return TRUE;
  459. case CDM_DRIVER_DEFAULT:
  460. //
  461. // Get the driver default devmode.
  462. // We need to open a handle to the printer
  463. // and then load basic driver information.
  464. //
  465. dwError = ERROR_GEN_FAILURE;
  466. pci = PLoadCommonInfo(NULL,
  467. pPrinterName,
  468. FLAG_OPENPRINTER_NORMAL|FLAG_OPEN_CONDITIONAL);
  469. if (pci && BCalcTotalOEMDMSize(pci->hPrinter, pci->pOemPlugins, &dwSize))
  470. {
  471. dwSize += sizeof(DEVMODE) + gDriverDMInfo.dmDriverExtra;
  472. //
  473. // Check if the output buffer is big enough
  474. //
  475. if (*pcbNeeded < (LONG) dwSize || pdmOut == NULL)
  476. dwError = ERROR_INSUFFICIENT_BUFFER;
  477. else if (BFillCommonInfoDevmode(pci, NULL, NULL))
  478. {
  479. //
  480. // Get the driver default devmode and
  481. // copy it to the output buffer
  482. //
  483. CopyMemory(pdmOut, pci->pdm, dwSize);
  484. dwError = NO_ERROR;
  485. }
  486. *pcbNeeded = dwSize;
  487. }
  488. VFreeCommonInfo(pci);
  489. SetLastError(dwError);
  490. return (dwError == NO_ERROR);
  491. default:
  492. ERR(("Invalid fMode in DrvConvertDevMode: %d\n", fMode));
  493. break;
  494. }
  495. SetLastError(ERROR_INVALID_PARAMETER);
  496. return FALSE;
  497. }