2 * PROJECT: ReactOS Spooler API
3 * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation
4 * PURPOSE: Functions giving information about DEVMODE structures
5 * COPYRIGHT: Copyright 2016 Colin Finck <colin@reactos.org>
10 typedef struct _MINIMUM_SIZE_TABLE
15 MINIMUM_SIZE_TABLE
, *PMINIMUM_SIZE_TABLE
;
18 * Minimum required DEVMODEA structure size based on the used fields. Must be in descending order!
20 static MINIMUM_SIZE_TABLE MinimumSizeA
[] = {
21 { DM_PANNINGHEIGHT
, FIELD_OFFSET(DEVMODEA
, dmPanningHeight
) + RTL_FIELD_SIZE(DEVMODEA
, dmPanningHeight
) },
22 { DM_PANNINGWIDTH
, FIELD_OFFSET(DEVMODEA
, dmPanningWidth
) + RTL_FIELD_SIZE(DEVMODEA
, dmPanningWidth
) },
23 { DM_DITHERTYPE
, FIELD_OFFSET(DEVMODEA
, dmDitherType
) + RTL_FIELD_SIZE(DEVMODEA
, dmDitherType
) },
24 { DM_MEDIATYPE
, FIELD_OFFSET(DEVMODEA
, dmMediaType
) + RTL_FIELD_SIZE(DEVMODEA
, dmMediaType
) },
25 { DM_ICMINTENT
, FIELD_OFFSET(DEVMODEA
, dmICMIntent
) + RTL_FIELD_SIZE(DEVMODEA
, dmICMIntent
) },
26 { DM_ICMMETHOD
, FIELD_OFFSET(DEVMODEA
, dmICMMethod
) + RTL_FIELD_SIZE(DEVMODEA
, dmICMMethod
) },
27 { DM_DISPLAYFREQUENCY
, FIELD_OFFSET(DEVMODEA
, dmDisplayFrequency
) + RTL_FIELD_SIZE(DEVMODEA
, dmDisplayFrequency
) },
28 { DM_NUP
, FIELD_OFFSET(DEVMODEA
, dmNup
) + RTL_FIELD_SIZE(DEVMODEA
, dmNup
) },
29 { DM_DISPLAYFLAGS
, FIELD_OFFSET(DEVMODEA
, dmDisplayFlags
) + RTL_FIELD_SIZE(DEVMODEA
, dmDisplayFlags
) },
30 { DM_PELSHEIGHT
, FIELD_OFFSET(DEVMODEA
, dmPelsHeight
) + RTL_FIELD_SIZE(DEVMODEA
, dmPelsHeight
) },
31 { DM_PELSWIDTH
, FIELD_OFFSET(DEVMODEA
, dmPelsWidth
) + RTL_FIELD_SIZE(DEVMODEA
, dmPelsWidth
) },
32 { DM_BITSPERPEL
, FIELD_OFFSET(DEVMODEA
, dmBitsPerPel
) + RTL_FIELD_SIZE(DEVMODEA
, dmBitsPerPel
) },
33 { DM_LOGPIXELS
, FIELD_OFFSET(DEVMODEA
, dmLogPixels
) + RTL_FIELD_SIZE(DEVMODEA
, dmLogPixels
) },
34 { DM_FORMNAME
, FIELD_OFFSET(DEVMODEA
, dmFormName
) + RTL_FIELD_SIZE(DEVMODEA
, dmFormName
) },
35 { DM_COLLATE
, FIELD_OFFSET(DEVMODEA
, dmCollate
) + RTL_FIELD_SIZE(DEVMODEA
, dmCollate
) },
36 { DM_TTOPTION
, FIELD_OFFSET(DEVMODEA
, dmTTOption
) + RTL_FIELD_SIZE(DEVMODEA
, dmTTOption
) },
37 { DM_YRESOLUTION
, FIELD_OFFSET(DEVMODEA
, dmYResolution
) + RTL_FIELD_SIZE(DEVMODEA
, dmYResolution
) },
38 { DM_DUPLEX
, FIELD_OFFSET(DEVMODEA
, dmDuplex
) + RTL_FIELD_SIZE(DEVMODEA
, dmDuplex
) },
39 { DM_COLOR
, FIELD_OFFSET(DEVMODEA
, dmColor
) + RTL_FIELD_SIZE(DEVMODEA
, dmColor
) },
40 { DM_DISPLAYFIXEDOUTPUT
, FIELD_OFFSET(DEVMODEA
, dmDisplayFixedOutput
) + RTL_FIELD_SIZE(DEVMODEA
, dmDisplayFixedOutput
) },
41 { DM_DISPLAYORIENTATION
, FIELD_OFFSET(DEVMODEA
, dmDisplayOrientation
) + RTL_FIELD_SIZE(DEVMODEA
, dmDisplayOrientation
) },
42 { DM_POSITION
, FIELD_OFFSET(DEVMODEA
, dmPosition
) + RTL_FIELD_SIZE(DEVMODEA
, dmPosition
) },
43 { DM_PRINTQUALITY
, FIELD_OFFSET(DEVMODEA
, dmPrintQuality
) + RTL_FIELD_SIZE(DEVMODEA
, dmPrintQuality
) },
44 { DM_DEFAULTSOURCE
, FIELD_OFFSET(DEVMODEA
, dmDefaultSource
) + RTL_FIELD_SIZE(DEVMODEA
, dmDefaultSource
) },
45 { DM_COPIES
, FIELD_OFFSET(DEVMODEA
, dmCopies
) + RTL_FIELD_SIZE(DEVMODEA
, dmCopies
) },
46 { DM_SCALE
, FIELD_OFFSET(DEVMODEA
, dmScale
) + RTL_FIELD_SIZE(DEVMODEA
, dmScale
) },
47 { DM_PAPERWIDTH
, FIELD_OFFSET(DEVMODEA
, dmPaperWidth
) + RTL_FIELD_SIZE(DEVMODEA
, dmPaperWidth
) },
48 { DM_PAPERLENGTH
, FIELD_OFFSET(DEVMODEA
, dmPaperLength
) + RTL_FIELD_SIZE(DEVMODEA
, dmPaperLength
) },
49 { DM_PAPERSIZE
, FIELD_OFFSET(DEVMODEA
, dmPaperSize
) + RTL_FIELD_SIZE(DEVMODEA
, dmPaperSize
) },
50 { DM_ORIENTATION
, FIELD_OFFSET(DEVMODEA
, dmOrientation
) + RTL_FIELD_SIZE(DEVMODEA
, dmOrientation
) },
55 * Minimum required DEVMODEW structure size based on the used fields. Must be in descending order!
57 static MINIMUM_SIZE_TABLE MinimumSizeW
[] = {
58 { DM_PANNINGHEIGHT
, FIELD_OFFSET(DEVMODEW
, dmPanningHeight
) + RTL_FIELD_SIZE(DEVMODEW
, dmPanningHeight
) },
59 { DM_PANNINGWIDTH
, FIELD_OFFSET(DEVMODEW
, dmPanningWidth
) + RTL_FIELD_SIZE(DEVMODEW
, dmPanningWidth
) },
60 { DM_DITHERTYPE
, FIELD_OFFSET(DEVMODEW
, dmDitherType
) + RTL_FIELD_SIZE(DEVMODEW
, dmDitherType
) },
61 { DM_MEDIATYPE
, FIELD_OFFSET(DEVMODEW
, dmMediaType
) + RTL_FIELD_SIZE(DEVMODEW
, dmMediaType
) },
62 { DM_ICMINTENT
, FIELD_OFFSET(DEVMODEW
, dmICMIntent
) + RTL_FIELD_SIZE(DEVMODEW
, dmICMIntent
) },
63 { DM_ICMMETHOD
, FIELD_OFFSET(DEVMODEW
, dmICMMethod
) + RTL_FIELD_SIZE(DEVMODEW
, dmICMMethod
) },
64 { DM_DISPLAYFREQUENCY
, FIELD_OFFSET(DEVMODEW
, dmDisplayFrequency
) + RTL_FIELD_SIZE(DEVMODEW
, dmDisplayFrequency
) },
65 { DM_NUP
, FIELD_OFFSET(DEVMODEW
, dmNup
) + RTL_FIELD_SIZE(DEVMODEW
, dmNup
) },
66 { DM_DISPLAYFLAGS
, FIELD_OFFSET(DEVMODEW
, dmDisplayFlags
) + RTL_FIELD_SIZE(DEVMODEW
, dmDisplayFlags
) },
67 { DM_PELSHEIGHT
, FIELD_OFFSET(DEVMODEW
, dmPelsHeight
) + RTL_FIELD_SIZE(DEVMODEW
, dmPelsHeight
) },
68 { DM_PELSWIDTH
, FIELD_OFFSET(DEVMODEW
, dmPelsWidth
) + RTL_FIELD_SIZE(DEVMODEW
, dmPelsWidth
) },
69 { DM_BITSPERPEL
, FIELD_OFFSET(DEVMODEW
, dmBitsPerPel
) + RTL_FIELD_SIZE(DEVMODEW
, dmBitsPerPel
) },
70 { DM_LOGPIXELS
, FIELD_OFFSET(DEVMODEW
, dmLogPixels
) + RTL_FIELD_SIZE(DEVMODEW
, dmLogPixels
) },
71 { DM_FORMNAME
, FIELD_OFFSET(DEVMODEW
, dmFormName
) + RTL_FIELD_SIZE(DEVMODEW
, dmFormName
) },
72 { DM_COLLATE
, FIELD_OFFSET(DEVMODEW
, dmCollate
) + RTL_FIELD_SIZE(DEVMODEW
, dmCollate
) },
73 { DM_TTOPTION
, FIELD_OFFSET(DEVMODEW
, dmTTOption
) + RTL_FIELD_SIZE(DEVMODEW
, dmTTOption
) },
74 { DM_YRESOLUTION
, FIELD_OFFSET(DEVMODEW
, dmYResolution
) + RTL_FIELD_SIZE(DEVMODEW
, dmYResolution
) },
75 { DM_DUPLEX
, FIELD_OFFSET(DEVMODEW
, dmDuplex
) + RTL_FIELD_SIZE(DEVMODEW
, dmDuplex
) },
76 { DM_COLOR
, FIELD_OFFSET(DEVMODEW
, dmColor
) + RTL_FIELD_SIZE(DEVMODEW
, dmColor
) },
77 { DM_DISPLAYFIXEDOUTPUT
, FIELD_OFFSET(DEVMODEW
, dmDisplayFixedOutput
) + RTL_FIELD_SIZE(DEVMODEW
, dmDisplayFixedOutput
) },
78 { DM_DISPLAYORIENTATION
, FIELD_OFFSET(DEVMODEW
, dmDisplayOrientation
) + RTL_FIELD_SIZE(DEVMODEW
, dmDisplayOrientation
) },
79 { DM_POSITION
, FIELD_OFFSET(DEVMODEW
, dmPosition
) + RTL_FIELD_SIZE(DEVMODEW
, dmPosition
) },
80 { DM_PRINTQUALITY
, FIELD_OFFSET(DEVMODEW
, dmPrintQuality
) + RTL_FIELD_SIZE(DEVMODEW
, dmPrintQuality
) },
81 { DM_DEFAULTSOURCE
, FIELD_OFFSET(DEVMODEW
, dmDefaultSource
) + RTL_FIELD_SIZE(DEVMODEW
, dmDefaultSource
) },
82 { DM_COPIES
, FIELD_OFFSET(DEVMODEW
, dmCopies
) + RTL_FIELD_SIZE(DEVMODEW
, dmCopies
) },
83 { DM_SCALE
, FIELD_OFFSET(DEVMODEW
, dmScale
) + RTL_FIELD_SIZE(DEVMODEW
, dmScale
) },
84 { DM_PAPERWIDTH
, FIELD_OFFSET(DEVMODEW
, dmPaperWidth
) + RTL_FIELD_SIZE(DEVMODEW
, dmPaperWidth
) },
85 { DM_PAPERLENGTH
, FIELD_OFFSET(DEVMODEW
, dmPaperLength
) + RTL_FIELD_SIZE(DEVMODEW
, dmPaperLength
) },
86 { DM_PAPERSIZE
, FIELD_OFFSET(DEVMODEW
, dmPaperSize
) + RTL_FIELD_SIZE(DEVMODEW
, dmPaperSize
) },
87 { DM_ORIENTATION
, FIELD_OFFSET(DEVMODEW
, dmOrientation
) + RTL_FIELD_SIZE(DEVMODEW
, dmOrientation
) },
92 * Replace the last character by a null terminator if the given ANSI string is not null-terminated.
95 _FixStringA(PBYTE String
, DWORD cbString
)
97 const PBYTE pLastCharacter
= &String
[cbString
/ sizeof(BYTE
) - 1];
102 if (p
== pLastCharacter
)
113 * Replace the last character by a null terminator if the given Unicode string is not null-terminated.
116 _FixStringW(PWSTR String
, DWORD cbString
)
118 const PWSTR pLastCharacter
= &String
[cbString
/ sizeof(WCHAR
) - 1];
123 if (p
== pLastCharacter
)
134 IsValidDevmodeA(PDEVMODEA pDevmode
, size_t DevmodeSize
)
136 PMINIMUM_SIZE_TABLE pTable
= MinimumSizeA
;
139 // Check if a Devmode was given at all.
143 // Verify that DevmodeSize is large enough to hold the public and private members of the structure.
144 if (DevmodeSize
< pDevmode
->dmSize
+ pDevmode
->dmDriverExtra
)
147 // If the structure has private members, the public structure must be 32-bit packed.
148 if (pDevmode
->dmDriverExtra
&& pDevmode
->dmSize
% 4)
151 // Now determine the minimum possible dmSize based on the given fields in dmFields.
152 wRequiredSize
= FIELD_OFFSET(DEVMODEA
, dmFields
) + RTL_FIELD_SIZE(DEVMODEA
, dmFields
);
154 while (pTable
->dwField
)
156 if (pDevmode
->dmFields
& pTable
->dwField
)
158 wRequiredSize
= pTable
->wSize
;
165 // Verify that the value in dmSize is big enough for the used fields.
166 if (pDevmode
->dmSize
< wRequiredSize
)
169 // Check if dmDeviceName and (if used) dmFormName are null-terminated.
170 // Fix this if they aren't.
171 _FixStringA(pDevmode
->dmDeviceName
, sizeof(pDevmode
->dmDeviceName
));
172 if (pDevmode
->dmFields
& DM_FORMNAME
)
173 _FixStringA(pDevmode
->dmFormName
, sizeof(pDevmode
->dmFormName
));
175 // Return success without setting the error code.
179 SetLastError(ERROR_INVALID_DATA
);
184 IsValidDevmodeW(PDEVMODEW pDevmode
, size_t DevmodeSize
)
186 PMINIMUM_SIZE_TABLE pTable
= MinimumSizeW
;
189 // Check if a Devmode was given at all.
193 // Verify that DevmodeSize is large enough to hold the public and private members of the structure.
194 if (DevmodeSize
< pDevmode
->dmSize
+ pDevmode
->dmDriverExtra
)
197 // If the structure has private members, the public structure must be 32-bit packed.
198 if (pDevmode
->dmDriverExtra
&& pDevmode
->dmSize
% 4)
201 // Now determine the minimum possible dmSize based on the given fields in dmFields.
202 wRequiredSize
= FIELD_OFFSET(DEVMODEW
, dmFields
) + RTL_FIELD_SIZE(DEVMODEW
, dmFields
);
204 while (pTable
->dwField
)
206 if (pDevmode
->dmFields
& pTable
->dwField
)
208 wRequiredSize
= pTable
->wSize
;
215 // Verify that the value in dmSize is big enough for the used fields.
216 if (pDevmode
->dmSize
< wRequiredSize
)
219 // Check if dmDeviceName and (if used) dmFormName are null-terminated.
220 // Fix this if they aren't.
221 _FixStringW(pDevmode
->dmDeviceName
, sizeof(pDevmode
->dmDeviceName
));
222 if (pDevmode
->dmFields
& DM_FORMNAME
)
223 _FixStringW(pDevmode
->dmFormName
, sizeof(pDevmode
->dmFormName
));
225 // Return success without setting the error code.
229 SetLastError(ERROR_INVALID_DATA
);