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
24 #include "wine/port.h"
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
46 #include "undocshell.h"
47 #include "shell32_main.h"
50 #include "shellfolder.h"
51 #include "wine/debug.h"
55 WINE_DEFAULT_DEBUG_CHANNEL (shell
);
57 /***********************************************************************
58 * IShellFolder implementation
62 IUnknown IUnknown_inner
;
64 IShellFolder2 IShellFolder2_iface
;
65 IPersistFolder3 IPersistFolder3_iface
;
66 IDropTarget IDropTarget_iface
;
67 ISFHelper ISFHelper_iface
;
72 /* both paths are parsible from the desktop */
73 LPWSTR sPathTarget
; /* complete path to target used for enumeration and ChangeNotify */
75 LPITEMIDLIST pidlRoot
; /* absolute pidl */
77 UINT cfShellIDList
; /* clipboardformat for IDropTarget */
78 BOOL fAcceptFmt
; /* flag for pending Drop */
81 static inline IGenericSFImpl
*impl_from_IUnknown(IUnknown
*iface
)
83 return CONTAINING_RECORD(iface
, IGenericSFImpl
, IUnknown_inner
);
86 static inline IGenericSFImpl
*impl_from_IShellFolder2(IShellFolder2
*iface
)
88 return CONTAINING_RECORD(iface
, IGenericSFImpl
, IShellFolder2_iface
);
91 static inline IGenericSFImpl
*impl_from_IPersistFolder3(IPersistFolder3
*iface
)
93 return CONTAINING_RECORD(iface
, IGenericSFImpl
, IPersistFolder3_iface
);
96 static inline IGenericSFImpl
*impl_from_IDropTarget(IDropTarget
*iface
)
98 return CONTAINING_RECORD(iface
, IGenericSFImpl
, IDropTarget_iface
);
101 static inline IGenericSFImpl
*impl_from_ISFHelper(ISFHelper
*iface
)
103 return CONTAINING_RECORD(iface
, IGenericSFImpl
, ISFHelper_iface
);
106 /**************************************************************************
107 * registers clipboardformat once
109 static void SF_RegisterClipFmt (IGenericSFImpl
* This
)
111 TRACE ("(%p)\n", This
);
113 if (!This
->cfShellIDList
) {
114 This
->cfShellIDList
= RegisterClipboardFormatW (CFSTR_SHELLIDLISTW
);
118 /**************************************************************************
121 static HRESULT WINAPI
IUnknown_fnQueryInterface(IUnknown
*iface
, REFIID riid
, void **ppvObj
)
123 IGenericSFImpl
*This
= impl_from_IUnknown(iface
);
125 TRACE("(%p)->(%s,%p)\n", This
, shdebugstr_guid(riid
), ppvObj
);
129 if (IsEqualIID (riid
, &IID_IUnknown
))
130 *ppvObj
= &This
->IUnknown_inner
;
131 else if (IsEqualIID(riid
, &IID_IShellFolder
) || IsEqualIID(riid
, &IID_IShellFolder2
))
132 *ppvObj
= &This
->IShellFolder2_iface
;
133 else if (IsEqualIID(riid
, &IID_IPersist
) || IsEqualIID(riid
, &IID_IPersistFolder
) ||
134 IsEqualIID(riid
, &IID_IPersistFolder2
) || IsEqualIID(riid
, &IID_IPersistFolder3
))
135 *ppvObj
= &This
->IPersistFolder3_iface
;
136 else if (IsEqualIID (riid
, &IID_ISFHelper
))
137 *ppvObj
= &This
->ISFHelper_iface
;
138 else if (IsEqualIID (riid
, &IID_IDropTarget
)) {
139 *ppvObj
= &This
->IDropTarget_iface
;
140 SF_RegisterClipFmt(This
);
144 IUnknown_AddRef((IUnknown
*)*ppvObj
);
145 TRACE ("-- Interface = %p\n", *ppvObj
);
148 TRACE ("-- Interface: E_NOINTERFACE\n");
149 return E_NOINTERFACE
;
152 static ULONG WINAPI
IUnknown_fnAddRef(IUnknown
*iface
)
154 IGenericSFImpl
*This
= impl_from_IUnknown(iface
);
155 ULONG ref
= InterlockedIncrement(&This
->ref
);
157 TRACE("(%p) ref=%d\n", This
, ref
);
162 static ULONG WINAPI
IUnknown_fnRelease(IUnknown
*iface
)
164 IGenericSFImpl
*This
= impl_from_IUnknown(iface
);
165 ULONG ref
= InterlockedDecrement(&This
->ref
);
167 TRACE("(%p) ref=%d\n", This
, ref
);
170 TRACE("-- destroying IShellFolder(%p)\n", This
);
172 SHFree(This
->pidlRoot
);
173 SHFree(This
->sPathTarget
);
179 static const IUnknownVtbl unkvt
=
181 IUnknown_fnQueryInterface
,
186 static const shvheader GenericSFHeader
[] = {
187 {IDS_SHV_COLUMN1
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 15},
188 {IDS_SHV_COLUMN2
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
189 {IDS_SHV_COLUMN3
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
190 {IDS_SHV_COLUMN4
, SHCOLSTATE_TYPE_DATE
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 12},
191 {IDS_SHV_COLUMN5
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 5}
194 #define GENERICSHELLVIEWCOLUMNS 5
196 /**************************************************************************
197 * IShellFolder_fnQueryInterface
199 static HRESULT WINAPI
IShellFolder_fnQueryInterface(IShellFolder2
*iface
, REFIID riid
,
202 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
204 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppvObj
);
207 /**************************************************************************
208 * IShellFolder_AddRef
210 static ULONG WINAPI
IShellFolder_fnAddRef(IShellFolder2
*iface
)
212 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
214 return IUnknown_AddRef(This
->outer_unk
);
217 /**************************************************************************
218 * IShellFolder_fnRelease
220 static ULONG WINAPI
IShellFolder_fnRelease(IShellFolder2
*iface
)
222 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
224 return IUnknown_Release(This
->outer_unk
);
227 /**************************************************************************
228 * SHELL32_CreatePidlFromBindCtx [internal]
230 * If the caller bound File System Bind Data, assume it is the
231 * find data for the path.
232 * This allows binding of paths that don't exist.
234 LPITEMIDLIST
SHELL32_CreatePidlFromBindCtx(IBindCtx
*pbc
, LPCWSTR path
)
236 static WCHAR szfsbc
[] = {
237 'F','i','l','e',' ','S','y','s','t','e','m',' ',
238 'B','i','n','d',' ','D','a','t','a',0 };
239 IFileSystemBindData
*fsbd
= NULL
;
240 LPITEMIDLIST pidl
= NULL
;
241 IUnknown
*unk
= NULL
;
244 TRACE("%p %s\n", pbc
, debugstr_w(path
));
249 /* see if the caller bound File System Bind Data */
250 r
= IBindCtx_GetObjectParam( pbc
, szfsbc
, &unk
);
254 r
= IUnknown_QueryInterface( unk
, &IID_IFileSystemBindData
, (void**)&fsbd
);
257 WIN32_FIND_DATAW wfd
;
259 r
= IFileSystemBindData_GetFindData( fsbd
, &wfd
);
262 lstrcpynW( &wfd
.cFileName
[0], path
, MAX_PATH
);
263 pidl
= _ILCreateFromFindDataW( &wfd
);
265 IFileSystemBindData_Release( fsbd
);
267 IUnknown_Release( unk
);
272 /**************************************************************************
273 * IShellFolder_ParseDisplayName {SHELL32}
275 * Parse a display name.
278 * hwndOwner [in] Parent window for any message's
279 * pbc [in] optional FileSystemBindData context
280 * lpszDisplayName [in] Unicode displayname.
281 * pchEaten [out] (unicode) characters processed
282 * ppidl [out] complex pidl to item
283 * pdwAttributes [out] items attributes
286 * Every folder tries to parse only its own (the leftmost) pidl and creates a
287 * subfolder to evaluate the remaining parts.
288 * Now we can parse into namespaces implemented by shell extensions
290 * Behaviour on win98: lpszDisplayName=NULL -> crash
291 * lpszDisplayName="" -> returns mycoputer-pidl
294 * pdwAttributes is not set
295 * pchEaten is not set like in windows
297 static HRESULT WINAPI
298 IShellFolder_fnParseDisplayName (IShellFolder2
* iface
,
301 LPOLESTR lpszDisplayName
,
302 DWORD
* pchEaten
, LPITEMIDLIST
* ppidl
,
303 DWORD
* pdwAttributes
)
305 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
307 HRESULT hr
= E_INVALIDARG
;
308 LPCWSTR szNext
= NULL
;
309 WCHAR szElement
[MAX_PATH
];
310 WCHAR szPath
[MAX_PATH
];
311 LPITEMIDLIST pidlTemp
= NULL
;
314 TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
315 This
, hwndOwner
, pbc
, lpszDisplayName
, debugstr_w (lpszDisplayName
),
316 pchEaten
, ppidl
, pdwAttributes
);
318 if (!lpszDisplayName
|| !ppidl
)
322 *pchEaten
= 0; /* strange but like the original */
324 pidlTemp
= SHELL32_CreatePidlFromBindCtx(pbc
, lpszDisplayName
);
325 if (!pidlTemp
&& *lpszDisplayName
)
327 /* get the next element */
328 szNext
= GetNextElementW (lpszDisplayName
, szElement
, MAX_PATH
);
330 /* build the full pathname to the element */
331 lstrcpynW(szPath
, This
->sPathTarget
, MAX_PATH
- 1);
332 PathAddBackslashW(szPath
);
333 len
= lstrlenW(szPath
);
334 lstrcpynW(szPath
+ len
, szElement
, MAX_PATH
- len
);
337 hr
= _ILCreateFromPathW(szPath
, &pidlTemp
);
340 if (szNext
&& *szNext
) {
341 /* try to analyse the next element */
342 hr
= SHELL32_ParseNextElement (iface
, hwndOwner
, pbc
,
343 &pidlTemp
, (LPOLESTR
) szNext
, pchEaten
, pdwAttributes
);
345 /* it's the last element */
346 if (pdwAttributes
&& *pdwAttributes
) {
347 hr
= SHELL32_GetItemAttributes((IShellFolder
*)&This
->IShellFolder2_iface
,
348 pidlTemp
, pdwAttributes
);
359 TRACE ("(%p)->(-- pidl=%p ret=0x%08x)\n", This
, *ppidl
, hr
);
364 /**************************************************************************
365 * IShellFolder_fnEnumObjects
367 * HWND hwndOwner, //[in ] Parent Window
368 * DWORD grfFlags, //[in ] SHCONTF enumeration mask
369 * LPENUMIDLIST* ppenumIDList //[out] IEnumIDList interface
371 static HRESULT WINAPI
372 IShellFolder_fnEnumObjects (IShellFolder2
* iface
, HWND hwndOwner
,
373 DWORD dwFlags
, LPENUMIDLIST
* ppEnumIDList
)
375 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
376 IEnumIDListImpl
*list
;
378 TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", This
, hwndOwner
,
379 dwFlags
, ppEnumIDList
);
381 if (!(list
= IEnumIDList_Constructor()))
382 return E_OUTOFMEMORY
;
383 CreateFolderEnumList(list
, This
->sPathTarget
, dwFlags
);
384 *ppEnumIDList
= &list
->IEnumIDList_iface
;
386 TRACE ("-- (%p)->(new ID List: %p)\n", This
, *ppEnumIDList
);
391 /**************************************************************************
392 * IShellFolder_fnBindToObject
394 * LPCITEMIDLIST pidl, //[in ] relative pidl to open
395 * LPBC pbc, //[in ] optional FileSystemBindData context
396 * REFIID riid, //[in ] Initial Interface
397 * LPVOID* ppvObject //[out] Interface*
399 static HRESULT WINAPI
400 IShellFolder_fnBindToObject (IShellFolder2
* iface
, LPCITEMIDLIST pidl
,
401 LPBC pbc
, REFIID riid
, LPVOID
* ppvOut
)
403 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
405 TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This
, pidl
, pbc
,
406 shdebugstr_guid (riid
), ppvOut
);
408 return SHELL32_BindToChild (This
->pidlRoot
, This
->sPathTarget
, pidl
, riid
,
412 /**************************************************************************
413 * IShellFolder_fnBindToStorage
415 * LPCITEMIDLIST pidl, //[in ] complex pidl to store
416 * LPBC pbc, //[in ] reserved
417 * REFIID riid, //[in ] Initial storage interface
418 * LPVOID* ppvObject //[out] Interface* returned
420 static HRESULT WINAPI
421 IShellFolder_fnBindToStorage (IShellFolder2
* iface
, LPCITEMIDLIST pidl
,
422 LPBC pbcReserved
, REFIID riid
, LPVOID
* ppvOut
)
424 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
426 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This
, pidl
, pbcReserved
,
427 shdebugstr_guid (riid
), ppvOut
);
433 /**************************************************************************
434 * IShellFolder_fnCompareIDs
437 static HRESULT WINAPI
438 IShellFolder_fnCompareIDs (IShellFolder2
* iface
, LPARAM lParam
,
439 LPCITEMIDLIST pidl1
, LPCITEMIDLIST pidl2
)
441 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
445 TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This
, lParam
, pidl1
, pidl2
);
446 nReturn
= SHELL32_CompareIDs(&This
->IShellFolder2_iface
, lParam
, pidl1
, pidl2
);
447 TRACE ("-- %i\n", nReturn
);
451 /**************************************************************************
452 * IShellFolder_fnCreateViewObject
454 static HRESULT WINAPI
455 IShellFolder_fnCreateViewObject (IShellFolder2
* iface
, HWND hwndOwner
,
456 REFIID riid
, LPVOID
* ppvOut
)
458 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
460 LPSHELLVIEW pShellView
;
461 HRESULT hr
= E_INVALIDARG
;
463 TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This
, hwndOwner
, shdebugstr_guid (riid
),
469 if (IsEqualIID (riid
, &IID_IDropTarget
)) {
470 hr
= IShellFolder2_QueryInterface (iface
, &IID_IDropTarget
, ppvOut
);
471 } else if (IsEqualIID (riid
, &IID_IContextMenu
)) {
472 FIXME ("IContextMenu not implemented\n");
474 } else if (IsEqualIID (riid
, &IID_IShellView
)) {
475 pShellView
= IShellView_Constructor ((IShellFolder
*) iface
);
477 hr
= IShellView_QueryInterface (pShellView
, riid
, ppvOut
);
478 IShellView_Release (pShellView
);
482 TRACE ("-- (%p)->(interface=%p)\n", This
, ppvOut
);
486 /**************************************************************************
487 * IShellFolder_fnGetAttributesOf
490 * UINT cidl, //[in ] num elements in pidl array
491 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
492 * ULONG* rgfInOut) //[out] result array
495 static HRESULT WINAPI
496 IShellFolder_fnGetAttributesOf (IShellFolder2
* iface
, UINT cidl
,
497 LPCITEMIDLIST
* apidl
, DWORD
* rgfInOut
)
499 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
503 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", This
, cidl
, apidl
,
504 rgfInOut
, rgfInOut
? *rgfInOut
: 0);
515 IShellFolder
*psfParent
= NULL
;
516 LPCITEMIDLIST rpidl
= NULL
;
518 hr
= SHBindToParent(This
->pidlRoot
, &IID_IShellFolder
, (LPVOID
*)&psfParent
, &rpidl
);
520 SHELL32_GetItemAttributes (psfParent
, rpidl
, rgfInOut
);
521 IShellFolder_Release(psfParent
);
525 while (cidl
> 0 && *apidl
) {
527 SHELL32_GetItemAttributes((IShellFolder
*)&This
->IShellFolder2_iface
, *apidl
, rgfInOut
);
532 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
533 *rgfInOut
&= ~SFGAO_VALIDATE
;
535 TRACE ("-- result=0x%08x\n", *rgfInOut
);
540 /**************************************************************************
541 * SHELL32_CreateExtensionUIObject (internal)
543 HRESULT
SHELL32_CreateExtensionUIObject(IShellFolder2
*iface
,
544 LPCITEMIDLIST pidl
, REFIID riid
, LPVOID
*ppvOut
)
546 static const WCHAR reg_blockedW
[] = {'S','o','f','t','w','a','r','e','\\',
547 'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
548 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
549 'S','h','e','l','l',' ','E','x','t','e','n','s','i','o','n','s','\\',
550 'B','l','o','c','k','e','d',0};
551 static const WCHAR formatW
[] = {'.','%','s','\\','S','h','e','l','l','E','x','\\',
552 '{','%','0','8','x','-','%','0','4','x','-','%','0','4','x','-',
553 '%','0','2','x','%','0','2','x','-','%','0','2','x','%','0','2','x',
554 '%','0','2','x','%','0','2','x','%','0','2','x','%','0','2','x','}',0};
556 IPersistFile
*persist_file
;
558 WCHAR extensionW
[20], buf
[MAX_PATH
];
559 DWORD size
= MAX_PATH
;
567 if(!_ILGetExtension(pidl
, extensionA
, 20))
570 MultiByteToWideChar(CP_ACP
, 0, extensionA
, -1, extensionW
, 20);
572 sprintfW(buf
, formatW
, extensionW
, riid
->Data1
, riid
->Data2
, riid
->Data3
,
573 riid
->Data4
[0], riid
->Data4
[1], riid
->Data4
[2], riid
->Data4
[3],
574 riid
->Data4
[4], riid
->Data4
[5], riid
->Data4
[6], riid
->Data4
[7]);
576 if(RegGetValueW(HKEY_CLASSES_ROOT
, buf
, NULL
, RRF_RT_REG_SZ
,
577 NULL
, buf
, &size
) != ERROR_SUCCESS
)
580 if(RegCreateKeyExW(HKEY_LOCAL_MACHINE
, reg_blockedW
, 0, 0, 0,
581 KEY_READ
, NULL
, &key
, NULL
) != ERROR_SUCCESS
)
583 if(RegQueryValueExW(key
, buf
, 0, NULL
, NULL
, NULL
)
584 != ERROR_FILE_NOT_FOUND
)
585 return E_ACCESSDENIED
;
588 if(RegCreateKeyExW(HKEY_CURRENT_USER
, reg_blockedW
, 0, 0, 0,
589 KEY_READ
, NULL
, &key
, NULL
) != ERROR_SUCCESS
)
591 if(RegQueryValueExW(key
, buf
, 0, NULL
, NULL
, NULL
)
592 != ERROR_FILE_NOT_FOUND
)
593 return E_ACCESSDENIED
;
596 if(!GUIDFromStringW(buf
, &guid
))
599 hr
= CoCreateInstance(&guid
, NULL
, CLSCTX_INPROC_SERVER
,
600 &IID_IPersistFile
, (void**)&persist_file
);
604 hr
= IShellFolder2_GetDisplayNameOf(iface
, pidl
, SHGDN_FORPARSING
, &path
);
606 hr
= StrRetToStrW(&path
, NULL
, &file
);
608 IPersistFile_Release(persist_file
);
612 hr
= IPersistFile_Load(persist_file
, file
, STGM_READ
);
615 IPersistFile_Release(persist_file
);
619 hr
= IPersistFile_QueryInterface(persist_file
, riid
, ppvOut
);
620 IPersistFile_Release(persist_file
);
624 /**************************************************************************
625 * IShellFolder_fnGetUIObjectOf
628 * HWND hwndOwner, //[in ] Parent window for any output
629 * UINT cidl, //[in ] array size
630 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
631 * REFIID riid, //[in ] Requested Interface
632 * UINT* prgfInOut, //[ ] reserved
633 * LPVOID* ppvObject) //[out] Resulting Interface
636 * This function gets asked to return "view objects" for one or more (multiple
638 * The viewobject typically is an COM object with one of the following
640 * IExtractIcon,IDataObject,IContextMenu
641 * In order to support icon positions in the default Listview your DataObject
642 * must implement the SetData method (in addition to GetData :) - the shell
643 * passes a barely documented "Icon positions" structure to SetData when the
644 * drag starts, and GetData's it if the drop is in another explorer window that
645 * needs the positions.
647 static HRESULT WINAPI
648 IShellFolder_fnGetUIObjectOf (IShellFolder2
* iface
,
650 UINT cidl
, LPCITEMIDLIST
* apidl
, REFIID riid
,
651 UINT
* prgfInOut
, LPVOID
* ppvOut
)
653 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
656 IUnknown
*pObj
= NULL
;
657 HRESULT hr
= E_INVALIDARG
;
659 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
660 This
, hwndOwner
, cidl
, apidl
, shdebugstr_guid (riid
), prgfInOut
, ppvOut
);
666 hr
= SHELL32_CreateExtensionUIObject(iface
, *apidl
, riid
, ppvOut
);
671 if (IsEqualIID (riid
, &IID_IContextMenu
) && (cidl
>= 1)) {
672 return ItemMenu_Constructor((IShellFolder
*)iface
, This
->pidlRoot
, apidl
, cidl
, riid
, ppvOut
);
673 } else if (IsEqualIID (riid
, &IID_IDataObject
) && (cidl
>= 1)) {
674 pObj
= (LPUNKNOWN
) IDataObject_Constructor (hwndOwner
,
675 This
->pidlRoot
, apidl
, cidl
);
677 } else if (IsEqualIID (riid
, &IID_IExtractIconA
) && (cidl
== 1)) {
678 pidl
= ILCombine (This
->pidlRoot
, apidl
[0]);
679 pObj
= (LPUNKNOWN
) IExtractIconA_Constructor (pidl
);
682 } else if (IsEqualIID (riid
, &IID_IExtractIconW
) && (cidl
== 1)) {
683 pidl
= ILCombine (This
->pidlRoot
, apidl
[0]);
684 pObj
= (LPUNKNOWN
) IExtractIconW_Constructor (pidl
);
687 } else if (IsEqualIID (riid
, &IID_IDropTarget
) && (cidl
>= 1)) {
688 hr
= IShellFolder2_QueryInterface (iface
, &IID_IDropTarget
,
690 } else if ((IsEqualIID(riid
,&IID_IShellLinkW
) ||
691 IsEqualIID(riid
,&IID_IShellLinkA
)) && (cidl
== 1)) {
692 pidl
= ILCombine (This
->pidlRoot
, apidl
[0]);
693 hr
= IShellLink_ConstructFromFile(NULL
, riid
, pidl
, &pObj
);
699 if (SUCCEEDED(hr
) && !pObj
)
704 TRACE ("(%p)->hr=0x%08x\n", This
, hr
);
708 static const WCHAR AdvancedW
[] = { 'S','O','F','T','W','A','R','E',
709 '\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
710 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l',
711 'o','r','e','r','\\','A','d','v','a','n','c','e','d',0 };
712 static const WCHAR HideFileExtW
[] = { 'H','i','d','e','F','i','l','e','E','x',
714 static const WCHAR NeverShowExtW
[] = { 'N','e','v','e','r','S','h','o','w','E',
717 /******************************************************************************
718 * SHELL_FS_HideExtension [Internal]
720 * Query the registry if the filename extension of a given path should be
724 * szPath [I] Relative or absolute path of a file
727 * TRUE, if the filename's extension should be hidden
730 BOOL
SHELL_FS_HideExtension(LPCWSTR szPath
)
734 DWORD dwDataSize
= sizeof (DWORD
);
735 BOOL doHide
= FALSE
; /* The default value is FALSE (win98 at least) */
737 if (!RegCreateKeyExW(HKEY_CURRENT_USER
, AdvancedW
, 0, 0, 0, KEY_ALL_ACCESS
, 0, &hKey
, 0)) {
738 if (!RegQueryValueExW(hKey
, HideFileExtW
, 0, 0, (LPBYTE
) &dwData
, &dwDataSize
))
744 LPWSTR ext
= PathFindExtensionW(szPath
);
747 WCHAR classname
[MAX_PATH
];
748 LONG classlen
= sizeof(classname
);
750 if (!RegQueryValueW(HKEY_CLASSES_ROOT
, ext
, classname
, &classlen
))
751 if (!RegOpenKeyW(HKEY_CLASSES_ROOT
, classname
, &hKey
)) {
752 if (!RegQueryValueExW(hKey
, NeverShowExtW
, 0, NULL
, NULL
, NULL
))
761 void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath
, DWORD dwFlags
)
763 /*FIXME: MSDN also mentions SHGDN_FOREDITING which is not yet handled. */
764 if (!(dwFlags
& SHGDN_FORPARSING
) &&
765 ((dwFlags
& SHGDN_INFOLDER
) || (dwFlags
== SHGDN_NORMAL
))) {
766 if (SHELL_FS_HideExtension(szPath
) && szPath
[0] != '.')
767 PathRemoveExtensionW(szPath
);
771 /**************************************************************************
772 * IShellFolder_fnGetDisplayNameOf
773 * Retrieves the display name for the specified file object or subfolder
776 * LPCITEMIDLIST pidl, //[in ] complex pidl to item
777 * DWORD dwFlags, //[in ] SHGNO formatting flags
778 * LPSTRRET lpName) //[out] Returned display name
781 * if the name is in the pidl the ret value should be a STRRET_OFFSET
784 static HRESULT WINAPI
785 IShellFolder_fnGetDisplayNameOf (IShellFolder2
* iface
, LPCITEMIDLIST pidl
,
786 DWORD dwFlags
, LPSTRRET strRet
)
788 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
794 TRACE ("(%p)->(pidl=%p,0x%08x,%p)\n", This
, pidl
, dwFlags
, strRet
);
797 if (!pidl
|| !strRet
)
800 pszPath
= CoTaskMemAlloc((MAX_PATH
+1) * sizeof(WCHAR
));
802 return E_OUTOFMEMORY
;
804 if (_ILIsDesktop(pidl
)) { /* empty pidl */
805 if ((GET_SHGDN_FOR(dwFlags
) & SHGDN_FORPARSING
) &&
806 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
))
808 if (This
->sPathTarget
)
809 lstrcpynW(pszPath
, This
->sPathTarget
, MAX_PATH
);
811 /* pidl has to contain exactly one non null SHITEMID */
814 } else if (_ILIsPidlSimple(pidl
)) {
815 if ((GET_SHGDN_FOR(dwFlags
) & SHGDN_FORPARSING
) &&
816 (GET_SHGDN_RELATION(dwFlags
) != SHGDN_INFOLDER
) &&
819 lstrcpynW(pszPath
, This
->sPathTarget
, MAX_PATH
);
820 PathAddBackslashW(pszPath
);
821 len
= lstrlenW(pszPath
);
823 _ILSimpleGetTextW(pidl
, pszPath
+ len
, MAX_PATH
+ 1 - len
);
824 if (!_ILIsFolder(pidl
)) SHELL_FS_ProcessDisplayFilename(pszPath
, dwFlags
);
826 hr
= SHELL32_GetDisplayNameOfChild(iface
, pidl
, dwFlags
, pszPath
, MAX_PATH
);
830 /* Win9x always returns ANSI strings, NT always returns Unicode strings */
831 if (GetVersion() & 0x80000000) {
832 strRet
->uType
= STRRET_CSTR
;
833 if (!WideCharToMultiByte(CP_ACP
, 0, pszPath
, -1, strRet
->u
.cStr
, MAX_PATH
,
835 strRet
->u
.cStr
[0] = '\0';
836 CoTaskMemFree(pszPath
);
838 strRet
->uType
= STRRET_WSTR
;
839 strRet
->u
.pOleStr
= pszPath
;
842 CoTaskMemFree(pszPath
);
844 TRACE ("-- (%p)->(%s)\n", This
, strRet
->uType
== STRRET_CSTR
? strRet
->u
.cStr
: debugstr_w(strRet
->u
.pOleStr
));
848 /**************************************************************************
849 * IShellFolder_fnSetNameOf
850 * Changes the name of a file object or subfolder, possibly changing its item
851 * identifier in the process.
854 * HWND hwndOwner, //[in ] Owner window for output
855 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
856 * LPCOLESTR lpszName, //[in ] the items new display name
857 * DWORD dwFlags, //[in ] SHGNO formatting flags
858 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
860 static HRESULT WINAPI
IShellFolder_fnSetNameOf (IShellFolder2
* iface
,
865 LPITEMIDLIST
* pPidlOut
)
867 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
868 WCHAR szSrc
[MAX_PATH
+ 1], szDest
[MAX_PATH
+ 1];
870 BOOL bIsFolder
= _ILIsFolder (ILFindLastID (pidl
));
872 TRACE ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", This
, hwndOwner
, pidl
,
873 debugstr_w (lpName
), dwFlags
, pPidlOut
);
875 /* build source path */
876 lstrcpynW(szSrc
, This
->sPathTarget
, MAX_PATH
);
877 ptr
= PathAddBackslashW (szSrc
);
879 _ILSimpleGetTextW (pidl
, ptr
, MAX_PATH
+ 1 - (ptr
- szSrc
));
881 /* build destination path */
882 if (dwFlags
== SHGDN_NORMAL
|| dwFlags
& SHGDN_INFOLDER
) {
883 lstrcpynW(szDest
, This
->sPathTarget
, MAX_PATH
);
884 ptr
= PathAddBackslashW (szDest
);
886 lstrcpynW(ptr
, lpName
, MAX_PATH
+ 1 - (ptr
- szDest
));
888 lstrcpynW(szDest
, lpName
, MAX_PATH
);
890 if(!(dwFlags
& SHGDN_FORPARSING
) && SHELL_FS_HideExtension(szSrc
)) {
891 WCHAR
*ext
= PathFindExtensionW(szSrc
);
893 INT len
= strlenW(szDest
);
894 lstrcpynW(szDest
+ len
, ext
, MAX_PATH
- len
);
898 TRACE ("src=%s dest=%s\n", debugstr_w(szSrc
), debugstr_w(szDest
));
900 if (MoveFileW (szSrc
, szDest
)) {
904 hr
= _ILCreateFromPathW(szDest
, pPidlOut
);
906 SHChangeNotify (bIsFolder
? SHCNE_RENAMEFOLDER
: SHCNE_RENAMEITEM
,
907 SHCNF_PATHW
, szSrc
, szDest
);
915 static HRESULT WINAPI
IShellFolder_fnGetDefaultSearchGUID (IShellFolder2
*iface
,
918 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
919 FIXME ("(%p)\n", This
);
922 static HRESULT WINAPI
IShellFolder_fnEnumSearches (IShellFolder2
* iface
,
923 IEnumExtraSearch
** ppenum
)
925 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
926 FIXME ("(%p)\n", This
);
930 static HRESULT WINAPI
931 IShellFolder_fnGetDefaultColumn (IShellFolder2
* iface
, DWORD dwRes
,
932 ULONG
* pSort
, ULONG
* pDisplay
)
934 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
936 TRACE ("(%p)\n", This
);
946 static HRESULT WINAPI
947 IShellFolder_fnGetDefaultColumnState (IShellFolder2
* iface
, UINT iColumn
,
950 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
952 TRACE ("(%p)\n", This
);
954 if (!pcsFlags
|| iColumn
>= GENERICSHELLVIEWCOLUMNS
)
957 *pcsFlags
= GenericSFHeader
[iColumn
].pcsFlags
;
962 static HRESULT WINAPI
963 IShellFolder_fnGetDetailsEx (IShellFolder2
* iface
, LPCITEMIDLIST pidl
,
964 const SHCOLUMNID
* pscid
, VARIANT
* pv
)
966 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
967 FIXME ("(%p)\n", This
);
972 static HRESULT WINAPI
973 IShellFolder_fnGetDetailsOf (IShellFolder2
* iface
, LPCITEMIDLIST pidl
,
974 UINT iColumn
, SHELLDETAILS
* psd
)
976 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
979 TRACE ("(%p)->(%p %i %p)\n", This
, pidl
, iColumn
, psd
);
981 if (!psd
|| iColumn
>= GENERICSHELLVIEWCOLUMNS
)
985 /* the header titles */
986 psd
->fmt
= GenericSFHeader
[iColumn
].fmt
;
987 psd
->cxChar
= GenericSFHeader
[iColumn
].cxChar
;
988 psd
->str
.uType
= STRRET_CSTR
;
989 LoadStringA (shell32_hInstance
, GenericSFHeader
[iColumn
].colnameid
,
990 psd
->str
.u
.cStr
, MAX_PATH
);
994 psd
->str
.uType
= STRRET_CSTR
;
995 /* the data from the pidl */
998 hr
= IShellFolder2_GetDisplayNameOf (iface
, pidl
,
999 SHGDN_NORMAL
| SHGDN_INFOLDER
, &psd
->str
);
1002 _ILGetFileSize (pidl
, psd
->str
.u
.cStr
, MAX_PATH
);
1005 _ILGetFileType (pidl
, psd
->str
.u
.cStr
, MAX_PATH
);
1008 _ILGetFileDate (pidl
, psd
->str
.u
.cStr
, MAX_PATH
);
1010 case 4: /* attributes */
1011 _ILGetFileAttributes (pidl
, psd
->str
.u
.cStr
, MAX_PATH
);
1019 static HRESULT WINAPI
1020 IShellFolder_fnMapColumnToSCID (IShellFolder2
* iface
, UINT column
,
1023 IGenericSFImpl
*This
= impl_from_IShellFolder2(iface
);
1024 FIXME ("(%p)\n", This
);
1028 static const IShellFolder2Vtbl sfvt
=
1030 IShellFolder_fnQueryInterface
,
1031 IShellFolder_fnAddRef
,
1032 IShellFolder_fnRelease
,
1033 IShellFolder_fnParseDisplayName
,
1034 IShellFolder_fnEnumObjects
,
1035 IShellFolder_fnBindToObject
,
1036 IShellFolder_fnBindToStorage
,
1037 IShellFolder_fnCompareIDs
,
1038 IShellFolder_fnCreateViewObject
,
1039 IShellFolder_fnGetAttributesOf
,
1040 IShellFolder_fnGetUIObjectOf
,
1041 IShellFolder_fnGetDisplayNameOf
,
1042 IShellFolder_fnSetNameOf
,
1044 IShellFolder_fnGetDefaultSearchGUID
,
1045 IShellFolder_fnEnumSearches
,
1046 IShellFolder_fnGetDefaultColumn
,
1047 IShellFolder_fnGetDefaultColumnState
,
1048 IShellFolder_fnGetDetailsEx
,
1049 IShellFolder_fnGetDetailsOf
,
1050 IShellFolder_fnMapColumnToSCID
1053 /****************************************************************************
1054 * ISFHelper for IShellFolder implementation
1057 static HRESULT WINAPI
ISFHelper_fnQueryInterface(ISFHelper
*iface
, REFIID riid
, void **ppvObj
)
1059 IGenericSFImpl
*This
= impl_from_ISFHelper(iface
);
1061 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppvObj
);
1064 static ULONG WINAPI
ISFHelper_fnAddRef(ISFHelper
*iface
)
1066 IGenericSFImpl
*This
= impl_from_ISFHelper(iface
);
1068 return IUnknown_AddRef(This
->outer_unk
);
1071 static ULONG WINAPI
ISFHelper_fnRelease(ISFHelper
*iface
)
1073 IGenericSFImpl
*This
= impl_from_ISFHelper(iface
);
1075 return IUnknown_Release(This
->outer_unk
);
1078 /****************************************************************************
1079 * ISFHelper_fnGetUniqueName
1081 * creates a unique folder name
1084 static HRESULT WINAPI
1085 ISFHelper_fnGetUniqueName (ISFHelper
* iface
, LPWSTR pwszName
, UINT uLen
)
1087 IGenericSFImpl
*This
= impl_from_ISFHelper(iface
);
1090 WCHAR wszText
[MAX_PATH
];
1091 WCHAR wszNewFolder
[25];
1092 const WCHAR wszFormat
[] = {'%','s',' ','%','d',0 };
1094 TRACE ("(%p)(%p %u)\n", This
, pwszName
, uLen
);
1096 LoadStringW(shell32_hInstance
, IDS_NEWFOLDER
, wszNewFolder
, sizeof(wszNewFolder
)/sizeof(WCHAR
));
1097 if (uLen
< sizeof(wszNewFolder
)/sizeof(WCHAR
) + 3)
1100 lstrcpynW (pwszName
, wszNewFolder
, uLen
);
1102 hr
= IShellFolder2_EnumObjects(&This
->IShellFolder2_iface
, 0,
1103 SHCONTF_FOLDERS
| SHCONTF_NONFOLDERS
| SHCONTF_INCLUDEHIDDEN
, &penum
);
1110 IEnumIDList_Reset (penum
);
1111 while (S_OK
== IEnumIDList_Next (penum
, 1, &pidl
, &dwFetched
) &&
1113 _ILSimpleGetTextW (pidl
, wszText
, MAX_PATH
);
1114 if (0 == lstrcmpiW (wszText
, pwszName
)) {
1115 snprintfW (pwszName
, uLen
, wszFormat
, wszNewFolder
, i
++);
1124 IEnumIDList_Release (penum
);
1129 /****************************************************************************
1130 * ISFHelper_fnAddFolder
1132 * adds a new folder.
1135 static HRESULT WINAPI
1136 ISFHelper_fnAddFolder (ISFHelper
* iface
, HWND hwnd
, LPCWSTR pwszName
,
1137 LPITEMIDLIST
* ppidlOut
)
1139 IGenericSFImpl
*This
= impl_from_ISFHelper(iface
);
1140 WCHAR wszNewDir
[MAX_PATH
];
1142 HRESULT hres
= E_FAIL
;
1144 TRACE ("(%p)(%s %p)\n", This
, debugstr_w(pwszName
), ppidlOut
);
1147 if (This
->sPathTarget
)
1148 lstrcpynW(wszNewDir
, This
->sPathTarget
, MAX_PATH
);
1149 PathAppendW(wszNewDir
, pwszName
);
1151 bRes
= CreateDirectoryW (wszNewDir
, NULL
);
1153 LPITEMIDLIST relPidl
;
1155 lstrcpyW(wszNewDir
, pwszName
);
1157 hres
= IShellFolder2_ParseDisplayName(&This
->IShellFolder2_iface
, hwnd
, NULL
, wszNewDir
,
1158 NULL
, &relPidl
, NULL
);
1160 if (SUCCEEDED(hres
)) {
1161 LPITEMIDLIST fullPidl
;
1163 fullPidl
= ILCombine(This
->pidlRoot
, relPidl
);
1166 SHChangeNotify(SHCNE_MKDIR
, SHCNF_IDLIST
, fullPidl
, NULL
);
1170 *ppidlOut
= relPidl
;
1174 WARN("failed to combine %s into a full PIDL\n", wine_dbgstr_w(pwszName
));
1179 WARN("failed to parse %s into a PIDL\n", wine_dbgstr_w(pwszName
));
1182 WCHAR wszText
[128 + MAX_PATH
];
1183 WCHAR wszTempText
[128];
1184 WCHAR wszCaption
[256];
1186 /* Cannot Create folder because of permissions */
1187 LoadStringW (shell32_hInstance
, IDS_CREATEFOLDER_DENIED
, wszTempText
,
1188 sizeof (wszTempText
)/sizeof (wszTempText
[0]));
1189 LoadStringW (shell32_hInstance
, IDS_CREATEFOLDER_CAPTION
, wszCaption
,
1190 sizeof (wszCaption
)/sizeof (wszCaption
[0]));
1191 sprintfW (wszText
, wszTempText
, wszNewDir
);
1192 MessageBoxW (hwnd
, wszText
, wszCaption
, MB_OK
| MB_ICONEXCLAMATION
);
1198 /****************************************************************************
1201 * Builds a list of paths like the one used in SHFileOperation from a table of
1202 * PIDLs relative to the given base folder
1204 static WCHAR
*build_paths_list(LPCWSTR wszBasePath
, int cidl
, const LPCITEMIDLIST
*pidls
)
1206 WCHAR
*wszPathsList
;
1211 iPathLen
= lstrlenW(wszBasePath
);
1212 wszPathsList
= HeapAlloc(GetProcessHeap(), 0, MAX_PATH
*sizeof(WCHAR
)*cidl
+1);
1213 wszListPos
= wszPathsList
;
1215 for (i
= 0; i
< cidl
; i
++) {
1216 if (!_ILIsFolder(pidls
[i
]) && !_ILIsValue(pidls
[i
]))
1219 lstrcpynW(wszListPos
, wszBasePath
, MAX_PATH
);
1220 /* FIXME: abort if path too long */
1221 _ILSimpleGetTextW(pidls
[i
], wszListPos
+iPathLen
, MAX_PATH
-iPathLen
);
1222 wszListPos
+= lstrlenW(wszListPos
)+1;
1225 return wszPathsList
;
1228 /****************************************************************************
1229 * ISFHelper_fnDeleteItems
1231 * deletes items in folder
1233 static HRESULT WINAPI
1234 ISFHelper_fnDeleteItems (ISFHelper
* iface
, UINT cidl
, LPCITEMIDLIST
* apidl
)
1236 IGenericSFImpl
*This
= impl_from_ISFHelper(iface
);
1239 WCHAR wszPath
[MAX_PATH
];
1240 WCHAR
*wszPathsList
;
1242 WCHAR
*wszCurrentPath
;
1244 TRACE ("(%p)(%u %p)\n", This
, cidl
, apidl
);
1245 if (cidl
==0) return S_OK
;
1247 if (This
->sPathTarget
)
1248 lstrcpynW(wszPath
, This
->sPathTarget
, MAX_PATH
);
1251 PathAddBackslashW(wszPath
);
1252 wszPathsList
= build_paths_list(wszPath
, cidl
, apidl
);
1254 ZeroMemory(&op
, sizeof(op
));
1255 op
.hwnd
= GetActiveWindow();
1256 op
.wFunc
= FO_DELETE
;
1257 op
.pFrom
= wszPathsList
;
1258 op
.fFlags
= FOF_ALLOWUNDO
;
1259 if (SHFileOperationW(&op
))
1261 WARN("SHFileOperation failed\n");
1267 /* we currently need to manually send the notifies */
1268 wszCurrentPath
= wszPathsList
;
1269 for (i
= 0; i
< cidl
; i
++)
1273 if (_ILIsFolder(apidl
[i
]))
1274 wEventId
= SHCNE_RMDIR
;
1275 else if (_ILIsValue(apidl
[i
]))
1276 wEventId
= SHCNE_DELETE
;
1280 /* check if file exists */
1281 if (GetFileAttributesW(wszCurrentPath
) == INVALID_FILE_ATTRIBUTES
)
1283 LPITEMIDLIST pidl
= ILCombine(This
->pidlRoot
, apidl
[i
]);
1284 SHChangeNotify(wEventId
, SHCNF_IDLIST
, pidl
, NULL
);
1288 wszCurrentPath
+= lstrlenW(wszCurrentPath
)+1;
1290 HeapFree(GetProcessHeap(), 0, wszPathsList
);
1294 /****************************************************************************
1295 * ISFHelper_fnCopyItems
1297 * copies items to this folder
1299 static HRESULT WINAPI
1300 ISFHelper_fnCopyItems (ISFHelper
* iface
, IShellFolder
* pSFFrom
, UINT cidl
,
1301 LPCITEMIDLIST
* apidl
)
1304 IPersistFolder2
*ppf2
= NULL
;
1305 WCHAR wszSrcPathRoot
[MAX_PATH
],
1306 wszDstPath
[MAX_PATH
+1];
1307 WCHAR
*wszSrcPathsList
;
1308 IGenericSFImpl
*This
= impl_from_ISFHelper(iface
);
1310 SHFILEOPSTRUCTW fop
;
1312 TRACE ("(%p)->(%p,%u,%p)\n", This
, pSFFrom
, cidl
, apidl
);
1314 IShellFolder_QueryInterface (pSFFrom
, &IID_IPersistFolder2
,
1319 if (SUCCEEDED (IPersistFolder2_GetCurFolder (ppf2
, &pidl
))) {
1320 SHGetPathFromIDListW (pidl
, wszSrcPathRoot
);
1321 ZeroMemory(wszDstPath
, MAX_PATH
+1);
1322 if (This
->sPathTarget
)
1323 lstrcpynW(wszDstPath
, This
->sPathTarget
, MAX_PATH
);
1324 PathAddBackslashW(wszSrcPathRoot
);
1325 PathAddBackslashW(wszDstPath
);
1326 wszSrcPathsList
= build_paths_list(wszSrcPathRoot
, cidl
, apidl
);
1327 ZeroMemory(&fop
, sizeof(fop
));
1328 fop
.hwnd
= GetActiveWindow();
1329 fop
.wFunc
= FO_COPY
;
1330 fop
.pFrom
= wszSrcPathsList
;
1331 fop
.pTo
= wszDstPath
;
1332 fop
.fFlags
= FOF_ALLOWUNDO
;
1334 if(SHFileOperationW(&fop
))
1336 WARN("Copy failed\n");
1339 HeapFree(GetProcessHeap(), 0, wszSrcPathsList
);
1343 IPersistFolder2_Release(ppf2
);
1348 static const ISFHelperVtbl shvt
=
1350 ISFHelper_fnQueryInterface
,
1352 ISFHelper_fnRelease
,
1353 ISFHelper_fnGetUniqueName
,
1354 ISFHelper_fnAddFolder
,
1355 ISFHelper_fnDeleteItems
,
1356 ISFHelper_fnCopyItems
1359 /************************************************************************
1360 * IFSFldr_PersistFolder3_QueryInterface
1363 static HRESULT WINAPI
IFSFldr_PersistFolder3_QueryInterface(IPersistFolder3
*iface
, REFIID iid
,
1366 IGenericSFImpl
*This
= impl_from_IPersistFolder3(iface
);
1368 return IUnknown_QueryInterface(This
->outer_unk
, iid
, ppv
);
1371 /************************************************************************
1372 * IFSFldr_PersistFolder3_AddRef
1375 static ULONG WINAPI
IFSFldr_PersistFolder3_AddRef(IPersistFolder3
*iface
)
1377 IGenericSFImpl
*This
= impl_from_IPersistFolder3(iface
);
1379 return IUnknown_AddRef(This
->outer_unk
);
1382 /************************************************************************
1383 * IFSFldr_PersistFolder3_Release
1386 static ULONG WINAPI
IFSFldr_PersistFolder3_Release(IPersistFolder3
*iface
)
1388 IGenericSFImpl
*This
= impl_from_IPersistFolder3(iface
);
1390 return IUnknown_Release(This
->outer_unk
);
1393 /************************************************************************
1394 * IFSFldr_PersistFolder3_GetClassID
1396 static HRESULT WINAPI
1397 IFSFldr_PersistFolder3_GetClassID (IPersistFolder3
* iface
, CLSID
* lpClassId
)
1399 IGenericSFImpl
*This
= impl_from_IPersistFolder3(iface
);
1401 TRACE ("(%p)\n", This
);
1405 *lpClassId
= *This
->pclsid
;
1410 /************************************************************************
1411 * IFSFldr_PersistFolder3_Initialize
1414 * sPathTarget is not set. Don't know how to handle in a non rooted environment.
1416 static HRESULT WINAPI
1417 IFSFldr_PersistFolder3_Initialize (IPersistFolder3
* iface
, LPCITEMIDLIST pidl
)
1419 WCHAR wszTemp
[MAX_PATH
];
1421 IGenericSFImpl
*This
= impl_from_IPersistFolder3(iface
);
1423 TRACE ("(%p)->(%p)\n", This
, pidl
);
1425 SHFree (This
->pidlRoot
); /* free the old pidl */
1426 This
->pidlRoot
= ILClone (pidl
); /* set my pidl */
1428 SHFree (This
->sPathTarget
);
1429 This
->sPathTarget
= NULL
;
1432 if (SHGetPathFromIDListW (pidl
, wszTemp
)) {
1433 int len
= strlenW(wszTemp
);
1434 This
->sPathTarget
= SHAlloc((len
+ 1) * sizeof(WCHAR
));
1435 if (!This
->sPathTarget
)
1436 return E_OUTOFMEMORY
;
1437 memcpy(This
->sPathTarget
, wszTemp
, (len
+ 1) * sizeof(WCHAR
));
1440 TRACE ("--(%p)->(%s)\n", This
, debugstr_w(This
->sPathTarget
));
1444 /**************************************************************************
1445 * IFSFldr_PersistFolder3_GetCurFolder
1447 static HRESULT WINAPI
1448 IFSFldr_PersistFolder3_fnGetCurFolder (IPersistFolder3
* iface
,
1449 LPITEMIDLIST
* pidl
)
1451 IGenericSFImpl
*This
= impl_from_IPersistFolder3(iface
);
1453 TRACE ("(%p)->(%p)\n", This
, pidl
);
1455 if (!pidl
) return E_POINTER
;
1456 *pidl
= ILClone (This
->pidlRoot
);
1460 /**************************************************************************
1461 * IFSFldr_PersistFolder3_InitializeEx
1463 * FIXME: error handling
1465 static HRESULT WINAPI
1466 IFSFldr_PersistFolder3_InitializeEx (IPersistFolder3
* iface
,
1467 IBindCtx
* pbc
, LPCITEMIDLIST pidlRoot
,
1468 const PERSIST_FOLDER_TARGET_INFO
* ppfti
)
1470 WCHAR wszTemp
[MAX_PATH
];
1472 IGenericSFImpl
*This
= impl_from_IPersistFolder3(iface
);
1474 TRACE ("(%p)->(%p,%p,%p)\n", This
, pbc
, pidlRoot
, ppfti
);
1476 TRACE ("--%p %s %s 0x%08x 0x%08x\n",
1477 ppfti
->pidlTargetFolder
, debugstr_w (ppfti
->szTargetParsingName
),
1478 debugstr_w (ppfti
->szNetworkProvider
), ppfti
->dwAttributes
,
1482 if (ppfti
&& ppfti
->pidlTargetFolder
)
1483 pdump (ppfti
->pidlTargetFolder
);
1486 __SHFreeAndNil (&This
->pidlRoot
); /* free the old */
1487 if (This
->sPathTarget
)
1488 __SHFreeAndNil (&This
->sPathTarget
);
1491 * Root path and pidl
1493 This
->pidlRoot
= ILClone (pidlRoot
);
1496 * the target folder is specified in csidl OR pidlTargetFolder OR
1497 * szTargetParsingName
1500 if (ppfti
->csidl
!= -1) {
1501 if (SHGetSpecialFolderPathW (0, wszTemp
, ppfti
->csidl
,
1502 ppfti
->csidl
& CSIDL_FLAG_CREATE
)) {
1503 int len
= strlenW(wszTemp
);
1504 This
->sPathTarget
= SHAlloc((len
+ 1) * sizeof(WCHAR
));
1505 if (!This
->sPathTarget
)
1506 return E_OUTOFMEMORY
;
1507 memcpy(This
->sPathTarget
, wszTemp
, (len
+ 1) * sizeof(WCHAR
));
1509 } else if (ppfti
->szTargetParsingName
[0]) {
1510 int len
= strlenW(ppfti
->szTargetParsingName
);
1511 This
->sPathTarget
= SHAlloc((len
+ 1) * sizeof(WCHAR
));
1512 if (!This
->sPathTarget
)
1513 return E_OUTOFMEMORY
;
1514 memcpy(This
->sPathTarget
, ppfti
->szTargetParsingName
,
1515 (len
+ 1) * sizeof(WCHAR
));
1516 } else if (ppfti
->pidlTargetFolder
) {
1517 if (SHGetPathFromIDListW(ppfti
->pidlTargetFolder
, wszTemp
)) {
1518 int len
= strlenW(wszTemp
);
1519 This
->sPathTarget
= SHAlloc((len
+ 1) * sizeof(WCHAR
));
1520 if (!This
->sPathTarget
)
1521 return E_OUTOFMEMORY
;
1522 memcpy(This
->sPathTarget
, wszTemp
, (len
+ 1) * sizeof(WCHAR
));
1527 TRACE ("--(%p)->(target=%s)\n", This
, debugstr_w(This
->sPathTarget
));
1528 pdump (This
->pidlRoot
);
1529 return (This
->sPathTarget
) ? S_OK
: E_FAIL
;
1532 static HRESULT WINAPI
1533 IFSFldr_PersistFolder3_GetFolderTargetInfo (IPersistFolder3
* iface
,
1534 PERSIST_FOLDER_TARGET_INFO
* ppfti
)
1536 IGenericSFImpl
*This
= impl_from_IPersistFolder3(iface
);
1537 FIXME ("(%p)->(%p)\n", This
, ppfti
);
1538 ZeroMemory (ppfti
, sizeof (*ppfti
));
1542 static const IPersistFolder3Vtbl pfvt
=
1544 IFSFldr_PersistFolder3_QueryInterface
,
1545 IFSFldr_PersistFolder3_AddRef
,
1546 IFSFldr_PersistFolder3_Release
,
1547 IFSFldr_PersistFolder3_GetClassID
,
1548 IFSFldr_PersistFolder3_Initialize
,
1549 IFSFldr_PersistFolder3_fnGetCurFolder
,
1550 IFSFldr_PersistFolder3_InitializeEx
,
1551 IFSFldr_PersistFolder3_GetFolderTargetInfo
1554 /****************************************************************************
1555 * ISFDropTarget implementation
1557 static HRESULT WINAPI
ISFDropTarget_QueryInterface(IDropTarget
*iface
, REFIID riid
, void **ppv
)
1559 IGenericSFImpl
*This
= impl_from_IDropTarget(iface
);
1561 return IUnknown_QueryInterface(This
->outer_unk
, riid
, ppv
);
1564 static ULONG WINAPI
ISFDropTarget_AddRef(IDropTarget
*iface
)
1566 IGenericSFImpl
*This
= impl_from_IDropTarget(iface
);
1568 return IUnknown_AddRef(This
->outer_unk
);
1571 static ULONG WINAPI
ISFDropTarget_Release(IDropTarget
*iface
)
1573 IGenericSFImpl
*This
= impl_from_IDropTarget(iface
);
1575 return IUnknown_Release(This
->outer_unk
);
1578 static HRESULT WINAPI
1579 ISFDropTarget_DragEnter (IDropTarget
* iface
, IDataObject
* pDataObject
,
1580 DWORD dwKeyState
, POINTL pt
, DWORD
* pdwEffect
)
1584 IGenericSFImpl
*This
= impl_from_IDropTarget(iface
);
1586 TRACE ("(%p)->(DataObject=%p)\n", This
, pDataObject
);
1588 InitFormatEtc (fmt
, This
->cfShellIDList
, TYMED_HGLOBAL
);
1589 This
->fAcceptFmt
= IDataObject_QueryGetData (pDataObject
, &fmt
) == S_OK
;
1590 if (This
->fAcceptFmt
)
1591 *pdwEffect
= KeyStateToDropEffect(dwKeyState
);
1593 *pdwEffect
= DROPEFFECT_NONE
;
1598 static HRESULT WINAPI
1599 ISFDropTarget_DragOver (IDropTarget
* iface
, DWORD dwKeyState
, POINTL pt
,
1602 IGenericSFImpl
*This
= impl_from_IDropTarget(iface
);
1604 TRACE ("(%p)\n", This
);
1607 return E_INVALIDARG
;
1609 if (This
->fAcceptFmt
)
1610 *pdwEffect
= KeyStateToDropEffect(dwKeyState
);
1612 *pdwEffect
= DROPEFFECT_NONE
;
1617 static HRESULT WINAPI
ISFDropTarget_DragLeave (IDropTarget
* iface
)
1619 IGenericSFImpl
*This
= impl_from_IDropTarget(iface
);
1621 TRACE ("(%p)\n", This
);
1623 This
->fAcceptFmt
= FALSE
;
1628 static HRESULT WINAPI
1629 ISFDropTarget_Drop (IDropTarget
* iface
, IDataObject
* pDataObject
,
1630 DWORD dwKeyState
, POINTL pt
, DWORD
* pdwEffect
)
1632 IGenericSFImpl
*This
= impl_from_IDropTarget(iface
);
1634 FIXME ("(%p) object dropped\n", This
);
1639 static const IDropTargetVtbl dtvt
= {
1640 ISFDropTarget_QueryInterface
,
1641 ISFDropTarget_AddRef
,
1642 ISFDropTarget_Release
,
1643 ISFDropTarget_DragEnter
,
1644 ISFDropTarget_DragOver
,
1645 ISFDropTarget_DragLeave
,
1649 HRESULT WINAPI
IFSFolder_Constructor(IUnknown
*outer_unk
, REFIID riid
, void **ppv
)
1654 TRACE("outer_unk=%p %s\n", outer_unk
, shdebugstr_guid(riid
));
1656 if (outer_unk
&& !IsEqualIID(riid
, &IID_IUnknown
))
1657 return CLASS_E_NOAGGREGATION
;
1659 sf
= LocalAlloc(LMEM_ZEROINIT
, sizeof(*sf
));
1661 return E_OUTOFMEMORY
;
1664 sf
->IUnknown_inner
.lpVtbl
= &unkvt
;
1665 sf
->IShellFolder2_iface
.lpVtbl
= &sfvt
;
1666 sf
->IPersistFolder3_iface
.lpVtbl
= &pfvt
;
1667 sf
->IDropTarget_iface
.lpVtbl
= &dtvt
;
1668 sf
->ISFHelper_iface
.lpVtbl
= &shvt
;
1669 sf
->pclsid
= (CLSID
*) & CLSID_ShellFSFolder
;
1670 sf
->outer_unk
= outer_unk
? outer_unk
: &sf
->IUnknown_inner
;
1672 hr
= IUnknown_QueryInterface(&sf
->IUnknown_inner
, riid
, ppv
);
1673 IUnknown_Release(&sf
->IUnknown_inner
);
1675 TRACE ("--%p\n", *ppv
);