Eliminated warnings.
[wine.git] / dlls / shell32 / shlfolder.c
blobc4dd7c3313baae4ab804496ded99a9a00739e670
1 /*
2 * Shell Folder stuff
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998 Juergen Schmied
6 *
7 * IShellFolder with IDropTarget, IPersistFolder
9 */
11 #include <stdlib.h>
12 #include <string.h>
14 #include "debugtools.h"
15 #include "winerror.h"
17 #include "oleidl.h"
18 #include "shlguid.h"
20 #include "pidl.h"
21 #include "wine/obj_base.h"
22 #include "wine/obj_dragdrop.h"
23 #include "wine/obj_shellfolder.h"
24 #include "wine/undocshell.h"
25 #include "shell32_main.h"
27 DEFAULT_DEBUG_CHANNEL(shell)
29 /***************************************************************************
30 * IDropTarget interface definition for the ShellFolder
33 typedef struct
34 { ICOM_VTABLE(IDropTarget)* lpvtbl;
35 ULONG ref;
36 } ISFDropTarget;
38 static struct ICOM_VTABLE(IDropTarget) dtvt;
41 /****************************************************************************
42 * ISFDropTarget implementation
45 static IDropTarget * WINAPI ISFDropTarget_Constructor(void)
47 ISFDropTarget* sf;
49 sf = HeapAlloc(GetProcessHeap(), 0, sizeof(ISFDropTarget));
51 if (sf)
52 { sf->lpvtbl = &dtvt;
53 sf->ref = 1;
56 return (IDropTarget *)sf;
59 static HRESULT WINAPI ISFDropTarget_QueryInterface(
60 IDropTarget *iface,
61 REFIID riid,
62 LPVOID *ppvObj)
64 ICOM_THIS(ISFDropTarget,iface);
66 char xriid[50];
67 WINE_StringFromCLSID((LPCLSID)riid,xriid);
69 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
71 if ( !This || !ppvObj)
72 return E_INVALIDARG;
74 *ppvObj = NULL;
76 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
77 { *ppvObj = This;
79 else if(IsEqualIID(riid, &IID_IDropTarget)) /*IShellFolder*/
80 { *ppvObj = (ISFDropTarget*)This;
83 if(*ppvObj)
84 { IDropTarget_AddRef((IDropTarget*)*ppvObj);
85 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
86 return S_OK;
89 TRACE("-- Interface: E_NOINTERFACE\n");
91 return E_NOINTERFACE;
94 static ULONG WINAPI ISFDropTarget_AddRef( IDropTarget *iface)
96 ICOM_THIS(ISFDropTarget,iface);
98 TRACE("(%p)->(count=%lu)\n",This,This->ref);
100 shell32_ObjCount++;
102 return ++(This->ref);
105 static ULONG WINAPI ISFDropTarget_Release( IDropTarget *iface)
107 ICOM_THIS(ISFDropTarget,iface);
109 shell32_ObjCount--;
111 if (!--(This->ref))
112 { TRACE("-- destroying ISFDropTarget (%p)\n",This);
113 HeapFree(GetProcessHeap(),0,This);
114 return 0;
116 return This->ref;
119 static HRESULT WINAPI ISFDropTarget_DragEnter(
120 IDropTarget *iface,
121 IDataObject *pDataObject,
122 DWORD grfKeyState,
123 POINTL pt,
124 DWORD *pdwEffect)
127 ICOM_THIS(ISFDropTarget,iface);
129 FIXME("Stub: This=%p, DataObject=%p\n",This,pDataObject);
131 return E_NOTIMPL;
134 static HRESULT WINAPI ISFDropTarget_DragOver(
135 IDropTarget *iface,
136 DWORD grfKeyState,
137 POINTL pt,
138 DWORD *pdwEffect)
140 ICOM_THIS(ISFDropTarget,iface);
142 FIXME("Stub: This=%p\n",This);
144 return E_NOTIMPL;
147 static HRESULT WINAPI ISFDropTarget_DragLeave(
148 IDropTarget *iface)
150 ICOM_THIS(ISFDropTarget,iface);
152 FIXME("Stub: This=%p\n",This);
154 return E_NOTIMPL;
157 static HRESULT WINAPI ISFDropTarget_Drop(
158 IDropTarget *iface,
159 IDataObject* pDataObject,
160 DWORD grfKeyState,
161 POINTL pt,
162 DWORD *pdwEffect)
164 ICOM_THIS(ISFDropTarget,iface);
166 FIXME("Stub: This=%p\n",This);
168 return E_NOTIMPL;
171 static struct ICOM_VTABLE(IDropTarget) dtvt =
173 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
174 ISFDropTarget_QueryInterface,
175 ISFDropTarget_AddRef,
176 ISFDropTarget_Release,
177 ISFDropTarget_DragEnter,
178 ISFDropTarget_DragOver,
179 ISFDropTarget_DragLeave,
180 ISFDropTarget_Drop
183 /***************************************************************************
184 * GetNextElement (internal function)
186 * gets a part of a string till the first backslash
188 * PARAMETERS
189 * pszNext [IN] string to get the element from
190 * pszOut [IN] pointer to buffer whitch receives string
191 * dwOut [IN] length of pszOut
193 * RETURNS
194 * LPSTR pointer to first, not yet parsed char
197 static LPCWSTR GetNextElementW(LPCWSTR pszNext,LPWSTR pszOut,DWORD dwOut)
198 { LPCWSTR pszTail = pszNext;
199 DWORD dwCopy;
200 TRACE("(%s %p 0x%08lx)\n",debugstr_w(pszNext),pszOut,dwOut);
202 *pszOut=0x0000;
204 if(!pszNext || !*pszNext)
205 return NULL;
207 while(*pszTail && (*pszTail != (WCHAR)'\\'))
208 pszTail++;
210 dwCopy = (WCHAR*)pszTail - (WCHAR*)pszNext + 1;
211 lstrcpynW(pszOut, pszNext, (dwOut<dwCopy)? dwOut : dwCopy);
213 if(*pszTail)
214 pszTail++;
215 else
216 pszTail = NULL;
218 TRACE("--(%s %s 0x%08lx %p)\n",debugstr_w(pszNext),debugstr_w(pszOut),dwOut,pszTail);
219 return pszTail;
222 static HRESULT SHELL32_ParseNextElement(
223 HWND hwndOwner,
224 IShellFolder * psf,
225 LPITEMIDLIST * pidlInOut,
226 LPOLESTR szNext,
227 DWORD *pEaten,
228 DWORD *pdwAttributes)
230 HRESULT hr = E_OUTOFMEMORY;
231 LPITEMIDLIST pidlOut, pidlTemp = NULL;
232 IShellFolder *psfChild;
234 TRACE("(%p %p %s)\n",psf, pidlInOut? *pidlInOut: NULL, debugstr_w(szNext));
237 /* get the shellfolder for the child pidl and let it analyse further */
238 hr = IShellFolder_BindToObject(psf, *pidlInOut, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
240 if (psfChild)
242 hr = IShellFolder_ParseDisplayName(psfChild, hwndOwner, NULL, szNext, pEaten, &pidlOut, pdwAttributes);
243 IShellFolder_Release(psfChild);
245 pidlTemp = ILCombine(*pidlInOut, pidlOut);
247 if (pidlOut)
248 ILFree(pidlOut);
251 ILFree(*pidlInOut);
252 *pidlInOut = pidlTemp;
254 TRACE("-- pidl=%p ret=0x%08lx\n", pidlInOut? *pidlInOut: NULL, hr);
255 return hr;
258 /***********************************************************************
259 * SHELL32_CoCreateInitSF
261 * creates a initialized shell folder
263 static HRESULT SHELL32_CoCreateInitSF (
264 LPITEMIDLIST pidlRoot,
265 LPITEMIDLIST pidlChild,
266 REFCLSID clsid,
267 REFIID iid,
268 LPVOID * ppvOut)
270 HRESULT hr;
271 LPITEMIDLIST absPidl;
272 IShellFolder *pShellFolder;
273 IPersistFolder *pPersistFolder;
275 TRACE("%p %p\n", pidlRoot, pidlChild);
277 *ppvOut = NULL;
279 hr = SHCoCreateInstance(NULL, clsid, NULL, iid, (LPVOID*)&pShellFolder);
280 if (SUCCEEDED(hr))
282 hr = IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&pPersistFolder);
283 if (SUCCEEDED(hr))
285 absPidl = ILCombine (pidlRoot, pidlChild);
286 hr = IPersistFolder_Initialize(pPersistFolder, absPidl);
287 IPersistFolder_Release(pPersistFolder);
288 SHFree(absPidl);
289 *ppvOut = pShellFolder;
293 TRACE("-- ret=0x%08lx\n", hr);
294 return hr;
297 static HRESULT SHELL32_GetDisplayNameOfChild(
298 IShellFolder * psf,
299 LPCITEMIDLIST pidl,
300 DWORD dwFlags,
301 LPSTR szOut,
302 DWORD dwOutLen)
304 LPITEMIDLIST pidlFirst, pidlNext;
305 IShellFolder * psfChild;
306 HRESULT hr = E_OUTOFMEMORY;
307 STRRET strTemp;
309 TRACE("(%p)->(pidl=%p 0x%08lx %p 0x%08lx)\n",psf,pidl,dwFlags,szOut, dwOutLen);
310 pdump(pidl);
312 if ((pidlFirst = ILCloneFirst(pidl)))
314 hr = IShellFolder_BindToObject(psf, pidlFirst, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
315 if (SUCCEEDED(hr))
317 pidlNext = ILGetNext(pidl);
319 hr = IShellFolder_GetDisplayNameOf(psfChild, pidlNext, dwFlags | SHGDN_INFOLDER, &strTemp);
320 if (SUCCEEDED(hr))
322 if (strTemp.uType == STRRET_CSTRA)
324 lstrcpynA(szOut , strTemp.u.cStr, dwOutLen);
326 else
328 FIXME("wrong return type");
332 IShellFolder_Release(psfChild);
334 ILFree(pidlFirst);
337 TRACE("-- ret=0x%08lx %s\n", hr, szOut);
339 return hr;
342 /***********************************************************************
343 * IShellFolder implementation
346 typedef struct
348 ICOM_VTABLE(IShellFolder)* lpvtbl;
349 DWORD ref;
351 ICOM_VTABLE(IPersistFolder)* lpvtblPersistFolder;
352 CLSID* pclsid;
354 LPSTR sMyPath;
355 LPITEMIDLIST absPidl; /* complete pidl */
356 } IGenericSFImpl;
358 static struct ICOM_VTABLE(IShellFolder) sfvt;
360 static struct ICOM_VTABLE(IPersistFolder) psfvt;
362 static IShellFolder * ISF_MyComputer_Constructor(void);
364 #define _IPersistFolder_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder)))
365 #define _ICOM_THIS_From_IPersistFolder(class, name) class* This = (class*)(((char*)name)-_IPersistFolder_Offset);
367 /**************************************************************************
368 * IShellFolder_Constructor
372 static IShellFolder * IShellFolder_Constructor(
373 IShellFolder * psf,
374 LPITEMIDLIST pidl)
376 IGenericSFImpl * sf;
377 IGenericSFImpl * sfParent = (IGenericSFImpl*) psf;
378 DWORD dwSize=0;
380 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
381 sf->ref=1;
383 sf->lpvtbl=&sfvt;
384 sf->lpvtblPersistFolder=&psfvt;
385 sf->pclsid = (CLSID*)&CLSID_SFFile;
387 TRACE("(%p)->(parent=%p, pidl=%p)\n",sf,sfParent, pidl);
388 pdump(pidl);
390 if(pidl) /* do we have a pidl? */
392 int len;
394 sf->absPidl = ILCombine(sfParent->absPidl, pidl); /* build a absolute pidl */
396 if (!_ILIsSpecialFolder(pidl)) /* only file system paths */
398 if(sfParent->sMyPath) /* get the size of the parents path */
400 dwSize += strlen(sfParent->sMyPath) ;
401 TRACE("-- (%p)->(parent's path=%s)\n",sf, debugstr_a(sfParent->sMyPath));
404 dwSize += _ILSimpleGetText(pidl,NULL,0); /* add the size of our name*/
405 sf->sMyPath = SHAlloc(dwSize + 2); /* '\0' and backslash */
407 if(!sf->sMyPath) return NULL;
408 *(sf->sMyPath)=0x00;
410 if(sfParent->sMyPath) /* if the parent has a path, get it*/
412 strcpy(sf->sMyPath, sfParent->sMyPath);
413 PathAddBackslashA (sf->sMyPath);
416 len = strlen(sf->sMyPath);
417 _ILSimpleGetText(pidl, sf->sMyPath + len, dwSize - len + 1);
420 TRACE("-- (%p)->(my pidl=%p, my path=%s)\n",sf, sf->absPidl,debugstr_a(sf->sMyPath));
422 pdump (sf->absPidl);
425 shell32_ObjCount++;
426 return (IShellFolder *)sf;
428 /**************************************************************************
429 * IShellFolder_fnQueryInterface
431 * PARAMETERS
432 * REFIID riid [in ] Requested InterfaceID
433 * LPVOID* ppvObject [out] Interface* to hold the result
435 static HRESULT WINAPI IShellFolder_fnQueryInterface(
436 IShellFolder * iface,
437 REFIID riid,
438 LPVOID *ppvObj)
440 ICOM_THIS(IGenericSFImpl, iface);
442 char xriid[50];
443 WINE_StringFromCLSID((LPCLSID)riid,xriid);
444 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
446 *ppvObj = NULL;
448 if(IsEqualIID(riid, &IID_IUnknown))
449 { *ppvObj = This;
451 else if(IsEqualIID(riid, &IID_IShellFolder))
452 { *ppvObj = (IShellFolder*)This;
454 else if(IsEqualIID(riid, &IID_IPersist))
455 { *ppvObj = (IPersistFolder*)&(This->lpvtblPersistFolder);
457 else if(IsEqualIID(riid, &IID_IPersistFolder))
458 { *ppvObj = (IPersistFolder*)&(This->lpvtblPersistFolder);
461 if(*ppvObj)
463 IUnknown_AddRef((IUnknown*)(*ppvObj));
464 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
465 return S_OK;
467 TRACE("-- Interface: E_NOINTERFACE\n");
468 return E_NOINTERFACE;
471 /**************************************************************************
472 * IShellFolder_AddRef
475 static ULONG WINAPI IShellFolder_fnAddRef(IShellFolder * iface)
477 ICOM_THIS(IGenericSFImpl, iface);
479 TRACE("(%p)->(count=%lu)\n",This,This->ref);
481 shell32_ObjCount++;
482 return ++(This->ref);
485 /**************************************************************************
486 * IShellFolder_fnRelease
488 static ULONG WINAPI IShellFolder_fnRelease(IShellFolder * iface)
490 ICOM_THIS(IGenericSFImpl, iface);
492 TRACE("(%p)->(count=%lu)\n",This,This->ref);
494 shell32_ObjCount--;
495 if (!--(This->ref))
496 { TRACE("-- destroying IShellFolder(%p)\n",This);
498 if (pdesktopfolder == iface)
499 { pdesktopfolder=NULL;
500 TRACE("-- destroyed IShellFolder(%p) was Desktopfolder\n",This);
502 if(This->absPidl)
503 { SHFree(This->absPidl);
505 if(This->sMyPath)
506 { SHFree(This->sMyPath);
509 HeapFree(GetProcessHeap(),0,This);
511 return 0;
513 return This->ref;
515 /**************************************************************************
516 * IShellFolder_fnParseDisplayName
517 * PARAMETERS
518 * HWND hwndOwner, //[in ] Parent window for any message's
519 * LPBC pbc, //[in ] reserved
520 * LPOLESTR lpszDisplayName,//[in ] "Unicode" displayname.
521 * ULONG* pchEaten, //[out] (unicode) characters processed
522 * LPITEMIDLIST* ppidl, //[out] complex pidl to item
523 * ULONG* pdwAttributes //[out] items attributes
525 * NOTES
526 * every folder trys to parse only it's own (the leftmost) pidl and creates a
527 * subfolder to evaluate the remaining parts
528 * now we can parse into namespaces implemented by shell extensions
530 * behaviour on win98: lpszDisplayName=NULL -> chrash
531 * lpszDisplayName="" -> returns mycoputer-pidl
533 * FIXME:
534 * pdwAttributes: not set
535 * pchEaten: not set like in windows
537 static HRESULT WINAPI IShellFolder_fnParseDisplayName(
538 IShellFolder * iface,
539 HWND hwndOwner,
540 LPBC pbcReserved,
541 LPOLESTR lpszDisplayName,
542 DWORD *pchEaten,
543 LPITEMIDLIST *ppidl,
544 DWORD *pdwAttributes)
546 ICOM_THIS(IGenericSFImpl, iface);
548 HRESULT hr = E_OUTOFMEMORY;
549 LPCWSTR szNext=NULL;
550 WCHAR szElement[MAX_PATH];
551 CHAR szTempA[MAX_PATH], szPath[MAX_PATH];
552 LPITEMIDLIST pidlTemp=NULL;
554 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
555 This,hwndOwner,pbcReserved,lpszDisplayName,
556 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
558 if (pchEaten) *pchEaten = 0; /* strange but like the original */
560 if (*lpszDisplayName)
562 /* get the next element */
563 szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
565 /* build the full pathname to the element */
566 WideCharToLocal(szTempA, szElement, lstrlenW(szElement) + 1);
567 strcpy(szPath, This->sMyPath);
568 PathAddBackslashA(szPath);
569 strcat(szPath, szTempA);
571 /* get the pidl */
572 pidlTemp = SHSimpleIDListFromPathA(szPath);
574 if (pidlTemp)
576 /* try to analyse the next element */
577 if (szNext && *szNext)
579 hr = SHELL32_ParseNextElement(hwndOwner, (IShellFolder*)This, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
581 else
583 hr = S_OK;
588 *ppidl = pidlTemp;
590 TRACE("(%p)->(-- pidl=%p ret=0x%08lx)\n", This, ppidl? *ppidl:0, hr);
592 return hr;
595 /**************************************************************************
596 * IShellFolder_fnEnumObjects
597 * PARAMETERS
598 * HWND hwndOwner, //[in ] Parent Window
599 * DWORD grfFlags, //[in ] SHCONTF enumeration mask
600 * LPENUMIDLIST* ppenumIDList //[out] IEnumIDList interface
602 static HRESULT WINAPI IShellFolder_fnEnumObjects(
603 IShellFolder * iface,
604 HWND hwndOwner,
605 DWORD dwFlags,
606 LPENUMIDLIST* ppEnumIDList)
608 ICOM_THIS(IGenericSFImpl, iface);
610 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
612 *ppEnumIDList = NULL;
613 *ppEnumIDList = IEnumIDList_Constructor (This->sMyPath, dwFlags, EIDL_FILE);
615 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
617 if(!*ppEnumIDList) return E_OUTOFMEMORY;
619 return S_OK;
622 /**************************************************************************
623 * IShellFolder_fnBindToObject
624 * PARAMETERS
625 * LPCITEMIDLIST pidl, //[in ] relative pidl to open
626 * LPBC pbc, //[in ] reserved
627 * REFIID riid, //[in ] Initial Interface
628 * LPVOID* ppvObject //[out] Interface*
630 static HRESULT WINAPI IShellFolder_fnBindToObject( IShellFolder * iface, LPCITEMIDLIST pidl,
631 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
633 ICOM_THIS(IGenericSFImpl, iface);
634 GUID const * iid;
635 char xriid[50];
636 IShellFolder *pShellFolder, *pSubFolder;
637 IPersistFolder *pPersistFolder;
638 LPITEMIDLIST absPidl;
640 WINE_StringFromCLSID(riid,xriid);
642 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",This,pidl,pbcReserved,xriid,ppvOut);
644 *ppvOut = NULL;
646 if ((iid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(iid, &IID_MyComputer))
648 /* we have to create a alien folder */
649 if ( SUCCEEDED(SHCoCreateInstance(NULL, iid, NULL, riid, (LPVOID*)&pShellFolder))
650 && SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&pPersistFolder)))
652 absPidl = ILCombine (This->absPidl, pidl);
653 IPersistFolder_Initialize(pPersistFolder, absPidl);
654 IPersistFolder_Release(pPersistFolder);
655 SHFree(absPidl);
657 else
659 return E_FAIL;
662 else
664 LPITEMIDLIST pidltemp = ILCloneFirst(pidl);
665 pShellFolder = IShellFolder_Constructor((IShellFolder*)This, pidltemp);
666 ILFree(pidltemp);
669 if (_ILIsPidlSimple(pidl))
671 *ppvOut = pShellFolder;
673 else
675 IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, &IID_IShellFolder, (LPVOID)&pSubFolder);
676 IShellFolder_Release(pShellFolder);
677 *ppvOut = pSubFolder;
680 TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
682 return S_OK;
685 /**************************************************************************
686 * IShellFolder_fnBindToStorage
687 * PARAMETERS
688 * LPCITEMIDLIST pidl, //[in ] complex pidl to store
689 * LPBC pbc, //[in ] reserved
690 * REFIID riid, //[in ] Initial storage interface
691 * LPVOID* ppvObject //[out] Interface* returned
693 static HRESULT WINAPI IShellFolder_fnBindToStorage(
694 IShellFolder * iface,
695 LPCITEMIDLIST pidl,
696 LPBC pbcReserved,
697 REFIID riid,
698 LPVOID *ppvOut)
700 ICOM_THIS(IGenericSFImpl, iface);
702 char xriid[50];
703 WINE_StringFromCLSID(riid,xriid);
705 FIXME("(%p)->(pidl=%p,%p,\n\tIID:%s,%p) stub\n",This,pidl,pbcReserved,xriid,ppvOut);
707 *ppvOut = NULL;
708 return E_NOTIMPL;
711 /**************************************************************************
712 * IShellFolder_fnCompareIDs
714 * PARMETERS
715 * LPARAM lParam, //[in ] Column?
716 * LPCITEMIDLIST pidl1, //[in ] simple pidl
717 * LPCITEMIDLIST pidl2) //[in ] simple pidl
719 * NOTES
720 * Special case - If one of the items is a Path and the other is a File,
721 * always make the Path come before the File.
723 * NOTES
724 * use SCODE_CODE() on the return value to get the result
727 static HRESULT WINAPI IShellFolder_fnCompareIDs(
728 IShellFolder * iface,
729 LPARAM lParam,
730 LPCITEMIDLIST pidl1,
731 LPCITEMIDLIST pidl2)
733 ICOM_THIS(IGenericSFImpl, iface);
735 CHAR szTemp1[MAX_PATH];
736 CHAR szTemp2[MAX_PATH];
737 int nReturn;
738 IShellFolder * psf;
739 HRESULT hr = E_OUTOFMEMORY;
740 LPCITEMIDLIST pidlTemp;
741 PIDLTYPE pt1, pt2;
743 TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n",This,lParam,pidl1,pidl2);
744 pdump (pidl1);
745 pdump (pidl2);
747 if (!pidl1 && !pidl2)
749 hr = ResultFromShort(0);
751 else if (!pidl1)
753 hr = ResultFromShort(-1);
755 else if (!pidl2)
757 hr = ResultFromShort(1);
759 else
761 LPPIDLDATA pd1, pd2;
762 pd1 = _ILGetDataPointer(pidl1);
763 pd2 = _ILGetDataPointer(pidl2);
765 /* compate the types. sort order is the PT_* constant */
766 pt1 = ( pd1 ? pd1->type: PT_DESKTOP);
767 pt2 = ( pd2 ? pd2->type: PT_DESKTOP);
769 if (pt1 != pt2)
771 hr = ResultFromShort(pt1-pt2);
773 else /* same type of pidl */
775 _ILSimpleGetText(pidl1, szTemp1, MAX_PATH);
776 _ILSimpleGetText(pidl2, szTemp2, MAX_PATH);
777 nReturn = strcasecmp(szTemp1, szTemp2);
779 if (nReturn == 0) /* first pidl different ? */
781 pidl1 = ILGetNext(pidl1);
783 if (pidl1 && pidl1->mkid.cb) /* go deeper? */
785 pidlTemp = ILCloneFirst(pidl1);
786 pidl2 = ILGetNext(pidl2);
788 hr = IShellFolder_BindToObject((IShellFolder*)This, pidlTemp, NULL, &IID_IShellFolder, (LPVOID*)&psf);
789 if (SUCCEEDED(hr))
791 nReturn = IShellFolder_CompareIDs(psf, 0, pidl1, pidl2);
792 IShellFolder_Release(psf);
793 hr = ResultFromShort(nReturn);
795 ILFree(pidlTemp);
797 else
799 hr = ResultFromShort(nReturn); /* two equal simple pidls */
802 else
804 hr = ResultFromShort(nReturn); /* two different simple pidls */
809 TRACE("-- res=0x%08lx\n", hr);
810 return hr;
813 /**************************************************************************
814 * IShellFolder_fnCreateViewObject
815 * Creates an View Object representing the ShellFolder
816 * IShellView / IShellBrowser / IContextMenu
818 * PARAMETERS
819 * HWND hwndOwner, // Handle of owner window
820 * REFIID riid, // Requested initial interface
821 * LPVOID* ppvObject) // Resultant interface*
823 * NOTES
824 * the same as SHCreateShellFolderViewEx ???
826 static HRESULT WINAPI IShellFolder_fnCreateViewObject( IShellFolder * iface,
827 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
829 ICOM_THIS(IGenericSFImpl, iface);
831 LPSHELLVIEW pShellView;
832 char xriid[50];
833 HRESULT hr;
835 WINE_StringFromCLSID(riid,xriid);
836 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,xriid,ppvOut);
838 *ppvOut = NULL;
840 pShellView = IShellView_Constructor((IShellFolder *) This);
842 if(!pShellView)
843 return E_OUTOFMEMORY;
845 hr = pShellView->lpvtbl->fnQueryInterface(pShellView, riid, ppvOut);
846 pShellView->lpvtbl->fnRelease(pShellView);
847 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
848 return hr;
851 /**************************************************************************
852 * IShellFolder_fnGetAttributesOf
854 * PARAMETERS
855 * UINT cidl, //[in ] num elements in pidl array
856 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
857 * ULONG* rgfInOut) //[out] result array
860 static HRESULT WINAPI IShellFolder_fnGetAttributesOf(IShellFolder * iface,UINT cidl,LPCITEMIDLIST *apidl,DWORD *rgfInOut)
862 ICOM_THIS(IGenericSFImpl, iface);
864 HRESULT hr = S_OK;
866 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
868 if ( (!cidl) || (!apidl) || (!rgfInOut))
869 return E_INVALIDARG;
871 while (cidl > 0 && *apidl)
873 pdump (*apidl);
874 if (_ILIsFolder( *apidl))
876 *rgfInOut &= 0xe0000177;
877 goto next;
879 else if (_ILIsValue( *apidl))
881 *rgfInOut &= 0x40000177;
882 goto next;
884 hr = E_INVALIDARG;
886 next: apidl++;
887 cidl--;
890 TRACE("-- result=0x%08lx\n",*rgfInOut);
892 return hr;
894 /**************************************************************************
895 * IShellFolder_fnGetUIObjectOf
897 * PARAMETERS
898 * HWND hwndOwner, //[in ] Parent window for any output
899 * UINT cidl, //[in ] array size
900 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
901 * REFIID riid, //[in ] Requested Interface
902 * UINT* prgfInOut, //[ ] reserved
903 * LPVOID* ppvObject) //[out] Resulting Interface
905 * NOTES
906 * This function gets asked to return "view objects" for one or more (multiple select)
907 * items:
908 * The viewobject typically is an COM object with one of the following interfaces:
909 * IExtractIcon,IDataObject,IContextMenu
910 * In order to support icon positions in the default Listview your DataObject
911 * must implement the SetData method (in addition to GetData :) - the shell passes
912 * a barely documented "Icon positions" structure to SetData when the drag starts,
913 * and GetData's it if the drop is in another explorer window that needs the positions.
915 static HRESULT WINAPI IShellFolder_fnGetUIObjectOf(
916 IShellFolder * iface,
917 HWND hwndOwner,
918 UINT cidl,
919 LPCITEMIDLIST * apidl,
920 REFIID riid,
921 UINT * prgfInOut,
922 LPVOID * ppvOut)
924 ICOM_THIS(IGenericSFImpl, iface);
926 char xclsid[50];
927 LPITEMIDLIST pidl;
928 LPUNKNOWN pObj = NULL;
930 WINE_StringFromCLSID(riid,xclsid);
932 TRACE("(%p)->(%u,%u,apidl=%p,\n\tIID:%s,%p,%p)\n",
933 This,hwndOwner,cidl,apidl,xclsid,prgfInOut,ppvOut);
935 if (!ppvOut)
936 return E_INVALIDARG;
938 *ppvOut = NULL;
940 if(IsEqualIID(riid, &IID_IContextMenu))
942 if(cidl < 1)
943 return E_INVALIDARG;
945 pObj = (LPUNKNOWN)IContextMenu_Constructor((IShellFolder *)This, This->absPidl, apidl, cidl);
947 else if (IsEqualIID(riid, &IID_IDataObject))
949 if (cidl < 1)
950 return E_INVALIDARG;
952 pObj = (LPUNKNOWN)IDataObject_Constructor (hwndOwner, This->absPidl, apidl, cidl);
954 else if(IsEqualIID(riid, &IID_IExtractIconA))
956 if (cidl != 1)
957 return E_INVALIDARG;
959 pidl = ILCombine(This->absPidl,apidl[0]);
960 pObj = (LPUNKNOWN)IExtractIconA_Constructor( pidl );
961 SHFree(pidl);
963 else if (IsEqualIID(riid, &IID_IDropTarget))
965 if (cidl < 1)
966 return E_INVALIDARG;
968 pObj = (LPUNKNOWN)ISFDropTarget_Constructor();
970 else
972 ERR("(%p)->E_NOINTERFACE\n",This);
973 return E_NOINTERFACE;
976 if(!pObj)
977 return E_OUTOFMEMORY;
979 *ppvOut = pObj;
980 return S_OK;
983 /**************************************************************************
984 * IShellFolder_fnGetDisplayNameOf
985 * Retrieves the display name for the specified file object or subfolder
987 * PARAMETERS
988 * LPCITEMIDLIST pidl, //[in ] complex pidl to item
989 * DWORD dwFlags, //[in ] SHGNO formatting flags
990 * LPSTRRET lpName) //[out] Returned display name
992 * FIXME
993 * if the name is in the pidl the ret value should be a STRRET_OFFSET
995 #define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
996 #define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
998 static HRESULT WINAPI IShellFolder_fnGetDisplayNameOf(
999 IShellFolder * iface,
1000 LPCITEMIDLIST pidl,
1001 DWORD dwFlags,
1002 LPSTRRET strRet)
1004 ICOM_THIS(IGenericSFImpl, iface);
1006 CHAR szPath[MAX_PATH]= "";
1007 int len = 0;
1008 BOOL bSimplePidl;
1010 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1011 pdump(pidl);
1013 if(!pidl || !strRet) return E_INVALIDARG;
1015 bSimplePidl = _ILIsPidlSimple(pidl);
1017 /* take names of special folders only if its only this folder */
1018 if (_ILIsSpecialFolder(pidl))
1020 if ( bSimplePidl)
1022 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1025 else
1027 if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sMyPath)
1029 strcpy (szPath, This->sMyPath); /* get path to root*/
1030 PathAddBackslashA(szPath);
1031 len = strlen(szPath);
1033 _ILSimpleGetText(pidl, szPath + len, MAX_PATH - len); /* append my own path */
1036 if ( (dwFlags & SHGDN_FORPARSING) && !bSimplePidl) /* go deeper if needed */
1038 PathAddBackslashA(szPath);
1039 len = strlen(szPath);
1041 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild((IShellFolder*)This, pidl, dwFlags, szPath + len, MAX_PATH - len)))
1042 return E_OUTOFMEMORY;
1044 strRet->uType = STRRET_CSTRA;
1045 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1047 TRACE("-- (%p)->(%s)\n", This, szPath);
1048 return S_OK;
1051 /**************************************************************************
1052 * IShellFolder_fnSetNameOf
1053 * Changes the name of a file object or subfolder, possibly changing its item
1054 * identifier in the process.
1056 * PARAMETERS
1057 * HWND hwndOwner, //[in ] Owner window for output
1058 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
1059 * LPCOLESTR lpszName, //[in ] the items new display name
1060 * DWORD dwFlags, //[in ] SHGNO formatting flags
1061 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
1063 static HRESULT WINAPI IShellFolder_fnSetNameOf(
1064 IShellFolder * iface,
1065 HWND hwndOwner,
1066 LPCITEMIDLIST pidl, /*simple pidl*/
1067 LPCOLESTR lpName,
1068 DWORD dw,
1069 LPITEMIDLIST *pPidlOut)
1071 ICOM_THIS(IGenericSFImpl, iface);
1073 FIXME("(%p)->(%u,pidl=%p,%s,%lu,%p),stub!\n",
1074 This,hwndOwner,pidl,debugstr_w(lpName),dw,pPidlOut);
1076 return E_NOTIMPL;
1079 /**************************************************************************
1080 * IShellFolder_fnGetFolderPath
1082 static HRESULT WINAPI IShellFolder_fnGetFolderPath(IShellFolder * iface, LPSTR lpszOut, DWORD dwOutSize)
1084 ICOM_THIS(IGenericSFImpl, iface);
1086 TRACE("(%p)->(%p %lu)\n",This, lpszOut, dwOutSize);
1088 if (!lpszOut) return FALSE;
1090 *lpszOut=0;
1092 if (! This->sMyPath) return FALSE;
1094 lstrcpynA(lpszOut, This->sMyPath, dwOutSize);
1096 TRACE("-- (%p)->(return=%s)\n",This, lpszOut);
1097 return TRUE;
1100 static ICOM_VTABLE(IShellFolder) sfvt =
1102 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1103 IShellFolder_fnQueryInterface,
1104 IShellFolder_fnAddRef,
1105 IShellFolder_fnRelease,
1106 IShellFolder_fnParseDisplayName,
1107 IShellFolder_fnEnumObjects,
1108 IShellFolder_fnBindToObject,
1109 IShellFolder_fnBindToStorage,
1110 IShellFolder_fnCompareIDs,
1111 IShellFolder_fnCreateViewObject,
1112 IShellFolder_fnGetAttributesOf,
1113 IShellFolder_fnGetUIObjectOf,
1114 IShellFolder_fnGetDisplayNameOf,
1115 IShellFolder_fnSetNameOf,
1116 IShellFolder_fnGetFolderPath
1119 /***********************************************************************
1120 * [Desktopfolder] IShellFolder implementation
1122 static struct ICOM_VTABLE(IShellFolder) sfdvt;
1124 /**************************************************************************
1125 * ISF_Desktop_Constructor
1128 IShellFolder * ISF_Desktop_Constructor()
1130 IGenericSFImpl * sf;
1132 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
1133 sf->ref=1;
1134 sf->lpvtbl=&sfdvt;
1135 sf->absPidl=_ILCreateDesktop(); /* my qualified pidl */
1137 TRACE("(%p)\n",sf);
1139 shell32_ObjCount++;
1140 return (IShellFolder *)sf;
1143 /**************************************************************************
1144 * ISF_Desktop_fnQueryInterface
1146 * NOTES supports not IPersist/IPersistFolder
1148 static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
1149 IShellFolder * iface,
1150 REFIID riid,
1151 LPVOID *ppvObj)
1153 ICOM_THIS(IGenericSFImpl, iface);
1155 char xriid[50];
1156 WINE_StringFromCLSID((LPCLSID)riid,xriid);
1157 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,xriid,ppvObj);
1159 *ppvObj = NULL;
1161 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
1162 { *ppvObj = This;
1164 else if(IsEqualIID(riid, &IID_IShellFolder)) /*IShellFolder*/
1165 { *ppvObj = (IShellFolder*)This;
1168 if(*ppvObj)
1170 IUnknown_AddRef((IUnknown*)(*ppvObj));
1171 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1172 return S_OK;
1174 TRACE("-- Interface: E_NOINTERFACE\n");
1175 return E_NOINTERFACE;
1178 /**************************************************************************
1179 * ISF_Desktop_fnParseDisplayName
1181 * NOTES
1182 * "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
1183 * to MyComputer
1185 static HRESULT WINAPI ISF_Desktop_fnParseDisplayName(
1186 IShellFolder * iface,
1187 HWND hwndOwner,
1188 LPBC pbcReserved,
1189 LPOLESTR lpszDisplayName,
1190 DWORD *pchEaten,
1191 LPITEMIDLIST *ppidl,
1192 DWORD *pdwAttributes)
1194 ICOM_THIS(IGenericSFImpl, iface);
1196 LPCWSTR szNext=NULL;
1197 LPITEMIDLIST pidlTemp=NULL;
1198 HRESULT hr=E_OUTOFMEMORY;
1200 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1201 This,hwndOwner,pbcReserved,lpszDisplayName,
1202 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1204 *ppidl = 0;
1205 if (pchEaten) *pchEaten = 0; /* strange but like the original */
1207 /* fixme no real parsing implemented */
1208 pidlTemp = _ILCreateMyComputer();
1209 szNext = lpszDisplayName;
1211 if (szNext && *szNext)
1213 hr = SHELL32_ParseNextElement(hwndOwner, (IShellFolder*)This, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1215 else
1217 hr = S_OK;
1220 *ppidl = pidlTemp;
1222 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1224 return hr;
1227 /**************************************************************************
1228 * ISF_Desktop_fnEnumObjects
1230 static HRESULT WINAPI ISF_Desktop_fnEnumObjects(
1231 IShellFolder * iface,
1232 HWND hwndOwner,
1233 DWORD dwFlags,
1234 LPENUMIDLIST* ppEnumIDList)
1236 ICOM_THIS(IGenericSFImpl, iface);
1238 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1240 *ppEnumIDList = NULL;
1241 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_DESK);
1243 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1245 if(!*ppEnumIDList) return E_OUTOFMEMORY;
1247 return S_OK;
1250 /**************************************************************************
1251 * ISF_Desktop_fnBindToObject
1253 static HRESULT WINAPI ISF_Desktop_fnBindToObject( IShellFolder * iface, LPCITEMIDLIST pidl,
1254 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1256 ICOM_THIS(IGenericSFImpl, iface);
1257 GUID const * clsid;
1258 char xriid[50];
1259 IShellFolder *pShellFolder, *pSubFolder;
1261 WINE_StringFromCLSID(riid,xriid);
1263 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",This,pidl,pbcReserved,xriid,ppvOut);
1265 *ppvOut = NULL;
1267 if (!(clsid=_ILGetGUIDPointer(pidl))) return E_INVALIDARG;
1269 if ( IsEqualIID(clsid, &IID_MyComputer))
1271 pShellFolder = ISF_MyComputer_Constructor();
1273 else
1275 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1277 return E_INVALIDARG;
1281 if (_ILIsPidlSimple(pidl)) /* no sub folders */
1283 *ppvOut = pShellFolder;
1285 else /* go deeper */
1287 IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID)&pSubFolder);
1288 IShellFolder_Release(pShellFolder);
1289 *ppvOut = pSubFolder;
1292 TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
1294 return S_OK;
1297 /**************************************************************************
1298 * ISF_Desktop_fnGetAttributesOf
1300 static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf(IShellFolder * iface,UINT cidl,LPCITEMIDLIST *apidl,DWORD *rgfInOut)
1302 ICOM_THIS(IGenericSFImpl, iface);
1304 GUID const * clsid;
1305 DWORD attributes;
1306 HRESULT hr = S_OK;
1308 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl, *rgfInOut);
1310 if ( (!cidl) || (!apidl) || (!rgfInOut))
1311 return E_INVALIDARG;
1313 while (cidl > 0 && *apidl)
1315 pdump (*apidl);
1317 if ((clsid=_ILGetGUIDPointer(*apidl)))
1319 if (IsEqualIID(clsid, &IID_MyComputer))
1321 *rgfInOut &= 0xb0000154;
1322 goto next;
1324 else if (HCR_GetFolderAttributes(clsid, &attributes))
1326 *rgfInOut &= attributes;
1327 goto next;
1330 else if (_ILIsFolder( *apidl))
1332 *rgfInOut &= 0xe0000177;
1333 goto next;
1335 else if (_ILIsValue( *apidl))
1337 *rgfInOut &= 0x40000177;
1338 goto next;
1340 hr = E_INVALIDARG;
1342 next: apidl++;
1343 cidl--;
1346 TRACE("-- result=0x%08lx\n",*rgfInOut);
1348 return hr;
1351 /**************************************************************************
1352 * ISF_Desktop_fnGetDisplayNameOf
1354 * NOTES
1355 * special case: pidl = null gives desktop-name back
1357 static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf(
1358 IShellFolder * iface,
1359 LPCITEMIDLIST pidl,
1360 DWORD dwFlags,
1361 LPSTRRET strRet)
1363 ICOM_THIS(IGenericSFImpl, iface);
1365 CHAR szPath[MAX_PATH]= "";
1367 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1368 pdump(pidl);
1370 if(!strRet) return E_INVALIDARG;
1372 if(!pidl)
1374 HCR_GetClassName(&CLSID_ShellDesktop, szPath, MAX_PATH);
1376 else if ( _ILIsPidlSimple(pidl) )
1378 _ILSimpleGetText(pidl, szPath, MAX_PATH);
1380 else
1382 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild((IShellFolder*)This, pidl, dwFlags, szPath, MAX_PATH)))
1383 return E_OUTOFMEMORY;
1385 strRet->uType = STRRET_CSTRA;
1386 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1389 TRACE("-- (%p)->(%s)\n", This, szPath);
1390 return S_OK;
1393 static ICOM_VTABLE(IShellFolder) sfdvt =
1395 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1396 ISF_Desktop_fnQueryInterface,
1397 IShellFolder_fnAddRef,
1398 IShellFolder_fnRelease,
1399 ISF_Desktop_fnParseDisplayName,
1400 ISF_Desktop_fnEnumObjects,
1401 ISF_Desktop_fnBindToObject,
1402 IShellFolder_fnBindToStorage,
1403 IShellFolder_fnCompareIDs,
1404 IShellFolder_fnCreateViewObject,
1405 ISF_Desktop_fnGetAttributesOf,
1406 IShellFolder_fnGetUIObjectOf,
1407 ISF_Desktop_fnGetDisplayNameOf,
1408 IShellFolder_fnSetNameOf,
1409 IShellFolder_fnGetFolderPath
1413 /***********************************************************************
1414 * IShellFolder [MyComputer] implementation
1417 static struct ICOM_VTABLE(IShellFolder) sfmcvt;
1419 /**************************************************************************
1420 * ISF_MyComputer_Constructor
1422 static IShellFolder * ISF_MyComputer_Constructor(void)
1424 IGenericSFImpl * sf;
1426 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
1427 sf->ref=1;
1429 sf->lpvtbl = &sfmcvt;
1430 sf->lpvtblPersistFolder = &psfvt;
1431 sf->pclsid = (CLSID*)&CLSID_SFMyComp;
1432 sf->absPidl=_ILCreateMyComputer(); /* my qualified pidl */
1434 TRACE("(%p)\n",sf);
1436 shell32_ObjCount++;
1437 return (IShellFolder *)sf;
1440 /**************************************************************************
1441 * ISF_MyComputer_fnParseDisplayName
1443 static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName(
1444 IShellFolder * iface,
1445 HWND hwndOwner,
1446 LPBC pbcReserved,
1447 LPOLESTR lpszDisplayName,
1448 DWORD *pchEaten,
1449 LPITEMIDLIST *ppidl,
1450 DWORD *pdwAttributes)
1452 ICOM_THIS(IGenericSFImpl, iface);
1454 HRESULT hr = E_OUTOFMEMORY;
1455 LPCWSTR szNext=NULL;
1456 WCHAR szElement[MAX_PATH];
1457 CHAR szTempA[MAX_PATH];
1458 LPITEMIDLIST pidlTemp;
1460 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1461 This,hwndOwner,pbcReserved,lpszDisplayName,
1462 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1464 *ppidl = 0;
1465 if (pchEaten) *pchEaten = 0; /* strange but like the original */
1467 if (PathIsRootW(lpszDisplayName))
1469 szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
1470 WideCharToLocal(szTempA, szElement, lstrlenW(szElement) + 1);
1471 pidlTemp = _ILCreateDrive(szTempA);
1473 if (szNext && *szNext)
1475 hr = SHELL32_ParseNextElement(hwndOwner, (IShellFolder*)This, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1477 else
1479 hr = S_OK;
1481 *ppidl = pidlTemp;
1484 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1486 return hr;
1489 /**************************************************************************
1490 * ISF_MyComputer_fnEnumObjects
1492 static HRESULT WINAPI ISF_MyComputer_fnEnumObjects(
1493 IShellFolder * iface,
1494 HWND hwndOwner,
1495 DWORD dwFlags,
1496 LPENUMIDLIST* ppEnumIDList)
1498 ICOM_THIS(IGenericSFImpl, iface);
1500 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1502 *ppEnumIDList = NULL;
1503 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
1505 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1507 if(!*ppEnumIDList) return E_OUTOFMEMORY;
1509 return S_OK;
1512 /**************************************************************************
1513 * ISF_MyComputer_fnBindToObject
1515 static HRESULT WINAPI ISF_MyComputer_fnBindToObject( IShellFolder * iface, LPCITEMIDLIST pidl,
1516 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1518 ICOM_THIS(IGenericSFImpl, iface);
1519 GUID const * clsid;
1520 char xriid[50];
1521 IShellFolder *pShellFolder, *pSubFolder;
1522 LPITEMIDLIST pidltemp;
1524 WINE_StringFromCLSID(riid,xriid);
1526 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",This,pidl,pbcReserved,xriid,ppvOut);
1528 *ppvOut = NULL;
1530 if ((clsid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(clsid, &IID_MyComputer))
1532 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1534 return E_FAIL;
1537 else
1539 if (!_ILIsDrive(pidl)) return E_INVALIDARG;
1541 pidltemp = ILCloneFirst(pidl);
1542 pShellFolder = IShellFolder_Constructor((IShellFolder*)This, pidltemp);
1543 ILFree(pidltemp);
1546 if (_ILIsPidlSimple(pidl)) /* no sub folders */
1548 *ppvOut = pShellFolder;
1550 else /* go deeper */
1552 IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, &IID_IShellFolder, (LPVOID)&pSubFolder);
1553 IShellFolder_Release(pShellFolder);
1554 *ppvOut = pSubFolder;
1557 TRACE("-- (%p) returning (%p)\n",This, *ppvOut);
1559 return S_OK;
1562 /**************************************************************************
1563 * ISF_MyComputer_fnGetAttributesOf
1565 static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf(IShellFolder * iface,UINT cidl,LPCITEMIDLIST *apidl,DWORD *rgfInOut)
1567 ICOM_THIS(IGenericSFImpl, iface);
1569 GUID const * clsid;
1570 DWORD attributes;
1571 HRESULT hr = S_OK;
1573 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
1575 if ( (!cidl) || (!apidl) || (!rgfInOut))
1576 return E_INVALIDARG;
1578 *rgfInOut = 0xffffffff;
1580 while (cidl > 0 && *apidl)
1582 pdump (*apidl);
1584 if (_ILIsDrive(*apidl))
1586 *rgfInOut &= 0xf0000144;
1587 goto next;
1589 else if ((clsid=_ILGetGUIDPointer(*apidl)))
1591 if (HCR_GetFolderAttributes(clsid, &attributes))
1593 *rgfInOut &= attributes;
1594 goto next;
1597 hr = E_INVALIDARG;
1599 next: apidl++;
1600 cidl--;
1603 TRACE("-- result=0x%08lx\n",*rgfInOut);
1604 return hr;
1607 /**************************************************************************
1608 * ISF_MyComputer_fnGetDisplayNameOf
1610 * NOTES
1611 * The desktopfolder creates only complete paths (SHGDN_FORPARSING).
1612 * SHGDN_INFOLDER makes no sense.
1614 static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf(
1615 IShellFolder * iface,
1616 LPCITEMIDLIST pidl,
1617 DWORD dwFlags,
1618 LPSTRRET strRet)
1620 ICOM_THIS(IGenericSFImpl, iface);
1622 char szPath[MAX_PATH], szDrive[18];
1623 int len = 0;
1624 BOOL bSimplePidl;
1626 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1627 pdump(pidl);
1629 if(!strRet) return E_INVALIDARG;
1631 szPath[0]=0x00; szDrive[0]=0x00;
1634 bSimplePidl = _ILIsPidlSimple(pidl);
1636 if (_ILIsSpecialFolder(pidl))
1638 /* take names of special folders only if its only this folder */
1639 if ( bSimplePidl )
1641 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1644 else
1646 if (!_ILIsDrive(pidl))
1648 ERR("Wrong pidl type\n");
1649 return E_INVALIDARG;
1652 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1654 /* long view "lw_name (C:)" */
1655 if ( bSimplePidl && !(dwFlags & SHGDN_FORPARSING))
1657 DWORD dwVolumeSerialNumber,dwMaximumComponetLength,dwFileSystemFlags;
1659 GetVolumeInformationA(szPath,szDrive,12,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
1660 strcat (szDrive," (");
1661 strncat (szDrive, szPath, 2);
1662 strcat (szDrive,")");
1663 strcpy (szPath, szDrive);
1667 if (!bSimplePidl) /* go deeper if needed */
1669 PathAddBackslashA(szPath);
1670 len = strlen(szPath);
1672 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild((IShellFolder*)This, pidl, dwFlags | SHGDN_FORPARSING, szPath + len, MAX_PATH - len)))
1673 return E_OUTOFMEMORY;
1675 strRet->uType = STRRET_CSTRA;
1676 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1679 TRACE("-- (%p)->(%s)\n", This, szPath);
1680 return S_OK;
1683 static ICOM_VTABLE(IShellFolder) sfmcvt =
1685 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1686 IShellFolder_fnQueryInterface,
1687 IShellFolder_fnAddRef,
1688 IShellFolder_fnRelease,
1689 ISF_MyComputer_fnParseDisplayName,
1690 ISF_MyComputer_fnEnumObjects,
1691 ISF_MyComputer_fnBindToObject,
1692 IShellFolder_fnBindToStorage,
1693 IShellFolder_fnCompareIDs,
1694 IShellFolder_fnCreateViewObject,
1695 ISF_MyComputer_fnGetAttributesOf,
1696 IShellFolder_fnGetUIObjectOf,
1697 ISF_MyComputer_fnGetDisplayNameOf,
1698 IShellFolder_fnSetNameOf,
1699 IShellFolder_fnGetFolderPath
1703 /************************************************************************
1704 * ISFPersistFolder_QueryInterface (IUnknown)
1707 static HRESULT WINAPI ISFPersistFolder_QueryInterface(
1708 IPersistFolder * iface,
1709 REFIID iid,
1710 LPVOID* ppvObj)
1712 _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface);
1714 return IShellFolder_QueryInterface((IShellFolder*)This, iid, ppvObj);
1717 /************************************************************************
1718 * ISFPersistFolder_AddRef (IUnknown)
1721 static ULONG WINAPI ISFPersistFolder_AddRef(
1722 IPersistFolder * iface)
1724 _ICOM_THIS_From_IPersistFolder(IShellFolder, iface);
1726 return IShellFolder_AddRef((IShellFolder*)This);
1729 /************************************************************************
1730 * ISFPersistFolder_Release (IUnknown)
1733 static ULONG WINAPI ISFPersistFolder_Release(
1734 IPersistFolder * iface)
1736 _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface);
1738 return IShellFolder_Release((IShellFolder*)This);
1741 /************************************************************************
1742 * ISFPersistFolder_GetClassID (IPersist)
1744 static HRESULT WINAPI ISFPersistFolder_GetClassID(
1745 IPersistFolder * iface,
1746 CLSID * lpClassId)
1748 _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface);
1750 if (!lpClassId) return E_POINTER;
1751 *lpClassId = *This->pclsid;
1753 return S_OK;
1756 /************************************************************************
1757 * ISFPersistFolder_Initialize (IPersistFolder)
1759 * NOTES
1760 * sMyPath is not set. Don't know how to handle in a non rooted environment.
1762 static HRESULT WINAPI ISFPersistFolder_Initialize(
1763 IPersistFolder * iface,
1764 LPCITEMIDLIST pidl)
1766 _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface);
1768 if(This->absPidl)
1770 SHFree(This->absPidl);
1771 This->absPidl = NULL;
1773 This->absPidl = ILClone(pidl);
1774 return S_OK;
1777 static ICOM_VTABLE(IPersistFolder) psfvt =
1779 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1780 ISFPersistFolder_QueryInterface,
1781 ISFPersistFolder_AddRef,
1782 ISFPersistFolder_Release,
1783 ISFPersistFolder_GetClassID,
1784 ISFPersistFolder_Initialize