ifs.c 18.7 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3 4
/*
 *	basic interfaces
 *
 *	Copyright 1997	Marcus Meissner
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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
Alexandre Julliard's avatar
Alexandre Julliard committed
19 20
 */

21 22
#include "config.h"

Alexandre Julliard's avatar
Alexandre Julliard committed
23
#include <ctype.h>
24
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
25 26
#include <stdlib.h>
#include <string.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
27
#include <assert.h>
28

29 30
#define COBJMACROS

31
#include "windef.h"
32
#include "winbase.h"
33
#include "winuser.h"
34
#include "ole2.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
35 36
#include "winerror.h"

37
#include "wine/debug.h"
38

39
WINE_DEFAULT_DEBUG_CHANNEL(olemalloc);
40

41 42 43 44 45 46 47 48 49
/******************************************************************************
 *	IMalloc32 implementation
 *
 * NOTES
 *  For supporting CoRegisterMallocSpy the IMalloc implementation must know if
 *  a given memory block was allocated with a spy active.
 *
 *****************************************************************************/
/* set the vtable later */
50
static const IMallocVtbl VT_IMalloc32;
Alexandre Julliard's avatar
Alexandre Julliard committed
51

52
typedef struct {
53
        const IMallocVtbl *lpVtbl;
54 55 56 57 58
        DWORD dummy;                /* nothing, we are static */
	IMallocSpy * pSpy;          /* the spy when active */
	DWORD SpyedAllocationsLeft; /* number of spyed allocations left */
	BOOL SpyReleasePending;     /* CoRevokeMallocSpy called with spyed allocations left*/
        LPVOID * SpyedBlocks;       /* root of the table */
59
        DWORD SpyedBlockTableLength;/* size of the table*/
60 61 62
} _Malloc32;

