ReactOS  0.4.14-dev-55-g2da92ac
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 "config.h"
22 
23 #include <ctype.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28 
29 #define COBJMACROS
30 
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "ole2.h"
35 #include "winerror.h"
36 
37 #include "wine/debug.h"
38 
40 
41 /******************************************************************************
42  * IMalloc32 implementation
43  *
44  * NOTES
45  * For supporting CoRegisterMallocSpy the IMalloc implementation must know if
46  * a given memory block was allocated with a spy active.
47  *
48  *****************************************************************************/
49 /* set the vtable later */
50 static const IMallocVtbl VT_IMalloc32;
51 
52 typedef struct {
54  DWORD dummy; /* nothing, we are static */
55  IMallocSpy * pSpy; /* the spy when active */
56  DWORD SpyedAllocationsLeft; /* number of spyed allocations left */
57  BOOL SpyReleasePending; /* CoRevokeMallocSpy called with spyed allocations left*/
58  LPVOID * SpyedBlocks; /* root of the table */
59  DWORD SpyedBlockTableLength;/* size of the table*/
60 } _Malloc32;
61 
62 /* this is the static object instance */
63 static _Malloc32 Malloc32 = {{&VT_IMalloc32}, 0, NULL, 0, 0, NULL, 0};
64 
65 /* with a spy active all calls from pre to post methods are threadsave */
68 {
69  0, 0, &IMalloc32_SpyCS,
71  0, 0, { (DWORD_PTR)(__FILE__ ": IMalloc32_SpyCS") }
72 };
73 static CRITICAL_SECTION IMalloc32_SpyCS = { &critsect_debug, -1, 0, 0, 0, 0 };
74 
75 /* resize the old table */
77 {
78  LPVOID *NewSpyedBlocks;
79 
80  if (!Malloc32.SpyedBlocks) NewSpyedBlocks = LocalAlloc(LMEM_ZEROINIT, NewLength * sizeof(PVOID));
81  else NewSpyedBlocks = LocalReAlloc(Malloc32.SpyedBlocks, NewLength * sizeof(PVOID), LMEM_ZEROINIT | LMEM_MOVEABLE);
82  if (NewSpyedBlocks) {
83  Malloc32.SpyedBlocks = NewSpyedBlocks;
85  }
86 
87  return NewSpyedBlocks != NULL;
88 }
89 
90 /* add a location to the table */
92 {
93  LPVOID * Current;
94 
95  /* allocate the table if not already allocated */
97  return FALSE;
98 
99  /* find a free location */
100  Current = Malloc32.SpyedBlocks;
101  while (*Current) {
102  Current++;
104  /* no more space in table, grow it */
105  DWORD old_length = Malloc32.SpyedBlockTableLength;
107  return FALSE;
108  Current = Malloc32.SpyedBlocks + old_length;
109  }
110  };
111 
112  /* put the location in our table */
113  *Current = pMem;
115  /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
116  return TRUE;
117 }
118 
120 {
121  LPVOID * Current;
122 
123  /* allocate the table if not already allocated */
125  return FALSE;
126 
127  Current = Malloc32.SpyedBlocks;
128 
129  /* find the location */
130  while (*Current != pMem) {
131  Current++;
133  return FALSE; /* not found */
134  }
135 
136  /* location found */
138  /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
139  *Current = NULL;
140  return TRUE;
141 }
142 
143 /******************************************************************************
144  * IMalloc32_QueryInterface [VTABLE]
145  */
146 static HRESULT WINAPI IMalloc_fnQueryInterface(IMalloc *iface, REFIID refiid, void **obj)
147 {
148  TRACE("(%s,%p)\n",debugstr_guid(refiid),obj);
149 
150  if (IsEqualIID(&IID_IUnknown,refiid) || IsEqualIID(&IID_IMalloc,refiid)) {
151  *obj = &Malloc32;
152  return S_OK;
153  }
154  return E_NOINTERFACE;
155 }
156 
157 /******************************************************************************
158  * IMalloc32_AddRefRelease [VTABLE]
159  */
161 {
162  return 1;
163 }
164 
165 /******************************************************************************
166  * IMalloc32_Alloc [VTABLE]
167  */
168 static void * WINAPI IMalloc_fnAlloc(IMalloc *iface, SIZE_T cb)
169 {
170  void *addr;
171 
172  TRACE("(%ld)\n",cb);
173 
174  if(Malloc32.pSpy) {
175  SIZE_T preAllocResult;
176 
178  preAllocResult = IMallocSpy_PreAlloc(Malloc32.pSpy, cb);
179  if ((cb != 0) && (preAllocResult == 0)) {
180  /* PreAlloc can force Alloc to fail, but not if cb == 0 */
181  TRACE("returning null\n");
183  return NULL;
184  }
185  }
186 
188 
189  if(Malloc32.pSpy) {
190  addr = IMallocSpy_PostAlloc(Malloc32.pSpy, addr);
193  }
194 
195  TRACE("--(%p)\n",addr);
196  return addr;
197 }
198 
199 /******************************************************************************
200  * IMalloc32_Realloc [VTABLE]
201  */
202 static void * WINAPI IMalloc_fnRealloc(IMalloc *iface, void *pv, SIZE_T cb)
203 {
204  void *pNewMemory;
205 
206  TRACE("(%p,%ld)\n",pv,cb);
207 
208  if(Malloc32.pSpy) {
209  void *pRealMemory;
210  BOOL fSpyed;
211 
213  fSpyed = RemoveMemoryLocation(pv);
214  cb = IMallocSpy_PreRealloc(Malloc32.pSpy, pv, cb, &pRealMemory, fSpyed);
215 
216  /* check if can release the spy */
218  IMallocSpy_Release(Malloc32.pSpy);
220  Malloc32.pSpy = NULL;
222  }
223 
224  if (0==cb) {
225  /* PreRealloc can force Realloc to fail */
226  if (Malloc32.pSpy)
228  return NULL;
229  }
230 
231  pv = pRealMemory;
232  }
233 
234  if (!pv) pNewMemory = HeapAlloc(GetProcessHeap(),0,cb);
235  else if (cb) pNewMemory = HeapReAlloc(GetProcessHeap(),0,pv,cb);
236  else {
237  HeapFree(GetProcessHeap(),0,pv);
238  pNewMemory = NULL;
239  }
240 
241  if(Malloc32.pSpy) {
242  pNewMemory = IMallocSpy_PostRealloc(Malloc32.pSpy, pNewMemory, TRUE);
243  if (pNewMemory) AddMemoryLocation(pNewMemory);
245  }
246 
247  TRACE("--(%p)\n",pNewMemory);
248  return pNewMemory;
249 }
250 
251 /******************************************************************************
252  * IMalloc32_Free [VTABLE]
253  */
254 static void WINAPI IMalloc_fnFree(IMalloc *iface, void *pv)
255 {
256  BOOL fSpyed = FALSE;
257 
258  TRACE("(%p)\n",pv);
259 
260  if(!pv)
261  return;
262 
263  if(Malloc32.pSpy) {
265  fSpyed = RemoveMemoryLocation(pv);
266  pv = IMallocSpy_PreFree(Malloc32.pSpy, pv, fSpyed);
267  }
268 
269  HeapFree(GetProcessHeap(),0,pv);
270 
271  if(Malloc32.pSpy) {
272  IMallocSpy_PostFree(Malloc32.pSpy, fSpyed);
273 
274  /* check if can release the spy */
276  IMallocSpy_Release(Malloc32.pSpy);
278  Malloc32.pSpy = NULL;
279  }
280 
282  }
283 }
284 
285 /******************************************************************************
286  * IMalloc32_GetSize [VTABLE]
287  *
288  * NOTES
289  * FIXME returns:
290  * win95: size allocated (4 byte boundarys)
291  * win2k: size originally requested !!! (allocated on 8 byte boundarys)
292  */
293 static SIZE_T WINAPI IMalloc_fnGetSize(IMalloc *iface, void *pv)
294 {
295  SIZE_T cb;
296  BOOL fSpyed = FALSE;
297 
298  TRACE("(%p)\n",pv);
299 
300  if(Malloc32.pSpy) {
302  pv = IMallocSpy_PreGetSize(Malloc32.pSpy, pv, fSpyed);
303  }
304 
305  cb = HeapSize(GetProcessHeap(),0,pv);
306 
307  if(Malloc32.pSpy) {
308  cb = IMallocSpy_PostGetSize(Malloc32.pSpy, cb, fSpyed);
310  }
311 
312  return cb;
313 }
314 
315 /******************************************************************************
316  * IMalloc32_DidAlloc [VTABLE]
317  */
318 static INT WINAPI IMalloc_fnDidAlloc(IMalloc *iface, void *pv)
319 {
320  BOOL fSpyed = FALSE;
321  int didAlloc;
322 
323  TRACE("(%p)\n",pv);
324 
325  if(Malloc32.pSpy) {
327  pv = IMallocSpy_PreDidAlloc(Malloc32.pSpy, pv, fSpyed);
328  }
329 
330  didAlloc = -1;
331 
332  if(Malloc32.pSpy) {
333  didAlloc = IMallocSpy_PostDidAlloc(Malloc32.pSpy, pv, fSpyed, didAlloc);
335  }
336  return didAlloc;
337 }
338 
339 /******************************************************************************
340  * IMalloc32_HeapMinimize [VTABLE]
341  */
343 {
344  TRACE("()\n");
345 
346  if(Malloc32.pSpy) {
348  IMallocSpy_PreHeapMinimize(Malloc32.pSpy);
349  }
350 
351  if(Malloc32.pSpy) {
352  IMallocSpy_PostHeapMinimize(Malloc32.pSpy);
354  }
355 }
356 
357 static const IMallocVtbl VT_IMalloc32 =
358 {
368 };
369 
370 /******************************************************************************
371  * CoGetMalloc [OLE32.@]
372  *
373  * Retrieves the current IMalloc interface for the process.
374  *
375  * PARAMS
376  * context [I] Should always be MEMCTX_TASK.
377  * imalloc [O] Address where memory allocator object will be stored.
378  *
379  * RETURNS
380  * Success: S_OK.
381  * Failure: HRESULT code.
382  */
384 {
385  if (context != MEMCTX_TASK) {
386  *imalloc = NULL;
387  return E_INVALIDARG;
388  }
389 
390  *imalloc = &Malloc32.IMalloc_iface;
391  return S_OK;
392 }
393 
394 /***********************************************************************
395  * CoTaskMemAlloc [OLE32.@]
396  *
397  * Allocates memory using the current process memory allocator.
398  *
399  * PARAMS
400  * size [I] Size of the memory block to allocate.
401  *
402  * RETURNS
403  * Success: Pointer to newly allocated memory block.
404  * Failure: NULL.
405  */
407 {
408  return IMalloc_Alloc(&Malloc32.IMalloc_iface,size);
409 }
410 
411 /***********************************************************************
412  * CoTaskMemFree [OLE32.@]
413  *
414  * Frees memory allocated from the current process memory allocator.
415  *
416  * PARAMS
417  * ptr [I] Memory block to free.
418  *
419  * RETURNS
420  * Nothing.
421  */
423 {
424  IMalloc_Free(&Malloc32.IMalloc_iface, ptr);
425 }
426 
427 /***********************************************************************
428  * CoTaskMemRealloc [OLE32.@]
429  *
430  * Allocates memory using the current process memory allocator.
431  *
432  * PARAMS
433  * pvOld [I] Pointer to old memory block.
434  * size [I] Size of the new memory block.
435  *
436  * RETURNS
437  * Success: Pointer to newly allocated memory block.
438  * Failure: NULL.
439  */
441 {
442  return IMalloc_Realloc(&Malloc32.IMalloc_iface, pvOld, size);
443 }
444 
445 /***********************************************************************
446  * CoRegisterMallocSpy [OLE32.@]
447  *
448  * Registers an object that receives notifications on memory allocations and
449  * frees.
450  *
451  * PARAMS
452  * pMallocSpy [I] New spy object.
453  *
454  * RETURNS
455  * Success: S_OK.
456  * Failure: HRESULT code.
457  *
458  * NOTES
459  * if a mallocspy is already registered, we can't do it again since
460  * only the spy knows, how to free a memory block
461  */
463 {
464  IMallocSpy* pSpy;
466 
467  TRACE("%p\n", pMallocSpy);
468 
469  if(!pMallocSpy) return E_INVALIDARG;
470 
472 
473  if (Malloc32.pSpy)
475  else if (SUCCEEDED(IMallocSpy_QueryInterface(pMallocSpy, &IID_IMallocSpy, (void**)&pSpy))) {
476  Malloc32.pSpy = pSpy;
477  hres = S_OK;
478  }
479 
481 
482  return hres;
483 }
484 
485 /***********************************************************************
486  * CoRevokeMallocSpy [OLE32.@]
487  *
488  * Revokes a previously registered object that receives notifications on memory
489  * allocations and frees.
490  *
491  * PARAMS
492  * pMallocSpy [I] New spy object.
493  *
494  * RETURNS
495  * Success: S_OK.
496  * Failure: HRESULT code.
497  *
498  * NOTES
499  * we can't revoke a malloc spy as long as memory blocks allocated with
500  * the spy are active since only the spy knows how to free them
501  */
503 {
504  HRESULT hres = S_OK;
505  TRACE("\n");
506 
508 
509  if (!Malloc32.pSpy)
511  else if (Malloc32.SpyedAllocationsLeft) {
512  TRACE("SpyReleasePending with %u allocations left\n", Malloc32.SpyedAllocationsLeft);
515  } else {
516  IMallocSpy_Release(Malloc32.pSpy);
517  Malloc32.pSpy = NULL;
518  }
520 
521  return hres;
522 }
523 
524 /******************************************************************************
525  * IsValidInterface [OLE32.@]
526  *
527  * Determines whether a pointer is a valid interface.
528  *
529  * PARAMS
530  * punk [I] Interface to be tested.
531  *
532  * RETURNS
533  * TRUE, if the passed pointer is a valid interface, or FALSE otherwise.
534  */
536 {
537  return !(
538  IsBadReadPtr(punk,4) ||
539  IsBadReadPtr(punk->lpVtbl,4) ||
540  IsBadReadPtr(punk->lpVtbl->QueryInterface,9) ||
541  IsBadCodePtr((FARPROC)punk->lpVtbl->QueryInterface)
542  );
543 }
#define E_ACCESSDENIED
Definition: winerror.h:2849
LPVOID * SpyedBlocks
Definition: ifs.c:58
#define REFIID
Definition: guiddef.h:118
#define TRUE
Definition: types.h:120
#define E_NOINTERFACE
Definition: winerror.h:2364
BOOL SpyReleasePending
Definition: ifs.c:57
VOID WINAPI CoTaskMemFree(LPVOID ptr)
Definition: ifs.c:422
#define DWORD_PTR
Definition: treelist.c:76
Definition: http.c:6587
static void *WINAPI IMalloc_fnAlloc(IMalloc *iface, SIZE_T cb)
Definition: ifs.c:168
static INT WINAPI IMalloc_fnDidAlloc(IMalloc *iface, void *pv)
Definition: ifs.c:318
static BOOL RemoveMemoryLocation(LPCVOID pMem)
Definition: ifs.c:119
static void *WINAPI IMalloc_fnRealloc(IMalloc *iface, void *pv, SIZE_T cb)
Definition: ifs.c:202
IMalloc IMalloc_iface
Definition: ifs.c:53
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
Definition: ifs.c:52
SIZE_T WINAPI HeapSize(HANDLE, DWORD, LPCVOID)
int32_t INT
Definition: typedefs.h:56
static CRITICAL_SECTION IMalloc32_SpyCS
Definition: ifs.c:66
static USHORT USHORT * NewLength
BOOL NTAPI IsBadCodePtr(FARPROC lpfn)
Definition: except.c:874
HRESULT WINAPI CoGetMalloc(DWORD context, IMalloc **imalloc)
Definition: ifs.c:383
unsigned int BOOL
Definition: ntddk_ex.h:94
HRESULT WINAPI CoRevokeMallocSpy(void)
Definition: ifs.c:502
static LPUNKNOWN
Definition: ndr_ole.c:49
static ULONG WINAPI IMalloc_fnAddRefRelease(IMalloc *iface)
Definition: ifs.c:160
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:50
static SIZE_T WINAPI IMalloc_fnGetSize(IMalloc *iface, void *pv)
Definition: ifs.c:293
#define debugstr_guid
Definition: kernel32.h:35
DWORD dummy
Definition: ifs.c:54
static void WINAPI IMalloc_fnHeapMinimize(IMalloc *iface)
Definition: ifs.c:342
#define TRACE(s)
Definition: solgame.cpp:4
GLsizeiptr size
Definition: glext.h:5919
HRESULT hres
Definition: protocol.c:465
#define GetProcessHeap()
Definition: compat.h:395
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:535
#define WINAPI
Definition: msvc.h:8
#define LMEM_MOVEABLE
Definition: winbase.h:350
unsigned long DWORD
Definition: ntddk_ex.h:95
interface IMallocSpy * LPMALLOCSPY
Definition: objfwd.h:13
static DWORD cb
Definition: integrity.c:41
GLenum const GLvoid * addr
Definition: glext.h:9621
DWORD SpyedBlockTableLength
Definition: ifs.c:59
static BOOL SetSpyedBlockTableLength(DWORD NewLength)
Definition: ifs.c:76
static void WINAPI IMalloc_fnFree(IMalloc *iface, void *pv)
Definition: ifs.c:254
LIST_ENTRY ProcessLocksList
Definition: winbase.h:848
IMallocSpy * pSpy
Definition: ifs.c:55
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:63
#define HeapReAlloc
Definition: compat.h:393
BOOL WINAPI IsBadReadPtr(IN LPCVOID lp, IN UINT_PTR ucb)
Definition: except.c:807
DWORD SpyedAllocationsLeft
Definition: ifs.c:56
HRESULT WINAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy)
Definition: ifs.c:462
static HRESULT WINAPI IMalloc_fnQueryInterface(IMalloc *iface, REFIID refiid, void **obj)
Definition: ifs.c:146
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:440
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:67
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:406
#define HeapFree(x, y, z)
Definition: compat.h:394
#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:91