f0c8462c5499581e048ad1d72e1d5ddffe3c5eaf
[reactos.git] / dll / win32 / qmgr / qmgr.c
1 /*
2 * Queue Manager (BITS) core functions
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
23 BackgroundCopyManagerImpl globalMgr;
24
25 static HRESULT WINAPI BackgroundCopyManager_QueryInterface(IBackgroundCopyManager *iface,
26 REFIID riid, void **ppv)
27 {
28 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
29
30 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IBackgroundCopyManager))
31 {
32 *ppv = iface;
33 IBackgroundCopyManager_AddRef(iface);
34 return S_OK;
35 }
36
37 *ppv = NULL;
38 return E_NOINTERFACE;
39 }
40
41 static ULONG WINAPI BackgroundCopyManager_AddRef(IBackgroundCopyManager *iface)
42 {
43 return 2;
44 }
45
46 static ULONG WINAPI BackgroundCopyManager_Release(IBackgroundCopyManager *iface)
47 {
48 return 1;
49 }
50
51 /*** IBackgroundCopyManager interface methods ***/
52
53 static HRESULT WINAPI BackgroundCopyManager_CreateJob(IBackgroundCopyManager *iface,
54 LPCWSTR DisplayName, BG_JOB_TYPE Type, GUID *pJobId, IBackgroundCopyJob **ppJob)
55 {
56 BackgroundCopyJobImpl *job;
57 HRESULT hres;
58
59 TRACE("(%s %d %p %p)\n", debugstr_w(DisplayName), Type, pJobId, ppJob);
60
61 hres = BackgroundCopyJobConstructor(DisplayName, Type, pJobId, &job);
62 if (FAILED(hres))
63 return hres;
64
65 /* Add a reference to the job to job list */
66 *ppJob = (IBackgroundCopyJob *)&job->IBackgroundCopyJob3_iface;
67 IBackgroundCopyJob_AddRef(*ppJob);
68 EnterCriticalSection(&globalMgr.cs);
69 list_add_head(&globalMgr.jobs, &job->entryFromQmgr);
70 LeaveCriticalSection(&globalMgr.cs);
71 return S_OK;
72 }
73
74 static HRESULT WINAPI BackgroundCopyManager_GetJob(IBackgroundCopyManager *iface,
75 REFGUID jobID, IBackgroundCopyJob **job)
76 {
77 BackgroundCopyManagerImpl *qmgr = &globalMgr;
78 HRESULT hr = BG_E_NOT_FOUND;
79 BackgroundCopyJobImpl *cur;
80
81 TRACE("(%s %p)\n", debugstr_guid(jobID), job);
82
83 if (!job || !jobID) return E_INVALIDARG;
84
85 *job = NULL;
86
87 EnterCriticalSection(&qmgr->cs);
88
89 LIST_FOR_EACH_ENTRY(cur, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr)
90 {
91 if (IsEqualGUID(&cur->jobId, jobID))
92 {
93 *job = (IBackgroundCopyJob *)&cur->IBackgroundCopyJob3_iface;
94 IBackgroundCopyJob3_AddRef(&cur->IBackgroundCopyJob3_iface);
95 hr = S_OK;
96 break;
97 }
98 }
99
100 LeaveCriticalSection(&qmgr->cs);
101
102 return hr;
103 }
104
105 static HRESULT WINAPI BackgroundCopyManager_EnumJobs(IBackgroundCopyManager *iface,
106 DWORD flags, IEnumBackgroundCopyJobs **ppEnum)
107 {
108 TRACE("(0x%x %p)\n", flags, ppEnum);
109 return enum_copy_job_create(&globalMgr, ppEnum);
110 }
111
112 static HRESULT WINAPI BackgroundCopyManager_GetErrorDescription(IBackgroundCopyManager *iface,
113 HRESULT hr, DWORD langid, LPWSTR *error_description)
114 {
115 FIXME("(0x%08x 0x%x %p): stub\n", hr, langid, error_description);
116 return E_NOTIMPL;
117 }
118
119 static const IBackgroundCopyManagerVtbl BackgroundCopyManagerVtbl =
120 {
121 BackgroundCopyManager_QueryInterface,
122 BackgroundCopyManager_AddRef,
123 BackgroundCopyManager_Release,
124 BackgroundCopyManager_CreateJob,
125 BackgroundCopyManager_GetJob,
126 BackgroundCopyManager_EnumJobs,
127 BackgroundCopyManager_GetErrorDescription
128 };
129
130 BackgroundCopyManagerImpl globalMgr = {
131 { &BackgroundCopyManagerVtbl },
132 { NULL, -1, 0, 0, 0, 0 },
133 NULL,
134 LIST_INIT(globalMgr.jobs)
135 };
136
137 /* Constructor for instances of background copy manager */
138 HRESULT BackgroundCopyManagerConstructor(LPVOID *ppObj)
139 {
140 TRACE("(%p)\n", ppObj);
141 *ppObj = &globalMgr;
142 return S_OK;
143 }
144
145 DWORD WINAPI fileTransfer(void *param)
146 {
147 BackgroundCopyManagerImpl *qmgr = &globalMgr;
148 HANDLE events[2];
149
150 events[0] = stop_event;
151 events[1] = qmgr->jobEvent;
152
153 for (;;)
154 {
155 BackgroundCopyJobImpl *job, *jobCur;
156 BOOL haveJob = FALSE;
157
158 /* Check if it's the stop_event */
159 if (WaitForMultipleObjects(2, events, FALSE, INFINITE) == WAIT_OBJECT_0)
160 {
161 LIST_FOR_EACH_ENTRY_SAFE(job, jobCur, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr)
162 {
163 list_remove(&job->entryFromQmgr);
164 IBackgroundCopyJob3_Release(&job->IBackgroundCopyJob3_iface);
165 }
166 return 0;
167 }
168
169 /* Note that other threads may add files to the job list, but only
170 this thread ever deletes them so we don't need to worry about jobs
171 magically disappearing from the list. */
172 EnterCriticalSection(&qmgr->cs);
173
174 LIST_FOR_EACH_ENTRY_SAFE(job, jobCur, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr)
175 {
176 if (job->state == BG_JOB_STATE_ACKNOWLEDGED || job->state == BG_JOB_STATE_CANCELLED)
177 {
178 list_remove(&job->entryFromQmgr);
179 IBackgroundCopyJob3_Release(&job->IBackgroundCopyJob3_iface);
180 }
181 else if (job->state == BG_JOB_STATE_QUEUED)
182 {
183 haveJob = TRUE;
184 break;
185 }
186 else if (job->state == BG_JOB_STATE_CONNECTING
187 || job->state == BG_JOB_STATE_TRANSFERRING)
188 {
189 ERR("Invalid state for job %p: %d\n", job, job->state);
190 }
191 }
192
193 if (!haveJob)
194 ResetEvent(qmgr->jobEvent);
195
196 LeaveCriticalSection(&qmgr->cs);
197
198 if (haveJob)
199 processJob(job);
200 }
201 }