4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998, 1999 Juergen Schmied
7 * IShellFolder2 and related interfaces
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #include "wine/obj_base.h"
37 #include "wine/obj_dragdrop.h"
38 #include "wine/obj_shellfolder.h"
39 #include "undocshell.h"
40 #include "shell32_main.h"
43 #include "shellfolder.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(shell);
49 /***************************************************************************
50 * debughelper: print out the return adress
51 * helps especially to track down unbalanced AddRef/Release
56 #define _CALL_TRACE TRACE("called from: 0x%08x\n", *( ((UINT*)&iface)-1 ));
70 /***************************************************************************
71 * GetNextElement (internal function)
73 * gets a part of a string till the first backslash
76 * pszNext [IN] string to get the element from
77 * pszOut [IN] pointer to buffer whitch receives string
78 * dwOut [IN] length of pszOut
81 * LPSTR pointer to first, not yet parsed char
84 static LPCWSTR GetNextElementW(LPCWSTR pszNext,LPWSTR pszOut,DWORD dwOut)
85 { LPCWSTR pszTail = pszNext;
87 TRACE("(%s %p 0x%08lx)\n",debugstr_w(pszNext),pszOut,dwOut);
91 if(!pszNext || !*pszNext)
94 while(*pszTail && (*pszTail != (WCHAR)'\\'))
97 dwCopy = (WCHAR*)pszTail - (WCHAR*)pszNext + 1;
98 lstrcpynW(pszOut, pszNext, (dwOut<dwCopy)? dwOut : dwCopy);
105 TRACE("--(%s %s 0x%08lx %p)\n",debugstr_w(pszNext),debugstr_w(pszOut),dwOut,pszTail);
109 static HRESULT SHELL32_ParseNextElement(
112 LPITEMIDLIST * pidlInOut,
115 DWORD *pdwAttributes)
117 HRESULT hr = E_OUTOFMEMORY;
118 LPITEMIDLIST pidlOut, pidlTemp = NULL;
119 IShellFolder *psfChild;
121 TRACE("(%p, %p, %s)\n",psf, pidlInOut ? *pidlInOut : NULL, debugstr_w(szNext));
124 /* get the shellfolder for the child pidl and let it analyse further */
125 hr = IShellFolder_BindToObject(psf, *pidlInOut, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
129 hr = IShellFolder_ParseDisplayName(psfChild, hwndOwner, NULL, szNext, pEaten, &pidlOut, pdwAttributes);
130 IShellFolder_Release(psfChild);
132 pidlTemp = ILCombine(*pidlInOut, pidlOut);
139 *pidlInOut = pidlTemp;
141 TRACE("-- pidl=%p ret=0x%08lx\n", pidlInOut? *pidlInOut: NULL, hr);
145 /***********************************************************************
146 * SHELL32_CoCreateInitSF
148 * creates a initialized shell folder
150 static HRESULT SHELL32_CoCreateInitSF (
151 LPITEMIDLIST pidlRoot,
152 LPITEMIDLIST pidlChild,
158 LPITEMIDLIST absPidl;
159 IShellFolder2 *pShellFolder;
160 IPersistFolder *pPersistFolder;
162 TRACE("%p %p\n", pidlRoot, pidlChild);
166 /* we have to ask first for IPersistFolder, some special folders are expecting this */
167 hr = SHCoCreateInstance(NULL, clsid, NULL, &IID_IPersistFolder, (LPVOID*)&pPersistFolder);
170 hr = IPersistFolder_QueryInterface(pPersistFolder, iid, (LPVOID*)&pShellFolder);
173 absPidl = ILCombine (pidlRoot, pidlChild);
174 hr = IPersistFolder_Initialize(pPersistFolder, absPidl);
175 IPersistFolder_Release(pPersistFolder);
177 *ppvOut = pShellFolder;
181 TRACE("-- ret=0x%08lx\n", hr);
185 static HRESULT SHELL32_GetDisplayNameOfChild(
192 LPITEMIDLIST pidlFirst, pidlNext;
193 IShellFolder2 * psfChild;
194 HRESULT hr = E_OUTOFMEMORY;
197 TRACE("(%p)->(pidl=%p 0x%08lx %p 0x%08lx)\n",psf,pidl,dwFlags,szOut, dwOutLen);
200 if ((pidlFirst = ILCloneFirst(pidl)))
202 hr = IShellFolder_BindToObject(psf, pidlFirst, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
205 pidlNext = ILGetNext(pidl);
207 hr = IShellFolder_GetDisplayNameOf(psfChild, pidlNext, dwFlags | SHGDN_INFOLDER, &strTemp);
210 hr = StrRetToStrNA(szOut, dwOutLen, &strTemp, pidlNext);
213 IShellFolder_Release(psfChild);
218 TRACE("-- ret=0x%08lx %s\n", hr, szOut);
223 /***********************************************************************
224 * SHELL32_GetItemAttributes
228 * folder: 0xE0000177 FILESYSTEM | HASSUBFOLDER | FOLDER
229 * file: 0x40000177 FILESYSTEM
230 * drive: 0xf0000144 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR
231 * mycomputer: 0xb0000154 HASSUBFOLDER | FOLDER | FILESYSANCESTOR
232 * (seems to be default for shell extensions if no registry entry exists)
234 * This functions does not set flags!! It only resets flags when nessesary.
236 static HRESULT SHELL32_GetItemAttributes(
239 LPDWORD pdwAttributes)
244 TRACE("0x%08lx\n", *pdwAttributes);
246 if (*pdwAttributes & (0xcff3fe88))
247 WARN("attribute 0x%08lx not implemented\n", *pdwAttributes);
248 *pdwAttributes &= ~SFGAO_LINK; /* FIXME: for native filedialogs */
250 if (_ILIsDrive(pidl))
252 *pdwAttributes &= 0xf0000144;
254 else if ((clsid=_ILGetGUIDPointer(pidl)))
256 if (HCR_GetFolderAttributes(clsid, &dwAttributes))
258 *pdwAttributes &= dwAttributes;
262 *pdwAttributes &= 0xb0000154;
265 else if (_ILGetDataPointer(pidl))
267 dwAttributes = _ILGetFileAttributes(pidl, NULL, 0);
268 *pdwAttributes &= ~SFGAO_FILESYSANCESTOR;
270 if(( SFGAO_FOLDER & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
271 *pdwAttributes &= ~(SFGAO_FOLDER|SFGAO_HASSUBFOLDER);
273 if(( SFGAO_HIDDEN & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_HIDDEN))
274 *pdwAttributes &= ~SFGAO_HIDDEN;
276 if(( SFGAO_READONLY & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_READONLY))
277 *pdwAttributes &= ~SFGAO_READONLY;
281 *pdwAttributes &= 0xb0000154;
283 TRACE("-- 0x%08lx\n", *pdwAttributes);
287 /***********************************************************************
288 * IShellFolder implementation
293 ICOM_VFIELD(IUnknown);
295 ICOM_VTABLE(IShellFolder2)* lpvtblShellFolder;
296 ICOM_VTABLE(IPersistFolder2)* lpvtblPersistFolder2;
297 ICOM_VTABLE(IDropTarget)* lpvtblDropTarget;
298 ICOM_VTABLE(ISFHelper)* lpvtblSFHelper;
300 IUnknown *pUnkOuter; /* used for aggregation */
305 LPITEMIDLIST absPidl; /* complete pidl */
307 UINT cfShellIDList; /* clipboardformat for IDropTarget */
308 BOOL fAcceptFmt; /* flag for pending Drop */
311 static struct ICOM_VTABLE(IUnknown) unkvt;
312 static struct ICOM_VTABLE(IShellFolder2) sfvt;
313 static struct ICOM_VTABLE(IPersistFolder2) psfvt;
314 static struct ICOM_VTABLE(IDropTarget) dtvt;
315 static struct ICOM_VTABLE(ISFHelper) shvt;
317 static IShellFolder * ISF_MyComputer_Constructor(void);
319 #define _IShellFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblShellFolder)))
320 #define _ICOM_THIS_From_IShellFolder2(class, name) class* This = (class*)(((char*)name)-_IShellFolder2_Offset);
322 #define _IPersistFolder_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder2)))
323 #define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder_Offset);
325 #define _IDropTarget_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblDropTarget)))
326 #define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset);
328 #define _ISFHelper_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblSFHelper)))
329 #define _ICOM_THIS_From_ISFHelper(class, name) class* This = (class*)(((char*)name)-_ISFHelper_Offset);
331 converts This to a interface pointer
333 #define _IUnknown_(This) (IUnknown*)&(This->lpVtbl)
334 #define _IShellFolder_(This) (IShellFolder*)&(This->lpvtblShellFolder)
335 #define _IShellFolder2_(This) (IShellFolder2*)&(This->lpvtblShellFolder)
336 #define _IPersist_(This) (IPersist*)&(This->lpvtblPersistFolder2)
337 #define _IPersistFolder_(This) (IPersistFolder*)&(This->lpvtblPersistFolder2)
338 #define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpvtblPersistFolder2)
339 #define _IDropTarget_(This) (IDropTarget*)&(This->lpvtblDropTarget)
340 #define _ISFHelper_(This) (ISFHelper*)&(This->lpvtblSFHelper)
341 /**************************************************************************
342 * registers clipboardformat once
344 static void SF_RegisterClipFmt (IGenericSFImpl * This)
346 TRACE("(%p)\n", This);
348 if (!This->cfShellIDList)
350 This->cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
354 /**************************************************************************
355 * we need a separate IUnknown to handle aggregation
358 static HRESULT WINAPI IUnknown_fnQueryInterface(
363 ICOM_THIS(IGenericSFImpl, iface);
366 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
370 if(IsEqualIID(riid, &IID_IUnknown)) *ppvObj = _IUnknown_(This);
371 else if(IsEqualIID(riid, &IID_IShellFolder)) *ppvObj = _IShellFolder_(This);
372 else if(IsEqualIID(riid, &IID_IShellFolder2)) *ppvObj = _IShellFolder_(This);
373 else if(IsEqualIID(riid, &IID_IPersist)) *ppvObj = _IPersist_(This);
374 else if(IsEqualIID(riid, &IID_IPersistFolder)) *ppvObj = _IPersistFolder_(This);
375 else if(IsEqualIID(riid, &IID_IPersistFolder2)) *ppvObj = _IPersistFolder2_(This);
376 else if(IsEqualIID(riid, &IID_ISFHelper)) *ppvObj = _ISFHelper_(This);
377 else if(IsEqualIID(riid, &IID_IDropTarget))
379 *ppvObj = _IDropTarget_(This);
380 SF_RegisterClipFmt(This);
385 IUnknown_AddRef((IUnknown*)(*ppvObj));
386 TRACE("-- Interface = %p\n", *ppvObj);
389 TRACE("-- Interface: E_NOINTERFACE\n");
390 return E_NOINTERFACE;
393 static ULONG WINAPI IUnknown_fnAddRef(IUnknown * iface)
395 ICOM_THIS(IGenericSFImpl, iface);
398 TRACE("(%p)->(count=%lu)\n",This,This->ref);
401 return ++(This->ref);
404 static ULONG WINAPI IUnknown_fnRelease(IUnknown * iface)
406 ICOM_THIS(IGenericSFImpl, iface);
409 TRACE("(%p)->(count=%lu)\n",This,This->ref);
414 TRACE("-- destroying IShellFolder(%p)\n",This);
416 if (pdesktopfolder == _IShellFolder_(This))
419 TRACE("-- destroyed IShellFolder(%p) was Desktopfolder\n",This);
421 if(This->absPidl) SHFree(This->absPidl);
422 if(This->sMyPath) SHFree(This->sMyPath);
423 HeapFree(GetProcessHeap(),0,This);
429 static ICOM_VTABLE(IUnknown) unkvt =
431 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
432 IUnknown_fnQueryInterface,
437 static shvheader GenericSFHeader [] =
439 { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
440 { IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
441 { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
442 { IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
443 { IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
445 #define GENERICSHELLVIEWCOLUMNS 5
447 /**************************************************************************
448 * IShellFolder_Constructor
451 * creating undocumented ShellFS_Folder as part of an aggregation
452 * {F3364BA0-65B9-11CE-A9BA-00AA004AE837}
455 * when pUnkOuter = 0 then rrid = IID_IShellFolder is returned
457 HRESULT IFSFolder_Constructor(
458 IUnknown * pUnkOuter,
465 TRACE("unkOut=%p riid=%s\n",pUnkOuter, debugstr_guid(riid));
467 if(pUnkOuter && ! IsEqualIID(riid, &IID_IUnknown))
469 hr = CLASS_E_NOAGGREGATION; /* forbidden by definition */
473 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
477 ICOM_VTBL(sf)=&unkvt;
478 sf->lpvtblShellFolder=&sfvt;
479 sf->lpvtblPersistFolder2=&psfvt;
480 sf->lpvtblDropTarget=&dtvt;
481 sf->lpvtblSFHelper=&shvt;
483 sf->pclsid = (CLSID*)&CLSID_SFFile;
484 sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_(sf);
485 *ppv = _IUnknown_(sf);
496 /**************************************************************************
497 * IShellFolder_Constructor
500 * THIS points to the parent folder
503 IShellFolder * IShellFolder_Constructor(
504 IShellFolder2 * iface,
510 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
512 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
515 ICOM_VTBL(sf)=&unkvt;
516 sf->lpvtblShellFolder=&sfvt;
517 sf->lpvtblPersistFolder2=&psfvt;
518 sf->lpvtblDropTarget=&dtvt;
519 sf->lpvtblSFHelper=&shvt;
521 sf->pclsid = (CLSID*)&CLSID_SFFile;
522 sf->pUnkOuter = _IUnknown_(sf);
524 TRACE("(%p)->(parent=%p, pidl=%p)\n",sf,This, pidl);
527 if(pidl && iface) /* do we have a pidl? */
531 sf->absPidl = ILCombine(This->absPidl, pidl); /* build a absolute pidl */
533 if (!_ILIsSpecialFolder(pidl)) /* only file system paths */
535 if(This->sMyPath) /* get the size of the parents path */
537 dwSize += strlen(This->sMyPath) ;
538 TRACE("-- (%p)->(parent's path=%s)\n",sf, debugstr_a(This->sMyPath));
541 dwSize += _ILSimpleGetText(pidl,NULL,0); /* add the size of our name*/
542 sf->sMyPath = SHAlloc(dwSize + 2); /* '\0' and backslash */
544 if(!sf->sMyPath) return NULL;
547 if(This->sMyPath) /* if the parent has a path, get it*/
549 strcpy(sf->sMyPath, This->sMyPath);
550 PathAddBackslashA (sf->sMyPath);
553 len = strlen(sf->sMyPath);
554 _ILSimpleGetText(pidl, sf->sMyPath + len, dwSize+2 - len);
557 TRACE("-- (%p)->(my pidl=%p, my path=%s)\n",sf, sf->absPidl,debugstr_a(sf->sMyPath));
563 return _IShellFolder_(sf);
566 /**************************************************************************
567 * IShellFolder_fnQueryInterface
570 * REFIID riid [in ] Requested InterfaceID
571 * LPVOID* ppvObject [out] Interface* to hold the result
573 static HRESULT WINAPI IShellFolder_fnQueryInterface(
574 IShellFolder2 * iface,
578 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
581 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
583 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
586 /**************************************************************************
587 * IShellFolder_AddRef
590 static ULONG WINAPI IShellFolder_fnAddRef(IShellFolder2 * iface)
592 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
595 TRACE("(%p)->(count=%lu)\n",This,This->ref);
597 return IUnknown_AddRef(This->pUnkOuter);
600 /**************************************************************************
601 * IShellFolder_fnRelease
603 static ULONG WINAPI IShellFolder_fnRelease(IShellFolder2 * iface)
605 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
608 TRACE("(%p)->(count=%lu)\n",This,This->ref);
610 return IUnknown_Release(This->pUnkOuter);
613 /**************************************************************************
614 * IShellFolder_fnParseDisplayName
616 * HWND hwndOwner, //[in ] Parent window for any message's
617 * LPBC pbc, //[in ] reserved
618 * LPOLESTR lpszDisplayName,//[in ] "Unicode" displayname.
619 * ULONG* pchEaten, //[out] (unicode) characters processed
620 * LPITEMIDLIST* ppidl, //[out] complex pidl to item
621 * ULONG* pdwAttributes //[out] items attributes
624 * every folder tries to parse only its own (the leftmost) pidl and creates a
625 * subfolder to evaluate the remaining parts
626 * now we can parse into namespaces implemented by shell extensions
628 * behaviour on win98: lpszDisplayName=NULL -> chrash
629 * lpszDisplayName="" -> returns mycoputer-pidl
632 * pdwAttributes: not set
633 * pchEaten: not set like in windows
635 static HRESULT WINAPI IShellFolder_fnParseDisplayName(
636 IShellFolder2 * iface,
639 LPOLESTR lpszDisplayName,
642 DWORD *pdwAttributes)
644 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
646 HRESULT hr = E_OUTOFMEMORY;
648 WCHAR szElement[MAX_PATH];
649 CHAR szTempA[MAX_PATH], szPath[MAX_PATH];
650 LPITEMIDLIST pidlTemp=NULL;
652 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
653 This,hwndOwner,pbcReserved,lpszDisplayName,
654 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
656 if (!lpszDisplayName || !ppidl) return E_INVALIDARG;
658 if (pchEaten) *pchEaten = 0; /* strange but like the original */
660 if (*lpszDisplayName)
662 /* get the next element */
663 szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
665 /* build the full pathname to the element */
666 WideCharToMultiByte( CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL );
667 strcpy(szPath, This->sMyPath);
668 PathAddBackslashA(szPath);
669 strcat(szPath, szTempA);
672 pidlTemp = SHSimpleIDListFromPathA(szPath);
676 /* try to analyse the next element */
677 if (szNext && *szNext)
679 hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
683 if (pdwAttributes && *pdwAttributes)
685 SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
686 /* WIN32_FIND_DATAA fd;
687 SHGetDataFromIDListA(_IShellFolder_(This), pidlTemp, SHGDFIL_FINDDATA, &fd, sizeof(fd));
688 if (!(FILE_ATTRIBUTE_DIRECTORY & fd.dwFileAttributes))
689 *pdwAttributes &= ~SFGAO_FOLDER;
690 if (FILE_ATTRIBUTE_READONLY & fd.dwFileAttributes)
691 *pdwAttributes &= ~(SFGAO_CANDELETE|SFGAO_CANMOVE|SFGAO_CANRENAME );
704 TRACE("(%p)->(-- pidl=%p ret=0x%08lx)\n", This, ppidl? *ppidl:0, hr);
709 /**************************************************************************
710 * IShellFolder_fnEnumObjects
712 * HWND hwndOwner, //[in ] Parent Window
713 * DWORD grfFlags, //[in ] SHCONTF enumeration mask
714 * LPENUMIDLIST* ppenumIDList //[out] IEnumIDList interface
716 static HRESULT WINAPI IShellFolder_fnEnumObjects(
717 IShellFolder2 * iface,
720 LPENUMIDLIST* ppEnumIDList)
722 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
724 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
726 *ppEnumIDList = NULL;
727 *ppEnumIDList = IEnumIDList_Constructor (This->sMyPath, dwFlags, EIDL_FILE);
729 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
731 if(!*ppEnumIDList) return E_OUTOFMEMORY;
736 /**************************************************************************
737 * IShellFolder_fnBindToObject
739 * LPCITEMIDLIST pidl, //[in ] relative pidl to open
740 * LPBC pbc, //[in ] reserved
741 * REFIID riid, //[in ] Initial Interface
742 * LPVOID* ppvObject //[out] Interface*
744 static HRESULT WINAPI IShellFolder_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
745 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
747 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
749 IShellFolder *pShellFolder, *pSubFolder;
750 IPersistFolder *pPersistFolder;
751 LPITEMIDLIST absPidl;
754 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
756 if(!pidl || !ppvOut) return E_INVALIDARG;
760 if ((iid=_ILGetGUIDPointer(pidl)))
762 /* we have to create a alien folder */
763 if ( SUCCEEDED(SHCoCreateInstance(NULL, iid, NULL, riid, (LPVOID*)&pShellFolder))
764 && SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&pPersistFolder)))
766 absPidl = ILCombine (This->absPidl, pidl);
767 IPersistFolder_Initialize(pPersistFolder, absPidl);
768 IPersistFolder_Release(pPersistFolder);
778 LPITEMIDLIST pidltemp = ILCloneFirst(pidl);
779 pShellFolder = IShellFolder_Constructor(iface, pidltemp);
783 if (_ILIsPidlSimple(pidl))
785 if(IsEqualIID(riid, &IID_IShellFolder))
787 *ppvOut = pShellFolder;
792 hr = IShellFolder_QueryInterface(pShellFolder, riid, ppvOut);
793 IShellFolder_Release(pShellFolder);
798 hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL,
799 riid, (LPVOID)&pSubFolder);
800 IShellFolder_Release(pShellFolder);
801 *ppvOut = pSubFolder;
804 TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
809 /**************************************************************************
810 * IShellFolder_fnBindToStorage
812 * LPCITEMIDLIST pidl, //[in ] complex pidl to store
813 * LPBC pbc, //[in ] reserved
814 * REFIID riid, //[in ] Initial storage interface
815 * LPVOID* ppvObject //[out] Interface* returned
817 static HRESULT WINAPI IShellFolder_fnBindToStorage(
818 IShellFolder2 * iface,
824 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
826 FIXME("(%p)->(pidl=%p,%p,\n\tIID:%s,%p) stub\n",
827 This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
833 /**************************************************************************
834 * IShellFolder_fnCompareIDs
837 * LPARAM lParam, //[in ] Column?
838 * LPCITEMIDLIST pidl1, //[in ] simple pidl
839 * LPCITEMIDLIST pidl2) //[in ] simple pidl
842 * Special case - If one of the items is a Path and the other is a File,
843 * always make the Path come before the File.
846 * use SCODE_CODE() on the return value to get the result
849 static HRESULT WINAPI IShellFolder_fnCompareIDs(
850 IShellFolder2 * iface,
855 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
857 CHAR szTemp1[MAX_PATH];
858 CHAR szTemp2[MAX_PATH];
861 HRESULT hr = E_OUTOFMEMORY;
862 LPCITEMIDLIST pidlTemp;
865 if (TRACE_ON(shell)) {
866 TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n",This,lParam,pidl1,pidl2);
871 if (!pidl1 && !pidl2)
873 hr = ResultFromShort(0);
877 hr = ResultFromShort(-1);
881 hr = ResultFromShort(1);
886 pd1 = _ILGetDataPointer(pidl1);
887 pd2 = _ILGetDataPointer(pidl2);
889 /* compate the types. sort order is the PT_* constant */
890 pt1 = ( pd1 ? pd1->type: PT_DESKTOP);
891 pt2 = ( pd2 ? pd2->type: PT_DESKTOP);
895 hr = ResultFromShort(pt1-pt2);
897 else /* same type of pidl */
899 _ILSimpleGetText(pidl1, szTemp1, MAX_PATH);
900 _ILSimpleGetText(pidl2, szTemp2, MAX_PATH);
901 nReturn = strcasecmp(szTemp1, szTemp2);
903 if (nReturn == 0) /* first pidl different ? */
905 pidl1 = ILGetNext(pidl1);
907 if (pidl1 && pidl1->mkid.cb) /* go deeper? */
909 pidlTemp = ILCloneFirst(pidl1);
910 pidl2 = ILGetNext(pidl2);
912 hr = IShellFolder_BindToObject(iface, pidlTemp, NULL, &IID_IShellFolder, (LPVOID*)&psf);
915 nReturn = IShellFolder_CompareIDs(psf, 0, pidl1, pidl2);
916 IShellFolder_Release(psf);
917 hr = ResultFromShort(nReturn);
921 else /* no deeper on #1 */
923 pidl2 = ILGetNext(pidl2);
924 if (pidl2 && pidl2->mkid.cb) /* go deeper on #2 ? */
925 hr = ResultFromShort(-1); /* two different */
927 hr = ResultFromShort(nReturn); /* two equal simple pidls */
932 hr = ResultFromShort(nReturn); /* two different simple pidls */
937 TRACE("-- res=0x%08lx\n", hr);
941 /**************************************************************************
942 * IShellFolder_fnCreateViewObject
944 static HRESULT WINAPI IShellFolder_fnCreateViewObject(
945 IShellFolder2 * iface,
950 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
952 LPSHELLVIEW pShellView;
953 HRESULT hr = E_INVALIDARG;
955 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
961 if(IsEqualIID(riid, &IID_IDropTarget))
963 hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, ppvOut);
965 else if(IsEqualIID(riid, &IID_IContextMenu))
967 FIXME("IContextMenu not implemented\n");
970 else if(IsEqualIID(riid, &IID_IShellView))
972 pShellView = IShellView_Constructor((IShellFolder*)iface);
975 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
976 IShellView_Release(pShellView);
980 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
984 /**************************************************************************
985 * IShellFolder_fnGetAttributesOf
988 * UINT cidl, //[in ] num elements in pidl array
989 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
990 * ULONG* rgfInOut) //[out] result array
993 static HRESULT WINAPI IShellFolder_fnGetAttributesOf(
994 IShellFolder2 * iface,
996 LPCITEMIDLIST *apidl,
999 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1003 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
1005 if ( (!cidl) || (!apidl) || (!rgfInOut))
1006 return E_INVALIDARG;
1008 while (cidl > 0 && *apidl)
1011 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
1016 TRACE("-- result=0x%08lx\n",*rgfInOut);
1020 /**************************************************************************
1021 * IShellFolder_fnGetUIObjectOf
1024 * HWND hwndOwner, //[in ] Parent window for any output
1025 * UINT cidl, //[in ] array size
1026 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
1027 * REFIID riid, //[in ] Requested Interface
1028 * UINT* prgfInOut, //[ ] reserved
1029 * LPVOID* ppvObject) //[out] Resulting Interface
1032 * This function gets asked to return "view objects" for one or more (multiple select)
1034 * The viewobject typically is an COM object with one of the following interfaces:
1035 * IExtractIcon,IDataObject,IContextMenu
1036 * In order to support icon positions in the default Listview your DataObject
1037 * must implement the SetData method (in addition to GetData :) - the shell passes
1038 * a barely documented "Icon positions" structure to SetData when the drag starts,
1039 * and GetData's it if the drop is in another explorer window that needs the positions.
1041 static HRESULT WINAPI IShellFolder_fnGetUIObjectOf(
1042 IShellFolder2 * iface,
1045 LPCITEMIDLIST * apidl,
1050 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1053 IUnknown* pObj = NULL;
1054 HRESULT hr = E_INVALIDARG;
1056 TRACE("(%p)->(0x%04x,%u,apidl=%p,\n\tIID:%s,%p,%p)\n",
1057 This,hwndOwner,cidl,apidl,debugstr_guid(riid),prgfInOut,ppvOut);
1063 if(IsEqualIID(riid, &IID_IContextMenu) && (cidl >= 1))
1065 pObj = (LPUNKNOWN)ISvItemCm_Constructor((IShellFolder*)iface, This->absPidl, apidl, cidl);
1068 else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1))
1070 pObj = (LPUNKNOWN)IDataObject_Constructor (hwndOwner, This->absPidl, apidl, cidl);
1073 else if (IsEqualIID(riid, &IID_IExtractIconA) && (cidl == 1))
1075 pidl = ILCombine(This->absPidl,apidl[0]);
1076 pObj = (LPUNKNOWN)IExtractIconA_Constructor( pidl );
1080 else if (IsEqualIID(riid, &IID_IDropTarget) && (cidl >= 1))
1082 hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, (LPVOID*)&pObj);
1094 TRACE("(%p)->hr=0x%08lx\n",This, hr);
1098 /**************************************************************************
1099 * IShellFolder_fnGetDisplayNameOf
1100 * Retrieves the display name for the specified file object or subfolder
1103 * LPCITEMIDLIST pidl, //[in ] complex pidl to item
1104 * DWORD dwFlags, //[in ] SHGNO formatting flags
1105 * LPSTRRET lpName) //[out] Returned display name
1108 * if the name is in the pidl the ret value should be a STRRET_OFFSET
1110 #define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
1111 #define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
1113 static HRESULT WINAPI IShellFolder_fnGetDisplayNameOf(
1114 IShellFolder2 * iface,
1119 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1121 CHAR szPath[MAX_PATH]= "";
1125 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1128 if(!pidl || !strRet) return E_INVALIDARG;
1130 bSimplePidl = _ILIsPidlSimple(pidl);
1132 /* take names of special folders only if its only this folder */
1133 if (_ILIsSpecialFolder(pidl))
1137 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1142 if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sMyPath)
1144 strcpy (szPath, This->sMyPath); /* get path to root*/
1145 PathAddBackslashA(szPath);
1146 len = strlen(szPath);
1148 _ILSimpleGetText(pidl, szPath + len, MAX_PATH - len); /* append my own path */
1150 /* MSDN also mentions SHGDN_FOREDITING, which isn't defined in wine */
1151 if(!_ILIsFolder(pidl) && !(dwFlags & SHGDN_FORPARSING) &&
1152 ((dwFlags & SHGDN_INFOLDER) || (dwFlags == SHGDN_NORMAL)))
1156 DWORD dwDataSize = sizeof(DWORD);
1157 BOOL doHide = 0; /* The default value is FALSE (win98 at least) */
1159 /* XXX should it do this only for known file types? -- that would make it even slower! */
1160 /* XXX That's what the prompt says!! */
1161 if(!RegCreateKeyExA(HKEY_CURRENT_USER,
1162 "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
1163 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0))
1165 if(!RegQueryValueExA(hKey, "HideFileExt", 0, 0, (LPBYTE)&dwData, &dwDataSize))
1169 if(doHide && szPath[0]!='.') PathRemoveExtensionA(szPath);
1173 if ( (dwFlags & SHGDN_FORPARSING) && !bSimplePidl) /* go deeper if needed */
1175 PathAddBackslashA(szPath);
1176 len = strlen(szPath);
1178 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath + len, MAX_PATH - len)))
1179 return E_OUTOFMEMORY;
1181 strRet->uType = STRRET_CSTRA;
1182 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1184 TRACE("-- (%p)->(%s)\n", This, szPath);
1188 /**************************************************************************
1189 * IShellFolder_fnSetNameOf
1190 * Changes the name of a file object or subfolder, possibly changing its item
1191 * identifier in the process.
1194 * HWND hwndOwner, //[in ] Owner window for output
1195 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
1196 * LPCOLESTR lpszName, //[in ] the items new display name
1197 * DWORD dwFlags, //[in ] SHGNO formatting flags
1198 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
1200 static HRESULT WINAPI IShellFolder_fnSetNameOf(
1201 IShellFolder2 * iface,
1203 LPCITEMIDLIST pidl, /*simple pidl*/
1206 LPITEMIDLIST *pPidlOut)
1208 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1209 char szSrc[MAX_PATH], szDest[MAX_PATH];
1211 BOOL bIsFolder = _ILIsFolder(ILFindLastID(pidl));
1213 TRACE("(%p)->(%u,pidl=%p,%s,%lu,%p)\n",
1214 This,hwndOwner,pidl,debugstr_w(lpName),dwFlags,pPidlOut);
1216 /* build source path */
1217 if (dwFlags & SHGDN_INFOLDER)
1219 strcpy(szSrc, This->sMyPath);
1220 PathAddBackslashA(szSrc);
1221 len = strlen (szSrc);
1222 _ILSimpleGetText(pidl, szSrc+len, MAX_PATH-len);
1226 SHGetPathFromIDListA(pidl, szSrc);
1229 /* build destination path */
1230 strcpy(szDest, This->sMyPath);
1231 PathAddBackslashA(szDest);
1232 len = strlen (szDest);
1233 WideCharToMultiByte( CP_ACP, 0, lpName, -1, szDest+len, MAX_PATH-len, NULL, NULL );
1234 szDest[MAX_PATH-1] = 0;
1235 TRACE("src=%s dest=%s\n", szSrc, szDest);
1236 if ( MoveFileA(szSrc, szDest) )
1238 if (pPidlOut) *pPidlOut = SHSimpleIDListFromPathA(szDest);
1239 SHChangeNotifyA( bIsFolder?SHCNE_RENAMEFOLDER:SHCNE_RENAMEITEM, SHCNF_PATHA, szSrc, szDest);
1245 static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID(
1246 IShellFolder2 * iface,
1249 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1250 FIXME("(%p)\n",This);
1253 static HRESULT WINAPI IShellFolder_fnEnumSearches(
1254 IShellFolder2 * iface,
1255 IEnumExtraSearch **ppenum)
1257 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1258 FIXME("(%p)\n",This);
1261 static HRESULT WINAPI IShellFolder_fnGetDefaultColumn(
1262 IShellFolder2 * iface,
1267 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1269 TRACE("(%p)\n",This);
1271 if (pSort) *pSort = 0;
1272 if (pDisplay) *pDisplay = 0;
1276 static HRESULT WINAPI IShellFolder_fnGetDefaultColumnState(
1277 IShellFolder2 * iface,
1281 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1283 TRACE("(%p)\n",This);
1285 if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1287 *pcsFlags = GenericSFHeader[iColumn].pcsFlags;
1291 static HRESULT WINAPI IShellFolder_fnGetDetailsEx(
1292 IShellFolder2 * iface,
1294 const SHCOLUMNID *pscid,
1297 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1298 FIXME("(%p)\n",This);
1302 static HRESULT WINAPI IShellFolder_fnGetDetailsOf(
1303 IShellFolder2 * iface,
1308 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1309 HRESULT hr = E_FAIL;
1311 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
1313 if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1317 /* the header titles */
1318 psd->fmt = GenericSFHeader[iColumn].fmt;
1319 psd->cxChar = GenericSFHeader[iColumn].cxChar;
1320 psd->str.uType = STRRET_CSTRA;
1321 LoadStringA(shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
1326 /* the data from the pidl */
1330 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
1333 _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
1336 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
1339 _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
1341 case 4: /* attributes */
1342 _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
1346 psd->str.uType = STRRET_CSTRA;
1351 static HRESULT WINAPI IShellFolder_fnMapNameToSCID(
1352 IShellFolder2 * iface,
1356 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1357 FIXME("(%p)\n",This);
1361 static ICOM_VTABLE(IShellFolder2) sfvt =
1363 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1364 IShellFolder_fnQueryInterface,
1365 IShellFolder_fnAddRef,
1366 IShellFolder_fnRelease,
1367 IShellFolder_fnParseDisplayName,
1368 IShellFolder_fnEnumObjects,
1369 IShellFolder_fnBindToObject,
1370 IShellFolder_fnBindToStorage,
1371 IShellFolder_fnCompareIDs,
1372 IShellFolder_fnCreateViewObject,
1373 IShellFolder_fnGetAttributesOf,
1374 IShellFolder_fnGetUIObjectOf,
1375 IShellFolder_fnGetDisplayNameOf,
1376 IShellFolder_fnSetNameOf,
1379 IShellFolder_fnGetDefaultSearchGUID,
1380 IShellFolder_fnEnumSearches,
1381 IShellFolder_fnGetDefaultColumn,
1382 IShellFolder_fnGetDefaultColumnState,
1383 IShellFolder_fnGetDetailsEx,
1384 IShellFolder_fnGetDetailsOf,
1385 IShellFolder_fnMapNameToSCID
1388 /****************************************************************************
1389 * ISFHelper for IShellFolder implementation
1392 static HRESULT WINAPI ISFHelper_fnQueryInterface(
1397 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1399 TRACE("(%p)\n", This);
1401 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
1404 static ULONG WINAPI ISFHelper_fnAddRef(
1407 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1409 TRACE("(%p)\n", This);
1411 return IUnknown_AddRef(This->pUnkOuter);
1414 static ULONG WINAPI ISFHelper_fnRelease(
1417 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1419 TRACE("(%p)\n", This);
1421 return IUnknown_Release(This->pUnkOuter);
1425 /****************************************************************************
1426 * ISFHelper_fnAddFolder
1428 * creates a unique folder name
1431 static HRESULT WINAPI ISFHelper_fnGetUniqueName(
1436 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1437 IEnumIDList * penum;
1439 char szText[MAX_PATH];
1440 char * szNewFolder = "New Folder";
1442 TRACE("(%p)(%s %u)\n", This, lpName, uLen);
1444 if (uLen < strlen(szNewFolder) + 4) return E_POINTER;
1446 strcpy(lpName, szNewFolder);
1448 hr = IShellFolder_fnEnumObjects(_IShellFolder2_(This), 0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
1455 next: IEnumIDList_Reset(penum);
1456 while(S_OK == IEnumIDList_Next(penum, 1, &pidl, &dwFetched) && dwFetched)
1458 _ILSimpleGetText(pidl, szText, MAX_PATH);
1459 if (0 == strcasecmp(szText, lpName))
1461 sprintf(lpName, "%s %d", szNewFolder, i++);
1471 IEnumIDList_Release(penum);
1476 /****************************************************************************
1477 * ISFHelper_fnAddFolder
1479 * adds a new folder.
1482 static HRESULT WINAPI ISFHelper_fnAddFolder(
1486 LPITEMIDLIST* ppidlOut)
1488 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1489 char lpstrNewDir[MAX_PATH];
1491 HRESULT hres = E_FAIL;
1493 TRACE("(%p)(%s %p)\n", This, lpName, ppidlOut);
1495 strcpy(lpstrNewDir, This->sMyPath);
1496 PathAddBackslashA(lpstrNewDir);
1497 strcat(lpstrNewDir, lpName);
1499 bRes = CreateDirectoryA(lpstrNewDir, NULL);
1503 LPITEMIDLIST pidl, pidlitem;
1505 pidlitem = SHSimpleIDListFromPathA(lpstrNewDir);
1507 pidl = ILCombine(This->absPidl, pidlitem);
1508 SHChangeNotifyA(SHCNE_MKDIR, SHCNF_IDLIST, pidl, NULL);
1511 if (ppidlOut) *ppidlOut = pidlitem;
1516 char lpstrText[128+MAX_PATH];
1517 char lpstrTempText[128];
1518 char lpstrCaption[256];
1520 /* Cannot Create folder because of permissions */
1521 LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, sizeof(lpstrTempText));
1522 LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, sizeof(lpstrCaption));
1523 sprintf(lpstrText,lpstrTempText, lpstrNewDir);
1524 MessageBoxA(hwnd,lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION);
1530 /****************************************************************************
1531 * ISFHelper_fnDeleteItems
1533 * deletes items in folder
1535 static HRESULT WINAPI ISFHelper_fnDeleteItems(
1538 LPCITEMIDLIST* apidl)
1540 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1542 char szPath[MAX_PATH];
1543 BOOL bConfirm = TRUE;
1545 TRACE("(%p)(%u %p)\n", This, cidl, apidl);
1547 /* deleting multiple items so give a slightly different warning */
1551 snprintf(tmp, sizeof(tmp), "%d", cidl);
1552 if(!SHELL_WarnItemDelete(ASK_DELETE_MULTIPLE_ITEM, tmp))
1557 for(i=0; i< cidl; i++)
1559 strcpy(szPath, This->sMyPath);
1560 PathAddBackslashA(szPath);
1561 _ILSimpleGetText(apidl[i], szPath+strlen(szPath), MAX_PATH);
1563 if (_ILIsFolder(apidl[i]))
1566 TRACE("delete %s\n", szPath);
1567 if (! SHELL_DeleteDirectoryA(szPath, bConfirm))
1569 TRACE("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
1572 pidl = ILCombine(This->absPidl, apidl[i]);
1573 SHChangeNotifyA(SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL);
1576 else if (_ILIsValue(apidl[i]))
1580 TRACE("delete %s\n", szPath);
1581 if (! SHELL_DeleteFileA(szPath, bConfirm))
1583 TRACE("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
1586 pidl = ILCombine(This->absPidl, apidl[i]);
1587 SHChangeNotifyA(SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL);
1595 /****************************************************************************
1596 * ISFHelper_fnCopyItems
1598 * copies items to this folder
1600 static HRESULT WINAPI ISFHelper_fnCopyItems(
1602 IShellFolder* pSFFrom,
1604 LPCITEMIDLIST *apidl)
1607 IPersistFolder2 * ppf2=NULL;
1608 char szSrcPath[MAX_PATH], szDstPath[MAX_PATH];
1609 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1611 TRACE("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl);
1613 IShellFolder_QueryInterface(pSFFrom, &IID_IPersistFolder2, (LPVOID*)&ppf2);
1617 if (SUCCEEDED(IPersistFolder2_GetCurFolder(ppf2, &pidl)))
1619 for (i=0; i<cidl; i++)
1621 SHGetPathFromIDListA(pidl, szSrcPath);
1622 PathAddBackslashA(szSrcPath);
1623 _ILSimpleGetText(apidl[i], szSrcPath+strlen(szSrcPath), MAX_PATH);
1625 strcpy(szDstPath, This->sMyPath);
1626 PathAddBackslashA(szDstPath);
1627 _ILSimpleGetText(apidl[i], szDstPath+strlen(szDstPath), MAX_PATH);
1628 MESSAGE("would copy %s to %s\n", szSrcPath, szDstPath);
1632 IPersistFolder2_Release(ppf2);
1637 static ICOM_VTABLE(ISFHelper) shvt =
1639 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1640 ISFHelper_fnQueryInterface,
1642 ISFHelper_fnRelease,
1643 ISFHelper_fnGetUniqueName,
1644 ISFHelper_fnAddFolder,
1645 ISFHelper_fnDeleteItems,
1646 ISFHelper_fnCopyItems,
1649 /***********************************************************************
1650 * [Desktopfolder] IShellFolder implementation
1652 static struct ICOM_VTABLE(IShellFolder2) sfdvt;
1654 static shvheader DesktopSFHeader [] =
1656 { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
1657 { IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1658 { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1659 { IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
1660 { IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
1662 #define DESKTOPSHELLVIEWCOLUMNS 5
1664 /**************************************************************************
1665 * ISF_Desktop_Constructor
1668 IShellFolder * ISF_Desktop_Constructor()
1670 IGenericSFImpl * sf;
1672 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
1674 ICOM_VTBL(sf)=&unkvt;
1675 sf->lpvtblShellFolder=&sfdvt;
1676 sf->absPidl=_ILCreateDesktop(); /* my qualified pidl */
1677 sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
1682 return _IShellFolder_(sf);
1685 /**************************************************************************
1686 * ISF_Desktop_fnQueryInterface
1688 * NOTES supports not IPersist/IPersistFolder
1690 static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
1691 IShellFolder2 * iface,
1695 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1697 TRACE("(%p)->(\n\tIID:\t%s,%p)\n",This,debugstr_guid(riid),ppvObj);
1701 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
1703 *ppvObj = _IUnknown_(This);
1705 else if(IsEqualIID(riid, &IID_IShellFolder)) /*IShellFolder*/
1707 *ppvObj = _IShellFolder_(This);
1709 else if(IsEqualIID(riid, &IID_IShellFolder2)) /*IShellFolder2*/
1711 *ppvObj = _IShellFolder_(This);
1716 IUnknown_AddRef((IUnknown*)(*ppvObj));
1717 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1720 TRACE("-- Interface: E_NOINTERFACE\n");
1721 return E_NOINTERFACE;
1724 /**************************************************************************
1725 * ISF_Desktop_fnParseDisplayName
1728 * "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
1731 static HRESULT WINAPI ISF_Desktop_fnParseDisplayName(
1732 IShellFolder2 * iface,
1735 LPOLESTR lpszDisplayName,
1737 LPITEMIDLIST *ppidl,
1738 DWORD *pdwAttributes)
1740 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1742 LPCWSTR szNext=NULL;
1743 LPITEMIDLIST pidlTemp=NULL;
1744 HRESULT hr=E_OUTOFMEMORY;
1746 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1747 This,hwndOwner,pbcReserved,lpszDisplayName,
1748 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1751 if (pchEaten) *pchEaten = 0; /* strange but like the original */
1753 /* FIXME no real parsing implemented */
1754 pidlTemp = _ILCreateMyComputer();
1755 szNext = lpszDisplayName;
1757 if (szNext && *szNext)
1759 hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1765 if (pdwAttributes && *pdwAttributes)
1767 SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
1773 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1778 /**************************************************************************
1779 * ISF_Desktop_fnEnumObjects
1781 static HRESULT WINAPI ISF_Desktop_fnEnumObjects(
1782 IShellFolder2 * iface,
1785 LPENUMIDLIST* ppEnumIDList)
1787 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1789 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1791 *ppEnumIDList = NULL;
1792 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_DESK);
1794 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1796 if(!*ppEnumIDList) return E_OUTOFMEMORY;
1801 /**************************************************************************
1802 * ISF_Desktop_fnBindToObject
1804 static HRESULT WINAPI ISF_Desktop_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
1805 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1807 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1809 IShellFolder *pShellFolder, *pSubFolder;
1812 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
1813 This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
1817 if ((clsid=_ILGetGUIDPointer(pidl)))
1819 if ( IsEqualIID(clsid, &CLSID_MyComputer))
1821 pShellFolder = ISF_MyComputer_Constructor();
1825 /* shell extension */
1826 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1828 return E_INVALIDARG;
1834 /* file system folder on the desktop */
1835 LPITEMIDLIST deskpidl, firstpidl, completepidl;
1836 IPersistFolder * ppf;
1839 SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, &deskpidl);
1840 firstpidl = ILCloneFirst(pidl);
1841 completepidl = ILCombine(deskpidl, firstpidl);
1843 pShellFolder = IShellFolder_Constructor(NULL, NULL);
1844 if (SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&ppf)))
1846 IPersistFolder_Initialize(ppf, completepidl);
1847 IPersistFolder_Release(ppf);
1849 ILFree(completepidl);
1854 if (_ILIsPidlSimple(pidl)) /* no sub folders */
1856 *ppvOut = pShellFolder;
1859 else /* go deeper */
1861 hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID)&pSubFolder);
1862 IShellFolder_Release(pShellFolder);
1863 *ppvOut = pSubFolder;
1866 TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
1871 /**************************************************************************
1872 * ISF_Desktop_fnCreateViewObject
1874 static HRESULT WINAPI ISF_Desktop_fnCreateViewObject( IShellFolder2 * iface,
1875 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
1877 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1879 LPSHELLVIEW pShellView;
1880 HRESULT hr = E_INVALIDARG;
1882 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
1888 if(IsEqualIID(riid, &IID_IDropTarget))
1890 WARN("IDropTarget not implemented\n");
1893 else if(IsEqualIID(riid, &IID_IContextMenu))
1895 WARN("IContextMenu not implemented\n");
1898 else if(IsEqualIID(riid, &IID_IShellView))
1900 pShellView = IShellView_Constructor((IShellFolder*)iface);
1903 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
1904 IShellView_Release(pShellView);
1908 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
1912 /**************************************************************************
1913 * ISF_Desktop_fnGetAttributesOf
1915 static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf(
1916 IShellFolder2 * iface,
1918 LPCITEMIDLIST *apidl,
1921 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1925 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl, *rgfInOut);
1927 if ( (!cidl) || (!apidl) || (!rgfInOut))
1928 return E_INVALIDARG;
1930 while (cidl > 0 && *apidl)
1933 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
1938 TRACE("-- result=0x%08lx\n",*rgfInOut);
1943 /**************************************************************************
1944 * ISF_Desktop_fnGetDisplayNameOf
1947 * special case: pidl = null gives desktop-name back
1949 static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf(
1950 IShellFolder2 * iface,
1955 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1957 CHAR szPath[MAX_PATH]= "";
1959 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1962 if(!strRet) return E_INVALIDARG;
1966 HCR_GetClassName(&CLSID_ShellDesktop, szPath, MAX_PATH);
1968 else if ( _ILIsPidlSimple(pidl) )
1970 _ILSimpleGetText(pidl, szPath, MAX_PATH);
1974 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath, MAX_PATH)))
1975 return E_OUTOFMEMORY;
1977 strRet->uType = STRRET_CSTRA;
1978 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1981 TRACE("-- (%p)->(%s)\n", This, szPath);
1985 static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID(
1986 IShellFolder2 * iface,
1989 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1990 FIXME("(%p)\n",This);
1993 static HRESULT WINAPI ISF_Desktop_fnEnumSearches(
1994 IShellFolder2 * iface,
1995 IEnumExtraSearch **ppenum)
1997 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1998 FIXME("(%p)\n",This);
2001 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn(
2002 IShellFolder2 * iface,
2007 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2009 TRACE("(%p)\n",This);
2011 if (pSort) *pSort = 0;
2012 if (pDisplay) *pDisplay = 0;
2016 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState(
2017 IShellFolder2 * iface,
2021 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2023 TRACE("(%p)\n",This);
2025 if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2027 *pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
2031 static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx(
2032 IShellFolder2 * iface,
2034 const SHCOLUMNID *pscid,
2037 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2038 FIXME("(%p)\n",This);
2042 static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf(
2043 IShellFolder2 * iface,
2048 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2049 HRESULT hr = E_FAIL;;
2051 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2053 if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2057 psd->fmt = DesktopSFHeader[iColumn].fmt;
2058 psd->cxChar = DesktopSFHeader[iColumn].cxChar;
2059 psd->str.uType = STRRET_CSTRA;
2060 LoadStringA(shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2065 /* the data from the pidl */
2069 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2072 _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
2075 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2078 _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
2080 case 4: /* attributes */
2081 _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
2085 psd->str.uType = STRRET_CSTRA;
2090 static HRESULT WINAPI ISF_Desktop_fnMapNameToSCID(
2091 IShellFolder2 * iface,
2095 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2096 FIXME("(%p)\n",This);
2100 static ICOM_VTABLE(IShellFolder2) sfdvt =
2102 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2103 ISF_Desktop_fnQueryInterface,
2104 IShellFolder_fnAddRef,
2105 IShellFolder_fnRelease,
2106 ISF_Desktop_fnParseDisplayName,
2107 ISF_Desktop_fnEnumObjects,
2108 ISF_Desktop_fnBindToObject,
2109 IShellFolder_fnBindToStorage,
2110 IShellFolder_fnCompareIDs,
2111 ISF_Desktop_fnCreateViewObject,
2112 ISF_Desktop_fnGetAttributesOf,
2113 IShellFolder_fnGetUIObjectOf,
2114 ISF_Desktop_fnGetDisplayNameOf,
2115 IShellFolder_fnSetNameOf,
2118 ISF_Desktop_fnGetDefaultSearchGUID,
2119 ISF_Desktop_fnEnumSearches,
2120 ISF_Desktop_fnGetDefaultColumn,
2121 ISF_Desktop_fnGetDefaultColumnState,
2122 ISF_Desktop_fnGetDetailsEx,
2123 ISF_Desktop_fnGetDetailsOf,
2124 ISF_Desktop_fnMapNameToSCID
2128 /***********************************************************************
2129 * IShellFolder [MyComputer] implementation
2132 static struct ICOM_VTABLE(IShellFolder2) sfmcvt;
2134 static shvheader MyComputerSFHeader [] =
2136 { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
2137 { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2138 { IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2139 { IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2141 #define MYCOMPUTERSHELLVIEWCOLUMNS 4
2143 /**************************************************************************
2144 * ISF_MyComputer_Constructor
2146 static IShellFolder * ISF_MyComputer_Constructor(void)
2148 IGenericSFImpl * sf;
2150 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
2153 ICOM_VTBL(sf)=&unkvt;
2154 sf->lpvtblShellFolder=&sfmcvt;
2155 sf->lpvtblPersistFolder2 = &psfvt;
2156 sf->pclsid = (CLSID*)&CLSID_SFMyComp;
2157 sf->absPidl=_ILCreateMyComputer(); /* my qualified pidl */
2158 sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
2163 return _IShellFolder_(sf);
2166 /**************************************************************************
2167 * ISF_MyComputer_fnParseDisplayName
2169 static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName(
2170 IShellFolder2 * iface,
2173 LPOLESTR lpszDisplayName,
2175 LPITEMIDLIST *ppidl,
2176 DWORD *pdwAttributes)
2178 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2180 HRESULT hr = E_OUTOFMEMORY;
2181 LPCWSTR szNext=NULL;
2182 WCHAR szElement[MAX_PATH];
2183 CHAR szTempA[MAX_PATH];
2184 LPITEMIDLIST pidlTemp;
2186 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
2187 This,hwndOwner,pbcReserved,lpszDisplayName,
2188 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
2191 if (pchEaten) *pchEaten = 0; /* strange but like the original */
2193 /* do we have an absolute path name ? */
2194 if (PathGetDriveNumberW(lpszDisplayName) >= 0 &&
2195 lpszDisplayName[2] == (WCHAR)'\\')
2197 szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
2198 WideCharToMultiByte( CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL );
2199 pidlTemp = _ILCreateDrive(szTempA);
2201 if (szNext && *szNext)
2203 hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
2207 if (pdwAttributes && *pdwAttributes)
2209 SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
2216 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
2221 /**************************************************************************
2222 * ISF_MyComputer_fnEnumObjects
2224 static HRESULT WINAPI ISF_MyComputer_fnEnumObjects(
2225 IShellFolder2 * iface,
2228 LPENUMIDLIST* ppEnumIDList)
2230 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2232 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
2234 *ppEnumIDList = NULL;
2235 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
2237 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
2239 if(!*ppEnumIDList) return E_OUTOFMEMORY;
2244 /**************************************************************************
2245 * ISF_MyComputer_fnBindToObject
2247 static HRESULT WINAPI ISF_MyComputer_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
2248 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
2250 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2252 IShellFolder *pShellFolder, *pSubFolder;
2253 LPITEMIDLIST pidltemp;
2256 TRACE("(%p)->(pidl=%p,%p,\n\tIID:\t%s,%p)\n",
2257 This,pidl,pbcReserved,debugstr_guid(riid),ppvOut);
2259 if(!pidl || !ppvOut) return E_INVALIDARG;
2263 if ((clsid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(clsid, &CLSID_MyComputer))
2265 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->absPidl, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
2272 if (!_ILIsDrive(pidl)) return E_INVALIDARG;
2274 pidltemp = ILCloneFirst(pidl);
2275 pShellFolder = IShellFolder_Constructor(iface, pidltemp);
2279 if (_ILIsPidlSimple(pidl)) /* no sub folders */
2281 *ppvOut = pShellFolder;
2284 else /* go deeper */
2286 hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL,
2287 riid, (LPVOID)&pSubFolder);
2288 IShellFolder_Release(pShellFolder);
2289 *ppvOut = pSubFolder;
2292 TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
2297 /**************************************************************************
2298 * ISF_MyComputer_fnCreateViewObject
2300 static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject( IShellFolder2 * iface,
2301 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
2303 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2305 LPSHELLVIEW pShellView;
2306 HRESULT hr = E_INVALIDARG;
2308 TRACE("(%p)->(hwnd=0x%x,\n\tIID:\t%s,%p)\n",This,hwndOwner,debugstr_guid(riid),ppvOut);
2314 if(IsEqualIID(riid, &IID_IDropTarget))
2316 WARN("IDropTarget not implemented\n");
2319 else if(IsEqualIID(riid, &IID_IContextMenu))
2321 WARN("IContextMenu not implemented\n");
2324 else if(IsEqualIID(riid, &IID_IShellView))
2326 pShellView = IShellView_Constructor((IShellFolder*)iface);
2329 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
2330 IShellView_Release(pShellView);
2334 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
2338 /**************************************************************************
2339 * ISF_MyComputer_fnGetAttributesOf
2341 static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf(
2342 IShellFolder2 * iface,
2344 LPCITEMIDLIST *apidl,
2347 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2351 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
2353 if ( (!cidl) || (!apidl) || (!rgfInOut))
2354 return E_INVALIDARG;
2356 while (cidl > 0 && *apidl)
2359 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
2364 TRACE("-- result=0x%08lx\n",*rgfInOut);
2368 /**************************************************************************
2369 * ISF_MyComputer_fnGetDisplayNameOf
2372 * The desktopfolder creates only complete paths (SHGDN_FORPARSING).
2373 * SHGDN_INFOLDER makes no sense.
2375 static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf(
2376 IShellFolder2 * iface,
2381 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2383 char szPath[MAX_PATH], szDrive[18];
2387 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
2390 if(!strRet) return E_INVALIDARG;
2392 szPath[0]=0x00; szDrive[0]=0x00;
2395 bSimplePidl = _ILIsPidlSimple(pidl);
2397 if (_ILIsSpecialFolder(pidl))
2399 /* take names of special folders only if its only this folder */
2402 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
2407 if (!_ILIsDrive(pidl))
2409 ERR("Wrong pidl type\n");
2410 return E_INVALIDARG;
2413 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
2415 /* long view "lw_name (C:)" */
2416 if ( bSimplePidl && !(dwFlags & SHGDN_FORPARSING))
2418 DWORD dwVolumeSerialNumber,dwMaximumComponetLength,dwFileSystemFlags;
2420 GetVolumeInformationA(szPath,szDrive,sizeof(szDrive)-6,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
2421 strcat (szDrive," (");
2422 strncat (szDrive, szPath, 2);
2423 strcat (szDrive,")");
2424 strcpy (szPath, szDrive);
2428 if (!bSimplePidl) /* go deeper if needed */
2430 PathAddBackslashA(szPath);
2431 len = strlen(szPath);
2433 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_FORPARSING, szPath + len, MAX_PATH - len)))
2434 return E_OUTOFMEMORY;
2436 strRet->uType = STRRET_CSTRA;
2437 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
2440 TRACE("-- (%p)->(%s)\n", This, szPath);
2444 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID(
2445 IShellFolder2 * iface,
2448 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2449 FIXME("(%p)\n",This);
2452 static HRESULT WINAPI ISF_MyComputer_fnEnumSearches(
2453 IShellFolder2 * iface,
2454 IEnumExtraSearch **ppenum)
2456 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2457 FIXME("(%p)\n",This);
2460 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn(
2461 IShellFolder2 * iface,
2466 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2468 TRACE("(%p)\n",This);
2470 if (pSort) *pSort = 0;
2471 if (pDisplay) *pDisplay = 0;
2475 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState(
2476 IShellFolder2 * iface,
2480 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2482 TRACE("(%p)\n",This);
2484 if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2486 *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
2490 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx(
2491 IShellFolder2 * iface,
2493 const SHCOLUMNID *pscid,
2496 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2497 FIXME("(%p)\n",This);
2502 /* FIXME: drive size >4GB is rolling over */
2503 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf(
2504 IShellFolder2 * iface,
2509 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2512 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2514 if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2518 psd->fmt = MyComputerSFHeader[iColumn].fmt;
2519 psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
2520 psd->str.uType = STRRET_CSTRA;
2521 LoadStringA(shell32_hInstance, MyComputerSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2526 char szPath[MAX_PATH];
2527 ULARGE_INTEGER ulBytes;
2529 psd->str.u.cStr[0] = 0x00;
2530 psd->str.uType = STRRET_CSTRA;
2534 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2537 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2539 case 2: /* total size */
2540 if (_ILIsDrive(pidl))
2542 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2543 GetDiskFreeSpaceExA(szPath, NULL, &ulBytes, NULL);
2544 StrFormatByteSizeA(ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
2547 case 3: /* free size */
2548 if (_ILIsDrive(pidl))
2550 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2551 GetDiskFreeSpaceExA(szPath, &ulBytes, NULL, NULL);
2552 StrFormatByteSizeA(ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
2561 static HRESULT WINAPI ISF_MyComputer_fnMapNameToSCID(
2562 IShellFolder2 * iface,
2566 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2567 FIXME("(%p)\n",This);
2571 static ICOM_VTABLE(IShellFolder2) sfmcvt =
2573 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2574 IShellFolder_fnQueryInterface,
2575 IShellFolder_fnAddRef,
2576 IShellFolder_fnRelease,
2577 ISF_MyComputer_fnParseDisplayName,
2578 ISF_MyComputer_fnEnumObjects,
2579 ISF_MyComputer_fnBindToObject,
2580 IShellFolder_fnBindToStorage,
2581 IShellFolder_fnCompareIDs,
2582 ISF_MyComputer_fnCreateViewObject,
2583 ISF_MyComputer_fnGetAttributesOf,
2584 IShellFolder_fnGetUIObjectOf,
2585 ISF_MyComputer_fnGetDisplayNameOf,
2586 IShellFolder_fnSetNameOf,
2589 ISF_MyComputer_fnGetDefaultSearchGUID,
2590 ISF_MyComputer_fnEnumSearches,
2591 ISF_MyComputer_fnGetDefaultColumn,
2592 ISF_MyComputer_fnGetDefaultColumnState,
2593 ISF_MyComputer_fnGetDetailsEx,
2594 ISF_MyComputer_fnGetDetailsOf,
2595 ISF_MyComputer_fnMapNameToSCID
2599 /************************************************************************
2600 * ISFPersistFolder_QueryInterface (IUnknown)
2603 static HRESULT WINAPI ISFPersistFolder2_QueryInterface(
2604 IPersistFolder2 * iface,
2608 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2610 TRACE("(%p)\n", This);
2612 return IUnknown_QueryInterface(This->pUnkOuter, iid, ppvObj);
2615 /************************************************************************
2616 * ISFPersistFolder_AddRef (IUnknown)
2619 static ULONG WINAPI ISFPersistFolder2_AddRef(
2620 IPersistFolder2 * iface)
2622 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2624 TRACE("(%p)\n", This);
2626 return IUnknown_AddRef(This->pUnkOuter);
2629 /************************************************************************
2630 * ISFPersistFolder_Release (IUnknown)
2633 static ULONG WINAPI ISFPersistFolder2_Release(
2634 IPersistFolder2 * iface)
2636 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2638 TRACE("(%p)\n", This);
2640 return IUnknown_Release(This->pUnkOuter);
2643 /************************************************************************
2644 * ISFPersistFolder_GetClassID (IPersist)
2646 static HRESULT WINAPI ISFPersistFolder2_GetClassID(
2647 IPersistFolder2 * iface,
2650 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2652 TRACE("(%p)\n", This);
2654 if (!lpClassId) return E_POINTER;
2655 *lpClassId = *This->pclsid;
2660 /************************************************************************
2661 * ISFPersistFolder_Initialize (IPersistFolder)
2664 * sMyPath is not set. Don't know how to handle in a non rooted environment.
2666 static HRESULT WINAPI ISFPersistFolder2_Initialize(
2667 IPersistFolder2 * iface,
2670 char sTemp[MAX_PATH];
2671 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2673 TRACE("(%p)->(%p)\n", This, pidl);
2675 /* free the old stuff */
2678 SHFree(This->absPidl);
2679 This->absPidl = NULL;
2683 SHFree(This->sMyPath);
2684 This->sMyPath = NULL;
2688 This->absPidl = ILClone(pidl);
2691 if (SHGetPathFromIDListA(pidl, sTemp))
2693 This->sMyPath = SHAlloc(strlen(sTemp)+1);
2694 strcpy(This->sMyPath, sTemp);
2697 TRACE("--(%p)->(%s)\n", This, This->sMyPath);
2702 /**************************************************************************
2703 * IPersistFolder2_fnGetCurFolder
2705 static HRESULT WINAPI ISFPersistFolder2_fnGetCurFolder(
2706 IPersistFolder2 * iface,
2707 LPITEMIDLIST * pidl)
2709 _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface);
2711 TRACE("(%p)->(%p)\n",This, pidl);
2713 if (!pidl) return E_POINTER;
2715 *pidl = ILClone(This->absPidl);
2720 static ICOM_VTABLE(IPersistFolder2) psfvt =
2722 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2723 ISFPersistFolder2_QueryInterface,
2724 ISFPersistFolder2_AddRef,
2725 ISFPersistFolder2_Release,
2726 ISFPersistFolder2_GetClassID,
2727 ISFPersistFolder2_Initialize,
2728 ISFPersistFolder2_fnGetCurFolder
2731 /****************************************************************************
2732 * ISFDropTarget implementation
2734 static BOOL ISFDropTarget_QueryDrop(
2739 DWORD dwEffect = *pdwEffect;
2741 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2743 *pdwEffect = DROPEFFECT_NONE;
2745 if (This->fAcceptFmt)
2746 { /* Does our interpretation of the keystate ... */
2747 *pdwEffect = KeyStateToDropEffect(dwKeyState);
2749 /* ... matches the desired effect ? */
2750 if (dwEffect & *pdwEffect)
2758 static HRESULT WINAPI ISFDropTarget_QueryInterface(
2763 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2765 TRACE("(%p)\n", This);
2767 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
2770 static ULONG WINAPI ISFDropTarget_AddRef( IDropTarget *iface)
2772 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2774 TRACE("(%p)\n", This);
2776 return IUnknown_AddRef(This->pUnkOuter);
2779 static ULONG WINAPI ISFDropTarget_Release( IDropTarget *iface)
2781 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2783 TRACE("(%p)\n", This);
2785 return IUnknown_Release(This->pUnkOuter);
2788 static HRESULT WINAPI ISFDropTarget_DragEnter(
2790 IDataObject *pDataObject,
2797 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2799 TRACE("(%p)->(DataObject=%p)\n",This,pDataObject);
2801 InitFormatEtc(fmt, This->cfShellIDList, TYMED_HGLOBAL);
2803 This->fAcceptFmt = (S_OK == IDataObject_QueryGetData(pDataObject, &fmt)) ? TRUE : FALSE;
2805 ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2810 static HRESULT WINAPI ISFDropTarget_DragOver(
2816 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2818 TRACE("(%p)\n",This);
2820 if(!pdwEffect) return E_INVALIDARG;
2822 ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2827 static HRESULT WINAPI ISFDropTarget_DragLeave(
2830 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2832 TRACE("(%p)\n",This);
2834 This->fAcceptFmt = FALSE;
2839 static HRESULT WINAPI ISFDropTarget_Drop(
2841 IDataObject* pDataObject,
2846 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2848 FIXME("(%p) object dropped\n",This);
2853 static struct ICOM_VTABLE(IDropTarget) dtvt =
2855 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2856 ISFDropTarget_QueryInterface,
2857 ISFDropTarget_AddRef,
2858 ISFDropTarget_Release,
2859 ISFDropTarget_DragEnter,
2860 ISFDropTarget_DragOver,
2861 ISFDropTarget_DragLeave,