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_LEFT
, 15},
67 {IDS_SHV_COLUMN2
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
68 {IDS_SHV_COLUMN3
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 10},
69 {IDS_SHV_COLUMN4
, SHCOLSTATE_TYPE_DATE
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 12},
72 #define DESKTOPSHELLVIEWCOLUMNS 4
74 static const DWORD dwDesktopAttributes
=
75 SFGAO_HASSUBFOLDER
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
|
76 SFGAO_STORAGEANCESTOR
| SFGAO_HASPROPSHEET
| SFGAO_STORAGE
| SFGAO_CANLINK
;
77 static const DWORD dwMyComputerAttributes
=
78 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
79 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_CANLINK
;
80 static DWORD dwMyNetPlacesAttributes
=
81 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
82 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_CANLINK
;
85 CDesktopFolderEnum::CDesktopFolderEnum()
89 CDesktopFolderEnum::~CDesktopFolderEnum()
93 static const WCHAR ClassicStartMenuW
[] = L
"SOFTWARE\\Microsoft\\Windows\\"
94 L
"CurrentVersion\\Explorer\\HideDesktopIcons\\ClassicStartMenu";
97 IsNamespaceExtensionHidden(const WCHAR
*iid
)
99 DWORD Result
, dwResult
;
100 dwResult
= sizeof(DWORD
);
102 if (RegGetValueW(HKEY_CURRENT_USER
, /* FIXME use NewStartPanel when activated */
108 &dwResult
) != ERROR_SUCCESS
)
116 /**************************************************************************
117 * CreateDesktopEnumList()
120 HRESULT WINAPI
CDesktopFolderEnum::Initialize(CDesktopFolder
*desktopFolder
, HWND hwndOwner
, DWORD dwFlags
)
123 WCHAR szPath
[MAX_PATH
];
125 static const WCHAR MyDocumentsClassString
[] = L
"{450D8FBA-AD25-11D0-98A8-0800361B1103}";
126 static const WCHAR Desktop_NameSpaceW
[] = L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\Namespace";
128 TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags
);
130 /* enumerate the root folders */
131 if (dwFlags
& SHCONTF_FOLDERS
)
137 /* create the pidl for This item */
138 if (IsNamespaceExtensionHidden(MyDocumentsClassString
) < 1)
140 ret
= AddToEnumList(_ILCreateMyDocuments());
142 ret
= AddToEnumList(_ILCreateMyComputer());
144 for (i
= 0; i
< 2; i
++)
147 dwResult
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, Desktop_NameSpaceW
, 0, KEY_READ
, &hkey
);
149 dwResult
= RegOpenKeyExW(HKEY_CURRENT_USER
, Desktop_NameSpaceW
, 0, KEY_READ
, &hkey
);
151 if (dwResult
== ERROR_SUCCESS
)
162 size
= sizeof (iid
) / sizeof (iid
[0]);
163 r
= RegEnumKeyExW(hkey
, i
, iid
, &size
, 0, NULL
, NULL
, NULL
);
164 if (ERROR_SUCCESS
== r
)
166 if (IsNamespaceExtensionHidden(iid
) < 1)
168 pidl
= _ILCreateGuidFromStrW(iid
);
171 if (!HasItemWithCLSID(pidl
))
173 ret
= AddToEnumList(pidl
);
182 else if (ERROR_NO_MORE_ITEMS
== r
)
191 for (i
= 0; i
< 2; i
++)
194 dwResult
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, ClassicStartMenuW
, 0, KEY_READ
, &hkey
);
196 dwResult
= RegOpenKeyExW(HKEY_CURRENT_USER
, ClassicStartMenuW
, 0, KEY_READ
, &hkey
);
198 if (dwResult
== ERROR_SUCCESS
)
200 DWORD j
= 0, dwVal
, Val
, dwType
, dwIID
;
207 dwIID
= sizeof(iid
) / sizeof(WCHAR
);
209 r
= RegEnumValueW(hkey
, j
++, iid
, &dwIID
, NULL
, &dwType
, (LPBYTE
)&Val
, &dwVal
);
210 if (r
== ERROR_SUCCESS
)
212 if (Val
== 0 && dwType
== REG_DWORD
)
214 LPITEMIDLIST pidl
= _ILCreateGuidFromStrW(iid
);
217 if (!HasItemWithCLSID(pidl
))
228 else if (ERROR_NO_MORE_ITEMS
== r
)
239 /* enumerate the elements in %windir%\desktop */
240 ret
= ret
&& SHGetSpecialFolderPathW(0, szPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
241 ret
= ret
&& CreateFolderEnumList(szPath
, dwFlags
);
243 ret
= ret
&& SHGetSpecialFolderPathW(0, szPath
, CSIDL_COMMON_DESKTOPDIRECTORY
, FALSE
);
244 ret
= ret
&& CreateFolderEnumList(szPath
, dwFlags
);
246 return ret
? S_OK
: E_FAIL
;
249 CDesktopFolder::CDesktopFolder() :
255 CDesktopFolder::~CDesktopFolder()
259 HRESULT WINAPI
CDesktopFolder::FinalConstruct()
261 WCHAR szMyPath
[MAX_PATH
];
263 CComPtr
<IPersistFolder3
> ppf3
;
265 /* Create the root pidl */
266 pidlRoot
= _ILCreateDesktop();
268 /* Create the inner fs folder */
269 hr
= SHCoCreateInstance(NULL
, &CLSID_ShellFSFolder
, NULL
, IID_PPV_ARG(IShellFolder
, &m_DesktopFSFolder
));
273 hr
= m_DesktopFSFolder
->QueryInterface(IID_PPV_ARG(IPersistFolder3
, &ppf3
));
277 PERSIST_FOLDER_TARGET_INFO info
;
278 ZeroMemory(&info
, sizeof(PERSIST_FOLDER_TARGET_INFO
));
279 info
.csidl
= CSIDL_DESKTOPDIRECTORY
;
280 hr
= ppf3
->InitializeEx(NULL
, pidlRoot
, &info
);
282 /* Create the inner shared fs folder */
283 hr
= SHCoCreateInstance(NULL
, &CLSID_ShellFSFolder
, NULL
, IID_PPV_ARG(IShellFolder
, &m_SharedDesktopFSFolder
));
287 hr
= m_SharedDesktopFSFolder
->QueryInterface(IID_PPV_ARG(IPersistFolder3
, &ppf3
));
291 info
.csidl
= CSIDL_COMMON_DESKTOPDIRECTORY
;
292 hr
= ppf3
->InitializeEx(NULL
, pidlRoot
, &info
);
294 if (!SHGetSpecialFolderPathW( 0, szMyPath
, CSIDL_DESKTOPDIRECTORY
, TRUE
))
297 sPathTarget
= (LPWSTR
)SHAlloc((wcslen(szMyPath
) + 1) * sizeof(WCHAR
));
298 wcscpy(sPathTarget
, szMyPath
);
302 /**************************************************************************
303 * CDesktopFolder::ParseDisplayName
306 * "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
309 HRESULT WINAPI
CDesktopFolder::ParseDisplayName(
312 LPOLESTR lpszDisplayName
,
314 PIDLIST_RELATIVE
*ppidl
,
315 DWORD
*pdwAttributes
)
317 LPCWSTR szNext
= NULL
;
318 LPITEMIDLIST pidlTemp
= NULL
;
322 TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
323 this, hwndOwner
, pbc
, lpszDisplayName
, debugstr_w(lpszDisplayName
),
324 pchEaten
, ppidl
, pdwAttributes
);
331 if (!lpszDisplayName
)
335 *pchEaten
= 0; /* strange but like the original */
337 urldata
.cbSize
= sizeof(urldata
);
339 if (lpszDisplayName
[0] == ':' && lpszDisplayName
[1] == ':')
341 return SH_ParseGuidDisplayName(this, hwndOwner
, pbc
, lpszDisplayName
, pchEaten
, ppidl
, pdwAttributes
);
343 else if (PathGetDriveNumberW (lpszDisplayName
) >= 0)
345 /* it's a filesystem path with a drive. Let MyComputer/UnixDosFolder parse it */
346 pidlTemp
= _ILCreateMyComputer ();
347 szNext
= lpszDisplayName
;
349 else if (PathIsUNCW(lpszDisplayName
))
351 pidlTemp
= _ILCreateNetwork();
352 szNext
= lpszDisplayName
;
354 else if( (pidlTemp
= SHELL32_CreatePidlFromBindCtx(pbc
, lpszDisplayName
)) )
359 else if (SUCCEEDED(ParseURLW(lpszDisplayName
, &urldata
)))
361 if (urldata
.nScheme
== URL_SCHEME_SHELL
) /* handle shell: urls */
363 TRACE ("-- shell url: %s\n", debugstr_w(urldata
.pszSuffix
));
364 pidlTemp
= _ILCreateGuidFromStrW(urldata
.pszSuffix
+ 2);
367 return IEParseDisplayNameWithBCW(CP_ACP
, lpszDisplayName
, pbc
, ppidl
);
371 if (*lpszDisplayName
)
373 /* it's a filesystem path on the desktop. Let a FSFolder parse it */
374 hr
= m_DesktopFSFolder
->ParseDisplayName(hwndOwner
, pbc
, lpszDisplayName
, pchEaten
, ppidl
, pdwAttributes
);
378 return m_SharedDesktopFSFolder
->ParseDisplayName(hwndOwner
, pbc
, lpszDisplayName
, pchEaten
, ppidl
, pdwAttributes
);
381 pidlTemp
= _ILCreateMyComputer();
386 if (SUCCEEDED(hr
) && pidlTemp
)
388 if (szNext
&& *szNext
)
390 hr
= SHELL32_ParseNextElement(this, hwndOwner
, pbc
,
391 &pidlTemp
, (LPOLESTR
) szNext
, pchEaten
, pdwAttributes
);
395 if (pdwAttributes
&& *pdwAttributes
)
397 if (_ILIsMyComputer(pidlTemp
))
398 *pdwAttributes
&= dwMyComputerAttributes
;
399 else if (_ILIsNetHood(pidlTemp
))
400 *pdwAttributes
&= dwMyNetPlacesAttributes
;
401 else if (_ILIsSpecialFolder(pidlTemp
))
402 SHELL32_GetGuidItemAttributes(this, pidlTemp
, pdwAttributes
);
403 else if(_ILIsFolder(pidlTemp
) || _ILIsValue(pidlTemp
))
404 SHELL32_GetFSItemAttributes(this, pidlTemp
, pdwAttributes
);
414 TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr
);
419 /**************************************************************************
420 * CDesktopFolder::EnumObjects
422 HRESULT WINAPI
CDesktopFolder::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
*ppEnumIDList
)
424 return ShellObjectCreatorInit
<CDesktopFolderEnum
>(this, hwndOwner
, dwFlags
, IID_IEnumIDList
, ppEnumIDList
);
427 /**************************************************************************
428 * CDesktopFolder::BindToObject
430 HRESULT WINAPI
CDesktopFolder::BindToObject(
431 PCUIDLIST_RELATIVE pidl
,
436 TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n",
437 this, pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
439 if (_ILIsSpecialFolder(pidl
))
440 return SHELL32_BindToGuidItem(pidlRoot
, pidl
, pbcReserved
, riid
, ppvOut
);
442 return m_DesktopFSFolder
->BindToObject(pidl
, pbcReserved
, riid
, ppvOut
);
445 /**************************************************************************
446 * CDesktopFolder::BindToStorage
448 HRESULT WINAPI
CDesktopFolder::BindToStorage(
449 PCUIDLIST_RELATIVE pidl
,
454 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
455 this, pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
461 /**************************************************************************
462 * CDesktopFolder::CompareIDs
464 HRESULT WINAPI
CDesktopFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
466 bool bIsDesktopFolder1
, bIsDesktopFolder2
;
468 if (!pidl1
|| !pidl2
)
470 ERR("Got null pidl pointer (%Ix %p %p)!\n", lParam
, pidl1
, pidl2
);
474 bIsDesktopFolder1
= _ILIsDesktop(pidl1
);
475 bIsDesktopFolder2
= _ILIsDesktop(pidl2
);
476 if (bIsDesktopFolder1
|| bIsDesktopFolder2
)
477 return MAKE_COMPARE_HRESULT(bIsDesktopFolder1
- bIsDesktopFolder2
);
479 if (_ILIsSpecialFolder(pidl1
) || _ILIsSpecialFolder(pidl2
))
480 return SHELL32_CompareGuidItems(this, lParam
, pidl1
, pidl2
);
482 return m_DesktopFSFolder
->CompareIDs(lParam
, pidl1
, pidl2
);
485 /**************************************************************************
486 * CDesktopFolder::CreateViewObject
488 HRESULT WINAPI
CDesktopFolder::CreateViewObject(
493 CComPtr
<IShellView
> pShellView
;
494 HRESULT hr
= E_INVALIDARG
;
496 TRACE ("(%p)->(hwnd=%p,%s,%p)\n",
497 this, hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
504 if (IsEqualIID (riid
, IID_IDropTarget
))
506 hr
= m_DesktopFSFolder
->CreateViewObject(hwndOwner
, riid
, ppvOut
);
508 else if (IsEqualIID (riid
, IID_IContextMenu
))
510 WARN ("IContextMenu not implemented\n");
513 else if (IsEqualIID (riid
, IID_IShellView
))
515 hr
= IShellView_Constructor((IShellFolder
*)this, &pShellView
);
517 hr
= pShellView
->QueryInterface(riid
, ppvOut
);
519 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
523 /**************************************************************************
524 * CDesktopFolder::GetAttributesOf
526 HRESULT WINAPI
CDesktopFolder::GetAttributesOf(
528 PCUITEMID_CHILD_ARRAY apidl
,
533 TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
534 this, cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
543 *rgfInOut
&= dwDesktopAttributes
;
546 /* TODO: always add SFGAO_CANLINK */
547 for (UINT i
= 0; i
< cidl
; ++i
)
550 if (_ILIsDesktop(*apidl
))
551 *rgfInOut
&= dwDesktopAttributes
;
552 else if (_ILIsMyComputer(apidl
[i
]))
553 *rgfInOut
&= dwMyComputerAttributes
;
554 else if (_ILIsNetHood(apidl
[i
]))
555 *rgfInOut
&= dwMyNetPlacesAttributes
;
556 else if (_ILIsSpecialFolder(apidl
[i
]))
557 SHELL32_GetGuidItemAttributes(this, apidl
[i
], rgfInOut
);
558 else if(_ILIsFolder(apidl
[i
]) || _ILIsValue(apidl
[i
]))
559 SHELL32_GetFSItemAttributes(this, apidl
[i
], rgfInOut
);
561 ERR("Got an unknown pidl type!!!\n");
564 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
565 *rgfInOut
&= ~SFGAO_VALIDATE
;
567 TRACE("-- result=0x%08x\n", *rgfInOut
);
572 /**************************************************************************
573 * CDesktopFolder::GetUIObjectOf
576 * HWND hwndOwner, //[in ] Parent window for any output
577 * UINT cidl, //[in ] array size
578 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
579 * REFIID riid, //[in ] Requested Interface
580 * UINT* prgfInOut, //[ ] reserved
581 * LPVOID* ppvObject) //[out] Resulting Interface
584 HRESULT WINAPI
CDesktopFolder::GetUIObjectOf(
587 PCUITEMID_CHILD_ARRAY apidl
,
594 HRESULT hr
= E_INVALIDARG
;
596 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
597 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
604 if (IsEqualIID (riid
, IID_IContextMenu
))
606 hr
= CDefFolderMenu_Create2(pidlRoot
, hwndOwner
, cidl
, apidl
, (IShellFolder
*)this, NULL
, 0, NULL
, (IContextMenu
**)&pObj
);
608 else if (IsEqualIID (riid
, IID_IDataObject
) && (cidl
>= 1))
610 hr
= IDataObject_Constructor( hwndOwner
, pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
612 else if ((IsEqualIID (riid
, IID_IExtractIconA
) || IsEqualIID (riid
, IID_IExtractIconW
)) && (cidl
== 1))
614 hr
= GenericExtractIcon_CreateInstance(this, apidl
[0], riid
, &pObj
);
616 else if (IsEqualIID (riid
, IID_IDropTarget
))
618 /* only interested in attempting to bind to shell folders, not files, semicolon intentionate */
621 hr
= this->_GetDropTarget(apidl
[0], (LPVOID
*) &pObj
);
624 else if ((IsEqualIID(riid
, IID_IShellLinkW
) ||
625 IsEqualIID(riid
, IID_IShellLinkA
)) && (cidl
== 1))
627 pidl
= ILCombine (pidlRoot
, apidl
[0]);
628 hr
= IShellLink_ConstructFromFile(NULL
, riid
, pidl
, (LPVOID
*)&pObj
);
634 if (SUCCEEDED(hr
) && !pObj
)
638 TRACE ("(%p)->hr=0x%08x\n", this, hr
);
642 /**************************************************************************
643 * CDesktopFolder::GetDisplayNameOf
646 * special case: pidl = null gives desktop-name back
648 HRESULT WINAPI
CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
653 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
659 if (!_ILIsPidlSimple (pidl
))
661 return SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
, strRet
);
663 else if (!_ILIsDesktop(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
);
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
);
716 /* Win9x always returns ANSI strings, NT always returns Unicode strings */
717 if (GetVersion() & 0x80000000)
719 strRet
->uType
= STRRET_CSTR
;
720 if (!WideCharToMultiByte(CP_ACP
, 0, pszPath
, -1, strRet
->cStr
, MAX_PATH
,
722 strRet
->cStr
[0] = '\0';
723 CoTaskMemFree(pszPath
);
727 strRet
->uType
= STRRET_WSTR
;
728 strRet
->pOleStr
= pszPath
;
732 CoTaskMemFree(pszPath
);
734 TRACE ("-- (%p)->(%s,0x%08x)\n", this,
735 strRet
->uType
== STRRET_CSTR
? strRet
->cStr
:
736 debugstr_w(strRet
->pOleStr
), hr
);
740 /**************************************************************************
741 * CDesktopFolder::SetNameOf
742 * Changes the name of a file object or subfolder, possibly changing its item
743 * identifier in the process.
746 * HWND hwndOwner, //[in ] Owner window for output
747 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
748 * LPCOLESTR lpszName, //[in ] the items new display name
749 * DWORD dwFlags, //[in ] SHGNO formatting flags
750 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
752 HRESULT WINAPI
CDesktopFolder::SetNameOf(
754 PCUITEMID_CHILD pidl
, /* simple pidl */
757 PITEMID_CHILD
*pPidlOut
)
759 CComPtr
<IShellFolder2
> psf
;
761 WCHAR szSrc
[MAX_PATH
+ 1], szDest
[MAX_PATH
+ 1];
763 BOOL bIsFolder
= _ILIsFolder (ILFindLastID (pidl
));
765 TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner
, pidl
,
766 debugstr_w (lpName
), dwFlags
, pPidlOut
);
768 if (_ILGetGUIDPointer(pidl
))
769 return SHELL32_SetNameOfGuidItem(pidl
, lpName
, dwFlags
, pPidlOut
);
771 /* build source path */
772 lstrcpynW(szSrc
, sPathTarget
, MAX_PATH
);
773 ptr
= PathAddBackslashW (szSrc
);
775 _ILSimpleGetTextW (pidl
, ptr
, MAX_PATH
+ 1 - (ptr
- szSrc
));
777 /* build destination path */
778 if (dwFlags
== SHGDN_NORMAL
|| dwFlags
& SHGDN_INFOLDER
) {
779 lstrcpynW(szDest
, sPathTarget
, MAX_PATH
);
780 ptr
= PathAddBackslashW (szDest
);
782 lstrcpynW(ptr
, lpName
, MAX_PATH
+ 1 - (ptr
- szDest
));
784 lstrcpynW(szDest
, lpName
, MAX_PATH
);
786 if(!(dwFlags
& SHGDN_FORPARSING
) && SHELL_FS_HideExtension(szSrc
)) {
787 WCHAR
*ext
= PathFindExtensionW(szSrc
);
789 INT len
= wcslen(szDest
);
790 lstrcpynW(szDest
+ len
, ext
, MAX_PATH
- len
);
794 if (!memcmp(szSrc
, szDest
, (wcslen(szDest
) + 1) * sizeof(WCHAR
)))
796 /* src and destination is the same */
799 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
804 TRACE ("src=%s dest=%s\n", debugstr_w(szSrc
), debugstr_w(szDest
));
805 if (MoveFileW (szSrc
, szDest
))
810 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
812 SHChangeNotify (bIsFolder
? SHCNE_RENAMEFOLDER
: SHCNE_RENAMEITEM
,
813 SHCNF_PATHW
, szSrc
, szDest
);
820 HRESULT WINAPI
CDesktopFolder::GetDefaultSearchGUID(GUID
*pguid
)
822 FIXME ("(%p)\n", this);
826 HRESULT WINAPI
CDesktopFolder::EnumSearches(IEnumExtraSearch
**ppenum
)
828 FIXME ("(%p)\n", this);
832 HRESULT WINAPI
CDesktopFolder::GetDefaultColumn(DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
834 TRACE ("(%p)\n", this);
844 HRESULT WINAPI
CDesktopFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
846 TRACE ("(%p)\n", this);
848 if (!pcsFlags
|| iColumn
>= DESKTOPSHELLVIEWCOLUMNS
)
851 *pcsFlags
= DesktopSFHeader
[iColumn
].pcsFlags
;
856 HRESULT WINAPI
CDesktopFolder::GetDetailsEx(
857 PCUITEMID_CHILD pidl
,
858 const SHCOLUMNID
*pscid
,
861 FIXME ("(%p)\n", this);
866 HRESULT WINAPI
CDesktopFolder::GetDetailsOf(
867 PCUITEMID_CHILD pidl
,
873 TRACE ("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
875 if (!psd
|| iColumn
>= DESKTOPSHELLVIEWCOLUMNS
)
880 psd
->fmt
= DesktopSFHeader
[iColumn
].fmt
;
881 psd
->cxChar
= DesktopSFHeader
[iColumn
].cxChar
;
882 return SHSetStrRet(&psd
->str
, DesktopSFHeader
[iColumn
].colnameid
);
884 else if (_ILIsSpecialFolder(pidl
))
886 return SHELL32_GetDetailsOfGuidItem(this, pidl
, iColumn
, psd
);
889 /* the data from the pidl */
890 psd
->str
.uType
= STRRET_CSTR
;
894 hr
= GetDisplayNameOf(pidl
,
895 SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
898 _ILGetFileSize (pidl
, psd
->str
.cStr
, MAX_PATH
);
901 _ILGetFileType (pidl
, psd
->str
.cStr
, MAX_PATH
);
904 _ILGetFileDate (pidl
, psd
->str
.cStr
, MAX_PATH
);
906 case 4: /* attributes */
907 _ILGetFileAttributes (pidl
, psd
->str
.cStr
, MAX_PATH
);
914 HRESULT WINAPI
CDesktopFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
*pscid
)
916 FIXME ("(%p)\n", this);
920 HRESULT WINAPI
CDesktopFolder::GetClassID(CLSID
*lpClassId
)
922 TRACE ("(%p)\n", this);
927 *lpClassId
= CLSID_ShellDesktop
;
932 HRESULT WINAPI
CDesktopFolder::Initialize(LPCITEMIDLIST pidl
)
934 TRACE ("(%p)->(%p)\n", this, pidl
);
939 HRESULT WINAPI
CDesktopFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
941 TRACE ("(%p)->(%p)\n", this, pidl
);
943 if (!pidl
) return E_POINTER
;
944 *pidl
= ILClone (pidlRoot
);
948 HRESULT WINAPI
CDesktopFolder::_GetDropTarget(LPCITEMIDLIST pidl
, LPVOID
*ppvOut
) {
951 TRACE("CFSFolder::_GetDropTarget entered\n");
953 if (_ILGetGUIDPointer (pidl
) || _ILIsFolder (pidl
))
954 return this->BindToObject(pidl
, NULL
, IID_IDropTarget
, ppvOut
);
956 LPITEMIDLIST pidlNext
= NULL
;
959 hr
= this->GetDisplayNameOf(pidl
, SHGDN_FORPARSING
, &strFile
);
962 WCHAR wszPath
[MAX_PATH
];
963 hr
= StrRetToBufW(&strFile
, pidl
, wszPath
, _countof(wszPath
));
967 PathRemoveFileSpecW (wszPath
);
968 hr
= this->ParseDisplayName(NULL
, NULL
, wszPath
, NULL
, &pidlNext
, NULL
);
972 CComPtr
<IShellFolder
> psf
;
973 hr
= this->BindToObject(pidlNext
, NULL
, IID_PPV_ARG(IShellFolder
, &psf
));
974 CoTaskMemFree(pidlNext
);
977 hr
= psf
->GetUIObjectOf(NULL
, 1, &pidl
, IID_IDropTarget
, NULL
, ppvOut
);
979 ERR("FS GetUIObjectOf failed: %x\n", hr
);
982 ERR("BindToObject failed: %x\n", hr
);
985 ERR("ParseDisplayName failed: %x\n", hr
);
988 ERR("StrRetToBufW failed: %x\n", hr
);
991 ERR("GetDisplayNameOf failed: %x\n", hr
);
996 /*************************************************************************
997 * SHGetDesktopFolder [SHELL32.@]
999 HRESULT WINAPI
SHGetDesktopFolder(IShellFolder
**psf
)
1001 HRESULT hres
= S_OK
;
1004 if(!psf
) return E_INVALIDARG
;
1006 hres
= CDesktopFolder::_CreatorClass::CreateInstance(NULL
, IID_PPV_ARG(IShellFolder
, psf
));
1008 TRACE("-- %p->(%p)\n",psf
, *psf
);