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 if (_ILIsSpecialFolder(pidl1
) || _ILIsSpecialFolder(pidl2
))
467 return SHELL32_CompareGuidItems(this, lParam
, pidl1
, pidl2
);
469 return m_DesktopFSFolder
->CompareIDs(lParam
, pidl1
, pidl2
);
472 /**************************************************************************
473 * CDesktopFolder::CreateViewObject
475 HRESULT WINAPI
CDesktopFolder::CreateViewObject(
480 CComPtr
<IShellView
> pShellView
;
481 HRESULT hr
= E_INVALIDARG
;
483 TRACE ("(%p)->(hwnd=%p,%s,%p)\n",
484 this, hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
491 if (IsEqualIID (riid
, IID_IDropTarget
))
493 hr
= m_DesktopFSFolder
->CreateViewObject(hwndOwner
, riid
, ppvOut
);
495 else if (IsEqualIID (riid
, IID_IContextMenu
))
497 WARN ("IContextMenu not implemented\n");
500 else if (IsEqualIID (riid
, IID_IShellView
))
502 hr
= IShellView_Constructor((IShellFolder
*)this, &pShellView
);
504 hr
= pShellView
->QueryInterface(riid
, ppvOut
);
506 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
510 /**************************************************************************
511 * CDesktopFolder::GetAttributesOf
513 HRESULT WINAPI
CDesktopFolder::GetAttributesOf(
515 PCUITEMID_CHILD_ARRAY apidl
,
520 TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
521 this, cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
530 *rgfInOut
&= dwDesktopAttributes
;
533 /* TODO: always add SFGAO_CANLINK */
534 for (UINT i
= 0; i
< cidl
; ++i
)
537 if (_ILIsDesktop(*apidl
))
538 *rgfInOut
&= dwDesktopAttributes
;
539 else if (_ILIsMyComputer(apidl
[i
]))
540 *rgfInOut
&= dwMyComputerAttributes
;
541 else if (_ILIsNetHood(apidl
[i
]))
542 *rgfInOut
&= dwMyNetPlacesAttributes
;
543 else if (_ILIsSpecialFolder(apidl
[i
]))
544 SHELL32_GetGuidItemAttributes(this, apidl
[i
], rgfInOut
);
545 else if(_ILIsFolder(apidl
[i
]) || _ILIsValue(apidl
[i
]))
546 SHELL32_GetFSItemAttributes(this, apidl
[i
], rgfInOut
);
548 ERR("Got an unknown pidl type!!!\n");
551 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
552 *rgfInOut
&= ~SFGAO_VALIDATE
;
554 TRACE("-- result=0x%08x\n", *rgfInOut
);
559 /**************************************************************************
560 * CDesktopFolder::GetUIObjectOf
563 * HWND hwndOwner, //[in ] Parent window for any output
564 * UINT cidl, //[in ] array size
565 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
566 * REFIID riid, //[in ] Requested Interface
567 * UINT* prgfInOut, //[ ] reserved
568 * LPVOID* ppvObject) //[out] Resulting Interface
571 HRESULT WINAPI
CDesktopFolder::GetUIObjectOf(
574 PCUITEMID_CHILD_ARRAY apidl
,
580 IUnknown
*pObj
= NULL
;
581 HRESULT hr
= E_INVALIDARG
;
583 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
584 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
591 if (IsEqualIID (riid
, IID_IContextMenu
))
593 hr
= CDefFolderMenu_Create2(pidlRoot
, hwndOwner
, cidl
, apidl
, (IShellFolder
*)this, NULL
, 0, NULL
, (IContextMenu
**)&pObj
);
595 else if (IsEqualIID (riid
, IID_IDataObject
) && (cidl
>= 1))
597 hr
= IDataObject_Constructor( hwndOwner
, pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
599 else if (IsEqualIID (riid
, IID_IExtractIconA
) && (cidl
== 1))
601 pidl
= ILCombine (pidlRoot
, apidl
[0]);
602 pObj
= IExtractIconA_Constructor (pidl
);
606 else if (IsEqualIID (riid
, IID_IExtractIconW
) && (cidl
== 1))
608 pidl
= ILCombine (pidlRoot
, apidl
[0]);
609 pObj
= IExtractIconW_Constructor (pidl
);
613 else if (IsEqualIID (riid
, IID_IDropTarget
))
615 /* only interested in attempting to bind to shell folders, not files, semicolon intentionate */
618 hr
= this->_GetDropTarget(apidl
[0], (LPVOID
*) &pObj
);
621 else if ((IsEqualIID(riid
, IID_IShellLinkW
) ||
622 IsEqualIID(riid
, IID_IShellLinkA
)) && (cidl
== 1))
624 pidl
= ILCombine (pidlRoot
, apidl
[0]);
625 hr
= IShellLink_ConstructFromFile(NULL
, riid
, pidl
, (LPVOID
*)&pObj
);
631 if (SUCCEEDED(hr
) && !pObj
)
635 TRACE ("(%p)->hr=0x%08x\n", this, hr
);
639 /**************************************************************************
640 * CDesktopFolder::GetDisplayNameOf
643 * special case: pidl = null gives desktop-name back
645 HRESULT WINAPI
CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
650 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
656 if (!_ILIsPidlSimple (pidl
))
658 return SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
, strRet
);
660 else if (!_ILIsDesktop(pidl
) && _ILIsSpecialFolder(pidl
))
662 return SHELL32_GetDisplayNameOfGUIDItem(this, L
"", pidl
, dwFlags
, strRet
);
665 pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
667 return E_OUTOFMEMORY
;
669 if (_ILIsDesktop (pidl
))
671 if ((GET_SHGDN_RELATION (dwFlags
) == SHGDN_NORMAL
) &&
672 (GET_SHGDN_FOR (dwFlags
) & SHGDN_FORPARSING
))
673 wcscpy(pszPath
, sPathTarget
);
675 HCR_GetClassNameW(CLSID_ShellDesktop
, pszPath
, MAX_PATH
);
681 /* file system folder or file rooted at the desktop */
682 if ((GET_SHGDN_FOR(dwFlags
) == SHGDN_FORPARSING
) &&
683 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
))
685 lstrcpynW(pszPath
, sPathTarget
, MAX_PATH
- 1);
686 PathAddBackslashW(pszPath
);
687 cLen
= wcslen(pszPath
);
690 _ILSimpleGetTextW(pidl
, pszPath
+ cLen
, MAX_PATH
- cLen
);
691 if (!_ILIsFolder(pidl
))
692 SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
694 if (GetFileAttributes(pszPath
) == INVALID_FILE_ATTRIBUTES
)
696 /* file system folder or file rooted at the AllUsers desktop */
697 if ((GET_SHGDN_FOR(dwFlags
) == SHGDN_FORPARSING
) &&
698 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
))
700 SHGetSpecialFolderPathW(0, pszPath
, CSIDL_COMMON_DESKTOPDIRECTORY
, FALSE
);
701 PathAddBackslashW(pszPath
);
702 cLen
= wcslen(pszPath
);
705 _ILSimpleGetTextW(pidl
, pszPath
+ cLen
, MAX_PATH
- cLen
);
706 if (!_ILIsFolder(pidl
))
707 SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
713 /* Win9x always returns ANSI strings, NT always returns Unicode strings */
714 if (GetVersion() & 0x80000000)
716 strRet
->uType
= STRRET_CSTR
;
717 if (!WideCharToMultiByte(CP_ACP
, 0, pszPath
, -1, strRet
->cStr
, MAX_PATH
,
719 strRet
->cStr
[0] = '\0';
720 CoTaskMemFree(pszPath
);
724 strRet
->uType
= STRRET_WSTR
;
725 strRet
->pOleStr
= pszPath
;
729 CoTaskMemFree(pszPath
);
731 TRACE ("-- (%p)->(%s,0x%08x)\n", this,
732 strRet
->uType
== STRRET_CSTR
? strRet
->cStr
:
733 debugstr_w(strRet
->pOleStr
), hr
);
737 /**************************************************************************
738 * CDesktopFolder::SetNameOf
739 * Changes the name of a file object or subfolder, possibly changing its item
740 * identifier in the process.
743 * HWND hwndOwner, //[in ] Owner window for output
744 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
745 * LPCOLESTR lpszName, //[in ] the items new display name
746 * DWORD dwFlags, //[in ] SHGNO formatting flags
747 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
749 HRESULT WINAPI
CDesktopFolder::SetNameOf(
751 PCUITEMID_CHILD pidl
, /* simple pidl */
754 PITEMID_CHILD
*pPidlOut
)
756 CComPtr
<IShellFolder2
> psf
;
758 WCHAR szSrc
[MAX_PATH
+ 1], szDest
[MAX_PATH
+ 1];
760 BOOL bIsFolder
= _ILIsFolder (ILFindLastID (pidl
));
762 TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner
, pidl
,
763 debugstr_w (lpName
), dwFlags
, pPidlOut
);
765 if (_ILGetGUIDPointer(pidl
))
766 return SHELL32_SetNameOfGuidItem(pidl
, lpName
, dwFlags
, pPidlOut
);
768 /* build source path */
769 lstrcpynW(szSrc
, sPathTarget
, MAX_PATH
);
770 ptr
= PathAddBackslashW (szSrc
);
772 _ILSimpleGetTextW (pidl
, ptr
, MAX_PATH
+ 1 - (ptr
- szSrc
));
774 /* build destination path */
775 if (dwFlags
== SHGDN_NORMAL
|| dwFlags
& SHGDN_INFOLDER
) {
776 lstrcpynW(szDest
, sPathTarget
, MAX_PATH
);
777 ptr
= PathAddBackslashW (szDest
);
779 lstrcpynW(ptr
, lpName
, MAX_PATH
+ 1 - (ptr
- szDest
));
781 lstrcpynW(szDest
, lpName
, MAX_PATH
);
783 if(!(dwFlags
& SHGDN_FORPARSING
) && SHELL_FS_HideExtension(szSrc
)) {
784 WCHAR
*ext
= PathFindExtensionW(szSrc
);
786 INT len
= wcslen(szDest
);
787 lstrcpynW(szDest
+ len
, ext
, MAX_PATH
- len
);
791 if (!memcmp(szSrc
, szDest
, (wcslen(szDest
) + 1) * sizeof(WCHAR
)))
793 /* src and destination is the same */
796 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
801 TRACE ("src=%s dest=%s\n", debugstr_w(szSrc
), debugstr_w(szDest
));
802 if (MoveFileW (szSrc
, szDest
))
807 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
809 SHChangeNotify (bIsFolder
? SHCNE_RENAMEFOLDER
: SHCNE_RENAMEITEM
,
810 SHCNF_PATHW
, szSrc
, szDest
);
817 HRESULT WINAPI
CDesktopFolder::GetDefaultSearchGUID(GUID
*pguid
)
819 FIXME ("(%p)\n", this);
823 HRESULT WINAPI
CDesktopFolder::EnumSearches(IEnumExtraSearch
**ppenum
)
825 FIXME ("(%p)\n", this);
829 HRESULT WINAPI
CDesktopFolder::GetDefaultColumn(DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
831 TRACE ("(%p)\n", this);
841 HRESULT WINAPI
CDesktopFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
843 TRACE ("(%p)\n", this);
845 if (!pcsFlags
|| iColumn
>= DESKTOPSHELLVIEWCOLUMNS
)
848 *pcsFlags
= DesktopSFHeader
[iColumn
].pcsFlags
;
853 HRESULT WINAPI
CDesktopFolder::GetDetailsEx(
854 PCUITEMID_CHILD pidl
,
855 const SHCOLUMNID
*pscid
,
858 FIXME ("(%p)\n", this);
863 HRESULT WINAPI
CDesktopFolder::GetDetailsOf(
864 PCUITEMID_CHILD pidl
,
870 TRACE ("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
872 if (!psd
|| iColumn
>= DESKTOPSHELLVIEWCOLUMNS
)
877 psd
->fmt
= DesktopSFHeader
[iColumn
].fmt
;
878 psd
->cxChar
= DesktopSFHeader
[iColumn
].cxChar
;
879 psd
->str
.uType
= STRRET_CSTR
;
880 LoadStringA (shell32_hInstance
, DesktopSFHeader
[iColumn
].colnameid
,
881 psd
->str
.cStr
, MAX_PATH
);
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
);