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 static const DWORD dwDesktopAttributes
=
76 SFGAO_HASSUBFOLDER
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
|
77 SFGAO_STORAGEANCESTOR
| SFGAO_HASPROPSHEET
| SFGAO_STORAGE
| SFGAO_CANLINK
;
78 static const DWORD dwMyComputerAttributes
=
79 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
80 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_CANLINK
;
81 static DWORD dwMyNetPlacesAttributes
=
82 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
83 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_CANLINK
;
86 CDesktopFolderEnum::CDesktopFolderEnum()
90 CDesktopFolderEnum::~CDesktopFolderEnum()
94 static const WCHAR ClassicStartMenuW
[] = L
"SOFTWARE\\Microsoft\\Windows\\"
95 L
"CurrentVersion\\Explorer\\HideDesktopIcons\\ClassicStartMenu";
98 IsNamespaceExtensionHidden(const WCHAR
*iid
)
100 DWORD Result
, dwResult
;
101 dwResult
= sizeof(DWORD
);
103 if (RegGetValueW(HKEY_CURRENT_USER
, /* FIXME use NewStartPanel when activated */
109 &dwResult
) != ERROR_SUCCESS
)
117 /**************************************************************************
118 * CreateDesktopEnumList()
121 HRESULT WINAPI
CDesktopFolderEnum::Initialize(CDesktopFolder
*desktopFolder
, HWND hwndOwner
, DWORD dwFlags
)
124 WCHAR szPath
[MAX_PATH
];
126 static const WCHAR MyDocumentsClassString
[] = L
"{450D8FBA-AD25-11D0-98A8-0800361B1103}";
127 static const WCHAR Desktop_NameSpaceW
[] = L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\Namespace";
129 TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags
);
131 /* enumerate the root folders */
132 if (dwFlags
& SHCONTF_FOLDERS
)
138 /* create the pidl for This item */
139 if (IsNamespaceExtensionHidden(MyDocumentsClassString
) < 1)
141 ret
= AddToEnumList(_ILCreateMyDocuments());
143 ret
= AddToEnumList(_ILCreateMyComputer());
145 for (i
= 0; i
< 2; i
++)
148 dwResult
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, Desktop_NameSpaceW
, 0, KEY_READ
, &hkey
);
150 dwResult
= RegOpenKeyExW(HKEY_CURRENT_USER
, Desktop_NameSpaceW
, 0, KEY_READ
, &hkey
);
152 if (dwResult
== ERROR_SUCCESS
)
163 size
= sizeof (iid
) / sizeof (iid
[0]);
164 r
= RegEnumKeyExW(hkey
, i
, iid
, &size
, 0, NULL
, NULL
, NULL
);
165 if (ERROR_SUCCESS
== r
)
167 if (IsNamespaceExtensionHidden(iid
) < 1)
169 pidl
= _ILCreateGuidFromStrW(iid
);
172 if (!HasItemWithCLSID(pidl
))
174 ret
= AddToEnumList(pidl
);
183 else if (ERROR_NO_MORE_ITEMS
== r
)
192 for (i
= 0; i
< 2; i
++)
195 dwResult
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, ClassicStartMenuW
, 0, KEY_READ
, &hkey
);
197 dwResult
= RegOpenKeyExW(HKEY_CURRENT_USER
, ClassicStartMenuW
, 0, KEY_READ
, &hkey
);
199 if (dwResult
== ERROR_SUCCESS
)
201 DWORD j
= 0, dwVal
, Val
, dwType
, dwIID
;
208 dwIID
= sizeof(iid
) / sizeof(WCHAR
);
210 r
= RegEnumValueW(hkey
, j
++, iid
, &dwIID
, NULL
, &dwType
, (LPBYTE
)&Val
, &dwVal
);
211 if (r
== ERROR_SUCCESS
)
213 if (Val
== 0 && dwType
== REG_DWORD
)
215 LPITEMIDLIST pidl
= _ILCreateGuidFromStrW(iid
);
218 if (!HasItemWithCLSID(pidl
))
229 else if (ERROR_NO_MORE_ITEMS
== r
)
240 /* enumerate the elements in %windir%\desktop */
241 ret
= ret
&& SHGetSpecialFolderPathW(0, szPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
242 ret
= ret
&& CreateFolderEnumList(szPath
, dwFlags
);
244 ret
= ret
&& SHGetSpecialFolderPathW(0, szPath
, CSIDL_COMMON_DESKTOPDIRECTORY
, FALSE
);
245 ret
= ret
&& CreateFolderEnumList(szPath
, dwFlags
);
247 return ret
? S_OK
: E_FAIL
;
250 CDesktopFolder::CDesktopFolder() :
256 CDesktopFolder::~CDesktopFolder()
260 HRESULT WINAPI
CDesktopFolder::FinalConstruct()
262 WCHAR szMyPath
[MAX_PATH
];
264 CComPtr
<IPersistFolder3
> ppf3
;
266 /* Create the root pidl */
267 pidlRoot
= _ILCreateDesktop();
269 /* Create the inner fs folder */
270 hr
= SHCoCreateInstance(NULL
, &CLSID_ShellFSFolder
, NULL
, IID_PPV_ARG(IShellFolder
, &m_DesktopFSFolder
));
274 hr
= m_DesktopFSFolder
->QueryInterface(IID_PPV_ARG(IPersistFolder3
, &ppf3
));
278 PERSIST_FOLDER_TARGET_INFO info
;
279 ZeroMemory(&info
, sizeof(PERSIST_FOLDER_TARGET_INFO
));
280 info
.csidl
= CSIDL_DESKTOPDIRECTORY
;
281 hr
= ppf3
->InitializeEx(NULL
, pidlRoot
, &info
);
283 /* Create the inner shared fs folder */
284 hr
= SHCoCreateInstance(NULL
, &CLSID_ShellFSFolder
, NULL
, IID_PPV_ARG(IShellFolder
, &m_SharedDesktopFSFolder
));
288 hr
= m_SharedDesktopFSFolder
->QueryInterface(IID_PPV_ARG(IPersistFolder3
, &ppf3
));
292 info
.csidl
= CSIDL_COMMON_DESKTOPDIRECTORY
;
293 hr
= ppf3
->InitializeEx(NULL
, pidlRoot
, &info
);
295 if (!SHGetSpecialFolderPathW( 0, szMyPath
, CSIDL_DESKTOPDIRECTORY
, TRUE
))
298 sPathTarget
= (LPWSTR
)SHAlloc((wcslen(szMyPath
) + 1) * sizeof(WCHAR
));
299 wcscpy(sPathTarget
, szMyPath
);
303 /**************************************************************************
304 * CDesktopFolder::ParseDisplayName
307 * "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
310 HRESULT WINAPI
CDesktopFolder::ParseDisplayName(
313 LPOLESTR lpszDisplayName
,
315 PIDLIST_RELATIVE
*ppidl
,
316 DWORD
*pdwAttributes
)
318 WCHAR szElement
[MAX_PATH
];
319 LPCWSTR szNext
= NULL
;
320 LPITEMIDLIST pidlTemp
= NULL
;
325 TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
326 this, hwndOwner
, pbc
, lpszDisplayName
, debugstr_w(lpszDisplayName
),
327 pchEaten
, ppidl
, pdwAttributes
);
332 if (!lpszDisplayName
)
341 *pchEaten
= 0; /* strange but like the original */
343 urldata
.cbSize
= sizeof(urldata
);
345 if (lpszDisplayName
[0] == ':' && lpszDisplayName
[1] == ':')
347 szNext
= GetNextElementW (lpszDisplayName
, szElement
, MAX_PATH
);
348 TRACE ("-- element: %s\n", debugstr_w (szElement
));
349 CLSIDFromString (szElement
+ 2, &clsid
);
350 pidlTemp
= _ILCreateGuid (PT_GUID
, clsid
);
352 else if (PathGetDriveNumberW (lpszDisplayName
) >= 0)
354 /* it's a filesystem path with a drive. Let MyComputer/UnixDosFolder parse it */
355 pidlTemp
= _ILCreateMyComputer ();
356 szNext
= lpszDisplayName
;
358 else if (PathIsUNCW(lpszDisplayName
))
360 pidlTemp
= _ILCreateNetwork();
361 szNext
= lpszDisplayName
;
363 else if( (pidlTemp
= SHELL32_CreatePidlFromBindCtx(pbc
, lpszDisplayName
)) )
368 else if (SUCCEEDED(ParseURLW(lpszDisplayName
, &urldata
)))
370 if (urldata
.nScheme
== URL_SCHEME_SHELL
) /* handle shell: urls */
372 TRACE ("-- shell url: %s\n", debugstr_w(urldata
.pszSuffix
));
373 SHCLSIDFromStringW (urldata
.pszSuffix
+ 2, &clsid
);
374 pidlTemp
= _ILCreateGuid (PT_GUID
, clsid
);
377 return IEParseDisplayNameWithBCW(CP_ACP
, lpszDisplayName
, pbc
, ppidl
);
381 if (*lpszDisplayName
)
383 /* it's a filesystem path on the desktop. Let a FSFolder parse it */
384 hr
= m_DesktopFSFolder
->ParseDisplayName(hwndOwner
, pbc
, lpszDisplayName
, pchEaten
, ppidl
, pdwAttributes
);
388 return m_SharedDesktopFSFolder
->ParseDisplayName(hwndOwner
, pbc
, lpszDisplayName
, pchEaten
, ppidl
, pdwAttributes
);
391 pidlTemp
= _ILCreateMyComputer();
396 if (SUCCEEDED(hr
) && pidlTemp
)
398 if (szNext
&& *szNext
)
400 hr
= SHELL32_ParseNextElement(this, hwndOwner
, pbc
,
401 &pidlTemp
, (LPOLESTR
) szNext
, pchEaten
, pdwAttributes
);
405 if (pdwAttributes
&& *pdwAttributes
)
407 if (_ILIsMyComputer(pidlTemp
))
408 *pdwAttributes
&= dwMyComputerAttributes
;
409 else if (_ILIsNetHood(pidlTemp
))
410 *pdwAttributes
&= dwMyNetPlacesAttributes
;
411 else if (_ILIsSpecialFolder(pidlTemp
))
412 SHELL32_GetGuidItemAttributes(this, pidlTemp
, pdwAttributes
);
413 else if(_ILIsFolder(pidlTemp
) || _ILIsValue(pidlTemp
))
414 SHELL32_GetFSItemAttributes(this, pidlTemp
, pdwAttributes
);
424 TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr
);
429 /**************************************************************************
430 * CDesktopFolder::EnumObjects
432 HRESULT WINAPI
CDesktopFolder::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
*ppEnumIDList
)
434 return ShellObjectCreatorInit
<CDesktopFolderEnum
>(this, hwndOwner
, dwFlags
, IID_IEnumIDList
, ppEnumIDList
);
437 /**************************************************************************
438 * CDesktopFolder::BindToObject
440 HRESULT WINAPI
CDesktopFolder::BindToObject(
441 PCUIDLIST_RELATIVE pidl
,
446 TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n",
447 this, pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
449 return SHELL32_BindToChild( pidlRoot
, sPathTarget
, pidl
, riid
, ppvOut
);
452 /**************************************************************************
453 * CDesktopFolder::BindToStorage
455 HRESULT WINAPI
CDesktopFolder::BindToStorage(
456 PCUIDLIST_RELATIVE pidl
,
461 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
462 this, pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
468 /**************************************************************************
469 * CDesktopFolder::CompareIDs
471 HRESULT WINAPI
CDesktopFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
473 if (_ILIsSpecialFolder(pidl1
) || _ILIsSpecialFolder(pidl2
))
474 return SHELL32_CompareIDs ((IShellFolder
*)this, lParam
, pidl1
, pidl2
);
476 return m_DesktopFSFolder
->CompareIDs(lParam
, pidl1
, pidl2
);
479 /**************************************************************************
480 * CDesktopFolder::CreateViewObject
482 HRESULT WINAPI
CDesktopFolder::CreateViewObject(
487 CComPtr
<IShellView
> pShellView
;
488 HRESULT hr
= E_INVALIDARG
;
490 TRACE ("(%p)->(hwnd=%p,%s,%p)\n",
491 this, hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
498 if (IsEqualIID (riid
, IID_IDropTarget
))
500 hr
= m_DesktopFSFolder
->CreateViewObject(hwndOwner
, riid
, ppvOut
);
502 else if (IsEqualIID (riid
, IID_IContextMenu
))
504 WARN ("IContextMenu not implemented\n");
507 else if (IsEqualIID (riid
, IID_IShellView
))
509 hr
= IShellView_Constructor((IShellFolder
*)this, &pShellView
);
511 hr
= pShellView
->QueryInterface(riid
, ppvOut
);
513 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
517 /**************************************************************************
518 * CDesktopFolder::GetAttributesOf
520 HRESULT WINAPI
CDesktopFolder::GetAttributesOf(
522 PCUITEMID_CHILD_ARRAY apidl
,
527 TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
528 this, cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
537 *rgfInOut
&= dwDesktopAttributes
;
540 /* TODO: always add SFGAO_CANLINK */
541 for (UINT i
= 0; i
< cidl
; ++i
)
544 if (_ILIsDesktop(*apidl
))
545 *rgfInOut
&= dwDesktopAttributes
;
546 else if (_ILIsMyComputer(apidl
[i
]))
547 *rgfInOut
&= dwMyComputerAttributes
;
548 else if (_ILIsNetHood(apidl
[i
]))
549 *rgfInOut
&= dwMyNetPlacesAttributes
;
550 else if (_ILIsSpecialFolder(apidl
[i
]))
551 SHELL32_GetGuidItemAttributes(this, apidl
[i
], rgfInOut
);
552 else if(_ILIsFolder(apidl
[i
]) || _ILIsValue(apidl
[i
]))
553 SHELL32_GetFSItemAttributes(this, apidl
[i
], rgfInOut
);
555 ERR("Got an unknown pidl type!!!\n");
558 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
559 *rgfInOut
&= ~SFGAO_VALIDATE
;
561 TRACE("-- result=0x%08x\n", *rgfInOut
);
566 /**************************************************************************
567 * CDesktopFolder::GetUIObjectOf
570 * HWND hwndOwner, //[in ] Parent window for any output
571 * UINT cidl, //[in ] array size
572 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
573 * REFIID riid, //[in ] Requested Interface
574 * UINT* prgfInOut, //[ ] reserved
575 * LPVOID* ppvObject) //[out] Resulting Interface
578 HRESULT WINAPI
CDesktopFolder::GetUIObjectOf(
581 PCUITEMID_CHILD_ARRAY apidl
,
587 IUnknown
*pObj
= NULL
;
588 HRESULT hr
= E_INVALIDARG
;
590 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
591 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
598 if (IsEqualIID (riid
, IID_IContextMenu
))
600 hr
= CDefFolderMenu_Create2(pidlRoot
, hwndOwner
, cidl
, apidl
, (IShellFolder
*)this, NULL
, 0, NULL
, (IContextMenu
**)&pObj
);
602 else if (IsEqualIID (riid
, IID_IDataObject
) && (cidl
>= 1))
604 hr
= IDataObject_Constructor( hwndOwner
, pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
606 else if (IsEqualIID (riid
, IID_IExtractIconA
) && (cidl
== 1))
608 pidl
= ILCombine (pidlRoot
, apidl
[0]);
609 pObj
= IExtractIconA_Constructor (pidl
);
613 else if (IsEqualIID (riid
, IID_IExtractIconW
) && (cidl
== 1))
615 pidl
= ILCombine (pidlRoot
, apidl
[0]);
616 pObj
= IExtractIconW_Constructor (pidl
);
620 else if (IsEqualIID (riid
, IID_IDropTarget
))
622 /* only interested in attempting to bind to shell folders, not files, semicolon intentionate */
625 hr
= this->_GetDropTarget(apidl
[0], (LPVOID
*) &pObj
);
628 else if ((IsEqualIID(riid
, IID_IShellLinkW
) ||
629 IsEqualIID(riid
, IID_IShellLinkA
)) && (cidl
== 1))
631 pidl
= ILCombine (pidlRoot
, apidl
[0]);
632 hr
= IShellLink_ConstructFromFile(NULL
, riid
, pidl
, (LPVOID
*)&pObj
);
638 if (SUCCEEDED(hr
) && !pObj
)
642 TRACE ("(%p)->hr=0x%08x\n", this, hr
);
646 /**************************************************************************
647 * CDesktopFolder::GetDisplayNameOf
650 * special case: pidl = null gives desktop-name back
652 HRESULT WINAPI
CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
657 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
663 if (!_ILIsDesktop(pidl
) && _ILIsPidlSimple(pidl
) && _ILIsSpecialFolder(pidl
))
665 return SHELL32_GetDisplayNameOfGUIDItem(this, L
"", pidl
, dwFlags
, strRet
);
668 pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
670 return E_OUTOFMEMORY
;
672 if (_ILIsDesktop (pidl
))
674 if ((GET_SHGDN_RELATION (dwFlags
) == SHGDN_NORMAL
) &&
675 (GET_SHGDN_FOR (dwFlags
) & SHGDN_FORPARSING
))
676 wcscpy(pszPath
, sPathTarget
);
678 HCR_GetClassNameW(CLSID_ShellDesktop
, pszPath
, MAX_PATH
);
680 else if (_ILIsPidlSimple (pidl
))
684 /* file system folder or file rooted at the desktop */
685 if ((GET_SHGDN_FOR(dwFlags
) == SHGDN_FORPARSING
) &&
686 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
))
688 lstrcpynW(pszPath
, sPathTarget
, MAX_PATH
- 1);
689 PathAddBackslashW(pszPath
);
690 cLen
= wcslen(pszPath
);
693 _ILSimpleGetTextW(pidl
, pszPath
+ cLen
, MAX_PATH
- cLen
);
694 if (!_ILIsFolder(pidl
))
695 SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
697 if (GetFileAttributes(pszPath
) == INVALID_FILE_ATTRIBUTES
)
699 /* file system folder or file rooted at the AllUsers desktop */
700 if ((GET_SHGDN_FOR(dwFlags
) == SHGDN_FORPARSING
) &&
701 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
))
703 SHGetSpecialFolderPathW(0, pszPath
, CSIDL_COMMON_DESKTOPDIRECTORY
, FALSE
);
704 PathAddBackslashW(pszPath
);
705 cLen
= wcslen(pszPath
);
708 _ILSimpleGetTextW(pidl
, pszPath
+ cLen
, MAX_PATH
- cLen
);
709 if (!_ILIsFolder(pidl
))
710 SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
715 /* a complex pidl, let the subfolder do the work */
716 hr
= SHELL32_GetDisplayNameOfChild (this, pidl
, dwFlags
,
722 /* Win9x always returns ANSI strings, NT always returns Unicode strings */
723 if (GetVersion() & 0x80000000)
725 strRet
->uType
= STRRET_CSTR
;
726 if (!WideCharToMultiByte(CP_ACP
, 0, pszPath
, -1, strRet
->cStr
, MAX_PATH
,
728 strRet
->cStr
[0] = '\0';
729 CoTaskMemFree(pszPath
);
733 strRet
->uType
= STRRET_WSTR
;
734 strRet
->pOleStr
= pszPath
;
738 CoTaskMemFree(pszPath
);
740 TRACE ("-- (%p)->(%s,0x%08x)\n", this,
741 strRet
->uType
== STRRET_CSTR
? strRet
->cStr
:
742 debugstr_w(strRet
->pOleStr
), hr
);
746 /**************************************************************************
747 * CDesktopFolder::SetNameOf
748 * Changes the name of a file object or subfolder, possibly changing its item
749 * identifier in the process.
752 * HWND hwndOwner, //[in ] Owner window for output
753 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
754 * LPCOLESTR lpszName, //[in ] the items new display name
755 * DWORD dwFlags, //[in ] SHGNO formatting flags
756 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
758 HRESULT WINAPI
CDesktopFolder::SetNameOf(
760 PCUITEMID_CHILD pidl
, /* simple pidl */
763 PITEMID_CHILD
*pPidlOut
)
765 CComPtr
<IShellFolder2
> psf
;
767 WCHAR szSrc
[MAX_PATH
+ 1], szDest
[MAX_PATH
+ 1];
769 BOOL bIsFolder
= _ILIsFolder (ILFindLastID (pidl
));
771 TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner
, pidl
,
772 debugstr_w (lpName
), dwFlags
, pPidlOut
);
774 if (_ILGetGUIDPointer(pidl
))
776 if (SUCCEEDED(BindToObject(pidl
, NULL
, IID_PPV_ARG(IShellFolder2
, &psf
))))
778 hr
= psf
->SetNameOf(hwndOwner
, pidl
, lpName
, dwFlags
, pPidlOut
);
783 /* build source path */
784 lstrcpynW(szSrc
, sPathTarget
, MAX_PATH
);
785 ptr
= PathAddBackslashW (szSrc
);
787 _ILSimpleGetTextW (pidl
, ptr
, MAX_PATH
+ 1 - (ptr
- szSrc
));
789 /* build destination path */
790 if (dwFlags
== SHGDN_NORMAL
|| dwFlags
& SHGDN_INFOLDER
) {
791 lstrcpynW(szDest
, sPathTarget
, MAX_PATH
);
792 ptr
= PathAddBackslashW (szDest
);
794 lstrcpynW(ptr
, lpName
, MAX_PATH
+ 1 - (ptr
- szDest
));
796 lstrcpynW(szDest
, lpName
, MAX_PATH
);
798 if(!(dwFlags
& SHGDN_FORPARSING
) && SHELL_FS_HideExtension(szSrc
)) {
799 WCHAR
*ext
= PathFindExtensionW(szSrc
);
801 INT len
= wcslen(szDest
);
802 lstrcpynW(szDest
+ len
, ext
, MAX_PATH
- len
);
806 if (!memcmp(szSrc
, szDest
, (wcslen(szDest
) + 1) * sizeof(WCHAR
)))
808 /* src and destination is the same */
811 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
816 TRACE ("src=%s dest=%s\n", debugstr_w(szSrc
), debugstr_w(szDest
));
817 if (MoveFileW (szSrc
, szDest
))
822 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
824 SHChangeNotify (bIsFolder
? SHCNE_RENAMEFOLDER
: SHCNE_RENAMEITEM
,
825 SHCNF_PATHW
, szSrc
, szDest
);
832 HRESULT WINAPI
CDesktopFolder::GetDefaultSearchGUID(GUID
*pguid
)
834 FIXME ("(%p)\n", this);
838 HRESULT WINAPI
CDesktopFolder::EnumSearches(IEnumExtraSearch
**ppenum
)
840 FIXME ("(%p)\n", this);
844 HRESULT WINAPI
CDesktopFolder::GetDefaultColumn(DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
846 TRACE ("(%p)\n", this);
856 HRESULT WINAPI
CDesktopFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
858 TRACE ("(%p)\n", this);
860 if (!pcsFlags
|| iColumn
>= DESKTOPSHELLVIEWCOLUMNS
)
863 *pcsFlags
= DesktopSFHeader
[iColumn
].pcsFlags
;
868 HRESULT WINAPI
CDesktopFolder::GetDetailsEx(
869 PCUITEMID_CHILD pidl
,
870 const SHCOLUMNID
*pscid
,
873 FIXME ("(%p)\n", this);
878 HRESULT WINAPI
CDesktopFolder::GetDetailsOf(
879 PCUITEMID_CHILD pidl
,
885 TRACE ("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
887 if (!psd
|| iColumn
>= DESKTOPSHELLVIEWCOLUMNS
)
892 psd
->fmt
= DesktopSFHeader
[iColumn
].fmt
;
893 psd
->cxChar
= DesktopSFHeader
[iColumn
].cxChar
;
894 psd
->str
.uType
= STRRET_CSTR
;
895 LoadStringA (shell32_hInstance
, DesktopSFHeader
[iColumn
].colnameid
,
896 psd
->str
.cStr
, MAX_PATH
);
900 /* the data from the pidl */
901 psd
->str
.uType
= STRRET_CSTR
;
905 hr
= GetDisplayNameOf(pidl
,
906 SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
909 _ILGetFileSize (pidl
, psd
->str
.cStr
, MAX_PATH
);
912 _ILGetFileType (pidl
, psd
->str
.cStr
, MAX_PATH
);
915 _ILGetFileDate (pidl
, psd
->str
.cStr
, MAX_PATH
);
917 case 4: /* attributes */
918 _ILGetFileAttributes (pidl
, psd
->str
.cStr
, MAX_PATH
);
925 HRESULT WINAPI
CDesktopFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
*pscid
)
927 FIXME ("(%p)\n", this);
931 HRESULT WINAPI
CDesktopFolder::GetClassID(CLSID
*lpClassId
)
933 TRACE ("(%p)\n", this);
938 *lpClassId
= CLSID_ShellDesktop
;
943 HRESULT WINAPI
CDesktopFolder::Initialize(LPCITEMIDLIST pidl
)
945 TRACE ("(%p)->(%p)\n", this, pidl
);
950 HRESULT WINAPI
CDesktopFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
952 TRACE ("(%p)->(%p)\n", this, pidl
);
954 if (!pidl
) return E_POINTER
;
955 *pidl
= ILClone (pidlRoot
);
959 HRESULT WINAPI
CDesktopFolder::GetUniqueName(LPWSTR pwszName
, UINT uLen
)
961 CComPtr
<ISFHelper
> psfHelper
;
962 HRESULT hr
= m_DesktopFSFolder
->QueryInterface(IID_PPV_ARG(ISFHelper
, &psfHelper
));
966 return psfHelper
->GetUniqueName(pwszName
, uLen
);
969 HRESULT WINAPI
CDesktopFolder::AddFolder(HWND hwnd
, LPCWSTR pwszName
, LPITEMIDLIST
*ppidlOut
)
971 CComPtr
<ISFHelper
> psfHelper
;
972 HRESULT hr
= m_DesktopFSFolder
->QueryInterface(IID_PPV_ARG(ISFHelper
, &psfHelper
));
976 return psfHelper
->AddFolder(hwnd
, pwszName
, ppidlOut
);
979 HRESULT WINAPI
CDesktopFolder::DeleteItems(UINT cidl
, LPCITEMIDLIST
*apidl
)
984 HRESULT WINAPI
CDesktopFolder::CopyItems(IShellFolder
*pSFFrom
, UINT cidl
, LPCITEMIDLIST
*apidl
, BOOL bCopy
)
986 CComPtr
<ISFHelper
> psfHelper
;
987 HRESULT hr
= m_DesktopFSFolder
->QueryInterface(IID_PPV_ARG(ISFHelper
, &psfHelper
));
991 return psfHelper
->CopyItems(pSFFrom
, cidl
, apidl
, bCopy
);
994 HRESULT WINAPI
CDesktopFolder::_GetDropTarget(LPCITEMIDLIST pidl
, LPVOID
*ppvOut
) {
997 TRACE("CFSFolder::_GetDropTarget entered\n");
999 if (_ILGetGUIDPointer (pidl
) || _ILIsFolder (pidl
))
1000 return this->BindToObject(pidl
, NULL
, IID_IDropTarget
, ppvOut
);
1002 LPITEMIDLIST pidlNext
= NULL
;
1005 hr
= this->GetDisplayNameOf(pidl
, SHGDN_FORPARSING
, &strFile
);
1008 WCHAR wszPath
[MAX_PATH
];
1009 hr
= StrRetToBufW(&strFile
, pidl
, wszPath
, _countof(wszPath
));
1013 PathRemoveFileSpecW (wszPath
);
1014 hr
= this->ParseDisplayName(NULL
, NULL
, wszPath
, NULL
, &pidlNext
, NULL
);
1018 CComPtr
<IShellFolder
> psf
;
1019 hr
= this->BindToObject(pidlNext
, NULL
, IID_PPV_ARG(IShellFolder
, &psf
));
1020 CoTaskMemFree(pidlNext
);
1023 hr
= psf
->GetUIObjectOf(NULL
, 1, &pidl
, IID_IDropTarget
, NULL
, ppvOut
);
1025 ERR("FS GetUIObjectOf failed: %x\n", hr
);
1028 ERR("BindToObject failed: %x\n", hr
);
1031 ERR("ParseDisplayName failed: %x\n", hr
);
1034 ERR("StrRetToBufW failed: %x\n", hr
);
1037 ERR("GetDisplayNameOf failed: %x\n", hr
);
1042 /*************************************************************************
1043 * SHGetDesktopFolder [SHELL32.@]
1045 HRESULT WINAPI
SHGetDesktopFolder(IShellFolder
**psf
)
1047 HRESULT hres
= S_OK
;
1050 if(!psf
) return E_INVALIDARG
;
1052 hres
= CDesktopFolder::_CreatorClass::CreateInstance(NULL
, IID_PPV_ARG(IShellFolder
, psf
));
1054 TRACE("-- %p->(%p)\n",psf
, *psf
);