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