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
);
27 static HRESULT
getIconLocationForFolder(IShellFolder
* psf
, LPCITEMIDLIST pidl
, UINT uFlags
,
28 LPWSTR szIconFile
, UINT cchMax
, int *piIndex
, UINT
*pwFlags
)
30 static const WCHAR shellClassInfo
[] = { '.', 'S', 'h', 'e', 'l', 'l', 'C', 'l', 'a', 's', 's', 'I', 'n', 'f', 'o', 0 };
31 static const WCHAR iconFile
[] = { 'I', 'c', 'o', 'n', 'F', 'i', 'l', 'e', 0 };
32 static const WCHAR clsid
[] = { 'C', 'L', 'S', 'I', 'D', 0 };
33 static const WCHAR clsid2
[] = { 'C', 'L', 'S', 'I', 'D', '2', 0 };
34 static const WCHAR iconIndex
[] = { 'I', 'c', 'o', 'n', 'I', 'n', 'd', 'e', 'x', 0 };
35 static const WCHAR wszDesktopIni
[] = { 'd','e','s','k','t','o','p','.','i','n','i',0 };
38 if (!(uFlags
& GIL_DEFAULTICON
) && (_ILGetFileAttributes(ILFindLastID(pidl
), NULL
, 0) & (FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_READONLY
)) != 0 )
40 WCHAR wszFolderPath
[MAX_PATH
];
42 if (!ILGetDisplayNameExW(psf
, pidl
, wszFolderPath
, 0))
45 PathAppendW(wszFolderPath
, wszDesktopIni
);
47 if (PathFileExistsW(wszFolderPath
))
49 WCHAR wszPath
[MAX_PATH
];
50 WCHAR wszCLSIDValue
[CHARS_IN_GUID
];
52 if (GetPrivateProfileStringW(shellClassInfo
, iconFile
, NULL
, wszPath
, MAX_PATH
, wszFolderPath
))
54 ExpandEnvironmentStringsW(wszPath
, szIconFile
, cchMax
);
56 *piIndex
= GetPrivateProfileIntW(shellClassInfo
, iconIndex
, 0, wszFolderPath
);
59 else if (GetPrivateProfileStringW(shellClassInfo
, clsid
, NULL
, wszCLSIDValue
, CHARS_IN_GUID
, wszFolderPath
) &&
60 HCR_GetIconW(wszCLSIDValue
, szIconFile
, NULL
, cchMax
, &icon_idx
))
65 else if (GetPrivateProfileStringW(shellClassInfo
, clsid2
, NULL
, wszCLSIDValue
, CHARS_IN_GUID
, wszFolderPath
) &&
66 HCR_GetIconW(wszCLSIDValue
, szIconFile
, NULL
, cchMax
, &icon_idx
))
74 static const WCHAR folder
[] = { 'F', 'o', 'l', 'd', 'e', 'r', 0 };
76 if (!HCR_GetIconW(folder
, szIconFile
, NULL
, cchMax
, &icon_idx
))
78 lstrcpynW(szIconFile
, swShell32Name
, cchMax
);
79 icon_idx
= -IDI_SHELL_FOLDER
;
82 if (uFlags
& GIL_OPENICON
)
83 *piIndex
= icon_idx
< 0 ? icon_idx
- 1 : icon_idx
+ 1;
90 HRESULT
CFSExtractIcon_CreateInstance(IShellFolder
* psf
, LPCITEMIDLIST pidl
, REFIID iid
, LPVOID
* ppvOut
)
92 CComPtr
<IDefaultExtractIconInit
> initIcon
;
95 UINT flags
= 0; // FIXME: Use it!
96 CHAR sTemp
[MAX_PATH
] = "";
97 WCHAR wTemp
[MAX_PATH
] = L
"";
99 hr
= SHCreateDefaultExtractIcon(IID_PPV_ARG(IDefaultExtractIconInit
,&initIcon
));
103 if (_ILIsFolder (pidl
))
105 if (SUCCEEDED(getIconLocationForFolder(psf
,
106 pidl
, 0, wTemp
, _countof(wTemp
),
110 initIcon
->SetNormalIcon(wTemp
, icon_idx
);
111 // FIXME: if/when getIconLocationForFolder does something for
112 // GIL_FORSHORTCUT, code below should be uncommented. and
113 // the following line removed.
114 initIcon
->SetShortcutIcon(wTemp
, icon_idx
);
116 if (SUCCEEDED(getIconLocationForFolder(psf
,
117 pidl
, GIL_DEFAULTICON
, wTemp
, _countof(wTemp
),
121 initIcon
->SetDefaultIcon(wTemp
, icon_idx
);
123 // if (SUCCEEDED(getIconLocationForFolder(psf,
124 // pidl, GIL_FORSHORTCUT, wTemp, _countof(wTemp),
128 // initIcon->SetShortcutIcon(wTemp, icon_idx);
130 if (SUCCEEDED(getIconLocationForFolder(psf
,
131 pidl
, GIL_OPENICON
, wTemp
, _countof(wTemp
),
135 initIcon
->SetOpenIcon(wTemp
, icon_idx
);
142 if (_ILGetExtension(pidl
, sTemp
, _countof(sTemp
)))
144 if (HCR_MapTypeToValueA(sTemp
, sTemp
, _countof(sTemp
), TRUE
)
145 && HCR_GetIconA(sTemp
, sTemp
, NULL
, _countof(sTemp
), &icon_idx
))
147 if (!lstrcmpA("%1", sTemp
)) /* icon is in the file */
149 ILGetDisplayNameExW(psf
, pidl
, wTemp
, 0);
154 MultiByteToWideChar(CP_ACP
, 0, sTemp
, -1, wTemp
, _countof(wTemp
));
159 else if (!lstrcmpiA(sTemp
, "lnkfile"))
161 /* extract icon from shell shortcut */
162 CComPtr
<IShellLinkW
> psl
;
163 CComPtr
<IExtractIconW
> pei
;
165 HRESULT hr
= psf
->GetUIObjectOf(NULL
, 1, &pidl
, IID_NULL_PPV_ARG(IShellLinkW
, &psl
));
168 hr
= psl
->GetIconLocation(wTemp
, _countof(wTemp
), &icon_idx
);
169 if (FAILED(hr
) || !*wTemp
)
171 /* The icon was not found directly, try to retrieve it from the shell link target */
172 hr
= psl
->QueryInterface(IID_PPV_ARG(IExtractIconW
, &pei
));
173 if (FAILED(hr
) || !pei
)
174 TRACE("No IExtractIconW interface!\n");
176 hr
= pei
->GetIconLocation(GIL_FORSHELL
, wTemp
, _countof(wTemp
), &icon_idx
, &flags
);
179 if (SUCCEEDED(hr
) && *wTemp
)
185 /* FIXME: We should normally use the correct icon format according to 'flags' */
188 initIcon
->SetNormalIcon(swShell32Name
, 0);
190 initIcon
->SetNormalIcon(wTemp
, icon_idx
);
193 return initIcon
->QueryInterface(iid
, ppvOut
);
197 CFileSysEnum should do an initial FindFirstFile and do a FindNextFile as each file is
198 returned by Next. When the enumerator is created, it can do numerous additional operations
199 including formatting a drive, reconnecting a network share drive, and requesting a disk
200 be inserted in a removable drive.
203 /***********************************************************************
204 * IShellFolder implementation
208 public CEnumIDListBase
214 HRESULT WINAPI
Initialize(LPWSTR sPathTarget
, DWORD dwFlags
);
216 BEGIN_COM_MAP(CFileSysEnum
)
217 COM_INTERFACE_ENTRY_IID(IID_IEnumIDList
, IEnumIDList
)
221 CFileSysEnum::CFileSysEnum()
225 CFileSysEnum::~CFileSysEnum()
229 HRESULT WINAPI
CFileSysEnum::Initialize(LPWSTR lpszPath
, DWORD dwFlags
)
231 WIN32_FIND_DATAW stffile
;
233 WCHAR szPath
[MAX_PATH
];
234 BOOL succeeded
= TRUE
;
235 static const WCHAR stars
[] = { '*','.','*',0 };
236 static const WCHAR dot
[] = { '.',0 };
237 static const WCHAR dotdot
[] = { '.','.',0 };
239 TRACE("(%p)->(path=%s flags=0x%08x)\n", this, debugstr_w(lpszPath
), dwFlags
);
241 if(!lpszPath
|| !lpszPath
[0]) return FALSE
;
243 wcscpy(szPath
, lpszPath
);
244 PathAddBackslashW(szPath
);
245 wcscat(szPath
,stars
);
247 hFile
= FindFirstFileW(szPath
,&stffile
);
248 if ( hFile
!= INVALID_HANDLE_VALUE
)
250 BOOL findFinished
= FALSE
;
254 if ( !(stffile
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
)
255 || (dwFlags
& SHCONTF_INCLUDEHIDDEN
) )
257 LPITEMIDLIST pidl
= NULL
;
259 if ( (stffile
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) &&
260 dwFlags
& SHCONTF_FOLDERS
&&
261 strcmpW(stffile
.cFileName
, dot
) && strcmpW(stffile
.cFileName
, dotdot
))
263 pidl
= _ILCreateFromFindDataW(&stffile
);
264 succeeded
= succeeded
&& AddToEnumList(pidl
);
266 else if (!(stffile
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
267 && dwFlags
& SHCONTF_NONFOLDERS
)
269 pidl
= _ILCreateFromFindDataW(&stffile
);
270 succeeded
= succeeded
&& AddToEnumList(pidl
);
275 if (!FindNextFileW(hFile
, &stffile
))
277 if (GetLastError() == ERROR_NO_MORE_FILES
)
283 } while (succeeded
&& !findFinished
);
290 CFSFolder::CFSFolder()
292 pclsid
= (CLSID
*)&CLSID_ShellFSFolder
;
295 m_bGroupPolicyActive
= 0;
298 CFSFolder::~CFSFolder()
300 TRACE("-- destroying IShellFolder(%p)\n", this);
307 static const shvheader GenericSFHeader
[] = {
308 {IDS_SHV_COLUMN_NAME
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 15},
309 {IDS_SHV_COLUMN_COMMENTS
, SHCOLSTATE_TYPE_STR
, LVCFMT_LEFT
, 0},
310 {IDS_SHV_COLUMN_TYPE
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 10},
311 {IDS_SHV_COLUMN_SIZE
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
312 {IDS_SHV_COLUMN_MODIFIED
, SHCOLSTATE_TYPE_DATE
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 12},
313 {IDS_SHV_COLUMN_ATTRIBUTES
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_LEFT
, 10}
316 #define GENERICSHELLVIEWCOLUMNS 6
318 /**************************************************************************
319 * SHELL32_CreatePidlFromBindCtx [internal]
321 * If the caller bound File System Bind Data, assume it is the
322 * find data for the path.
323 * This allows binding of paths that don't exist.
325 LPITEMIDLIST
SHELL32_CreatePidlFromBindCtx(IBindCtx
*pbc
, LPCWSTR path
)
327 IFileSystemBindData
*fsbd
= NULL
;
328 LPITEMIDLIST pidl
= NULL
;
329 IUnknown
*param
= NULL
;
330 WIN32_FIND_DATAW wfd
;
333 TRACE("%p %s\n", pbc
, debugstr_w(path
));
338 /* see if the caller bound File System Bind Data */
339 r
= pbc
->GetObjectParam((LPOLESTR
)STR_FILE_SYS_BIND_DATA
, ¶m
);
343 r
= param
->QueryInterface(IID_PPV_ARG(IFileSystemBindData
,&fsbd
));
346 r
= fsbd
->GetFindData(&wfd
);
349 lstrcpynW(&wfd
.cFileName
[0], path
, MAX_PATH
);
350 pidl
= _ILCreateFromFindDataW(&wfd
);
358 void SHELL32_GetCLSIDForDirectory(LPCWSTR pwszDir
, CLSID
* pclsidFolder
)
360 WCHAR wszCLSIDValue
[CHARS_IN_GUID
];
361 WCHAR wszDesktopIni
[MAX_PATH
];
362 StringCchCopyW(wszDesktopIni
, MAX_PATH
, pwszDir
);
363 StringCchCatW(wszDesktopIni
, MAX_PATH
, L
"\\desktop.ini");
365 if (GetPrivateProfileStringW(L
".ShellClassInfo",
372 CLSIDFromString (wszCLSIDValue
, pclsidFolder
);
377 static const DWORD dwSupportedAttr
=
378 SFGAO_CANCOPY
| /*0x00000001 */
379 SFGAO_CANMOVE
| /*0x00000002 */
380 SFGAO_CANLINK
| /*0x00000004 */
381 SFGAO_CANRENAME
| /*0x00000010 */
382 SFGAO_CANDELETE
| /*0x00000020 */
383 SFGAO_HASPROPSHEET
| /*0x00000040 */
384 SFGAO_DROPTARGET
| /*0x00000100 */
385 SFGAO_LINK
| /*0x00010000 */
386 SFGAO_READONLY
| /*0x00040000 */
387 SFGAO_HIDDEN
| /*0x00080000 */
388 SFGAO_FILESYSANCESTOR
| /*0x10000000 */
389 SFGAO_FOLDER
| /*0x20000000 */
390 SFGAO_FILESYSTEM
| /*0x40000000 */
391 SFGAO_HASSUBFOLDER
; /*0x80000000 */
393 HRESULT
SHELL32_GetFSItemAttributes(IShellFolder
* psf
, LPCITEMIDLIST pidl
, LPDWORD pdwAttributes
)
395 DWORD dwFileAttributes
, dwShellAttributes
;
397 if (!_ILIsFolder(pidl
) && !_ILIsValue(pidl
))
399 ERR("Got wrong type of pidl!\n");
400 *pdwAttributes
&= SFGAO_CANLINK
;
404 if (*pdwAttributes
& ~dwSupportedAttr
)
406 WARN ("attributes 0x%08x not implemented\n", (*pdwAttributes
& ~dwSupportedAttr
));
407 *pdwAttributes
&= dwSupportedAttr
;
410 dwFileAttributes
= _ILGetFileAttributes(pidl
, NULL
, 0);
412 /* Set common attributes */
413 dwShellAttributes
= *pdwAttributes
;
414 dwShellAttributes
|= SFGAO_FILESYSTEM
| SFGAO_DROPTARGET
| SFGAO_HASPROPSHEET
| SFGAO_CANDELETE
|
415 SFGAO_CANRENAME
| SFGAO_CANLINK
| SFGAO_CANMOVE
| SFGAO_CANCOPY
;
417 if (dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
419 dwShellAttributes
|= (SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_FILESYSANCESTOR
);
422 dwShellAttributes
&= ~(SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_FILESYSANCESTOR
);
424 if (dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
)
425 dwShellAttributes
|= SFGAO_HIDDEN
;
427 dwShellAttributes
&= ~SFGAO_HIDDEN
;
429 if (dwFileAttributes
& FILE_ATTRIBUTE_READONLY
)
430 dwShellAttributes
|= SFGAO_READONLY
;
432 dwShellAttributes
&= ~SFGAO_READONLY
;
434 if (SFGAO_LINK
& *pdwAttributes
)
438 if (!_ILGetExtension(pidl
, ext
, MAX_PATH
) || lstrcmpiA(ext
, "lnk"))
439 dwShellAttributes
&= ~SFGAO_LINK
;
442 if (SFGAO_HASSUBFOLDER
& *pdwAttributes
)
444 CComPtr
<IShellFolder
> psf2
;
445 if (SUCCEEDED(psf
->BindToObject(pidl
, 0, IID_PPV_ARG(IShellFolder
, &psf2
))))
447 CComPtr
<IEnumIDList
> pEnumIL
;
448 if (SUCCEEDED(psf2
->EnumObjects(0, SHCONTF_FOLDERS
, &pEnumIL
)))
450 if (pEnumIL
->Skip(1) != S_OK
)
451 dwShellAttributes
&= ~SFGAO_HASSUBFOLDER
;
456 *pdwAttributes
&= dwShellAttributes
;
458 TRACE ("-- 0x%08x\n", *pdwAttributes
);
462 /**************************************************************************
463 * CFSFolder::ParseDisplayName {SHELL32}
465 * Parse a display name.
468 * hwndOwner [in] Parent window for any message's
469 * pbc [in] optional FileSystemBindData context
470 * lpszDisplayName [in] Unicode displayname.
471 * pchEaten [out] (unicode) characters processed
472 * ppidl [out] complex pidl to item
473 * pdwAttributes [out] items attributes
476 * Every folder tries to parse only its own (the leftmost) pidl and creates a
477 * subfolder to evaluate the remaining parts.
478 * Now we can parse into namespaces implemented by shell extensions
480 * Behaviour on win98: lpszDisplayName=NULL -> crash
481 * lpszDisplayName="" -> returns mycoputer-pidl
484 * pdwAttributes is not set
485 * pchEaten is not set like in windows
487 HRESULT WINAPI
CFSFolder::ParseDisplayName(HWND hwndOwner
,
489 LPOLESTR lpszDisplayName
,
490 DWORD
*pchEaten
, PIDLIST_RELATIVE
*ppidl
,
491 DWORD
*pdwAttributes
)
493 HRESULT hr
= E_INVALIDARG
;
494 LPCWSTR szNext
= NULL
;
495 WCHAR szElement
[MAX_PATH
];
496 WCHAR szPath
[MAX_PATH
];
497 LPITEMIDLIST pidlTemp
= NULL
;
500 TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
501 this, hwndOwner
, pbc
, lpszDisplayName
, debugstr_w (lpszDisplayName
),
502 pchEaten
, ppidl
, pdwAttributes
);
507 if (!lpszDisplayName
)
516 *pchEaten
= 0; /* strange but like the original */
518 if (*lpszDisplayName
)
520 /* get the next element */
521 szNext
= GetNextElementW (lpszDisplayName
, szElement
, MAX_PATH
);
523 pidlTemp
= SHELL32_CreatePidlFromBindCtx(pbc
, szElement
);
524 if (pidlTemp
!= NULL
)
526 /* We are creating an id list without ensuring that the items exist.
527 If we have a remaining path, this must be a folder.
528 We have to do it now because it is set as a file by default */
531 pidlTemp
->mkid
.abID
[0] = PT_FOLDER
;
537 /* build the full pathname to the element */
538 lstrcpynW(szPath
, sPathTarget
, MAX_PATH
- 1);
539 PathAddBackslashW(szPath
);
540 len
= wcslen(szPath
);
541 lstrcpynW(szPath
+ len
, szElement
, MAX_PATH
- len
);
544 hr
= _ILCreateFromPathW(szPath
, &pidlTemp
);
549 if (szNext
&& *szNext
)
551 /* try to analyse the next element */
552 hr
= SHELL32_ParseNextElement(this, hwndOwner
, pbc
,
553 &pidlTemp
, (LPOLESTR
) szNext
, pchEaten
, pdwAttributes
);
557 /* it's the last element */
558 if (pdwAttributes
&& *pdwAttributes
)
559 hr
= SHELL32_GetFSItemAttributes(this, pidlTemp
, pdwAttributes
);
569 TRACE("(%p)->(-- pidl=%p ret=0x%08x)\n", this, ppidl
? *ppidl
: 0, hr
);
574 /**************************************************************************
575 * CFSFolder::EnumObjects
577 * HWND hwndOwner, //[in ] Parent Window
578 * DWORD grfFlags, //[in ] SHCONTF enumeration mask
579 * LPENUMIDLIST* ppenumIDList //[out] IEnumIDList interface
581 HRESULT WINAPI
CFSFolder::EnumObjects(
584 LPENUMIDLIST
*ppEnumIDList
)
586 return ShellObjectCreatorInit
<CFileSysEnum
>(sPathTarget
, dwFlags
, IID_PPV_ARG(IEnumIDList
, ppEnumIDList
));
589 /**************************************************************************
590 * CFSFolder::BindToObject
592 * LPCITEMIDLIST pidl, //[in ] relative pidl to open
593 * LPBC pbc, //[in ] optional FileSystemBindData context
594 * REFIID riid, //[in ] Initial Interface
595 * LPVOID* ppvObject //[out] Interface*
597 HRESULT WINAPI
CFSFolder::BindToObject(
598 PCUIDLIST_RELATIVE pidl
,
603 TRACE("(%p)->(pidl=%p,%p,%s,%p)\n", this, pidl
, pbc
,
604 shdebugstr_guid(&riid
), ppvOut
);
606 CComPtr
<IShellFolder
> pSF
;
609 if (!pidlRoot
|| !ppvOut
|| !pidl
|| !pidl
->mkid
.cb
)
612 if (_ILIsValue(pidl
))
614 ERR("Binding to file is unimplemented\n");
615 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
617 if (!_ILIsFolder(pidl
))
619 ERR("Got an unknown type of pidl!\n");
625 /* Get the pidl data */
626 FileStruct
* pData
= &_ILGetDataPointer(pidl
)->u
.file
;
627 FileStructW
* pDataW
= _ILGetFileStructW(pidl
);
629 /* Create the target folder info */
630 PERSIST_FOLDER_TARGET_INFO pfti
= {0};
631 pfti
.dwAttributes
= -1;
633 PathCombineW(pfti
.szTargetParsingName
, sPathTarget
, pDataW
->wszName
);
635 /* Get the CLSID to bind to */
636 CLSID clsidFolder
= CLSID_ShellFSFolder
;
637 if ((pData
->uFileAttribs
& (FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_READONLY
)) != 0)
638 SHELL32_GetCLSIDForDirectory(pfti
.szTargetParsingName
, &clsidFolder
);
640 hr
= SHELL32_BindToSF(pidlRoot
, &pfti
, pidl
, &clsidFolder
, riid
, ppvOut
);
641 if (FAILED_UNEXPECTEDLY(hr
))
644 TRACE ("-- returning (%p) %08x\n", *ppvOut
, hr
);
650 /**************************************************************************
651 * CFSFolder::BindToStorage
653 * LPCITEMIDLIST pidl, //[in ] complex pidl to store
654 * LPBC pbc, //[in ] reserved
655 * REFIID riid, //[in ] Initial storage interface
656 * LPVOID* ppvObject //[out] Interface* returned
658 HRESULT WINAPI
CFSFolder::BindToStorage(
659 PCUIDLIST_RELATIVE pidl
,
664 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this, pidl
, pbcReserved
,
665 shdebugstr_guid (&riid
), ppvOut
);
671 /**************************************************************************
672 * CFSFolder::CompareIDs
675 HRESULT WINAPI
CFSFolder::CompareIDs(LPARAM lParam
,
676 PCUIDLIST_RELATIVE pidl1
,
677 PCUIDLIST_RELATIVE pidl2
)
679 LPPIDLDATA pData1
= _ILGetDataPointer(pidl1
);
680 LPPIDLDATA pData2
= _ILGetDataPointer(pidl2
);
681 FileStructW
* pDataW1
= _ILGetFileStructW(pidl1
);
682 FileStructW
* pDataW2
= _ILGetFileStructW(pidl2
);
683 BOOL bIsFolder1
= _ILIsFolder(pidl1
);
684 BOOL bIsFolder2
= _ILIsFolder(pidl2
);
685 LPWSTR pExtension1
, pExtension2
;
687 if (!pDataW1
|| !pDataW2
|| LOWORD(lParam
) >= GENERICSHELLVIEWCOLUMNS
)
690 /* When sorting between a File and a Folder, the Folder gets sorted first */
691 if (bIsFolder1
!= bIsFolder2
)
693 return MAKE_COMPARE_HRESULT(bIsFolder1
? -1 : 1);
697 switch (LOWORD(lParam
))
700 result
= wcsicmp(pDataW1
->wszName
, pDataW2
->wszName
);
702 case 1: /* Comments */
706 pExtension1
= PathFindExtensionW(pDataW1
->wszName
);
707 pExtension2
= PathFindExtensionW(pDataW2
->wszName
);
708 result
= wcsicmp(pExtension1
, pExtension2
);
711 result
= pData1
->u
.file
.dwFileSize
- pData2
->u
.file
.dwFileSize
;
713 case 4: /* Modified */
714 result
= pData1
->u
.file
.uFileDate
- pData2
->u
.file
.uFileDate
;
716 result
= pData1
->u
.file
.uFileTime
- pData2
->u
.file
.uFileTime
;
718 case 5: /* Attributes */
719 return SHELL32_CompareDetails(this, lParam
, pidl1
, pidl2
);
723 return SHELL32_CompareChildren(this, lParam
, pidl1
, pidl2
);
725 return MAKE_COMPARE_HRESULT(result
);
728 /**************************************************************************
729 * CFSFolder::CreateViewObject
731 HRESULT WINAPI
CFSFolder::CreateViewObject(HWND hwndOwner
,
732 REFIID riid
, LPVOID
* ppvOut
)
734 CComPtr
<IShellView
> pShellView
;
735 HRESULT hr
= E_INVALIDARG
;
737 TRACE ("(%p)->(hwnd=%p,%s,%p)\n", this, hwndOwner
, shdebugstr_guid (&riid
),
744 if (IsEqualIID (riid
, IID_IDropTarget
))
745 hr
= CFSDropTarget_CreateInstance(sPathTarget
, riid
, ppvOut
);
746 else if (IsEqualIID (riid
, IID_IContextMenu
))
750 AddClassKeyToArray(L
"Directory\\Background", hKeys
, &cKeys
);
753 dcm
.hwnd
= hwndOwner
;
755 dcm
.pidlFolder
= pidlRoot
;
761 dcm
.punkAssociationInfo
= NULL
;
762 hr
= SHCreateDefaultContextMenu (&dcm
, riid
, ppvOut
);
764 else if (IsEqualIID (riid
, IID_IShellView
))
766 SFV_CREATE sfvparams
= {sizeof(SFV_CREATE
), this};
767 hr
= SHCreateShellFolderView(&sfvparams
, (IShellView
**)ppvOut
);
770 TRACE("-- (%p)->(interface=%p)\n", this, ppvOut
);
774 /**************************************************************************
775 * CFSFolder::GetAttributesOf
778 * UINT cidl, //[in ] num elements in pidl array
779 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
780 * ULONG* rgfInOut) //[out] result array
783 HRESULT WINAPI
CFSFolder::GetAttributesOf(UINT cidl
,
784 PCUITEMID_CHILD_ARRAY apidl
, DWORD
* rgfInOut
)
798 LPCITEMIDLIST rpidl
= ILFindLastID(pidlRoot
);
800 if (_ILIsFolder(rpidl
) || _ILIsValue(rpidl
))
802 SHELL32_GetFSItemAttributes(this, rpidl
, rgfInOut
);
804 else if (_ILIsDrive(rpidl
))
806 IShellFolder
*psfParent
= NULL
;
807 hr
= SHBindToParent(pidlRoot
, IID_PPV_ARG(IShellFolder
, &psfParent
), NULL
);
810 hr
= psfParent
->GetAttributesOf(1, &rpidl
, (SFGAOF
*)rgfInOut
);
811 psfParent
->Release();
816 ERR("Got and unknown pidl!\n");
821 while (cidl
> 0 && *apidl
)
824 if(_ILIsFolder(*apidl
) || _ILIsValue(*apidl
))
825 SHELL32_GetFSItemAttributes(this, *apidl
, rgfInOut
);
827 ERR("Got an unknown type of pidl!!!\n");
832 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
833 *rgfInOut
&= ~SFGAO_VALIDATE
;
835 TRACE("-- result=0x%08x\n", *rgfInOut
);
840 /**************************************************************************
841 * CFSFolder::GetUIObjectOf
844 * HWND hwndOwner, //[in ] Parent window for any output
845 * UINT cidl, //[in ] array size
846 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
847 * REFIID riid, //[in ] Requested Interface
848 * UINT* prgfInOut, //[ ] reserved
849 * LPVOID* ppvObject) //[out] Resulting Interface
852 * This function gets asked to return "view objects" for one or more (multiple
854 * The viewobject typically is an COM object with one of the following
856 * IExtractIcon,IDataObject,IContextMenu
857 * In order to support icon positions in the default Listview your DataObject
858 * must implement the SetData method (in addition to GetData :) - the shell
859 * passes a barely documented "Icon positions" structure to SetData when the
860 * drag starts, and GetData's it if the drop is in another explorer window that
861 * needs the positions.
863 HRESULT WINAPI
CFSFolder::GetUIObjectOf(HWND hwndOwner
,
864 UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
,
865 REFIID riid
, UINT
* prgfInOut
,
869 HRESULT hr
= E_INVALIDARG
;
871 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
872 this, hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
878 if (IsEqualIID(riid
, IID_IContextMenu
) && (cidl
>= 1))
882 AddFSClassKeysToArray(apidl
[0], hKeys
, &cKeys
);
885 dcm
.hwnd
= hwndOwner
;
887 dcm
.pidlFolder
= pidlRoot
;
893 dcm
.punkAssociationInfo
= NULL
;
894 hr
= SHCreateDefaultContextMenu (&dcm
, riid
, &pObj
);
896 else if (IsEqualIID (riid
, IID_IDataObject
))
900 hr
= IDataObject_Constructor (hwndOwner
, pidlRoot
, apidl
, cidl
, (IDataObject
**)&pObj
);
907 else if ((IsEqualIID (riid
, IID_IExtractIconA
) || IsEqualIID (riid
, IID_IExtractIconW
)) && (cidl
== 1))
909 hr
= CFSExtractIcon_CreateInstance(this, apidl
[0], riid
, &pObj
);
911 else if (IsEqualIID (riid
, IID_IDropTarget
))
913 /* only interested in attempting to bind to shell folders, not files (except exe), so if we fail, rebind to root */
914 if (cidl
!= 1 || FAILED(hr
= this->_GetDropTarget(apidl
[0], (LPVOID
*) &pObj
)))
916 IDropTarget
* pDt
= NULL
;
917 hr
= CFSDropTarget_CreateInstance(sPathTarget
, riid
, ppvOut
);
921 else if ((IsEqualIID(riid
, IID_IShellLinkW
) ||
922 IsEqualIID(riid
, IID_IShellLinkA
)) && (cidl
== 1))
924 hr
= IShellLink_ConstructFromFile(this, apidl
[0], riid
, &pObj
);
929 if (SUCCEEDED(hr
) && !pObj
)
934 TRACE("(%p)->hr=0x%08x\n", this, hr
);
938 static const WCHAR AdvancedW
[] = L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced";
939 static const WCHAR HideFileExtW
[] = L
"HideFileExt";
940 static const WCHAR NeverShowExtW
[] = L
"NeverShowExt";
942 /******************************************************************************
943 * SHELL_FS_HideExtension [Internal]
945 * Query the registry if the filename extension of a given path should be
949 * szPath [I] Relative or absolute path of a file
952 * TRUE, if the filename's extension should be hidden
955 BOOL
SHELL_FS_HideExtension(LPWSTR szPath
)
959 DWORD dwDataSize
= sizeof (DWORD
);
960 BOOL doHide
= FALSE
; /* The default value is FALSE (win98 at least) */
962 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, AdvancedW
, 0, 0, 0, KEY_ALL_ACCESS
, 0, &hKey
, 0)) {
963 if (!RegQueryValueExW(hKey
, HideFileExtW
, 0, 0, (LPBYTE
) &dwData
, &dwDataSize
))
969 LPWSTR ext
= PathFindExtensionW(szPath
);
972 WCHAR classname
[MAX_PATH
];
973 LONG classlen
= sizeof(classname
);
975 if (!RegQueryValueW(HKEY_CLASSES_ROOT
, ext
, classname
, &classlen
))
976 if (!RegOpenKeyW(HKEY_CLASSES_ROOT
, classname
, &hKey
)) {
977 if (!RegQueryValueExW(hKey
, NeverShowExtW
, 0, NULL
, NULL
, NULL
))
986 void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath
, DWORD dwFlags
)
988 /*FIXME: MSDN also mentions SHGDN_FOREDITING which is not yet handled. */
989 if (!(dwFlags
& SHGDN_FORPARSING
) &&
990 ((dwFlags
& SHGDN_INFOLDER
) || (dwFlags
== SHGDN_NORMAL
))) {
991 if (SHELL_FS_HideExtension(szPath
) && szPath
[0] != '.')
992 PathRemoveExtensionW(szPath
);
996 /**************************************************************************
997 * CFSFolder::GetDisplayNameOf
998 * Retrieves the display name for the specified file object or subfolder
1001 * LPCITEMIDLIST pidl, //[in ] complex pidl to item
1002 * DWORD dwFlags, //[in ] SHGNO formatting flags
1003 * LPSTRRET lpName) //[out] Returned display name
1006 * if the name is in the pidl the ret value should be a STRRET_OFFSET
1009 HRESULT WINAPI
CFSFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
,
1010 DWORD dwFlags
, LPSTRRET strRet
)
1013 return E_INVALIDARG
;
1015 /* If it is a complex pidl, let the child handle it */
1016 if (!_ILIsPidlSimple (pidl
)) /* complex pidl */
1018 return SHELL32_GetDisplayNameOfChild(this, pidl
, dwFlags
, strRet
);
1020 else if (pidl
&& !pidl
->mkid
.cb
) /* empty pidl */
1022 /* If it is an empty pidl return only the path of the folder */
1023 if ((GET_SHGDN_FOR(dwFlags
) & SHGDN_FORPARSING
) &&
1024 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
) &&
1027 return SHSetStrRet(strRet
, sPathTarget
);
1029 return E_INVALIDARG
;
1033 LPWSTR pszPath
= (LPWSTR
)CoTaskMemAlloc((MAX_PATH
+ 1) * sizeof(WCHAR
));
1035 return E_OUTOFMEMORY
;
1037 if ((GET_SHGDN_FOR(dwFlags
) & SHGDN_FORPARSING
) &&
1038 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
) &&
1041 lstrcpynW(pszPath
, sPathTarget
, MAX_PATH
);
1042 PathAddBackslashW(pszPath
);
1043 len
= wcslen(pszPath
);
1045 _ILSimpleGetTextW(pidl
, pszPath
+ len
, MAX_PATH
+ 1 - len
);
1046 if (!_ILIsFolder(pidl
)) SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
1048 strRet
->uType
= STRRET_WSTR
;
1049 strRet
->pOleStr
= pszPath
;
1051 TRACE ("-- (%p)->(%s)\n", this, strRet
->uType
== STRRET_CSTR
? strRet
->cStr
: debugstr_w(strRet
->pOleStr
));
1055 /**************************************************************************
1056 * CFSFolder::SetNameOf
1057 * Changes the name of a file object or subfolder, possibly changing its item
1058 * identifier in the process.
1061 * HWND hwndOwner, //[in ] Owner window for output
1062 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
1063 * LPCOLESTR lpszName, //[in ] the items new display name
1064 * DWORD dwFlags, //[in ] SHGNO formatting flags
1065 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
1067 HRESULT WINAPI
CFSFolder::SetNameOf(
1069 PCUITEMID_CHILD pidl
,
1072 PITEMID_CHILD
*pPidlOut
)
1074 WCHAR szSrc
[MAX_PATH
+ 1], szDest
[MAX_PATH
+ 1];
1076 BOOL bIsFolder
= _ILIsFolder (ILFindLastID (pidl
));
1078 TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this, hwndOwner
, pidl
,
1079 debugstr_w (lpName
), dwFlags
, pPidlOut
);
1081 /* build source path */
1082 lstrcpynW(szSrc
, sPathTarget
, MAX_PATH
);
1083 ptr
= PathAddBackslashW (szSrc
);
1085 _ILSimpleGetTextW (pidl
, ptr
, MAX_PATH
+ 1 - (ptr
- szSrc
));
1087 /* build destination path */
1088 if (dwFlags
== SHGDN_NORMAL
|| dwFlags
& SHGDN_INFOLDER
) {
1089 lstrcpynW(szDest
, sPathTarget
, MAX_PATH
);
1090 ptr
= PathAddBackslashW (szDest
);
1092 lstrcpynW(ptr
, lpName
, MAX_PATH
+ 1 - (ptr
- szDest
));
1094 lstrcpynW(szDest
, lpName
, MAX_PATH
);
1096 if(!(dwFlags
& SHGDN_FORPARSING
) && SHELL_FS_HideExtension(szSrc
)) {
1097 WCHAR
*ext
= PathFindExtensionW(szSrc
);
1099 INT len
= wcslen(szDest
);
1100 lstrcpynW(szDest
+ len
, ext
, MAX_PATH
- len
);
1104 TRACE ("src=%s dest=%s\n", debugstr_w(szSrc
), debugstr_w(szDest
));
1105 if (!memcmp(szSrc
, szDest
, (wcslen(szDest
) + 1) * sizeof(WCHAR
)))
1107 /* src and destination is the same */
1110 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
1116 if (MoveFileW (szSrc
, szDest
))
1121 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
1123 SHChangeNotify (bIsFolder
? SHCNE_RENAMEFOLDER
: SHCNE_RENAMEITEM
,
1124 SHCNF_PATHW
, szSrc
, szDest
);
1132 HRESULT WINAPI
CFSFolder::GetDefaultSearchGUID(GUID
* pguid
)
1134 FIXME ("(%p)\n", this);
1138 HRESULT WINAPI
CFSFolder::EnumSearches(IEnumExtraSearch
** ppenum
)
1140 FIXME ("(%p)\n", this);
1144 HRESULT WINAPI
CFSFolder::GetDefaultColumn(DWORD dwRes
,
1145 ULONG
* pSort
, ULONG
* pDisplay
)
1147 TRACE ("(%p)\n", this);
1157 HRESULT WINAPI
CFSFolder::GetDefaultColumnState(UINT iColumn
,
1160 TRACE ("(%p)\n", this);
1162 if (!pcsFlags
|| iColumn
>= GENERICSHELLVIEWCOLUMNS
)
1163 return E_INVALIDARG
;
1165 *pcsFlags
= GenericSFHeader
[iColumn
].pcsFlags
;
1170 HRESULT WINAPI
CFSFolder::GetDetailsEx(PCUITEMID_CHILD pidl
,
1171 const SHCOLUMNID
* pscid
, VARIANT
* pv
)
1173 FIXME ("(%p)\n", this);
1178 HRESULT WINAPI
CFSFolder::GetDetailsOf(PCUITEMID_CHILD pidl
,
1179 UINT iColumn
, SHELLDETAILS
* psd
)
1181 HRESULT hr
= E_FAIL
;
1183 TRACE ("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
1185 if (!psd
|| iColumn
>= GENERICSHELLVIEWCOLUMNS
)
1186 return E_INVALIDARG
;
1190 /* the header titles */
1191 psd
->fmt
= GenericSFHeader
[iColumn
].fmt
;
1192 psd
->cxChar
= GenericSFHeader
[iColumn
].cxChar
;
1193 return SHSetStrRet(&psd
->str
, GenericSFHeader
[iColumn
].colnameid
);
1198 psd
->str
.uType
= STRRET_CSTR
;
1199 /* the data from the pidl */
1203 hr
= GetDisplayNameOf (pidl
, SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
1205 case 1: /* FIXME: comments */
1206 psd
->str
.cStr
[0] = 0;
1209 _ILGetFileType(pidl
, psd
->str
.cStr
, MAX_PATH
);
1212 _ILGetFileSize(pidl
, psd
->str
.cStr
, MAX_PATH
);
1215 _ILGetFileDate(pidl
, psd
->str
.cStr
, MAX_PATH
);
1217 case 5: /* attributes */
1218 _ILGetFileAttributes(pidl
, psd
->str
.cStr
, MAX_PATH
);
1226 HRESULT WINAPI
CFSFolder::MapColumnToSCID (UINT column
,
1229 FIXME ("(%p)\n", this);
1233 /************************************************************************
1234 * CFSFolder::GetClassID
1236 HRESULT WINAPI
CFSFolder::GetClassID(CLSID
* lpClassId
)
1238 TRACE ("(%p)\n", this);
1243 *lpClassId
= *pclsid
;
1248 /************************************************************************
1249 * CFSFolder::Initialize
1252 * sPathTarget is not set. Don't know how to handle in a non rooted environment.
1254 HRESULT WINAPI
CFSFolder::Initialize(LPCITEMIDLIST pidl
)
1256 WCHAR wszTemp
[MAX_PATH
];
1258 TRACE ("(%p)->(%p)\n", this, pidl
);
1260 SHFree (pidlRoot
); /* free the old pidl */
1261 pidlRoot
= ILClone (pidl
); /* set my pidl */
1263 SHFree (sPathTarget
);
1267 if (SHGetPathFromIDListW (pidl
, wszTemp
))
1269 int len
= wcslen(wszTemp
);
1270 sPathTarget
= (WCHAR
*)SHAlloc((len
+ 1) * sizeof(WCHAR
));
1272 return E_OUTOFMEMORY
;
1273 memcpy(sPathTarget
, wszTemp
, (len
+ 1) * sizeof(WCHAR
));
1276 TRACE ("--(%p)->(%s)\n", this, debugstr_w(sPathTarget
));
1280 /**************************************************************************
1281 * CFSFolder::GetCurFolder
1283 HRESULT WINAPI
CFSFolder::GetCurFolder(LPITEMIDLIST
* pidl
)
1285 TRACE ("(%p)->(%p)\n", this, pidl
);
1290 *pidl
= ILClone(pidlRoot
);
1294 /**************************************************************************
1295 * CFSFolder::InitializeEx
1297 * FIXME: error handling
1299 HRESULT WINAPI
CFSFolder::InitializeEx(IBindCtx
* pbc
, LPCITEMIDLIST pidlRootx
,
1300 const PERSIST_FOLDER_TARGET_INFO
* ppfti
)
1302 WCHAR wszTemp
[MAX_PATH
];
1304 TRACE("(%p)->(%p,%p,%p)\n", this, pbc
, pidlRootx
, ppfti
);
1306 TRACE("--%p %s %s 0x%08x 0x%08x\n",
1307 ppfti
->pidlTargetFolder
, debugstr_w (ppfti
->szTargetParsingName
),
1308 debugstr_w (ppfti
->szNetworkProvider
), ppfti
->dwAttributes
,
1312 if (ppfti
&& ppfti
->pidlTargetFolder
)
1313 pdump(ppfti
->pidlTargetFolder
);
1316 __SHFreeAndNil(&pidlRoot
); /* free the old */
1318 __SHFreeAndNil(&sPathTarget
);
1321 * Root path and pidl
1323 pidlRoot
= ILClone(pidlRootx
);
1326 * the target folder is spezified in csidl OR pidlTargetFolder OR
1327 * szTargetParsingName
1331 if (ppfti
->csidl
!= -1)
1333 if (SHGetSpecialFolderPathW(0, wszTemp
, ppfti
->csidl
,
1334 ppfti
->csidl
& CSIDL_FLAG_CREATE
)) {
1335 int len
= wcslen(wszTemp
);
1336 sPathTarget
= (WCHAR
*)SHAlloc((len
+ 1) * sizeof(WCHAR
));
1338 return E_OUTOFMEMORY
;
1339 memcpy(sPathTarget
, wszTemp
, (len
+ 1) * sizeof(WCHAR
));
1342 else if (ppfti
->szTargetParsingName
[0])
1344 int len
= wcslen(ppfti
->szTargetParsingName
);
1345 sPathTarget
= (WCHAR
*)SHAlloc((len
+ 1) * sizeof(WCHAR
));
1347 return E_OUTOFMEMORY
;
1348 memcpy(sPathTarget
, ppfti
->szTargetParsingName
,
1349 (len
+ 1) * sizeof(WCHAR
));
1351 else if (ppfti
->pidlTargetFolder
)
1353 if (SHGetPathFromIDListW(ppfti
->pidlTargetFolder
, wszTemp
))
1355 int len
= wcslen(wszTemp
);
1356 sPathTarget
= (WCHAR
*)SHAlloc((len
+ 1) * sizeof(WCHAR
));
1358 return E_OUTOFMEMORY
;
1359 memcpy(sPathTarget
, wszTemp
, (len
+ 1) * sizeof(WCHAR
));
1364 TRACE("--(%p)->(target=%s)\n", this, debugstr_w(sPathTarget
));
1366 return (sPathTarget
) ? S_OK
: E_FAIL
;
1369 HRESULT WINAPI
CFSFolder::GetFolderTargetInfo(PERSIST_FOLDER_TARGET_INFO
* ppfti
)
1371 FIXME("(%p)->(%p)\n", this, ppfti
);
1372 ZeroMemory(ppfti
, sizeof (*ppfti
));
1376 HRESULT WINAPI
CFSFolder::_GetDropTarget(LPCITEMIDLIST pidl
, LPVOID
*ppvOut
) {
1380 TRACE("CFSFolder::_GetDropTarget entered\n");
1382 if (_ILIsFolder (pidl
))
1384 CComPtr
<IShellFolder
> psfChild
;
1385 hr
= this->BindToObject(pidl
, NULL
, IID_PPV_ARG(IShellFolder
, &psfChild
));
1386 if (FAILED_UNEXPECTEDLY(hr
))
1389 return psfChild
->CreateViewObject(NULL
, IID_IDropTarget
, ppvOut
);
1393 hr
= this->GetDisplayNameOf(pidl
, SHGDN_FORPARSING
, &strFile
);
1396 WCHAR wszPath
[MAX_PATH
];
1397 hr
= StrRetToBufW(&strFile
, pidl
, wszPath
, _countof(wszPath
));
1401 LPCWSTR pwszExt
= PathFindExtensionW(wszPath
);
1404 /* enumerate dynamic/static for a given file class */
1405 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, pwszExt
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
1407 /* load dynamic extensions from file extension key, for example .jpg */
1408 _LoadDynamicDropTargetHandlerForKey(hKey
, wszPath
, ppvOut
);
1413 DWORD dwSize
= sizeof(wszTemp
);
1414 if (RegGetValueW(HKEY_CLASSES_ROOT
, pwszExt
, NULL
, RRF_RT_REG_SZ
, NULL
, wszTemp
, &dwSize
) == ERROR_SUCCESS
)
1416 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, wszTemp
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
)
1418 /* load dynamic extensions from progid key, for example jpegfile */
1419 _LoadDynamicDropTargetHandlerForKey(hKey
, wszPath
, ppvOut
);
1427 ERR("GetDisplayNameOf failed: %x\n", hr
);
1432 HRESULT WINAPI
CFSFolder::_LoadDynamicDropTargetHandlerForKey(HKEY hRootKey
, LPCWSTR pwcsname
, LPVOID
*ppvOut
)
1434 TRACE("CFSFolder::_LoadDynamicDropTargetHandlerForKey entered\n");
1436 WCHAR wszName
[MAX_PATH
];
1437 DWORD dwSize
= sizeof(wszName
);
1441 res
= RegGetValueW(hRootKey
, L
"shellex\\DropHandler", NULL
, RRF_RT_REG_SZ
, NULL
, wszName
, &dwSize
);
1442 if (res
!= ERROR_SUCCESS
)
1446 hr
= CLSIDFromString(wszName
, &clsid
);
1447 if (FAILED_UNEXPECTEDLY(hr
))
1450 if (m_bGroupPolicyActive
)
1452 res
= RegGetValueW(HKEY_LOCAL_MACHINE
,
1453 L
"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved",
1459 if (res
!= ERROR_SUCCESS
)
1461 ERR("DropHandler extension %S not approved\n", wszName
);
1466 hr
= _LoadDynamicDropTargetHandler(&clsid
, pwcsname
, ppvOut
);
1467 if (FAILED_UNEXPECTEDLY(hr
))
1473 HRESULT WINAPI
CFSFolder::_LoadDynamicDropTargetHandler(const CLSID
*pclsid
, LPCWSTR pwcsname
, LPVOID
*ppvOut
)
1475 TRACE("CFSFolder::_LoadDynamicDropTargetHandler entered\n");
1478 CComPtr
<IPersistFile
> pp
;
1479 hr
= SHCoCreateInstance(NULL
, pclsid
, NULL
, IID_PPV_ARG(IPersistFile
, &pp
));
1482 ERR("SHCoCreateInstance failed %x\n", GetLastError());
1484 pp
->Load(pwcsname
, 0);
1486 hr
= pp
->QueryInterface(IID_PPV_ARG(IDropTarget
, (IDropTarget
**) ppvOut
));
1489 ERR("Failed to query for interface IID_IShellExtInit hr %x pclsid %s\n", hr
, wine_dbgstr_guid(pclsid
));
1495 HRESULT WINAPI
CFSFolder::CallBack(IShellFolder
*psf
, HWND hwndOwner
, IDataObject
*pdtobj
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1497 if (uMsg
!= DFM_MERGECONTEXTMENU
&& uMsg
!= DFM_INVOKECOMMAND
)
1500 /* no data object means no selection */
1503 if (uMsg
== DFM_INVOKECOMMAND
&& wParam
== DFM_CMD_PROPERTIES
)
1505 PUITEMID_CHILD pidlChild
= ILClone(ILFindLastID(pidlRoot
));
1506 LPITEMIDLIST pidlParent
= ILClone(pidlRoot
);
1507 ILRemoveLastID(pidlParent
);
1508 HRESULT hr
= SH_ShowPropertiesDialog(sPathTarget
, pidlParent
, &pidlChild
);
1510 ERR("SH_ShowPropertiesDialog failed\n");
1514 else if (uMsg
== DFM_MERGECONTEXTMENU
)
1516 QCMINFO
*pqcminfo
= (QCMINFO
*)lParam
;
1517 _InsertMenuItemW(pqcminfo
->hmenu
, pqcminfo
->indexMenu
++, TRUE
, 0, MFT_SEPARATOR
, NULL
, 0);
1518 _InsertMenuItemW(pqcminfo
->hmenu
, pqcminfo
->indexMenu
++, TRUE
, FCIDM_SHVIEW_PROPERTIES
, MFT_STRING
, MAKEINTRESOURCEW(IDS_PROPERTIES
), MFS_ENABLED
);
1524 if (uMsg
!= DFM_INVOKECOMMAND
|| wParam
!= DFM_CMD_PROPERTIES
)
1527 PIDLIST_ABSOLUTE pidlFolder
;
1528 PUITEMID_CHILD
*apidl
;
1530 HRESULT hr
= SH_GetApidlFromDataObject(pdtobj
, &pidlFolder
, &apidl
, &cidl
);
1531 if (FAILED_UNEXPECTEDLY(hr
))
1535 ERR("SHMultiFileProperties is not yet implemented\n");
1538 hr
= GetDisplayNameOf(apidl
[0], SHGDN_FORPARSING
, &strFile
);
1541 hr
= SH_ShowPropertiesDialog(strFile
.pOleStr
, pidlFolder
, apidl
);
1543 ERR("SH_ShowPropertiesDialog failed\n");
1547 ERR("Failed to get display name\n");
1551 _ILFreeaPidl(apidl
, cidl
);