sync with trunk r47227
[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 <windows.h>
23 #include <shlobj.h>
24 #include <shlobj_undoc.h>
25 #include <shlguid.h>
26 #include <shlguid_undoc.h>
27 #include <tchar.h>
28 #include <atlbase.h>
29 #include <atlcom.h>
30 #include <atlwin.h>
31 #include "resource.h"
32 #include "wine/debug.h"
33 #include "aclmulti.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(browseui);
36
37 void CACLMulti::release_obj(struct ACLMultiSublist *obj)
38 {
39 obj->punk->Release();
40 if (obj->pEnum)
41 obj->pEnum->Release();
42 if (obj->pACL)
43 obj->pACL->Release();
44 }
45
46 CACLMulti::CACLMulti()
47 {
48 fObjectCount = 0;
49 fCurrentObject = 0;
50 fObjects = NULL;
51 }
52
53 CACLMulti::~CACLMulti()
54 {
55 int i;
56
57 TRACE("destroying %p\n", this);
58 for (i = 0; i < fObjectCount; i++)
59 release_obj(&fObjects[i]);
60 CoTaskMemFree(fObjects);
61 }
62
63 HRESULT STDMETHODCALLTYPE CACLMulti::Append(IUnknown *punk)
64 {
65 TRACE("(%p, %p)\n", this, punk);
66 if (punk == NULL)
67 return E_FAIL;
68
69 fObjects = reinterpret_cast<struct ACLMultiSublist *>(CoTaskMemRealloc(fObjects, sizeof(fObjects[0]) * (fObjectCount + 1)));
70 fObjects[fObjectCount].punk = punk;
71 punk->AddRef();
72 if (FAILED(punk->QueryInterface(IID_IEnumString, (void **)&fObjects[fObjectCount].pEnum)))
73 fObjects[fObjectCount].pEnum = NULL;
74 if (FAILED(punk->QueryInterface(IID_IACList, (void **)&fObjects[fObjectCount].pACL)))
75 fObjects[fObjectCount].pACL = NULL;
76 fObjectCount++;
77 return S_OK;
78 }
79
80 HRESULT STDMETHODCALLTYPE CACLMulti::Remove(IUnknown *punk)
81 {
82 int i;
83
84 TRACE("(%p, %p)\n", this, punk);
85 for (i = 0; i < fObjectCount; i++)
86 if (fObjects[i].punk == punk)
87 {
88 release_obj(&fObjects[i]);
89 memmove(&fObjects[i], &fObjects[i + 1], (fObjectCount - i - 1) * sizeof(struct ACLMultiSublist));
90 fObjectCount--;
91 fObjects = reinterpret_cast<struct ACLMultiSublist *>(CoTaskMemRealloc(fObjects, sizeof(fObjects[0]) * fObjectCount));
92 return S_OK;
93 }
94
95 return E_FAIL;
96 }
97
98 HRESULT STDMETHODCALLTYPE CACLMulti::Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched)
99 {
100 TRACE("(%p, %d, %p, %p)\n", this, celt, rgelt, pceltFetched);
101 while (fCurrentObject < fObjectCount)
102 {
103 if (fObjects[fCurrentObject].pEnum)
104 {
105 /* native browseui 6.0 also returns only one element */
106 HRESULT ret = fObjects[fCurrentObject].pEnum->Next(1, rgelt, pceltFetched);
107 if (ret != S_FALSE)
108 return ret;
109 }
110 fCurrentObject++;
111 }
112
113 if (pceltFetched)
114 *pceltFetched = 0;
115 *rgelt = NULL;
116 return S_FALSE;
117 }
118
119 HRESULT STDMETHODCALLTYPE CACLMulti::Reset()
120 {
121 int i;
122
123 fCurrentObject = 0;
124 for (i = 0; i < fObjectCount; i++)
125 {
126 if (fObjects[i].pEnum)
127 fObjects[i].pEnum->Reset();
128 }
129 return S_OK;
130 }
131
132 HRESULT STDMETHODCALLTYPE CACLMulti::Skip(ULONG celt)
133 {
134 /* native browseui 6.0 returns this: */
135 return E_NOTIMPL;
136 }
137
138 HRESULT STDMETHODCALLTYPE CACLMulti::Clone(IEnumString **ppOut)
139 {
140 *ppOut = NULL;
141 /* native browseui 6.0 returns this: */
142 return E_OUTOFMEMORY;
143 }
144
145 HRESULT STDMETHODCALLTYPE CACLMulti::Expand(LPCWSTR wstr)
146 {
147 HRESULT res = S_OK;
148 int i;
149
150 for (i = 0; i < fObjectCount; i++)
151 {
152 if (!fObjects[i].pACL)
153 continue;
154 res = fObjects[i].pACL->Expand(wstr);
155 if (res == S_OK)
156 break;
157 }
158 return res;
159 }