Merge r67713 and r67936 (Eric's parport driver) from trunk
[reactos.git] / reactos / win32ss / printing / base / spoolss / tools.c
1 /*
2 * PROJECT: ReactOS Spooler Router
3 * LICENSE: GNU LGPL v2.1 or any later version as published by the Free Software Foundation
4 * PURPOSE: Miscellaneous tool functions
5 * COPYRIGHT: Copyright 2015 Colin Finck <colin@reactos.org>
6 */
7
8 #include "precomp.h"
9
10
11 /**
12 * @name MarshallDownStructure
13 *
14 * Prepare a structure for marshalling/serialization by replacing absolute pointer addresses in its fields by relative offsets.
15 *
16 * @param pStructure
17 * Pointer to the structure to operate on.
18 *
19 * @param pParameters
20 * Array of MARSHALL_DOWN_INFO elements containing information about the fields of the structure as well as how to modify them.
21 * See the documentation on MARSHALL_DOWN_INFO for more information.
22 * You have to indicate the end of the array by setting the dwOffset field to MAXDWORD.
23 *
24 * @param cbStructureSize
25 * Apparently, this is the size in bytes of the structure given through pStructure under Windows.
26 * This parameter is unused in my implementation.
27 *
28 * @param bSomeBoolean
29 * Unknown boolean value
30 *
31 * @return
32 * TRUE if the structure was successfully adjusted, FALSE otherwise.
33 */
34 BOOL WINAPI
35 MarshallDownStructure(PVOID pStructure, PMARSHALL_DOWN_INFO pParameters, DWORD cbStructureSize, BOOL bSomeBoolean)
36 {
37 // Sanity checks
38 if (!pStructure || !pParameters)
39 {
40 SetLastError(ERROR_INVALID_PARAMETER);
41 return FALSE;
42 }
43
44 // Loop until we reach an element with offset set to MAXDWORD.
45 while (pParameters->dwOffset != MAXDWORD)
46 {
47 if (pParameters->bAdjustAddress)
48 {
49 // Apply the byte offset on pStructure. There must be a pointer at this position, whose address we're adjusting
50 // by subtracting the address of pStructure from it.
51 *((PULONG_PTR)((PBYTE)pStructure + pParameters->dwOffset)) -= (ULONG_PTR)pStructure;
52 }
53
54 // Advance to the next element description.
55 pParameters++;
56 }
57
58 return TRUE;
59 }
60
61 /**
62 * @name PackStrings
63 *
64 * Takes an array of Unicode strings and fills an output buffer with these strings at the end and pointers to each string at specific offsets.
65 * Useful helper for functions that copy an information structure including strings into a given buffer (like PRINTER_INFO_1).
66 *
67 * @param pSource
68 * The array of Unicode strings to copy. Needs to have at least as many elements as the DestOffsets array.
69 *
70 * @param pDest
71 * Pointer to the beginning of the output buffer.
72 * The caller is responsible for verifying that this buffer is large enough to hold all strings and pointers.
73 *
74 * @param DestOffsets
75 * Array of byte offsets in the output buffer. For each element of DestOffsets, the function will copy the address of the corresponding copied
76 * string of pSource to this location in the output buffer. If a string in pSource is NULL, the function will set the pointer address to NULL
77 * in the output buffer.
78 * Use macros like FIELD_OFFSET to calculate the offsets for this array.
79 * The last element of the array must have the value MAXDWORD to let the function detect the end of the array.
80 *
81 * @param pEnd
82 * Pointer to the end of the output buffer. That means the first element outside of the buffer given in pDest.
83 *
84 * @return
85 * Returns a pointer to the beginning of the strings in pDest.
86 * The strings are copied in reverse order, so this pointer will point to the last copied string of pSource.
87 */
88 PBYTE WINAPI
89 PackStrings(PCWSTR* pSource, PBYTE pDest, PDWORD DestOffsets, PBYTE pEnd)
90 {
91 DWORD cbString;
92 ULONG_PTR StringAddress;
93
94 // Loop until we reach an element with offset set to MAXDWORD.
95 while (*DestOffsets != MAXDWORD)
96 {
97 StringAddress = 0;
98
99 if (*pSource)
100 {
101 // Determine the length of the source string.
102 cbString = (wcslen(*pSource) + 1) * sizeof(WCHAR);
103
104 // Copy it before the last string.
105 pEnd -= cbString;
106 StringAddress = (ULONG_PTR)pEnd;
107 CopyMemory(pEnd, *pSource, cbString);
108 }
109
110 // Copy the address of the copied string to the location given by the offset.
111 CopyMemory(&pDest[*DestOffsets], &StringAddress, sizeof(ULONG_PTR));
112
113 // Advance to the next source string and destination offset.
114 pSource++;
115 DestOffsets++;
116 }
117
118 // pEnd is now at the last string we copied. Return this value as a pointer to the beginning of all strings in the output buffer.
119 return pEnd;
120 }