2 * handling of SHELL32.DLL OLE-Objects
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include "undocshell.h"
34 #include "wine/unicode.h"
35 #include "shell32_main.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
41 DWORD WINAPI
SHCLSIDFromStringA (LPCSTR clsid
, CLSID
*id
);
42 extern IShellFolder
* IShellFolder_Constructor(
45 extern HRESULT
IFSFolder_Constructor(
50 /*************************************************************************
51 * SHCoCreateInstance [SHELL32.102]
56 LRESULT WINAPI
SHCoCreateInstance(
59 LPUNKNOWN unknownouter
,
65 CLSID
* myclsid
= (CLSID
*)clsid
;
69 if (!aclsid
) return REGDB_E_CLASSNOTREG
;
70 SHCLSIDFromStringA(aclsid
, &iid
);
74 TRACE("(%p,\n\tCLSID:\t%s, unk:%p\n\tIID:\t%s,%p)\n",
75 aclsid
,debugstr_guid(myclsid
),unknownouter
,debugstr_guid(refiid
),ppv
);
77 if IsEqualCLSID(myclsid
, &CLSID_ShellFSFolder
)
79 hres
= IFSFolder_Constructor(unknownouter
, refiid
, ppv
);
84 hres
= CoCreateInstance(myclsid
, unknownouter
, CLSCTX_INPROC_SERVER
, refiid
, ppv
);
89 ERR("failed (0x%08lx) to create \n\tCLSID:\t%s\n\tIID:\t%s\n",
90 hres
, debugstr_guid(myclsid
), debugstr_guid(refiid
));
91 ERR("class not found in registry\n");
94 TRACE("-- instance: %p\n",*ppv
);
98 /*************************************************************************
99 * DllGetClassObject [SHELL32.128]
101 HRESULT WINAPI
SHELL32_DllGetClassObject(REFCLSID rclsid
, REFIID iid
,LPVOID
*ppv
)
102 { HRESULT hres
= E_OUTOFMEMORY
;
103 LPCLASSFACTORY lpclf
;
105 TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid
),debugstr_guid(iid
));
109 if(IsEqualCLSID(rclsid
, &CLSID_ShellDesktop
)||
110 IsEqualCLSID(rclsid
, &CLSID_ShellLink
))
112 lpclf
= IClassFactory_Constructor( rclsid
);
116 hres
= IClassFactory_QueryInterface(lpclf
,iid
, ppv
);
117 IClassFactory_Release(lpclf
);
122 WARN("-- CLSID not found\n");
123 hres
= CLASS_E_CLASSNOTAVAILABLE
;
125 TRACE("-- pointer to class factory: %p\n",*ppv
);
129 /*************************************************************************
130 * SHCLSIDFromString [SHELL32.147]
133 * exported by ordinal
135 DWORD WINAPI
SHCLSIDFromStringA (LPCSTR clsid
, CLSID
*id
)
138 TRACE("(%p(%s) %p)\n", clsid
, clsid
, id
);
139 if (!MultiByteToWideChar( CP_ACP
, 0, clsid
, -1, buffer
, sizeof(buffer
)/sizeof(WCHAR
) ))
140 return CO_E_CLASSSTRING
;
141 return CLSIDFromString( buffer
, id
);
143 DWORD WINAPI
SHCLSIDFromStringW (LPWSTR clsid
, CLSID
*id
)
145 TRACE("(%p(%s) %p)\n", clsid
, debugstr_w(clsid
), id
);
146 return CLSIDFromString(clsid
, id
);
148 DWORD WINAPI
SHCLSIDFromStringAW (LPVOID clsid
, CLSID
*id
)
150 if (SHELL_OsIsUnicode())
151 return SHCLSIDFromStringW (clsid
, id
);
152 return SHCLSIDFromStringA (clsid
, id
);
155 /*************************************************************************
156 * SHGetMalloc [SHELL32.@]
157 * returns the interface to shell malloc.
159 * [SDK header win95/shlobj.h:
160 * equivalent to: #define SHGetMalloc(ppmem) CoGetMalloc(MEMCTX_TASK, ppmem)
162 * What we are currently doing is not very wrong, since we always use the same
163 * heap (ProcessHeap).
165 DWORD WINAPI
SHGetMalloc(LPMALLOC
*lpmal
)
167 TRACE("(%p)\n", lpmal
);
168 return CoGetMalloc(MEMCTX_TASK
, lpmal
);
171 /*************************************************************************
172 * SHGetDesktopFolder [SHELL32.@]
174 LPSHELLFOLDER pdesktopfolder
=NULL
;
176 DWORD WINAPI
SHGetDesktopFolder(IShellFolder
**psf
)
179 LPCLASSFACTORY lpclf
;
180 TRACE("%p->(%p)\n",psf
,*psf
);
186 lpclf
= IClassFactory_Constructor(&CLSID_ShellDesktop
);
189 hres
= IClassFactory_CreateInstance(lpclf
,NULL
,(REFIID
)&IID_IShellFolder
, (void*)&pdesktopfolder
);
190 IClassFactory_Release(lpclf
);
196 /* even if we create the folder, add a ref so the application canĀ“t destroy the folder*/
197 IShellFolder_AddRef(pdesktopfolder
);
198 *psf
= pdesktopfolder
;
201 TRACE("-- %p->(%p)\n",psf
, *psf
);
205 /**************************************************************************
206 * IClassFactory Implementation
211 /* IUnknown fields */
212 ICOM_VFIELD(IClassFactory
);
217 static ICOM_VTABLE(IClassFactory
) clfvt
;
219 /**************************************************************************
220 * IClassFactory_Constructor
223 LPCLASSFACTORY
IClassFactory_Constructor(REFCLSID rclsid
)
225 IClassFactoryImpl
* lpclf
;
227 lpclf
= (IClassFactoryImpl
*)HeapAlloc(GetProcessHeap(),0,sizeof(IClassFactoryImpl
));
229 ICOM_VTBL(lpclf
) = &clfvt
;
230 lpclf
->rclsid
= (CLSID
*)rclsid
;
232 TRACE("(%p)->()\n",lpclf
);
233 InterlockedIncrement(&shell32_ObjCount
);
234 return (LPCLASSFACTORY
)lpclf
;
236 /**************************************************************************
237 * IClassFactory_QueryInterface
239 static HRESULT WINAPI
IClassFactory_fnQueryInterface(
240 LPCLASSFACTORY iface
, REFIID riid
, LPVOID
*ppvObj
)
242 ICOM_THIS(IClassFactoryImpl
,iface
);
243 TRACE("(%p)->(\n\tIID:\t%s)\n",This
,debugstr_guid(riid
));
247 if(IsEqualIID(riid
, &IID_IUnknown
)) /*IUnknown*/
250 else if(IsEqualIID(riid
, &IID_IClassFactory
)) /*IClassFactory*/
251 { *ppvObj
= (IClassFactory
*)This
;
255 { IUnknown_AddRef((LPUNKNOWN
)*ppvObj
);
256 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
259 TRACE("-- Interface: %s E_NOINTERFACE\n", debugstr_guid(riid
));
260 return E_NOINTERFACE
;
262 /******************************************************************************
263 * IClassFactory_AddRef
265 static ULONG WINAPI
IClassFactory_fnAddRef(LPCLASSFACTORY iface
)
267 ICOM_THIS(IClassFactoryImpl
,iface
);
268 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
270 InterlockedIncrement(&shell32_ObjCount
);
271 return InterlockedIncrement(&This
->ref
);
273 /******************************************************************************
274 * IClassFactory_Release
276 static ULONG WINAPI
IClassFactory_fnRelease(LPCLASSFACTORY iface
)
278 ICOM_THIS(IClassFactoryImpl
,iface
);
279 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
281 InterlockedDecrement(&shell32_ObjCount
);
282 if (!InterlockedDecrement(&This
->ref
))
284 TRACE("-- destroying IClassFactory(%p)\n",This
);
285 HeapFree(GetProcessHeap(),0,This
);
290 /******************************************************************************
291 * IClassFactory_CreateInstance
293 static HRESULT WINAPI
IClassFactory_fnCreateInstance(
294 LPCLASSFACTORY iface
, LPUNKNOWN pUnknown
, REFIID riid
, LPVOID
*ppObject
)
296 ICOM_THIS(IClassFactoryImpl
,iface
);
297 IUnknown
*pObj
= NULL
;
300 TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This
,pUnknown
,debugstr_guid(riid
),ppObject
);
306 return(CLASS_E_NOAGGREGATION
);
309 if (IsEqualCLSID(This
->rclsid
, &CLSID_ShellDesktop
))
311 pObj
= (IUnknown
*)ISF_Desktop_Constructor();
313 else if (IsEqualCLSID(This
->rclsid
, &CLSID_ShellLink
))
315 pObj
= (IUnknown
*)IShellLink_Constructor(FALSE
);
319 ERR("unknown IID requested\n\tIID:\t%s\n",debugstr_guid(riid
));
320 return(E_NOINTERFACE
);
325 return(E_OUTOFMEMORY
);
328 hres
= IUnknown_QueryInterface(pObj
,riid
, ppObject
);
329 IUnknown_Release(pObj
);
331 TRACE("-- Object created: (%p)->%p\n",This
,*ppObject
);
335 /******************************************************************************
336 * IClassFactory_LockServer
338 static HRESULT WINAPI
IClassFactory_fnLockServer(LPCLASSFACTORY iface
, BOOL fLock
)
340 ICOM_THIS(IClassFactoryImpl
,iface
);
341 TRACE("%p->(0x%x), not implemented\n",This
, fLock
);
345 static ICOM_VTABLE(IClassFactory
) clfvt
=
347 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
348 IClassFactory_fnQueryInterface
,
349 IClassFactory_fnAddRef
,
350 IClassFactory_fnRelease
,
351 IClassFactory_fnCreateInstance
,
352 IClassFactory_fnLockServer
355 /**************************************************************************
356 * Default ClassFactory Implementation
358 * SHCreateDefClassObject
361 * helper function for dll's without a own classfactory
362 * a generic classfactory is returned
363 * when the CreateInstance of the cf is called the callback is executed
365 typedef HRESULT (CALLBACK
*LPFNCREATEINSTANCE
)(IUnknown
* pUnkOuter
, REFIID riid
, LPVOID
* ppvObject
);
369 ICOM_VFIELD(IClassFactory
);
372 LPFNCREATEINSTANCE lpfnCI
;
373 const IID
* riidInst
;
374 ULONG
* pcRefDll
; /* pointer to refcounter in external dll (ugrrr...) */
377 static ICOM_VTABLE(IClassFactory
) dclfvt
;
379 /**************************************************************************
380 * IDefClF_fnConstructor
383 IClassFactory
* IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI
, PLONG pcRefDll
, REFIID riidInst
)
387 lpclf
= (IDefClFImpl
*)HeapAlloc(GetProcessHeap(),0,sizeof(IDefClFImpl
));
389 ICOM_VTBL(lpclf
) = &dclfvt
;
390 lpclf
->lpfnCI
= lpfnCI
;
391 lpclf
->pcRefDll
= pcRefDll
;
393 if (pcRefDll
) InterlockedIncrement(pcRefDll
);
394 lpclf
->riidInst
= riidInst
;
396 TRACE("(%p)\n\tIID:\t%s\n",lpclf
, debugstr_guid(riidInst
));
397 InterlockedIncrement(&shell32_ObjCount
);
398 return (LPCLASSFACTORY
)lpclf
;
400 /**************************************************************************
401 * IDefClF_fnQueryInterface
403 static HRESULT WINAPI
IDefClF_fnQueryInterface(
404 LPCLASSFACTORY iface
, REFIID riid
, LPVOID
*ppvObj
)
406 ICOM_THIS(IDefClFImpl
,iface
);
408 TRACE("(%p)->(\n\tIID:\t%s)\n",This
,debugstr_guid(riid
));
412 if(IsEqualIID(riid
, &IID_IUnknown
)) /*IUnknown*/
415 else if(IsEqualIID(riid
, &IID_IClassFactory
)) /*IClassFactory*/
416 { *ppvObj
= (IClassFactory
*)This
;
420 { IUnknown_AddRef((LPUNKNOWN
)*ppvObj
);
421 TRACE("-- Interface: (%p)->(%p)\n",ppvObj
,*ppvObj
);
424 TRACE("-- Interface: %s E_NOINTERFACE\n", debugstr_guid(riid
));
425 return E_NOINTERFACE
;
427 /******************************************************************************
430 static ULONG WINAPI
IDefClF_fnAddRef(LPCLASSFACTORY iface
)
432 ICOM_THIS(IDefClFImpl
,iface
);
433 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
435 InterlockedIncrement(&shell32_ObjCount
);
436 return InterlockedIncrement(&This
->ref
);
438 /******************************************************************************
441 static ULONG WINAPI
IDefClF_fnRelease(LPCLASSFACTORY iface
)
443 ICOM_THIS(IDefClFImpl
,iface
);
444 TRACE("(%p)->(count=%lu)\n",This
,This
->ref
);
446 InterlockedDecrement(&shell32_ObjCount
);
448 if (!InterlockedDecrement(&This
->ref
))
450 if (This
->pcRefDll
) InterlockedDecrement(This
->pcRefDll
);
452 TRACE("-- destroying IClassFactory(%p)\n",This
);
453 HeapFree(GetProcessHeap(),0,This
);
458 /******************************************************************************
459 * IDefClF_fnCreateInstance
461 static HRESULT WINAPI
IDefClF_fnCreateInstance(
462 LPCLASSFACTORY iface
, LPUNKNOWN pUnkOuter
, REFIID riid
, LPVOID
*ppvObject
)
464 ICOM_THIS(IDefClFImpl
,iface
);
466 TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This
,pUnkOuter
,debugstr_guid(riid
),ppvObject
);
471 return(CLASS_E_NOAGGREGATION
);
473 if ( This
->riidInst
==NULL
||
474 IsEqualCLSID(riid
, This
->riidInst
) ||
475 IsEqualCLSID(riid
, &IID_IUnknown
) )
477 return This
->lpfnCI(pUnkOuter
, riid
, ppvObject
);
480 ERR("unknown IID requested\n\tIID:\t%s\n",debugstr_guid(riid
));
481 return E_NOINTERFACE
;
483 /******************************************************************************
484 * IDefClF_fnLockServer
486 static HRESULT WINAPI
IDefClF_fnLockServer(LPCLASSFACTORY iface
, BOOL fLock
)
488 ICOM_THIS(IDefClFImpl
,iface
);
489 TRACE("%p->(0x%x), not implemented\n",This
, fLock
);
493 static ICOM_VTABLE(IClassFactory
) dclfvt
=
495 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
496 IDefClF_fnQueryInterface
,
499 IDefClF_fnCreateInstance
,
503 /******************************************************************************
504 * SHCreateDefClassObject [SHELL32.70]
506 HRESULT WINAPI
SHCreateDefClassObject(
509 LPFNCREATEINSTANCE lpfnCI
, /* [in] create instance callback entry */
510 LPDWORD pcRefDll
, /* [in/out] ref count of the dll */
511 REFIID riidInst
) /* [in] optional interface to the instance */
513 TRACE("\n\tIID:\t%s %p %p %p \n\tIIDIns:\t%s\n",
514 debugstr_guid(riid
), ppv
, lpfnCI
, pcRefDll
, debugstr_guid(riidInst
));
516 if ( IsEqualCLSID(riid
, &IID_IClassFactory
) )
518 IClassFactory
* pcf
= IDefClF_fnConstructor(lpfnCI
, pcRefDll
, riidInst
);
524 return E_OUTOFMEMORY
;
526 return E_NOINTERFACE
;
529 /*************************************************************************
530 * DragAcceptFiles [SHELL32.54]
532 void WINAPI
DragAcceptFiles(HWND hWnd
, BOOL b
)
536 if( !IsWindow(hWnd
) ) return;
537 exstyle
= GetWindowLongA(hWnd
,GWL_EXSTYLE
);
539 exstyle
|= WS_EX_ACCEPTFILES
;
541 exstyle
&= ~WS_EX_ACCEPTFILES
;
542 SetWindowLongA(hWnd
,GWL_EXSTYLE
,exstyle
);
545 /*************************************************************************
546 * DragFinish [SHELL32.80]
548 void WINAPI
DragFinish(HDROP h
)
551 GlobalFree((HGLOBAL
)h
);
554 /*************************************************************************
555 * DragQueryPoint [SHELL32.135]
557 BOOL WINAPI
DragQueryPoint(HDROP hDrop
, POINT
*p
)
559 DROPFILES
*lpDropFileStruct
;
564 lpDropFileStruct
= (DROPFILES
*) GlobalLock(hDrop
);
566 *p
= lpDropFileStruct
->pt
;
567 bRet
= lpDropFileStruct
->fNC
;
573 /*************************************************************************
574 * DragQueryFile [SHELL32.81]
575 * DragQueryFileA [SHELL32.82]
577 UINT WINAPI
DragQueryFileA(
585 DROPFILES
*lpDropFileStruct
= (DROPFILES
*) GlobalLock(hDrop
);
587 TRACE("(%08x, %x, %p, %u)\n", hDrop
,lFile
,lpszFile
,lLength
);
589 if(!lpDropFileStruct
) goto end
;
591 lpDrop
= (LPSTR
) lpDropFileStruct
+ lpDropFileStruct
->pFiles
;
595 while (*lpDrop
++); /* skip filename */
598 i
= (lFile
== 0xFFFFFFFF) ? i
: 0;
605 if (!lpszFile
) goto end
; /* needed buffer size */
606 i
= (lLength
> i
) ? i
: lLength
;
607 lstrcpynA (lpszFile
, lpDrop
, i
);
613 /*************************************************************************
614 * DragQueryFileW [SHELL32.133]
616 UINT WINAPI
DragQueryFileW(
624 DROPFILES
*lpDropFileStruct
= (DROPFILES
*) GlobalLock(hDrop
);
626 TRACE("(%08x, %x, %p, %u)\n", hDrop
,lFile
,lpszwFile
,lLength
);
628 if(!lpDropFileStruct
) goto end
;
630 lpwDrop
= (LPWSTR
) lpDropFileStruct
+ lpDropFileStruct
->pFiles
;
635 while (*lpwDrop
++); /* skip filename */
638 i
= (lFile
== 0xFFFFFFFF) ? i
: 0;
643 i
= strlenW(lpwDrop
);
645 if ( !lpszwFile
) goto end
; /* needed buffer size */
647 i
= (lLength
> i
) ? i
: lLength
;
648 lstrcpynW (lpszwFile
, lpwDrop
, i
);