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