Use documented DROPFILES structure instead of internal DROPFILESTRUCT.
[wine.git] / dlls / shell32 / shellole.c
blob421fe868035f3ab4d54148406262ca84fc4c609d
1 /*
2 * handling of SHELL32.DLL OLE-Objects
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998 Juergen Schmied <juergen.schmied@metronet.de>
7 */
9 #include <stdlib.h>
10 #include <string.h>
12 #include "shlobj.h"
13 #include "shlguid.h"
14 #include "winreg.h"
15 #include "wine/unicode.h"
16 #include "winerror.h"
17 #include "debugtools.h"
19 #include "shell32_main.h"
21 DEFAULT_DEBUG_CHANNEL(shell);
23 DWORD WINAPI SHCLSIDFromStringA (LPSTR clsid, CLSID *id);
24 extern IShellFolder * IShellFolder_Constructor(
25 IShellFolder * psf,
26 LPITEMIDLIST pidl);
27 extern HRESULT IFSFolder_Constructor(
28 IUnknown * pUnkOuter,
29 REFIID riid,
30 LPVOID * ppv);
32 /*************************************************************************
33 * SHCoCreateInstance [SHELL32.102]
35 * NOTES
36 * exported by ordinal
38 LRESULT WINAPI SHCoCreateInstance(
39 LPSTR aclsid,
40 REFCLSID clsid,
41 IUnknown * unknownouter,
42 REFIID refiid,
43 LPVOID *ppv)
45 DWORD hres;
46 IID iid;
47 CLSID * myclsid = (CLSID*)clsid;
49 if (!clsid)
51 if (!aclsid) return REGDB_E_CLASSNOTREG;
52 SHCLSIDFromStringA(aclsid, &iid);
53 myclsid = &iid;
56 TRACE("(%p,\n\tCLSID:\t%s, unk:%p\n\tIID:\t%s,%p)\n",
57 aclsid,debugstr_guid(myclsid),unknownouter,debugstr_guid(refiid),ppv);
59 if IsEqualCLSID(myclsid, &CLSID_ShellFSFolder)
61 hres = IFSFolder_Constructor(unknownouter, refiid, ppv);
63 else
65 hres = CoCreateInstance(myclsid, unknownouter, CLSCTX_INPROC_SERVER, refiid, ppv);
68 if(hres!=S_OK)
70 ERR("failed (0x%08lx) to create \n\tCLSID:\t%s\n\tIID:\t%s\n",
71 hres, debugstr_guid(myclsid), debugstr_guid(refiid));
72 ERR("class not found in registry\n");
75 TRACE("-- instance: %p\n",*ppv);
76 return hres;
79 /*************************************************************************
80 * SHELL32_DllGetClassObject [SHELL32.128]
82 HRESULT WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv)
83 { HRESULT hres = E_OUTOFMEMORY;
84 LPCLASSFACTORY lpclf;
86 TRACE("\n\tCLSID:\t%s,\n\tIID:\t%s\n",debugstr_guid(rclsid),debugstr_guid(iid));
88 *ppv = NULL;
90 if(IsEqualCLSID(rclsid, &CLSID_ShellDesktop)||
91 IsEqualCLSID(rclsid, &CLSID_ShellLink))
93 lpclf = IClassFactory_Constructor( rclsid );
95 if(lpclf)
97 hres = IClassFactory_QueryInterface(lpclf,iid, ppv);
98 IClassFactory_Release(lpclf);
101 else
103 WARN("-- CLSID not found\n");
104 hres = CLASS_E_CLASSNOTAVAILABLE;
106 TRACE("-- pointer to class factory: %p\n",*ppv);
107 return hres;
110 /*************************************************************************
111 * SHCLSIDFromString [SHELL32.147]
113 * NOTES
114 * exported by ordinal
116 DWORD WINAPI SHCLSIDFromStringA (LPSTR clsid, CLSID *id)
118 WCHAR buffer[40];
119 TRACE("(%p(%s) %p)\n", clsid, clsid, id);
120 if (!MultiByteToWideChar( CP_ACP, 0, clsid, -1, buffer, sizeof(buffer)/sizeof(WCHAR) ))
121 return CO_E_CLASSSTRING;
122 return CLSIDFromString( buffer, id );
124 DWORD WINAPI SHCLSIDFromStringW (LPWSTR clsid, CLSID *id)
126 TRACE("(%p(%s) %p)\n", clsid, debugstr_w(clsid), id);
127 return CLSIDFromString(clsid, id);
129 DWORD WINAPI SHCLSIDFromStringAW (LPVOID clsid, CLSID *id)
131 if (SHELL_OsIsUnicode())
132 return SHCLSIDFromStringW (clsid, id);
133 return SHCLSIDFromStringA (clsid, id);
136 /*************************************************************************
137 * SHGetMalloc [SHELL32.220]
138 * returns the interface to shell malloc.
140 * [SDK header win95/shlobj.h:
141 * equivalent to: #define SHGetMalloc(ppmem) CoGetMalloc(MEMCTX_TASK, ppmem)
143 * What we are currently doing is not very wrong, since we always use the same
144 * heap (ProcessHeap).
146 DWORD WINAPI SHGetMalloc(LPMALLOC *lpmal)
148 TRACE("(%p)\n", lpmal);
149 return CoGetMalloc(0,lpmal);
152 /*************************************************************************
153 * SHGetDesktopFolder [SHELL32.216]
155 LPSHELLFOLDER pdesktopfolder=NULL;
157 DWORD WINAPI SHGetDesktopFolder(IShellFolder **psf)
159 HRESULT hres = S_OK;
160 LPCLASSFACTORY lpclf;
161 TRACE("%p->(%p)\n",psf,*psf);
163 *psf=NULL;
165 if (!pdesktopfolder)
167 lpclf = IClassFactory_Constructor(&CLSID_ShellDesktop);
168 if(lpclf)
170 hres = IClassFactory_CreateInstance(lpclf,NULL,(REFIID)&IID_IShellFolder, (void*)&pdesktopfolder);
171 IClassFactory_Release(lpclf);
175 if (pdesktopfolder)
177 /* even if we create the folder, add a ref so the application canĀ“t destroy the folder*/
178 IShellFolder_AddRef(pdesktopfolder);
179 *psf = pdesktopfolder;
182 TRACE("-- %p->(%p)\n",psf, *psf);
183 return hres;
186 /**************************************************************************
187 * IClassFactory Implementation
190 typedef struct
192 /* IUnknown fields */
193 ICOM_VFIELD(IClassFactory);
194 DWORD ref;
195 CLSID *rclsid;
196 } IClassFactoryImpl;
198 static ICOM_VTABLE(IClassFactory) clfvt;
200 /**************************************************************************
201 * IClassFactory_Constructor
204 LPCLASSFACTORY IClassFactory_Constructor(REFCLSID rclsid)
206 IClassFactoryImpl* lpclf;
208 lpclf= (IClassFactoryImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IClassFactoryImpl));
209 lpclf->ref = 1;
210 ICOM_VTBL(lpclf) = &clfvt;
211 lpclf->rclsid = (CLSID*)rclsid;
213 TRACE("(%p)->()\n",lpclf);
214 InterlockedIncrement(&shell32_ObjCount);
215 return (LPCLASSFACTORY)lpclf;
217 /**************************************************************************
218 * IClassFactory_QueryInterface
220 static HRESULT WINAPI IClassFactory_fnQueryInterface(
221 LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
223 ICOM_THIS(IClassFactoryImpl,iface);
224 TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
226 *ppvObj = NULL;
228 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
229 { *ppvObj = This;
231 else if(IsEqualIID(riid, &IID_IClassFactory)) /*IClassFactory*/
232 { *ppvObj = (IClassFactory*)This;
235 if(*ppvObj)
236 { IUnknown_AddRef((LPUNKNOWN)*ppvObj);
237 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
238 return S_OK;
240 TRACE("-- Interface: %s E_NOINTERFACE\n", debugstr_guid(riid));
241 return E_NOINTERFACE;
243 /******************************************************************************
244 * IClassFactory_AddRef
246 static ULONG WINAPI IClassFactory_fnAddRef(LPCLASSFACTORY iface)
248 ICOM_THIS(IClassFactoryImpl,iface);
249 TRACE("(%p)->(count=%lu)\n",This,This->ref);
251 InterlockedIncrement(&shell32_ObjCount);
252 return InterlockedIncrement(&This->ref);
254 /******************************************************************************
255 * IClassFactory_Release
257 static ULONG WINAPI IClassFactory_fnRelease(LPCLASSFACTORY iface)
259 ICOM_THIS(IClassFactoryImpl,iface);
260 TRACE("(%p)->(count=%lu)\n",This,This->ref);
262 InterlockedDecrement(&shell32_ObjCount);
263 if (!InterlockedDecrement(&This->ref))
265 TRACE("-- destroying IClassFactory(%p)\n",This);
266 HeapFree(GetProcessHeap(),0,This);
267 return 0;
269 return This->ref;
271 /******************************************************************************
272 * IClassFactory_CreateInstance
274 static HRESULT WINAPI IClassFactory_fnCreateInstance(
275 LPCLASSFACTORY iface, LPUNKNOWN pUnknown, REFIID riid, LPVOID *ppObject)
277 ICOM_THIS(IClassFactoryImpl,iface);
278 IUnknown *pObj = NULL;
279 HRESULT hres;
281 TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnknown,debugstr_guid(riid),ppObject);
283 *ppObject = NULL;
285 if(pUnknown)
287 return(CLASS_E_NOAGGREGATION);
290 if (IsEqualCLSID(This->rclsid, &CLSID_ShellDesktop))
292 pObj = (IUnknown *)ISF_Desktop_Constructor();
294 else if (IsEqualCLSID(This->rclsid, &CLSID_ShellLink))
296 pObj = (IUnknown *)IShellLink_Constructor(FALSE);
298 else
300 ERR("unknown IID requested\n\tIID:\t%s\n",debugstr_guid(riid));
301 return(E_NOINTERFACE);
304 if (!pObj)
306 return(E_OUTOFMEMORY);
309 hres = IUnknown_QueryInterface(pObj,riid, ppObject);
310 IUnknown_Release(pObj);
312 TRACE("-- Object created: (%p)->%p\n",This,*ppObject);
314 return hres;
316 /******************************************************************************
317 * IClassFactory_LockServer
319 static HRESULT WINAPI IClassFactory_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
321 ICOM_THIS(IClassFactoryImpl,iface);
322 TRACE("%p->(0x%x), not implemented\n",This, fLock);
323 return E_NOTIMPL;
326 static ICOM_VTABLE(IClassFactory) clfvt =
328 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
329 IClassFactory_fnQueryInterface,
330 IClassFactory_fnAddRef,
331 IClassFactory_fnRelease,
332 IClassFactory_fnCreateInstance,
333 IClassFactory_fnLockServer
336 /**************************************************************************
337 * Default ClassFactory Implementation
339 * SHCreateDefClassObject
341 * NOTES
342 * helper function for dll's without a own classfactory
343 * a generic classfactory is returned
344 * when the CreateInstance of the cf is called the callback is executed
346 typedef HRESULT (CALLBACK * LPFNCREATEINSTANCE)(IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject);
348 typedef struct
350 ICOM_VFIELD(IClassFactory);
351 DWORD ref;
352 CLSID *rclsid;
353 LPFNCREATEINSTANCE lpfnCI;
354 const IID * riidInst;
355 ULONG * pcRefDll; /* pointer to refcounter in external dll (ugrrr...) */
356 } IDefClFImpl;
358 static ICOM_VTABLE(IClassFactory) dclfvt;
360 /**************************************************************************
361 * IDefClF_fnConstructor
364 IClassFactory * IDefClF_fnConstructor(LPFNCREATEINSTANCE lpfnCI, PLONG pcRefDll, REFIID riidInst)
366 IDefClFImpl* lpclf;
368 lpclf = (IDefClFImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(IDefClFImpl));
369 lpclf->ref = 1;
370 ICOM_VTBL(lpclf) = &dclfvt;
371 lpclf->lpfnCI = lpfnCI;
372 lpclf->pcRefDll = pcRefDll;
374 if (pcRefDll) InterlockedIncrement(pcRefDll);
375 lpclf->riidInst = riidInst;
377 TRACE("(%p)\n\tIID:\t%s\n",lpclf, debugstr_guid(riidInst));
378 InterlockedIncrement(&shell32_ObjCount);
379 return (LPCLASSFACTORY)lpclf;
381 /**************************************************************************
382 * IDefClF_fnQueryInterface
384 static HRESULT WINAPI IDefClF_fnQueryInterface(
385 LPCLASSFACTORY iface, REFIID riid, LPVOID *ppvObj)
387 ICOM_THIS(IDefClFImpl,iface);
389 TRACE("(%p)->(\n\tIID:\t%s)\n",This,debugstr_guid(riid));
391 *ppvObj = NULL;
393 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
394 { *ppvObj = This;
396 else if(IsEqualIID(riid, &IID_IClassFactory)) /*IClassFactory*/
397 { *ppvObj = (IClassFactory*)This;
400 if(*ppvObj)
401 { IUnknown_AddRef((LPUNKNOWN)*ppvObj);
402 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
403 return S_OK;
405 TRACE("-- Interface: %s E_NOINTERFACE\n", debugstr_guid(riid));
406 return E_NOINTERFACE;
408 /******************************************************************************
409 * IDefClF_fnAddRef
411 static ULONG WINAPI IDefClF_fnAddRef(LPCLASSFACTORY iface)
413 ICOM_THIS(IDefClFImpl,iface);
414 TRACE("(%p)->(count=%lu)\n",This,This->ref);
416 InterlockedIncrement(&shell32_ObjCount);
417 return InterlockedIncrement(&This->ref);
419 /******************************************************************************
420 * IDefClF_fnRelease
422 static ULONG WINAPI IDefClF_fnRelease(LPCLASSFACTORY iface)
424 ICOM_THIS(IDefClFImpl,iface);
425 TRACE("(%p)->(count=%lu)\n",This,This->ref);
427 InterlockedDecrement(&shell32_ObjCount);
429 if (!InterlockedDecrement(&This->ref))
431 if (This->pcRefDll) InterlockedDecrement(This->pcRefDll);
433 TRACE("-- destroying IClassFactory(%p)\n",This);
434 HeapFree(GetProcessHeap(),0,This);
435 return 0;
437 return This->ref;
439 /******************************************************************************
440 * IDefClF_fnCreateInstance
442 static HRESULT WINAPI IDefClF_fnCreateInstance(
443 LPCLASSFACTORY iface, LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject)
445 ICOM_THIS(IDefClFImpl,iface);
447 TRACE("%p->(%p,\n\tIID:\t%s,%p)\n",This,pUnkOuter,debugstr_guid(riid),ppvObject);
449 *ppvObject = NULL;
451 if(pUnkOuter)
452 return(CLASS_E_NOAGGREGATION);
454 if ( This->riidInst==NULL ||
455 IsEqualCLSID(riid, This->riidInst) ||
456 IsEqualCLSID(riid, &IID_IUnknown) )
458 return This->lpfnCI(pUnkOuter, riid, ppvObject);
461 ERR("unknown IID requested\n\tIID:\t%s\n",debugstr_guid(riid));
462 return E_NOINTERFACE;
464 /******************************************************************************
465 * IDefClF_fnLockServer
467 static HRESULT WINAPI IDefClF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
469 ICOM_THIS(IDefClFImpl,iface);
470 TRACE("%p->(0x%x), not implemented\n",This, fLock);
471 return E_NOTIMPL;
474 static ICOM_VTABLE(IClassFactory) dclfvt =
476 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
477 IDefClF_fnQueryInterface,
478 IDefClF_fnAddRef,
479 IDefClF_fnRelease,
480 IDefClF_fnCreateInstance,
481 IDefClF_fnLockServer
484 /******************************************************************************
485 * SHCreateDefClassObject [SHELL32.70]
487 HRESULT WINAPI SHCreateDefClassObject(
488 REFIID riid,
489 LPVOID* ppv,
490 LPFNCREATEINSTANCE lpfnCI, /* create instance callback entry */
491 PLONG pcRefDll, /* ref count of the dll */
492 REFIID riidInst) /* optional interface to the instance */
494 TRACE("\n\tIID:\t%s %p %p %p \n\tIIDIns:\t%s\n",
495 debugstr_guid(riid), ppv, lpfnCI, pcRefDll, debugstr_guid(riidInst));
497 if ( IsEqualCLSID(riid, &IID_IClassFactory) )
499 IClassFactory * pcf = IDefClF_fnConstructor(lpfnCI, pcRefDll, riidInst);
500 if (pcf)
502 *ppv = pcf;
503 return NOERROR;
505 return E_OUTOFMEMORY;
507 return E_NOINTERFACE;
510 /*************************************************************************
511 * DragAcceptFiles [SHELL32.54]
513 void WINAPI DragAcceptFiles(HWND hWnd, BOOL b)
515 LONG exstyle;
517 if( !IsWindow(hWnd) ) return;
518 exstyle = GetWindowLongA(hWnd,GWL_EXSTYLE);
519 if (b)
520 exstyle |= WS_EX_ACCEPTFILES;
521 else
522 exstyle &= ~WS_EX_ACCEPTFILES;
523 SetWindowLongA(hWnd,GWL_EXSTYLE,exstyle);
526 /*************************************************************************
527 * DragFinish [SHELL32.80]
529 void WINAPI DragFinish(HDROP h)
531 TRACE("\n");
532 GlobalFree((HGLOBAL)h);
535 /*************************************************************************
536 * DragQueryPoint [SHELL32.135]
538 BOOL WINAPI DragQueryPoint(HDROP hDrop, POINT *p)
540 DROPFILES *lpDropFileStruct;
541 BOOL bRet;
543 TRACE("\n");
545 lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
547 *p = lpDropFileStruct->pt;
548 bRet = lpDropFileStruct->fNC;
550 GlobalUnlock(hDrop);
551 return bRet;
554 /*************************************************************************
555 * DragQueryFileA [SHELL32.81] [shell32.82]
557 UINT WINAPI DragQueryFileA(
558 HDROP hDrop,
559 UINT lFile,
560 LPSTR lpszFile,
561 UINT lLength)
563 LPSTR lpDrop;
564 UINT i = 0;
565 DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
567 TRACE("(%08x, %x, %p, %u)\n", hDrop,lFile,lpszFile,lLength);
569 if(!lpDropFileStruct) goto end;
571 lpDrop = (LPSTR) lpDropFileStruct + lpDropFileStruct->pFiles;
573 while (i++ < lFile)
575 while (*lpDrop++); /* skip filename */
576 if (!*lpDrop)
578 i = (lFile == 0xFFFFFFFF) ? i : 0;
579 goto end;
583 i = strlen(lpDrop);
584 i++;
585 if (!lpszFile ) goto end; /* needed buffer size */
586 i = (lLength > i) ? i : lLength;
587 lstrcpynA (lpszFile, lpDrop, i);
588 end:
589 GlobalUnlock(hDrop);
590 return i;
593 /*************************************************************************
594 * DragQueryFileW [shell32.133]
596 UINT WINAPI DragQueryFileW(
597 HDROP hDrop,
598 UINT lFile,
599 LPWSTR lpszwFile,
600 UINT lLength)
602 LPWSTR lpwDrop;
603 UINT i = 0;
604 DROPFILES *lpDropFileStruct = (DROPFILES *) GlobalLock(hDrop);
606 TRACE("(%08x, %x, %p, %u)\n", hDrop,lFile,lpszwFile,lLength);
608 if(!lpDropFileStruct) goto end;
610 lpwDrop = (LPWSTR) lpDropFileStruct + lpDropFileStruct->pFiles;
612 i = 0;
613 while (i++ < lFile)
615 while (*lpwDrop++); /* skip filename */
616 if (!*lpwDrop)
618 i = (lFile == 0xFFFFFFFF) ? i : 0;
619 goto end;
623 i = strlenW(lpwDrop);
624 i++;
625 if ( !lpszwFile) goto end; /* needed buffer size */
627 i = (lLength > i) ? i : lLength;
628 lstrcpynW (lpszwFile, lpwDrop, i);
629 end:
630 GlobalUnlock(hDrop);
631 return i;