ReactOS  0.4.14-dev-583-g2a1ba2c
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 */
48 static const IMallocVtbl VT_IMalloc32;
49 
50 typedef 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 */
61 static _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 };
71 static 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 */
103  DWORD old_length = Malloc32.SpyedBlockTableLength;
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 
118 {
119  LPVOID * Current;
120 
121  /* allocate the table if not already allocated */
123  return FALSE;
124 
125  Current = Malloc32.SpyedBlocks;
126 
127  /* find the location */
128  while (*Current != pMem) {
129  Current++;
131  return FALSE; /* not found */
132  }
133 
134  /* location found */
136  /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
137  *Current = NULL;
138  return TRUE;
139 }
140 
141 /******************************************************************************
142  * IMalloc32_QueryInterface [VTABLE]
143  */
144 static HRESULT WINAPI IMalloc_fnQueryInterface(IMalloc *iface, REFIID refiid, void **obj)
145 {
146  TRACE("(%s,%p)\n",debugstr_guid(refiid),obj);
147 
148  if (IsEqualIID(&IID_IUnknown,refiid) || IsEqualIID(&IID_IMalloc,refiid)) {
149  *obj = &Malloc32;
150  return S_OK;
151  }
152  return E_NOINTERFACE;
153 }
154 
155 /******************************************************************************
156  * IMalloc32_AddRefRelease [VTABLE]
157  */
159 {
160  return 1;
161 }
162 
163 /******************************************************************************
164  * IMalloc32_Alloc [VTABLE]
165  */
166 static void * WINAPI IMalloc_fnAlloc(IMalloc *iface, SIZE_T cb)
167 {
168  void *addr;
169 
170  TRACE("(%ld)\n",cb);
171 
172  if(Malloc32.pSpy) {
173  SIZE_T preAllocResult;
174 
176  preAllocResult = IMallocSpy_PreAlloc(Malloc32.pSpy, cb);
177  if ((cb != 0) && (preAllocResult == 0)) {
178  /* PreAlloc can force Alloc to fail, but not if cb == 0 */
179  TRACE("returning null\n");
181  return NULL;
182  }
183  }
184 
186 
187  if(Malloc32.pSpy) {
188  addr = IMallocSpy_PostAlloc(Malloc32.pSpy, addr);
191  }
192 
193  TRACE("--(%p)\n",addr);
194  return addr;
195 }
196 
197 /******************************************************************************
198  * IMalloc32_Realloc [VTABLE]
199  */
200 static void * WINAPI IMalloc_fnRealloc(IMalloc *iface, void *pv, SIZE_T cb)
201 {
202  void *pNewMemory;
203 
204  TRACE("(%p,%ld)\n",pv,cb);
205 
206  if(Malloc32.pSpy) {
207  void *pRealMemory;
208  BOOL fSpyed;
209 
211  fSpyed = RemoveMemoryLocation(pv);
212  cb = IMallocSpy_PreRealloc(Malloc32.pSpy, pv, cb, &pRealMemory, fSpyed);
213 
214  /* check if can release the spy */
216  IMallocSpy_Release(Malloc32.pSpy);
218  Malloc32.pSpy = NULL;
220  }
221 
222  if (0==cb) {
223  /* PreRealloc can force Realloc to fail */
224  if (Malloc32.pSpy)
226  return NULL;
227  }
228 
229  pv = pRealMemory;
230  }
231 
232  if (!pv) pNewMemory = HeapAlloc(GetProcessHeap(),0,cb);
233  else if (cb) pNewMemory = HeapReAlloc(GetProcessHeap(),0,pv,cb);
234  else {
235  HeapFree(GetProcessHeap(),0,pv);
236  pNewMemory = NULL;
237  }
238 
239  if(Malloc32.pSpy) {
240  pNewMemory = IMallocSpy_PostRealloc(Malloc32.pSpy, pNewMemory, TRUE);
241  if (pNewMemory) AddMemoryLocation(pNewMemory);
243  }
244 
245  TRACE("--(%p)\n",pNewMemory);
246  return pNewMemory;
247 }
248 
249 /******************************************************************************
250  * IMalloc32_Free [VTABLE]
251  */
252 static void WINAPI IMalloc_fnFree(IMalloc *iface, void *pv)
253 {
254  BOOL fSpyed = FALSE;
255 
256  TRACE("(%p)\n",pv);
257 
258  if(!pv)
259  return;
260 
261  if(Malloc32.pSpy) {
263  fSpyed = RemoveMemoryLocation(pv);
264  pv = IMallocSpy_PreFree(Malloc32.pSpy, pv, fSpyed);
265  }
266 
267  HeapFree(GetProcessHeap(),0,pv);
268 
269  if(Malloc32.pSpy) {
270  IMallocSpy_PostFree(Malloc32.pSpy, fSpyed);
271 
272  /* check if can release the spy */
274  IMallocSpy_Release(Malloc32.pSpy);
276  Malloc32.pSpy = NULL;
277  }
278 
280  }
281 }
282 
283 /******************************************************************************
284  * IMalloc32_GetSize [VTABLE]
285  *
286  * NOTES
287  * FIXME returns:
288  * win95: size allocated (4 byte boundarys)
289  * win2k: size originally requested !!! (allocated on 8 byte boundarys)
290  */
291 static SIZE_T WINAPI IMalloc_fnGetSize(IMalloc *iface, void *pv)
292 {
293  SIZE_T cb;
294  BOOL fSpyed = FALSE;
295 
296  TRACE("(%p)\n",pv);
297 
298  if(Malloc32.pSpy) {
300  pv = IMallocSpy_PreGetSize(Malloc32.pSpy, pv, fSpyed);
301  }
302 
303  cb = HeapSize(GetProcessHeap(),0,pv);
304 
305  if(Malloc32.pSpy) {
306  cb = IMallocSpy_PostGetSize(Malloc32.pSpy, cb, fSpyed);
308  }
309 
310  return cb;
311 }
312 
313 /******************************************************************************
314  * IMalloc32_DidAlloc [VTABLE]
315  */
316 static INT WINAPI IMalloc_fnDidAlloc(IMalloc *iface, void *pv)
317 {
318  BOOL fSpyed = FALSE;
319  int didAlloc;
320 
321  TRACE("(%p)\n",pv);
322 
323  if(Malloc32.pSpy) {
325  pv = IMallocSpy_PreDidAlloc(Malloc32.pSpy, pv, fSpyed);
326  }
327 
328  didAlloc = -1;
329 
330  if(Malloc32.pSpy) {
331  didAlloc = IMallocSpy_PostDidAlloc(Malloc32.pSpy, pv, fSpyed, didAlloc);
333  }
334  return didAlloc;
335 }
336 
337 /******************************************************************************
338  * IMalloc32_HeapMinimize [VTABLE]
339  */
341 {
342  TRACE("()\n");
343 
344  if(Malloc32.pSpy) {
346  IMallocSpy_PreHeapMinimize(Malloc32.pSpy);
347  }
348 
349  if(Malloc32.pSpy) {
350  IMallocSpy_PostHeapMinimize(Malloc32.pSpy);
352  }
353 }
354 
355 static const IMallocVtbl VT_IMalloc32 =
356 {
366 };
367 
368 /******************************************************************************
369  * CoGetMalloc [OLE32.@]
370  *
371  * Retrieves the current IMalloc interface for the process.
372  *
373  * PARAMS
374  * context [I] Should always be MEMCTX_TASK.
375  * imalloc [O] Address where memory allocator object will be stored.
376  *
377  * RETURNS
378  * Success: S_OK.
379  * Failure: HRESULT code.
380  */
382 {
383  if (context != MEMCTX_TASK) {
384  *imalloc = NULL;
385  return E_INVALIDARG;
386  }
387 
388  *imalloc = &Malloc32.IMalloc_iface;
389  return S_OK;
390 }
391 
392 /***********************************************************************
393  * CoTaskMemAlloc [OLE32.@]
394  *
395  * Allocates memory using the current process memory allocator.
396  *
397  * PARAMS
398  * size [I] Size of the memory block to allocate.
399  *
400  * RETURNS
401  * Success: Pointer to newly allocated memory block.
402  * Failure: NULL.
403  */
405 {
406  return IMalloc_Alloc(&Malloc32.IMalloc_iface,size);
407 }
408 
409 /***********************************************************************
410  * CoTaskMemFree [OLE32.@]
411  *
412  * Frees memory allocated from the current process memory allocator.
413  *
414  * PARAMS
415  * ptr [I] Memory block to free.
416  *
417  * RETURNS
418  * Nothing.
419  */
421 {
422  IMalloc_Free(&Malloc32.IMalloc_iface, ptr);
423 }
424 
425 /***********************************************************************
426  * CoTaskMemRealloc [OLE32.@]
427  *
428  * Allocates memory using the current process memory allocator.
429  *
430  * PARAMS
431  * pvOld [I] Pointer to old memory block.
432  * size [I] Size of the new memory block.
433  *
434  * RETURNS
435  * Success: Pointer to newly allocated memory block.
436  * Failure: NULL.
437  */
439 {
440  return IMalloc_Realloc(&Malloc32.IMalloc_iface, pvOld, size);
441 }
442 
443 /***********************************************************************
444  * CoRegisterMallocSpy [OLE32.@]
445  *
446  * Registers an object that receives notifications on memory allocations and
447  * frees.
448  *
449  * PARAMS
450  * pMallocSpy [I] New spy object.
451  *
452  * RETURNS
453  * Success: S_OK.
454  * Failure: HRESULT code.
455  *
456  * NOTES
457  * if a mallocspy is already registered, we can't do it again since
458  * only the spy knows, how to free a memory block
459  */
461 {
462  IMallocSpy* pSpy;
464 
465  TRACE("%p\n", pMallocSpy);
466 
467  if(!pMallocSpy) return E_INVALIDARG;
468 
470 
471  if (Malloc32.pSpy)
473  else if (SUCCEEDED(IMallocSpy_QueryInterface(pMallocSpy, &IID_IMallocSpy, (void**)&pSpy))) {
474  Malloc32.pSpy = pSpy;
475  hres = S_OK;
476  }
477 
479 
480  return hres;
481 }
482 
483 /***********************************************************************
484  * CoRevokeMallocSpy [OLE32.@]
485  *
486  * Revokes a previously registered object that receives notifications on memory
487  * allocations and frees.
488  *
489  * PARAMS
490  * pMallocSpy [I] New spy object.
491  *
492  * RETURNS
493  * Success: S_OK.
494  * Failure: HRESULT code.
495  *
496  * NOTES
497  * we can't revoke a malloc spy as long as memory blocks allocated with
498  * the spy are active since only the spy knows how to free them
499  */
501 {
502  HRESULT hres = S_OK;
503  TRACE("\n");
504 
506 
507  if (!Malloc32.pSpy)
509  else if (Malloc32.SpyedAllocationsLeft) {
510  TRACE("SpyReleasePending with %u allocations left\n", Malloc32.SpyedAllocationsLeft);
513  } else {
514  IMallocSpy_Release(Malloc32.pSpy);
515  Malloc32.pSpy = NULL;
516  }
518 
519  return hres;
520 }
521 
522 /******************************************************************************
523  * IsValidInterface [OLE32.@]
524  *
525  * Determines whether a pointer is a valid interface.
526  *
527  * PARAMS
528  * punk [I] Interface to be tested.
529  *
530  * RETURNS
531  * TRUE, if the passed pointer is a valid interface, or FALSE otherwise.
532  */
534 {
535  return !(
536  IsBadReadPtr(punk,4) ||
537  IsBadReadPtr(punk->lpVtbl,4) ||
538  IsBadReadPtr(punk->lpVtbl->QueryInterface,9) ||
539  IsBadCodePtr((FARPROC)punk->lpVtbl->QueryInterface)
540  );
541 }
#define E_ACCESSDENIED
Definition: winerror.h:2849
LPVOID * SpyedBlocks
Definition: ifs.c:56
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
#define E_NOINTERFACE
Definition: winerror.h:2364
BOOL SpyReleasePending
Definition: ifs.c:55
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:420
#define DWORD_PTR
Definition: treelist.c:76
Definition: http.c:7098
static void *WINAPI IMalloc_fnAlloc(IMalloc *iface, SIZE_T cb)
Definition: ifs.c:166
static INT WINAPI IMalloc_fnDidAlloc(IMalloc *iface, void *pv)
Definition: ifs.c:316
static BOOL RemoveMemoryLocation(LPCVOID pMem)
Definition: ifs.c:117
static void *WINAPI IMalloc_fnRealloc(IMalloc *iface, void *pv, SIZE_T cb)
Definition: ifs.c:200
IMalloc IMalloc_iface
Definition: ifs.c:51
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
Definition: ifs.c:50
SIZE_T WINAPI HeapSize(HANDLE, DWORD, LPCVOID)
int32_t INT
Definition: typedefs.h:56
static CRITICAL_SECTION IMalloc32_SpyCS
Definition: ifs.c:64
static USHORT USHORT * NewLength
BOOL NTAPI IsBadCodePtr(FARPROC lpfn)
Definition: except.c:874
HRESULT WINAPI CoGetMalloc(DWORD context, IMalloc **imalloc)
Definition: ifs.c:381
unsigned int BOOL
Definition: ntddk_ex.h:94
HRESULT WINAPI CoRevokeMallocSpy(void)
Definition: ifs.c:500
static LPUNKNOWN
Definition: ndr_ole.c:49
static ULONG WINAPI IMalloc_fnAddRefRelease(IMalloc *iface)
Definition: ifs.c:158
static PVOID ptr
Definition: dispmode.c:27
WINE_DEFAULT_DEBUG_CHANNEL(olemalloc)
#define E_INVALIDARG
Definition: ddrawi.h:101
smooth NULL
Definition: ftsmooth.c:416
static const IMallocVtbl VT_IMalloc32
Definition: ifs.c:48
static SIZE_T WINAPI IMalloc_fnGetSize(IMalloc *iface, void *pv)
Definition: ifs.c:291
#define debugstr_guid
Definition: kernel32.h:35
DWORD dummy
Definition: ifs.c:52
static void WINAPI IMalloc_fnHeapMinimize(IMalloc *iface)
Definition: ifs.c:340
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
HRESULT hres
Definition: protocol.c:465
#define GetProcessHeap()
Definition: compat.h:403
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define LMEM_ZEROINIT
Definition: winbase.h:356
LONG HRESULT
Definition: typedefs.h:77
#define CO_E_OBJNOTREG
Definition: winerror.h:2814
const GUID IID_IUnknown
BOOL WINAPI IsValidInterface(LPUNKNOWN punk)
Definition: ifs.c:533
#define WINAPI
Definition: msvc.h:6
#define LMEM_MOVEABLE
Definition: winbase.h:350
unsigned long DWORD
Definition: ntddk_ex.h:95
interface IMallocSpy * LPMALLOCSPY
Definition: objfwd.h:13
GLenum const GLvoid * addr
Definition: glext.h:9621
DWORD SpyedBlockTableLength
Definition: ifs.c:57
static BOOL SetSpyedBlockTableLength(DWORD NewLength)
Definition: ifs.c:74
static void WINAPI IMalloc_fnFree(IMalloc *iface, void *pv)
Definition: ifs.c:252
LIST_ENTRY ProcessLocksList
Definition: winbase.h:855
IMallocSpy * pSpy
Definition: ifs.c:53
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define S_OK
Definition: intsafe.h:59
HLOCAL NTAPI LocalReAlloc(HLOCAL hMem, SIZE_T dwBytes, UINT uFlags)
Definition: heapmem.c:1608
static _Malloc32 Malloc32
Definition: ifs.c:61
#define HeapReAlloc
Definition: compat.h:401
BOOL WINAPI IsBadReadPtr(IN LPCVOID lp, IN UINT_PTR ucb)
Definition: except.c:807
DWORD SpyedAllocationsLeft
Definition: ifs.c:54
HRESULT WINAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy)
Definition: ifs.c:460
static HRESULT WINAPI IMalloc_fnQueryInterface(IMalloc *iface, REFIID refiid, void **obj)
Definition: ifs.c:144
static HMODULE MODULEINFO DWORD cb
Definition: module.c:32
CONST void * LPCVOID
Definition: windef.h:191
unsigned int ULONG
Definition: retypes.h:1
LPVOID WINAPI CoTaskMemRealloc(LPVOID pvOld, SIZE_T size)
Definition: ifs.c:438
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1373
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
static CRITICAL_SECTION_DEBUG critsect_debug
Definition: ifs.c:65
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:404
#define HeapFree(x, y, z)
Definition: compat.h:402
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
int(* FARPROC)()
Definition: compat.h:28
#define CO_E_OBJISREG
Definition: winerror.h:2815
#define SUCCEEDED(hr)
Definition: intsafe.h:57
static BOOL AddMemoryLocation(LPVOID *pMem)
Definition: ifs.c:89