aboutsummaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/memutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/memutil.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/memutil.cpp336
1 files changed, 336 insertions, 0 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/memutil.cpp b/src/libs/dutil/WixToolset.DUtil/memutil.cpp
new file mode 100644
index 00000000..c805a9c0
--- /dev/null
+++ b/src/libs/dutil/WixToolset.DUtil/memutil.cpp
@@ -0,0 +1,336 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4
5
6// Exit macros
7#define MemExitOnLastError(x, s, ...) ExitOnLastErrorSource(DUTIL_SOURCE_MEMUTIL, x, s, __VA_ARGS__)
8#define MemExitOnLastErrorDebugTrace(x, s, ...) ExitOnLastErrorDebugTraceSource(DUTIL_SOURCE_MEMUTIL, x, s, __VA_ARGS__)
9#define MemExitWithLastError(x, s, ...) ExitWithLastErrorSource(DUTIL_SOURCE_MEMUTIL, x, s, __VA_ARGS__)
10#define MemExitOnFailure(x, s, ...) ExitOnFailureSource(DUTIL_SOURCE_MEMUTIL, x, s, __VA_ARGS__)
11#define MemExitOnRootFailure(x, s, ...) ExitOnRootFailureSource(DUTIL_SOURCE_MEMUTIL, x, s, __VA_ARGS__)
12#define MemExitOnFailureDebugTrace(x, s, ...) ExitOnFailureDebugTraceSource(DUTIL_SOURCE_MEMUTIL, x, s, __VA_ARGS__)
13#define MemExitOnNull(p, x, e, s, ...) ExitOnNullSource(DUTIL_SOURCE_MEMUTIL, p, x, e, s, __VA_ARGS__)
14#define MemExitOnNullWithLastError(p, x, s, ...) ExitOnNullWithLastErrorSource(DUTIL_SOURCE_MEMUTIL, p, x, s, __VA_ARGS__)
15#define MemExitOnNullDebugTrace(p, x, e, s, ...) ExitOnNullDebugTraceSource(DUTIL_SOURCE_MEMUTIL, p, x, e, s, __VA_ARGS__)
16#define MemExitOnInvalidHandleWithLastError(p, x, s, ...) ExitOnInvalidHandleWithLastErrorSource(DUTIL_SOURCE_MEMUTIL, p, x, s, __VA_ARGS__)
17#define MemExitOnWin32Error(e, x, s, ...) ExitOnWin32ErrorSource(DUTIL_SOURCE_MEMUTIL, e, x, s, __VA_ARGS__)
18#define MemExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_MEMUTIL, g, x, s, __VA_ARGS__)
19
20
21#if DEBUG
22static BOOL vfMemInitialized = FALSE;
23#endif
24
25extern "C" HRESULT DAPI MemInitialize()
26{
27#if DEBUG
28 vfMemInitialized = TRUE;
29#endif
30 return S_OK;
31}
32
33extern "C" void DAPI MemUninitialize()
34{
35#if DEBUG
36 vfMemInitialized = FALSE;
37#endif
38}
39
40extern "C" LPVOID DAPI MemAlloc(
41 __in SIZE_T cbSize,
42 __in BOOL fZero
43 )
44{
45// AssertSz(vfMemInitialized, "MemInitialize() not called, this would normally crash");
46 AssertSz(0 < cbSize, "MemAlloc() called with invalid size");
47 return ::HeapAlloc(::GetProcessHeap(), fZero ? HEAP_ZERO_MEMORY : 0, cbSize);
48}
49
50
51extern "C" LPVOID DAPI MemReAlloc(
52 __in LPVOID pv,
53 __in SIZE_T cbSize,
54 __in BOOL fZero
55 )
56{
57// AssertSz(vfMemInitialized, "MemInitialize() not called, this would normally crash");
58 AssertSz(0 < cbSize, "MemReAlloc() called with invalid size");
59 return ::HeapReAlloc(::GetProcessHeap(), fZero ? HEAP_ZERO_MEMORY : 0, pv, cbSize);
60}
61
62
63extern "C" HRESULT DAPI MemReAllocSecure(
64 __in LPVOID pv,
65 __in SIZE_T cbSize,
66 __in BOOL fZero,
67 __deref_out LPVOID* ppvNew
68 )
69{
70// AssertSz(vfMemInitialized, "MemInitialize() not called, this would normally crash");
71 AssertSz(ppvNew, "MemReAllocSecure() called with uninitialized pointer");
72 AssertSz(0 < cbSize, "MemReAllocSecure() called with invalid size");
73
74 HRESULT hr = S_OK;
75 DWORD dwFlags = HEAP_REALLOC_IN_PLACE_ONLY;
76 LPVOID pvNew = NULL;
77
78 dwFlags |= fZero ? HEAP_ZERO_MEMORY : 0;
79 pvNew = ::HeapReAlloc(::GetProcessHeap(), dwFlags, pv, cbSize);
80 if (!pvNew)
81 {
82 pvNew = MemAlloc(cbSize, fZero);
83 if (pvNew)
84 {
85 const SIZE_T cbCurrent = MemSize(pv);
86 if (-1 == cbCurrent)
87 {
88 MemExitOnRootFailure(hr = E_INVALIDARG, "Failed to get memory size");
89 }
90
91 // HeapReAlloc may allocate more memory than requested.
92 const SIZE_T cbNew = MemSize(pvNew);
93 if (-1 == cbNew)
94 {
95 MemExitOnRootFailure(hr = E_INVALIDARG, "Failed to get memory size");
96 }
97
98 cbSize = cbNew;
99 if (cbSize > cbCurrent)
100 {
101 cbSize = cbCurrent;
102 }
103
104 memcpy_s(pvNew, cbNew, pv, cbSize);
105
106 SecureZeroMemory(pv, cbCurrent);
107 MemFree(pv);
108 }
109 }
110 MemExitOnNull(pvNew, hr, E_OUTOFMEMORY, "Failed to reallocate memory");
111
112 *ppvNew = pvNew;
113 pvNew = NULL;
114
115LExit:
116 ReleaseMem(pvNew);
117
118 return hr;
119}
120
121
122extern "C" HRESULT DAPI MemAllocArray(
123 __inout LPVOID* ppvArray,
124 __in SIZE_T cbArrayType,
125 __in DWORD dwItemCount
126 )
127{
128 return MemReAllocArray(ppvArray, 0, cbArrayType, dwItemCount);
129}
130
131
132extern "C" HRESULT DAPI MemReAllocArray(
133 __inout LPVOID* ppvArray,
134 __in DWORD cArray,
135 __in SIZE_T cbArrayType,
136 __in DWORD dwNewItemCount
137 )
138{
139 HRESULT hr = S_OK;
140 DWORD cNew = 0;
141 LPVOID pvNew = NULL;
142 SIZE_T cbNew = 0;
143
144 hr = ::DWordAdd(cArray, dwNewItemCount, &cNew);
145 MemExitOnFailure(hr, "Integer overflow when calculating new element count.");
146
147 hr = ::SIZETMult(cNew, cbArrayType, &cbNew);
148 MemExitOnFailure(hr, "Integer overflow when calculating new block size.");
149
150 if (*ppvArray)
151 {
152 SIZE_T cbCurrent = MemSize(*ppvArray);
153 if (cbCurrent < cbNew)
154 {
155 pvNew = MemReAlloc(*ppvArray, cbNew, TRUE);
156 MemExitOnNull(pvNew, hr, E_OUTOFMEMORY, "Failed to allocate larger array.");
157
158 *ppvArray = pvNew;
159 }
160 }
161 else
162 {
163 pvNew = MemAlloc(cbNew, TRUE);
164 MemExitOnNull(pvNew, hr, E_OUTOFMEMORY, "Failed to allocate new array.");
165
166 *ppvArray = pvNew;
167 }
168
169LExit:
170 return hr;
171}
172
173
174extern "C" HRESULT DAPI MemEnsureArraySize(
175 __deref_inout_bcount(cArray * cbArrayType) LPVOID* ppvArray,
176 __in DWORD cArray,
177 __in SIZE_T cbArrayType,
178 __in DWORD dwGrowthCount
179 )
180{
181 HRESULT hr = S_OK;
182 DWORD cNew = 0;
183 LPVOID pvNew = NULL;
184 SIZE_T cbNew = 0;
185
186 hr = ::DWordAdd(cArray, dwGrowthCount, &cNew);
187 MemExitOnFailure(hr, "Integer overflow when calculating new element count.");
188
189 hr = ::SIZETMult(cNew, cbArrayType, &cbNew);
190 MemExitOnFailure(hr, "Integer overflow when calculating new block size.");
191
192 if (*ppvArray)
193 {
194 SIZE_T cbUsed = cArray * cbArrayType;
195 SIZE_T cbCurrent = MemSize(*ppvArray);
196 if (cbCurrent < cbUsed)
197 {
198 pvNew = MemReAlloc(*ppvArray, cbNew, TRUE);
199 MemExitOnNull(pvNew, hr, E_OUTOFMEMORY, "Failed to allocate array larger.");
200
201 *ppvArray = pvNew;
202 }
203 }
204 else
205 {
206 pvNew = MemAlloc(cbNew, TRUE);
207 MemExitOnNull(pvNew, hr, E_OUTOFMEMORY, "Failed to allocate new array.");
208
209 *ppvArray = pvNew;
210 }
211
212LExit:
213 return hr;
214}
215
216
217extern "C" HRESULT DAPI MemInsertIntoArray(
218 __deref_inout_bcount((cExistingArray + cInsertItems) * cbArrayType) LPVOID* ppvArray,
219 __in DWORD dwInsertIndex,
220 __in DWORD cInsertItems,
221 __in DWORD cExistingArray,
222 __in SIZE_T cbArrayType,
223 __in DWORD dwGrowthCount
224 )
225{
226 HRESULT hr = S_OK;
227 DWORD i;
228 BYTE *pbArray = NULL;
229
230 if (0 == cInsertItems)
231 {
232 ExitFunction1(hr = S_OK);
233 }
234
235 hr = MemEnsureArraySize(ppvArray, cExistingArray + cInsertItems, cbArrayType, dwGrowthCount);
236 MemExitOnFailure(hr, "Failed to resize array while inserting items");
237
238 pbArray = reinterpret_cast<BYTE *>(*ppvArray);
239 for (i = cExistingArray + cInsertItems - 1; i > dwInsertIndex; --i)
240 {
241 memcpy_s(pbArray + i * cbArrayType, cbArrayType, pbArray + (i - 1) * cbArrayType, cbArrayType);
242 }
243
244 // Zero out the newly-inserted items
245 memset(pbArray + dwInsertIndex * cbArrayType, 0, cInsertItems * cbArrayType);
246
247LExit:
248 return hr;
249}
250
251extern "C" void DAPI MemRemoveFromArray(
252 __inout_bcount((cExistingArray) * cbArrayType) LPVOID pvArray,
253 __in DWORD dwRemoveIndex,
254 __in DWORD cRemoveItems,
255 __in DWORD cExistingArray,
256 __in SIZE_T cbArrayType,
257 __in BOOL fPreserveOrder
258 )
259{
260 BYTE *pbArray = static_cast<BYTE *>(pvArray);
261 DWORD cItemsLeftAfterRemoveIndex = (cExistingArray - cRemoveItems - dwRemoveIndex);
262
263 if (fPreserveOrder)
264 {
265 memmove(pbArray + dwRemoveIndex * cbArrayType, pbArray + (dwRemoveIndex + cRemoveItems) * cbArrayType, cItemsLeftAfterRemoveIndex * cbArrayType);
266 }
267 else
268 {
269 DWORD cItemsToMove = (cRemoveItems > cItemsLeftAfterRemoveIndex ? cItemsLeftAfterRemoveIndex : cRemoveItems);
270 memmove(pbArray + dwRemoveIndex * cbArrayType, pbArray + (cExistingArray - cItemsToMove) * cbArrayType, cItemsToMove * cbArrayType);
271 }
272
273 ZeroMemory(pbArray + (cExistingArray - cRemoveItems) * cbArrayType, cRemoveItems * cbArrayType);
274}
275
276extern "C" void DAPI MemArraySwapItems(
277 __inout_bcount(cbArrayType) LPVOID pvArray,
278 __in DWORD dwIndex1,
279 __in DWORD dwIndex2,
280 __in SIZE_T cbArrayType
281 )
282{
283 BYTE *pbArrayItem1 = static_cast<BYTE *>(pvArray) + dwIndex1 * cbArrayType;
284 BYTE *pbArrayItem2 = static_cast<BYTE *>(pvArray) + dwIndex2 * cbArrayType;
285 DWORD dwByteIndex = 0;
286
287 if (dwIndex1 == dwIndex2)
288 {
289 return;
290 }
291
292 // Use XOR swapping to avoid the need for a temporary item
293 while (dwByteIndex < cbArrayType)
294 {
295 // Try to do many bytes at a time in most cases
296 if (cbArrayType - dwByteIndex > sizeof(DWORD64))
297 {
298 // x: X xor Y
299 *(reinterpret_cast<DWORD64 *>(pbArrayItem1 + dwByteIndex)) ^= *(reinterpret_cast<DWORD64 *>(pbArrayItem2 + dwByteIndex));
300 // y: X xor Y
301 *(reinterpret_cast<DWORD64 *>(pbArrayItem2 + dwByteIndex)) = *(reinterpret_cast<DWORD64 *>(pbArrayItem1 + dwByteIndex)) ^ *(reinterpret_cast<DWORD64 *>(pbArrayItem2 + dwByteIndex));
302 // x: X xor Y
303 *(reinterpret_cast<DWORD64 *>(pbArrayItem1 + dwByteIndex)) ^= *(reinterpret_cast<DWORD64 *>(pbArrayItem2 + dwByteIndex));
304
305 dwByteIndex += sizeof(DWORD64);
306 }
307 else
308 {
309 // x: X xor Y
310 *(reinterpret_cast<unsigned char *>(pbArrayItem1 + dwByteIndex)) ^= *(reinterpret_cast<unsigned char *>(pbArrayItem2 + dwByteIndex));
311 // y: X xor Y
312 *(reinterpret_cast<unsigned char *>(pbArrayItem2 + dwByteIndex)) = *(reinterpret_cast<unsigned char *>(pbArrayItem1 + dwByteIndex)) ^ *(reinterpret_cast<unsigned char *>(pbArrayItem2 + dwByteIndex));
313 // x: X xor Y
314 *(reinterpret_cast<unsigned char *>(pbArrayItem1 + dwByteIndex)) ^= *(reinterpret_cast<unsigned char *>(pbArrayItem2 + dwByteIndex));
315
316 dwByteIndex += sizeof(unsigned char);
317 }
318 }
319}
320
321extern "C" HRESULT DAPI MemFree(
322 __in LPVOID pv
323 )
324{
325// AssertSz(vfMemInitialized, "MemInitialize() not called, this would normally crash");
326 return ::HeapFree(::GetProcessHeap(), 0, pv) ? S_OK : HRESULT_FROM_WIN32(::GetLastError());
327}
328
329
330extern "C" SIZE_T DAPI MemSize(
331 __in LPCVOID pv
332 )
333{
334// AssertSz(vfMemInitialized, "MemInitialize() not called, this would normally crash");
335 return ::HeapSize(::GetProcessHeap(), 0, pv);
336}