source: trunk/src/ole32/ifs.c@ 22020

Last change on this file since 22020 was 22020, checked in by dmik, 13 years ago

Disable debug fields of RTL_CRITICAL_SECTION_DEBUG.

Odin uses the DebugInfo ptr in CRITICAL_SECTION for its own purposes
which are incompatible with NT. For this reason any NT-style usage must
be disabled.

This in particular fixes debug assertions and crashes in CRYPT32.DLL (due to
misinterpretation of the structure fields) which happened e.g. during playback of
some Flash content.

File size: 16.8 KB
Line 
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "config.h"
22
23#include <ctype.h>
24#include <stdlib.h>
25#include <string.h>
26#include <assert.h>
27
28#include "ole2.h"
29#include "windef.h"
30#include "winbase.h"
31#include "winerror.h"
32
33#include "wine/obj_base.h"
34
35#include "wine/debug.h"
36
37WINE_DEFAULT_DEBUG_CHANNEL(ole);
38
39/******************************************************************************
40 * IMalloc32 implementation
41 *
42 * NOTES
43 * For supporting CoRegisterMallocSpy the IMalloc implementation must know if
44 * a given memory block was allocated with a spy active.
45 *
46 *****************************************************************************/
47/* set the vtable later */
48extern ICOM_VTABLE(IMalloc) VT_IMalloc32;
49
50typedef 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;
59
60/* this is the static object instance */
61_Malloc32 Malloc32 = {&VT_IMalloc32, 0, NULL, 0, 0, NULL, 0};
62
63/* with a spy active all calls from pre to post methods are threadsave */
64static CRITICAL_SECTION IMalloc32_SpyCS = CRITICAL_SECTION_INIT("IMalloc32_SpyCS");
65
66/* resize the old table */
67static int SetSpyedBlockTableLength ( int NewLength )
68{
69 Malloc32.SpyedBlocks = (LPVOID*)LocalReAlloc((HLOCAL)Malloc32.SpyedBlocks, NewLength, GMEM_ZEROINIT);
70 Malloc32.SpyedBlockTableLength = NewLength;
71 return Malloc32.SpyedBlocks ? 1 : 0;
72}
73
74/* add a location to the table */
75static int AddMemoryLocation(LPVOID * pMem)
76{
77 LPVOID * Current;
78
79 /* allocate the table if not already allocated */
80 if (!Malloc32.SpyedBlockTableLength) {
81 if (!SetSpyedBlockTableLength(0x1000)) return 0;
82 }
83
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;
91 }
92 };
93
94 /* put the location in our table */
95 *Current = pMem;
96 Malloc32.SpyedAllocationsLeft++;
97 /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
98 return 1;
99}
100
101static int RemoveMemoryLocation(LPVOID * pMem)
102{
103 LPVOID * Current = Malloc32.SpyedBlocks;
104
105 /* find the location */
106 while (*Current != pMem) {
107 Current++;
108 if (Current >= Malloc32.SpyedBlocks + Malloc32.SpyedBlockTableLength) return 0; /* not found */
109 }
110
111 /* location found */
112 Malloc32.SpyedAllocationsLeft--;
113 /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
114 *Current = NULL;
115 return 1;
116}
117
118/******************************************************************************
119 * IMalloc32_QueryInterface [VTABLE]
120 */
121static HRESULT WINAPI IMalloc_fnQueryInterface(LPMALLOC iface,REFIID refiid,LPVOID *obj) {
122
123 TRACE("(%s,%p)\n",debugstr_guid(refiid),obj);
124
125 if (IsEqualIID(&IID_IUnknown,refiid) || IsEqualIID(&IID_IMalloc,refiid)) {
126 *obj = (LPMALLOC)&Malloc32;
127 return S_OK;
128 }
129 return E_NOINTERFACE;
130}
131
132/******************************************************************************
133 * IMalloc32_AddRefRelease [VTABLE]
134 */
135static ULONG WINAPI IMalloc_fnAddRefRelease (LPMALLOC iface) {
136 return 1;
137}
138
139/******************************************************************************
140 * IMalloc32_Alloc [VTABLE]
141 */
142static LPVOID WINAPI IMalloc_fnAlloc(LPMALLOC iface, DWORD cb) {
143
144 LPVOID addr;
145
146 TRACE("%s: (cb=%ld)\n", __FUNCTION__, cb);
147
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;
155 }
156 }
157
158
159 addr = HeapAlloc(GetProcessHeap(),0,cb);
160
161 if(Malloc32.pSpy) {
162 addr = IMallocSpy_PostAlloc(Malloc32.pSpy, addr);
163 if (addr) AddMemoryLocation(addr);
164 LeaveCriticalSection(&IMalloc32_SpyCS);
165 }
166
167 TRACE("%s: success, memory ptr: %p\n", __FUNCTION__, addr);
168 return addr;
169}
170
171/******************************************************************************
172 * IMalloc32_Realloc [VTABLE]
173 */
174static LPVOID WINAPI IMalloc_fnRealloc(LPMALLOC iface,LPVOID pv,DWORD cb) {
175
176 LPVOID pNewMemory;
177
178 TRACE("%s: (%p,cb=%ld)\n",__FUNCTION__, pv,cb);
179
180 if(Malloc32.pSpy) {
181 LPVOID pRealMemory;
182 BOOL fSpyed;
183
184 EnterCriticalSection(&IMalloc32_SpyCS);
185 fSpyed = RemoveMemoryLocation(pv);
186 cb = IMallocSpy_PreRealloc(Malloc32.pSpy, pv, cb, &pRealMemory, fSpyed);
187
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;
193 }
194
195 if (0==cb) {
196 /* PreRealloc can force Realloc to fail */
197 LeaveCriticalSection(&IMalloc32_SpyCS);
198 return NULL;
199 }
200 pv = pRealMemory;
201 }
202
203 pNewMemory = HeapReAlloc(GetProcessHeap(),0,pv,cb);
204
205 if(Malloc32.pSpy) {
206 pNewMemory = IMallocSpy_PostRealloc(Malloc32.pSpy, pNewMemory, TRUE);
207 if (pNewMemory) AddMemoryLocation(pNewMemory);
208 LeaveCriticalSection(&IMalloc32_SpyCS);
209 }
210
211 TRACE("s%: --(%p)\n", __FUNCTION__, pNewMemory);
212 return pNewMemory;
213}
214
215/******************************************************************************
216 * IMalloc32_Free [VTABLE]
217 */
218static VOID WINAPI IMalloc_fnFree(LPMALLOC iface,LPVOID pv) {
219
220 BOOL fSpyed = 0;
221
222 TRACE("%s: (pv=%p)\n", __FUNCTION__, pv);
223
224 if(Malloc32.pSpy) {
225 EnterCriticalSection(&IMalloc32_SpyCS);
226 fSpyed = RemoveMemoryLocation(pv);
227 pv = IMallocSpy_PreFree(Malloc32.pSpy, pv, fSpyed);
228 }
229
230 HeapFree(GetProcessHeap(),0,pv);
231
232 if(Malloc32.pSpy) {
233 IMallocSpy_PostFree(Malloc32.pSpy, fSpyed);
234
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;
240 }
241
242 LeaveCriticalSection(&IMalloc32_SpyCS);
243 }
244}
245
246/******************************************************************************
247 * IMalloc32_GetSize [VTABLE]
248 *
249 * NOTES
250 * FIXME returns:
251 * win95: size allocated (4 byte boundarys)
252 * win2k: size originally requested !!! (allocated on 8 byte boundarys)
253 */
254static DWORD WINAPI IMalloc_fnGetSize(LPCMALLOC iface,LPVOID pv) {
255
256 DWORD cb;
257 BOOL fSpyed = 0;
258
259 TRACE("%s: (pv=%p)\n", __FUNCTION__, pv);
260
261 if(Malloc32.pSpy) {
262 EnterCriticalSection(&IMalloc32_SpyCS);
263 pv = IMallocSpy_PreGetSize(Malloc32.pSpy, pv, fSpyed);
264 }
265
266 cb = HeapSize(GetProcessHeap(),0,pv);
267
268 if(Malloc32.pSpy) {
269 cb = IMallocSpy_PostGetSize(Malloc32.pSpy, cb, fSpyed);
270 LeaveCriticalSection(&IMalloc32_SpyCS);
271 }
272
273 return cb;
274}
275
276/******************************************************************************
277 * IMalloc32_DidAlloc [VTABLE]
278 */
279static INT WINAPI IMalloc_fnDidAlloc(LPCMALLOC iface,LPVOID pv) {
280
281 BOOL fSpyed = 0;
282 int didAlloc;
283
284 TRACE("%s: (%p)\n", __FUNCTION__, pv);
285
286 if(Malloc32.pSpy) {
287 EnterCriticalSection(&IMalloc32_SpyCS);
288 pv = IMallocSpy_PreDidAlloc(Malloc32.pSpy, pv, fSpyed);
289 }
290
291 didAlloc = -1;
292
293 if(Malloc32.pSpy) {
294 didAlloc = IMallocSpy_PostDidAlloc(Malloc32.pSpy, pv, fSpyed, didAlloc);
295 LeaveCriticalSection(&IMalloc32_SpyCS);
296 }
297 return didAlloc;
298}
299
300/******************************************************************************
301 * IMalloc32_HeapMinimize [VTABLE]
302 */
303static LPVOID WINAPI IMalloc_fnHeapMinimize(LPMALLOC iface) {
304 TRACE("()\n");
305
306 if(Malloc32.pSpy) {
307 EnterCriticalSection(&IMalloc32_SpyCS);
308 IMallocSpy_PreHeapMinimize(Malloc32.pSpy);
309 }
310
311 if(Malloc32.pSpy) {
312 IMallocSpy_PostHeapMinimize(Malloc32.pSpy);
313 LeaveCriticalSection(&IMalloc32_SpyCS);
314 }
315}
316
317#ifdef __WIN32OS2__
318 ICOM_VTABLE(IMalloc) VT_IMalloc32 =
319#else
320static ICOM_VTABLE(IMalloc) VT_IMalloc32 =
321#endif
322{
323 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
324 IMalloc_fnQueryInterface,
325 IMalloc_fnAddRefRelease,
326 IMalloc_fnAddRefRelease,
327 IMalloc_fnAlloc,
328 IMalloc_fnRealloc,
329 IMalloc_fnFree,
330 IMalloc_fnGetSize,
331 IMalloc_fnDidAlloc,
332 IMalloc_fnHeapMinimize
333};
334
335/******************************************************************************
336 * IMallocSpy implementation
337 *****************************************************************************/
338
339/* set the vtable later */
340extern ICOM_VTABLE(IMallocSpy) VT_IMallocSpy;
341
342typedef struct {
343 ICOM_VFIELD(IMallocSpy);
344 DWORD ref;
345} _MallocSpy;
346
347/* this is the static object instance */
348_MallocSpy MallocSpy = {&VT_IMallocSpy, 0};
349
350/******************************************************************************
351 * IMalloc32_QueryInterface [VTABLE]
352 */
353static HRESULT WINAPI IMallocSpy_fnQueryInterface(LPMALLOCSPY iface,REFIID refiid,LPVOID *obj)
354{
355
356 TRACE("(%s,%p)\n",debugstr_guid(refiid),obj);
357
358 if (IsEqualIID(&IID_IUnknown,refiid) || IsEqualIID(&IID_IMallocSpy,refiid)) {
359 *obj = (LPMALLOC)&MallocSpy;
360 return S_OK;
361 }
362 return E_NOINTERFACE;
363}
364
365/******************************************************************************
366 * IMalloc32_AddRef [VTABLE]
367 */
368static ULONG WINAPI IMallocSpy_fnAddRef (LPMALLOCSPY iface)
369{
370
371 ICOM_THIS (_MallocSpy, iface);
372
373 TRACE ("(%p)->(count=%lu)\n", This, This->ref);
374
375 return ++(This->ref);
376}
377
378/******************************************************************************
379 * IMalloc32_AddRelease [VTABLE]
380 *
381 * NOTES
382 * Our MallocSpy is static. If the count reaches 0 we dump the leaks
383 */
384static ULONG WINAPI IMallocSpy_fnRelease (LPMALLOCSPY iface)
385{
386
387 ICOM_THIS (_MallocSpy, iface);
388
389 TRACE ("(%p)->(count=%lu)\n", This, This->ref);
390
391 if (!--(This->ref)) {
392 /* our allocation list MUST be empty here */
393 }
394 return This->ref;
395}
396
397static ULONG WINAPI IMallocSpy_fnPreAlloc(LPMALLOCSPY iface, ULONG cbRequest)
398{
399 ICOM_THIS (_MallocSpy, iface);
400 TRACE ("(%p)->(%lu)\n", This, cbRequest);
401 return cbRequest;
402}
403static PVOID WINAPI IMallocSpy_fnPostAlloc(LPMALLOCSPY iface, void* pActual)
404{
405 ICOM_THIS (_MallocSpy, iface);
406 TRACE ("(%p)->(%p)\n", This, pActual);
407 return pActual;
408}
409
410static PVOID WINAPI IMallocSpy_fnPreFree(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed)
411{
412 ICOM_THIS (_MallocSpy, iface);
413 TRACE ("(%p)->(%p %u)\n", This, pRequest, fSpyed);
414 return pRequest;
415}
416static void WINAPI IMallocSpy_fnPostFree(LPMALLOCSPY iface, BOOL fSpyed)
417{
418 ICOM_THIS (_MallocSpy, iface);
419 TRACE ("(%p)->(%u)\n", This, fSpyed);
420}
421
422static ULONG WINAPI IMallocSpy_fnPreRealloc(LPMALLOCSPY iface, void* pRequest, ULONG cbRequest, void** ppNewRequest, BOOL fSpyed)
423{
424 ICOM_THIS (_MallocSpy, iface);
425 TRACE ("(%p)->(%p %lu %u)\n", This, pRequest, cbRequest, fSpyed);
426 *ppNewRequest = pRequest;
427 return cbRequest;
428}
429
430static PVOID WINAPI IMallocSpy_fnPostRealloc(LPMALLOCSPY iface, void* pActual, BOOL fSpyed)
431{
432 ICOM_THIS (_MallocSpy, iface);
433 TRACE ("(%p)->(%p %u)\n", This, pActual, fSpyed);
434 return pActual;
435}
436
437static PVOID WINAPI IMallocSpy_fnPreGetSize(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed)
438{
439 ICOM_THIS (_MallocSpy, iface);
440 TRACE ("(%p)->(%p %u)\n", This, pRequest, fSpyed);
441 return pRequest;
442}
443
444static ULONG WINAPI IMallocSpy_fnPostGetSize(LPMALLOCSPY iface, ULONG cbActual, BOOL fSpyed)
445{
446 ICOM_THIS (_MallocSpy, iface);
447 TRACE ("(%p)->(%lu %u)\n", This, cbActual, fSpyed);
448 return cbActual;
449}
450
451static PVOID WINAPI IMallocSpy_fnPreDidAlloc(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed)
452{
453 ICOM_THIS (_MallocSpy, iface);
454 TRACE ("(%p)->(%p %u)\n", This, pRequest, fSpyed);
455 return pRequest;
456}
457
458static int WINAPI IMallocSpy_fnPostDidAlloc(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed, int fActual)
459{
460 ICOM_THIS (_MallocSpy, iface);
461 TRACE ("(%p)->(%p %u %u)\n", This, pRequest, fSpyed, fActual);
462 return fActual;
463}
464
465static int WINAPI IMallocSpy_fnPreHeapMinimize(LPMALLOCSPY iface)
466{
467 ICOM_THIS (_MallocSpy, iface);
468 TRACE ("(%p)->()\n", This);
469 return 0;
470}
471
472static int WINAPI IMallocSpy_fnPostHeapMinimize(LPMALLOCSPY iface)
473{
474 ICOM_THIS (_MallocSpy, iface);
475 TRACE ("(%p)->()\n", This);
476 return 0;
477}
478
479static void MallocSpyDumpLeaks() {
480 TRACE("leaks: %lu\n", Malloc32.SpyedAllocationsLeft);
481}
482
483#ifdef __WIN32OS2__
484 ICOM_VTABLE(IMallocSpy) VT_IMallocSpy =
485#else
486static ICOM_VTABLE(IMallocSpy) VT_IMallocSpy =
487#endif
488{
489 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
490 IMallocSpy_fnQueryInterface,
491 IMallocSpy_fnAddRef,
492 IMallocSpy_fnRelease,
493 IMallocSpy_fnPreAlloc,
494 IMallocSpy_fnPostAlloc,
495 IMallocSpy_fnPreFree,
496 IMallocSpy_fnPostFree,
497 IMallocSpy_fnPreRealloc,
498 IMallocSpy_fnPostRealloc,
499 IMallocSpy_fnPreGetSize,
500 IMallocSpy_fnPostGetSize,
501 IMallocSpy_fnPreDidAlloc,
502 IMallocSpy_fnPostDidAlloc,
503 IMallocSpy_fnPreHeapMinimize,
504 IMallocSpy_fnPostHeapMinimize
505};
506
507/******************************************************************************
508 * CoGetMalloc [OLE32.20]
509 *
510 * RETURNS
511 * The win32 IMalloc
512 */
513HRESULT WINAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC *lpMalloc)
514{
515 *lpMalloc = (LPMALLOC)&Malloc32;
516 return S_OK;
517}
518
519/***********************************************************************
520 * CoTaskMemAlloc [OLE32.43]
521 * RETURNS
522 * pointer to newly allocated block
523 */
524LPVOID WINAPI CoTaskMemAlloc(ULONG size)
525{
526 return IMalloc_Alloc((LPMALLOC)&Malloc32,size);
527}
528/***********************************************************************
529 * CoTaskMemFree [OLE32.44]
530 */
531VOID WINAPI CoTaskMemFree(LPVOID ptr)
532{
533 IMalloc_Free((LPMALLOC)&Malloc32, ptr);
534}
535
536/***********************************************************************
537 * CoTaskMemRealloc [OLE32.45]
538 * RETURNS
539 * pointer to newly allocated block
540 */
541LPVOID WINAPI CoTaskMemRealloc(LPVOID pvOld, ULONG size)
542{
543 return IMalloc_Realloc((LPMALLOC)&Malloc32, pvOld, size);
544}
545
546/***********************************************************************
547 * CoRegisterMallocSpy [OLE32.37]
548 *
549 * NOTES
550 * if a mallocspy is already registered, we cant do it again since
551 * only the spy knows, how to free a memory block
552 */
553HRESULT WINAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy)
554{
555 IMallocSpy* pSpy;
556 HRESULT hres = E_INVALIDARG;
557
558 TRACE("\n");
559
560 /* HACK TO ACTIVATE OUT SPY */
561 if (pMallocSpy == (LPVOID)-1) pMallocSpy =(IMallocSpy*)&MallocSpy;
562
563 if(Malloc32.pSpy) return CO_E_OBJISREG;
564
565 EnterCriticalSection(&IMalloc32_SpyCS);
566
567 if (SUCCEEDED(IUnknown_QueryInterface(pMallocSpy, &IID_IMallocSpy, (LPVOID*)&pSpy))) {
568 Malloc32.pSpy = pSpy;
569 hres = S_OK;
570 }
571
572 LeaveCriticalSection(&IMalloc32_SpyCS);
573
574 return hres;
575}
576
577/***********************************************************************
578 * CoRevokeMallocSpy [OLE32.41]
579 *
580 * NOTES
581 * we can't rewoke a malloc spy as long as memory blocks allocated with
582 * the spy are active since only the spy knows how to free them
583 */
584HRESULT WINAPI CoRevokeMallocSpy(void)
585{
586 HRESULT hres = S_OK;
587 TRACE("\n");
588
589 EnterCriticalSection(&IMalloc32_SpyCS);
590
591 /* if it's our spy it's time to dump the leaks */
592 if (Malloc32.pSpy == (IMallocSpy*)&MallocSpy) {
593 MallocSpyDumpLeaks();
594 }
595
596 if (Malloc32.SpyedAllocationsLeft) {
597 TRACE("SpyReleasePending with %lu allocations left\n", Malloc32.SpyedAllocationsLeft);
598 Malloc32.SpyReleasePending = TRUE;
599 hres = E_ACCESSDENIED;
600 } else {
601 IMallocSpy_Release(Malloc32.pSpy);
602 Malloc32.pSpy = NULL;
603 }
604 LeaveCriticalSection(&IMalloc32_SpyCS);
605
606 return S_OK;
607}
608
609/******************************************************************************
610 * IsValidInterface [OLE32.78]
611 *
612 * RETURNS
613 * True, if the passed pointer is a valid interface
614 */
615BOOL WINAPI IsValidInterface(
616 LPUNKNOWN punk /* [in] interface to be tested */
617) {
618 return !(
619 IsBadReadPtr(punk,4) ||
620 IsBadReadPtr(ICOM_VTBL(punk),4) ||
621#ifdef __WIN32OS2__
622 IsBadReadPtr(ICOM_VTBL(punk)->fnQueryInterface,9) ||
623 IsBadCodePtr((FARPROC)ICOM_VTBL(punk)->fnQueryInterface)
624#else
625 IsBadReadPtr(ICOM_VTBL(punk)->QueryInterface,9) ||
626 IsBadCodePtr((FARPROC)ICOM_VTBL(punk)->QueryInterface)
627#endif
628 );
629}
Note: See TracBrowser for help on using the repository browser.