1c2c66affSColin Finck /*
2c2c66affSColin Finck * Queue Manager (BITS) core functions
3c2c66affSColin Finck *
4c2c66affSColin Finck * Copyright 2007, 2008 Google (Roy Shea, Dan Hipschman)
5c2c66affSColin Finck *
6c2c66affSColin Finck * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck * License as published by the Free Software Foundation; either
9c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck *
11c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14c2c66affSColin Finck * Lesser General Public License for more details.
15c2c66affSColin Finck *
16c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19c2c66affSColin Finck */
20c2c66affSColin Finck
21c2c66affSColin Finck #include "qmgr.h"
22*017748ceSAmine Khaldi #include "wine/debug.h"
23*017748ceSAmine Khaldi
24*017748ceSAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
25c2c66affSColin Finck
26c2c66affSColin Finck BackgroundCopyManagerImpl globalMgr;
27c2c66affSColin Finck
BackgroundCopyManager_QueryInterface(IBackgroundCopyManager * iface,REFIID riid,void ** ppv)28c2c66affSColin Finck static HRESULT WINAPI BackgroundCopyManager_QueryInterface(IBackgroundCopyManager *iface,
29c2c66affSColin Finck REFIID riid, void **ppv)
30c2c66affSColin Finck {
31c2c66affSColin Finck TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
32c2c66affSColin Finck
33c2c66affSColin Finck if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IBackgroundCopyManager))
34c2c66affSColin Finck {
35c2c66affSColin Finck *ppv = iface;
36c2c66affSColin Finck IBackgroundCopyManager_AddRef(iface);
37c2c66affSColin Finck return S_OK;
38c2c66affSColin Finck }
39c2c66affSColin Finck
40c2c66affSColin Finck *ppv = NULL;
41c2c66affSColin Finck return E_NOINTERFACE;
42c2c66affSColin Finck }
43c2c66affSColin Finck
BackgroundCopyManager_AddRef(IBackgroundCopyManager * iface)44c2c66affSColin Finck static ULONG WINAPI BackgroundCopyManager_AddRef(IBackgroundCopyManager *iface)
45c2c66affSColin Finck {
46c2c66affSColin Finck return 2;
47c2c66affSColin Finck }
48c2c66affSColin Finck
BackgroundCopyManager_Release(IBackgroundCopyManager * iface)49c2c66affSColin Finck static ULONG WINAPI BackgroundCopyManager_Release(IBackgroundCopyManager *iface)
50c2c66affSColin Finck {
51c2c66affSColin Finck return 1;
52c2c66affSColin Finck }
53c2c66affSColin Finck
54c2c66affSColin Finck /*** IBackgroundCopyManager interface methods ***/
55c2c66affSColin Finck
BackgroundCopyManager_CreateJob(IBackgroundCopyManager * iface,LPCWSTR DisplayName,BG_JOB_TYPE Type,GUID * pJobId,IBackgroundCopyJob ** ppJob)56c2c66affSColin Finck static HRESULT WINAPI BackgroundCopyManager_CreateJob(IBackgroundCopyManager *iface,
57c2c66affSColin Finck LPCWSTR DisplayName, BG_JOB_TYPE Type, GUID *pJobId, IBackgroundCopyJob **ppJob)
58c2c66affSColin Finck {
59c2c66affSColin Finck BackgroundCopyJobImpl *job;
60c2c66affSColin Finck HRESULT hres;
61c2c66affSColin Finck
62c2c66affSColin Finck TRACE("(%s %d %p %p)\n", debugstr_w(DisplayName), Type, pJobId, ppJob);
63c2c66affSColin Finck
64c2c66affSColin Finck hres = BackgroundCopyJobConstructor(DisplayName, Type, pJobId, &job);
65c2c66affSColin Finck if (FAILED(hres))
66c2c66affSColin Finck return hres;
67c2c66affSColin Finck
68c2c66affSColin Finck /* Add a reference to the job to job list */
69c2c66affSColin Finck *ppJob = (IBackgroundCopyJob *)&job->IBackgroundCopyJob3_iface;
70c2c66affSColin Finck IBackgroundCopyJob_AddRef(*ppJob);
71c2c66affSColin Finck EnterCriticalSection(&globalMgr.cs);
72c2c66affSColin Finck list_add_head(&globalMgr.jobs, &job->entryFromQmgr);
73c2c66affSColin Finck LeaveCriticalSection(&globalMgr.cs);
74c2c66affSColin Finck return S_OK;
75c2c66affSColin Finck }
76c2c66affSColin Finck
BackgroundCopyManager_GetJob(IBackgroundCopyManager * iface,REFGUID jobID,IBackgroundCopyJob ** job)77c2c66affSColin Finck static HRESULT WINAPI BackgroundCopyManager_GetJob(IBackgroundCopyManager *iface,
78c2c66affSColin Finck REFGUID jobID, IBackgroundCopyJob **job)
79c2c66affSColin Finck {
80c2c66affSColin Finck BackgroundCopyManagerImpl *qmgr = &globalMgr;
81c2c66affSColin Finck HRESULT hr = BG_E_NOT_FOUND;
82c2c66affSColin Finck BackgroundCopyJobImpl *cur;
83c2c66affSColin Finck
84c2c66affSColin Finck TRACE("(%s %p)\n", debugstr_guid(jobID), job);
85c2c66affSColin Finck
86c2c66affSColin Finck if (!job || !jobID) return E_INVALIDARG;
87c2c66affSColin Finck
88c2c66affSColin Finck *job = NULL;
89c2c66affSColin Finck
90c2c66affSColin Finck EnterCriticalSection(&qmgr->cs);
91c2c66affSColin Finck
92c2c66affSColin Finck LIST_FOR_EACH_ENTRY(cur, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr)
93c2c66affSColin Finck {
94c2c66affSColin Finck if (IsEqualGUID(&cur->jobId, jobID))
95c2c66affSColin Finck {
96c2c66affSColin Finck *job = (IBackgroundCopyJob *)&cur->IBackgroundCopyJob3_iface;
97c2c66affSColin Finck IBackgroundCopyJob3_AddRef(&cur->IBackgroundCopyJob3_iface);
98c2c66affSColin Finck hr = S_OK;
99c2c66affSColin Finck break;
100c2c66affSColin Finck }
101c2c66affSColin Finck }
102c2c66affSColin Finck
103c2c66affSColin Finck LeaveCriticalSection(&qmgr->cs);
104c2c66affSColin Finck
105c2c66affSColin Finck return hr;
106c2c66affSColin Finck }
107c2c66affSColin Finck
BackgroundCopyManager_EnumJobs(IBackgroundCopyManager * iface,DWORD flags,IEnumBackgroundCopyJobs ** ppEnum)108c2c66affSColin Finck static HRESULT WINAPI BackgroundCopyManager_EnumJobs(IBackgroundCopyManager *iface,
109c2c66affSColin Finck DWORD flags, IEnumBackgroundCopyJobs **ppEnum)
110c2c66affSColin Finck {
111c2c66affSColin Finck TRACE("(0x%x %p)\n", flags, ppEnum);
112c2c66affSColin Finck return enum_copy_job_create(&globalMgr, ppEnum);
113c2c66affSColin Finck }
114c2c66affSColin Finck
BackgroundCopyManager_GetErrorDescription(IBackgroundCopyManager * iface,HRESULT hr,DWORD langid,LPWSTR * error_description)115c2c66affSColin Finck static HRESULT WINAPI BackgroundCopyManager_GetErrorDescription(IBackgroundCopyManager *iface,
116c2c66affSColin Finck HRESULT hr, DWORD langid, LPWSTR *error_description)
117c2c66affSColin Finck {
118c2c66affSColin Finck FIXME("(0x%08x 0x%x %p): stub\n", hr, langid, error_description);
119c2c66affSColin Finck return E_NOTIMPL;
120c2c66affSColin Finck }
121c2c66affSColin Finck
122c2c66affSColin Finck static const IBackgroundCopyManagerVtbl BackgroundCopyManagerVtbl =
123c2c66affSColin Finck {
124c2c66affSColin Finck BackgroundCopyManager_QueryInterface,
125c2c66affSColin Finck BackgroundCopyManager_AddRef,
126c2c66affSColin Finck BackgroundCopyManager_Release,
127c2c66affSColin Finck BackgroundCopyManager_CreateJob,
128c2c66affSColin Finck BackgroundCopyManager_GetJob,
129c2c66affSColin Finck BackgroundCopyManager_EnumJobs,
130c2c66affSColin Finck BackgroundCopyManager_GetErrorDescription
131c2c66affSColin Finck };
132c2c66affSColin Finck
133c2c66affSColin Finck BackgroundCopyManagerImpl globalMgr = {
134c2c66affSColin Finck { &BackgroundCopyManagerVtbl },
135c2c66affSColin Finck { NULL, -1, 0, 0, 0, 0 },
136c2c66affSColin Finck NULL,
137c2c66affSColin Finck LIST_INIT(globalMgr.jobs)
138c2c66affSColin Finck };
139c2c66affSColin Finck
140c2c66affSColin Finck /* Constructor for instances of background copy manager */
BackgroundCopyManagerConstructor(LPVOID * ppObj)141c2c66affSColin Finck HRESULT BackgroundCopyManagerConstructor(LPVOID *ppObj)
142c2c66affSColin Finck {
143c2c66affSColin Finck TRACE("(%p)\n", ppObj);
144c2c66affSColin Finck *ppObj = &globalMgr;
145c2c66affSColin Finck return S_OK;
146c2c66affSColin Finck }
147c2c66affSColin Finck
fileTransfer(void * param)148c2c66affSColin Finck DWORD WINAPI fileTransfer(void *param)
149c2c66affSColin Finck {
150c2c66affSColin Finck BackgroundCopyManagerImpl *qmgr = &globalMgr;
151c2c66affSColin Finck HANDLE events[2];
152c2c66affSColin Finck
153c2c66affSColin Finck events[0] = stop_event;
154c2c66affSColin Finck events[1] = qmgr->jobEvent;
155c2c66affSColin Finck
156c2c66affSColin Finck for (;;)
157c2c66affSColin Finck {
158c2c66affSColin Finck BackgroundCopyJobImpl *job, *jobCur;
159c2c66affSColin Finck BOOL haveJob = FALSE;
160c2c66affSColin Finck
161c2c66affSColin Finck /* Check if it's the stop_event */
162c2c66affSColin Finck if (WaitForMultipleObjects(2, events, FALSE, INFINITE) == WAIT_OBJECT_0)
163c2c66affSColin Finck {
164c2c66affSColin Finck LIST_FOR_EACH_ENTRY_SAFE(job, jobCur, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr)
165c2c66affSColin Finck {
166c2c66affSColin Finck list_remove(&job->entryFromQmgr);
167c2c66affSColin Finck IBackgroundCopyJob3_Release(&job->IBackgroundCopyJob3_iface);
168c2c66affSColin Finck }
169c2c66affSColin Finck return 0;
170c2c66affSColin Finck }
171c2c66affSColin Finck
172c2c66affSColin Finck /* Note that other threads may add files to the job list, but only
173c2c66affSColin Finck this thread ever deletes them so we don't need to worry about jobs
174c2c66affSColin Finck magically disappearing from the list. */
175c2c66affSColin Finck EnterCriticalSection(&qmgr->cs);
176c2c66affSColin Finck
177c2c66affSColin Finck LIST_FOR_EACH_ENTRY_SAFE(job, jobCur, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr)
178c2c66affSColin Finck {
179c2c66affSColin Finck if (job->state == BG_JOB_STATE_ACKNOWLEDGED || job->state == BG_JOB_STATE_CANCELLED)
180c2c66affSColin Finck {
181c2c66affSColin Finck list_remove(&job->entryFromQmgr);
182c2c66affSColin Finck IBackgroundCopyJob3_Release(&job->IBackgroundCopyJob3_iface);
183c2c66affSColin Finck }
184c2c66affSColin Finck else if (job->state == BG_JOB_STATE_QUEUED)
185c2c66affSColin Finck {
186c2c66affSColin Finck haveJob = TRUE;
187c2c66affSColin Finck break;
188c2c66affSColin Finck }
189c2c66affSColin Finck else if (job->state == BG_JOB_STATE_CONNECTING
190c2c66affSColin Finck || job->state == BG_JOB_STATE_TRANSFERRING)
191c2c66affSColin Finck {
192c2c66affSColin Finck ERR("Invalid state for job %p: %d\n", job, job->state);
193c2c66affSColin Finck }
194c2c66affSColin Finck }
195c2c66affSColin Finck
196c2c66affSColin Finck if (!haveJob)
197c2c66affSColin Finck ResetEvent(qmgr->jobEvent);
198c2c66affSColin Finck
199c2c66affSColin Finck LeaveCriticalSection(&qmgr->cs);
200c2c66affSColin Finck
201c2c66affSColin Finck if (haveJob)
202c2c66affSColin Finck processJob(job);
203c2c66affSColin Finck }
204c2c66affSColin Finck }
205