No longer directly accessing debuggee memory.
[wine] / dlls / shell32 / shellole.c
1 /*
2  *      handling of SHELL32.DLL OLE-Objects
3  *
4  *      Copyright 1997  Marcus Meissner
5  *      Copyright 1998  Juergen Schmied  <juergen.schmied@metronet.de>
6  *
7  */
8
9 #include <stdlib.h>
10 #include <string.h>
11
12 #include "wine/obj_base.h"
13 #include "wine/obj_shelllink.h"
14 #include "wine/obj_shellfolder.h"
15 #include "wine/obj_shellbrowser.h"
16 #include "wine/obj_contextmenu.h"
17 #include "wine/obj_shellextinit.h"
18 #include "wine/obj_extracticon.h"
19
20 #include "shlguid.h"
21 #include "winversion.h"
22 #include "winreg.h"
23 #include "winerror.h"
24 #include "debugtools.h"
25
26 #include "shell32_main.h"
27
28 DEFAULT_DEBUG_CHANNEL(shell)
29
30 DWORD WINAPI SHCLSIDFromStringA (LPSTR clsid, CLSID *id);
31 extern IShellFolder * IShellFolder_Constructor(
32         IShellFolder * psf,
33         LPITEMIDLIST pidl);
34 extern HRESULT IFSFolder_Constructor(
35         IUnknown * pUnkOuter,
36         REFIID riid,
37         LPVOID * ppv);
38
39 /*************************************************************************
40  * SHCoCreateInstance [SHELL32.102]
41  * 
42  * NOTES
43  *     exported by ordinal
44  */
45 LRESULT WINAPI SHCoCreateInstance(
46         LPSTR aclsid,
47         REFCLSID clsid,
48         IUnknown * unknownouter,
49         REFIID refiid,
50         LPVOID *ppv)
51 {
52         DWORD   hres;
53         IID     iid;
54         CLSID * myclsid = (CLSID*)clsid;
55         
56         if (!clsid)
57         {
58           if (!aclsid) return REGDB_E_CLASSNOTREG;
59           SHCLSIDFromStringA(aclsid, &iid);
60           myclsid = &iid;
61         }
62
63         TRACE("(%p,\n\tCLSID:\t%s, unk:%p\n\tIID:\t%s,%p)\n",
64                 aclsid,debugstr_guid(myclsid),unknownouter,debugstr_guid(refiid),ppv);
65
66         if IsEqualCLSID(myclsid, &CLSID_ShellFSFolder)
67         {
68           hres = IFSFolder_Constructor(unknownouter, refiid, ppv);
69         }
70         else
71         {
72           hres = CoCreateInstance(myclsid, unknownouter, CLSCTX_INPROC_SERVER, refiid, ppv);
73         }
74         
75         if(hres!=S_OK)
76         {
77           ERR("failed (0x%08lx) to create \n\tCLSID:\t%s\n\tIID:\t%s\n",
78               hres, debugstr_guid(myclsid), debugstr_guid(refiid));
79           ERR("class not found in registry\n");
80         }
81
82         TRACE("-- instance: %p\n",*ppv);
83         return hres;
84 }
85
86 /*************************************************************************
87  * SHELL32_DllGetClassObject   [SHELL32.128]
88  */
89 HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
90 {       HRESULT hres = E_OUTOFMEMORY;
91         LPCLASSFACTORY lpclf;
92
93         TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
94         
95         *ppv = NULL;
96
97         if(IsEqualCLSID(rclsid, &CLSID_ShellDesktop)|| 
98            IsEqualCLSID(rclsid, &CLSID_ShellLink))
99         {
100           lpclf = IClassFactory_Constructor( rclsid );
101
102           if(lpclf) 
103           {
104             hres = IClassFactory_QueryInterface(lpclf,iid, ppv);
105             IClassFactory_Release(lpclf);
106           }
107         }
108         else
109         {
110           WARN("-- CLSID not found\n");
111           hres = CLASS_E_CLASSNOTAVAILABLE;
112         }
113         TRACE("-- pointer to class factory: %p\n",*ppv);
114         return hres;
115 }
116
117 /*************************************************************************
118  * SHCLSIDFromString                            [SHELL32.147]
119  *
120  * NOTES
121  *     exported by ordinal
122  */
123 DWORD WINAPI SHCLSIDFromStringA (LPSTR clsid, CLSID *id)
124 {
125         TRACE("(%p(%s) %p)\n", clsid, clsid, id);
126         return CLSIDFromString16(clsid, id); 
127 }
128 DWORD WINAPI SHCLSIDFromStringW (LPWSTR clsid, CLSID *id)
129 {
130         TRACE("(%p(%s) %p)\n", clsid, debugstr_w(clsid), id);
131         return CLSIDFromString(clsid, id); 
132 }
133 DWORD WINAPI SHCLSIDFromStringAW (LPVOID clsid, CLSID *id)
134 {
135         if (VERSION_OsIsUnicode())
136           return SHCLSIDFromStringW (clsid, id);
137         return SHCLSIDFromStringA (clsid, id);
138 }
139
140 /*************************************************************************
141  *                       SHGetMalloc                    [SHELL32.220]
142  * returns the interface to shell malloc.
143  *
144  * [SDK header win95/shlobj.h:
145  * equivalent to:  #define SHGetMalloc(ppmem)   CoGetMalloc(MEMCTX_TASK, ppmem)
146  * ]
147  * What we are currently doing is not very wrong, since we always use the same
148  * heap (ProcessHeap).
149  */
150 DWORD WINAPI SHGetMalloc(LPMALLOC *lpmal) 
151 {
152         TRACE("(%p)\n", lpmal);
153         return CoGetMalloc(0,lpmal);
154 }
155
156 /*************************************************************************
157  * SHGetDesktopFolder                   [SHELL32.216]
158  */
159 LPSHELLFOLDER pdesktopfolder=NULL;
160
161 DWORD WINAPI SHGetDesktopFolder(IShellFolder **psf)
162 {
163         HRESULT hres = S_OK;
164         LPCLASSFACTORY lpclf;
165         TRACE("%p->(%p)\n",psf,*psf);
166
167         *psf=NULL;
168
169         if (!pdesktopfolder) 
170         {
171           lpclf = IClassFactory_Constructor(&CLSID_ShellDesktop);
172           if(lpclf) 
173           {
174             hres = IClassFactory_CreateInstance(lpclf,NULL,(REFIID)&IID_IShellFolder, (void*)&pdesktopfolder);
175             IClassFactory_Release(lpclf);
176           }  
177         }
178         
179         if (pdesktopfolder) 
180         {
181           /* even if we create the folder, add a ref so the application canĀ“t destroy the folder*/
182           IShellFolder_AddRef(pdesktopfolder);
183           *psf = pdesktopfolder;
184         }
185
186         TRACE("-- %p->(%p)\n",psf, *psf);
187         return hres;
188 }
189
190 /**************************************************************************
191 *  IClassFactory Implementation
192 */
193
194 typedef struct
195 {
196     /* IUnknown fields */
197     ICOM_VFIELD(IClassFactory);
198     DWORD                       ref;
199     CLSID                       *rclsid;
200 } IClassFactoryImpl;
201
202 static ICOM_VTABLE(IClassFactory) clfvt;
203
204 /**************************************************************************
205  *  IClassFactory_Constructor
206  */
207
208 LPCLASSFACTORY IClassFactory_Constructor(REFCLSID rclsid)
209 {
210         IClassFactoryImpl* lpclf;
211
212         lpclf= (IClassFactoryImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IClassFactoryImpl));
213         lpclf->ref = 1;
214         ICOM_VTBL(lpclf) = &clfvt;
215         lpclf->rclsid = (CLSID*)rclsid;
216
217         TRACE("(%p)->()\n",lpclf);
218         shell32_ObjCount++;
219         return (LPCLASSFACTORY)lpclf;
220 }
221 /**************************************************************************
222  *  IClassFactory_QueryInterface
223  */
224 static HRESULT WINAPI IClassFactory_fnQueryInterface(
225   LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
226 {
227         ICOM_THIS(IClassFactoryImpl,iface);
228         TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
229
230         *ppvObj = NULL;
231
232         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
233         { *ppvObj = This; 
234         }
235         else if(IsEqualIID(riid, &IID_IClassFactory))  /*IClassFactory*/
236         { *ppvObj = (IClassFactory*)This;
237         }   
238
239         if(*ppvObj)
240         { IUnknown_AddRef((LPUNKNOWN)*ppvObj);          
241           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
242           return S_OK;
243         }
244         TRACE("-- Interface: %s E_NOINTERFACE\n", debugstr_guid(riid));
245         return E_NOINTERFACE;
246 }  
247 /******************************************************************************
248  * IClassFactory_AddRef
249  */
250 static ULONG WINAPI IClassFactory_fnAddRef(LPCLASSFACTORY iface)
251 {
252         ICOM_THIS(IClassFactoryImpl,iface);
253         TRACE("(%p)->(count=%lu)\n",This,This->ref);
254
255         shell32_ObjCount++;
256         return ++(This->ref);
257 }
258 /******************************************************************************
259  * IClassFactory_Release
260  */
261 static ULONG WINAPI IClassFactory_fnRelease(LPCLASSFACTORY iface)
262 {
263         ICOM_THIS(IClassFactoryImpl,iface);
264         TRACE("(%p)->(count=%lu)\n",This,This->ref);
265
266         shell32_ObjCount--;
267         if (!--(This->ref)) 
268         { TRACE("-- destroying IClassFactory(%p)\n",This);
269                 HeapFree(GetProcessHeap(),0,This);
270                 return 0;
271         }
272         return This->ref;
273 }
274 /******************************************************************************
275  * IClassFactory_CreateInstance
276  */
277 static HRESULT WINAPI IClassFactory_fnCreateInstance(
278   LPCLASSFACTORY iface, LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
279 {
280         ICOM_THIS(IClassFactoryImpl,iface);
281         IUnknown *pObj = NULL;
282         HRESULT hres;
283
284         TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnknown,debugstr_guid(riid),ppObject);
285
286         *ppObject = NULL;
287                 
288         if(pUnknown)
289         {
290           return(CLASS_E_NOAGGREGATION);
291         }
292
293         if (IsEqualCLSID(This->rclsid, &CLSID_ShellDesktop))
294         {
295           pObj = (IUnknown *)ISF_Desktop_Constructor();
296         }
297         else if (IsEqualCLSID(This->rclsid, &CLSID_ShellLink))
298         {
299           pObj = (IUnknown *)IShellLink_Constructor(FALSE);
300         } 
301         else
302         {
303           ERR("unknown IID requested\n\tIID:\t%s\n",debugstr_guid(riid));
304           return(E_NOINTERFACE);
305         }
306         
307         if (!pObj)
308         {
309           return(E_OUTOFMEMORY);
310         }
311          
312         hres = IUnknown_QueryInterface(pObj,riid, ppObject);
313         IUnknown_Release(pObj);
314
315         TRACE("-- Object created: (%p)->%p\n",This,*ppObject);
316
317         return hres;
318 }
319 /******************************************************************************
320  * IClassFactory_LockServer
321  */
322 static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
323 {
324         ICOM_THIS(IClassFactoryImpl,iface);
325         TRACE("%p->(0x%x), not implemented\n",This, fLock);
326         return E_NOTIMPL;
327 }
328
329 static ICOM_VTABLE(IClassFactory) clfvt = 
330 {
331     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
332     IClassFactory_fnQueryInterface,
333     IClassFactory_fnAddRef,
334   IClassFactory_fnRelease,
335   IClassFactory_fnCreateInstance,
336   IClassFactory_fnLockServer
337 };
338
339 /**************************************************************************
340  * Default ClassFactory Implementation
341  *
342  * SHCreateDefClassObject
343  *
344  * NOTES
345  *  helper function for dll's without a own classfactory
346  *  a generic classfactory is returned
347  *  when the CreateInstance of the cf is called the callback is executed
348  */
349 typedef HRESULT (CALLBACK * LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
350
351 typedef struct
352 {
353     ICOM_VFIELD(IClassFactory);
354     DWORD                       ref;
355     CLSID                       *rclsid;
356     LPFNCREATEINSTANCE          lpfnCI;
357     const IID *                 riidInst;
358     UINT *                      pcRefDll; /* pointer to refcounter in external dll (ugrrr...) */
359 } IDefClFImpl;
360
361 static ICOM_VTABLE(IClassFactory) dclfvt;
362
363 /**************************************************************************
364  *  IDefClF_fnConstructor
365  */
366
367 IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, UINT * pcRefDll, REFIID riidInst)
368 {
369         IDefClFImpl* lpclf;
370
371         lpclf = (IDefClFImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDefClFImpl));
372         lpclf->ref = 1;
373         ICOM_VTBL(lpclf) = &dclfvt;
374         lpclf->lpfnCI = lpfnCI;
375         lpclf->pcRefDll = pcRefDll;
376
377         if (pcRefDll) 
378           (*pcRefDll)++;
379
380         lpclf->riidInst = riidInst;
381
382         TRACE("(%p)\n\tIID:\t%s\n",lpclf, debugstr_guid(riidInst));
383         shell32_ObjCount++;
384         return (LPCLASSFACTORY)lpclf;
385 }
386 /**************************************************************************
387  *  IDefClF_fnQueryInterface
388  */
389 static HRESULT WINAPI IDefClF_fnQueryInterface(
390   LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
391 {
392         ICOM_THIS(IDefClFImpl,iface);
393
394         TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
395
396         *ppvObj = NULL;
397
398         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
399         { *ppvObj = This; 
400         }
401         else if(IsEqualIID(riid, &IID_IClassFactory))  /*IClassFactory*/
402         { *ppvObj = (IClassFactory*)This;
403         }   
404
405         if(*ppvObj)
406         { IUnknown_AddRef((LPUNKNOWN)*ppvObj);          
407           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
408           return S_OK;
409         }
410         TRACE("-- Interface: %s E_NOINTERFACE\n", debugstr_guid(riid));
411         return E_NOINTERFACE;
412 }  
413 /******************************************************************************
414  * IDefClF_fnAddRef
415  */
416 static ULONG WINAPI IDefClF_fnAddRef(LPCLASSFACTORY iface)
417 {
418         ICOM_THIS(IDefClFImpl,iface);
419         TRACE("(%p)->(count=%lu)\n",This,This->ref);
420
421         shell32_ObjCount++;
422
423         return ++(This->ref);
424 }
425 /******************************************************************************
426  * IDefClF_fnRelease
427  */
428 static ULONG WINAPI IDefClF_fnRelease(LPCLASSFACTORY iface)
429 {
430         ICOM_THIS(IDefClFImpl,iface);
431         TRACE("(%p)->(count=%lu)\n",This,This->ref);
432
433         shell32_ObjCount--;
434
435         if (!--(This->ref)) 
436         { 
437           if (This->pcRefDll) 
438             (*This->pcRefDll)--;
439
440           TRACE("-- destroying IClassFactory(%p)\n",This);
441           HeapFree(GetProcessHeap(),0,This);
442           return 0;
443         }
444         return This->ref;
445 }
446 /******************************************************************************
447  * IDefClF_fnCreateInstance
448  */
449 static HRESULT WINAPI IDefClF_fnCreateInstance(
450   LPCLASSFACTORY iface, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject)
451 {
452         ICOM_THIS(IDefClFImpl,iface);
453
454         TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnkOuter,debugstr_guid(riid),ppvObject);
455
456         *ppvObject = NULL;
457                 
458         if(pUnkOuter)
459           return(CLASS_E_NOAGGREGATION);
460
461         if ( This->riidInst==NULL ||
462              IsEqualCLSID(riid, This->riidInst) ||
463              IsEqualCLSID(riid, &IID_IUnknown) )
464         {
465           return This->lpfnCI(pUnkOuter, riid, ppvObject);
466         }
467
468         ERR("unknown IID requested\n\tIID:\t%s\n",debugstr_guid(riid));
469         return E_NOINTERFACE;
470 }
471 /******************************************************************************
472  * IDefClF_fnLockServer
473  */
474 static HRESULT WINAPI IDefClF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
475 {
476         ICOM_THIS(IDefClFImpl,iface);
477         TRACE("%p->(0x%x), not implemented\n",This, fLock);
478         return E_NOTIMPL;
479 }
480
481 static ICOM_VTABLE(IClassFactory) dclfvt = 
482 {
483     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
484     IDefClF_fnQueryInterface,
485     IDefClF_fnAddRef,
486   IDefClF_fnRelease,
487   IDefClF_fnCreateInstance,
488   IDefClF_fnLockServer
489 };
490
491 /******************************************************************************
492  * SHCreateDefClassObject                       [SHELL32.70]
493  */
494 HRESULT WINAPI SHCreateDefClassObject(
495         REFIID  riid,                           
496         LPVOID* ppv,    
497         LPFNCREATEINSTANCE lpfnCI,      /* create instance callback entry */
498         UINT    *pcRefDll,              /* ref count of the dll */
499         REFIID  riidInst)               /* optional interface to the instance */
500 {
501         TRACE("\n\tIID:\t%s %p %p %p \n\tIIDIns:\t%s\n",
502               debugstr_guid(riid), ppv, lpfnCI, pcRefDll, debugstr_guid(riidInst));
503
504         if ( IsEqualCLSID(riid, &IID_IClassFactory) )
505         {
506           IClassFactory * pcf = IDefClF_fnConstructor(lpfnCI, pcRefDll, riidInst);
507           if (pcf)
508           {
509             *ppv = pcf;
510             return NOERROR;
511           }
512           return E_OUTOFMEMORY;
513         }
514         return E_NOINTERFACE;
515 }
516