5 * Copyright 1997 Marcus Meissner
6 * Copyright 1998, 1999, 2002 Juergen Schmied
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 CFileSysEnum should do an initial FindFirstFile and do a FindNextFile as each file is
29 returned by Next. When the enumerator is created, it can do numerous additional operations
30 including formatting a drive, reconnecting a network share drive, and requesting a disk
31 be inserted in a removable drive.
34 /***********************************************************************
35 * IShellFolder implementation
39 public CEnumIDListBase
45 HRESULT WINAPI
Initialize(LPWSTR sPathTarget
, DWORD dwFlags
);
47 BEGIN_COM_MAP(CFileSysEnum
)
48 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList
, IEnumIDList
)
52 CFileSysEnum::CFileSysEnum()
56 CFileSysEnum::~CFileSysEnum()
60 HRESULT WINAPI
CFileSysEnum::Initialize(LPWSTR sPathTarget
, DWORD dwFlags
)
62 return CreateFolderEnumList(sPathTarget
, dwFlags
);
65 CFSFolder::CFSFolder()
67 pclsid
= (CLSID
*)&CLSID_ShellFSFolder
;
70 m_bGroupPolicyActive
= 0;
73 CFSFolder::~CFSFolder()
75 TRACE("-- destroying IShellFolder(%p)\n", this);
82 static const shvheader GenericSFHeader
[] = {
83 {IDS_SHV_COLUMN_NAME
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
84 {IDS_SHV_COLUMN_COMMENTS
, SHCOLSTATE_TYPE_STR
, LVCFMT_LEFT
, 0},
85 {IDS_SHV_COLUMN_TYPE
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 10},
86 {IDS_SHV_COLUMN_SIZE
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
87 {IDS_SHV_COLUMN_MODIFIED
, SHCOLSTATE_TYPE_DATE
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 12},
88 {IDS_SHV_COLUMN_ATTRIBUTES
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 10}
91 #define GENERICSHELLVIEWCOLUMNS 6
93 /**************************************************************************
94 * SHELL32_CreatePidlFromBindCtx [internal]
96 * If the caller bound File System Bind Data, assume it is the
97 * find data for the path.
98 * This allows binding of paths that don't exist.
100 LPITEMIDLIST
SHELL32_CreatePidlFromBindCtx(IBindCtx
*pbc
, LPCWSTR path
)
102 IFileSystemBindData
*fsbd
= NULL
;
103 LPITEMIDLIST pidl
= NULL
;
104 IUnknown
*param
= NULL
;
105 WIN32_FIND_DATAW wfd
;
108 TRACE("%p %s\n", pbc
, debugstr_w(path
));
113 /* see if the caller bound File System Bind Data */
114 r
= pbc
->GetObjectParam((LPOLESTR
)STR_FILE_SYS_BIND_DATA
, ¶m
);
118 r
= param
->QueryInterface(IID_PPV_ARG(IFileSystemBindData
,&fsbd
));
121 r
= fsbd
->GetFindData(&wfd
);
124 lstrcpynW(&wfd
.cFileName
[0], path
, MAX_PATH
);
125 pidl
= _ILCreateFromFindDataW(&wfd
);
133 /**************************************************************************
134 * CFSFolder::ParseDisplayName {SHELL32}
136 * Parse a display name.
139 * hwndOwner [in] Parent window for any message's
140 * pbc [in] optional FileSystemBindData context
141 * lpszDisplayName [in] Unicode displayname.
142 * pchEaten [out] (unicode) characters processed
143 * ppidl [out] complex pidl to item
144 * pdwAttributes [out] items attributes
147 * Every folder tries to parse only its own (the leftmost) pidl and creates a
148 * subfolder to evaluate the remaining parts.
149 * Now we can parse into namespaces implemented by shell extensions
151 * Behaviour on win98: lpszDisplayName=NULL -> crash
152 * lpszDisplayName="" -> returns mycoputer-pidl
155 * pdwAttributes is not set
156 * pchEaten is not set like in windows
158 HRESULT WINAPI
CFSFolder::ParseDisplayName(HWND hwndOwner
,
160 LPOLESTR lpszDisplayName
,
161 DWORD
*pchEaten
, PIDLIST_RELATIVE
*ppidl
,
162 DWORD
*pdwAttributes
)
164 HRESULT hr
= E_INVALIDARG
;
165 LPCWSTR szNext
= NULL
;
166 WCHAR szElement
[MAX_PATH
];
167 WCHAR szPath
[MAX_PATH
];
168 LPITEMIDLIST pidlTemp
= NULL
;
171 TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
172 this, hwndOwner
, pbc
, lpszDisplayName
, debugstr_w (lpszDisplayName
),
173 pchEaten
, ppidl
, pdwAttributes
);
178 if (!lpszDisplayName
)
187 *pchEaten
= 0; /* strange but like the original */
189 if (*lpszDisplayName
)
191 /* get the next element */
192 szNext
= GetNextElementW (lpszDisplayName
, szElement
, MAX_PATH
);
194 pidlTemp
= SHELL32_CreatePidlFromBindCtx(pbc
, szElement
);
195 if (pidlTemp
!= NULL
)
197 /* We are creating an id list without ensuring that the items exist.
198 If we have a remaining path, this must be a folder.
199 We have to do it now because it is set as a file by default */
202 pidlTemp
->mkid
.abID
[0] = PT_FOLDER
;
208 /* build the full pathname to the element */
209 lstrcpynW(szPath
, sPathTarget
, MAX_PATH
- 1);
210 PathAddBackslashW(szPath
);
211 len
= wcslen(szPath
);
212 lstrcpynW(szPath
+ len
, szElement
, MAX_PATH
- len
);
215 hr
= _ILCreateFromPathW(szPath
, &pidlTemp
);
220 if (szNext
&& *szNext
)
222 /* try to analyse the next element */
223 hr
= SHELL32_ParseNextElement(this, hwndOwner
, pbc
,
224 &pidlTemp
, (LPOLESTR
) szNext
, pchEaten
, pdwAttributes
);
228 /* it's the last element */
229 if (pdwAttributes
&& *pdwAttributes
)
230 hr
= SHELL32_GetFSItemAttributes(this, pidlTemp
, pdwAttributes
);
240 TRACE("(%p)->(-- pidl=%p ret=0x%08x)\n", this, ppidl
? *ppidl
: 0, hr
);
245 /**************************************************************************
246 * CFSFolder::EnumObjects
248 * HWND hwndOwner, //[in ] Parent Window
249 * DWORD grfFlags, //[in ] SHCONTF enumeration mask
250 * LPENUMIDLIST* ppenumIDList //[out] IEnumIDList interface
252 HRESULT WINAPI
CFSFolder::EnumObjects(
255 LPENUMIDLIST
*ppEnumIDList
)
257 return ShellObjectCreatorInit
<CFileSysEnum
>(sPathTarget
, dwFlags
, IID_PPV_ARG(IEnumIDList
, ppEnumIDList
));
260 /**************************************************************************
261 * CFSFolder::BindToObject
263 * LPCITEMIDLIST pidl, //[in ] relative pidl to open
264 * LPBC pbc, //[in ] optional FileSystemBindData context
265 * REFIID riid, //[in ] Initial Interface
266 * LPVOID* ppvObject //[out] Interface*
268 HRESULT WINAPI
CFSFolder::BindToObject(
269 PCUIDLIST_RELATIVE pidl
,
274 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this, pidl
, pbc
,
275 shdebugstr_guid(&riid
), ppvOut
);
277 return SHELL32_BindToFS(pidlRoot
, sPathTarget
, pidl
, riid
, ppvOut
);
280 /**************************************************************************
281 * CFSFolder::BindToStorage
283 * LPCITEMIDLIST pidl, //[in ] complex pidl to store
284 * LPBC pbc, //[in ] reserved
285 * REFIID riid, //[in ] Initial storage interface
286 * LPVOID* ppvObject //[out] Interface* returned
288 HRESULT WINAPI
CFSFolder::BindToStorage(
289 PCUIDLIST_RELATIVE pidl
,
294 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this, pidl
, pbcReserved
,
295 shdebugstr_guid (&riid
), ppvOut
);
301 /**************************************************************************
302 * CFSFolder::CompareIDs
305 HRESULT WINAPI
CFSFolder::CompareIDs(LPARAM lParam
,
306 PCUIDLIST_RELATIVE pidl1
,
307 PCUIDLIST_RELATIVE pidl2
)
309 LPPIDLDATA pData1
= _ILGetDataPointer(pidl1
);
310 LPPIDLDATA pData2
= _ILGetDataPointer(pidl2
);
311 FileStructW
* pDataW1
= _ILGetFileStructW(pidl1
);
312 FileStructW
* pDataW2
= _ILGetFileStructW(pidl2
);
313 BOOL bIsFolder1
= _ILIsFolder(pidl1
);
314 BOOL bIsFolder2
= _ILIsFolder(pidl2
);
315 LPWSTR pExtension1
, pExtension2
;
317 if (!pDataW1
|| !pDataW2
|| LOWORD(lParam
) >= GENERICSHELLVIEWCOLUMNS
)
320 /* When sorting between a File and a Folder, the Folder gets sorted first */
321 if (bIsFolder1
!= bIsFolder2
)
323 return MAKE_COMPARE_HRESULT(bIsFolder1
? -1 : 1);
327 switch (LOWORD(lParam
))
330 result
= wcsicmp(pDataW1
->wszName
, pDataW2
->wszName
);
332 case 1: /* Comments */
336 pExtension1
= PathFindExtensionW(pDataW1
->wszName
);
337 pExtension2
= PathFindExtensionW(pDataW2
->wszName
);
338 result
= wcsicmp(pExtension1
, pExtension2
);
341 result
= pData1
->u
.file
.dwFileSize
- pData2
->u
.file
.dwFileSize
;
343 case 4: /* Modified */
344 result
= pData1
->u
.file
.uFileDate
- pData2
->u
.file
.uFileDate
;
346 result
= pData1
->u
.file
.uFileTime
- pData2
->u
.file
.uFileTime
;
348 case 5: /* Attributes */
349 return SHELL32_CompareDetails(this, lParam
, pidl1
, pidl2
);
353 return SHELL32_CompareChildren(this, lParam
, pidl1
, pidl2
);
355 return MAKE_COMPARE_HRESULT(result
);
358 /**************************************************************************
359 * CFSFolder::CreateViewObject
361 HRESULT WINAPI
CFSFolder::CreateViewObject(HWND hwndOwner
,
362 REFIID riid
, LPVOID
* ppvOut
)
364 CComPtr
<IShellView
> pShellView
;
365 HRESULT hr
= E_INVALIDARG
;
367 TRACE ("(%p)->(hwnd=%p,%s,%p)\n", this, hwndOwner
, shdebugstr_guid (&riid
),
374 if (IsEqualIID (riid
, IID_IDropTarget
))
375 hr
= CFSDropTarget_CreateInstance(sPathTarget
, riid
, ppvOut
);
376 else if (IsEqualIID (riid
, IID_IContextMenu
))
380 AddClassKeyToArray(L
"Directory\\Background", hKeys
, &cKeys
);
383 dcm
.hwnd
= hwndOwner
;
385 dcm
.pidlFolder
= pidlRoot
;
391 dcm
.punkAssociationInfo
= NULL
;
392 hr
= SHCreateDefaultContextMenu (&dcm
, riid
, ppvOut
);
394 else if (IsEqualIID (riid
, IID_IShellView
))
396 SFV_CREATE sfvparams
= {sizeof(SFV_CREATE
), this};
397 hr
= SHCreateShellFolderView(&sfvparams
, (IShellView
**)ppvOut
);
400 TRACE("-- (%p)->(interface=%p)\n", this, ppvOut
);
404 /**************************************************************************
405 * CFSFolder::GetAttributesOf
408 * UINT cidl, //[in ] num elements in pidl array
409 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
410 * ULONG* rgfInOut) //[out] result array
413 HRESULT WINAPI
CFSFolder::GetAttributesOf(UINT cidl
,
414 PCUITEMID_CHILD_ARRAY apidl
, DWORD
* rgfInOut
)
428 LPCITEMIDLIST rpidl
= ILFindLastID(pidlRoot
);
430 if (_ILIsFolder(rpidl
) || _ILIsValue(rpidl
))
432 SHELL32_GetFSItemAttributes(this, rpidl
, rgfInOut
);
434 else if (_ILIsDrive(rpidl
))
436 IShellFolder
*psfParent
= NULL
;
437 hr
= SHBindToParent(pidlRoot
, IID_PPV_ARG(IShellFolder
, &psfParent
), NULL
);
440 hr
= psfParent
->GetAttributesOf(1, &rpidl
, (SFGAOF
*)rgfInOut
);
441 psfParent
->Release();
446 ERR("Got and unknown pidl!\n");
451 while (cidl
> 0 && *apidl
)
454 if(_ILIsFolder(*apidl
) || _ILIsValue(*apidl
))
455 SHELL32_GetFSItemAttributes(this, *apidl
, rgfInOut
);
457 ERR("Got an unknown type of pidl!!!\n");
462 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
463 *rgfInOut
&= ~SFGAO_VALIDATE
;
465 TRACE("-- result=0x%08x\n", *rgfInOut
);
470 /**************************************************************************
471 * CFSFolder::GetUIObjectOf
474 * HWND hwndOwner, //[in ] Parent window for any output
475 * UINT cidl, //[in ] array size
476 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
477 * REFIID riid, //[in ] Requested Interface
478 * UINT* prgfInOut, //[ ] reserved
479 * LPVOID* ppvObject) //[out] Resulting Interface
482 * This function gets asked to return "view objects" for one or more (multiple
484 * The viewobject typically is an COM object with one of the following
486 * IExtractIcon,IDataObject,IContextMenu
487 * In order to support icon positions in the default Listview your DataObject
488 * must implement the SetData method (in addition to GetData :) - the shell
489 * passes a barely documented "Icon positions" structure to SetData when the
490 * drag starts, and GetData's it if the drop is in another explorer window that
491 * needs the positions.
493 HRESULT WINAPI
CFSFolder::GetUIObjectOf(HWND hwndOwner
,
494 UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
,
495 REFIID riid
, UINT
* prgfInOut
,
499 HRESULT hr
= E_INVALIDARG
;
501 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
502 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
508 if (IsEqualIID(riid
, IID_IContextMenu
) && (cidl
>= 1))
512 AddFSClassKeysToArray(apidl
[0], hKeys
, &cKeys
);
515 dcm
.hwnd
= hwndOwner
;
517 dcm
.pidlFolder
= pidlRoot
;
523 dcm
.punkAssociationInfo
= NULL
;
524 hr
= SHCreateDefaultContextMenu (&dcm
, riid
, &pObj
);
526 else if (IsEqualIID (riid
, IID_IDataObject
))
530 hr
= IDataObject_Constructor (hwndOwner
, pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
537 else if ((IsEqualIID (riid
, IID_IExtractIconA
) || IsEqualIID (riid
, IID_IExtractIconW
)) && (cidl
== 1))
539 hr
= CFSExtractIcon_CreateInstance(this, apidl
[0], riid
, &pObj
);
541 else if (IsEqualIID (riid
, IID_IDropTarget
))
543 /* only interested in attempting to bind to shell folders, not files (except exe), so if we fail, rebind to root */
544 if (cidl
!= 1 || FAILED(hr
= this->_GetDropTarget(apidl
[0], (LPVOID
*) &pObj
)))
546 IDropTarget
* pDt
= NULL
;
547 hr
= CFSDropTarget_CreateInstance(sPathTarget
, riid
, ppvOut
);
551 else if ((IsEqualIID(riid
, IID_IShellLinkW
) ||
552 IsEqualIID(riid
, IID_IShellLinkA
)) && (cidl
== 1))
554 hr
= IShellLink_ConstructFromFile(this, apidl
[0], riid
, &pObj
);
559 if (SUCCEEDED(hr
) && !pObj
)
564 TRACE("(%p)->hr=0x%08x\n", this, hr
);
568 static const WCHAR AdvancedW
[] = L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced";
569 static const WCHAR HideFileExtW
[] = L
"HideFileExt";
570 static const WCHAR NeverShowExtW
[] = L
"NeverShowExt";
572 /******************************************************************************
573 * SHELL_FS_HideExtension [Internal]
575 * Query the registry if the filename extension of a given path should be
579 * szPath [I] Relative or absolute path of a file
582 * TRUE, if the filename's extension should be hidden
585 BOOL
SHELL_FS_HideExtension(LPWSTR szPath
)
589 DWORD dwDataSize
= sizeof (DWORD
);
590 BOOL doHide
= FALSE
; /* The default value is FALSE (win98 at least) */
592 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, AdvancedW
, 0, 0, 0, KEY_ALL_ACCESS
, 0, &hKey
, 0)) {
593 if (!RegQueryValueExW(hKey
, HideFileExtW
, 0, 0, (LPBYTE
) &dwData
, &dwDataSize
))
599 LPWSTR ext
= PathFindExtensionW(szPath
);
602 WCHAR classname
[MAX_PATH
];
603 LONG classlen
= sizeof(classname
);
605 if (!RegQueryValueW(HKEY_CLASSES_ROOT
, ext
, classname
, &classlen
))
606 if (!RegOpenKeyW(HKEY_CLASSES_ROOT
, classname
, &hKey
)) {
607 if (!RegQueryValueExW(hKey
, NeverShowExtW
, 0, NULL
, NULL
, NULL
))
616 void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath
, DWORD dwFlags
)
618 /*FIXME: MSDN also mentions SHGDN_FOREDITING which is not yet handled. */
619 if (!(dwFlags
& SHGDN_FORPARSING
) &&
620 ((dwFlags
& SHGDN_INFOLDER
) || (dwFlags
== SHGDN_NORMAL
))) {
621 if (SHELL_FS_HideExtension(szPath
) && szPath
[0] != '.')
622 PathRemoveExtensionW(szPath
);
626 /**************************************************************************
627 * CFSFolder::GetDisplayNameOf
628 * Retrieves the display name for the specified file object or subfolder
631 * LPCITEMIDLIST pidl, //[in ] complex pidl to item
632 * DWORD dwFlags, //[in ] SHGNO formatting flags
633 * LPSTRRET lpName) //[out] Returned display name
636 * if the name is in the pidl the ret value should be a STRRET_OFFSET
639 HRESULT WINAPI
CFSFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
,
640 DWORD dwFlags
, LPSTRRET strRet
)
645 /* If it is a complex pidl, let the child handle it */
646 if (!_ILIsPidlSimple (pidl
)) /* complex pidl */
648 return SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
, strRet
);
650 else if (pidl
&& !pidl
->mkid
.cb
) /* empty pidl */
652 /* If it is an empty pidl return only the path of the folder */
653 if ((GET_SHGDN_FOR(dwFlags
) & SHGDN_FORPARSING
) &&
654 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
) &&
657 return SHSetStrRet(strRet
, sPathTarget
);
663 LPWSTR pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
665 return E_OUTOFMEMORY
;
667 if ((GET_SHGDN_FOR(dwFlags
) & SHGDN_FORPARSING
) &&
668 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
) &&
671 lstrcpynW(pszPath
, sPathTarget
, MAX_PATH
);
672 PathAddBackslashW(pszPath
);
673 len
= wcslen(pszPath
);
675 _ILSimpleGetTextW(pidl
, pszPath
+ len
, MAX_PATH
+ 1 - len
);
676 if (!_ILIsFolder(pidl
)) SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
678 strRet
->uType
= STRRET_WSTR
;
679 strRet
->pOleStr
= pszPath
;
681 TRACE ("-- (%p)->(%s)\n", this, strRet
->uType
== STRRET_CSTR
? strRet
->cStr
: debugstr_w(strRet
->pOleStr
));
685 /**************************************************************************
686 * CFSFolder::SetNameOf
687 * Changes the name of a file object or subfolder, possibly changing its item
688 * identifier in the process.
691 * HWND hwndOwner, //[in ] Owner window for output
692 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
693 * LPCOLESTR lpszName, //[in ] the items new display name
694 * DWORD dwFlags, //[in ] SHGNO formatting flags
695 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
697 HRESULT WINAPI
CFSFolder::SetNameOf(
699 PCUITEMID_CHILD pidl
,
702 PITEMID_CHILD
*pPidlOut
)
704 WCHAR szSrc
[MAX_PATH
+ 1], szDest
[MAX_PATH
+ 1];
706 BOOL bIsFolder
= _ILIsFolder (ILFindLastID (pidl
));
708 TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner
, pidl
,
709 debugstr_w (lpName
), dwFlags
, pPidlOut
);
711 /* build source path */
712 lstrcpynW(szSrc
, sPathTarget
, MAX_PATH
);
713 ptr
= PathAddBackslashW (szSrc
);
715 _ILSimpleGetTextW (pidl
, ptr
, MAX_PATH
+ 1 - (ptr
- szSrc
));
717 /* build destination path */
718 if (dwFlags
== SHGDN_NORMAL
|| dwFlags
& SHGDN_INFOLDER
) {
719 lstrcpynW(szDest
, sPathTarget
, MAX_PATH
);
720 ptr
= PathAddBackslashW (szDest
);
722 lstrcpynW(ptr
, lpName
, MAX_PATH
+ 1 - (ptr
- szDest
));
724 lstrcpynW(szDest
, lpName
, MAX_PATH
);
726 if(!(dwFlags
& SHGDN_FORPARSING
) && SHELL_FS_HideExtension(szSrc
)) {
727 WCHAR
*ext
= PathFindExtensionW(szSrc
);
729 INT len
= wcslen(szDest
);
730 lstrcpynW(szDest
+ len
, ext
, MAX_PATH
- len
);
734 TRACE ("src=%s dest=%s\n", debugstr_w(szSrc
), debugstr_w(szDest
));
735 if (!memcmp(szSrc
, szDest
, (wcslen(szDest
) + 1) * sizeof(WCHAR
)))
737 /* src and destination is the same */
740 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
746 if (MoveFileW (szSrc
, szDest
))
751 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
753 SHChangeNotify (bIsFolder
? SHCNE_RENAMEFOLDER
: SHCNE_RENAMEITEM
,
754 SHCNF_PATHW
, szSrc
, szDest
);
762 HRESULT WINAPI
CFSFolder::GetDefaultSearchGUID(GUID
* pguid
)
764 FIXME ("(%p)\n", this);
768 HRESULT WINAPI
CFSFolder::EnumSearches(IEnumExtraSearch
** ppenum
)
770 FIXME ("(%p)\n", this);
774 HRESULT WINAPI
CFSFolder::GetDefaultColumn(DWORD dwRes
,
775 ULONG
* pSort
, ULONG
* pDisplay
)
777 TRACE ("(%p)\n", this);
787 HRESULT WINAPI
CFSFolder::GetDefaultColumnState(UINT iColumn
,
790 TRACE ("(%p)\n", this);
792 if (!pcsFlags
|| iColumn
>= GENERICSHELLVIEWCOLUMNS
)
795 *pcsFlags
= GenericSFHeader
[iColumn
].pcsFlags
;
800 HRESULT WINAPI
CFSFolder::GetDetailsEx(PCUITEMID_CHILD pidl
,
801 const SHCOLUMNID
* pscid
, VARIANT
* pv
)
803 FIXME ("(%p)\n", this);
808 HRESULT WINAPI
CFSFolder::GetDetailsOf(PCUITEMID_CHILD pidl
,
809 UINT iColumn
, SHELLDETAILS
* psd
)
813 TRACE ("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
815 if (!psd
|| iColumn
>= GENERICSHELLVIEWCOLUMNS
)
820 /* the header titles */
821 psd
->fmt
= GenericSFHeader
[iColumn
].fmt
;
822 psd
->cxChar
= GenericSFHeader
[iColumn
].cxChar
;
823 return SHSetStrRet(&psd
->str
, GenericSFHeader
[iColumn
].colnameid
);
828 psd
->str
.uType
= STRRET_CSTR
;
829 /* the data from the pidl */
833 hr
= GetDisplayNameOf (pidl
, SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
835 case 1: /* FIXME: comments */
836 psd
->str
.cStr
[0] = 0;
839 _ILGetFileType(pidl
, psd
->str
.cStr
, MAX_PATH
);
842 _ILGetFileSize(pidl
, psd
->str
.cStr
, MAX_PATH
);
845 _ILGetFileDate(pidl
, psd
->str
.cStr
, MAX_PATH
);
847 case 5: /* attributes */
848 _ILGetFileAttributes(pidl
, psd
->str
.cStr
, MAX_PATH
);
856 HRESULT WINAPI
CFSFolder::MapColumnToSCID (UINT column
,
859 FIXME ("(%p)\n", this);
863 /************************************************************************
864 * CFSFolder::GetClassID
866 HRESULT WINAPI
CFSFolder::GetClassID(CLSID
* lpClassId
)
868 TRACE ("(%p)\n", this);
873 *lpClassId
= *pclsid
;
878 /************************************************************************
879 * CFSFolder::Initialize
882 * sPathTarget is not set. Don't know how to handle in a non rooted environment.
884 HRESULT WINAPI
CFSFolder::Initialize(LPCITEMIDLIST pidl
)
886 WCHAR wszTemp
[MAX_PATH
];
888 TRACE ("(%p)->(%p)\n", this, pidl
);
890 SHFree (pidlRoot
); /* free the old pidl */
891 pidlRoot
= ILClone (pidl
); /* set my pidl */
893 SHFree (sPathTarget
);
897 if (SHGetPathFromIDListW (pidl
, wszTemp
))
899 int len
= wcslen(wszTemp
);
900 sPathTarget
= (WCHAR
*)SHAlloc((len
+ 1) * sizeof(WCHAR
));
902 return E_OUTOFMEMORY
;
903 memcpy(sPathTarget
, wszTemp
, (len
+ 1) * sizeof(WCHAR
));
906 TRACE ("--(%p)->(%s)\n", this, debugstr_w(sPathTarget
));
910 /**************************************************************************
911 * CFSFolder::GetCurFolder
913 HRESULT WINAPI
CFSFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
915 TRACE ("(%p)->(%p)\n", this, pidl
);
920 *pidl
= ILClone(pidlRoot
);
924 /**************************************************************************
925 * CFSFolder::InitializeEx
927 * FIXME: error handling
929 HRESULT WINAPI
CFSFolder::InitializeEx(IBindCtx
* pbc
, LPCITEMIDLIST pidlRootx
,
930 const PERSIST_FOLDER_TARGET_INFO
* ppfti
)
932 WCHAR wszTemp
[MAX_PATH
];
934 TRACE("(%p)->(%p,%p,%p)\n", this, pbc
, pidlRootx
, ppfti
);
936 TRACE("--%p %s %s 0x%08x 0x%08x\n",
937 ppfti
->pidlTargetFolder
, debugstr_w (ppfti
->szTargetParsingName
),
938 debugstr_w (ppfti
->szNetworkProvider
), ppfti
->dwAttributes
,
942 if (ppfti
&& ppfti
->pidlTargetFolder
)
943 pdump(ppfti
->pidlTargetFolder
);
946 __SHFreeAndNil(&pidlRoot
); /* free the old */
948 __SHFreeAndNil(&sPathTarget
);
953 pidlRoot
= ILClone(pidlRootx
);
956 * the target folder is spezified in csidl OR pidlTargetFolder OR
957 * szTargetParsingName
961 if (ppfti
->csidl
!= -1)
963 if (SHGetSpecialFolderPathW(0, wszTemp
, ppfti
->csidl
,
964 ppfti
->csidl
& CSIDL_FLAG_CREATE
)) {
965 int len
= wcslen(wszTemp
);
966 sPathTarget
= (WCHAR
*)SHAlloc((len
+ 1) * sizeof(WCHAR
));
968 return E_OUTOFMEMORY
;
969 memcpy(sPathTarget
, wszTemp
, (len
+ 1) * sizeof(WCHAR
));
972 else if (ppfti
->szTargetParsingName
[0])
974 int len
= wcslen(ppfti
->szTargetParsingName
);
975 sPathTarget
= (WCHAR
*)SHAlloc((len
+ 1) * sizeof(WCHAR
));
977 return E_OUTOFMEMORY
;
978 memcpy(sPathTarget
, ppfti
->szTargetParsingName
,
979 (len
+ 1) * sizeof(WCHAR
));
981 else if (ppfti
->pidlTargetFolder
)
983 if (SHGetPathFromIDListW(ppfti
->pidlTargetFolder
, wszTemp
))
985 int len
= wcslen(wszTemp
);
986 sPathTarget
= (WCHAR
*)SHAlloc((len
+ 1) * sizeof(WCHAR
));
988 return E_OUTOFMEMORY
;
989 memcpy(sPathTarget
, wszTemp
, (len
+ 1) * sizeof(WCHAR
));
994 TRACE("--(%p)->(target=%s)\n", this, debugstr_w(sPathTarget
));
996 return (sPathTarget
) ? S_OK
: E_FAIL
;
999 HRESULT WINAPI
CFSFolder::GetFolderTargetInfo(PERSIST_FOLDER_TARGET_INFO
* ppfti
)
1001 FIXME("(%p)->(%p)\n", this, ppfti
);
1002 ZeroMemory(ppfti
, sizeof (*ppfti
));
1006 HRESULT WINAPI
CFSFolder::_GetDropTarget(LPCITEMIDLIST pidl
, LPVOID
*ppvOut
) {
1010 TRACE("CFSFolder::_GetDropTarget entered\n");
1012 if (_ILIsFolder (pidl
))
1014 CComPtr
<IShellFolder
> psfChild
;
1015 hr
= this->BindToObject(pidl
, NULL
, IID_PPV_ARG(IShellFolder
, &psfChild
));
1016 if (FAILED_UNEXPECTEDLY(hr
))
1019 return psfChild
->CreateViewObject(NULL
, IID_IDropTarget
, ppvOut
);
1023 hr
= this->GetDisplayNameOf(pidl
, SHGDN_FORPARSING
, &strFile
);
1026 WCHAR wszPath
[MAX_PATH
];
1027 hr
= StrRetToBufW(&strFile
, pidl
, wszPath
, _countof(wszPath
));
1031 LPCWSTR pwszExt
= PathFindExtensionW(wszPath
);
1034 /* enumerate dynamic/static for a given file class */
1035 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, pwszExt
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
1037 /* load dynamic extensions from file extension key, for example .jpg */
1038 _LoadDynamicDropTargetHandlerForKey(hKey
, wszPath
, ppvOut
);
1043 DWORD dwSize
= sizeof(wszTemp
);
1044 if (RegGetValueW(HKEY_CLASSES_ROOT
, pwszExt
, NULL
, RRF_RT_REG_SZ
, NULL
, wszTemp
, &dwSize
) == ERROR_SUCCESS
)
1046 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszTemp
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
1048 /* load dynamic extensions from progid key, for example jpegfile */
1049 _LoadDynamicDropTargetHandlerForKey(hKey
, wszPath
, ppvOut
);
1057 ERR("GetDisplayNameOf failed: %x\n", hr
);
1062 HRESULT WINAPI
CFSFolder::_LoadDynamicDropTargetHandlerForKey(HKEY hRootKey
, LPCWSTR pwcsname
, LPVOID
*ppvOut
)
1064 TRACE("CFSFolder::_LoadDynamicDropTargetHandlerForKey entered\n");
1066 WCHAR wszName
[MAX_PATH
];
1067 DWORD dwSize
= sizeof(wszName
);
1071 res
= RegGetValueW(hRootKey
, L
"shellex\\DropHandler", NULL
, RRF_RT_REG_SZ
, NULL
, wszName
, &dwSize
);
1072 if (res
!= ERROR_SUCCESS
)
1076 hr
= CLSIDFromString(wszName
, &clsid
);
1077 if (FAILED_UNEXPECTEDLY(hr
))
1080 if (m_bGroupPolicyActive
)
1082 res
= RegGetValueW(HKEY_LOCAL_MACHINE
,
1083 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
1089 if (res
!= ERROR_SUCCESS
)
1091 ERR("DropHandler extension %S not approved\n", wszName
);
1096 hr
= _LoadDynamicDropTargetHandler(&clsid
, pwcsname
, ppvOut
);
1097 if (FAILED_UNEXPECTEDLY(hr
))
1103 HRESULT WINAPI
CFSFolder::_LoadDynamicDropTargetHandler(const CLSID
*pclsid
, LPCWSTR pwcsname
, LPVOID
*ppvOut
)
1105 TRACE("CFSFolder::_LoadDynamicDropTargetHandler entered\n");
1108 CComPtr
<IPersistFile
> pp
;
1109 hr
= SHCoCreateInstance(NULL
, pclsid
, NULL
, IID_PPV_ARG(IPersistFile
, &pp
));
1112 ERR("SHCoCreateInstance failed %x\n", GetLastError());
1114 pp
->Load(pwcsname
, 0);
1116 hr
= pp
->QueryInterface(IID_PPV_ARG(IDropTarget
, (IDropTarget
**) ppvOut
));
1119 ERR("Failed to query for interface IID_IShellExtInit hr %x pclsid %s\n", hr
, wine_dbgstr_guid(pclsid
));
1125 HRESULT WINAPI
CFSFolder::CallBack(IShellFolder
*psf
, HWND hwndOwner
, IDataObject
*pdtobj
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1127 if (uMsg
!= DFM_MERGECONTEXTMENU
&& uMsg
!= DFM_INVOKECOMMAND
)
1130 /* no data object means no selection */
1133 if (uMsg
== DFM_INVOKECOMMAND
&& wParam
== DFM_CMD_PROPERTIES
)
1135 PUITEMID_CHILD pidlChild
= ILClone(ILFindLastID(pidlRoot
));
1136 LPITEMIDLIST pidlParent
= ILClone(pidlRoot
);
1137 ILRemoveLastID(pidlParent
);
1138 HRESULT hr
= SH_ShowPropertiesDialog(sPathTarget
, pidlParent
, &pidlChild
);
1140 ERR("SH_ShowPropertiesDialog failed\n");
1144 else if (uMsg
== DFM_MERGECONTEXTMENU
)
1146 QCMINFO
*pqcminfo
= (QCMINFO
*)lParam
;
1147 _InsertMenuItemW(pqcminfo
->hmenu
, pqcminfo
->indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
1148 _InsertMenuItemW(pqcminfo
->hmenu
, pqcminfo
->indexMenu
++, TRUE
, FCIDM_SHVIEW_PROPERTIES
, MFT_STRING
, MAKEINTRESOURCEW(IDS_PROPERTIES
), MFS_ENABLED
);
1154 if (uMsg
!= DFM_INVOKECOMMAND
|| wParam
!= DFM_CMD_PROPERTIES
)
1157 PIDLIST_ABSOLUTE pidlFolder
;
1158 PUITEMID_CHILD
*apidl
;
1160 HRESULT hr
= SH_GetApidlFromDataObject(pdtobj
, &pidlFolder
, &apidl
, &cidl
);
1161 if (FAILED_UNEXPECTEDLY(hr
))
1165 ERR("SHMultiFileProperties is not yet implemented\n");
1168 hr
= GetDisplayNameOf(apidl
[0], SHGDN_FORPARSING
, &strFile
);
1171 hr
= SH_ShowPropertiesDialog(strFile
.pOleStr
, pidlFolder
, apidl
);
1173 ERR("SH_ShowPropertiesDialog failed\n");
1177 ERR("Failed to get display name\n");
1181 _ILFreeaPidl(apidl
, cidl
);