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