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 if (_ILIsSpecialFolder(pidl
))
450 return SHELL32_BindToGuidItem(pidlRoot
, pidl
, pbcReserved
, riid
, ppvOut
);
452 return SHELL32_BindToFS( pidlRoot
, sPathTarget
, pidl
, riid
, ppvOut
);
455 /**************************************************************************
456 * CDesktopFolder::BindToStorage
458 HRESULT WINAPI
CDesktopFolder::BindToStorage(
459 PCUIDLIST_RELATIVE pidl
,
464 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
465 this, pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
471 /**************************************************************************
472 * CDesktopFolder::CompareIDs
474 HRESULT WINAPI
CDesktopFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
476 if (_ILIsSpecialFolder(pidl1
) || _ILIsSpecialFolder(pidl2
))
477 return SHELL32_CompareIDs ((IShellFolder
*)this, lParam
, pidl1
, pidl2
);
479 return m_DesktopFSFolder
->CompareIDs(lParam
, pidl1
, pidl2
);
482 /**************************************************************************
483 * CDesktopFolder::CreateViewObject
485 HRESULT WINAPI
CDesktopFolder::CreateViewObject(
490 CComPtr
<IShellView
> pShellView
;
491 HRESULT hr
= E_INVALIDARG
;
493 TRACE ("(%p)->(hwnd=%p,%s,%p)\n",
494 this, hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
501 if (IsEqualIID (riid
, IID_IDropTarget
))
503 hr
= m_DesktopFSFolder
->CreateViewObject(hwndOwner
, riid
, ppvOut
);
505 else if (IsEqualIID (riid
, IID_IContextMenu
))
507 WARN ("IContextMenu not implemented\n");
510 else if (IsEqualIID (riid
, IID_IShellView
))
512 hr
= IShellView_Constructor((IShellFolder
*)this, &pShellView
);
514 hr
= pShellView
->QueryInterface(riid
, ppvOut
);
516 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
520 /**************************************************************************
521 * CDesktopFolder::GetAttributesOf
523 HRESULT WINAPI
CDesktopFolder::GetAttributesOf(
525 PCUITEMID_CHILD_ARRAY apidl
,
530 TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
531 this, cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
540 *rgfInOut
&= dwDesktopAttributes
;
543 /* TODO: always add SFGAO_CANLINK */
544 for (UINT i
= 0; i
< cidl
; ++i
)
547 if (_ILIsDesktop(*apidl
))
548 *rgfInOut
&= dwDesktopAttributes
;
549 else if (_ILIsMyComputer(apidl
[i
]))
550 *rgfInOut
&= dwMyComputerAttributes
;
551 else if (_ILIsNetHood(apidl
[i
]))
552 *rgfInOut
&= dwMyNetPlacesAttributes
;
553 else if (_ILIsSpecialFolder(apidl
[i
]))
554 SHELL32_GetGuidItemAttributes(this, apidl
[i
], rgfInOut
);
555 else if(_ILIsFolder(apidl
[i
]) || _ILIsValue(apidl
[i
]))
556 SHELL32_GetFSItemAttributes(this, apidl
[i
], rgfInOut
);
558 ERR("Got an unknown pidl type!!!\n");
561 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
562 *rgfInOut
&= ~SFGAO_VALIDATE
;
564 TRACE("-- result=0x%08x\n", *rgfInOut
);
569 /**************************************************************************
570 * CDesktopFolder::GetUIObjectOf
573 * HWND hwndOwner, //[in ] Parent window for any output
574 * UINT cidl, //[in ] array size
575 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
576 * REFIID riid, //[in ] Requested Interface
577 * UINT* prgfInOut, //[ ] reserved
578 * LPVOID* ppvObject) //[out] Resulting Interface
581 HRESULT WINAPI
CDesktopFolder::GetUIObjectOf(
584 PCUITEMID_CHILD_ARRAY apidl
,
590 IUnknown
*pObj
= NULL
;
591 HRESULT hr
= E_INVALIDARG
;
593 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
594 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
601 if (IsEqualIID (riid
, IID_IContextMenu
))
603 hr
= CDefFolderMenu_Create2(pidlRoot
, hwndOwner
, cidl
, apidl
, (IShellFolder
*)this, NULL
, 0, NULL
, (IContextMenu
**)&pObj
);
605 else if (IsEqualIID (riid
, IID_IDataObject
) && (cidl
>= 1))
607 hr
= IDataObject_Constructor( hwndOwner
, pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
609 else if (IsEqualIID (riid
, IID_IExtractIconA
) && (cidl
== 1))
611 pidl
= ILCombine (pidlRoot
, apidl
[0]);
612 pObj
= IExtractIconA_Constructor (pidl
);
616 else if (IsEqualIID (riid
, IID_IExtractIconW
) && (cidl
== 1))
618 pidl
= ILCombine (pidlRoot
, apidl
[0]);
619 pObj
= IExtractIconW_Constructor (pidl
);
623 else if (IsEqualIID (riid
, IID_IDropTarget
))
625 /* only interested in attempting to bind to shell folders, not files, semicolon intentionate */
628 hr
= this->_GetDropTarget(apidl
[0], (LPVOID
*) &pObj
);
631 else if ((IsEqualIID(riid
, IID_IShellLinkW
) ||
632 IsEqualIID(riid
, IID_IShellLinkA
)) && (cidl
== 1))
634 pidl
= ILCombine (pidlRoot
, apidl
[0]);
635 hr
= IShellLink_ConstructFromFile(NULL
, riid
, pidl
, (LPVOID
*)&pObj
);
641 if (SUCCEEDED(hr
) && !pObj
)
645 TRACE ("(%p)->hr=0x%08x\n", this, hr
);
649 /**************************************************************************
650 * CDesktopFolder::GetDisplayNameOf
653 * special case: pidl = null gives desktop-name back
655 HRESULT WINAPI
CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
660 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
666 if (!_ILIsPidlSimple (pidl
))
668 return SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
, strRet
);
670 else if (!_ILIsDesktop(pidl
) && _ILIsSpecialFolder(pidl
))
672 return SHELL32_GetDisplayNameOfGUIDItem(this, L
"", pidl
, dwFlags
, strRet
);
675 pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
677 return E_OUTOFMEMORY
;
679 if (_ILIsDesktop (pidl
))
681 if ((GET_SHGDN_RELATION (dwFlags
) == SHGDN_NORMAL
) &&
682 (GET_SHGDN_FOR (dwFlags
) & SHGDN_FORPARSING
))
683 wcscpy(pszPath
, sPathTarget
);
685 HCR_GetClassNameW(CLSID_ShellDesktop
, pszPath
, MAX_PATH
);
691 /* file system folder or file rooted at the desktop */
692 if ((GET_SHGDN_FOR(dwFlags
) == SHGDN_FORPARSING
) &&
693 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
))
695 lstrcpynW(pszPath
, sPathTarget
, MAX_PATH
- 1);
696 PathAddBackslashW(pszPath
);
697 cLen
= wcslen(pszPath
);
700 _ILSimpleGetTextW(pidl
, pszPath
+ cLen
, MAX_PATH
- cLen
);
701 if (!_ILIsFolder(pidl
))
702 SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
704 if (GetFileAttributes(pszPath
) == INVALID_FILE_ATTRIBUTES
)
706 /* file system folder or file rooted at the AllUsers desktop */
707 if ((GET_SHGDN_FOR(dwFlags
) == SHGDN_FORPARSING
) &&
708 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
))
710 SHGetSpecialFolderPathW(0, pszPath
, CSIDL_COMMON_DESKTOPDIRECTORY
, FALSE
);
711 PathAddBackslashW(pszPath
);
712 cLen
= wcslen(pszPath
);
715 _ILSimpleGetTextW(pidl
, pszPath
+ cLen
, MAX_PATH
- cLen
);
716 if (!_ILIsFolder(pidl
))
717 SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
723 /* Win9x always returns ANSI strings, NT always returns Unicode strings */
724 if (GetVersion() & 0x80000000)
726 strRet
->uType
= STRRET_CSTR
;
727 if (!WideCharToMultiByte(CP_ACP
, 0, pszPath
, -1, strRet
->cStr
, MAX_PATH
,
729 strRet
->cStr
[0] = '\0';
730 CoTaskMemFree(pszPath
);
734 strRet
->uType
= STRRET_WSTR
;
735 strRet
->pOleStr
= pszPath
;
739 CoTaskMemFree(pszPath
);
741 TRACE ("-- (%p)->(%s,0x%08x)\n", this,
742 strRet
->uType
== STRRET_CSTR
? strRet
->cStr
:
743 debugstr_w(strRet
->pOleStr
), hr
);
747 /**************************************************************************
748 * CDesktopFolder::SetNameOf
749 * Changes the name of a file object or subfolder, possibly changing its item
750 * identifier in the process.
753 * HWND hwndOwner, //[in ] Owner window for output
754 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
755 * LPCOLESTR lpszName, //[in ] the items new display name
756 * DWORD dwFlags, //[in ] SHGNO formatting flags
757 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
759 HRESULT WINAPI
CDesktopFolder::SetNameOf(
761 PCUITEMID_CHILD pidl
, /* simple pidl */
764 PITEMID_CHILD
*pPidlOut
)
766 CComPtr
<IShellFolder2
> psf
;
768 WCHAR szSrc
[MAX_PATH
+ 1], szDest
[MAX_PATH
+ 1];
770 BOOL bIsFolder
= _ILIsFolder (ILFindLastID (pidl
));
772 TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner
, pidl
,
773 debugstr_w (lpName
), dwFlags
, pPidlOut
);
775 if (_ILGetGUIDPointer(pidl
))
777 if (SUCCEEDED(BindToObject(pidl
, NULL
, IID_PPV_ARG(IShellFolder2
, &psf
))))
779 hr
= psf
->SetNameOf(hwndOwner
, pidl
, lpName
, dwFlags
, pPidlOut
);
784 /* build source path */
785 lstrcpynW(szSrc
, sPathTarget
, MAX_PATH
);
786 ptr
= PathAddBackslashW (szSrc
);
788 _ILSimpleGetTextW (pidl
, ptr
, MAX_PATH
+ 1 - (ptr
- szSrc
));
790 /* build destination path */
791 if (dwFlags
== SHGDN_NORMAL
|| dwFlags
& SHGDN_INFOLDER
) {
792 lstrcpynW(szDest
, sPathTarget
, MAX_PATH
);
793 ptr
= PathAddBackslashW (szDest
);
795 lstrcpynW(ptr
, lpName
, MAX_PATH
+ 1 - (ptr
- szDest
));
797 lstrcpynW(szDest
, lpName
, MAX_PATH
);
799 if(!(dwFlags
& SHGDN_FORPARSING
) && SHELL_FS_HideExtension(szSrc
)) {
800 WCHAR
*ext
= PathFindExtensionW(szSrc
);
802 INT len
= wcslen(szDest
);
803 lstrcpynW(szDest
+ len
, ext
, MAX_PATH
- len
);
807 if (!memcmp(szSrc
, szDest
, (wcslen(szDest
) + 1) * sizeof(WCHAR
)))
809 /* src and destination is the same */
812 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
817 TRACE ("src=%s dest=%s\n", debugstr_w(szSrc
), debugstr_w(szDest
));
818 if (MoveFileW (szSrc
, szDest
))
823 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
825 SHChangeNotify (bIsFolder
? SHCNE_RENAMEFOLDER
: SHCNE_RENAMEITEM
,
826 SHCNF_PATHW
, szSrc
, szDest
);
833 HRESULT WINAPI
CDesktopFolder::GetDefaultSearchGUID(GUID
*pguid
)
835 FIXME ("(%p)\n", this);
839 HRESULT WINAPI
CDesktopFolder::EnumSearches(IEnumExtraSearch
**ppenum
)
841 FIXME ("(%p)\n", this);
845 HRESULT WINAPI
CDesktopFolder::GetDefaultColumn(DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
847 TRACE ("(%p)\n", this);
857 HRESULT WINAPI
CDesktopFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
859 TRACE ("(%p)\n", this);
861 if (!pcsFlags
|| iColumn
>= DESKTOPSHELLVIEWCOLUMNS
)
864 *pcsFlags
= DesktopSFHeader
[iColumn
].pcsFlags
;
869 HRESULT WINAPI
CDesktopFolder::GetDetailsEx(
870 PCUITEMID_CHILD pidl
,
871 const SHCOLUMNID
*pscid
,
874 FIXME ("(%p)\n", this);
879 HRESULT WINAPI
CDesktopFolder::GetDetailsOf(
880 PCUITEMID_CHILD pidl
,
886 TRACE ("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
888 if (!psd
|| iColumn
>= DESKTOPSHELLVIEWCOLUMNS
)
893 psd
->fmt
= DesktopSFHeader
[iColumn
].fmt
;
894 psd
->cxChar
= DesktopSFHeader
[iColumn
].cxChar
;
895 psd
->str
.uType
= STRRET_CSTR
;
896 LoadStringA (shell32_hInstance
, DesktopSFHeader
[iColumn
].colnameid
,
897 psd
->str
.cStr
, MAX_PATH
);
901 /* the data from the pidl */
902 psd
->str
.uType
= STRRET_CSTR
;
906 hr
= GetDisplayNameOf(pidl
,
907 SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
910 _ILGetFileSize (pidl
, psd
->str
.cStr
, MAX_PATH
);
913 _ILGetFileType (pidl
, psd
->str
.cStr
, MAX_PATH
);
916 _ILGetFileDate (pidl
, psd
->str
.cStr
, MAX_PATH
);
918 case 4: /* attributes */
919 _ILGetFileAttributes (pidl
, psd
->str
.cStr
, MAX_PATH
);
926 HRESULT WINAPI
CDesktopFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
*pscid
)
928 FIXME ("(%p)\n", this);
932 HRESULT WINAPI
CDesktopFolder::GetClassID(CLSID
*lpClassId
)
934 TRACE ("(%p)\n", this);
939 *lpClassId
= CLSID_ShellDesktop
;
944 HRESULT WINAPI
CDesktopFolder::Initialize(LPCITEMIDLIST pidl
)
946 TRACE ("(%p)->(%p)\n", this, pidl
);
951 HRESULT WINAPI
CDesktopFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
953 TRACE ("(%p)->(%p)\n", this, pidl
);
955 if (!pidl
) return E_POINTER
;
956 *pidl
= ILClone (pidlRoot
);
960 HRESULT WINAPI
CDesktopFolder::GetUniqueName(LPWSTR pwszName
, UINT uLen
)
962 CComPtr
<ISFHelper
> psfHelper
;
963 HRESULT hr
= m_DesktopFSFolder
->QueryInterface(IID_PPV_ARG(ISFHelper
, &psfHelper
));
967 return psfHelper
->GetUniqueName(pwszName
, uLen
);
970 HRESULT WINAPI
CDesktopFolder::AddFolder(HWND hwnd
, LPCWSTR pwszName
, LPITEMIDLIST
*ppidlOut
)
972 CComPtr
<ISFHelper
> psfHelper
;
973 HRESULT hr
= m_DesktopFSFolder
->QueryInterface(IID_PPV_ARG(ISFHelper
, &psfHelper
));
977 return psfHelper
->AddFolder(hwnd
, pwszName
, ppidlOut
);
980 HRESULT WINAPI
CDesktopFolder::DeleteItems(UINT cidl
, LPCITEMIDLIST
*apidl
)
985 HRESULT WINAPI
CDesktopFolder::CopyItems(IShellFolder
*pSFFrom
, UINT cidl
, LPCITEMIDLIST
*apidl
, BOOL bCopy
)
987 CComPtr
<ISFHelper
> psfHelper
;
988 HRESULT hr
= m_DesktopFSFolder
->QueryInterface(IID_PPV_ARG(ISFHelper
, &psfHelper
));
992 return psfHelper
->CopyItems(pSFFrom
, cidl
, apidl
, bCopy
);
995 HRESULT WINAPI
CDesktopFolder::_GetDropTarget(LPCITEMIDLIST pidl
, LPVOID
*ppvOut
) {
998 TRACE("CFSFolder::_GetDropTarget entered\n");
1000 if (_ILGetGUIDPointer (pidl
) || _ILIsFolder (pidl
))
1001 return this->BindToObject(pidl
, NULL
, IID_IDropTarget
, ppvOut
);
1003 LPITEMIDLIST pidlNext
= NULL
;
1006 hr
= this->GetDisplayNameOf(pidl
, SHGDN_FORPARSING
, &strFile
);
1009 WCHAR wszPath
[MAX_PATH
];
1010 hr
= StrRetToBufW(&strFile
, pidl
, wszPath
, _countof(wszPath
));
1014 PathRemoveFileSpecW (wszPath
);
1015 hr
= this->ParseDisplayName(NULL
, NULL
, wszPath
, NULL
, &pidlNext
, NULL
);
1019 CComPtr
<IShellFolder
> psf
;
1020 hr
= this->BindToObject(pidlNext
, NULL
, IID_PPV_ARG(IShellFolder
, &psf
));
1021 CoTaskMemFree(pidlNext
);
1024 hr
= psf
->GetUIObjectOf(NULL
, 1, &pidl
, IID_IDropTarget
, NULL
, ppvOut
);
1026 ERR("FS GetUIObjectOf failed: %x\n", hr
);
1029 ERR("BindToObject failed: %x\n", hr
);
1032 ERR("ParseDisplayName failed: %x\n", hr
);
1035 ERR("StrRetToBufW failed: %x\n", hr
);
1038 ERR("GetDisplayNameOf failed: %x\n", hr
);
1043 /*************************************************************************
1044 * SHGetDesktopFolder [SHELL32.@]
1046 HRESULT WINAPI
SHGetDesktopFolder(IShellFolder
**psf
)
1048 HRESULT hres
= S_OK
;
1051 if(!psf
) return E_INVALIDARG
;
1053 hres
= CDesktopFolder::_CreatorClass::CreateInstance(NULL
, IID_PPV_ARG(IShellFolder
, psf
));
1055 TRACE("-- %p->(%p)\n",psf
, *psf
);