ReactOS 0.4.15-dev-8428-g6910fa6
ifs.c
Go to the documentation of this file.
1/*
2 * basic interfaces
3 *
4 * Copyright 1997 Marcus Meissner
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include <ctype.h>
22#include <stdarg.h>
23#include <stdlib.h>
24#include <string.h>
25#include <assert.h>
26
27#define COBJMACROS
28
29#include "windef.h"
30#include "winbase.h"
31#include "winuser.h"
32#include "ole2.h"
33#include "winerror.h"
34
35#include "wine/debug.h"
36
38
39/******************************************************************************
40 * IMalloc32 implementation
41 *
42 * NOTES
43 * For supporting CoRegisterMallocSpy the IMalloc implementation must know if
44 * a given memory block was allocated with a spy active.
45 *
46 *****************************************************************************/
47/* set the vtable later */
48static const IMallocVtbl VT_IMalloc32;
49
50typedef struct {
52 DWORD dummy; /* nothing, we are static */
53 IMallocSpy * pSpy; /* the spy when active */
54 DWORD SpyedAllocationsLeft; /* number of spyed allocations left */
55 BOOL SpyReleasePending; /* CoRevokeMallocSpy called with spyed allocations left*/
56 LPVOID * SpyedBlocks; /* root of the table */
57 DWORD SpyedBlockTableLength;/* size of the table*/
58} _Malloc32;
59
60/* this is the static object instance */
61static _Malloc32 Malloc32 = {{&VT_IMalloc32}, 0, NULL, 0, 0, NULL, 0};
62
63/* with a spy active all calls from pre to post methods are threadsave */
66{
67 0, 0, &IMalloc32_SpyCS,
69 0, 0, { (DWORD_PTR)(__FILE__ ": IMalloc32_SpyCS") }
70};
71static CRITICAL_SECTION IMalloc32_SpyCS = { &critsect_debug, -1, 0, 0, 0, 0 };
72
73/* resize the old table */
75{
76 LPVOID *NewSpyedBlocks;
77
78 if (!Malloc32.SpyedBlocks) NewSpyedBlocks = LocalAlloc(LMEM_ZEROINIT, NewLength * sizeof(PVOID));
79 else NewSpyedBlocks = LocalReAlloc(Malloc32.SpyedBlocks, NewLength * sizeof(PVOID), LMEM_ZEROINIT | LMEM_MOVEABLE);
80 if (NewSpyedBlocks) {
81 Malloc32.SpyedBlocks = NewSpyedBlocks;
83 }
84
85 return NewSpyedBlocks != NULL;
86}
87
88/* add a location to the table */
90{
91 LPVOID * Current;
92
93 /* allocate the table if not already allocated */
95 return FALSE;
96
97 /* find a free location */
98 Current = Malloc32.SpyedBlocks;
99 while (*Current) {
100 Current++;
102 /* no more space in table, grow it */
105 return FALSE;
106 Current = Malloc32.SpyedBlocks + old_length;
107 }
108 };
109
110 /* put the location in our table */
111 *Current = pMem;
113 /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
114 return TRUE;
115}
116
117static void** mallocspy_is_allocation_spyed(const void *mem)
118{
120
121 while (*current != mem)
122 {
123 current++;
125 return NULL;
126 }
127
128 return current;
129}
130
132{
133 LPVOID * Current;
134
135 /* allocate the table if not already allocated */
137 return FALSE;
138
139 if (!(Current = mallocspy_is_allocation_spyed(pMem)))
140 return FALSE;
141
142 /* location found */
144 /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
145 *Current = NULL;
146 return TRUE;
147}
148
149/******************************************************************************
150 * IMalloc32_QueryInterface [VTABLE]
151 */
153{
154 TRACE("(%s,%p)\n",debugstr_guid(refiid),obj);
155
156 if (IsEqualIID(&IID_IUnknown,refiid) || IsEqualIID(&IID_IMalloc,refiid)) {
157 *obj = &Malloc32;
158 return S_OK;
159 }
160 return E_NOINTERFACE;
161}
162
163/******************************************************************************
164 * IMalloc32_AddRefRelease [VTABLE]
165 */
167{
168 return 1;
169}
170
171/******************************************************************************
172 * IMalloc32_Alloc [VTABLE]
173 */
174static void * WINAPI IMalloc_fnAlloc(IMalloc *iface, SIZE_T cb)
175{
176 void *addr;
177
178 TRACE("(%ld)\n",cb);
179
180 if(Malloc32.pSpy) {
181 SIZE_T preAllocResult;
182
184 preAllocResult = IMallocSpy_PreAlloc(Malloc32.pSpy, cb);
185 if ((cb != 0) && (preAllocResult == 0)) {
186 /* PreAlloc can force Alloc to fail, but not if cb == 0 */
187 TRACE("returning null\n");
189 return NULL;
190 }
191 }
192
194
195 if(Malloc32.pSpy) {
196 addr = IMallocSpy_PostAlloc(Malloc32.pSpy, addr);
199 }
200
201 TRACE("--(%p)\n",addr);
202 return addr;
203}
204
205/******************************************************************************
206 * IMalloc32_Realloc [VTABLE]
207 */
208static void * WINAPI IMalloc_fnRealloc(IMalloc *iface, void *pv, SIZE_T cb)
209{
210 void *pNewMemory;
211
212 TRACE("(%p,%ld)\n",pv,cb);
213
214 if(Malloc32.pSpy) {
215 void *pRealMemory;
216 BOOL fSpyed;
217
219 fSpyed = RemoveMemoryLocation(pv);
220 cb = IMallocSpy_PreRealloc(Malloc32.pSpy, pv, cb, &pRealMemory, fSpyed);
221
222 /* check if can release the spy */
224 IMallocSpy_Release(Malloc32.pSpy);
228 }
229
230 if (0==cb) {
231 /* PreRealloc can force Realloc to fail */
232 if (Malloc32.pSpy)
234 return NULL;
235 }
236
237 pv = pRealMemory;
238 }
239
240 if (!pv) pNewMemory = HeapAlloc(GetProcessHeap(),0,cb);
241 else if (cb) pNewMemory = HeapReAlloc(GetProcessHeap(),0,pv,cb);
242 else {
243 HeapFree(GetProcessHeap(),0,pv);
244 pNewMemory = NULL;
245 }
246
247 if(Malloc32.pSpy) {
248 pNewMemory = IMallocSpy_PostRealloc(Malloc32.pSpy, pNewMemory, TRUE);
249 if (pNewMemory) AddMemoryLocation(pNewMemory);
251 }
252
253 TRACE("--(%p)\n",pNewMemory);
254 return pNewMemory;
255}
256
257/******************************************************************************
258 * IMalloc32_Free [VTABLE]
259 */
260static void WINAPI IMalloc_fnFree(IMalloc *iface, void *pv)
261{
262 BOOL fSpyed = FALSE;
263
264 TRACE("(%p)\n",pv);
265
266 if(!pv)
267 return;
268
269 if(Malloc32.pSpy) {
271 fSpyed = RemoveMemoryLocation(pv);
272 pv = IMallocSpy_PreFree(Malloc32.pSpy, pv, fSpyed);
273 }
274
275 HeapFree(GetProcessHeap(),0,pv);
276
277 if(Malloc32.pSpy) {
278 IMallocSpy_PostFree(Malloc32.pSpy, fSpyed);
279
280 /* check if can release the spy */
282 IMallocSpy_Release(Malloc32.pSpy);
285 }
286
288 }
289}
290
291/******************************************************************************
292 * IMalloc32_GetSize [VTABLE]
293 *
294 * NOTES
295 * FIXME returns:
296 * win95: size allocated (4 byte boundarys)
297 * win2k: size originally requested !!! (allocated on 8 byte boundarys)
298 */
300{
301 BOOL spyed_block = FALSE, spy_active = FALSE;
302 SIZE_T size;
303
304 TRACE("(%p)\n", mem);
305
306 if (!mem)
307 return (SIZE_T)-1;
308
309 if (Malloc32.pSpy)
310 {
312 spyed_block = !!mallocspy_is_allocation_spyed(mem);
313 spy_active = TRUE;
314 mem = IMallocSpy_PreGetSize(Malloc32.pSpy, mem, spyed_block);
315 }
316
318
319 if (spy_active)
320 {
321 size = IMallocSpy_PostGetSize(Malloc32.pSpy, size, spyed_block);
323 }
324 return size;
325}
326
327/******************************************************************************
328 * IMalloc32_DidAlloc [VTABLE]
329 */
331{
332 BOOL spyed_block = FALSE, spy_active = FALSE;
333 int did_alloc;
334
335 TRACE("(%p)\n", mem);
336
337 if (!mem)
338 return -1;
339
340 if (Malloc32.pSpy)
341 {
343 spyed_block = !!mallocspy_is_allocation_spyed(mem);
344 spy_active = TRUE;
345 mem = IMallocSpy_PreDidAlloc(Malloc32.pSpy, mem, spyed_block);
346 }
347
348 did_alloc = HeapValidate(GetProcessHeap(), 0, mem);
349
350 if (spy_active)
351 {
352 did_alloc = IMallocSpy_PostDidAlloc(Malloc32.pSpy, mem, spyed_block, did_alloc);
354 }
355
356 return did_alloc;
357}
358
359/******************************************************************************
360 * IMalloc32_HeapMinimize [VTABLE]
361 */
363{
364 TRACE("()\n");
365
366 if(Malloc32.pSpy) {
368 IMallocSpy_PreHeapMinimize(Malloc32.pSpy);
369 }
370
371 if(Malloc32.pSpy) {
372 IMallocSpy_PostHeapMinimize(Malloc32.pSpy);
374 }
375}
376
377static const IMallocVtbl VT_IMalloc32 =
378{
388};
389
390/******************************************************************************
391 * CoGetMalloc [OLE32.@]
392 *
393 * Retrieves the current IMalloc interface for the process.
394 *
395 * PARAMS
396 * context [I] Should always be MEMCTX_TASK.
397 * imalloc [O] Address where memory allocator object will be stored.
398 *
399 * RETURNS
400 * Success: S_OK.
401 * Failure: HRESULT code.
402 */
404{
405 if (context != MEMCTX_TASK) {
406 *imalloc = NULL;
407 return E_INVALIDARG;
408 }
409
410 *imalloc = &Malloc32.IMalloc_iface;
411 return S_OK;
412}
413
414/***********************************************************************
415 * CoTaskMemAlloc [OLE32.@]
416 *
417 * Allocates memory using the current process memory allocator.
418 *
419 * PARAMS
420 * size [I] Size of the memory block to allocate.
421 *
422 * RETURNS
423 * Success: Pointer to newly allocated memory block.
424 * Failure: NULL.
425 */
427{
428 return IMalloc_Alloc(&Malloc32.IMalloc_iface,size);
429}
430
431/***********************************************************************
432 * CoTaskMemFree [OLE32.@]
433 *
434 * Frees memory allocated from the current process memory allocator.
435 *
436 * PARAMS
437 * ptr [I] Memory block to free.
438 *
439 * RETURNS
440 * Nothing.
441 */
443{
444 IMalloc_Free(&Malloc32.IMalloc_iface, ptr);
445}
446
447/***********************************************************************
448 * CoTaskMemRealloc [OLE32.@]
449 *
450 * Allocates memory using the current process memory allocator.
451 *
452 * PARAMS
453 * pvOld [I] Pointer to old memory block.
454 * size [I] Size of the new memory block.
455 *
456 * RETURNS
457 * Success: Pointer to newly allocated memory block.
458 * Failure: NULL.
459 */
461{
462 return IMalloc_Realloc(&Malloc32.IMalloc_iface, pvOld, size);
463}
464
465/***********************************************************************
466 * CoRegisterMallocSpy [OLE32.@]
467 *
468 * Registers an object that receives notifications on memory allocations and
469 * frees.
470 *
471 * PARAMS
472 * pMallocSpy [I] New spy object.
473 *
474 * RETURNS
475 * Success: S_OK.
476 * Failure: HRESULT code.
477 *
478 * NOTES
479 * if a mallocspy is already registered, we can't do it again since
480 * only the spy knows, how to free a memory block
481 */
483{
484 IMallocSpy* pSpy;
486
487 TRACE("%p\n", pMallocSpy);
488
489 if(!pMallocSpy) return E_INVALIDARG;
490
492
493 if (Malloc32.pSpy)
495 else if (SUCCEEDED(IMallocSpy_QueryInterface(pMallocSpy, &IID_IMallocSpy, (void**)&pSpy))) {
496 Malloc32.pSpy = pSpy;
497 hres = S_OK;
498 }
499
501
502 return hres;
503}
504
505/***********************************************************************
506 * CoRevokeMallocSpy [OLE32.@]
507 *
508 * Revokes a previously registered object that receives notifications on memory
509 * allocations and frees.
510 *
511 * PARAMS
512 * pMallocSpy [I] New spy object.
513 *
514 * RETURNS
515 * Success: S_OK.
516 * Failure: HRESULT code.
517 *
518 * NOTES
519 * we can't revoke a malloc spy as long as memory blocks allocated with
520 * the spy are active since only the spy knows how to free them
521 */
523{
524 HRESULT hres = S_OK;
525 TRACE("\n");
526
528
529 if (!Malloc32.pSpy)
532 TRACE("SpyReleasePending with %u allocations left\n", Malloc32.SpyedAllocationsLeft);
535 } else {
536 IMallocSpy_Release(Malloc32.pSpy);
538 }
540
541 return hres;
542}
543
544/******************************************************************************
545 * IsValidInterface [OLE32.@]
546 *
547 * Determines whether a pointer is a valid interface.
548 *
549 * PARAMS
550 * punk [I] Interface to be tested.
551 *
552 * RETURNS
553 * TRUE, if the passed pointer is a valid interface, or FALSE otherwise.
554 */
556{
557 return !(
558 IsBadReadPtr(punk,4) ||
559 IsBadReadPtr(punk->lpVtbl,4) ||
560 IsBadReadPtr(punk->lpVtbl->QueryInterface,9) ||
561 IsBadCodePtr((FARPROC)punk->lpVtbl->QueryInterface)
562 );
563}
static USHORT USHORT * NewLength
#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
int(* FARPROC)()
Definition: compat.h:36
#define HeapAlloc
Definition: compat.h:733
#define HeapReAlloc
Definition: compat.h:734
#define HeapFree(x, y, z)
Definition: compat.h:735
BOOL WINAPI IsBadReadPtr(IN LPCVOID lp, IN UINT_PTR ucb)
Definition: except.c:805
BOOL NTAPI IsBadCodePtr(FARPROC lpfn)
Definition: except.c:872
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLsizeiptr size
Definition: glext.h:5919
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
static BOOL AddMemoryLocation(LPVOID *pMem)
Definition: ifs.c:89
HRESULT WINAPI CoRevokeMallocSpy(void)
Definition: ifs.c:522
static ULONG WINAPI IMalloc_fnAddRefRelease(IMalloc *iface)
Definition: ifs.c:166
static INT WINAPI IMalloc_fnDidAlloc(IMalloc *iface, void *mem)
Definition: ifs.c:330
static void *WINAPI IMalloc_fnRealloc(IMalloc *iface, void *pv, SIZE_T cb)
Definition: ifs.c:208
static CRITICAL_SECTION_DEBUG critsect_debug
Definition: ifs.c:65
LPVOID WINAPI CoTaskMemRealloc(LPVOID pvOld, SIZE_T size)
Definition: ifs.c:460
static HRESULT WINAPI IMalloc_fnQueryInterface(IMalloc *iface, REFIID refiid, void **obj)
Definition: ifs.c:152
static void ** mallocspy_is_allocation_spyed(const void *mem)
Definition: ifs.c:117
BOOL WINAPI IsValidInterface(LPUNKNOWN punk)
Definition: ifs.c:555
static CRITICAL_SECTION IMalloc32_SpyCS
Definition: ifs.c:64
static _Malloc32 Malloc32
Definition: ifs.c:61
static void WINAPI IMalloc_fnHeapMinimize(IMalloc *iface)
Definition: ifs.c:362
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:442
static const IMallocVtbl VT_IMalloc32
Definition: ifs.c:48
HRESULT WINAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy)
Definition: ifs.c:482
HRESULT WINAPI CoGetMalloc(DWORD context, IMalloc **imalloc)
Definition: ifs.c:403
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
static void *WINAPI IMalloc_fnAlloc(IMalloc *iface, SIZE_T cb)
Definition: ifs.c:174
static SIZE_T WINAPI IMalloc_fnGetSize(IMalloc *iface, void *mem)
Definition: ifs.c:299
static BOOL RemoveMemoryLocation(LPCVOID pMem)
Definition: ifs.c:131
static void WINAPI IMalloc_fnFree(IMalloc *iface, void *pv)
Definition: ifs.c:260
static BOOL SetSpyedBlockTableLength(DWORD NewLength)
Definition: ifs.c:74
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define debugstr_guid
Definition: kernel32.h:35
struct task_struct * current
Definition: linux.c:32
static PVOID ptr
Definition: dispmode.c:27
HRESULT hres
Definition: protocol.c:465
static HMODULE MODULEINFO DWORD cb
Definition: module.c:33
static LPUNKNOWN
Definition: ndr_ole.c:49
interface IMallocSpy * LPMALLOCSPY
Definition: objfwd.h:13
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
#define TRACE(s)
Definition: solgame.cpp:4
LIST_ENTRY ProcessLocksList
Definition: winbase.h:883
Definition: ifs.c:50
BOOL SpyReleasePending
Definition: ifs.c:55
IMalloc IMalloc_iface
Definition: ifs.c:51
DWORD SpyedBlockTableLength
Definition: ifs.c:57
LPVOID * SpyedBlocks
Definition: ifs.c:56
DWORD dummy
Definition: ifs.c:52
DWORD SpyedAllocationsLeft
Definition: ifs.c:54
IMallocSpy * pSpy
Definition: ifs.c:53
Definition: http.c:7252
Definition: mem.c:156
#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
#define LMEM_MOVEABLE
Definition: winbase.h:369
SIZE_T WINAPI HeapSize(HANDLE, DWORD, LPCVOID)
#define LMEM_ZEROINIT
Definition: winbase.h:375
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
CONST void * LPCVOID
Definition: windef.h:191
#define WINAPI
Definition: msvc.h:6
#define E_NOINTERFACE
Definition: winerror.h:2364
#define E_ACCESSDENIED
Definition: winerror.h:2849
#define CO_E_OBJNOTREG
Definition: winerror.h:2814
#define CO_E_OBJISREG
Definition: winerror.h:2815