[CLT2012]
[reactos.git] / dll / win32 / browseui / aclmulti.cpp
1 /*
2 * Multisource AutoComplete list
3 *
4 * Copyright 2007 Mikolaj Zalewski
5 * Copyright 2009 Andrew Hill
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "precomp.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(browseui);
25
26 void CACLMulti::release_obj(struct ACLMultiSublist *obj)
27 {
28 obj->punk->Release();
29 if (obj->pEnum)
30 obj->pEnum->Release();
31 if (obj->pACL)
32 obj->pACL->Release();
33 }
34
35 CACLMulti::CACLMulti()
36 {
37 fObjectCount = 0;
38 fCurrentObject = 0;
39 fObjects = NULL;
40 }
41
42 CACLMulti::~CACLMulti()
43 {
44 int i;
45
46 TRACE("destroying %p\n", this);
47 for (i = 0; i < fObjectCount; i++)
48 release_obj(&fObjects[i]);
49 CoTaskMemFree(fObjects);
50 }
51
52 HRESULT STDMETHODCALLTYPE CACLMulti::Append(IUnknown *punk)
53 {
54 TRACE("(%p, %p)\n", this, punk);
55 if (punk == NULL)
56 return E_FAIL;
57
58 fObjects = reinterpret_cast<struct ACLMultiSublist *>(CoTaskMemRealloc(fObjects, sizeof(fObjects[0]) * (fObjectCount + 1)));
59 fObjects[fObjectCount].punk = punk;
60 punk->AddRef();
61 if (FAILED(punk->QueryInterface(IID_IEnumString, (void **)&fObjects[fObjectCount].pEnum)))
62 fObjects[fObjectCount].pEnum = NULL;
63 if (FAILED(punk->QueryInterface(IID_IACList, (void **)&fObjects[fObjectCount].pACL)))
64 fObjects[fObjectCount].pACL = NULL;
65 fObjectCount++;
66 return S_OK;
67 }
68
69 HRESULT STDMETHODCALLTYPE CACLMulti::Remove(IUnknown *punk)
70 {
71 int i;
72
73 TRACE("(%p, %p)\n", this, punk);
74 for (i = 0; i < fObjectCount; i++)
75 if (fObjects[i].punk == punk)
76 {
77 release_obj(&fObjects[i]);
78 memmove(&fObjects[i], &fObjects[i + 1], (fObjectCount - i - 1) * sizeof(struct ACLMultiSublist));
79 fObjectCount--;
80 fObjects = reinterpret_cast<struct ACLMultiSublist *>(CoTaskMemRealloc(fObjects, sizeof(fObjects[0]) * fObjectCount));
81 return S_OK;
82 }
83
84 return E_FAIL;
85 }
86
87 HRESULT STDMETHODCALLTYPE CACLMulti::Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched)
88 {
89 TRACE("(%p, %d, %p, %p)\n", this, celt, rgelt, pceltFetched);
90 while (fCurrentObject < fObjectCount)
91 {
92 if (fObjects[fCurrentObject].pEnum)
93 {
94 /* native browseui 6.0 also returns only one element */
95 HRESULT ret = fObjects[fCurrentObject].pEnum->Next(1, rgelt, pceltFetched);
96 if (ret != S_FALSE)
97 return ret;
98 }
99 fCurrentObject++;
100 }
101
102 if (pceltFetched)
103 *pceltFetched = 0;
104 *rgelt = NULL;
105 return S_FALSE;
106 }
107
108 HRESULT STDMETHODCALLTYPE CACLMulti::Reset()
109 {
110 int i;
111
112 fCurrentObject = 0;
113 for (i = 0; i < fObjectCount; i++)
114 {
115 if (fObjects[i].pEnum)
116 fObjects[i].pEnum->Reset();
117 }
118 return S_OK;
119 }
120
121 HRESULT STDMETHODCALLTYPE CACLMulti::Skip(ULONG celt)
122 {
123 /* native browseui 6.0 returns this: */
124 return E_NOTIMPL;
125 }
126
127 HRESULT STDMETHODCALLTYPE CACLMulti::Clone(IEnumString **ppOut)
128 {
129 *ppOut = NULL;
130 /* native browseui 6.0 returns this: */
131 return E_OUTOFMEMORY;
132 }
133
134 HRESULT STDMETHODCALLTYPE CACLMulti::Expand(LPCWSTR wstr)
135 {
136 HRESULT res = S_OK;
137 int i;
138
139 for (i = 0; i < fObjectCount; i++)
140 {
141 if (!fObjects[i].pACL)
142 continue;
143 res = fObjects[i].pACL->Expand(wstr);
144 if (res == S_OK)
145 break;
146 }
147 return res;
148 }