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
25 #include "wine/port.h"
39 #include "wine/obj_base.h"
40 #include "wine/obj_dragdrop.h"
41 #include "wine/obj_shellfolder.h"
42 #include "undocshell.h"
43 #include "shell32_main.h"
46 #include "shellfolder.h"
47 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(shell);
53 /***************************************************************************
54 * debughelper: print out the return adress
55 * helps especially to track down unbalanced AddRef/Release
60 #define _CALL_TRACE TRACE("called from: 0x%08x\n", *( ((UINT*)&iface)-1 ));
74 /***************************************************************************
75 * GetNextElement (internal function)
77 * gets a part of a string till the first backslash
80 * pszNext [IN] string to get the element from
81 * pszOut [IN] pointer to buffer whitch receives string
82 * dwOut [IN] length of pszOut
85 * LPSTR pointer to first, not yet parsed char
88 static LPCWSTR GetNextElementW(LPCWSTR pszNext,LPWSTR pszOut,DWORD dwOut)
89 { LPCWSTR pszTail = pszNext;
91 TRACE("(%s %p 0x%08lx)\n",debugstr_w(pszNext),pszOut,dwOut);
95 if(!pszNext || !*pszNext)
98 while(*pszTail && (*pszTail != (WCHAR)'\\'))
101 dwCopy = (WCHAR*)pszTail - (WCHAR*)pszNext + 1;
102 lstrcpynW(pszOut, pszNext, (dwOut<dwCopy)? dwOut : dwCopy);
109 TRACE("--(%s %s 0x%08lx %p)\n",debugstr_w(pszNext),debugstr_w(pszOut),dwOut,pszTail);
113 static HRESULT SHELL32_ParseNextElement(
116 LPITEMIDLIST * pidlInOut,
119 DWORD *pdwAttributes)
121 HRESULT hr = E_OUTOFMEMORY;
122 LPITEMIDLIST pidlOut, pidlTemp = NULL;
123 IShellFolder *psfChild;
125 TRACE("(%p, %p, %s)\n",psf, pidlInOut ? *pidlInOut : NULL, debugstr_w(szNext));
128 /* get the shellfolder for the child pidl and let it analyse further */
129 hr = IShellFolder_BindToObject(psf, *pidlInOut, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
133 hr = IShellFolder_ParseDisplayName(psfChild, hwndOwner, NULL, szNext, pEaten, &pidlOut, pdwAttributes);
134 IShellFolder_Release(psfChild);
136 pidlTemp = ILCombine(*pidlInOut, pidlOut);
143 *pidlInOut = pidlTemp;
145 TRACE("-- pidl=%p ret=0x%08lx\n", pidlInOut? *pidlInOut: NULL, hr);
149 /***********************************************************************
150 * SHELL32_CoCreateInitSF
152 * creates a initialized shell folder
154 static HRESULT SHELL32_CoCreateInitSF (
155 LPITEMIDLIST pidlRoot,
156 LPITEMIDLIST pidlChild,
162 LPITEMIDLIST pidlAbsolute;
165 TRACE("%p %p\n", pidlRoot, pidlChild);
169 if (SUCCEEDED((hr = SHCoCreateInstance(NULL, clsid, NULL, &IID_IPersistFolder, (LPVOID*)&pPF)))) {
170 if(SUCCEEDED((hr = IPersistFolder_QueryInterface(pPF, iid, ppvOut)))) {
171 pidlAbsolute = ILCombine (pidlRoot, pidlChild);
172 hr = IPersistFolder_Initialize(pPF, pidlAbsolute);
173 IPersistFolder_Release(pPF);
174 SHFree(pidlAbsolute);
178 TRACE("-- ret=0x%08lx\n", hr);
182 static HRESULT SHELL32_GetDisplayNameOfChild(
189 LPITEMIDLIST pidlFirst, pidlNext;
190 IShellFolder2 * psfChild;
191 HRESULT hr = E_OUTOFMEMORY;
194 TRACE("(%p)->(pidl=%p 0x%08lx %p 0x%08lx)\n",psf,pidl,dwFlags,szOut, dwOutLen);
197 if ((pidlFirst = ILCloneFirst(pidl)))
199 hr = IShellFolder_BindToObject(psf, pidlFirst, NULL, &IID_IShellFolder, (LPVOID*)&psfChild);
202 pidlNext = ILGetNext(pidl);
204 hr = IShellFolder_GetDisplayNameOf(psfChild, pidlNext, dwFlags | SHGDN_INFOLDER, &strTemp);
207 hr = StrRetToStrNA(szOut, dwOutLen, &strTemp, pidlNext);
210 IShellFolder_Release(psfChild);
215 TRACE("-- ret=0x%08lx %s\n", hr, szOut);
220 /***********************************************************************
221 * SHELL32_GetItemAttributes
225 * folder: 0xE0000177 FILESYSTEM | HASSUBFOLDER | FOLDER
226 * file: 0x40000177 FILESYSTEM
227 * drive: 0xf0000144 FILESYSTEM | HASSUBFOLDER | FOLDER | FILESYSANCESTOR
228 * mycomputer: 0xb0000154 HASSUBFOLDER | FOLDER | FILESYSANCESTOR
229 * (seems to be default for shell extensions if no registry entry exists)
231 * This functions does not set flags!! It only resets flags when nessesary.
233 static HRESULT SHELL32_GetItemAttributes(
236 LPDWORD pdwAttributes)
241 TRACE("0x%08lx\n", *pdwAttributes);
243 if (*pdwAttributes & (0xcff3fe88))
244 WARN("attribute 0x%08lx not implemented\n", *pdwAttributes);
245 *pdwAttributes &= ~SFGAO_LINK; /* FIXME: for native filedialogs */
247 if (_ILIsDrive(pidl))
249 *pdwAttributes &= 0xf0000144;
251 else if ((clsid=_ILGetGUIDPointer(pidl)))
253 if (HCR_GetFolderAttributes(clsid, &dwAttributes))
255 *pdwAttributes &= dwAttributes;
259 *pdwAttributes &= 0xb0000154;
262 else if (_ILGetDataPointer(pidl))
264 dwAttributes = _ILGetFileAttributes(pidl, NULL, 0);
265 *pdwAttributes &= ~SFGAO_FILESYSANCESTOR;
267 if(( SFGAO_FOLDER & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_DIRECTORY))
268 *pdwAttributes &= ~(SFGAO_FOLDER|SFGAO_HASSUBFOLDER);
270 if(( SFGAO_HIDDEN & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_HIDDEN))
271 *pdwAttributes &= ~SFGAO_HIDDEN;
273 if(( SFGAO_READONLY & *pdwAttributes) && !(dwAttributes & FILE_ATTRIBUTE_READONLY))
274 *pdwAttributes &= ~SFGAO_READONLY;
278 *pdwAttributes &= 0xb0000154;
280 TRACE("-- 0x%08lx\n", *pdwAttributes);
284 /***********************************************************************
285 * IShellFolder implementation
290 ICOM_VFIELD(IUnknown);
292 ICOM_VTABLE(IShellFolder2)* lpvtblShellFolder;
293 ICOM_VTABLE(IPersistFolder3)* lpvtblPersistFolder3;
294 ICOM_VTABLE(IDropTarget)* lpvtblDropTarget;
295 ICOM_VTABLE(ISFHelper)* lpvtblSFHelper;
297 IUnknown *pUnkOuter; /* used for aggregation */
301 /* both paths are parsible from the desktop */
302 LPSTR sPathRoot; /* complete path used as return value */
303 LPSTR sPathTarget; /* complete path to target used for enumeration and ChangeNotify */
305 LPITEMIDLIST pidlRoot; /* absolute pidl */
306 LPITEMIDLIST pidlTarget; /* absolute pidl */
308 int dwAttributes; /* attributes returned by GetAttributesOf FIXME: use it */
310 UINT cfShellIDList; /* clipboardformat for IDropTarget */
311 BOOL fAcceptFmt; /* flag for pending Drop */
314 static struct ICOM_VTABLE(IUnknown) unkvt;
315 static struct ICOM_VTABLE(IShellFolder2) sfvt;
316 static struct ICOM_VTABLE(IPersistFolder3) psfvt;
317 static struct ICOM_VTABLE(IDropTarget) dtvt;
318 static struct ICOM_VTABLE(ISFHelper) shvt;
320 static IShellFolder * ISF_MyComputer_Constructor(void);
322 #define _IShellFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblShellFolder)))
323 #define _ICOM_THIS_From_IShellFolder2(class, name) class* This = (class*)(((char*)name)-_IShellFolder2_Offset);
325 #define _IPersistFolder_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder3)))
326 #define _ICOM_THIS_From_IPersistFolder3(class, name) class* This = (class*)(((char*)name)-_IPersistFolder_Offset);
328 #define _IDropTarget_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblDropTarget)))
329 #define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset);
331 #define _ISFHelper_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblSFHelper)))
332 #define _ICOM_THIS_From_ISFHelper(class, name) class* This = (class*)(((char*)name)-_ISFHelper_Offset);
334 converts This to a interface pointer
336 #define _IUnknown_(This) (IUnknown*)&(This->lpVtbl)
337 #define _IShellFolder_(This) (IShellFolder*)&(This->lpvtblShellFolder)
338 #define _IShellFolder2_(This) (IShellFolder2*)&(This->lpvtblShellFolder)
339 #define _IPersist_(This) (IPersist*)&(This->lpvtblPersistFolder3)
340 #define _IPersistFolder_(This) (IPersistFolder*)&(This->lpvtblPersistFolder3)
341 #define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpvtblPersistFolder3)
342 #define _IPersistFolder3_(This) (IPersistFolder3*)&(This->lpvtblPersistFolder3)
343 #define _IDropTarget_(This) (IDropTarget*)&(This->lpvtblDropTarget)
344 #define _ISFHelper_(This) (ISFHelper*)&(This->lpvtblSFHelper)
345 /**************************************************************************
346 * registers clipboardformat once
348 static void SF_RegisterClipFmt (IGenericSFImpl * This)
350 TRACE("(%p)\n", This);
352 if (!This->cfShellIDList)
354 This->cfShellIDList = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
358 /**************************************************************************
359 * we need a separate IUnknown to handle aggregation
362 static HRESULT WINAPI IUnknown_fnQueryInterface(
367 ICOM_THIS(IGenericSFImpl, iface);
370 TRACE("(%p)->(%s,%p)\n",This,shdebugstr_guid(riid),ppvObj);
374 if(IsEqualIID(riid, &IID_IUnknown)) *ppvObj = _IUnknown_(This);
375 else if(IsEqualIID(riid, &IID_IShellFolder)) *ppvObj = _IShellFolder_(This);
376 else if(IsEqualIID(riid, &IID_IShellFolder2)) *ppvObj = _IShellFolder_(This);
377 else if(IsEqualIID(riid, &IID_IPersist)) *ppvObj = _IPersist_(This);
378 else if(IsEqualIID(riid, &IID_IPersistFolder)) *ppvObj = _IPersistFolder_(This);
379 else if(IsEqualIID(riid, &IID_IPersistFolder2)) *ppvObj = _IPersistFolder2_(This);
380 else if(IsEqualIID(riid, &IID_IPersistFolder3)) *ppvObj = _IPersistFolder3_(This);
381 else if(IsEqualIID(riid, &IID_ISFHelper)) *ppvObj = _ISFHelper_(This);
382 else if(IsEqualIID(riid, &IID_IDropTarget))
384 *ppvObj = _IDropTarget_(This);
385 SF_RegisterClipFmt(This);
390 IUnknown_AddRef((IUnknown*)(*ppvObj));
391 TRACE("-- Interface = %p\n", *ppvObj);
394 TRACE("-- Interface: E_NOINTERFACE\n");
395 return E_NOINTERFACE;
398 static ULONG WINAPI IUnknown_fnAddRef(IUnknown * iface)
400 ICOM_THIS(IGenericSFImpl, iface);
403 TRACE("(%p)->(count=%lu)\n",This,This->ref);
406 return ++(This->ref);
409 static ULONG WINAPI IUnknown_fnRelease(IUnknown * iface)
411 ICOM_THIS(IGenericSFImpl, iface);
414 TRACE("(%p)->(count=%lu)\n",This,This->ref);
419 TRACE("-- destroying IShellFolder(%p)\n",This);
421 if(This->pidlRoot) SHFree(This->pidlRoot);
422 if(This->sPathRoot) SHFree(This->sPathRoot);
423 LocalFree((HLOCAL)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 * IFSFolder_Constructor
451 * creating undocumented ShellFS_Folder as part of an aggregation
452 * {F3364BA0-65B9-11CE-A9BA-00AA004AE837}
455 HRESULT WINAPI IFSFolder_Constructor(
456 IUnknown * pUnkOuter,
462 TRACE("unkOut=%p %s\n",pUnkOuter, shdebugstr_guid(riid));
464 if(pUnkOuter && ! IsEqualIID(riid, &IID_IUnknown)) return CLASS_E_NOAGGREGATION;
465 sf=(IGenericSFImpl*) LocalAlloc(GMEM_ZEROINIT,sizeof(IGenericSFImpl));
466 if (!sf) return E_OUTOFMEMORY;
469 ICOM_VTBL(sf)=&unkvt;
470 sf->lpvtblShellFolder=&sfvt;
471 sf->lpvtblPersistFolder3=&psfvt;
472 sf->lpvtblDropTarget=&dtvt;
473 sf->lpvtblSFHelper=&shvt;
474 sf->pclsid = (CLSID*)&CLSID_ShellFSFolder;
475 sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_(sf);
477 /* we have to return the inner IUnknown */
478 *ppv = _IUnknown_(sf);
481 TRACE("--%p\n", *ppv);
485 /**************************************************************************
486 * InitializeGenericSF
488 static HRESULT InitializeGenericSF(IGenericSFImpl * sf, LPITEMIDLIST pidlRoot, LPITEMIDLIST pidlFolder, LPCSTR sPathRoot)
490 TRACE("(%p)->(pidl=%p, path=%s)\n",sf,pidlRoot, sPathRoot);
494 sf->pidlRoot = ILCombine(pidlRoot, pidlFolder);
495 if (!_ILIsSpecialFolder(pidlFolder)) { /* only file system paths */
496 char sNewPath[MAX_PATH];
500 strcpy(sNewPath, sPathRoot);
501 if (!((sPos = PathAddBackslashA (sNewPath)))) return E_UNEXPECTED;
505 _ILSimpleGetText(pidlFolder, sPos, MAX_PATH - (sPos - sNewPath));
506 if(!((sf->sPathRoot = SHAlloc(strlen(sNewPath+1))))) return E_OUTOFMEMORY;
507 strcpy(sf->sPathRoot, sNewPath);
508 TRACE("-- %s\n", sNewPath);
513 /**************************************************************************
514 * IShellFolder_Constructor
516 IGenericSFImpl * IShellFolder_Constructor()
518 IGenericSFImpl * sf=(IGenericSFImpl*) LocalAlloc(GMEM_ZEROINIT,sizeof(IGenericSFImpl));
521 ICOM_VTBL(sf)=&unkvt;
522 sf->lpvtblShellFolder=&sfvt;
523 sf->lpvtblPersistFolder3=&psfvt;
524 sf->lpvtblDropTarget=&dtvt;
525 sf->lpvtblSFHelper=&shvt;
527 sf->pclsid = (CLSID*)&CLSID_ShellFSFolder;
528 sf->pUnkOuter = _IUnknown_(sf);
530 TRACE("(%p)->()\n",sf);
536 /**************************************************************************
537 * IShellFolder_fnQueryInterface
540 * REFIID riid [in ] Requested InterfaceID
541 * LPVOID* ppvObject [out] Interface* to hold the result
543 static HRESULT WINAPI IShellFolder_fnQueryInterface(
544 IShellFolder2 * iface,
548 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
551 TRACE("(%p)->(%s,%p)\n",This,shdebugstr_guid(riid),ppvObj);
553 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
556 /**************************************************************************
557 * IShellFolder_AddRef
560 static ULONG WINAPI IShellFolder_fnAddRef(IShellFolder2 * iface)
562 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
565 TRACE("(%p)->(count=%lu)\n",This,This->ref);
567 return IUnknown_AddRef(This->pUnkOuter);
570 /**************************************************************************
571 * IShellFolder_fnRelease
573 static ULONG WINAPI IShellFolder_fnRelease(IShellFolder2 * iface)
575 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
578 TRACE("(%p)->(count=%lu)\n",This,This->ref);
580 return IUnknown_Release(This->pUnkOuter);
583 /**************************************************************************
584 * IShellFolder_fnParseDisplayName
586 * HWND hwndOwner, //[in ] Parent window for any message's
587 * LPBC pbc, //[in ] reserved
588 * LPOLESTR lpszDisplayName,//[in ] "Unicode" displayname.
589 * ULONG* pchEaten, //[out] (unicode) characters processed
590 * LPITEMIDLIST* ppidl, //[out] complex pidl to item
591 * ULONG* pdwAttributes //[out] items attributes
594 * every folder tries to parse only its own (the leftmost) pidl and creates a
595 * subfolder to evaluate the remaining parts
596 * now we can parse into namespaces implemented by shell extensions
598 * behaviour on win98: lpszDisplayName=NULL -> chrash
599 * lpszDisplayName="" -> returns mycoputer-pidl
602 * pdwAttributes: not set
603 * pchEaten: not set like in windows
605 static HRESULT WINAPI IShellFolder_fnParseDisplayName(
606 IShellFolder2 * iface,
609 LPOLESTR lpszDisplayName,
612 DWORD *pdwAttributes)
614 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
616 HRESULT hr = E_OUTOFMEMORY;
618 WCHAR szElement[MAX_PATH];
619 CHAR szTempA[MAX_PATH], szPath[MAX_PATH];
620 LPITEMIDLIST pidlTemp=NULL;
622 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
623 This,hwndOwner,pbcReserved,lpszDisplayName,
624 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
626 if (!lpszDisplayName || !ppidl) return E_INVALIDARG;
628 if (pchEaten) *pchEaten = 0; /* strange but like the original */
630 if (*lpszDisplayName)
632 /* get the next element */
633 szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
635 /* build the full pathname to the element */
636 WideCharToMultiByte( CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL );
637 strcpy(szPath, This->sPathRoot);
638 PathAddBackslashA(szPath);
639 strcat(szPath, szTempA);
642 pidlTemp = SHSimpleIDListFromPathA(szPath);
646 /* try to analyse the next element */
647 if (szNext && *szNext)
649 hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
653 if (pdwAttributes && *pdwAttributes)
655 SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
656 /* WIN32_FIND_DATAA fd;
657 SHGetDataFromIDListA(_IShellFolder_(This), pidlTemp, SHGDFIL_FINDDATA, &fd, sizeof(fd));
658 if (!(FILE_ATTRIBUTE_DIRECTORY & fd.dwFileAttributes))
659 *pdwAttributes &= ~SFGAO_FOLDER;
660 if (FILE_ATTRIBUTE_READONLY & fd.dwFileAttributes)
661 *pdwAttributes &= ~(SFGAO_CANDELETE|SFGAO_CANMOVE|SFGAO_CANRENAME );
674 TRACE("(%p)->(-- pidl=%p ret=0x%08lx)\n", This, ppidl? *ppidl:0, hr);
679 /**************************************************************************
680 * IShellFolder_fnEnumObjects
682 * HWND hwndOwner, //[in ] Parent Window
683 * DWORD grfFlags, //[in ] SHCONTF enumeration mask
684 * LPENUMIDLIST* ppenumIDList //[out] IEnumIDList interface
686 static HRESULT WINAPI IShellFolder_fnEnumObjects(
687 IShellFolder2 * iface,
690 LPENUMIDLIST* ppEnumIDList)
692 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
694 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
696 *ppEnumIDList = NULL;
697 *ppEnumIDList = IEnumIDList_Constructor (This->sPathRoot, dwFlags, EIDL_FILE);
699 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
701 if(!*ppEnumIDList) return E_OUTOFMEMORY;
706 /**************************************************************************
707 * IShellFolder_fnBindToObject
709 * LPCITEMIDLIST pidl, //[in ] relative pidl to open
710 * LPBC pbc, //[in ] reserved
711 * REFIID riid, //[in ] Initial Interface
712 * LPVOID* ppvObject //[out] Interface*
714 static HRESULT WINAPI IShellFolder_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
715 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
717 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
719 IShellFolder *pShellFolder, *pSubFolder;
720 IGenericSFImpl *pSFImpl;
721 IPersistFolder *pPersistFolder;
722 LPITEMIDLIST pidlRoot;
725 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n",This,pidl,pbcReserved,shdebugstr_guid(riid),ppvOut);
727 if(!pidl || !ppvOut) return E_INVALIDARG;
731 if ((iid=_ILGetGUIDPointer(pidl)))
733 /* we have to create a alien folder */
734 if ( SUCCEEDED(SHCoCreateInstance(NULL, iid, NULL, riid, (LPVOID*)&pShellFolder))
735 && SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&pPersistFolder)))
737 pidlRoot = ILCombine (This->pidlRoot, pidl);
738 IPersistFolder_Initialize(pPersistFolder, pidlRoot);
739 IPersistFolder_Release(pPersistFolder);
749 if ((pSFImpl = IShellFolder_Constructor())) {
750 LPITEMIDLIST pidltemp = ILCloneFirst(pidl);
751 hr = InitializeGenericSF(pSFImpl, This->pidlRoot, pidltemp, This->sPathRoot);
753 pShellFolder = _IShellFolder_(pSFImpl);
757 if (_ILIsPidlSimple(pidl))
759 if(IsEqualIID(riid, &IID_IShellFolder))
761 *ppvOut = pShellFolder;
766 hr = IShellFolder_QueryInterface(pShellFolder, riid, ppvOut);
767 IShellFolder_Release(pShellFolder);
772 hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID)&pSubFolder);
773 IShellFolder_Release(pShellFolder);
774 *ppvOut = pSubFolder;
777 TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
782 /**************************************************************************
783 * IShellFolder_fnBindToStorage
785 * LPCITEMIDLIST pidl, //[in ] complex pidl to store
786 * LPBC pbc, //[in ] reserved
787 * REFIID riid, //[in ] Initial storage interface
788 * LPVOID* ppvObject //[out] Interface* returned
790 static HRESULT WINAPI IShellFolder_fnBindToStorage(
791 IShellFolder2 * iface,
797 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
799 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n",
800 This,pidl,pbcReserved,shdebugstr_guid(riid),ppvOut);
806 /**************************************************************************
807 * IShellFolder_fnCompareIDs
810 * LPARAM lParam, //[in ] Column?
811 * LPCITEMIDLIST pidl1, //[in ] simple pidl
812 * LPCITEMIDLIST pidl2) //[in ] simple pidl
815 * Special case - If one of the items is a Path and the other is a File,
816 * always make the Path come before the File.
819 * use SCODE_CODE() on the return value to get the result
822 static HRESULT WINAPI IShellFolder_fnCompareIDs(
823 IShellFolder2 * iface,
828 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
830 CHAR szTemp1[MAX_PATH];
831 CHAR szTemp2[MAX_PATH];
834 HRESULT hr = E_OUTOFMEMORY;
835 LPCITEMIDLIST pidlTemp;
838 if (TRACE_ON(shell)) {
839 TRACE("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n",This,lParam,pidl1,pidl2);
844 if (!pidl1 && !pidl2)
846 hr = ResultFromShort(0);
850 hr = ResultFromShort(-1);
854 hr = ResultFromShort(1);
859 pd1 = _ILGetDataPointer(pidl1);
860 pd2 = _ILGetDataPointer(pidl2);
862 /* compate the types. sort order is the PT_* constant */
863 pt1 = ( pd1 ? pd1->type: PT_DESKTOP);
864 pt2 = ( pd2 ? pd2->type: PT_DESKTOP);
868 hr = ResultFromShort(pt1-pt2);
870 else /* same type of pidl */
872 _ILSimpleGetText(pidl1, szTemp1, MAX_PATH);
873 _ILSimpleGetText(pidl2, szTemp2, MAX_PATH);
874 nReturn = strcasecmp(szTemp1, szTemp2);
876 if (nReturn == 0) /* first pidl different ? */
878 pidl1 = ILGetNext(pidl1);
880 if (pidl1 && pidl1->mkid.cb) /* go deeper? */
882 pidlTemp = ILCloneFirst(pidl1);
883 pidl2 = ILGetNext(pidl2);
885 hr = IShellFolder_BindToObject(iface, pidlTemp, NULL, &IID_IShellFolder, (LPVOID*)&psf);
888 nReturn = IShellFolder_CompareIDs(psf, 0, pidl1, pidl2);
889 IShellFolder_Release(psf);
890 hr = ResultFromShort(nReturn);
894 else /* no deeper on #1 */
896 pidl2 = ILGetNext(pidl2);
897 if (pidl2 && pidl2->mkid.cb) /* go deeper on #2 ? */
898 hr = ResultFromShort(-1); /* two different */
900 hr = ResultFromShort(nReturn); /* two equal simple pidls */
905 hr = ResultFromShort(nReturn); /* two different simple pidls */
910 TRACE("-- res=0x%08lx\n", hr);
914 /**************************************************************************
915 * IShellFolder_fnCreateViewObject
917 static HRESULT WINAPI IShellFolder_fnCreateViewObject(
918 IShellFolder2 * iface,
923 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
925 LPSHELLVIEW pShellView;
926 HRESULT hr = E_INVALIDARG;
928 TRACE("(%p)->(hwnd=0x%x,%s,%p)\n",This,hwndOwner,shdebugstr_guid(riid),ppvOut);
934 if(IsEqualIID(riid, &IID_IDropTarget))
936 hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, ppvOut);
938 else if(IsEqualIID(riid, &IID_IContextMenu))
940 FIXME("IContextMenu not implemented\n");
943 else if(IsEqualIID(riid, &IID_IShellView))
945 pShellView = IShellView_Constructor((IShellFolder*)iface);
948 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
949 IShellView_Release(pShellView);
953 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
957 /**************************************************************************
958 * IShellFolder_fnGetAttributesOf
961 * UINT cidl, //[in ] num elements in pidl array
962 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
963 * ULONG* rgfInOut) //[out] result array
966 static HRESULT WINAPI IShellFolder_fnGetAttributesOf(
967 IShellFolder2 * iface,
969 LPCITEMIDLIST *apidl,
972 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
976 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
978 if ( (!cidl) || (!apidl) || (!rgfInOut))
981 while (cidl > 0 && *apidl)
984 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
989 TRACE("-- result=0x%08lx\n",*rgfInOut);
993 /**************************************************************************
994 * IShellFolder_fnGetUIObjectOf
997 * HWND hwndOwner, //[in ] Parent window for any output
998 * UINT cidl, //[in ] array size
999 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
1000 * REFIID riid, //[in ] Requested Interface
1001 * UINT* prgfInOut, //[ ] reserved
1002 * LPVOID* ppvObject) //[out] Resulting Interface
1005 * This function gets asked to return "view objects" for one or more (multiple select)
1007 * The viewobject typically is an COM object with one of the following interfaces:
1008 * IExtractIcon,IDataObject,IContextMenu
1009 * In order to support icon positions in the default Listview your DataObject
1010 * must implement the SetData method (in addition to GetData :) - the shell passes
1011 * a barely documented "Icon positions" structure to SetData when the drag starts,
1012 * and GetData's it if the drop is in another explorer window that needs the positions.
1014 static HRESULT WINAPI IShellFolder_fnGetUIObjectOf(
1015 IShellFolder2 * iface,
1018 LPCITEMIDLIST * apidl,
1023 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1026 IUnknown* pObj = NULL;
1027 HRESULT hr = E_INVALIDARG;
1029 TRACE("(%p)->(0x%04x,%u,apidl=%p,%s,%p,%p)\n",
1030 This,hwndOwner,cidl,apidl,shdebugstr_guid(riid),prgfInOut,ppvOut);
1036 if(IsEqualIID(riid, &IID_IContextMenu) && (cidl >= 1))
1038 pObj = (LPUNKNOWN)ISvItemCm_Constructor((IShellFolder*)iface, This->pidlRoot, apidl, cidl);
1041 else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1))
1043 pObj = (LPUNKNOWN)IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl);
1046 else if (IsEqualIID(riid, &IID_IExtractIconA) && (cidl == 1))
1048 pidl = ILCombine(This->pidlRoot,apidl[0]);
1049 pObj = (LPUNKNOWN)IExtractIconA_Constructor( pidl );
1053 else if (IsEqualIID(riid, &IID_IDropTarget) && (cidl >= 1))
1055 hr = IShellFolder_QueryInterface(iface, &IID_IDropTarget, (LPVOID*)&pObj);
1067 TRACE("(%p)->hr=0x%08lx\n",This, hr);
1071 /**************************************************************************
1072 * IShellFolder_fnGetDisplayNameOf
1073 * Retrieves the display name for the specified file object or subfolder
1076 * LPCITEMIDLIST pidl, //[in ] complex pidl to item
1077 * DWORD dwFlags, //[in ] SHGNO formatting flags
1078 * LPSTRRET lpName) //[out] Returned display name
1081 * if the name is in the pidl the ret value should be a STRRET_OFFSET
1083 #define GET_SHGDN_FOR(dwFlags) ((DWORD)dwFlags & (DWORD)0x0000FF00)
1084 #define GET_SHGDN_RELATION(dwFlags) ((DWORD)dwFlags & (DWORD)0x000000FF)
1086 static HRESULT WINAPI IShellFolder_fnGetDisplayNameOf(
1087 IShellFolder2 * iface,
1092 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1094 CHAR szPath[MAX_PATH]= "";
1098 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1101 if(!pidl || !strRet) return E_INVALIDARG;
1103 bSimplePidl = _ILIsPidlSimple(pidl);
1105 /* take names of special folders only if its only this folder */
1106 if (_ILIsSpecialFolder(pidl))
1110 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
1115 if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sPathRoot)
1117 strcpy (szPath, This->sPathRoot); /* get path to root*/
1118 PathAddBackslashA(szPath);
1119 len = strlen(szPath);
1121 _ILSimpleGetText(pidl, szPath + len, MAX_PATH - len); /* append my own path */
1123 /* MSDN also mentions SHGDN_FOREDITING, which isn't defined in wine */
1124 if(!_ILIsFolder(pidl) && !(dwFlags & SHGDN_FORPARSING) &&
1125 ((dwFlags & SHGDN_INFOLDER) || (dwFlags == SHGDN_NORMAL)))
1129 DWORD dwDataSize = sizeof(DWORD);
1130 BOOL doHide = 0; /* The default value is FALSE (win98 at least) */
1132 /* XXX should it do this only for known file types? -- that would make it even slower! */
1133 /* XXX That's what the prompt says!! */
1134 if(!RegCreateKeyExA(HKEY_CURRENT_USER,
1135 "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
1136 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0))
1138 if(!RegQueryValueExA(hKey, "HideFileExt", 0, 0, (LPBYTE)&dwData, &dwDataSize))
1142 if(doHide && szPath[0]!='.') PathRemoveExtensionA(szPath);
1146 if ( (dwFlags & SHGDN_FORPARSING) && !bSimplePidl) /* go deeper if needed */
1148 PathAddBackslashA(szPath);
1149 len = strlen(szPath);
1151 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath + len, MAX_PATH - len)))
1152 return E_OUTOFMEMORY;
1154 strRet->uType = STRRET_CSTR;
1155 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1157 TRACE("-- (%p)->(%s)\n", This, szPath);
1161 /**************************************************************************
1162 * IShellFolder_fnSetNameOf
1163 * Changes the name of a file object or subfolder, possibly changing its item
1164 * identifier in the process.
1167 * HWND hwndOwner, //[in ] Owner window for output
1168 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
1169 * LPCOLESTR lpszName, //[in ] the items new display name
1170 * DWORD dwFlags, //[in ] SHGNO formatting flags
1171 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
1173 static HRESULT WINAPI IShellFolder_fnSetNameOf(
1174 IShellFolder2 * iface,
1176 LPCITEMIDLIST pidl, /*simple pidl*/
1179 LPITEMIDLIST *pPidlOut)
1181 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1182 char szSrc[MAX_PATH], szDest[MAX_PATH];
1184 BOOL bIsFolder = _ILIsFolder(ILFindLastID(pidl));
1186 TRACE("(%p)->(%u,pidl=%p,%s,%lu,%p)\n",
1187 This,hwndOwner,pidl,debugstr_w(lpName),dwFlags,pPidlOut);
1189 /* build source path */
1190 if (dwFlags & SHGDN_INFOLDER)
1192 strcpy(szSrc, This->sPathRoot);
1193 PathAddBackslashA(szSrc);
1194 len = strlen (szSrc);
1195 _ILSimpleGetText(pidl, szSrc+len, MAX_PATH-len);
1199 SHGetPathFromIDListA(pidl, szSrc);
1202 /* build destination path */
1203 strcpy(szDest, This->sPathRoot);
1204 PathAddBackslashA(szDest);
1205 len = strlen (szDest);
1206 WideCharToMultiByte( CP_ACP, 0, lpName, -1, szDest+len, MAX_PATH-len, NULL, NULL );
1207 szDest[MAX_PATH-1] = 0;
1208 TRACE("src=%s dest=%s\n", szSrc, szDest);
1209 if ( MoveFileA(szSrc, szDest) )
1211 if (pPidlOut) *pPidlOut = SHSimpleIDListFromPathA(szDest);
1212 SHChangeNotifyA( bIsFolder?SHCNE_RENAMEFOLDER:SHCNE_RENAMEITEM, SHCNF_PATHA, szSrc, szDest);
1218 static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID(
1219 IShellFolder2 * iface,
1222 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1223 FIXME("(%p)\n",This);
1226 static HRESULT WINAPI IShellFolder_fnEnumSearches(
1227 IShellFolder2 * iface,
1228 IEnumExtraSearch **ppenum)
1230 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1231 FIXME("(%p)\n",This);
1234 static HRESULT WINAPI IShellFolder_fnGetDefaultColumn(
1235 IShellFolder2 * iface,
1240 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1242 TRACE("(%p)\n",This);
1244 if (pSort) *pSort = 0;
1245 if (pDisplay) *pDisplay = 0;
1249 static HRESULT WINAPI IShellFolder_fnGetDefaultColumnState(
1250 IShellFolder2 * iface,
1254 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1256 TRACE("(%p)\n",This);
1258 if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1260 *pcsFlags = GenericSFHeader[iColumn].pcsFlags;
1264 static HRESULT WINAPI IShellFolder_fnGetDetailsEx(
1265 IShellFolder2 * iface,
1267 const SHCOLUMNID *pscid,
1270 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1271 FIXME("(%p)\n",This);
1275 static HRESULT WINAPI IShellFolder_fnGetDetailsOf(
1276 IShellFolder2 * iface,
1281 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1282 HRESULT hr = E_FAIL;
1284 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
1286 if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS ) return E_INVALIDARG;
1290 /* the header titles */
1291 psd->fmt = GenericSFHeader[iColumn].fmt;
1292 psd->cxChar = GenericSFHeader[iColumn].cxChar;
1293 psd->str.uType = STRRET_CSTR;
1294 LoadStringA(shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
1299 /* the data from the pidl */
1303 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
1306 _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
1309 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
1312 _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
1314 case 4: /* attributes */
1315 _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
1319 psd->str.uType = STRRET_CSTR;
1324 static HRESULT WINAPI IShellFolder_fnMapNameToSCID(
1325 IShellFolder2 * iface,
1329 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1330 FIXME("(%p)\n",This);
1334 static ICOM_VTABLE(IShellFolder2) sfvt =
1336 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1337 IShellFolder_fnQueryInterface,
1338 IShellFolder_fnAddRef,
1339 IShellFolder_fnRelease,
1340 IShellFolder_fnParseDisplayName,
1341 IShellFolder_fnEnumObjects,
1342 IShellFolder_fnBindToObject,
1343 IShellFolder_fnBindToStorage,
1344 IShellFolder_fnCompareIDs,
1345 IShellFolder_fnCreateViewObject,
1346 IShellFolder_fnGetAttributesOf,
1347 IShellFolder_fnGetUIObjectOf,
1348 IShellFolder_fnGetDisplayNameOf,
1349 IShellFolder_fnSetNameOf,
1352 IShellFolder_fnGetDefaultSearchGUID,
1353 IShellFolder_fnEnumSearches,
1354 IShellFolder_fnGetDefaultColumn,
1355 IShellFolder_fnGetDefaultColumnState,
1356 IShellFolder_fnGetDetailsEx,
1357 IShellFolder_fnGetDetailsOf,
1358 IShellFolder_fnMapNameToSCID
1361 /****************************************************************************
1362 * ISFHelper for IShellFolder implementation
1365 static HRESULT WINAPI ISFHelper_fnQueryInterface(
1370 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1372 TRACE("(%p)->(count=%lu)\n",This,This->ref);
1374 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
1377 static ULONG WINAPI ISFHelper_fnAddRef(
1380 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1382 TRACE("(%p)->(count=%lu)\n",This,This->ref);
1384 return IUnknown_AddRef(This->pUnkOuter);
1387 static ULONG WINAPI ISFHelper_fnRelease(
1390 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1392 TRACE("(%p)\n", This);
1394 return IUnknown_Release(This->pUnkOuter);
1398 /****************************************************************************
1399 * ISFHelper_fnAddFolder
1401 * creates a unique folder name
1404 static HRESULT WINAPI ISFHelper_fnGetUniqueName(
1409 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1410 IEnumIDList * penum;
1412 char szText[MAX_PATH];
1413 char * szNewFolder = "New Folder";
1415 TRACE("(%p)(%s %u)\n", This, lpName, uLen);
1417 if (uLen < strlen(szNewFolder) + 4) return E_POINTER;
1419 strcpy(lpName, szNewFolder);
1421 hr = IShellFolder_fnEnumObjects(_IShellFolder2_(This), 0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
1428 next: IEnumIDList_Reset(penum);
1429 while(S_OK == IEnumIDList_Next(penum, 1, &pidl, &dwFetched) && dwFetched)
1431 _ILSimpleGetText(pidl, szText, MAX_PATH);
1432 if (0 == strcasecmp(szText, lpName))
1434 sprintf(lpName, "%s %d", szNewFolder, i++);
1444 IEnumIDList_Release(penum);
1449 /****************************************************************************
1450 * ISFHelper_fnAddFolder
1452 * adds a new folder.
1455 static HRESULT WINAPI ISFHelper_fnAddFolder(
1459 LPITEMIDLIST* ppidlOut)
1461 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1462 char lpstrNewDir[MAX_PATH];
1464 HRESULT hres = E_FAIL;
1466 TRACE("(%p)(%s %p)\n", This, lpName, ppidlOut);
1468 strcpy(lpstrNewDir, This->sPathRoot);
1469 PathAddBackslashA(lpstrNewDir);
1470 strcat(lpstrNewDir, lpName);
1472 bRes = CreateDirectoryA(lpstrNewDir, NULL);
1476 LPITEMIDLIST pidl, pidlitem;
1478 pidlitem = SHSimpleIDListFromPathA(lpstrNewDir);
1480 pidl = ILCombine(This->pidlRoot, pidlitem);
1481 SHChangeNotifyA(SHCNE_MKDIR, SHCNF_IDLIST, pidl, NULL);
1484 if (ppidlOut) *ppidlOut = pidlitem;
1489 char lpstrText[128+MAX_PATH];
1490 char lpstrTempText[128];
1491 char lpstrCaption[256];
1493 /* Cannot Create folder because of permissions */
1494 LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, sizeof(lpstrTempText));
1495 LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, sizeof(lpstrCaption));
1496 sprintf(lpstrText,lpstrTempText, lpstrNewDir);
1497 MessageBoxA(hwnd,lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION);
1503 /****************************************************************************
1504 * ISFHelper_fnDeleteItems
1506 * deletes items in folder
1508 static HRESULT WINAPI ISFHelper_fnDeleteItems(
1511 LPCITEMIDLIST* apidl)
1513 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface)
1515 char szPath[MAX_PATH];
1516 BOOL bConfirm = TRUE;
1518 TRACE("(%p)(%u %p)\n", This, cidl, apidl);
1520 /* deleting multiple items so give a slightly different warning */
1524 snprintf(tmp, sizeof(tmp), "%d", cidl);
1525 if(!SHELL_WarnItemDelete(ASK_DELETE_MULTIPLE_ITEM, tmp))
1530 for(i=0; i< cidl; i++)
1532 strcpy(szPath, This->sPathRoot);
1533 PathAddBackslashA(szPath);
1534 _ILSimpleGetText(apidl[i], szPath+strlen(szPath), MAX_PATH);
1536 if (_ILIsFolder(apidl[i]))
1539 TRACE("delete %s\n", szPath);
1540 if (! SHELL_DeleteDirectoryA(szPath, bConfirm))
1542 TRACE("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
1545 pidl = ILCombine(This->pidlRoot, apidl[i]);
1546 SHChangeNotifyA(SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL);
1549 else if (_ILIsValue(apidl[i]))
1553 TRACE("delete %s\n", szPath);
1554 if (! SHELL_DeleteFileA(szPath, bConfirm))
1556 TRACE("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
1559 pidl = ILCombine(This->pidlRoot, apidl[i]);
1560 SHChangeNotifyA(SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL);
1568 /****************************************************************************
1569 * ISFHelper_fnCopyItems
1571 * copies items to this folder
1573 static HRESULT WINAPI ISFHelper_fnCopyItems(
1575 IShellFolder* pSFFrom,
1577 LPCITEMIDLIST *apidl)
1580 IPersistFolder2 * ppf2=NULL;
1581 char szSrcPath[MAX_PATH], szDstPath[MAX_PATH];
1582 _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface);
1584 TRACE("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl);
1586 IShellFolder_QueryInterface(pSFFrom, &IID_IPersistFolder2, (LPVOID*)&ppf2);
1590 if (SUCCEEDED(IPersistFolder2_GetCurFolder(ppf2, &pidl)))
1592 for (i=0; i<cidl; i++)
1594 SHGetPathFromIDListA(pidl, szSrcPath);
1595 PathAddBackslashA(szSrcPath);
1596 _ILSimpleGetText(apidl[i], szSrcPath+strlen(szSrcPath), MAX_PATH);
1598 strcpy(szDstPath, This->sPathRoot);
1599 PathAddBackslashA(szDstPath);
1600 _ILSimpleGetText(apidl[i], szDstPath+strlen(szDstPath), MAX_PATH);
1601 MESSAGE("would copy %s to %s\n", szSrcPath, szDstPath);
1605 IPersistFolder2_Release(ppf2);
1610 static ICOM_VTABLE(ISFHelper) shvt =
1612 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1613 ISFHelper_fnQueryInterface,
1615 ISFHelper_fnRelease,
1616 ISFHelper_fnGetUniqueName,
1617 ISFHelper_fnAddFolder,
1618 ISFHelper_fnDeleteItems,
1619 ISFHelper_fnCopyItems,
1622 /***********************************************************************
1623 * [Desktopfolder] IShellFolder implementation
1625 static struct ICOM_VTABLE(IShellFolder2) sfdvt;
1627 static shvheader DesktopSFHeader [] =
1629 { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
1630 { IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1631 { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
1632 { IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
1633 { IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 }
1635 #define DESKTOPSHELLVIEWCOLUMNS 5
1637 /**************************************************************************
1638 * ISF_Desktop_Constructor
1641 HRESULT WINAPI ISF_Desktop_Constructor (
1642 IUnknown * pUnkOuter,
1646 IGenericSFImpl * sf;
1648 TRACE("unkOut=%p %s\n",pUnkOuter, shdebugstr_guid(riid));
1650 if(!ppv) return E_POINTER;
1653 FIXME("CLASS_E_NOAGGREGATION\n");
1654 return CLASS_E_NOAGGREGATION;
1657 sf=(IGenericSFImpl*) LocalAlloc(GMEM_ZEROINIT,sizeof(IGenericSFImpl));
1659 ICOM_VTBL(sf)=&unkvt;
1660 sf->lpvtblShellFolder=&sfdvt;
1661 sf->pidlRoot=_ILCreateDesktop(); /* my qualified pidl */
1662 sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
1664 *ppv = _IShellFolder_(sf);
1667 TRACE("--(%p)\n",sf);
1671 /**************************************************************************
1672 * ISF_Desktop_fnQueryInterface
1674 * NOTES supports not IPersist/IPersistFolder
1676 static HRESULT WINAPI ISF_Desktop_fnQueryInterface(
1677 IShellFolder2 * iface,
1681 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1683 TRACE("(%p)->(%s,%p)\n",This,shdebugstr_guid(riid),ppvObj);
1687 if(IsEqualIID(riid, &IID_IUnknown)) /*IUnknown*/
1689 *ppvObj = _IUnknown_(This);
1691 else if(IsEqualIID(riid, &IID_IShellFolder)) /*IShellFolder*/
1693 *ppvObj = _IShellFolder_(This);
1695 else if(IsEqualIID(riid, &IID_IShellFolder2)) /*IShellFolder2*/
1697 *ppvObj = _IShellFolder_(This);
1702 IUnknown_AddRef((IUnknown*)(*ppvObj));
1703 TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj);
1706 TRACE("-- Interface: E_NOINTERFACE\n");
1707 return E_NOINTERFACE;
1710 /**************************************************************************
1711 * ISF_Desktop_fnParseDisplayName
1714 * "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
1717 static HRESULT WINAPI ISF_Desktop_fnParseDisplayName(
1718 IShellFolder2 * iface,
1721 LPOLESTR lpszDisplayName,
1723 LPITEMIDLIST *ppidl,
1724 DWORD *pdwAttributes)
1726 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1728 WCHAR szElement[MAX_PATH];
1729 LPCWSTR szNext=NULL;
1730 LPITEMIDLIST pidlTemp=NULL;
1731 HRESULT hr=E_OUTOFMEMORY;
1734 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
1735 This,hwndOwner,pbcReserved,lpszDisplayName,
1736 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
1739 if (pchEaten) *pchEaten = 0; /* strange but like the original */
1741 if(lpszDisplayName[0] == ':' && lpszDisplayName[1] == ':') {
1742 szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
1743 TRACE("-- element: %s\n", debugstr_w(szElement));
1744 CLSIDFromString(szElement+2, &clsid);
1745 TRACE("-- %s\n", shdebugstr_guid(&clsid));
1746 pidlTemp = _ILCreate(PT_MYCOMP, &clsid, sizeof(clsid));
1748 pidlTemp = _ILCreateMyComputer();
1749 /* it's a filesystem path, so we cant cut anything away */
1750 szNext = lpszDisplayName;
1754 if (szNext && *szNext)
1756 hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
1762 if (pdwAttributes && *pdwAttributes)
1764 SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
1770 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
1775 /**************************************************************************
1776 * ISF_Desktop_fnEnumObjects
1778 static HRESULT WINAPI ISF_Desktop_fnEnumObjects(
1779 IShellFolder2 * iface,
1782 LPENUMIDLIST* ppEnumIDList)
1784 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1786 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
1788 *ppEnumIDList = NULL;
1789 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_DESK);
1791 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
1793 if(!*ppEnumIDList) return E_OUTOFMEMORY;
1798 /**************************************************************************
1799 * ISF_Desktop_fnBindToObject
1801 static HRESULT WINAPI ISF_Desktop_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
1802 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
1804 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1806 IShellFolder *pShellFolder, *pSubFolder;
1807 IGenericSFImpl *pSFImpl;
1810 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n",
1811 This,pidl,pbcReserved,shdebugstr_guid(riid),ppvOut);
1815 if ((clsid=_ILGetGUIDPointer(pidl)))
1817 if ( IsEqualIID(clsid, &CLSID_MyComputer))
1819 pShellFolder = ISF_MyComputer_Constructor();
1823 /* shell extension */
1824 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->pidlRoot, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
1826 return E_INVALIDARG;
1832 /* file system folder on the desktop */
1833 LPITEMIDLIST deskpidl, firstpidl, completepidl;
1834 IPersistFolder * ppf;
1837 if ((pSFImpl = IShellFolder_Constructor())) {
1838 pShellFolder = _IShellFolder_(pSFImpl);
1839 if (SUCCEEDED(IShellFolder_QueryInterface(pShellFolder, &IID_IPersistFolder, (LPVOID*)&ppf))) {
1840 SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, &deskpidl);
1841 firstpidl = ILCloneFirst(pidl);
1842 completepidl = ILCombine(deskpidl, firstpidl);
1843 IPersistFolder_Initialize(ppf, completepidl);
1844 IPersistFolder_Release(ppf);
1845 ILFree(completepidl);
1852 if (_ILIsPidlSimple(pidl)) /* no sub folders */
1854 *ppvOut = pShellFolder;
1857 else /* go deeper */
1859 hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL, riid, (LPVOID)&pSubFolder);
1860 IShellFolder_Release(pShellFolder);
1861 *ppvOut = pSubFolder;
1864 TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
1869 /**************************************************************************
1870 * ISF_Desktop_fnCreateViewObject
1872 static HRESULT WINAPI ISF_Desktop_fnCreateViewObject( IShellFolder2 * iface,
1873 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
1875 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1877 LPSHELLVIEW pShellView;
1878 HRESULT hr = E_INVALIDARG;
1880 TRACE("(%p)->(hwnd=0x%x,%s,%p)\n",This,hwndOwner,shdebugstr_guid(riid),ppvOut);
1886 if(IsEqualIID(riid, &IID_IDropTarget))
1888 WARN("IDropTarget not implemented\n");
1891 else if(IsEqualIID(riid, &IID_IContextMenu))
1893 WARN("IContextMenu not implemented\n");
1896 else if(IsEqualIID(riid, &IID_IShellView))
1898 pShellView = IShellView_Constructor((IShellFolder*)iface);
1901 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
1902 IShellView_Release(pShellView);
1906 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
1910 /**************************************************************************
1911 * ISF_Desktop_fnGetAttributesOf
1913 static HRESULT WINAPI ISF_Desktop_fnGetAttributesOf(
1914 IShellFolder2 * iface,
1916 LPCITEMIDLIST *apidl,
1919 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1923 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl, *rgfInOut);
1925 if ( (!cidl) || (!apidl) || (!rgfInOut))
1926 return E_INVALIDARG;
1928 while (cidl > 0 && *apidl)
1931 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
1936 TRACE("-- result=0x%08lx\n",*rgfInOut);
1941 /**************************************************************************
1942 * ISF_Desktop_fnGetDisplayNameOf
1945 * special case: pidl = null gives desktop-name back
1947 static HRESULT WINAPI ISF_Desktop_fnGetDisplayNameOf(
1948 IShellFolder2 * iface,
1953 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1955 CHAR szPath[MAX_PATH]= "";
1957 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
1960 if(!strRet) return E_INVALIDARG;
1964 HCR_GetClassName(&CLSID_ShellDesktop, szPath, MAX_PATH);
1966 else if ( _ILIsPidlSimple(pidl) )
1968 _ILSimpleGetText(pidl, szPath, MAX_PATH);
1972 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, szPath, MAX_PATH)))
1973 return E_OUTOFMEMORY;
1975 strRet->uType = STRRET_CSTR;
1976 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
1979 TRACE("-- (%p)->(%s)\n", This, szPath);
1983 static HRESULT WINAPI ISF_Desktop_fnGetDefaultSearchGUID(
1984 IShellFolder2 * iface,
1987 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1988 FIXME("(%p)\n",This);
1991 static HRESULT WINAPI ISF_Desktop_fnEnumSearches(
1992 IShellFolder2 * iface,
1993 IEnumExtraSearch **ppenum)
1995 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
1996 FIXME("(%p)\n",This);
1999 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumn(
2000 IShellFolder2 * iface,
2005 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2007 TRACE("(%p)\n",This);
2009 if (pSort) *pSort = 0;
2010 if (pDisplay) *pDisplay = 0;
2014 static HRESULT WINAPI ISF_Desktop_fnGetDefaultColumnState(
2015 IShellFolder2 * iface,
2019 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2021 TRACE("(%p)\n",This);
2023 if (!pcsFlags || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2025 *pcsFlags = DesktopSFHeader[iColumn].pcsFlags;
2029 static HRESULT WINAPI ISF_Desktop_fnGetDetailsEx(
2030 IShellFolder2 * iface,
2032 const SHCOLUMNID *pscid,
2035 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2036 FIXME("(%p)\n",This);
2040 static HRESULT WINAPI ISF_Desktop_fnGetDetailsOf(
2041 IShellFolder2 * iface,
2046 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2047 HRESULT hr = E_FAIL;
2049 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2051 if (!psd || iColumn >= DESKTOPSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2055 psd->fmt = DesktopSFHeader[iColumn].fmt;
2056 psd->cxChar = DesktopSFHeader[iColumn].cxChar;
2057 psd->str.uType = STRRET_CSTR;
2058 LoadStringA(shell32_hInstance, DesktopSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2063 /* the data from the pidl */
2067 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2070 _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
2073 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2076 _ILGetFileDate(pidl, psd->str.u.cStr, MAX_PATH);
2078 case 4: /* attributes */
2079 _ILGetFileAttributes(pidl, psd->str.u.cStr, MAX_PATH);
2083 psd->str.uType = STRRET_CSTR;
2088 static HRESULT WINAPI ISF_Desktop_fnMapNameToSCID(
2089 IShellFolder2 * iface,
2093 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2094 FIXME("(%p)\n",This);
2098 static ICOM_VTABLE(IShellFolder2) sfdvt =
2100 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2101 ISF_Desktop_fnQueryInterface,
2102 IShellFolder_fnAddRef,
2103 IShellFolder_fnRelease,
2104 ISF_Desktop_fnParseDisplayName,
2105 ISF_Desktop_fnEnumObjects,
2106 ISF_Desktop_fnBindToObject,
2107 IShellFolder_fnBindToStorage,
2108 IShellFolder_fnCompareIDs,
2109 ISF_Desktop_fnCreateViewObject,
2110 ISF_Desktop_fnGetAttributesOf,
2111 IShellFolder_fnGetUIObjectOf,
2112 ISF_Desktop_fnGetDisplayNameOf,
2113 IShellFolder_fnSetNameOf,
2116 ISF_Desktop_fnGetDefaultSearchGUID,
2117 ISF_Desktop_fnEnumSearches,
2118 ISF_Desktop_fnGetDefaultColumn,
2119 ISF_Desktop_fnGetDefaultColumnState,
2120 ISF_Desktop_fnGetDetailsEx,
2121 ISF_Desktop_fnGetDetailsOf,
2122 ISF_Desktop_fnMapNameToSCID
2126 /***********************************************************************
2127 * IShellFolder [MyComputer] implementation
2130 static struct ICOM_VTABLE(IShellFolder2) sfmcvt;
2132 static shvheader MyComputerSFHeader [] =
2134 { IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
2135 { IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2136 { IDS_SHV_COLUMN6, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2137 { IDS_SHV_COLUMN7, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
2139 #define MYCOMPUTERSHELLVIEWCOLUMNS 4
2141 /**************************************************************************
2142 * ISF_MyComputer_Constructor
2144 static IShellFolder * ISF_MyComputer_Constructor(void)
2146 IGenericSFImpl * sf;
2148 sf=(IGenericSFImpl*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IGenericSFImpl));
2151 ICOM_VTBL(sf)=&unkvt;
2152 sf->lpvtblShellFolder=&sfmcvt;
2153 sf->lpvtblPersistFolder3 = &psfvt;
2154 sf->pclsid = (CLSID*)&CLSID_MyComputer;
2155 sf->pidlRoot=_ILCreateMyComputer(); /* my qualified pidl */
2156 sf->pUnkOuter = (IUnknown *) &sf->lpVtbl;
2161 return _IShellFolder_(sf);
2164 /**************************************************************************
2165 * ISF_MyComputer_fnParseDisplayName
2167 static HRESULT WINAPI ISF_MyComputer_fnParseDisplayName(
2168 IShellFolder2 * iface,
2171 LPOLESTR lpszDisplayName,
2173 LPITEMIDLIST *ppidl,
2174 DWORD *pdwAttributes)
2176 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2178 HRESULT hr = E_OUTOFMEMORY;
2179 LPCWSTR szNext=NULL;
2180 WCHAR szElement[MAX_PATH];
2181 CHAR szTempA[MAX_PATH];
2182 LPITEMIDLIST pidlTemp;
2184 TRACE("(%p)->(HWND=0x%08x,%p,%p=%s,%p,pidl=%p,%p)\n",
2185 This,hwndOwner,pbcReserved,lpszDisplayName,
2186 debugstr_w(lpszDisplayName),pchEaten,ppidl,pdwAttributes);
2189 if (pchEaten) *pchEaten = 0; /* strange but like the original */
2191 /* do we have an absolute path name ? */
2192 if (PathGetDriveNumberW(lpszDisplayName) >= 0 &&
2193 lpszDisplayName[2] == (WCHAR)'\\')
2195 szNext = GetNextElementW(lpszDisplayName, szElement, MAX_PATH);
2196 WideCharToMultiByte( CP_ACP, 0, szElement, -1, szTempA, MAX_PATH, NULL, NULL );
2197 pidlTemp = _ILCreateDrive(szTempA);
2199 if (szNext && *szNext)
2201 hr = SHELL32_ParseNextElement(hwndOwner, iface, &pidlTemp, (LPOLESTR)szNext, pchEaten, pdwAttributes);
2205 if (pdwAttributes && *pdwAttributes)
2207 SHELL32_GetItemAttributes(_IShellFolder_(This), pidlTemp, pdwAttributes);
2214 TRACE("(%p)->(-- ret=0x%08lx)\n", This, hr);
2219 /**************************************************************************
2220 * ISF_MyComputer_fnEnumObjects
2222 static HRESULT WINAPI ISF_MyComputer_fnEnumObjects(
2223 IShellFolder2 * iface,
2226 LPENUMIDLIST* ppEnumIDList)
2228 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2230 TRACE("(%p)->(HWND=0x%08x flags=0x%08lx pplist=%p)\n",This,hwndOwner,dwFlags,ppEnumIDList);
2232 *ppEnumIDList = NULL;
2233 *ppEnumIDList = IEnumIDList_Constructor (NULL, dwFlags, EIDL_MYCOMP);
2235 TRACE("-- (%p)->(new ID List: %p)\n",This,*ppEnumIDList);
2237 if(!*ppEnumIDList) return E_OUTOFMEMORY;
2242 /**************************************************************************
2243 * ISF_MyComputer_fnBindToObject
2245 static HRESULT WINAPI ISF_MyComputer_fnBindToObject( IShellFolder2 * iface, LPCITEMIDLIST pidl,
2246 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
2248 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2250 IShellFolder *pShellFolder, *pSubFolder;
2251 IGenericSFImpl *pSFImpl;
2252 LPITEMIDLIST pidltemp;
2255 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n",
2256 This,pidl,pbcReserved,shdebugstr_guid(riid),ppvOut);
2258 if(!pidl || !ppvOut) return E_INVALIDARG;
2262 if ((clsid=_ILGetGUIDPointer(pidl)) && !IsEqualIID(clsid, &CLSID_MyComputer))
2264 if (!SUCCEEDED(SHELL32_CoCreateInitSF (This->pidlRoot, pidl, clsid, riid, (LPVOID*)&pShellFolder)))
2271 if (!_ILIsDrive(pidl)) return E_INVALIDARG;
2273 if ((pSFImpl = IShellFolder_Constructor())) {
2274 pidltemp = ILCloneFirst(pidl);
2275 InitializeGenericSF(pSFImpl, This->pidlRoot, pidltemp, This->sPathRoot);
2277 pShellFolder = _IShellFolder_(pSFImpl);
2281 if (_ILIsPidlSimple(pidl)) /* no sub folders */
2283 *ppvOut = pShellFolder;
2286 else /* go deeper */
2288 hr = IShellFolder_BindToObject(pShellFolder, ILGetNext(pidl), NULL,
2289 riid, (LPVOID)&pSubFolder);
2290 IShellFolder_Release(pShellFolder);
2291 *ppvOut = pSubFolder;
2294 TRACE("-- (%p) returning (%p) %08lx\n",This, *ppvOut, hr);
2299 /**************************************************************************
2300 * ISF_MyComputer_fnCreateViewObject
2302 static HRESULT WINAPI ISF_MyComputer_fnCreateViewObject( IShellFolder2 * iface,
2303 HWND hwndOwner, REFIID riid, LPVOID *ppvOut)
2305 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2307 LPSHELLVIEW pShellView;
2308 HRESULT hr = E_INVALIDARG;
2310 TRACE("(%p)->(hwnd=0x%x,%s,%p)\n",This,hwndOwner,shdebugstr_guid(riid),ppvOut);
2316 if(IsEqualIID(riid, &IID_IDropTarget))
2318 WARN("IDropTarget not implemented\n");
2321 else if(IsEqualIID(riid, &IID_IContextMenu))
2323 WARN("IContextMenu not implemented\n");
2326 else if(IsEqualIID(riid, &IID_IShellView))
2328 pShellView = IShellView_Constructor((IShellFolder*)iface);
2331 hr = IShellView_QueryInterface(pShellView, riid, ppvOut);
2332 IShellView_Release(pShellView);
2336 TRACE("-- (%p)->(interface=%p)\n",This, ppvOut);
2340 /**************************************************************************
2341 * ISF_MyComputer_fnGetAttributesOf
2343 static HRESULT WINAPI ISF_MyComputer_fnGetAttributesOf(
2344 IShellFolder2 * iface,
2346 LPCITEMIDLIST *apidl,
2349 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2353 TRACE("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n",This,cidl,apidl,*rgfInOut);
2355 if ( (!cidl) || (!apidl) || (!rgfInOut))
2356 return E_INVALIDARG;
2358 while (cidl > 0 && *apidl)
2361 SHELL32_GetItemAttributes(_IShellFolder_(This), *apidl, rgfInOut);
2366 TRACE("-- result=0x%08lx\n",*rgfInOut);
2370 /**************************************************************************
2371 * ISF_MyComputer_fnGetDisplayNameOf
2374 * The desktopfolder creates only complete paths (SHGDN_FORPARSING).
2375 * SHGDN_INFOLDER makes no sense.
2377 static HRESULT WINAPI ISF_MyComputer_fnGetDisplayNameOf(
2378 IShellFolder2 * iface,
2383 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2385 char szPath[MAX_PATH], szDrive[18];
2389 TRACE("(%p)->(pidl=%p,0x%08lx,%p)\n",This,pidl,dwFlags,strRet);
2392 if(!strRet) return E_INVALIDARG;
2394 szPath[0]=0x00; szDrive[0]=0x00;
2397 bSimplePidl = _ILIsPidlSimple(pidl);
2399 if (_ILIsSpecialFolder(pidl))
2401 /* take names of special folders only if its only this folder */
2404 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
2409 if (!_ILIsDrive(pidl))
2411 ERR("Wrong pidl type\n");
2412 return E_INVALIDARG;
2415 _ILSimpleGetText(pidl, szPath, MAX_PATH); /* append my own path */
2417 /* long view "lw_name (C:)" */
2418 if ( bSimplePidl && !(dwFlags & SHGDN_FORPARSING))
2420 DWORD dwVolumeSerialNumber,dwMaximumComponetLength,dwFileSystemFlags;
2422 GetVolumeInformationA(szPath,szDrive,sizeof(szDrive)-6,&dwVolumeSerialNumber,&dwMaximumComponetLength,&dwFileSystemFlags,NULL,0);
2423 strcat (szDrive," (");
2424 strncat (szDrive, szPath, 2);
2425 strcat (szDrive,")");
2426 strcpy (szPath, szDrive);
2430 if (!bSimplePidl) /* go deeper if needed */
2432 PathAddBackslashA(szPath);
2433 len = strlen(szPath);
2435 if (!SUCCEEDED(SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags | SHGDN_FORPARSING, szPath + len, MAX_PATH - len)))
2436 return E_OUTOFMEMORY;
2438 strRet->uType = STRRET_CSTR;
2439 lstrcpynA(strRet->u.cStr, szPath, MAX_PATH);
2442 TRACE("-- (%p)->(%s)\n", This, szPath);
2446 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultSearchGUID(
2447 IShellFolder2 * iface,
2450 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2451 FIXME("(%p)\n",This);
2454 static HRESULT WINAPI ISF_MyComputer_fnEnumSearches(
2455 IShellFolder2 * iface,
2456 IEnumExtraSearch **ppenum)
2458 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2459 FIXME("(%p)\n",This);
2462 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumn(
2463 IShellFolder2 * iface,
2468 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2470 TRACE("(%p)\n",This);
2472 if (pSort) *pSort = 0;
2473 if (pDisplay) *pDisplay = 0;
2477 static HRESULT WINAPI ISF_MyComputer_fnGetDefaultColumnState(
2478 IShellFolder2 * iface,
2482 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2484 TRACE("(%p)\n",This);
2486 if (!pcsFlags || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2488 *pcsFlags = MyComputerSFHeader[iColumn].pcsFlags;
2492 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsEx(
2493 IShellFolder2 * iface,
2495 const SHCOLUMNID *pscid,
2498 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2499 FIXME("(%p)\n",This);
2504 /* FIXME: drive size >4GB is rolling over */
2505 static HRESULT WINAPI ISF_MyComputer_fnGetDetailsOf(
2506 IShellFolder2 * iface,
2511 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2514 TRACE("(%p)->(%p %i %p)\n",This, pidl, iColumn, psd);
2516 if (!psd || iColumn >= MYCOMPUTERSHELLVIEWCOLUMNS ) return E_INVALIDARG;
2520 psd->fmt = MyComputerSFHeader[iColumn].fmt;
2521 psd->cxChar = MyComputerSFHeader[iColumn].cxChar;
2522 psd->str.uType = STRRET_CSTR;
2523 LoadStringA(shell32_hInstance, MyComputerSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
2528 char szPath[MAX_PATH];
2529 ULARGE_INTEGER ulBytes;
2531 psd->str.u.cStr[0] = 0x00;
2532 psd->str.uType = STRRET_CSTR;
2536 hr = IShellFolder_GetDisplayNameOf(iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
2539 _ILGetFileType(pidl, psd->str.u.cStr, MAX_PATH);
2541 case 2: /* total size */
2542 if (_ILIsDrive(pidl))
2544 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2545 GetDiskFreeSpaceExA(szPath, NULL, &ulBytes, NULL);
2546 StrFormatByteSizeA(ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
2549 case 3: /* free size */
2550 if (_ILIsDrive(pidl))
2552 _ILSimpleGetText(pidl, szPath, MAX_PATH);
2553 GetDiskFreeSpaceExA(szPath, &ulBytes, NULL, NULL);
2554 StrFormatByteSizeA(ulBytes.s.LowPart, psd->str.u.cStr, MAX_PATH);
2563 static HRESULT WINAPI ISF_MyComputer_fnMapNameToSCID(
2564 IShellFolder2 * iface,
2568 _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface)
2569 FIXME("(%p)\n",This);
2573 static ICOM_VTABLE(IShellFolder2) sfmcvt =
2575 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2576 IShellFolder_fnQueryInterface,
2577 IShellFolder_fnAddRef,
2578 IShellFolder_fnRelease,
2579 ISF_MyComputer_fnParseDisplayName,
2580 ISF_MyComputer_fnEnumObjects,
2581 ISF_MyComputer_fnBindToObject,
2582 IShellFolder_fnBindToStorage,
2583 IShellFolder_fnCompareIDs,
2584 ISF_MyComputer_fnCreateViewObject,
2585 ISF_MyComputer_fnGetAttributesOf,
2586 IShellFolder_fnGetUIObjectOf,
2587 ISF_MyComputer_fnGetDisplayNameOf,
2588 IShellFolder_fnSetNameOf,
2591 ISF_MyComputer_fnGetDefaultSearchGUID,
2592 ISF_MyComputer_fnEnumSearches,
2593 ISF_MyComputer_fnGetDefaultColumn,
2594 ISF_MyComputer_fnGetDefaultColumnState,
2595 ISF_MyComputer_fnGetDetailsEx,
2596 ISF_MyComputer_fnGetDetailsOf,
2597 ISF_MyComputer_fnMapNameToSCID
2601 /************************************************************************
2602 * ISFPersistFolder_QueryInterface (IUnknown)
2605 static HRESULT WINAPI ISFPersistFolder3_QueryInterface(
2606 IPersistFolder3 * iface,
2610 _ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
2612 TRACE("(%p)\n", This);
2614 return IUnknown_QueryInterface(This->pUnkOuter, iid, ppvObj);
2617 /************************************************************************
2618 * ISFPersistFolder_AddRef (IUnknown)
2621 static ULONG WINAPI ISFPersistFolder3_AddRef(
2622 IPersistFolder3 * iface)
2624 _ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
2626 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2628 return IUnknown_AddRef(This->pUnkOuter);
2631 /************************************************************************
2632 * ISFPersistFolder_Release (IUnknown)
2635 static ULONG WINAPI ISFPersistFolder3_Release(
2636 IPersistFolder3 * iface)
2638 _ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
2640 TRACE("(%p)->(count=%lu)\n",This,This->ref);
2642 return IUnknown_Release(This->pUnkOuter);
2645 /************************************************************************
2646 * ISFPersistFolder_GetClassID (IPersist)
2648 static HRESULT WINAPI ISFPersistFolder3_GetClassID(
2649 IPersistFolder3 * iface,
2652 _ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
2654 TRACE("(%p)\n", This);
2656 if (!lpClassId) return E_POINTER;
2657 *lpClassId = *This->pclsid;
2662 /************************************************************************
2663 * ISFPersistFolder_Initialize (IPersistFolder)
2666 * sPathRoot is not set. Don't know how to handle in a non rooted environment.
2668 static HRESULT WINAPI ISFPersistFolder3_Initialize(
2669 IPersistFolder3 * iface,
2672 char sTemp[MAX_PATH];
2673 _ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
2675 TRACE("(%p)->(%p)\n", This, pidl);
2677 if(This->pidlRoot) SHFree(This->pidlRoot); /* free the old pidl */
2678 This->pidlRoot = ILClone(pidl); /* set my pidl */
2680 if(This->sPathRoot) SHFree(This->sPathRoot);
2683 if (SHGetPathFromIDListA(pidl, sTemp))
2685 This->sPathRoot = SHAlloc(strlen(sTemp)+1);
2686 strcpy(This->sPathRoot, sTemp);
2689 TRACE("--(%p)->(%s)\n", This, This->sPathRoot);
2693 /**************************************************************************
2694 * IPersistFolder2_fnGetCurFolder
2696 static HRESULT WINAPI ISFPersistFolder3_fnGetCurFolder(
2697 IPersistFolder3 * iface,
2698 LPITEMIDLIST * pidl)
2700 _ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
2702 TRACE("(%p)->(%p)\n",This, pidl);
2704 if (!pidl) return E_POINTER;
2706 *pidl = ILClone(This->pidlRoot);
2711 static HRESULT WINAPI ISFPersistFolder3_InitializeEx(
2712 IPersistFolder3 * iface,
2714 LPCITEMIDLIST pidlRoot,
2715 const PERSIST_FOLDER_TARGET_INFO *ppfti)
2717 char sTemp[MAX_PATH];
2718 _ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
2720 FIXME("(%p)->(%p,%p,%p)\n",This,pbc,pidlRoot,ppfti);
2721 TRACE("--%p %s %s 0x%08lx 0x%08x\n",
2722 ppfti->pidlTargetFolder, debugstr_w(ppfti->szTargetParsingName),
2723 debugstr_w(ppfti->szNetworkProvider), ppfti->dwAttributes, ppfti->csidl);
2726 if(ppfti->pidlTargetFolder) pdump(ppfti->pidlTargetFolder);
2728 if(This->pidlRoot) SHFree(This->pidlRoot); /* free the old pidl */
2730 if(ppfti->csidl == -1) { /* set my pidl */
2731 This->pidlRoot = ILClone(ppfti->pidlTargetFolder);
2733 SHGetSpecialFolderLocation(0, ppfti->csidl, &This->pidlRoot);
2736 if(This->sPathRoot) SHFree(This->sPathRoot);
2739 if (SHGetPathFromIDListA(This->pidlRoot, sTemp))
2741 This->sPathRoot = SHAlloc(strlen(sTemp)+1);
2742 strcpy(This->sPathRoot, sTemp);
2745 TRACE("--(%p)->(%s)\n", This, This->sPathRoot);
2749 static HRESULT WINAPI ISFPersistFolder3_GetFolderTargetInfo(
2750 IPersistFolder3 *iface,
2751 PERSIST_FOLDER_TARGET_INFO *ppfti)
2753 _ICOM_THIS_From_IPersistFolder3(IGenericSFImpl, iface);
2754 FIXME("(%p)->(%p)\n",This,ppfti);
2755 ZeroMemory(ppfti, sizeof(ppfti));
2759 static ICOM_VTABLE(IPersistFolder3) psfvt =
2761 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2762 ISFPersistFolder3_QueryInterface,
2763 ISFPersistFolder3_AddRef,
2764 ISFPersistFolder3_Release,
2765 ISFPersistFolder3_GetClassID,
2766 ISFPersistFolder3_Initialize,
2767 ISFPersistFolder3_fnGetCurFolder,
2768 ISFPersistFolder3_InitializeEx,
2769 ISFPersistFolder3_GetFolderTargetInfo
2772 /****************************************************************************
2773 * ISFDropTarget implementation
2775 static BOOL ISFDropTarget_QueryDrop(
2780 DWORD dwEffect = *pdwEffect;
2782 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2784 *pdwEffect = DROPEFFECT_NONE;
2786 if (This->fAcceptFmt)
2787 { /* Does our interpretation of the keystate ... */
2788 *pdwEffect = KeyStateToDropEffect(dwKeyState);
2790 /* ... matches the desired effect ? */
2791 if (dwEffect & *pdwEffect)
2799 static HRESULT WINAPI ISFDropTarget_QueryInterface(
2804 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2806 TRACE("(%p)\n", This);
2808 return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj);
2811 static ULONG WINAPI ISFDropTarget_AddRef( IDropTarget *iface)
2813 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2815 TRACE("(%p)\n", This);
2817 return IUnknown_AddRef(This->pUnkOuter);
2820 static ULONG WINAPI ISFDropTarget_Release( IDropTarget *iface)
2822 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2824 TRACE("(%p)\n", This);
2826 return IUnknown_Release(This->pUnkOuter);
2829 static HRESULT WINAPI ISFDropTarget_DragEnter(
2831 IDataObject *pDataObject,
2838 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2840 TRACE("(%p)->(DataObject=%p)\n",This,pDataObject);
2842 InitFormatEtc(fmt, This->cfShellIDList, TYMED_HGLOBAL);
2844 This->fAcceptFmt = (S_OK == IDataObject_QueryGetData(pDataObject, &fmt)) ? TRUE : FALSE;
2846 ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2851 static HRESULT WINAPI ISFDropTarget_DragOver(
2857 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2859 TRACE("(%p)\n",This);
2861 if(!pdwEffect) return E_INVALIDARG;
2863 ISFDropTarget_QueryDrop(iface, dwKeyState, pdwEffect);
2868 static HRESULT WINAPI ISFDropTarget_DragLeave(
2871 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2873 TRACE("(%p)\n",This);
2875 This->fAcceptFmt = FALSE;
2880 static HRESULT WINAPI ISFDropTarget_Drop(
2882 IDataObject* pDataObject,
2887 _ICOM_THIS_From_IDropTarget(IGenericSFImpl,iface);
2889 FIXME("(%p) object dropped\n",This);
2894 static struct ICOM_VTABLE(IDropTarget) dtvt =
2896 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2897 ISFDropTarget_QueryInterface,
2898 ISFDropTarget_AddRef,
2899 ISFDropTarget_Release,
2900 ISFDropTarget_DragEnter,
2901 ISFDropTarget_DragOver,
2902 ISFDropTarget_DragLeave,