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