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