win32u: Move NtUserGetMessage implementation from user32.
[wine.git] / dlls / shell32 / shfldr_fs.c
blob662d8b52d5b1a51960799b34e6d37bdc7edcf675
2 /*
3 * file system folder
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
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdarg.h>
26 #include <stdio.h>
28 #define COBJMACROS
29 #define NONAMELESSUNION
31 #include "winerror.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winreg.h"
35 #include "wingdi.h"
36 #include "winuser.h"
38 #include "ole2.h"
39 #include "shlguid.h"
41 #include "pidl.h"
42 #include "shell32_main.h"
43 #include "shresdef.h"
44 #include "shlwapi.h"
45 #include "shellfolder.h"
46 #include "wine/debug.h"
47 #include "debughlp.h"
48 #include "shfldr.h"
50 WINE_DEFAULT_DEBUG_CHANNEL (shell);
52 /***********************************************************************
53 * IShellFolder implementation
56 typedef struct {
57 IUnknown IUnknown_inner;
58 LONG ref;
59 IShellFolder2 IShellFolder2_iface;
60 IPersistFolder3 IPersistFolder3_iface;
61 IPersistPropertyBag IPersistPropertyBag_iface;
62 IDropTarget IDropTarget_iface;
63 ISFHelper ISFHelper_iface;
64 IUnknown *outer_unk;
66 const CLSID *pclsid;
68 /* both paths are parsible from the desktop */
69 LPWSTR sPathTarget; /* complete path to target used for enumeration and ChangeNotify */
71 LPITEMIDLIST pidlRoot; /* absolute pidl */
72 DWORD drop_effects_mask;
73 } IGenericSFImpl;
75 static UINT cfShellIDList;
77 static inline IGenericSFImpl *impl_from_IUnknown(IUnknown *iface)
79 return CONTAINING_RECORD(iface, IGenericSFImpl, IUnknown_inner);
82 static inline IGenericSFImpl *impl_from_IShellFolder2(IShellFolder2 *iface)
84 return CONTAINING_RECORD(iface, IGenericSFImpl, IShellFolder2_iface);
87 static inline IGenericSFImpl *impl_from_IPersistFolder3(IPersistFolder3 *iface)
89 return CONTAINING_RECORD(iface, IGenericSFImpl, IPersistFolder3_iface);
92 static inline IGenericSFImpl *impl_from_IPersistPropertyBag(IPersistPropertyBag *iface)
94 return CONTAINING_RECORD(iface, IGenericSFImpl, IPersistPropertyBag_iface);
97 static inline IGenericSFImpl *impl_from_IDropTarget(IDropTarget *iface)
99 return CONTAINING_RECORD(iface, IGenericSFImpl, IDropTarget_iface);
102 static inline IGenericSFImpl *impl_from_ISFHelper(ISFHelper *iface)
104 return CONTAINING_RECORD(iface, IGenericSFImpl, ISFHelper_iface);
107 /**************************************************************************
108 * inner IUnknown
110 static HRESULT WINAPI IUnknown_fnQueryInterface(IUnknown *iface, REFIID riid, void **ppvObj)
112 IGenericSFImpl *This = impl_from_IUnknown(iface);
114 TRACE("(%p)->(%s,%p)\n", This, shdebugstr_guid(riid), ppvObj);
116 *ppvObj = NULL;
118 if (IsEqualIID (riid, &IID_IUnknown))
119 *ppvObj = &This->IUnknown_inner;
120 else if (IsEqualIID(riid, &IID_IShellFolder) || IsEqualIID(riid, &IID_IShellFolder2))
121 *ppvObj = &This->IShellFolder2_iface;
122 else if (IsEqualIID(riid, &IID_IPersist) || IsEqualIID(riid, &IID_IPersistFolder) ||
123 IsEqualIID(riid, &IID_IPersistFolder2) || IsEqualIID(riid, &IID_IPersistFolder3))
124 *ppvObj = &This->IPersistFolder3_iface;
125 else if (IsEqualIID(&IID_IPersistPropertyBag, riid))
126 *ppvObj = &This->IPersistPropertyBag_iface;
127 else if (IsEqualIID (riid, &IID_ISFHelper))
128 *ppvObj = &This->ISFHelper_iface;
129 else if (IsEqualIID (riid, &IID_IDropTarget)) {
130 *ppvObj = &This->IDropTarget_iface;
131 if (!cfShellIDList) cfShellIDList = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
134 if (*ppvObj) {
135 IUnknown_AddRef((IUnknown *)*ppvObj);
136 TRACE ("-- Interface = %p\n", *ppvObj);
137 return S_OK;
139 TRACE ("-- Interface: E_NOINTERFACE\n");
140 return E_NOINTERFACE;
143 static ULONG WINAPI IUnknown_fnAddRef(IUnknown *iface)
145 IGenericSFImpl *This = impl_from_IUnknown(iface);
146 ULONG ref = InterlockedIncrement(&This->ref);
148 TRACE("(%p) ref=%ld\n", This, ref);
150 return ref;
153 static ULONG WINAPI IUnknown_fnRelease(IUnknown *iface)
155 IGenericSFImpl *This = impl_from_IUnknown(iface);
156 ULONG ref = InterlockedDecrement(&This->ref);
158 TRACE("(%p) ref=%ld\n", This, ref);
160 if (!ref) {
161 TRACE("-- destroying IShellFolder(%p)\n", This);
163 SHFree(This->pidlRoot);
164 SHFree(This->sPathTarget);
165 LocalFree(This);
167 return ref;
170 static const IUnknownVtbl unkvt =
172 IUnknown_fnQueryInterface,
173 IUnknown_fnAddRef,
174 IUnknown_fnRelease,
177 static const shvheader GenericSFHeader[] =
179 { &FMTID_Storage, PID_STG_NAME, IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15 },
180 { &FMTID_Storage, PID_STG_SIZE, IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
181 { &FMTID_Storage, PID_STG_STORAGETYPE, IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10 },
182 { &FMTID_Storage, PID_STG_WRITETIME, IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12 },
183 { &FMTID_Storage, PID_STG_ATTRIBUTES, IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5 },
186 #define GENERICSHELLVIEWCOLUMNS 5
188 /**************************************************************************
189 * IShellFolder_fnQueryInterface
191 static HRESULT WINAPI IShellFolder_fnQueryInterface(IShellFolder2 *iface, REFIID riid,
192 void **ppvObj)
194 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
196 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
199 /**************************************************************************
200 * IShellFolder_AddRef
202 static ULONG WINAPI IShellFolder_fnAddRef(IShellFolder2 *iface)
204 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
206 return IUnknown_AddRef(This->outer_unk);
209 /**************************************************************************
210 * IShellFolder_fnRelease
212 static ULONG WINAPI IShellFolder_fnRelease(IShellFolder2 *iface)
214 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
216 return IUnknown_Release(This->outer_unk);
219 /**************************************************************************
220 * SHELL32_CreatePidlFromBindCtx [internal]
222 * If the caller bound File System Bind Data, assume it is the
223 * find data for the path.
224 * This allows binding of paths that don't exist.
226 LPITEMIDLIST SHELL32_CreatePidlFromBindCtx(IBindCtx *pbc, LPCWSTR path)
228 IFileSystemBindData *fsbd = NULL;
229 LPITEMIDLIST pidl = NULL;
230 IUnknown *unk = NULL;
231 HRESULT r;
233 TRACE("%p %s\n", pbc, debugstr_w(path));
235 if (!pbc)
236 return NULL;
238 /* see if the caller bound File System Bind Data */
239 r = IBindCtx_GetObjectParam( pbc, (WCHAR *)L"File System Bind Data", &unk );
240 if (FAILED(r))
241 return NULL;
243 r = IUnknown_QueryInterface( unk, &IID_IFileSystemBindData, (void**)&fsbd );
244 if (SUCCEEDED(r))
246 WIN32_FIND_DATAW wfd;
248 r = IFileSystemBindData_GetFindData( fsbd, &wfd );
249 if (SUCCEEDED(r))
251 lstrcpynW( &wfd.cFileName[0], path, MAX_PATH );
252 pidl = _ILCreateFromFindDataW( &wfd );
254 IFileSystemBindData_Release( fsbd );
256 IUnknown_Release( unk );
258 return pidl;
261 /**************************************************************************
262 * IShellFolder_ParseDisplayName {SHELL32}
264 * Parse a display name.
266 * PARAMS
267 * hwndOwner [in] Parent window for any message's
268 * pbc [in] optional FileSystemBindData context
269 * lpszDisplayName [in] Unicode displayname.
270 * pchEaten [out] (unicode) characters processed
271 * ppidl [out] complex pidl to item
272 * pdwAttributes [out] items attributes
274 * NOTES
275 * Every folder tries to parse only its own (the leftmost) pidl and creates a
276 * subfolder to evaluate the remaining parts.
277 * Now we can parse into namespaces implemented by shell extensions
279 * Behaviour on win98: lpszDisplayName=NULL -> crash
280 * lpszDisplayName="" -> returns mycomputer-pidl
282 * FIXME
283 * pdwAttributes is not set
284 * pchEaten is not set like in windows
286 static HRESULT WINAPI
287 IShellFolder_fnParseDisplayName (IShellFolder2 * iface,
288 HWND hwndOwner,
289 LPBC pbc,
290 LPOLESTR lpszDisplayName,
291 DWORD * pchEaten, LPITEMIDLIST * ppidl,
292 DWORD * pdwAttributes)
294 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
296 HRESULT hr = S_OK;
297 LPCWSTR szNext = NULL;
298 WCHAR *p, szPath[MAX_PATH];
299 WIN32_FIND_DATAW find_data = { 0 };
300 IFileSystemBindData *fsbd = NULL;
301 LPITEMIDLIST pidlTemp = NULL;
302 DWORD len;
304 TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
305 This, hwndOwner, pbc, lpszDisplayName, debugstr_w (lpszDisplayName),
306 pchEaten, ppidl, pdwAttributes);
308 if (!lpszDisplayName || !lpszDisplayName[0] || !ppidl) return E_INVALIDARG;
310 if (pchEaten)
311 *pchEaten = 0; /* strange but like the original */
313 if (pbc)
315 IUnknown *unk;
317 /* see if the caller bound File System Bind Data */
318 if (SUCCEEDED( IBindCtx_GetObjectParam( pbc, (WCHAR *)L"File System Bind Data", &unk )))
320 IUnknown_QueryInterface( unk, &IID_IFileSystemBindData, (void**)&fsbd );
321 IUnknown_Release( unk );
325 if (*lpszDisplayName)
327 /* build the full pathname to the element */
328 lstrcpynW(szPath, This->sPathTarget, MAX_PATH - 1);
329 PathAddBackslashW(szPath);
330 len = lstrlenW(szPath);
331 /* get the next element */
332 szNext = GetNextElementW( lpszDisplayName, szPath + len, MAX_PATH - len );
334 if (IsEqualCLSID( This->pclsid, &CLSID_UnixFolder ) && lpszDisplayName[0] == '/')
336 lstrcpynW( szPath + len, lpszDisplayName + 1, MAX_PATH - len );
337 for (p = szPath + len; *p; p++) if (*p == '/') *p = '\\';
339 else if (!wcsnicmp( lpszDisplayName, L"\\\\?\\unix\\", 9 ))
341 lstrcpynW( szPath + len, lpszDisplayName + 9, MAX_PATH - len );
342 if ((p = wcschr( szPath + len, '\\' )))
343 while (*p == '\\') *p++ = 0;
344 szNext = p;
347 /* Special case for the root folder. */
348 if (!wcsicmp( szPath, L"\\\\?\\unix\\" ))
350 *ppidl = SHAlloc(sizeof(USHORT));
351 if (!*ppidl) return E_FAIL;
352 (*ppidl)->mkid.cb = 0; /* Terminate the ITEMIDLIST */
353 return S_OK;
356 PathRemoveBackslashW( szPath );
358 if (szNext && *szNext)
360 hr = _ILCreateFromPathW( szPath, &pidlTemp );
361 if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) && fsbd)
363 find_data.dwFileAttributes = FILE_ATTRIBUTE_DIRECTORY;
364 lstrcpyW( find_data.cFileName, szPath + len );
365 pidlTemp = _ILCreateFromFindDataW( &find_data );
367 if (pidlTemp) /* try to analyse the next element */
368 hr = SHELL32_ParseNextElement( iface, hwndOwner, pbc, &pidlTemp,
369 (WCHAR *)szNext, pchEaten, pdwAttributes );
371 else /* it's the last element */
373 if (fsbd)
375 if (FAILED( IFileSystemBindData_GetFindData( fsbd, &find_data )))
376 find_data.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
377 lstrcpyW( find_data.cFileName, szPath + len );
378 pidlTemp = _ILCreateFromFindDataW( &find_data );
380 else hr = _ILCreateFromPathW(szPath, &pidlTemp);
382 if (pidlTemp && pdwAttributes && *pdwAttributes)
383 hr = SHELL32_GetItemAttributes(&This->IShellFolder2_iface, pidlTemp, pdwAttributes);
387 if (SUCCEEDED(hr))
388 *ppidl = pidlTemp;
389 else
390 *ppidl = NULL;
392 TRACE ("(%p)->(-- pidl=%p ret=0x%08lx)\n", This, *ppidl, hr);
394 if (fsbd) IFileSystemBindData_Release( fsbd );
395 return hr;
398 /**************************************************************************
399 * IShellFolder_fnEnumObjects
400 * PARAMETERS
401 * HWND hwndOwner, //[in ] Parent Window
402 * DWORD grfFlags, //[in ] SHCONTF enumeration mask
403 * LPENUMIDLIST* ppenumIDList //[out] IEnumIDList interface
405 static HRESULT WINAPI
406 IShellFolder_fnEnumObjects (IShellFolder2 * iface, HWND hwndOwner,
407 DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
409 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
410 IEnumIDListImpl *list;
412 TRACE ("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This, hwndOwner,
413 dwFlags, ppEnumIDList);
415 if (!(list = IEnumIDList_Constructor()))
416 return E_OUTOFMEMORY;
417 CreateFolderEnumList(list, This->sPathTarget, dwFlags);
418 *ppEnumIDList = &list->IEnumIDList_iface;
420 TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
422 return S_OK;
425 /**************************************************************************
426 * IShellFolder_fnBindToObject
427 * PARAMETERS
428 * LPCITEMIDLIST pidl, //[in ] relative pidl to open
429 * LPBC pbc, //[in ] optional FileSystemBindData context
430 * REFIID riid, //[in ] Initial Interface
431 * LPVOID* ppvObject //[out] Interface*
433 static HRESULT WINAPI
434 IShellFolder_fnBindToObject (IShellFolder2 * iface, LPCITEMIDLIST pidl,
435 LPBC pbc, REFIID riid, LPVOID * ppvOut)
437 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
438 const CLSID *clsid = This->pclsid;
440 TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbc,
441 shdebugstr_guid (riid), ppvOut);
443 if (!IsEqualCLSID( clsid, &CLSID_UnixFolder ) && !IsEqualCLSID( clsid, &CLSID_UnixDosFolder ))
444 clsid = &CLSID_ShellFSFolder;
446 return SHELL32_BindToChild (This->pidlRoot, clsid, This->sPathTarget, pidl, riid, ppvOut);
449 /**************************************************************************
450 * IShellFolder_fnBindToStorage
451 * PARAMETERS
452 * LPCITEMIDLIST pidl, //[in ] complex pidl to store
453 * LPBC pbc, //[in ] reserved
454 * REFIID riid, //[in ] Initial storage interface
455 * LPVOID* ppvObject //[out] Interface* returned
457 static HRESULT WINAPI
458 IShellFolder_fnBindToStorage (IShellFolder2 * iface, LPCITEMIDLIST pidl,
459 LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
461 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
463 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved,
464 shdebugstr_guid (riid), ppvOut);
466 *ppvOut = NULL;
467 return E_NOTIMPL;
470 /**************************************************************************
471 * IShellFolder_fnCompareIDs
474 static HRESULT WINAPI
475 IShellFolder_fnCompareIDs (IShellFolder2 * iface, LPARAM lParam,
476 LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
478 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
480 int nReturn;
482 TRACE ("(%p)->(0x%08Ix,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2);
483 nReturn = SHELL32_CompareIDs(&This->IShellFolder2_iface, lParam, pidl1, pidl2);
484 TRACE ("-- %i\n", nReturn);
485 return nReturn;
488 /**************************************************************************
489 * IShellFolder_fnCreateViewObject
491 static HRESULT WINAPI
492 IShellFolder_fnCreateViewObject (IShellFolder2 * iface, HWND hwndOwner,
493 REFIID riid, LPVOID * ppvOut)
495 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
497 LPSHELLVIEW pShellView;
498 HRESULT hr = E_INVALIDARG;
500 TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This, hwndOwner, shdebugstr_guid (riid),
501 ppvOut);
503 if (ppvOut) {
504 *ppvOut = NULL;
506 if (IsEqualIID (riid, &IID_IDropTarget)) {
507 hr = IShellFolder2_QueryInterface (iface, &IID_IDropTarget, ppvOut);
508 } else if (IsEqualIID (riid, &IID_IContextMenu)) {
509 hr = BackgroundMenu_Constructor((IShellFolder*)iface, FALSE, riid, ppvOut);
510 } else if (IsEqualIID (riid, &IID_IShellView)) {
511 pShellView = IShellView_Constructor ((IShellFolder *) iface);
512 if (pShellView) {
513 hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
514 IShellView_Release (pShellView);
518 TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
519 return hr;
522 /**************************************************************************
523 * IShellFolder_fnGetAttributesOf
525 * PARAMETERS
526 * UINT cidl, //[in ] num elements in pidl array
527 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
528 * ULONG* rgfInOut) //[out] result array
531 static HRESULT WINAPI
532 IShellFolder_fnGetAttributesOf (IShellFolder2 * iface, UINT cidl,
533 LPCITEMIDLIST * apidl, DWORD * rgfInOut)
535 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
537 HRESULT hr = S_OK;
539 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08lx))\n", This, cidl, apidl,
540 rgfInOut, rgfInOut ? *rgfInOut : 0);
542 if (!rgfInOut)
543 return E_INVALIDARG;
544 if (cidl && !apidl)
545 return E_INVALIDARG;
547 if (*rgfInOut == 0)
548 *rgfInOut = ~0;
550 if(cidl == 0){
551 IShellFolder2 *parent = NULL;
552 LPCITEMIDLIST rpidl = NULL;
554 if (_ILIsSpecialFolder(This->pidlRoot))
556 *rgfInOut &= (SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR |
557 SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANRENAME);
559 else
561 hr = SHBindToParent(This->pidlRoot, &IID_IShellFolder2, (void **)&parent, &rpidl);
562 if(SUCCEEDED(hr)) {
563 SHELL32_GetItemAttributes(parent, rpidl, rgfInOut);
564 IShellFolder2_Release(parent);
568 else {
569 while (cidl > 0 && *apidl) {
570 pdump (*apidl);
571 SHELL32_GetItemAttributes(&This->IShellFolder2_iface, *apidl, rgfInOut);
572 apidl++;
573 cidl--;
576 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
577 *rgfInOut &= ~SFGAO_VALIDATE;
579 TRACE ("-- result=0x%08lx\n", *rgfInOut);
581 return hr;
584 /**************************************************************************
585 * SHELL32_CreateExtensionUIObject (internal)
587 static HRESULT SHELL32_CreateExtensionUIObject(IShellFolder2 *iface,
588 LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppvOut)
590 IPersistFile *persist_file;
591 char extensionA[20];
592 WCHAR extensionW[20], buf[MAX_PATH];
593 DWORD size = MAX_PATH;
594 STRRET path;
595 WCHAR *file;
596 GUID guid;
597 HKEY key;
598 HRESULT hr;
601 if(!_ILGetExtension(pidl, extensionA, 20))
602 return S_FALSE;
604 MultiByteToWideChar(CP_ACP, 0, extensionA, -1, extensionW, 20);
606 swprintf(buf, ARRAY_SIZE(buf), L".%s\\ShellEx\\{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
607 extensionW, riid->Data1, riid->Data2, riid->Data3,
608 riid->Data4[0], riid->Data4[1], riid->Data4[2], riid->Data4[3],
609 riid->Data4[4], riid->Data4[5], riid->Data4[6], riid->Data4[7]);
611 if(RegGetValueW(HKEY_CLASSES_ROOT, buf, NULL, RRF_RT_REG_SZ,
612 NULL, buf, &size) != ERROR_SUCCESS)
613 return S_FALSE;
615 if(RegCreateKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Blocked", 0, 0, 0,
616 KEY_READ, NULL, &key, NULL) != ERROR_SUCCESS)
617 return E_FAIL;
618 if(RegQueryValueExW(key, buf, 0, NULL, NULL, NULL)
619 != ERROR_FILE_NOT_FOUND)
620 return E_ACCESSDENIED;
621 RegCloseKey(key);
623 if(RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Blocked", 0, 0, 0,
624 KEY_READ, NULL, &key, NULL) != ERROR_SUCCESS)
625 return E_FAIL;
626 if(RegQueryValueExW(key, buf, 0, NULL, NULL, NULL)
627 != ERROR_FILE_NOT_FOUND)
628 return E_ACCESSDENIED;
629 RegCloseKey(key);
631 if(!GUIDFromStringW(buf, &guid))
632 return E_FAIL;
634 hr = CoCreateInstance(&guid, NULL, CLSCTX_INPROC_SERVER,
635 &IID_IPersistFile, (void**)&persist_file);
636 if(FAILED(hr))
637 return hr;
639 hr = IShellFolder2_GetDisplayNameOf(iface, pidl, SHGDN_FORPARSING, &path);
640 if(SUCCEEDED(hr))
641 hr = StrRetToStrW(&path, NULL, &file);
642 if(FAILED(hr)) {
643 IPersistFile_Release(persist_file);
644 return hr;
647 hr = IPersistFile_Load(persist_file, file, STGM_READ);
648 CoTaskMemFree(file);
649 if(FAILED(hr)) {
650 IPersistFile_Release(persist_file);
651 return hr;
654 hr = IPersistFile_QueryInterface(persist_file, riid, ppvOut);
655 IPersistFile_Release(persist_file);
656 return hr;
659 /**************************************************************************
660 * IShellFolder_fnGetUIObjectOf
662 * PARAMETERS
663 * HWND hwndOwner, //[in ] Parent window for any output
664 * UINT cidl, //[in ] array size
665 * LPCITEMIDLIST* apidl, //[in ] simple pidl array
666 * REFIID riid, //[in ] Requested Interface
667 * UINT* prgfInOut, //[ ] reserved
668 * LPVOID* ppvObject) //[out] Resulting Interface
670 * NOTES
671 * This function gets asked to return "view objects" for one or more (multiple
672 * select) items:
673 * The viewobject typically is an COM object with one of the following
674 * interfaces:
675 * IExtractIcon,IDataObject,IContextMenu
676 * In order to support icon positions in the default Listview your DataObject
677 * must implement the SetData method (in addition to GetData :) - the shell
678 * passes a barely documented "Icon positions" structure to SetData when the
679 * drag starts, and GetData's it if the drop is in another explorer window that
680 * needs the positions.
682 static HRESULT WINAPI
683 IShellFolder_fnGetUIObjectOf (IShellFolder2 * iface,
684 HWND hwndOwner,
685 UINT cidl, LPCITEMIDLIST * apidl, REFIID riid,
686 UINT * prgfInOut, LPVOID * ppvOut)
688 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
690 LPITEMIDLIST pidl;
691 IUnknown *pObj = NULL;
692 HRESULT hr = E_INVALIDARG;
694 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
695 This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
697 if (ppvOut) {
698 *ppvOut = NULL;
700 if(cidl == 1) {
701 hr = SHELL32_CreateExtensionUIObject(iface, *apidl, riid, ppvOut);
702 if(hr != S_FALSE)
703 return hr;
706 if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1)) {
707 return ItemMenu_Constructor((IShellFolder*)iface, This->pidlRoot, apidl, cidl, riid, ppvOut);
708 } else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) {
709 pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner,
710 This->pidlRoot, apidl, cidl);
711 hr = S_OK;
712 } else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1)) {
713 pidl = ILCombine (This->pidlRoot, apidl[0]);
714 pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
715 SHFree (pidl);
716 hr = S_OK;
717 } else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1)) {
718 pidl = ILCombine (This->pidlRoot, apidl[0]);
719 pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl);
720 SHFree (pidl);
721 hr = S_OK;
722 } else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) {
723 hr = IShellFolder2_QueryInterface (iface, &IID_IDropTarget,
724 (LPVOID *) & pObj);
725 } else if ((IsEqualIID(riid,&IID_IShellLinkW) ||
726 IsEqualIID(riid,&IID_IShellLinkA)) && (cidl == 1)) {
727 pidl = ILCombine (This->pidlRoot, apidl[0]);
728 hr = IShellLink_ConstructFromFile(NULL, riid, pidl, &pObj);
729 SHFree (pidl);
730 } else {
731 hr = E_NOINTERFACE;
734 if (SUCCEEDED(hr) && !pObj)
735 hr = E_OUTOFMEMORY;
737 *ppvOut = pObj;
739 TRACE ("(%p)->hr=0x%08lx\n", This, hr);
740 return hr;
743 /******************************************************************************
744 * SHELL_FS_HideExtension [Internal]
746 * Query the registry if the filename extension of a given path should be
747 * hidden.
749 * PARAMS
750 * szPath [I] Relative or absolute path of a file
752 * RETURNS
753 * TRUE, if the filename's extension should be hidden
754 * FALSE, otherwise.
756 static BOOL SHELL_FS_HideExtension(LPCWSTR szPath)
758 HKEY hKey;
759 DWORD dwData;
760 DWORD dwDataSize = sizeof (DWORD);
761 BOOL doHide = FALSE; /* The default value is FALSE (win98 at least) */
763 if (!RegCreateKeyExW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
764 0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0)) {
765 if (!RegQueryValueExW(hKey, L"HideFileExt", 0, 0, (LPBYTE) &dwData, &dwDataSize))
766 doHide = dwData;
767 RegCloseKey (hKey);
770 if (!doHide) {
771 LPWSTR ext = PathFindExtensionW(szPath);
773 if (*ext != '\0') {
774 WCHAR classname[MAX_PATH];
775 LONG classlen = sizeof(classname);
777 if (!RegQueryValueW(HKEY_CLASSES_ROOT, ext, classname, &classlen))
778 if (!RegOpenKeyW(HKEY_CLASSES_ROOT, classname, &hKey)) {
779 if (!RegQueryValueExW(hKey, L"NeverShowExt", 0, NULL, NULL, NULL))
780 doHide = TRUE;
781 RegCloseKey(hKey);
785 return doHide;
788 void SHELL_FS_ProcessDisplayFilename(LPWSTR szPath, DWORD dwFlags)
790 /*FIXME: MSDN also mentions SHGDN_FOREDITING which is not yet handled. */
791 if (!(dwFlags & SHGDN_FORPARSING) &&
792 ((dwFlags & SHGDN_INFOLDER) || (dwFlags == SHGDN_NORMAL))) {
793 if (SHELL_FS_HideExtension(szPath) && szPath[0] != '.')
794 PathRemoveExtensionW(szPath);
798 static void get_display_name( WCHAR dest[MAX_PATH], const WCHAR *path, LPCITEMIDLIST pidl, BOOL is_unix )
800 char *buffer;
801 WCHAR *res;
802 DWORD i, len;
804 lstrcpynW( dest, path, MAX_PATH );
806 /* try to get a better path than the \\?\unix one */
807 if (!wcsnicmp( path, L"\\\\?\\unix\\", 9 ))
809 if (!is_unix)
811 len = WideCharToMultiByte( CP_UNIXCP, 0, path + 8, -1, NULL, 0, NULL, NULL );
812 buffer = heap_alloc( len );
813 len = WideCharToMultiByte( CP_UNIXCP, 0, path + 8, -1, buffer, len, NULL, NULL );
814 for (i = 0; i < len; i++) if (buffer[i] == '\\') buffer[i] = '/';
815 if ((res = wine_get_dos_file_name( buffer )))
817 lstrcpynW( dest, res, MAX_PATH );
818 heap_free( res );
821 else lstrcpynW( dest, path + 8, MAX_PATH );
824 if (!_ILIsDesktop(pidl))
826 PathAddBackslashW( dest );
827 len = lstrlenW( dest );
828 _ILSimpleGetTextW( pidl, dest + len, MAX_PATH - len );
830 if (is_unix) for (i = 0; dest[i]; i++) if (dest[i] == '\\') dest[i] = '/';
833 /**************************************************************************
834 * IShellFolder_fnGetDisplayNameOf
835 * Retrieves the display name for the specified file object or subfolder
837 * PARAMETERS
838 * LPCITEMIDLIST pidl, //[in ] complex pidl to item
839 * DWORD dwFlags, //[in ] SHGNO formatting flags
840 * LPSTRRET lpName) //[out] Returned display name
842 * FIXME
843 * if the name is in the pidl the ret value should be a STRRET_OFFSET
846 static HRESULT WINAPI
847 IShellFolder_fnGetDisplayNameOf (IShellFolder2 * iface, LPCITEMIDLIST pidl,
848 DWORD dwFlags, LPSTRRET strRet)
850 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
851 LPWSTR pszPath;
853 HRESULT hr = S_OK;
855 TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet);
856 pdump (pidl);
858 if (!strRet)
859 return E_INVALIDARG;
861 pszPath = CoTaskMemAlloc((MAX_PATH +1) * sizeof(WCHAR));
862 if (!pszPath)
863 return E_OUTOFMEMORY;
865 if (_ILIsDesktop(pidl)) { /* empty pidl */
866 if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) &&
867 (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER))
869 if (This->sPathTarget)
870 get_display_name( pszPath, This->sPathTarget, pidl,
871 IsEqualCLSID( This->pclsid, &CLSID_UnixFolder ));
872 } else {
873 /* pidl has to contain exactly one non null SHITEMID */
874 hr = E_INVALIDARG;
876 } else if (_ILIsPidlSimple(pidl)) {
877 if ((GET_SHGDN_FOR(dwFlags) & SHGDN_FORPARSING) &&
878 (GET_SHGDN_RELATION(dwFlags) != SHGDN_INFOLDER) &&
879 This->sPathTarget)
881 get_display_name( pszPath, This->sPathTarget, pidl,
882 IsEqualCLSID( This->pclsid, &CLSID_UnixFolder ));
884 else _ILSimpleGetTextW(pidl, pszPath, MAX_PATH);
885 if (!_ILIsFolder(pidl)) SHELL_FS_ProcessDisplayFilename(pszPath, dwFlags);
886 } else {
887 hr = SHELL32_GetDisplayNameOfChild(iface, pidl, dwFlags, pszPath, MAX_PATH);
890 if (SUCCEEDED(hr)) {
891 /* Win9x always returns ANSI strings, NT always returns Unicode strings */
892 if (GetVersion() & 0x80000000) {
893 strRet->uType = STRRET_CSTR;
894 if (!WideCharToMultiByte(CP_ACP, 0, pszPath, -1, strRet->u.cStr, MAX_PATH,
895 NULL, NULL))
896 strRet->u.cStr[0] = '\0';
897 CoTaskMemFree(pszPath);
898 } else {
899 strRet->uType = STRRET_WSTR;
900 strRet->u.pOleStr = pszPath;
902 } else
903 CoTaskMemFree(pszPath);
905 TRACE ("-- (%p)->(%s)\n", This, strRet->uType == STRRET_CSTR ? strRet->u.cStr : debugstr_w(strRet->u.pOleStr));
906 return hr;
909 /**************************************************************************
910 * IShellFolder_fnSetNameOf
911 * Changes the name of a file object or subfolder, possibly changing its item
912 * identifier in the process.
914 * PARAMETERS
915 * HWND hwndOwner, //[in ] Owner window for output
916 * LPCITEMIDLIST pidl, //[in ] simple pidl of item to change
917 * LPCOLESTR lpszName, //[in ] the items new display name
918 * DWORD dwFlags, //[in ] SHGNO formatting flags
919 * LPITEMIDLIST* ppidlOut) //[out] simple pidl returned
921 static HRESULT WINAPI IShellFolder_fnSetNameOf (IShellFolder2 * iface,
922 HWND hwndOwner,
923 LPCITEMIDLIST pidl,
924 LPCOLESTR lpName,
925 DWORD dwFlags,
926 LPITEMIDLIST * pPidlOut)
928 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
929 WCHAR szSrc[MAX_PATH + 1], szDest[MAX_PATH + 1];
930 LPWSTR ptr;
931 BOOL bIsFolder = _ILIsFolder (ILFindLastID (pidl));
933 TRACE ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl,
934 debugstr_w (lpName), dwFlags, pPidlOut);
936 /* pidl has to contain a single non-empty SHITEMID */
937 if (_ILIsDesktop(pidl) || !_ILIsPidlSimple(pidl) || !_ILGetTextPointer(pidl)) return E_INVALIDARG;
939 if (wcspbrk( lpName, L"\\/:*?\"<>|" )) return HRESULT_FROM_WIN32(ERROR_CANCELLED);
941 /* build source path */
942 lstrcpynW(szSrc, This->sPathTarget, MAX_PATH);
943 ptr = PathAddBackslashW (szSrc);
944 _ILSimpleGetTextW (pidl, ptr, MAX_PATH + 1 - (ptr - szSrc));
946 /* build destination path */
947 lstrcpynW(szDest, This->sPathTarget, MAX_PATH);
948 ptr = PathAddBackslashW (szDest);
949 lstrcpynW(ptr, lpName, MAX_PATH + 1 - (ptr - szDest));
951 if(!(dwFlags & SHGDN_FORPARSING) && SHELL_FS_HideExtension(szSrc)) {
952 WCHAR *ext = PathFindExtensionW(szSrc);
953 if(*ext != '\0') {
954 INT len = lstrlenW(szDest);
955 lstrcpynW(szDest + len, ext, MAX_PATH - len);
959 TRACE ("src=%s dest=%s\n", debugstr_w(szSrc), debugstr_w(szDest));
961 if (MoveFileW (szSrc, szDest)) {
962 HRESULT hr = S_OK;
964 if (pPidlOut)
965 hr = _ILCreateFromPathW(szDest, pPidlOut);
967 SHChangeNotify (bIsFolder ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM,
968 SHCNF_PATHW, szSrc, szDest);
970 return hr;
973 return E_FAIL;
976 static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID(IShellFolder2 *iface, GUID *guid)
978 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
979 TRACE("(%p)->(%p)\n", This, guid);
980 return E_NOTIMPL;
983 static HRESULT WINAPI IShellFolder_fnEnumSearches (IShellFolder2 * iface,
984 IEnumExtraSearch ** ppenum)
986 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
987 FIXME ("(%p)\n", This);
988 return E_NOTIMPL;
991 static HRESULT WINAPI
992 IShellFolder_fnGetDefaultColumn(IShellFolder2 *iface, DWORD reserved, ULONG *sort, ULONG *display)
994 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
996 TRACE("(%p)->(%#lx, %p, %p)\n", This, reserved, sort, display);
998 return E_NOTIMPL;
1001 static HRESULT WINAPI
1002 IShellFolder_fnGetDefaultColumnState (IShellFolder2 * iface, UINT iColumn,
1003 DWORD * pcsFlags)
1005 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
1007 TRACE ("(%p)\n", This);
1009 if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS)
1010 return E_INVALIDARG;
1012 *pcsFlags = GenericSFHeader[iColumn].pcsFlags;
1014 return S_OK;
1017 static HRESULT WINAPI
1018 IShellFolder_fnGetDetailsEx (IShellFolder2 * iface, LPCITEMIDLIST pidl,
1019 const SHCOLUMNID * pscid, VARIANT * pv)
1021 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
1022 FIXME ("(%p)\n", This);
1024 return E_NOTIMPL;
1027 static HRESULT WINAPI
1028 IShellFolder_fnGetDetailsOf (IShellFolder2 * iface, LPCITEMIDLIST pidl,
1029 UINT iColumn, SHELLDETAILS * psd)
1031 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
1033 TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd);
1035 if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS)
1036 return E_INVALIDARG;
1038 if (!pidl) return SHELL32_GetColumnDetails(GenericSFHeader, iColumn, psd);
1040 return shellfolder_get_file_details( iface, pidl, GenericSFHeader, iColumn, psd );
1043 static HRESULT WINAPI
1044 IShellFolder_fnMapColumnToSCID (IShellFolder2 *iface, UINT column, SHCOLUMNID *scid)
1046 IGenericSFImpl *This = impl_from_IShellFolder2(iface);
1048 TRACE("(%p)->(%u %p)\n", This, column, scid);
1050 if (column >= GENERICSHELLVIEWCOLUMNS)
1051 return E_INVALIDARG;
1053 return shellfolder_map_column_to_scid(GenericSFHeader, column, scid);
1056 static const IShellFolder2Vtbl sfvt =
1058 IShellFolder_fnQueryInterface,
1059 IShellFolder_fnAddRef,
1060 IShellFolder_fnRelease,
1061 IShellFolder_fnParseDisplayName,
1062 IShellFolder_fnEnumObjects,
1063 IShellFolder_fnBindToObject,
1064 IShellFolder_fnBindToStorage,
1065 IShellFolder_fnCompareIDs,
1066 IShellFolder_fnCreateViewObject,
1067 IShellFolder_fnGetAttributesOf,
1068 IShellFolder_fnGetUIObjectOf,
1069 IShellFolder_fnGetDisplayNameOf,
1070 IShellFolder_fnSetNameOf,
1071 /* ShellFolder2 */
1072 IShellFolder_fnGetDefaultSearchGUID,
1073 IShellFolder_fnEnumSearches,
1074 IShellFolder_fnGetDefaultColumn,
1075 IShellFolder_fnGetDefaultColumnState,
1076 IShellFolder_fnGetDetailsEx,
1077 IShellFolder_fnGetDetailsOf,
1078 IShellFolder_fnMapColumnToSCID
1081 /****************************************************************************
1082 * ISFHelper for IShellFolder implementation
1085 static HRESULT WINAPI ISFHelper_fnQueryInterface(ISFHelper *iface, REFIID riid, void **ppvObj)
1087 IGenericSFImpl *This = impl_from_ISFHelper(iface);
1089 return IUnknown_QueryInterface(This->outer_unk, riid, ppvObj);
1092 static ULONG WINAPI ISFHelper_fnAddRef(ISFHelper *iface)
1094 IGenericSFImpl *This = impl_from_ISFHelper(iface);
1096 return IUnknown_AddRef(This->outer_unk);
1099 static ULONG WINAPI ISFHelper_fnRelease(ISFHelper *iface)
1101 IGenericSFImpl *This = impl_from_ISFHelper(iface);
1103 return IUnknown_Release(This->outer_unk);
1106 /****************************************************************************
1107 * ISFHelper_fnGetUniqueName
1109 * creates a unique folder name
1112 static HRESULT WINAPI
1113 ISFHelper_fnGetUniqueName (ISFHelper * iface, LPWSTR pwszName, UINT uLen)
1115 IGenericSFImpl *This = impl_from_ISFHelper(iface);
1116 IEnumIDList *penum;
1117 HRESULT hr;
1118 WCHAR wszText[MAX_PATH];
1119 WCHAR wszNewFolder[25];
1121 TRACE ("(%p)(%p %u)\n", This, pwszName, uLen);
1123 LoadStringW(shell32_hInstance, IDS_NEWFOLDER, wszNewFolder, ARRAY_SIZE(wszNewFolder));
1124 if (uLen < ARRAY_SIZE(wszNewFolder) + 3)
1125 return E_POINTER;
1127 lstrcpynW (pwszName, wszNewFolder, uLen);
1129 hr = IShellFolder2_EnumObjects(&This->IShellFolder2_iface, 0,
1130 SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
1131 if (penum) {
1132 LPITEMIDLIST pidl;
1133 DWORD dwFetched;
1134 int i = 1;
1136 next:
1137 IEnumIDList_Reset (penum);
1138 while (S_OK == IEnumIDList_Next (penum, 1, &pidl, &dwFetched) &&
1139 dwFetched) {
1140 _ILSimpleGetTextW (pidl, wszText, MAX_PATH);
1141 if (0 == lstrcmpiW (wszText, pwszName)) {
1142 swprintf (pwszName, uLen, L"%s %d", wszNewFolder, i++);
1143 if (i > 99) {
1144 hr = E_FAIL;
1145 break;
1147 goto next;
1151 IEnumIDList_Release (penum);
1153 return hr;
1156 /****************************************************************************
1157 * ISFHelper_fnAddFolder
1159 * adds a new folder.
1162 static HRESULT WINAPI
1163 ISFHelper_fnAddFolder (ISFHelper * iface, HWND hwnd, LPCWSTR pwszName,
1164 LPITEMIDLIST * ppidlOut)
1166 IGenericSFImpl *This = impl_from_ISFHelper(iface);
1167 WCHAR wszNewDir[MAX_PATH];
1168 BOOL bRes;
1169 HRESULT hres = E_FAIL;
1171 TRACE ("(%p)(%s %p)\n", This, debugstr_w(pwszName), ppidlOut);
1173 wszNewDir[0] = 0;
1174 if (This->sPathTarget)
1175 lstrcpynW(wszNewDir, This->sPathTarget, MAX_PATH);
1176 PathAppendW(wszNewDir, pwszName);
1178 bRes = CreateDirectoryW (wszNewDir, NULL);
1179 if (bRes) {
1180 LPITEMIDLIST relPidl;
1182 lstrcpyW(wszNewDir, pwszName);
1184 hres = IShellFolder2_ParseDisplayName(&This->IShellFolder2_iface, hwnd, NULL, wszNewDir,
1185 NULL, &relPidl, NULL);
1187 if (SUCCEEDED(hres)) {
1188 LPITEMIDLIST fullPidl;
1190 fullPidl = ILCombine(This->pidlRoot, relPidl);
1192 if (fullPidl) {
1193 SHChangeNotify(SHCNE_MKDIR, SHCNF_IDLIST, fullPidl, NULL);
1194 ILFree(fullPidl);
1196 if (ppidlOut)
1197 *ppidlOut = relPidl;
1198 else
1199 ILFree(relPidl);
1200 } else {
1201 WARN("failed to combine %s into a full PIDL\n", wine_dbgstr_w(pwszName));
1202 ILFree(relPidl);
1205 } else
1206 WARN("failed to parse %s into a PIDL\n", wine_dbgstr_w(pwszName));
1208 } else {
1209 WCHAR wszText[128 + MAX_PATH];
1210 WCHAR wszTempText[128];
1211 WCHAR wszCaption[256];
1213 /* Cannot Create folder because of permissions */
1214 LoadStringW (shell32_hInstance, IDS_CREATEFOLDER_DENIED, wszTempText, ARRAY_SIZE(wszTempText));
1215 LoadStringW (shell32_hInstance, IDS_CREATEFOLDER_CAPTION, wszCaption, ARRAY_SIZE(wszCaption));
1216 swprintf (wszText, ARRAY_SIZE(wszText), wszTempText, wszNewDir);
1217 MessageBoxW (hwnd, wszText, wszCaption, MB_OK | MB_ICONEXCLAMATION);
1220 return hres;
1223 /****************************************************************************
1224 * build_paths_list
1226 * Builds a list of paths like the one used in SHFileOperation from a table of
1227 * PIDLs relative to the given base folder
1229 static WCHAR *build_paths_list(LPCWSTR wszBasePath, int cidl, const LPCITEMIDLIST *pidls)
1231 WCHAR *wszPathsList;
1232 WCHAR *wszListPos;
1233 int iPathLen;
1234 int i;
1236 iPathLen = lstrlenW(wszBasePath);
1237 wszPathsList = heap_alloc(MAX_PATH*sizeof(WCHAR)*cidl+1);
1238 wszListPos = wszPathsList;
1240 for (i = 0; i < cidl; i++) {
1241 if (!_ILIsFolder(pidls[i]) && !_ILIsValue(pidls[i]))
1242 continue;
1244 lstrcpynW(wszListPos, wszBasePath, MAX_PATH);
1245 /* FIXME: abort if path too long */
1246 _ILSimpleGetTextW(pidls[i], wszListPos+iPathLen, MAX_PATH-iPathLen);
1247 wszListPos += lstrlenW(wszListPos)+1;
1249 *wszListPos=0;
1250 return wszPathsList;
1253 /****************************************************************************
1254 * ISFHelper_fnDeleteItems
1256 * deletes items in folder
1258 static HRESULT WINAPI
1259 ISFHelper_fnDeleteItems (ISFHelper * iface, UINT cidl, LPCITEMIDLIST * apidl)
1261 IGenericSFImpl *This = impl_from_ISFHelper(iface);
1262 UINT i;
1263 SHFILEOPSTRUCTW op;
1264 WCHAR wszPath[MAX_PATH];
1265 WCHAR *wszPathsList;
1266 HRESULT ret;
1267 WCHAR *wszCurrentPath;
1269 TRACE ("(%p)(%u %p)\n", This, cidl, apidl);
1270 if (cidl==0) return S_OK;
1272 if (This->sPathTarget)
1273 lstrcpynW(wszPath, This->sPathTarget, MAX_PATH);
1274 else
1275 wszPath[0] = '\0';
1276 PathAddBackslashW(wszPath);
1277 wszPathsList = build_paths_list(wszPath, cidl, apidl);
1279 ZeroMemory(&op, sizeof(op));
1280 op.hwnd = GetActiveWindow();
1281 op.wFunc = FO_DELETE;
1282 op.pFrom = wszPathsList;
1283 op.fFlags = FOF_ALLOWUNDO;
1284 if (SHFileOperationW(&op))
1286 WARN("SHFileOperation failed\n");
1287 ret = E_FAIL;
1289 else
1290 ret = S_OK;
1292 /* we currently need to manually send the notifies */
1293 wszCurrentPath = wszPathsList;
1294 for (i = 0; i < cidl; i++)
1296 LONG wEventId;
1298 if (_ILIsFolder(apidl[i]))
1299 wEventId = SHCNE_RMDIR;
1300 else if (_ILIsValue(apidl[i]))
1301 wEventId = SHCNE_DELETE;
1302 else
1303 continue;
1305 /* check if file exists */
1306 if (GetFileAttributesW(wszCurrentPath) == INVALID_FILE_ATTRIBUTES)
1308 LPITEMIDLIST pidl = ILCombine(This->pidlRoot, apidl[i]);
1309 SHChangeNotify(wEventId, SHCNF_IDLIST, pidl, NULL);
1310 SHFree(pidl);
1313 wszCurrentPath += lstrlenW(wszCurrentPath)+1;
1315 heap_free(wszPathsList);
1316 return ret;
1319 /****************************************************************************
1320 * ISFHelper_fnCopyItems
1322 * copies items to this folder
1324 static HRESULT WINAPI
1325 ISFHelper_fnCopyItems (ISFHelper * iface, IShellFolder * pSFFrom, UINT cidl,
1326 LPCITEMIDLIST * apidl)
1328 HRESULT ret=E_FAIL;
1329 IPersistFolder2 *ppf2 = NULL;
1330 WCHAR wszSrcPathRoot[MAX_PATH],
1331 wszDstPath[MAX_PATH+1];
1332 WCHAR *wszSrcPathsList;
1333 IGenericSFImpl *This = impl_from_ISFHelper(iface);
1335 SHFILEOPSTRUCTW fop;
1337 TRACE ("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl);
1339 IShellFolder_QueryInterface (pSFFrom, &IID_IPersistFolder2,
1340 (LPVOID *) & ppf2);
1341 if (ppf2) {
1342 LPITEMIDLIST pidl;
1344 if (SUCCEEDED (IPersistFolder2_GetCurFolder (ppf2, &pidl))) {
1345 SHGetPathFromIDListW (pidl, wszSrcPathRoot);
1346 if (This->sPathTarget)
1347 lstrcpynW(wszDstPath, This->sPathTarget, MAX_PATH);
1348 else
1349 wszDstPath[0] = 0;
1350 PathAddBackslashW(wszSrcPathRoot);
1351 PathAddBackslashW(wszDstPath);
1352 wszSrcPathsList = build_paths_list(wszSrcPathRoot, cidl, apidl);
1353 ZeroMemory(&fop, sizeof(fop));
1354 fop.hwnd = GetActiveWindow();
1355 fop.wFunc = FO_COPY;
1356 fop.pFrom = wszSrcPathsList;
1357 fop.pTo = wszDstPath;
1358 fop.fFlags = FOF_ALLOWUNDO;
1359 ret = S_OK;
1360 if(SHFileOperationW(&fop))
1362 WARN("Copy failed\n");
1363 ret = E_FAIL;
1365 heap_free(wszSrcPathsList);
1367 SHFree(pidl);
1368 IPersistFolder2_Release(ppf2);
1370 return ret;
1373 static const ISFHelperVtbl shvt =
1375 ISFHelper_fnQueryInterface,
1376 ISFHelper_fnAddRef,
1377 ISFHelper_fnRelease,
1378 ISFHelper_fnGetUniqueName,
1379 ISFHelper_fnAddFolder,
1380 ISFHelper_fnDeleteItems,
1381 ISFHelper_fnCopyItems
1384 /************************************************************************
1385 * IFSFldr_PersistFolder3_QueryInterface
1388 static HRESULT WINAPI IFSFldr_PersistFolder3_QueryInterface(IPersistFolder3 *iface, REFIID iid,
1389 void **ppv)
1391 IGenericSFImpl *This = impl_from_IPersistFolder3(iface);
1393 return IUnknown_QueryInterface(This->outer_unk, iid, ppv);
1396 /************************************************************************
1397 * IFSFldr_PersistFolder3_AddRef
1400 static ULONG WINAPI IFSFldr_PersistFolder3_AddRef(IPersistFolder3 *iface)
1402 IGenericSFImpl *This = impl_from_IPersistFolder3(iface);
1404 return IUnknown_AddRef(This->outer_unk);
1407 /************************************************************************
1408 * IFSFldr_PersistFolder3_Release
1411 static ULONG WINAPI IFSFldr_PersistFolder3_Release(IPersistFolder3 *iface)
1413 IGenericSFImpl *This = impl_from_IPersistFolder3(iface);
1415 return IUnknown_Release(This->outer_unk);
1418 /************************************************************************
1419 * IFSFldr_PersistFolder3_GetClassID
1421 static HRESULT WINAPI
1422 IFSFldr_PersistFolder3_GetClassID (IPersistFolder3 * iface, CLSID * lpClassId)
1424 IGenericSFImpl *This = impl_from_IPersistFolder3(iface);
1426 TRACE ("(%p)\n", This);
1428 if (!lpClassId)
1429 return E_POINTER;
1430 *lpClassId = *This->pclsid;
1432 return S_OK;
1435 /************************************************************************
1436 * IFSFldr_PersistFolder3_Initialize
1438 * NOTES
1439 * sPathTarget is not set. Don't know how to handle in a non rooted environment.
1441 static HRESULT WINAPI
1442 IFSFldr_PersistFolder3_Initialize (IPersistFolder3 * iface, LPCITEMIDLIST pidl)
1444 WCHAR wszTemp[MAX_PATH];
1445 int len;
1446 IGenericSFImpl *This = impl_from_IPersistFolder3(iface);
1448 TRACE ("(%p)->(%p)\n", This, pidl);
1450 wszTemp[0] = 0;
1452 SHFree (This->pidlRoot); /* free the old pidl */
1453 This->pidlRoot = ILClone (pidl); /* set my pidl */
1455 /* FolderShortcuts' Initialize method only sets the ITEMIDLIST, which
1456 * specifies the location in the shell namespace, but leaves the
1457 * target folder alone */
1458 if (IsEqualCLSID( This->pclsid, &CLSID_FolderShortcut )) return S_OK;
1460 SHFree (This->sPathTarget);
1461 This->sPathTarget = NULL;
1463 /* set my path */
1464 if (_ILIsSpecialFolder(pidl) && IsEqualCLSID( This->pclsid, _ILGetGUIDPointer(pidl) ))
1466 if (IsEqualCLSID( This->pclsid, &CLSID_MyDocuments ))
1468 if (!SHGetSpecialFolderPathW( 0, wszTemp, CSIDL_PERSONAL, FALSE )) return E_FAIL;
1469 PathAddBackslashW( wszTemp );
1471 else lstrcpyW( wszTemp, L"\\\\?\\unix\\" );
1473 else SHGetPathFromIDListW( pidl, wszTemp );
1475 if ((len = lstrlenW(wszTemp)))
1477 This->sPathTarget = SHAlloc((len + 1) * sizeof(WCHAR));
1478 if (!This->sPathTarget) return E_OUTOFMEMORY;
1479 memcpy(This->sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR));
1482 TRACE ("--(%p)->(%s)\n", This, debugstr_w(This->sPathTarget));
1483 return S_OK;
1486 /**************************************************************************
1487 * IFSFldr_PersistFolder3_GetCurFolder
1489 static HRESULT WINAPI
1490 IFSFldr_PersistFolder3_fnGetCurFolder (IPersistFolder3 * iface,
1491 LPITEMIDLIST * pidl)
1493 IGenericSFImpl *This = impl_from_IPersistFolder3(iface);
1495 TRACE ("(%p)->(%p)\n", This, pidl);
1497 if (!pidl) return E_POINTER;
1498 *pidl = ILClone (This->pidlRoot);
1499 return S_OK;
1502 /**************************************************************************
1503 * IFSFldr_PersistFolder3_InitializeEx
1505 * FIXME: error handling
1507 static HRESULT WINAPI
1508 IFSFldr_PersistFolder3_InitializeEx (IPersistFolder3 * iface,
1509 IBindCtx * pbc, LPCITEMIDLIST pidlRoot,
1510 const PERSIST_FOLDER_TARGET_INFO * ppfti)
1512 WCHAR wszTemp[MAX_PATH];
1514 IGenericSFImpl *This = impl_from_IPersistFolder3(iface);
1516 TRACE ("(%p)->(%p,%p,%p)\n", This, pbc, pidlRoot, ppfti);
1517 if (ppfti)
1518 TRACE ("--%p %s %s 0x%08lx 0x%08x\n",
1519 ppfti->pidlTargetFolder, debugstr_w (ppfti->szTargetParsingName),
1520 debugstr_w (ppfti->szNetworkProvider), ppfti->dwAttributes,
1521 ppfti->csidl);
1523 pdump (pidlRoot);
1524 if (ppfti && ppfti->pidlTargetFolder)
1525 pdump (ppfti->pidlTargetFolder);
1527 if (This->pidlRoot)
1529 SHFree(This->pidlRoot);
1530 This->pidlRoot = NULL;
1532 if (This->sPathTarget)
1534 SHFree(This->sPathTarget);
1535 This->sPathTarget = NULL;
1539 * Root path and pidl
1541 This->pidlRoot = ILClone (pidlRoot);
1544 * the target folder is specified in csidl OR pidlTargetFolder OR
1545 * szTargetParsingName
1547 if (ppfti) {
1548 if (ppfti->csidl != -1) {
1549 if (SHGetSpecialFolderPathW (0, wszTemp, ppfti->csidl,
1550 ppfti->csidl & CSIDL_FLAG_CREATE)) {
1551 int len = lstrlenW(wszTemp);
1552 This->sPathTarget = SHAlloc((len + 1) * sizeof(WCHAR));
1553 if (!This->sPathTarget)
1554 return E_OUTOFMEMORY;
1555 memcpy(This->sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR));
1557 } else if (ppfti->szTargetParsingName[0]) {
1558 int len = lstrlenW(ppfti->szTargetParsingName);
1559 This->sPathTarget = SHAlloc((len + 1) * sizeof(WCHAR));
1560 if (!This->sPathTarget)
1561 return E_OUTOFMEMORY;
1562 memcpy(This->sPathTarget, ppfti->szTargetParsingName,
1563 (len + 1) * sizeof(WCHAR));
1564 } else if (ppfti->pidlTargetFolder) {
1565 if (SHGetPathFromIDListW(ppfti->pidlTargetFolder, wszTemp)) {
1566 int len = lstrlenW(wszTemp);
1567 This->sPathTarget = SHAlloc((len + 1) * sizeof(WCHAR));
1568 if (!This->sPathTarget)
1569 return E_OUTOFMEMORY;
1570 memcpy(This->sPathTarget, wszTemp, (len + 1) * sizeof(WCHAR));
1575 TRACE ("--(%p)->(target=%s)\n", This, debugstr_w(This->sPathTarget));
1576 pdump (This->pidlRoot);
1577 return (This->sPathTarget) ? S_OK : E_FAIL;
1580 static HRESULT WINAPI
1581 IFSFldr_PersistFolder3_GetFolderTargetInfo (IPersistFolder3 * iface,
1582 PERSIST_FOLDER_TARGET_INFO * ppfti)
1584 IGenericSFImpl *This = impl_from_IPersistFolder3(iface);
1585 FIXME ("(%p)->(%p)\n", This, ppfti);
1586 ZeroMemory (ppfti, sizeof (*ppfti));
1587 return E_NOTIMPL;
1590 static const IPersistFolder3Vtbl pfvt =
1592 IFSFldr_PersistFolder3_QueryInterface,
1593 IFSFldr_PersistFolder3_AddRef,
1594 IFSFldr_PersistFolder3_Release,
1595 IFSFldr_PersistFolder3_GetClassID,
1596 IFSFldr_PersistFolder3_Initialize,
1597 IFSFldr_PersistFolder3_fnGetCurFolder,
1598 IFSFldr_PersistFolder3_InitializeEx,
1599 IFSFldr_PersistFolder3_GetFolderTargetInfo
1602 /****************************************************************************
1603 * IPersistPropertyBag implementation
1605 static HRESULT WINAPI PersistPropertyBag_QueryInterface(IPersistPropertyBag* iface,
1606 REFIID riid, void** ppv)
1608 IGenericSFImpl *This = impl_from_IPersistPropertyBag(iface);
1609 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
1612 static ULONG WINAPI PersistPropertyBag_AddRef(IPersistPropertyBag* iface)
1614 IGenericSFImpl *This = impl_from_IPersistPropertyBag(iface);
1615 return IUnknown_AddRef(This->outer_unk);
1618 static ULONG WINAPI PersistPropertyBag_Release(IPersistPropertyBag* iface)
1620 IGenericSFImpl *This = impl_from_IPersistPropertyBag(iface);
1621 return IUnknown_Release(This->outer_unk);
1624 static HRESULT WINAPI PersistPropertyBag_GetClassID(IPersistPropertyBag* iface, CLSID* pClassID)
1626 IGenericSFImpl *This = impl_from_IPersistPropertyBag(iface);
1627 return IPersistFolder3_GetClassID(&This->IPersistFolder3_iface, pClassID);
1630 static HRESULT WINAPI PersistPropertyBag_InitNew(IPersistPropertyBag* iface)
1632 IGenericSFImpl *This = impl_from_IPersistPropertyBag(iface);
1633 FIXME("(%p): stub\n", This);
1634 return E_NOTIMPL;
1637 static HRESULT WINAPI PersistPropertyBag_Load(IPersistPropertyBag *iface,
1638 IPropertyBag *pPropertyBag, IErrorLog *pErrorLog)
1640 IGenericSFImpl *This = impl_from_IPersistPropertyBag(iface);
1641 PERSIST_FOLDER_TARGET_INFO pftiTarget;
1642 VARIANT var;
1643 HRESULT hr;
1645 TRACE("(%p)->(%p %p)\n", This, pPropertyBag, pErrorLog);
1647 if (!pPropertyBag)
1648 return E_POINTER;
1650 /* Get 'Target' property from the property bag. */
1651 V_VT(&var) = VT_BSTR;
1652 hr = IPropertyBag_Read(pPropertyBag, L"Target", &var, NULL);
1653 if (FAILED(hr))
1654 return E_FAIL;
1655 lstrcpyW(pftiTarget.szTargetParsingName, V_BSTR(&var));
1656 SysFreeString(V_BSTR(&var));
1658 pftiTarget.pidlTargetFolder = NULL;
1659 pftiTarget.szNetworkProvider[0] = 0;
1660 pftiTarget.dwAttributes = -1;
1661 pftiTarget.csidl = -1;
1663 return IPersistFolder3_InitializeEx(&This->IPersistFolder3_iface, NULL, NULL, &pftiTarget);
1666 static HRESULT WINAPI PersistPropertyBag_Save(IPersistPropertyBag *iface,
1667 IPropertyBag *pPropertyBag, BOOL fClearDirty, BOOL fSaveAllProperties)
1669 IGenericSFImpl *This = impl_from_IPersistPropertyBag(iface);
1670 FIXME("(%p): stub\n", This);
1671 return E_NOTIMPL;
1674 static const IPersistPropertyBagVtbl ppbvt = {
1675 PersistPropertyBag_QueryInterface,
1676 PersistPropertyBag_AddRef,
1677 PersistPropertyBag_Release,
1678 PersistPropertyBag_GetClassID,
1679 PersistPropertyBag_InitNew,
1680 PersistPropertyBag_Load,
1681 PersistPropertyBag_Save
1684 /****************************************************************************
1685 * ISFDropTarget implementation
1687 static HRESULT WINAPI ISFDropTarget_QueryInterface(IDropTarget *iface, REFIID riid, void **ppv)
1689 IGenericSFImpl *This = impl_from_IDropTarget(iface);
1691 return IUnknown_QueryInterface(This->outer_unk, riid, ppv);
1694 static ULONG WINAPI ISFDropTarget_AddRef(IDropTarget *iface)
1696 IGenericSFImpl *This = impl_from_IDropTarget(iface);
1698 return IUnknown_AddRef(This->outer_unk);
1701 static ULONG WINAPI ISFDropTarget_Release(IDropTarget *iface)
1703 IGenericSFImpl *This = impl_from_IDropTarget(iface);
1705 return IUnknown_Release(This->outer_unk);
1708 #define HIDA_GetPIDLFolder(pida) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[0])
1709 #define HIDA_GetPIDLItem(pida, i) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[i+1])
1711 static HRESULT WINAPI
1712 ISFDropTarget_DragEnter (IDropTarget * iface, IDataObject * pDataObject,
1713 DWORD dwKeyState, POINTL pt, DWORD * pdwEffect)
1715 IGenericSFImpl *This = impl_from_IDropTarget(iface);
1716 FORMATETC format;
1717 STGMEDIUM medium;
1719 TRACE("(%p)->(%p 0x%08lx {.x=%ld, .y=%ld} %p)\n", This, pDataObject, dwKeyState, pt.x, pt.y, pdwEffect);
1721 if (!pdwEffect || !pDataObject)
1722 return E_INVALIDARG;
1724 /* Compute a mask of supported drop-effects for this shellfolder object and the given data
1725 * object. Dropping is only supported on folders, which represent filesystem locations. One
1726 * can't drop on file objects. And the 'move' drop effect is only supported, if the source
1727 * folder is not identical to the target folder. */
1728 This->drop_effects_mask = DROPEFFECT_NONE;
1729 InitFormatEtc(format, cfShellIDList, TYMED_HGLOBAL);
1730 if (_ILIsFolder(ILFindLastID(This->pidlRoot)) && /* Only drop to folders, not to files */
1731 SUCCEEDED(IDataObject_GetData(pDataObject, &format, &medium))) /* Only ShellIDList format */
1733 LPIDA pidaShellIDList = GlobalLock(medium.u.hGlobal);
1734 This->drop_effects_mask |= DROPEFFECT_COPY|DROPEFFECT_LINK;
1736 if (pidaShellIDList) { /* Files can only be moved between two different folders */
1737 if (!ILIsEqual(HIDA_GetPIDLFolder(pidaShellIDList), This->pidlRoot))
1738 This->drop_effects_mask |= DROPEFFECT_MOVE;
1739 GlobalUnlock(medium.u.hGlobal);
1743 *pdwEffect = KeyStateToDropEffect(dwKeyState) & This->drop_effects_mask;
1745 return S_OK;
1748 static HRESULT WINAPI
1749 ISFDropTarget_DragOver (IDropTarget * iface, DWORD dwKeyState, POINTL pt,
1750 DWORD * pdwEffect)
1752 IGenericSFImpl *This = impl_from_IDropTarget(iface);
1754 TRACE("(%p)->(0x%08lx {.x=%ld, .y=%ld} %p)\n", This, dwKeyState, pt.x, pt.y, pdwEffect);
1756 if (!pdwEffect)
1757 return E_INVALIDARG;
1759 *pdwEffect = KeyStateToDropEffect(dwKeyState) & This->drop_effects_mask;
1761 return S_OK;
1764 static HRESULT WINAPI ISFDropTarget_DragLeave (IDropTarget * iface)
1766 IGenericSFImpl *This = impl_from_IDropTarget(iface);
1768 TRACE("(%p)\n", This);
1770 This->drop_effects_mask = DROPEFFECT_NONE;
1771 return S_OK;
1774 static HRESULT WINAPI
1775 ISFDropTarget_Drop (IDropTarget * iface, IDataObject * pDataObject,
1776 DWORD dwKeyState, POINTL pt, DWORD * pdwEffect)
1778 IGenericSFImpl *This = impl_from_IDropTarget(iface);
1779 FORMATETC format;
1780 STGMEDIUM medium;
1781 HRESULT hr;
1783 TRACE("(%p)->(%p %ld {.x=%ld, .y=%ld} %p) semi-stub\n",
1784 This, pDataObject, dwKeyState, pt.x, pt.y, pdwEffect);
1786 InitFormatEtc(format, cfShellIDList, TYMED_HGLOBAL);
1787 hr = IDataObject_GetData(pDataObject, &format, &medium);
1788 if (FAILED(hr))
1789 return hr;
1791 if (medium.tymed == TYMED_HGLOBAL) {
1792 IShellFolder *psfSourceFolder, *psfDesktopFolder;
1793 LPIDA pidaShellIDList = GlobalLock(medium.u.hGlobal);
1794 STRRET strret;
1795 UINT i;
1797 if (!pidaShellIDList)
1798 return HRESULT_FROM_WIN32(GetLastError());
1800 hr = SHGetDesktopFolder(&psfDesktopFolder);
1801 if (FAILED(hr)) {
1802 GlobalUnlock(medium.u.hGlobal);
1803 return hr;
1806 hr = IShellFolder_BindToObject(psfDesktopFolder, HIDA_GetPIDLFolder(pidaShellIDList), NULL,
1807 &IID_IShellFolder, (LPVOID*)&psfSourceFolder);
1808 IShellFolder_Release(psfDesktopFolder);
1809 if (FAILED(hr)) {
1810 GlobalUnlock(medium.u.hGlobal);
1811 return hr;
1814 for (i = 0; i < pidaShellIDList->cidl; i++) {
1815 WCHAR wszSourcePath[MAX_PATH];
1817 hr = IShellFolder_GetDisplayNameOf(psfSourceFolder, HIDA_GetPIDLItem(pidaShellIDList, i),
1818 SHGDN_FORPARSING, &strret);
1819 if (FAILED(hr))
1820 break;
1822 hr = StrRetToBufW(&strret, NULL, wszSourcePath, MAX_PATH);
1823 if (FAILED(hr))
1824 break;
1826 switch (*pdwEffect) {
1827 case DROPEFFECT_MOVE:
1828 FIXME("Move %s to %s!\n", debugstr_w(wszSourcePath), debugstr_w(This->sPathTarget));
1829 break;
1830 case DROPEFFECT_COPY:
1831 FIXME("Copy %s to %s!\n", debugstr_w(wszSourcePath), debugstr_w(This->sPathTarget));
1832 break;
1833 case DROPEFFECT_LINK:
1834 FIXME("Link %s from %s!\n", debugstr_w(wszSourcePath), debugstr_w(This->sPathTarget));
1835 break;
1839 IShellFolder_Release(psfSourceFolder);
1840 GlobalUnlock(medium.u.hGlobal);
1841 return hr;
1844 return E_NOTIMPL;
1847 static const IDropTargetVtbl dtvt = {
1848 ISFDropTarget_QueryInterface,
1849 ISFDropTarget_AddRef,
1850 ISFDropTarget_Release,
1851 ISFDropTarget_DragEnter,
1852 ISFDropTarget_DragOver,
1853 ISFDropTarget_DragLeave,
1854 ISFDropTarget_Drop
1857 static HRESULT create_fs( IUnknown *outer_unk, REFIID riid, void **ppv, const CLSID *clsid)
1859 IGenericSFImpl *sf;
1860 HRESULT hr;
1862 TRACE("outer_unk=%p %s\n", outer_unk, shdebugstr_guid(riid));
1864 if (outer_unk && !IsEqualIID(riid, &IID_IUnknown))
1865 return CLASS_E_NOAGGREGATION;
1867 sf = LocalAlloc(LMEM_ZEROINIT, sizeof(*sf));
1868 if (!sf)
1869 return E_OUTOFMEMORY;
1871 sf->ref = 1;
1872 sf->IUnknown_inner.lpVtbl = &unkvt;
1873 sf->IShellFolder2_iface.lpVtbl = &sfvt;
1874 sf->IPersistFolder3_iface.lpVtbl = &pfvt;
1875 sf->IPersistPropertyBag_iface.lpVtbl = &ppbvt;
1876 sf->IDropTarget_iface.lpVtbl = &dtvt;
1877 sf->ISFHelper_iface.lpVtbl = &shvt;
1878 sf->pclsid = clsid;
1879 sf->outer_unk = outer_unk ? outer_unk : &sf->IUnknown_inner;
1881 hr = IUnknown_QueryInterface(&sf->IUnknown_inner, riid, ppv);
1882 IUnknown_Release(&sf->IUnknown_inner);
1884 TRACE ("--%p\n", *ppv);
1885 return hr;
1888 HRESULT WINAPI IFSFolder_Constructor(IUnknown *outer_unk, REFIID riid, void **ppv)
1890 return create_fs( outer_unk, riid, ppv, &CLSID_ShellFSFolder );
1893 HRESULT WINAPI UnixFolder_Constructor(IUnknown *outer_unk, REFIID riid, void **ppv)
1895 return create_fs( outer_unk, riid, ppv, &CLSID_UnixFolder );
1898 HRESULT WINAPI UnixDosFolder_Constructor(IUnknown *outer_unk, REFIID riid, void **ppv)
1900 return create_fs( outer_unk, riid, ppv, &CLSID_UnixDosFolder );
1903 HRESULT WINAPI FolderShortcut_Constructor(IUnknown *outer_unk, REFIID riid, void **ppv)
1905 return create_fs( outer_unk, riid, ppv, &CLSID_FolderShortcut );
1908 HRESULT WINAPI MyDocuments_Constructor(IUnknown *outer_unk, REFIID riid, void **ppv)
1910 return create_fs( outer_unk, riid, ppv, &CLSID_MyDocuments );