xref: /reactos/dll/win32/qmgr/enum_files.c (revision 017748ce)
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