1 /*
2  * PROJECT:     ReactOS Spooler Router API Tests
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Tests for AlignRpcPtr/UndoAlignRpcPtr
5  * COPYRIGHT:   Copyright 2017 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 <spoolss.h>
14 
15 START_TEST(AlignRpcPtr)
16 {
17     char* pMemory;
18     char* pInputBuffer;
19     char* pOutputBuffer;
20     DWORD cbBuffer;
21     PDWORD pcbBuffer;
22 
23     // Allocate memory with GlobalAlloc. It is guaranteed to be aligned to a 8-byte boundary.
24     pMemory = (char*)GlobalAlloc(GMEM_FIXED, 16);
25 
26     // First try AlignRpcPtr with already aligned memory and buffer size. It should leave everything unchanged.
27     pInputBuffer = pMemory;
28     cbBuffer = 8;
29     pOutputBuffer = (char*)AlignRpcPtr(pInputBuffer, &cbBuffer);
30     ok(pOutputBuffer == pInputBuffer, "pOutputBuffer != pInputBuffer\n");
31     ok(cbBuffer == 8, "cbBuffer is %lu\n", cbBuffer);
32 
33     // Now try it with unaligned buffer size. The size should be aligned down while the buffer stays the same.
34     pInputBuffer = pMemory;
35     cbBuffer = 7;
36     pOutputBuffer = (char*)AlignRpcPtr(pInputBuffer, &cbBuffer);
37     ok(pOutputBuffer == pInputBuffer, "pOutputBuffer != pInputBuffer\n");
38     ok(cbBuffer == 4, "cbBuffer is %lu\n", cbBuffer);
39 
40     // Now try with unaligned memory, but aligned buffer size. A new buffer is allocated while the size stays the same.
41     // The allocated buffer is then freed with UndoAlignRpcPtr. It is important to specify 0 as the size here, otherwise
42     // the NULL pointer for pDestinationBuffer is accessed.
43     pInputBuffer = pMemory + 1;
44     cbBuffer = 8;
45     pOutputBuffer = (char*)AlignRpcPtr(pInputBuffer, &cbBuffer);
46     ok(pOutputBuffer != pInputBuffer, "pOutputBuffer == pInputBuffer\n");
47     ok(cbBuffer == 8, "cbBuffer is %lu\n", cbBuffer);
48     ok(!UndoAlignRpcPtr(NULL, pOutputBuffer, 0, NULL), "UndoAlignRpcPtr returns something\n");
49 
50     // Now try with memory and buffer size unaligned. A new buffer of the aligned down size is allocated.
51     pInputBuffer = pMemory + 1;
52     cbBuffer = 7;
53     pOutputBuffer = (char*)AlignRpcPtr(pInputBuffer, &cbBuffer);
54     ok(pOutputBuffer != pInputBuffer, "pOutputBuffer == pInputBuffer\n");
55     ok(cbBuffer == 4, "cbBuffer is %lu\n", cbBuffer);
56 
57     // Prove that AlignRpcPtr also works with a NULL buffer. The size should be aligned down.
58     cbBuffer = 6;
59     ok(!AlignRpcPtr(NULL, &cbBuffer), "AlignRpcPtr returns something\n");
60     ok(cbBuffer == 4, "cbBuffer is %lu\n", cbBuffer);
61 
62     // We can also test all parameters of UndoAlignRpcPtr here.
63     // Because pOutputBuffer != pInputBuffer, it copies the given 4 bytes from (aligned) pOutputBuffer to (unaligned) pInputBuffer
64     // while aligning up the given 7 bytes in our passed &cbBuffer.
65     // &cbBuffer is also returned.
66     strcpy(pOutputBuffer, "abc");
67     strcpy(pInputBuffer, "XXXXXXXXX");
68     cbBuffer = 5;
69     pcbBuffer = UndoAlignRpcPtr(pInputBuffer, pOutputBuffer, 4, &cbBuffer);
70     ok(strcmp(pInputBuffer, "abc") == 0, "pInputBuffer is %s\n", pInputBuffer);
71     ok(pcbBuffer == &cbBuffer, "pcbBuffer != &cbBuffer\n");
72     ok(cbBuffer == 8, "cbBuffer is %lu\n", cbBuffer);
73 
74     // Prove that UndoAlignRpcPtr works without any parameters and doesn't try to copy data from NULL pointers.
75     ok(!UndoAlignRpcPtr(NULL, NULL, 0, NULL), "UndoAlignRpcPtr returns something\n");
76     ok(!UndoAlignRpcPtr(NULL, NULL, 6, NULL), "UndoAlignRpcPtr returns something\n");
77 
78     // Prove that UndoAlignRpcPtr doesn't access source and destination memory at all when they are equal.
79     // If it did, it should crash here, because I'm giving invalid memory addresses.
80     ok(!UndoAlignRpcPtr((PVOID)1, (PVOID)1, 4, NULL), "UndoAlignRpcPtr returns something\n");
81 
82     // Prove that the pcbNeeded parameter of UndoAlignRpcPtr works independently and aligns up to a DWORD.
83     cbBuffer = 0xFFFFFFFD;
84     pcbBuffer = UndoAlignRpcPtr(NULL, NULL, 0, &cbBuffer);
85     ok(pcbBuffer == &cbBuffer, "pcbBuffer != &cbBuffer\n");
86     ok(cbBuffer == 0, "cbBuffer is %lu\n", cbBuffer);
87 
88     GlobalFree(pMemory);
89 }
90