msado15: Implement Dispatch functions in Fields.
[wine.git] / dlls / browseui / aclmulti.c
blob820b246a40307a7ac6b9a335e0123d864cd6bd1c
1 /*
2 * Multisource AutoComplete list
4 * Copyright 2007 Mikolaj Zalewski
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <stdarg.h>
23 #define COBJMACROS
25 #include "wine/debug.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winuser.h"
30 #include "shlwapi.h"
31 #include "winerror.h"
32 #include "objbase.h"
34 #include "shlguid.h"
35 #include "shlobj.h"
37 #include "wine/heap.h"
39 #include "browseui.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(browseui);
43 struct ACLMultiSublist {
44 IUnknown *punk;
45 IEnumString *pEnum;
46 IACList *pACL;
49 typedef struct tagACLMulti {
50 IEnumString IEnumString_iface;
51 IACList IACList_iface;
52 IObjMgr IObjMgr_iface;
53 LONG refCount;
54 INT nObjs;
55 INT currObj;
56 struct ACLMultiSublist *objs;
57 } ACLMulti;
59 static inline ACLMulti *impl_from_IEnumString(IEnumString *iface)
61 return CONTAINING_RECORD(iface, ACLMulti, IEnumString_iface);
64 static inline ACLMulti *impl_from_IACList(IACList *iface)
66 return CONTAINING_RECORD(iface, ACLMulti, IACList_iface);
69 static inline ACLMulti *impl_from_IObjMgr(IObjMgr *iface)
71 return CONTAINING_RECORD(iface, ACLMulti, IObjMgr_iface);
74 static void release_obj(struct ACLMultiSublist *obj)
76 IUnknown_Release(obj->punk);
77 if (obj->pEnum)
78 IEnumString_Release(obj->pEnum);
79 if (obj->pACL)
80 IACList_Release(obj->pACL);
83 static void ACLMulti_Destructor(ACLMulti *This)
85 int i;
86 TRACE("destroying %p\n", This);
87 for (i = 0; i < This->nObjs; i++)
88 release_obj(&This->objs[i]);
89 heap_free(This->objs);
90 heap_free(This);
91 BROWSEUI_refCount--;
94 static HRESULT WINAPI ACLMulti_QueryInterface(IEnumString *iface, REFIID iid, LPVOID *ppvOut)
96 ACLMulti *This = impl_from_IEnumString(iface);
97 *ppvOut = NULL;
99 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumString))
101 *ppvOut = &This->IEnumString_iface;
103 else if (IsEqualIID(iid, &IID_IACList))
105 *ppvOut = &This->IACList_iface;
107 else if (IsEqualIID(iid, &IID_IObjMgr))
109 *ppvOut = &This->IObjMgr_iface;
112 if (*ppvOut)
114 IEnumString_AddRef(iface);
115 return S_OK;
118 WARN("unsupported interface: %s\n", debugstr_guid(iid));
119 return E_NOINTERFACE;
122 static ULONG WINAPI ACLMulti_AddRef(IEnumString *iface)
124 ACLMulti *This = impl_from_IEnumString(iface);
125 return InterlockedIncrement(&This->refCount);
128 static ULONG WINAPI ACLMulti_Release(IEnumString *iface)
130 ACLMulti *This = impl_from_IEnumString(iface);
131 ULONG ret;
133 ret = InterlockedDecrement(&This->refCount);
134 if (ret == 0)
135 ACLMulti_Destructor(This);
136 return ret;
139 static HRESULT WINAPI ACLMulti_Next(IEnumString *iface, ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched)
141 ACLMulti *This = impl_from_IEnumString(iface);
143 TRACE("(%p, %d, %p, %p)\n", iface, celt, rgelt, pceltFetched);
144 while (This->currObj < This->nObjs)
146 if (This->objs[This->currObj].pEnum)
148 /* native browseui 6.0 also returns only one element */
149 HRESULT ret = IEnumString_Next(This->objs[This->currObj].pEnum, 1, rgelt, pceltFetched);
150 if (ret != S_FALSE)
151 return ret;
153 This->currObj++;
156 if (pceltFetched)
157 *pceltFetched = 0;
158 *rgelt = NULL;
159 return S_FALSE;
162 static HRESULT WINAPI ACLMulti_Reset(IEnumString *iface)
164 ACLMulti *This = impl_from_IEnumString(iface);
165 int i;
167 This->currObj = 0;
168 for (i = 0; i < This->nObjs; i++)
170 if (This->objs[i].pEnum)
171 IEnumString_Reset(This->objs[i].pEnum);
173 return S_OK;
176 static HRESULT WINAPI ACLMulti_Skip(IEnumString *iface, ULONG celt)
178 /* native browseui 6.0 returns this: */
179 return E_NOTIMPL;
182 static HRESULT WINAPI ACLMulti_Clone(IEnumString *iface, IEnumString **ppOut)
184 *ppOut = NULL;
185 /* native browseui 6.0 returns this: */
186 return E_OUTOFMEMORY;
189 static const IEnumStringVtbl ACLMultiVtbl =
191 ACLMulti_QueryInterface,
192 ACLMulti_AddRef,
193 ACLMulti_Release,
195 ACLMulti_Next,
196 ACLMulti_Skip,
197 ACLMulti_Reset,
198 ACLMulti_Clone
201 static HRESULT WINAPI ACLMulti_IObjMgr_QueryInterface(IObjMgr *iface, REFIID iid, LPVOID *ppvOut)
203 ACLMulti *This = impl_from_IObjMgr(iface);
204 return IEnumString_QueryInterface(&This->IEnumString_iface, iid, ppvOut);
207 static ULONG WINAPI ACLMulti_IObjMgr_AddRef(IObjMgr *iface)
209 ACLMulti *This = impl_from_IObjMgr(iface);
210 return IEnumString_AddRef(&This->IEnumString_iface);
213 static ULONG WINAPI ACLMulti_IObjMgr_Release(IObjMgr *iface)
215 ACLMulti *This = impl_from_IObjMgr(iface);
216 return IEnumString_Release(&This->IEnumString_iface);
219 static HRESULT WINAPI ACLMulti_Append(IObjMgr *iface, IUnknown *obj)
221 ACLMulti *This = impl_from_IObjMgr(iface);
223 TRACE("(%p, %p)\n", This, obj);
224 if (obj == NULL)
225 return E_FAIL;
227 This->objs = heap_realloc(This->objs, sizeof(This->objs[0]) * (This->nObjs+1));
228 This->objs[This->nObjs].punk = obj;
229 IUnknown_AddRef(obj);
230 if (FAILED(IUnknown_QueryInterface(obj, &IID_IEnumString, (LPVOID *)&This->objs[This->nObjs].pEnum)))
231 This->objs[This->nObjs].pEnum = NULL;
232 if (FAILED(IUnknown_QueryInterface(obj, &IID_IACList, (LPVOID *)&This->objs[This->nObjs].pACL)))
233 This->objs[This->nObjs].pACL = NULL;
234 This->nObjs++;
235 return S_OK;
238 static HRESULT WINAPI ACLMulti_Remove(IObjMgr *iface, IUnknown *obj)
240 ACLMulti *This = impl_from_IObjMgr(iface);
241 int i;
243 TRACE("(%p, %p)\n", This, obj);
244 for (i = 0; i < This->nObjs; i++)
245 if (This->objs[i].punk == obj)
247 release_obj(&This->objs[i]);
248 memmove(&This->objs[i], &This->objs[i+1], (This->nObjs-i-1)*sizeof(struct ACLMultiSublist));
249 This->nObjs--;
250 This->objs = heap_realloc(This->objs, sizeof(This->objs[0]) * This->nObjs);
251 return S_OK;
254 return E_FAIL;
257 static const IObjMgrVtbl ACLMulti_ObjMgrVtbl =
259 ACLMulti_IObjMgr_QueryInterface,
260 ACLMulti_IObjMgr_AddRef,
261 ACLMulti_IObjMgr_Release,
263 ACLMulti_Append,
264 ACLMulti_Remove
267 static HRESULT WINAPI ACLMulti_IACList_QueryInterface(IACList *iface, REFIID iid, LPVOID *ppvOut)
269 ACLMulti *This = impl_from_IACList(iface);
270 return IEnumString_QueryInterface(&This->IEnumString_iface, iid, ppvOut);
273 static ULONG WINAPI ACLMulti_IACList_AddRef(IACList *iface)
275 ACLMulti *This = impl_from_IACList(iface);
276 return IEnumString_AddRef(&This->IEnumString_iface);
279 static ULONG WINAPI ACLMulti_IACList_Release(IACList *iface)
281 ACLMulti *This = impl_from_IACList(iface);
282 return IEnumString_Release(&This->IEnumString_iface);
285 static HRESULT WINAPI ACLMulti_Expand(IACList *iface, LPCWSTR wstr)
287 ACLMulti *This = impl_from_IACList(iface);
288 HRESULT res = S_OK;
289 int i;
291 for (i = 0; i < This->nObjs; i++)
293 if (!This->objs[i].pACL)
294 continue;
295 res = IACList_Expand(This->objs[i].pACL, wstr);
296 /* Vista behaviour - XP would break out of the loop if res == S_OK (usually calling Expand only once) */
298 return res;
301 static const IACListVtbl ACLMulti_ACListVtbl =
303 ACLMulti_IACList_QueryInterface,
304 ACLMulti_IACList_AddRef,
305 ACLMulti_IACList_Release,
307 ACLMulti_Expand
310 HRESULT ACLMulti_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
312 ACLMulti *This;
313 if (pUnkOuter)
314 return CLASS_E_NOAGGREGATION;
316 This = heap_alloc_zero(sizeof(ACLMulti));
317 if (This == NULL)
318 return E_OUTOFMEMORY;
320 This->IEnumString_iface.lpVtbl = &ACLMultiVtbl;
321 This->IACList_iface.lpVtbl = &ACLMulti_ACListVtbl;
322 This->IObjMgr_iface.lpVtbl = &ACLMulti_ObjMgrVtbl;
323 This->refCount = 1;
325 TRACE("returning %p\n", This);
326 *ppOut = (IUnknown *)&This->IEnumString_iface;
327 BROWSEUI_refCount++;
328 return S_OK;