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