Sync with trunk (r48545)
[reactos.git] / dll / win32 / netshell / enumlist.c
1 #include <precomp.h>
2
3 WINE_DEFAULT_DEBUG_CHANNEL(shell);
4
5 typedef struct tagGUIDStruct
6 {
7 BYTE dummy; /* offset 01 is unknown */
8 GUID guid; /* offset 02 */
9 } GUIDStruct;
10
11 #define PT_GUID 0x1F
12
13 typedef struct tagPIDLDATA
14 {
15 BYTE type; /*00*/
16 union
17 {
18 struct tagGUIDStruct guid;
19 struct tagVALUEStruct value;
20 }u;
21 } PIDLDATA, *LPPIDLDATA;
22
23 typedef struct tagENUMLIST
24 {
25 struct tagENUMLIST *pNext;
26 LPITEMIDLIST pidl;
27
28 }ENUMLIST, *LPENUMLIST;
29
30 typedef struct
31 {
32 const IEnumIDListVtbl *lpVtbl;
33 LONG ref;
34 LPENUMLIST mpFirst;
35 LPENUMLIST mpLast;
36 LPENUMLIST mpCurrent;
37
38 } IEnumIDListImpl;
39
40 /**************************************************************************
41 * AddToEnumList()
42 */
43 BOOL
44 AddToEnumList(
45 IEnumIDList * iface,
46 LPITEMIDLIST pidl)
47 {
48 LPENUMLIST pNew;
49 IEnumIDListImpl *This = (IEnumIDListImpl *)iface;
50
51
52 if (!iface || !pidl)
53 return FALSE;
54
55 pNew = (LPENUMLIST)SHAlloc(sizeof(ENUMLIST));
56 if(pNew)
57 {
58 pNew->pNext = NULL;
59 pNew->pidl = pidl;
60
61 if(!This->mpFirst)
62 {
63 This->mpFirst = pNew;
64 This->mpCurrent = pNew;
65 }
66
67 if(This->mpLast)
68 {
69 /*add the new item to the end of the list */
70 This->mpLast->pNext = pNew;
71 }
72
73 /*update the last item pointer */
74 This->mpLast = pNew;
75 return TRUE;
76 }
77 return FALSE;
78 }
79
80 static
81 HRESULT
82 WINAPI
83 IEnumIDList_fnQueryInterface(
84 IEnumIDList * iface,
85 REFIID riid,
86 LPVOID *ppvObj)
87 {
88 IEnumIDListImpl *This = (IEnumIDListImpl *)iface;
89
90 *ppvObj = NULL;
91
92 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IEnumIDList))
93 {
94 *ppvObj = This;
95 IEnumIDList_AddRef((IEnumIDList*)*ppvObj);
96 return S_OK;
97 }
98
99 return E_NOINTERFACE;
100 }
101
102 static
103 ULONG
104 WINAPI
105 IEnumIDList_fnAddRef(
106 IEnumIDList * iface)
107 {
108 IEnumIDListImpl *This = (IEnumIDListImpl *)iface;
109 ULONG refCount = InterlockedIncrement(&This->ref);
110
111 return refCount;
112 }
113
114 static
115 ULONG
116 WINAPI IEnumIDList_fnRelease(
117 IEnumIDList * iface)
118 {
119 LPENUMLIST pDelete;
120 IEnumIDListImpl *This = (IEnumIDListImpl *)iface;
121 ULONG refCount = InterlockedDecrement(&This->ref);
122
123 if (!refCount)
124 {
125 while(This->mpFirst)
126 {
127 pDelete = This->mpFirst;
128 This->mpFirst = pDelete->pNext;
129 SHFree(pDelete->pidl);
130 SHFree(pDelete);
131 }
132 CoTaskMemFree(This);
133 }
134 return refCount;
135 }
136
137 static
138 HRESULT
139 WINAPI
140 IEnumIDList_fnNext(
141 IEnumIDList * iface,
142 ULONG celt,
143 LPITEMIDLIST * rgelt,
144 ULONG *pceltFetched)
145 {
146 IEnumIDListImpl *This = (IEnumIDListImpl *)iface;
147
148 ULONG i;
149 HRESULT hr = S_OK;
150 LPITEMIDLIST temp;
151
152 if(pceltFetched)
153 *pceltFetched = 0;
154
155 *rgelt=0;
156
157 if(celt > 1 && !pceltFetched)
158 {
159 return E_INVALIDARG;
160 }
161
162 if(celt > 0 && !This->mpCurrent)
163 {
164 return S_FALSE;
165 }
166
167 for(i = 0; i < celt; i++)
168 {
169 if(!(This->mpCurrent))
170 break;
171
172 temp = ILClone(This->mpCurrent->pidl);
173 rgelt[i] = temp;
174 This->mpCurrent = This->mpCurrent->pNext;
175 }
176
177 if(pceltFetched)
178 {
179 *pceltFetched = i;
180 }
181
182 return hr;
183 }
184
185 static
186 HRESULT
187 WINAPI
188 IEnumIDList_fnSkip(
189 IEnumIDList * iface,ULONG celt)
190 {
191 IEnumIDListImpl *This = (IEnumIDListImpl *)iface;
192
193 DWORD dwIndex;
194 HRESULT hr = S_OK;
195
196 for(dwIndex = 0; dwIndex < celt; dwIndex++)
197 {
198 if(!This->mpCurrent)
199 {
200 hr = S_FALSE;
201 break;
202 }
203 This->mpCurrent = This->mpCurrent->pNext;
204 }
205 return hr;
206 }
207
208 static
209 HRESULT
210 WINAPI
211 IEnumIDList_fnReset(
212 IEnumIDList * iface)
213 {
214 IEnumIDListImpl *This = (IEnumIDListImpl *)iface;
215
216 This->mpCurrent = This->mpFirst;
217 return S_OK;
218 }
219
220 static
221 HRESULT
222 WINAPI
223 IEnumIDList_fnClone(
224 IEnumIDList * iface,
225 LPENUMIDLIST * ppenum)
226 {
227 //IEnumIDListImpl *This = (IEnumIDListImpl *)iface;
228
229 return E_NOTIMPL;
230 }
231
232 static const IEnumIDListVtbl eidlvt =
233 {
234 IEnumIDList_fnQueryInterface,
235 IEnumIDList_fnAddRef,
236 IEnumIDList_fnRelease,
237 IEnumIDList_fnNext,
238 IEnumIDList_fnSkip,
239 IEnumIDList_fnReset,
240 IEnumIDList_fnClone,
241 };
242
243 IEnumIDList * IEnumIDList_Constructor(void)
244 {
245 IEnumIDListImpl *lpeidl = CoTaskMemAlloc(sizeof(IEnumIDListImpl));
246
247 if (lpeidl)
248 {
249 lpeidl->ref = 1;
250 lpeidl->lpVtbl = &eidlvt;
251 lpeidl->mpCurrent = NULL;
252 lpeidl->mpLast = NULL;
253 lpeidl->mpFirst = NULL;
254 }
255
256 return (IEnumIDList*)lpeidl;
257 }
258
259 LPPIDLDATA _ILGetDataPointer(LPCITEMIDLIST pidl)
260 {
261 if(pidl && pidl->mkid.cb != 0x00)
262 return (LPPIDLDATA) &(pidl->mkid.abID);
263 return NULL;
264 }
265
266 LPITEMIDLIST _ILAlloc(BYTE type, unsigned int size)
267 {
268 LPITEMIDLIST pidlOut = NULL;
269
270 pidlOut = SHAlloc(size + 5);
271 if(pidlOut)
272 {
273 LPPIDLDATA pData;
274
275 ZeroMemory(pidlOut, size + 5);
276 pidlOut->mkid.cb = size + 3;
277 pData = _ILGetDataPointer(pidlOut);
278 if (pData)
279 pData->type = type;
280
281 }
282
283 return pidlOut;
284 }
285
286 LPITEMIDLIST _ILCreateNetConnect()
287 {
288 LPITEMIDLIST pidlOut;
289
290 pidlOut = _ILAlloc(PT_GUID, sizeof(PIDLDATA));
291 if (pidlOut)
292 {
293 LPPIDLDATA pData = _ILGetDataPointer(pidlOut);
294
295 memcpy(&(pData->u.guid.guid), &CLSID_NetworkConnections, sizeof(GUID));
296 }
297 return pidlOut;
298 }
299
300 IID* _ILGetGUIDPointer(LPCITEMIDLIST pidl)
301 {
302 LPPIDLDATA pdata =_ILGetDataPointer(pidl);
303
304 if (!pdata)
305 return NULL;
306
307 if (pdata->type != PT_GUID)
308 return NULL;
309 else
310 return &(pdata->u.guid.guid);
311
312 }
313
314 BOOL _ILIsNetConnect(LPCITEMIDLIST pidl)
315 {
316 REFIID iid = _ILGetGUIDPointer(pidl);
317
318 if (iid)
319 return IsEqualIID(iid, &CLSID_NetworkConnections);
320 return FALSE;
321 }
322
323 LPITEMIDLIST ILCreateNetConnectItem(INetConnection * pItem)
324 {
325 LPITEMIDLIST pidl;
326 LPPIDLDATA pdata;
327
328 pidl = _ILAlloc(0x99, sizeof(PIDLDATA));
329 pdata = _ILGetDataPointer(pidl);
330 pdata->u.value.pItem = (PVOID)pItem;
331
332 return pidl;
333 }
334
335 VALUEStruct * _ILGetValueStruct(LPCITEMIDLIST pidl)
336 {
337 LPPIDLDATA pdata = _ILGetDataPointer(pidl);
338
339 if (pdata && pdata->type==0x99)
340 return (VALUEStruct*)&(pdata->u.value);
341
342 return NULL;
343 }