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