Removed some unnecessary includes.
[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 "config.h"
10
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "shellapi.h"
15 #include "shlobj.h"
16 #include "shlguid.h"
17 #include "winreg.h"
18 #include "winerror.h"
19
20 #include "wine/undocshell.h"
21 #include "wine/unicode.h"
22 #include "shell32_main.h"
23
24 #include "debugtools.h"
25
26 DEFAULT_DEBUG_CHANNEL(shell);
27
28 DWORD WINAPI SHCLSIDFromStringA (LPCSTR clsid, CLSID *id);
29 extern IShellFolder * IShellFolder_Constructor(
30         IShellFolder * psf,
31         LPITEMIDLIST pidl);
32 extern HRESULT IFSFolder_Constructor(
33         IUnknown * pUnkOuter,
34         REFIID riid,
35         LPVOID * ppv);
36
37 /*************************************************************************
38  * SHCoCreateInstance [SHELL32.102]
39  * 
40  * NOTES
41  *     exported by ordinal
42  */
43 LRESULT WINAPI SHCoCreateInstance(
44         LPCSTR aclsid,
45         REFCLSID clsid,
46         LPUNKNOWN unknownouter,
47         REFIID refiid,
48         LPVOID *ppv)
49 {
50         DWORD   hres;
51         IID     iid;
52         CLSID * myclsid = (CLSID*)clsid;
53         
54         if (!clsid)
55         {
56           if (!aclsid) return REGDB_E_CLASSNOTREG;
57           SHCLSIDFromStringA(aclsid, &iid);
58           myclsid = &iid;
59         }
60
61         TRACE("(%p,\n\tCLSID:\t%s, unk:%p\n\tIID:\t%s,%p)\n",
62                 aclsid,debugstr_guid(myclsid),unknownouter,debugstr_guid(refiid),ppv);
63
64         if IsEqualCLSID(myclsid, &CLSID_ShellFSFolder)
65         {
66           hres = IFSFolder_Constructor(unknownouter, refiid, ppv);
67         }
68         else
69         {
70           hres = CoCreateInstance(myclsid, unknownouter, CLSCTX_INPROC_SERVER, refiid, ppv);
71         }
72         
73         if(hres!=S_OK)
74         {
75           ERR("failed (0x%08lx) to create \n\tCLSID:\t%s\n\tIID:\t%s\n",
76               hres, debugstr_guid(myclsid), debugstr_guid(refiid));
77           ERR("class not found in registry\n");
78         }
79
80         TRACE("-- instance: %p\n",*ppv);
81         return hres;
82 }
83
84 /*************************************************************************
85  * DllGetClassObject   [SHELL32.128]
86  */
87 HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
88 {       HRESULT hres = E_OUTOFMEMORY;
89         LPCLASSFACTORY lpclf;
90
91         TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
92         
93         *ppv = NULL;
94
95         if(IsEqualCLSID(rclsid, &CLSID_ShellDesktop)|| 
96            IsEqualCLSID(rclsid, &CLSID_ShellLink))
97         {
98           lpclf = IClassFactory_Constructor( rclsid );
99
100           if(lpclf) 
101           {
102             hres = IClassFactory_QueryInterface(lpclf,iid, ppv);
103             IClassFactory_Release(lpclf);
104           }
105         }
106         else
107         {
108           WARN("-- CLSID not found\n");
109           hres = CLASS_E_CLASSNOTAVAILABLE;
110         }
111         TRACE("-- pointer to class factory: %p\n",*ppv);
112         return hres;
113 }
114
115 /*************************************************************************
116  * SHCLSIDFromString                            [SHELL32.147]
117  *
118  * NOTES
119  *     exported by ordinal
120  */
121 DWORD WINAPI SHCLSIDFromStringA (LPCSTR clsid, CLSID *id)
122 {
123     WCHAR buffer[40];
124     TRACE("(%p(%s) %p)\n", clsid, clsid, id);
125     if (!MultiByteToWideChar( CP_ACP, 0, clsid, -1, buffer, sizeof(buffer)/sizeof(WCHAR) ))
126         return CO_E_CLASSSTRING;
127     return CLSIDFromString( buffer, id );
128 }
129 DWORD WINAPI SHCLSIDFromStringW (LPWSTR clsid, CLSID *id)
130 {
131         TRACE("(%p(%s) %p)\n", clsid, debugstr_w(clsid), id);
132         return CLSIDFromString(clsid, id); 
133 }
134 DWORD WINAPI SHCLSIDFromStringAW (LPVOID clsid, CLSID *id)
135 {
136         if (SHELL_OsIsUnicode())
137           return SHCLSIDFromStringW (clsid, id);
138         return SHCLSIDFromStringA (clsid, id);
139 }
140
141 /*************************************************************************
142  *                       SHGetMalloc                    [SHELL32.@]
143  * returns the interface to shell malloc.
144  *
145  * [SDK header win95/shlobj.h:
146  * equivalent to:  #define SHGetMalloc(ppmem)   CoGetMalloc(MEMCTX_TASK, ppmem)
147  * ]
148  * What we are currently doing is not very wrong, since we always use the same
149  * heap (ProcessHeap).
150  */
151 DWORD WINAPI SHGetMalloc(LPMALLOC *lpmal) 
152 {
153         TRACE("(%p)\n", lpmal);
154         return CoGetMalloc(MEMCTX_TASK, lpmal);
155 }
156
157 /*************************************************************************
158  * SHGetDesktopFolder                   [SHELL32.@]
159  */
160 LPSHELLFOLDER pdesktopfolder=NULL;
161
162 DWORD WINAPI SHGetDesktopFolder(IShellFolder **psf)
163 {
164         HRESULT hres = S_OK;
165         LPCLASSFACTORY lpclf;
166         TRACE("%p->(%p)\n",psf,*psf);
167
168         *psf=NULL;
169
170         if (!pdesktopfolder) 
171         {
172           lpclf = IClassFactory_Constructor(&CLSID_ShellDesktop);
173           if(lpclf) 
174           {
175             hres = IClassFactory_CreateInstance(lpclf,NULL,(REFIID)&IID_IShellFolder, (void*)&pdesktopfolder);
176             IClassFactory_Release(lpclf);
177           }  
178         }
179         
180         if (pdesktopfolder) 
181         {
182           /* even if we create the folder, add a ref so the application canĀ“t destroy the folder*/
183           IShellFolder_AddRef(pdesktopfolder);
184           *psf = pdesktopfolder;
185         }
186
187         TRACE("-- %p->(%p)\n",psf, *psf);
188         return hres;
189 }
190
191 /**************************************************************************
192 *  IClassFactory Implementation
193 */
194
195 typedef struct
196 {
197     /* IUnknown fields */
198     ICOM_VFIELD(IClassFactory);
199     DWORD                       ref;
200     CLSID                       *rclsid;
201 } IClassFactoryImpl;
202
203 static ICOM_VTABLE(IClassFactory) clfvt;
204
205 /**************************************************************************
206  *  IClassFactory_Constructor
207  */
208
209 LPCLASSFACTORY IClassFactory_Constructor(REFCLSID rclsid)
210 {
211         IClassFactoryImpl* lpclf;
212
213         lpclf= (IClassFactoryImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IClassFactoryImpl));
214         lpclf->ref = 1;
215         ICOM_VTBL(lpclf) = &clfvt;
216         lpclf->rclsid = (CLSID*)rclsid;
217
218         TRACE("(%p)->()\n",lpclf);
219         InterlockedIncrement(&shell32_ObjCount);
220         return (LPCLASSFACTORY)lpclf;
221 }
222 /**************************************************************************
223  *  IClassFactory_QueryInterface
224  */
225 static HRESULT WINAPI IClassFactory_fnQueryInterface(
226   LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
227 {
228         ICOM_THIS(IClassFactoryImpl,iface);
229         TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
230
231         *ppvObj = NULL;
232
233         if(IsEqualIID(riid, &IID_IUnknown))          /*IUnknown*/
234         { *ppvObj = This; 
235         }
236         else if(IsEqualIID(riid, &IID_IClassFactory))  /*IClassFactory*/
237         { *ppvObj = (IClassFactory*)This;
238         }   
239
240         if(*ppvObj)
241         { IUnknown_AddRef((LPUNKNOWN)*ppvObj);          
242           TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
243           return S_OK;
244         }
245         TRACE("-- Interface: %s E_NOINTERFACE\n", debugstr_guid(riid));
246         return E_NOINTERFACE;
247 }  
248 /******************************************************************************
249  * IClassFactory_AddRef
250  */
251 static ULONG WINAPI IClassFactory_fnAddRef(LPCLASSFACTORY iface)
252 {
253         ICOM_THIS(IClassFactoryImpl,iface);
254         TRACE("(%p)->(count=%lu)\n",This,This->ref);
255
256         InterlockedIncrement(&shell32_ObjCount);
257         return InterlockedIncrement(&This->ref);
258 }
259 /******************************************************************************
260  * IClassFactory_Release
261  */
262 static ULONG WINAPI IClassFactory_fnRelease(LPCLASSFACTORY iface)
263 {
264         ICOM_THIS(IClassFactoryImpl,iface);
265         TRACE("(%p)->(count=%lu)\n",This,This->ref);
266
267         InterlockedDecrement(&shell32_ObjCount);
268         if (!InterlockedDecrement(&This->ref)) 
269         {
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
286         TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnknown,debugstr_guid(riid),ppObject);
287
288         *ppObject = NULL;
289                 
290         if(pUnknown)
291         {
292           return(CLASS_E_NOAGGREGATION);
293         }
294
295         if (IsEqualCLSID(This->rclsid, &CLSID_ShellDesktop))
296         {
297           pObj = (IUnknown *)ISF_Desktop_Constructor();
298         }
299         else if (IsEqualCLSID(This->rclsid, &CLSID_ShellLink))
300         {
301           pObj = (IUnknown *)IShellLink_Constructor(FALSE);
302         } 
303         else
304         {
305           ERR("unknown IID requested\n\tIID:\t%s\n",debugstr_guid(riid));
306           return(E_NOINTERFACE);
307         }
308         
309         if (!pObj)
310         {
311           return(E_OUTOFMEMORY);
312         }
313          
314         hres = IUnknown_QueryInterface(pObj,riid, ppObject);
315         IUnknown_Release(pObj);
316
317         TRACE("-- Object created: (%p)->%p\n",This,*ppObject);
318
319         return hres;
320 }
321 /******************************************************************************
322  * IClassFactory_LockServer
323  */
324 static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
325 {
326         ICOM_THIS(IClassFactoryImpl,iface);
327         TRACE("%p->(0x%x), not implemented\n",This, fLock);
328         return E_NOTIMPL;
329 }
330
331 static ICOM_VTABLE(IClassFactory) clfvt = 
332 {
333     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
334     IClassFactory_fnQueryInterface,
335     IClassFactory_fnAddRef,
336   IClassFactory_fnRelease,
337   IClassFactory_fnCreateInstance,
338   IClassFactory_fnLockServer
339 };
340
341 /**************************************************************************
342  * Default ClassFactory Implementation
343  *
344  * SHCreateDefClassObject
345  *
346  * NOTES
347  *  helper function for dll's without a own classfactory
348  *  a generic classfactory is returned
349  *  when the CreateInstance of the cf is called the callback is executed
350  */
351 typedef HRESULT CALLBACK (*LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
352
353 typedef struct
354 {
355     ICOM_VFIELD(IClassFactory);
356     DWORD                       ref;
357     CLSID                       *rclsid;
358     LPFNCREATEINSTANCE          lpfnCI;
359     const IID *                 riidInst;
360     ULONG *                     pcRefDll; /* pointer to refcounter in external dll (ugrrr...) */
361 } IDefClFImpl;
362
363 static ICOM_VTABLE(IClassFactory) dclfvt;
364
365 /**************************************************************************
366  *  IDefClF_fnConstructor
367  */
368
369 IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst)
370 {
371         IDefClFImpl* lpclf;
372
373         lpclf = (IDefClFImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDefClFImpl));
374         lpclf->ref = 1;
375         ICOM_VTBL(lpclf) = &dclfvt;
376         lpclf->lpfnCI = lpfnCI;
377         lpclf->pcRefDll = pcRefDll;
378
379         if (pcRefDll) InterlockedIncrement(pcRefDll);
380         lpclf->riidInst = riidInst;
381
382         TRACE("(%p)\n\tIID:\t%s\n",lpclf, debugstr_guid(riidInst));
383         InterlockedIncrement(&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         InterlockedIncrement(&shell32_ObjCount);
422         return InterlockedIncrement(&This->ref);
423 }
424 /******************************************************************************
425  * IDefClF_fnRelease
426  */
427 static ULONG WINAPI IDefClF_fnRelease(LPCLASSFACTORY iface)
428 {
429         ICOM_THIS(IDefClFImpl,iface);
430         TRACE("(%p)->(count=%lu)\n",This,This->ref);
431
432         InterlockedDecrement(&shell32_ObjCount);
433
434         if (!InterlockedDecrement(&This->ref)) 
435         { 
436           if (This->pcRefDll) InterlockedDecrement(This->pcRefDll);
437
438           TRACE("-- destroying IClassFactory(%p)\n",This);
439           HeapFree(GetProcessHeap(),0,This);
440           return 0;
441         }
442         return This->ref;
443 }
444 /******************************************************************************
445  * IDefClF_fnCreateInstance
446  */
447 static HRESULT WINAPI IDefClF_fnCreateInstance(
448   LPCLASSFACTORY iface, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject)
449 {
450         ICOM_THIS(IDefClFImpl,iface);
451
452         TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnkOuter,debugstr_guid(riid),ppvObject);
453
454         *ppvObject = NULL;
455                 
456         if(pUnkOuter)
457           return(CLASS_E_NOAGGREGATION);
458
459         if ( This->riidInst==NULL ||
460              IsEqualCLSID(riid, This->riidInst) ||
461              IsEqualCLSID(riid, &IID_IUnknown) )
462         {
463           return This->lpfnCI(pUnkOuter, riid, ppvObject);
464         }
465
466         ERR("unknown IID requested\n\tIID:\t%s\n",debugstr_guid(riid));
467         return E_NOINTERFACE;
468 }
469 /******************************************************************************
470  * IDefClF_fnLockServer
471  */
472 static HRESULT WINAPI IDefClF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
473 {
474         ICOM_THIS(IDefClFImpl,iface);
475         TRACE("%p->(0x%x), not implemented\n",This, fLock);
476         return E_NOTIMPL;
477 }
478
479 static ICOM_VTABLE(IClassFactory) dclfvt = 
480 {
481     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
482     IDefClF_fnQueryInterface,
483     IDefClF_fnAddRef,
484   IDefClF_fnRelease,
485   IDefClF_fnCreateInstance,
486   IDefClF_fnLockServer
487 };
488
489 /******************************************************************************
490  * SHCreateDefClassObject                       [SHELL32.70]
491  */
492 HRESULT WINAPI SHCreateDefClassObject(
493         REFIID  riid,                           
494         LPVOID* ppv,    
495         LPFNCREATEINSTANCE lpfnCI,      /* [in] create instance callback entry */
496         LPDWORD pcRefDll,               /* [in/out] ref count of the dll */
497         REFIID  riidInst)               /* [in] optional interface to the instance */
498 {
499         TRACE("\n\tIID:\t%s %p %p %p \n\tIIDIns:\t%s\n",
500               debugstr_guid(riid), ppv, lpfnCI, pcRefDll, debugstr_guid(riidInst));
501
502         if ( IsEqualCLSID(riid, &IID_IClassFactory) )
503         {
504           IClassFactory * pcf = IDefClF_fnConstructor(lpfnCI, pcRefDll, riidInst);
505           if (pcf)
506           {
507             *ppv = pcf;
508             return NOERROR;
509           }
510           return E_OUTOFMEMORY;
511         }
512         return E_NOINTERFACE;
513 }
514
515 /*************************************************************************
516  *  DragAcceptFiles             [SHELL32.54]
517  */
518 void WINAPI DragAcceptFiles(HWND hWnd, BOOL b)
519 {
520         LONG exstyle;
521   
522         if( !IsWindow(hWnd) ) return;
523         exstyle = GetWindowLongA(hWnd,GWL_EXSTYLE);
524         if (b)
525           exstyle |= WS_EX_ACCEPTFILES;
526         else
527           exstyle &= ~WS_EX_ACCEPTFILES;
528         SetWindowLongA(hWnd,GWL_EXSTYLE,exstyle);
529 }
530
531 /*************************************************************************
532  * DragFinish           [SHELL32.80]
533  */
534 void WINAPI DragFinish(HDROP h)
535 {
536         TRACE("\n");
537         GlobalFree((HGLOBAL)h);
538 }
539
540 /*************************************************************************
541  * DragQueryPoint               [SHELL32.135]
542  */
543 BOOL WINAPI DragQueryPoint(HDROP hDrop, POINT *p)
544 {
545         DROPFILES *lpDropFileStruct;
546         BOOL bRet;
547
548         TRACE("\n");
549
550         lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
551
552         *p = lpDropFileStruct->pt;
553         bRet = lpDropFileStruct->fNC;
554   
555         GlobalUnlock(hDrop);
556         return bRet;
557 }
558
559 /*************************************************************************
560  *  DragQueryFile               [SHELL32.81]
561  *  DragQueryFileA              [SHELL32.82]
562  */
563 UINT WINAPI DragQueryFileA(
564         HDROP hDrop,
565         UINT lFile,
566         LPSTR lpszFile,
567         UINT lLength)
568 {
569         LPSTR lpDrop;
570         UINT i = 0;
571         DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
572     
573         TRACE("(%08x, %x, %p, %u)\n",   hDrop,lFile,lpszFile,lLength);
574     
575         if(!lpDropFileStruct) goto end;
576
577         lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->pFiles;
578
579         while (i++ < lFile)
580         {
581           while (*lpDrop++); /* skip filename */
582           if (!*lpDrop) 
583           {
584             i = (lFile == 0xFFFFFFFF) ? i : 0; 
585             goto end;
586           }
587         }
588     
589         i = strlen(lpDrop);
590         i++;
591         if (!lpszFile ) goto end;   /* needed buffer size */
592         i = (lLength > i) ? i : lLength;
593         lstrcpynA (lpszFile,  lpDrop,  i);
594 end:
595         GlobalUnlock(hDrop);
596         return i;
597 }
598
599 /*************************************************************************
600  *  DragQueryFileW              [SHELL32.133]
601  */
602 UINT WINAPI DragQueryFileW(
603         HDROP hDrop,
604         UINT lFile,
605         LPWSTR lpszwFile,
606         UINT lLength)
607 {
608         LPWSTR lpwDrop;
609         UINT i = 0;
610         DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
611     
612         TRACE("(%08x, %x, %p, %u)\n", hDrop,lFile,lpszwFile,lLength);
613     
614         if(!lpDropFileStruct) goto end;
615
616         lpwDrop = (LPWSTR) lpDropFileStruct + lpDropFileStruct->pFiles;
617
618         i = 0;
619         while (i++ < lFile)
620         {
621           while (*lpwDrop++); /* skip filename */
622           if (!*lpwDrop) 
623           {
624             i = (lFile == 0xFFFFFFFF) ? i : 0; 
625             goto end;
626           }
627         }
628     
629         i = strlenW(lpwDrop);
630         i++;
631         if ( !lpszwFile) goto end;   /* needed buffer size */
632
633         i = (lLength > i) ? i : lLength;
634         lstrcpynW (lpszwFile, lpwDrop, i);
635 end:
636         GlobalUnlock(hDrop);
637         return i;
638 }