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 /***********************************************************************
48 * Desktopfolder implementation
53 class CDesktopFolderEnum
:
54 public CEnumIDListBase
57 // CComPtr fDesktopEnumerator;
58 // CComPtr fCommonDesktopEnumerator;
61 ~CDesktopFolderEnum();
62 HRESULT WINAPI
Initialize(CDesktopFolder
*desktopFolder
, HWND hwndOwner
, DWORD dwFlags
);
64 BEGIN_COM_MAP(CDesktopFolderEnum
)
65 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList
, IEnumIDList
)
69 int SHELL_ConfirmMsgBox(HWND hWnd
, LPWSTR lpszText
, LPWSTR lpszCaption
, HICON hIcon
, BOOL bYesToAll
);
71 static const shvheader DesktopSFHeader
[] = {
72 {IDS_SHV_COLUMN1
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 15},
73 {IDS_SHV_COLUMN2
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
74 {IDS_SHV_COLUMN3
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
75 {IDS_SHV_COLUMN4
, SHCOLSTATE_TYPE_DATE
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 12},
76 {IDS_SHV_COLUMN5
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 5}
79 #define DESKTOPSHELLVIEWCOLUMNS 5
81 CDesktopFolderEnum::CDesktopFolderEnum()
85 CDesktopFolderEnum::~CDesktopFolderEnum()
89 static const WCHAR ClassicStartMenuW
[] = L
"SOFTWARE\\Microsoft\\Windows\\"
90 L
"CurrentVersion\\Explorer\\HideDesktopIcons\\ClassicStartMenu";
93 IsNamespaceExtensionHidden(const WCHAR
*iid
)
95 DWORD Result
, dwResult
;
96 dwResult
= sizeof(DWORD
);
98 if (RegGetValueW(HKEY_CURRENT_USER
, /* FIXME use NewStartPanel when activated */
104 &dwResult
) != ERROR_SUCCESS
)
113 SetNamespaceExtensionVisibleStatus(const WCHAR
* iid
, DWORD dwStatus
)
117 if (RegOpenKeyExW(HKEY_CURRENT_USER
, ClassicStartMenuW
, 0, KEY_WRITE
, &hKey
) == ERROR_SUCCESS
)
119 RegSetValueExW(hKey
, iid
, 0, REG_DWORD
, (LPBYTE
)&dwStatus
, sizeof(DWORD
));
124 /**************************************************************************
125 * CreateDesktopEnumList()
128 HRESULT WINAPI
CDesktopFolderEnum::Initialize(CDesktopFolder
*desktopFolder
, HWND hwndOwner
, DWORD dwFlags
)
131 WCHAR szPath
[MAX_PATH
];
133 static const WCHAR MyDocumentsClassString
[] = L
"{450D8FBA-AD25-11D0-98A8-0800361B1103}";
134 static const WCHAR Desktop_NameSpaceW
[] = L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\Namespace";
136 TRACE("(%p)->(flags=0x%08x)\n", this, dwFlags
);
138 /* enumerate the root folders */
139 if (dwFlags
& SHCONTF_FOLDERS
)
145 /* create the pidl for This item */
146 if (IsNamespaceExtensionHidden(MyDocumentsClassString
) < 1)
148 ret
= AddToEnumList(_ILCreateMyDocuments());
150 ret
= AddToEnumList(_ILCreateMyComputer());
152 for (i
= 0; i
< 2; i
++)
155 dwResult
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, Desktop_NameSpaceW
, 0, KEY_READ
, &hkey
);
157 dwResult
= RegOpenKeyExW(HKEY_CURRENT_USER
, Desktop_NameSpaceW
, 0, KEY_READ
, &hkey
);
159 if (dwResult
== ERROR_SUCCESS
)
170 size
= sizeof (iid
) / sizeof (iid
[0]);
171 r
= RegEnumKeyExW(hkey
, i
, iid
, &size
, 0, NULL
, NULL
, NULL
);
172 if (ERROR_SUCCESS
== r
)
174 if (IsNamespaceExtensionHidden(iid
) < 1)
176 pidl
= _ILCreateGuidFromStrW(iid
);
179 if (!HasItemWithCLSID(pidl
))
181 ret
= AddToEnumList(pidl
);
190 else if (ERROR_NO_MORE_ITEMS
== r
)
199 for (i
= 0; i
< 2; i
++)
202 dwResult
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, ClassicStartMenuW
, 0, KEY_READ
, &hkey
);
204 dwResult
= RegOpenKeyExW(HKEY_CURRENT_USER
, ClassicStartMenuW
, 0, KEY_READ
, &hkey
);
206 if (dwResult
== ERROR_SUCCESS
)
208 DWORD j
= 0, dwVal
, Val
, dwType
, dwIID
;
215 dwIID
= sizeof(iid
) / sizeof(WCHAR
);
217 r
= RegEnumValueW(hkey
, j
++, iid
, &dwIID
, NULL
, &dwType
, (LPBYTE
)&Val
, &dwVal
);
218 if (r
== ERROR_SUCCESS
)
220 if (Val
== 0 && dwType
== REG_DWORD
)
222 LPITEMIDLIST pidl
= _ILCreateGuidFromStrW(iid
);
225 if (!HasItemWithCLSID(pidl
))
236 else if (ERROR_NO_MORE_ITEMS
== r
)
247 /* enumerate the elements in %windir%\desktop */
248 ret
= ret
&& SHGetSpecialFolderPathW(0, szPath
, CSIDL_DESKTOPDIRECTORY
, FALSE
);
249 ret
= ret
&& CreateFolderEnumList(szPath
, dwFlags
);
251 ret
= ret
&& SHGetSpecialFolderPathW(0, szPath
, CSIDL_COMMON_DESKTOPDIRECTORY
, FALSE
);
252 ret
= ret
&& CreateFolderEnumList(szPath
, dwFlags
);
254 return ret
? S_OK
: E_FAIL
;
257 void CDesktopFolder::SF_RegisterClipFmt()
259 TRACE ("(%p)\n", this);
262 cfShellIDList
= RegisterClipboardFormatW(CFSTR_SHELLIDLIST
);
265 CDesktopFolder::CDesktopFolder()
270 SF_RegisterClipFmt();
274 CDesktopFolder::~CDesktopFolder()
278 HRESULT WINAPI
CDesktopFolder::FinalConstruct()
280 WCHAR szMyPath
[MAX_PATH
];
282 if (!SHGetSpecialFolderPathW( 0, szMyPath
, CSIDL_DESKTOPDIRECTORY
, TRUE
))
285 pidlRoot
= _ILCreateDesktop(); /* my qualified pidl */
286 sPathTarget
= (LPWSTR
)SHAlloc((wcslen(szMyPath
) + 1) * sizeof(WCHAR
));
287 wcscpy(sPathTarget
, szMyPath
);
291 /**************************************************************************
292 * CDesktopFolder::ParseDisplayName
295 * "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" and "" binds
298 HRESULT WINAPI
CDesktopFolder::ParseDisplayName(
301 LPOLESTR lpszDisplayName
,
303 PIDLIST_RELATIVE
*ppidl
,
304 DWORD
*pdwAttributes
)
306 WCHAR szElement
[MAX_PATH
];
307 LPCWSTR szNext
= NULL
;
308 LPITEMIDLIST pidlTemp
= NULL
;
313 TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
314 this, hwndOwner
, pbc
, lpszDisplayName
, debugstr_w(lpszDisplayName
),
315 pchEaten
, ppidl
, pdwAttributes
);
320 if (!lpszDisplayName
)
329 *pchEaten
= 0; /* strange but like the original */
331 urldata
.cbSize
= sizeof(urldata
);
333 if (lpszDisplayName
[0] == ':' && lpszDisplayName
[1] == ':')
335 szNext
= GetNextElementW (lpszDisplayName
, szElement
, MAX_PATH
);
336 TRACE ("-- element: %s\n", debugstr_w (szElement
));
337 CLSIDFromString (szElement
+ 2, &clsid
);
338 pidlTemp
= _ILCreateGuid (PT_GUID
, clsid
);
340 else if (PathGetDriveNumberW (lpszDisplayName
) >= 0)
342 /* it's a filesystem path with a drive. Let MyComputer/UnixDosFolder parse it */
343 pidlTemp
= _ILCreateMyComputer ();
344 szNext
= lpszDisplayName
;
346 else if (PathIsUNCW(lpszDisplayName
))
348 pidlTemp
= _ILCreateNetwork();
349 szNext
= lpszDisplayName
;
351 else if( (pidlTemp
= SHELL32_CreatePidlFromBindCtx(pbc
, lpszDisplayName
)) )
356 else if (SUCCEEDED(ParseURLW(lpszDisplayName
, &urldata
)))
358 if (urldata
.nScheme
== URL_SCHEME_SHELL
) /* handle shell: urls */
360 TRACE ("-- shell url: %s\n", debugstr_w(urldata
.pszSuffix
));
361 SHCLSIDFromStringW (urldata
.pszSuffix
+ 2, &clsid
);
362 pidlTemp
= _ILCreateGuid (PT_GUID
, clsid
);
365 return IEParseDisplayNameWithBCW(CP_ACP
, lpszDisplayName
, pbc
, ppidl
);
369 /* it's a filesystem path on the desktop. Let a FSFolder parse it */
371 if (*lpszDisplayName
)
373 WCHAR szPath
[MAX_PATH
];
376 /* build a complete path to create a simple pidl */
377 lstrcpynW(szPath
, sPathTarget
, MAX_PATH
);
378 pathPtr
= PathAddBackslashW(szPath
);
381 lstrcpynW(pathPtr
, lpszDisplayName
, MAX_PATH
- (pathPtr
- szPath
));
382 hr
= _ILCreateFromPathW(szPath
, &pidlTemp
);
386 /* should never reach here, but for completeness */
387 hr
= HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
);
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
)
406 hr
= SHELL32_GetItemAttributes((IShellFolder
*)this,
407 pidlTemp
, pdwAttributes
);
416 TRACE ("(%p)->(-- ret=0x%08x)\n", this, hr
);
421 /**************************************************************************
422 * CDesktopFolder::EnumObjects
424 HRESULT WINAPI
CDesktopFolder::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
*ppEnumIDList
)
426 return ShellObjectCreatorInit
<CDesktopFolderEnum
>(this, hwndOwner
, dwFlags
, IID_IEnumIDList
, ppEnumIDList
);
429 /**************************************************************************
430 * CDesktopFolder::BindToObject
432 HRESULT WINAPI
CDesktopFolder::BindToObject(
433 PCUIDLIST_RELATIVE pidl
,
438 TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n",
439 this, pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
441 return SHELL32_BindToChild( pidlRoot
, sPathTarget
, pidl
, riid
, ppvOut
);
444 /**************************************************************************
445 * CDesktopFolder::BindToStorage
447 HRESULT WINAPI
CDesktopFolder::BindToStorage(
448 PCUIDLIST_RELATIVE pidl
,
453 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
454 this, pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
460 /**************************************************************************
461 * CDesktopFolder::CompareIDs
463 HRESULT WINAPI
CDesktopFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
467 TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam
, pidl1
, pidl2
);
468 nReturn
= SHELL32_CompareIDs ((IShellFolder
*)this, lParam
, pidl1
, pidl2
);
469 TRACE ("-- %i\n", nReturn
);
473 /**************************************************************************
474 * CDesktopFolder::CreateViewObject
476 HRESULT WINAPI
CDesktopFolder::CreateViewObject(
481 CComPtr
<IShellView
> pShellView
;
482 HRESULT hr
= E_INVALIDARG
;
484 TRACE ("(%p)->(hwnd=%p,%s,%p)\n",
485 this, hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
492 if (IsEqualIID (riid
, IID_IDropTarget
))
494 hr
= this->QueryInterface (IID_IDropTarget
, ppvOut
);
496 else if (IsEqualIID (riid
, IID_IContextMenu
))
498 WARN ("IContextMenu not implemented\n");
501 else if (IsEqualIID (riid
, IID_IShellView
))
503 hr
= IShellView_Constructor((IShellFolder
*)this, &pShellView
);
505 hr
= pShellView
->QueryInterface(riid
, ppvOut
);
507 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
511 /**************************************************************************
512 * CDesktopFolder::GetAttributesOf
514 HRESULT WINAPI
CDesktopFolder::GetAttributesOf(
516 PCUITEMID_CHILD_ARRAY apidl
,
520 static const DWORD dwDesktopAttributes
=
521 SFGAO_HASSUBFOLDER
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
|
522 SFGAO_STORAGEANCESTOR
| SFGAO_HASPROPSHEET
| SFGAO_STORAGE
| SFGAO_CANLINK
;
523 static const DWORD dwMyComputerAttributes
=
524 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
525 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_CANLINK
;
526 static DWORD dwMyNetPlacesAttributes
=
527 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
528 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_CANLINK
;
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
;
554 SHELL32_GetItemAttributes((IShellFolder
*)this, apidl
[i
], rgfInOut
);
557 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
558 *rgfInOut
&= ~SFGAO_VALIDATE
;
560 TRACE("-- result=0x%08x\n", *rgfInOut
);
565 /**************************************************************************
566 * CDesktopFolder::GetUIObjectOf
569 * HWND hwndOwner, //[in ] Parent window for any output
570 * UINT cidl, //[in ] array size
571 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
572 * REFIID riid, //[in ] Requested Interface
573 * UINT* prgfInOut, //[ ] reserved
574 * LPVOID* ppvObject) //[out] Resulting Interface
577 HRESULT WINAPI
CDesktopFolder::GetUIObjectOf(
580 PCUITEMID_CHILD_ARRAY apidl
,
586 IUnknown
*pObj
= NULL
;
587 HRESULT hr
= E_INVALIDARG
;
589 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
590 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
597 if (IsEqualIID (riid
, IID_IContextMenu
))
599 hr
= CDefFolderMenu_Create2(pidlRoot
, hwndOwner
, cidl
, apidl
, (IShellFolder
*)this, NULL
, 0, NULL
, (IContextMenu
**)&pObj
);
601 else if (IsEqualIID (riid
, IID_IDataObject
) && (cidl
>= 1))
603 hr
= IDataObject_Constructor( hwndOwner
, pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
605 else if (IsEqualIID (riid
, IID_IExtractIconA
) && (cidl
== 1))
607 pidl
= ILCombine (pidlRoot
, apidl
[0]);
608 pObj
= IExtractIconA_Constructor (pidl
);
612 else if (IsEqualIID (riid
, IID_IExtractIconW
) && (cidl
== 1))
614 pidl
= ILCombine (pidlRoot
, apidl
[0]);
615 pObj
= IExtractIconW_Constructor (pidl
);
619 else if (IsEqualIID (riid
, IID_IDropTarget
))
621 /* only interested in attempting to bind to shell folders, not files, semicolon intentionate */
622 if (cidl
!= 1 || FAILED(hr
= this->_GetDropTarget(apidl
[0], (LPVOID
*) &pObj
)))
624 IDropTarget
* pDt
= NULL
;
625 hr
= this->QueryInterface(IID_PPV_ARG(IDropTarget
, &pDt
));
629 else if ((IsEqualIID(riid
, IID_IShellLinkW
) ||
630 IsEqualIID(riid
, IID_IShellLinkA
)) && (cidl
== 1))
632 pidl
= ILCombine (pidlRoot
, apidl
[0]);
633 hr
= IShellLink_ConstructFromFile(NULL
, riid
, pidl
, (LPVOID
*)&pObj
);
639 if (SUCCEEDED(hr
) && !pObj
)
643 TRACE ("(%p)->hr=0x%08x\n", this, hr
);
647 /**************************************************************************
648 * CDesktopFolder::GetDisplayNameOf
651 * special case: pidl = null gives desktop-name back
653 HRESULT WINAPI
CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
658 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
664 pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
666 return E_OUTOFMEMORY
;
668 if (_ILIsDesktop (pidl
))
670 if ((GET_SHGDN_RELATION (dwFlags
) == SHGDN_NORMAL
) &&
671 (GET_SHGDN_FOR (dwFlags
) & SHGDN_FORPARSING
))
672 wcscpy(pszPath
, sPathTarget
);
674 HCR_GetClassNameW(CLSID_ShellDesktop
, pszPath
, MAX_PATH
);
676 else if (_ILIsPidlSimple (pidl
))
680 if ((clsid
= _ILGetGUIDPointer (pidl
)))
682 if (GET_SHGDN_FOR (dwFlags
) == SHGDN_FORPARSING
)
684 int bWantsForParsing
;
687 * We can only get a filesystem path from a shellfolder if the
688 * value WantsFORPARSING in CLSID\\{...}\\shellfolder exists.
690 * Exception: The MyComputer folder doesn't have this key,
691 * but any other filesystem backed folder it needs it.
693 if (IsEqualIID (*clsid
, CLSID_MyComputer
))
695 bWantsForParsing
= TRUE
;
699 /* get the "WantsFORPARSING" flag from the registry */
700 static const WCHAR clsidW
[] =
701 { 'C', 'L', 'S', 'I', 'D', '\\', 0 };
702 static const WCHAR shellfolderW
[] =
703 { '\\', 's', 'h', 'e', 'l', 'l', 'f', 'o', 'l', 'd', 'e', 'r', 0 };
704 static const WCHAR wantsForParsingW
[] =
705 { 'W', 'a', 'n', 't', 's', 'F', 'o', 'r', 'P', 'a', 'r', 's', 'i', 'n',
708 WCHAR szRegPath
[100];
711 wcscpy (szRegPath
, clsidW
);
712 SHELL32_GUIDToStringW (*clsid
, &szRegPath
[6]);
713 wcscat (szRegPath
, shellfolderW
);
714 r
= SHGetValueW(HKEY_CLASSES_ROOT
, szRegPath
,
715 wantsForParsingW
, NULL
, NULL
, NULL
);
716 if (r
== ERROR_SUCCESS
)
717 bWantsForParsing
= TRUE
;
719 bWantsForParsing
= FALSE
;
722 if ((GET_SHGDN_RELATION (dwFlags
) == SHGDN_NORMAL
) &&
726 * we need the filesystem path to the destination folder.
727 * Only the folder itself can know it
729 hr
= SHELL32_GetDisplayNameOfChild (this, pidl
, dwFlags
,
735 /* parsing name like ::{...} */
738 SHELL32_GUIDToStringW (*clsid
, &pszPath
[2]);
743 /* user friendly name */
744 HCR_GetClassNameW (*clsid
, pszPath
, MAX_PATH
);
751 /* file system folder or file rooted at the desktop */
752 if ((GET_SHGDN_FOR(dwFlags
) == SHGDN_FORPARSING
) &&
753 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
))
755 lstrcpynW(pszPath
, sPathTarget
, MAX_PATH
- 1);
756 PathAddBackslashW(pszPath
);
757 cLen
= wcslen(pszPath
);
760 _ILSimpleGetTextW(pidl
, pszPath
+ cLen
, MAX_PATH
- cLen
);
761 if (!_ILIsFolder(pidl
))
762 SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
764 if (GetFileAttributes(pszPath
) == INVALID_FILE_ATTRIBUTES
)
766 /* file system folder or file rooted at the AllUsers desktop */
767 if ((GET_SHGDN_FOR(dwFlags
) == SHGDN_FORPARSING
) &&
768 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
))
770 SHGetSpecialFolderPathW(0, pszPath
, CSIDL_COMMON_DESKTOPDIRECTORY
, FALSE
);
771 PathAddBackslashW(pszPath
);
772 cLen
= wcslen(pszPath
);
775 _ILSimpleGetTextW(pidl
, pszPath
+ cLen
, MAX_PATH
- cLen
);
776 if (!_ILIsFolder(pidl
))
777 SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
783 /* a complex pidl, let the subfolder do the work */
784 hr
= SHELL32_GetDisplayNameOfChild (this, pidl
, dwFlags
,
790 /* Win9x always returns ANSI strings, NT always returns Unicode strings */
791 if (GetVersion() & 0x80000000)
793 strRet
->uType
= STRRET_CSTR
;
794 if (!WideCharToMultiByte(CP_ACP
, 0, pszPath
, -1, strRet
->cStr
, MAX_PATH
,
796 strRet
->cStr
[0] = '\0';
797 CoTaskMemFree(pszPath
);
801 strRet
->uType
= STRRET_WSTR
;
802 strRet
->pOleStr
= pszPath
;
806 CoTaskMemFree(pszPath
);
808 TRACE ("-- (%p)->(%s,0x%08x)\n", this,
809 strRet
->uType
== STRRET_CSTR
? strRet
->cStr
:
810 debugstr_w(strRet
->pOleStr
), hr
);
814 /**************************************************************************
815 * CDesktopFolder::SetNameOf
816 * Changes the name of a file object or subfolder, possibly changing its item
817 * identifier in the process.
820 * HWND hwndOwner, //[in ] Owner window for output
821 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
822 * LPCOLESTR lpszName, //[in ] the items new display name
823 * DWORD dwFlags, //[in ] SHGNO formatting flags
824 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
826 HRESULT WINAPI
CDesktopFolder::SetNameOf(
828 PCUITEMID_CHILD pidl
, /* simple pidl */
831 PITEMID_CHILD
*pPidlOut
)
833 CComPtr
<IShellFolder2
> psf
;
835 WCHAR szSrc
[MAX_PATH
+ 1], szDest
[MAX_PATH
+ 1];
837 BOOL bIsFolder
= _ILIsFolder (ILFindLastID (pidl
));
839 TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner
, pidl
,
840 debugstr_w (lpName
), dwFlags
, pPidlOut
);
842 if (_ILGetGUIDPointer(pidl
))
844 if (SUCCEEDED(BindToObject(pidl
, NULL
, IID_PPV_ARG(IShellFolder2
, &psf
))))
846 hr
= psf
->SetNameOf(hwndOwner
, pidl
, lpName
, dwFlags
, pPidlOut
);
851 /* build source path */
852 lstrcpynW(szSrc
, sPathTarget
, MAX_PATH
);
853 ptr
= PathAddBackslashW (szSrc
);
855 _ILSimpleGetTextW (pidl
, ptr
, MAX_PATH
+ 1 - (ptr
- szSrc
));
857 /* build destination path */
858 if (dwFlags
== SHGDN_NORMAL
|| dwFlags
& SHGDN_INFOLDER
) {
859 lstrcpynW(szDest
, sPathTarget
, MAX_PATH
);
860 ptr
= PathAddBackslashW (szDest
);
862 lstrcpynW(ptr
, lpName
, MAX_PATH
+ 1 - (ptr
- szDest
));
864 lstrcpynW(szDest
, lpName
, MAX_PATH
);
866 if(!(dwFlags
& SHGDN_FORPARSING
) && SHELL_FS_HideExtension(szSrc
)) {
867 WCHAR
*ext
= PathFindExtensionW(szSrc
);
869 INT len
= wcslen(szDest
);
870 lstrcpynW(szDest
+ len
, ext
, MAX_PATH
- len
);
874 if (!memcmp(szSrc
, szDest
, (wcslen(szDest
) + 1) * sizeof(WCHAR
)))
876 /* src and destination is the same */
879 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
884 TRACE ("src=%s dest=%s\n", debugstr_w(szSrc
), debugstr_w(szDest
));
885 if (MoveFileW (szSrc
, szDest
))
890 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
892 SHChangeNotify (bIsFolder
? SHCNE_RENAMEFOLDER
: SHCNE_RENAMEITEM
,
893 SHCNF_PATHW
, szSrc
, szDest
);
900 HRESULT WINAPI
CDesktopFolder::GetDefaultSearchGUID(GUID
*pguid
)
902 FIXME ("(%p)\n", this);
906 HRESULT WINAPI
CDesktopFolder::EnumSearches(IEnumExtraSearch
**ppenum
)
908 FIXME ("(%p)\n", this);
912 HRESULT WINAPI
CDesktopFolder::GetDefaultColumn(DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
914 TRACE ("(%p)\n", this);
924 HRESULT WINAPI
CDesktopFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
926 TRACE ("(%p)\n", this);
928 if (!pcsFlags
|| iColumn
>= DESKTOPSHELLVIEWCOLUMNS
)
931 *pcsFlags
= DesktopSFHeader
[iColumn
].pcsFlags
;
936 HRESULT WINAPI
CDesktopFolder::GetDetailsEx(
937 PCUITEMID_CHILD pidl
,
938 const SHCOLUMNID
*pscid
,
941 FIXME ("(%p)\n", this);
946 HRESULT WINAPI
CDesktopFolder::GetDetailsOf(
947 PCUITEMID_CHILD pidl
,
953 TRACE ("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
955 if (!psd
|| iColumn
>= DESKTOPSHELLVIEWCOLUMNS
)
960 psd
->fmt
= DesktopSFHeader
[iColumn
].fmt
;
961 psd
->cxChar
= DesktopSFHeader
[iColumn
].cxChar
;
962 psd
->str
.uType
= STRRET_CSTR
;
963 LoadStringA (shell32_hInstance
, DesktopSFHeader
[iColumn
].colnameid
,
964 psd
->str
.cStr
, MAX_PATH
);
968 /* the data from the pidl */
969 psd
->str
.uType
= STRRET_CSTR
;
973 hr
= GetDisplayNameOf(pidl
,
974 SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
977 _ILGetFileSize (pidl
, psd
->str
.cStr
, MAX_PATH
);
980 _ILGetFileType (pidl
, psd
->str
.cStr
, MAX_PATH
);
983 _ILGetFileDate (pidl
, psd
->str
.cStr
, MAX_PATH
);
985 case 4: /* attributes */
986 _ILGetFileAttributes (pidl
, psd
->str
.cStr
, MAX_PATH
);
993 HRESULT WINAPI
CDesktopFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
*pscid
)
995 FIXME ("(%p)\n", this);
999 HRESULT WINAPI
CDesktopFolder::GetClassID(CLSID
*lpClassId
)
1001 TRACE ("(%p)\n", this);
1006 *lpClassId
= CLSID_ShellDesktop
;
1011 HRESULT WINAPI
CDesktopFolder::Initialize(LPCITEMIDLIST pidl
)
1013 TRACE ("(%p)->(%p)\n", this, pidl
);
1018 HRESULT WINAPI
CDesktopFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
1020 TRACE ("(%p)->(%p)\n", this, pidl
);
1022 if (!pidl
) return E_POINTER
;
1023 *pidl
= ILClone (pidlRoot
);
1027 HRESULT WINAPI
CDesktopFolder::GetUniqueName(LPWSTR pwszName
, UINT uLen
)
1029 CComPtr
<IEnumIDList
> penum
;
1031 WCHAR wszText
[MAX_PATH
];
1032 WCHAR wszNewFolder
[25];
1033 const WCHAR wszFormat
[] = {'%', 's', ' ', '%', 'd', 0 };
1035 LoadStringW(shell32_hInstance
, IDS_NEWFOLDER
, wszNewFolder
, sizeof(wszNewFolder
) / sizeof(WCHAR
));
1037 TRACE ("(%p)(%p %u)\n", this, pwszName
, uLen
);
1039 if (uLen
< sizeof(wszNewFolder
) / sizeof(WCHAR
) + 3)
1042 lstrcpynW (pwszName
, wszNewFolder
, uLen
);
1045 SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
| SHCONTF_INCLUDEHIDDEN
, &penum
);
1053 while (S_OK
== penum
->Next(1, &pidl
, &dwFetched
) &&
1055 _ILSimpleGetTextW (pidl
, wszText
, MAX_PATH
);
1056 if (0 == lstrcmpiW (wszText
, pwszName
)) {
1057 _snwprintf (pwszName
, uLen
, wszFormat
, wszNewFolder
, i
++);
1070 HRESULT WINAPI
CDesktopFolder::AddFolder(HWND hwnd
, LPCWSTR pwszName
, LPITEMIDLIST
*ppidlOut
)
1072 WCHAR wszNewDir
[MAX_PATH
];
1074 HRESULT hres
= E_FAIL
;
1076 TRACE ("(%p)(%s %p)\n", this, debugstr_w(pwszName
), ppidlOut
);
1080 lstrcpynW(wszNewDir
, sPathTarget
, MAX_PATH
);
1081 PathAppendW(wszNewDir
, pwszName
);
1082 bRes
= CreateDirectoryW (wszNewDir
, NULL
);
1085 SHChangeNotify (SHCNE_MKDIR
, SHCNF_PATHW
, wszNewDir
, NULL
);
1088 hres
= _ILCreateFromPathW(wszNewDir
, ppidlOut
);
1094 HRESULT WINAPI
CDesktopFolder::DeleteItems(UINT cidl
, LPCITEMIDLIST
*apidl
)
1098 WCHAR wszPath
[MAX_PATH
];
1099 WCHAR wszCaption
[50];
1100 WCHAR
*wszPathsList
;
1102 WCHAR
*wszCurrentPath
;
1103 UINT bRestoreWithDeskCpl
= FALSE
;
1106 TRACE ("(%p)(%u %p)\n", this, cidl
, apidl
);
1107 if (cidl
== 0) return S_OK
;
1109 for(i
= 0; i
< cidl
; i
++)
1111 if (_ILIsMyComputer(apidl
[i
]))
1112 bRestoreWithDeskCpl
++;
1113 else if (_ILIsNetHood(apidl
[i
]))
1114 bRestoreWithDeskCpl
++;
1115 else if (_ILIsMyDocuments(apidl
[i
]))
1116 bRestoreWithDeskCpl
++;
1119 if (bRestoreWithDeskCpl
)
1121 /* FIXME use FormatMessage
1122 * use a similar message resource as in windows
1124 LoadStringW(shell32_hInstance
, IDS_DELETEMULTIPLE_TEXT
, wszPath
, sizeof(wszPath
) / sizeof(WCHAR
));
1125 wszPath
[(sizeof(wszPath
)/sizeof(WCHAR
))-1] = 0;
1127 LoadStringW(shell32_hInstance
, IDS_DELETEITEM_CAPTION
, wszCaption
, sizeof(wszCaption
) / sizeof(WCHAR
));
1128 wszCaption
[(sizeof(wszCaption
)/sizeof(WCHAR
))-1] = 0;
1130 res
= SHELL_ConfirmMsgBox(GetActiveWindow(), wszPath
, wszCaption
, NULL
, cidl
> 1);
1131 if (res
== IDC_YESTOALL
|| res
== IDYES
)
1133 for(i
= 0; i
< cidl
; i
++)
1135 if (_ILIsMyComputer(apidl
[i
]))
1136 SetNamespaceExtensionVisibleStatus(L
"{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0x1);
1137 else if (_ILIsNetHood(apidl
[i
]))
1138 SetNamespaceExtensionVisibleStatus(L
"{208D2C60-3AEA-1069-A2D7-08002B30309D}", 0x1);
1139 else if (_ILIsMyDocuments(apidl
[i
]))
1140 SetNamespaceExtensionVisibleStatus(L
"{450D8FBA-AD25-11D0-98A8-0800361B1103}", 0x1);
1145 lstrcpynW(wszPath
, sPathTarget
, MAX_PATH
);
1149 PathAddBackslashW(wszPath
);
1150 wszPathsList
= BuildPathsList(wszPath
, cidl
, apidl
);
1152 ZeroMemory(&op
, sizeof(op
));
1153 op
.hwnd
= GetActiveWindow();
1154 op
.wFunc
= FO_DELETE
;
1155 op
.pFrom
= wszPathsList
;
1156 op
.fFlags
= FOF_ALLOWUNDO
;
1157 if (SHFileOperationW(&op
))
1159 WARN("SHFileOperation failed\n");
1165 /* we currently need to manually send the notifies */
1166 wszCurrentPath
= wszPathsList
;
1167 for (i
= 0; i
< cidl
; i
++)
1171 if (_ILIsFolder(apidl
[i
]))
1172 wEventId
= SHCNE_RMDIR
;
1173 else if (_ILIsValue(apidl
[i
]))
1174 wEventId
= SHCNE_DELETE
;
1178 /* check if file exists */
1179 if (GetFileAttributesW(wszCurrentPath
) == INVALID_FILE_ATTRIBUTES
)
1181 LPITEMIDLIST pidl
= ILCombine(pidlRoot
, apidl
[i
]);
1182 SHChangeNotify(wEventId
, SHCNF_IDLIST
, pidl
, NULL
);
1186 wszCurrentPath
+= wcslen(wszCurrentPath
) + 1;
1188 HeapFree(GetProcessHeap(), 0, wszPathsList
);
1192 HRESULT WINAPI
CDesktopFolder::CopyItems(IShellFolder
*pSFFrom
, UINT cidl
, LPCITEMIDLIST
*apidl
, BOOL bCopy
)
1194 CComPtr
<IPersistFolder2
> ppf2
;
1195 WCHAR szSrcPath
[MAX_PATH
];
1196 WCHAR szTargetPath
[MAX_PATH
];
1199 LPWSTR pszSrc
, pszTarget
, pszSrcList
, pszTargetList
, pszFileName
;
1203 TRACE ("(%p)->(%p,%u,%p)\n", this, pSFFrom
, cidl
, apidl
);
1205 pSFFrom
->QueryInterface(IID_PPV_ARG(IPersistFolder2
, &ppf2
));
1208 if (FAILED(ppf2
->GetCurFolder(&pidl
)))
1211 if (FAILED(pSFFrom
->GetDisplayNameOf(pidl
, SHGDN_FORPARSING
, &strRet
)))
1217 if (FAILED(StrRetToBufW(&strRet
, pidl
, szSrcPath
, MAX_PATH
)))
1224 pszSrc
= PathAddBackslashW (szSrcPath
);
1226 wcscpy(szTargetPath
, sPathTarget
);
1227 pszTarget
= PathAddBackslashW (szTargetPath
);
1229 pszSrcList
= BuildPathsList(szSrcPath
, cidl
, apidl
);
1230 pszTargetList
= BuildPathsList(szTargetPath
, cidl
, apidl
);
1232 if (!pszSrcList
|| !pszTargetList
)
1235 HeapFree(GetProcessHeap(), 0, pszSrcList
);
1238 HeapFree(GetProcessHeap(), 0, pszTargetList
);
1241 return E_OUTOFMEMORY
;
1243 ZeroMemory(&op
, sizeof(op
));
1246 /* remove trailing backslash */
1249 op
.pFrom
= szSrcPath
;
1253 op
.pFrom
= pszSrcList
;
1256 if (!pszTargetList
[0])
1258 /* remove trailing backslash */
1259 if (pszTarget
- szTargetPath
> 3)
1262 pszTarget
[0] = L
'\0';
1266 pszTarget
[1] = L
'\0';
1269 op
.pTo
= szTargetPath
;
1274 op
.pTo
= pszTargetList
;
1275 op
.fFlags
= FOF_MULTIDESTFILES
;
1277 op
.hwnd
= GetActiveWindow();
1278 op
.wFunc
= bCopy
? FO_COPY
: FO_MOVE
;
1279 op
.fFlags
|= FOF_ALLOWUNDO
| FOF_NOCONFIRMMKDIR
;
1281 res
= SHFileOperationW(&op
);
1283 if (res
== DE_SAMEFILE
)
1285 length
= wcslen(szTargetPath
);
1288 pszFileName
= wcsrchr(pszSrcList
, '\\');
1291 if (LoadStringW(shell32_hInstance
, IDS_COPY_OF
, pszTarget
, MAX_PATH
- length
))
1293 wcscat(szTargetPath
, L
" ");
1296 wcscat(szTargetPath
, pszFileName
);
1297 op
.pTo
= szTargetPath
;
1299 res
= SHFileOperationW(&op
);
1303 HeapFree(GetProcessHeap(), 0, pszSrcList
);
1304 HeapFree(GetProcessHeap(), 0, pszTargetList
);
1314 /****************************************************************************
1315 * IDropTarget implementation
1317 * This should allow two somewhat separate things, copying files to the users directory,
1318 * as well as allowing icons to be moved anywhere and updating the registry to save.
1320 * The first thing I think is best done using fs.cpp to prevent WET code. So we'll simulate
1321 * a drop to the user's home directory. The second will look at the pointer location and
1322 * set sensible places for the icons to live.
1325 BOOL
CDesktopFolder::QueryDrop(DWORD dwKeyState
, LPDWORD pdwEffect
)
1327 /* TODO Windows does different drop effects if dragging across drives.
1328 i.e., it will copy instead of move if the directories are on different disks. */
1330 DWORD dwEffect
= DROPEFFECT_MOVE
;
1332 *pdwEffect
= DROPEFFECT_NONE
;
1334 if (fAcceptFmt
) { /* Does our interpretation of the keystate ... */
1335 *pdwEffect
= KeyStateToDropEffect (dwKeyState
);
1337 if (*pdwEffect
== DROPEFFECT_NONE
)
1338 *pdwEffect
= dwEffect
;
1340 /* ... matches the desired effect ? */
1341 if (dwEffect
& *pdwEffect
) {
1348 HRESULT WINAPI
CDesktopFolder::DragEnter(IDataObject
*pDataObject
,
1349 DWORD dwKeyState
, POINTL pt
, DWORD
*pdwEffect
)
1351 TRACE("(%p)->(DataObject=%p)\n", this, pDataObject
);
1356 InitFormatEtc (fmt
, cfShellIDList
, TYMED_HGLOBAL
);
1357 InitFormatEtc (fmt2
, CF_HDROP
, TYMED_HGLOBAL
);
1359 if (SUCCEEDED(pDataObject
->QueryGetData(&fmt
)))
1361 else if (SUCCEEDED(pDataObject
->QueryGetData(&fmt2
)))
1364 QueryDrop(dwKeyState
, pdwEffect
);
1368 HRESULT WINAPI
CDesktopFolder::DragOver(DWORD dwKeyState
, POINTL pt
,
1371 TRACE("(%p)\n", this);
1374 return E_INVALIDARG
;
1376 QueryDrop(dwKeyState
, pdwEffect
);
1381 HRESULT WINAPI
CDesktopFolder::DragLeave()
1383 TRACE("(%p)\n", this);
1388 HRESULT WINAPI
CDesktopFolder::Drop(IDataObject
*pDataObject
,
1389 DWORD dwKeyState
, POINTL pt
, DWORD
*pdwEffect
)
1391 TRACE("(%p) object dropped desktop\n", this);
1394 bool passthroughtofs
= FALSE
;
1395 FORMATETC formatetc
;
1396 InitFormatEtc(formatetc
, RegisterClipboardFormatW(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
1398 HRESULT hr
= pDataObject
->GetData(&formatetc
, &medium
);
1401 /* lock the handle */
1402 LPIDA lpcida
= (LPIDA
)GlobalLock(medium
.hGlobal
);
1405 ReleaseStgMedium(&medium
);
1409 /* convert the clipboard data into pidl (pointer to id list) */
1411 LPITEMIDLIST
*apidl
= _ILCopyCidaToaPidl(&pidl
, lpcida
);
1414 ReleaseStgMedium(&medium
);
1417 passthroughtofs
= !_ILIsDesktop(pidl
) || (dwKeyState
& MK_CONTROL
);
1419 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1420 ReleaseStgMedium(&medium
);
1424 InitFormatEtc (formatetc
, CF_HDROP
, TYMED_HGLOBAL
);
1425 if (SUCCEEDED(pDataObject
->QueryGetData(&formatetc
)))
1427 passthroughtofs
= TRUE
;
1430 /* We only want to really move files around if they don't already
1431 come from the desktop, or we're linking or copying */
1432 if (passthroughtofs
)
1434 LPITEMIDLIST pidl
= NULL
;
1436 WCHAR szPath
[MAX_PATH
];
1439 /* build a complete path to create a simple pidl */
1440 lstrcpynW(szPath
, sPathTarget
, MAX_PATH
);
1441 /*pathPtr = */PathAddBackslashW(szPath
);
1442 //hr = _ILCreateFromPathW(szPath, &pidl);
1443 hr
= this->ParseDisplayName(NULL
, NULL
, szPath
, NULL
, &pidl
, NULL
);
1447 CComPtr
<IDropTarget
> pDT
;
1448 hr
= this->BindToObject(pidl
, NULL
, IID_PPV_ARG(IDropTarget
, &pDT
));
1449 CoTaskMemFree(pidl
);
1451 SHSimulateDrop(pDT
, pDataObject
, dwKeyState
, NULL
, pdwEffect
);
1453 ERR("Error Binding");
1456 ERR("Error creating from %s\n", debugstr_w(szPath
));
1459 /* Todo, rewrite the registry such that the icons are well placed.
1460 Blocked by no bags implementation. */
1464 HRESULT WINAPI
CDesktopFolder::_GetDropTarget(LPCITEMIDLIST pidl
, LPVOID
*ppvOut
) {
1467 TRACE("CFSFolder::_GetDropTarget entered\n");
1469 if (_ILGetGUIDPointer (pidl
) || _ILIsFolder (pidl
))
1470 return this->BindToObject(pidl
, NULL
, IID_IDropTarget
, ppvOut
);
1472 LPITEMIDLIST pidlNext
= NULL
;
1475 hr
= this->GetDisplayNameOf(pidl
, SHGDN_FORPARSING
, &strFile
);
1478 WCHAR wszPath
[MAX_PATH
];
1479 hr
= StrRetToBufW(&strFile
, pidl
, wszPath
, _countof(wszPath
));
1483 PathRemoveFileSpecW (wszPath
);
1484 hr
= this->ParseDisplayName(NULL
, NULL
, wszPath
, NULL
, &pidlNext
, NULL
);
1488 CComPtr
<IShellFolder
> psf
;
1489 hr
= this->BindToObject(pidlNext
, NULL
, IID_PPV_ARG(IShellFolder
, &psf
));
1490 CoTaskMemFree(pidlNext
);
1493 hr
= psf
->GetUIObjectOf(NULL
, 1, &pidl
, IID_IDropTarget
, NULL
, ppvOut
);
1495 ERR("FS GetUIObjectOf failed: %x\n", hr
);
1498 ERR("BindToObject failed: %x\n", hr
);
1501 ERR("ParseDisplayName failed: %x\n", hr
);
1504 ERR("StrRetToBufW failed: %x\n", hr
);
1507 ERR("GetDisplayNameOf failed: %x\n", hr
);
1512 /*************************************************************************
1513 * SHGetDesktopFolder [SHELL32.@]
1515 HRESULT WINAPI
SHGetDesktopFolder(IShellFolder
**psf
)
1517 HRESULT hres
= S_OK
;
1520 if(!psf
) return E_INVALIDARG
;
1522 hres
= CDesktopFolder::_CreatorClass::CreateInstance(NULL
, IID_PPV_ARG(IShellFolder
, psf
));
1524 TRACE("-- %p->(%p)\n",psf
, *psf
);