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