Reactos

[PRINTING] Implement the undocumented MarshallDownStructure, MarshallDownStructuresArray, MarshallUpStructure, and MarshallUpStructuresArray to the extent I need and could find out through black-box testing.

PDBs reveal that these functions are also used in winspool.drv, but not imported from spoolss.dll to retain the client/server architecture.
As winspool.drv highly benefits from the MarshallUp* functions, I put them in a source file shared between spoolss.dll and winspool.drv.

The added API Tests cover my testing and all implemented features.
One more item done from https://reactos.org/wiki/Printing !

+445 -55
+2
modules/rostests/apitests/spoolss/CMakeLists.txt
··· 3 3 4 4 list(APPEND SOURCE 5 5 AlignRpcPtr.c 6 + MarshallDownStructuresArray.c 7 + MarshallUpStructuresArray.c 6 8 PackStrings.c 7 9 ReallocSplStr.c 8 10 SplInitializeWinSpoolDrv.c
+118
modules/rostests/apitests/spoolss/MarshallDownStructuresArray.c
··· 1 + /* 2 + * PROJECT: ReactOS Spooler Router API Tests 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Tests for MarshallDownStructuresArray 5 + * COPYRIGHT: Copyright 2018 Colin Finck (colin@reactos.org) 6 + */ 7 + 8 + #include <apitest.h> 9 + 10 + #define WIN32_NO_STATUS 11 + #include <windef.h> 12 + #include <winbase.h> 13 + #include <wingdi.h> 14 + #include <winspool.h> 15 + #include <ndk/rtlfuncs.h> 16 + 17 + #include <spoolss.h> 18 + #include <marshalling/marshalling.h> 19 + #include <marshalling/ports.h> 20 + 21 + START_TEST(MarshallDownStructuresArray) 22 + { 23 + const DWORD cElements = 2; 24 + const DWORD dwPortInfo2Offsets[] = { 25 + FIELD_OFFSET(PORT_INFO_2W, pPortName), 26 + FIELD_OFFSET(PORT_INFO_2W, pMonitorName), 27 + FIELD_OFFSET(PORT_INFO_2W, pDescription), 28 + MAXDWORD 29 + }; 30 + 31 + PPORT_INFO_2W pPortInfo2; 32 + PPORT_INFO_2W pPortInfo2Copy; 33 + PPORT_INFO_2W pPortInfo2Test; 34 + PBYTE pPortInfoEnd; 35 + PWSTR pwszStrings[] = { L"PortName", L"MonitorName", L"Description" }; 36 + DWORD cbPortInfo2Size = cElements * (sizeof(PORT_INFO_2W) + (wcslen(pwszStrings[0]) + 1 + wcslen(pwszStrings[1]) + 1 + wcslen(pwszStrings[2]) + 1) * sizeof(WCHAR)); 37 + DWORD fPortType = 1337; 38 + DWORD Reserved = 42; 39 + 40 + // Setting cElements to zero should yield success. 41 + SetLastError(0xDEADBEEF); 42 + ok(MarshallDownStructuresArray(NULL, 0, NULL, 0, FALSE), "MarshallDownStructuresArray returns FALSE!\n"); 43 + ok(GetLastError() == 0xDEADBEEF, "GetLastError returns %lu!\n", GetLastError()); 44 + 45 + // Setting cElements non-zero should fail with ERROR_INVALID_PARAMETER. 46 + SetLastError(0xDEADBEEF); 47 + ok(!MarshallDownStructuresArray(NULL, 1, NULL, 0, FALSE), "MarshallDownStructuresArray returns TRUE!\n"); 48 + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError returns %lu!\n", GetLastError()); 49 + 50 + // This is triggered by both pStructuresArray and pInfo. 51 + SetLastError(0xDEADBEEF); 52 + ok(!MarshallDownStructuresArray((PVOID)0xDEADDEAD, 1, NULL, 0, FALSE), "MarshallDownStructuresArray returns TRUE!\n"); 53 + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError returns %lu!\n", GetLastError()); 54 + 55 + SetLastError(0xDEADBEEF); 56 + ok(!MarshallDownStructuresArray(NULL, 1, (const MARSHALLING_INFO*)0xDEADDEAD, 0, FALSE), "MarshallDownStructuresArray returns TRUE!\n"); 57 + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError returns %lu!\n", GetLastError()); 58 + 59 + // Now create two PORT_INFO_2W structures. 60 + pPortInfo2 = (PPORT_INFO_2W)HeapAlloc(GetProcessHeap(), 0, cbPortInfo2Size); 61 + pPortInfoEnd = (PBYTE)pPortInfo2 + cbPortInfo2Size; 62 + 63 + (&pPortInfo2[0])->fPortType = fPortType; 64 + (&pPortInfo2[0])->Reserved = Reserved; 65 + pPortInfoEnd = PackStrings(pwszStrings, (PBYTE)(&pPortInfo2[0]), dwPortInfo2Offsets, pPortInfoEnd); 66 + 67 + (&pPortInfo2[1])->fPortType = fPortType + 1; 68 + (&pPortInfo2[1])->Reserved = Reserved + 1; 69 + pPortInfoEnd = PackStrings(pwszStrings, (PBYTE)(&pPortInfo2[1]), dwPortInfo2Offsets, pPortInfoEnd); 70 + 71 + // Create a backup. 72 + pPortInfo2Copy = (PPORT_INFO_2W)HeapAlloc(GetProcessHeap(), 0, cbPortInfo2Size); 73 + CopyMemory(pPortInfo2Copy, pPortInfo2, cbPortInfo2Size); 74 + 75 + // Marshall them down. 76 + SetLastError(0xDEADBEEF); 77 + ok(MarshallDownStructuresArray(pPortInfo2, cElements, PortInfo2Marshalling.pInfo, PortInfo2Marshalling.cbStructureSize, TRUE), "MarshallDownStructuresArray returns FALSE!\n"); 78 + ok(GetLastError() == 0xDEADBEEF, "GetLastError returns %lu!\n", GetLastError()); 79 + 80 + // DWORD values should be unchanged. 81 + ok((&pPortInfo2[0])->fPortType == fPortType, "fPortType is %lu!\n", (&pPortInfo2[0])->fPortType); 82 + ok((&pPortInfo2[0])->Reserved == Reserved, "Reserved is %lu!\n", (&pPortInfo2[0])->Reserved); 83 + ok((&pPortInfo2[1])->fPortType == fPortType + 1, "fPortType is %lu!\n", (&pPortInfo2[1])->fPortType); 84 + ok((&pPortInfo2[1])->Reserved == Reserved + 1, "Reserved is %lu!\n", (&pPortInfo2[1])->Reserved); 85 + 86 + // Pointers should now contain relative offsets. 87 + ok((ULONG_PTR)(&pPortInfo2[0])->pPortName == ((ULONG_PTR)(&pPortInfo2Copy[0])->pPortName - (ULONG_PTR)(&pPortInfo2[0])), "pPortName is %p!\n", (&pPortInfo2[0])->pPortName); 88 + ok((ULONG_PTR)(&pPortInfo2[0])->pMonitorName == ((ULONG_PTR)(&pPortInfo2Copy[0])->pMonitorName - (ULONG_PTR)(&pPortInfo2[0])), "pMonitorName is %p!\n", (&pPortInfo2[0])->pMonitorName); 89 + ok((ULONG_PTR)(&pPortInfo2[0])->pDescription == ((ULONG_PTR)(&pPortInfo2Copy[0])->pDescription - (ULONG_PTR)(&pPortInfo2[0])), "pDescription is %p!\n", (&pPortInfo2[0])->pDescription); 90 + ok((ULONG_PTR)(&pPortInfo2[1])->pPortName == ((ULONG_PTR)(&pPortInfo2Copy[1])->pPortName - (ULONG_PTR)(&pPortInfo2[1])), "pPortName is %p!\n", (&pPortInfo2[1])->pPortName); 91 + ok((ULONG_PTR)(&pPortInfo2[1])->pMonitorName == ((ULONG_PTR)(&pPortInfo2Copy[1])->pMonitorName - (ULONG_PTR)(&pPortInfo2[1])), "pMonitorName is %p!\n", (&pPortInfo2[1])->pMonitorName); 92 + ok((ULONG_PTR)(&pPortInfo2[1])->pDescription == ((ULONG_PTR)(&pPortInfo2Copy[1])->pDescription - (ULONG_PTR)(&pPortInfo2[1])), "pDescription is %p!\n", (&pPortInfo2[1])->pDescription); 93 + 94 + // Marshall them up again. 95 + // We need a backup of the marshalled down array to experiment with MarshallUpStructuresArray. 96 + pPortInfo2Test = (PPORT_INFO_2W)HeapAlloc(GetProcessHeap(), 0, cbPortInfo2Size); 97 + CopyMemory(pPortInfo2Test, pPortInfo2, cbPortInfo2Size); 98 + 99 + // Due to the implementation of PackStrings, (&pPortInfo2[0])->pPortName contains the highest offset. 100 + // Show that MarshallUpStructuresArray checks the offsets and bails out with ERROR_INVALID_DATA if cbSize <= highest offset. 101 + SetLastError(0xDEADBEEF); 102 + ok(!MarshallUpStructuresArray((DWORD)(&pPortInfo2[0])->pPortName, pPortInfo2Test, cElements, PortInfo2Marshalling.pInfo, PortInfo2Marshalling.cbStructureSize, TRUE), "MarshallUpStructuresArray returns TRUE!\n"); 103 + ok(GetLastError() == ERROR_INVALID_DATA, "GetLastError returns %lu!\n", GetLastError()); 104 + 105 + // It works with cbSize > highest offset. 106 + // In real world cases, we would use cbPortInfo2Size for cbSize. 107 + SetLastError(0xDEADBEEF); 108 + ok(MarshallUpStructuresArray((DWORD)(&pPortInfo2[0])->pPortName + 1, pPortInfo2, cElements, PortInfo2Marshalling.pInfo, PortInfo2Marshalling.cbStructureSize, TRUE), "MarshallUpStructuresArray returns FALSE!\n"); 109 + ok(GetLastError() == 0xDEADBEEF, "GetLastError returns %lu!\n", GetLastError()); 110 + 111 + // pPortInfo2 should now be identical to the copy again. 112 + ok(RtlEqualMemory(pPortInfo2, pPortInfo2Copy, cbPortInfo2Size), "pPortInfo2 and pPortInfo2Copy are not equal after marshalling down and up!\n"); 113 + 114 + // Free all memory. 115 + HeapFree(GetProcessHeap(), 0, pPortInfo2); 116 + HeapFree(GetProcessHeap(), 0, pPortInfo2Copy); 117 + HeapFree(GetProcessHeap(), 0, pPortInfo2Test); 118 + }
+37
modules/rostests/apitests/spoolss/MarshallUpStructuresArray.c
··· 1 + /* 2 + * PROJECT: ReactOS Spooler Router API Tests 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Tests for MarshallUpStructuresArray 5 + * COPYRIGHT: Copyright 2018 Colin Finck (colin@reactos.org) 6 + */ 7 + 8 + #include <apitest.h> 9 + 10 + #define WIN32_NO_STATUS 11 + #include <windef.h> 12 + #include <winbase.h> 13 + #include <marshalling/marshalling.h> 14 + 15 + START_TEST(MarshallUpStructuresArray) 16 + { 17 + // Setting cElements to zero should yield success. 18 + SetLastError(0xDEADBEEF); 19 + ok(MarshallUpStructuresArray(0, NULL, 0, NULL, 0, FALSE), "MarshallUpStructuresArray returns FALSE!\n"); 20 + ok(GetLastError() == 0xDEADBEEF, "GetLastError returns %lu!\n", GetLastError()); 21 + 22 + // Setting cElements non-zero should fail with ERROR_INVALID_PARAMETER. 23 + SetLastError(0xDEADBEEF); 24 + ok(!MarshallUpStructuresArray(0, NULL, 1, NULL, 0, FALSE), "MarshallUpStructuresArray returns TRUE!\n"); 25 + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError returns %lu!\n", GetLastError()); 26 + 27 + // This is triggered by both pStructuresArray and pInfo. 28 + SetLastError(0xDEADBEEF); 29 + ok(!MarshallUpStructuresArray(0, (PVOID)0xDEADDEAD, 1, NULL, 0, FALSE), "MarshallUpStructuresArray returns TRUE!\n"); 30 + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError returns %lu!\n", GetLastError()); 31 + 32 + SetLastError(0xDEADBEEF); 33 + ok(!MarshallUpStructuresArray(0, NULL, 1, (const MARSHALLING_INFO*)0xDEADDEAD, 0, FALSE), "MarshallUpStructuresArray returns TRUE!\n"); 34 + ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError returns %lu!\n", GetLastError()); 35 + 36 + // More testing is conducted in the MarshallDownStructuresArray test. 37 + }
+5 -1
modules/rostests/apitests/spoolss/testlist.c
··· 2 2 * PROJECT: ReactOS Spooler Router API Tests 3 3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 4 * PURPOSE: Test list 5 - * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org) 5 + * COPYRIGHT: Copyright 2015-2018 Colin Finck (colin@reactos.org) 6 6 */ 7 7 8 8 #define __ROS_LONG64__ ··· 11 11 #include <apitest.h> 12 12 13 13 extern void func_AlignRpcPtr(void); 14 + extern void func_MarshallDownStructuresArray(void); 15 + extern void func_MarshallUpStructuresArray(void); 14 16 extern void func_PackStrings(void); 15 17 extern void func_ReallocSplStr(void); 16 18 extern void func_SplInitializeWinSpoolDrv(void); ··· 18 20 const struct test winetest_testlist[] = 19 21 { 20 22 { "AlignRpcPtr", func_AlignRpcPtr }, 23 + { "MarshallDownStructuresArray", func_MarshallDownStructuresArray }, 24 + { "MarshallUpStructuresArray", func_MarshallUpStructuresArray }, 21 25 { "PackStrings", func_PackStrings }, 22 26 { "ReallocSplStr", func_ReallocSplStr }, 23 27 { "SplInitializeWinSpoolDrv", func_SplInitializeWinSpoolDrv },
+212
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 + }
+1
win32ss/printing/base/spoolss/CMakeLists.txt
··· 2 2 spec2def(spoolss.dll spoolss.spec ADD_IMPORTLIB) 3 3 4 4 list(APPEND SOURCE 5 + ../marshalling.c 5 6 context.c 6 7 jobs.c 7 8 main.c
+1
win32ss/printing/base/spoolss/precomp.h
··· 18 18 #include <ndk/rtlfuncs.h> 19 19 20 20 #include <spoolss.h> 21 + #include <marshalling/marshalling.h> 21 22 22 23 #include <wine/debug.h> 23 24 WINE_DEFAULT_DEBUG_CHANNEL(spoolss);
+3 -3
win32ss/printing/base/spoolss/spoolss.spec
··· 97 97 @ stub LoadDriverWithVersion 98 98 @ stub LogWmiTraceEvent 99 99 @ stdcall MarshallDownStructure(ptr ptr long long) 100 - @ stub MarshallDownStructuresArray 101 - @ stub MarshallUpStructure 102 - @ stub MarshallUpStructuresArray 100 + @ stdcall MarshallDownStructuresArray(ptr long ptr long long) 101 + @ stdcall MarshallUpStructure(long ptr ptr long long) 102 + @ stdcall MarshallUpStructuresArray(long ptr long ptr long long) 103 103 @ stub MIDL_user_allocate1 104 104 @ stub MIDL_user_free1 105 105 @ stub OldGetPrinterDriverW
-50
win32ss/printing/base/spoolss/tools.c
··· 9 9 10 10 11 11 /** 12 - * @name MarshallDownStructure 13 - * 14 - * Prepare a structure for marshalling/serialization by replacing absolute pointer addresses in its fields by relative offsets. 15 - * 16 - * @param pStructure 17 - * Pointer to the structure to operate on. 18 - * 19 - * @param pParameters 20 - * Array of MARSHALL_DOWN_INFO elements containing information about the fields of the structure as well as how to modify them. 21 - * See the documentation on MARSHALL_DOWN_INFO for more information. 22 - * You have to indicate the end of the array by setting the dwOffset field to MAXDWORD. 23 - * 24 - * @param cbStructureSize 25 - * Apparently, this is the size in bytes of the structure given through pStructure under Windows. 26 - * This parameter is unused in my implementation. 27 - * 28 - * @param bSomeBoolean 29 - * Unknown boolean value 30 - * 31 - * @return 32 - * TRUE if the structure was successfully adjusted, FALSE otherwise. 33 - */ 34 - BOOL WINAPI 35 - MarshallDownStructure(PVOID pStructure, PMARSHALL_DOWN_INFO pParameters, DWORD cbStructureSize, BOOL bSomeBoolean) 36 - { 37 - // Sanity checks 38 - if (!pStructure || !pParameters) 39 - { 40 - SetLastError(ERROR_INVALID_PARAMETER); 41 - return FALSE; 42 - } 43 - 44 - // Loop until we reach an element with offset set to MAXDWORD. 45 - while (pParameters->dwOffset != MAXDWORD) 46 - { 47 - if (pParameters->bAdjustAddress) 48 - { 49 - // Apply the byte offset on pStructure. There must be a pointer at this position, whose address we're adjusting 50 - // by subtracting the address of pStructure from it. 51 - *((PULONG_PTR)((PBYTE)pStructure + pParameters->dwOffset)) -= (ULONG_PTR)pStructure; 52 - } 53 - 54 - // Advance to the next element description. 55 - pParameters++; 56 - } 57 - 58 - return TRUE; 59 - } 60 - 61 - /** 62 12 * @name PackStrings 63 13 * 64 14 * Takes an array of Unicode strings and fills an output buffer with these strings at the end and pointers to each string at specific offsets.
+2
win32ss/printing/base/spoolsv/precomp.h
··· 17 17 #include <winspool.h> 18 18 #include <winsplp.h> 19 19 #include <winspool_s.h> 20 + #include <ndk/rtlfuncs.h> 20 21 21 22 #include <spoolss.h> 23 + #include <marshalling/marshalling.h> 22 24 23 25 #include <wine/debug.h> 24 26 WINE_DEFAULT_DEBUG_CHANNEL(spoolsv);
+1
win32ss/printing/base/winspool/CMakeLists.txt
··· 4 4 spec2def(winspool.drv winspool.spec ADD_IMPORTLIB) 5 5 6 6 list(APPEND SOURCE 7 + ../marshalling.c 7 8 devmode.c 8 9 forms.c 9 10 jobs.c
+2
win32ss/printing/base/winspool/precomp.h
··· 15 15 #include <winreg.h> 16 16 #include <winspool.h> 17 17 #include <winspool_c.h> 18 + #include <ndk/rtlfuncs.h> 18 19 19 20 #include <spoolss.h> 21 + #include <marshalling/marshalling.h> 20 22 21 23 #include <wine/debug.h> 22 24 WINE_DEFAULT_DEBUG_CHANNEL(winspool);
+35
win32ss/printing/include/marshalling/marshalling.h
··· 1 + /* 2 + * PROJECT: ReactOS Printing Stack Marshalling Functions 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Marshalling definitions 5 + * COPYRIGHT: Copyright 2015-2018 Colin Finck (colin@reactos.org) 6 + */ 7 + 8 + 9 + #ifndef _MARSHALLING_H 10 + #define _MARSHALLING_H 11 + 12 + typedef struct _MARSHALLING_INFO 13 + { 14 + DWORD dwOffset; /** Byte offset of this element within the structure or MAXDWORD to indicate the end of the array */ 15 + DWORD cbSize; /** Total size of this element in bytes under Windows. Unused here, I don't know what we need this number for. */ 16 + DWORD cbPerElementSize; /** If this element is a structure itself, this field gives the size in bytes of each element of the structure. 17 + Otherwise, this is the same as cbTotalSize. E.g. for SYSTEMTIME, cbSize would be 16 and cbPerElementSize would be 2. 18 + Unused here, I don't know what we need this number for. */ 19 + BOOL bAdjustAddress; /** TRUE if MarshallDownStructure shall adjust the address of this element, FALSE if it shall leave this element untouched. */ 20 + } 21 + MARSHALLING_INFO; 22 + 23 + typedef struct _MARSHALLING 24 + { 25 + DWORD cbStructureSize; 26 + MARSHALLING_INFO pInfo[]; 27 + } 28 + MARSHALLING; 29 + 30 + BOOL WINAPI MarshallDownStructure(PVOID pStructure, const MARSHALLING_INFO* pInfo, DWORD cbStructureSize, BOOL bSomeBoolean); 31 + BOOL WINAPI MarshallDownStructuresArray(PVOID pStructuresArray, DWORD cElements, const MARSHALLING_INFO* pInfo, DWORD cbStructureSize, BOOL bSomeBoolean); 32 + BOOL WINAPI MarshallUpStructure(DWORD cbSize, PVOID pStructure, const MARSHALLING_INFO* pInfo, DWORD cbStructureSize, BOOL bSomeBoolean); 33 + BOOL WINAPI MarshallUpStructuresArray(DWORD cbSize, PVOID pStructuresArray, DWORD cElements, const MARSHALLING_INFO* pInfo, DWORD cbStructureSize, BOOL bSomeBoolean); 34 + 35 + #endif
+26
win32ss/printing/include/marshalling/ports.h
··· 1 + /* 2 + * PROJECT: ReactOS Printing Stack Marshalling Functions 3 + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) 4 + * PURPOSE: Marshalling definitions for PORT_INFO_* 5 + * COPYRIGHT: Copyright 2015-2018 Colin Finck (colin@reactos.org) 6 + */ 7 + 8 + const MARSHALLING PortInfo1Marshalling = { 9 + sizeof(PORT_INFO_1W), 10 + { 11 + { FIELD_OFFSET(PORT_INFO_1W, pName), RTL_FIELD_SIZE(PORT_INFO_1W, pName), RTL_FIELD_SIZE(PORT_INFO_1W, pName), TRUE }, 12 + { MAXDWORD, 0, 0, FALSE } 13 + } 14 + }; 15 + 16 + const MARSHALLING PortInfo2Marshalling = { 17 + sizeof(PORT_INFO_2W), 18 + { 19 + { FIELD_OFFSET(PORT_INFO_2W, pPortName), RTL_FIELD_SIZE(PORT_INFO_2W, pPortName), RTL_FIELD_SIZE(PORT_INFO_2W, pPortName), TRUE }, 20 + { FIELD_OFFSET(PORT_INFO_2W, pMonitorName), RTL_FIELD_SIZE(PORT_INFO_2W, pMonitorName), RTL_FIELD_SIZE(PORT_INFO_2W, pMonitorName), TRUE }, 21 + { FIELD_OFFSET(PORT_INFO_2W, pDescription), RTL_FIELD_SIZE(PORT_INFO_2W, pDescription), RTL_FIELD_SIZE(PORT_INFO_2W, pDescription), TRUE }, 22 + { FIELD_OFFSET(PORT_INFO_2W, fPortType), RTL_FIELD_SIZE(PORT_INFO_2W, fPortType), RTL_FIELD_SIZE(PORT_INFO_2W, fPortType), FALSE }, 23 + { FIELD_OFFSET(PORT_INFO_2W, Reserved), RTL_FIELD_SIZE(PORT_INFO_2W, Reserved), RTL_FIELD_SIZE(PORT_INFO_2W, Reserved), FALSE }, 24 + { MAXDWORD, 0, 0, FALSE } 25 + } 26 + };
-1
win32ss/printing/include/spoolss.h
··· 63 63 BOOL WINAPI DllFreeSplMem(PVOID pMem); 64 64 BOOL WINAPI DllFreeSplStr(PWSTR pwszString); 65 65 BOOL WINAPI InitializeRouter(HANDLE SpoolerStatusHandle); 66 - BOOL WINAPI MarshallDownStructure(PVOID pStructure, PMARSHALL_DOWN_INFO pParameters, DWORD cbStructureSize, BOOL bSomeBoolean); 67 66 PBYTE WINAPI PackStrings(PWSTR* pSource, PBYTE pDest, const DWORD* DestOffsets, PBYTE pEnd); 68 67 PVOID WINAPI ReallocSplMem(PVOID pOldMem, DWORD cbOld, DWORD cbNew); 69 68 BOOL WINAPI ReallocSplStr(PWSTR* ppwszString, PCWSTR pwszInput);