diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index c83e3598401..c8b8430e322 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -126,9 +126,6 @@ HINSTANCE16 COMPOBJ_hInstance = 0; HINSTANCE COMPOBJ_hInstance32 = 0; static int COMPOBJ_Attach = 0; -LPMALLOC16 currentMalloc16=NULL; -LPMALLOC currentMalloc32=NULL; - HTASK16 hETask = 0; WORD Table_ETask[62]; @@ -212,6 +209,35 @@ DWORD WINAPI CoBuildVersion(void) return (rmm<<16)+rup; } +LPMALLOC16 currentMalloc16=NULL; + +/*********************************************************************** + * CoGetMalloc [COMPOBJ.4] + * RETURNS + * The current win16 IMalloc + */ +HRESULT WINAPI CoGetMalloc16( + DWORD dwMemContext, /* [in] unknown */ + LPMALLOC16 * lpMalloc /* [out] current win16 malloc interface */ +) { + if(!currentMalloc16) + currentMalloc16 = IMalloc16_Constructor(); + *lpMalloc = currentMalloc16; + return S_OK; +} + +/*********************************************************************** + * CoCreateStandardMalloc [COMPOBJ.71] + */ +HRESULT WINAPI CoCreateStandardMalloc16(DWORD dwMemContext, + LPMALLOC16 *lpMalloc) +{ + /* FIXME: docu says we shouldn't return the same allocator as in + * CoGetMalloc16 */ + *lpMalloc = IMalloc16_Constructor(); + return S_OK; +} + /****************************************************************************** * CoInitialize [COMPOBJ.2] * Set the win16 IMalloc used for memory management @@ -367,49 +393,6 @@ void WINAPI CoUninitialize(void) } } -/*********************************************************************** - * CoGetMalloc [COMPOBJ.4] - * RETURNS - * The current win16 IMalloc - */ -HRESULT WINAPI CoGetMalloc16( - DWORD dwMemContext, /* [in] unknown */ - LPMALLOC16 * lpMalloc /* [out] current win16 malloc interface */ -) { - if(!currentMalloc16) - currentMalloc16 = IMalloc16_Constructor(); - *lpMalloc = currentMalloc16; - return S_OK; -} - -/****************************************************************************** - * CoGetMalloc [OLE32.20] - * - * RETURNS - * The current win32 IMalloc - */ -HRESULT WINAPI CoGetMalloc( - DWORD dwMemContext, /* [in] unknown */ - LPMALLOC *lpMalloc /* [out] current win32 malloc interface */ -) { - if(!currentMalloc32) - currentMalloc32 = IMalloc_Constructor(); - *lpMalloc = currentMalloc32; - return S_OK; -} - -/*********************************************************************** - * CoCreateStandardMalloc [COMPOBJ.71] - */ -HRESULT WINAPI CoCreateStandardMalloc16(DWORD dwMemContext, - LPMALLOC16 *lpMalloc) -{ - /* FIXME: docu says we shouldn't return the same allocator as in - * CoGetMalloc16 */ - *lpMalloc = IMalloc16_Constructor(); - return S_OK; -} - /****************************************************************************** * CoDisconnectObject [COMPOBJ.15] * CoDisconnectObject [OLE32.8] @@ -1781,55 +1764,6 @@ HRESULT WINAPI CoFileTimeNow( FILETIME *lpFileTime ) /* [out] the current time * return S_OK; } -/*********************************************************************** - * CoTaskMemAlloc (OLE32.43) - * RETURNS - * pointer to newly allocated block - */ -LPVOID WINAPI CoTaskMemAlloc( - ULONG size /* [in] size of memoryblock to be allocated */ -) { - LPMALLOC lpmalloc; - HRESULT ret = CoGetMalloc(0,&lpmalloc); - - if (FAILED(ret)) - return NULL; - - return IMalloc_Alloc(lpmalloc,size); -} -/*********************************************************************** - * CoTaskMemFree (OLE32.44) - */ -VOID WINAPI CoTaskMemFree( - LPVOID ptr /* [in] pointer to be freed */ -) { - LPMALLOC lpmalloc; - HRESULT ret = CoGetMalloc(0,&lpmalloc); - - if (FAILED(ret)) - return; - - IMalloc_Free(lpmalloc, ptr); -} - -/*********************************************************************** - * CoTaskMemRealloc (OLE32.45) - * RETURNS - * pointer to newly allocated block - */ -LPVOID WINAPI CoTaskMemRealloc( - LPVOID pvOld, - ULONG size) /* [in] size of memoryblock to be allocated */ -{ - LPMALLOC lpmalloc; - HRESULT ret = CoGetMalloc(0,&lpmalloc); - - if (FAILED(ret)) - return NULL; - - return IMalloc_Realloc(lpmalloc, pvOld, size); -} - /*********************************************************************** * CoLoadLibrary (OLE32.30) */ diff --git a/dlls/ole32/ifs.c b/dlls/ole32/ifs.c index 452dc00ad67..c92de7e88e5 100644 --- a/dlls/ole32/ifs.c +++ b/dlls/ole32/ifs.c @@ -35,75 +35,7 @@ #include "wine/debug.h" -WINE_DEFAULT_DEBUG_CHANNEL(relay); - -/* --- IUnknown implementation */ - -typedef struct -{ - /* IUnknown fields */ - ICOM_VFIELD(IUnknown); - DWORD ref; -} IUnknownImpl; - -/****************************************************************************** - * IUnknown_AddRef [VTABLE:IUNKNOWN.1] - */ -static ULONG WINAPI IUnknown_fnAddRef(LPUNKNOWN iface) { - ICOM_THIS(IUnknownImpl,iface); - TRACE("(%p)->AddRef()\n",This); - return ++(This->ref); -} - -/****************************************************************************** - * IUnknown_Release [VTABLE:IUNKNOWN.2] - */ -static ULONG WINAPI IUnknown_fnRelease(LPUNKNOWN iface) { - ICOM_THIS(IUnknownImpl,iface); - TRACE("(%p)->Release()\n",This); - if (!--(This->ref)) { - HeapFree(GetProcessHeap(),0,This); - return 0; - } - return This->ref; -} - -/****************************************************************************** - * IUnknown_QueryInterface [VTABLE:IUNKNOWN.0] - */ -static HRESULT WINAPI IUnknown_fnQueryInterface(LPUNKNOWN iface,REFIID refiid,LPVOID *obj) { - ICOM_THIS(IUnknownImpl,iface); - - TRACE("(%p)->QueryInterface(%s,%p)\n",This,debugstr_guid(refiid),obj); - - if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) { - *obj = This; - return 0; - } - return OLE_E_ENUM_NOMORE; -} - -static ICOM_VTABLE(IUnknown) uvt = -{ - ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE - IUnknown_fnQueryInterface, - IUnknown_fnAddRef, - IUnknown_fnRelease -}; - -/****************************************************************************** - * IUnknown_Constructor [INTERNAL] - */ -LPUNKNOWN -IUnknown_Constructor() { - IUnknownImpl* unk; - - unk = (IUnknownImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IUnknownImpl)); - ICOM_VTBL(unk) = &uvt; - unk->ref = 1; - return (LPUNKNOWN)unk; -} - +WINE_DEFAULT_DEBUG_CHANNEL(ole); /* --- IMalloc16 implementation */ @@ -245,57 +177,135 @@ IMalloc16_Constructor() } -/* --- IMalloc32 implementation */ +/****************************************************************************** + * 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 */ +extern ICOM_VTABLE(IMalloc) VT_IMalloc32; -typedef struct -{ - /* IUnknown fields */ +typedef struct { ICOM_VFIELD(IMalloc); - DWORD ref; -} IMalloc32Impl; + 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 */ + int SpyedBlockTableLength; /* size of the table*/ +} _Malloc32; + +/* this is the static object instance */ +_Malloc32 Malloc32 = {&VT_IMalloc32, 0, NULL, 0, 0, NULL, 0}; + +/* with a spy active all calls from pre to post methods are threadsave */ +static CRITICAL_SECTION IMalloc32_SpyCS = CRITICAL_SECTION_INIT("IMalloc32_SpyCS"); + +/* resize the old table */ +static int SetSpyedBlockTableLength ( int NewLength ) +{ + Malloc32.SpyedBlocks = (LPVOID*)LocalReAlloc((HLOCAL)Malloc32.SpyedBlocks, NewLength, GMEM_ZEROINIT); + Malloc32.SpyedBlockTableLength = NewLength; + return Malloc32.SpyedBlocks ? 1 : 0; +} + +/* 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 */ + if (!SetSpyedBlockTableLength( Malloc32.SpyedBlockTableLength + 0x1000 )) return 0; + } + }; + + /* put the location in our table */ + *Current = pMem; + Malloc32.SpyedAllocationsLeft++; + /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/ + return 1; +} + +static int RemoveMemoryLocation(LPVOID * pMem) +{ + LPVOID * Current = Malloc32.SpyedBlocks; + + /* 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; +} /****************************************************************************** - * IMalloc32_QueryInterface [VTABLE] + * IMalloc32_QueryInterface [VTABLE] */ static HRESULT WINAPI IMalloc_fnQueryInterface(LPMALLOC iface,REFIID refiid,LPVOID *obj) { - ICOM_THIS(IMalloc32Impl,iface); - TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj); + TRACE("(%s,%p)\n",debugstr_guid(refiid),obj); - if (IsEqualIID(&IID_IUnknown,refiid) || - IsEqualIID(&IID_IMalloc,refiid)) { - *obj = This; + if (IsEqualIID(&IID_IUnknown,refiid) || IsEqualIID(&IID_IMalloc,refiid)) { + *obj = (LPMALLOC)&Malloc32; return S_OK; } return E_NOINTERFACE; } /****************************************************************************** - * IMalloc32_AddRef [VTABLE] + * IMalloc32_AddRefRelease [VTABLE] */ -static ULONG WINAPI IMalloc_fnAddRef(LPMALLOC iface) { - ICOM_THIS(IMalloc32Impl,iface); - TRACE("(%p)->AddRef()\n",This); - return 1; /* cannot be freed */ +static ULONG WINAPI IMalloc_fnAddRefRelease (LPMALLOC iface) { + return 1; } /****************************************************************************** - * IMalloc32_Release [VTABLE] + * IMalloc32_Alloc [VTABLE] */ -static ULONG WINAPI IMalloc_fnRelease(LPMALLOC iface) { - ICOM_THIS(IMalloc32Impl,iface); - TRACE("(%p)->Release()\n",This); - return 1; /* cannot be freed */ -} +static LPVOID WINAPI IMalloc_fnAlloc(LPMALLOC iface, DWORD cb) { -/****************************************************************************** - * IMalloc32_Alloc [VTABLE] - */ -static LPVOID WINAPI IMalloc_fnAlloc(LPMALLOC iface,DWORD cb) { LPVOID addr; - ICOM_THIS(IMalloc32Impl,iface); + + TRACE("(%ld)\n",cb); + + if(Malloc32.pSpy) { + EnterCriticalSection(&IMalloc32_SpyCS); + cb = IMallocSpy_PreAlloc(Malloc32.pSpy, cb); + if (0==cb) { + /* PreAlloc can force Alloc to fail */ + LeaveCriticalSection(&IMalloc32_SpyCS); + return NULL; + } + } + + addr = HeapAlloc(GetProcessHeap(),0,cb); - TRACE("(%p)->Alloc(%ld) -> %p\n",This,cb,addr); + + if(Malloc32.pSpy) { + addr = IMallocSpy_PostAlloc(Malloc32.pSpy, addr); + if (addr) AddMemoryLocation(addr); + LeaveCriticalSection(&IMalloc32_SpyCS); + } + + TRACE("--(%p)\n",addr); return addr; } @@ -303,76 +313,431 @@ static LPVOID WINAPI IMalloc_fnAlloc(LPMALLOC iface,DWORD cb) { * IMalloc32_Realloc [VTABLE] */ static LPVOID WINAPI IMalloc_fnRealloc(LPMALLOC iface,LPVOID pv,DWORD cb) { - ICOM_THIS(IMalloc32Impl,iface); - TRACE("(%p)->Realloc(%p,%ld)\n",This,pv,cb); - return HeapReAlloc(GetProcessHeap(),0,pv,cb); + + LPVOID pNewMemory; + + TRACE("(%p,%ld)\n",pv,cb); + + 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; + } + + pNewMemory = HeapReAlloc(GetProcessHeap(),0,pv,cb); + + if(Malloc32.pSpy) { + pNewMemory = IMallocSpy_PostRealloc(Malloc32.pSpy, pNewMemory, TRUE); + if (pNewMemory) AddMemoryLocation(pNewMemory); + LeaveCriticalSection(&IMalloc32_SpyCS); + } + + TRACE("--(%p)\n",pNewMemory); + return pNewMemory; } /****************************************************************************** * IMalloc32_Free [VTABLE] */ static VOID WINAPI IMalloc_fnFree(LPMALLOC iface,LPVOID pv) { - ICOM_THIS(IMalloc32Impl,iface); - TRACE("(%p)->Free(%p)\n",This,pv); + + BOOL fSpyed = 0; + + TRACE("(%p)\n",pv); + + if(Malloc32.pSpy) { + EnterCriticalSection(&IMalloc32_SpyCS); + fSpyed = RemoveMemoryLocation(pv); + pv = IMallocSpy_PreFree(Malloc32.pSpy, pv, fSpyed); + } + HeapFree(GetProcessHeap(),0,pv); + + 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); + } } /****************************************************************************** * IMalloc32_GetSize [VTABLE] + * + * NOTES + * FIXME returns: + * win95: size allocated (4 byte boundarys) + * win2k: size originally requested !!! (allocated on 8 byte boundarys) */ static DWORD WINAPI IMalloc_fnGetSize(LPMALLOC iface,LPVOID pv) { - ICOM_CTHIS(IMalloc,iface); - TRACE("(%p)->GetSize(%p)\n",This,pv); - return HeapSize(GetProcessHeap(),0,pv); + + 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; } /****************************************************************************** * IMalloc32_DidAlloc [VTABLE] */ static INT WINAPI IMalloc_fnDidAlloc(LPMALLOC iface,LPVOID pv) { - ICOM_CTHIS(IMalloc32Impl,iface); - TRACE("(%p)->DidAlloc(%p)\n",This,pv); - return -1; + + 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; } /****************************************************************************** * IMalloc32_HeapMinimize [VTABLE] */ static VOID WINAPI IMalloc_fnHeapMinimize(LPMALLOC iface) { - ICOM_THIS(IMalloc32Impl,iface); - TRACE("(%p)->HeapMinimize()\n",This); + TRACE("()\n"); + + if(Malloc32.pSpy) { + EnterCriticalSection(&IMalloc32_SpyCS); + IMallocSpy_PreHeapMinimize(Malloc32.pSpy); + } + + if(Malloc32.pSpy) { + IMallocSpy_PostHeapMinimize(Malloc32.pSpy); + LeaveCriticalSection(&IMalloc32_SpyCS); + } } static ICOM_VTABLE(IMalloc) VT_IMalloc32 = { - ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE - IMalloc_fnQueryInterface, - IMalloc_fnAddRef, - IMalloc_fnRelease, - IMalloc_fnAlloc, - IMalloc_fnRealloc, - IMalloc_fnFree, - IMalloc_fnGetSize, - IMalloc_fnDidAlloc, - IMalloc_fnHeapMinimize + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + IMalloc_fnQueryInterface, + IMalloc_fnAddRefRelease, + IMalloc_fnAddRefRelease, + IMalloc_fnAlloc, + IMalloc_fnRealloc, + IMalloc_fnFree, + IMalloc_fnGetSize, + IMalloc_fnDidAlloc, + IMalloc_fnHeapMinimize }; /****************************************************************************** - * IMalloc32_Constructor [VTABLE] - */ -LPMALLOC -IMalloc_Constructor() { - IMalloc32Impl* This; + * IMallocSpy implementation + *****************************************************************************/ - This = (IMalloc32Impl*)HeapAlloc(GetProcessHeap(),0,sizeof(IMalloc32Impl)); - ICOM_VTBL(This) = &VT_IMalloc32; - This->ref = 1; - return (LPMALLOC)This; +/* set the vtable later */ +extern ICOM_VTABLE(IMallocSpy) VT_IMallocSpy; + +typedef struct { + ICOM_VFIELD(IMallocSpy); + DWORD ref; +} _MallocSpy; + +/* this is the static object instance */ +_MallocSpy MallocSpy = {&VT_IMallocSpy, 0}; + +/****************************************************************************** + * 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)) { + *obj = (LPMALLOC)&MallocSpy; + return S_OK; + } + return E_NOINTERFACE; } -/**************************************************************************** - * API Functions +/****************************************************************************** + * IMalloc32_AddRef [VTABLE] */ +static ULONG WINAPI IMallocSpy_fnAddRef (LPMALLOCSPY iface) +{ + + ICOM_THIS (_MallocSpy, iface); + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + return ++(This->ref); +} + +/****************************************************************************** + * IMalloc32_AddRelease [VTABLE] + * + * NOTES + * Our MallocSpy is static. If the count reaches 0 we dump the leaks + */ +static ULONG WINAPI IMallocSpy_fnRelease (LPMALLOCSPY iface) +{ + + ICOM_THIS (_MallocSpy, iface); + + TRACE ("(%p)->(count=%lu)\n", This, This->ref); + + if (!--(This->ref)) { + /* our allocation list MUST be empty here */ + } + return This->ref; +} + +static ULONG WINAPI IMallocSpy_fnPreAlloc(LPMALLOCSPY iface, ULONG cbRequest) +{ + ICOM_THIS (_MallocSpy, iface); + TRACE ("(%p)->(%lu)\n", This, cbRequest); + return cbRequest; +} +static PVOID WINAPI IMallocSpy_fnPostAlloc(LPMALLOCSPY iface, void* pActual) +{ + ICOM_THIS (_MallocSpy, iface); + TRACE ("(%p)->(%p)\n", This, pActual); + return pActual; +} + +static PVOID WINAPI IMallocSpy_fnPreFree(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed) +{ + ICOM_THIS (_MallocSpy, iface); + TRACE ("(%p)->(%p %u)\n", This, pRequest, fSpyed); + return pRequest; +} +static void WINAPI IMallocSpy_fnPostFree(LPMALLOCSPY iface, BOOL fSpyed) +{ + ICOM_THIS (_MallocSpy, iface); + TRACE ("(%p)->(%u)\n", This, fSpyed); +} + +static ULONG WINAPI IMallocSpy_fnPreRealloc(LPMALLOCSPY iface, void* pRequest, ULONG cbRequest, void** ppNewRequest, BOOL fSpyed) +{ + ICOM_THIS (_MallocSpy, iface); + TRACE ("(%p)->(%p %lu %u)\n", This, pRequest, cbRequest, fSpyed); + *ppNewRequest = pRequest; + return cbRequest; +} + +static PVOID WINAPI IMallocSpy_fnPostRealloc(LPMALLOCSPY iface, void* pActual, BOOL fSpyed) +{ + ICOM_THIS (_MallocSpy, iface); + TRACE ("(%p)->(%p %u)\n", This, pActual, fSpyed); + return pActual; +} + +static PVOID WINAPI IMallocSpy_fnPreGetSize(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed) +{ + ICOM_THIS (_MallocSpy, iface); + TRACE ("(%p)->(%p %u)\n", This, pRequest, fSpyed); + return pRequest; +} + +static ULONG WINAPI IMallocSpy_fnPostGetSize(LPMALLOCSPY iface, ULONG cbActual, BOOL fSpyed) +{ + ICOM_THIS (_MallocSpy, iface); + TRACE ("(%p)->(%lu %u)\n", This, cbActual, fSpyed); + return cbActual; +} + +static PVOID WINAPI IMallocSpy_fnPreDidAlloc(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed) +{ + ICOM_THIS (_MallocSpy, iface); + TRACE ("(%p)->(%p %u)\n", This, pRequest, fSpyed); + return pRequest; +} + +static int WINAPI IMallocSpy_fnPostDidAlloc(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed, int fActual) +{ + ICOM_THIS (_MallocSpy, iface); + TRACE ("(%p)->(%p %u %u)\n", This, pRequest, fSpyed, fActual); + return fActual; +} + +static int WINAPI IMallocSpy_fnPreHeapMinimize(LPMALLOCSPY iface) +{ + ICOM_THIS (_MallocSpy, iface); + TRACE ("(%p)->()\n", This); + return 0; +} + +static int WINAPI IMallocSpy_fnPostHeapMinimize(LPMALLOCSPY iface) +{ + ICOM_THIS (_MallocSpy, iface); + TRACE ("(%p)->()\n", This); + return 0; +} + +static void MallocSpyDumpLeaks() { + TRACE("leaks: %lu\n", Malloc32.SpyedAllocationsLeft); +} + +static ICOM_VTABLE(IMallocSpy) VT_IMallocSpy = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + 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 +}; + +/****************************************************************************** + * CoGetMalloc [OLE32.20] + * + * RETURNS + * The win32 IMalloc + */ +HRESULT WINAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC *lpMalloc) +{ + *lpMalloc = (LPMALLOC)&Malloc32; + return S_OK; +} + +/*********************************************************************** + * CoTaskMemAlloc [OLE32.43] + * RETURNS + * pointer to newly allocated block + */ +LPVOID WINAPI CoTaskMemAlloc(ULONG size) +{ + return IMalloc_Alloc((LPMALLOC)&Malloc32,size); +} +/*********************************************************************** + * CoTaskMemFree [OLE32.44] + */ +VOID WINAPI CoTaskMemFree(LPVOID ptr) +{ + IMalloc_Free((LPMALLOC)&Malloc32, ptr); +} + +/*********************************************************************** + * CoTaskMemRealloc [OLE32.45] + * RETURNS + * pointer to newly allocated block + */ +LPVOID WINAPI CoTaskMemRealloc(LPVOID pvOld, ULONG size) +{ + return IMalloc_Realloc((LPMALLOC)&Malloc32, pvOld, size); +} + +/*********************************************************************** + * CoRegisterMallocSpy [OLE32.37] + * + * NOTES + * if a mallocspy is already registered, we cant do it again since + * only the spy knows, how to free a memory block + */ +HRESULT WINAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy) +{ + IMallocSpy* pSpy; + HRESULT hres = E_INVALIDARG; + + TRACE("\n"); + + /* HACK TO ACTIVATE OUT SPY */ + if (pMallocSpy == (LPVOID)-1) pMallocSpy =(IMallocSpy*)&MallocSpy; + + if(Malloc32.pSpy) return CO_E_OBJISREG; + + EnterCriticalSection(&IMalloc32_SpyCS); + + if (SUCCEEDED(IUnknown_QueryInterface(pMallocSpy, &IID_IMallocSpy, (LPVOID*)&pSpy))) { + Malloc32.pSpy = pSpy; + hres = S_OK; + } + + LeaveCriticalSection(&IMalloc32_SpyCS); + + return hres; +} + +/*********************************************************************** + * CoRevokeMallocSpy [OLE32.41] + * + * NOTES + * we can't rewoke a malloc spy as long as memory blocks allocated with + * the spy are active since only the spy knows how to free them + */ +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 */ + if (Malloc32.pSpy == (IMallocSpy*)&MallocSpy) { + MallocSpyDumpLeaks(); + } + + if (Malloc32.SpyedAllocationsLeft) { + TRACE("SpyReleasePending with %lu allocations left\n", Malloc32.SpyedAllocationsLeft); + Malloc32.SpyReleasePending = TRUE; + hres = E_ACCESSDENIED; + } else { + IMallocSpy_Release(Malloc32.pSpy); + Malloc32.pSpy = NULL; + } + LeaveCriticalSection(&IMalloc32_SpyCS); + + return S_OK; +} /****************************************************************************** * IsValidInterface [OLE32.78] diff --git a/dlls/ole32/ifs.h b/dlls/ole32/ifs.h index abf2c26b885..8d6fe2cd054 100644 --- a/dlls/ole32/ifs.h +++ b/dlls/ole32/ifs.h @@ -56,6 +56,5 @@ ICOM_DEFINE(IMalloc16,IUnknown) /**********************************************************************/ extern LPMALLOC16 IMalloc16_Constructor(); -extern LPMALLOC IMalloc_Constructor(); #endif /* __WINE_OLE_IFS_H */ diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 8d1bfd9182b..8b83bcd87ad 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -36,11 +36,11 @@ init OLE32_DllEntryPoint 34 stdcall CoMarshalInterface(ptr ptr ptr long ptr long) CoMarshalInterface 35 stub CoQueryReleaseObject 36 stdcall CoRegisterClassObject(ptr ptr long long ptr) CoRegisterClassObject - 37 stub CoRegisterMallocSpy # stdcall (ptr) return 0,ERR_NOTIMPLEMENTED + 37 stdcall CoRegisterMallocSpy (ptr) CoRegisterMallocSpy 38 stdcall CoRegisterMessageFilter(ptr ptr) CoRegisterMessageFilter 39 stub CoReleaseMarshalData # stdcall (ptr) return 0,ERR_NOTIMPLEMENTED 40 stdcall CoRevokeClassObject(long) CoRevokeClassObject - 41 stub CoRevokeMallocSpy # stdcall () return 0,ERR_NOTIMPLEMENTED + 41 stdcall CoRevokeMallocSpy() CoRevokeMallocSpy 42 stdcall CoSetState(ptr) CoSetState 43 stdcall CoTaskMemAlloc(long) CoTaskMemAlloc 44 stdcall CoTaskMemFree(ptr) CoTaskMemFree diff --git a/dlls/ole32/ole32_main.c b/dlls/ole32/ole32_main.c index 7ebe5497782..5e9043a7fae 100644 --- a/dlls/ole32/ole32_main.c +++ b/dlls/ole32/ole32_main.c @@ -22,6 +22,7 @@ #include "winerror.h" #include "ole32_main.h" #include "wine/debug.h" +#include "wine/obj_misc.h" /* FIXME: CoRegisterMallocSpy */ WINE_DEFAULT_DEBUG_CHANNEL(ole); @@ -39,9 +40,11 @@ BOOL WINAPI OLE32_DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImp case DLL_PROCESS_ATTACH: OLE32_hInstance = hinstDLL; COMPOBJ_InitProcess(); + if (TRACE_ON(ole)) CoRegisterMallocSpy((LPVOID)-1); break; case DLL_PROCESS_DETACH: + if (TRACE_ON(ole)) CoRevokeMallocSpy(); COMPOBJ_UninitProcess(); OLE32_hInstance = 0; break; diff --git a/include/wine/obj_misc.h b/include/wine/obj_misc.h index 19719f3bc84..13c8a97c015 100644 --- a/include/wine/obj_misc.h +++ b/include/wine/obj_misc.h @@ -24,6 +24,8 @@ #ifndef __WINE_WINE_OBJ_MISC_H #define __WINE_WINE_OBJ_MISC_H +#include "wine/obj_base.h" + #ifdef __cplusplus extern "C" { #endif /* defined(__cplusplus) */ @@ -103,7 +105,7 @@ ICOM_DEFINE(IEnumUnknown,IUnknown) #define ICOM_INTERFACE IMallocSpy #define IMallocSpy_METHODS \ ICOM_METHOD1 (ULONG,PreAlloc, ULONG,cbRequest) \ - ICOM_VMETHOD1( PostAlloc, void*,pActual) \ + ICOM_METHOD1 (PVOID,PostAlloc, void*,pActual) \ ICOM_METHOD2 (PVOID,PreFree, void*,pRequest, BOOL,fSpyed) \ ICOM_VMETHOD1( PostFree, BOOL,fSpyed) \ ICOM_METHOD4 (ULONG,PreRealloc, void*,pRequest, ULONG,cbRequest, void**,ppNewRequest, BOOL,fSpyed) \