[PRINTING] Implement the undocumented MarshallDownStructure, MarshallDownStructuresAr...
authorColin Finck <colin@reactos.org>
Wed, 17 Jan 2018 09:13:25 +0000 (10:13 +0100)
committerColin Finck <colin@reactos.org>
Wed, 17 Jan 2018 09:13:25 +0000 (10:13 +0100)
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 !

15 files changed:
modules/rostests/apitests/spoolss/CMakeLists.txt
modules/rostests/apitests/spoolss/MarshallDownStructuresArray.c [new file with mode: 0644]
modules/rostests/apitests/spoolss/MarshallUpStructuresArray.c [new file with mode: 0644]
modules/rostests/apitests/spoolss/testlist.c
win32ss/printing/base/marshalling.c [new file with mode: 0644]
win32ss/printing/base/spoolss/CMakeLists.txt
win32ss/printing/base/spoolss/precomp.h
win32ss/printing/base/spoolss/spoolss.spec
win32ss/printing/base/spoolss/tools.c
win32ss/printing/base/spoolsv/precomp.h
win32ss/printing/base/winspool/CMakeLists.txt
win32ss/printing/base/winspool/precomp.h
win32ss/printing/include/marshalling/marshalling.h [new file with mode: 0644]
win32ss/printing/include/marshalling/ports.h [new file with mode: 0644]
win32ss/printing/include/spoolss.h

index f838489..d746573 100644 (file)
@@ -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 (file)
index 0000000..cd05707
--- /dev/null
@@ -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@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 (file)
index 0000000..d47c8b2
--- /dev/null
@@ -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@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.
+}
index 67b885c..f37cc35 100644 (file)
@@ -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@reactos.org)
+ * COPYRIGHT:   Copyright 2015-2018 Colin Finck (colin@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 (file)
index 0000000..bdca025
--- /dev/null
@@ -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@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;
+}
index f7ef3f2..12d6649 100644 (file)
@@ -2,6 +2,7 @@
 spec2def(spoolss.dll spoolss.spec ADD_IMPORTLIB)
 
 list(APPEND SOURCE
+    ../marshalling.c
     context.c
     jobs.c
     main.c
index 6ec7633..3a859aa 100644 (file)
@@ -18,6 +18,7 @@
 #include <ndk/rtlfuncs.h>
 
 #include <spoolss.h>
+#include <marshalling/marshalling.h>
 
 #include <wine/debug.h>
 WINE_DEFAULT_DEBUG_CHANNEL(spoolss);
index 172ab0b..87e136c 100644 (file)
@@ -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
index e6545bd..7b8410a 100644 (file)
@@ -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
  *
index f7d09e1..5ab518a 100644 (file)
 #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);
index b4dcf8a..aea2d85 100644 (file)
@@ -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
index 9cf5be3..cbfaac9 100644 (file)
 #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 (file)
index 0000000..d82db43
--- /dev/null
@@ -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@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 (file)
index 0000000..b53eb31
--- /dev/null
@@ -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@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 }
+    }
+};
index a841fb2..7e1c132 100644 (file)
@@ -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);