2 * Network Places (Neighbourhood) folder
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998, 1999, 2002 Juergen Schmied
6 * Copyright 2003 Mike McCormack for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
32 #define NONAMELESSUNION
33 #define NONAMELESSSTRUCT
41 #include "enumidlist.h"
42 #include "undocshell.h"
43 #include "shell32_main.h"
45 #include "wine/debug.h"
46 #include "wine/unicode.h"
50 WINE_DEFAULT_DEBUG_CHANNEL (shell);
52 /***********************************************************************
53 * IShellFolder implementation
57 const IShellFolder2Vtbl *lpVtbl;
59 const IPersistFolder2Vtbl *lpVtblPersistFolder2;
61 /* both paths are parsible from the desktop */
62 LPITEMIDLIST pidlRoot; /* absolute pidl */
65 static const IShellFolder2Vtbl vt_ShellFolder2;
66 static const IPersistFolder2Vtbl vt_NP_PersistFolder2;
69 #define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = \
70 (class*)(((char*)name) - FIELD_OFFSET(IGenericSFImpl, lpVtblPersistFolder2))
72 #define _IUnknown_(This) ((IUnknown*)&(This)->lpVtbl)
73 #define _IShellFolder_(This) ((IShellFolder*)&(This)->lpVtbl)
74 #define _IPersistFolder2_(This) (&(This)->lpVtblPersistFolder2)
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}
81 #define NETWORKPLACESSHELLVIEWCOLUMNS 2
83 /**************************************************************************
84 * ISF_NetworkPlaces_Constructor
86 HRESULT WINAPI ISF_NetworkPlaces_Constructor (IUnknown * pUnkOuter, REFIID riid, LPVOID * ppv)
90 TRACE ("unkOut=%p %s\n", pUnkOuter, shdebugstr_guid (riid));
95 return CLASS_E_NOAGGREGATION;
97 sf = HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof (IGenericSFImpl));
102 sf->lpVtbl = &vt_ShellFolder2;
103 sf->lpVtblPersistFolder2 = &vt_NP_PersistFolder2;
104 sf->pidlRoot = _ILCreateNetHood(); /* my qualified pidl */
106 if (FAILED (IUnknown_QueryInterface (_IUnknown_ (sf), riid, ppv)))
108 IUnknown_Release (_IUnknown_ (sf));
109 return E_NOINTERFACE;
112 TRACE ("--(%p)\n", sf);
116 /**************************************************************************
117 * ISF_NetworkPlaces_fnQueryInterface
120 * supports not IPersist/IPersistFolder
122 static HRESULT WINAPI ISF_NetworkPlaces_fnQueryInterface (IShellFolder2 *iface, REFIID riid, LPVOID *ppvObj)
124 IGenericSFImpl *This = (IGenericSFImpl *)iface;
126 TRACE ("(%p)->(%s,%p)\n", This, shdebugstr_guid (riid), ppvObj);
130 if (IsEqualIID (riid, &IID_IUnknown) ||
131 IsEqualIID (riid, &IID_IShellFolder) ||
132 IsEqualIID (riid, &IID_IShellFolder2))
136 else if (IsEqualIID (riid, &IID_IPersist) ||
137 IsEqualIID (riid, &IID_IPersistFolder) ||
138 IsEqualIID (riid, &IID_IPersistFolder2))
140 *ppvObj = _IPersistFolder2_ (This);
145 IUnknown_AddRef ((IUnknown *) (*ppvObj));
146 TRACE ("-- Interface: (%p)->(%p)\n", ppvObj, *ppvObj);
149 TRACE ("-- Interface: E_NOINTERFACE\n");
150 return E_NOINTERFACE;
153 static ULONG WINAPI ISF_NetworkPlaces_fnAddRef (IShellFolder2 * iface)
155 IGenericSFImpl *This = (IGenericSFImpl *)iface;
156 ULONG refCount = InterlockedIncrement(&This->ref);
158 TRACE ("(%p)->(count=%u)\n", This, refCount - 1);
163 static ULONG WINAPI ISF_NetworkPlaces_fnRelease (IShellFolder2 * iface)
165 IGenericSFImpl *This = (IGenericSFImpl *)iface;
166 ULONG refCount = InterlockedDecrement(&This->ref);
168 TRACE ("(%p)->(count=%u)\n", This, refCount + 1);
171 TRACE ("-- destroying IShellFolder(%p)\n", This);
172 SHFree (This->pidlRoot);
173 HeapFree (GetProcessHeap(), 0, This);
178 /**************************************************************************
179 * ISF_NetworkPlaces_fnParseDisplayName
181 static HRESULT WINAPI ISF_NetworkPlaces_fnParseDisplayName (IShellFolder2 * iface,
182 HWND hwndOwner, LPBC pbcReserved, LPOLESTR lpszDisplayName,
183 DWORD * pchEaten, LPITEMIDLIST * ppidl, DWORD * pdwAttributes)
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;
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);
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])))
204 pidlTemp = _ILCreateEntireNetwork();
211 FIXME("not implemented for %s\n", debugstr_w(lpszDisplayName));
213 if (SUCCEEDED(hr) && pidlTemp)
215 if (szNext && *szNext)
217 hr = SHELL32_ParseNextElement(iface, hwndOwner, pbcReserved,
218 &pidlTemp, (LPOLESTR) szNext, pchEaten, pdwAttributes);
222 if (pdwAttributes && *pdwAttributes)
223 hr = SHELL32_GetItemAttributes(_IShellFolder_ (This),
224 pidlTemp, pdwAttributes);
233 TRACE ("(%p)->(-- ret=0x%08x)\n", This, hr);
238 /**************************************************************************
239 * ISF_NetworkPlaces_fnEnumObjects
241 static HRESULT WINAPI ISF_NetworkPlaces_fnEnumObjects (IShellFolder2 * iface,
242 HWND hwndOwner, DWORD dwFlags, LPENUMIDLIST * ppEnumIDList)
244 IGenericSFImpl *This = (IGenericSFImpl *)iface;
246 TRACE ("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", This,
247 hwndOwner, dwFlags, ppEnumIDList);
249 *ppEnumIDList = IEnumIDList_Constructor();
251 TRACE ("-- (%p)->(new ID List: %p)\n", This, *ppEnumIDList);
253 return (*ppEnumIDList) ? S_OK : E_OUTOFMEMORY;
256 /**************************************************************************
257 * ISF_NetworkPlaces_fnBindToObject
259 static HRESULT WINAPI ISF_NetworkPlaces_fnBindToObject (IShellFolder2 * iface,
260 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
262 IGenericSFImpl *This = (IGenericSFImpl *)iface;
264 TRACE ("(%p)->(pidl=%p,%p,%s,%p)\n", This,
265 pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
267 return SHELL32_BindToChild (This->pidlRoot, NULL, pidl, riid, ppvOut);
270 /**************************************************************************
271 * ISF_NetworkPlaces_fnBindToStorage
273 static HRESULT WINAPI ISF_NetworkPlaces_fnBindToStorage (IShellFolder2 * iface,
274 LPCITEMIDLIST pidl, LPBC pbcReserved, REFIID riid, LPVOID * ppvOut)
276 IGenericSFImpl *This = (IGenericSFImpl *)iface;
278 FIXME ("(%p)->(pidl=%p,%p,%s,%p) stub\n", This,
279 pidl, pbcReserved, shdebugstr_guid (riid), ppvOut);
285 /**************************************************************************
286 * ISF_NetworkPlaces_fnCompareIDs
289 static HRESULT WINAPI ISF_NetworkPlaces_fnCompareIDs (IShellFolder2 * iface,
290 LPARAM lParam, LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
292 IGenericSFImpl *This = (IGenericSFImpl *)iface;
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);
301 /**************************************************************************
302 * ISF_NetworkPlaces_fnCreateViewObject
304 static HRESULT WINAPI ISF_NetworkPlaces_fnCreateViewObject (IShellFolder2 * iface,
305 HWND hwndOwner, REFIID riid, LPVOID * ppvOut)
307 IGenericSFImpl *This = (IGenericSFImpl *)iface;
308 LPSHELLVIEW pShellView;
309 HRESULT hr = E_INVALIDARG;
311 TRACE ("(%p)->(hwnd=%p,%s,%p)\n", This,
312 hwndOwner, shdebugstr_guid (riid), ppvOut);
319 if (IsEqualIID (riid, &IID_IDropTarget))
321 WARN ("IDropTarget not implemented\n");
324 else if (IsEqualIID (riid, &IID_IContextMenu))
326 WARN ("IContextMenu not implemented\n");
329 else if (IsEqualIID (riid, &IID_IShellView))
331 pShellView = IShellView_Constructor ((IShellFolder *) iface);
334 hr = IShellView_QueryInterface (pShellView, riid, ppvOut);
335 IShellView_Release (pShellView);
338 TRACE ("-- (%p)->(interface=%p)\n", This, ppvOut);
342 /**************************************************************************
343 * ISF_NetworkPlaces_fnGetAttributesOf
345 static HRESULT WINAPI ISF_NetworkPlaces_fnGetAttributesOf (IShellFolder2 * iface,
346 UINT cidl, LPCITEMIDLIST * apidl, DWORD * rgfInOut)
348 IGenericSFImpl *This = (IGenericSFImpl *)iface;
351 TRACE ("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", This,
352 cidl, apidl, rgfInOut, rgfInOut ? *rgfInOut : 0);
364 IShellFolder *psfParent = NULL;
365 LPCITEMIDLIST rpidl = NULL;
367 hr = SHBindToParent(This->pidlRoot, &IID_IShellFolder, (LPVOID*)&psfParent, (LPCITEMIDLIST*)&rpidl);
370 SHELL32_GetItemAttributes (psfParent, rpidl, rgfInOut);
371 IShellFolder_Release(psfParent);
376 while (cidl > 0 && *apidl)
379 SHELL32_GetItemAttributes (_IShellFolder_ (This), *apidl, rgfInOut);
385 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
386 *rgfInOut &= ~SFGAO_VALIDATE;
388 TRACE ("-- result=0x%08x\n", *rgfInOut);
392 /**************************************************************************
393 * ISF_NetworkPlaces_fnGetUIObjectOf
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
404 static HRESULT WINAPI ISF_NetworkPlaces_fnGetUIObjectOf (IShellFolder2 * iface,
405 HWND hwndOwner, UINT cidl, LPCITEMIDLIST * apidl, REFIID riid,
406 UINT * prgfInOut, LPVOID * ppvOut)
408 IGenericSFImpl *This = (IGenericSFImpl *)iface;
411 IUnknown *pObj = NULL;
412 HRESULT hr = E_INVALIDARG;
414 TRACE ("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", This,
415 hwndOwner, cidl, apidl, shdebugstr_guid (riid), prgfInOut, ppvOut);
422 if (IsEqualIID (riid, &IID_IContextMenu) && (cidl >= 1))
424 pObj = (LPUNKNOWN) ISvItemCm_Constructor ((IShellFolder *) iface, This->pidlRoot, apidl, cidl);
427 else if (IsEqualIID (riid, &IID_IDataObject) && (cidl >= 1))
429 pObj = (LPUNKNOWN) IDataObject_Constructor (hwndOwner, This->pidlRoot, apidl, cidl);
432 else if (IsEqualIID (riid, &IID_IExtractIconA) && (cidl == 1))
434 pidl = ILCombine (This->pidlRoot, apidl[0]);
435 pObj = (LPUNKNOWN) IExtractIconA_Constructor (pidl);
439 else if (IsEqualIID (riid, &IID_IExtractIconW) && (cidl == 1))
441 pidl = ILCombine (This->pidlRoot, apidl[0]);
442 pObj = (LPUNKNOWN) IExtractIconW_Constructor (pidl);
446 else if (IsEqualIID (riid, &IID_IDropTarget) && (cidl >= 1))
448 hr = IShellFolder_QueryInterface (iface, &IID_IDropTarget, (LPVOID *) & pObj);
453 if (SUCCEEDED(hr) && !pObj)
457 TRACE ("(%p)->hr=0x%08x\n", This, hr);
461 /**************************************************************************
462 * ISF_NetworkPlaces_fnGetDisplayNameOf
465 static HRESULT WINAPI ISF_NetworkPlaces_fnGetDisplayNameOf (IShellFolder2 * iface,
466 LPCITEMIDLIST pidl, DWORD dwFlags, LPSTRRET strRet)
468 IGenericSFImpl *This = (IGenericSFImpl *)iface;
470 FIXME ("(%p)->(pidl=%p,0x%08x,%p)\n", This, pidl, dwFlags, strRet);
479 /**************************************************************************
480 * ISF_NetworkPlaces_fnSetNameOf
481 * Changes the name of a file object or subfolder, possibly changing its item
482 * identifier in the process.
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
491 static HRESULT WINAPI ISF_NetworkPlaces_fnSetNameOf (IShellFolder2 * iface,
492 HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl */
493 LPCOLESTR lpName, DWORD dwFlags, LPITEMIDLIST * pPidlOut)
495 IGenericSFImpl *This = (IGenericSFImpl *)iface;
496 FIXME ("(%p)->(%p,pidl=%p,%s,%u,%p)\n", This,
497 hwndOwner, pidl, debugstr_w (lpName), dwFlags, pPidlOut);
501 static HRESULT WINAPI ISF_NetworkPlaces_fnGetDefaultSearchGUID (
502 IShellFolder2 * iface, GUID * pguid)
504 IGenericSFImpl *This = (IGenericSFImpl *)iface;
505 FIXME ("(%p)\n", This);
509 static HRESULT WINAPI ISF_NetworkPlaces_fnEnumSearches (IShellFolder2 * iface,
510 IEnumExtraSearch ** ppenum)
512 IGenericSFImpl *This = (IGenericSFImpl *)iface;
513 FIXME ("(%p)\n", This);
517 static HRESULT WINAPI ISF_NetworkPlaces_fnGetDefaultColumn (IShellFolder2 * iface,
518 DWORD dwRes, ULONG * pSort, ULONG * pDisplay)
520 IGenericSFImpl *This = (IGenericSFImpl *)iface;
522 TRACE ("(%p)\n", This);
532 static HRESULT WINAPI ISF_NetworkPlaces_fnGetDefaultColumnState (
533 IShellFolder2 * iface, UINT iColumn, DWORD * pcsFlags)
535 IGenericSFImpl *This = (IGenericSFImpl *)iface;
537 TRACE ("(%p)\n", This);
539 if (!pcsFlags || iColumn >= NETWORKPLACESSHELLVIEWCOLUMNS)
541 *pcsFlags = NetworkPlacesSFHeader[iColumn].pcsFlags;
545 static HRESULT WINAPI ISF_NetworkPlaces_fnGetDetailsEx (IShellFolder2 * iface,
546 LPCITEMIDLIST pidl, const SHCOLUMNID * pscid, VARIANT * pv)
548 IGenericSFImpl *This = (IGenericSFImpl *)iface;
549 FIXME ("(%p)\n", This);
553 static HRESULT WINAPI ISF_NetworkPlaces_fnGetDetailsOf (IShellFolder2 * iface,
554 LPCITEMIDLIST pidl, UINT iColumn, SHELLDETAILS * psd)
556 IGenericSFImpl *This = (IGenericSFImpl *)iface;
558 FIXME ("(%p)->(%p %i %p)\n", This, pidl, iColumn, psd);
563 static HRESULT WINAPI ISF_NetworkPlaces_fnMapColumnToSCID (IShellFolder2 * iface,
564 UINT column, SHCOLUMNID * pscid)
566 IGenericSFImpl *This = (IGenericSFImpl *)iface;
568 FIXME ("(%p)\n", This);
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,
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
597 /************************************************************************
598 * INPFldr_PersistFolder2_QueryInterface
600 static HRESULT WINAPI INPFldr_PersistFolder2_QueryInterface (IPersistFolder2 * iface,
601 REFIID iid, LPVOID * ppvObj)
603 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
605 TRACE ("(%p)\n", This);
607 return IUnknown_QueryInterface (_IUnknown_ (This), iid, ppvObj);
610 /************************************************************************
611 * INPFldr_PersistFolder2_AddRef
613 static ULONG WINAPI INPFldr_PersistFolder2_AddRef (IPersistFolder2 * iface)
615 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
617 TRACE ("(%p)->(count=%u)\n", This, This->ref);
619 return IUnknown_AddRef (_IUnknown_ (This));
622 /************************************************************************
623 * ISFPersistFolder_Release
625 static ULONG WINAPI INPFldr_PersistFolder2_Release (IPersistFolder2 * iface)
627 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
629 TRACE ("(%p)->(count=%u)\n", This, This->ref);
631 return IUnknown_Release (_IUnknown_ (This));
634 /************************************************************************
635 * INPFldr_PersistFolder2_GetClassID
637 static HRESULT WINAPI INPFldr_PersistFolder2_GetClassID (
638 IPersistFolder2 * iface, CLSID * lpClassId)
640 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
642 TRACE ("(%p)\n", This);
647 *lpClassId = CLSID_NetworkPlaces;
652 /************************************************************************
653 * INPFldr_PersistFolder2_Initialize
655 * NOTES: it makes no sense to change the pidl
657 static HRESULT WINAPI INPFldr_PersistFolder2_Initialize (
658 IPersistFolder2 * iface, LPCITEMIDLIST pidl)
660 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
662 TRACE ("(%p)->(%p)\n", This, pidl);
667 /**************************************************************************
668 * IPersistFolder2_fnGetCurFolder
670 static HRESULT WINAPI INPFldr_PersistFolder2_GetCurFolder (
671 IPersistFolder2 * iface, LPITEMIDLIST * pidl)
673 _ICOM_THIS_From_IPersistFolder2 (IGenericSFImpl, iface);
675 TRACE ("(%p)->(%p)\n", This, pidl);
680 *pidl = ILClone (This->pidlRoot);
685 static const IPersistFolder2Vtbl vt_NP_PersistFolder2 =
687 INPFldr_PersistFolder2_QueryInterface,
688 INPFldr_PersistFolder2_AddRef,
689 INPFldr_PersistFolder2_Release,
690 INPFldr_PersistFolder2_GetClassID,
691 INPFldr_PersistFolder2_Initialize,
692 INPFldr_PersistFolder2_GetCurFolder