xref: /reactos/dll/win32/qmgr/qmgr.c (revision 58588b76)
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 }
205