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