1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS Spooler API
3c2c66affSColin Finck * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4c2c66affSColin Finck * PURPOSE: Functions giving information about DEVMODE structures
51f6f08ecSColin Finck * COPYRIGHT: Copyright 2016-2017 Colin Finck (colin@reactos.org)
6c2c66affSColin Finck */
7c2c66affSColin Finck
8c2c66affSColin Finck #include "precomp.h"
9c2c66affSColin Finck
10c2c66affSColin Finck typedef struct _MINIMUM_SIZE_TABLE
11c2c66affSColin Finck {
12c2c66affSColin Finck DWORD dwField;
13c2c66affSColin Finck WORD wSize;
14c2c66affSColin Finck }
15c2c66affSColin Finck MINIMUM_SIZE_TABLE, *PMINIMUM_SIZE_TABLE;
16c2c66affSColin Finck
17c2c66affSColin Finck /**
18c2c66affSColin Finck * Minimum required DEVMODEA structure size based on the used fields. Must be in descending order!
19c2c66affSColin Finck */
20c2c66affSColin Finck static MINIMUM_SIZE_TABLE MinimumSizeA[] = {
21c2c66affSColin Finck { DM_PANNINGHEIGHT, FIELD_OFFSET(DEVMODEA, dmPanningHeight) + RTL_FIELD_SIZE(DEVMODEA, dmPanningHeight) },
22c2c66affSColin Finck { DM_PANNINGWIDTH, FIELD_OFFSET(DEVMODEA, dmPanningWidth) + RTL_FIELD_SIZE(DEVMODEA, dmPanningWidth) },
23c2c66affSColin Finck { DM_DITHERTYPE, FIELD_OFFSET(DEVMODEA, dmDitherType) + RTL_FIELD_SIZE(DEVMODEA, dmDitherType) },
24c2c66affSColin Finck { DM_MEDIATYPE, FIELD_OFFSET(DEVMODEA, dmMediaType) + RTL_FIELD_SIZE(DEVMODEA, dmMediaType) },
25c2c66affSColin Finck { DM_ICMINTENT, FIELD_OFFSET(DEVMODEA, dmICMIntent) + RTL_FIELD_SIZE(DEVMODEA, dmICMIntent) },
26c2c66affSColin Finck { DM_ICMMETHOD, FIELD_OFFSET(DEVMODEA, dmICMMethod) + RTL_FIELD_SIZE(DEVMODEA, dmICMMethod) },
27c2c66affSColin Finck { DM_DISPLAYFREQUENCY, FIELD_OFFSET(DEVMODEA, dmDisplayFrequency) + RTL_FIELD_SIZE(DEVMODEA, dmDisplayFrequency) },
28c2c66affSColin Finck { DM_NUP, FIELD_OFFSET(DEVMODEA, dmNup) + RTL_FIELD_SIZE(DEVMODEA, dmNup) },
29c2c66affSColin Finck { DM_DISPLAYFLAGS, FIELD_OFFSET(DEVMODEA, dmDisplayFlags) + RTL_FIELD_SIZE(DEVMODEA, dmDisplayFlags) },
30c2c66affSColin Finck { DM_PELSHEIGHT, FIELD_OFFSET(DEVMODEA, dmPelsHeight) + RTL_FIELD_SIZE(DEVMODEA, dmPelsHeight) },
31c2c66affSColin Finck { DM_PELSWIDTH, FIELD_OFFSET(DEVMODEA, dmPelsWidth) + RTL_FIELD_SIZE(DEVMODEA, dmPelsWidth) },
32c2c66affSColin Finck { DM_BITSPERPEL, FIELD_OFFSET(DEVMODEA, dmBitsPerPel) + RTL_FIELD_SIZE(DEVMODEA, dmBitsPerPel) },
33c2c66affSColin Finck { DM_LOGPIXELS, FIELD_OFFSET(DEVMODEA, dmLogPixels) + RTL_FIELD_SIZE(DEVMODEA, dmLogPixels) },
34c2c66affSColin Finck { DM_FORMNAME, FIELD_OFFSET(DEVMODEA, dmFormName) + RTL_FIELD_SIZE(DEVMODEA, dmFormName) },
35c2c66affSColin Finck { DM_COLLATE, FIELD_OFFSET(DEVMODEA, dmCollate) + RTL_FIELD_SIZE(DEVMODEA, dmCollate) },
36c2c66affSColin Finck { DM_TTOPTION, FIELD_OFFSET(DEVMODEA, dmTTOption) + RTL_FIELD_SIZE(DEVMODEA, dmTTOption) },
37c2c66affSColin Finck { DM_YRESOLUTION, FIELD_OFFSET(DEVMODEA, dmYResolution) + RTL_FIELD_SIZE(DEVMODEA, dmYResolution) },
38c2c66affSColin Finck { DM_DUPLEX, FIELD_OFFSET(DEVMODEA, dmDuplex) + RTL_FIELD_SIZE(DEVMODEA, dmDuplex) },
39c2c66affSColin Finck { DM_COLOR, FIELD_OFFSET(DEVMODEA, dmColor) + RTL_FIELD_SIZE(DEVMODEA, dmColor) },
40c2c66affSColin Finck { DM_DISPLAYFIXEDOUTPUT, FIELD_OFFSET(DEVMODEA, dmDisplayFixedOutput) + RTL_FIELD_SIZE(DEVMODEA, dmDisplayFixedOutput) },
41c2c66affSColin Finck { DM_DISPLAYORIENTATION, FIELD_OFFSET(DEVMODEA, dmDisplayOrientation) + RTL_FIELD_SIZE(DEVMODEA, dmDisplayOrientation) },
42c2c66affSColin Finck { DM_POSITION, FIELD_OFFSET(DEVMODEA, dmPosition) + RTL_FIELD_SIZE(DEVMODEA, dmPosition) },
43c2c66affSColin Finck { DM_PRINTQUALITY, FIELD_OFFSET(DEVMODEA, dmPrintQuality) + RTL_FIELD_SIZE(DEVMODEA, dmPrintQuality) },
44c2c66affSColin Finck { DM_DEFAULTSOURCE, FIELD_OFFSET(DEVMODEA, dmDefaultSource) + RTL_FIELD_SIZE(DEVMODEA, dmDefaultSource) },
45c2c66affSColin Finck { DM_COPIES, FIELD_OFFSET(DEVMODEA, dmCopies) + RTL_FIELD_SIZE(DEVMODEA, dmCopies) },
46c2c66affSColin Finck { DM_SCALE, FIELD_OFFSET(DEVMODEA, dmScale) + RTL_FIELD_SIZE(DEVMODEA, dmScale) },
47c2c66affSColin Finck { DM_PAPERWIDTH, FIELD_OFFSET(DEVMODEA, dmPaperWidth) + RTL_FIELD_SIZE(DEVMODEA, dmPaperWidth) },
48c2c66affSColin Finck { DM_PAPERLENGTH, FIELD_OFFSET(DEVMODEA, dmPaperLength) + RTL_FIELD_SIZE(DEVMODEA, dmPaperLength) },
49c2c66affSColin Finck { DM_PAPERSIZE, FIELD_OFFSET(DEVMODEA, dmPaperSize) + RTL_FIELD_SIZE(DEVMODEA, dmPaperSize) },
50c2c66affSColin Finck { DM_ORIENTATION, FIELD_OFFSET(DEVMODEA, dmOrientation) + RTL_FIELD_SIZE(DEVMODEA, dmOrientation) },
51c2c66affSColin Finck { 0, 0 }
52c2c66affSColin Finck };
53c2c66affSColin Finck
54c2c66affSColin Finck /**
55c2c66affSColin Finck * Minimum required DEVMODEW structure size based on the used fields. Must be in descending order!
56c2c66affSColin Finck */
57c2c66affSColin Finck static MINIMUM_SIZE_TABLE MinimumSizeW[] = {
58c2c66affSColin Finck { DM_PANNINGHEIGHT, FIELD_OFFSET(DEVMODEW, dmPanningHeight) + RTL_FIELD_SIZE(DEVMODEW, dmPanningHeight) },
59c2c66affSColin Finck { DM_PANNINGWIDTH, FIELD_OFFSET(DEVMODEW, dmPanningWidth) + RTL_FIELD_SIZE(DEVMODEW, dmPanningWidth) },
60c2c66affSColin Finck { DM_DITHERTYPE, FIELD_OFFSET(DEVMODEW, dmDitherType) + RTL_FIELD_SIZE(DEVMODEW, dmDitherType) },
61c2c66affSColin Finck { DM_MEDIATYPE, FIELD_OFFSET(DEVMODEW, dmMediaType) + RTL_FIELD_SIZE(DEVMODEW, dmMediaType) },
62c2c66affSColin Finck { DM_ICMINTENT, FIELD_OFFSET(DEVMODEW, dmICMIntent) + RTL_FIELD_SIZE(DEVMODEW, dmICMIntent) },
63c2c66affSColin Finck { DM_ICMMETHOD, FIELD_OFFSET(DEVMODEW, dmICMMethod) + RTL_FIELD_SIZE(DEVMODEW, dmICMMethod) },
64c2c66affSColin Finck { DM_DISPLAYFREQUENCY, FIELD_OFFSET(DEVMODEW, dmDisplayFrequency) + RTL_FIELD_SIZE(DEVMODEW, dmDisplayFrequency) },
65c2c66affSColin Finck { DM_NUP, FIELD_OFFSET(DEVMODEW, dmNup) + RTL_FIELD_SIZE(DEVMODEW, dmNup) },
66c2c66affSColin Finck { DM_DISPLAYFLAGS, FIELD_OFFSET(DEVMODEW, dmDisplayFlags) + RTL_FIELD_SIZE(DEVMODEW, dmDisplayFlags) },
67c2c66affSColin Finck { DM_PELSHEIGHT, FIELD_OFFSET(DEVMODEW, dmPelsHeight) + RTL_FIELD_SIZE(DEVMODEW, dmPelsHeight) },
68c2c66affSColin Finck { DM_PELSWIDTH, FIELD_OFFSET(DEVMODEW, dmPelsWidth) + RTL_FIELD_SIZE(DEVMODEW, dmPelsWidth) },
69c2c66affSColin Finck { DM_BITSPERPEL, FIELD_OFFSET(DEVMODEW, dmBitsPerPel) + RTL_FIELD_SIZE(DEVMODEW, dmBitsPerPel) },
70c2c66affSColin Finck { DM_LOGPIXELS, FIELD_OFFSET(DEVMODEW, dmLogPixels) + RTL_FIELD_SIZE(DEVMODEW, dmLogPixels) },
71c2c66affSColin Finck { DM_FORMNAME, FIELD_OFFSET(DEVMODEW, dmFormName) + RTL_FIELD_SIZE(DEVMODEW, dmFormName) },
72c2c66affSColin Finck { DM_COLLATE, FIELD_OFFSET(DEVMODEW, dmCollate) + RTL_FIELD_SIZE(DEVMODEW, dmCollate) },
73c2c66affSColin Finck { DM_TTOPTION, FIELD_OFFSET(DEVMODEW, dmTTOption) + RTL_FIELD_SIZE(DEVMODEW, dmTTOption) },
74c2c66affSColin Finck { DM_YRESOLUTION, FIELD_OFFSET(DEVMODEW, dmYResolution) + RTL_FIELD_SIZE(DEVMODEW, dmYResolution) },
75c2c66affSColin Finck { DM_DUPLEX, FIELD_OFFSET(DEVMODEW, dmDuplex) + RTL_FIELD_SIZE(DEVMODEW, dmDuplex) },
76c2c66affSColin Finck { DM_COLOR, FIELD_OFFSET(DEVMODEW, dmColor) + RTL_FIELD_SIZE(DEVMODEW, dmColor) },
77c2c66affSColin Finck { DM_DISPLAYFIXEDOUTPUT, FIELD_OFFSET(DEVMODEW, dmDisplayFixedOutput) + RTL_FIELD_SIZE(DEVMODEW, dmDisplayFixedOutput) },
78c2c66affSColin Finck { DM_DISPLAYORIENTATION, FIELD_OFFSET(DEVMODEW, dmDisplayOrientation) + RTL_FIELD_SIZE(DEVMODEW, dmDisplayOrientation) },
79c2c66affSColin Finck { DM_POSITION, FIELD_OFFSET(DEVMODEW, dmPosition) + RTL_FIELD_SIZE(DEVMODEW, dmPosition) },
80c2c66affSColin Finck { DM_PRINTQUALITY, FIELD_OFFSET(DEVMODEW, dmPrintQuality) + RTL_FIELD_SIZE(DEVMODEW, dmPrintQuality) },
81c2c66affSColin Finck { DM_DEFAULTSOURCE, FIELD_OFFSET(DEVMODEW, dmDefaultSource) + RTL_FIELD_SIZE(DEVMODEW, dmDefaultSource) },
82c2c66affSColin Finck { DM_COPIES, FIELD_OFFSET(DEVMODEW, dmCopies) + RTL_FIELD_SIZE(DEVMODEW, dmCopies) },
83c2c66affSColin Finck { DM_SCALE, FIELD_OFFSET(DEVMODEW, dmScale) + RTL_FIELD_SIZE(DEVMODEW, dmScale) },
84c2c66affSColin Finck { DM_PAPERWIDTH, FIELD_OFFSET(DEVMODEW, dmPaperWidth) + RTL_FIELD_SIZE(DEVMODEW, dmPaperWidth) },
85c2c66affSColin Finck { DM_PAPERLENGTH, FIELD_OFFSET(DEVMODEW, dmPaperLength) + RTL_FIELD_SIZE(DEVMODEW, dmPaperLength) },
86c2c66affSColin Finck { DM_PAPERSIZE, FIELD_OFFSET(DEVMODEW, dmPaperSize) + RTL_FIELD_SIZE(DEVMODEW, dmPaperSize) },
87c2c66affSColin Finck { DM_ORIENTATION, FIELD_OFFSET(DEVMODEW, dmOrientation) + RTL_FIELD_SIZE(DEVMODEW, dmOrientation) },
88c2c66affSColin Finck { 0, 0 }
89c2c66affSColin Finck };
90c2c66affSColin Finck
91c2c66affSColin Finck /**
92c2c66affSColin Finck * Replace the last character by a null terminator if the given ANSI string is not null-terminated.
93c2c66affSColin Finck */
94c2c66affSColin Finck static __inline void
_FixStringA(PBYTE String,DWORD cbString)95c2c66affSColin Finck _FixStringA(PBYTE String, DWORD cbString)
96c2c66affSColin Finck {
97c2c66affSColin Finck const PBYTE pLastCharacter = &String[cbString / sizeof(BYTE) - 1];
98c2c66affSColin Finck PBYTE p = String;
99c2c66affSColin Finck
100c2c66affSColin Finck while (*p)
101c2c66affSColin Finck {
102c2c66affSColin Finck if (p == pLastCharacter)
103c2c66affSColin Finck {
104c2c66affSColin Finck *p = 0;
105c2c66affSColin Finck break;
106c2c66affSColin Finck }
107c2c66affSColin Finck
108c2c66affSColin Finck p++;
109c2c66affSColin Finck }
110c2c66affSColin Finck }
111c2c66affSColin Finck
112c2c66affSColin Finck /**
113c2c66affSColin Finck * Replace the last character by a null terminator if the given Unicode string is not null-terminated.
114c2c66affSColin Finck */
115c2c66affSColin Finck static __inline void
_FixStringW(PWSTR String,DWORD cbString)116c2c66affSColin Finck _FixStringW(PWSTR String, DWORD cbString)
117c2c66affSColin Finck {
118c2c66affSColin Finck const PWSTR pLastCharacter = &String[cbString / sizeof(WCHAR) - 1];
119c2c66affSColin Finck PWSTR p = String;
120c2c66affSColin Finck
121c2c66affSColin Finck while (*p)
122c2c66affSColin Finck {
123c2c66affSColin Finck if (p == pLastCharacter)
124c2c66affSColin Finck {
125c2c66affSColin Finck *p = 0;
126c2c66affSColin Finck break;
127c2c66affSColin Finck }
128c2c66affSColin Finck
129c2c66affSColin Finck p++;
130c2c66affSColin Finck }
131c2c66affSColin Finck }
132c2c66affSColin Finck
133c2c66affSColin Finck BOOL WINAPI
IsValidDevmodeA(PDEVMODEA pDevmode,size_t DevmodeSize)134c2c66affSColin Finck IsValidDevmodeA(PDEVMODEA pDevmode, size_t DevmodeSize)
135c2c66affSColin Finck {
136c2c66affSColin Finck PMINIMUM_SIZE_TABLE pTable = MinimumSizeA;
137c2c66affSColin Finck WORD wRequiredSize;
138c2c66affSColin Finck
1391f6f08ecSColin Finck TRACE("IsValidDevmodeA(%p, %lu)\n", pDevmode, DevmodeSize);
1401f6f08ecSColin Finck
141c2c66affSColin Finck // Check if a Devmode was given at all.
142c2c66affSColin Finck if (!pDevmode)
143c2c66affSColin Finck goto Failure;
144c2c66affSColin Finck
145c2c66affSColin Finck // Verify that DevmodeSize is large enough to hold the public and private members of the structure.
146c2c66affSColin Finck if (DevmodeSize < pDevmode->dmSize + pDevmode->dmDriverExtra)
147c2c66affSColin Finck goto Failure;
148c2c66affSColin Finck
149c2c66affSColin Finck // If the structure has private members, the public structure must be 32-bit packed.
150c2c66affSColin Finck if (pDevmode->dmDriverExtra && pDevmode->dmSize % 4)
151c2c66affSColin Finck goto Failure;
152c2c66affSColin Finck
153c2c66affSColin Finck // Now determine the minimum possible dmSize based on the given fields in dmFields.
154c2c66affSColin Finck wRequiredSize = FIELD_OFFSET(DEVMODEA, dmFields) + RTL_FIELD_SIZE(DEVMODEA, dmFields);
155c2c66affSColin Finck
156c2c66affSColin Finck while (pTable->dwField)
157c2c66affSColin Finck {
158c2c66affSColin Finck if (pDevmode->dmFields & pTable->dwField)
159c2c66affSColin Finck {
160c2c66affSColin Finck wRequiredSize = pTable->wSize;
161c2c66affSColin Finck break;
162c2c66affSColin Finck }
163c2c66affSColin Finck
164c2c66affSColin Finck pTable++;
165c2c66affSColin Finck }
166c2c66affSColin Finck
167c2c66affSColin Finck // Verify that the value in dmSize is big enough for the used fields.
168c2c66affSColin Finck if (pDevmode->dmSize < wRequiredSize)
169c2c66affSColin Finck goto Failure;
170c2c66affSColin Finck
171c2c66affSColin Finck // Check if dmDeviceName and (if used) dmFormName are null-terminated.
172c2c66affSColin Finck // Fix this if they aren't.
173c2c66affSColin Finck _FixStringA(pDevmode->dmDeviceName, sizeof(pDevmode->dmDeviceName));
174c2c66affSColin Finck if (pDevmode->dmFields & DM_FORMNAME)
175c2c66affSColin Finck _FixStringA(pDevmode->dmFormName, sizeof(pDevmode->dmFormName));
176c2c66affSColin Finck
177c2c66affSColin Finck // Return success without setting the error code.
178c2c66affSColin Finck return TRUE;
179c2c66affSColin Finck
180c2c66affSColin Finck Failure:
181c2c66affSColin Finck SetLastError(ERROR_INVALID_DATA);
182c2c66affSColin Finck return FALSE;
183c2c66affSColin Finck }
184c2c66affSColin Finck
185c2c66affSColin Finck BOOL WINAPI
IsValidDevmodeW(PDEVMODEW pDevmode,size_t DevmodeSize)186c2c66affSColin Finck IsValidDevmodeW(PDEVMODEW pDevmode, size_t DevmodeSize)
187c2c66affSColin Finck {
188c2c66affSColin Finck PMINIMUM_SIZE_TABLE pTable = MinimumSizeW;
189c2c66affSColin Finck WORD wRequiredSize;
190c2c66affSColin Finck
1911f6f08ecSColin Finck TRACE("IsValidDevmodeW(%p, %lu)\n", pDevmode, DevmodeSize);
1921f6f08ecSColin Finck
193c2c66affSColin Finck // Check if a Devmode was given at all.
194c2c66affSColin Finck if (!pDevmode)
195c2c66affSColin Finck goto Failure;
196c2c66affSColin Finck
197c2c66affSColin Finck // Verify that DevmodeSize is large enough to hold the public and private members of the structure.
198c2c66affSColin Finck if (DevmodeSize < pDevmode->dmSize + pDevmode->dmDriverExtra)
199c2c66affSColin Finck goto Failure;
200c2c66affSColin Finck
201c2c66affSColin Finck // If the structure has private members, the public structure must be 32-bit packed.
202c2c66affSColin Finck if (pDevmode->dmDriverExtra && pDevmode->dmSize % 4)
203c2c66affSColin Finck goto Failure;
204c2c66affSColin Finck
205c2c66affSColin Finck // Now determine the minimum possible dmSize based on the given fields in dmFields.
206c2c66affSColin Finck wRequiredSize = FIELD_OFFSET(DEVMODEW, dmFields) + RTL_FIELD_SIZE(DEVMODEW, dmFields);
207c2c66affSColin Finck
208c2c66affSColin Finck while (pTable->dwField)
209c2c66affSColin Finck {
210c2c66affSColin Finck if (pDevmode->dmFields & pTable->dwField)
211c2c66affSColin Finck {
212c2c66affSColin Finck wRequiredSize = pTable->wSize;
213c2c66affSColin Finck break;
214c2c66affSColin Finck }
215c2c66affSColin Finck
216c2c66affSColin Finck pTable++;
217c2c66affSColin Finck }
218c2c66affSColin Finck
219c2c66affSColin Finck // Verify that the value in dmSize is big enough for the used fields.
220c2c66affSColin Finck if (pDevmode->dmSize < wRequiredSize)
221c2c66affSColin Finck goto Failure;
222c2c66affSColin Finck
223c2c66affSColin Finck // Check if dmDeviceName and (if used) dmFormName are null-terminated.
224c2c66affSColin Finck // Fix this if they aren't.
225c2c66affSColin Finck _FixStringW(pDevmode->dmDeviceName, sizeof(pDevmode->dmDeviceName));
226c2c66affSColin Finck if (pDevmode->dmFields & DM_FORMNAME)
227c2c66affSColin Finck _FixStringW(pDevmode->dmFormName, sizeof(pDevmode->dmFormName));
228c2c66affSColin Finck
229c2c66affSColin Finck // Return success without setting the error code.
230c2c66affSColin Finck return TRUE;
231c2c66affSColin Finck
232c2c66affSColin Finck Failure:
233c2c66affSColin Finck SetLastError(ERROR_INVALID_DATA);
234c2c66affSColin Finck return FALSE;
235c2c66affSColin Finck }
2363077c0e4SDoug Lyons
2377bffb703SJames Tabor BOOL WINAPI
IsValidDevmodeNoSizeW(PDEVMODEW pDevmode)2387bffb703SJames Tabor IsValidDevmodeNoSizeW(PDEVMODEW pDevmode)
2397bffb703SJames Tabor {
2407bffb703SJames Tabor PMINIMUM_SIZE_TABLE pTable = MinimumSizeW;
2417bffb703SJames Tabor WORD wRequiredSize;
2427bffb703SJames Tabor
2437bffb703SJames Tabor TRACE("IsValidDevmodeNoSizeW(%p)\n", pDevmode);
2447bffb703SJames Tabor
2457bffb703SJames Tabor // Check if a Devmode was given at all.
2467bffb703SJames Tabor if (!pDevmode)
2477bffb703SJames Tabor goto Failure;
2487bffb703SJames Tabor
2497bffb703SJames Tabor // If the structure has private members, the public structure must be 32-bit packed.
2507bffb703SJames Tabor if (pDevmode->dmDriverExtra && pDevmode->dmSize % 4)
2517bffb703SJames Tabor goto Failure;
2527bffb703SJames Tabor
2537bffb703SJames Tabor // Now determine the minimum possible dmSize based on the given fields in dmFields.
2547bffb703SJames Tabor wRequiredSize = FIELD_OFFSET(DEVMODEW, dmFields) + RTL_FIELD_SIZE(DEVMODEW, dmFields);
2557bffb703SJames Tabor
2567bffb703SJames Tabor while (pTable->dwField)
2577bffb703SJames Tabor {
2587bffb703SJames Tabor if (pDevmode->dmFields & pTable->dwField)
2597bffb703SJames Tabor {
2607bffb703SJames Tabor wRequiredSize = pTable->wSize;
2617bffb703SJames Tabor break;
2627bffb703SJames Tabor }
2637bffb703SJames Tabor
2647bffb703SJames Tabor pTable++;
2657bffb703SJames Tabor }
2667bffb703SJames Tabor
2677bffb703SJames Tabor // Verify that the value in dmSize is big enough for the used fields.
2687bffb703SJames Tabor if (pDevmode->dmSize < wRequiredSize)
2697bffb703SJames Tabor goto Failure;
2707bffb703SJames Tabor
2717bffb703SJames Tabor // Check if dmDeviceName and (if used) dmFormName are null-terminated.
2727bffb703SJames Tabor // Fix this if they aren't.
2737bffb703SJames Tabor _FixStringW(pDevmode->dmDeviceName, sizeof(pDevmode->dmDeviceName));
2747bffb703SJames Tabor if (pDevmode->dmFields & DM_FORMNAME)
2757bffb703SJames Tabor _FixStringW(pDevmode->dmFormName, sizeof(pDevmode->dmFormName));
2767bffb703SJames Tabor
2777bffb703SJames Tabor // Return success without setting the error code.
2787bffb703SJames Tabor return TRUE;
2797bffb703SJames Tabor
2807bffb703SJames Tabor Failure:
2817bffb703SJames Tabor SetLastError(ERROR_INVALID_DATA);
2827bffb703SJames Tabor return FALSE;
2837bffb703SJames Tabor }
2847bffb703SJames Tabor
RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput,PDEVMODEW * pDevModeOutput)2857bffb703SJames Tabor void RosConvertAnsiDevModeToUnicodeDevmode(PDEVMODEA pDevModeInput, PDEVMODEW *pDevModeOutput)
2863077c0e4SDoug Lyons {
2873077c0e4SDoug Lyons // FIXME: This function should become ConvertAnsiDevModeToUnicodeDevmode when its parameters are known!
2883077c0e4SDoug Lyons
2893077c0e4SDoug Lyons // Check if a pDevModeInput and pDevModeOutput are both not NULL.
2903077c0e4SDoug Lyons if (!pDevModeInput || !pDevModeOutput)
2913077c0e4SDoug Lyons return;
2923077c0e4SDoug Lyons
2937bffb703SJames Tabor *pDevModeOutput = GdiConvertToDevmodeW(pDevModeInput);
2943077c0e4SDoug Lyons }
2953077c0e4SDoug Lyons
2963077c0e4SDoug Lyons // Internal counterpart to GdiConvertToDevmodeW from gdi32
2973077c0e4SDoug Lyons static __inline DEVMODEA*
_ConvertToDevmodeA(const DEVMODEW * dmW)2983077c0e4SDoug Lyons _ConvertToDevmodeA(const DEVMODEW *dmW)
2993077c0e4SDoug Lyons {
3003077c0e4SDoug Lyons DEVMODEA *dmA;
3013077c0e4SDoug Lyons WORD dmA_size, dmW_size;
3023077c0e4SDoug Lyons size_t BytesToCopy;
3033077c0e4SDoug Lyons
3043077c0e4SDoug Lyons dmW_size = dmW->dmSize;
3053077c0e4SDoug Lyons
3063077c0e4SDoug Lyons /* this is the minimal dmSize that XP accepts */
3073077c0e4SDoug Lyons if (dmW_size < FIELD_OFFSET(DEVMODEW, dmFields))
3083077c0e4SDoug Lyons return NULL;
3093077c0e4SDoug Lyons
3103077c0e4SDoug Lyons // Guard against callers that set dmSize incorrectly.
3113077c0e4SDoug Lyons if (dmW_size > sizeof(DEVMODEW))
3123077c0e4SDoug Lyons dmW_size = sizeof(DEVMODEW);
3133077c0e4SDoug Lyons
3143077c0e4SDoug Lyons // dmA_size must become dmW_size without the additional 1 byte per character for each Unicode string (dmDeviceName and dmFormName).
3153077c0e4SDoug Lyons dmA_size = dmW_size - CCHDEVICENAME;
3163077c0e4SDoug Lyons if (dmW_size >= FIELD_OFFSET(DEVMODEW, dmFormName) + CCHFORMNAME * sizeof(WCHAR))
3173077c0e4SDoug Lyons dmA_size -= CCHFORMNAME;
3183077c0e4SDoug Lyons
3193077c0e4SDoug Lyons // Allocate the required bytes, that is dmSize for the ANSI DEVMODEA structure plus any extra bytes requested through dmDriverExtra.
3203077c0e4SDoug Lyons dmA = HeapAlloc(GetProcessHeap(), 0, dmA_size + dmW->dmDriverExtra);
3213077c0e4SDoug Lyons if (!dmA) return NULL;
3223077c0e4SDoug Lyons
3233077c0e4SDoug Lyons // Every valid DEVMODEW has a dmDeviceName, which we convert to ANSI here.
3243077c0e4SDoug Lyons WideCharToMultiByte(CP_ACP, 0, dmW->dmDeviceName, -1, (LPSTR)dmA->dmDeviceName, CCHDEVICENAME, NULL, NULL);
3253077c0e4SDoug Lyons
3263077c0e4SDoug Lyons // Copy everything up to dmFormName or the remaining dmW_size, whatever is smaller.
3273077c0e4SDoug Lyons BytesToCopy = min(FIELD_OFFSET(DEVMODEW, dmFormName) - FIELD_OFFSET(DEVMODEW, dmSpecVersion), dmW_size - CCHDEVICENAME * sizeof(WCHAR));
3283077c0e4SDoug Lyons memcpy(&dmA->dmSpecVersion, &dmW->dmSpecVersion, BytesToCopy);
3293077c0e4SDoug Lyons
3303077c0e4SDoug Lyons // Handle dmFormName if the input DEVMODEW is large enough to contain one.
3313077c0e4SDoug Lyons if (dmW_size >= FIELD_OFFSET(DEVMODEW, dmFormName) + CCHFORMNAME * sizeof(WCHAR))
3323077c0e4SDoug Lyons {
3333077c0e4SDoug Lyons if (dmW->dmFields & DM_FORMNAME)
3343077c0e4SDoug Lyons WideCharToMultiByte(CP_ACP, 0, dmW->dmFormName, -1, (LPSTR)dmA->dmFormName, CCHFORMNAME, NULL, NULL);
3353077c0e4SDoug Lyons else
3363077c0e4SDoug Lyons dmA->dmFormName[0] = 0;
3373077c0e4SDoug Lyons
3383077c0e4SDoug Lyons // Copy the remaining fields.
3393077c0e4SDoug Lyons if (dmW_size > FIELD_OFFSET(DEVMODEW, dmLogPixels))
3403077c0e4SDoug Lyons memcpy(&dmA->dmLogPixels, &dmW->dmLogPixels, dmW_size - FIELD_OFFSET(DEVMODEW, dmLogPixels));
3413077c0e4SDoug Lyons }
3423077c0e4SDoug Lyons
3433077c0e4SDoug Lyons // Append dmDriverExtra if required.
3443077c0e4SDoug Lyons if (dmW->dmDriverExtra)
3453077c0e4SDoug Lyons memcpy((char *)dmA + dmA_size, (const char *)dmW + dmW_size, dmW->dmDriverExtra);
3463077c0e4SDoug Lyons
3473077c0e4SDoug Lyons // Set the corrected dmSize and we are done.
3483077c0e4SDoug Lyons dmA->dmSize = dmA_size;
3493077c0e4SDoug Lyons
3503077c0e4SDoug Lyons return dmA;
3513077c0e4SDoug Lyons }
3523077c0e4SDoug Lyons
RosConvertUnicodeDevModeToAnsiDevmode(PDEVMODEW pDevModeInput,PDEVMODEA pDevModeOutput)3533077c0e4SDoug Lyons void RosConvertUnicodeDevModeToAnsiDevmode(PDEVMODEW pDevModeInput, PDEVMODEA pDevModeOutput)
3543077c0e4SDoug Lyons {
3557bffb703SJames Tabor PDEVMODEA pTmp;
3567bffb703SJames Tabor
3573077c0e4SDoug Lyons // FIXME: This function should become ConvertUnicodeDevModeToAnsiDevmode when its parameters are known!
3583077c0e4SDoug Lyons
3593077c0e4SDoug Lyons // Check if a pDevModeInput and pDevModeOutput are both not NULL.
3603077c0e4SDoug Lyons if (!pDevModeInput || !pDevModeOutput)
3613077c0e4SDoug Lyons return;
3623077c0e4SDoug Lyons
3637bffb703SJames Tabor pTmp = _ConvertToDevmodeA(pDevModeInput);
3647bffb703SJames Tabor memcpy( pDevModeOutput, pTmp, pTmp->dmSize + pTmp->dmDriverExtra); // Copy into a Wide char (Larger) buffer.
3657bffb703SJames Tabor HeapFree(hProcessHeap, 0, pTmp);
3663077c0e4SDoug Lyons }
367*a2a8ce49STimo Kreuzer
368*a2a8ce49STimo Kreuzer VOID
369*a2a8ce49STimo Kreuzer WINAPI
DeviceMode(PVOID param_1,PVOID param_2,PCHAR param_3,PVOID param_4)370*a2a8ce49STimo Kreuzer DeviceMode(
371*a2a8ce49STimo Kreuzer PVOID param_1,
372*a2a8ce49STimo Kreuzer PVOID param_2,
373*a2a8ce49STimo Kreuzer PCHAR param_3,
374*a2a8ce49STimo Kreuzer PVOID param_4)
375*a2a8ce49STimo Kreuzer {
376*a2a8ce49STimo Kreuzer UNIMPLEMENTED;
377*a2a8ce49STimo Kreuzer }
378*a2a8ce49STimo Kreuzer
379*a2a8ce49STimo Kreuzer LONG
380*a2a8ce49STimo Kreuzer WINAPI
ExtDeviceMode(HWND hWnd,HANDLE hInst,LPDEVMODEA pDevModeOutput,LPSTR pDeviceName,LPSTR pPort,LPDEVMODEA pDevModeInput,LPSTR pProfile,DWORD fMode)381*a2a8ce49STimo Kreuzer ExtDeviceMode(
382*a2a8ce49STimo Kreuzer HWND hWnd,
383*a2a8ce49STimo Kreuzer HANDLE hInst,
384*a2a8ce49STimo Kreuzer LPDEVMODEA pDevModeOutput,
385*a2a8ce49STimo Kreuzer LPSTR pDeviceName,
386*a2a8ce49STimo Kreuzer LPSTR pPort,
387*a2a8ce49STimo Kreuzer LPDEVMODEA pDevModeInput,
388*a2a8ce49STimo Kreuzer LPSTR pProfile,
389*a2a8ce49STimo Kreuzer DWORD fMode)
390*a2a8ce49STimo Kreuzer {
391*a2a8ce49STimo Kreuzer UNIMPLEMENTED;
392*a2a8ce49STimo Kreuzer return 0;
393*a2a8ce49STimo Kreuzer }
394