HTTP_DealWithProxy: Only add http:// to proxy string when needed.
[wine/multimedia.git] / dlls / ole32 / ifs.c
blobf4e7c48c91b92f171ecab143c8e727eec68d3435
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 <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "ole2.h"
33 #include "winerror.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;
65 static CRITICAL_SECTION_DEBUG critsect_debug =
67 0, 0, &IMalloc32_SpyCS,
68 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
69 0, 0, { 0, (DWORD)(__FILE__ ": IMalloc32_SpyCS") }
71 static CRITICAL_SECTION IMalloc32_SpyCS = { &critsect_debug, -1, 0, 0, 0, 0 };
73 /* resize the old table */
74 static int SetSpyedBlockTableLength ( int NewLength )
76 if (!Malloc32.SpyedBlocks) Malloc32.SpyedBlocks = (LPVOID*)LocalAlloc(NewLength, GMEM_ZEROINIT);
77 else Malloc32.SpyedBlocks = (LPVOID*)LocalReAlloc((HLOCAL)Malloc32.SpyedBlocks, NewLength, GMEM_ZEROINIT);
78 Malloc32.SpyedBlockTableLength = NewLength;
79 return Malloc32.SpyedBlocks ? 1 : 0;
82 /* add a location to the table */
83 static int AddMemoryLocation(LPVOID * pMem)
85 LPVOID * Current;
87 /* allocate the table if not already allocated */
88 if (!Malloc32.SpyedBlockTableLength) {
89 if (!SetSpyedBlockTableLength(0x1000)) return 0;
92 /* find a free location */
93 Current = Malloc32.SpyedBlocks;
94 while (*Current) {
95 Current++;
96 if (Current >= Malloc32.SpyedBlocks + Malloc32.SpyedBlockTableLength) {
97 /* no more space in table, grow it */
98 if (!SetSpyedBlockTableLength( Malloc32.SpyedBlockTableLength + 0x1000 )) return 0;
102 /* put the location in our table */
103 *Current = pMem;
104 Malloc32.SpyedAllocationsLeft++;
105 /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
106 return 1;
109 static int RemoveMemoryLocation(LPVOID * pMem)
111 LPVOID * Current;
113 /* allocate the table if not already allocated */
114 if (!Malloc32.SpyedBlockTableLength) {
115 if (!SetSpyedBlockTableLength(0x1000)) return 0;
118 Current = Malloc32.SpyedBlocks;
120 /* find the location */
121 while (*Current != pMem) {
122 Current++;
123 if (Current >= Malloc32.SpyedBlocks + Malloc32.SpyedBlockTableLength) return 0; /* not found */
126 /* location found */
127 Malloc32.SpyedAllocationsLeft--;
128 /*TRACE("%lu\n",Malloc32.SpyedAllocationsLeft);*/
129 *Current = NULL;
130 return 1;
133 /******************************************************************************
134 * IMalloc32_QueryInterface [VTABLE]
136 static HRESULT WINAPI IMalloc_fnQueryInterface(LPMALLOC iface,REFIID refiid,LPVOID *obj) {
138 TRACE("(%s,%p)\n",debugstr_guid(refiid),obj);
140 if (IsEqualIID(&IID_IUnknown,refiid) || IsEqualIID(&IID_IMalloc,refiid)) {
141 *obj = (LPMALLOC)&Malloc32;
142 return S_OK;
144 return E_NOINTERFACE;
147 /******************************************************************************
148 * IMalloc32_AddRefRelease [VTABLE]
150 static ULONG WINAPI IMalloc_fnAddRefRelease (LPMALLOC iface) {
151 return 1;
154 /******************************************************************************
155 * IMalloc32_Alloc [VTABLE]
157 static LPVOID WINAPI IMalloc_fnAlloc(LPMALLOC iface, DWORD cb) {
159 LPVOID addr;
161 TRACE("(%ld)\n",cb);
163 if(Malloc32.pSpy) {
164 DWORD preAllocResult;
166 EnterCriticalSection(&IMalloc32_SpyCS);
167 preAllocResult = IMallocSpy_PreAlloc(Malloc32.pSpy, cb);
168 if ((cb != 0) && (preAllocResult == 0)) {
169 /* PreAlloc can force Alloc to fail, but not if cb == 0 */
170 TRACE("returning null\n");
171 LeaveCriticalSection(&IMalloc32_SpyCS);
172 return NULL;
176 addr = HeapAlloc(GetProcessHeap(),0,cb);
178 if(Malloc32.pSpy) {
179 addr = IMallocSpy_PostAlloc(Malloc32.pSpy, addr);
180 if (addr) AddMemoryLocation(addr);
181 LeaveCriticalSection(&IMalloc32_SpyCS);
184 TRACE("--(%p)\n",addr);
185 return addr;
188 /******************************************************************************
189 * IMalloc32_Realloc [VTABLE]
191 static LPVOID WINAPI IMalloc_fnRealloc(LPMALLOC iface,LPVOID pv,DWORD cb) {
193 LPVOID pNewMemory;
195 TRACE("(%p,%ld)\n",pv,cb);
197 if(Malloc32.pSpy) {
198 LPVOID pRealMemory;
199 BOOL fSpyed;
201 EnterCriticalSection(&IMalloc32_SpyCS);
202 fSpyed = RemoveMemoryLocation(pv);
203 cb = IMallocSpy_PreRealloc(Malloc32.pSpy, pv, cb, &pRealMemory, fSpyed);
205 /* check if can release the spy */
206 if(Malloc32.SpyReleasePending && !Malloc32.SpyedAllocationsLeft) {
207 IMallocSpy_Release(Malloc32.pSpy);
208 Malloc32.SpyReleasePending = FALSE;
209 Malloc32.pSpy = NULL;
212 if (0==cb) {
213 /* PreRealloc can force Realloc to fail */
214 LeaveCriticalSection(&IMalloc32_SpyCS);
215 return NULL;
217 pv = pRealMemory;
220 if (!pv) pNewMemory = HeapAlloc(GetProcessHeap(),0,cb);
221 else if (cb) pNewMemory = HeapReAlloc(GetProcessHeap(),0,pv,cb);
222 else {
223 HeapFree(GetProcessHeap(),0,pv);
224 pNewMemory = NULL;
227 if(Malloc32.pSpy) {
228 pNewMemory = IMallocSpy_PostRealloc(Malloc32.pSpy, pNewMemory, TRUE);
229 if (pNewMemory) AddMemoryLocation(pNewMemory);
230 LeaveCriticalSection(&IMalloc32_SpyCS);
233 TRACE("--(%p)\n",pNewMemory);
234 return pNewMemory;
237 /******************************************************************************
238 * IMalloc32_Free [VTABLE]
240 static VOID WINAPI IMalloc_fnFree(LPMALLOC iface,LPVOID pv) {
242 BOOL fSpyed = 0;
244 TRACE("(%p)\n",pv);
246 if(Malloc32.pSpy) {
247 EnterCriticalSection(&IMalloc32_SpyCS);
248 fSpyed = RemoveMemoryLocation(pv);
249 pv = IMallocSpy_PreFree(Malloc32.pSpy, pv, fSpyed);
252 HeapFree(GetProcessHeap(),0,pv);
254 if(Malloc32.pSpy) {
255 IMallocSpy_PostFree(Malloc32.pSpy, fSpyed);
257 /* check if can release the spy */
258 if(Malloc32.SpyReleasePending && !Malloc32.SpyedAllocationsLeft) {
259 IMallocSpy_Release(Malloc32.pSpy);
260 Malloc32.SpyReleasePending = FALSE;
261 Malloc32.pSpy = NULL;
264 LeaveCriticalSection(&IMalloc32_SpyCS);
268 /******************************************************************************
269 * IMalloc32_GetSize [VTABLE]
271 * NOTES
272 * FIXME returns:
273 * win95: size allocated (4 byte boundarys)
274 * win2k: size originally requested !!! (allocated on 8 byte boundarys)
276 static DWORD WINAPI IMalloc_fnGetSize(LPMALLOC iface,LPVOID pv) {
278 DWORD cb;
279 BOOL fSpyed = 0;
281 TRACE("(%p)\n",pv);
283 if(Malloc32.pSpy) {
284 EnterCriticalSection(&IMalloc32_SpyCS);
285 pv = IMallocSpy_PreGetSize(Malloc32.pSpy, pv, fSpyed);
288 cb = HeapSize(GetProcessHeap(),0,pv);
290 if(Malloc32.pSpy) {
291 cb = IMallocSpy_PostGetSize(Malloc32.pSpy, cb, fSpyed);
292 LeaveCriticalSection(&IMalloc32_SpyCS);
295 return cb;
298 /******************************************************************************
299 * IMalloc32_DidAlloc [VTABLE]
301 static INT WINAPI IMalloc_fnDidAlloc(LPMALLOC iface,LPVOID pv) {
303 BOOL fSpyed = 0;
304 int didAlloc;
306 TRACE("(%p)\n",pv);
308 if(Malloc32.pSpy) {
309 EnterCriticalSection(&IMalloc32_SpyCS);
310 pv = IMallocSpy_PreDidAlloc(Malloc32.pSpy, pv, fSpyed);
313 didAlloc = -1;
315 if(Malloc32.pSpy) {
316 didAlloc = IMallocSpy_PostDidAlloc(Malloc32.pSpy, pv, fSpyed, didAlloc);
317 LeaveCriticalSection(&IMalloc32_SpyCS);
319 return didAlloc;
322 /******************************************************************************
323 * IMalloc32_HeapMinimize [VTABLE]
325 static VOID WINAPI IMalloc_fnHeapMinimize(LPMALLOC iface) {
326 TRACE("()\n");
328 if(Malloc32.pSpy) {
329 EnterCriticalSection(&IMalloc32_SpyCS);
330 IMallocSpy_PreHeapMinimize(Malloc32.pSpy);
333 if(Malloc32.pSpy) {
334 IMallocSpy_PostHeapMinimize(Malloc32.pSpy);
335 LeaveCriticalSection(&IMalloc32_SpyCS);
339 static ICOM_VTABLE(IMalloc) VT_IMalloc32 =
341 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
342 IMalloc_fnQueryInterface,
343 IMalloc_fnAddRefRelease,
344 IMalloc_fnAddRefRelease,
345 IMalloc_fnAlloc,
346 IMalloc_fnRealloc,
347 IMalloc_fnFree,
348 IMalloc_fnGetSize,
349 IMalloc_fnDidAlloc,
350 IMalloc_fnHeapMinimize
353 /******************************************************************************
354 * IMallocSpy implementation
355 *****************************************************************************/
357 /* set the vtable later */
358 extern ICOM_VTABLE(IMallocSpy) VT_IMallocSpy;
360 typedef struct {
361 ICOM_VFIELD(IMallocSpy);
362 DWORD ref;
363 } _MallocSpy;
365 /* this is the static object instance */
366 _MallocSpy MallocSpy = {&VT_IMallocSpy, 0};
368 /******************************************************************************
369 * IMalloc32_QueryInterface [VTABLE]
371 static HRESULT WINAPI IMallocSpy_fnQueryInterface(LPMALLOCSPY iface,REFIID refiid,LPVOID *obj)
374 TRACE("(%s,%p)\n",debugstr_guid(refiid),obj);
376 if (IsEqualIID(&IID_IUnknown,refiid) || IsEqualIID(&IID_IMallocSpy,refiid)) {
377 *obj = (LPMALLOC)&MallocSpy;
378 return S_OK;
380 return E_NOINTERFACE;
383 /******************************************************************************
384 * IMalloc32_AddRef [VTABLE]
386 static ULONG WINAPI IMallocSpy_fnAddRef (LPMALLOCSPY iface)
389 ICOM_THIS (_MallocSpy, iface);
391 TRACE ("(%p)->(count=%lu)\n", This, This->ref);
393 return ++(This->ref);
396 /******************************************************************************
397 * IMalloc32_AddRelease [VTABLE]
399 * NOTES
400 * Our MallocSpy is static. If the count reaches 0 we dump the leaks
402 static ULONG WINAPI IMallocSpy_fnRelease (LPMALLOCSPY iface)
405 ICOM_THIS (_MallocSpy, iface);
407 TRACE ("(%p)->(count=%lu)\n", This, This->ref);
409 if (!--(This->ref)) {
410 /* our allocation list MUST be empty here */
412 return This->ref;
415 static ULONG WINAPI IMallocSpy_fnPreAlloc(LPMALLOCSPY iface, ULONG cbRequest)
417 ICOM_THIS (_MallocSpy, iface);
418 TRACE ("(%p)->(%lu)\n", This, cbRequest);
419 return cbRequest;
421 static PVOID WINAPI IMallocSpy_fnPostAlloc(LPMALLOCSPY iface, void* pActual)
423 ICOM_THIS (_MallocSpy, iface);
424 TRACE ("(%p)->(%p)\n", This, pActual);
425 return pActual;
428 static PVOID WINAPI IMallocSpy_fnPreFree(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed)
430 ICOM_THIS (_MallocSpy, iface);
431 TRACE ("(%p)->(%p %u)\n", This, pRequest, fSpyed);
432 return pRequest;
434 static void WINAPI IMallocSpy_fnPostFree(LPMALLOCSPY iface, BOOL fSpyed)
436 ICOM_THIS (_MallocSpy, iface);
437 TRACE ("(%p)->(%u)\n", This, fSpyed);
440 static ULONG WINAPI IMallocSpy_fnPreRealloc(LPMALLOCSPY iface, void* pRequest, ULONG cbRequest, void** ppNewRequest, BOOL fSpyed)
442 ICOM_THIS (_MallocSpy, iface);
443 TRACE ("(%p)->(%p %lu %u)\n", This, pRequest, cbRequest, fSpyed);
444 *ppNewRequest = pRequest;
445 return cbRequest;
448 static PVOID WINAPI IMallocSpy_fnPostRealloc(LPMALLOCSPY iface, void* pActual, BOOL fSpyed)
450 ICOM_THIS (_MallocSpy, iface);
451 TRACE ("(%p)->(%p %u)\n", This, pActual, fSpyed);
452 return pActual;
455 static PVOID WINAPI IMallocSpy_fnPreGetSize(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed)
457 ICOM_THIS (_MallocSpy, iface);
458 TRACE ("(%p)->(%p %u)\n", This, pRequest, fSpyed);
459 return pRequest;
462 static ULONG WINAPI IMallocSpy_fnPostGetSize(LPMALLOCSPY iface, ULONG cbActual, BOOL fSpyed)
464 ICOM_THIS (_MallocSpy, iface);
465 TRACE ("(%p)->(%lu %u)\n", This, cbActual, fSpyed);
466 return cbActual;
469 static PVOID WINAPI IMallocSpy_fnPreDidAlloc(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed)
471 ICOM_THIS (_MallocSpy, iface);
472 TRACE ("(%p)->(%p %u)\n", This, pRequest, fSpyed);
473 return pRequest;
476 static int WINAPI IMallocSpy_fnPostDidAlloc(LPMALLOCSPY iface, void* pRequest, BOOL fSpyed, int fActual)
478 ICOM_THIS (_MallocSpy, iface);
479 TRACE ("(%p)->(%p %u %u)\n", This, pRequest, fSpyed, fActual);
480 return fActual;
483 static void WINAPI IMallocSpy_fnPreHeapMinimize(LPMALLOCSPY iface)
485 ICOM_THIS (_MallocSpy, iface);
486 TRACE ("(%p)->()\n", This);
489 static void WINAPI IMallocSpy_fnPostHeapMinimize(LPMALLOCSPY iface)
491 ICOM_THIS (_MallocSpy, iface);
492 TRACE ("(%p)->()\n", This);
495 static void MallocSpyDumpLeaks() {
496 TRACE("leaks: %lu\n", Malloc32.SpyedAllocationsLeft);
499 static ICOM_VTABLE(IMallocSpy) VT_IMallocSpy =
501 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
502 IMallocSpy_fnQueryInterface,
503 IMallocSpy_fnAddRef,
504 IMallocSpy_fnRelease,
505 IMallocSpy_fnPreAlloc,
506 IMallocSpy_fnPostAlloc,
507 IMallocSpy_fnPreFree,
508 IMallocSpy_fnPostFree,
509 IMallocSpy_fnPreRealloc,
510 IMallocSpy_fnPostRealloc,
511 IMallocSpy_fnPreGetSize,
512 IMallocSpy_fnPostGetSize,
513 IMallocSpy_fnPreDidAlloc,
514 IMallocSpy_fnPostDidAlloc,
515 IMallocSpy_fnPreHeapMinimize,
516 IMallocSpy_fnPostHeapMinimize
519 /******************************************************************************
520 * CoGetMalloc [OLE32.@]
522 * RETURNS
523 * The win32 IMalloc
525 HRESULT WINAPI CoGetMalloc(DWORD dwMemContext, LPMALLOC *lpMalloc)
527 *lpMalloc = (LPMALLOC)&Malloc32;
528 return S_OK;
531 /***********************************************************************
532 * CoTaskMemAlloc [OLE32.@]
533 * RETURNS
534 * pointer to newly allocated block
536 LPVOID WINAPI CoTaskMemAlloc(ULONG size)
538 return IMalloc_Alloc((LPMALLOC)&Malloc32,size);
540 /***********************************************************************
541 * CoTaskMemFree [OLE32.@]
543 VOID WINAPI CoTaskMemFree(LPVOID ptr)
545 IMalloc_Free((LPMALLOC)&Malloc32, ptr);
548 /***********************************************************************
549 * CoTaskMemRealloc [OLE32.@]
550 * RETURNS
551 * pointer to newly allocated block
553 LPVOID WINAPI CoTaskMemRealloc(LPVOID pvOld, ULONG size)
555 return IMalloc_Realloc((LPMALLOC)&Malloc32, pvOld, size);
558 /***********************************************************************
559 * CoRegisterMallocSpy [OLE32.@]
561 * NOTES
562 * if a mallocspy is already registered, we cant do it again since
563 * only the spy knows, how to free a memory block
565 HRESULT WINAPI CoRegisterMallocSpy(LPMALLOCSPY pMallocSpy)
567 IMallocSpy* pSpy;
568 HRESULT hres = E_INVALIDARG;
570 TRACE("\n");
572 /* HACK TO ACTIVATE OUT SPY */
573 if (pMallocSpy == (LPVOID)-1) pMallocSpy =(IMallocSpy*)&MallocSpy;
575 if(Malloc32.pSpy) return CO_E_OBJISREG;
577 EnterCriticalSection(&IMalloc32_SpyCS);
579 if (SUCCEEDED(IUnknown_QueryInterface(pMallocSpy, &IID_IMallocSpy, (LPVOID*)&pSpy))) {
580 Malloc32.pSpy = pSpy;
581 hres = S_OK;
584 LeaveCriticalSection(&IMalloc32_SpyCS);
586 return hres;
589 /***********************************************************************
590 * CoRevokeMallocSpy [OLE32.@]
592 * NOTES
593 * we can't rewoke a malloc spy as long as memory blocks allocated with
594 * the spy are active since only the spy knows how to free them
596 HRESULT WINAPI CoRevokeMallocSpy(void)
598 HRESULT hres = S_OK;
599 TRACE("\n");
601 EnterCriticalSection(&IMalloc32_SpyCS);
603 /* if it's our spy it's time to dump the leaks */
604 if (Malloc32.pSpy == (IMallocSpy*)&MallocSpy) {
605 MallocSpyDumpLeaks();
608 if (Malloc32.SpyedAllocationsLeft) {
609 TRACE("SpyReleasePending with %lu allocations left\n", Malloc32.SpyedAllocationsLeft);
610 Malloc32.SpyReleasePending = TRUE;
611 hres = E_ACCESSDENIED;
612 } else {
613 IMallocSpy_Release(Malloc32.pSpy);
614 Malloc32.pSpy = NULL;
616 LeaveCriticalSection(&IMalloc32_SpyCS);
618 return S_OK;
621 /******************************************************************************
622 * IsValidInterface [OLE32.@]
624 * RETURNS
625 * True, if the passed pointer is a valid interface
627 BOOL WINAPI IsValidInterface(
628 LPUNKNOWN punk /* [in] interface to be tested */
630 return !(
631 IsBadReadPtr(punk,4) ||
632 IsBadReadPtr(punk->lpVtbl,4) ||
633 IsBadReadPtr(punk->lpVtbl->QueryInterface,9) ||
634 IsBadCodePtr((FARPROC)punk->lpVtbl->QueryInterface)