Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/browseui/aclmulti.c
5968 views
1
/*
2
* Multisource AutoComplete list
3
*
4
* Copyright 2007 Mikolaj Zalewski
5
*
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.
10
*
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.
15
*
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
19
*/
20
21
#include <stdarg.h>
22
23
#define COBJMACROS
24
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"
33
34
#include "shlguid.h"
35
#include "shlobj.h"
36
37
#include "browseui.h"
38
39
WINE_DEFAULT_DEBUG_CHANNEL(browseui);
40
41
struct ACLMultiSublist {
42
IUnknown *punk;
43
IEnumString *pEnum;
44
IACList *pACL;
45
};
46
47
typedef struct tagACLMulti {
48
IEnumString IEnumString_iface;
49
IACList IACList_iface;
50
IObjMgr IObjMgr_iface;
51
LONG refCount;
52
INT nObjs;
53
INT currObj;
54
struct ACLMultiSublist *objs;
55
} ACLMulti;
56
57
static inline ACLMulti *impl_from_IEnumString(IEnumString *iface)
58
{
59
return CONTAINING_RECORD(iface, ACLMulti, IEnumString_iface);
60
}
61
62
static inline ACLMulti *impl_from_IACList(IACList *iface)
63
{
64
return CONTAINING_RECORD(iface, ACLMulti, IACList_iface);
65
}
66
67
static inline ACLMulti *impl_from_IObjMgr(IObjMgr *iface)
68
{
69
return CONTAINING_RECORD(iface, ACLMulti, IObjMgr_iface);
70
}
71
72
static void release_obj(struct ACLMultiSublist *obj)
73
{
74
IUnknown_Release(obj->punk);
75
if (obj->pEnum)
76
IEnumString_Release(obj->pEnum);
77
if (obj->pACL)
78
IACList_Release(obj->pACL);
79
}
80
81
static HRESULT WINAPI ACLMulti_QueryInterface(IEnumString *iface, REFIID iid, LPVOID *ppvOut)
82
{
83
ACLMulti *This = impl_from_IEnumString(iface);
84
*ppvOut = NULL;
85
86
if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumString))
87
{
88
*ppvOut = &This->IEnumString_iface;
89
}
90
else if (IsEqualIID(iid, &IID_IACList))
91
{
92
*ppvOut = &This->IACList_iface;
93
}
94
else if (IsEqualIID(iid, &IID_IObjMgr))
95
{
96
*ppvOut = &This->IObjMgr_iface;
97
}
98
99
if (*ppvOut)
100
{
101
IEnumString_AddRef(iface);
102
return S_OK;
103
}
104
105
WARN("unsupported interface: %s\n", debugstr_guid(iid));
106
return E_NOINTERFACE;
107
}
108
109
static ULONG WINAPI ACLMulti_AddRef(IEnumString *iface)
110
{
111
ACLMulti *This = impl_from_IEnumString(iface);
112
return InterlockedIncrement(&This->refCount);
113
}
114
115
static ULONG WINAPI ACLMulti_Release(IEnumString *iface)
116
{
117
ACLMulti *This = impl_from_IEnumString(iface);
118
ULONG ret;
119
int i;
120
121
ret = InterlockedDecrement(&This->refCount);
122
if (ret == 0)
123
{
124
for (i = 0; i < This->nObjs; i++)
125
release_obj(&This->objs[i]);
126
free(This->objs);
127
free(This);
128
BROWSEUI_refCount--;
129
}
130
131
return ret;
132
}
133
134
static HRESULT WINAPI ACLMulti_Next(IEnumString *iface, ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched)
135
{
136
ACLMulti *This = impl_from_IEnumString(iface);
137
138
TRACE("(%p, %ld, %p, %p)\n", iface, celt, rgelt, pceltFetched);
139
while (This->currObj < This->nObjs)
140
{
141
if (This->objs[This->currObj].pEnum)
142
{
143
/* native browseui 6.0 also returns only one element */
144
HRESULT ret = IEnumString_Next(This->objs[This->currObj].pEnum, 1, rgelt, pceltFetched);
145
if (ret != S_FALSE)
146
return ret;
147
}
148
This->currObj++;
149
}
150
151
if (pceltFetched)
152
*pceltFetched = 0;
153
*rgelt = NULL;
154
return S_FALSE;
155
}
156
157
static HRESULT WINAPI ACLMulti_Reset(IEnumString *iface)
158
{
159
ACLMulti *This = impl_from_IEnumString(iface);
160
int i;
161
162
This->currObj = 0;
163
for (i = 0; i < This->nObjs; i++)
164
{
165
if (This->objs[i].pEnum)
166
IEnumString_Reset(This->objs[i].pEnum);
167
}
168
return S_OK;
169
}
170
171
static HRESULT WINAPI ACLMulti_Skip(IEnumString *iface, ULONG celt)
172
{
173
/* native browseui 6.0 returns this: */
174
return E_NOTIMPL;
175
}
176
177
static HRESULT WINAPI ACLMulti_Clone(IEnumString *iface, IEnumString **ppOut)
178
{
179
*ppOut = NULL;
180
/* native browseui 6.0 returns this: */
181
return E_OUTOFMEMORY;
182
}
183
184
static const IEnumStringVtbl ACLMultiVtbl =
185
{
186
ACLMulti_QueryInterface,
187
ACLMulti_AddRef,
188
ACLMulti_Release,
189
190
ACLMulti_Next,
191
ACLMulti_Skip,
192
ACLMulti_Reset,
193
ACLMulti_Clone
194
};
195
196
static HRESULT WINAPI ACLMulti_IObjMgr_QueryInterface(IObjMgr *iface, REFIID iid, LPVOID *ppvOut)
197
{
198
ACLMulti *This = impl_from_IObjMgr(iface);
199
return IEnumString_QueryInterface(&This->IEnumString_iface, iid, ppvOut);
200
}
201
202
static ULONG WINAPI ACLMulti_IObjMgr_AddRef(IObjMgr *iface)
203
{
204
ACLMulti *This = impl_from_IObjMgr(iface);
205
return IEnumString_AddRef(&This->IEnumString_iface);
206
}
207
208
static ULONG WINAPI ACLMulti_IObjMgr_Release(IObjMgr *iface)
209
{
210
ACLMulti *This = impl_from_IObjMgr(iface);
211
return IEnumString_Release(&This->IEnumString_iface);
212
}
213
214
static HRESULT WINAPI ACLMulti_Append(IObjMgr *iface, IUnknown *obj)
215
{
216
ACLMulti *This = impl_from_IObjMgr(iface);
217
218
TRACE("(%p, %p)\n", This, obj);
219
if (obj == NULL)
220
return E_FAIL;
221
222
This->objs = realloc(This->objs, sizeof(This->objs[0]) * (This->nObjs+1));
223
This->objs[This->nObjs].punk = obj;
224
IUnknown_AddRef(obj);
225
if (FAILED(IUnknown_QueryInterface(obj, &IID_IEnumString, (LPVOID *)&This->objs[This->nObjs].pEnum)))
226
This->objs[This->nObjs].pEnum = NULL;
227
if (FAILED(IUnknown_QueryInterface(obj, &IID_IACList, (LPVOID *)&This->objs[This->nObjs].pACL)))
228
This->objs[This->nObjs].pACL = NULL;
229
This->nObjs++;
230
return S_OK;
231
}
232
233
static HRESULT WINAPI ACLMulti_Remove(IObjMgr *iface, IUnknown *obj)
234
{
235
ACLMulti *This = impl_from_IObjMgr(iface);
236
int i;
237
238
TRACE("(%p, %p)\n", This, obj);
239
for (i = 0; i < This->nObjs; i++)
240
if (This->objs[i].punk == obj)
241
{
242
release_obj(&This->objs[i]);
243
memmove(&This->objs[i], &This->objs[i+1], (This->nObjs-i-1)*sizeof(struct ACLMultiSublist));
244
This->nObjs--;
245
This->objs = realloc(This->objs, sizeof(This->objs[0]) * This->nObjs);
246
return S_OK;
247
}
248
249
return E_FAIL;
250
}
251
252
static const IObjMgrVtbl ACLMulti_ObjMgrVtbl =
253
{
254
ACLMulti_IObjMgr_QueryInterface,
255
ACLMulti_IObjMgr_AddRef,
256
ACLMulti_IObjMgr_Release,
257
258
ACLMulti_Append,
259
ACLMulti_Remove
260
};
261
262
static HRESULT WINAPI ACLMulti_IACList_QueryInterface(IACList *iface, REFIID iid, LPVOID *ppvOut)
263
{
264
ACLMulti *This = impl_from_IACList(iface);
265
return IEnumString_QueryInterface(&This->IEnumString_iface, iid, ppvOut);
266
}
267
268
static ULONG WINAPI ACLMulti_IACList_AddRef(IACList *iface)
269
{
270
ACLMulti *This = impl_from_IACList(iface);
271
return IEnumString_AddRef(&This->IEnumString_iface);
272
}
273
274
static ULONG WINAPI ACLMulti_IACList_Release(IACList *iface)
275
{
276
ACLMulti *This = impl_from_IACList(iface);
277
return IEnumString_Release(&This->IEnumString_iface);
278
}
279
280
static HRESULT WINAPI ACLMulti_Expand(IACList *iface, LPCWSTR wstr)
281
{
282
ACLMulti *This = impl_from_IACList(iface);
283
HRESULT res = S_OK;
284
int i;
285
286
for (i = 0; i < This->nObjs; i++)
287
{
288
if (!This->objs[i].pACL)
289
continue;
290
res = IACList_Expand(This->objs[i].pACL, wstr);
291
/* Vista behaviour - XP would break out of the loop if res == S_OK (usually calling Expand only once) */
292
}
293
return res;
294
}
295
296
static const IACListVtbl ACLMulti_ACListVtbl =
297
{
298
ACLMulti_IACList_QueryInterface,
299
ACLMulti_IACList_AddRef,
300
ACLMulti_IACList_Release,
301
302
ACLMulti_Expand
303
};
304
305
HRESULT ACLMulti_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
306
{
307
ACLMulti *This;
308
if (pUnkOuter)
309
return CLASS_E_NOAGGREGATION;
310
311
if (!(This = calloc(1, sizeof(ACLMulti))))
312
return E_OUTOFMEMORY;
313
314
This->IEnumString_iface.lpVtbl = &ACLMultiVtbl;
315
This->IACList_iface.lpVtbl = &ACLMulti_ACListVtbl;
316
This->IObjMgr_iface.lpVtbl = &ACLMulti_ObjMgrVtbl;
317
This->refCount = 1;
318
319
TRACE("returning %p\n", This);
320
*ppOut = (IUnknown *)&This->IEnumString_iface;
321
BROWSEUI_refCount++;
322
return S_OK;
323
}
324
325