28a90d7f658fa7598ccf68d6bbca7028120ddf21
[reactos.git] / reactos / 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 BITS_IBackgroundCopyManager_QueryInterface(IBackgroundCopyManager *iface,
26 REFIID riid, void **ppv)
27 {
28 TRACE("(%p,%s,%p)\n", iface, 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 BITS_IBackgroundCopyManager_AddRef(IBackgroundCopyManager *iface)
42 {
43 return 2;
44 }
45
46 static ULONG WINAPI BITS_IBackgroundCopyManager_Release(IBackgroundCopyManager *iface)
47 {
48 return 1;
49 }
50
51 /*** IBackgroundCopyManager interface methods ***/
52
53 static HRESULT WINAPI BITS_IBackgroundCopyManager_CreateJob(IBackgroundCopyManager *iface,
54 LPCWSTR DisplayName, BG_JOB_TYPE Type, GUID *pJobId, IBackgroundCopyJob **ppJob)
55 {
56 BackgroundCopyJobImpl *job;
57 HRESULT hres;
58 TRACE("\n");
59
60 hres = BackgroundCopyJobConstructor(DisplayName, Type, pJobId, &job);
61 if (FAILED(hres))
62 return hres;
63
64 /* Add a reference to the job to job list */
65 *ppJob = (IBackgroundCopyJob*)&job->IBackgroundCopyJob2_iface;
66 IBackgroundCopyJob_AddRef(*ppJob);
67 EnterCriticalSection(&globalMgr.cs);
68 list_add_head(&globalMgr.jobs, &job->entryFromQmgr);
69 LeaveCriticalSection(&globalMgr.cs);
70 return S_OK;
71 }
72
73 static HRESULT WINAPI BITS_IBackgroundCopyManager_GetJob(IBackgroundCopyManager *iface,
74 REFGUID jobID, IBackgroundCopyJob **ppJob)
75 {
76 FIXME("Not implemented\n");
77 return E_NOTIMPL;
78 }
79
80 static HRESULT WINAPI BITS_IBackgroundCopyManager_EnumJobs(IBackgroundCopyManager *iface,
81 DWORD dwFlags, IEnumBackgroundCopyJobs **ppEnum)
82 {
83 TRACE("\n");
84 return enum_copy_job_create(&globalMgr, ppEnum);
85 }
86
87 static HRESULT WINAPI BITS_IBackgroundCopyManager_GetErrorDescription(IBackgroundCopyManager *iface,
88 HRESULT hResult, DWORD LanguageId, LPWSTR *pErrorDescription)
89 {
90 FIXME("Not implemented\n");
91 return E_NOTIMPL;
92 }
93
94
95 static const IBackgroundCopyManagerVtbl BITS_IBackgroundCopyManager_Vtbl =
96 {
97 BITS_IBackgroundCopyManager_QueryInterface,
98 BITS_IBackgroundCopyManager_AddRef,
99 BITS_IBackgroundCopyManager_Release,
100 BITS_IBackgroundCopyManager_CreateJob,
101 BITS_IBackgroundCopyManager_GetJob,
102 BITS_IBackgroundCopyManager_EnumJobs,
103 BITS_IBackgroundCopyManager_GetErrorDescription
104 };
105
106 BackgroundCopyManagerImpl globalMgr = {
107 { &BITS_IBackgroundCopyManager_Vtbl },
108 { NULL, -1, 0, 0, 0, 0 },
109 NULL,
110 LIST_INIT(globalMgr.jobs)
111 };
112
113 /* Constructor for instances of background copy manager */
114 HRESULT BackgroundCopyManagerConstructor(IUnknown *pUnkOuter, LPVOID *ppObj)
115 {
116 TRACE("(%p,%p)\n", pUnkOuter, ppObj);
117 *ppObj = &globalMgr;
118 return S_OK;
119 }
120
121 DWORD WINAPI fileTransfer(void *param)
122 {
123 BackgroundCopyManagerImpl *qmgr = &globalMgr;
124 HANDLE events[2];
125
126 events[0] = stop_event;
127 events[1] = qmgr->jobEvent;
128
129 for (;;)
130 {
131 BackgroundCopyJobImpl *job, *jobCur;
132 BOOL haveJob = FALSE;
133
134 /* Check if it's the stop_event */
135 if (WaitForMultipleObjects(2, events, FALSE, INFINITE) == WAIT_OBJECT_0)
136 {
137 LIST_FOR_EACH_ENTRY_SAFE(job, jobCur, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr)
138 {
139 list_remove(&job->entryFromQmgr);
140 IBackgroundCopyJob2_Release(&job->IBackgroundCopyJob2_iface);
141 }
142 return 0;
143 }
144
145 /* Note that other threads may add files to the job list, but only
146 this thread ever deletes them so we don't need to worry about jobs
147 magically disappearing from the list. */
148 EnterCriticalSection(&qmgr->cs);
149
150 LIST_FOR_EACH_ENTRY_SAFE(job, jobCur, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr)
151 {
152 if (job->state == BG_JOB_STATE_ACKNOWLEDGED || job->state == BG_JOB_STATE_CANCELLED)
153 {
154 list_remove(&job->entryFromQmgr);
155 IBackgroundCopyJob2_Release(&job->IBackgroundCopyJob2_iface);
156 }
157 else if (job->state == BG_JOB_STATE_QUEUED)
158 {
159 haveJob = TRUE;
160 break;
161 }
162 else if (job->state == BG_JOB_STATE_CONNECTING
163 || job->state == BG_JOB_STATE_TRANSFERRING)
164 {
165 ERR("Invalid state for job %p: %d\n", job, job->state);
166 }
167 }
168
169 if (!haveJob)
170 ResetEvent(qmgr->jobEvent);
171
172 LeaveCriticalSection(&qmgr->cs);
173
174 if (haveJob)
175 processJob(job);
176 }
177 }