source: trunk/src/shell32/new/shellole.cpp@ 791

Last change on this file since 791 was 791, checked in by phaller, 26 years ago

Add: shell32/new - a direct port of WINE's Shell32 implmentation

File size: 13.2 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#include <odin.h>
12
13#define ICOM_CINTERFACE 1
14#define CINTERFACE 1
15
16#include "wine/obj_base.h"
17#include "wine/obj_shelllink.h"
18#include "wine/obj_shellfolder.h"
19#include "wine/obj_shellbrowser.h"
20#include "wine/obj_contextmenu.h"
21#include "wine/obj_shellextinit.h"
22#include "wine/obj_extracticon.h"
23
24#include "shlguid.h"
25#include "winversion.h"
26#include "winreg.h"
27#include "winerror.h"
28#include "debugtools.h"
29
30#include "shell32_main.h"
31
32#include <misc.h>
33
34DEFAULT_DEBUG_CHANNEL(shell)
35
36DWORD WINAPI SHCLSIDFromStringA (LPSTR clsid, CLSID *id);
37
38/*************************************************************************
39 * SHCoCreateInstance [SHELL32.102]
40 *
41 * NOTES
42 * exported by ordinal
43 */
44LRESULT WINAPI SHCoCreateInstance(
45 LPSTR aclsid,
46 REFCLSID clsid,
47 IUnknown * unknownouter,
48 REFIID refiid,
49 LPVOID *ppv)
50{
51 char xclsid[48], xiid[48], xuout[48];
52 DWORD hres;
53 IID iid;
54 CLSID * myclsid = (CLSID*)clsid;
55
56 WINE_StringFromCLSID(refiid,xiid);
57
58 if (!clsid)
59 {
60 if (!aclsid) return REGDB_E_CLASSNOTREG;
61 SHCLSIDFromStringA(aclsid, &iid);
62 myclsid = &iid;
63 }
64
65 WINE_StringFromCLSID(myclsid,xclsid);
66 WINE_StringFromCLSID(refiid,xiid);
67 if (unknownouter)
68 WINE_StringFromCLSID(unknownouter,xuout);
69
70 TRACE("(%p,\n\tCLSID:\t%s\n\tUOUT:\t%s\n\tIID:\t%s,%p)\n",
71 aclsid,xclsid,unknownouter?xuout:"nil",xiid,ppv);
72
73 hres = CoCreateInstance(myclsid, NULL, CLSCTX_INPROC_SERVER, refiid, ppv);
74
75 if(hres!=S_OK)
76 {
77 ERR("failed (0x%08lx) to create \n\tCLSID:\t%s\n\tIID:\t%s\n", hres, xclsid, xiid);
78 ERR("you might need to import the winedefault.reg\n");
79 }
80
81 return hres;
82}
83
84/*************************************************************************
85 * SHELL32_DllGetClassObject [SHELL32.128]
86 */
87HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
88{ HRESULT hres = E_OUTOFMEMORY;
89 LPCLASSFACTORY lpclf;
90
91 char xclsid[50],xiid[50];
92 WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
93 WINE_StringFromCLSID((LPCLSID)iid,xiid);
94 TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",xclsid,xiid);
95
96 *ppv = NULL;
97
98 if(IsEqualCLSID(rclsid, &CLSID_PaperBin))
99 {
100 ERR("paper bin not implemented\n");
101 return CLASS_E_CLASSNOTAVAILABLE;
102 }
103 if(IsEqualCLSID(rclsid, &CLSID_ShellDesktop)||
104 IsEqualCLSID(rclsid, &CLSID_ShellLink))
105 {
106 lpclf = IClassFactory_Constructor( rclsid );
107
108 if(lpclf)
109 {
110 hres = IClassFactory_QueryInterface(lpclf,iid, ppv);
111 IClassFactory_Release(lpclf);
112 }
113 }
114 else
115 {
116 WARN("-- CLSID not found\n");
117 hres = CLASS_E_CLASSNOTAVAILABLE;
118 }
119 TRACE("-- pointer to class factory: %p\n",*ppv);
120 return hres;
121}
122
123/*************************************************************************
124 * SHCLSIDFromString [SHELL32.147]
125 *
126 * NOTES
127 * exported by ordinal
128 */
129DWORD WINAPI SHCLSIDFromStringA (LPSTR clsid, CLSID *id)
130{
131 TRACE("(%p(%s) %p)\n", clsid, clsid, id);
132 return CLSIDFromString16(clsid, id);
133}
134DWORD WINAPI SHCLSIDFromStringW (LPWSTR clsid, CLSID *id)
135{
136 TRACE("(%p(%s) %p)\n", clsid, debugstr_w(clsid), id);
137 return CLSIDFromString(clsid, id);
138}
139DWORD WINAPI SHCLSIDFromStringAW (LPVOID clsid, CLSID *id)
140{
141 if (VERSION_OsIsUnicode())
142 return SHCLSIDFromStringW (clsid, id);
143 return SHCLSIDFromStringA (clsid, id);
144}
145
146/*************************************************************************
147 * SHGetMalloc [SHELL32.220]
148 * returns the interface to shell malloc.
149 *
150 * [SDK header win95/shlobj.h:
151 * equivalent to: #define SHGetMalloc(ppmem) CoGetMalloc(MEMCTX_TASK, ppmem)
152 * ]
153 * What we are currently doing is not very wrong, since we always use the same
154 * heap (ProcessHeap).
155 */
156DWORD WINAPI SHGetMalloc(LPMALLOC *lpmal)
157{
158 TRACE("(%p)\n", lpmal);
159 return CoGetMalloc(0,lpmal);
160}
161
162/*************************************************************************
163 * SHGetDesktopFolder [SHELL32.216]
164 */
165LPSHELLFOLDER pdesktopfolder=NULL;
166
167DWORD WINAPI SHGetDesktopFolder(IShellFolder **psf)
168{
169 HRESULT hres = S_OK;
170 LPCLASSFACTORY lpclf;
171 TRACE_(shell)("%p->(%p)\n",psf,*psf);
172
173 *psf=NULL;
174
175 if (!pdesktopfolder)
176 {
177 lpclf = IClassFactory_Constructor(&CLSID_ShellDesktop);
178 if(lpclf)
179 {
180 hres = IClassFactory_CreateInstance(lpclf,NULL,(REFIID)&IID_IShellFolder, (void*)&pdesktopfolder);
181 IClassFactory_Release(lpclf);
182 }
183 }
184
185 if (pdesktopfolder)
186 {
187 /* even if we create the folder, add a ref so the application canŽt destroy the folder*/
188 IShellFolder_AddRef(pdesktopfolder);
189 *psf = pdesktopfolder;
190 }
191
192 TRACE_(shell)("-- %p->(%p)\n",psf, *psf);
193 return hres;
194}
195
196/**************************************************************************
197* IClassFactory Implementation
198*/
199
200typedef struct
201{
202 /* IUnknown fields */
203 ICOM_VTABLE(IClassFactory)* lpvtbl;
204 DWORD ref;
205 CLSID *rclsid;
206} IClassFactoryImpl;
207
208static ICOM_VTABLE(IClassFactory) clfvt;
209
210/**************************************************************************
211 * IClassFactory_Constructor
212 */
213
214LPCLASSFACTORY IClassFactory_Constructor(REFCLSID rclsid)
215{
216 IClassFactoryImpl* lpclf;
217
218 lpclf= (IClassFactoryImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IClassFactoryImpl));
219 lpclf->ref = 1;
220 lpclf->lpvtbl = &clfvt;
221 lpclf->rclsid = (CLSID*)rclsid;
222
223 TRACE("(%p)->()\n",lpclf);
224 shell32_ObjCount++;
225 return (LPCLASSFACTORY)lpclf;
226}
227/**************************************************************************
228 * IClassFactory_QueryInterface
229 */
230static HRESULT WINAPI IClassFactory_fnQueryInterface(
231 LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
232{
233 ICOM_THIS(IClassFactoryImpl,iface);
234 char xriid[50];
235 WINE_StringFromCLSID((LPCLSID)riid,xriid);
236 TRACE("(%p)->(\n\tIID:\t%s)\n",This,xriid);
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", xriid);
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 shell32_ObjCount++;
264 return ++(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 shell32_ObjCount--;
275 if (!--(This->ref))
276 { TRACE("-- destroying IClassFactory(%p)\n",This);
277 HeapFree(GetProcessHeap(),0,This);
278 return 0;
279 }
280 return This->ref;
281}
282/******************************************************************************
283 * IClassFactory_CreateInstance
284 */
285static HRESULT WINAPI IClassFactory_fnCreateInstance(
286 LPCLASSFACTORY iface, LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
287{
288 ICOM_THIS(IClassFactoryImpl,iface);
289 IUnknown *pObj = NULL;
290 HRESULT hres;
291 char xriid[50];
292
293 WINE_StringFromCLSID((LPCLSID)riid,xriid);
294 TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnknown,xriid,ppObject);
295
296 *ppObject = NULL;
297
298 if(pUnknown)
299 {
300 return(CLASS_E_NOAGGREGATION);
301 }
302
303 if (IsEqualCLSID(This->rclsid, &CLSID_ShellDesktop))
304 {
305 pObj = (IUnknown *)ISF_Desktop_Constructor();
306 }
307 else if (IsEqualCLSID(This->rclsid, &CLSID_ShellLink))
308 {
309 pObj = (IUnknown *)IShellLink_Constructor(FALSE);
310 }
311 else
312 {
313 ERR("unknown IID requested\n\tIID:\t%s\n",xriid);
314 return(E_NOINTERFACE);
315 }
316
317 if (!pObj)
318 {
319 return(E_OUTOFMEMORY);
320 }
321
322 hres = IUnknown_QueryInterface(pObj,riid, ppObject);
323 IUnknown_Release(pObj);
324
325 TRACE("-- Object created: (%p)->%p\n",This,*ppObject);
326
327 return hres;
328}
329/******************************************************************************
330 * IClassFactory_LockServer
331 */
332static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
333{
334 ICOM_THIS(IClassFactoryImpl,iface);
335 TRACE("%p->(0x%x), not implemented\n",This, fLock);
336 return E_NOTIMPL;
337}
338
339static ICOM_VTABLE(IClassFactory) clfvt =
340{
341 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
342 IClassFactory_fnQueryInterface,
343 IClassFactory_fnAddRef,
344 IClassFactory_fnRelease,
345 IClassFactory_fnCreateInstance,
346 IClassFactory_fnLockServer
347};
348
349/**************************************************************************
350 * Default ClassFactory Implementation
351 *
352 * SHCreateDefClassObject
353 *
354 * NOTES
355 * helper function for dll's without a own classfactory
356 * a generic classfactory is returned
357 * when the CreateInstance of the cf is called the callback is executed
358 */
359typedef HRESULT (CALLBACK * LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
360
361typedef struct
362{
363 ICOM_VTABLE(IClassFactory)* lpvtbl;
364 DWORD ref;
365 CLSID *rclsid;
366 LPFNCREATEINSTANCE lpfnCI;
367 const IID * riidInst;
368 UINT * pcRefDll; /* pointer to refcounter in external dll (ugrrr...) */
369} IDefClFImpl;
370
371static ICOM_VTABLE(IClassFactory) dclfvt;
372
373/**************************************************************************
374 * IDefClF_fnConstructor
375 */
376
377IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, UINT * pcRefDll, REFIID riidInst)
378{
379 IDefClFImpl* lpclf;
380 char xriidInst[50];
381
382 WINE_StringFromCLSID((LPCLSID)riidInst,xriidInst);
383
384 lpclf = (IDefClFImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDefClFImpl));
385 lpclf->ref = 1;
386 lpclf->lpvtbl = &dclfvt;
387 lpclf->lpfnCI = lpfnCI;
388 lpclf->pcRefDll = pcRefDll;
389
390 if (pcRefDll)
391 (*pcRefDll)++;
392
393 lpclf->riidInst = riidInst;
394
395 TRACE("(%p)\n\tIID:\t%s\n",lpclf, xriidInst);
396 shell32_ObjCount++;
397 return (LPCLASSFACTORY)lpclf;
398}
399/**************************************************************************
400 * IDefClF_fnQueryInterface
401 */
402static HRESULT WINAPI IDefClF_fnQueryInterface(
403 LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
404{
405 ICOM_THIS(IDefClFImpl,iface);
406 char xriid[50];
407 WINE_StringFromCLSID((LPCLSID)riid,xriid);
408 TRACE("(%p)->(\n\tIID:\t%s)\n",This,xriid);
409
410 *ppvObj = NULL;
411
412 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
413 { *ppvObj = This;
414 }
415 else if(IsEqualIID(riid, &IID_IClassFactory)) /*IClassFactory*/
416 { *ppvObj = (IClassFactory*)This;
417 }
418
419 if(*ppvObj)
420 { IUnknown_AddRef((LPUNKNOWN)*ppvObj);
421 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
422 return S_OK;
423 }
424 TRACE("-- Interface: %s E_NOINTERFACE\n", xriid);
425 return E_NOINTERFACE;
426}
427/******************************************************************************
428 * IDefClF_fnAddRef
429 */
430static ULONG WINAPI IDefClF_fnAddRef(LPCLASSFACTORY iface)
431{
432 ICOM_THIS(IDefClFImpl,iface);
433 TRACE("(%p)->(count=%lu)\n",This,This->ref);
434
435 shell32_ObjCount++;
436
437 return ++(This->ref);
438}
439/******************************************************************************
440 * IDefClF_fnRelease
441 */
442static ULONG WINAPI IDefClF_fnRelease(LPCLASSFACTORY iface)
443{
444 ICOM_THIS(IDefClFImpl,iface);
445 TRACE("(%p)->(count=%lu)\n",This,This->ref);
446
447 shell32_ObjCount--;
448
449 if (!--(This->ref))
450 {
451 if (This->pcRefDll)
452 (*This->pcRefDll)--;
453
454 TRACE("-- destroying IClassFactory(%p)\n",This);
455 HeapFree(GetProcessHeap(),0,This);
456 return 0;
457 }
458 return This->ref;
459}
460/******************************************************************************
461 * IDefClF_fnCreateInstance
462 */
463static HRESULT WINAPI IDefClF_fnCreateInstance(
464 LPCLASSFACTORY iface, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject)
465{
466 ICOM_THIS(IDefClFImpl,iface);
467 char xriid[50];
468
469 WINE_StringFromCLSID((LPCLSID)riid,xriid);
470 TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnkOuter,xriid,ppvObject);
471
472 *ppvObject = NULL;
473
474 if(pUnkOuter)
475 return(CLASS_E_NOAGGREGATION);
476
477 if ( This->riidInst==NULL ||
478 IsEqualCLSID(riid, This->riidInst) ||
479 IsEqualCLSID(riid, &IID_IUnknown) )
480 {
481 return This->lpfnCI(pUnkOuter, riid, ppvObject);
482 }
483
484 ERR("unknown IID requested\n\tIID:\t%s\n",xriid);
485 return E_NOINTERFACE;
486}
487/******************************************************************************
488 * IDefClF_fnLockServer
489 */
490static HRESULT WINAPI IDefClF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
491{
492 ICOM_THIS(IDefClFImpl,iface);
493 TRACE("%p->(0x%x), not implemented\n",This, fLock);
494 return E_NOTIMPL;
495}
496
497static ICOM_VTABLE(IClassFactory) dclfvt =
498{
499 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
500 IDefClF_fnQueryInterface,
501 IDefClF_fnAddRef,
502 IDefClF_fnRelease,
503 IDefClF_fnCreateInstance,
504 IDefClF_fnLockServer
505};
506
507/******************************************************************************
508 * SHCreateDefClassObject [SHELL32.70]
509 */
510HRESULT WINAPI SHCreateDefClassObject(
511 REFIID riid,
512 LPVOID* ppv,
513 LPFNCREATEINSTANCE lpfnCI, /* create instance callback entry */
514 UINT *pcRefDll, /* ref count of the dll */
515 REFIID riidInst) /* optional interface to the instance */
516{
517
518 char xriid[50],xriidInst[50];
519 WINE_StringFromCLSID((LPCLSID)riid,xriid);
520 WINE_StringFromCLSID((LPCLSID)riidInst,xriidInst);
521
522 TRACE("\n\tIID:\t%s %p %p %p \n\tIIDIns:\t%s\n",
523 xriid, ppv, lpfnCI, pcRefDll, xriidInst);
524
525 if ( IsEqualCLSID(riid, &IID_IClassFactory) )
526 {
527 IClassFactory * pcf = IDefClF_fnConstructor(lpfnCI, pcRefDll, riidInst);
528 if (pcf)
529 {
530 *ppv = pcf;
531 return NOERROR;
532 }
533 return E_OUTOFMEMORY;
534 }
535 return E_NOINTERFACE;
536}
537
Note: See TracBrowser for help on using the repository browser.