| /* |
| * Queue Manager (BITS) Job Enumerator |
| * |
| * Copyright 2007 Google (Roy Shea) |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include "qmgr.h" |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(qmgr); |
| |
| typedef struct |
| { |
| IEnumBackgroundCopyJobs IEnumBackgroundCopyJobs_iface; |
| LONG ref; |
| IBackgroundCopyJob3 **jobs; |
| ULONG numJobs; |
| ULONG indexJobs; |
| } EnumBackgroundCopyJobsImpl; |
| |
| static inline EnumBackgroundCopyJobsImpl *impl_from_IEnumBackgroundCopyJobs(IEnumBackgroundCopyJobs *iface) |
| { |
| return CONTAINING_RECORD(iface, EnumBackgroundCopyJobsImpl, IEnumBackgroundCopyJobs_iface); |
| } |
| |
| static HRESULT WINAPI EnumBackgroundCopyJobs_QueryInterface(IEnumBackgroundCopyJobs *iface, |
| REFIID riid, void **ppv) |
| { |
| EnumBackgroundCopyJobsImpl *This = impl_from_IEnumBackgroundCopyJobs(iface); |
| |
| TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppv); |
| |
| if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IEnumBackgroundCopyJobs)) |
| { |
| *ppv = iface; |
| IEnumBackgroundCopyJobs_AddRef(iface); |
| return S_OK; |
| } |
| |
| *ppv = NULL; |
| return E_NOINTERFACE; |
| } |
| |
| static ULONG WINAPI EnumBackgroundCopyJobs_AddRef(IEnumBackgroundCopyJobs *iface) |
| { |
| EnumBackgroundCopyJobsImpl *This = impl_from_IEnumBackgroundCopyJobs(iface); |
| ULONG ref = InterlockedIncrement(&This->ref); |
| |
| TRACE("(%p)->(%d)\n", This, ref); |
| |
| return ref; |
| } |
| |
| static ULONG WINAPI EnumBackgroundCopyJobs_Release(IEnumBackgroundCopyJobs *iface) |
| { |
| EnumBackgroundCopyJobsImpl *This = impl_from_IEnumBackgroundCopyJobs(iface); |
| ULONG ref = InterlockedDecrement(&This->ref); |
| ULONG i; |
| |
| TRACE("(%p)->(%d)\n", This, ref); |
| |
| if (ref == 0) { |
| for(i = 0; i < This->numJobs; i++) |
| IBackgroundCopyJob3_Release(This->jobs[i]); |
| HeapFree(GetProcessHeap(), 0, This->jobs); |
| HeapFree(GetProcessHeap(), 0, This); |
| } |
| |
| return ref; |
| } |
| |
| static HRESULT WINAPI EnumBackgroundCopyJobs_Next(IEnumBackgroundCopyJobs *iface, ULONG celt, |
| IBackgroundCopyJob **rgelt, ULONG *pceltFetched) |
| { |
| EnumBackgroundCopyJobsImpl *This = impl_from_IEnumBackgroundCopyJobs(iface); |
| ULONG fetched; |
| ULONG i; |
| IBackgroundCopyJob3 *job; |
| |
| TRACE("(%p)->(%d %p %p)\n", This, celt, rgelt, pceltFetched); |
| |
| fetched = min(celt, This->numJobs - This->indexJobs); |
| if (pceltFetched) |
| *pceltFetched = fetched; |
| else |
| { |
| /* We need to initialize this array if the caller doesn't request |
| the length because length_is will default to celt. */ |
| for (i = 0; i < celt; ++i) |
| rgelt[i] = NULL; |
| |
| /* pceltFetched can only be NULL if celt is 1 */ |
| if (celt != 1) |
| return E_INVALIDARG; |
| } |
| |
| /* Fill in the array of objects */ |
| for (i = 0; i < fetched; ++i) |
| { |
| job = This->jobs[This->indexJobs++]; |
| IBackgroundCopyJob3_AddRef(job); |
| rgelt[i] = (IBackgroundCopyJob *)job; |
| } |
| |
| return fetched == celt ? S_OK : S_FALSE; |
| } |
| |
| static HRESULT WINAPI EnumBackgroundCopyJobs_Skip(IEnumBackgroundCopyJobs *iface, ULONG celt) |
| { |
| EnumBackgroundCopyJobsImpl *This = impl_from_IEnumBackgroundCopyJobs(iface); |
| |
| TRACE("(%p)->(%d)\n", This, celt); |
| |
| if (This->numJobs - This->indexJobs < celt) |
| { |
| This->indexJobs = This->numJobs; |
| return S_FALSE; |
| } |
| |
| This->indexJobs += celt; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI EnumBackgroundCopyJobs_Reset(IEnumBackgroundCopyJobs *iface) |
| { |
| EnumBackgroundCopyJobsImpl *This = impl_from_IEnumBackgroundCopyJobs(iface); |
| |
| TRACE("(%p)\n", This); |
| |
| This->indexJobs = 0; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI EnumBackgroundCopyJobs_Clone(IEnumBackgroundCopyJobs *iface, |
| IEnumBackgroundCopyJobs **ppenum) |
| { |
| EnumBackgroundCopyJobsImpl *This = impl_from_IEnumBackgroundCopyJobs(iface); |
| FIXME("(%p)->(%p): stub\n", This, ppenum); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI EnumBackgroundCopyJobs_GetCount(IEnumBackgroundCopyJobs *iface, |
| ULONG *puCount) |
| { |
| EnumBackgroundCopyJobsImpl *This = impl_from_IEnumBackgroundCopyJobs(iface); |
| |
| TRACE("(%p)->(%p)\n", This, puCount); |
| |
| *puCount = This->numJobs; |
| return S_OK; |
| } |
| |
| static const IEnumBackgroundCopyJobsVtbl EnumBackgroundCopyJobsVtbl = |
| { |
| EnumBackgroundCopyJobs_QueryInterface, |
| EnumBackgroundCopyJobs_AddRef, |
| EnumBackgroundCopyJobs_Release, |
| EnumBackgroundCopyJobs_Next, |
| EnumBackgroundCopyJobs_Skip, |
| EnumBackgroundCopyJobs_Reset, |
| EnumBackgroundCopyJobs_Clone, |
| EnumBackgroundCopyJobs_GetCount |
| }; |
| |
| HRESULT enum_copy_job_create(BackgroundCopyManagerImpl *qmgr, IEnumBackgroundCopyJobs **enumjob) |
| { |
| EnumBackgroundCopyJobsImpl *This; |
| BackgroundCopyJobImpl *job; |
| ULONG i; |
| |
| TRACE("%p, %p)\n", qmgr, enumjob); |
| |
| This = HeapAlloc(GetProcessHeap(), 0, sizeof *This); |
| if (!This) |
| return E_OUTOFMEMORY; |
| This->IEnumBackgroundCopyJobs_iface.lpVtbl = &EnumBackgroundCopyJobsVtbl; |
| This->ref = 1; |
| |
| /* Create array of jobs */ |
| This->indexJobs = 0; |
| |
| EnterCriticalSection(&qmgr->cs); |
| This->numJobs = list_count(&qmgr->jobs); |
| |
| if (0 < This->numJobs) |
| { |
| This->jobs = HeapAlloc(GetProcessHeap(), 0, |
| This->numJobs * sizeof *This->jobs); |
| if (!This->jobs) |
| { |
| LeaveCriticalSection(&qmgr->cs); |
| HeapFree(GetProcessHeap(), 0, This); |
| return E_OUTOFMEMORY; |
| } |
| } |
| else |
| This->jobs = NULL; |
| |
| i = 0; |
| LIST_FOR_EACH_ENTRY(job, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr) |
| { |
| IBackgroundCopyJob3_AddRef(&job->IBackgroundCopyJob3_iface); |
| This->jobs[i++] = &job->IBackgroundCopyJob3_iface; |
| } |
| LeaveCriticalSection(&qmgr->cs); |
| |
| *enumjob = &This->IEnumBackgroundCopyJobs_iface; |
| return S_OK; |
| } |