18d47872eSGiannis Adamopoulos /*
28d47872eSGiannis Adamopoulos * PROJECT: ReactOS Shell
38d47872eSGiannis Adamopoulos * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
48d47872eSGiannis Adamopoulos * PURPOSE: CNetworkConnections Shell Folder items enumerator
58d47872eSGiannis Adamopoulos * COPYRIGHT: Copyright 2008 Johannes Anderwald (johannes.anderwald@reactos.org)
68d47872eSGiannis Adamopoulos */
78d47872eSGiannis Adamopoulos
8c2c66affSColin Finck #include "precomp.h"
9c2c66affSColin Finck
ILGetConnData(PCITEMID_CHILD pidl)1021a5a559SGiannis Adamopoulos PNETCONIDSTRUCT ILGetConnData(PCITEMID_CHILD pidl)
11c73d8c64SGiannis Adamopoulos {
12*ea608909SWhindmar Saksit if (pidl && pidl->mkid.cb >= 2 + sizeof(NETCONIDSTRUCT))
13*ea608909SWhindmar Saksit {
14*ea608909SWhindmar Saksit PNETCONIDSTRUCT pData = (PNETCONIDSTRUCT)pidl->mkid.abID;
15*ea608909SWhindmar Saksit if (pData->Signature == NETCONIDSTRUCT_SIG)
16*ea608909SWhindmar Saksit return pData;
17*ea608909SWhindmar Saksit }
1821a5a559SGiannis Adamopoulos return NULL;
1921a5a559SGiannis Adamopoulos }
20c73d8c64SGiannis Adamopoulos
ILGetConnName(PCITEMID_CHILD pidl)2121a5a559SGiannis Adamopoulos PWCHAR ILGetConnName(PCITEMID_CHILD pidl)
2221a5a559SGiannis Adamopoulos {
2321a5a559SGiannis Adamopoulos PNETCONIDSTRUCT pdata = ILGetConnData(pidl);
2421a5a559SGiannis Adamopoulos if (!pdata)
2521a5a559SGiannis Adamopoulos return NULL;
2621a5a559SGiannis Adamopoulos return (PWCHAR)&pidl->mkid.abID[pdata->uNameOffset];
2721a5a559SGiannis Adamopoulos }
28c73d8c64SGiannis Adamopoulos
ILGetDeviceName(PCITEMID_CHILD pidl)2921a5a559SGiannis Adamopoulos PWCHAR ILGetDeviceName(PCITEMID_CHILD pidl)
30c73d8c64SGiannis Adamopoulos {
3121a5a559SGiannis Adamopoulos PNETCONIDSTRUCT pdata = ILGetConnData(pidl);
3221a5a559SGiannis Adamopoulos if (!pdata)
3321a5a559SGiannis Adamopoulos return NULL;
3421a5a559SGiannis Adamopoulos return (PWCHAR)&pidl->mkid.abID[pdata->uDeviceNameOffset];
3521a5a559SGiannis Adamopoulos }
3621a5a559SGiannis Adamopoulos
ILCreateNetConnectItem(INetConnection * pItem)3721a5a559SGiannis Adamopoulos PITEMID_CHILD ILCreateNetConnectItem(INetConnection * pItem)
38c73d8c64SGiannis Adamopoulos {
3921a5a559SGiannis Adamopoulos PITEMID_CHILD pidl;
4021a5a559SGiannis Adamopoulos ULONG_PTR size;
4121a5a559SGiannis Adamopoulos NETCON_PROPERTIES * pProperties;
4221a5a559SGiannis Adamopoulos PNETCONIDSTRUCT pnetid;
4321a5a559SGiannis Adamopoulos PWCHAR pwchName;
4421a5a559SGiannis Adamopoulos
4521a5a559SGiannis Adamopoulos if (pItem->GetProperties(&pProperties) != S_OK)
4621a5a559SGiannis Adamopoulos return NULL;
4721a5a559SGiannis Adamopoulos
4821a5a559SGiannis Adamopoulos size = sizeof(WORD); /* nr of bytes in this item */
4921a5a559SGiannis Adamopoulos size += sizeof(NETCONIDSTRUCT);
5021a5a559SGiannis Adamopoulos size += (wcslen(pProperties->pszwName) + 1) * sizeof(WCHAR);
5121a5a559SGiannis Adamopoulos size += (wcslen(pProperties->pszwDeviceName) + 1) * sizeof(WCHAR);
5221a5a559SGiannis Adamopoulos
5321a5a559SGiannis Adamopoulos /* Allocate enough memory for the trailing id which will indicate that this is a simple id */
5421a5a559SGiannis Adamopoulos pidl = static_cast<LPITEMIDLIST>(SHAlloc(size + sizeof(SHITEMID)));
55*ea608909SWhindmar Saksit if (!pidl)
56*ea608909SWhindmar Saksit goto end;
5721a5a559SGiannis Adamopoulos pidl->mkid.cb = (WORD)size;
58*ea608909SWhindmar Saksit ((PNETCONIDSTRUCT)(pidl->mkid.abID))->Signature = NETCONIDSTRUCT_SIG;
5921a5a559SGiannis Adamopoulos
6021a5a559SGiannis Adamopoulos /* Copy the connection properties */
6121a5a559SGiannis Adamopoulos pnetid = ILGetConnData(pidl);
62*ea608909SWhindmar Saksit memset(pnetid->Unknown, 0, sizeof(pnetid->Unknown));
63*ea608909SWhindmar Saksit pnetid->clsidThisObject = pProperties->clsidThisObject;
6421a5a559SGiannis Adamopoulos pnetid->guidId = pProperties->guidId;
6521a5a559SGiannis Adamopoulos pnetid->Status = pProperties->Status;
6621a5a559SGiannis Adamopoulos pnetid->MediaType = pProperties->MediaType;
6721a5a559SGiannis Adamopoulos pnetid->dwCharacter = pProperties->dwCharacter;
6821a5a559SGiannis Adamopoulos pnetid->uNameOffset = sizeof(NETCONIDSTRUCT);
69*ea608909SWhindmar Saksit pnetid->uDeviceNameOffset = ULONG(pnetid->uNameOffset + (wcslen(pProperties->pszwName) + 1) * sizeof(WCHAR));
7021a5a559SGiannis Adamopoulos
7121a5a559SGiannis Adamopoulos pwchName = ILGetConnName(pidl);
7221a5a559SGiannis Adamopoulos wcscpy(pwchName, pProperties->pszwName);
7321a5a559SGiannis Adamopoulos
7421a5a559SGiannis Adamopoulos pwchName = ILGetDeviceName(pidl);
7521a5a559SGiannis Adamopoulos wcscpy(pwchName, pProperties->pszwDeviceName);
7621a5a559SGiannis Adamopoulos
7721a5a559SGiannis Adamopoulos /* Set the trailing id to null */
7821a5a559SGiannis Adamopoulos memset((void*)((ULONG_PTR)pidl + size), 0, sizeof(SHITEMID));
79*ea608909SWhindmar Saksit end:
8021a5a559SGiannis Adamopoulos NcFreeNetconProperties(pProperties);
8121a5a559SGiannis Adamopoulos
8221a5a559SGiannis Adamopoulos return pidl;
8321a5a559SGiannis Adamopoulos }
8421a5a559SGiannis Adamopoulos
ILGetConnection(PCITEMID_CHILD pidl,INetConnection ** pItem)8521a5a559SGiannis Adamopoulos HRESULT ILGetConnection(PCITEMID_CHILD pidl, INetConnection ** pItem)
8621a5a559SGiannis Adamopoulos {
8721a5a559SGiannis Adamopoulos HRESULT hr;
8821a5a559SGiannis Adamopoulos CComPtr<INetConnectionManager> pNetConMan;
8921a5a559SGiannis Adamopoulos CComPtr<IEnumNetConnection> pEnumCon;
9021a5a559SGiannis Adamopoulos CComPtr<INetConnection> INetCon;
9121a5a559SGiannis Adamopoulos ULONG Count;
9221a5a559SGiannis Adamopoulos NETCON_PROPERTIES * pProperties;
9321a5a559SGiannis Adamopoulos
9421a5a559SGiannis Adamopoulos PNETCONIDSTRUCT pdata = ILGetConnData(pidl);
9521a5a559SGiannis Adamopoulos if (!pdata)
9621a5a559SGiannis Adamopoulos return E_FAIL;
9721a5a559SGiannis Adamopoulos
9821a5a559SGiannis Adamopoulos /* get an instance to of IConnectionManager */
9921a5a559SGiannis Adamopoulos hr = CNetConnectionManager_CreateInstance(IID_PPV_ARG(INetConnectionManager, &pNetConMan));
10021a5a559SGiannis Adamopoulos if (FAILED_UNEXPECTEDLY(hr))
10121a5a559SGiannis Adamopoulos return hr;
10221a5a559SGiannis Adamopoulos
10321a5a559SGiannis Adamopoulos hr = pNetConMan->EnumConnections(NCME_DEFAULT, &pEnumCon);
10421a5a559SGiannis Adamopoulos if (FAILED_UNEXPECTEDLY(hr))
10521a5a559SGiannis Adamopoulos return hr;
10621a5a559SGiannis Adamopoulos
10721a5a559SGiannis Adamopoulos while (TRUE)
10821a5a559SGiannis Adamopoulos {
10921a5a559SGiannis Adamopoulos hr = pEnumCon->Next(1, &INetCon, &Count);
11021a5a559SGiannis Adamopoulos if (hr != S_OK)
11121a5a559SGiannis Adamopoulos return E_FAIL;
11221a5a559SGiannis Adamopoulos
11321a5a559SGiannis Adamopoulos hr = INetCon->GetProperties(&pProperties);
11421a5a559SGiannis Adamopoulos if (FAILED_UNEXPECTEDLY(hr))
11521a5a559SGiannis Adamopoulos continue;
11621a5a559SGiannis Adamopoulos
11721a5a559SGiannis Adamopoulos BOOL bSame = !memcmp(&pProperties->guidId, &pdata->guidId, sizeof(GUID));
11821a5a559SGiannis Adamopoulos
11921a5a559SGiannis Adamopoulos NcFreeNetconProperties(pProperties);
12021a5a559SGiannis Adamopoulos
12121a5a559SGiannis Adamopoulos if (bSame)
12221a5a559SGiannis Adamopoulos {
12321a5a559SGiannis Adamopoulos *pItem = INetCon.Detach();
12421a5a559SGiannis Adamopoulos return S_OK;
12521a5a559SGiannis Adamopoulos }
12621a5a559SGiannis Adamopoulos }
12721a5a559SGiannis Adamopoulos
12821a5a559SGiannis Adamopoulos return E_FAIL;
12921a5a559SGiannis Adamopoulos }
130c73d8c64SGiannis Adamopoulos
131c73d8c64SGiannis Adamopoulos typedef struct tagENUMLIST
132c73d8c64SGiannis Adamopoulos {
133c73d8c64SGiannis Adamopoulos struct tagENUMLIST *pNext;
134c73d8c64SGiannis Adamopoulos PITEMID_CHILD pidl;
135c73d8c64SGiannis Adamopoulos } ENUMLIST, *LPENUMLIST;
136c73d8c64SGiannis Adamopoulos
137c73d8c64SGiannis Adamopoulos class CEnumIDList:
138c73d8c64SGiannis Adamopoulos public CComObjectRootEx<CComMultiThreadModelNoCS>,
139c73d8c64SGiannis Adamopoulos public IEnumIDList
140c73d8c64SGiannis Adamopoulos {
141c73d8c64SGiannis Adamopoulos public:
142c73d8c64SGiannis Adamopoulos CEnumIDList();
143c73d8c64SGiannis Adamopoulos ~CEnumIDList();
144c73d8c64SGiannis Adamopoulos
145c73d8c64SGiannis Adamopoulos HRESULT Initialize();
146c73d8c64SGiannis Adamopoulos
147c73d8c64SGiannis Adamopoulos // IEnumIDList
148b2d56cf3SKatayama Hirofumi MZ STDMETHOD(Next)(ULONG celt, PITEMID_CHILD *rgelt, ULONG *pceltFetched) override;
149b2d56cf3SKatayama Hirofumi MZ STDMETHOD(Skip)(ULONG celt) override;
150b2d56cf3SKatayama Hirofumi MZ STDMETHOD(Reset)() override;
151b2d56cf3SKatayama Hirofumi MZ STDMETHOD(Clone)(IEnumIDList **ppenum) override;
152c73d8c64SGiannis Adamopoulos
153c73d8c64SGiannis Adamopoulos private:
154c73d8c64SGiannis Adamopoulos BOOL AddToEnumList(PITEMID_CHILD pidl);
155c73d8c64SGiannis Adamopoulos
156c73d8c64SGiannis Adamopoulos LPENUMLIST m_pFirst;
157c73d8c64SGiannis Adamopoulos LPENUMLIST m_pLast;
158c73d8c64SGiannis Adamopoulos LPENUMLIST m_pCurrent;
159c73d8c64SGiannis Adamopoulos
160c73d8c64SGiannis Adamopoulos public:
161c73d8c64SGiannis Adamopoulos DECLARE_NOT_AGGREGATABLE(CEnumIDList)
162c73d8c64SGiannis Adamopoulos DECLARE_PROTECT_FINAL_CONSTRUCT()
163c73d8c64SGiannis Adamopoulos
164c73d8c64SGiannis Adamopoulos BEGIN_COM_MAP(CEnumIDList)
165c73d8c64SGiannis Adamopoulos COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
166c73d8c64SGiannis Adamopoulos END_COM_MAP()
167c73d8c64SGiannis Adamopoulos };
168c73d8c64SGiannis Adamopoulos
169c2c66affSColin Finck /**************************************************************************
170c2c66affSColin Finck * AddToEnumList()
171c2c66affSColin Finck */
172c2c66affSColin Finck BOOL
AddToEnumList(PITEMID_CHILD pidl)173c2c66affSColin Finck CEnumIDList::AddToEnumList(PITEMID_CHILD pidl)
174c2c66affSColin Finck {
175c2c66affSColin Finck LPENUMLIST pNew;
176c2c66affSColin Finck
177c2c66affSColin Finck if (!pidl)
178c2c66affSColin Finck return FALSE;
179c2c66affSColin Finck
180c2c66affSColin Finck pNew = static_cast<LPENUMLIST>(SHAlloc(sizeof(ENUMLIST)));
181c2c66affSColin Finck if (pNew)
182c2c66affSColin Finck {
183c2c66affSColin Finck pNew->pNext = NULL;
184c2c66affSColin Finck pNew->pidl = pidl;
185c2c66affSColin Finck
186c2c66affSColin Finck if (!m_pFirst)
187c2c66affSColin Finck {
188c2c66affSColin Finck m_pFirst = pNew;
189c2c66affSColin Finck m_pCurrent = pNew;
190c2c66affSColin Finck }
191c2c66affSColin Finck
192c2c66affSColin Finck if (m_pLast)
193c2c66affSColin Finck {
194c2c66affSColin Finck /*add the new item to the end of the list */
195c2c66affSColin Finck m_pLast->pNext = pNew;
196c2c66affSColin Finck }
197c2c66affSColin Finck
198c2c66affSColin Finck /*update the last item pointer */
199c2c66affSColin Finck m_pLast = pNew;
200c2c66affSColin Finck return TRUE;
201c2c66affSColin Finck }
202c2c66affSColin Finck return FALSE;
203c2c66affSColin Finck }
204c2c66affSColin Finck
CEnumIDList()205c2c66affSColin Finck CEnumIDList::CEnumIDList() :
206c2c66affSColin Finck m_pFirst(NULL),
207c2c66affSColin Finck m_pLast(NULL),
208c2c66affSColin Finck m_pCurrent(NULL)
209c2c66affSColin Finck {
210c2c66affSColin Finck }
211c2c66affSColin Finck
~CEnumIDList()212c2c66affSColin Finck CEnumIDList::~CEnumIDList()
213c2c66affSColin Finck {
214c2c66affSColin Finck LPENUMLIST pDelete;
215c2c66affSColin Finck
216c2c66affSColin Finck while (m_pFirst)
217c2c66affSColin Finck {
218c2c66affSColin Finck pDelete = m_pFirst;
219c2c66affSColin Finck m_pFirst = pDelete->pNext;
220c2c66affSColin Finck SHFree(pDelete->pidl);
221c2c66affSColin Finck SHFree(pDelete);
222c2c66affSColin Finck }
223c2c66affSColin Finck }
224c2c66affSColin Finck
225c2c66affSColin Finck HRESULT
Initialize()226c73d8c64SGiannis Adamopoulos CEnumIDList::Initialize()
227c2c66affSColin Finck {
228c73d8c64SGiannis Adamopoulos HRESULT hr;
229769b102eSGiannis Adamopoulos CComPtr<INetConnectionManager> pNetConMan;
230769b102eSGiannis Adamopoulos CComPtr<IEnumNetConnection> pEnumCon;
231c73d8c64SGiannis Adamopoulos ULONG Count;
232c73d8c64SGiannis Adamopoulos PITEMID_CHILD pidl;
233c2c66affSColin Finck
234c73d8c64SGiannis Adamopoulos /* get an instance to of IConnectionManager */
235769b102eSGiannis Adamopoulos hr = CNetConnectionManager_CreateInstance(IID_PPV_ARG(INetConnectionManager, &pNetConMan));
236769b102eSGiannis Adamopoulos if (FAILED_UNEXPECTEDLY(hr))
237c73d8c64SGiannis Adamopoulos return S_OK;
238c73d8c64SGiannis Adamopoulos
239c73d8c64SGiannis Adamopoulos hr = pNetConMan->EnumConnections(NCME_DEFAULT, &pEnumCon);
240769b102eSGiannis Adamopoulos if (FAILED_UNEXPECTEDLY(hr))
241c2c66affSColin Finck return S_OK;
242c2c66affSColin Finck
243769b102eSGiannis Adamopoulos while (TRUE)
244c2c66affSColin Finck {
245769b102eSGiannis Adamopoulos CComPtr<INetConnection> INetCon;
246769b102eSGiannis Adamopoulos
247c73d8c64SGiannis Adamopoulos hr = pEnumCon->Next(1, &INetCon, &Count);
248769b102eSGiannis Adamopoulos if (hr != S_OK)
249769b102eSGiannis Adamopoulos break;
250769b102eSGiannis Adamopoulos
251c73d8c64SGiannis Adamopoulos pidl = ILCreateNetConnectItem(INetCon);
252c73d8c64SGiannis Adamopoulos if (pidl)
253c73d8c64SGiannis Adamopoulos {
254c73d8c64SGiannis Adamopoulos AddToEnumList(pidl);
255c73d8c64SGiannis Adamopoulos }
256c73d8c64SGiannis Adamopoulos }
257c2c66affSColin Finck
258c73d8c64SGiannis Adamopoulos return S_OK;
259c2c66affSColin Finck }
260c2c66affSColin Finck
261c2c66affSColin Finck HRESULT
262c2c66affSColin Finck WINAPI
Next(ULONG celt,PITEMID_CHILD * rgelt,ULONG * pceltFetched)263c2c66affSColin Finck CEnumIDList::Next(
264c2c66affSColin Finck ULONG celt,
265c2c66affSColin Finck PITEMID_CHILD *rgelt,
266c2c66affSColin Finck ULONG *pceltFetched)
267c2c66affSColin Finck {
268c2c66affSColin Finck ULONG i;
269c2c66affSColin Finck HRESULT hr = S_OK;
270c2c66affSColin Finck PITEMID_CHILD temp;
271c2c66affSColin Finck
272c2c66affSColin Finck if (pceltFetched)
273c2c66affSColin Finck *pceltFetched = 0;
274c2c66affSColin Finck
275c2c66affSColin Finck if (celt > 1 && !pceltFetched)
276c2c66affSColin Finck {
277c2c66affSColin Finck return E_INVALIDARG;
278c2c66affSColin Finck }
279c2c66affSColin Finck
280c2c66affSColin Finck if (celt > 0 && !m_pCurrent)
281c2c66affSColin Finck {
282c2c66affSColin Finck return S_FALSE;
283c2c66affSColin Finck }
284c2c66affSColin Finck
285c2c66affSColin Finck for (i = 0; i < celt; i++)
286c2c66affSColin Finck {
287c2c66affSColin Finck if (!m_pCurrent)
288f283a3f9SWhindmar Saksit {
289f283a3f9SWhindmar Saksit hr = S_FALSE;
290c2c66affSColin Finck break;
291f283a3f9SWhindmar Saksit }
292c2c66affSColin Finck
293c2c66affSColin Finck temp = ILClone(m_pCurrent->pidl);
294f283a3f9SWhindmar Saksit if (!temp)
295f283a3f9SWhindmar Saksit {
296f283a3f9SWhindmar Saksit hr = i ? S_FALSE : E_OUTOFMEMORY;
297f283a3f9SWhindmar Saksit break;
298f283a3f9SWhindmar Saksit }
299c2c66affSColin Finck rgelt[i] = temp;
300c2c66affSColin Finck m_pCurrent = m_pCurrent->pNext;
301c2c66affSColin Finck }
302c2c66affSColin Finck
303c2c66affSColin Finck if (pceltFetched)
304c2c66affSColin Finck *pceltFetched = i;
305c2c66affSColin Finck
306c2c66affSColin Finck return hr;
307c2c66affSColin Finck }
308c2c66affSColin Finck
309c2c66affSColin Finck HRESULT
310c2c66affSColin Finck WINAPI
Skip(ULONG celt)311c2c66affSColin Finck CEnumIDList::Skip(ULONG celt)
312c2c66affSColin Finck {
313c2c66affSColin Finck DWORD dwIndex;
314c2c66affSColin Finck HRESULT hr = S_OK;
315c2c66affSColin Finck
316c2c66affSColin Finck for (dwIndex = 0; dwIndex < celt; dwIndex++)
317c2c66affSColin Finck {
318c2c66affSColin Finck if (!m_pCurrent)
319c2c66affSColin Finck {
320c2c66affSColin Finck hr = S_FALSE;
321c2c66affSColin Finck break;
322c2c66affSColin Finck }
323c2c66affSColin Finck m_pCurrent = m_pCurrent->pNext;
324c2c66affSColin Finck }
325c2c66affSColin Finck
326c2c66affSColin Finck return hr;
327c2c66affSColin Finck }
328c2c66affSColin Finck
329c2c66affSColin Finck HRESULT
330c2c66affSColin Finck WINAPI
Reset()331c2c66affSColin Finck CEnumIDList::Reset()
332c2c66affSColin Finck {
333c2c66affSColin Finck m_pCurrent = m_pFirst;
334c2c66affSColin Finck return S_OK;
335c2c66affSColin Finck }
336c2c66affSColin Finck
337c2c66affSColin Finck HRESULT
338c2c66affSColin Finck WINAPI
Clone(LPENUMIDLIST * ppenum)339c2c66affSColin Finck CEnumIDList::Clone(
340c2c66affSColin Finck LPENUMIDLIST * ppenum)
341c2c66affSColin Finck {
342c2c66affSColin Finck return E_NOTIMPL;
343c2c66affSColin Finck }
344c2c66affSColin Finck
CEnumIDList_CreateInstance(HWND hwndOwner,DWORD dwFlags,REFIID riid,LPVOID * ppv)345c73d8c64SGiannis Adamopoulos HRESULT CEnumIDList_CreateInstance(HWND hwndOwner, DWORD dwFlags, REFIID riid, LPVOID * ppv)
346c73d8c64SGiannis Adamopoulos {
347c73d8c64SGiannis Adamopoulos return ShellObjectCreatorInit<CEnumIDList>(riid, ppv);
348c73d8c64SGiannis Adamopoulos }
349