Compiler warnings fix.
[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 /*************************************************************************
31  *
32  */
33 typedef DWORD (* WINAPI GetClassPtr)(REFCLSID,REFIID,LPVOID);
34
35 static GetClassPtr SH_find_moduleproc(LPSTR dllname,HMODULE *xhmod,LPSTR name)
36 {       HMODULE hmod;
37         FARPROC dllunload,nameproc;
38
39         TRACE("dll=%s, hmodule=%p, name=%s\n",dllname, xhmod, name);
40
41         if (xhmod)
42         { *xhmod = 0;
43         }
44
45         if (!strcasecmp(PathFindFilenameA(dllname),"shell32.dll"))
46         { return (GetClassPtr)SHELL32_DllGetClassObject;
47         }
48
49         hmod = LoadLibraryExA(dllname,0,LOAD_WITH_ALTERED_SEARCH_PATH);
50
51         if (!hmod)
52         { return NULL;
53         }
54
55         dllunload = GetProcAddress(hmod,"DllCanUnloadNow");
56
57         if (!dllunload)
58         { if (xhmod)
59           { *xhmod = hmod;
60           }
61         }
62
63         nameproc = GetProcAddress(hmod,name);
64
65         if (!nameproc)
66         { FreeLibrary(hmod);
67           return NULL;
68         }
69
70         /* register unloadable dll with unloadproc ... */
71         return (GetClassPtr)nameproc;
72 }
73 /*************************************************************************
74  *
75  */
76 static DWORD SH_get_instance(REFCLSID clsid,LPSTR dllname,LPVOID unknownouter,REFIID refiid,LPVOID *ppv) 
77 {       GetClassPtr     dllgetclassob;
78         DWORD           hres;
79         LPCLASSFACTORY  classfac;
80
81         char    xclsid[50],xrefiid[50];
82         WINE_StringFromCLSID((LPCLSID)clsid,xclsid);
83         WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
84
85         TRACE("\n\tCLSID:%s,%s,%p,\n\tIID:%s,%p\n",xclsid, dllname,unknownouter,xrefiid,ppv);
86         
87         dllgetclassob = SH_find_moduleproc(dllname,NULL,"DllGetClassObject");
88
89         if (!dllgetclassob)
90         { return 0x80070000|GetLastError();
91         }
92
93         hres = (*dllgetclassob)(clsid,(REFIID)&IID_IClassFactory,&classfac);
94
95         if ((hres<0) || (hres>=0x80000000))
96             return hres;
97
98         if (!classfac)
99         { FIXME("no classfactory, but hres is 0x%ld!\n",hres);
100           return E_FAIL;
101         }
102
103         IClassFactory_CreateInstance(classfac,unknownouter,refiid,ppv);
104         IClassFactory_Release(classfac);
105         return S_OK;
106 }
107
108 /*************************************************************************
109  * SHCoCreateInstance [SHELL32.102]
110  * 
111  * NOTES
112  *     exported by ordinal
113  */
114 LRESULT WINAPI SHCoCreateInstance(
115         LPSTR aclsid,
116         CLSID *clsid,
117         LPUNKNOWN unknownouter,
118         REFIID refiid,
119         LPVOID *ppv)
120 {
121         char    buffer[256],xclsid[48],xiid[48],path[260],tmodel[100];
122         HKEY    inprockey;
123         DWORD   pathlen,type,tmodellen;
124         DWORD   hres;
125         
126         WINE_StringFromCLSID(refiid,xiid);
127
128         if (clsid)
129         { WINE_StringFromCLSID(clsid,xclsid);
130         }
131         else
132         { if (!aclsid)
133           {     return REGDB_E_CLASSNOTREG;
134           }
135           strcpy(xclsid,aclsid);
136         }
137
138         TRACE("(%p,\n\tSID:\t%s,%p,\n\tIID:\t%s,%p)\n",aclsid,xclsid,unknownouter,xiid,ppv);
139
140         sprintf(buffer,"CLSID\\%s\\InProcServer32",xclsid);
141
142         if (RegOpenKeyExA(HKEY_CLASSES_ROOT,buffer,0,0x02000000,&inprockey))
143         { return SH_get_instance(clsid,"shell32.dll",unknownouter,refiid,ppv);
144         }
145         pathlen=sizeof(path);
146
147         if (RegQueryValueA(inprockey,NULL,path,&pathlen))
148         { RegCloseKey(inprockey);
149           return SH_get_instance(clsid,"shell32.dll",unknownouter,refiid,ppv);
150         }
151
152         TRACE("Server dll is %s\n",path);
153         tmodellen=sizeof(tmodel);
154         type=REG_SZ;
155
156         if (RegQueryValueExA(inprockey,"ThreadingModel",NULL,&type,tmodel,&tmodellen))
157         { RegCloseKey(inprockey);
158           return SH_get_instance(clsid,"shell32.dll",unknownouter,refiid,ppv);
159         }
160
161         TRACE("Threading model is %s\n",tmodel);
162
163         hres=SH_get_instance(clsid,path,unknownouter,refiid,ppv);
164         if (hres<0 || (hres>0x80000000))
165         { hres=SH_get_instance(clsid,"shell32.dll",unknownouter,refiid,ppv);
166         }
167         RegCloseKey(inprockey);
168
169         TRACE("-- interface is %p\n", *ppv);
170         return hres;
171 }
172
173
174 /*************************************************************************
175  * SHELL32_DllGetClassObject   [SHELL32.128]
176  *
177  * [Standart OLE/COM Interface Method]
178  * This Function retrives the pointer to a specified interface (iid) of
179  * a given class (rclsid).
180  * With this pointer it's possible to call the IClassFactory_CreateInstance
181  * method to get a instance of the requested Class.
182  * This function does NOT instantiate the Class!!!
183  *
184  */
185 HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
186 {       HRESULT hres = E_OUTOFMEMORY;
187         LPCLASSFACTORY lpclf;
188
189         char xclsid[50],xiid[50];
190         WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
191         WINE_StringFromCLSID((LPCLSID)iid,xiid);
192         TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",xclsid,xiid);
193         
194         *ppv = NULL;
195         if(IsEqualCLSID(rclsid, &CLSID_ShellDesktop)|| 
196            IsEqualCLSID(rclsid, &CLSID_ShellLink))
197         {
198           lpclf = IClassFactory_Constructor( rclsid );
199
200           if(lpclf) 
201           {
202             hres = IClassFactory_QueryInterface(lpclf,iid, ppv);
203             IClassFactory_Release(lpclf);
204           }
205         }
206         else
207         { WARN("-- CLSID not found\n");
208           hres = CLASS_E_CLASSNOTAVAILABLE;
209         }
210         TRACE("-- pointer to class factory: %p\n",*ppv);
211         return hres;
212 }
213
214 /*************************************************************************
215  * SHCLSIDFromString                            [SHELL32.147]
216  *
217  * NOTES
218  *     exported by ordinal
219  */
220 DWORD WINAPI SHCLSIDFromString (LPSTR clsid, CLSID *id)
221 {
222         TRACE("(%p(%s) %p)\n", clsid, clsid, id);
223         return CLSIDFromString16(clsid, id); 
224 }
225
226 /*************************************************************************
227  *                       SHGetMalloc                    [SHELL32.220]
228  * returns the interface to shell malloc.
229  *
230  * [SDK header win95/shlobj.h:
231  * equivalent to:  #define SHGetMalloc(ppmem)   CoGetMalloc(MEMCTX_TASK, ppmem)
232  * ]
233  * What we are currently doing is not very wrong, since we always use the same
234  * heap (ProcessHeap).
235  */
236 DWORD WINAPI SHGetMalloc(LPMALLOC *lpmal) 
237 {       TRACE("(%p)\n", lpmal);
238         return CoGetMalloc(0,lpmal);
239 }
240
241 /**************************************************************************
242 *  IClassFactory Implementation
243 */
244
245 typedef struct
246 {
247     /* IUnknown fields */
248     ICOM_VTABLE(IClassFactory)* lpvtbl;
249     DWORD                       ref;
250     CLSID                       *rclsid;
251 } IClassFactoryImpl;
252
253 static ICOM_VTABLE(IClassFactory) clfvt;
254
255 /**************************************************************************
256  *  IClassFactory_Constructor
257  */
258
259 LPCLASSFACTORY IClassFactory_Constructor(REFCLSID rclsid)
260 {
261         IClassFactoryImpl* lpclf;
262
263         lpclf= (IClassFactoryImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IClassFactoryImpl));
264         lpclf->ref = 1;
265         lpclf->lpvtbl = &clfvt;
266         lpclf->rclsid = (CLSID*)rclsid;
267
268         TRACE("(%p)->()\n",lpclf);
269         shell32_ObjCount++;
270         return (LPCLASSFACTORY)lpclf;
271 }
272 /**************************************************************************
273  *  IClassFactory_QueryInterface
274  */
275 static HRESULT WINAPI IClassFactory_fnQueryInterface(
276   LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
277 {
278         ICOM_THIS(IClassFactoryImpl,iface);
279         char    xriid[50];
280         WINE_StringFromCLSID((LPCLSID)riid,xriid);
281         TRACE("(%p)->(\n\tIID:\t%s)\n",This,xriid);
282
283         *ppvObj = NULL;
284
285         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
286         { *ppvObj = This; 
287         }
288         else if(IsEqualIID(riid, &IID_IClassFactory))  /*IClassFactory*/
289         { *ppvObj = (IClassFactory*)This;
290         }   
291
292         if(*ppvObj)
293         { IUnknown_AddRef((LPUNKNOWN)*ppvObj);          
294           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
295           return S_OK;
296         }
297         TRACE("-- Interface: %s E_NOINTERFACE\n", xriid);
298         return E_NOINTERFACE;
299 }  
300 /******************************************************************************
301  * IClassFactory_AddRef
302  */
303 static ULONG WINAPI IClassFactory_fnAddRef(LPCLASSFACTORY iface)
304 {
305         ICOM_THIS(IClassFactoryImpl,iface);
306         TRACE("(%p)->(count=%lu)\n",This,This->ref);
307
308         shell32_ObjCount++;
309         return ++(This->ref);
310 }
311 /******************************************************************************
312  * IClassFactory_Release
313  */
314 static ULONG WINAPI IClassFactory_fnRelease(LPCLASSFACTORY iface)
315 {
316         ICOM_THIS(IClassFactoryImpl,iface);
317         TRACE("(%p)->(count=%lu)\n",This,This->ref);
318
319         shell32_ObjCount--;
320         if (!--(This->ref)) 
321         { TRACE("-- destroying IClassFactory(%p)\n",This);
322                 HeapFree(GetProcessHeap(),0,This);
323                 return 0;
324         }
325         return This->ref;
326 }
327 /******************************************************************************
328  * IClassFactory_CreateInstance
329  */
330 static HRESULT WINAPI IClassFactory_fnCreateInstance(
331   LPCLASSFACTORY iface, LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
332 {
333         ICOM_THIS(IClassFactoryImpl,iface);
334         IUnknown *pObj = NULL;
335         HRESULT hres;
336         char    xriid[50];
337
338         WINE_StringFromCLSID((LPCLSID)riid,xriid);
339         TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnknown,xriid,ppObject);
340
341         *ppObject = NULL;
342                 
343         if(pUnknown)
344         {
345           return(CLASS_E_NOAGGREGATION);
346         }
347
348         if (IsEqualCLSID(This->rclsid, &CLSID_ShellDesktop))
349         {
350           pObj = (IUnknown *)IShellFolder_Constructor(NULL,NULL);
351         }
352         else if (IsEqualCLSID(This->rclsid, &CLSID_ShellLink))
353         {
354           pObj = (IUnknown *)IShellLink_Constructor(FALSE);
355         } 
356         else
357         {
358           ERR("unknown IID requested\n\tIID:\t%s\n",xriid);
359           return(E_NOINTERFACE);
360         }
361         
362         if (!pObj)
363         {
364           return(E_OUTOFMEMORY);
365         }
366          
367         hres = IUnknown_QueryInterface(pObj,riid, ppObject);
368         IUnknown_Release(pObj);
369
370         TRACE("-- Object created: (%p)->%p\n",This,*ppObject);
371
372         return hres;
373 }
374 /******************************************************************************
375  * IClassFactory_LockServer
376  */
377 static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
378 {
379         ICOM_THIS(IClassFactoryImpl,iface);
380         TRACE("%p->(0x%x), not implemented\n",This, fLock);
381         return E_NOTIMPL;
382 }
383
384 static ICOM_VTABLE(IClassFactory) clfvt = 
385 {
386     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
387     IClassFactory_fnQueryInterface,
388     IClassFactory_fnAddRef,
389   IClassFactory_fnRelease,
390   IClassFactory_fnCreateInstance,
391   IClassFactory_fnLockServer
392 };
393