1 /*
2 * Queue Manager (BITS) File Enumerator
3 *
4 * Copyright 2007, 2008 Google (Roy Shea, Dan Hipschman)
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 "qmgr.h"
22 #include "wine/debug.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
25
26 typedef struct
27 {
28 IEnumBackgroundCopyFiles IEnumBackgroundCopyFiles_iface;
29 LONG ref;
30 IBackgroundCopyFile2 **files;
31 ULONG numFiles;
32 ULONG indexFiles;
33 } EnumBackgroundCopyFilesImpl;
34
impl_from_IEnumBackgroundCopyFiles(IEnumBackgroundCopyFiles * iface)35 static inline EnumBackgroundCopyFilesImpl *impl_from_IEnumBackgroundCopyFiles(IEnumBackgroundCopyFiles *iface)
36 {
37 return CONTAINING_RECORD(iface, EnumBackgroundCopyFilesImpl, IEnumBackgroundCopyFiles_iface);
38 }
39
EnumBackgroundCopyFiles_QueryInterface(IEnumBackgroundCopyFiles * iface,REFIID riid,void ** ppv)40 static HRESULT WINAPI EnumBackgroundCopyFiles_QueryInterface(IEnumBackgroundCopyFiles *iface,
41 REFIID riid, void **ppv)
42 {
43 EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);
44
45 TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv);
46
47 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IEnumBackgroundCopyFiles))
48 {
49 *ppv = iface;
50 IEnumBackgroundCopyFiles_AddRef(iface);
51 return S_OK;
52 }
53
54 *ppv = NULL;
55 return E_NOINTERFACE;
56 }
57
EnumBackgroundCopyFiles_AddRef(IEnumBackgroundCopyFiles * iface)58 static ULONG WINAPI EnumBackgroundCopyFiles_AddRef(IEnumBackgroundCopyFiles *iface)
59 {
60 EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);
61 ULONG ref = InterlockedIncrement(&This->ref);
62
63 TRACE("(%p)->(%d)\n", This, ref);
64 return ref;
65 }
66
EnumBackgroundCopyFiles_Release(IEnumBackgroundCopyFiles * iface)67 static ULONG WINAPI EnumBackgroundCopyFiles_Release(IEnumBackgroundCopyFiles *iface)
68 {
69 EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);
70 ULONG ref = InterlockedDecrement(&This->ref);
71 ULONG i;
72
73 TRACE("(%p)->(%d)\n", This, ref);
74
75 if (ref == 0)
76 {
77 for(i = 0; i < This->numFiles; i++)
78 IBackgroundCopyFile2_Release(This->files[i]);
79 HeapFree(GetProcessHeap(), 0, This->files);
80 HeapFree(GetProcessHeap(), 0, This);
81 }
82
83 return ref;
84 }
85
86 /* Return reference to one or more files in the file enumerator */
EnumBackgroundCopyFiles_Next(IEnumBackgroundCopyFiles * iface,ULONG celt,IBackgroundCopyFile ** rgelt,ULONG * pceltFetched)87 static HRESULT WINAPI EnumBackgroundCopyFiles_Next(IEnumBackgroundCopyFiles *iface,
88 ULONG celt, IBackgroundCopyFile **rgelt, ULONG *pceltFetched)
89 {
90 EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);
91 ULONG fetched;
92 ULONG i;
93 IBackgroundCopyFile2 *file;
94
95 TRACE("(%p)->(%d %p %p)\n", This, celt, rgelt, pceltFetched);
96
97 /* Despite documented behavior, Windows (tested on XP) is not verifying
98 that the caller set pceltFetched to zero. No check here. */
99
100 fetched = min(celt, This->numFiles - This->indexFiles);
101 if (pceltFetched)
102 *pceltFetched = fetched;
103 else
104 {
105 /* We need to initialize this array if the caller doesn't request
106 the length because length_is will default to celt. */
107 for (i = 0; i < celt; i++)
108 rgelt[i] = NULL;
109
110 /* pceltFetched can only be NULL if celt is 1 */
111 if (celt != 1)
112 return E_INVALIDARG;
113 }
114
115 /* Fill in the array of objects */
116 for (i = 0; i < fetched; i++)
117 {
118 file = This->files[This->indexFiles++];
119 IBackgroundCopyFile2_AddRef(file);
120 rgelt[i] = (IBackgroundCopyFile *)file;
121 }
122
123 return fetched == celt ? S_OK : S_FALSE;
124 }
125
126 /* Skip over one or more files in the file enumerator */
EnumBackgroundCopyFiles_Skip(IEnumBackgroundCopyFiles * iface,ULONG celt)127 static HRESULT WINAPI EnumBackgroundCopyFiles_Skip(IEnumBackgroundCopyFiles *iface,
128 ULONG celt)
129 {
130 EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);
131
132 TRACE("(%p)->(%d)\n", This, celt);
133
134 if (celt > This->numFiles - This->indexFiles)
135 {
136 This->indexFiles = This->numFiles;
137 return S_FALSE;
138 }
139
140 This->indexFiles += celt;
141 return S_OK;
142 }
143
EnumBackgroundCopyFiles_Reset(IEnumBackgroundCopyFiles * iface)144 static HRESULT WINAPI EnumBackgroundCopyFiles_Reset(IEnumBackgroundCopyFiles *iface)
145 {
146 EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);
147
148 TRACE("(%p)\n", This);
149
150 This->indexFiles = 0;
151 return S_OK;
152 }
153
EnumBackgroundCopyFiles_Clone(IEnumBackgroundCopyFiles * iface,IEnumBackgroundCopyFiles ** ppenum)154 static HRESULT WINAPI EnumBackgroundCopyFiles_Clone(IEnumBackgroundCopyFiles *iface,
155 IEnumBackgroundCopyFiles **ppenum)
156 {
157 EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);
158 FIXME("(%p)->(%p): stub\n", This, ppenum);
159 return E_NOTIMPL;
160 }
161
EnumBackgroundCopyFiles_GetCount(IEnumBackgroundCopyFiles * iface,ULONG * puCount)162 static HRESULT WINAPI EnumBackgroundCopyFiles_GetCount(IEnumBackgroundCopyFiles *iface,
163 ULONG *puCount)
164 {
165 EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);
166 TRACE("(%p)->(%p)\n", This, puCount);
167 *puCount = This->numFiles;
168 return S_OK;
169 }
170
171 static const IEnumBackgroundCopyFilesVtbl EnumBackgroundCopyFilesVtbl =
172 {
173 EnumBackgroundCopyFiles_QueryInterface,
174 EnumBackgroundCopyFiles_AddRef,
175 EnumBackgroundCopyFiles_Release,
176 EnumBackgroundCopyFiles_Next,
177 EnumBackgroundCopyFiles_Skip,
178 EnumBackgroundCopyFiles_Reset,
179 EnumBackgroundCopyFiles_Clone,
180 EnumBackgroundCopyFiles_GetCount
181 };
182
EnumBackgroundCopyFilesConstructor(BackgroundCopyJobImpl * job,IEnumBackgroundCopyFiles ** enum_files)183 HRESULT EnumBackgroundCopyFilesConstructor(BackgroundCopyJobImpl *job, IEnumBackgroundCopyFiles **enum_files)
184 {
185 EnumBackgroundCopyFilesImpl *This;
186 BackgroundCopyFileImpl *file;
187 ULONG i;
188
189 TRACE("%p, %p)\n", job, enum_files);
190
191 This = HeapAlloc(GetProcessHeap(), 0, sizeof *This);
192 if (!This)
193 return E_OUTOFMEMORY;
194
195 This->IEnumBackgroundCopyFiles_iface.lpVtbl = &EnumBackgroundCopyFilesVtbl;
196 This->ref = 1;
197
198 /* Create array of files */
199 This->indexFiles = 0;
200 EnterCriticalSection(&job->cs);
201 This->numFiles = list_count(&job->files);
202 This->files = NULL;
203 if (This->numFiles > 0)
204 {
205 This->files = HeapAlloc(GetProcessHeap(), 0,
206 This->numFiles * sizeof This->files[0]);
207 if (!This->files)
208 {
209 LeaveCriticalSection(&job->cs);
210 HeapFree(GetProcessHeap(), 0, This);
211 return E_OUTOFMEMORY;
212 }
213 }
214
215 i = 0;
216 LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob)
217 {
218 IBackgroundCopyFile2_AddRef(&file->IBackgroundCopyFile2_iface);
219 This->files[i] = &file->IBackgroundCopyFile2_iface;
220 ++i;
221 }
222 LeaveCriticalSection(&job->cs);
223
224 *enum_files = &This->IEnumBackgroundCopyFiles_iface;
225 return S_OK;
226 }
227