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.

506 lines
11 KiB

  1. /*++
  2. Copyright (c) 1990-2003 Microsoft Corporation
  3. Module Name:
  4. devmode.c
  5. Abstract:
  6. This module contains devmode conversion
  7. Development History:
  8. 08-Jun-1995 Thu 13:47:33 created
  9. [Environment:]
  10. GDI printer drivers, user and kernel mode
  11. [Notes:]
  12. Revision History:
  13. 11/09/95
  14. New conversion routines
  15. 09-Feb-1999 Tue 11:15:55 updated
  16. Move from printers\lib directory
  17. --*/
  18. #include "precomp.h"
  19. #pragma hdrstop
  20. //
  21. // This is the devmode version 320 (DM_SPECVERSION)
  22. //
  23. #define DM_SPECVERSION320 0x0320
  24. #define DM_SPECVERSION400 0x0400
  25. #define DM_SPECVERSION401 0x0401
  26. #define DM_SPECVER_BASE DM_SPECVERSION320
  27. //
  28. // size of a device name string
  29. //
  30. #define CCHDEVICENAME320 32
  31. #define CCHFORMNAME320 32
  32. typedef struct _devicemode320A {
  33. BYTE dmDeviceName[CCHDEVICENAME320];
  34. WORD dmSpecVersion;
  35. WORD dmDriverVersion;
  36. WORD dmSize;
  37. WORD dmDriverExtra;
  38. DWORD dmFields;
  39. short dmOrientation;
  40. short dmPaperSize;
  41. short dmPaperLength;
  42. short dmPaperWidth;
  43. short dmScale;
  44. short dmCopies;
  45. short dmDefaultSource;
  46. short dmPrintQuality;
  47. short dmColor;
  48. short dmDuplex;
  49. short dmYResolution;
  50. short dmTTOption;
  51. short dmCollate;
  52. BYTE dmFormName[CCHFORMNAME320];
  53. WORD dmLogPixels;
  54. DWORD dmBitsPerPel;
  55. DWORD dmPelsWidth;
  56. DWORD dmPelsHeight;
  57. DWORD dmDisplayFlags;
  58. DWORD dmDisplayFrequency;
  59. } DEVMODE320A, *PDEVMODE320A, *NPDEVMODE320A, *LPDEVMODE320A;
  60. typedef struct _devicemode320W {
  61. WCHAR dmDeviceName[CCHDEVICENAME320];
  62. WORD dmSpecVersion;
  63. WORD dmDriverVersion;
  64. WORD dmSize;
  65. WORD dmDriverExtra;
  66. DWORD dmFields;
  67. short dmOrientation;
  68. short dmPaperSize;
  69. short dmPaperLength;
  70. short dmPaperWidth;
  71. short dmScale;
  72. short dmCopies;
  73. short dmDefaultSource;
  74. short dmPrintQuality;
  75. short dmColor;
  76. short dmDuplex;
  77. short dmYResolution;
  78. short dmTTOption;
  79. short dmCollate;
  80. WCHAR dmFormName[CCHFORMNAME320];
  81. WORD dmLogPixels;
  82. DWORD dmBitsPerPel;
  83. DWORD dmPelsWidth;
  84. DWORD dmPelsHeight;
  85. DWORD dmDisplayFlags;
  86. DWORD dmDisplayFrequency;
  87. } DEVMODE320W, *PDEVMODE320W, *NPDEVMODE320W, *LPDEVMODE320W;
  88. #ifdef UNICODE
  89. typedef DEVMODE320W DEVMODE320;
  90. typedef PDEVMODE320W PDEVMODE320;
  91. typedef NPDEVMODE320W NPDEVMODE320;
  92. typedef LPDEVMODE320W LPDEVMODE320;
  93. #else
  94. typedef DEVMODE320A DEVMODE320;
  95. typedef PDEVMODE320A PDEVMODE320;
  96. typedef NPDEVMODE320A NPDEVMODE320;
  97. typedef LPDEVMODE320A LPDEVMODE320;
  98. #endif // UNICODE
  99. typedef struct _DMEXTRA400 {
  100. DWORD dmICMMethod;
  101. DWORD dmICMIntent;
  102. DWORD dmMediaType;
  103. DWORD dmDitherType;
  104. DWORD dmICCManufacturer;
  105. DWORD dmICCModel;
  106. } DMEXTRA400;
  107. typedef struct _DMEXTRA401 {
  108. DWORD dmPanningWidth;
  109. DWORD dmPanningHeight;
  110. } DMEXTRA401;
  111. #define DM_SIZE320 sizeof(DEVMODE320)
  112. #define DM_SIZE400 (DM_SIZE320 + sizeof(DMEXTRA400))
  113. #define DM_SIZE401 (DM_SIZE400 + sizeof(DMEXTRA401))
  114. // Current version devmode size - public portion only
  115. #ifdef UNICODE
  116. #define DM_SIZE_CURRENT sizeof(DEVMODEW)
  117. #else
  118. #define DM_SIZE_CURRENT sizeof(DEVMODEA)
  119. #endif
  120. WORD
  121. CheckDevmodeVersion(
  122. PDEVMODE pdm
  123. )
  124. /*++
  125. Routine Description:
  126. Verify dmSpecVersion and dmSize fields of a devmode
  127. Arguments:
  128. pdm - Specifies a devmode to be version-checked
  129. Return Value:
  130. 0 if the input devmode is unacceptable
  131. Otherwise, return the expected dmSpecVersion value
  132. --*/
  133. {
  134. WORD expectedVersion;
  135. if (pdm == NULL)
  136. return 0;
  137. // Check against known devmode sizes
  138. switch (pdm->dmSize) {
  139. case DM_SIZE320:
  140. expectedVersion = DM_SPECVERSION320;
  141. break;
  142. case DM_SIZE400:
  143. expectedVersion = DM_SPECVERSION400;
  144. break;
  145. case DM_SIZE401:
  146. expectedVersion = DM_SPECVERSION401;
  147. break;
  148. default:
  149. expectedVersion = pdm->dmSpecVersion;
  150. break;
  151. }
  152. return expectedVersion;
  153. }
  154. LONG
  155. ConvertDevmode(
  156. PDEVMODE pdmIn,
  157. PDEVMODE pdmOut
  158. )
  159. /*++
  160. Routine Description:
  161. Convert an input devmode to a different version devmode.
  162. Whenever driver gets an input devmode, it should call this
  163. routine to convert it to current version.
  164. Arguments:
  165. pdmIn - Points to an input devmode
  166. pdmOut - Points to an initialized/valid output devmode
  167. Return Value:
  168. Total number of bytes copied
  169. -1 if either input or output devmode is invalid
  170. --*/
  171. {
  172. WORD dmSpecVersion, dmDriverVersion;
  173. WORD dmSize, dmDriverExtra;
  174. LONG cbCopied = 0;
  175. //
  176. // Parameter check
  177. //
  178. if (NULL == pdmIn ||
  179. NULL == pdmOut )
  180. {
  181. return -1;
  182. }
  183. // Look for inconsistency between dmSpecVersion and dmSize
  184. if (! CheckDevmodeVersion(pdmIn) ||
  185. ! (dmSpecVersion = CheckDevmodeVersion(pdmOut)))
  186. {
  187. return -1;
  188. }
  189. // Copy public devmode fields
  190. dmDriverVersion = pdmOut->dmDriverVersion;
  191. dmSize = pdmOut->dmSize;
  192. dmDriverExtra = pdmOut->dmDriverExtra;
  193. cbCopied = min(dmSize, pdmIn->dmSize);
  194. memcpy(pdmOut, pdmIn, cbCopied);
  195. pdmOut->dmSpecVersion = dmSpecVersion;
  196. pdmOut->dmDriverVersion = dmDriverVersion;
  197. pdmOut->dmSize = dmSize;
  198. pdmOut->dmDriverExtra = dmDriverExtra;
  199. // Copy private devmode fields
  200. cbCopied += min(dmDriverExtra, pdmIn->dmDriverExtra);
  201. memcpy((PBYTE) pdmOut + pdmOut->dmSize,
  202. (PBYTE) pdmIn + pdmIn->dmSize,
  203. min(dmDriverExtra, pdmIn->dmDriverExtra));
  204. return cbCopied;
  205. }
  206. #if defined(UMODE) || defined(USERMODE_DRIVER)
  207. BOOL
  208. ConvertDevmodeOut(
  209. PDEVMODE pdmSrc,
  210. PDEVMODE pdmIn,
  211. PDEVMODE pdmOut
  212. )
  213. /*++
  214. Routine Description:
  215. Copy a source devmode to an output devmode buffer.
  216. Driver should call this routine before it returns to the caller
  217. of DrvDocumentPropertySheets.
  218. Arguments:
  219. pdmSrc - Points to a current version source devmode
  220. pdmIn - Points to input devmode passed to DrvDocumentPropertySheets through lparam
  221. pdmOut - Output buffer pointer passed to DrvDocumentPropertySheets through lparam
  222. Return Value:
  223. TRUE if successful, FALSE otherwise
  224. --*/
  225. {
  226. if (pdmIn == NULL) {
  227. if (pdmSrc == NULL || pdmOut == NULL)
  228. {
  229. return FALSE;
  230. }
  231. memcpy(pdmOut, pdmSrc, pdmSrc->dmSize + pdmSrc->dmDriverExtra);
  232. return TRUE;
  233. } else {
  234. if (pdmSrc == NULL || pdmOut == NULL)
  235. {
  236. return FALSE;
  237. }
  238. // We have to deal with the public fields and private fields
  239. // separately. Also remember pdmIn and pdmOut may point to
  240. // the same buffer.
  241. // Public fields: take dmSpecVersion and dmSize from
  242. // the smaller of pdmSrc and pdmIn
  243. if (pdmIn->dmSize < pdmSrc->dmSize) {
  244. pdmOut->dmSpecVersion = pdmIn->dmSpecVersion;
  245. pdmOut->dmSize = pdmIn->dmSize;
  246. } else {
  247. pdmOut->dmSpecVersion = pdmSrc->dmSpecVersion;
  248. pdmOut->dmSize = pdmSrc->dmSize;
  249. }
  250. // Similarly for private fields
  251. if (pdmIn->dmDriverExtra < pdmSrc->dmDriverExtra) {
  252. pdmOut->dmDriverVersion = pdmIn->dmDriverVersion;
  253. pdmOut->dmDriverExtra = pdmIn->dmDriverExtra;
  254. } else {
  255. pdmOut->dmDriverVersion = pdmSrc->dmDriverVersion;
  256. pdmOut->dmDriverExtra = pdmSrc->dmDriverExtra;
  257. }
  258. return ConvertDevmode(pdmSrc, pdmOut) > 0;
  259. }
  260. }
  261. INT
  262. CommonDrvConvertDevmode(
  263. PWSTR pPrinterName,
  264. PDEVMODE pdmIn,
  265. PDEVMODE pdmOut,
  266. PLONG pcbNeeded,
  267. DWORD fMode,
  268. PDRIVER_VERSION_INFO pDriverVersions
  269. )
  270. /*++
  271. Routine Description:
  272. Library routine to handle common cases of DrvConvertDevMode
  273. Arguments:
  274. pPrinterName, pdmIn, pdmOut, pcbNeeded, fMode
  275. Correspond to parameters passed to DrvConvertDevMode
  276. pDriverVersions - Specifies driver version numbers and private devmode sizes
  277. Return Value:
  278. CDM_RESULT_TRUE
  279. If the case is handled by the library routine and driver
  280. shoud return TRUE to the caller of DrvConvertDevMode.
  281. CDM_RESULT_FALSE
  282. If the case is handled by the library routine and driver
  283. shoud return FALSE to the caller of DrvConvertDevMode.
  284. CDM_RESULT_NOT_HANDLED
  285. The case is NOT handled by the library routine and driver
  286. should continue on with whatever it needs to do.
  287. --*/
  288. {
  289. LONG size;
  290. // Make sure pcbNeeded parameter is not NULL
  291. if (pcbNeeded == NULL) {
  292. SetLastError(ERROR_INVALID_PARAMETER);
  293. return CDM_RESULT_FALSE;
  294. }
  295. switch (fMode) {
  296. case CDM_CONVERT:
  297. // Convert any input devmode to any output devmode.
  298. // Both input and output must be valid.
  299. if (pdmOut != NULL &&
  300. *pcbNeeded >= (pdmOut->dmSize + pdmOut->dmDriverExtra) &&
  301. ConvertDevmode(pdmIn, pdmOut) > 0)
  302. {
  303. *pcbNeeded = pdmOut->dmSize + pdmOut->dmDriverExtra;
  304. return CDM_RESULT_TRUE;
  305. }
  306. break;
  307. case CDM_CONVERT351:
  308. // Convert any input devmode to 3.51 version devmode
  309. // First check if the caller provided buffer is large enough
  310. size = DM_SIZE320 + pDriverVersions->dmDriverExtra351;
  311. if (*pcbNeeded < size || pdmOut == NULL) {
  312. *pcbNeeded = size;
  313. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  314. return CDM_RESULT_FALSE;
  315. }
  316. // Do the conversion from input devmode to 3.51 devmode
  317. pdmOut->dmSpecVersion = DM_SPECVERSION320;
  318. pdmOut->dmSize = DM_SIZE320;
  319. pdmOut->dmDriverVersion = pDriverVersions->dmDriverVersion351;
  320. pdmOut->dmDriverExtra = pDriverVersions->dmDriverExtra351;
  321. if (ConvertDevmode(pdmIn, pdmOut) > 0) {
  322. *pcbNeeded = size;
  323. return CDM_RESULT_TRUE;
  324. }
  325. break;
  326. case CDM_DRIVER_DEFAULT:
  327. // Convert any input devmode to current version devmode
  328. // First check if the caller provided buffer is large enough
  329. size = DM_SIZE_CURRENT + pDriverVersions->dmDriverExtra;
  330. if (*pcbNeeded < size || pdmOut == NULL) {
  331. *pcbNeeded = size;
  332. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  333. return CDM_RESULT_FALSE;
  334. }
  335. // This case (getting driver-default devmode) is not handled
  336. // by the library routine.
  337. *pcbNeeded = size;
  338. // FALL THROUGH TO THE DEFAULT CASE!
  339. default:
  340. return CDM_RESULT_NOT_HANDLED;
  341. }
  342. SetLastError(ERROR_INVALID_PARAMETER);
  343. return CDM_RESULT_FALSE;
  344. }
  345. #endif // USER MODE