Assorted spelling fixes.
[wine.git] / dlls / ole32 / ifs.c
blob696a7b832ccc464fdc5e7ba661346b241d2cf105
1 /*
2 * basic interfaces
4 * Copyright 1997 Marcus Meissner
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.
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.
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
21 #include "config.h"
23 #include <ctype.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
29 #define COBJMACROS
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winuser.h"
34 #include "ole2.h"
35 #include "winerror.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(olemalloc);
41 /******************************************************************************
42 * IMalloc32 implementation
44 * NOTES
45 * For supporting CoRegisterMallocSpy the IMalloc implementation must know if
46 * a given memory block was allocated with a spy active.
48 *****************************************************************************/
49 /* set the vtable later */
50 static const IMallocVtbl VT_IMalloc32;
52 typedef struct {
53 IMalloc IMalloc_iface;
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;
62 /* this is the static object instance */
63 static _Malloc32 Malloc32 = {{&VT_IMalloc32}, 0, NULL, 0, 0, NULL, 0};
65 /* with a spy active all calls from pre to post methods are threadsave */
66 static CRITICAL_SECTION IMalloc32_SpyCS;
67 static CRITICAL_SECTION_DEBUG critsect_debug =
69 0, 0, &IMalloc32_SpyCS,
70 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
71 0, 0, { (DWORD_PTR)(__FILE__ ": IMalloc32_SpyCS") }
73 static CRITICAL_SECTION IMalloc32_SpyCS = { &critsect_debug, -1, 0, 0, 0, 0 };
75 /* resize the old table */
76 static BOOL SetSpyedBlockTableLength ( DWORD NewLength )
78 LPVOID *NewSpyedBlocks;
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;
84 Malloc32.SpyedBlockTableLength = NewLength;
87 return NewSpyedBlocks != NULL;
90 /* add a location to the table */
91 static BOOL AddMemoryLocation(LPVOID * pMem)
93 LPVOID * Current;
95 /* allocate the table if not already allocated */
96 if (!Malloc32.SpyedBlockTableLength && !SetSpyedBlockTableLength(0x1000))
97 return FALSE;
99 /* find a free location */
100 Current = Malloc32.SpyedBlocks;
101 while (*Current) {
102 Current++;
103 if (Current >= Malloc32.SpyedBlocks + Malloc32.SpyedBlockTableLength) {
104 /* no more space in table, grow it */
105 DWORD old_length = Malloc32.SpyedBlockTableLength;
106 if (!SetSpyedBlockTableLength( Malloc32.SpyedBlockTableLength + 0x1000))
107 return FALSE;
108 Current = Malloc32.SpyedBlocks + old_length;
112 /* put the location in our table */
113 *Current = pMem;
114 Malloc32.SpyedAllocationsLeft++;
115 /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
116 return TRUE;
119 static BOOL RemoveMemoryLocation(LPCVOID pMem)
121 LPVOID * Current;
123 /* allocate the table if not already allocated */
124 if (!Malloc32.SpyedBlockTableLength && !SetSpyedBlockTableLength(0x1000))
125 return FALSE;
127 Current = Malloc32.SpyedBlocks;
129 /* find the location */
130 while (*Current != pMem) {
131 Current++;
132 if (Current >= Malloc32.SpyedBlocks + Malloc32.SpyedBlockTableLength)
133 return FALSE; /* not found */
136 /* location found */
137 Malloc32.SpyedAllocationsLeft--;
138 /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
139 *Current = NULL;
140 return TRUE;
143 /******************************************************************************
144 * IMalloc32_QueryInterface [VTABLE]
146 static HRESULT WINAPI IMalloc_fnQueryInterface(LPMALLOC iface,REFIID refiid,LPVOID *obj) {
148 TRACE("(%s,%p)\n",debugstr_guid(refiid),obj);
150 if (IsEqualIID(&IID_IUnknown,refiid) || IsEqualIID(&IID_IMalloc,refiid)) {
151 *obj = &Malloc32;
152 return S_OK;
154 return E_NOINTERFACE;
157 /******************************************************************************
158 * IMalloc32_AddRefRelease [VTABLE]
160 static ULONG WINAPI IMalloc_fnAddRefRelease (LPMALLOC iface) {
161 return 1;
164 /******************************************************************************
165 * IMalloc32_Alloc [VTABLE]
167 static LPVOID WINAPI IMalloc_fnAlloc(LPMALLOC iface, DWORD cb) {
169 LPVOID addr;
171 TRACE("(%d)\n",cb);
173 if(Malloc32.pSpy) {
174 DWORD preAllocResult;
176 EnterCriticalSection(&IMalloc32_SpyCS);
177 preAllocResult = IMallocSpy_PreAlloc(Malloc32.pSpy, cb);
178 if ((cb != 0) && (preAllocResult == 0)) {
179 /* PreAlloc can force Alloc to fail, but not if cb == 0 */
180 TRACE("returning null\n");
181 LeaveCriticalSection(&IMalloc32_SpyCS);
182 return NULL;
186 addr = HeapAlloc(GetProcessHeap(),0,cb);
188 if(Malloc32.pSpy) {
189 addr = IMallocSpy_PostAlloc(Malloc32.pSpy, addr);
190 if (addr) AddMemoryLocation(addr);
191 LeaveCriticalSection(&IMalloc32_SpyCS);
194 TRACE("--(%p)\n",addr);
195 return addr;
198 /******************************************************************************
199 * IMalloc32_Realloc [VTABLE]
201 static LPVOID WINAPI IMalloc_fnRealloc(LPMALLOC iface,LPVOID pv,DWORD cb) {
203 LPVOID pNewMemory;
205 TRACE("(%p,%d)\n",pv,cb);
207 if(Malloc32.pSpy) {
208 LPVOID pRealMemory;
209 BOOL fSpyed;
211 EnterCriticalSection(&IMalloc32_SpyCS);
212 fSpyed = RemoveMemoryLocation(pv);
213 cb = IMallocSpy_PreRealloc(Malloc32.pSpy, pv, cb, &pRealMemory, fSpyed);
215 /* check if can release the spy */
216 if(Malloc32.SpyReleasePending && !Malloc32.SpyedAllocationsLeft) {
217 IMallocSpy_Release(Malloc32.pSpy);
218 Malloc32.SpyReleasePending = FALSE;
219 Malloc32.pSpy = NULL;
220 LeaveCriticalSection(&IMalloc32_SpyCS);
223 if (0==cb) {
224 /* PreRealloc can force Realloc to fail */
225 if (Malloc32.pSpy)
226 LeaveCriticalSection(&IMalloc32_SpyCS);
227 return NULL;
230 pv = pRealMemory;
233 if (!pv) pNewMemory = HeapAlloc(GetProcessHeap(),0,cb);
234 else if (cb) pNewMemory = HeapReAlloc(GetProcessHeap(),0,pv,cb);
235 else {
236 HeapFree(GetProcessHeap(),0,pv);
237 pNewMemory = NULL;
240 if(Malloc32.pSpy) {
241 pNewMemory = IMallocSpy_PostRealloc(Malloc32.pSpy, pNewMemory, TRUE);
242 if (pNewMemory) AddMemoryLocation(pNewMemory);
243 LeaveCriticalSection(&IMalloc32_SpyCS);
246 TRACE("--(%p)\n",pNewMemory);
247 return pNewMemory;
250 /******************************************************************************
251 * IMalloc32_Free [VTABLE]
253 static VOID WINAPI IMalloc_fnFree(LPMALLOC iface,LPVOID pv) {
255 BOOL fSpyed = FALSE;
257 TRACE("(%p)\n",pv);
259 if(Malloc32.pSpy) {
260 EnterCriticalSection(&IMalloc32_SpyCS);
261 fSpyed = RemoveMemoryLocation(pv);
262 pv = IMallocSpy_PreFree(Malloc32.pSpy, pv, fSpyed);
265 HeapFree(GetProcessHeap(),0,pv);
267 if(Malloc32.pSpy) {
268 IMallocSpy_PostFree(Malloc32.pSpy, fSpyed);
270 /* check if can release the spy */
271 if(Malloc32.SpyReleasePending && !Malloc32.SpyedAllocationsLeft) {
272 IMallocSpy_Release(Malloc32.pSpy);
273 Malloc32.SpyReleasePending = FALSE;
274 Malloc32.pSpy = NULL;
277 LeaveCriticalSection(&IMalloc32_SpyCS);
281 /******************************************************************************
282 * IMalloc32_GetSize [VTABLE]
284 * NOTES
285 * FIXME returns:
286 * win95: size allocated (4 byte boundarys)
287 * win2k: size originally requested !!! (allocated on 8 byte boundarys)
289 static DWORD WINAPI IMalloc_fnGetSize(LPMALLOC iface,LPVOID pv) {
291 DWORD cb;
292 BOOL fSpyed = FALSE;
294 TRACE("(%p)\n",pv);
296 if(Malloc32.pSpy) {
297 EnterCriticalSection(&IMalloc32_SpyCS);
298 pv = IMallocSpy_PreGetSize(Malloc32.pSpy, pv, fSpyed);
301 cb = HeapSize(GetProcessHeap(),0,pv);
303 if(Malloc32.pSpy) {
304 cb = IMallocSpy_PostGetSize(Malloc32.pSpy, cb, fSpyed);
305 LeaveCriticalSection(&IMalloc32_SpyCS);
308 return cb;
311 /******************************************************************************
312 * IMalloc32_DidAlloc [VTABLE]
314 static INT WINAPI IMalloc_fnDidAlloc(LPMALLOC iface,LPVOID pv) {
316 BOOL fSpyed = FALSE;
317 int didAlloc;
319 TRACE("(%p)\n",pv);
321 if(Malloc32.pSpy) {
322 EnterCriticalSection(&IMalloc32_SpyCS);
323 pv = IMallocSpy_PreDidAlloc(Malloc32.pSpy, pv, fSpyed);
326 didAlloc = -1;
328 if(Malloc32.pSpy) {
329 didAlloc = IMallocSpy_PostDidAlloc(Malloc32.pSpy, pv, fSpyed, didAlloc);
330 LeaveCriticalSection(&IMalloc32_SpyCS);
332 return didAlloc;
335 /******************************************************************************
336 * IMalloc32_HeapMinimize [VTABLE]
338 static VOID WINAPI IMalloc_fnHeapMinimize(LPMALLOC iface) {
339 TRACE("()\n");
341 if(Malloc32.pSpy) {
342 EnterCriticalSection(&IMalloc32_SpyCS);
343 IMallocSpy_PreHeapMinimize(Malloc32.pSpy);
346 if(Malloc32.pSpy) {
347 IMallocSpy_PostHeapMinimize(Malloc32.pSpy);
348 LeaveCriticalSection(&IMalloc32_SpyCS);
352 static const IMallocVtbl VT_IMalloc32 =
354 IMalloc_fnQueryInterface,
355 IMalloc_fnAddRefRelease,
356 IMalloc_fnAddRefRelease,
357 IMalloc_fnAlloc,
358 IMalloc_fnRealloc,
359 IMalloc_fnFree,
360 IMalloc_fnGetSize,
361 IMalloc_fnDidAlloc,
362 IMalloc_fnHeapMinimize
365 /******************************************************************************
366 * CoGetMalloc [OLE32.@]
368 * Retrieves the current IMalloc interface for the process.
370 * PARAMS
371 * dwMemContext [I]
372 * lpMalloc [O] Address where memory allocator object will be stored.
374 * RETURNS
375 * Success: S_OK.
376 * Failure: HRESULT code.
378 HRESULT WINAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC *lpMalloc)
380 *lpMalloc = &Malloc32.IMalloc_iface;
381 return S_OK;
384 /***********************************************************************
385 * CoTaskMemAlloc [OLE32.@]
387 * Allocates memory using the current process memory allocator.
389 * PARAMS
390 * size [I] Size of the memory block to allocate.
392 * RETURNS
393 * Success: Pointer to newly allocated memory block.
394 * Failure: NULL.
396 LPVOID WINAPI CoTaskMemAlloc(ULONG size)
398 return IMalloc_Alloc(&Malloc32.IMalloc_iface,size);
401 /***********************************************************************
402 * CoTaskMemFree [OLE32.@]
404 * Frees memory allocated from the current process memory allocator.
406 * PARAMS
407 * ptr [I] Memory block to free.
409 * RETURNS
410 * Nothing.
412 VOID WINAPI CoTaskMemFree(LPVOID ptr)
414 IMalloc_Free(&Malloc32.IMalloc_iface, ptr);
417 /***********************************************************************
418 * CoTaskMemRealloc [OLE32.@]
420 * Allocates memory using the current process memory allocator.
422 * PARAMS
423 * pvOld [I] Pointer to old memory block.
424 * size [I] Size of the new memory block.
426 * RETURNS
427 * Success: Pointer to newly allocated memory block.
428 * Failure: NULL.
430 LPVOID WINAPI CoTaskMemRealloc(LPVOID pvOld, ULONG size)
432 return IMalloc_Realloc(&Malloc32.IMalloc_iface, pvOld, size);
435 /***********************************************************************
436 * CoRegisterMallocSpy [OLE32.@]
438 * Registers an object that receives notifications on memory allocations and
439 * frees.
441 * PARAMS
442 * pMallocSpy [I] New spy object.
444 * RETURNS
445 * Success: S_OK.
446 * Failure: HRESULT code.
448 * NOTES
449 * if a mallocspy is already registered, we can't do it again since
450 * only the spy knows, how to free a memory block
452 HRESULT WINAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy)
454 IMallocSpy* pSpy;
455 HRESULT hres = E_INVALIDARG;
457 TRACE("\n");
459 if(Malloc32.pSpy) return CO_E_OBJISREG;
461 EnterCriticalSection(&IMalloc32_SpyCS);
463 if (SUCCEEDED(IMallocSpy_QueryInterface(pMallocSpy, &IID_IMallocSpy, (void**)&pSpy))) {
464 Malloc32.pSpy = pSpy;
465 hres = S_OK;
468 LeaveCriticalSection(&IMalloc32_SpyCS);
470 return hres;
473 /***********************************************************************
474 * CoRevokeMallocSpy [OLE32.@]
476 * Revokes a previously registered object that receives notifications on memory
477 * allocations and frees.
479 * PARAMS
480 * pMallocSpy [I] New spy object.
482 * RETURNS
483 * Success: S_OK.
484 * Failure: HRESULT code.
486 * NOTES
487 * we can't revoke a malloc spy as long as memory blocks allocated with
488 * the spy are active since only the spy knows how to free them
490 HRESULT WINAPI CoRevokeMallocSpy(void)
492 HRESULT hres = S_OK;
493 TRACE("\n");
495 EnterCriticalSection(&IMalloc32_SpyCS);
497 if (Malloc32.SpyedAllocationsLeft) {
498 TRACE("SpyReleasePending with %u allocations left\n", Malloc32.SpyedAllocationsLeft);
499 Malloc32.SpyReleasePending = TRUE;
500 hres = E_ACCESSDENIED;
501 } else {
502 IMallocSpy_Release(Malloc32.pSpy);
503 Malloc32.pSpy = NULL;
505 LeaveCriticalSection(&IMalloc32_SpyCS);
507 return hres;
510 /******************************************************************************
511 * IsValidInterface [OLE32.@]
513 * Determines whether a pointer is a valid interface.
515 * PARAMS
516 * punk [I] Interface to be tested.
518 * RETURNS
519 * TRUE, if the passed pointer is a valid interface, or FALSE otherwise.
521 BOOL WINAPI IsValidInterface(LPUNKNOWN punk)
523 return !(
524 IsBadReadPtr(punk,4) ||
525 IsBadReadPtr(punk->lpVtbl,4) ||
526 IsBadReadPtr(punk->lpVtbl->QueryInterface,9) ||
527 IsBadCodePtr((FARPROC)punk->lpVtbl->QueryInterface)