ReactOS 0.4.16-dev-2320-ge1853c6
malloc.c
Go to the documentation of this file.
1/*
2 * Copyright 1997 Marcus Meissner
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19#define COBJMACROS
20
21#include "oleauto.h"
22
23#include "wine/debug.h"
24
26
27static const IMallocVtbl allocator_vtbl;
28
30{
34 BOOL spy_release_pending; /* CoRevokeMallocSpy called with spyed allocations left */
35 void **blocks;
37};
38
39static struct allocator allocator = { .IMalloc_iface.lpVtbl = &allocator_vtbl };
40
43{
44 0, 0, &allocspy_cs,
46 0, 0, { (DWORD_PTR)(__FILE__ ": allocspy_cs") }
47};
48static CRITICAL_SECTION allocspy_cs = { &allocspy_cs_debug, -1, 0, 0, 0, 0 };
49
51{
52 void **blocks;
53
54 if (!allocator.blocks) blocks = LocalAlloc(LMEM_ZEROINIT, length * sizeof(void *));
56 if (blocks)
57 {
60 }
61
62 return blocks != NULL;
63}
64
65static void mallocspy_add_mem(void *mem)
66{
67 void **current;
68
69 if (!mem || (!allocator.blocks_length && !mallocspy_grow(0x1000)))
70 return;
71
72 /* Find a free location */
74 while (*current)
75 {
76 current++;
78 {
79 DWORD old_length = allocator.blocks_length;
81 return;
82 current = allocator.blocks + old_length;
83 }
84 }
85
86 *current = mem;
88}
89
90static void** mallocspy_is_allocation_spyed(const void *mem)
91{
92 void **current = allocator.blocks;
93
94 while (*current != mem)
95 {
96 current++;
98 return NULL;
99 }
100
101 return current;
102}
103
105{
106 void **current;
107
109 return FALSE;
110
112 return FALSE;
113
115 *current = NULL;
116 return TRUE;
117}
118
120{
121 TRACE("%s, %p.\n", debugstr_guid(riid), obj);
122
123 if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IMalloc, riid))
124 {
126 return S_OK;
127 }
128
129 return E_NOINTERFACE;
130}
131
133{
134 return 2;
135}
136
138{
139 return 1;
140}
141
142static void * WINAPI allocator_Alloc(IMalloc *iface, SIZE_T cb)
143{
144 void *addr;
145
146 TRACE("%Id.\n", cb);
147
148 if (allocator.spy)
149 {
150 SIZE_T preAllocResult;
151
153 preAllocResult = IMallocSpy_PreAlloc(allocator.spy, cb);
154 if (cb && !preAllocResult)
155 {
156 /* PreAlloc can force Alloc to fail, but not if cb == 0 */
157 TRACE("returning null\n");
159 return NULL;
160 }
161 }
162
164
165 if (allocator.spy)
166 {
167 addr = IMallocSpy_PostAlloc(allocator.spy, addr);
170 }
171
172 TRACE("%p.\n",addr);
173 return addr;
174}
175
176static void * WINAPI allocator_Realloc(IMalloc *iface, void *pv, SIZE_T cb)
177{
178 void *addr;
179
180 TRACE("%p, %Id.\n", pv, cb);
181
182 if (allocator.spy)
183 {
184 void *real_mem;
185 BOOL spyed;
186
189 cb = IMallocSpy_PreRealloc(allocator.spy, pv, cb, &real_mem, spyed);
190
191 /* check if can release the spy */
193 {
194 IMallocSpy_Release(allocator.spy);
198 }
199
200 if (!cb)
201 {
202 /* PreRealloc can force Realloc to fail */
203 if (allocator.spy)
205 return NULL;
206 }
207
208 pv = real_mem;
209 }
210
211 if (!pv) addr = HeapAlloc(GetProcessHeap(), 0, cb);
212 else if (cb) addr = HeapReAlloc(GetProcessHeap(), 0, pv, cb);
213 else
214 {
215 HeapFree(GetProcessHeap(), 0, pv);
216 addr = NULL;
217 }
218
219 if (allocator.spy)
220 {
221 addr = IMallocSpy_PostRealloc(allocator.spy, addr, TRUE);
224 }
225
226 TRACE("%p.\n", addr);
227 return addr;
228}
229
230static void WINAPI allocator_Free(IMalloc *iface, void *mem)
231{
232 BOOL spyed_block = FALSE, spy_active = FALSE;
233
234 TRACE("%p.\n", mem);
235
236 if (!mem)
237 return;
238
239 if (allocator.spy)
240 {
242 spyed_block = mallocspy_remove_spyed_memory(mem);
243 spy_active = TRUE;
244 mem = IMallocSpy_PreFree(allocator.spy, mem, spyed_block);
245 }
246
248
249 if (spy_active)
250 {
251 IMallocSpy_PostFree(allocator.spy, spyed_block);
252
253 /* check if can release the spy */
255 {
256 IMallocSpy_Release(allocator.spy);
259 }
260
262 }
263}
264
265/******************************************************************************
266 * NOTES
267 * FIXME returns:
268 * win95: size allocated (4 byte boundaries)
269 * win2k: size originally requested !!! (allocated on 8 byte boundaries)
270 */
272{
273 BOOL spyed_block = FALSE, spy_active = FALSE;
274 SIZE_T size;
275
276 TRACE("%p.\n", mem);
277
278 if (!mem)
279 return (SIZE_T)-1;
280
281 if (allocator.spy)
282 {
284 spyed_block = !!mallocspy_is_allocation_spyed(mem);
285 spy_active = TRUE;
286 mem = IMallocSpy_PreGetSize(allocator.spy, mem, spyed_block);
287 }
288
290
291 if (spy_active)
292 {
293 size = IMallocSpy_PostGetSize(allocator.spy, size, spyed_block);
295 }
296
297 return size;
298}
299
301{
302 BOOL spyed_block = FALSE, spy_active = FALSE;
303 int did_alloc;
304
305 TRACE("%p.\n", mem);
306
307 if (!mem)
308 return -1;
309
310 if (allocator.spy)
311 {
313 spyed_block = !!mallocspy_is_allocation_spyed(mem);
314 spy_active = TRUE;
315 mem = IMallocSpy_PreDidAlloc(allocator.spy, mem, spyed_block);
316 }
317
318 did_alloc = HeapValidate(GetProcessHeap(), 0, mem);
319
320 if (spy_active)
321 {
322 did_alloc = IMallocSpy_PostDidAlloc(allocator.spy, mem, spyed_block, did_alloc);
324 }
325
326 return did_alloc;
327}
328
330{
331 BOOL spy_active = FALSE;
332
333 TRACE("\n");
334
335 if (allocator.spy)
336 {
338 spy_active = TRUE;
339 IMallocSpy_PreHeapMinimize(allocator.spy);
340 }
341
342 if (spy_active)
343 {
344 IMallocSpy_PostHeapMinimize(allocator.spy);
346 }
347}
348
349static const IMallocVtbl allocator_vtbl =
350{
360};
361
362/******************************************************************************
363 * CoGetMalloc (combase.@)
364 */
366{
367 if (context != MEMCTX_TASK)
368 {
369 *imalloc = NULL;
370 return E_INVALIDARG;
371 }
372
373 *imalloc = &allocator.IMalloc_iface;
374
375 return S_OK;
376}
377
378/***********************************************************************
379 * CoTaskMemAlloc (combase.@)
380 */
382{
383 return IMalloc_Alloc(&allocator.IMalloc_iface, size);
384}
385
386/***********************************************************************
387 * CoTaskMemFree (combase.@)
388 */
390{
391 IMalloc_Free(&allocator.IMalloc_iface, ptr);
392}
393
394/***********************************************************************
395 * CoTaskMemRealloc (combase.@)
396 */
398{
399 return IMalloc_Realloc(&allocator.IMalloc_iface, ptr, size);
400}
401
402/***********************************************************************
403 * CoRegisterMallocSpy (combase.@)
404 */
406{
408
409 TRACE("%p.\n", spy);
410
411 if (!spy) return E_INVALIDARG;
412
414
415 if (allocator.spy)
417 else if (SUCCEEDED(IMallocSpy_QueryInterface(spy, &IID_IMallocSpy, (void **)&spy)))
418 {
419 allocator.spy = spy;
420 hr = S_OK;
421 }
422
424
425 return hr;
426}
427
428/***********************************************************************
429 * CoRevokeMallocSpy (combase.@)
430 */
432{
433 HRESULT hr = S_OK;
434
435 TRACE("\n");
436
438
439 if (!allocator.spy)
442 {
445 }
446 else
447 {
448 IMallocSpy_Release(allocator.spy);
450 }
451
453
454 return hr;
455}
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
const GUID IID_IUnknown
#define E_INVALIDARG
Definition: ddrawi.h:101
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define GetProcessHeap()
Definition: compat.h:736
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define HeapFree(x, y, z)
Definition: compat.h:735
static MonoProfilerRuntimeShutdownBeginCallback cb
Definition: metahost.c:118
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLsizeiptr size
Definition: glext.h:5919
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLenum const GLvoid * addr
Definition: glext.h:9621
HLOCAL NTAPI LocalReAlloc(HLOCAL hMem, SIZE_T dwBytes, UINT uFlags)
Definition: heapmem.c:1625
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1390
BOOL WINAPI HeapValidate(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem)
Definition: heapmem.c:156
REFIID riid
Definition: atlbase.h:39
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define debugstr_guid
Definition: kernel32.h:35
HRESULT WINAPI CoRevokeMallocSpy(void)
Definition: malloc.c:431
static CRITICAL_SECTION allocspy_cs
Definition: malloc.c:41
HRESULT WINAPI CoRegisterMallocSpy(IMallocSpy *spy)
Definition: malloc.c:405
void *WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: malloc.c:381
static SIZE_T WINAPI allocator_GetSize(IMalloc *iface, void *mem)
Definition: malloc.c:271
void *WINAPI CoTaskMemRealloc(void *ptr, SIZE_T size)
Definition: malloc.c:397
static INT WINAPI allocator_DidAlloc(IMalloc *iface, void *mem)
Definition: malloc.c:300
static void *WINAPI allocator_Realloc(IMalloc *iface, void *pv, SIZE_T cb)
Definition: malloc.c:176
static ULONG WINAPI allocator_AddRef(IMalloc *iface)
Definition: malloc.c:132
static void WINAPI allocator_Free(IMalloc *iface, void *mem)
Definition: malloc.c:230
static CRITICAL_SECTION_DEBUG allocspy_cs_debug
Definition: malloc.c:42
void WINAPI CoTaskMemFree(void *ptr)
Definition: malloc.c:389
static void ** mallocspy_is_allocation_spyed(const void *mem)
Definition: malloc.c:90
static HRESULT WINAPI allocator_QueryInterface(IMalloc *iface, REFIID riid, void **obj)
Definition: malloc.c:119
static void mallocspy_add_mem(void *mem)
Definition: malloc.c:65
static const IMallocVtbl allocator_vtbl
Definition: malloc.c:27
static void *WINAPI allocator_Alloc(IMalloc *iface, SIZE_T cb)
Definition: malloc.c:142
static ULONG WINAPI allocator_Release(IMalloc *iface)
Definition: malloc.c:137
HRESULT WINAPI CoGetMalloc(DWORD context, IMalloc **imalloc)
Definition: malloc.c:365
static BOOL mallocspy_grow(DWORD length)
Definition: malloc.c:50
static void WINAPI allocator_HeapMinimize(IMalloc *iface)
Definition: malloc.c:329
static BOOL mallocspy_remove_spyed_memory(const void *mem)
Definition: malloc.c:104
#define LMEM_MOVEABLE
Definition: minwinbase.h:82
#define LMEM_ZEROINIT
Definition: minwinbase.h:85
static int blocks
Definition: mkdosfs.c:527
struct task_struct * current
Definition: linux.c:32
static PVOID ptr
Definition: dispmode.c:27
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
HRESULT hr
Definition: shlfolder.c:183
#define TRACE(s)
Definition: solgame.cpp:4
DWORD spyed_allocations
Definition: malloc.c:33
IMallocSpy * spy
Definition: malloc.c:32
IMalloc IMalloc_iface
Definition: malloc.c:31
DWORD blocks_length
Definition: malloc.c:36
BOOL spy_release_pending
Definition: malloc.c:34
void ** blocks
Definition: malloc.c:35
Definition: http.c:7252
Definition: mem.c:349
#define DWORD_PTR
Definition: treelist.c:76
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
SIZE_T WINAPI HeapSize(HANDLE, DWORD, LPCVOID)
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define WINAPI
Definition: msvc.h:6
#define E_NOINTERFACE
Definition: winerror.h:3479
#define E_ACCESSDENIED
Definition: winerror.h:4116
#define CO_E_OBJNOTREG
Definition: winerror.h:3927
#define CO_E_OBJISREG
Definition: winerror.h:3928