https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f3ea8225cb2217463fa68…
commit f3ea8225cb2217463fa68b5892c1ddc9c064a27a
Author: Colin Finck <colin(a)reactos.org>
AuthorDate: Wed Jan 17 10:13:25 2018 +0100
Commit: Colin Finck <colin(a)reactos.org>
CommitDate: Wed Jan 17 10:13:25 2018 +0100
[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 !
---
modules/rostests/apitests/spoolss/CMakeLists.txt | 2 +
.../apitests/spoolss/MarshallDownStructuresArray.c | 118 ++++++++++++
.../apitests/spoolss/MarshallUpStructuresArray.c | 37 ++++
modules/rostests/apitests/spoolss/testlist.c | 6 +-
win32ss/printing/base/marshalling.c | 212 +++++++++++++++++++++
win32ss/printing/base/spoolss/CMakeLists.txt | 1 +
win32ss/printing/base/spoolss/precomp.h | 1 +
win32ss/printing/base/spoolss/spoolss.spec | 6 +-
win32ss/printing/base/spoolss/tools.c | 50 -----
win32ss/printing/base/spoolsv/precomp.h | 2 +
win32ss/printing/base/winspool/CMakeLists.txt | 1 +
win32ss/printing/base/winspool/precomp.h | 2 +
win32ss/printing/include/marshalling/marshalling.h | 35 ++++
win32ss/printing/include/marshalling/ports.h | 26 +++
win32ss/printing/include/spoolss.h | 1 -
15 files changed, 445 insertions(+), 55 deletions(-)
diff --git a/modules/rostests/apitests/spoolss/CMakeLists.txt
b/modules/rostests/apitests/spoolss/CMakeLists.txt
index f838489dc4..d746573b24 100644
--- a/modules/rostests/apitests/spoolss/CMakeLists.txt
+++ b/modules/rostests/apitests/spoolss/CMakeLists.txt
@@ -3,6 +3,8 @@ include_directories(${REACTOS_SOURCE_DIR}/win32ss/printing/include)
list(APPEND SOURCE
AlignRpcPtr.c
+ MarshallDownStructuresArray.c
+ MarshallUpStructuresArray.c
PackStrings.c
ReallocSplStr.c
SplInitializeWinSpoolDrv.c
diff --git a/modules/rostests/apitests/spoolss/MarshallDownStructuresArray.c
b/modules/rostests/apitests/spoolss/MarshallDownStructuresArray.c
new file mode 100644
index 0000000000..cd057074ec
--- /dev/null
+++ b/modules/rostests/apitests/spoolss/MarshallDownStructuresArray.c
@@ -0,0 +1,118 @@
+/*
+ * PROJECT: ReactOS Spooler Router API Tests
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Tests for MarshallDownStructuresArray
+ * COPYRIGHT: Copyright 2018 Colin Finck (colin(a)reactos.org)
+ */
+
+#include <apitest.h>
+
+#define WIN32_NO_STATUS
+#include <windef.h>
+#include <winbase.h>
+#include <wingdi.h>
+#include <winspool.h>
+#include <ndk/rtlfuncs.h>
+
+#include <spoolss.h>
+#include <marshalling/marshalling.h>
+#include <marshalling/ports.h>
+
+START_TEST(MarshallDownStructuresArray)
+{
+ const DWORD cElements = 2;
+ const DWORD dwPortInfo2Offsets[] = {
+ FIELD_OFFSET(PORT_INFO_2W, pPortName),
+ FIELD_OFFSET(PORT_INFO_2W, pMonitorName),
+ FIELD_OFFSET(PORT_INFO_2W, pDescription),
+ MAXDWORD
+ };
+
+ PPORT_INFO_2W pPortInfo2;
+ PPORT_INFO_2W pPortInfo2Copy;
+ PPORT_INFO_2W pPortInfo2Test;
+ PBYTE pPortInfoEnd;
+ PWSTR pwszStrings[] = { L"PortName", L"MonitorName",
L"Description" };
+ DWORD cbPortInfo2Size = cElements * (sizeof(PORT_INFO_2W) + (wcslen(pwszStrings[0]) +
1 + wcslen(pwszStrings[1]) + 1 + wcslen(pwszStrings[2]) + 1) * sizeof(WCHAR));
+ DWORD fPortType = 1337;
+ DWORD Reserved = 42;
+
+ // Setting cElements to zero should yield success.
+ SetLastError(0xDEADBEEF);
+ ok(MarshallDownStructuresArray(NULL, 0, NULL, 0, FALSE),
"MarshallDownStructuresArray returns FALSE!\n");
+ ok(GetLastError() == 0xDEADBEEF, "GetLastError returns %lu!\n",
GetLastError());
+
+ // Setting cElements non-zero should fail with ERROR_INVALID_PARAMETER.
+ SetLastError(0xDEADBEEF);
+ ok(!MarshallDownStructuresArray(NULL, 1, NULL, 0, FALSE),
"MarshallDownStructuresArray returns TRUE!\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError returns
%lu!\n", GetLastError());
+
+ // This is triggered by both pStructuresArray and pInfo.
+ SetLastError(0xDEADBEEF);
+ ok(!MarshallDownStructuresArray((PVOID)0xDEADDEAD, 1, NULL, 0, FALSE),
"MarshallDownStructuresArray returns TRUE!\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError returns
%lu!\n", GetLastError());
+
+ SetLastError(0xDEADBEEF);
+ ok(!MarshallDownStructuresArray(NULL, 1, (const MARSHALLING_INFO*)0xDEADDEAD, 0,
FALSE), "MarshallDownStructuresArray returns TRUE!\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError returns
%lu!\n", GetLastError());
+
+ // Now create two PORT_INFO_2W structures.
+ pPortInfo2 = (PPORT_INFO_2W)HeapAlloc(GetProcessHeap(), 0, cbPortInfo2Size);
+ pPortInfoEnd = (PBYTE)pPortInfo2 + cbPortInfo2Size;
+
+ (&pPortInfo2[0])->fPortType = fPortType;
+ (&pPortInfo2[0])->Reserved = Reserved;
+ pPortInfoEnd = PackStrings(pwszStrings, (PBYTE)(&pPortInfo2[0]),
dwPortInfo2Offsets, pPortInfoEnd);
+
+ (&pPortInfo2[1])->fPortType = fPortType + 1;
+ (&pPortInfo2[1])->Reserved = Reserved + 1;
+ pPortInfoEnd = PackStrings(pwszStrings, (PBYTE)(&pPortInfo2[1]),
dwPortInfo2Offsets, pPortInfoEnd);
+
+ // Create a backup.
+ pPortInfo2Copy = (PPORT_INFO_2W)HeapAlloc(GetProcessHeap(), 0, cbPortInfo2Size);
+ CopyMemory(pPortInfo2Copy, pPortInfo2, cbPortInfo2Size);
+
+ // Marshall them down.
+ SetLastError(0xDEADBEEF);
+ ok(MarshallDownStructuresArray(pPortInfo2, cElements, PortInfo2Marshalling.pInfo,
PortInfo2Marshalling.cbStructureSize, TRUE), "MarshallDownStructuresArray returns
FALSE!\n");
+ ok(GetLastError() == 0xDEADBEEF, "GetLastError returns %lu!\n",
GetLastError());
+
+ // DWORD values should be unchanged.
+ ok((&pPortInfo2[0])->fPortType == fPortType, "fPortType is %lu!\n",
(&pPortInfo2[0])->fPortType);
+ ok((&pPortInfo2[0])->Reserved == Reserved, "Reserved is %lu!\n",
(&pPortInfo2[0])->Reserved);
+ ok((&pPortInfo2[1])->fPortType == fPortType + 1, "fPortType is
%lu!\n", (&pPortInfo2[1])->fPortType);
+ ok((&pPortInfo2[1])->Reserved == Reserved + 1, "Reserved is %lu!\n",
(&pPortInfo2[1])->Reserved);
+
+ // Pointers should now contain relative offsets.
+ ok((ULONG_PTR)(&pPortInfo2[0])->pPortName ==
((ULONG_PTR)(&pPortInfo2Copy[0])->pPortName - (ULONG_PTR)(&pPortInfo2[0])),
"pPortName is %p!\n", (&pPortInfo2[0])->pPortName);
+ ok((ULONG_PTR)(&pPortInfo2[0])->pMonitorName ==
((ULONG_PTR)(&pPortInfo2Copy[0])->pMonitorName - (ULONG_PTR)(&pPortInfo2[0])),
"pMonitorName is %p!\n", (&pPortInfo2[0])->pMonitorName);
+ ok((ULONG_PTR)(&pPortInfo2[0])->pDescription ==
((ULONG_PTR)(&pPortInfo2Copy[0])->pDescription - (ULONG_PTR)(&pPortInfo2[0])),
"pDescription is %p!\n", (&pPortInfo2[0])->pDescription);
+ ok((ULONG_PTR)(&pPortInfo2[1])->pPortName ==
((ULONG_PTR)(&pPortInfo2Copy[1])->pPortName - (ULONG_PTR)(&pPortInfo2[1])),
"pPortName is %p!\n", (&pPortInfo2[1])->pPortName);
+ ok((ULONG_PTR)(&pPortInfo2[1])->pMonitorName ==
((ULONG_PTR)(&pPortInfo2Copy[1])->pMonitorName - (ULONG_PTR)(&pPortInfo2[1])),
"pMonitorName is %p!\n", (&pPortInfo2[1])->pMonitorName);
+ ok((ULONG_PTR)(&pPortInfo2[1])->pDescription ==
((ULONG_PTR)(&pPortInfo2Copy[1])->pDescription - (ULONG_PTR)(&pPortInfo2[1])),
"pDescription is %p!\n", (&pPortInfo2[1])->pDescription);
+
+ // Marshall them up again.
+ // We need a backup of the marshalled down array to experiment with
MarshallUpStructuresArray.
+ pPortInfo2Test = (PPORT_INFO_2W)HeapAlloc(GetProcessHeap(), 0, cbPortInfo2Size);
+ CopyMemory(pPortInfo2Test, pPortInfo2, cbPortInfo2Size);
+
+ // Due to the implementation of PackStrings, (&pPortInfo2[0])->pPortName
contains the highest offset.
+ // Show that MarshallUpStructuresArray checks the offsets and bails out with
ERROR_INVALID_DATA if cbSize <= highest offset.
+ SetLastError(0xDEADBEEF);
+ ok(!MarshallUpStructuresArray((DWORD)(&pPortInfo2[0])->pPortName,
pPortInfo2Test, cElements, PortInfo2Marshalling.pInfo,
PortInfo2Marshalling.cbStructureSize, TRUE), "MarshallUpStructuresArray returns
TRUE!\n");
+ ok(GetLastError() == ERROR_INVALID_DATA, "GetLastError returns %lu!\n",
GetLastError());
+
+ // It works with cbSize > highest offset.
+ // In real world cases, we would use cbPortInfo2Size for cbSize.
+ SetLastError(0xDEADBEEF);
+ ok(MarshallUpStructuresArray((DWORD)(&pPortInfo2[0])->pPortName + 1,
pPortInfo2, cElements, PortInfo2Marshalling.pInfo, PortInfo2Marshalling.cbStructureSize,
TRUE), "MarshallUpStructuresArray returns FALSE!\n");
+ ok(GetLastError() == 0xDEADBEEF, "GetLastError returns %lu!\n",
GetLastError());
+
+ // pPortInfo2 should now be identical to the copy again.
+ ok(RtlEqualMemory(pPortInfo2, pPortInfo2Copy, cbPortInfo2Size), "pPortInfo2 and
pPortInfo2Copy are not equal after marshalling down and up!\n");
+
+ // Free all memory.
+ HeapFree(GetProcessHeap(), 0, pPortInfo2);
+ HeapFree(GetProcessHeap(), 0, pPortInfo2Copy);
+ HeapFree(GetProcessHeap(), 0, pPortInfo2Test);
+}
diff --git a/modules/rostests/apitests/spoolss/MarshallUpStructuresArray.c
b/modules/rostests/apitests/spoolss/MarshallUpStructuresArray.c
new file mode 100644
index 0000000000..d47c8b21dd
--- /dev/null
+++ b/modules/rostests/apitests/spoolss/MarshallUpStructuresArray.c
@@ -0,0 +1,37 @@
+/*
+ * PROJECT: ReactOS Spooler Router API Tests
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Tests for MarshallUpStructuresArray
+ * COPYRIGHT: Copyright 2018 Colin Finck (colin(a)reactos.org)
+ */
+
+#include <apitest.h>
+
+#define WIN32_NO_STATUS
+#include <windef.h>
+#include <winbase.h>
+#include <marshalling/marshalling.h>
+
+START_TEST(MarshallUpStructuresArray)
+{
+ // Setting cElements to zero should yield success.
+ SetLastError(0xDEADBEEF);
+ ok(MarshallUpStructuresArray(0, NULL, 0, NULL, 0, FALSE),
"MarshallUpStructuresArray returns FALSE!\n");
+ ok(GetLastError() == 0xDEADBEEF, "GetLastError returns %lu!\n",
GetLastError());
+
+ // Setting cElements non-zero should fail with ERROR_INVALID_PARAMETER.
+ SetLastError(0xDEADBEEF);
+ ok(!MarshallUpStructuresArray(0, NULL, 1, NULL, 0, FALSE),
"MarshallUpStructuresArray returns TRUE!\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError returns
%lu!\n", GetLastError());
+
+ // This is triggered by both pStructuresArray and pInfo.
+ SetLastError(0xDEADBEEF);
+ ok(!MarshallUpStructuresArray(0, (PVOID)0xDEADDEAD, 1, NULL, 0, FALSE),
"MarshallUpStructuresArray returns TRUE!\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError returns
%lu!\n", GetLastError());
+
+ SetLastError(0xDEADBEEF);
+ ok(!MarshallUpStructuresArray(0, NULL, 1, (const MARSHALLING_INFO*)0xDEADDEAD, 0,
FALSE), "MarshallUpStructuresArray returns TRUE!\n");
+ ok(GetLastError() == ERROR_INVALID_PARAMETER, "GetLastError returns
%lu!\n", GetLastError());
+
+ // More testing is conducted in the MarshallDownStructuresArray test.
+}
diff --git a/modules/rostests/apitests/spoolss/testlist.c
b/modules/rostests/apitests/spoolss/testlist.c
index 67b885cbd6..f37cc351df 100644
--- a/modules/rostests/apitests/spoolss/testlist.c
+++ b/modules/rostests/apitests/spoolss/testlist.c
@@ -2,7 +2,7 @@
* PROJECT: ReactOS Spooler Router API Tests
* LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
* PURPOSE: Test list
- * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin(a)reactos.org)
+ * COPYRIGHT: Copyright 2015-2018 Colin Finck (colin(a)reactos.org)
*/
#define __ROS_LONG64__
@@ -11,6 +11,8 @@
#include <apitest.h>
extern void func_AlignRpcPtr(void);
+extern void func_MarshallDownStructuresArray(void);
+extern void func_MarshallUpStructuresArray(void);
extern void func_PackStrings(void);
extern void func_ReallocSplStr(void);
extern void func_SplInitializeWinSpoolDrv(void);
@@ -18,6 +20,8 @@ extern void func_SplInitializeWinSpoolDrv(void);
const struct test winetest_testlist[] =
{
{ "AlignRpcPtr", func_AlignRpcPtr },
+ { "MarshallDownStructuresArray", func_MarshallDownStructuresArray },
+ { "MarshallUpStructuresArray", func_MarshallUpStructuresArray },
{ "PackStrings", func_PackStrings },
{ "ReallocSplStr", func_ReallocSplStr },
{ "SplInitializeWinSpoolDrv", func_SplInitializeWinSpoolDrv },
diff --git a/win32ss/printing/base/marshalling.c b/win32ss/printing/base/marshalling.c
new file mode 100644
index 0000000000..bdca025076
--- /dev/null
+++ b/win32ss/printing/base/marshalling.c
@@ -0,0 +1,212 @@
+/*
+ * PROJECT: ReactOS Printing Stack Marshalling Functions
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Marshalling functions
+ * COPYRIGHT: Copyright 2015-2018 Colin Finck (colin(a)reactos.org)
+ */
+
+
+/**
+ * @name MarshallDownStructure
+ *
+ * Prepare a structure for marshalling/serialization by replacing absolute pointer
addresses in its fields by relative offsets.
+ *
+ * @param pStructure
+ * Pointer to the structure to operate on.
+ *
+ * @param pInfo
+ * Array of MARSHALLING_INFO elements containing information about the fields of the
structure as well as how to modify them.
+ * See the documentation on MARSHALLING_INFO for more information.
+ * You have to indicate the end of the array by setting the dwOffset field to MAXDWORD.
+ *
+ * @param cbStructureSize
+ * Size in bytes of the structure.
+ * This parameter is unused in my implementation.
+ *
+ * @param bSomeBoolean
+ * Unknown boolean value, set to TRUE.
+ *
+ * @return
+ * TRUE if the structure was successfully adjusted, FALSE otherwise.
+ */
+BOOL WINAPI
+MarshallDownStructure(PVOID pStructure, const MARSHALLING_INFO* pInfo, DWORD
cbStructureSize, BOOL bSomeBoolean)
+{
+ // Sanity checks
+ if (!pStructure || !pInfo)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ // Loop until we reach an element with offset set to MAXDWORD.
+ while (pInfo->dwOffset != MAXDWORD)
+ {
+ PULONG_PTR pCurrentField = (PULONG_PTR)((PBYTE)pStructure + pInfo->dwOffset);
+
+ if (pInfo->bAdjustAddress && *pCurrentField)
+ {
+ // Make a relative offset out of the absolute pointer address.
+ *pCurrentField -= (ULONG_PTR)pStructure;
+ }
+
+ // Advance to the next field description.
+ pInfo++;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @name MarshallDownStructuresArray
+ *
+ * Prepare an array of structures for marshalling/serialization by replacing absolute
pointer addresses in its fields by relative offsets.
+ *
+ * @param pStructuresArray
+ * Pointer to the array of structures to operate on.
+ *
+ * @param cElements
+ * Number of array elements.
+ *
+ * @param pInfo
+ * Array of MARSHALLING_INFO elements containing information about the fields of the
structure as well as how to modify them.
+ * See the documentation on MARSHALLING_INFO for more information.
+ * You have to indicate the end of the array by setting the dwOffset field to MAXDWORD.
+ *
+ * @param cbStructureSize
+ * Size in bytes of each structure array element.
+ *
+ * @param bSomeBoolean
+ * Unknown boolean value, set to TRUE.
+ *
+ * @return
+ * TRUE if the array was successfully adjusted, FALSE otherwise.
+ */
+BOOL WINAPI
+MarshallDownStructuresArray(PVOID pStructuresArray, DWORD cElements, const
MARSHALLING_INFO* pInfo, DWORD cbStructureSize, BOOL bSomeBoolean)
+{
+ PBYTE pCurrentElement = pStructuresArray;
+
+ // Call MarshallDownStructure on all array elements given by cElements of
cbStructureSize.
+ while (cElements--)
+ {
+ if (!MarshallDownStructure(pCurrentElement, pInfo, cbStructureSize,
bSomeBoolean))
+ return FALSE;
+
+ // Advance to the next array element.
+ pCurrentElement += cbStructureSize;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @name MarshallUpStructure
+ *
+ * Unmarshall/deserialize a structure previuosly marshalled by MarshallDownStructure by
replacing relative offsets in its fields
+ * by absolute pointer addresses again.
+ *
+ * @param cbSize
+ * Size in bytes of the memory allocated for both the structure and its data.
+ * The function will check if all relative offsets are within the bounds given by this
size.
+ *
+ * @param pStructure
+ * Pointer to the structure to operate on.
+ *
+ * @param pInfo
+ * Array of MARSHALLING_INFO elements containing information about the fields of the
structure as well as how to modify them.
+ * See the documentation on MARSHALLING_INFO for more information.
+ * You have to indicate the end of the array by setting the dwOffset field to MAXDWORD.
+ *
+ * @param cbStructureSize
+ * Size in bytes of the structure.
+ * This parameter is unused in my implementation.
+ *
+ * @param bSomeBoolean
+ * Unknown boolean value, set to TRUE.
+ *
+ * @return
+ * TRUE if the structure was successfully adjusted, FALSE otherwise.
+ */
+BOOL WINAPI
+MarshallUpStructure(DWORD cbSize, PVOID pStructure, const MARSHALLING_INFO* pInfo, DWORD
cbStructureSize, BOOL bSomeBoolean)
+{
+ // Sanity checks
+ if (!pStructure || !pInfo)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ // Loop until we reach an element with offset set to MAXDWORD.
+ while (pInfo->dwOffset != MAXDWORD)
+ {
+ PULONG_PTR pCurrentField = (PULONG_PTR)((PBYTE)pStructure + pInfo->dwOffset);
+
+ if (pInfo->bAdjustAddress && *pCurrentField)
+ {
+ // Verify that the offset in the current field is within the bounds given by
cbSize.
+ if (cbSize <= *pCurrentField)
+ {
+ SetLastError(ERROR_INVALID_DATA);
+ return FALSE;
+ }
+
+ // Make an absolute pointer address out of the relative offset.
+ *pCurrentField += (ULONG_PTR)pStructure;
+ }
+
+ // Advance to the next field description.
+ pInfo++;
+ }
+
+ return TRUE;
+}
+
+/**
+ * @name MarshallUpStructuresArray
+ *
+ * Unmarshall/deserialize an array of structures previuosly marshalled by
MarshallDownStructuresArray by replacing relative offsets
+ * in its fields by absolute pointer addresses again.
+ *
+ * @param cbSize
+ * Size in bytes of the memory allocated for the entire structure array and its data.
+ * The function will check if all relative offsets are within the bounds given by this
size.
+ *
+ * @param pStructuresArray
+ * Pointer to the array of structures to operate on.
+ *
+ * @param cElements
+ * Number of array elements.
+ *
+ * @param pInfo
+ * Array of MARSHALLING_INFO elements containing information about the fields of the
structure as well as how to modify them.
+ * See the documentation on MARSHALLING_INFO for more information.
+ * You have to indicate the end of the array by setting the dwOffset field to MAXDWORD.
+ *
+ * @param cbStructureSize
+ * Size in bytes of each structure array element.
+ *
+ * @param bSomeBoolean
+ * Unknown boolean value, set to TRUE.
+ *
+ * @return
+ * TRUE if the array was successfully adjusted, FALSE otherwise.
+ */
+BOOL WINAPI
+MarshallUpStructuresArray(DWORD cbSize, PVOID pStructuresArray, DWORD cElements, const
MARSHALLING_INFO* pInfo, DWORD cbStructureSize, BOOL bSomeBoolean)
+{
+ PBYTE pCurrentElement = pStructuresArray;
+
+ // Call MarshallUpStructure on all array elements given by cElements of
cbStructureSize.
+ while (cElements--)
+ {
+ if (!MarshallUpStructure(cbSize, pCurrentElement, pInfo, cbStructureSize,
bSomeBoolean))
+ return FALSE;
+
+ // Advance to the next array element.
+ pCurrentElement += cbStructureSize;
+ }
+
+ return TRUE;
+}
diff --git a/win32ss/printing/base/spoolss/CMakeLists.txt
b/win32ss/printing/base/spoolss/CMakeLists.txt
index f7ef3f273d..12d6649e63 100644
--- a/win32ss/printing/base/spoolss/CMakeLists.txt
+++ b/win32ss/printing/base/spoolss/CMakeLists.txt
@@ -2,6 +2,7 @@
spec2def(spoolss.dll spoolss.spec ADD_IMPORTLIB)
list(APPEND SOURCE
+ ../marshalling.c
context.c
jobs.c
main.c
diff --git a/win32ss/printing/base/spoolss/precomp.h
b/win32ss/printing/base/spoolss/precomp.h
index 6ec7633c2b..3a859aa2d7 100644
--- a/win32ss/printing/base/spoolss/precomp.h
+++ b/win32ss/printing/base/spoolss/precomp.h
@@ -18,6 +18,7 @@
#include <ndk/rtlfuncs.h>
#include <spoolss.h>
+#include <marshalling/marshalling.h>
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(spoolss);
diff --git a/win32ss/printing/base/spoolss/spoolss.spec
b/win32ss/printing/base/spoolss/spoolss.spec
index 172ab0b151..87e136c9a4 100644
--- a/win32ss/printing/base/spoolss/spoolss.spec
+++ b/win32ss/printing/base/spoolss/spoolss.spec
@@ -97,9 +97,9 @@
@ stub LoadDriverWithVersion
@ stub LogWmiTraceEvent
@ stdcall MarshallDownStructure(ptr ptr long long)
-@ stub MarshallDownStructuresArray
-@ stub MarshallUpStructure
-@ stub MarshallUpStructuresArray
+@ stdcall MarshallDownStructuresArray(ptr long ptr long long)
+@ stdcall MarshallUpStructure(long ptr ptr long long)
+@ stdcall MarshallUpStructuresArray(long ptr long ptr long long)
@ stub MIDL_user_allocate1
@ stub MIDL_user_free1
@ stub OldGetPrinterDriverW
diff --git a/win32ss/printing/base/spoolss/tools.c
b/win32ss/printing/base/spoolss/tools.c
index e6545bdf28..7b8410a41a 100644
--- a/win32ss/printing/base/spoolss/tools.c
+++ b/win32ss/printing/base/spoolss/tools.c
@@ -8,56 +8,6 @@
#include "precomp.h"
-/**
- * @name MarshallDownStructure
- *
- * Prepare a structure for marshalling/serialization by replacing absolute pointer
addresses in its fields by relative offsets.
- *
- * @param pStructure
- * Pointer to the structure to operate on.
- *
- * @param pParameters
- * Array of MARSHALL_DOWN_INFO elements containing information about the fields of the
structure as well as how to modify them.
- * See the documentation on MARSHALL_DOWN_INFO for more information.
- * You have to indicate the end of the array by setting the dwOffset field to MAXDWORD.
- *
- * @param cbStructureSize
- * Apparently, this is the size in bytes of the structure given through pStructure under
Windows.
- * This parameter is unused in my implementation.
- *
- * @param bSomeBoolean
- * Unknown boolean value
- *
- * @return
- * TRUE if the structure was successfully adjusted, FALSE otherwise.
- */
-BOOL WINAPI
-MarshallDownStructure(PVOID pStructure, PMARSHALL_DOWN_INFO pParameters, DWORD
cbStructureSize, BOOL bSomeBoolean)
-{
- // Sanity checks
- if (!pStructure || !pParameters)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return FALSE;
- }
-
- // Loop until we reach an element with offset set to MAXDWORD.
- while (pParameters->dwOffset != MAXDWORD)
- {
- if (pParameters->bAdjustAddress)
- {
- // Apply the byte offset on pStructure. There must be a pointer at this
position, whose address we're adjusting
- // by subtracting the address of pStructure from it.
- *((PULONG_PTR)((PBYTE)pStructure + pParameters->dwOffset)) -=
(ULONG_PTR)pStructure;
- }
-
- // Advance to the next element description.
- pParameters++;
- }
-
- return TRUE;
-}
-
/**
* @name PackStrings
*
diff --git a/win32ss/printing/base/spoolsv/precomp.h
b/win32ss/printing/base/spoolsv/precomp.h
index f7d09e1e3d..5ab518a43c 100644
--- a/win32ss/printing/base/spoolsv/precomp.h
+++ b/win32ss/printing/base/spoolsv/precomp.h
@@ -17,8 +17,10 @@
#include <winspool.h>
#include <winsplp.h>
#include <winspool_s.h>
+#include <ndk/rtlfuncs.h>
#include <spoolss.h>
+#include <marshalling/marshalling.h>
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(spoolsv);
diff --git a/win32ss/printing/base/winspool/CMakeLists.txt
b/win32ss/printing/base/winspool/CMakeLists.txt
index b4dcf8a163..aea2d85f3d 100644
--- a/win32ss/printing/base/winspool/CMakeLists.txt
+++ b/win32ss/printing/base/winspool/CMakeLists.txt
@@ -4,6 +4,7 @@ add_rpc_files(client
${REACTOS_SOURCE_DIR}/sdk/include/reactos/idl/winspool.idl)
spec2def(winspool.drv winspool.spec ADD_IMPORTLIB)
list(APPEND SOURCE
+ ../marshalling.c
devmode.c
forms.c
jobs.c
diff --git a/win32ss/printing/base/winspool/precomp.h
b/win32ss/printing/base/winspool/precomp.h
index 9cf5be3e90..cbfaac933c 100644
--- a/win32ss/printing/base/winspool/precomp.h
+++ b/win32ss/printing/base/winspool/precomp.h
@@ -15,8 +15,10 @@
#include <winreg.h>
#include <winspool.h>
#include <winspool_c.h>
+#include <ndk/rtlfuncs.h>
#include <spoolss.h>
+#include <marshalling/marshalling.h>
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(winspool);
diff --git a/win32ss/printing/include/marshalling/marshalling.h
b/win32ss/printing/include/marshalling/marshalling.h
new file mode 100644
index 0000000000..d82db43a2b
--- /dev/null
+++ b/win32ss/printing/include/marshalling/marshalling.h
@@ -0,0 +1,35 @@
+/*
+ * PROJECT: ReactOS Printing Stack Marshalling Functions
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Marshalling definitions
+ * COPYRIGHT: Copyright 2015-2018 Colin Finck (colin(a)reactos.org)
+ */
+
+
+#ifndef _MARSHALLING_H
+#define _MARSHALLING_H
+
+typedef struct _MARSHALLING_INFO
+{
+ DWORD dwOffset; /** Byte offset of this element within the structure or
MAXDWORD to indicate the end of the array */
+ DWORD cbSize; /** Total size of this element in bytes under Windows.
Unused here, I don't know what we need this number for. */
+ DWORD cbPerElementSize; /** If this element is a structure itself, this field
gives the size in bytes of each element of the structure.
+ Otherwise, this is the same as cbTotalSize. E.g. for
SYSTEMTIME, cbSize would be 16 and cbPerElementSize would be 2.
+ Unused here, I don't know what we need this number
for. */
+ BOOL bAdjustAddress; /** TRUE if MarshallDownStructure shall adjust the
address of this element, FALSE if it shall leave this element untouched. */
+}
+MARSHALLING_INFO;
+
+typedef struct _MARSHALLING
+{
+ DWORD cbStructureSize;
+ MARSHALLING_INFO pInfo[];
+}
+MARSHALLING;
+
+BOOL WINAPI MarshallDownStructure(PVOID pStructure, const MARSHALLING_INFO* pInfo, DWORD
cbStructureSize, BOOL bSomeBoolean);
+BOOL WINAPI MarshallDownStructuresArray(PVOID pStructuresArray, DWORD cElements, const
MARSHALLING_INFO* pInfo, DWORD cbStructureSize, BOOL bSomeBoolean);
+BOOL WINAPI MarshallUpStructure(DWORD cbSize, PVOID pStructure, const MARSHALLING_INFO*
pInfo, DWORD cbStructureSize, BOOL bSomeBoolean);
+BOOL WINAPI MarshallUpStructuresArray(DWORD cbSize, PVOID pStructuresArray, DWORD
cElements, const MARSHALLING_INFO* pInfo, DWORD cbStructureSize, BOOL bSomeBoolean);
+
+#endif
diff --git a/win32ss/printing/include/marshalling/ports.h
b/win32ss/printing/include/marshalling/ports.h
new file mode 100644
index 0000000000..b53eb31742
--- /dev/null
+++ b/win32ss/printing/include/marshalling/ports.h
@@ -0,0 +1,26 @@
+/*
+ * PROJECT: ReactOS Printing Stack Marshalling Functions
+ * LICENSE: GPL-2.0+ (
https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE: Marshalling definitions for PORT_INFO_*
+ * COPYRIGHT: Copyright 2015-2018 Colin Finck (colin(a)reactos.org)
+ */
+
+const MARSHALLING PortInfo1Marshalling = {
+ sizeof(PORT_INFO_1W),
+ {
+ { FIELD_OFFSET(PORT_INFO_1W, pName), RTL_FIELD_SIZE(PORT_INFO_1W, pName),
RTL_FIELD_SIZE(PORT_INFO_1W, pName), TRUE },
+ { MAXDWORD, 0, 0, FALSE }
+ }
+};
+
+const MARSHALLING PortInfo2Marshalling = {
+ sizeof(PORT_INFO_2W),
+ {
+ { FIELD_OFFSET(PORT_INFO_2W, pPortName), RTL_FIELD_SIZE(PORT_INFO_2W, pPortName),
RTL_FIELD_SIZE(PORT_INFO_2W, pPortName), TRUE },
+ { FIELD_OFFSET(PORT_INFO_2W, pMonitorName), RTL_FIELD_SIZE(PORT_INFO_2W,
pMonitorName), RTL_FIELD_SIZE(PORT_INFO_2W, pMonitorName), TRUE },
+ { FIELD_OFFSET(PORT_INFO_2W, pDescription), RTL_FIELD_SIZE(PORT_INFO_2W,
pDescription), RTL_FIELD_SIZE(PORT_INFO_2W, pDescription), TRUE },
+ { FIELD_OFFSET(PORT_INFO_2W, fPortType), RTL_FIELD_SIZE(PORT_INFO_2W, fPortType),
RTL_FIELD_SIZE(PORT_INFO_2W, fPortType), FALSE },
+ { FIELD_OFFSET(PORT_INFO_2W, Reserved), RTL_FIELD_SIZE(PORT_INFO_2W, Reserved),
RTL_FIELD_SIZE(PORT_INFO_2W, Reserved), FALSE },
+ { MAXDWORD, 0, 0, FALSE }
+ }
+};
diff --git a/win32ss/printing/include/spoolss.h b/win32ss/printing/include/spoolss.h
index a841fb29e0..7e1c132dcf 100644
--- a/win32ss/printing/include/spoolss.h
+++ b/win32ss/printing/include/spoolss.h
@@ -63,7 +63,6 @@ PVOID WINAPI DllAllocSplMem(DWORD dwBytes);
BOOL WINAPI DllFreeSplMem(PVOID pMem);
BOOL WINAPI DllFreeSplStr(PWSTR pwszString);
BOOL WINAPI InitializeRouter(HANDLE SpoolerStatusHandle);
-BOOL WINAPI MarshallDownStructure(PVOID pStructure, PMARSHALL_DOWN_INFO pParameters,
DWORD cbStructureSize, BOOL bSomeBoolean);
PBYTE WINAPI PackStrings(PWSTR* pSource, PBYTE pDest, const DWORD* DestOffsets, PBYTE
pEnd);
PVOID WINAPI ReallocSplMem(PVOID pOldMem, DWORD cbOld, DWORD cbNew);
BOOL WINAPI ReallocSplStr(PWSTR* ppwszString, PCWSTR pwszInput);