[PRINTING] Implement the undocumented MarshallDownStructure, MarshallDownStructuresAr...
[reactos.git] / win32ss / printing / base / marshalling.c
1 /*
2 * PROJECT: ReactOS Printing Stack Marshalling Functions
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Marshalling functions
5 * COPYRIGHT: Copyright 2015-2018 Colin Finck (colin@reactos.org)
6 */
7
8
9 /**
10 * @name MarshallDownStructure
11 *
12 * Prepare a structure for marshalling/serialization by replacing absolute pointer addresses in its fields by relative offsets.
13 *
14 * @param pStructure
15 * Pointer to the structure to operate on.
16 *
17 * @param pInfo
18 * Array of MARSHALLING_INFO elements containing information about the fields of the structure as well as how to modify them.
19 * See the documentation on MARSHALLING_INFO for more information.
20 * You have to indicate the end of the array by setting the dwOffset field to MAXDWORD.
21 *
22 * @param cbStructureSize
23 * Size in bytes of the structure.
24 * This parameter is unused in my implementation.
25 *
26 * @param bSomeBoolean
27 * Unknown boolean value, set to TRUE.
28 *
29 * @return
30 * TRUE if the structure was successfully adjusted, FALSE otherwise.
31 */
32 BOOL WINAPI
33 MarshallDownStructure(PVOID pStructure, const MARSHALLING_INFO* pInfo, DWORD cbStructureSize, BOOL bSomeBoolean)
34 {
35 // Sanity checks
36 if (!pStructure || !pInfo)
37 {
38 SetLastError(ERROR_INVALID_PARAMETER);
39 return FALSE;
40 }
41
42 // Loop until we reach an element with offset set to MAXDWORD.
43 while (pInfo->dwOffset != MAXDWORD)
44 {
45 PULONG_PTR pCurrentField = (PULONG_PTR)((PBYTE)pStructure + pInfo->dwOffset);
46
47 if (pInfo->bAdjustAddress && *pCurrentField)
48 {
49 // Make a relative offset out of the absolute pointer address.
50 *pCurrentField -= (ULONG_PTR)pStructure;
51 }
52
53 // Advance to the next field description.
54 pInfo++;
55 }
56
57 return TRUE;
58 }
59
60 /**
61 * @name MarshallDownStructuresArray
62 *
63 * Prepare an array of structures for marshalling/serialization by replacing absolute pointer addresses in its fields by relative offsets.
64 *
65 * @param pStructuresArray
66 * Pointer to the array of structures to operate on.
67 *
68 * @param cElements
69 * Number of array elements.
70 *
71 * @param pInfo
72 * Array of MARSHALLING_INFO elements containing information about the fields of the structure as well as how to modify them.
73 * See the documentation on MARSHALLING_INFO for more information.
74 * You have to indicate the end of the array by setting the dwOffset field to MAXDWORD.
75 *
76 * @param cbStructureSize
77 * Size in bytes of each structure array element.
78 *
79 * @param bSomeBoolean
80 * Unknown boolean value, set to TRUE.
81 *
82 * @return
83 * TRUE if the array was successfully adjusted, FALSE otherwise.
84 */
85 BOOL WINAPI
86 MarshallDownStructuresArray(PVOID pStructuresArray, DWORD cElements, const MARSHALLING_INFO* pInfo, DWORD cbStructureSize, BOOL bSomeBoolean)
87 {
88 PBYTE pCurrentElement = pStructuresArray;
89
90 // Call MarshallDownStructure on all array elements given by cElements of cbStructureSize.
91 while (cElements--)
92 {
93 if (!MarshallDownStructure(pCurrentElement, pInfo, cbStructureSize, bSomeBoolean))
94 return FALSE;
95
96 // Advance to the next array element.
97 pCurrentElement += cbStructureSize;
98 }
99
100 return TRUE;
101 }
102
103 /**
104 * @name MarshallUpStructure
105 *
106 * Unmarshall/deserialize a structure previuosly marshalled by MarshallDownStructure by replacing relative offsets in its fields
107 * by absolute pointer addresses again.
108 *
109 * @param cbSize
110 * Size in bytes of the memory allocated for both the structure and its data.
111 * The function will check if all relative offsets are within the bounds given by this size.
112 *
113 * @param pStructure
114 * Pointer to the structure to operate on.
115 *
116 * @param pInfo
117 * Array of MARSHALLING_INFO elements containing information about the fields of the structure as well as how to modify them.
118 * See the documentation on MARSHALLING_INFO for more information.
119 * You have to indicate the end of the array by setting the dwOffset field to MAXDWORD.
120 *
121 * @param cbStructureSize
122 * Size in bytes of the structure.
123 * This parameter is unused in my implementation.
124 *
125 * @param bSomeBoolean
126 * Unknown boolean value, set to TRUE.
127 *
128 * @return
129 * TRUE if the structure was successfully adjusted, FALSE otherwise.
130 */
131 BOOL WINAPI
132 MarshallUpStructure(DWORD cbSize, PVOID pStructure, const MARSHALLING_INFO* pInfo, DWORD cbStructureSize, BOOL bSomeBoolean)
133 {
134 // Sanity checks
135 if (!pStructure || !pInfo)
136 {
137 SetLastError(ERROR_INVALID_PARAMETER);
138 return FALSE;
139 }
140
141 // Loop until we reach an element with offset set to MAXDWORD.
142 while (pInfo->dwOffset != MAXDWORD)
143 {
144 PULONG_PTR pCurrentField = (PULONG_PTR)((PBYTE)pStructure + pInfo->dwOffset);
145
146 if (pInfo->bAdjustAddress && *pCurrentField)
147 {
148 // Verify that the offset in the current field is within the bounds given by cbSize.
149 if (cbSize <= *pCurrentField)
150 {
151 SetLastError(ERROR_INVALID_DATA);
152 return FALSE;
153 }
154
155 // Make an absolute pointer address out of the relative offset.
156 *pCurrentField += (ULONG_PTR)pStructure;
157 }
158
159 // Advance to the next field description.
160 pInfo++;
161 }
162
163 return TRUE;
164 }
165
166 /**
167 * @name MarshallUpStructuresArray
168 *
169 * Unmarshall/deserialize an array of structures previuosly marshalled by MarshallDownStructuresArray by replacing relative offsets
170 * in its fields by absolute pointer addresses again.
171 *
172 * @param cbSize
173 * Size in bytes of the memory allocated for the entire structure array and its data.
174 * The function will check if all relative offsets are within the bounds given by this size.
175 *
176 * @param pStructuresArray
177 * Pointer to the array of structures to operate on.
178 *
179 * @param cElements
180 * Number of array elements.
181 *
182 * @param pInfo
183 * Array of MARSHALLING_INFO elements containing information about the fields of the structure as well as how to modify them.
184 * See the documentation on MARSHALLING_INFO for more information.
185 * You have to indicate the end of the array by setting the dwOffset field to MAXDWORD.
186 *
187 * @param cbStructureSize
188 * Size in bytes of each structure array element.
189 *
190 * @param bSomeBoolean
191 * Unknown boolean value, set to TRUE.
192 *
193 * @return
194 * TRUE if the array was successfully adjusted, FALSE otherwise.
195 */
196 BOOL WINAPI
197 MarshallUpStructuresArray(DWORD cbSize, PVOID pStructuresArray, DWORD cElements, const MARSHALLING_INFO* pInfo, DWORD cbStructureSize, BOOL bSomeBoolean)
198 {
199 PBYTE pCurrentElement = pStructuresArray;
200
201 // Call MarshallUpStructure on all array elements given by cElements of cbStructureSize.
202 while (cElements--)
203 {
204 if (!MarshallUpStructure(cbSize, pCurrentElement, pInfo, cbStructureSize, bSomeBoolean))
205 return FALSE;
206
207 // Advance to the next array element.
208 pCurrentElement += cbStructureSize;
209 }
210
211 return TRUE;
212 }