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

Last change on this file since 5087 was 4121, checked in by sandervl, 25 years ago

complete merge with shell32 from wine 20000801

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