/* 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 */
66 67 68 69 70
static CRITICAL_SECTION IMalloc32_SpyCS;
static CRITICAL_SECTION_DEBUG critsect_debug =
{
    0, 0, &IMalloc32_SpyCS,
    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
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 */
76
static int SetSpyedBlockTableLength ( DWORD NewLength )
77
{
78 79
	LPVOID *NewSpyedBlocks;

80 81
	if (!Malloc32.SpyedBlocks) NewSpyedBlocks = LocalAlloc(LMEM_ZEROINIT, NewLength * sizeof(PVOID));
	else NewSpyedBlocks = LocalReAlloc(Malloc32.SpyedBlocks, NewLength * sizeof(PVOID), LMEM_ZEROINIT);
82 83 84 85 86 87
	if (NewSpyedBlocks) {
		Malloc32.SpyedBlocks = NewSpyedBlocks;
		Malloc32.SpyedBlockTableLength = NewLength;
	}

	return NewSpyedBlocks != NULL;
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
}

/* add a location to the table */
static int AddMemoryLocation(LPVOID * pMem)
{
        LPVOID * Current;

	/* allocate the table if not already allocated */
	if (!Malloc32.SpyedBlockTableLength) {
            if (!SetSpyedBlockTableLength(0x1000)) return 0;
	}

	/* find a free location */
	Current = Malloc32.SpyedBlocks;
	while (*Current) {
            Current++;
	    if (Current >= Malloc32.SpyedBlocks + Malloc32.SpyedBlockTableLength) {
	        /* no more space in table, grow it */
106
                DWORD old_length = Malloc32.SpyedBlockTableLength;
107
	        if (!SetSpyedBlockTableLength( Malloc32.SpyedBlockTableLength + 0x1000 )) return 0;
108
                Current = Malloc32.SpyedBlocks + old_length;
109 110 111 112 113 114 115 116 117 118
	    }
	};

	/* put the location in our table */
	*Current = pMem;
        Malloc32.SpyedAllocationsLeft++;
	/*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
        return 1;
}

119
static int RemoveMemoryLocation(LPCVOID pMem)
120
{
121 122 123 124 125 126 127 128
        LPVOID * Current;

	/* allocate the table if not already allocated */
	if (!Malloc32.SpyedBlockTableLength) {
            if (!SetSpyedBlockTableLength(0x1000)) return 0;
	}

	Current = Malloc32.SpyedBlocks;
129 130 131 132 133 134 135 136 137 138 139 140 141

	/* find the location */
	while (*Current != pMem) {
            Current++;
	    if (Current >= Malloc32.SpyedBlocks + Malloc32.SpyedBlockTableLength)  return 0;      /* not found  */
	}

	/* location found */
        Malloc32.SpyedAllocationsLeft--;
	/*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
	*Current = NULL;
	return 1;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
142

143
/******************************************************************************
144
 *	IMalloc32_QueryInterface	[VTABLE]
145
 */
146
static HRESULT WINAPI IMalloc_fnQueryInterface(LPMALLOC iface,REFIID refiid,LPVOID *obj) {
Alexandre Julliard's avatar
Alexandre Julliard committed
147

148
	TRACE("(%s,%p)\n",debugstr_guid(refiid),obj);
149

150
	if (IsEqualIID(&IID_IUnknown,refiid) || IsEqualIID(&IID_IMalloc,refiid)) {
151
		*obj = (LPMALLOC)&Malloc32;
152
		return S_OK;
Alexandre Julliard's avatar
Alexandre Julliard committed
153
	}
154
	return E_NOINTERFACE;
Alexandre Julliard's avatar
Alexandre Julliard committed
155 156
}

157
/******************************************************************************
158
 *	IMalloc32_AddRefRelease		[VTABLE]
159
 */
160 161
static ULONG WINAPI IMalloc_fnAddRefRelease (LPMALLOC iface) {
	return 1;
162 163 164
}

/******************************************************************************
165
 *	IMalloc32_Alloc 		[VTABLE]
166
 */
167
static LPVOID WINAPI IMalloc_fnAlloc(LPMALLOC iface, DWORD cb) {
168

Andreas Mohr's avatar
Andreas Mohr committed
169
	LPVOID addr;
170

171
	TRACE("(%d)\n",cb);
172 173

	if(Malloc32.pSpy) {
174 175
	    DWORD preAllocResult;
	    
176
	    EnterCriticalSection(&IMalloc32_SpyCS);
177 178 179 180 181
	    preAllocResult = IMallocSpy_PreAlloc(Malloc32.pSpy, cb);
	    if ((cb != 0) && (preAllocResult == 0)) {
		/* PreAlloc can force Alloc to fail, but not if cb == 0 */
		TRACE("returning null\n");
		LeaveCriticalSection(&IMalloc32_SpyCS);
182 183 184
		return NULL;
	    }
	}
185
 	
Andreas Mohr's avatar
Andreas Mohr committed
186
	addr = HeapAlloc(GetProcessHeap(),0,cb);
187 188 189 190 191 192 193 194

	if(Malloc32.pSpy) {
	    addr = IMallocSpy_PostAlloc(Malloc32.pSpy, addr);
	    if (addr) AddMemoryLocation(addr);
	    LeaveCriticalSection(&IMalloc32_SpyCS);
	}

	TRACE("--(%p)\n",addr);
Andreas Mohr's avatar
Andreas Mohr committed
195
	return addr;
Alexandre Julliard's avatar
Alexandre Julliard committed
196 197
}

Matthew Becker's avatar
Matthew Becker committed
198 199 200
/******************************************************************************
 * IMalloc32_Realloc [VTABLE]
 */
201
static LPVOID WINAPI IMalloc_fnRealloc(LPMALLOC iface,LPVOID pv,DWORD cb) {
202 203 204

	LPVOID pNewMemory;

205
	TRACE("(%p,%d)\n",pv,cb);
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229

	if(Malloc32.pSpy) {
	    LPVOID pRealMemory;
	    BOOL fSpyed;

	    EnterCriticalSection(&IMalloc32_SpyCS);
            fSpyed = RemoveMemoryLocation(pv);
            cb = IMallocSpy_PreRealloc(Malloc32.pSpy, pv, cb, &pRealMemory, fSpyed);

	    /* check if can release the spy */
	    if(Malloc32.SpyReleasePending && !Malloc32.SpyedAllocationsLeft) {
	        IMallocSpy_Release(Malloc32.pSpy);
		Malloc32.SpyReleasePending = FALSE;
		Malloc32.pSpy = NULL;
	    }

	    if (0==cb) {
	        /* PreRealloc can force Realloc to fail */
                LeaveCriticalSection(&IMalloc32_SpyCS);
		return NULL;
	    }
	    pv = pRealMemory;
	}

230 231 232 233 234 235
        if (!pv) pNewMemory = HeapAlloc(GetProcessHeap(),0,cb);
	else if (cb) pNewMemory = HeapReAlloc(GetProcessHeap(),0,pv,cb);
	else {
	    HeapFree(GetProcessHeap(),0,pv);
	    pNewMemory = NULL;
	}
236 237 238 239 240 241 242 243 244

	if(Malloc32.pSpy) {
	    pNewMemory = IMallocSpy_PostRealloc(Malloc32.pSpy, pNewMemory, TRUE);
	    if (pNewMemory) AddMemoryLocation(pNewMemory);
            LeaveCriticalSection(&IMalloc32_SpyCS);
	}

	TRACE("--(%p)\n",pNewMemory);
	return pNewMemory;
Alexandre Julliard's avatar
Alexandre Julliard committed
245
}
Matthew Becker's avatar
Matthew Becker committed
246 247 248 249

/******************************************************************************
 * IMalloc32_Free [VTABLE]
 */
250
static VOID WINAPI IMalloc_fnFree(LPMALLOC iface,LPVOID pv) {
251 252 253 254 255 256 257 258 259 260 261

	BOOL fSpyed = 0;

	TRACE("(%p)\n",pv);

	if(Malloc32.pSpy) {
            EnterCriticalSection(&IMalloc32_SpyCS);
            fSpyed = RemoveMemoryLocation(pv);
	    pv = IMallocSpy_PreFree(Malloc32.pSpy, pv, fSpyed);
	}

Alexandre Julliard's avatar
Alexandre Julliard committed
262
	HeapFree(GetProcessHeap(),0,pv);
263 264 265 266 267 268 269 270 271 272 273 274 275

	if(Malloc32.pSpy) {
	    IMallocSpy_PostFree(Malloc32.pSpy, fSpyed);

	    /* check if can release the spy */
	    if(Malloc32.SpyReleasePending && !Malloc32.SpyedAllocationsLeft) {
	        IMallocSpy_Release(Malloc32.pSpy);
		Malloc32.SpyReleasePending = FALSE;
		Malloc32.pSpy = NULL;
	    }

	    LeaveCriticalSection(&IMalloc32_SpyCS);
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
276 277
}

Matthew Becker's avatar
Matthew Becker committed
278 279
/******************************************************************************
 * IMalloc32_GetSize [VTABLE]
280 281 282 283 284
 *
 * NOTES
 *  FIXME returns:
 *      win95:  size allocated (4 byte boundarys)
 *      win2k:  size originally requested !!! (allocated on 8 byte boundarys)
Matthew Becker's avatar
Matthew Becker committed
285
 */
Patrik Stridvall's avatar
Patrik Stridvall committed
286
static DWORD WINAPI IMalloc_fnGetSize(LPMALLOC iface,LPVOID pv) {
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305

	DWORD cb;
	BOOL fSpyed = 0;

	TRACE("(%p)\n",pv);

	if(Malloc32.pSpy) {
            EnterCriticalSection(&IMalloc32_SpyCS);
	    pv = IMallocSpy_PreGetSize(Malloc32.pSpy, pv, fSpyed);
	}

	cb = HeapSize(GetProcessHeap(),0,pv);

	if(Malloc32.pSpy) {
	    cb = IMallocSpy_PostGetSize(Malloc32.pSpy, cb, fSpyed);
	    LeaveCriticalSection(&IMalloc32_SpyCS);
	}

	return cb;
Alexandre Julliard's avatar
Alexandre Julliard committed
306 307
}

Matthew Becker's avatar
Matthew Becker committed
308 309 310
/******************************************************************************
 * IMalloc32_DidAlloc [VTABLE]
 */
Patrik Stridvall's avatar
Patrik Stridvall committed
311
static INT WINAPI IMalloc_fnDidAlloc(LPMALLOC iface,LPVOID pv) {
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329

	BOOL fSpyed = 0;
	int didAlloc;

	TRACE("(%p)\n",pv);

	if(Malloc32.pSpy) {
            EnterCriticalSection(&IMalloc32_SpyCS);
	    pv = IMallocSpy_PreDidAlloc(Malloc32.pSpy, pv, fSpyed);
	}

	didAlloc = -1;

	if(Malloc32.pSpy) {
	    didAlloc = IMallocSpy_PostDidAlloc(Malloc32.pSpy, pv, fSpyed, didAlloc);
            LeaveCriticalSection(&IMalloc32_SpyCS);
	}
	return didAlloc;
Alexandre Julliard's avatar
Alexandre Julliard committed
330
}
Matthew Becker's avatar
Matthew Becker committed
331 332 333 334

/******************************************************************************
 * IMalloc32_HeapMinimize [VTABLE]
 */
335
static VOID WINAPI IMalloc_fnHeapMinimize(LPMALLOC iface) {
336 337 338 339 340 341 342 343 344 345 346
	TRACE("()\n");

	if(Malloc32.pSpy) {
            EnterCriticalSection(&IMalloc32_SpyCS);
	    IMallocSpy_PreHeapMinimize(Malloc32.pSpy);
	}

	if(Malloc32.pSpy) {
	    IMallocSpy_PostHeapMinimize(Malloc32.pSpy);
            LeaveCriticalSection(&IMalloc32_SpyCS);
	}
Alexandre Julliard's avatar
Alexandre Julliard committed
347 348
}

349
static const IMallocVtbl VT_IMalloc32 =
350
{
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
	IMalloc_fnQueryInterface,
	IMalloc_fnAddRefRelease,
	IMalloc_fnAddRefRelease,
	IMalloc_fnAlloc,
	IMalloc_fnRealloc,
	IMalloc_fnFree,
	IMalloc_fnGetSize,
	IMalloc_fnDidAlloc,
	IMalloc_fnHeapMinimize
};

/******************************************************************************
 *	IMallocSpy implementation
 *****************************************************************************/

/* set the vtable later */
367
static const IMallocSpyVtbl VT_IMallocSpy;
368 369

typedef struct {
370
        const IMallocSpyVtbl *lpVtbl;
371
        LONG ref;
372 373 374
} _MallocSpy;

/* this is the static object instance */
375
static _MallocSpy MallocSpy = {&VT_IMallocSpy, 0};
376 377 378 379 380 381 382 383 384 385

/******************************************************************************
 *	IMalloc32_QueryInterface	[VTABLE]
 */
static HRESULT WINAPI IMallocSpy_fnQueryInterface(LPMALLOCSPY iface,REFIID refiid,LPVOID *obj)
{

	TRACE("(%s,%p)\n",debugstr_guid(refiid),obj);

	if (IsEqualIID(&IID_IUnknown,refiid) || IsEqualIID(&IID_IMallocSpy,refiid)) {
386
		*obj = (LPMALLOC)&MallocSpy;
387 388 389 390 391 392 393 394 395 396 397
		return S_OK;
	}
	return E_NOINTERFACE;
}

/******************************************************************************
 *	IMalloc32_AddRef		[VTABLE]
 */
static ULONG WINAPI IMallocSpy_fnAddRef (LPMALLOCSPY iface)
{

398
    _MallocSpy *This = (_MallocSpy *)iface;
399
    ULONG ref = InterlockedIncrement(&This->ref);
400

401
    TRACE ("(%p)->(count=%u)\n", This, ref - 1);
402

403
    return ref;
404 405 406 407 408 409 410 411 412 413 414
}

/******************************************************************************
 *	IMalloc32_AddRelease		[VTABLE]
 *
 * NOTES
 *   Our MallocSpy is static. If the count reaches 0 we dump the leaks
 */
static ULONG WINAPI IMallocSpy_fnRelease (LPMALLOCSPY iface)
{

415
    _MallocSpy *This = (_MallocSpy *)iface;
416
    ULONG ref = InterlockedDecrement(&This->ref);
417

418
    TRACE ("(%p)->(count=%u)\n", This, ref + 1);
419

420
    if (!ref) {
421 422
        /* our allocation list MUST be empty here */
    }
423
    return ref;
424 425 426 427
}

static ULONG WINAPI IMallocSpy_fnPreAlloc(LPMALLOCSPY iface, ULONG cbRequest)
{
428
    _MallocSpy *This = (_MallocSpy *)iface;
429
    TRACE ("(%p)->(%u)\n", This, cbRequest);
430 431 432 433
    return cbRequest;
}
static PVOID WINAPI IMallocSpy_fnPostAlloc(LPMALLOCSPY iface, void* pActual)
{
434
    _MallocSpy *This = (_MallocSpy *)iface;
435 436 437 438 439 440
    TRACE ("(%p)->(%p)\n", This, pActual);
    return pActual;
}

static PVOID WINAPI IMallocSpy_fnPreFree(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed)
{
441
    _MallocSpy *This = (_MallocSpy *)iface;
442 443 444 445 446
    TRACE ("(%p)->(%p %u)\n", This, pRequest, fSpyed);
    return pRequest;
}
static void  WINAPI IMallocSpy_fnPostFree(LPMALLOCSPY iface, BOOL fSpyed)
{
447
    _MallocSpy *This = (_MallocSpy *)iface;
448 449 450 451 452
    TRACE ("(%p)->(%u)\n", This, fSpyed);
}

static ULONG WINAPI IMallocSpy_fnPreRealloc(LPMALLOCSPY iface, void* pRequest, ULONG cbRequest, void** ppNewRequest, BOOL fSpyed)
{
453
    _MallocSpy *This = (_MallocSpy *)iface;
454
    TRACE ("(%p)->(%p %u %u)\n", This, pRequest, cbRequest, fSpyed);
455 456 457 458 459 460
    *ppNewRequest = pRequest;
    return cbRequest;
}

static PVOID WINAPI IMallocSpy_fnPostRealloc(LPMALLOCSPY iface, void* pActual, BOOL fSpyed)
{
461
    _MallocSpy *This = (_MallocSpy *)iface;
462 463 464 465 466 467
    TRACE ("(%p)->(%p %u)\n", This, pActual, fSpyed);
    return pActual;
}

static PVOID WINAPI IMallocSpy_fnPreGetSize(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed)
{
468
    _MallocSpy *This = (_MallocSpy *)iface;
469 470 471 472 473 474
    TRACE ("(%p)->(%p %u)\n", This,  pRequest, fSpyed);
    return pRequest;
}

static ULONG WINAPI IMallocSpy_fnPostGetSize(LPMALLOCSPY iface, ULONG cbActual, BOOL fSpyed)
{
475
    _MallocSpy *This = (_MallocSpy *)iface;
476
    TRACE ("(%p)->(%u %u)\n", This, cbActual, fSpyed);
477 478 479 480 481
    return cbActual;
}

static PVOID WINAPI IMallocSpy_fnPreDidAlloc(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed)
{
482
    _MallocSpy *This = (_MallocSpy *)iface;
483 484 485 486 487 488
    TRACE ("(%p)->(%p %u)\n", This, pRequest, fSpyed);
    return pRequest;
}

static int WINAPI IMallocSpy_fnPostDidAlloc(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed, int fActual)
{
489
    _MallocSpy *This = (_MallocSpy *)iface;
490 491 492 493
    TRACE ("(%p)->(%p %u %u)\n", This, pRequest, fSpyed, fActual);
    return fActual;
}

494
static void WINAPI IMallocSpy_fnPreHeapMinimize(LPMALLOCSPY iface)
495
{
496
    _MallocSpy *This = (_MallocSpy *)iface;
497 498 499
    TRACE ("(%p)->()\n", This);
}

500
static void WINAPI IMallocSpy_fnPostHeapMinimize(LPMALLOCSPY iface)
501
{
502
    _MallocSpy *This = (_MallocSpy *)iface;
503 504 505
    TRACE ("(%p)->()\n", This);
}

506
static void MallocSpyDumpLeaks(void) {
507
        TRACE("leaks: %u\n", Malloc32.SpyedAllocationsLeft);
508 509
}

510
static const IMallocSpyVtbl VT_IMallocSpy =
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
{
	IMallocSpy_fnQueryInterface,
	IMallocSpy_fnAddRef,
	IMallocSpy_fnRelease,
	IMallocSpy_fnPreAlloc,
	IMallocSpy_fnPostAlloc,
	IMallocSpy_fnPreFree,
	IMallocSpy_fnPostFree,
	IMallocSpy_fnPreRealloc,
	IMallocSpy_fnPostRealloc,
	IMallocSpy_fnPreGetSize,
	IMallocSpy_fnPostGetSize,
	IMallocSpy_fnPreDidAlloc,
	IMallocSpy_fnPostDidAlloc,
	IMallocSpy_fnPreHeapMinimize,
	IMallocSpy_fnPostHeapMinimize
Alexandre Julliard's avatar
Alexandre Julliard committed
527 528
};

Matthew Becker's avatar
Matthew Becker committed
529
/******************************************************************************
530
 *		CoGetMalloc	[OLE32.@]
531
 *
532 533 534 535 536 537
 * Retrieves the current IMalloc interface for the process.
 *
 * PARAMS
 *  dwMemContext [I]
 *  lpMalloc     [O] Address where memory allocator object will be stored.
 *
538
 * RETURNS
539 540
 *	Success: S_OK.
 *  Failure: HRESULT code.
541 542 543
 */
HRESULT WINAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC *lpMalloc)
{
544
        *lpMalloc = (LPMALLOC)&Malloc32;
545 546 547 548
        return S_OK;
}

/***********************************************************************
549
 *           CoTaskMemAlloc     [OLE32.@]
550 551 552 553 554 555
 *
 * Allocates memory using the current process memory allocator.
 *
 * PARAMS
 *  size [I] Size of the memory block to allocate.
 *
556
 * RETURNS
557 558
 * 	Success: Pointer to newly allocated memory block.
 *  Failure: NULL.
Matthew Becker's avatar
Matthew Becker committed
559
 */
560 561
LPVOID WINAPI CoTaskMemAlloc(ULONG size)
{
562
        return IMalloc_Alloc((LPMALLOC)&Malloc32,size);
563
}
564

565
/***********************************************************************
566
 *           CoTaskMemFree      [OLE32.@]
567 568 569 570 571 572 573 574
 *
 * Frees memory allocated from the current process memory allocator.
 *
 * PARAMS
 *  ptr [I] Memory block to free.
 *
 * RETURNS
 *  Nothing.
575 576 577
 */
VOID WINAPI CoTaskMemFree(LPVOID ptr)
{
578
        IMalloc_Free((LPMALLOC)&Malloc32, ptr);
579 580 581
}

/***********************************************************************
582
 *           CoTaskMemRealloc   [OLE32.@]
583 584 585 586 587 588 589
 *
 * Allocates memory using the current process memory allocator.
 *
 * PARAMS
 *  pvOld [I] Pointer to old memory block.
 *  size  [I] Size of the new memory block.
 *
590
 * RETURNS
591 592
 * 	Success: Pointer to newly allocated memory block.
 *  Failure: NULL.
593 594 595
 */
LPVOID WINAPI CoTaskMemRealloc(LPVOID pvOld, ULONG size)
{
596
        return IMalloc_Realloc((LPMALLOC)&Malloc32, pvOld, size);
597 598 599
}

/***********************************************************************
600
 *           CoRegisterMallocSpy        [OLE32.@]
601
 *
602 603 604 605 606 607 608 609 610 611
 * Registers an object that receives notifications on memory allocations and
 * frees.
 *
 * PARAMS
 *  pMallocSpy [I] New spy object.
 *
 * RETURNS
 *  Success: S_OK.
 *  Failure: HRESULT code.
 *
612
 * NOTES
613
 *  if a mallocspy is already registered, we can't do it again since
614 615 616 617 618 619
 *  only the spy knows, how to free a memory block
 */
HRESULT WINAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy)
{
	IMallocSpy* pSpy;
        HRESULT hres = E_INVALIDARG;
Alexandre Julliard's avatar
Alexandre Julliard committed
620

621 622 623
	TRACE("\n");

	/* HACK TO ACTIVATE OUT SPY */
624
	if (pMallocSpy == (LPVOID)-1) pMallocSpy =(IMallocSpy*)&MallocSpy;
625 626 627 628 629

	if(Malloc32.pSpy) return CO_E_OBJISREG;

        EnterCriticalSection(&IMalloc32_SpyCS);

630
	if (SUCCEEDED(IUnknown_QueryInterface(pMallocSpy, &IID_IMallocSpy, (LPVOID*)&pSpy))) {
631 632 633 634 635 636 637
	    Malloc32.pSpy = pSpy;
	    hres = S_OK;
	}

	LeaveCriticalSection(&IMalloc32_SpyCS);

	return hres;
Alexandre Julliard's avatar
Alexandre Julliard committed
638
}
639

640
/***********************************************************************
641
 *           CoRevokeMallocSpy  [OLE32.@]
642
 *
Austin English's avatar
Austin English committed
643
 * Revokes a previously registered object that receives notifications on memory
644 645 646 647 648 649 650 651 652
 * allocations and frees.
 *
 * PARAMS
 *  pMallocSpy [I] New spy object.
 *
 * RETURNS
 *  Success: S_OK.
 *  Failure: HRESULT code.
 *
653
 * NOTES
654
 *  we can't revoke a malloc spy as long as memory blocks allocated with
655
 *  the spy are active since only the spy knows how to free them
Alexandre Julliard's avatar
Alexandre Julliard committed
656
 */
657 658 659 660 661 662 663 664
HRESULT WINAPI CoRevokeMallocSpy(void)
{
	HRESULT hres = S_OK;
	TRACE("\n");

        EnterCriticalSection(&IMalloc32_SpyCS);

	/* if it's our spy it's time to dump the leaks */
665
	if (Malloc32.pSpy == (IMallocSpy*)&MallocSpy) {
666 667 668 669
	    MallocSpyDumpLeaks();
	}

	if (Malloc32.SpyedAllocationsLeft) {
670
            TRACE("SpyReleasePending with %u allocations left\n", Malloc32.SpyedAllocationsLeft);
671 672 673 674 675 676 677 678 679 680
	    Malloc32.SpyReleasePending = TRUE;
	    hres = E_ACCESSDENIED;
	} else {
	    IMallocSpy_Release(Malloc32.pSpy);
	    Malloc32.pSpy = NULL;
        }
	LeaveCriticalSection(&IMalloc32_SpyCS);

	return S_OK;
}
681 682

/******************************************************************************
683
 *		IsValidInterface	[OLE32.@]
684
 *
685 686 687 688 689
 * Determines whether a pointer is a valid interface.
 *
 * PARAMS
 *  punk [I] Interface to be tested.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
690
 * RETURNS
691
 *  TRUE, if the passed pointer is a valid interface, or FALSE otherwise.
Alexandre Julliard's avatar
Alexandre Julliard committed
692
 */
693 694
BOOL WINAPI IsValidInterface(LPUNKNOWN punk)
{
Alexandre Julliard's avatar
Alexandre Julliard committed
695
	return !(
696
		IsBadReadPtr(punk,4)					||
697 698 699
		IsBadReadPtr(punk->lpVtbl,4)				||
		IsBadReadPtr(punk->lpVtbl->QueryInterface,9)	||
		IsBadCodePtr((FARPROC)punk->lpVtbl->QueryInterface)
Alexandre Julliard's avatar
Alexandre Julliard committed
700 701
	);
}