xref: /reactos/dll/shellext/netshell/enumlist.cpp (revision ea608909)
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