2 * Virtual Desktop Folder
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998, 1999, 2002 Juergen Schmied
6 * Copyright 2009 Andrew Hill
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
28 CDesktopFolder should create two file system folders internally, one representing the
29 user's desktop folder, and the other representing the common desktop folder. It should
30 also create a CRegFolder to represent the virtual items that exist only in the registry.
31 The CRegFolder is aggregated by the CDesktopFolder, and queries for the CLSID_IShellFolder,
32 CLSID_IShellFolder2, or CLSID_IShellIconOverlay interfaces prefer the CRegFolder
34 The CDesktopFolderEnum class should create two enumerators, one for each of the file
35 system folders, and enumerate the contents of each folder. Since the CRegFolder
36 implementation of IShellFolder::EnumObjects enumerates the virtual items, the
37 CDesktopFolderEnum is only responsible for returning the physical items.
38 CDesktopFolderEnum is incorrect where it filters My Computer from the enumeration
39 if the new start menu is used. The CDesktopViewCallback is responsible for filtering
40 it from the view by handling the IncludeObject query to return S_FALSE. The enumerator
41 always shows My Computer.
44 /* Undocumented functions from shdocvw */
45 extern "C" HRESULT WINAPI
IEParseDisplayNameWithBCW(DWORD codepage
, LPCWSTR lpszDisplayName
, LPBC pbc
, LPITEMIDLIST
*ppidl
);
47 class CDesktopFolderEnum
:
48 public CEnumIDListBase
51 // CComPtr fDesktopEnumerator;
52 // CComPtr fCommonDesktopEnumerator;
55 ~CDesktopFolderEnum();
56 HRESULT WINAPI
Initialize(CDesktopFolder
*desktopFolder
, HWND hwndOwner
, DWORD dwFlags
);
58 BEGIN_COM_MAP(CDesktopFolderEnum
)
59 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList
, IEnumIDList
)
63 int SHELL_ConfirmMsgBox(HWND hWnd
, LPWSTR lpszText
, LPWSTR lpszCaption
, HICON hIcon
, BOOL bYesToAll
);
65 static const shvheader DesktopSFHeader
[] = {
66 {IDS_SHV_COLUMN1
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 15},
67 {IDS_SHV_COLUMN2
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
68 {IDS_SHV_COLUMN3
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
69 {IDS_SHV_COLUMN4
, SHCOLSTATE_TYPE_DATE
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 12},
70 {IDS_SHV_COLUMN5
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 5}
73 #define DESKTOPSHELLVIEWCOLUMNS 5
75 CDesktopFolderEnum::CDesktopFolderEnum()
79 CDesktopFolderEnum::~CDesktopFolderEnum()
83 static const WCHAR ClassicStartMenuW
[] = L
"SOFTWARE\\Microsoft\\Windows\\"
84 L
"CurrentVersion\\Explorer\\HideDesktopIcons\\ClassicStartMenu";
87 IsNamespaceExtensionHidden(const WCHAR
*iid
)
89 DWORD Result
, dwResult
;
90 dwResult
= sizeof(DWORD
);
92 if (RegGetValueW(HKEY_CURRENT_USER
, /* FIXME use NewStartPanel when activated */
98 &dwResult
) != ERROR_SUCCESS
)
106 /**************************************************************************
107 * CreateDesktopEnumList()
110 HRESULT WINAPI
CDesktopFolderEnum::Initialize(CDesktopFolder
*desktopFolder
, HWND hwndOwner
, DWORD dwFlags
)
113 WCHAR szPath
[MAX_PATH
];
115 static const WCHAR MyDocumentsClassString
[] = L
"{450D8FBA-AD25-11D0-98A8-0800361B1103}";
116 static const WCHAR Desktop_NameSpaceW
[] = L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\Namespace";
118 TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags
);
120 /* enumerate the root folders */
121 if (dwFlags
& SHCONTF_FOLDERS
)
127 /* create the pidl for This item */
128 if (IsNamespaceExtensionHidden(MyDocumentsClassString
) < 1)
130 ret
= AddToEnumList(_ILCreateMyDocuments());
132 ret
= AddToEnumList(_ILCreateMyComputer());
134 for (i
= 0; i
< 2; i
++)
137 dwResult
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, Desktop_NameSpaceW
, 0, KEY_READ
, &hkey
);
139 dwResult
= RegOpenKeyExW(HKEY_CURRENT_USER
, Desktop_NameSpaceW
, 0, KEY_READ
, &hkey
);
141 if (dwResult
== ERROR_SUCCESS
)
152 size
= sizeof (iid
) / sizeof (iid
[0]);
153 r
= RegEnumKeyExW(hkey
, i
, iid
, &size
, 0, NULL
, NULL
, NULL
);
154 if (ERROR_SUCCESS
== r
)
156 if (IsNamespaceExtensionHidden(iid
) < 1)
158 pidl
= _ILCreateGuidFromStrW(iid
);
161 if (!HasItemWithCLSID(pidl
))
163 ret
= AddToEnumList(pidl
);
172 else if (ERROR_NO_MORE_ITEMS
== r
)
181 for (i
= 0; i
< 2; i
++)
184 dwResult
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, ClassicStartMenuW
, 0, KEY_READ
, &hkey
);
186 dwResult
= RegOpenKeyExW(HKEY_CURRENT_USER
, ClassicStartMenuW
, 0, KEY_READ
, &hkey
);
188 if (dwResult
== ERROR_SUCCESS
)
190 DWORD j
= 0, dwVal
, Val
, dwType
, dwIID
;
197 dwIID
= sizeof(iid
) / sizeof(WCHAR
);
199 r
= RegEnumValueW(hkey
, j
++, iid
, &dwIID
, NULL
, &dwType
, (LPBYTE
)&Val
, &dwVal
);
200 if (r
== ERROR_SUCCESS
)
202 if (Val
== 0 && dwType
== REG_DWORD
)
204 LPITEMIDLIST pidl
= _ILCreateGuidFromStrW(iid
);
207 if (!HasItemWithCLSID(pidl
))
218 else if (ERROR_NO_MORE_ITEMS
== r
)
229 /* enumerate the elements in %windir%\desktop */
230 ret
= ret
&& SHGetSpecialFolderPathW(0, szPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
231 ret
= ret
&& CreateFolderEnumList(szPath
, dwFlags
);
233 ret
= ret
&& SHGetSpecialFolderPathW(0, szPath
, CSIDL_COMMON_DESKTOPDIRECTORY
, FALSE
);
234 ret
= ret
&& CreateFolderEnumList(szPath
, dwFlags
);
236 return ret
? S_OK
: E_FAIL
;
239 CDesktopFolder::CDesktopFolder() :
245 CDesktopFolder::~CDesktopFolder()
249 HRESULT WINAPI
CDesktopFolder::FinalConstruct()
251 WCHAR szMyPath
[MAX_PATH
];
253 CComPtr
<IPersistFolder3
> ppf3
;
255 /* Create the root pidl */
256 pidlRoot
= _ILCreateDesktop();
258 /* Create the inner fs folder */
259 hr
= SHCoCreateInstance(NULL
, &CLSID_ShellFSFolder
, NULL
, IID_PPV_ARG(IShellFolder
, &m_DesktopFSFolder
));
263 hr
= m_DesktopFSFolder
->QueryInterface(IID_PPV_ARG(IPersistFolder3
, &ppf3
));
267 PERSIST_FOLDER_TARGET_INFO info
;
268 ZeroMemory(&info
, sizeof(PERSIST_FOLDER_TARGET_INFO
));
269 info
.csidl
= CSIDL_DESKTOPDIRECTORY
;
270 hr
= ppf3
->InitializeEx(NULL
, pidlRoot
, &info
);
272 /* Create the inner shared fs folder */
273 hr
= SHCoCreateInstance(NULL
, &CLSID_ShellFSFolder
, NULL
, IID_PPV_ARG(IShellFolder
, &m_SharedDesktopFSFolder
));
277 hr
= m_DesktopFSFolder
->QueryInterface(IID_PPV_ARG(IPersistFolder3
, &ppf3
));
281 info
.csidl
= CSIDL_COMMON_DESKTOPDIRECTORY
;
282 hr
= ppf3
->InitializeEx(NULL
, pidlRoot
, &info
);
284 if (!SHGetSpecialFolderPathW( 0, szMyPath
, CSIDL_DESKTOPDIRECTORY
, TRUE
))
287 sPathTarget
= (LPWSTR
)SHAlloc((wcslen(szMyPath
) + 1) * sizeof(WCHAR
));
288 wcscpy(sPathTarget
, szMyPath
);
292 /**************************************************************************
293 * CDesktopFolder::ParseDisplayName
296 * "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
299 HRESULT WINAPI
CDesktopFolder::ParseDisplayName(
302 LPOLESTR lpszDisplayName
,
304 PIDLIST_RELATIVE
*ppidl
,
305 DWORD
*pdwAttributes
)
307 WCHAR szElement
[MAX_PATH
];
308 LPCWSTR szNext
= NULL
;
309 LPITEMIDLIST pidlTemp
= NULL
;
314 TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
315 this, hwndOwner
, pbc
, lpszDisplayName
, debugstr_w(lpszDisplayName
),
316 pchEaten
, ppidl
, pdwAttributes
);
321 if (!lpszDisplayName
)
330 *pchEaten
= 0; /* strange but like the original */
332 urldata
.cbSize
= sizeof(urldata
);
334 if (lpszDisplayName
[0] == ':' && lpszDisplayName
[1] == ':')
336 szNext
= GetNextElementW (lpszDisplayName
, szElement
, MAX_PATH
);
337 TRACE ("-- element: %s\n", debugstr_w (szElement
));
338 CLSIDFromString (szElement
+ 2, &clsid
);
339 pidlTemp
= _ILCreateGuid (PT_GUID
, clsid
);
341 else if (PathGetDriveNumberW (lpszDisplayName
) >= 0)
343 /* it's a filesystem path with a drive. Let MyComputer/UnixDosFolder parse it */
344 pidlTemp
= _ILCreateMyComputer ();
345 szNext
= lpszDisplayName
;
347 else if (PathIsUNCW(lpszDisplayName
))
349 pidlTemp
= _ILCreateNetwork();
350 szNext
= lpszDisplayName
;
352 else if( (pidlTemp
= SHELL32_CreatePidlFromBindCtx(pbc
, lpszDisplayName
)) )
357 else if (SUCCEEDED(ParseURLW(lpszDisplayName
, &urldata
)))
359 if (urldata
.nScheme
== URL_SCHEME_SHELL
) /* handle shell: urls */
361 TRACE ("-- shell url: %s\n", debugstr_w(urldata
.pszSuffix
));
362 SHCLSIDFromStringW (urldata
.pszSuffix
+ 2, &clsid
);
363 pidlTemp
= _ILCreateGuid (PT_GUID
, clsid
);
366 return IEParseDisplayNameWithBCW(CP_ACP
, lpszDisplayName
, pbc
, ppidl
);
370 if (*lpszDisplayName
)
372 /* it's a filesystem path on the desktop. Let a FSFolder parse it */
373 hr
= m_DesktopFSFolder
->ParseDisplayName(hwndOwner
, pbc
, lpszDisplayName
, pchEaten
, ppidl
, pdwAttributes
);
377 return m_SharedDesktopFSFolder
->ParseDisplayName(hwndOwner
, pbc
, lpszDisplayName
, pchEaten
, ppidl
, pdwAttributes
);
380 pidlTemp
= _ILCreateMyComputer();
385 if (SUCCEEDED(hr
) && pidlTemp
)
387 if (szNext
&& *szNext
)
389 hr
= SHELL32_ParseNextElement(this, hwndOwner
, pbc
,
390 &pidlTemp
, (LPOLESTR
) szNext
, pchEaten
, pdwAttributes
);
394 if (pdwAttributes
&& *pdwAttributes
)
395 hr
= SHELL32_GetItemAttributes((IShellFolder
*)this,
396 pidlTemp
, pdwAttributes
);
405 TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr
);
410 /**************************************************************************
411 * CDesktopFolder::EnumObjects
413 HRESULT WINAPI
CDesktopFolder::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
*ppEnumIDList
)
415 return ShellObjectCreatorInit
<CDesktopFolderEnum
>(this, hwndOwner
, dwFlags
, IID_IEnumIDList
, ppEnumIDList
);
418 /**************************************************************************
419 * CDesktopFolder::BindToObject
421 HRESULT WINAPI
CDesktopFolder::BindToObject(
422 PCUIDLIST_RELATIVE pidl
,
427 TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n",
428 this, pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
430 return SHELL32_BindToChild( pidlRoot
, sPathTarget
, pidl
, riid
, ppvOut
);
433 /**************************************************************************
434 * CDesktopFolder::BindToStorage
436 HRESULT WINAPI
CDesktopFolder::BindToStorage(
437 PCUIDLIST_RELATIVE pidl
,
442 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
443 this, pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
449 /**************************************************************************
450 * CDesktopFolder::CompareIDs
452 HRESULT WINAPI
CDesktopFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
454 if (_ILIsSpecialFolder(pidl1
) || _ILIsSpecialFolder(pidl2
))
455 return SHELL32_CompareIDs ((IShellFolder
*)this, lParam
, pidl1
, pidl2
);
457 return m_DesktopFSFolder
->CompareIDs(lParam
, pidl1
, pidl2
);
460 /**************************************************************************
461 * CDesktopFolder::CreateViewObject
463 HRESULT WINAPI
CDesktopFolder::CreateViewObject(
468 CComPtr
<IShellView
> pShellView
;
469 HRESULT hr
= E_INVALIDARG
;
471 TRACE ("(%p)->(hwnd=%p,%s,%p)\n",
472 this, hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
479 if (IsEqualIID (riid
, IID_IDropTarget
))
481 hr
= m_DesktopFSFolder
->CreateViewObject(hwndOwner
, riid
, ppvOut
);
483 else if (IsEqualIID (riid
, IID_IContextMenu
))
485 WARN ("IContextMenu not implemented\n");
488 else if (IsEqualIID (riid
, IID_IShellView
))
490 hr
= IShellView_Constructor((IShellFolder
*)this, &pShellView
);
492 hr
= pShellView
->QueryInterface(riid
, ppvOut
);
494 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
498 /**************************************************************************
499 * CDesktopFolder::GetAttributesOf
501 HRESULT WINAPI
CDesktopFolder::GetAttributesOf(
503 PCUITEMID_CHILD_ARRAY apidl
,
507 static const DWORD dwDesktopAttributes
=
508 SFGAO_HASSUBFOLDER
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
|
509 SFGAO_STORAGEANCESTOR
| SFGAO_HASPROPSHEET
| SFGAO_STORAGE
| SFGAO_CANLINK
;
510 static const DWORD dwMyComputerAttributes
=
511 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
512 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_CANLINK
;
513 static DWORD dwMyNetPlacesAttributes
=
514 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
515 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_CANLINK
;
517 TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
518 this, cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
527 *rgfInOut
&= dwDesktopAttributes
;
530 /* TODO: always add SFGAO_CANLINK */
531 for (UINT i
= 0; i
< cidl
; ++i
)
534 if (_ILIsDesktop(*apidl
))
535 *rgfInOut
&= dwDesktopAttributes
;
536 else if (_ILIsMyComputer(apidl
[i
]))
537 *rgfInOut
&= dwMyComputerAttributes
;
538 else if (_ILIsNetHood(apidl
[i
]))
539 *rgfInOut
&= dwMyNetPlacesAttributes
;
540 else if (_ILIsSpecialFolder(apidl
[i
]))
541 SHELL32_GetGuidItemAttributes(this, apidl
[i
], rgfInOut
);
542 else if(_ILIsFolder(apidl
[i
]) || _ILIsValue(apidl
[i
]))
543 SHELL32_GetItemAttributes(this, apidl
[i
], rgfInOut
);
545 ERR("Got an unknown pidl type!!!\n");
548 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
549 *rgfInOut
&= ~SFGAO_VALIDATE
;
551 TRACE("-- result=0x%08x\n", *rgfInOut
);
556 /**************************************************************************
557 * CDesktopFolder::GetUIObjectOf
560 * HWND hwndOwner, //[in ] Parent window for any output
561 * UINT cidl, //[in ] array size
562 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
563 * REFIID riid, //[in ] Requested Interface
564 * UINT* prgfInOut, //[ ] reserved
565 * LPVOID* ppvObject) //[out] Resulting Interface
568 HRESULT WINAPI
CDesktopFolder::GetUIObjectOf(
571 PCUITEMID_CHILD_ARRAY apidl
,
577 IUnknown
*pObj
= NULL
;
578 HRESULT hr
= E_INVALIDARG
;
580 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
581 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
588 if (IsEqualIID (riid
, IID_IContextMenu
))
590 hr
= CDefFolderMenu_Create2(pidlRoot
, hwndOwner
, cidl
, apidl
, (IShellFolder
*)this, NULL
, 0, NULL
, (IContextMenu
**)&pObj
);
592 else if (IsEqualIID (riid
, IID_IDataObject
) && (cidl
>= 1))
594 hr
= IDataObject_Constructor( hwndOwner
, pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
596 else if (IsEqualIID (riid
, IID_IExtractIconA
) && (cidl
== 1))
598 pidl
= ILCombine (pidlRoot
, apidl
[0]);
599 pObj
= IExtractIconA_Constructor (pidl
);
603 else if (IsEqualIID (riid
, IID_IExtractIconW
) && (cidl
== 1))
605 pidl
= ILCombine (pidlRoot
, apidl
[0]);
606 pObj
= IExtractIconW_Constructor (pidl
);
610 else if (IsEqualIID (riid
, IID_IDropTarget
))
612 /* only interested in attempting to bind to shell folders, not files, semicolon intentionate */
615 hr
= this->_GetDropTarget(apidl
[0], (LPVOID
*) &pObj
);
618 else if ((IsEqualIID(riid
, IID_IShellLinkW
) ||
619 IsEqualIID(riid
, IID_IShellLinkA
)) && (cidl
== 1))
621 pidl
= ILCombine (pidlRoot
, apidl
[0]);
622 hr
= IShellLink_ConstructFromFile(NULL
, riid
, pidl
, (LPVOID
*)&pObj
);
628 if (SUCCEEDED(hr
) && !pObj
)
632 TRACE ("(%p)->hr=0x%08x\n", this, hr
);
636 /**************************************************************************
637 * CDesktopFolder::GetDisplayNameOf
640 * special case: pidl = null gives desktop-name back
642 HRESULT WINAPI
CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
647 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
653 if (!_ILIsDesktop(pidl
) && _ILIsPidlSimple(pidl
) && _ILIsSpecialFolder(pidl
))
655 return SHELL32_GetDisplayNameOfGUIDItem(this, L
"", pidl
, dwFlags
, strRet
);
658 pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
660 return E_OUTOFMEMORY
;
662 if (_ILIsDesktop (pidl
))
664 if ((GET_SHGDN_RELATION (dwFlags
) == SHGDN_NORMAL
) &&
665 (GET_SHGDN_FOR (dwFlags
) & SHGDN_FORPARSING
))
666 wcscpy(pszPath
, sPathTarget
);
668 HCR_GetClassNameW(CLSID_ShellDesktop
, pszPath
, MAX_PATH
);
670 else if (_ILIsPidlSimple (pidl
))
674 /* file system folder or file rooted at the desktop */
675 if ((GET_SHGDN_FOR(dwFlags
) == SHGDN_FORPARSING
) &&
676 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
))
678 lstrcpynW(pszPath
, sPathTarget
, MAX_PATH
- 1);
679 PathAddBackslashW(pszPath
);
680 cLen
= wcslen(pszPath
);
683 _ILSimpleGetTextW(pidl
, pszPath
+ cLen
, MAX_PATH
- cLen
);
684 if (!_ILIsFolder(pidl
))
685 SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
687 if (GetFileAttributes(pszPath
) == INVALID_FILE_ATTRIBUTES
)
689 /* file system folder or file rooted at the AllUsers desktop */
690 if ((GET_SHGDN_FOR(dwFlags
) == SHGDN_FORPARSING
) &&
691 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
))
693 SHGetSpecialFolderPathW(0, pszPath
, CSIDL_COMMON_DESKTOPDIRECTORY
, FALSE
);
694 PathAddBackslashW(pszPath
);
695 cLen
= wcslen(pszPath
);
698 _ILSimpleGetTextW(pidl
, pszPath
+ cLen
, MAX_PATH
- cLen
);
699 if (!_ILIsFolder(pidl
))
700 SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
705 /* a complex pidl, let the subfolder do the work */
706 hr
= SHELL32_GetDisplayNameOfChild (this, pidl
, dwFlags
,
712 /* Win9x always returns ANSI strings, NT always returns Unicode strings */
713 if (GetVersion() & 0x80000000)
715 strRet
->uType
= STRRET_CSTR
;
716 if (!WideCharToMultiByte(CP_ACP
, 0, pszPath
, -1, strRet
->cStr
, MAX_PATH
,
718 strRet
->cStr
[0] = '\0';
719 CoTaskMemFree(pszPath
);
723 strRet
->uType
= STRRET_WSTR
;
724 strRet
->pOleStr
= pszPath
;
728 CoTaskMemFree(pszPath
);
730 TRACE ("-- (%p)->(%s,0x%08x)\n", this,
731 strRet
->uType
== STRRET_CSTR
? strRet
->cStr
:
732 debugstr_w(strRet
->pOleStr
), hr
);
736 /**************************************************************************
737 * CDesktopFolder::SetNameOf
738 * Changes the name of a file object or subfolder, possibly changing its item
739 * identifier in the process.
742 * HWND hwndOwner, //[in ] Owner window for output
743 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
744 * LPCOLESTR lpszName, //[in ] the items new display name
745 * DWORD dwFlags, //[in ] SHGNO formatting flags
746 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
748 HRESULT WINAPI
CDesktopFolder::SetNameOf(
750 PCUITEMID_CHILD pidl
, /* simple pidl */
753 PITEMID_CHILD
*pPidlOut
)
755 CComPtr
<IShellFolder2
> psf
;
757 WCHAR szSrc
[MAX_PATH
+ 1], szDest
[MAX_PATH
+ 1];
759 BOOL bIsFolder
= _ILIsFolder (ILFindLastID (pidl
));
761 TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner
, pidl
,
762 debugstr_w (lpName
), dwFlags
, pPidlOut
);
764 if (_ILGetGUIDPointer(pidl
))
766 if (SUCCEEDED(BindToObject(pidl
, NULL
, IID_PPV_ARG(IShellFolder2
, &psf
))))
768 hr
= psf
->SetNameOf(hwndOwner
, pidl
, lpName
, dwFlags
, pPidlOut
);
773 /* build source path */
774 lstrcpynW(szSrc
, sPathTarget
, MAX_PATH
);
775 ptr
= PathAddBackslashW (szSrc
);
777 _ILSimpleGetTextW (pidl
, ptr
, MAX_PATH
+ 1 - (ptr
- szSrc
));
779 /* build destination path */
780 if (dwFlags
== SHGDN_NORMAL
|| dwFlags
& SHGDN_INFOLDER
) {
781 lstrcpynW(szDest
, sPathTarget
, MAX_PATH
);
782 ptr
= PathAddBackslashW (szDest
);
784 lstrcpynW(ptr
, lpName
, MAX_PATH
+ 1 - (ptr
- szDest
));
786 lstrcpynW(szDest
, lpName
, MAX_PATH
);
788 if(!(dwFlags
& SHGDN_FORPARSING
) && SHELL_FS_HideExtension(szSrc
)) {
789 WCHAR
*ext
= PathFindExtensionW(szSrc
);
791 INT len
= wcslen(szDest
);
792 lstrcpynW(szDest
+ len
, ext
, MAX_PATH
- len
);
796 if (!memcmp(szSrc
, szDest
, (wcslen(szDest
) + 1) * sizeof(WCHAR
)))
798 /* src and destination is the same */
801 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
806 TRACE ("src=%s dest=%s\n", debugstr_w(szSrc
), debugstr_w(szDest
));
807 if (MoveFileW (szSrc
, szDest
))
812 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
814 SHChangeNotify (bIsFolder
? SHCNE_RENAMEFOLDER
: SHCNE_RENAMEITEM
,
815 SHCNF_PATHW
, szSrc
, szDest
);
822 HRESULT WINAPI
CDesktopFolder::GetDefaultSearchGUID(GUID
*pguid
)
824 FIXME ("(%p)\n", this);
828 HRESULT WINAPI
CDesktopFolder::EnumSearches(IEnumExtraSearch
**ppenum
)
830 FIXME ("(%p)\n", this);
834 HRESULT WINAPI
CDesktopFolder::GetDefaultColumn(DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
836 TRACE ("(%p)\n", this);
846 HRESULT WINAPI
CDesktopFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
848 TRACE ("(%p)\n", this);
850 if (!pcsFlags
|| iColumn
>= DESKTOPSHELLVIEWCOLUMNS
)
853 *pcsFlags
= DesktopSFHeader
[iColumn
].pcsFlags
;
858 HRESULT WINAPI
CDesktopFolder::GetDetailsEx(
859 PCUITEMID_CHILD pidl
,
860 const SHCOLUMNID
*pscid
,
863 FIXME ("(%p)\n", this);
868 HRESULT WINAPI
CDesktopFolder::GetDetailsOf(
869 PCUITEMID_CHILD pidl
,
875 TRACE ("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
877 if (!psd
|| iColumn
>= DESKTOPSHELLVIEWCOLUMNS
)
882 psd
->fmt
= DesktopSFHeader
[iColumn
].fmt
;
883 psd
->cxChar
= DesktopSFHeader
[iColumn
].cxChar
;
884 psd
->str
.uType
= STRRET_CSTR
;
885 LoadStringA (shell32_hInstance
, DesktopSFHeader
[iColumn
].colnameid
,
886 psd
->str
.cStr
, MAX_PATH
);
890 /* the data from the pidl */
891 psd
->str
.uType
= STRRET_CSTR
;
895 hr
= GetDisplayNameOf(pidl
,
896 SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
899 _ILGetFileSize (pidl
, psd
->str
.cStr
, MAX_PATH
);
902 _ILGetFileType (pidl
, psd
->str
.cStr
, MAX_PATH
);
905 _ILGetFileDate (pidl
, psd
->str
.cStr
, MAX_PATH
);
907 case 4: /* attributes */
908 _ILGetFileAttributes (pidl
, psd
->str
.cStr
, MAX_PATH
);
915 HRESULT WINAPI
CDesktopFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
*pscid
)
917 FIXME ("(%p)\n", this);
921 HRESULT WINAPI
CDesktopFolder::GetClassID(CLSID
*lpClassId
)
923 TRACE ("(%p)\n", this);
928 *lpClassId
= CLSID_ShellDesktop
;
933 HRESULT WINAPI
CDesktopFolder::Initialize(LPCITEMIDLIST pidl
)
935 TRACE ("(%p)->(%p)\n", this, pidl
);
940 HRESULT WINAPI
CDesktopFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
942 TRACE ("(%p)->(%p)\n", this, pidl
);
944 if (!pidl
) return E_POINTER
;
945 *pidl
= ILClone (pidlRoot
);
949 HRESULT WINAPI
CDesktopFolder::GetUniqueName(LPWSTR pwszName
, UINT uLen
)
951 CComPtr
<ISFHelper
> psfHelper
;
952 HRESULT hr
= m_DesktopFSFolder
->QueryInterface(IID_PPV_ARG(ISFHelper
, &psfHelper
));
956 return psfHelper
->GetUniqueName(pwszName
, uLen
);
959 HRESULT WINAPI
CDesktopFolder::AddFolder(HWND hwnd
, LPCWSTR pwszName
, LPITEMIDLIST
*ppidlOut
)
961 CComPtr
<ISFHelper
> psfHelper
;
962 HRESULT hr
= m_DesktopFSFolder
->QueryInterface(IID_PPV_ARG(ISFHelper
, &psfHelper
));
966 return psfHelper
->AddFolder(hwnd
, pwszName
, ppidlOut
);
969 HRESULT WINAPI
CDesktopFolder::DeleteItems(UINT cidl
, LPCITEMIDLIST
*apidl
)
974 HRESULT WINAPI
CDesktopFolder::CopyItems(IShellFolder
*pSFFrom
, UINT cidl
, LPCITEMIDLIST
*apidl
, BOOL bCopy
)
976 CComPtr
<ISFHelper
> psfHelper
;
977 HRESULT hr
= m_DesktopFSFolder
->QueryInterface(IID_PPV_ARG(ISFHelper
, &psfHelper
));
981 return psfHelper
->CopyItems(pSFFrom
, cidl
, apidl
, bCopy
);
984 HRESULT WINAPI
CDesktopFolder::_GetDropTarget(LPCITEMIDLIST pidl
, LPVOID
*ppvOut
) {
987 TRACE("CFSFolder::_GetDropTarget entered\n");
989 if (_ILGetGUIDPointer (pidl
) || _ILIsFolder (pidl
))
990 return this->BindToObject(pidl
, NULL
, IID_IDropTarget
, ppvOut
);
992 LPITEMIDLIST pidlNext
= NULL
;
995 hr
= this->GetDisplayNameOf(pidl
, SHGDN_FORPARSING
, &strFile
);
998 WCHAR wszPath
[MAX_PATH
];
999 hr
= StrRetToBufW(&strFile
, pidl
, wszPath
, _countof(wszPath
));
1003 PathRemoveFileSpecW (wszPath
);
1004 hr
= this->ParseDisplayName(NULL
, NULL
, wszPath
, NULL
, &pidlNext
, NULL
);
1008 CComPtr
<IShellFolder
> psf
;
1009 hr
= this->BindToObject(pidlNext
, NULL
, IID_PPV_ARG(IShellFolder
, &psf
));
1010 CoTaskMemFree(pidlNext
);
1013 hr
= psf
->GetUIObjectOf(NULL
, 1, &pidl
, IID_IDropTarget
, NULL
, ppvOut
);
1015 ERR("FS GetUIObjectOf failed: %x\n", hr
);
1018 ERR("BindToObject failed: %x\n", hr
);
1021 ERR("ParseDisplayName failed: %x\n", hr
);
1024 ERR("StrRetToBufW failed: %x\n", hr
);
1027 ERR("GetDisplayNameOf failed: %x\n", hr
);
1032 /*************************************************************************
1033 * SHGetDesktopFolder [SHELL32.@]
1035 HRESULT WINAPI
SHGetDesktopFolder(IShellFolder
**psf
)
1037 HRESULT hres
= S_OK
;
1040 if(!psf
) return E_INVALIDARG
;
1042 hres
= CDesktopFolder::_CreatorClass::CreateInstance(NULL
, IID_PPV_ARG(IShellFolder
, psf
));
1044 TRACE("-- %p->(%p)\n",psf
, *psf
);