source: trunk/src/shell32/shellole.c@ 5655

Last change on this file since 5655 was 5618, checked in by sandervl, 24 years ago

resync with latest wine

File size: 15.7 KB
Line 
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 "shlobj.h"
13#include "shellapi.h"
14#include "shlguid.h"
15#include "winreg.h"
16#include "wine/unicode.h"
17#include "winerror.h"
18#include "debugtools.h"
19
20#include "shell32_main.h"
21
22DEFAULT_DEBUG_CHANNEL(shell);
23
24DWORD WINAPI SHCLSIDFromStringA (LPSTR clsid, CLSID *id);
25extern IShellFolder * IShellFolder_Constructor(
26 IShellFolder * psf,
27 LPITEMIDLIST pidl);
28extern HRESULT IFSFolder_Constructor(
29 IUnknown * pUnkOuter,
30 REFIID riid,
31 LPVOID * ppv);
32
33/*************************************************************************
34 * SHCoCreateInstance [SHELL32.102]
35 *
36 * NOTES
37 * exported by ordinal
38 */
39LRESULT WINAPI SHCoCreateInstance(
40 LPSTR aclsid,
41 REFCLSID clsid,
42 IUnknown * unknownouter,
43 REFIID refiid,
44 LPVOID *ppv)
45{
46 DWORD hres;
47 IID iid;
48 CLSID * myclsid = (CLSID*)clsid;
49
50 if (!clsid)
51 {
52 if (!aclsid) return REGDB_E_CLASSNOTREG;
53 SHCLSIDFromStringA(aclsid, &iid);
54 myclsid = &iid;
55 }
56
57 TRACE("(%p,\n\tCLSID:\t%s, unk:%p\n\tIID:\t%s,%p)\n",
58 aclsid,debugstr_guid(myclsid),unknownouter,debugstr_guid(refiid),ppv);
59
60 if IsEqualCLSID(myclsid, &CLSID_ShellFSFolder)
61 {
62 hres = IFSFolder_Constructor(unknownouter, refiid, ppv);
63 }
64 else
65 {
66 hres = CoCreateInstance(myclsid, unknownouter, CLSCTX_INPROC_SERVER, refiid, ppv);
67 }
68
69 if(hres!=S_OK)
70 {
71 ERR("failed (0x%08lx) to create \n\tCLSID:\t%s\n\tIID:\t%s\n",
72 hres, debugstr_guid(myclsid), debugstr_guid(refiid));
73 ERR("class not found in registry\n");
74 }
75
76 TRACE("-- instance: %p\n",*ppv);
77 return hres;
78}
79
80/*************************************************************************
81 * SHELL32_DllGetClassObject [SHELL32.128]
82 */
83HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
84{ HRESULT hres = E_OUTOFMEMORY;
85 LPCLASSFACTORY lpclf;
86
87 TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
88
89 *ppv = NULL;
90
91 if(IsEqualCLSID(rclsid, &CLSID_ShellDesktop)||
92 IsEqualCLSID(rclsid, &CLSID_ShellLink))
93 {
94 lpclf = IClassFactory_Constructor( rclsid );
95
96 if(lpclf)
97 {
98 hres = IClassFactory_QueryInterface(lpclf,iid, ppv);
99 IClassFactory_Release(lpclf);
100 }
101 }
102 else
103 {
104 WARN("-- CLSID not found\n");
105 hres = CLASS_E_CLASSNOTAVAILABLE;
106 }
107 TRACE("-- pointer to class factory: %p\n",*ppv);
108 return hres;
109}
110
111/*************************************************************************
112 * SHCLSIDFromString [SHELL32.147]
113 *
114 * NOTES
115 * exported by ordinal
116 */
117DWORD WINAPI SHCLSIDFromStringA (LPSTR clsid, CLSID *id)
118{
119 WCHAR buffer[40];
120 TRACE("(%p(%s) %p)\n", clsid, clsid, id);
121 if (!MultiByteToWideChar( CP_ACP, 0, clsid, -1, buffer, sizeof(buffer)/sizeof(WCHAR) ))
122 return CO_E_CLASSSTRING;
123 return CLSIDFromString( buffer, id );
124}
125DWORD WINAPI SHCLSIDFromStringW (LPWSTR clsid, CLSID *id)
126{
127 TRACE("(%p(%s) %p)\n", clsid, debugstr_w(clsid), id);
128 return CLSIDFromString(clsid, id);
129}
130DWORD WINAPI SHCLSIDFromStringAW (LPVOID clsid, CLSID *id)
131{
132 if (SHELL_OsIsUnicode())
133 return SHCLSIDFromStringW (clsid, id);
134 return SHCLSIDFromStringA (clsid, id);
135}
136
137/*************************************************************************
138 * SHGetMalloc [SHELL32.220]
139 * returns the interface to shell malloc.
140 *
141 * [SDK header win95/shlobj.h:
142 * equivalent to: #define SHGetMalloc(ppmem) CoGetMalloc(MEMCTX_TASK, ppmem)
143 * ]
144 * What we are currently doing is not very wrong, since we always use the same
145 * heap (ProcessHeap).
146 */
147DWORD WINAPI SHGetMalloc(LPMALLOC *lpmal)
148{
149 TRACE("(%p)\n", lpmal);
150 return CoGetMalloc(MEMCTX_TASK, lpmal);
151}
152
153/*************************************************************************
154 * SHGetDesktopFolder [SHELL32.216]
155 */
156LPSHELLFOLDER pdesktopfolder=NULL;
157
158DWORD WINAPI SHGetDesktopFolder(IShellFolder **psf)
159{
160 HRESULT hres = S_OK;
161 LPCLASSFACTORY lpclf;
162 TRACE("%p->(%p)\n",psf,*psf);
163
164 *psf=NULL;
165
166 if (!pdesktopfolder)
167 {
168 lpclf = IClassFactory_Constructor(&CLSID_ShellDesktop);
169 if(lpclf)
170 {
171 hres = IClassFactory_CreateInstance(lpclf,NULL,(REFIID)&IID_IShellFolder, (void*)&pdesktopfolder);
172 IClassFactory_Release(lpclf);
173 }
174 }
175
176 if (pdesktopfolder)
177 {
178 /* even if we create the folder, add a ref so the application canŽt destroy the folder*/
179 IShellFolder_AddRef(pdesktopfolder);
180 *psf = pdesktopfolder;
181 }
182
183 TRACE("-- %p->(%p)\n",psf, *psf);
184 return hres;
185}
186
187/**************************************************************************
188* IClassFactory Implementation
189*/
190
191typedef struct
192{
193 /* IUnknown fields */
194 ICOM_VFIELD(IClassFactory);
195 DWORD ref;
196 CLSID *rclsid;
197} IClassFactoryImpl;
198
199static ICOM_VTABLE(IClassFactory) clfvt;
200
201/**************************************************************************
202 * IClassFactory_Constructor
203 */
204
205LPCLASSFACTORY IClassFactory_Constructor(REFCLSID rclsid)
206{
207 IClassFactoryImpl* lpclf;
208
209 lpclf= (IClassFactoryImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IClassFactoryImpl));
210 lpclf->ref = 1;
211 ICOM_VTBL(lpclf) = &clfvt;
212 lpclf->rclsid = (CLSID*)rclsid;
213
214 TRACE("(%p)->()\n",lpclf);
215 InterlockedIncrement(&shell32_ObjCount);
216 return (LPCLASSFACTORY)lpclf;
217}
218/**************************************************************************
219 * IClassFactory_QueryInterface
220 */
221static HRESULT WINAPI IClassFactory_fnQueryInterface(
222 LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
223{
224 ICOM_THIS(IClassFactoryImpl,iface);
225 TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
226
227 *ppvObj = NULL;
228
229 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
230 { *ppvObj = This;
231 }
232 else if(IsEqualIID(riid, &IID_IClassFactory)) /*IClassFactory*/
233 { *ppvObj = (IClassFactory*)This;
234 }
235
236 if(*ppvObj)
237 { IUnknown_AddRef((LPUNKNOWN)*ppvObj);
238 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
239 return S_OK;
240 }
241 TRACE("-- Interface: %s E_NOINTERFACE\n", debugstr_guid(riid));
242 return E_NOINTERFACE;
243}
244/******************************************************************************
245 * IClassFactory_AddRef
246 */
247static ULONG WINAPI IClassFactory_fnAddRef(LPCLASSFACTORY iface)
248{
249 ICOM_THIS(IClassFactoryImpl,iface);
250 TRACE("(%p)->(count=%lu)\n",This,This->ref);
251
252 InterlockedIncrement(&shell32_ObjCount);
253 return InterlockedIncrement(&This->ref);
254}
255/******************************************************************************
256 * IClassFactory_Release
257 */
258static ULONG WINAPI IClassFactory_fnRelease(LPCLASSFACTORY iface)
259{
260 ICOM_THIS(IClassFactoryImpl,iface);
261 TRACE("(%p)->(count=%lu)\n",This,This->ref);
262
263 InterlockedDecrement(&shell32_ObjCount);
264 if (!InterlockedDecrement(&This->ref))
265 {
266 TRACE("-- destroying IClassFactory(%p)\n",This);
267 HeapFree(GetProcessHeap(),0,This);
268 return 0;
269 }
270 return This->ref;
271}
272/******************************************************************************
273 * IClassFactory_CreateInstance
274 */
275static HRESULT WINAPI IClassFactory_fnCreateInstance(
276 LPCLASSFACTORY iface, LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
277{
278 ICOM_THIS(IClassFactoryImpl,iface);
279 IUnknown *pObj = NULL;
280 HRESULT hres;
281
282 TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnknown,debugstr_guid(riid),ppObject);
283
284 *ppObject = NULL;
285
286 if(pUnknown)
287 {
288 return(CLASS_E_NOAGGREGATION);
289 }
290
291 if (IsEqualCLSID(This->rclsid, &CLSID_ShellDesktop))
292 {
293 pObj = (IUnknown *)ISF_Desktop_Constructor();
294 }
295 else if (IsEqualCLSID(This->rclsid, &CLSID_ShellLink))
296 {
297 pObj = (IUnknown *)IShellLink_Constructor(FALSE);
298 }
299 else
300 {
301 ERR("unknown IID requested\n\tIID:\t%s\n",debugstr_guid(riid));
302 return(E_NOINTERFACE);
303 }
304
305 if (!pObj)
306 {
307 return(E_OUTOFMEMORY);
308 }
309
310 hres = IUnknown_QueryInterface(pObj,riid, ppObject);
311 IUnknown_Release(pObj);
312
313 TRACE("-- Object created: (%p)->%p\n",This,*ppObject);
314
315 return hres;
316}
317/******************************************************************************
318 * IClassFactory_LockServer
319 */
320static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
321{
322 ICOM_THIS(IClassFactoryImpl,iface);
323 TRACE("%p->(0x%x), not implemented\n",This, fLock);
324 return E_NOTIMPL;
325}
326
327static ICOM_VTABLE(IClassFactory) clfvt =
328{
329 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
330 IClassFactory_fnQueryInterface,
331 IClassFactory_fnAddRef,
332 IClassFactory_fnRelease,
333 IClassFactory_fnCreateInstance,
334 IClassFactory_fnLockServer
335};
336
337/**************************************************************************
338 * Default ClassFactory Implementation
339 *
340 * SHCreateDefClassObject
341 *
342 * NOTES
343 * helper function for dll's without a own classfactory
344 * a generic classfactory is returned
345 * when the CreateInstance of the cf is called the callback is executed
346 */
347#ifdef __WIN32OS2__
348typedef HRESULT (* CALLBACK LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
349#else
350typedef HRESULT CALLBACK (*LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
351#endif
352
353typedef 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
363static ICOM_VTABLE(IClassFactory) dclfvt;
364
365/**************************************************************************
366 * IDefClF_fnConstructor
367 */
368
369IClassFactory * 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 */
389static 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 */
416static 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 */
427static 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 */
447static 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 */
472static 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
479static 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 */
492HRESULT WINAPI SHCreateDefClassObject(
493 REFIID riid,
494 LPVOID* ppv,
495 LPFNCREATEINSTANCE lpfnCI, /* [in] create instance callback entry */
496 PLONG 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 */
518void 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 */
534void WINAPI DragFinish(HDROP h)
535{
536 TRACE("\n");
537 GlobalFree((HGLOBAL)h);
538}
539
540/*************************************************************************
541 * DragQueryPoint [SHELL32.135]
542 */
543BOOL 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 * DragQueryFileA [SHELL32.81] [shell32.82]
561 */
562UINT WINAPI DragQueryFileA(
563 HDROP hDrop,
564 UINT lFile,
565 LPSTR lpszFile,
566 UINT lLength)
567{
568 LPSTR lpDrop;
569 UINT i = 0;
570 DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
571
572 TRACE("(%08x, %x, %p, %u)\n", hDrop,lFile,lpszFile,lLength);
573
574 if(!lpDropFileStruct) goto end;
575
576 lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->pFiles;
577
578 while (i++ < lFile)
579 {
580 while (*lpDrop++); /* skip filename */
581 if (!*lpDrop)
582 {
583 i = (lFile == 0xFFFFFFFF) ? i : 0;
584 goto end;
585 }
586 }
587
588 i = strlen(lpDrop);
589 i++;
590 if (!lpszFile ) goto end; /* needed buffer size */
591 i = (lLength > i) ? i : lLength;
592 lstrcpynA (lpszFile, lpDrop, i);
593end:
594 GlobalUnlock(hDrop);
595 return i;
596}
597
598/*************************************************************************
599 * DragQueryFileW [shell32.133]
600 */
601UINT WINAPI DragQueryFileW(
602 HDROP hDrop,
603 UINT lFile,
604 LPWSTR lpszwFile,
605 UINT lLength)
606{
607 LPWSTR lpwDrop;
608 UINT i = 0;
609 DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
610
611 TRACE("(%08x, %x, %p, %u)\n", hDrop,lFile,lpszwFile,lLength);
612
613 if(!lpDropFileStruct) goto end;
614
615 lpwDrop = (LPWSTR) lpDropFileStruct + lpDropFileStruct->pFiles;
616
617 i = 0;
618 while (i++ < lFile)
619 {
620 while (*lpwDrop++); /* skip filename */
621 if (!*lpwDrop)
622 {
623 i = (lFile == 0xFFFFFFFF) ? i : 0;
624 goto end;
625 }
626 }
627
628 i = strlenW(lpwDrop);
629 i++;
630 if ( !lpszwFile) goto end; /* needed buffer size */
631
632 i = (lLength > i) ? i : lLength;
633 lstrcpynW (lpszwFile, lpwDrop, i);
634end:
635 GlobalUnlock(hDrop);
636 return i;
637}
Note: See TracBrowser for help on using the repository browser.