[QMGR] Sync with Wine Staging 3.3. CORE-14434
[reactos.git] / dll / win32 / 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 #include "qmgr.h"
26 #include "wine/debug.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
29
30 BOOL transitionJobState(BackgroundCopyJobImpl *job, BG_JOB_STATE from, BG_JOB_STATE to)
31 {
32 BOOL ret = FALSE;
33
34 EnterCriticalSection(&globalMgr.cs);
35 if (job->state == from)
36 {
37 job->state = to;
38 ret = TRUE;
39 }
40 LeaveCriticalSection(&globalMgr.cs);
41 return ret;
42 }
43
44 struct copy_error
45 {
46 IBackgroundCopyError IBackgroundCopyError_iface;
47 LONG refs;
48 BG_ERROR_CONTEXT context;
49 HRESULT code;
50 IBackgroundCopyFile2 *file;
51 };
52
53 static inline struct copy_error *impl_from_IBackgroundCopyError(IBackgroundCopyError *iface)
54 {
55 return CONTAINING_RECORD(iface, struct copy_error, IBackgroundCopyError_iface);
56 }
57
58 static HRESULT WINAPI copy_error_QueryInterface(
59 IBackgroundCopyError *iface,
60 REFIID riid,
61 void **obj)
62 {
63 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
64
65 TRACE("(%p)->(%s %p)\n", error, debugstr_guid(riid), obj);
66
67 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IBackgroundCopyError))
68 {
69 *obj = &error->IBackgroundCopyError_iface;
70 }
71 else
72 {
73 *obj = NULL;
74 WARN("interface %s not supported\n", debugstr_guid(riid));
75 return E_NOINTERFACE;
76 }
77
78 IBackgroundCopyError_AddRef(iface);
79 return S_OK;
80 }
81
82 static ULONG WINAPI copy_error_AddRef(
83 IBackgroundCopyError *iface)
84 {
85 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
86 LONG refs = InterlockedIncrement(&error->refs);
87 TRACE("(%p)->(%d)\n", error, refs);
88 return refs;
89 }
90
91 static ULONG WINAPI copy_error_Release(
92 IBackgroundCopyError *iface)
93 {
94 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
95 LONG refs = InterlockedDecrement(&error->refs);
96
97 TRACE("(%p)->(%d)\n", error, refs);
98
99 if (!refs)
100 {
101 if (error->file) IBackgroundCopyFile2_Release(error->file);
102 HeapFree(GetProcessHeap(), 0, error);
103 }
104 return refs;
105 }
106
107 static HRESULT WINAPI copy_error_GetError(
108 IBackgroundCopyError *iface,
109 BG_ERROR_CONTEXT *pContext,
110 HRESULT *pCode)
111 {
112 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
113
114 TRACE("(%p)->(%p %p)\n", error, pContext, pCode);
115
116 *pContext = error->context;
117 *pCode = error->code;
118
119 TRACE("returning context %u error code 0x%08x\n", error->context, error->code);
120 return S_OK;
121 }
122
123 static HRESULT WINAPI copy_error_GetFile(
124 IBackgroundCopyError *iface,
125 IBackgroundCopyFile **pVal)
126 {
127 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
128
129 TRACE("(%p)->(%p)\n", error, pVal);
130
131 if (error->file)
132 {
133 IBackgroundCopyFile2_AddRef(error->file);
134 *pVal = (IBackgroundCopyFile *)error->file;
135 return S_OK;
136 }
137 *pVal = NULL;
138 return BG_E_FILE_NOT_AVAILABLE;
139 }
140
141 static HRESULT WINAPI copy_error_GetErrorDescription(
142 IBackgroundCopyError *iface,
143 DWORD LanguageId,
144 LPWSTR *pErrorDescription)
145 {
146 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
147 FIXME("(%p)->(%p)\n", error, pErrorDescription);
148 return E_NOTIMPL;
149 }
150
151 static HRESULT WINAPI copy_error_GetErrorContextDescription(
152 IBackgroundCopyError *iface,
153 DWORD LanguageId,
154 LPWSTR *pContextDescription)
155 {
156 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
157 FIXME("(%p)->(%p)\n", error, pContextDescription);
158 return E_NOTIMPL;
159 }
160
161 static HRESULT WINAPI copy_error_GetProtocol(
162 IBackgroundCopyError *iface,
163 LPWSTR *pProtocol)
164 {
165 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
166 FIXME("(%p)->(%p)\n", error, pProtocol);
167 return E_NOTIMPL;
168 }
169
170 static const IBackgroundCopyErrorVtbl copy_error_vtbl =
171 {
172 copy_error_QueryInterface,
173 copy_error_AddRef,
174 copy_error_Release,
175 copy_error_GetError,
176 copy_error_GetFile,
177 copy_error_GetErrorDescription,
178 copy_error_GetErrorContextDescription,
179 copy_error_GetProtocol
180 };
181
182 static HRESULT create_copy_error(
183 BG_ERROR_CONTEXT context,
184 HRESULT code,
185 IBackgroundCopyFile2 *file,
186 IBackgroundCopyError **obj)
187 {
188 struct copy_error *error;
189
190 TRACE("context %u code %08x file %p\n", context, code, file);
191
192 if (!(error = HeapAlloc(GetProcessHeap(), 0, sizeof(*error) ))) return E_OUTOFMEMORY;
193 error->IBackgroundCopyError_iface.lpVtbl = &copy_error_vtbl;
194 error->refs = 1;
195 error->context = context;
196 error->code = code;
197 error->file = file;
198 if (error->file) IBackgroundCopyFile2_AddRef(error->file);
199
200 *obj = &error->IBackgroundCopyError_iface;
201 TRACE("returning iface %p\n", *obj);
202 return S_OK;
203 }
204
205 static inline BOOL is_job_done(const BackgroundCopyJobImpl *job)
206 {
207 return job->state == BG_JOB_STATE_CANCELLED || job->state == BG_JOB_STATE_ACKNOWLEDGED;
208 }
209
210 static inline BackgroundCopyJobImpl *impl_from_IBackgroundCopyJob3(IBackgroundCopyJob3 *iface)
211 {
212 return CONTAINING_RECORD(iface, BackgroundCopyJobImpl, IBackgroundCopyJob3_iface);
213 }
214
215 static HRESULT WINAPI BackgroundCopyJob_QueryInterface(
216 IBackgroundCopyJob3 *iface, REFIID riid, void **obj)
217 {
218 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
219
220 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
221
222 if (IsEqualGUID(riid, &IID_IUnknown) ||
223 IsEqualGUID(riid, &IID_IBackgroundCopyJob) ||
224 IsEqualGUID(riid, &IID_IBackgroundCopyJob2) ||
225 IsEqualGUID(riid, &IID_IBackgroundCopyJob3))
226 {
227 *obj = &This->IBackgroundCopyJob3_iface;
228 }
229 else if (IsEqualGUID(riid, &IID_IBackgroundCopyJobHttpOptions))
230 {
231 *obj = &This->IBackgroundCopyJobHttpOptions_iface;
232 }
233 else
234 {
235 *obj = NULL;
236 return E_NOINTERFACE;
237 }
238
239 IBackgroundCopyJob3_AddRef(iface);
240 return S_OK;
241 }
242
243 static ULONG WINAPI BackgroundCopyJob_AddRef(IBackgroundCopyJob3 *iface)
244 {
245 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
246 ULONG ref = InterlockedIncrement(&This->ref);
247 TRACE("(%p)->(%d)\n", This, ref);
248 return ref;
249 }
250
251 static ULONG WINAPI BackgroundCopyJob_Release(IBackgroundCopyJob3 *iface)
252 {
253 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
254 ULONG i, j, ref = InterlockedDecrement(&This->ref);
255
256 TRACE("(%p)->(%d)\n", This, ref);
257
258 if (ref == 0)
259 {
260 This->cs.DebugInfo->Spare[0] = 0;
261 DeleteCriticalSection(&This->cs);
262 if (This->callback)
263 IBackgroundCopyCallback2_Release(This->callback);
264 HeapFree(GetProcessHeap(), 0, This->displayName);
265 HeapFree(GetProcessHeap(), 0, This->description);
266 HeapFree(GetProcessHeap(), 0, This->http_options.headers);
267 for (i = 0; i < BG_AUTH_TARGET_PROXY; i++)
268 {
269 for (j = 0; j < BG_AUTH_SCHEME_PASSPORT; j++)
270 {
271 BG_AUTH_CREDENTIALS *cred = &This->http_options.creds[i][j];
272 HeapFree(GetProcessHeap(), 0, cred->Credentials.Basic.UserName);
273 HeapFree(GetProcessHeap(), 0, cred->Credentials.Basic.Password);
274 }
275 }
276 CloseHandle(This->wait);
277 CloseHandle(This->cancel);
278 CloseHandle(This->done);
279 HeapFree(GetProcessHeap(), 0, This);
280 }
281
282 return ref;
283 }
284
285 /*** IBackgroundCopyJob methods ***/
286
287 static HRESULT WINAPI BackgroundCopyJob_AddFileSet(
288 IBackgroundCopyJob3 *iface,
289 ULONG cFileCount,
290 BG_FILE_INFO *pFileSet)
291 {
292 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
293 HRESULT hr = S_OK;
294 ULONG i;
295
296 TRACE("(%p)->(%d %p)\n", This, cFileCount, pFileSet);
297
298 EnterCriticalSection(&This->cs);
299
300 for (i = 0; i < cFileCount; ++i)
301 {
302 BackgroundCopyFileImpl *file;
303
304 /* We should return E_INVALIDARG in these cases. */
305 FIXME("Check for valid filenames and supported protocols\n");
306
307 hr = BackgroundCopyFileConstructor(This, pFileSet[i].RemoteName, pFileSet[i].LocalName, &file);
308 if (hr != S_OK) break;
309
310 /* Add a reference to the file to file list */
311 list_add_head(&This->files, &file->entryFromJob);
312 This->jobProgress.BytesTotal = BG_SIZE_UNKNOWN;
313 ++This->jobProgress.FilesTotal;
314 }
315
316 LeaveCriticalSection(&This->cs);
317
318 return hr;
319 }
320
321 static HRESULT WINAPI BackgroundCopyJob_AddFile(
322 IBackgroundCopyJob3 *iface,
323 LPCWSTR RemoteUrl,
324 LPCWSTR LocalName)
325 {
326 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
327 BG_FILE_INFO file;
328
329 TRACE("(%p)->(%s %s)\n", This, debugstr_w(RemoteUrl), debugstr_w(LocalName));
330
331 file.RemoteName = (LPWSTR)RemoteUrl;
332 file.LocalName = (LPWSTR)LocalName;
333 return IBackgroundCopyJob3_AddFileSet(iface, 1, &file);
334 }
335
336 static HRESULT WINAPI BackgroundCopyJob_EnumFiles(
337 IBackgroundCopyJob3 *iface,
338 IEnumBackgroundCopyFiles **enum_files)
339 {
340 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
341 TRACE("(%p)->(%p)\n", This, enum_files);
342 return EnumBackgroundCopyFilesConstructor(This, enum_files);
343 }
344
345 static HRESULT WINAPI BackgroundCopyJob_Suspend(
346 IBackgroundCopyJob3 *iface)
347 {
348 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
349 FIXME("(%p): stub\n", This);
350 return E_NOTIMPL;
351 }
352
353 static HRESULT WINAPI BackgroundCopyJob_Resume(
354 IBackgroundCopyJob3 *iface)
355 {
356 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
357 HRESULT rv = S_OK;
358
359 TRACE("(%p)\n", This);
360
361 EnterCriticalSection(&globalMgr.cs);
362 if (is_job_done(This))
363 {
364 rv = BG_E_INVALID_STATE;
365 }
366 else if (This->jobProgress.FilesTransferred == This->jobProgress.FilesTotal)
367 {
368 rv = BG_E_EMPTY;
369 }
370 else if (This->state != BG_JOB_STATE_CONNECTING
371 && This->state != BG_JOB_STATE_TRANSFERRING)
372 {
373 This->state = BG_JOB_STATE_QUEUED;
374 This->error.context = 0;
375 This->error.code = S_OK;
376 if (This->error.file)
377 {
378 IBackgroundCopyFile2_Release(This->error.file);
379 This->error.file = NULL;
380 }
381 SetEvent(globalMgr.jobEvent);
382 }
383 LeaveCriticalSection(&globalMgr.cs);
384
385 return rv;
386 }
387
388 static HRESULT WINAPI BackgroundCopyJob_Cancel(
389 IBackgroundCopyJob3 *iface)
390 {
391 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
392 HRESULT rv = S_OK;
393
394 TRACE("(%p)\n", This);
395
396 EnterCriticalSection(&This->cs);
397
398 if (is_job_done(This))
399 {
400 rv = BG_E_INVALID_STATE;
401 }
402 else
403 {
404 BackgroundCopyFileImpl *file;
405
406 if (This->state == BG_JOB_STATE_CONNECTING || This->state == BG_JOB_STATE_TRANSFERRING)
407 {
408 This->state = BG_JOB_STATE_CANCELLED;
409 SetEvent(This->cancel);
410
411 LeaveCriticalSection(&This->cs);
412 WaitForSingleObject(This->done, INFINITE);
413 EnterCriticalSection(&This->cs);
414 }
415
416 LIST_FOR_EACH_ENTRY(file, &This->files, BackgroundCopyFileImpl, entryFromJob)
417 {
418 if (file->tempFileName[0] && !DeleteFileW(file->tempFileName))
419 {
420 WARN("Couldn't delete %s (%u)\n", debugstr_w(file->tempFileName), GetLastError());
421 rv = BG_S_UNABLE_TO_DELETE_FILES;
422 }
423 if (file->info.LocalName && !DeleteFileW(file->info.LocalName))
424 {
425 WARN("Couldn't delete %s (%u)\n", debugstr_w(file->info.LocalName), GetLastError());
426 rv = BG_S_UNABLE_TO_DELETE_FILES;
427 }
428 }
429 This->state = BG_JOB_STATE_CANCELLED;
430 }
431
432 LeaveCriticalSection(&This->cs);
433 return rv;
434 }
435
436 static HRESULT WINAPI BackgroundCopyJob_Complete(
437 IBackgroundCopyJob3 *iface)
438 {
439 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
440 HRESULT rv = S_OK;
441
442 TRACE("(%p)\n", This);
443
444 EnterCriticalSection(&This->cs);
445
446 if (is_job_done(This))
447 {
448 rv = BG_E_INVALID_STATE;
449 }
450 else
451 {
452 BackgroundCopyFileImpl *file;
453 LIST_FOR_EACH_ENTRY(file, &This->files, BackgroundCopyFileImpl, entryFromJob)
454 {
455 if (file->fileProgress.Completed)
456 {
457 if (!MoveFileExW(file->tempFileName, file->info.LocalName,
458 (MOVEFILE_COPY_ALLOWED
459 | MOVEFILE_REPLACE_EXISTING
460 | MOVEFILE_WRITE_THROUGH)))
461 {
462 ERR("Couldn't rename file %s -> %s\n",
463 debugstr_w(file->tempFileName),
464 debugstr_w(file->info.LocalName));
465 rv = BG_S_PARTIAL_COMPLETE;
466 }
467 }
468 else
469 rv = BG_S_PARTIAL_COMPLETE;
470 }
471 }
472
473 This->state = BG_JOB_STATE_ACKNOWLEDGED;
474 LeaveCriticalSection(&This->cs);
475
476 return rv;
477 }
478
479 static HRESULT WINAPI BackgroundCopyJob_GetId(
480 IBackgroundCopyJob3 *iface,
481 GUID *pVal)
482 {
483 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
484 TRACE("(%p)->(%p)\n", This, pVal);
485 *pVal = This->jobId;
486 return S_OK;
487 }
488
489 static HRESULT WINAPI BackgroundCopyJob_GetType(
490 IBackgroundCopyJob3 *iface,
491 BG_JOB_TYPE *pVal)
492 {
493 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
494
495 TRACE("(%p)->(%p)\n", This, pVal);
496
497 if (!pVal)
498 return E_INVALIDARG;
499
500 *pVal = This->type;
501 return S_OK;
502 }
503
504 static HRESULT WINAPI BackgroundCopyJob_GetProgress(
505 IBackgroundCopyJob3 *iface,
506 BG_JOB_PROGRESS *pVal)
507 {
508 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
509
510 TRACE("(%p)->(%p)\n", This, pVal);
511
512 if (!pVal)
513 return E_INVALIDARG;
514
515 EnterCriticalSection(&This->cs);
516 *pVal = This->jobProgress;
517 LeaveCriticalSection(&This->cs);
518
519 return S_OK;
520 }
521
522 static HRESULT WINAPI BackgroundCopyJob_GetTimes(
523 IBackgroundCopyJob3 *iface,
524 BG_JOB_TIMES *pVal)
525 {
526 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
527 FIXME("(%p)->(%p): stub\n", This, pVal);
528 return E_NOTIMPL;
529 }
530
531 static HRESULT WINAPI BackgroundCopyJob_GetState(
532 IBackgroundCopyJob3 *iface,
533 BG_JOB_STATE *pVal)
534 {
535 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
536
537 TRACE("(%p)->(%p)\n", This, pVal);
538
539 if (!pVal)
540 return E_INVALIDARG;
541
542 /* Don't think we need a critical section for this */
543 *pVal = This->state;
544 return S_OK;
545 }
546
547 static HRESULT WINAPI BackgroundCopyJob_GetError(
548 IBackgroundCopyJob3 *iface,
549 IBackgroundCopyError **ppError)
550 {
551 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface);
552
553 TRACE("(%p)->(%p)\n", job, ppError);
554
555 if (!job->error.context) return BG_E_ERROR_INFORMATION_UNAVAILABLE;
556
557 return create_copy_error(job->error.context, job->error.code, job->error.file, ppError);
558 }
559
560 static HRESULT WINAPI BackgroundCopyJob_GetOwner(
561 IBackgroundCopyJob3 *iface,
562 LPWSTR *pVal)
563 {
564 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
565 FIXME("(%p)->(%p): stub\n", This, pVal);
566 return E_NOTIMPL;
567 }
568
569 static HRESULT WINAPI BackgroundCopyJob_SetDisplayName(
570 IBackgroundCopyJob3 *iface,
571 LPCWSTR Val)
572 {
573 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
574 FIXME("(%p)->(%s): stub\n", This, debugstr_w(Val));
575 return E_NOTIMPL;
576 }
577
578 static HRESULT WINAPI BackgroundCopyJob_GetDisplayName(
579 IBackgroundCopyJob3 *iface,
580 LPWSTR *pVal)
581 {
582 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
583
584 TRACE("(%p)->(%p)\n", This, pVal);
585
586 return return_strval(This->displayName, pVal);
587 }
588
589 static HRESULT WINAPI BackgroundCopyJob_SetDescription(
590 IBackgroundCopyJob3 *iface,
591 LPCWSTR Val)
592 {
593 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
594 static const int max_description_len = 1024;
595 HRESULT hr = S_OK;
596 int len;
597
598 TRACE("(%p)->(%s)\n", This, debugstr_w(Val));
599
600 if (!Val) return E_INVALIDARG;
601
602 len = strlenW(Val);
603 if (len > max_description_len) return BG_E_STRING_TOO_LONG;
604
605 EnterCriticalSection(&This->cs);
606
607 if (is_job_done(This))
608 {
609 hr = BG_E_INVALID_STATE;
610 }
611 else
612 {
613 HeapFree(GetProcessHeap(), 0, This->description);
614 if ((This->description = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR))))
615 strcpyW(This->description, Val);
616 else
617 hr = E_OUTOFMEMORY;
618 }
619
620 LeaveCriticalSection(&This->cs);
621
622 return hr;
623 }
624
625 static HRESULT WINAPI BackgroundCopyJob_GetDescription(
626 IBackgroundCopyJob3 *iface,
627 LPWSTR *pVal)
628 {
629 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
630
631 TRACE("(%p)->(%p)\n", This, pVal);
632
633 return return_strval(This->description, pVal);
634 }
635
636 static HRESULT WINAPI BackgroundCopyJob_SetPriority(
637 IBackgroundCopyJob3 *iface,
638 BG_JOB_PRIORITY Val)
639 {
640 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
641 FIXME("(%p)->(%d): stub\n", This, Val);
642 return S_OK;
643 }
644
645 static HRESULT WINAPI BackgroundCopyJob_GetPriority(
646 IBackgroundCopyJob3 *iface,
647 BG_JOB_PRIORITY *pVal)
648 {
649 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
650 FIXME("(%p)->(%p): stub\n", This, pVal);
651 return E_NOTIMPL;
652 }
653
654 static HRESULT WINAPI BackgroundCopyJob_SetNotifyFlags(
655 IBackgroundCopyJob3 *iface,
656 ULONG Val)
657 {
658 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
659 static const ULONG valid_flags = BG_NOTIFY_JOB_TRANSFERRED |
660 BG_NOTIFY_JOB_ERROR |
661 BG_NOTIFY_DISABLE |
662 BG_NOTIFY_JOB_MODIFICATION |
663 BG_NOTIFY_FILE_TRANSFERRED;
664
665 TRACE("(%p)->(0x%x)\n", This, Val);
666
667 if (is_job_done(This)) return BG_E_INVALID_STATE;
668 if (Val & ~valid_flags) return E_NOTIMPL;
669 This->notify_flags = Val;
670 return S_OK;
671 }
672
673 static HRESULT WINAPI BackgroundCopyJob_GetNotifyFlags(
674 IBackgroundCopyJob3 *iface,
675 ULONG *pVal)
676 {
677 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
678
679 TRACE("(%p)->(%p)\n", This, pVal);
680
681 if (!pVal) return E_INVALIDARG;
682
683 *pVal = This->notify_flags;
684
685 return S_OK;
686 }
687
688 static HRESULT WINAPI BackgroundCopyJob_SetNotifyInterface(
689 IBackgroundCopyJob3 *iface,
690 IUnknown *Val)
691 {
692 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
693 HRESULT hr = S_OK;
694
695 TRACE("(%p)->(%p)\n", This, Val);
696
697 if (is_job_done(This)) return BG_E_INVALID_STATE;
698
699 if (This->callback)
700 {
701 IBackgroundCopyCallback2_Release(This->callback);
702 This->callback = NULL;
703 This->callback2 = FALSE;
704 }
705
706 if (Val)
707 {
708 hr = IUnknown_QueryInterface(Val, &IID_IBackgroundCopyCallback2, (void**)&This->callback);
709 if (FAILED(hr))
710 hr = IUnknown_QueryInterface(Val, &IID_IBackgroundCopyCallback, (void**)&This->callback);
711 else
712 This->callback2 = TRUE;
713 }
714
715 return hr;
716 }
717
718 static HRESULT WINAPI BackgroundCopyJob_GetNotifyInterface(
719 IBackgroundCopyJob3 *iface,
720 IUnknown **pVal)
721 {
722 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
723
724 TRACE("(%p)->(%p)\n", This, pVal);
725
726 if (!pVal) return E_INVALIDARG;
727
728 *pVal = (IUnknown*)This->callback;
729 if (*pVal)
730 IUnknown_AddRef(*pVal);
731
732 return S_OK;
733 }
734
735 static HRESULT WINAPI BackgroundCopyJob_SetMinimumRetryDelay(
736 IBackgroundCopyJob3 *iface,
737 ULONG Seconds)
738 {
739 FIXME("%u\n", Seconds);
740 return S_OK;
741 }
742
743 static HRESULT WINAPI BackgroundCopyJob_GetMinimumRetryDelay(
744 IBackgroundCopyJob3 *iface,
745 ULONG *Seconds)
746 {
747 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
748 FIXME("(%p)->(%p): stub\n", This, Seconds);
749 *Seconds = 30;
750 return S_OK;
751 }
752
753 static HRESULT WINAPI BackgroundCopyJob_SetNoProgressTimeout(
754 IBackgroundCopyJob3 *iface,
755 ULONG Seconds)
756 {
757 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
758 FIXME("(%p)->(%d): stub\n", This, Seconds);
759 return S_OK;
760 }
761
762 static HRESULT WINAPI BackgroundCopyJob_GetNoProgressTimeout(
763 IBackgroundCopyJob3 *iface,
764 ULONG *Seconds)
765 {
766 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
767 FIXME("(%p)->(%p): stub\n", This, Seconds);
768 *Seconds = 900;
769 return S_OK;
770 }
771
772 static HRESULT WINAPI BackgroundCopyJob_GetErrorCount(
773 IBackgroundCopyJob3 *iface,
774 ULONG *Errors)
775 {
776 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
777 FIXME("(%p)->(%p): stub\n", This, Errors);
778 return E_NOTIMPL;
779 }
780
781 static HRESULT WINAPI BackgroundCopyJob_SetProxySettings(
782 IBackgroundCopyJob3 *iface,
783 BG_JOB_PROXY_USAGE ProxyUsage,
784 const WCHAR *ProxyList,
785 const WCHAR *ProxyBypassList)
786 {
787 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
788 FIXME("(%p)->(%d %s %s): stub\n", This, ProxyUsage, debugstr_w(ProxyList), debugstr_w(ProxyBypassList));
789 return E_NOTIMPL;
790 }
791
792 static HRESULT WINAPI BackgroundCopyJob_GetProxySettings(
793 IBackgroundCopyJob3 *iface,
794 BG_JOB_PROXY_USAGE *pProxyUsage,
795 LPWSTR *pProxyList,
796 LPWSTR *pProxyBypassList)
797 {
798 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
799 FIXME("(%p)->(%p %p %p): stub\n", This, pProxyUsage, pProxyList, pProxyBypassList);
800 return E_NOTIMPL;
801 }
802
803 static HRESULT WINAPI BackgroundCopyJob_TakeOwnership(
804 IBackgroundCopyJob3 *iface)
805 {
806 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
807 FIXME("(%p): stub\n", This);
808 return E_NOTIMPL;
809 }
810
811 static HRESULT WINAPI BackgroundCopyJob_SetNotifyCmdLine(
812 IBackgroundCopyJob3 *iface,
813 LPCWSTR prog,
814 LPCWSTR params)
815 {
816 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
817 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(prog), debugstr_w(params));
818 return E_NOTIMPL;
819 }
820
821 static HRESULT WINAPI BackgroundCopyJob_GetNotifyCmdLine(
822 IBackgroundCopyJob3 *iface,
823 LPWSTR *prog,
824 LPWSTR *params)
825 {
826 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
827 FIXME("(%p)->(%p %p): stub\n", This, prog, params);
828 return E_NOTIMPL;
829 }
830
831 static HRESULT WINAPI BackgroundCopyJob_GetReplyProgress(
832 IBackgroundCopyJob3 *iface,
833 BG_JOB_REPLY_PROGRESS *progress)
834 {
835 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
836 FIXME("(%p)->(%p): stub\n", This, progress);
837 return E_NOTIMPL;
838 }
839
840 static HRESULT WINAPI BackgroundCopyJob_GetReplyData(
841 IBackgroundCopyJob3 *iface,
842 byte **pBuffer,
843 UINT64 *pLength)
844 {
845 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
846 FIXME("(%p)->(%p %p): stub\n", This, pBuffer, pLength);
847 return E_NOTIMPL;
848 }
849
850 static HRESULT WINAPI BackgroundCopyJob_SetReplyFileName(
851 IBackgroundCopyJob3 *iface,
852 LPCWSTR filename)
853 {
854 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
855 FIXME("(%p)->(%s): stub\n", This, debugstr_w(filename));
856 return E_NOTIMPL;
857 }
858
859 static HRESULT WINAPI BackgroundCopyJob_GetReplyFileName(
860 IBackgroundCopyJob3 *iface,
861 LPWSTR *pFilename)
862 {
863 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
864 FIXME("(%p)->(%p): stub\n", This, pFilename);
865 return E_NOTIMPL;
866 }
867
868 static int index_from_target(BG_AUTH_TARGET target)
869 {
870 if (!target || target > BG_AUTH_TARGET_PROXY) return -1;
871 return target - 1;
872 }
873
874 static int index_from_scheme(BG_AUTH_SCHEME scheme)
875 {
876 if (!scheme || scheme > BG_AUTH_SCHEME_PASSPORT) return -1;
877 return scheme - 1;
878 }
879
880 static HRESULT WINAPI BackgroundCopyJob_SetCredentials(
881 IBackgroundCopyJob3 *iface,
882 BG_AUTH_CREDENTIALS *cred)
883 {
884 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface);
885 BG_AUTH_CREDENTIALS *new_cred;
886 int idx_target, idx_scheme;
887
888 TRACE("(%p)->(%p)\n", job, cred);
889
890 if ((idx_target = index_from_target(cred->Target)) < 0) return BG_E_INVALID_AUTH_TARGET;
891 if ((idx_scheme = index_from_scheme(cred->Scheme)) < 0) return BG_E_INVALID_AUTH_SCHEME;
892 new_cred = &job->http_options.creds[idx_target][idx_scheme];
893
894 EnterCriticalSection(&job->cs);
895
896 new_cred->Target = cred->Target;
897 new_cred->Scheme = cred->Scheme;
898
899 if (cred->Credentials.Basic.UserName)
900 {
901 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.UserName);
902 new_cred->Credentials.Basic.UserName = strdupW(cred->Credentials.Basic.UserName);
903 }
904 if (cred->Credentials.Basic.Password)
905 {
906 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.Password);
907 new_cred->Credentials.Basic.Password = strdupW(cred->Credentials.Basic.Password);
908 }
909
910 LeaveCriticalSection(&job->cs);
911 return S_OK;
912 }
913
914 static HRESULT WINAPI BackgroundCopyJob_RemoveCredentials(
915 IBackgroundCopyJob3 *iface,
916 BG_AUTH_TARGET target,
917 BG_AUTH_SCHEME scheme)
918 {
919 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface);
920 BG_AUTH_CREDENTIALS *new_cred;
921 int idx_target, idx_scheme;
922
923 TRACE("(%p)->(%u %u)\n", job, target, scheme);
924
925 if ((idx_target = index_from_target(target)) < 0) return BG_E_INVALID_AUTH_TARGET;
926 if ((idx_scheme = index_from_scheme(scheme)) < 0) return BG_E_INVALID_AUTH_SCHEME;
927 new_cred = &job->http_options.creds[idx_target][idx_scheme];
928
929 EnterCriticalSection(&job->cs);
930
931 new_cred->Target = new_cred->Scheme = 0;
932 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.UserName);
933 new_cred->Credentials.Basic.UserName = NULL;
934 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.Password);
935 new_cred->Credentials.Basic.Password = NULL;
936
937 LeaveCriticalSection(&job->cs);
938 return S_OK;
939 }
940
941 static HRESULT WINAPI BackgroundCopyJob_ReplaceRemotePrefix(
942 IBackgroundCopyJob3 *iface,
943 LPCWSTR OldPrefix,
944 LPCWSTR NewPrefix)
945 {
946 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
947 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(OldPrefix), debugstr_w(NewPrefix));
948 return S_OK;
949 }
950
951 static HRESULT WINAPI BackgroundCopyJob_AddFileWithRanges(
952 IBackgroundCopyJob3 *iface,
953 LPCWSTR RemoteUrl,
954 LPCWSTR LocalName,
955 DWORD RangeCount,
956 BG_FILE_RANGE Ranges[])
957 {
958 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
959 FIXME("(%p)->(%s %s %u %p): stub\n", This, debugstr_w(RemoteUrl), debugstr_w(LocalName), RangeCount, Ranges);
960 return S_OK;
961 }
962
963 static HRESULT WINAPI BackgroundCopyJob_SetFileACLFlags(
964 IBackgroundCopyJob3 *iface,
965 DWORD Flags)
966 {
967 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
968 FIXME("(%p)->(%x): stub\n", This, Flags);
969 return S_OK;
970 }
971
972 static HRESULT WINAPI BackgroundCopyJob_GetFileACLFlags(
973 IBackgroundCopyJob3 *iface,
974 DWORD *Flags)
975 {
976 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
977 FIXME("(%p)->(%p): stub\n", This, Flags);
978 return S_OK;
979 }
980
981 static const IBackgroundCopyJob3Vtbl BackgroundCopyJob3Vtbl =
982 {
983 BackgroundCopyJob_QueryInterface,
984 BackgroundCopyJob_AddRef,
985 BackgroundCopyJob_Release,
986 BackgroundCopyJob_AddFileSet,
987 BackgroundCopyJob_AddFile,
988 BackgroundCopyJob_EnumFiles,
989 BackgroundCopyJob_Suspend,
990 BackgroundCopyJob_Resume,
991 BackgroundCopyJob_Cancel,
992 BackgroundCopyJob_Complete,
993 BackgroundCopyJob_GetId,
994 BackgroundCopyJob_GetType,
995 BackgroundCopyJob_GetProgress,
996 BackgroundCopyJob_GetTimes,
997 BackgroundCopyJob_GetState,
998 BackgroundCopyJob_GetError,
999 BackgroundCopyJob_GetOwner,
1000 BackgroundCopyJob_SetDisplayName,
1001 BackgroundCopyJob_GetDisplayName,
1002 BackgroundCopyJob_SetDescription,
1003 BackgroundCopyJob_GetDescription,
1004 BackgroundCopyJob_SetPriority,
1005 BackgroundCopyJob_GetPriority,
1006 BackgroundCopyJob_SetNotifyFlags,
1007 BackgroundCopyJob_GetNotifyFlags,
1008 BackgroundCopyJob_SetNotifyInterface,
1009 BackgroundCopyJob_GetNotifyInterface,
1010 BackgroundCopyJob_SetMinimumRetryDelay,
1011 BackgroundCopyJob_GetMinimumRetryDelay,
1012 BackgroundCopyJob_SetNoProgressTimeout,
1013 BackgroundCopyJob_GetNoProgressTimeout,
1014 BackgroundCopyJob_GetErrorCount,
1015 BackgroundCopyJob_SetProxySettings,
1016 BackgroundCopyJob_GetProxySettings,
1017 BackgroundCopyJob_TakeOwnership,
1018 BackgroundCopyJob_SetNotifyCmdLine,
1019 BackgroundCopyJob_GetNotifyCmdLine,
1020 BackgroundCopyJob_GetReplyProgress,
1021 BackgroundCopyJob_GetReplyData,
1022 BackgroundCopyJob_SetReplyFileName,
1023 BackgroundCopyJob_GetReplyFileName,
1024 BackgroundCopyJob_SetCredentials,
1025 BackgroundCopyJob_RemoveCredentials,
1026 BackgroundCopyJob_ReplaceRemotePrefix,
1027 BackgroundCopyJob_AddFileWithRanges,
1028 BackgroundCopyJob_SetFileACLFlags,
1029 BackgroundCopyJob_GetFileACLFlags
1030 };
1031
1032 static inline BackgroundCopyJobImpl *impl_from_IBackgroundCopyJobHttpOptions(
1033 IBackgroundCopyJobHttpOptions *iface)
1034 {
1035 return CONTAINING_RECORD(iface, BackgroundCopyJobImpl, IBackgroundCopyJobHttpOptions_iface);
1036 }
1037
1038 static HRESULT WINAPI http_options_QueryInterface(
1039 IBackgroundCopyJobHttpOptions *iface,
1040 REFIID riid,
1041 void **ppvObject)
1042 {
1043 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1044 return IBackgroundCopyJob3_QueryInterface(&job->IBackgroundCopyJob3_iface, riid, ppvObject);
1045 }
1046
1047 static ULONG WINAPI http_options_AddRef(
1048 IBackgroundCopyJobHttpOptions *iface)
1049 {
1050 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1051 return IBackgroundCopyJob3_AddRef(&job->IBackgroundCopyJob3_iface);
1052 }
1053
1054 static ULONG WINAPI http_options_Release(
1055 IBackgroundCopyJobHttpOptions *iface)
1056 {
1057 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1058 return IBackgroundCopyJob3_Release(&job->IBackgroundCopyJob3_iface);
1059 }
1060
1061 static HRESULT WINAPI http_options_SetClientCertificateByID(
1062 IBackgroundCopyJobHttpOptions *iface,
1063 BG_CERT_STORE_LOCATION StoreLocation,
1064 LPCWSTR StoreName,
1065 BYTE *pCertHashBlob)
1066 {
1067 FIXME("\n");
1068 return E_NOTIMPL;
1069 }
1070
1071 static HRESULT WINAPI http_options_SetClientCertificateByName(
1072 IBackgroundCopyJobHttpOptions *iface,
1073 BG_CERT_STORE_LOCATION StoreLocation,
1074 LPCWSTR StoreName,
1075 LPCWSTR SubjectName)
1076 {
1077 FIXME("\n");
1078 return E_NOTIMPL;
1079 }
1080
1081 static HRESULT WINAPI http_options_RemoveClientCertificate(
1082 IBackgroundCopyJobHttpOptions *iface)
1083 {
1084 FIXME("\n");
1085 return E_NOTIMPL;
1086 }
1087
1088 static HRESULT WINAPI http_options_GetClientCertificate(
1089 IBackgroundCopyJobHttpOptions *iface,
1090 BG_CERT_STORE_LOCATION *pStoreLocation,
1091 LPWSTR *pStoreName,
1092 BYTE **ppCertHashBlob,
1093 LPWSTR *pSubjectName)
1094 {
1095 FIXME("\n");
1096 return E_NOTIMPL;
1097 }
1098
1099 static HRESULT WINAPI http_options_SetCustomHeaders(
1100 IBackgroundCopyJobHttpOptions *iface,
1101 LPCWSTR RequestHeaders)
1102 {
1103 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1104
1105 TRACE("(%p)->(%s)\n", iface, debugstr_w(RequestHeaders));
1106
1107 EnterCriticalSection(&job->cs);
1108
1109 if (RequestHeaders)
1110 {
1111 WCHAR *headers = strdupW(RequestHeaders);
1112 if (!headers)
1113 {
1114 LeaveCriticalSection(&job->cs);
1115 return E_OUTOFMEMORY;
1116 }
1117 HeapFree(GetProcessHeap(), 0, job->http_options.headers);
1118 job->http_options.headers = headers;
1119 }
1120 else
1121 {
1122 HeapFree(GetProcessHeap(), 0, job->http_options.headers);
1123 job->http_options.headers = NULL;
1124 }
1125
1126 LeaveCriticalSection(&job->cs);
1127 return S_OK;
1128 }
1129
1130 static HRESULT WINAPI http_options_GetCustomHeaders(
1131 IBackgroundCopyJobHttpOptions *iface,
1132 LPWSTR *pRequestHeaders)
1133 {
1134 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1135
1136 TRACE("(%p)->(%p)\n", iface, pRequestHeaders);
1137
1138 EnterCriticalSection(&job->cs);
1139
1140 if (job->http_options.headers)
1141 {
1142 WCHAR *headers = co_strdupW(job->http_options.headers);
1143 if (!headers)
1144 {
1145 LeaveCriticalSection(&job->cs);
1146 return E_OUTOFMEMORY;
1147 }
1148 *pRequestHeaders = headers;
1149 LeaveCriticalSection(&job->cs);
1150 return S_OK;
1151 }
1152
1153 *pRequestHeaders = NULL;
1154 LeaveCriticalSection(&job->cs);
1155 return S_FALSE;
1156 }
1157
1158 static HRESULT WINAPI http_options_SetSecurityFlags(
1159 IBackgroundCopyJobHttpOptions *iface,
1160 ULONG Flags)
1161 {
1162 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1163
1164 TRACE("(%p)->(0x%08x)\n", iface, Flags);
1165
1166 job->http_options.flags = Flags;
1167 return S_OK;
1168 }
1169
1170 static HRESULT WINAPI http_options_GetSecurityFlags(
1171 IBackgroundCopyJobHttpOptions *iface,
1172 ULONG *pFlags)
1173 {
1174 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1175
1176 TRACE("(%p)->(%p)\n", iface, pFlags);
1177
1178 *pFlags = job->http_options.flags;
1179 return S_OK;
1180 }
1181
1182 static const IBackgroundCopyJobHttpOptionsVtbl http_options_vtbl =
1183 {
1184 http_options_QueryInterface,
1185 http_options_AddRef,
1186 http_options_Release,
1187 http_options_SetClientCertificateByID,
1188 http_options_SetClientCertificateByName,
1189 http_options_RemoveClientCertificate,
1190 http_options_GetClientCertificate,
1191 http_options_SetCustomHeaders,
1192 http_options_GetCustomHeaders,
1193 http_options_SetSecurityFlags,
1194 http_options_GetSecurityFlags
1195 };
1196
1197 HRESULT BackgroundCopyJobConstructor(LPCWSTR displayName, BG_JOB_TYPE type, GUID *job_id, BackgroundCopyJobImpl **job)
1198 {
1199 HRESULT hr;
1200 BackgroundCopyJobImpl *This;
1201
1202 TRACE("(%s,%d,%p)\n", debugstr_w(displayName), type, job);
1203
1204 This = HeapAlloc(GetProcessHeap(), 0, sizeof *This);
1205 if (!This)
1206 return E_OUTOFMEMORY;
1207
1208 This->IBackgroundCopyJob3_iface.lpVtbl = &BackgroundCopyJob3Vtbl;
1209 This->IBackgroundCopyJobHttpOptions_iface.lpVtbl = &http_options_vtbl;
1210 InitializeCriticalSection(&This->cs);
1211 This->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BackgroundCopyJobImpl.cs");
1212
1213 This->ref = 1;
1214 This->type = type;
1215
1216 This->displayName = strdupW(displayName);
1217 if (!This->displayName)
1218 {
1219 This->cs.DebugInfo->Spare[0] = 0;
1220 DeleteCriticalSection(&This->cs);
1221 HeapFree(GetProcessHeap(), 0, This);
1222 return E_OUTOFMEMORY;
1223 }
1224
1225 hr = CoCreateGuid(&This->jobId);
1226 if (FAILED(hr))
1227 {
1228 This->cs.DebugInfo->Spare[0] = 0;
1229 DeleteCriticalSection(&This->cs);
1230 HeapFree(GetProcessHeap(), 0, This->displayName);
1231 HeapFree(GetProcessHeap(), 0, This);
1232 return hr;
1233 }
1234 *job_id = This->jobId;
1235
1236 list_init(&This->files);
1237 This->jobProgress.BytesTotal = 0;
1238 This->jobProgress.BytesTransferred = 0;
1239 This->jobProgress.FilesTotal = 0;
1240 This->jobProgress.FilesTransferred = 0;
1241
1242 This->state = BG_JOB_STATE_SUSPENDED;
1243 This->description = NULL;
1244 This->notify_flags = BG_NOTIFY_JOB_ERROR | BG_NOTIFY_JOB_TRANSFERRED;
1245 This->callback = NULL;
1246 This->callback2 = FALSE;
1247
1248 This->error.context = 0;
1249 This->error.code = S_OK;
1250 This->error.file = NULL;
1251
1252 memset(&This->http_options, 0, sizeof(This->http_options));
1253
1254 This->wait = CreateEventW(NULL, FALSE, FALSE, NULL);
1255 This->cancel = CreateEventW(NULL, FALSE, FALSE, NULL);
1256 This->done = CreateEventW(NULL, FALSE, FALSE, NULL);
1257
1258 *job = This;
1259
1260 TRACE("created job %s:%p\n", debugstr_guid(&This->jobId), This);
1261
1262 return S_OK;
1263 }
1264
1265 void processJob(BackgroundCopyJobImpl *job)
1266 {
1267 for (;;)
1268 {
1269 BackgroundCopyFileImpl *file;
1270 BOOL done = TRUE;
1271
1272 EnterCriticalSection(&job->cs);
1273 LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob)
1274 if (!file->fileProgress.Completed)
1275 {
1276 done = FALSE;
1277 break;
1278 }
1279 LeaveCriticalSection(&job->cs);
1280 if (done)
1281 {
1282 transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRED);
1283 return;
1284 }
1285
1286 if (!processFile(file, job))
1287 return;
1288 }
1289 }