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.

490 lines
10 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. )
  209. /*++
  210. Routine Description:
  211. Copy a source devmode to an output devmode buffer.
  212. Driver should call this routine before it returns to the caller
  213. of DrvDocumentProperties.
  214. Arguments:
  215. pdmSrc - Points to a current version source devmode
  216. pdmIn - Points to input devmode passed to DrvDocumentProperties
  217. pdmOut - Output buffer pointer passed to DrvDocumentProperties
  218. Return Value:
  219. TRUE if successful, FALSE otherwise
  220. --*/
  221. {
  222. if (pdmIn == NULL) {
  223. memcpy(pdmOut, pdmSrc, pdmSrc->dmSize + pdmSrc->dmDriverExtra);
  224. return TRUE;
  225. } else {
  226. // We have to deal with the public fields and private fields
  227. // separately. Also remember pdmIn and pdmOut may point to
  228. // the same buffer.
  229. // Public fields: take dmSpecVersion and dmSize from
  230. // the smaller of pdmSrc and pdmIn
  231. if (pdmIn->dmSize < pdmSrc->dmSize) {
  232. pdmOut->dmSpecVersion = pdmIn->dmSpecVersion;
  233. pdmOut->dmSize = pdmIn->dmSize;
  234. } else {
  235. pdmOut->dmSpecVersion = pdmSrc->dmSpecVersion;
  236. pdmOut->dmSize = pdmSrc->dmSize;
  237. }
  238. // Similarly for private fields
  239. if (pdmIn->dmDriverExtra < pdmSrc->dmDriverExtra) {
  240. pdmOut->dmDriverVersion = pdmIn->dmDriverVersion;
  241. pdmOut->dmDriverExtra = pdmIn->dmDriverExtra;
  242. } else {
  243. pdmOut->dmDriverVersion = pdmSrc->dmDriverVersion;
  244. pdmOut->dmDriverExtra = pdmSrc->dmDriverExtra;
  245. }
  246. return ConvertDevmode(pdmSrc, pdmOut) > 0;
  247. }
  248. }
  249. INT
  250. CommonDrvConvertDevmode(
  251. PWSTR pPrinterName,
  252. PDEVMODE pdmIn,
  253. PDEVMODE pdmOut,
  254. PLONG pcbNeeded,
  255. DWORD fMode,
  256. PDRIVER_VERSION_INFO pDriverVersions
  257. )
  258. /*++
  259. Routine Description:
  260. Library routine to handle common cases of DrvConvertDevMode
  261. Arguments:
  262. pPrinterName, pdmIn, pdmOut, pcbNeeded, fMode
  263. Correspond to parameters passed to DrvConvertDevMode
  264. pDriverVersions - Specifies driver version numbers and private devmode sizes
  265. Return Value:
  266. CDM_RESULT_TRUE
  267. If the case is handled by the library routine and driver
  268. shoud return TRUE to the caller of DrvConvertDevMode.
  269. CDM_RESULT_FALSE
  270. If the case is handled by the library routine and driver
  271. shoud return FALSE to the caller of DrvConvertDevMode.
  272. CDM_RESULT_NOT_HANDLED
  273. The case is NOT handled by the library routine and driver
  274. should continue on with whatever it needs to do.
  275. --*/
  276. {
  277. LONG size;
  278. // Make sure pcbNeeded parameter is not NULL
  279. if (pcbNeeded == NULL) {
  280. SetLastError(ERROR_INVALID_PARAMETER);
  281. return CDM_RESULT_FALSE;
  282. }
  283. switch (fMode) {
  284. case CDM_CONVERT:
  285. // Convert any input devmode to any output devmode.
  286. // Both input and output must be valid.
  287. if (pdmOut != NULL &&
  288. *pcbNeeded >= (pdmOut->dmSize + pdmOut->dmDriverExtra) &&
  289. ConvertDevmode(pdmIn, pdmOut) > 0)
  290. {
  291. *pcbNeeded = pdmOut->dmSize + pdmOut->dmDriverExtra;
  292. return CDM_RESULT_TRUE;
  293. }
  294. break;
  295. case CDM_CONVERT351:
  296. // Convert any input devmode to 3.51 version devmode
  297. // First check if the caller provided buffer is large enough
  298. size = DM_SIZE320 + pDriverVersions->dmDriverExtra351;
  299. if (*pcbNeeded < size || pdmOut == NULL) {
  300. *pcbNeeded = size;
  301. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  302. return CDM_RESULT_FALSE;
  303. }
  304. // Do the conversion from input devmode to 3.51 devmode
  305. pdmOut->dmSpecVersion = DM_SPECVERSION320;
  306. pdmOut->dmSize = DM_SIZE320;
  307. pdmOut->dmDriverVersion = pDriverVersions->dmDriverVersion351;
  308. pdmOut->dmDriverExtra = pDriverVersions->dmDriverExtra351;
  309. if (ConvertDevmode(pdmIn, pdmOut) > 0) {
  310. *pcbNeeded = size;
  311. return CDM_RESULT_TRUE;
  312. }
  313. break;
  314. case CDM_DRIVER_DEFAULT:
  315. // Convert any input devmode to current version devmode
  316. // First check if the caller provided buffer is large enough
  317. size = DM_SIZE_CURRENT + pDriverVersions->dmDriverExtra;
  318. if (*pcbNeeded < size || pdmOut == NULL) {
  319. *pcbNeeded = size;
  320. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  321. return CDM_RESULT_FALSE;
  322. }
  323. // This case (getting driver-default devmode) is not handled
  324. // by the library routine.
  325. *pcbNeeded = size;
  326. // FALL THROUGH TO THE DEFAULT CASE!
  327. default:
  328. return CDM_RESULT_NOT_HANDLED;
  329. }
  330. SetLastError(ERROR_INVALID_PARAMETER);
  331. return CDM_RESULT_FALSE;
  332. }
  333. #endif // !KERNEL_MODE