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