wintrust: Use path in WIN_TRUST_SUBJECT_FILE structure rather than assuming a path...
[wine] / dlls / qmgr / job.c
1 /*
2  * Background Copy Job Interface for BITS
3  *
4  * Copyright 2007 Google (Roy Shea)
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 <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25
26 #include "qmgr.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
30
31 static void BackgroundCopyJobDestructor(BackgroundCopyJobImpl *This)
32 {
33     DeleteCriticalSection(&This->cs);
34     HeapFree(GetProcessHeap(), 0, This->displayName);
35     HeapFree(GetProcessHeap(), 0, This);
36 }
37
38 static ULONG WINAPI BITS_IBackgroundCopyJob_AddRef(IBackgroundCopyJob2 *iface)
39 {
40     BackgroundCopyJobImpl *This = (BackgroundCopyJobImpl *) iface;
41     return InterlockedIncrement(&This->ref);
42 }
43
44 static HRESULT WINAPI BITS_IBackgroundCopyJob_QueryInterface(
45     IBackgroundCopyJob2 *iface, REFIID riid, LPVOID *ppvObject)
46 {
47     BackgroundCopyJobImpl *This = (BackgroundCopyJobImpl *) iface;
48     TRACE("IID: %s\n", debugstr_guid(riid));
49
50     if (IsEqualGUID(riid, &IID_IUnknown)
51         || IsEqualGUID(riid, &IID_IBackgroundCopyJob)
52         || IsEqualGUID(riid, &IID_IBackgroundCopyJob2))
53     {
54         *ppvObject = &This->lpVtbl;
55         BITS_IBackgroundCopyJob_AddRef(iface);
56         return S_OK;
57     }
58
59     *ppvObject = NULL;
60     return E_NOINTERFACE;
61 }
62
63 static ULONG WINAPI BITS_IBackgroundCopyJob_Release(IBackgroundCopyJob2 *iface)
64 {
65     BackgroundCopyJobImpl *This = (BackgroundCopyJobImpl *) iface;
66     ULONG ref = InterlockedDecrement(&This->ref);
67
68     if (ref == 0)
69         BackgroundCopyJobDestructor(This);
70
71     return ref;
72 }
73
74 /*** IBackgroundCopyJob methods ***/
75
76 static HRESULT WINAPI BITS_IBackgroundCopyJob_AddFileSet(
77     IBackgroundCopyJob2 *iface,
78     ULONG cFileCount,
79     BG_FILE_INFO *pFileSet)
80 {
81     ULONG i;
82     for (i = 0; i < cFileCount; ++i)
83     {
84         HRESULT hr = IBackgroundCopyJob_AddFile(iface, pFileSet[i].RemoteName,
85                                                 pFileSet[i].LocalName);
86         if (!SUCCEEDED(hr))
87             return hr;
88     }
89     return S_OK;
90 }
91
92 static HRESULT WINAPI BITS_IBackgroundCopyJob_AddFile(
93     IBackgroundCopyJob2 *iface,
94     LPCWSTR RemoteUrl,
95     LPCWSTR LocalName)
96 {
97     BackgroundCopyJobImpl *This = (BackgroundCopyJobImpl *) iface;
98     IBackgroundCopyFile *pFile;
99     BackgroundCopyFileImpl *file;
100     HRESULT res;
101
102     /* We should return E_INVALIDARG in these cases.  */
103     FIXME("Check for valid filenames and supported protocols\n");
104
105     res = BackgroundCopyFileConstructor(This, RemoteUrl, LocalName, (LPVOID *) &pFile);
106     if (res != S_OK)
107         return res;
108
109     /* Add a reference to the file to file list */
110     IBackgroundCopyFile_AddRef(pFile);
111     file = (BackgroundCopyFileImpl *) pFile;
112     EnterCriticalSection(&This->cs);
113     list_add_head(&This->files, &file->entryFromJob);
114     This->jobProgress.BytesTotal = BG_SIZE_UNKNOWN;
115     ++This->jobProgress.FilesTotal;
116     LeaveCriticalSection(&This->cs);
117
118     return S_OK;
119 }
120
121 static HRESULT WINAPI BITS_IBackgroundCopyJob_EnumFiles(
122     IBackgroundCopyJob2 *iface,
123     IEnumBackgroundCopyFiles **ppEnum)
124 {
125     TRACE("\n");
126     return EnumBackgroundCopyFilesConstructor((LPVOID *) ppEnum, iface);
127 }
128
129 static HRESULT WINAPI BITS_IBackgroundCopyJob_Suspend(
130     IBackgroundCopyJob2 *iface)
131 {
132     FIXME("Not implemented\n");
133     return E_NOTIMPL;
134 }
135
136 static HRESULT WINAPI BITS_IBackgroundCopyJob_Resume(
137     IBackgroundCopyJob2 *iface)
138 {
139     BackgroundCopyJobImpl *This = (BackgroundCopyJobImpl *) iface;
140     HRESULT rv = S_OK;
141
142     EnterCriticalSection(&globalMgr.cs);
143     if (This->state == BG_JOB_STATE_CANCELLED
144         || This->state == BG_JOB_STATE_ACKNOWLEDGED)
145     {
146         rv = BG_E_INVALID_STATE;
147     }
148     else if (This->jobProgress.FilesTransferred == This->jobProgress.FilesTotal)
149     {
150         rv = BG_E_EMPTY;
151     }
152     else if (This->state != BG_JOB_STATE_CONNECTING
153              && This->state != BG_JOB_STATE_TRANSFERRING)
154     {
155         This->state = BG_JOB_STATE_QUEUED;
156         SetEvent(globalMgr.jobEvent);
157     }
158     LeaveCriticalSection(&globalMgr.cs);
159
160     return rv;
161 }
162
163 static HRESULT WINAPI BITS_IBackgroundCopyJob_Cancel(
164     IBackgroundCopyJob2 *iface)
165 {
166     FIXME("Not implemented\n");
167     return E_NOTIMPL;
168 }
169
170 static HRESULT WINAPI BITS_IBackgroundCopyJob_Complete(
171     IBackgroundCopyJob2 *iface)
172 {
173     BackgroundCopyJobImpl *This = (BackgroundCopyJobImpl *) iface;
174     HRESULT rv = S_OK;
175
176     EnterCriticalSection(&This->cs);
177
178     if (This->state == BG_JOB_STATE_CANCELLED
179         || This->state == BG_JOB_STATE_ACKNOWLEDGED)
180     {
181         rv = BG_E_INVALID_STATE;
182     }
183     else
184     {
185         BackgroundCopyFileImpl *file;
186         LIST_FOR_EACH_ENTRY(file, &This->files, BackgroundCopyFileImpl, entryFromJob)
187         {
188             if (file->fileProgress.Completed)
189             {
190                 if (!MoveFileExW(file->tempFileName, file->info.LocalName,
191                                  (MOVEFILE_COPY_ALLOWED
192                                   | MOVEFILE_REPLACE_EXISTING
193                                   | MOVEFILE_WRITE_THROUGH)))
194                 {
195                     ERR("Couldn't rename file %s -> %s\n",
196                         debugstr_w(file->tempFileName),
197                         debugstr_w(file->info.LocalName));
198                     rv = BG_S_PARTIAL_COMPLETE;
199                 }
200             }
201             else
202                 rv = BG_S_PARTIAL_COMPLETE;
203         }
204     }
205
206     This->state = BG_JOB_STATE_ACKNOWLEDGED;
207     LeaveCriticalSection(&This->cs);
208
209     return rv;
210 }
211
212 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetId(
213     IBackgroundCopyJob2 *iface,
214     GUID *pVal)
215 {
216     BackgroundCopyJobImpl *This = (BackgroundCopyJobImpl *) iface;
217     *pVal = This->jobId;
218     return S_OK;
219 }
220
221 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetType(
222     IBackgroundCopyJob2 *iface,
223     BG_JOB_TYPE *pVal)
224 {
225     BackgroundCopyJobImpl *This = (BackgroundCopyJobImpl *) iface;
226
227     if (!pVal)
228         return E_INVALIDARG;
229
230     *pVal = This->type;
231     return S_OK;
232 }
233
234 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetProgress(
235     IBackgroundCopyJob2 *iface,
236     BG_JOB_PROGRESS *pVal)
237 {
238     BackgroundCopyJobImpl *This = (BackgroundCopyJobImpl *) iface;
239
240     if (!pVal)
241         return E_INVALIDARG;
242
243     EnterCriticalSection(&This->cs);
244     pVal->BytesTotal = This->jobProgress.BytesTotal;
245     pVal->BytesTransferred = This->jobProgress.BytesTransferred;
246     pVal->FilesTotal = This->jobProgress.FilesTotal;
247     pVal->FilesTransferred = This->jobProgress.FilesTransferred;
248     LeaveCriticalSection(&This->cs);
249
250     return S_OK;
251 }
252
253 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetTimes(
254     IBackgroundCopyJob2 *iface,
255     BG_JOB_TIMES *pVal)
256 {
257     FIXME("Not implemented\n");
258     return E_NOTIMPL;
259 }
260
261 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetState(
262     IBackgroundCopyJob2 *iface,
263     BG_JOB_STATE *pVal)
264 {
265     BackgroundCopyJobImpl *This = (BackgroundCopyJobImpl *) iface;
266
267     if (!pVal)
268         return E_INVALIDARG;
269
270     /* Don't think we need a critical section for this */
271     *pVal = This->state;
272     return S_OK;
273 }
274
275 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetError(
276     IBackgroundCopyJob2 *iface,
277     IBackgroundCopyError **ppError)
278 {
279     FIXME("Not implemented\n");
280     return E_NOTIMPL;
281 }
282
283 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetOwner(
284     IBackgroundCopyJob2 *iface,
285     LPWSTR *pVal)
286 {
287     FIXME("Not implemented\n");
288     return E_NOTIMPL;
289 }
290
291 static HRESULT WINAPI BITS_IBackgroundCopyJob_SetDisplayName(
292     IBackgroundCopyJob2 *iface,
293     LPCWSTR Val)
294 {
295     FIXME("Not implemented\n");
296     return E_NOTIMPL;
297 }
298
299 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetDisplayName(
300     IBackgroundCopyJob2 *iface,
301     LPWSTR *pVal)
302 {
303     BackgroundCopyJobImpl *This = (BackgroundCopyJobImpl *) iface;
304     int n;
305
306     if (!pVal)
307         return E_INVALIDARG;
308
309     n = (lstrlenW(This->displayName) + 1) * sizeof **pVal;
310     *pVal = CoTaskMemAlloc(n);
311     if (*pVal == NULL)
312         return E_OUTOFMEMORY;
313     memcpy(*pVal, This->displayName, n);
314     return S_OK;
315 }
316
317 static HRESULT WINAPI BITS_IBackgroundCopyJob_SetDescription(
318     IBackgroundCopyJob2 *iface,
319     LPCWSTR Val)
320 {
321     FIXME("Not implemented\n");
322     return E_NOTIMPL;
323 }
324
325 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetDescription(
326     IBackgroundCopyJob2 *iface,
327     LPWSTR *pVal)
328 {
329     FIXME("Not implemented\n");
330     return E_NOTIMPL;
331 }
332
333 static HRESULT WINAPI BITS_IBackgroundCopyJob_SetPriority(
334     IBackgroundCopyJob2 *iface,
335     BG_JOB_PRIORITY Val)
336 {
337     FIXME("Not implemented\n");
338     return E_NOTIMPL;
339 }
340
341 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetPriority(
342     IBackgroundCopyJob2 *iface,
343     BG_JOB_PRIORITY *pVal)
344 {
345     FIXME("Not implemented\n");
346     return E_NOTIMPL;
347 }
348
349 static HRESULT WINAPI BITS_IBackgroundCopyJob_SetNotifyFlags(
350     IBackgroundCopyJob2 *iface,
351     ULONG Val)
352 {
353     FIXME("Not implemented\n");
354     return E_NOTIMPL;
355 }
356
357 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetNotifyFlags(
358     IBackgroundCopyJob2 *iface,
359     ULONG *pVal)
360 {
361     FIXME("Not implemented\n");
362     return E_NOTIMPL;
363 }
364
365 static HRESULT WINAPI BITS_IBackgroundCopyJob_SetNotifyInterface(
366     IBackgroundCopyJob2 *iface,
367     IUnknown *Val)
368 {
369     FIXME("Not implemented\n");
370     return E_NOTIMPL;
371 }
372
373 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetNotifyInterface(
374     IBackgroundCopyJob2 *iface,
375     IUnknown **pVal)
376 {
377     FIXME("Not implemented\n");
378     return E_NOTIMPL;
379 }
380
381 static HRESULT WINAPI BITS_IBackgroundCopyJob_SetMinimumRetryDelay(
382     IBackgroundCopyJob2 *iface,
383     ULONG Seconds)
384 {
385     FIXME("Not implemented\n");
386     return E_NOTIMPL;
387 }
388
389 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetMinimumRetryDelay(
390     IBackgroundCopyJob2 *iface,
391     ULONG *Seconds)
392 {
393     FIXME("Not implemented\n");
394     return E_NOTIMPL;
395 }
396
397 static HRESULT WINAPI BITS_IBackgroundCopyJob_SetNoProgressTimeout(
398     IBackgroundCopyJob2 *iface,
399     ULONG Seconds)
400 {
401     FIXME("Not implemented\n");
402     return E_NOTIMPL;
403 }
404
405 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetNoProgressTimeout(
406     IBackgroundCopyJob2 *iface,
407     ULONG *Seconds)
408 {
409     FIXME("Not implemented\n");
410     return E_NOTIMPL;
411 }
412
413 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetErrorCount(
414     IBackgroundCopyJob2 *iface,
415     ULONG *Errors)
416 {
417     FIXME("Not implemented\n");
418     return E_NOTIMPL;
419 }
420
421 static HRESULT WINAPI BITS_IBackgroundCopyJob_SetProxySettings(
422     IBackgroundCopyJob2 *iface,
423     BG_JOB_PROXY_USAGE ProxyUsage,
424     const WCHAR *ProxyList,
425     const WCHAR *ProxyBypassList)
426 {
427     FIXME("Not implemented\n");
428     return E_NOTIMPL;
429 }
430
431 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetProxySettings(
432     IBackgroundCopyJob2 *iface,
433     BG_JOB_PROXY_USAGE *pProxyUsage,
434     LPWSTR *pProxyList,
435     LPWSTR *pProxyBypassList)
436 {
437     FIXME("Not implemented\n");
438     return E_NOTIMPL;
439 }
440
441 static HRESULT WINAPI BITS_IBackgroundCopyJob_TakeOwnership(
442     IBackgroundCopyJob2 *iface)
443 {
444     FIXME("Not implemented\n");
445     return E_NOTIMPL;
446 }
447
448 static HRESULT WINAPI BITS_IBackgroundCopyJob_SetNotifyCmdLine(
449     IBackgroundCopyJob2 *iface,
450     LPCWSTR prog,
451     LPCWSTR params)
452 {
453     FIXME("Not implemented\n");
454     return E_NOTIMPL;
455 }
456
457 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetNotifyCmdLine(
458     IBackgroundCopyJob2 *iface,
459     LPWSTR prog,
460     LPWSTR params)
461 {
462     FIXME("Not implemented\n");
463     return E_NOTIMPL;
464 }
465
466 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetReplyProgress(
467     IBackgroundCopyJob2 *iface,
468     BG_JOB_REPLY_PROGRESS *progress)
469 {
470     FIXME("Not implemented\n");
471     return E_NOTIMPL;
472 }
473
474 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetReplyData(
475     IBackgroundCopyJob2 *iface,
476     byte **pBuffer,
477     UINT64 *pLength)
478 {
479     FIXME("Not implemented\n");
480     return E_NOTIMPL;
481 }
482
483 static HRESULT WINAPI BITS_IBackgroundCopyJob_SetReplyFileName(
484     IBackgroundCopyJob2 *iface,
485     LPCWSTR filename)
486 {
487     FIXME("Not implemented\n");
488     return E_NOTIMPL;
489 }
490
491 static HRESULT WINAPI BITS_IBackgroundCopyJob_GetReplyFileName(
492     IBackgroundCopyJob2 *iface,
493     LPWSTR *pFilename)
494 {
495     FIXME("Not implemented\n");
496     return E_NOTIMPL;
497 }
498
499 static HRESULT WINAPI BITS_IBackgroundCopyJob_SetCredentials(
500     IBackgroundCopyJob2 *iface,
501     BG_AUTH_CREDENTIALS *cred)
502 {
503     FIXME("Not implemented\n");
504     return E_NOTIMPL;
505 }
506
507 static HRESULT WINAPI BITS_IBackgroundCopyJob_RemoveCredentials(
508     IBackgroundCopyJob2 *iface,
509     BG_AUTH_TARGET target,
510     BG_AUTH_SCHEME scheme)
511 {
512     FIXME("Not implemented\n");
513     return E_NOTIMPL;
514 }
515
516 static const IBackgroundCopyJob2Vtbl BITS_IBackgroundCopyJob_Vtbl =
517 {
518     BITS_IBackgroundCopyJob_QueryInterface,
519     BITS_IBackgroundCopyJob_AddRef,
520     BITS_IBackgroundCopyJob_Release,
521     BITS_IBackgroundCopyJob_AddFileSet,
522     BITS_IBackgroundCopyJob_AddFile,
523     BITS_IBackgroundCopyJob_EnumFiles,
524     BITS_IBackgroundCopyJob_Suspend,
525     BITS_IBackgroundCopyJob_Resume,
526     BITS_IBackgroundCopyJob_Cancel,
527     BITS_IBackgroundCopyJob_Complete,
528     BITS_IBackgroundCopyJob_GetId,
529     BITS_IBackgroundCopyJob_GetType,
530     BITS_IBackgroundCopyJob_GetProgress,
531     BITS_IBackgroundCopyJob_GetTimes,
532     BITS_IBackgroundCopyJob_GetState,
533     BITS_IBackgroundCopyJob_GetError,
534     BITS_IBackgroundCopyJob_GetOwner,
535     BITS_IBackgroundCopyJob_SetDisplayName,
536     BITS_IBackgroundCopyJob_GetDisplayName,
537     BITS_IBackgroundCopyJob_SetDescription,
538     BITS_IBackgroundCopyJob_GetDescription,
539     BITS_IBackgroundCopyJob_SetPriority,
540     BITS_IBackgroundCopyJob_GetPriority,
541     BITS_IBackgroundCopyJob_SetNotifyFlags,
542     BITS_IBackgroundCopyJob_GetNotifyFlags,
543     BITS_IBackgroundCopyJob_SetNotifyInterface,
544     BITS_IBackgroundCopyJob_GetNotifyInterface,
545     BITS_IBackgroundCopyJob_SetMinimumRetryDelay,
546     BITS_IBackgroundCopyJob_GetMinimumRetryDelay,
547     BITS_IBackgroundCopyJob_SetNoProgressTimeout,
548     BITS_IBackgroundCopyJob_GetNoProgressTimeout,
549     BITS_IBackgroundCopyJob_GetErrorCount,
550     BITS_IBackgroundCopyJob_SetProxySettings,
551     BITS_IBackgroundCopyJob_GetProxySettings,
552     BITS_IBackgroundCopyJob_TakeOwnership,
553     BITS_IBackgroundCopyJob_SetNotifyCmdLine,
554     BITS_IBackgroundCopyJob_GetNotifyCmdLine,
555     BITS_IBackgroundCopyJob_GetReplyProgress,
556     BITS_IBackgroundCopyJob_GetReplyData,
557     BITS_IBackgroundCopyJob_SetReplyFileName,
558     BITS_IBackgroundCopyJob_GetReplyFileName,
559     BITS_IBackgroundCopyJob_SetCredentials,
560     BITS_IBackgroundCopyJob_RemoveCredentials
561 };
562
563 HRESULT BackgroundCopyJobConstructor(LPCWSTR displayName, BG_JOB_TYPE type,
564                                      GUID *pJobId, LPVOID *ppObj)
565 {
566     HRESULT hr;
567     BackgroundCopyJobImpl *This;
568     int n;
569
570     TRACE("(%s,%d,%p)\n", debugstr_w(displayName), type, ppObj);
571
572     This = HeapAlloc(GetProcessHeap(), 0, sizeof *This);
573     if (!This)
574         return E_OUTOFMEMORY;
575
576     This->lpVtbl = &BITS_IBackgroundCopyJob_Vtbl;
577     InitializeCriticalSection(&This->cs);
578     This->ref = 1;
579     This->type = type;
580
581     n = (lstrlenW(displayName) + 1) *  sizeof *displayName;
582     This->displayName = HeapAlloc(GetProcessHeap(), 0, n);
583     if (!This->displayName)
584     {
585         DeleteCriticalSection(&This->cs);
586         HeapFree(GetProcessHeap(), 0, This);
587         return E_OUTOFMEMORY;
588     }
589     memcpy(This->displayName, displayName, n);
590
591     hr = CoCreateGuid(&This->jobId);
592     if (FAILED(hr))
593     {
594         DeleteCriticalSection(&This->cs);
595         HeapFree(GetProcessHeap(), 0, This->displayName);
596         HeapFree(GetProcessHeap(), 0, This);
597         return hr;
598     }
599     *pJobId = This->jobId;
600
601     list_init(&This->files);
602     This->jobProgress.BytesTotal = 0;
603     This->jobProgress.BytesTransferred = 0;
604     This->jobProgress.FilesTotal = 0;
605     This->jobProgress.FilesTransferred = 0;
606
607     This->state = BG_JOB_STATE_SUSPENDED;
608
609     *ppObj = &This->lpVtbl;
610     return S_OK;
611 }
612
613 void processJob(BackgroundCopyJobImpl *job)
614 {
615     for (;;)
616     {
617         BackgroundCopyFileImpl *file;
618         BOOL done = TRUE;
619
620         EnterCriticalSection(&job->cs);
621         LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob)
622             if (!file->fileProgress.Completed)
623             {
624                 done = FALSE;
625                 break;
626             }
627         LeaveCriticalSection(&job->cs);
628         if (done)
629         {
630             transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRED);
631             return;
632         }
633
634         if (!processFile(file, job))
635           return;
636     }
637 }