https://git.reactos.org/?p=reactos.git;a=commitdiff;h=f3ea8225cb2217463fa68b5892c1ddc9c064a27a

commit f3ea8225cb2217463fa68b5892c1ddc9c064a27a
Author:     Colin Finck <co...@reactos.org>
AuthorDate: Wed Jan 17 10:13:25 2018 +0100
Commit:     Colin Finck <co...@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 (co...@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 (co...@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 (co...@reactos.org)
+ * COPYRIGHT:   Copyright 2015-2018 Colin Finck (co...@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 (co...@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 (co...@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 (co...@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);

Reply via email to