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 IEnumIDListImpl
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(
427 LPENUMIDLIST
*ppEnumIDList
)
429 CComObject
<CDesktopFolderEnum
> *theEnumerator
;
430 CComPtr
<IEnumIDList
> result
;
433 TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this, hwndOwner
, dwFlags
, ppEnumIDList
);
435 if (ppEnumIDList
== NULL
)
437 *ppEnumIDList
= NULL
;
439 ATLTRY (theEnumerator
= new CComObject
<CDesktopFolderEnum
>);
441 if (theEnumerator
== NULL
)
442 return E_OUTOFMEMORY
;
444 hResult
= theEnumerator
->QueryInterface(IID_PPV_ARG(IEnumIDList
, &result
));
445 if (FAILED (hResult
))
447 delete theEnumerator
;
451 hResult
= theEnumerator
->Initialize (this, hwndOwner
, dwFlags
);
452 if (FAILED (hResult
))
454 *ppEnumIDList
= result
.Detach ();
456 TRACE ("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList
);
461 /**************************************************************************
462 * CDesktopFolder::BindToObject
464 HRESULT WINAPI
CDesktopFolder::BindToObject(
465 PCUIDLIST_RELATIVE pidl
,
470 TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n",
471 this, pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
473 return SHELL32_BindToChild( pidlRoot
, sPathTarget
, pidl
, riid
, ppvOut
);
476 /**************************************************************************
477 * CDesktopFolder::BindToStorage
479 HRESULT WINAPI
CDesktopFolder::BindToStorage(
480 PCUIDLIST_RELATIVE pidl
,
485 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n",
486 this, pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
492 /**************************************************************************
493 * CDesktopFolder::CompareIDs
495 HRESULT WINAPI
CDesktopFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
499 TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", this, lParam
, pidl1
, pidl2
);
500 nReturn
= SHELL32_CompareIDs ((IShellFolder
*)this, lParam
, pidl1
, pidl2
);
501 TRACE ("-- %i\n", nReturn
);
505 /**************************************************************************
506 * CDesktopFolder::CreateViewObject
508 HRESULT WINAPI
CDesktopFolder::CreateViewObject(
513 CComPtr
<IShellView
> pShellView
;
514 HRESULT hr
= E_INVALIDARG
;
516 TRACE ("(%p)->(hwnd=%p,%s,%p)\n",
517 this, hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
524 if (IsEqualIID (riid
, IID_IDropTarget
))
526 hr
= this->QueryInterface (IID_IDropTarget
, ppvOut
);
528 else if (IsEqualIID (riid
, IID_IContextMenu
))
530 WARN ("IContextMenu not implemented\n");
533 else if (IsEqualIID (riid
, IID_IShellView
))
535 hr
= IShellView_Constructor((IShellFolder
*)this, &pShellView
);
537 hr
= pShellView
->QueryInterface(riid
, ppvOut
);
539 TRACE ("-- (%p)->(interface=%p)\n", this, ppvOut
);
543 /**************************************************************************
544 * CDesktopFolder::GetAttributesOf
546 HRESULT WINAPI
CDesktopFolder::GetAttributesOf(
548 PCUITEMID_CHILD_ARRAY apidl
,
552 static const DWORD dwDesktopAttributes
=
553 SFGAO_HASSUBFOLDER
| SFGAO_FILESYSTEM
| SFGAO_FOLDER
| SFGAO_FILESYSANCESTOR
|
554 SFGAO_STORAGEANCESTOR
| SFGAO_HASPROPSHEET
| SFGAO_STORAGE
| SFGAO_CANLINK
;
555 static const DWORD dwMyComputerAttributes
=
556 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
557 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_CANLINK
;
558 static DWORD dwMyNetPlacesAttributes
=
559 SFGAO_CANRENAME
| SFGAO_CANDELETE
| SFGAO_HASPROPSHEET
| SFGAO_DROPTARGET
|
560 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_CANLINK
;
562 TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n",
563 this, cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
572 *rgfInOut
&= dwDesktopAttributes
;
575 /* TODO: always add SFGAO_CANLINK */
576 for (UINT i
= 0; i
< cidl
; ++i
)
579 if (_ILIsDesktop(*apidl
))
580 *rgfInOut
&= dwDesktopAttributes
;
581 else if (_ILIsMyComputer(apidl
[i
]))
582 *rgfInOut
&= dwMyComputerAttributes
;
583 else if (_ILIsNetHood(apidl
[i
]))
584 *rgfInOut
&= dwMyNetPlacesAttributes
;
586 SHELL32_GetItemAttributes((IShellFolder
*)this, apidl
[i
], rgfInOut
);
589 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
590 *rgfInOut
&= ~SFGAO_VALIDATE
;
592 TRACE("-- result=0x%08x\n", *rgfInOut
);
597 /**************************************************************************
598 * CDesktopFolder::GetUIObjectOf
601 * HWND hwndOwner, //[in ] Parent window for any output
602 * UINT cidl, //[in ] array size
603 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
604 * REFIID riid, //[in ] Requested Interface
605 * UINT* prgfInOut, //[ ] reserved
606 * LPVOID* ppvObject) //[out] Resulting Interface
609 HRESULT WINAPI
CDesktopFolder::GetUIObjectOf(
612 PCUITEMID_CHILD_ARRAY apidl
,
618 IUnknown
*pObj
= NULL
;
619 HRESULT hr
= E_INVALIDARG
;
621 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
622 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
629 if (IsEqualIID (riid
, IID_IContextMenu
))
631 hr
= CDefFolderMenu_Create2(pidlRoot
, hwndOwner
, cidl
, apidl
, (IShellFolder
*)this, NULL
, 0, NULL
, (IContextMenu
**)&pObj
);
633 else if (IsEqualIID (riid
, IID_IDataObject
) && (cidl
>= 1))
635 hr
= IDataObject_Constructor( hwndOwner
, pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
637 else if (IsEqualIID (riid
, IID_IExtractIconA
) && (cidl
== 1))
639 pidl
= ILCombine (pidlRoot
, apidl
[0]);
640 pObj
= IExtractIconA_Constructor (pidl
);
644 else if (IsEqualIID (riid
, IID_IExtractIconW
) && (cidl
== 1))
646 pidl
= ILCombine (pidlRoot
, apidl
[0]);
647 pObj
= IExtractIconW_Constructor (pidl
);
651 else if (IsEqualIID (riid
, IID_IDropTarget
))
653 /* only interested in attempting to bind to shell folders, not files, semicolon intentionate */
654 if (cidl
!= 1 || FAILED(hr
= this->_GetDropTarget(apidl
[0], (LPVOID
*) &pObj
)))
656 IDropTarget
* pDt
= NULL
;
657 hr
= this->QueryInterface(IID_PPV_ARG(IDropTarget
, &pDt
));
661 else if ((IsEqualIID(riid
, IID_IShellLinkW
) ||
662 IsEqualIID(riid
, IID_IShellLinkA
)) && (cidl
== 1))
664 pidl
= ILCombine (pidlRoot
, apidl
[0]);
665 hr
= IShellLink_ConstructFromFile(NULL
, riid
, pidl
, (LPVOID
*)&pObj
);
671 if (SUCCEEDED(hr
) && !pObj
)
675 TRACE ("(%p)->hr=0x%08x\n", this, hr
);
679 /**************************************************************************
680 * CDesktopFolder::GetDisplayNameOf
683 * special case: pidl = null gives desktop-name back
685 HRESULT WINAPI
CDesktopFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
690 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", this, pidl
, dwFlags
, strRet
);
696 pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
698 return E_OUTOFMEMORY
;
700 if (_ILIsDesktop (pidl
))
702 if ((GET_SHGDN_RELATION (dwFlags
) == SHGDN_NORMAL
) &&
703 (GET_SHGDN_FOR (dwFlags
) & SHGDN_FORPARSING
))
704 wcscpy(pszPath
, sPathTarget
);
706 HCR_GetClassNameW(CLSID_ShellDesktop
, pszPath
, MAX_PATH
);
708 else if (_ILIsPidlSimple (pidl
))
712 if ((clsid
= _ILGetGUIDPointer (pidl
)))
714 if (GET_SHGDN_FOR (dwFlags
) & SHGDN_FORPARSING
)
716 int bWantsForParsing
;
719 * We can only get a filesystem path from a shellfolder if the
720 * value WantsFORPARSING in CLSID\\{...}\\shellfolder exists.
722 * Exception: The MyComputer folder doesn't have this key,
723 * but any other filesystem backed folder it needs it.
725 if (IsEqualIID (*clsid
, CLSID_MyComputer
))
727 bWantsForParsing
= TRUE
;
731 /* get the "WantsFORPARSING" flag from the registry */
732 static const WCHAR clsidW
[] =
733 { 'C', 'L', 'S', 'I', 'D', '\\', 0 };
734 static const WCHAR shellfolderW
[] =
735 { '\\', 's', 'h', 'e', 'l', 'l', 'f', 'o', 'l', 'd', 'e', 'r', 0 };
736 static const WCHAR wantsForParsingW
[] =
737 { 'W', 'a', 'n', 't', 's', 'F', 'o', 'r', 'P', 'a', 'r', 's', 'i', 'n',
740 WCHAR szRegPath
[100];
743 wcscpy (szRegPath
, clsidW
);
744 SHELL32_GUIDToStringW (*clsid
, &szRegPath
[6]);
745 wcscat (szRegPath
, shellfolderW
);
746 r
= SHGetValueW(HKEY_CLASSES_ROOT
, szRegPath
,
747 wantsForParsingW
, NULL
, NULL
, NULL
);
748 if (r
== ERROR_SUCCESS
)
749 bWantsForParsing
= TRUE
;
751 bWantsForParsing
= FALSE
;
754 if ((GET_SHGDN_RELATION (dwFlags
) == SHGDN_NORMAL
) &&
758 * we need the filesystem path to the destination folder.
759 * Only the folder itself can know it
761 hr
= SHELL32_GetDisplayNameOfChild (this, pidl
, dwFlags
,
767 /* parsing name like ::{...} */
770 SHELL32_GUIDToStringW (*clsid
, &pszPath
[2]);
775 /* user friendly name */
776 HCR_GetClassNameW (*clsid
, pszPath
, MAX_PATH
);
783 /* file system folder or file rooted at the desktop */
784 if ((GET_SHGDN_FOR(dwFlags
) == SHGDN_FORPARSING
) &&
785 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
))
787 lstrcpynW(pszPath
, sPathTarget
, MAX_PATH
- 1);
788 PathAddBackslashW(pszPath
);
789 cLen
= wcslen(pszPath
);
792 _ILSimpleGetTextW(pidl
, pszPath
+ cLen
, MAX_PATH
- cLen
);
793 if (!_ILIsFolder(pidl
))
794 SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
796 if (GetFileAttributes(pszPath
) == INVALID_FILE_ATTRIBUTES
)
798 /* file system folder or file rooted at the AllUsers desktop */
799 if ((GET_SHGDN_FOR(dwFlags
) == SHGDN_FORPARSING
) &&
800 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
))
802 SHGetSpecialFolderPathW(0, pszPath
, CSIDL_COMMON_DESKTOPDIRECTORY
, FALSE
);
803 PathAddBackslashW(pszPath
);
804 cLen
= wcslen(pszPath
);
807 _ILSimpleGetTextW(pidl
, pszPath
+ cLen
, MAX_PATH
- cLen
);
808 if (!_ILIsFolder(pidl
))
809 SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
815 /* a complex pidl, let the subfolder do the work */
816 hr
= SHELL32_GetDisplayNameOfChild (this, pidl
, dwFlags
,
822 /* Win9x always returns ANSI strings, NT always returns Unicode strings */
823 if (GetVersion() & 0x80000000)
825 strRet
->uType
= STRRET_CSTR
;
826 if (!WideCharToMultiByte(CP_ACP
, 0, pszPath
, -1, strRet
->cStr
, MAX_PATH
,
828 strRet
->cStr
[0] = '\0';
829 CoTaskMemFree(pszPath
);
833 strRet
->uType
= STRRET_WSTR
;
834 strRet
->pOleStr
= pszPath
;
838 CoTaskMemFree(pszPath
);
840 TRACE ("-- (%p)->(%s,0x%08x)\n", this,
841 strRet
->uType
== STRRET_CSTR
? strRet
->cStr
:
842 debugstr_w(strRet
->pOleStr
), hr
);
846 /**************************************************************************
847 * CDesktopFolder::SetNameOf
848 * Changes the name of a file object or subfolder, possibly changing its item
849 * identifier in the process.
852 * HWND hwndOwner, //[in ] Owner window for output
853 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
854 * LPCOLESTR lpszName, //[in ] the items new display name
855 * DWORD dwFlags, //[in ] SHGNO formatting flags
856 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
858 HRESULT WINAPI
CDesktopFolder::SetNameOf(
860 PCUITEMID_CHILD pidl
, /* simple pidl */
863 PITEMID_CHILD
*pPidlOut
)
865 CComPtr
<IShellFolder2
> psf
;
867 WCHAR szSrc
[MAX_PATH
+ 1], szDest
[MAX_PATH
+ 1];
869 BOOL bIsFolder
= _ILIsFolder (ILFindLastID (pidl
));
871 TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner
, pidl
,
872 debugstr_w (lpName
), dwFlags
, pPidlOut
);
874 if (_ILGetGUIDPointer(pidl
))
876 if (SUCCEEDED(BindToObject(pidl
, NULL
, IID_PPV_ARG(IShellFolder2
, &psf
))))
878 hr
= psf
->SetNameOf(hwndOwner
, pidl
, lpName
, dwFlags
, pPidlOut
);
883 /* build source path */
884 lstrcpynW(szSrc
, sPathTarget
, MAX_PATH
);
885 ptr
= PathAddBackslashW (szSrc
);
887 _ILSimpleGetTextW (pidl
, ptr
, MAX_PATH
+ 1 - (ptr
- szSrc
));
889 /* build destination path */
890 if (dwFlags
== SHGDN_NORMAL
|| dwFlags
& SHGDN_INFOLDER
) {
891 lstrcpynW(szDest
, sPathTarget
, MAX_PATH
);
892 ptr
= PathAddBackslashW (szDest
);
894 lstrcpynW(ptr
, lpName
, MAX_PATH
+ 1 - (ptr
- szDest
));
896 lstrcpynW(szDest
, lpName
, MAX_PATH
);
898 if(!(dwFlags
& SHGDN_FORPARSING
) && SHELL_FS_HideExtension(szSrc
)) {
899 WCHAR
*ext
= PathFindExtensionW(szSrc
);
901 INT len
= wcslen(szDest
);
902 lstrcpynW(szDest
+ len
, ext
, MAX_PATH
- len
);
906 if (!memcmp(szSrc
, szDest
, (wcslen(szDest
) + 1) * sizeof(WCHAR
)))
908 /* src and destination is the same */
911 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
916 TRACE ("src=%s dest=%s\n", debugstr_w(szSrc
), debugstr_w(szDest
));
917 if (MoveFileW (szSrc
, szDest
))
922 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
924 SHChangeNotify (bIsFolder
? SHCNE_RENAMEFOLDER
: SHCNE_RENAMEITEM
,
925 SHCNF_PATHW
, szSrc
, szDest
);
932 HRESULT WINAPI
CDesktopFolder::GetDefaultSearchGUID(GUID
*pguid
)
934 FIXME ("(%p)\n", this);
938 HRESULT WINAPI
CDesktopFolder::EnumSearches(IEnumExtraSearch
**ppenum
)
940 FIXME ("(%p)\n", this);
944 HRESULT WINAPI
CDesktopFolder::GetDefaultColumn(DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
946 TRACE ("(%p)\n", this);
956 HRESULT WINAPI
CDesktopFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
958 TRACE ("(%p)\n", this);
960 if (!pcsFlags
|| iColumn
>= DESKTOPSHELLVIEWCOLUMNS
)
963 *pcsFlags
= DesktopSFHeader
[iColumn
].pcsFlags
;
968 HRESULT WINAPI
CDesktopFolder::GetDetailsEx(
969 PCUITEMID_CHILD pidl
,
970 const SHCOLUMNID
*pscid
,
973 FIXME ("(%p)\n", this);
978 HRESULT WINAPI
CDesktopFolder::GetDetailsOf(
979 PCUITEMID_CHILD pidl
,
985 TRACE ("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
987 if (!psd
|| iColumn
>= DESKTOPSHELLVIEWCOLUMNS
)
992 psd
->fmt
= DesktopSFHeader
[iColumn
].fmt
;
993 psd
->cxChar
= DesktopSFHeader
[iColumn
].cxChar
;
994 psd
->str
.uType
= STRRET_CSTR
;
995 LoadStringA (shell32_hInstance
, DesktopSFHeader
[iColumn
].colnameid
,
996 psd
->str
.cStr
, MAX_PATH
);
1000 /* the data from the pidl */
1001 psd
->str
.uType
= STRRET_CSTR
;
1005 hr
= GetDisplayNameOf(pidl
,
1006 SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
1009 _ILGetFileSize (pidl
, psd
->str
.cStr
, MAX_PATH
);
1012 _ILGetFileType (pidl
, psd
->str
.cStr
, MAX_PATH
);
1015 _ILGetFileDate (pidl
, psd
->str
.cStr
, MAX_PATH
);
1017 case 4: /* attributes */
1018 _ILGetFileAttributes (pidl
, psd
->str
.cStr
, MAX_PATH
);
1025 HRESULT WINAPI
CDesktopFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
*pscid
)
1027 FIXME ("(%p)\n", this);
1031 HRESULT WINAPI
CDesktopFolder::GetClassID(CLSID
*lpClassId
)
1033 TRACE ("(%p)\n", this);
1038 *lpClassId
= CLSID_ShellDesktop
;
1043 HRESULT WINAPI
CDesktopFolder::Initialize(LPCITEMIDLIST pidl
)
1045 TRACE ("(%p)->(%p)\n", this, pidl
);
1050 HRESULT WINAPI
CDesktopFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
1052 TRACE ("(%p)->(%p)\n", this, pidl
);
1054 if (!pidl
) return E_POINTER
;
1055 *pidl
= ILClone (pidlRoot
);
1059 HRESULT WINAPI
CDesktopFolder::GetUniqueName(LPWSTR pwszName
, UINT uLen
)
1061 CComPtr
<IEnumIDList
> penum
;
1063 WCHAR wszText
[MAX_PATH
];
1064 WCHAR wszNewFolder
[25];
1065 const WCHAR wszFormat
[] = {'%', 's', ' ', '%', 'd', 0 };
1067 LoadStringW(shell32_hInstance
, IDS_NEWFOLDER
, wszNewFolder
, sizeof(wszNewFolder
) / sizeof(WCHAR
));
1069 TRACE ("(%p)(%p %u)\n", this, pwszName
, uLen
);
1071 if (uLen
< sizeof(wszNewFolder
) / sizeof(WCHAR
) + 3)
1074 lstrcpynW (pwszName
, wszNewFolder
, uLen
);
1077 SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
| SHCONTF_INCLUDEHIDDEN
, &penum
);
1085 while (S_OK
== penum
->Next(1, &pidl
, &dwFetched
) &&
1087 _ILSimpleGetTextW (pidl
, wszText
, MAX_PATH
);
1088 if (0 == lstrcmpiW (wszText
, pwszName
)) {
1089 _snwprintf (pwszName
, uLen
, wszFormat
, wszNewFolder
, i
++);
1102 HRESULT WINAPI
CDesktopFolder::AddFolder(HWND hwnd
, LPCWSTR pwszName
, LPITEMIDLIST
*ppidlOut
)
1104 WCHAR wszNewDir
[MAX_PATH
];
1106 HRESULT hres
= E_FAIL
;
1108 TRACE ("(%p)(%s %p)\n", this, debugstr_w(pwszName
), ppidlOut
);
1112 lstrcpynW(wszNewDir
, sPathTarget
, MAX_PATH
);
1113 PathAppendW(wszNewDir
, pwszName
);
1114 bRes
= CreateDirectoryW (wszNewDir
, NULL
);
1117 SHChangeNotify (SHCNE_MKDIR
, SHCNF_PATHW
, wszNewDir
, NULL
);
1120 hres
= _ILCreateFromPathW(wszNewDir
, ppidlOut
);
1126 HRESULT WINAPI
CDesktopFolder::DeleteItems(UINT cidl
, LPCITEMIDLIST
*apidl
)
1130 WCHAR wszPath
[MAX_PATH
];
1131 WCHAR wszCaption
[50];
1132 WCHAR
*wszPathsList
;
1134 WCHAR
*wszCurrentPath
;
1135 UINT bRestoreWithDeskCpl
= FALSE
;
1138 TRACE ("(%p)(%u %p)\n", this, cidl
, apidl
);
1139 if (cidl
== 0) return S_OK
;
1141 for(i
= 0; i
< cidl
; i
++)
1143 if (_ILIsMyComputer(apidl
[i
]))
1144 bRestoreWithDeskCpl
++;
1145 else if (_ILIsNetHood(apidl
[i
]))
1146 bRestoreWithDeskCpl
++;
1147 else if (_ILIsMyDocuments(apidl
[i
]))
1148 bRestoreWithDeskCpl
++;
1151 if (bRestoreWithDeskCpl
)
1153 /* FIXME use FormatMessage
1154 * use a similar message resource as in windows
1156 LoadStringW(shell32_hInstance
, IDS_DELETEMULTIPLE_TEXT
, wszPath
, sizeof(wszPath
) / sizeof(WCHAR
));
1157 wszPath
[(sizeof(wszPath
)/sizeof(WCHAR
))-1] = 0;
1159 LoadStringW(shell32_hInstance
, IDS_DELETEITEM_CAPTION
, wszCaption
, sizeof(wszCaption
) / sizeof(WCHAR
));
1160 wszCaption
[(sizeof(wszCaption
)/sizeof(WCHAR
))-1] = 0;
1162 res
= SHELL_ConfirmMsgBox(GetActiveWindow(), wszPath
, wszCaption
, NULL
, cidl
> 1);
1163 if (res
== IDC_YESTOALL
|| res
== IDYES
)
1165 for(i
= 0; i
< cidl
; i
++)
1167 if (_ILIsMyComputer(apidl
[i
]))
1168 SetNamespaceExtensionVisibleStatus(L
"{20D04FE0-3AEA-1069-A2D8-08002B30309D}", 0x1);
1169 else if (_ILIsNetHood(apidl
[i
]))
1170 SetNamespaceExtensionVisibleStatus(L
"{208D2C60-3AEA-1069-A2D7-08002B30309D}", 0x1);
1171 else if (_ILIsMyDocuments(apidl
[i
]))
1172 SetNamespaceExtensionVisibleStatus(L
"{450D8FBA-AD25-11D0-98A8-0800361B1103}", 0x1);
1177 lstrcpynW(wszPath
, sPathTarget
, MAX_PATH
);
1181 PathAddBackslashW(wszPath
);
1182 wszPathsList
= BuildPathsList(wszPath
, cidl
, apidl
);
1184 ZeroMemory(&op
, sizeof(op
));
1185 op
.hwnd
= GetActiveWindow();
1186 op
.wFunc
= FO_DELETE
;
1187 op
.pFrom
= wszPathsList
;
1188 op
.fFlags
= FOF_ALLOWUNDO
;
1189 if (SHFileOperationW(&op
))
1191 WARN("SHFileOperation failed\n");
1197 /* we currently need to manually send the notifies */
1198 wszCurrentPath
= wszPathsList
;
1199 for (i
= 0; i
< cidl
; i
++)
1203 if (_ILIsFolder(apidl
[i
]))
1204 wEventId
= SHCNE_RMDIR
;
1205 else if (_ILIsValue(apidl
[i
]))
1206 wEventId
= SHCNE_DELETE
;
1210 /* check if file exists */
1211 if (GetFileAttributesW(wszCurrentPath
) == INVALID_FILE_ATTRIBUTES
)
1213 LPITEMIDLIST pidl
= ILCombine(pidlRoot
, apidl
[i
]);
1214 SHChangeNotify(wEventId
, SHCNF_IDLIST
, pidl
, NULL
);
1218 wszCurrentPath
+= wcslen(wszCurrentPath
) + 1;
1220 HeapFree(GetProcessHeap(), 0, wszPathsList
);
1224 HRESULT WINAPI
CDesktopFolder::CopyItems(IShellFolder
*pSFFrom
, UINT cidl
, LPCITEMIDLIST
*apidl
, bool bCopy
)
1226 CComPtr
<IPersistFolder2
> ppf2
;
1227 WCHAR szSrcPath
[MAX_PATH
];
1228 WCHAR szTargetPath
[MAX_PATH
];
1231 LPWSTR pszSrc
, pszTarget
, pszSrcList
, pszTargetList
, pszFileName
;
1235 TRACE ("(%p)->(%p,%u,%p)\n", this, pSFFrom
, cidl
, apidl
);
1237 pSFFrom
->QueryInterface(IID_PPV_ARG(IPersistFolder2
, &ppf2
));
1240 if (FAILED(ppf2
->GetCurFolder(&pidl
)))
1243 if (FAILED(pSFFrom
->GetDisplayNameOf(pidl
, SHGDN_FORPARSING
, &strRet
)))
1249 if (FAILED(StrRetToBufW(&strRet
, pidl
, szSrcPath
, MAX_PATH
)))
1256 pszSrc
= PathAddBackslashW (szSrcPath
);
1258 wcscpy(szTargetPath
, sPathTarget
);
1259 pszTarget
= PathAddBackslashW (szTargetPath
);
1261 pszSrcList
= BuildPathsList(szSrcPath
, cidl
, apidl
);
1262 pszTargetList
= BuildPathsList(szTargetPath
, cidl
, apidl
);
1264 if (!pszSrcList
|| !pszTargetList
)
1267 HeapFree(GetProcessHeap(), 0, pszSrcList
);
1270 HeapFree(GetProcessHeap(), 0, pszTargetList
);
1273 return E_OUTOFMEMORY
;
1275 ZeroMemory(&op
, sizeof(op
));
1278 /* remove trailing backslash */
1281 op
.pFrom
= szSrcPath
;
1285 op
.pFrom
= pszSrcList
;
1288 if (!pszTargetList
[0])
1290 /* remove trailing backslash */
1291 if (pszTarget
- szTargetPath
> 3)
1294 pszTarget
[0] = L
'\0';
1298 pszTarget
[1] = L
'\0';
1301 op
.pTo
= szTargetPath
;
1306 op
.pTo
= pszTargetList
;
1307 op
.fFlags
= FOF_MULTIDESTFILES
;
1309 op
.hwnd
= GetActiveWindow();
1310 op
.wFunc
= bCopy
? FO_COPY
: FO_MOVE
;
1311 op
.fFlags
|= FOF_ALLOWUNDO
| FOF_NOCONFIRMMKDIR
;
1313 res
= SHFileOperationW(&op
);
1315 if (res
== DE_SAMEFILE
)
1317 length
= wcslen(szTargetPath
);
1320 pszFileName
= wcsrchr(pszSrcList
, '\\');
1323 if (LoadStringW(shell32_hInstance
, IDS_COPY_OF
, pszTarget
, MAX_PATH
- length
))
1325 wcscat(szTargetPath
, L
" ");
1328 wcscat(szTargetPath
, pszFileName
);
1329 op
.pTo
= szTargetPath
;
1331 res
= SHFileOperationW(&op
);
1335 HeapFree(GetProcessHeap(), 0, pszSrcList
);
1336 HeapFree(GetProcessHeap(), 0, pszTargetList
);
1346 /****************************************************************************
1347 * IDropTarget implementation
1349 * This should allow two somewhat separate things, copying files to the users directory,
1350 * as well as allowing icons to be moved anywhere and updating the registry to save.
1352 * The first thing I think is best done using fs.cpp to prevent WET code. So we'll simulate
1353 * a drop to the user's home directory. The second will look at the pointer location and
1354 * set sensible places for the icons to live.
1357 BOOL
CDesktopFolder::QueryDrop(DWORD dwKeyState
, LPDWORD pdwEffect
)
1359 /* TODO Windows does different drop effects if dragging across drives.
1360 i.e., it will copy instead of move if the directories are on different disks. */
1362 DWORD dwEffect
= DROPEFFECT_MOVE
;
1364 *pdwEffect
= DROPEFFECT_NONE
;
1366 if (fAcceptFmt
) { /* Does our interpretation of the keystate ... */
1367 *pdwEffect
= KeyStateToDropEffect (dwKeyState
);
1369 if (*pdwEffect
== DROPEFFECT_NONE
)
1370 *pdwEffect
= dwEffect
;
1372 /* ... matches the desired effect ? */
1373 if (dwEffect
& *pdwEffect
) {
1380 HRESULT WINAPI
CDesktopFolder::DragEnter(IDataObject
*pDataObject
,
1381 DWORD dwKeyState
, POINTL pt
, DWORD
*pdwEffect
)
1383 TRACE("(%p)->(DataObject=%p)\n", this, pDataObject
);
1388 InitFormatEtc (fmt
, cfShellIDList
, TYMED_HGLOBAL
);
1389 InitFormatEtc (fmt2
, CF_HDROP
, TYMED_HGLOBAL
);
1391 if (SUCCEEDED(pDataObject
->QueryGetData(&fmt
)))
1393 else if (SUCCEEDED(pDataObject
->QueryGetData(&fmt2
)))
1396 QueryDrop(dwKeyState
, pdwEffect
);
1400 HRESULT WINAPI
CDesktopFolder::DragOver(DWORD dwKeyState
, POINTL pt
,
1403 TRACE("(%p)\n", this);
1406 return E_INVALIDARG
;
1408 QueryDrop(dwKeyState
, pdwEffect
);
1413 HRESULT WINAPI
CDesktopFolder::DragLeave()
1415 TRACE("(%p)\n", this);
1420 HRESULT WINAPI
CDesktopFolder::Drop(IDataObject
*pDataObject
,
1421 DWORD dwKeyState
, POINTL pt
, DWORD
*pdwEffect
)
1423 TRACE("(%p) object dropped desktop\n", this);
1426 bool passthroughtofs
= FALSE
;
1427 FORMATETC formatetc
;
1428 InitFormatEtc(formatetc
, RegisterClipboardFormatW(CFSTR_SHELLIDLIST
), TYMED_HGLOBAL
);
1430 HRESULT hr
= pDataObject
->GetData(&formatetc
, &medium
);
1433 /* lock the handle */
1434 LPIDA lpcida
= (LPIDA
)GlobalLock(medium
.hGlobal
);
1437 ReleaseStgMedium(&medium
);
1441 /* convert the clipboard data into pidl (pointer to id list) */
1443 LPITEMIDLIST
*apidl
= _ILCopyCidaToaPidl(&pidl
, lpcida
);
1446 ReleaseStgMedium(&medium
);
1449 passthroughtofs
= !_ILIsDesktop(pidl
) || (dwKeyState
& MK_CONTROL
);
1451 _ILFreeaPidl(apidl
, lpcida
->cidl
);
1452 ReleaseStgMedium(&medium
);
1456 InitFormatEtc (formatetc
, CF_HDROP
, TYMED_HGLOBAL
);
1457 if (SUCCEEDED(pDataObject
->QueryGetData(&formatetc
)))
1459 passthroughtofs
= TRUE
;
1462 /* We only want to really move files around if they don't already
1463 come from the desktop, or we're linking or copying */
1464 if (passthroughtofs
)
1466 LPITEMIDLIST pidl
= NULL
;
1468 WCHAR szPath
[MAX_PATH
];
1471 /* build a complete path to create a simple pidl */
1472 lstrcpynW(szPath
, sPathTarget
, MAX_PATH
);
1473 /*pathPtr = */PathAddBackslashW(szPath
);
1474 //hr = _ILCreateFromPathW(szPath, &pidl);
1475 hr
= this->ParseDisplayName(NULL
, NULL
, szPath
, NULL
, &pidl
, NULL
);
1479 CComPtr
<IDropTarget
> pDT
;
1480 hr
= this->BindToObject(pidl
, NULL
, IID_PPV_ARG(IDropTarget
, &pDT
));
1481 CoTaskMemFree(pidl
);
1483 SHSimulateDrop(pDT
, pDataObject
, dwKeyState
, NULL
, pdwEffect
);
1485 ERR("Error Binding");
1488 ERR("Error creating from %s\n", debugstr_w(szPath
));
1491 /* Todo, rewrite the registry such that the icons are well placed.
1492 Blocked by no bags implementation. */
1496 HRESULT WINAPI
CDesktopFolder::_GetDropTarget(LPCITEMIDLIST pidl
, LPVOID
*ppvOut
) {
1499 TRACE("CFSFolder::_GetDropTarget entered\n");
1501 if (_ILGetGUIDPointer (pidl
) || _ILIsFolder (pidl
))
1502 return this->BindToObject(pidl
, NULL
, IID_IDropTarget
, ppvOut
);
1504 LPITEMIDLIST pidlNext
= NULL
;
1507 hr
= this->GetDisplayNameOf(pidl
, SHGDN_FORPARSING
, &strFile
);
1510 WCHAR wszPath
[MAX_PATH
];
1511 hr
= StrRetToBufW(&strFile
, pidl
, wszPath
, _countof(wszPath
));
1515 PathRemoveFileSpecW (wszPath
);
1516 hr
= this->ParseDisplayName(NULL
, NULL
, wszPath
, NULL
, &pidlNext
, NULL
);
1520 CComPtr
<IShellFolder
> psf
;
1521 hr
= this->BindToObject(pidlNext
, NULL
, IID_PPV_ARG(IShellFolder
, &psf
));
1522 CoTaskMemFree(pidlNext
);
1525 hr
= psf
->GetUIObjectOf(NULL
, 1, &pidl
, IID_IDropTarget
, NULL
, ppvOut
);
1527 ERR("FS GetUIObjectOf failed: %x\n", hr
);
1530 ERR("BindToObject failed: %x\n", hr
);
1533 ERR("ParseDisplayName failed: %x\n", hr
);
1536 ERR("StrRetToBufW failed: %x\n", hr
);
1539 ERR("GetDisplayNameOf failed: %x\n", hr
);