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)
10 #define WIN32_NO_STATUS
15 #include <ndk/rtlfuncs.h>
18 #include <marshalling/marshalling.h>
19 #include <marshalling/ports.h>
21 #define INVALID_POINTER ((PVOID)(ULONG_PTR)0xdeadbeefdeadbeefULL)
23 START_TEST(MarshallDownStructuresArray
)
25 const DWORD cElements
= 2;
26 const DWORD dwPortInfo2Offsets
[] = {
27 FIELD_OFFSET(PORT_INFO_2W
, pPortName
),
28 FIELD_OFFSET(PORT_INFO_2W
, pMonitorName
),
29 FIELD_OFFSET(PORT_INFO_2W
, pDescription
),
33 PPORT_INFO_2W pPortInfo2
;
34 PPORT_INFO_2W pPortInfo2Copy
;
35 PPORT_INFO_2W pPortInfo2Test
;
37 PCWSTR pwszStrings
[] = { L
"PortName", L
"MonitorName", L
"Description" };
38 SIZE_T cbPortInfo2Size
= cElements
* (sizeof(PORT_INFO_2W
) + (wcslen(pwszStrings
[0]) + 1 + wcslen(pwszStrings
[1]) + 1 + wcslen(pwszStrings
[2]) + 1) * sizeof(WCHAR
));
39 DWORD fPortType
= 1337;
42 // Setting cElements to zero should yield success.
43 SetLastError(0xDEADBEEF);
44 ok(MarshallDownStructuresArray(NULL
, 0, NULL
, 0, FALSE
), "MarshallDownStructuresArray returns FALSE!\n");
45 ok(GetLastError() == 0xDEADBEEF, "GetLastError returns %lu!\n", GetLastError());
47 // Setting cElements non-zero should fail with ERROR_INVALID_PARAMETER.
48 SetLastError(0xDEADBEEF);
49 ok(!MarshallDownStructuresArray(NULL
, 1, NULL
, 0, FALSE
), "MarshallDownStructuresArray returns TRUE!\n");
50 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "GetLastError returns %lu!\n", GetLastError());
52 // This is triggered by both pStructuresArray and pInfo.
53 SetLastError(0xDEADBEEF);
54 ok(!MarshallDownStructuresArray(INVALID_POINTER
, 1, NULL
, 0, FALSE
), "MarshallDownStructuresArray returns TRUE!\n");
55 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "GetLastError returns %lu!\n", GetLastError());
57 SetLastError(0xDEADBEEF);
58 ok(!MarshallDownStructuresArray(NULL
, 1, (const MARSHALLING_INFO
*)INVALID_POINTER
, 0, FALSE
), "MarshallDownStructuresArray returns TRUE!\n");
59 ok(GetLastError() == ERROR_INVALID_PARAMETER
, "GetLastError returns %lu!\n", GetLastError());
61 // Now create two PORT_INFO_2W structures.
62 pPortInfo2
= (PPORT_INFO_2W
)HeapAlloc(GetProcessHeap(), 0, cbPortInfo2Size
);
63 pPortInfoEnd
= (PBYTE
)pPortInfo2
+ cbPortInfo2Size
;
65 (&pPortInfo2
[0])->fPortType
= fPortType
;
66 (&pPortInfo2
[0])->Reserved
= Reserved
;
67 pPortInfoEnd
= PackStrings(pwszStrings
, (PBYTE
)(&pPortInfo2
[0]), dwPortInfo2Offsets
, pPortInfoEnd
);
69 (&pPortInfo2
[1])->fPortType
= fPortType
+ 1;
70 (&pPortInfo2
[1])->Reserved
= Reserved
+ 1;
71 pPortInfoEnd
= PackStrings(pwszStrings
, (PBYTE
)(&pPortInfo2
[1]), dwPortInfo2Offsets
, pPortInfoEnd
);
74 pPortInfo2Copy
= (PPORT_INFO_2W
)HeapAlloc(GetProcessHeap(), 0, cbPortInfo2Size
);
75 CopyMemory(pPortInfo2Copy
, pPortInfo2
, cbPortInfo2Size
);
77 // Marshall them down.
78 SetLastError(0xDEADBEEF);
79 ok(MarshallDownStructuresArray(pPortInfo2
, cElements
, pPortInfoMarshalling
[2]->pInfo
, pPortInfoMarshalling
[2]->cbStructureSize
, TRUE
), "MarshallDownStructuresArray returns FALSE!\n");
80 ok(GetLastError() == 0xDEADBEEF, "GetLastError returns %lu!\n", GetLastError());
82 // DWORD values should be unchanged.
83 ok((&pPortInfo2
[0])->fPortType
== fPortType
, "fPortType is %lu!\n", (&pPortInfo2
[0])->fPortType
);
84 ok((&pPortInfo2
[0])->Reserved
== Reserved
, "Reserved is %lu!\n", (&pPortInfo2
[0])->Reserved
);
85 ok((&pPortInfo2
[1])->fPortType
== fPortType
+ 1, "fPortType is %lu!\n", (&pPortInfo2
[1])->fPortType
);
86 ok((&pPortInfo2
[1])->Reserved
== Reserved
+ 1, "Reserved is %lu!\n", (&pPortInfo2
[1])->Reserved
);
88 // Pointers should now contain relative offsets.
89 ok((ULONG_PTR
)(&pPortInfo2
[0])->pPortName
== ((ULONG_PTR
)(&pPortInfo2Copy
[0])->pPortName
- (ULONG_PTR
)(&pPortInfo2
[0])), "pPortName is %p!\n", (&pPortInfo2
[0])->pPortName
);
90 ok((ULONG_PTR
)(&pPortInfo2
[0])->pMonitorName
== ((ULONG_PTR
)(&pPortInfo2Copy
[0])->pMonitorName
- (ULONG_PTR
)(&pPortInfo2
[0])), "pMonitorName is %p!\n", (&pPortInfo2
[0])->pMonitorName
);
91 ok((ULONG_PTR
)(&pPortInfo2
[0])->pDescription
== ((ULONG_PTR
)(&pPortInfo2Copy
[0])->pDescription
- (ULONG_PTR
)(&pPortInfo2
[0])), "pDescription is %p!\n", (&pPortInfo2
[0])->pDescription
);
92 ok((ULONG_PTR
)(&pPortInfo2
[1])->pPortName
== ((ULONG_PTR
)(&pPortInfo2Copy
[1])->pPortName
- (ULONG_PTR
)(&pPortInfo2
[1])), "pPortName is %p!\n", (&pPortInfo2
[1])->pPortName
);
93 ok((ULONG_PTR
)(&pPortInfo2
[1])->pMonitorName
== ((ULONG_PTR
)(&pPortInfo2Copy
[1])->pMonitorName
- (ULONG_PTR
)(&pPortInfo2
[1])), "pMonitorName is %p!\n", (&pPortInfo2
[1])->pMonitorName
);
94 ok((ULONG_PTR
)(&pPortInfo2
[1])->pDescription
== ((ULONG_PTR
)(&pPortInfo2Copy
[1])->pDescription
- (ULONG_PTR
)(&pPortInfo2
[1])), "pDescription is %p!\n", (&pPortInfo2
[1])->pDescription
);
96 // Marshall them up again.
97 // We need a backup of the marshalled down array to experiment with MarshallUpStructuresArray.
98 pPortInfo2Test
= (PPORT_INFO_2W
)HeapAlloc(GetProcessHeap(), 0, cbPortInfo2Size
);
99 CopyMemory(pPortInfo2Test
, pPortInfo2
, cbPortInfo2Size
);
101 // Due to the implementation of PackStrings, (&pPortInfo2[0])->pPortName contains the highest offset.
102 // Show that MarshallUpStructuresArray checks the offsets and bails out with ERROR_INVALID_DATA if cbSize <= highest offset.
103 SetLastError(0xDEADBEEF);
104 ok(!MarshallUpStructuresArray((DWORD_PTR
)(&pPortInfo2
[0])->pPortName
, pPortInfo2Test
, cElements
, pPortInfoMarshalling
[2]->pInfo
, pPortInfoMarshalling
[2]->cbStructureSize
, TRUE
), "MarshallUpStructuresArray returns TRUE!\n");
105 ok(GetLastError() == ERROR_INVALID_DATA
, "GetLastError returns %lu!\n", GetLastError());
107 // It works with cbSize > highest offset.
108 // In real world cases, we would use cbPortInfo2Size for cbSize.
109 SetLastError(0xDEADBEEF);
110 ok(MarshallUpStructuresArray((DWORD_PTR
)(&pPortInfo2
[0])->pPortName
+ 1, pPortInfo2
, cElements
, pPortInfoMarshalling
[2]->pInfo
, pPortInfoMarshalling
[2]->cbStructureSize
, TRUE
), "MarshallUpStructuresArray returns FALSE!\n");
111 ok(GetLastError() == 0xDEADBEEF, "GetLastError returns %lu!\n", GetLastError());
113 // pPortInfo2 should now be identical to the copy again.
114 ok(RtlEqualMemory(pPortInfo2
, pPortInfo2Copy
, cbPortInfo2Size
), "pPortInfo2 and pPortInfo2Copy are not equal after marshalling down and up!\n");
117 HeapFree(GetProcessHeap(), 0, pPortInfo2
);
118 HeapFree(GetProcessHeap(), 0, pPortInfo2Copy
);
119 HeapFree(GetProcessHeap(), 0, pPortInfo2Test
);