shell32: RunFileDlg: make the error messages easier to understand for the user.
[wine] / dlls / shell32 / shfldr_netplaces.c
1 /*
2  *      Network Places (Neighbourhood) folder
3  *
4  *      Copyright 1997                  Marcus Meissner
5  *      Copyright 1998, 1999, 2002      Juergen Schmied
6  *      Copyright 2003                  Mike McCormack for CodeWeavers
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdarg.h>
29 #include <stdio.h>
30
31 #define COBJMACROS
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
34
35 #include "winerror.h"
36 #include "windef.h"
37 #include "winbase.h"
38 #include "winreg.h"
39
40 #include "pidl.h"
41 #include "enumidlist.h"
42 #include "undocshell.h"
43 #include "shell32_main.h"
44 #include "shresdef.h"
45 #include "wine/debug.h"
46 #include "wine/unicode.h"
47 #include "debughlp.h"
48 #include "shfldr.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL (shell);
51
52 /***********************************************************************
53 *   IShellFolder implementation
54 */
55
56 typedef struct {
57     const IShellFolder2Vtbl  *lpVtbl;
58     LONG                       ref;
59     const IPersistFolder2Vtbl *lpVtblPersistFolder2;
60
61     /* both paths are parsible from the desktop */
62     LPITEMIDLIST pidlRoot;      /* absolute pidl */
63 } IGenericSFImpl;
64
65 static const IShellFolder2Vtbl vt_ShellFolder2;
66 static const IPersistFolder2Vtbl vt_NP_PersistFolder2;
67
68
69 #define _IPersistFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpVtblPersistFolder2)))
70 #define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder2_Offset);
71
72 #define _IUnknown_(This)        (IUnknown*)&(This->lpVtbl)
73 #define _IShellFolder_(This)    (IShellFolder*)&(This->lpVtbl)
74 #define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpVtblPersistFolder2)
75
76 static const shvheader NetworkPlacesSFHeader[] = {
77     {IDS_SHV_COLUMN1, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 15},
78     {IDS_SHV_COLUMN9, SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT, LVCFMT_RIGHT, 10}
79 };
80
81 #define NETWORKPLACESSHELLVIEWCOLUMNS 2
82
83 /**************************************************************************
84 *       ISF_NetworkPlaces_Constructor
85 */
86 HRESULT WINAPI ISF_NetworkPlaces_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
87 {
88     IGenericSFImpl *sf;
89
90     TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
91
92     if (!ppv)
93         return E_POINTER;
94     if (pUnkOuter)
95         return CLASS_E_NOAGGREGATION;
96
97     sf = (IGenericSFImpl *) HeapAlloc ( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (IGenericSFImpl));
98     if (!sf)
99         return E_OUTOFMEMORY;
100
101     sf->ref = 0;
102     sf->lpVtbl = &vt_ShellFolder2;
103     sf->lpVtblPersistFolder2 = &vt_NP_PersistFolder2;
104     sf->pidlRoot = _ILCreateNetHood();  /* my qualified pidl */
105
106     if (!SUCCEEDED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv)))
107     {
108         IUnknown_Release (_IUnknown_ (sf));
109         return E_NOINTERFACE;
110     }
111
112     TRACE ("--(%p)\n", sf);
113     return S_OK;
114 }
115
116 /**************************************************************************
117  *      ISF_NetworkPlaces_fnQueryInterface
118  *
119  * NOTE
120  *     supports not IPersist/IPersistFolder
121  */
122 static HRESULT WINAPI ISF_NetworkPlaces_fnQueryInterface (IShellFolder2 *iface, REFIID riid, LPVOID *ppvObj)
123 {
124     IGenericSFImpl *This = (IGenericSFImpl *)iface;
125
126     TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);
127
128     *ppvObj = NULL;
129
130     if (IsEqualIID (riid, &IID_IUnknown) ||
131         IsEqualIID (riid, &IID_IShellFolder) ||
132         IsEqualIID (riid, &IID_IShellFolder2))
133     {
134         *ppvObj = This;
135     }
136     else if (IsEqualIID (riid, &IID_IPersist) ||
137              IsEqualIID (riid, &IID_IPersistFolder) ||
138              IsEqualIID (riid, &IID_IPersistFolder2))
139     {
140         *ppvObj = _IPersistFolder2_ (This);
141     }
142
143     if (*ppvObj)
144     {
145         IUnknown_AddRef ((IUnknown *) (*ppvObj));
146         TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj);
147         return S_OK;
148     }
149     TRACE ("-- Interface: E_NOINTERFACE\n");
150     return E_NOINTERFACE;
151 }
152
153 static ULONG WINAPI ISF_NetworkPlaces_fnAddRef (IShellFolder2 * iface)
154 {
155     IGenericSFImpl *This = (IGenericSFImpl *)iface;
156     ULONG refCount = InterlockedIncrement(&This->ref);
157
158     TRACE ("(%p)->(count=%u)\n", This, refCount - 1);
159
160     return refCount;
161 }
162
163 static ULONG WINAPI ISF_NetworkPlaces_fnRelease (IShellFolder2 * iface)
164 {
165     IGenericSFImpl *This = (IGenericSFImpl *)iface;
166     ULONG refCount = InterlockedDecrement(&This->ref);
167
168     TRACE ("(%p)->(count=%u)\n", This, refCount + 1);
169
170     if (!refCount) {
171         TRACE ("-- destroying IShellFolder(%p)\n", This);
172         SHFree (This->pidlRoot);
173         HeapFree (GetProcessHeap(), 0, This);
174     }
175     return refCount;
176 }
177
178 /**************************************************************************
179 *       ISF_NetworkPlaces_fnParseDisplayName
180 */
181 static HRESULT WINAPI ISF_NetworkPlaces_fnParseDisplayName (IShellFolder2 * iface,
182                HWND hwndOwner, LPBC pbcReserved, LPOLESTR lpszDisplayName,
183                DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
184 {
185     static const WCHAR wszEntireNetwork[] = {'E','n','t','i','r','e','N','e','t','w','o','r','k'}; /* not nul-terminated */
186     IGenericSFImpl *This = (IGenericSFImpl *)iface;
187     HRESULT hr = E_INVALIDARG;
188     LPCWSTR szNext = NULL;
189     WCHAR szElement[MAX_PATH];
190     LPITEMIDLIST pidlTemp = NULL;
191     int len;
192
193     TRACE ("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", This,
194             hwndOwner, pbcReserved, lpszDisplayName, debugstr_w (lpszDisplayName),
195             pchEaten, ppidl, pdwAttributes);
196
197     *ppidl = NULL;
198
199     szNext = GetNextElementW (lpszDisplayName, szElement, MAX_PATH);
200     len = strlenW(szElement);
201     if (len == sizeof(wszEntireNetwork)/sizeof(wszEntireNetwork[0]) &&
202         !strncmpiW(szElement, wszEntireNetwork, sizeof(wszEntireNetwork)/sizeof(wszEntireNetwork[0])))
203     {
204         pidlTemp = _ILCreateEntireNetwork();
205         if (pidlTemp)
206             hr = S_OK;
207         else
208             hr = E_OUTOFMEMORY;
209     }
210     else
211         FIXME("not implemented for %s\n", debugstr_w(lpszDisplayName));
212
213     if (SUCCEEDED(hr) && pidlTemp)
214     {
215         if (szNext && *szNext)
216         {
217             hr = SHELL32_ParseNextElement(iface, hwndOwner, pbcReserved,
218                     &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
219         }
220         else
221         {
222             if (pdwAttributes && *pdwAttributes)
223                 hr = SHELL32_GetItemAttributes(_IShellFolder_ (This),
224                                                pidlTemp, pdwAttributes);
225         }
226     }
227
228     if (SUCCEEDED(hr))
229         *ppidl = pidlTemp;
230     else
231         ILFree(pidlTemp);
232
233     TRACE ("(%p)->(-- ret=0x%08x)\n", This, hr);
234
235     return hr;
236 }
237
238 /**************************************************************************
239 *               ISF_NetworkPlaces_fnEnumObjects
240 */
241 static HRESULT WINAPI ISF_NetworkPlaces_fnEnumObjects (IShellFolder2 * iface,
242                HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
243 {
244     IGenericSFImpl *This = (IGenericSFImpl *)iface;
245
246     TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", This,
247             hwndOwner, dwFlags, ppEnumIDList);
248
249     *ppEnumIDList = IEnumIDList_Constructor();
250
251     TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
252
253     return (*ppEnumIDList) ? S_OK : E_OUTOFMEMORY;
254 }
255
256 /**************************************************************************
257 *               ISF_NetworkPlaces_fnBindToObject
258 */
259 static HRESULT WINAPI ISF_NetworkPlaces_fnBindToObject (IShellFolder2 * iface,
260                LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
261 {
262     IGenericSFImpl *This = (IGenericSFImpl *)iface;
263
264     TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This,
265             pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
266
267     return SHELL32_BindToChild (This->pidlRoot, NULL, pidl, riid, ppvOut);
268 }
269
270 /**************************************************************************
271 *       ISF_NetworkPlaces_fnBindToStorage
272 */
273 static HRESULT WINAPI ISF_NetworkPlaces_fnBindToStorage (IShellFolder2 * iface,
274                LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
275 {
276     IGenericSFImpl *This = (IGenericSFImpl *)iface;
277
278     FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This,
279             pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
280
281     *ppvOut = NULL;
282     return E_NOTIMPL;
283 }
284
285 /**************************************************************************
286 *       ISF_NetworkPlaces_fnCompareIDs
287 */
288
289 static HRESULT WINAPI ISF_NetworkPlaces_fnCompareIDs (IShellFolder2 * iface,
290                LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
291 {
292     IGenericSFImpl *This = (IGenericSFImpl *)iface;
293     int nReturn;
294
295     TRACE ("(%p)->(0x%08lx,pidl1=%p,pidl2=%p)\n", This, lParam, pidl1, pidl2);
296     nReturn = SHELL32_CompareIDs (_IShellFolder_ (This), lParam, pidl1, pidl2);
297     TRACE ("-- %i\n", nReturn);
298     return nReturn;
299 }
300
301 /**************************************************************************
302 *       ISF_NetworkPlaces_fnCreateViewObject
303 */
304 static HRESULT WINAPI ISF_NetworkPlaces_fnCreateViewObject (IShellFolder2 * iface,
305                HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
306 {
307     IGenericSFImpl *This = (IGenericSFImpl *)iface;
308     LPSHELLVIEW pShellView;
309     HRESULT hr = E_INVALIDARG;
310
311     TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This,
312            hwndOwner, shdebugstr_guid (riid), ppvOut);
313
314     if (!ppvOut)
315         return hr;
316
317     *ppvOut = NULL;
318
319     if (IsEqualIID (riid, &IID_IDropTarget))
320     {
321         WARN ("IDropTarget not implemented\n");
322         hr = E_NOTIMPL;
323     }
324     else if (IsEqualIID (riid, &IID_IContextMenu))
325     {
326         WARN ("IContextMenu not implemented\n");
327         hr = E_NOTIMPL;
328     }
329     else if (IsEqualIID (riid, &IID_IShellView))
330     {
331         pShellView = IShellView_Constructor ((IShellFolder *) iface);
332         if (pShellView)
333         {
334             hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
335             IShellView_Release (pShellView);
336         }
337     }
338     TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
339     return hr;
340 }
341
342 /**************************************************************************
343 *  ISF_NetworkPlaces_fnGetAttributesOf
344 */
345 static HRESULT WINAPI ISF_NetworkPlaces_fnGetAttributesOf (IShellFolder2 * iface,
346                UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
347 {
348     IGenericSFImpl *This = (IGenericSFImpl *)iface;
349     HRESULT hr = S_OK;
350
351     TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", This,
352             cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
353
354     if (!rgfInOut)
355         return E_INVALIDARG;
356     if (cidl && !apidl)
357         return E_INVALIDARG;
358
359     if (*rgfInOut == 0)
360         *rgfInOut = ~0;
361
362     if (cidl == 0)
363     {
364         IShellFolder *psfParent = NULL;
365         LPCITEMIDLIST rpidl = NULL;
366
367         hr = SHBindToParent(This->pidlRoot, &IID_IShellFolder, (LPVOID*)&psfParent, (LPCITEMIDLIST*)&rpidl);
368         if(SUCCEEDED(hr))
369         {
370             SHELL32_GetItemAttributes (psfParent, rpidl, rgfInOut);
371             IShellFolder_Release(psfParent);
372         }
373     }
374     else
375     {
376         while (cidl > 0 && *apidl)
377         {
378             pdump (*apidl);
379             SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut);
380             apidl++;
381             cidl--;
382         }
383     }
384
385     /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
386     *rgfInOut &= ~SFGAO_VALIDATE;
387
388     TRACE ("-- result=0x%08x\n", *rgfInOut);
389     return hr;
390 }
391
392 /**************************************************************************
393 *       ISF_NetworkPlaces_fnGetUIObjectOf
394 *
395 * PARAMETERS
396 *  hwndOwner [in]  Parent window for any output
397 *  cidl      [in]  array size
398 *  apidl     [in]  simple pidl array
399 *  riid      [in]  Requested Interface
400 *  prgfInOut [   ] reserved
401 *  ppvObject [out] Resulting Interface
402 *
403 */
404 static HRESULT WINAPI ISF_NetworkPlaces_fnGetUIObjectOf (IShellFolder2 * iface,
405                HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl, REFIID riid,
406                UINT * prgfInOut, LPVOID * ppvOut)
407 {
408     IGenericSFImpl *This = (IGenericSFImpl *)iface;
409
410     LPITEMIDLIST pidl;
411     IUnknown *pObj = NULL;
412     HRESULT hr = E_INVALIDARG;
413
414     TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", This,
415             hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
416
417     if (!ppvOut)
418         return hr;
419
420     *ppvOut = NULL;
421
422     if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1))
423     {
424         pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl);
425         hr = S_OK;
426     }
427     else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1))
428     {
429         pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl);
430         hr = S_OK;
431     }
432     else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1))
433     {
434         pidl = ILCombine (This->pidlRoot, apidl[0]);
435         pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
436         SHFree (pidl);
437         hr = S_OK;
438     }
439     else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1))
440     {
441         pidl = ILCombine (This->pidlRoot, apidl[0]);
442         pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl);
443         SHFree (pidl);
444         hr = S_OK;
445     }
446     else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1))
447     {
448         hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj);
449     }
450     else
451         hr = E_NOINTERFACE;
452
453     if (SUCCEEDED(hr) && !pObj)
454         hr = E_OUTOFMEMORY;
455
456     *ppvOut = pObj;
457     TRACE ("(%p)->hr=0x%08x\n", This, hr);
458     return hr;
459 }
460
461 /**************************************************************************
462 *       ISF_NetworkPlaces_fnGetDisplayNameOf
463 *
464 */
465 static HRESULT WINAPI ISF_NetworkPlaces_fnGetDisplayNameOf (IShellFolder2 * iface,
466                LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
467 {
468     IGenericSFImpl *This = (IGenericSFImpl *)iface;
469
470     FIXME ("(%p)->(pidl=%p,0x%08x,%p)\n", This, pidl, dwFlags, strRet);
471     pdump (pidl);
472
473     if (!strRet)
474         return E_INVALIDARG;
475
476     return E_NOTIMPL;
477 }
478
479 /**************************************************************************
480 *  ISF_NetworkPlaces_fnSetNameOf
481 *  Changes the name of a file object or subfolder, possibly changing its item
482 *  identifier in the process.
483 *
484 * PARAMETERS
485 *  hwndOwner [in]  Owner window for output
486 *  pidl      [in]  simple pidl of item to change
487 *  lpszName  [in]  the items new display name
488 *  dwFlags   [in]  SHGNO formatting flags
489 *  ppidlOut  [out] simple pidl returned
490 */
491 static HRESULT WINAPI ISF_NetworkPlaces_fnSetNameOf (IShellFolder2 * iface,
492                HWND hwndOwner, LPCITEMIDLIST pidl,      /*simple pidl */
493                LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
494 {
495     IGenericSFImpl *This = (IGenericSFImpl *)iface;
496     FIXME ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", This,
497             hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
498     return E_FAIL;
499 }
500
501 static HRESULT WINAPI ISF_NetworkPlaces_fnGetDefaultSearchGUID (
502                IShellFolder2 * iface, GUID * pguid)
503 {
504     IGenericSFImpl *This = (IGenericSFImpl *)iface;
505     FIXME ("(%p)\n", This);
506     return E_NOTIMPL;
507 }
508
509 static HRESULT WINAPI ISF_NetworkPlaces_fnEnumSearches (IShellFolder2 * iface,
510                IEnumExtraSearch ** ppenum)
511 {
512     IGenericSFImpl *This = (IGenericSFImpl *)iface;
513     FIXME ("(%p)\n", This);
514     return E_NOTIMPL;
515 }
516
517 static HRESULT WINAPI ISF_NetworkPlaces_fnGetDefaultColumn (IShellFolder2 * iface,
518                DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
519 {
520     IGenericSFImpl *This = (IGenericSFImpl *)iface;
521
522     TRACE ("(%p)\n", This);
523
524     if (pSort)
525         *pSort = 0;
526     if (pDisplay)
527         *pDisplay = 0;
528
529     return S_OK;
530 }
531
532 static HRESULT WINAPI ISF_NetworkPlaces_fnGetDefaultColumnState (
533                IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags)
534 {
535     IGenericSFImpl *This = (IGenericSFImpl *)iface;
536
537     TRACE ("(%p)\n", This);
538
539     if (!pcsFlags || iColumn >= NETWORKPLACESSHELLVIEWCOLUMNS)
540         return E_INVALIDARG;
541     *pcsFlags = NetworkPlacesSFHeader[iColumn].pcsFlags;
542     return S_OK;
543 }
544
545 static HRESULT WINAPI ISF_NetworkPlaces_fnGetDetailsEx (IShellFolder2 * iface,
546                LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
547 {
548     IGenericSFImpl *This = (IGenericSFImpl *)iface;
549     FIXME ("(%p)\n", This);
550     return E_NOTIMPL;
551 }
552
553 static HRESULT WINAPI ISF_NetworkPlaces_fnGetDetailsOf (IShellFolder2 * iface,
554                LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd)
555 {
556     IGenericSFImpl *This = (IGenericSFImpl *)iface;
557
558     FIXME ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd);
559
560     return E_NOTIMPL;
561 }
562
563 static HRESULT WINAPI ISF_NetworkPlaces_fnMapColumnToSCID (IShellFolder2 * iface,
564                UINT column, SHCOLUMNID * pscid)
565 {
566     IGenericSFImpl *This = (IGenericSFImpl *)iface;
567
568     FIXME ("(%p)\n", This);
569
570     return E_NOTIMPL;
571 }
572
573 static const IShellFolder2Vtbl vt_ShellFolder2 = {
574     ISF_NetworkPlaces_fnQueryInterface,
575     ISF_NetworkPlaces_fnAddRef,
576     ISF_NetworkPlaces_fnRelease,
577     ISF_NetworkPlaces_fnParseDisplayName,
578     ISF_NetworkPlaces_fnEnumObjects,
579     ISF_NetworkPlaces_fnBindToObject,
580     ISF_NetworkPlaces_fnBindToStorage,
581     ISF_NetworkPlaces_fnCompareIDs,
582     ISF_NetworkPlaces_fnCreateViewObject,
583     ISF_NetworkPlaces_fnGetAttributesOf,
584     ISF_NetworkPlaces_fnGetUIObjectOf,
585     ISF_NetworkPlaces_fnGetDisplayNameOf,
586     ISF_NetworkPlaces_fnSetNameOf,
587     /* ShellFolder2 */
588     ISF_NetworkPlaces_fnGetDefaultSearchGUID,
589     ISF_NetworkPlaces_fnEnumSearches,
590     ISF_NetworkPlaces_fnGetDefaultColumn,
591     ISF_NetworkPlaces_fnGetDefaultColumnState,
592     ISF_NetworkPlaces_fnGetDetailsEx,
593     ISF_NetworkPlaces_fnGetDetailsOf,
594     ISF_NetworkPlaces_fnMapColumnToSCID
595 };
596
597 /************************************************************************
598  *      INPFldr_PersistFolder2_QueryInterface
599  */
600 static HRESULT WINAPI INPFldr_PersistFolder2_QueryInterface (IPersistFolder2 * iface,
601                REFIID iid, LPVOID * ppvObj)
602 {
603     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
604
605     TRACE ("(%p)\n", This);
606
607     return IUnknown_QueryInterface (_IUnknown_ (This), iid, ppvObj);
608 }
609
610 /************************************************************************
611  *      INPFldr_PersistFolder2_AddRef
612  */
613 static ULONG WINAPI INPFldr_PersistFolder2_AddRef (IPersistFolder2 * iface)
614 {
615     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
616
617     TRACE ("(%p)->(count=%u)\n", This, This->ref);
618
619     return IUnknown_AddRef (_IUnknown_ (This));
620 }
621
622 /************************************************************************
623  *      ISFPersistFolder_Release
624  */
625 static ULONG WINAPI INPFldr_PersistFolder2_Release (IPersistFolder2 * iface)
626 {
627     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
628
629     TRACE ("(%p)->(count=%u)\n", This, This->ref);
630
631     return IUnknown_Release (_IUnknown_ (This));
632 }
633
634 /************************************************************************
635  *      INPFldr_PersistFolder2_GetClassID
636  */
637 static HRESULT WINAPI INPFldr_PersistFolder2_GetClassID (
638                IPersistFolder2 * iface, CLSID * lpClassId)
639 {
640     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
641
642     TRACE ("(%p)\n", This);
643
644     if (!lpClassId)
645         return E_POINTER;
646
647     *lpClassId = CLSID_NetworkPlaces;
648
649     return S_OK;
650 }
651
652 /************************************************************************
653  *      INPFldr_PersistFolder2_Initialize
654  *
655  * NOTES: it makes no sense to change the pidl
656  */
657 static HRESULT WINAPI INPFldr_PersistFolder2_Initialize (
658                IPersistFolder2 * iface, LPCITEMIDLIST pidl)
659 {
660     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
661
662     TRACE ("(%p)->(%p)\n", This, pidl);
663
664     return E_NOTIMPL;
665 }
666
667 /**************************************************************************
668  *      IPersistFolder2_fnGetCurFolder
669  */
670 static HRESULT WINAPI INPFldr_PersistFolder2_GetCurFolder (
671                IPersistFolder2 * iface, LPITEMIDLIST * pidl)
672 {
673     _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
674
675     TRACE ("(%p)->(%p)\n", This, pidl);
676
677     if (!pidl)
678         return E_POINTER;
679
680     *pidl = ILClone (This->pidlRoot);
681
682     return S_OK;
683 }
684
685 static const IPersistFolder2Vtbl vt_NP_PersistFolder2 =
686 {
687     INPFldr_PersistFolder2_QueryInterface,
688     INPFldr_PersistFolder2_AddRef,
689     INPFldr_PersistFolder2_Release,
690     INPFldr_PersistFolder2_GetClassID,
691     INPFldr_PersistFolder2_Initialize,
692     INPFldr_PersistFolder2_GetCurFolder
693 };