2 * Network Places (Neighbourhood) folder
4 * Copyright 1997 Marcus Meissner
5 * Copyright 1998, 1999, 2002 Juergen Schmied
6 * Copyright 2003 Mike McCormack for Codeweavers
7 * Copyright 2009 Andrew Hill
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 WINE_DEFAULT_DEBUG_CHANNEL (shell
);
28 #define HACKY_UNC_PATHS
30 /***********************************************************************
31 * IShellFolder implementation
34 static shvheader NetworkPlacesSFHeader
[] = {
35 {IDS_SHV_COLUMN8
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 15},
36 {IDS_SHV_COLUMN13
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 10},
37 {IDS_SHV_COLUMN_WORKGROUP
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 15},
38 {IDS_SHV_NETWORKLOCATION
, SHCOLSTATE_TYPE_STR
| SHCOLSTATE_ONBYDEFAULT
, LVCFMT_RIGHT
, 15}
42 #define COLUMN_CATEGORY 1
43 #define COLUMN_WORKGROUP 2
44 #define COLUMN_NETLOCATION 3
46 #define NETWORKPLACESSHELLVIEWCOLUMNS 4
48 CNetFolder::CNetFolder()
53 CNetFolder::~CNetFolder()
55 TRACE("-- destroying IShellFolder(%p)\n", this);
59 HRESULT WINAPI
CNetFolder::FinalConstruct()
61 pidlRoot
= _ILCreateGuid(PT_GUID
, CLSID_NetworkPlaces
); /* my qualified pidl */
67 /**************************************************************************
68 * CNetFolder::ParseDisplayName
70 HRESULT WINAPI
CNetFolder::ParseDisplayName(HWND hwndOwner
, LPBC pbcReserved
, LPOLESTR lpszDisplayName
,
71 DWORD
*pchEaten
, PIDLIST_RELATIVE
*ppidl
, DWORD
*pdwAttributes
)
73 HRESULT hr
= E_UNEXPECTED
;
74 #ifdef HACKY_UNC_PATHS
75 /* FIXME: the code below is an ugly hack */
77 /* Can we use a CFSFolder on that path? */
78 DWORD attrs
= GetFileAttributes(lpszDisplayName
);
79 if ((attrs
& FILE_ATTRIBUTE_DIRECTORY
))
83 /* Create our hacky pidl */
84 int cbData
= sizeof(WORD
) + sizeof(WCHAR
) * (wcslen(lpszDisplayName
)+1);
85 LPITEMIDLIST pidl
= (LPITEMIDLIST
)SHAlloc(cbData
+ sizeof(WORD
));
89 pidl
->mkid
.cb
= cbData
;
90 wcscpy((WCHAR
*)&pidl
->mkid
.abID
[0], lpszDisplayName
);
91 *(WORD
*)((char*)pidl
+ cbData
) = 0;
95 *pdwAttributes
= SFGAO_FILESYSTEM
| SFGAO_CANLINK
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_FILESYSANCESTOR
;
100 TRACE("(%p)->(HWND=%p,%p,%p=%s,%p,pidl=%p,%p)\n", this,
101 hwndOwner
, pbcReserved
, lpszDisplayName
, debugstr_w (lpszDisplayName
),
102 pchEaten
, ppidl
, pdwAttributes
);
106 *pchEaten
= 0; /* strange but like the original */
108 TRACE("(%p)->(-- ret=0x%08x)\n", this, hr
);
113 /**************************************************************************
114 * CNetFolder::EnumObjects
116 HRESULT WINAPI
CNetFolder::EnumObjects(HWND hwndOwner
, DWORD dwFlags
, LPENUMIDLIST
*ppEnumIDList
)
118 TRACE("(%p)->(HWND=%p flags=0x%08x pplist=%p)\n", this,
119 hwndOwner
, dwFlags
, ppEnumIDList
);
121 *ppEnumIDList
= NULL
; //IEnumIDList_Constructor();
123 TRACE("-- (%p)->(new ID List: %p)\n", this, *ppEnumIDList
);
125 // return (*ppEnumIDList) ? S_OK : E_OUTOFMEMORY;
128 /**************************************************************************
129 * CNetFolder::BindToObject
131 HRESULT WINAPI
CNetFolder::BindToObject(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
133 #ifdef HACKY_UNC_PATHS
135 CComPtr
<IPersistFolder3
> ppf3
;
136 hr
= SHCoCreateInstance(NULL
, &CLSID_ShellFSFolder
, NULL
, IID_PPV_ARG(IPersistFolder3
, &ppf3
));
140 PERSIST_FOLDER_TARGET_INFO pfti
= {0};
142 wcscpy(pfti
.szTargetParsingName
, (WCHAR
*)pidl
->mkid
.abID
);
144 PCUIDLIST_RELATIVE pidlChild
= ILCloneFirst (pidl
);
146 hr
= ppf3
->InitializeEx(NULL
, ILCombine(pidlRoot
,pidlChild
), &pfti
);
150 if (_ILIsPidlSimple (pidl
))
152 return ppf3
->QueryInterface(riid
, ppvOut
);
156 CComPtr
<IShellFolder
> psf
;
157 hr
= ppf3
->QueryInterface(IID_PPV_ARG(IShellFolder
, &psf
));
161 return psf
->BindToObject(ILGetNext (pidl
), pbcReserved
, riid
, ppvOut
);
169 /**************************************************************************
170 * CNetFolder::BindToStorage
172 HRESULT WINAPI
CNetFolder::BindToStorage(PCUIDLIST_RELATIVE pidl
, LPBC pbcReserved
, REFIID riid
, LPVOID
*ppvOut
)
174 FIXME("(%p)->(pidl=%p,%p,%s,%p) stub\n", this,
175 pidl
, pbcReserved
, shdebugstr_guid (&riid
), ppvOut
);
181 /**************************************************************************
182 * CNetFolder::CompareIDs
185 HRESULT WINAPI
CNetFolder::CompareIDs(LPARAM lParam
, PCUIDLIST_RELATIVE pidl1
, PCUIDLIST_RELATIVE pidl2
)
190 /**************************************************************************
191 * CNetFolder::CreateViewObject
193 HRESULT WINAPI
CNetFolder::CreateViewObject(HWND hwndOwner
, REFIID riid
, LPVOID
*ppvOut
)
195 CComPtr
<IShellView
> pShellView
;
196 HRESULT hr
= E_INVALIDARG
;
198 TRACE("(%p)->(hwnd=%p,%s,%p)\n", this,
199 hwndOwner
, shdebugstr_guid (&riid
), ppvOut
);
206 if (IsEqualIID(riid
, IID_IDropTarget
))
208 WARN("IDropTarget not implemented\n");
211 else if (IsEqualIID(riid
, IID_IContextMenu
))
213 WARN("IContextMenu not implemented\n");
216 else if (IsEqualIID(riid
, IID_IShellView
))
218 hr
= CDefView_Constructor(this, riid
, ppvOut
);
220 TRACE("-- (%p)->(interface=%p)\n", this, ppvOut
);
224 /**************************************************************************
225 * CNetFolder::GetAttributesOf
227 HRESULT WINAPI
CNetFolder::GetAttributesOf(UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, DWORD
*rgfInOut
)
229 static const DWORD dwNethoodAttributes
=
230 SFGAO_STORAGE
| SFGAO_HASPROPSHEET
| SFGAO_STORAGEANCESTOR
|
231 SFGAO_FILESYSANCESTOR
| SFGAO_FOLDER
| SFGAO_FILESYSTEM
| SFGAO_HASSUBFOLDER
| SFGAO_CANRENAME
| SFGAO_CANDELETE
;
234 TRACE("(%p)->(cidl=%d apidl=%p mask=%p (0x%08x))\n", this,
235 cidl
, apidl
, rgfInOut
, rgfInOut
? *rgfInOut
: 0);
246 *rgfInOut
= dwNethoodAttributes
;
249 /* FIXME: Implement when enumerating items is implemented */
250 #ifdef HACKY_UNC_PATHS
251 *rgfInOut
= SFGAO_FILESYSTEM
| SFGAO_CANLINK
| SFGAO_FOLDER
| SFGAO_HASSUBFOLDER
| SFGAO_FILESYSANCESTOR
;
255 /* make sure SFGAO_VALIDATE is cleared, some apps depend on that */
256 *rgfInOut
&= ~SFGAO_VALIDATE
;
258 TRACE("-- result=0x%08x\n", *rgfInOut
);
262 /**************************************************************************
263 * CNetFolder::GetUIObjectOf
266 * hwndOwner [in] Parent window for any output
267 * cidl [in] array size
268 * apidl [in] simple pidl array
269 * riid [in] Requested Interface
270 * prgfInOut [ ] reserved
271 * ppvObject [out] Resulting Interface
274 HRESULT WINAPI
CNetFolder::GetUIObjectOf(HWND hwndOwner
, UINT cidl
, PCUITEMID_CHILD_ARRAY apidl
, REFIID riid
,
275 UINT
* prgfInOut
, LPVOID
* ppvOut
)
278 IUnknown
*pObj
= NULL
;
279 HRESULT hr
= E_INVALIDARG
;
281 TRACE("(%p)->(%p,%u,apidl=%p,%s,%p,%p)\n", this,
282 hwndOwner
, cidl
, apidl
, shdebugstr_guid (&riid
), prgfInOut
, ppvOut
);
289 if (IsEqualIID(riid
, IID_IContextMenu
) && (cidl
>= 1))
291 IContextMenu
* pCm
= NULL
;
292 hr
= CDefFolderMenu_Create2(pidlRoot
, hwndOwner
, cidl
, apidl
, static_cast<IShellFolder
*>(this), NULL
, 0, NULL
, &pCm
);
295 else if (IsEqualIID(riid
, IID_IDataObject
) && (cidl
>= 1))
297 IDataObject
* pDo
= NULL
;
298 hr
= IDataObject_Constructor (hwndOwner
, pidlRoot
, apidl
, cidl
, &pDo
);
301 else if (IsEqualIID(riid
, IID_IExtractIconA
) && (cidl
== 1))
303 pidl
= ILCombine (pidlRoot
, apidl
[0]);
304 pObj
= IExtractIconA_Constructor (pidl
);
308 else if (IsEqualIID(riid
, IID_IExtractIconW
) && (cidl
== 1))
310 pidl
= ILCombine (pidlRoot
, apidl
[0]);
311 pObj
= IExtractIconW_Constructor (pidl
);
315 else if (IsEqualIID(riid
, IID_IDropTarget
) && (cidl
>= 1))
317 IDropTarget
* pDt
= NULL
;
318 hr
= this->QueryInterface(IID_PPV_ARG(IDropTarget
, &pDt
));
324 if (SUCCEEDED(hr
) && !pObj
)
328 TRACE("(%p)->hr=0x%08x\n", this, hr
);
332 /**************************************************************************
333 * CNetFolder::GetDisplayNameOf
336 HRESULT WINAPI
CNetFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl
, DWORD dwFlags
, LPSTRRET strRet
)
340 TRACE ("(%p)->(pidl=%p,0x%08lx,%p)\n", this, pidl
, dwFlags
, strRet
);
348 pszName
= (LPWSTR
)CoTaskMemAlloc(MAX_PATH
* sizeof(WCHAR
));
350 return E_OUTOFMEMORY
;
352 if (LoadStringW(shell32_hInstance
, IDS_NETWORKPLACE
, pszName
, MAX_PATH
))
354 pszName
[MAX_PATH
-1] = L
'\0';
355 strRet
->uType
= STRRET_WSTR
;
356 strRet
->pOleStr
= pszName
;
359 CoTaskMemFree(pszName
);
362 #ifdef HACKY_UNC_PATHS
365 LPCWSTR pstr
= (LPCWSTR
)pidl
->mkid
.abID
;
366 pszName
= (LPWSTR
)CoTaskMemAlloc(MAX_PATH
* sizeof(WCHAR
));
368 return E_OUTOFMEMORY
;
370 wcscpy(pszName
, pstr
);
371 strRet
->pOleStr
= pszName
;
372 strRet
->uType
= STRRET_WSTR
;
379 /**************************************************************************
380 * CNetFolder::SetNameOf
381 * Changes the name of a file object or subfolder, possibly changing its item
382 * identifier in the process.
385 * hwndOwner [in] Owner window for output
386 * pidl [in] simple pidl of item to change
387 * lpszName [in] the items new display name
388 * dwFlags [in] SHGNO formatting flags
389 * ppidlOut [out] simple pidl returned
391 HRESULT WINAPI
CNetFolder::SetNameOf(HWND hwndOwner
, PCUITEMID_CHILD pidl
, /*simple pidl */
392 LPCOLESTR lpName
, DWORD dwFlags
, PITEMID_CHILD
*pPidlOut
)
394 FIXME("(%p)->(%p,pidl=%p,%s,%u,%p)\n", this,
395 hwndOwner
, pidl
, debugstr_w (lpName
), dwFlags
, pPidlOut
);
399 HRESULT WINAPI
CNetFolder::GetDefaultSearchGUID(GUID
*pguid
)
401 FIXME("(%p)\n", this);
405 HRESULT WINAPI
CNetFolder::EnumSearches(IEnumExtraSearch
** ppenum
)
407 FIXME("(%p)\n", this);
411 HRESULT WINAPI
CNetFolder::GetDefaultColumn (DWORD dwRes
, ULONG
*pSort
, ULONG
*pDisplay
)
413 TRACE("(%p)\n", this);
423 HRESULT WINAPI
CNetFolder::GetDefaultColumnState(UINT iColumn
, DWORD
*pcsFlags
)
425 TRACE("(%p)\n", this);
427 if (!pcsFlags
|| iColumn
>= NETWORKPLACESSHELLVIEWCOLUMNS
)
429 *pcsFlags
= NetworkPlacesSFHeader
[iColumn
].pcsFlags
;
433 HRESULT WINAPI
CNetFolder::GetDetailsEx(PCUITEMID_CHILD pidl
, const SHCOLUMNID
*pscid
, VARIANT
*pv
)
435 FIXME("(%p)\n", this);
439 HRESULT WINAPI
CNetFolder::GetDetailsOf(PCUITEMID_CHILD pidl
, UINT iColumn
, SHELLDETAILS
*psd
)
441 WCHAR buffer
[MAX_PATH
] = {0};
444 if (iColumn
>= NETWORKPLACESSHELLVIEWCOLUMNS
)
447 psd
->fmt
= NetworkPlacesSFHeader
[iColumn
].fmt
;
448 psd
->cxChar
= NetworkPlacesSFHeader
[iColumn
].cxChar
;
451 psd
->str
.uType
= STRRET_WSTR
;
452 if (LoadStringW(shell32_hInstance
, NetworkPlacesSFHeader
[iColumn
].colnameid
, buffer
, _countof(buffer
)))
453 hr
= SHStrDupW(buffer
, &psd
->str
.pOleStr
);
458 if (iColumn
== COLUMN_NAME
)
459 return GetDisplayNameOf(pidl
, SHGDN_NORMAL
, &psd
->str
);
461 FIXME("(%p)->(%p %i %p)\n", this, pidl
, iColumn
, psd
);
466 HRESULT WINAPI
CNetFolder::MapColumnToSCID(UINT column
, SHCOLUMNID
*pscid
)
468 FIXME("(%p)\n", this);
473 /************************************************************************
474 * CNetFolder::GetClassID
476 HRESULT WINAPI
CNetFolder::GetClassID(CLSID
*lpClassId
)
478 TRACE("(%p)\n", this);
483 *lpClassId
= CLSID_NetworkPlaces
;
488 /************************************************************************
489 * CNetFolder::Initialize
491 * NOTES: it makes no sense to change the pidl
493 HRESULT WINAPI
CNetFolder::Initialize(LPCITEMIDLIST pidl
)
495 TRACE("(%p)->(%p)\n", this, pidl
);
500 /**************************************************************************
501 * CNetFolder::GetCurFolder
503 HRESULT WINAPI
CNetFolder::GetCurFolder(LPITEMIDLIST
*pidl
)
505 TRACE("(%p)->(%p)\n", this, pidl
);
510 *pidl
= ILClone(pidlRoot
);