Added missing prototypes for StrRetToBuf(A|W).
[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
32 /*************************************************************************
33  * SHCoCreateInstance [SHELL32.102]
34  * 
35  * NOTES
36  *     exported by ordinal
37  */
38 LRESULT WINAPI SHCoCreateInstance(
39         LPSTR aclsid,
40         REFCLSID clsid,
41         IUnknown * unknownouter,
42         REFIID refiid,
43         LPVOID *ppv)
44 {
45         char    xclsid[48], xiid[48], xuout[48];
46         DWORD   hres;
47         IID     iid;
48         CLSID * myclsid = (CLSID*)clsid;
49         
50         WINE_StringFromCLSID(refiid,xiid);
51
52         if (!clsid)
53         {
54           if (!aclsid) return REGDB_E_CLASSNOTREG;
55           SHCLSIDFromStringA(aclsid, &iid);
56           myclsid = &iid;
57         }
58
59         WINE_StringFromCLSID(myclsid,xclsid);
60         WINE_StringFromCLSID(refiid,xiid);
61         if (unknownouter)
62                 WINE_StringFromCLSID(unknownouter,xuout);
63           
64         TRACE("(%p,\n\tCLSID:\t%s\n\tUOUT:\t%s\n\tIID:\t%s,%p)\n",
65                 aclsid,xclsid,unknownouter?xuout:"nil",xiid,ppv);
66
67         hres = CoCreateInstance(myclsid, NULL, CLSCTX_INPROC_SERVER, refiid, ppv);
68
69         if(hres!=S_OK)
70         {
71           ERR("failed (0x%08lx) to create \n\tCLSID:\t%s\n\tIID:\t%s\n", hres, xclsid, xiid);
72           ERR("you might need to import the winedefault.reg\n");
73         }
74
75         return hres;
76 }
77
78 /*************************************************************************
79  * SHELL32_DllGetClassObject   [SHELL32.128]
80  */
81 HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
82 {       HRESULT hres = E_OUTOFMEMORY;
83         LPCLASSFACTORY lpclf;
84
85         char xclsid[50],xiid[50];
86         WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
87         WINE_StringFromCLSID((LPCLSID)iid,xiid);
88         TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",xclsid,xiid);
89         
90         *ppv = NULL;
91
92         if(IsEqualCLSID(rclsid, &CLSID_PaperBin))
93         {
94           ERR("paper bin not implemented\n");
95           return CLASS_E_CLASSNOTAVAILABLE;
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_(shell)("%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_(shell)("-- %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_VTABLE(IClassFactory)* lpvtbl;
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         lpclf->lpvtbl = &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         char    xriid[50];
229         WINE_StringFromCLSID((LPCLSID)riid,xriid);
230         TRACE("(%p)->(\n\tIID:\t%s)\n",This,xriid);
231
232         *ppvObj = NULL;
233
234         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
235         { *ppvObj = This; 
236         }
237         else if(IsEqualIID(riid, &IID_IClassFactory))  /*IClassFactory*/
238         { *ppvObj = (IClassFactory*)This;
239         }   
240
241         if(*ppvObj)
242         { IUnknown_AddRef((LPUNKNOWN)*ppvObj);          
243           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
244           return S_OK;
245         }
246         TRACE("-- Interface: %s E_NOINTERFACE\n", xriid);
247         return E_NOINTERFACE;
248 }  
249 /******************************************************************************
250  * IClassFactory_AddRef
251  */
252 static ULONG WINAPI IClassFactory_fnAddRef(LPCLASSFACTORY iface)
253 {
254         ICOM_THIS(IClassFactoryImpl,iface);
255         TRACE("(%p)->(count=%lu)\n",This,This->ref);
256
257         shell32_ObjCount++;
258         return ++(This->ref);
259 }
260 /******************************************************************************
261  * IClassFactory_Release
262  */
263 static ULONG WINAPI IClassFactory_fnRelease(LPCLASSFACTORY iface)
264 {
265         ICOM_THIS(IClassFactoryImpl,iface);
266         TRACE("(%p)->(count=%lu)\n",This,This->ref);
267
268         shell32_ObjCount--;
269         if (!--(This->ref)) 
270         { TRACE("-- destroying IClassFactory(%p)\n",This);
271                 HeapFree(GetProcessHeap(),0,This);
272                 return 0;
273         }
274         return This->ref;
275 }
276 /******************************************************************************
277  * IClassFactory_CreateInstance
278  */
279 static HRESULT WINAPI IClassFactory_fnCreateInstance(
280   LPCLASSFACTORY iface, LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
281 {
282         ICOM_THIS(IClassFactoryImpl,iface);
283         IUnknown *pObj = NULL;
284         HRESULT hres;
285         char    xriid[50];
286
287         WINE_StringFromCLSID((LPCLSID)riid,xriid);
288         TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnknown,xriid,ppObject);
289
290         *ppObject = NULL;
291                 
292         if(pUnknown)
293         {
294           return(CLASS_E_NOAGGREGATION);
295         }
296
297         if (IsEqualCLSID(This->rclsid, &CLSID_ShellDesktop))
298         {
299           pObj = (IUnknown *)ISF_Desktop_Constructor();
300         }
301         else if (IsEqualCLSID(This->rclsid, &CLSID_ShellLink))
302         {
303           pObj = (IUnknown *)IShellLink_Constructor(FALSE);
304         } 
305         else
306         {
307           ERR("unknown IID requested\n\tIID:\t%s\n",xriid);
308           return(E_NOINTERFACE);
309         }
310         
311         if (!pObj)
312         {
313           return(E_OUTOFMEMORY);
314         }
315          
316         hres = IUnknown_QueryInterface(pObj,riid, ppObject);
317         IUnknown_Release(pObj);
318
319         TRACE("-- Object created: (%p)->%p\n",This,*ppObject);
320
321         return hres;
322 }
323 /******************************************************************************
324  * IClassFactory_LockServer
325  */
326 static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
327 {
328         ICOM_THIS(IClassFactoryImpl,iface);
329         TRACE("%p->(0x%x), not implemented\n",This, fLock);
330         return E_NOTIMPL;
331 }
332
333 static ICOM_VTABLE(IClassFactory) clfvt = 
334 {
335     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
336     IClassFactory_fnQueryInterface,
337     IClassFactory_fnAddRef,
338   IClassFactory_fnRelease,
339   IClassFactory_fnCreateInstance,
340   IClassFactory_fnLockServer
341 };
342
343 /**************************************************************************
344  * Default ClassFactory Implementation
345  *
346  * SHCreateDefClassObject
347  *
348  * NOTES
349  *  helper function for dll's without a own classfactory
350  *  a generic classfactory is returned
351  *  when the CreateInstance of the cf is called the callback is executed
352  */
353 typedef HRESULT (CALLBACK * LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
354
355 typedef struct
356 {
357     ICOM_VTABLE(IClassFactory)* lpvtbl;
358     DWORD                       ref;
359     CLSID                       *rclsid;
360     LPFNCREATEINSTANCE          lpfnCI;
361     const IID *                 riidInst;
362     UINT *                      pcRefDll; /* pointer to refcounter in external dll (ugrrr...) */
363 } IDefClFImpl;
364
365 static ICOM_VTABLE(IClassFactory) dclfvt;
366
367 /**************************************************************************
368  *  IDefClF_fnConstructor
369  */
370
371 IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, UINT * pcRefDll, REFIID riidInst)
372 {
373         IDefClFImpl* lpclf;
374         char    xriidInst[50];
375
376         WINE_StringFromCLSID((LPCLSID)riidInst,xriidInst);
377
378         lpclf = (IDefClFImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDefClFImpl));
379         lpclf->ref = 1;
380         lpclf->lpvtbl = &dclfvt;
381         lpclf->lpfnCI = lpfnCI;
382         lpclf->pcRefDll = pcRefDll;
383
384         if (pcRefDll) 
385           (*pcRefDll)++;
386
387         lpclf->riidInst = riidInst;
388
389         TRACE("(%p)\n\tIID:\t%s\n",lpclf, xriidInst);
390         shell32_ObjCount++;
391         return (LPCLASSFACTORY)lpclf;
392 }
393 /**************************************************************************
394  *  IDefClF_fnQueryInterface
395  */
396 static HRESULT WINAPI IDefClF_fnQueryInterface(
397   LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
398 {
399         ICOM_THIS(IDefClFImpl,iface);
400         char    xriid[50];
401         WINE_StringFromCLSID((LPCLSID)riid,xriid);
402         TRACE("(%p)->(\n\tIID:\t%s)\n",This,xriid);
403
404         *ppvObj = NULL;
405
406         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
407         { *ppvObj = This; 
408         }
409         else if(IsEqualIID(riid, &IID_IClassFactory))  /*IClassFactory*/
410         { *ppvObj = (IClassFactory*)This;
411         }   
412
413         if(*ppvObj)
414         { IUnknown_AddRef((LPUNKNOWN)*ppvObj);          
415           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
416           return S_OK;
417         }
418         TRACE("-- Interface: %s E_NOINTERFACE\n", xriid);
419         return E_NOINTERFACE;
420 }  
421 /******************************************************************************
422  * IDefClF_fnAddRef
423  */
424 static ULONG WINAPI IDefClF_fnAddRef(LPCLASSFACTORY iface)
425 {
426         ICOM_THIS(IDefClFImpl,iface);
427         TRACE("(%p)->(count=%lu)\n",This,This->ref);
428
429         shell32_ObjCount++;
430
431         return ++(This->ref);
432 }
433 /******************************************************************************
434  * IDefClF_fnRelease
435  */
436 static ULONG WINAPI IDefClF_fnRelease(LPCLASSFACTORY iface)
437 {
438         ICOM_THIS(IDefClFImpl,iface);
439         TRACE("(%p)->(count=%lu)\n",This,This->ref);
440
441         shell32_ObjCount--;
442
443         if (!--(This->ref)) 
444         { 
445           if (This->pcRefDll) 
446             (*This->pcRefDll)--;
447
448           TRACE("-- destroying IClassFactory(%p)\n",This);
449           HeapFree(GetProcessHeap(),0,This);
450           return 0;
451         }
452         return This->ref;
453 }
454 /******************************************************************************
455  * IDefClF_fnCreateInstance
456  */
457 static HRESULT WINAPI IDefClF_fnCreateInstance(
458   LPCLASSFACTORY iface, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject)
459 {
460         ICOM_THIS(IDefClFImpl,iface);
461         char    xriid[50];
462
463         WINE_StringFromCLSID((LPCLSID)riid,xriid);
464         TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnkOuter,xriid,ppvObject);
465
466         *ppvObject = NULL;
467                 
468         if(pUnkOuter)
469           return(CLASS_E_NOAGGREGATION);
470
471         if ( This->riidInst==NULL ||
472              IsEqualCLSID(riid, This->riidInst) ||
473              IsEqualCLSID(riid, &IID_IUnknown) )
474         {
475           return This->lpfnCI(pUnkOuter, riid, ppvObject);
476         }
477
478         ERR("unknown IID requested\n\tIID:\t%s\n",xriid);
479         return E_NOINTERFACE;
480 }
481 /******************************************************************************
482  * IDefClF_fnLockServer
483  */
484 static HRESULT WINAPI IDefClF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
485 {
486         ICOM_THIS(IDefClFImpl,iface);
487         TRACE("%p->(0x%x), not implemented\n",This, fLock);
488         return E_NOTIMPL;
489 }
490
491 static ICOM_VTABLE(IClassFactory) dclfvt = 
492 {
493     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
494     IDefClF_fnQueryInterface,
495     IDefClF_fnAddRef,
496   IDefClF_fnRelease,
497   IDefClF_fnCreateInstance,
498   IDefClF_fnLockServer
499 };
500
501 /******************************************************************************
502  * SHCreateDefClassObject                       [SHELL32.70]
503  */
504 HRESULT WINAPI SHCreateDefClassObject(
505         REFIID  riid,                           
506         LPVOID* ppv,    
507         LPFNCREATEINSTANCE lpfnCI,      /* create instance callback entry */
508         UINT    *pcRefDll,              /* ref count of the dll */
509         REFIID  riidInst)               /* optional interface to the instance */
510 {
511
512         char xriid[50],xriidInst[50];
513         WINE_StringFromCLSID((LPCLSID)riid,xriid);
514         WINE_StringFromCLSID((LPCLSID)riidInst,xriidInst);
515
516         TRACE("\n\tIID:\t%s %p %p %p \n\tIIDIns:\t%s\n",
517         xriid, ppv, lpfnCI, pcRefDll, xriidInst);
518
519         if ( IsEqualCLSID(riid, &IID_IClassFactory) )
520         {
521           IClassFactory * pcf = IDefClF_fnConstructor(lpfnCI, pcRefDll, riidInst);
522           if (pcf)
523           {
524             *ppv = pcf;
525             return NOERROR;
526           }
527           return E_OUTOFMEMORY;
528         }
529         return E_NOINTERFACE;
530 }
531