| /* |
| * 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); |
| |
| static void EnumBackgroundCopyJobsDestructor(EnumBackgroundCopyJobsImpl *This) |
| { |
| ULONG i; |
| |
| for(i = 0; i < This->numJobs; i++) |
| IBackgroundCopyJob_Release(This->jobs[i]); |
| |
| HeapFree(GetProcessHeap(), 0, This->jobs); |
| HeapFree(GetProcessHeap(), 0, This); |
| } |
| |
| static ULONG WINAPI BITS_IEnumBackgroundCopyJobs_AddRef( |
| IEnumBackgroundCopyJobs* iface) |
| { |
| EnumBackgroundCopyJobsImpl *This = (EnumBackgroundCopyJobsImpl *) iface; |
| return InterlockedIncrement(&This->ref); |
| } |
| |
| static HRESULT WINAPI BITS_IEnumBackgroundCopyJobs_QueryInterface( |
| IEnumBackgroundCopyJobs* iface, |
| REFIID riid, |
| void **ppvObject) |
| { |
| EnumBackgroundCopyJobsImpl *This = (EnumBackgroundCopyJobsImpl *) iface; |
| TRACE("IID: %s\n", debugstr_guid(riid)); |
| |
| if (IsEqualGUID(riid, &IID_IUnknown) |
| || IsEqualGUID(riid, &IID_IEnumBackgroundCopyJobs)) |
| { |
| *ppvObject = &This->lpVtbl; |
| BITS_IEnumBackgroundCopyJobs_AddRef(iface); |
| return S_OK; |
| } |
| |
| *ppvObject = NULL; |
| return E_NOINTERFACE; |
| } |
| |
| static ULONG WINAPI BITS_IEnumBackgroundCopyJobs_Release( |
| IEnumBackgroundCopyJobs* iface) |
| { |
| EnumBackgroundCopyJobsImpl *This = (EnumBackgroundCopyJobsImpl *) iface; |
| ULONG ref = InterlockedDecrement(&This->ref); |
| |
| if (ref == 0) |
| EnumBackgroundCopyJobsDestructor(This); |
| |
| return ref; |
| } |
| |
| static HRESULT WINAPI BITS_IEnumBackgroundCopyJobs_Next( |
| IEnumBackgroundCopyJobs* iface, |
| ULONG celt, |
| IBackgroundCopyJob **rgelt, |
| ULONG *pceltFetched) |
| { |
| EnumBackgroundCopyJobsImpl *This = (EnumBackgroundCopyJobsImpl *) iface; |
| ULONG fetched; |
| ULONG i; |
| IBackgroundCopyJob *job; |
| |
| 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++]; |
| IBackgroundCopyJob_AddRef(job); |
| rgelt[i] = job; |
| } |
| |
| return fetched == celt ? S_OK : S_FALSE; |
| } |
| |
| static HRESULT WINAPI BITS_IEnumBackgroundCopyJobs_Skip( |
| IEnumBackgroundCopyJobs* iface, |
| ULONG celt) |
| { |
| EnumBackgroundCopyJobsImpl *This = (EnumBackgroundCopyJobsImpl *) iface; |
| |
| if (This->numJobs - This->indexJobs < celt) |
| { |
| This->indexJobs = This->numJobs; |
| return S_FALSE; |
| } |
| |
| This->indexJobs += celt; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BITS_IEnumBackgroundCopyJobs_Reset( |
| IEnumBackgroundCopyJobs* iface) |
| { |
| EnumBackgroundCopyJobsImpl *This = (EnumBackgroundCopyJobsImpl *) iface; |
| This->indexJobs = 0; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BITS_IEnumBackgroundCopyJobs_Clone( |
| IEnumBackgroundCopyJobs* iface, |
| IEnumBackgroundCopyJobs **ppenum) |
| { |
| FIXME("Not implemented\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BITS_IEnumBackgroundCopyJobs_GetCount( |
| IEnumBackgroundCopyJobs* iface, |
| ULONG *puCount) |
| { |
| EnumBackgroundCopyJobsImpl *This = (EnumBackgroundCopyJobsImpl *) iface; |
| *puCount = This->numJobs; |
| return S_OK; |
| } |
| |
| static const IEnumBackgroundCopyJobsVtbl BITS_IEnumBackgroundCopyJobs_Vtbl = |
| { |
| BITS_IEnumBackgroundCopyJobs_QueryInterface, |
| BITS_IEnumBackgroundCopyJobs_AddRef, |
| BITS_IEnumBackgroundCopyJobs_Release, |
| BITS_IEnumBackgroundCopyJobs_Next, |
| BITS_IEnumBackgroundCopyJobs_Skip, |
| BITS_IEnumBackgroundCopyJobs_Reset, |
| BITS_IEnumBackgroundCopyJobs_Clone, |
| BITS_IEnumBackgroundCopyJobs_GetCount |
| }; |
| |
| HRESULT EnumBackgroundCopyJobsConstructor(LPVOID *ppObj, |
| IBackgroundCopyManager* copyManager) |
| { |
| BackgroundCopyManagerImpl *qmgr = (BackgroundCopyManagerImpl *) copyManager; |
| EnumBackgroundCopyJobsImpl *This; |
| BackgroundCopyJobImpl *job; |
| ULONG i; |
| |
| TRACE("%p, %p)\n", ppObj, copyManager); |
| |
| This = HeapAlloc(GetProcessHeap(), 0, sizeof *This); |
| if (!This) |
| return E_OUTOFMEMORY; |
| This->lpVtbl = &BITS_IEnumBackgroundCopyJobs_Vtbl; |
| 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) |
| { |
| IBackgroundCopyJob *iJob = (IBackgroundCopyJob *) job; |
| IBackgroundCopyJob_AddRef(iJob); |
| This->jobs[i++] = iJob; |
| } |
| LeaveCriticalSection(&qmgr->cs); |
| |
| *ppObj = &This->lpVtbl; |
| return S_OK; |
| } |