Framework for the doppler effect.
[wine] / dlls / shell32 / shfldr_fs.c
1
2 /*
3  *      file system folder
4  *
5  *      Copyright 1997                  Marcus Meissner
6  *      Copyright 1998, 1999, 2002      Juergen Schmied
7  *
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.
12  *
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.
17  *
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29
30 #define NONAMELESSUNION
31 #define NONAMELESSSTRUCT
32 #include "winerror.h"
33 #include "winbase.h"
34 #include "winreg.h"
35
36 #include "ole2.h"
37 #include "shlguid.h"
38
39 #include "pidl.h"
40 #include "undocshell.h"
41 #include "shell32_main.h"
42 #include "shresdef.h"
43 #include "shlwapi.h"
44 #include "shellfolder.h"
45 #include "wine/debug.h"
46 #include "debughlp.h"
47 #include "shfldr.h"
48
49 WINE_DEFAULT_DEBUG_CHANNEL (shell);
50
51 /***********************************************************************
52 *   IShellFolder implementation
53 */
54
55 typedef struct {
56     ICOM_VFIELD (IUnknown);
57     DWORD ref;
58     ICOM_VTABLE (IShellFolder2) * lpvtblShellFolder;
59     ICOM_VTABLE (IPersistFolder3) * lpvtblPersistFolder3;
60     ICOM_VTABLE (IDropTarget) * lpvtblDropTarget;
61     ICOM_VTABLE (ISFHelper) * lpvtblSFHelper;
62
63     IUnknown *pUnkOuter;        /* used for aggregation */
64
65     CLSID *pclsid;
66
67     /* both paths are parsible from the desktop */
68     LPSTR sPathTarget;          /* complete path to target used for enumeration and ChangeNotify */
69
70     LPITEMIDLIST pidlRoot;      /* absolute pidl */
71
72     int dwAttributes;           /* attributes returned by GetAttributesOf FIXME: use it */
73
74     UINT cfShellIDList;         /* clipboardformat for IDropTarget */
75     BOOL fAcceptFmt;            /* flag for pending Drop */
76 } IGenericSFImpl;
77
78 static struct ICOM_VTABLE (IUnknown) unkvt;
79 static struct ICOM_VTABLE (IShellFolder2) sfvt;
80 static struct ICOM_VTABLE (IPersistFolder3) vt_FSFldr_PersistFolder3;   /* IPersistFolder3 for a FS_Folder */
81 static struct ICOM_VTABLE (IDropTarget) dtvt;
82 static struct ICOM_VTABLE (ISFHelper) shvt;
83
84 #define _IShellFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblShellFolder)))
85 #define _ICOM_THIS_From_IShellFolder2(class, name) class* This = (class*)(((char*)name)-_IShellFolder2_Offset);
86
87 #define _IPersistFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder3)))
88 #define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset);
89
90 #define _IPersistFolder3_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder3)))
91 #define _ICOM_THIS_From_IPersistFolder3(class, name) class* This = (class*)(((char*)name)-_IPersistFolder3_Offset);
92
93 #define _IDropTarget_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblDropTarget)))
94 #define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset);
95
96 #define _ISFHelper_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblSFHelper)))
97 #define _ICOM_THIS_From_ISFHelper(class, name) class* This = (class*)(((char*)name)-_ISFHelper_Offset);
98
99 /*
100   converts This to a interface pointer
101 */
102 #define _IUnknown_(This)        (IUnknown*)&(This->lpVtbl)
103 #define _IShellFolder_(This)    (IShellFolder*)&(This->lpvtblShellFolder)
104 #define _IShellFolder2_(This)   (IShellFolder2*)&(This->lpvtblShellFolder)
105 #define _IPersist_(This)        (IPersist*)&(This->lpvtblPersistFolder3)
106 #define _IPersistFolder_(This)  (IPersistFolder*)&(This->lpvtblPersistFolder3)
107 #define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpvtblPersistFolder3)
108 #define _IPersistFolder3_(This) (IPersistFolder3*)&(This->lpvtblPersistFolder3)
109 #define _IDropTarget_(This)     (IDropTarget*)&(This->lpvtblDropTarget)
110 #define _ISFHelper_(This)       (ISFHelper*)&(This->lpvtblSFHelper)
111
112 /**************************************************************************
113 *       registers clipboardformat once
114 */
115 static void SF_RegisterClipFmt (IGenericSFImpl * This)
116 {
117     TRACE ("(%p)\n", This);
118
119     if (!This->cfShellIDList) {
120         This->cfShellIDList = RegisterClipboardFormatA (CFSTR_SHELLIDLIST);
121     }
122 }
123
124 /**************************************************************************
125 *       we need a separate IUnknown to handle aggregation
126 *       (inner IUnknown)
127 */
128 static HRESULT WINAPI IUnknown_fnQueryInterface (IUnknown * iface, REFIID riid, LPVOID * ppvObj)
129 {
130     ICOM_THIS (IGenericSFImpl, iface);
131
132     TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);
133
134     *ppvObj = NULL;
135
136     if (IsEqualIID (riid, &IID_IUnknown))
137         *ppvObj = _IUnknown_ (This);
138     else if (IsEqualIID (riid, &IID_IShellFolder))
139         *ppvObj = _IShellFolder_ (This);
140     else if (IsEqualIID (riid, &IID_IShellFolder2))
141         *ppvObj = _IShellFolder_ (This);
142     else if (IsEqualIID (riid, &IID_IPersist))
143         *ppvObj = _IPersist_ (This);
144     else if (IsEqualIID (riid, &IID_IPersistFolder))
145         *ppvObj = _IPersistFolder_ (This);
146     else if (IsEqualIID (riid, &IID_IPersistFolder2))
147         *ppvObj = _IPersistFolder2_ (This);
148     else if (IsEqualIID (riid, &IID_IPersistFolder3))
149         *ppvObj = _IPersistFolder3_ (This);
150     else if (IsEqualIID (riid, &IID_ISFHelper))
151         *ppvObj = _ISFHelper_ (This);
152     else if (IsEqualIID (riid, &IID_IDropTarget)) {
153         *ppvObj = _IDropTarget_ (This);
154         SF_RegisterClipFmt (This);
155     }
156
157     if (*ppvObj) {
158         IUnknown_AddRef ((IUnknown *) (*ppvObj));
159         TRACE ("-- Interface = %p\n", *ppvObj);
160         return S_OK;
161     }
162     TRACE ("-- Interface: E_NOINTERFACE\n");
163     return E_NOINTERFACE;
164 }
165
166 static ULONG WINAPI IUnknown_fnAddRef (IUnknown * iface)
167 {
168     ICOM_THIS (IGenericSFImpl, iface);
169
170     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
171
172     return ++(This->ref);
173 }
174
175 static ULONG WINAPI IUnknown_fnRelease (IUnknown * iface)
176 {
177     ICOM_THIS (IGenericSFImpl, iface);
178
179     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
180
181     if (!--(This->ref)) {
182         TRACE ("-- destroying IShellFolder(%p)\n", This);
183
184         if (This->pidlRoot)
185             SHFree (This->pidlRoot);
186         if (This->sPathTarget)
187             SHFree (This->sPathTarget);
188         LocalFree ((HLOCAL) This);
189         return 0;
190     }
191     return This->ref;
192 }
193
194 static ICOM_VTABLE (IUnknown) unkvt =
195 {
196     ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE IUnknown_fnQueryInterface,
197       IUnknown_fnAddRef,
198       IUnknown_fnRelease,
199 };
200
201 static shvheader GenericSFHeader[] = {
202     {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
203     {IDS_SHV_COLUMN2, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
204     {IDS_SHV_COLUMN3, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10},
205     {IDS_SHV_COLUMN4, SHCOLSTATE_TYPE_DATE | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 12},
206     {IDS_SHV_COLUMN5, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 5}
207 };
208
209 #define GENERICSHELLVIEWCOLUMNS 5
210
211 /**************************************************************************
212 *       IFSFolder_Constructor
213 *
214 * NOTES
215 *  creating undocumented ShellFS_Folder as part of an aggregation
216 *  {F3364BA0-65B9-11CE-A9BA-00AA004AE837}
217 *
218 */
219 HRESULT WINAPI IFSFolder_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
220 {
221     IGenericSFImpl *sf;
222
223     TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
224
225     if (pUnkOuter && !IsEqualIID (riid, &IID_IUnknown))
226         return CLASS_E_NOAGGREGATION;
227     sf = (IGenericSFImpl *) LocalAlloc (GMEM_ZEROINIT, sizeof (IGenericSFImpl));
228     if (!sf)
229         return E_OUTOFMEMORY;
230
231     sf->ref = 0;
232     ICOM_VTBL (sf) = &unkvt;
233     sf->lpvtblShellFolder = &sfvt;
234     sf->lpvtblPersistFolder3 = &vt_FSFldr_PersistFolder3;
235     sf->lpvtblDropTarget = &dtvt;
236     sf->lpvtblSFHelper = &shvt;
237     sf->pclsid = (CLSID *) & CLSID_ShellFSFolder;
238     sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_ (sf);
239
240     if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv))) {
241         IUnknown_Release (_IUnknown_ (sf));
242         return E_NOINTERFACE;
243     }
244
245     TRACE ("--%p\n", *ppv);
246     return S_OK;
247 }
248
249 /**************************************************************************
250  *  IShellFolder_fnQueryInterface
251  *
252  * PARAMETERS
253  *  REFIID riid         [in ] Requested InterfaceID
254  *  LPVOID* ppvObject   [out] Interface* to hold the result
255  */
256 static HRESULT WINAPI IShellFolder_fnQueryInterface (IShellFolder2 * iface, REFIID riid, LPVOID * ppvObj)
257 {
258     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
259
260         TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);
261
262     return IUnknown_QueryInterface (This->pUnkOuter, riid, ppvObj);
263 }
264
265 /**************************************************************************
266 *  IShellFolder_AddRef
267 */
268
269 static ULONG WINAPI IShellFolder_fnAddRef (IShellFolder2 * iface)
270 {
271     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
272
273     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
274
275     return IUnknown_AddRef (This->pUnkOuter);
276 }
277
278 /**************************************************************************
279  *  IShellFolder_fnRelease
280  */
281 static ULONG WINAPI IShellFolder_fnRelease (IShellFolder2 * iface)
282 {
283     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
284
285     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
286
287     return IUnknown_Release (This->pUnkOuter);
288 }
289
290 /**************************************************************************
291 * IShellFolder_ParseDisplayName {SHELL32}
292 *
293 * Parse a display name.
294 *
295 * PARAMS
296 *  hwndOwner       [in]  Parent window for any message's
297 *  pbc             [in]  Reserved
298 *  lpszDisplayName [in]  Unicode displayname.
299 *  pchEaten        [out] (unicode) characters processed
300 *  ppidl           [out] complex pidl to item
301 *  pdwAttributes   [out] items attributes
302 *
303 * NOTES
304 *  Every folder tries to parse only its own (the leftmost) pidl and creates a
305 *  subfolder to evaluate the remaining parts.
306 *  Now we can parse into namespaces implemented by shell extensions
307 *
308 *  Behaviour on win98:  lpszDisplayName=NULL -> crash
309 *                       lpszDisplayName="" -> returns mycoputer-pidl
310 *
311 * FIXME
312 *    pdwAttributes is not set
313 *    pchEaten is not set like in windows
314 */
315 static HRESULT WINAPI
316 IShellFolder_fnParseDisplayName (IShellFolder2 * iface,
317                                  HWND hwndOwner,
318                                  LPBC pbcReserved,
319                                  LPOLESTR lpszDisplayName,
320                                  DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
321 {
322     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
323
324     HRESULT hr = E_OUTOFMEMORY;
325     LPCWSTR szNext = NULL;
326     WCHAR szElement[MAX_PATH];
327     CHAR szPath[MAX_PATH];
328     LPITEMIDLIST pidlTemp = NULL;
329     DWORD len;
330
331     TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n",
332            This, hwndOwner, pbcReserved, lpszDisplayName, debugstr_w (lpszDisplayName), pchEaten, ppidl, pdwAttributes);
333
334     if (!lpszDisplayName || !ppidl)
335         return E_INVALIDARG;
336
337     if (pchEaten)
338         *pchEaten = 0;          /* strange but like the original */
339
340     if (*lpszDisplayName) {
341         /* get the next element */
342         szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
343
344         /* build the full pathname to the element */
345         lstrcpyA(szPath, This->sPathTarget);
346         PathAddBackslashA(szPath);
347         len = lstrlenA(szPath);
348         WideCharToMultiByte(CP_ACP, 0, szElement, -1, szPath + len, MAX_PATH - len, NULL, NULL);
349
350         /* get the pidl */
351         pidlTemp = _ILCreateFromPathA(szPath);
352         if (pidlTemp) {
353             if (szNext && *szNext) {
354                 /* try to analyse the next element */
355                 hr = SHELL32_ParseNextElement (hwndOwner, iface, &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
356             } else {
357                 /* it's the last element */
358                 if (pdwAttributes && *pdwAttributes) {
359                     SHELL32_GetItemAttributes (_IShellFolder_ (This), pidlTemp, pdwAttributes);
360                 }
361                 hr = S_OK;
362             }
363         }
364     }
365
366     if (!hr)
367         *ppidl = pidlTemp;
368     else
369         *ppidl = NULL;
370
371     TRACE ("(%p)->(-- pidl=%p ret=0x%08lx)\n", This, ppidl ? *ppidl : 0, hr);
372
373     return hr;
374 }
375
376 /**************************************************************************
377 *               IShellFolder_fnEnumObjects
378 * PARAMETERS
379 *  HWND          hwndOwner,    //[in ] Parent Window
380 *  DWORD         grfFlags,     //[in ] SHCONTF enumeration mask
381 *  LPENUMIDLIST* ppenumIDList  //[out] IEnumIDList interface
382 */
383 static HRESULT WINAPI
384 IShellFolder_fnEnumObjects (IShellFolder2 * iface, HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
385 {
386     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
387
388     TRACE ("(%p)->(HWND=%p flags=0x%08lx pplist=%p)\n", This, hwndOwner, dwFlags, ppEnumIDList);
389
390     *ppEnumIDList = IEnumIDList_Constructor (This->sPathTarget, dwFlags, EIDL_FILE);
391
392     TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
393
394     return *ppEnumIDList ? S_OK : E_OUTOFMEMORY;
395 }
396
397 /**************************************************************************
398 *               IShellFolder_fnBindToObject
399 * PARAMETERS
400 *  LPCITEMIDLIST pidl,       //[in ] relative pidl to open
401 *  LPBC          pbc,        //[in ] reserved
402 *  REFIID        riid,       //[in ] Initial Interface
403 *  LPVOID*       ppvObject   //[out] Interface*
404 */
405 static HRESULT WINAPI
406 IShellFolder_fnBindToObject (IShellFolder2 * iface, LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
407 {
408     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
409
410     TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
411
412     return SHELL32_BindToChild (This->pidlRoot, This->sPathTarget, pidl, riid, ppvOut);
413 }
414
415 /**************************************************************************
416 *  IShellFolder_fnBindToStorage
417 * PARAMETERS
418 *  LPCITEMIDLIST pidl,       //[in ] complex pidl to store
419 *  LPBC          pbc,        //[in ] reserved
420 *  REFIID        riid,       //[in ] Initial storage interface
421 *  LPVOID*       ppvObject   //[out] Interface* returned
422 */
423 static HRESULT WINAPI
424 IShellFolder_fnBindToStorage (IShellFolder2 * iface, LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
425 {
426     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
427
428     FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This, pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
429
430     *ppvOut = NULL;
431     return E_NOTIMPL;
432 }
433
434 /**************************************************************************
435 *  IShellFolder_fnCompareIDs
436 */
437
438 static HRESULT WINAPI
439 IShellFolder_fnCompareIDs (IShellFolder2 * iface, LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
440 {
441     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
442
443     int nReturn;
444
445     TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2);
446     nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2);
447     TRACE ("-- %i\n", nReturn);
448     return nReturn;
449 }
450
451 /**************************************************************************
452 *       IShellFolder_fnCreateViewObject
453 */
454 static HRESULT WINAPI
455 IShellFolder_fnCreateViewObject (IShellFolder2 * iface, HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
456 {
457     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
458
459     LPSHELLVIEW pShellView;
460     HRESULT hr = E_INVALIDARG;
461
462     TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This, hwndOwner, shdebugstr_guid (riid), ppvOut);
463
464     if (ppvOut) {
465         *ppvOut = NULL;
466
467         if (IsEqualIID (riid, &IID_IDropTarget)) {
468             hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, ppvOut);
469         } else if (IsEqualIID (riid, &IID_IContextMenu)) {
470             FIXME ("IContextMenu not implemented\n");
471             hr = E_NOTIMPL;
472         } else if (IsEqualIID (riid, &IID_IShellView)) {
473             pShellView = IShellView_Constructor ((IShellFolder *) iface);
474             if (pShellView) {
475                 hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
476                 IShellView_Release (pShellView);
477             }
478         }
479     }
480     TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
481     return hr;
482 }
483
484 /**************************************************************************
485 *  IShellFolder_fnGetAttributesOf
486 *
487 * PARAMETERS
488 *  UINT            cidl,     //[in ] num elements in pidl array
489 *  LPCITEMIDLIST*  apidl,    //[in ] simple pidl array
490 *  ULONG*          rgfInOut) //[out] result array
491 *
492 */
493 static HRESULT WINAPI
494 IShellFolder_fnGetAttributesOf (IShellFolder2 * iface, UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
495 {
496     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
497
498     HRESULT hr = S_OK;
499
500     TRACE ("(%p)->(cidl=%d apidl=%p mask=0x%08lx)\n", This, cidl, apidl, *rgfInOut);
501
502     if ((!cidl) || (!apidl) || (!rgfInOut))
503         return E_INVALIDARG;
504
505     while (cidl > 0 && *apidl) {
506         pdump (*apidl);
507         SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut);
508         apidl++;
509         cidl--;
510     }
511
512     TRACE ("-- result=0x%08lx\n", *rgfInOut);
513
514     return hr;
515 }
516
517 /**************************************************************************
518 *  IShellFolder_fnGetUIObjectOf
519 *
520 * PARAMETERS
521 *  HWND           hwndOwner, //[in ] Parent window for any output
522 *  UINT           cidl,      //[in ] array size
523 *  LPCITEMIDLIST* apidl,     //[in ] simple pidl array
524 *  REFIID         riid,      //[in ] Requested Interface
525 *  UINT*          prgfInOut, //[   ] reserved
526 *  LPVOID*        ppvObject) //[out] Resulting Interface
527 *
528 * NOTES
529 *  This function gets asked to return "view objects" for one or more (multiple select)
530 *  items:
531 *  The viewobject typically is an COM object with one of the following interfaces:
532 *  IExtractIcon,IDataObject,IContextMenu
533 *  In order to support icon positions in the default Listview your DataObject
534 *  must implement the SetData method (in addition to GetData :) - the shell passes
535 *  a barely documented "Icon positions" structure to SetData when the drag starts,
536 *  and GetData's it if the drop is in another explorer window that needs the positions.
537 */
538 static HRESULT WINAPI
539 IShellFolder_fnGetUIObjectOf (IShellFolder2 * iface,
540                               HWND hwndOwner,
541                               UINT cidl, LPCITEMIDLIST * apidl, REFIID riid, UINT * prgfInOut, LPVOID * ppvOut)
542 {
543     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
544
545     LPITEMIDLIST pidl;
546     IUnknown *pObj = NULL;
547     HRESULT hr = E_INVALIDARG;
548
549     TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n",
550            This, hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
551
552     if (ppvOut) {
553         *ppvOut = NULL;
554
555         if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1)) {
556             pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl);
557             hr = S_OK;
558         } else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1)) {
559             pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl);
560             hr = S_OK;
561         } else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1)) {
562             pidl = ILCombine (This->pidlRoot, apidl[0]);
563             pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
564             SHFree (pidl);
565             hr = S_OK;
566         } else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1)) {
567             pidl = ILCombine (This->pidlRoot, apidl[0]);
568             pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl);
569             SHFree (pidl);
570             hr = S_OK;
571         } else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1)) {
572             hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj);
573         } else {
574             hr = E_NOINTERFACE;
575         }
576
577         if (!pObj)
578             hr = E_OUTOFMEMORY;
579
580         *ppvOut = pObj;
581     }
582     TRACE ("(%p)->hr=0x%08lx\n", This, hr);
583     return hr;
584 }
585
586 /**************************************************************************
587 *  IShellFolder_fnGetDisplayNameOf
588 *  Retrieves the display name for the specified file object or subfolder
589 *
590 * PARAMETERS
591 *  LPCITEMIDLIST pidl,    //[in ] complex pidl to item
592 *  DWORD         dwFlags, //[in ] SHGNO formatting flags
593 *  LPSTRRET      lpName)  //[out] Returned display name
594 *
595 * FIXME
596 *  if the name is in the pidl the ret value should be a STRRET_OFFSET
597 */
598
599 static HRESULT WINAPI
600 IShellFolder_fnGetDisplayNameOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
601 {
602     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
603
604     CHAR szPath[MAX_PATH] = "";
605     int len = 0;
606     BOOL bSimplePidl;
607
608     TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", This, pidl, dwFlags, strRet);
609     pdump (pidl);
610
611     if (!pidl || !strRet)
612         return E_INVALIDARG;
613
614     bSimplePidl = _ILIsPidlSimple (pidl);
615
616     /* take names of special folders only if its only this folder */
617     if (_ILIsSpecialFolder (pidl)) {
618         if (bSimplePidl) {
619             _ILSimpleGetText (pidl, szPath, MAX_PATH);  /* append my own path */
620         } else {
621             FIXME ("special pidl\n");
622         }
623     } else {
624         if (!(dwFlags & SHGDN_INFOLDER) && (dwFlags & SHGDN_FORPARSING) && This->sPathTarget) {
625             lstrcpyA (szPath, This->sPathTarget);       /* get path to root */
626             PathAddBackslashA (szPath);
627             len = lstrlenA (szPath);
628         }
629         _ILSimpleGetText (pidl, szPath + len, MAX_PATH - len);  /* append my own path */
630
631         /* MSDN also mentions SHGDN_FOREDITING, which isn't defined in wine */
632         if (!_ILIsFolder (pidl) && !(dwFlags & SHGDN_FORPARSING) &&
633             ((dwFlags & SHGDN_INFOLDER) || (dwFlags == SHGDN_NORMAL))) {
634             HKEY hKey;
635             DWORD dwData;
636             DWORD dwDataSize = sizeof (DWORD);
637             BOOL doHide = 0;    /* The default value is FALSE (win98 at least) */
638
639             /* XXX should it do this only for known file types? -- that would make it even slower! */
640             /* XXX That's what the prompt says!! */
641             if (!RegCreateKeyExA (HKEY_CURRENT_USER,
642                                   "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
643                                   0, 0, 0, KEY_ALL_ACCESS, 0, &hKey, 0)) {
644                 if (!RegQueryValueExA (hKey, "HideFileExt", 0, 0, (LPBYTE) & dwData, &dwDataSize))
645                     doHide = dwData;
646                 RegCloseKey (hKey);
647             }
648             if (doHide && szPath[0] != '.')
649                 PathRemoveExtensionA (szPath);
650         }
651     }
652
653     if ((dwFlags & SHGDN_FORPARSING) && !bSimplePidl) { /* go deeper if needed */
654         PathAddBackslashA (szPath);
655         len = lstrlenA (szPath);
656
657         if (!SUCCEEDED
658             (SHELL32_GetDisplayNameOfChild (iface, pidl, dwFlags | SHGDN_INFOLDER, szPath + len, MAX_PATH - len)))
659             return E_OUTOFMEMORY;
660     }
661     strRet->uType = STRRET_CSTR;
662     lstrcpynA (strRet->u.cStr, szPath, MAX_PATH);
663
664     TRACE ("-- (%p)->(%s)\n", This, szPath);
665     return S_OK;
666 }
667
668 /**************************************************************************
669 *  IShellFolder_fnSetNameOf
670 *  Changes the name of a file object or subfolder, possibly changing its item
671 *  identifier in the process.
672 *
673 * PARAMETERS
674 *  HWND          hwndOwner,  //[in ] Owner window for output
675 *  LPCITEMIDLIST pidl,       //[in ] simple pidl of item to change
676 *  LPCOLESTR     lpszName,   //[in ] the items new display name
677 *  DWORD         dwFlags,    //[in ] SHGNO formatting flags
678 *  LPITEMIDLIST* ppidlOut)   //[out] simple pidl returned
679 */
680 static HRESULT WINAPI IShellFolder_fnSetNameOf (IShellFolder2 * iface, HWND hwndOwner, LPCITEMIDLIST pidl,      /*simple pidl */
681                                                 LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
682 {
683     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
684     char szSrc[MAX_PATH],
685       szDest[MAX_PATH];
686     int len;
687     BOOL bIsFolder = _ILIsFolder (ILFindLastID (pidl));
688
689     TRACE ("(%p)->(%p,pidl=%p,%s,%lu,%p)\n", This, hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
690
691     /* build source path */
692     if (dwFlags & SHGDN_INFOLDER) {
693         strcpy (szSrc, This->sPathTarget);
694         PathAddBackslashA (szSrc);
695         len = strlen (szSrc);
696         _ILSimpleGetText (pidl, szSrc + len, MAX_PATH - len);
697     } else {
698         /* FIXME: Can this work with a simple PIDL? */
699         SHGetPathFromIDListA (pidl, szSrc);
700     }
701
702     /* build destination path */
703     strcpy (szDest, This->sPathTarget);
704     PathAddBackslashA (szDest);
705     len = strlen (szDest);
706     WideCharToMultiByte (CP_ACP, 0, lpName, -1, szDest + len, MAX_PATH - len, NULL, NULL);
707     szDest[MAX_PATH - 1] = 0;
708     TRACE ("src=%s dest=%s\n", szSrc, szDest);
709     if (MoveFileA (szSrc, szDest)) {
710         if (pPidlOut)
711             *pPidlOut = _ILCreateFromPathA(szDest);
712         SHChangeNotify (bIsFolder ? SHCNE_RENAMEFOLDER : SHCNE_RENAMEITEM, SHCNF_PATHA, szSrc, szDest);
713         return S_OK;
714     }
715     return E_FAIL;
716 }
717
718 static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID (IShellFolder2 * iface, GUID * pguid)
719 {
720     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
721         FIXME ("(%p)\n", This);
722     return E_NOTIMPL;
723 }
724 static HRESULT WINAPI IShellFolder_fnEnumSearches (IShellFolder2 * iface, IEnumExtraSearch ** ppenum)
725 {
726     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
727         FIXME ("(%p)\n", This);
728     return E_NOTIMPL;
729 }
730 static HRESULT WINAPI
731 IShellFolder_fnGetDefaultColumn (IShellFolder2 * iface, DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
732 {
733     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
734
735         TRACE ("(%p)\n", This);
736
737     if (pSort)
738         *pSort = 0;
739     if (pDisplay)
740         *pDisplay = 0;
741
742     return S_OK;
743 }
744 static HRESULT WINAPI IShellFolder_fnGetDefaultColumnState (IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags)
745 {
746     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
747
748         TRACE ("(%p)\n", This);
749
750     if (!pcsFlags || iColumn >= GENERICSHELLVIEWCOLUMNS)
751         return E_INVALIDARG;
752
753     *pcsFlags = GenericSFHeader[iColumn].pcsFlags;
754
755     return S_OK;
756 }
757 static HRESULT WINAPI
758 IShellFolder_fnGetDetailsEx (IShellFolder2 * iface, LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
759 {
760     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
761         FIXME ("(%p)\n", This);
762
763     return E_NOTIMPL;
764 }
765 static HRESULT WINAPI
766 IShellFolder_fnGetDetailsOf (IShellFolder2 * iface, LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd)
767 {
768     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
769     HRESULT hr = E_FAIL;
770
771     TRACE ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd);
772
773     if (!psd || iColumn >= GENERICSHELLVIEWCOLUMNS)
774         return E_INVALIDARG;
775
776     if (!pidl) {
777         /* the header titles */
778         psd->fmt = GenericSFHeader[iColumn].fmt;
779         psd->cxChar = GenericSFHeader[iColumn].cxChar;
780         psd->str.uType = STRRET_CSTR;
781         LoadStringA (shell32_hInstance, GenericSFHeader[iColumn].colnameid, psd->str.u.cStr, MAX_PATH);
782         return S_OK;
783     } else {
784         /* the data from the pidl */
785         switch (iColumn) {
786         case 0:         /* name */
787             hr = IShellFolder_GetDisplayNameOf (iface, pidl, SHGDN_NORMAL | SHGDN_INFOLDER, &psd->str);
788             break;
789         case 1:         /* size */
790             _ILGetFileSize (pidl, psd->str.u.cStr, MAX_PATH);
791             break;
792         case 2:         /* type */
793             _ILGetFileType (pidl, psd->str.u.cStr, MAX_PATH);
794             break;
795         case 3:         /* date */
796             _ILGetFileDate (pidl, psd->str.u.cStr, MAX_PATH);
797             break;
798         case 4:         /* attributes */
799             _ILGetFileAttributes (pidl, psd->str.u.cStr, MAX_PATH);
800             break;
801         }
802         hr = S_OK;
803         psd->str.uType = STRRET_CSTR;
804     }
805
806     return hr;
807 }
808 static HRESULT WINAPI IShellFolder_fnMapNameToSCID (IShellFolder2 * iface, LPCWSTR pwszName, SHCOLUMNID * pscid)
809 {
810     _ICOM_THIS_From_IShellFolder2 (IGenericSFImpl, iface)
811     FIXME ("(%p)\n", This);
812     return E_NOTIMPL;
813 }
814
815 static ICOM_VTABLE (IShellFolder2) sfvt =
816 {
817         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
818         IShellFolder_fnQueryInterface,
819         IShellFolder_fnAddRef,
820         IShellFolder_fnRelease,
821         IShellFolder_fnParseDisplayName,
822         IShellFolder_fnEnumObjects,
823         IShellFolder_fnBindToObject,
824         IShellFolder_fnBindToStorage,
825         IShellFolder_fnCompareIDs,
826         IShellFolder_fnCreateViewObject,
827         IShellFolder_fnGetAttributesOf,
828         IShellFolder_fnGetUIObjectOf,
829         IShellFolder_fnGetDisplayNameOf,
830         IShellFolder_fnSetNameOf,
831         /* ShellFolder2 */
832         IShellFolder_fnGetDefaultSearchGUID,
833         IShellFolder_fnEnumSearches,
834         IShellFolder_fnGetDefaultColumn,
835         IShellFolder_fnGetDefaultColumnState,
836         IShellFolder_fnGetDetailsEx,
837         IShellFolder_fnGetDetailsOf,
838         IShellFolder_fnMapNameToSCID
839 };
840
841 /****************************************************************************
842  * ISFHelper for IShellFolder implementation
843  */
844
845 static HRESULT WINAPI ISFHelper_fnQueryInterface (ISFHelper * iface, REFIID riid, LPVOID * ppvObj)
846 {
847     _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface);
848
849     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
850
851     return IUnknown_QueryInterface (This->pUnkOuter, riid, ppvObj);
852 }
853
854 static ULONG WINAPI ISFHelper_fnAddRef (ISFHelper * iface)
855 {
856     _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface);
857
858     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
859
860     return IUnknown_AddRef (This->pUnkOuter);
861 }
862
863 static ULONG WINAPI ISFHelper_fnRelease (ISFHelper * iface)
864 {
865     _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface);
866
867     TRACE ("(%p)\n", This);
868
869     return IUnknown_Release (This->pUnkOuter);
870 }
871
872 /****************************************************************************
873  * ISFHelper_fnAddFolder
874  *
875  * creates a unique folder name
876  */
877
878 static HRESULT WINAPI ISFHelper_fnGetUniqueName (ISFHelper * iface, LPSTR lpName, UINT uLen)
879 {
880     _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface)
881     IEnumIDList *penum;
882     HRESULT hr;
883     char szText[MAX_PATH];
884     char *szNewFolder = "New Folder";
885
886     TRACE ("(%p)(%s %u)\n", This, lpName, uLen);
887
888     if (uLen < strlen (szNewFolder) + 4)
889         return E_POINTER;
890
891     strcpy (lpName, szNewFolder);
892
893     hr = IShellFolder_fnEnumObjects (_IShellFolder2_ (This), 0,
894                                      SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum);
895     if (penum) {
896         LPITEMIDLIST pidl;
897         DWORD dwFetched;
898         int i = 1;
899
900       next:IEnumIDList_Reset (penum);
901         while (S_OK == IEnumIDList_Next (penum, 1, &pidl, &dwFetched) && dwFetched) {
902             _ILSimpleGetText (pidl, szText, MAX_PATH);
903             if (0 == strcasecmp (szText, lpName)) {
904                 sprintf (lpName, "%s %d", szNewFolder, i++);
905                 if (i > 99) {
906                     hr = E_FAIL;
907                     break;
908                 }
909                 goto next;
910             }
911         }
912
913         IEnumIDList_Release (penum);
914     }
915     return hr;
916 }
917
918 /****************************************************************************
919  * ISFHelper_fnAddFolder
920  *
921  * adds a new folder.
922  */
923
924 static HRESULT WINAPI ISFHelper_fnAddFolder (ISFHelper * iface, HWND hwnd, LPCSTR lpName, LPITEMIDLIST * ppidlOut)
925 {
926     _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface)
927     char lpstrNewDir[MAX_PATH];
928     DWORD bRes;
929     HRESULT hres = E_FAIL;
930
931     TRACE ("(%p)(%s %p)\n", This, lpName, ppidlOut);
932
933     strcpy (lpstrNewDir, This->sPathTarget);
934     PathAppendA(lpstrNewDir, lpName);
935
936     bRes = CreateDirectoryA (lpstrNewDir, NULL);
937     if (bRes) {
938         SHChangeNotify (SHCNE_MKDIR, SHCNF_PATHA, lpstrNewDir, NULL);
939         if (ppidlOut)
940             *ppidlOut = _ILCreateFromPathA(lpstrNewDir);
941         hres = S_OK;
942     } else {
943         char lpstrText[128 + MAX_PATH];
944         char lpstrTempText[128];
945         char lpstrCaption[256];
946
947         /* Cannot Create folder because of permissions */
948         LoadStringA (shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, sizeof (lpstrTempText));
949         LoadStringA (shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, sizeof (lpstrCaption));
950         sprintf (lpstrText, lpstrTempText, lpstrNewDir);
951         MessageBoxA (hwnd, lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION);
952     }
953
954     return hres;
955 }
956
957 /****************************************************************************
958  * ISFHelper_fnDeleteItems
959  *
960  * deletes items in folder
961  */
962 static HRESULT WINAPI ISFHelper_fnDeleteItems (ISFHelper * iface, UINT cidl, LPCITEMIDLIST * apidl)
963 {
964     _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface)
965     UINT i;
966     char szPath[MAX_PATH];
967     BOOL bConfirm = TRUE;
968
969     TRACE ("(%p)(%u %p)\n", This, cidl, apidl);
970
971     /* deleting multiple items so give a slightly different warning */
972     if (cidl != 1) {
973         char tmp[8];
974
975         snprintf (tmp, sizeof (tmp), "%d", cidl);
976         if (!SHELL_ConfirmDialog(ASK_DELETE_MULTIPLE_ITEM, tmp))
977             return E_FAIL;
978         bConfirm = FALSE;
979     }
980
981     for (i = 0; i < cidl; i++) {
982         strcpy (szPath, This->sPathTarget);
983         PathAddBackslashA (szPath);
984         _ILSimpleGetText (apidl[i], szPath + strlen (szPath), MAX_PATH);
985
986         if (_ILIsFolder (apidl[i])) {
987             LPITEMIDLIST pidl;
988
989             TRACE ("delete %s\n", szPath);
990             if (!SHELL_DeleteDirectoryA (szPath, bConfirm)) {
991                 TRACE ("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
992                 return E_FAIL;
993             }
994             pidl = ILCombine (This->pidlRoot, apidl[i]);
995             SHChangeNotify (SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL);
996             SHFree (pidl);
997         } else if (_ILIsValue (apidl[i])) {
998             LPITEMIDLIST pidl;
999
1000             TRACE ("delete %s\n", szPath);
1001             if (!SHELL_DeleteFileA (szPath, bConfirm)) {
1002                 TRACE ("delete %s failed, bConfirm=%d\n", szPath, bConfirm);
1003                 return E_FAIL;
1004             }
1005             pidl = ILCombine (This->pidlRoot, apidl[i]);
1006             SHChangeNotify (SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL);
1007             SHFree (pidl);
1008         }
1009
1010     }
1011     return S_OK;
1012 }
1013
1014 /****************************************************************************
1015  * ISFHelper_fnCopyItems
1016  *
1017  * copies items to this folder
1018  */
1019 static HRESULT WINAPI
1020 ISFHelper_fnCopyItems (ISFHelper * iface, IShellFolder * pSFFrom, UINT cidl, LPCITEMIDLIST * apidl)
1021 {
1022     UINT i;
1023     IPersistFolder2 *ppf2 = NULL;
1024     char szSrcPath[MAX_PATH],
1025       szDstPath[MAX_PATH];
1026
1027     _ICOM_THIS_From_ISFHelper (IGenericSFImpl, iface);
1028
1029     TRACE ("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl);
1030
1031     IShellFolder_QueryInterface (pSFFrom, &IID_IPersistFolder2, (LPVOID *) & ppf2);
1032     if (ppf2) {
1033         LPITEMIDLIST pidl;
1034
1035         if (SUCCEEDED (IPersistFolder2_GetCurFolder (ppf2, &pidl))) {
1036             for (i = 0; i < cidl; i++) {
1037                 SHGetPathFromIDListA (pidl, szSrcPath);
1038                 PathAddBackslashA (szSrcPath);
1039                 _ILSimpleGetText (apidl[i], szSrcPath + strlen (szSrcPath), MAX_PATH);
1040
1041                 strcpy (szDstPath, This->sPathTarget);
1042                 PathAddBackslashA (szDstPath);
1043                 _ILSimpleGetText (apidl[i], szDstPath + strlen (szDstPath), MAX_PATH);
1044                 MESSAGE ("would copy %s to %s\n", szSrcPath, szDstPath);
1045             }
1046             SHFree (pidl);
1047         }
1048         IPersistFolder2_Release (ppf2);
1049     }
1050     return S_OK;
1051 }
1052
1053 static ICOM_VTABLE (ISFHelper) shvt =
1054 {
1055         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1056         ISFHelper_fnQueryInterface,
1057         ISFHelper_fnAddRef,
1058         ISFHelper_fnRelease,
1059         ISFHelper_fnGetUniqueName,
1060         ISFHelper_fnAddFolder,
1061         ISFHelper_fnDeleteItems,
1062         ISFHelper_fnCopyItems
1063 };
1064
1065 /************************************************************************
1066  *      IFSFldr_PersistFolder3_QueryInterface
1067  *
1068  */
1069 static HRESULT WINAPI IFSFldr_PersistFolder3_QueryInterface (IPersistFolder3 * iface, REFIID iid, LPVOID * ppvObj)
1070 {
1071     _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
1072
1073     TRACE ("(%p)\n", This);
1074
1075     return IUnknown_QueryInterface (This->pUnkOuter, iid, ppvObj);
1076 }
1077
1078 /************************************************************************
1079  *      IFSFldr_PersistFolder3_AddRef
1080  *
1081  */
1082 static ULONG WINAPI IFSFldr_PersistFolder3_AddRef (IPersistFolder3 * iface)
1083 {
1084     _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
1085
1086     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
1087
1088     return IUnknown_AddRef (This->pUnkOuter);
1089 }
1090
1091 /************************************************************************
1092  *      IFSFldr_PersistFolder3_Release
1093  *
1094  */
1095 static ULONG WINAPI IFSFldr_PersistFolder3_Release (IPersistFolder3 * iface)
1096 {
1097     _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
1098
1099     TRACE ("(%p)->(count=%lu)\n", This, This->ref);
1100
1101     return IUnknown_Release (This->pUnkOuter);
1102 }
1103
1104 /************************************************************************
1105  *      IFSFldr_PersistFolder3_GetClassID
1106  */
1107 static HRESULT WINAPI IFSFldr_PersistFolder3_GetClassID (IPersistFolder3 * iface, CLSID * lpClassId)
1108 {
1109     _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
1110
1111     TRACE ("(%p)\n", This);
1112
1113     if (!lpClassId)
1114         return E_POINTER;
1115     *lpClassId = *This->pclsid;
1116
1117     return S_OK;
1118 }
1119
1120 /************************************************************************
1121  *      IFSFldr_PersistFolder3_Initialize
1122  *
1123  * NOTES
1124  *  sPathTarget is not set. Don't know how to handle in a non rooted environment.
1125  */
1126 static HRESULT WINAPI IFSFldr_PersistFolder3_Initialize (IPersistFolder3 * iface, LPCITEMIDLIST pidl)
1127 {
1128     char sTemp[MAX_PATH];
1129
1130     _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
1131
1132     TRACE ("(%p)->(%p)\n", This, pidl);
1133
1134     if (This->pidlRoot)
1135         SHFree (This->pidlRoot);        /* free the old pidl */
1136     This->pidlRoot = ILClone (pidl);    /* set my pidl */
1137
1138     if (This->sPathTarget)
1139         SHFree (This->sPathTarget);
1140
1141     /* set my path */
1142     if (SHGetPathFromIDListA (pidl, sTemp)) {
1143         This->sPathTarget = SHAlloc (strlen (sTemp) + 1);
1144         strcpy (This->sPathTarget, sTemp);
1145     }
1146
1147     TRACE ("--(%p)->(%s)\n", This, This->sPathTarget);
1148     return S_OK;
1149 }
1150
1151 /**************************************************************************
1152  *      IFSFldr_PersistFolder3_GetCurFolder
1153  */
1154 static HRESULT WINAPI IFSFldr_PersistFolder3_fnGetCurFolder (IPersistFolder3 * iface, LPITEMIDLIST * pidl)
1155 {
1156     _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
1157
1158     TRACE ("(%p)->(%p)\n", This, pidl);
1159
1160     if (!pidl) return E_POINTER;
1161     *pidl = ILClone (This->pidlRoot);
1162     return S_OK;
1163 }
1164
1165 /**************************************************************************
1166  *      IFSFldr_PersistFolder3_InitializeEx
1167  *
1168  * FIXME: errorhandling
1169  */
1170 static HRESULT WINAPI
1171 IFSFldr_PersistFolder3_InitializeEx (IPersistFolder3 * iface,
1172                                      IBindCtx * pbc, LPCITEMIDLIST pidlRoot, const PERSIST_FOLDER_TARGET_INFO * ppfti)
1173 {
1174     char sTemp[MAX_PATH];
1175
1176     _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
1177
1178     TRACE ("(%p)->(%p,%p,%p)\n", This, pbc, pidlRoot, ppfti);
1179     if (ppfti)
1180         TRACE ("--%p %s %s 0x%08lx 0x%08x\n",
1181                ppfti->pidlTargetFolder, debugstr_w (ppfti->szTargetParsingName),
1182                debugstr_w (ppfti->szNetworkProvider), ppfti->dwAttributes, ppfti->csidl);
1183
1184     pdump (pidlRoot);
1185     if (ppfti && ppfti->pidlTargetFolder)
1186         pdump (ppfti->pidlTargetFolder);
1187
1188     if (This->pidlRoot)
1189         __SHFreeAndNil (&This->pidlRoot);       /* free the old */
1190     if (This->sPathTarget)
1191         __SHFreeAndNil (&This->sPathTarget);
1192
1193     /*
1194      * Root path and pidl
1195      */
1196     This->pidlRoot = ILClone (pidlRoot);
1197
1198     /*
1199      *  the target folder is spezified in csidl OR pidlTargetFolder OR szTargetParsingName
1200      */
1201     if (ppfti) {
1202         if (ppfti->csidl != -1) {
1203             if (SHGetSpecialFolderPathA (0, sTemp, ppfti->csidl, ppfti->csidl & CSIDL_FLAG_CREATE)) {
1204                 __SHCloneStrA (&This->sPathTarget, sTemp);
1205             }
1206         } else if (ppfti->szTargetParsingName[0]) {
1207             __SHCloneStrWtoA (&This->sPathTarget, ppfti->szTargetParsingName);
1208         } else if (ppfti->pidlTargetFolder) {
1209             if (SHGetPathFromIDListA (ppfti->pidlTargetFolder, sTemp)) {
1210                 __SHCloneStrA (&This->sPathTarget, sTemp);
1211             }
1212         }
1213     }
1214
1215     TRACE ("--(%p)->(target=%s)\n", This, debugstr_a (This->sPathTarget));
1216     pdump (This->pidlRoot);
1217     return (This->sPathTarget) ? S_OK : E_FAIL;
1218 }
1219
1220 static HRESULT WINAPI
1221 IFSFldr_PersistFolder3_GetFolderTargetInfo (IPersistFolder3 * iface, PERSIST_FOLDER_TARGET_INFO * ppfti)
1222 {
1223     _ICOM_THIS_From_IPersistFolder3 (IGenericSFImpl, iface);
1224     FIXME ("(%p)->(%p)\n", This, ppfti);
1225     ZeroMemory (ppfti, sizeof (ppfti));
1226     return E_NOTIMPL;
1227 }
1228
1229 static ICOM_VTABLE (IPersistFolder3) vt_FSFldr_PersistFolder3 =
1230 {
1231         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1232         IFSFldr_PersistFolder3_QueryInterface,
1233         IFSFldr_PersistFolder3_AddRef,
1234         IFSFldr_PersistFolder3_Release,
1235         IFSFldr_PersistFolder3_GetClassID,
1236         IFSFldr_PersistFolder3_Initialize,
1237         IFSFldr_PersistFolder3_fnGetCurFolder,
1238         IFSFldr_PersistFolder3_InitializeEx,
1239         IFSFldr_PersistFolder3_GetFolderTargetInfo
1240 };
1241
1242 /****************************************************************************
1243  * ISFDropTarget implementation
1244  */
1245 static BOOL ISFDropTarget_QueryDrop (IDropTarget * iface, DWORD dwKeyState, LPDWORD pdwEffect)
1246 {
1247     DWORD dwEffect = *pdwEffect;
1248
1249     _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
1250
1251     *pdwEffect = DROPEFFECT_NONE;
1252
1253     if (This->fAcceptFmt) {     /* Does our interpretation of the keystate ... */
1254         *pdwEffect = KeyStateToDropEffect (dwKeyState);
1255
1256         /* ... matches the desired effect ? */
1257         if (dwEffect & *pdwEffect) {
1258             return TRUE;
1259         }
1260     }
1261     return FALSE;
1262 }
1263
1264 static HRESULT WINAPI ISFDropTarget_QueryInterface (IDropTarget * iface, REFIID riid, LPVOID * ppvObj)
1265 {
1266     _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
1267
1268     TRACE ("(%p)\n", This);
1269
1270     return IUnknown_QueryInterface (This->pUnkOuter, riid, ppvObj);
1271 }
1272
1273 static ULONG WINAPI ISFDropTarget_AddRef (IDropTarget * iface)
1274 {
1275     _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
1276
1277     TRACE ("(%p)\n", This);
1278
1279     return IUnknown_AddRef (This->pUnkOuter);
1280 }
1281
1282 static ULONG WINAPI ISFDropTarget_Release (IDropTarget * iface)
1283 {
1284     _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
1285
1286     TRACE ("(%p)\n", This);
1287
1288     return IUnknown_Release (This->pUnkOuter);
1289 }
1290
1291 static HRESULT WINAPI
1292 ISFDropTarget_DragEnter (IDropTarget * iface, IDataObject * pDataObject, DWORD dwKeyState, POINTL pt, DWORD * pdwEffect)
1293 {
1294     FORMATETC fmt;
1295
1296     _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
1297
1298     TRACE ("(%p)->(DataObject=%p)\n", This, pDataObject);
1299
1300     InitFormatEtc (fmt, This->cfShellIDList, TYMED_HGLOBAL);
1301
1302     This->fAcceptFmt = (S_OK == IDataObject_QueryGetData (pDataObject, &fmt)) ? TRUE : FALSE;
1303
1304     ISFDropTarget_QueryDrop (iface, dwKeyState, pdwEffect);
1305
1306     return S_OK;
1307 }
1308
1309 static HRESULT WINAPI ISFDropTarget_DragOver (IDropTarget * iface, DWORD dwKeyState, POINTL pt, DWORD * pdwEffect)
1310 {
1311     _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
1312
1313     TRACE ("(%p)\n", This);
1314
1315     if (!pdwEffect)
1316         return E_INVALIDARG;
1317
1318     ISFDropTarget_QueryDrop (iface, dwKeyState, pdwEffect);
1319
1320     return S_OK;
1321 }
1322
1323 static HRESULT WINAPI ISFDropTarget_DragLeave (IDropTarget * iface)
1324 {
1325     _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
1326
1327     TRACE ("(%p)\n", This);
1328
1329     This->fAcceptFmt = FALSE;
1330
1331     return S_OK;
1332 }
1333
1334 static HRESULT WINAPI
1335 ISFDropTarget_Drop (IDropTarget * iface, IDataObject * pDataObject, DWORD dwKeyState, POINTL pt, DWORD * pdwEffect)
1336 {
1337     _ICOM_THIS_From_IDropTarget (IGenericSFImpl, iface);
1338
1339     FIXME ("(%p) object dropped\n", This);
1340
1341     return E_NOTIMPL;
1342 }
1343
1344 static struct ICOM_VTABLE (IDropTarget) dtvt = {
1345         ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1346         ISFDropTarget_QueryInterface,
1347         ISFDropTarget_AddRef,
1348         ISFDropTarget_Release,
1349         ISFDropTarget_DragEnter,
1350         ISFDropTarget_DragOver,
1351         ISFDropTarget_DragLeave,
1352         ISFDropTarget_Drop
1353 };