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.

496 lines
11 KiB

  1. /*++
  2. Copyright (c) 1990-1993 Microsoft Corporation
  3. Module Name:
  4. devmode.c
  5. Abstract:
  6. This module contains devmode conversion
  7. Author:
  8. 08-Jun-1995 Thu 13:47:33 created -by- Daniel Chou (danielc)
  9. [Environment:]
  10. GDI printer drivers, user and kernel mode
  11. [Notes:]
  12. Revision History:
  13. 11/09/95 -davidx-
  14. New conversion routines
  15. --*/
  16. #include <windef.h>
  17. #include <winerror.h>
  18. #include <wingdi.h>
  19. #include <libproto.h>
  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. // Look for inconsistency between dmSpecVersion and dmSize
  176. if (! CheckDevmodeVersion(pdmIn) ||
  177. ! (dmSpecVersion = CheckDevmodeVersion(pdmOut)))
  178. {
  179. return -1;
  180. }
  181. // Copy public devmode fields
  182. dmDriverVersion = pdmOut->dmDriverVersion;
  183. dmSize = pdmOut->dmSize;
  184. dmDriverExtra = pdmOut->dmDriverExtra;
  185. cbCopied = min(dmSize, pdmIn->dmSize);
  186. memcpy(pdmOut, pdmIn, cbCopied);
  187. pdmOut->dmSpecVersion = dmSpecVersion;
  188. pdmOut->dmDriverVersion = dmDriverVersion;
  189. pdmOut->dmSize = dmSize;
  190. pdmOut->dmDriverExtra = dmDriverExtra;
  191. // Copy private devmode fields
  192. cbCopied += min(dmDriverExtra, pdmIn->dmDriverExtra);
  193. memcpy((PBYTE) pdmOut + pdmOut->dmSize,
  194. (PBYTE) pdmIn + pdmIn->dmSize,
  195. min(dmDriverExtra, pdmIn->dmDriverExtra));
  196. return cbCopied;
  197. }
  198. #ifndef KERNEL_MODE
  199. #include <windows.h>
  200. #include <winspool.h>
  201. #include <commctrl.h>
  202. #include <winddiui.h>
  203. BOOL
  204. ConvertDevmodeOut(
  205. PDEVMODE pdmSrc,
  206. PDEVMODE pdmIn,
  207. PDEVMODE pdmOut,
  208. LONG lBufferSize
  209. )
  210. /*++
  211. Routine Description:
  212. Copy a source devmode to an output devmode buffer.
  213. Driver should call this routine before it returns to the caller
  214. of DrvDocumentProperties.
  215. Arguments:
  216. pdmSrc - Points to a current version source devmode
  217. pdmIn - Points to input devmode passed to DrvDocumentProperties
  218. pdmOut - Output buffer pointer passed to DrvDocumentProperties
  219. lBufferSize - pdmOut size in BYTES.
  220. Return Value:
  221. TRUE if successful, FALSE otherwise
  222. --*/
  223. {
  224. if (pdmIn == NULL)
  225. {
  226. if (lBufferSize < pdmSrc->dmSize + pdmSrc->dmDriverExtra)
  227. {
  228. return FALSE;
  229. }
  230. memcpy(pdmOut, pdmSrc, pdmSrc->dmSize + pdmSrc->dmDriverExtra);
  231. return TRUE;
  232. }
  233. else
  234. {
  235. // We have to deal with the public fields and private fields
  236. // separately. Also remember pdmIn and pdmOut may point to
  237. // the same buffer.
  238. // Public fields: take dmSpecVersion and dmSize from
  239. // the smaller of pdmSrc and pdmIn
  240. if (pdmIn->dmSize < pdmSrc->dmSize)
  241. {
  242. pdmOut->dmSpecVersion = pdmIn->dmSpecVersion;
  243. pdmOut->dmSize = pdmIn->dmSize;
  244. }
  245. else
  246. {
  247. pdmOut->dmSpecVersion = pdmSrc->dmSpecVersion;
  248. pdmOut->dmSize = pdmSrc->dmSize;
  249. }
  250. // Similarly for private fields
  251. if (pdmIn->dmDriverExtra < pdmSrc->dmDriverExtra)
  252. {
  253. pdmOut->dmDriverVersion = pdmIn->dmDriverVersion;
  254. pdmOut->dmDriverExtra = pdmIn->dmDriverExtra;
  255. }
  256. else
  257. {
  258. pdmOut->dmDriverVersion = pdmSrc->dmDriverVersion;
  259. pdmOut->dmDriverExtra = pdmSrc->dmDriverExtra;
  260. }
  261. return ConvertDevmode(pdmSrc, pdmOut) > 0;
  262. }
  263. }
  264. INT
  265. CommonDrvConvertDevmode(
  266. PWSTR pPrinterName,
  267. PDEVMODE pdmIn,
  268. PDEVMODE pdmOut,
  269. PLONG pcbNeeded,
  270. DWORD fMode,
  271. PDRIVER_VERSION_INFO pDriverVersions
  272. )
  273. /*++
  274. Routine Description:
  275. Library routine to handle common cases of DrvConvertDevMode
  276. Arguments:
  277. pPrinterName, pdmIn, pdmOut, pcbNeeded, fMode
  278. Correspond to parameters passed to DrvConvertDevMode
  279. pDriverVersions - Specifies driver version numbers and private devmode sizes
  280. Return Value:
  281. CDM_RESULT_TRUE
  282. If the case is handled by the library routine and driver
  283. shoud return TRUE to the caller of DrvConvertDevMode.
  284. CDM_RESULT_FALSE
  285. If the case is handled by the library routine and driver
  286. shoud return FALSE to the caller of DrvConvertDevMode.
  287. CDM_RESULT_NOT_HANDLED
  288. The case is NOT handled by the library routine and driver
  289. should continue on with whatever it needs to do.
  290. --*/
  291. {
  292. LONG size;
  293. // Make sure pcbNeeded parameter is not NULL
  294. if (pcbNeeded == NULL) {
  295. SetLastError(ERROR_INVALID_PARAMETER);
  296. return CDM_RESULT_FALSE;
  297. }
  298. switch (fMode) {
  299. case CDM_CONVERT:
  300. // Convert any input devmode to any output devmode.
  301. // Both input and output must be valid.
  302. if (pdmOut != NULL &&
  303. *pcbNeeded >= (pdmOut->dmSize + pdmOut->dmDriverExtra) &&
  304. ConvertDevmode(pdmIn, pdmOut) > 0)
  305. {
  306. *pcbNeeded = pdmOut->dmSize + pdmOut->dmDriverExtra;
  307. return CDM_RESULT_TRUE;
  308. }
  309. break;
  310. case CDM_CONVERT351:
  311. // Convert any input devmode to 3.51 version devmode
  312. // First check if the caller provided buffer is large enough
  313. size = DM_SIZE320 + pDriverVersions->dmDriverExtra351;
  314. if (*pcbNeeded < size || pdmOut == NULL) {
  315. *pcbNeeded = size;
  316. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  317. return CDM_RESULT_FALSE;
  318. }
  319. // Do the conversion from input devmode to 3.51 devmode
  320. pdmOut->dmSpecVersion = DM_SPECVERSION320;
  321. pdmOut->dmSize = DM_SIZE320;
  322. pdmOut->dmDriverVersion = pDriverVersions->dmDriverVersion351;
  323. pdmOut->dmDriverExtra = pDriverVersions->dmDriverExtra351;
  324. if (ConvertDevmode(pdmIn, pdmOut) > 0) {
  325. *pcbNeeded = size;
  326. return CDM_RESULT_TRUE;
  327. }
  328. break;
  329. case CDM_DRIVER_DEFAULT:
  330. // Convert any input devmode to current version devmode
  331. // First check if the caller provided buffer is large enough
  332. size = DM_SIZE_CURRENT + pDriverVersions->dmDriverExtra;
  333. if (*pcbNeeded < size || pdmOut == NULL) {
  334. *pcbNeeded = size;
  335. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  336. return CDM_RESULT_FALSE;
  337. }
  338. // This case (getting driver-default devmode) is not handled
  339. // by the library routine.
  340. *pcbNeeded = size;
  341. // FALL THROUGH TO THE DEFAULT CASE!
  342. default:
  343. return CDM_RESULT_NOT_HANDLED;
  344. }
  345. SetLastError(ERROR_INVALID_PARAMETER);
  346. return CDM_RESULT_FALSE;
  347. }
  348. #endif // !KERNEL_MODE