[INCLUDE/REACTOS][LOCALMON][LOCALSPL][SPOOLSS] Add some missing VOIDs. CORE-11799...
[reactos.git] / win32ss / printing / base / spoolss / memory.c
1 /*
2 * PROJECT: ReactOS Spooler Router
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Functions for allocating and freeing memory
5 * COPYRIGHT: Copyright 2015-2017 Colin Finck (colin@reactos.org)
6 */
7
8 #include "precomp.h"
9
10
11 /**
12 * @name AlignRpcPtr
13 *
14 * Checks if the input buffer and buffer size are 4-byte aligned.
15 * If the buffer size is not 4-byte aligned, it is aligned down.
16 * If the input buffer is not 4-byte aligned, a 4-byte aligned buffer of the aligned down buffer size is allocated and returned.
17 *
18 * @param pBuffer
19 * The buffer to check.
20 *
21 * @param pcbBuffer
22 * Pointer to the buffer size to check. Its value is aligned down if needed.
23 *
24 * @return
25 * pBuffer if pBuffer is already 4-byte aligned, or a newly allocated 4-byte aligned buffer of the aligned down buffer size otherwise.
26 * If a buffer was allocated, you have to free it using UndoAlignRpcPtr.
27 */
28 PVOID WINAPI
29 AlignRpcPtr(PVOID pBuffer, PDWORD pcbBuffer)
30 {
31 ASSERT(pcbBuffer);
32
33 // Align down the buffer size in pcbBuffer to a 4-byte boundary.
34 *pcbBuffer -= *pcbBuffer % sizeof(DWORD);
35
36 // Check if pBuffer is 4-byte aligned. If not, allocate a 4-byte aligned buffer.
37 if ((ULONG_PTR)pBuffer % sizeof(DWORD))
38 pBuffer = DllAllocSplMem(*pcbBuffer);
39
40 return pBuffer;
41 }
42
43 /**
44 * @name AllocSplStr
45 *
46 * Allocates memory for a Unicode string and copies the input string into it.
47 * Equivalent of wcsdup, but the returned buffer is allocated from the spooler heap and must be freed with DllFreeSplStr.
48 *
49 * @param pwszInput
50 * The input string to copy
51 *
52 * @return
53 * Pointer to the copied string or NULL if no memory could be allocated.
54 */
55 PWSTR WINAPI
56 AllocSplStr(PCWSTR pwszInput)
57 {
58 DWORD cbInput;
59 PWSTR pwszOutput;
60
61 // Sanity check
62 if (!pwszInput)
63 return NULL;
64
65 // Get the length of the input string.
66 cbInput = (wcslen(pwszInput) + 1) * sizeof(WCHAR);
67
68 // Allocate it. We don't use DllAllocSplMem here, because it unnecessarily zeroes the memory.
69 pwszOutput = HeapAlloc(hProcessHeap, 0, cbInput);
70 if (!pwszOutput)
71 {
72 ERR("HeapAlloc failed!\n");
73 return NULL;
74 }
75
76 // Copy the string and return it.
77 CopyMemory(pwszOutput, pwszInput, cbInput);
78 return pwszOutput;
79 }
80
81 /**
82 * @name DllAllocSplMem
83 *
84 * Allocate a block of zeroed memory.
85 * Windows allocates from a separate spooler heap here while we just use the process heap.
86 *
87 * @param dwBytes
88 * Number of bytes to allocate.
89 *
90 * @return
91 * A pointer to the allocated memory or NULL in case of an error.
92 * You have to free this memory using DllFreeSplMem.
93 */
94 PVOID WINAPI
95 DllAllocSplMem(DWORD dwBytes)
96 {
97 return HeapAlloc(hProcessHeap, HEAP_ZERO_MEMORY, dwBytes);
98 }
99
100 /**
101 * @name DllFreeSplMem
102 *
103 * Frees the memory allocated with DllAllocSplMem.
104 *
105 * @param pMem
106 * Pointer to the allocated memory.
107 *
108 * @return
109 * TRUE in case of success, FALSE otherwise.
110 */
111 BOOL WINAPI
112 DllFreeSplMem(PVOID pMem)
113 {
114 return HeapFree(hProcessHeap, 0, pMem);
115 }
116
117 /**
118 * @name DllFreeSplStr
119 *
120 * Frees the string allocated with AllocSplStr.
121 *
122 * @param pwszString
123 * Pointer to the allocated string.
124 *
125 * @return
126 * TRUE in case of success, FALSE otherwise.
127 */
128 BOOL WINAPI
129 DllFreeSplStr(PWSTR pwszString)
130 {
131 return HeapFree(hProcessHeap, 0, pwszString);
132 }
133
134 /**
135 * @name ReallocSplMem
136 *
137 * Allocates a new block of memory and copies the contents of the old block into the new one.
138 *
139 * @param pOldMem
140 * Pointer to the old block of memory.
141 * If this parameter is NULL, ReallocSplMem behaves exactly like DllAllocSplMem.
142 *
143 * @param cbOld
144 * Number of bytes to copy from the old block into the new one.
145 *
146 * @param cbNew
147 * Number of bytes to allocate for the new block.
148 *
149 * @return
150 * A pointer to the allocated new block or NULL in case of an error.
151 * You have to free this memory using DllFreeSplMem.
152 */
153 PVOID WINAPI
154 ReallocSplMem(PVOID pOldMem, DWORD cbOld, DWORD cbNew)
155 {
156 PVOID pNewMem;
157
158 // Always allocate the new block of memory.
159 pNewMem = DllAllocSplMem(cbNew);
160 if (!pNewMem)
161 {
162 ERR("DllAllocSplMem failed!\n");
163 return NULL;
164 }
165
166 // Copy the old memory into the new block and free it.
167 if (pOldMem)
168 {
169 CopyMemory(pNewMem, pOldMem, min(cbOld, cbNew));
170 DllFreeSplMem(pOldMem);
171 }
172
173 return pNewMem;
174 }
175
176 /**
177 * @name ReallocSplStr
178 *
179 * Frees a string allocated by AllocSplStr and copies the given Unicode string into a newly allocated block of memory.
180 *
181 * @param ppwszString
182 * Pointer to the string pointer allocated by AllocSplStr.
183 * When the function returns, the variable receives the pointer to the copied string.
184 *
185 * @param pwszInput
186 * The Unicode string to copy into the new block of memory.
187 *
188 * @return
189 * Returns TRUE in any case.
190 */
191 BOOL WINAPI
192 ReallocSplStr(PWSTR* ppwszString, PCWSTR pwszInput)
193 {
194 if (*ppwszString)
195 DllFreeSplStr(*ppwszString);
196
197 *ppwszString = AllocSplStr(pwszInput);
198
199 return TRUE;
200 }
201
202 /**
203 * @name UndoAlignRpcPtr
204 *
205 * Copies the data from the aligned buffer previously allocated by AlignRpcPtr back to the original unaligned buffer.
206 * The aligned buffer is freed.
207 *
208 * Also aligns up the returned required buffer size of a function to a 4-byte boundary.
209 *
210 * @param pDestinationBuffer
211 * The original unaligned buffer, which you input as pBuffer to AlignRpcPtr.
212 * The data from pSourceBuffer is copied into this buffer before pSourceBuffer is freed.
213 * If AlignRpcPtr did not allocate a buffer, pDestinationBuffer equals pSourceBuffer and no memory is copied or freed.
214 * This parameter may be NULL if pSourceBuffer is NULL or cbBuffer is 0.
215 *
216 * @param pSourceBuffer
217 * The aligned buffer, which is returned by AlignRpcPtr.
218 * Its data is copied into pDestinationBuffer and then pSourceBuffer is freed.
219 * If AlignRpcPtr did not allocate a buffer, pDestinationBuffer equals pSourceBuffer and no memory is copied or freed.
220 * This parameter may be NULL.
221 *
222 * @param cbBuffer
223 * Number of bytes to copy.
224 * Set this to the size returned by AlignRpcPtr's pcbBuffer or less.
225 *
226 * @param pcbNeeded
227 * Let this parameter point to your variable calculating the needed bytes for a buffer and returning this value to the user.
228 * It is then aligned up to a 4-byte boundary, so that the user supplies a large enough buffer in the next call.
229 * Otherwise, AlignRpcPtr would align down the buffer size in the next call and your buffer would be smaller than intended.
230 * This parameter may be NULL.
231 *
232 * @return
233 * pcbNeeded
234 */
235 PDWORD WINAPI
236 UndoAlignRpcPtr(PVOID pDestinationBuffer, PVOID pSourceBuffer, DWORD cbBuffer, PDWORD pcbNeeded)
237 {
238 // pDestinationBuffer is accessed unless pSourceBuffer equals pDestinationBuffer or cbBuffer is 0.
239 ASSERT(pDestinationBuffer || pSourceBuffer == pDestinationBuffer || cbBuffer == 0);
240
241 // If pSourceBuffer is given, and source and destination pointers don't match,
242 // we assume that pSourceBuffer is the buffer allocated by AlignRpcPtr.
243 if (pSourceBuffer && pSourceBuffer != pDestinationBuffer)
244 {
245 // Copy back the buffer data to the (usually unaligned) destination buffer
246 // and free the buffer allocated by AlignRpcPtr.
247 CopyMemory(pDestinationBuffer, pSourceBuffer, cbBuffer);
248 DllFreeSplMem(pSourceBuffer);
249 }
250
251 // If pcbNeeded is given, align it up to a 4-byte boundary.
252 if (pcbNeeded && *pcbNeeded % sizeof(DWORD))
253 *pcbNeeded += sizeof(DWORD) - *pcbNeeded % sizeof(DWORD);
254
255 return pcbNeeded;
256 }