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)
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.
19 * The buffer to check.
22 * Pointer to the buffer size to check. Its value is aligned down if needed.
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.
29 AlignRpcPtr(PVOID pBuffer
, PDWORD pcbBuffer
)
33 // Align down the buffer size in pcbBuffer to a 4-byte boundary.
34 *pcbBuffer
-= *pcbBuffer
% sizeof(DWORD
);
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
);
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.
50 * The input string to copy
53 * Pointer to the copied string or NULL if no memory could be allocated.
56 AllocSplStr(PCWSTR pwszInput
)
65 // Get the length of the input string.
66 cbInput
= (wcslen(pwszInput
) + 1) * sizeof(WCHAR
);
68 // Allocate it. We don't use DllAllocSplMem here, because it unnecessarily zeroes the memory.
69 pwszOutput
= HeapAlloc(hProcessHeap
, 0, cbInput
);
72 ERR("HeapAlloc failed!\n");
76 // Copy the string and return it.
77 CopyMemory(pwszOutput
, pwszInput
, cbInput
);
82 * @name DllAllocSplMem
84 * Allocate a block of zeroed memory.
85 * Windows allocates from a separate spooler heap here while we just use the process heap.
88 * Number of bytes to allocate.
91 * A pointer to the allocated memory or NULL in case of an error.
92 * You have to free this memory using DllFreeSplMem.
95 DllAllocSplMem(DWORD dwBytes
)
97 return HeapAlloc(hProcessHeap
, HEAP_ZERO_MEMORY
, dwBytes
);
101 * @name DllFreeSplMem
103 * Frees the memory allocated with DllAllocSplMem.
106 * Pointer to the allocated memory.
109 * TRUE in case of success, FALSE otherwise.
112 DllFreeSplMem(PVOID pMem
)
114 return HeapFree(hProcessHeap
, 0, pMem
);
118 * @name DllFreeSplStr
120 * Frees the string allocated with AllocSplStr.
123 * Pointer to the allocated string.
126 * TRUE in case of success, FALSE otherwise.
129 DllFreeSplStr(PWSTR pwszString
)
131 return HeapFree(hProcessHeap
, 0, pwszString
);
135 * @name ReallocSplMem
137 * Allocates a new block of memory and copies the contents of the old block into the new one.
140 * Pointer to the old block of memory.
141 * If this parameter is NULL, ReallocSplMem behaves exactly like DllAllocSplMem.
144 * Number of bytes to copy from the old block into the new one.
147 * Number of bytes to allocate for the new block.
150 * A pointer to the allocated new block or NULL in case of an error.
151 * You have to free this memory using DllFreeSplMem.
154 ReallocSplMem(PVOID pOldMem
, DWORD cbOld
, DWORD cbNew
)
158 // Always allocate the new block of memory.
159 pNewMem
= DllAllocSplMem(cbNew
);
162 ERR("DllAllocSplMem failed!\n");
166 // Copy the old memory into the new block and free it.
169 CopyMemory(pNewMem
, pOldMem
, min(cbOld
, cbNew
));
170 DllFreeSplMem(pOldMem
);
177 * @name ReallocSplStr
179 * Frees a string allocated by AllocSplStr and copies the given Unicode string into a newly allocated block of memory.
182 * Pointer to the string pointer allocated by AllocSplStr.
183 * When the function returns, the variable receives the pointer to the copied string.
186 * The Unicode string to copy into the new block of memory.
189 * Returns TRUE in any case.
192 ReallocSplStr(PWSTR
* ppwszString
, PCWSTR pwszInput
)
195 DllFreeSplStr(*ppwszString
);
197 *ppwszString
= AllocSplStr(pwszInput
);
203 * @name UndoAlignRpcPtr
205 * Copies the data from the aligned buffer previously allocated by AlignRpcPtr back to the original unaligned buffer.
206 * The aligned buffer is freed.
208 * Also aligns up the returned required buffer size of a function to a 4-byte boundary.
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.
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.
223 * Number of bytes to copy.
224 * Set this to the size returned by AlignRpcPtr's pcbBuffer or less.
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.
236 UndoAlignRpcPtr(PVOID pDestinationBuffer
, PVOID pSourceBuffer
, DWORD cbBuffer
, PDWORD pcbNeeded
)
238 // pDestinationBuffer is accessed unless pSourceBuffer equals pDestinationBuffer or cbBuffer is 0.
239 ASSERT(pDestinationBuffer
|| pSourceBuffer
== pDestinationBuffer
|| cbBuffer
== 0);
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
)
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
);
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
);