Mark immutable objects as const. Fix inconsistent *-style.
[wine/multimedia.git] / dlls / ole32 / ifs.c
bloba71f69d51b3ecacb880a60ba6c6b300b050c9e19
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include <ctype.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <assert.h>
28 #include "ole2.h"
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winerror.h"
33 #include "wine/obj_base.h"
35 #include "wine/debug.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(ole);
39 /******************************************************************************
40 * IMalloc32 implementation
42 * NOTES
43 * For supporting CoRegisterMallocSpy the IMalloc implementation must know if
44 * a given memory block was allocated with a spy active.
46 *****************************************************************************/
47 /* set the vtable later */
48 extern ICOM_VTABLE(IMalloc) VT_IMalloc32;
50 typedef struct {
51 ICOM_VFIELD(IMalloc);
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 int SpyedBlockTableLength; /* size of the table*/
58 } _Malloc32;
60 /* this is the static object instance */
61 _Malloc32 Malloc32 = {&VT_IMalloc32, 0, NULL, 0, 0, NULL, 0};
63 /* with a spy active all calls from pre to post methods are threadsave */
64 static CRITICAL_SECTION IMalloc32_SpyCS = CRITICAL_SECTION_INIT("IMalloc32_SpyCS");
66 /* resize the old table */
67 static int SetSpyedBlockTableLength ( int NewLength )
69 Malloc32.SpyedBlocks = (LPVOID*)LocalReAlloc((HLOCAL)Malloc32.SpyedBlocks, NewLength, GMEM_ZEROINIT);
70 Malloc32.SpyedBlockTableLength = NewLength;
71 return Malloc32.SpyedBlocks ? 1 : 0;
74 /* add a location to the table */
75 static int AddMemoryLocation(LPVOID * pMem)
77 LPVOID * Current;
79 /* allocate the table if not already allocated */
80 if (!Malloc32.SpyedBlockTableLength) {
81 if (!SetSpyedBlockTableLength(0x1000)) return 0;
84 /* find a free location */
85 Current = Malloc32.SpyedBlocks;
86 while (*Current) {
87 Current++;
88 if (Current >= Malloc32.SpyedBlocks + Malloc32.SpyedBlockTableLength) {
89 /* no more space in table, grow it */
90 if (!SetSpyedBlockTableLength( Malloc32.SpyedBlockTableLength + 0x1000 )) return 0;
94 /* put the location in our table */
95 *Current = pMem;
96 Malloc32.SpyedAllocationsLeft++;
97 /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
98 return 1;
101 static int RemoveMemoryLocation(LPVOID * pMem)
103 LPVOID * Current = Malloc32.SpyedBlocks;
105 /* find the location */
106 while (*Current != pMem) {
107 Current++;
108 if (Current >= Malloc32.SpyedBlocks + Malloc32.SpyedBlockTableLength) return 0; /* not found */
111 /* location found */
112 Malloc32.SpyedAllocationsLeft--;
113 /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
114 *Current = NULL;
115 return 1;
118 /******************************************************************************
119 * IMalloc32_QueryInterface [VTABLE]
121 static HRESULT WINAPI IMalloc_fnQueryInterface(LPMALLOC iface,REFIID refiid,LPVOID *obj) {
123 TRACE("(%s,%p)\n",debugstr_guid(refiid),obj);
125 if (IsEqualIID(&IID_IUnknown,refiid) || IsEqualIID(&IID_IMalloc,refiid)) {
126 *obj = (LPMALLOC)&Malloc32;
127 return S_OK;
129 return E_NOINTERFACE;
132 /******************************************************************************
133 * IMalloc32_AddRefRelease [VTABLE]
135 static ULONG WINAPI IMalloc_fnAddRefRelease (LPMALLOC iface) {
136 return 1;
139 /******************************************************************************
140 * IMalloc32_Alloc [VTABLE]
142 static LPVOID WINAPI IMalloc_fnAlloc(LPMALLOC iface, DWORD cb) {
144 LPVOID addr;
146 TRACE("(%ld)\n",cb);
148 if(Malloc32.pSpy) {
149 EnterCriticalSection(&IMalloc32_SpyCS);
150 cb = IMallocSpy_PreAlloc(Malloc32.pSpy, cb);
151 if (0==cb) {
152 /* PreAlloc can force Alloc to fail */
153 LeaveCriticalSection(&IMalloc32_SpyCS);
154 return NULL;
159 addr = HeapAlloc(GetProcessHeap(),0,cb);
161 if(Malloc32.pSpy) {
162 addr = IMallocSpy_PostAlloc(Malloc32.pSpy, addr);
163 if (addr) AddMemoryLocation(addr);
164 LeaveCriticalSection(&IMalloc32_SpyCS);
167 TRACE("--(%p)\n",addr);
168 return addr;
171 /******************************************************************************
172 * IMalloc32_Realloc [VTABLE]
174 static LPVOID WINAPI IMalloc_fnRealloc(LPMALLOC iface,LPVOID pv,DWORD cb) {
176 LPVOID pNewMemory;
178 TRACE("(%p,%ld)\n",pv,cb);
180 if(Malloc32.pSpy) {
181 LPVOID pRealMemory;
182 BOOL fSpyed;
184 EnterCriticalSection(&IMalloc32_SpyCS);
185 fSpyed = RemoveMemoryLocation(pv);
186 cb = IMallocSpy_PreRealloc(Malloc32.pSpy, pv, cb, &pRealMemory, fSpyed);
188 /* check if can release the spy */
189 if(Malloc32.SpyReleasePending && !Malloc32.SpyedAllocationsLeft) {
190 IMallocSpy_Release(Malloc32.pSpy);
191 Malloc32.SpyReleasePending = FALSE;
192 Malloc32.pSpy = NULL;
195 if (0==cb) {
196 /* PreRealloc can force Realloc to fail */
197 LeaveCriticalSection(&IMalloc32_SpyCS);
198 return NULL;
200 pv = pRealMemory;
203 pNewMemory = HeapReAlloc(GetProcessHeap(),0,pv,cb);
205 if(Malloc32.pSpy) {
206 pNewMemory = IMallocSpy_PostRealloc(Malloc32.pSpy, pNewMemory, TRUE);
207 if (pNewMemory) AddMemoryLocation(pNewMemory);
208 LeaveCriticalSection(&IMalloc32_SpyCS);
211 TRACE("--(%p)\n",pNewMemory);
212 return pNewMemory;
215 /******************************************************************************
216 * IMalloc32_Free [VTABLE]
218 static VOID WINAPI IMalloc_fnFree(LPMALLOC iface,LPVOID pv) {
220 BOOL fSpyed = 0;
222 TRACE("(%p)\n",pv);
224 if(Malloc32.pSpy) {
225 EnterCriticalSection(&IMalloc32_SpyCS);
226 fSpyed = RemoveMemoryLocation(pv);
227 pv = IMallocSpy_PreFree(Malloc32.pSpy, pv, fSpyed);
230 HeapFree(GetProcessHeap(),0,pv);
232 if(Malloc32.pSpy) {
233 IMallocSpy_PostFree(Malloc32.pSpy, fSpyed);
235 /* check if can release the spy */
236 if(Malloc32.SpyReleasePending && !Malloc32.SpyedAllocationsLeft) {
237 IMallocSpy_Release(Malloc32.pSpy);
238 Malloc32.SpyReleasePending = FALSE;
239 Malloc32.pSpy = NULL;
242 LeaveCriticalSection(&IMalloc32_SpyCS);
246 /******************************************************************************
247 * IMalloc32_GetSize [VTABLE]
249 * NOTES
250 * FIXME returns:
251 * win95: size allocated (4 byte boundarys)
252 * win2k: size originally requested !!! (allocated on 8 byte boundarys)
254 static DWORD WINAPI IMalloc_fnGetSize(LPMALLOC iface,LPVOID pv) {
256 DWORD cb;
257 BOOL fSpyed = 0;
259 TRACE("(%p)\n",pv);
261 if(Malloc32.pSpy) {
262 EnterCriticalSection(&IMalloc32_SpyCS);
263 pv = IMallocSpy_PreGetSize(Malloc32.pSpy, pv, fSpyed);
266 cb = HeapSize(GetProcessHeap(),0,pv);
268 if(Malloc32.pSpy) {
269 cb = IMallocSpy_PostGetSize(Malloc32.pSpy, cb, fSpyed);
270 LeaveCriticalSection(&IMalloc32_SpyCS);
273 return cb;
276 /******************************************************************************
277 * IMalloc32_DidAlloc [VTABLE]
279 static INT WINAPI IMalloc_fnDidAlloc(LPMALLOC iface,LPVOID pv) {
281 BOOL fSpyed = 0;
282 int didAlloc;
284 TRACE("(%p)\n",pv);
286 if(Malloc32.pSpy) {
287 EnterCriticalSection(&IMalloc32_SpyCS);
288 pv = IMallocSpy_PreDidAlloc(Malloc32.pSpy, pv, fSpyed);
291 didAlloc = -1;
293 if(Malloc32.pSpy) {
294 didAlloc = IMallocSpy_PostDidAlloc(Malloc32.pSpy, pv, fSpyed, didAlloc);
295 LeaveCriticalSection(&IMalloc32_SpyCS);
297 return didAlloc;
300 /******************************************************************************
301 * IMalloc32_HeapMinimize [VTABLE]
303 static VOID WINAPI IMalloc_fnHeapMinimize(LPMALLOC iface) {
304 TRACE("()\n");
306 if(Malloc32.pSpy) {
307 EnterCriticalSection(&IMalloc32_SpyCS);
308 IMallocSpy_PreHeapMinimize(Malloc32.pSpy);
311 if(Malloc32.pSpy) {
312 IMallocSpy_PostHeapMinimize(Malloc32.pSpy);
313 LeaveCriticalSection(&IMalloc32_SpyCS);
317 static ICOM_VTABLE(IMalloc) VT_IMalloc32 =
319 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
320 IMalloc_fnQueryInterface,
321 IMalloc_fnAddRefRelease,
322 IMalloc_fnAddRefRelease,
323 IMalloc_fnAlloc,
324 IMalloc_fnRealloc,
325 IMalloc_fnFree,
326 IMalloc_fnGetSize,
327 IMalloc_fnDidAlloc,
328 IMalloc_fnHeapMinimize
331 /******************************************************************************
332 * IMallocSpy implementation
333 *****************************************************************************/
335 /* set the vtable later */
336 extern ICOM_VTABLE(IMallocSpy) VT_IMallocSpy;
338 typedef struct {
339 ICOM_VFIELD(IMallocSpy);
340 DWORD ref;
341 } _MallocSpy;
343 /* this is the static object instance */
344 _MallocSpy MallocSpy = {&VT_IMallocSpy, 0};
346 /******************************************************************************
347 * IMalloc32_QueryInterface [VTABLE]
349 static HRESULT WINAPI IMallocSpy_fnQueryInterface(LPMALLOCSPY iface,REFIID refiid,LPVOID *obj)
352 TRACE("(%s,%p)\n",debugstr_guid(refiid),obj);
354 if (IsEqualIID(&IID_IUnknown,refiid) || IsEqualIID(&IID_IMallocSpy,refiid)) {
355 *obj = (LPMALLOC)&MallocSpy;
356 return S_OK;
358 return E_NOINTERFACE;
361 /******************************************************************************
362 * IMalloc32_AddRef [VTABLE]
364 static ULONG WINAPI IMallocSpy_fnAddRef (LPMALLOCSPY iface)
367 ICOM_THIS (_MallocSpy, iface);
369 TRACE ("(%p)->(count=%lu)\n", This, This->ref);
371 return ++(This->ref);
374 /******************************************************************************
375 * IMalloc32_AddRelease [VTABLE]
377 * NOTES
378 * Our MallocSpy is static. If the count reaches 0 we dump the leaks
380 static ULONG WINAPI IMallocSpy_fnRelease (LPMALLOCSPY iface)
383 ICOM_THIS (_MallocSpy, iface);
385 TRACE ("(%p)->(count=%lu)\n", This, This->ref);
387 if (!--(This->ref)) {
388 /* our allocation list MUST be empty here */
390 return This->ref;
393 static ULONG WINAPI IMallocSpy_fnPreAlloc(LPMALLOCSPY iface, ULONG cbRequest)
395 ICOM_THIS (_MallocSpy, iface);
396 TRACE ("(%p)->(%lu)\n", This, cbRequest);
397 return cbRequest;
399 static PVOID WINAPI IMallocSpy_fnPostAlloc(LPMALLOCSPY iface, void* pActual)
401 ICOM_THIS (_MallocSpy, iface);
402 TRACE ("(%p)->(%p)\n", This, pActual);
403 return pActual;
406 static PVOID WINAPI IMallocSpy_fnPreFree(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed)
408 ICOM_THIS (_MallocSpy, iface);
409 TRACE ("(%p)->(%p %u)\n", This, pRequest, fSpyed);
410 return pRequest;
412 static void WINAPI IMallocSpy_fnPostFree(LPMALLOCSPY iface, BOOL fSpyed)
414 ICOM_THIS (_MallocSpy, iface);
415 TRACE ("(%p)->(%u)\n", This, fSpyed);
418 static ULONG WINAPI IMallocSpy_fnPreRealloc(LPMALLOCSPY iface, void* pRequest, ULONG cbRequest, void** ppNewRequest, BOOL fSpyed)
420 ICOM_THIS (_MallocSpy, iface);
421 TRACE ("(%p)->(%p %lu %u)\n", This, pRequest, cbRequest, fSpyed);
422 *ppNewRequest = pRequest;
423 return cbRequest;
426 static PVOID WINAPI IMallocSpy_fnPostRealloc(LPMALLOCSPY iface, void* pActual, BOOL fSpyed)
428 ICOM_THIS (_MallocSpy, iface);
429 TRACE ("(%p)->(%p %u)\n", This, pActual, fSpyed);
430 return pActual;
433 static PVOID WINAPI IMallocSpy_fnPreGetSize(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed)
435 ICOM_THIS (_MallocSpy, iface);
436 TRACE ("(%p)->(%p %u)\n", This, pRequest, fSpyed);
437 return pRequest;
440 static ULONG WINAPI IMallocSpy_fnPostGetSize(LPMALLOCSPY iface, ULONG cbActual, BOOL fSpyed)
442 ICOM_THIS (_MallocSpy, iface);
443 TRACE ("(%p)->(%lu %u)\n", This, cbActual, fSpyed);
444 return cbActual;
447 static PVOID WINAPI IMallocSpy_fnPreDidAlloc(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed)
449 ICOM_THIS (_MallocSpy, iface);
450 TRACE ("(%p)->(%p %u)\n", This, pRequest, fSpyed);
451 return pRequest;
454 static int WINAPI IMallocSpy_fnPostDidAlloc(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed, int fActual)
456 ICOM_THIS (_MallocSpy, iface);
457 TRACE ("(%p)->(%p %u %u)\n", This, pRequest, fSpyed, fActual);
458 return fActual;
461 static int WINAPI IMallocSpy_fnPreHeapMinimize(LPMALLOCSPY iface)
463 ICOM_THIS (_MallocSpy, iface);
464 TRACE ("(%p)->()\n", This);
465 return 0;
468 static int WINAPI IMallocSpy_fnPostHeapMinimize(LPMALLOCSPY iface)
470 ICOM_THIS (_MallocSpy, iface);
471 TRACE ("(%p)->()\n", This);
472 return 0;
475 static void MallocSpyDumpLeaks() {
476 TRACE("leaks: %lu\n", Malloc32.SpyedAllocationsLeft);
479 static ICOM_VTABLE(IMallocSpy) VT_IMallocSpy =
481 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
482 IMallocSpy_fnQueryInterface,
483 IMallocSpy_fnAddRef,
484 IMallocSpy_fnRelease,
485 IMallocSpy_fnPreAlloc,
486 IMallocSpy_fnPostAlloc,
487 IMallocSpy_fnPreFree,
488 IMallocSpy_fnPostFree,
489 IMallocSpy_fnPreRealloc,
490 IMallocSpy_fnPostRealloc,
491 IMallocSpy_fnPreGetSize,
492 IMallocSpy_fnPostGetSize,
493 IMallocSpy_fnPreDidAlloc,
494 IMallocSpy_fnPostDidAlloc,
495 IMallocSpy_fnPreHeapMinimize,
496 IMallocSpy_fnPostHeapMinimize
499 /******************************************************************************
500 * CoGetMalloc [OLE32.20]
502 * RETURNS
503 * The win32 IMalloc
505 HRESULT WINAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC *lpMalloc)
507 *lpMalloc = (LPMALLOC)&Malloc32;
508 return S_OK;
511 /***********************************************************************
512 * CoTaskMemAlloc [OLE32.43]
513 * RETURNS
514 * pointer to newly allocated block
516 LPVOID WINAPI CoTaskMemAlloc(ULONG size)
518 return IMalloc_Alloc((LPMALLOC)&Malloc32,size);
520 /***********************************************************************
521 * CoTaskMemFree [OLE32.44]
523 VOID WINAPI CoTaskMemFree(LPVOID ptr)
525 IMalloc_Free((LPMALLOC)&Malloc32, ptr);
528 /***********************************************************************
529 * CoTaskMemRealloc [OLE32.45]
530 * RETURNS
531 * pointer to newly allocated block
533 LPVOID WINAPI CoTaskMemRealloc(LPVOID pvOld, ULONG size)
535 return IMalloc_Realloc((LPMALLOC)&Malloc32, pvOld, size);
538 /***********************************************************************
539 * CoRegisterMallocSpy [OLE32.37]
541 * NOTES
542 * if a mallocspy is already registered, we cant do it again since
543 * only the spy knows, how to free a memory block
545 HRESULT WINAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy)
547 IMallocSpy* pSpy;
548 HRESULT hres = E_INVALIDARG;
550 TRACE("\n");
552 /* HACK TO ACTIVATE OUT SPY */
553 if (pMallocSpy == (LPVOID)-1) pMallocSpy =(IMallocSpy*)&MallocSpy;
555 if(Malloc32.pSpy) return CO_E_OBJISREG;
557 EnterCriticalSection(&IMalloc32_SpyCS);
559 if (SUCCEEDED(IUnknown_QueryInterface(pMallocSpy, &IID_IMallocSpy, (LPVOID*)&pSpy))) {
560 Malloc32.pSpy = pSpy;
561 hres = S_OK;
564 LeaveCriticalSection(&IMalloc32_SpyCS);
566 return hres;
569 /***********************************************************************
570 * CoRevokeMallocSpy [OLE32.41]
572 * NOTES
573 * we can't rewoke a malloc spy as long as memory blocks allocated with
574 * the spy are active since only the spy knows how to free them
576 HRESULT WINAPI CoRevokeMallocSpy(void)
578 HRESULT hres = S_OK;
579 TRACE("\n");
581 EnterCriticalSection(&IMalloc32_SpyCS);
583 /* if it's our spy it's time to dump the leaks */
584 if (Malloc32.pSpy == (IMallocSpy*)&MallocSpy) {
585 MallocSpyDumpLeaks();
588 if (Malloc32.SpyedAllocationsLeft) {
589 TRACE("SpyReleasePending with %lu allocations left\n", Malloc32.SpyedAllocationsLeft);
590 Malloc32.SpyReleasePending = TRUE;
591 hres = E_ACCESSDENIED;
592 } else {
593 IMallocSpy_Release(Malloc32.pSpy);
594 Malloc32.pSpy = NULL;
596 LeaveCriticalSection(&IMalloc32_SpyCS);
598 return S_OK;
601 /******************************************************************************
602 * IsValidInterface [OLE32.78]
604 * RETURNS
605 * True, if the passed pointer is a valid interface
607 BOOL WINAPI IsValidInterface(
608 LPUNKNOWN punk /* [in] interface to be tested */
610 return !(
611 IsBadReadPtr(punk,4) ||
612 IsBadReadPtr(ICOM_VTBL(punk),4) ||
613 IsBadReadPtr(ICOM_VTBL(punk)->QueryInterface,9) ||
614 IsBadCodePtr((FARPROC)ICOM_VTBL(punk)->QueryInterface)