qmgr: Don't inline transitionJobState.
[wine/multimedia.git] / dlls / qmgr / job.c
blob8ca04ad6bd0144bc67bf71b66aa95ffe8c7fab14
1 /*
2 * Background Copy Job Interface for BITS
4 * Copyright 2007 Google (Roy Shea)
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.
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.
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
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "qmgr.h"
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
30 BOOL transitionJobState(BackgroundCopyJobImpl *job, BG_JOB_STATE from, BG_JOB_STATE to)
32 BOOL ret = FALSE;
34 EnterCriticalSection(&globalMgr.cs);
35 if (job->state == from)
37 job->state = to;
38 ret = TRUE;
40 LeaveCriticalSection(&globalMgr.cs);
41 return ret;
44 struct copy_error
46 IBackgroundCopyError IBackgroundCopyError_iface;
47 LONG refs;
48 BG_ERROR_CONTEXT context;
49 HRESULT code;
50 IBackgroundCopyFile2 *file;
53 static inline struct copy_error *impl_from_IBackgroundCopyError(IBackgroundCopyError *iface)
55 return CONTAINING_RECORD(iface, struct copy_error, IBackgroundCopyError_iface);
58 static HRESULT WINAPI copy_error_QueryInterface(
59 IBackgroundCopyError *iface,
60 REFIID riid,
61 void **obj)
63 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
65 TRACE("(%p)->(%s %p)\n", error, debugstr_guid(riid), obj);
67 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IBackgroundCopyError))
69 *obj = &error->IBackgroundCopyError_iface;
71 else
73 *obj = NULL;
74 WARN("interface %s not supported\n", debugstr_guid(riid));
75 return E_NOINTERFACE;
78 IBackgroundCopyError_AddRef(iface);
79 return S_OK;
82 static ULONG WINAPI copy_error_AddRef(
83 IBackgroundCopyError *iface)
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;
91 static ULONG WINAPI copy_error_Release(
92 IBackgroundCopyError *iface)
94 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
95 LONG refs = InterlockedDecrement(&error->refs);
97 TRACE("(%p)->(%d)\n", error, refs);
99 if (!refs)
101 if (error->file) IBackgroundCopyFile2_Release(error->file);
102 HeapFree(GetProcessHeap(), 0, error);
104 return refs;
107 static HRESULT WINAPI copy_error_GetError(
108 IBackgroundCopyError *iface,
109 BG_ERROR_CONTEXT *pContext,
110 HRESULT *pCode)
112 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
114 TRACE("(%p)->(%p %p)\n", error, pContext, pCode);
116 *pContext = error->context;
117 *pCode = error->code;
119 TRACE("returning context %u error code 0x%08x\n", error->context, error->code);
120 return S_OK;
123 static HRESULT WINAPI copy_error_GetFile(
124 IBackgroundCopyError *iface,
125 IBackgroundCopyFile **pVal)
127 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
129 TRACE("(%p)->(%p)\n", error, pVal);
131 if (error->file)
133 IBackgroundCopyFile2_AddRef(error->file);
134 *pVal = (IBackgroundCopyFile *)error->file;
135 return S_OK;
137 *pVal = NULL;
138 return BG_E_FILE_NOT_AVAILABLE;
141 static HRESULT WINAPI copy_error_GetErrorDescription(
142 IBackgroundCopyError *iface,
143 DWORD LanguageId,
144 LPWSTR *pErrorDescription)
146 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
147 FIXME("(%p)->(%p)\n", error, pErrorDescription);
148 return E_NOTIMPL;
151 static HRESULT WINAPI copy_error_GetErrorContextDescription(
152 IBackgroundCopyError *iface,
153 DWORD LanguageId,
154 LPWSTR *pContextDescription)
156 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
157 FIXME("(%p)->(%p)\n", error, pContextDescription);
158 return E_NOTIMPL;
161 static HRESULT WINAPI copy_error_GetProtocol(
162 IBackgroundCopyError *iface,
163 LPWSTR *pProtocol)
165 struct copy_error *error = impl_from_IBackgroundCopyError(iface);
166 FIXME("(%p)->(%p)\n", error, pProtocol);
167 return E_NOTIMPL;
170 static const IBackgroundCopyErrorVtbl copy_error_vtbl =
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
182 static HRESULT create_copy_error(
183 BG_ERROR_CONTEXT context,
184 HRESULT code,
185 IBackgroundCopyFile2 *file,
186 IBackgroundCopyError **obj)
188 struct copy_error *error;
190 TRACE("context %u code %08x file %p\n", context, code, file);
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);
200 *obj = &error->IBackgroundCopyError_iface;
201 TRACE("returning iface %p\n", *obj);
202 return S_OK;
205 static inline BOOL is_job_done(const BackgroundCopyJobImpl *job)
207 return job->state == BG_JOB_STATE_CANCELLED || job->state == BG_JOB_STATE_ACKNOWLEDGED;
210 static inline BackgroundCopyJobImpl *impl_from_IBackgroundCopyJob3(IBackgroundCopyJob3 *iface)
212 return CONTAINING_RECORD(iface, BackgroundCopyJobImpl, IBackgroundCopyJob3_iface);
215 static HRESULT WINAPI BackgroundCopyJob_QueryInterface(
216 IBackgroundCopyJob3 *iface, REFIID riid, void **obj)
218 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
220 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj);
222 if (IsEqualGUID(riid, &IID_IUnknown) ||
223 IsEqualGUID(riid, &IID_IBackgroundCopyJob) ||
224 IsEqualGUID(riid, &IID_IBackgroundCopyJob2) ||
225 IsEqualGUID(riid, &IID_IBackgroundCopyJob3))
227 *obj = &This->IBackgroundCopyJob3_iface;
229 else if (IsEqualGUID(riid, &IID_IBackgroundCopyJobHttpOptions))
231 *obj = &This->IBackgroundCopyJobHttpOptions_iface;
233 else
235 *obj = NULL;
236 return E_NOINTERFACE;
239 IBackgroundCopyJob3_AddRef(iface);
240 return S_OK;
243 static ULONG WINAPI BackgroundCopyJob_AddRef(IBackgroundCopyJob3 *iface)
245 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
246 ULONG ref = InterlockedIncrement(&This->ref);
247 TRACE("(%p)->(%d)\n", This, ref);
248 return ref;
251 static ULONG WINAPI BackgroundCopyJob_Release(IBackgroundCopyJob3 *iface)
253 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
254 ULONG i, j, ref = InterlockedDecrement(&This->ref);
256 TRACE("(%p)->(%d)\n", This, ref);
258 if (ref == 0)
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++)
269 for (j = 0; j < BG_AUTH_SCHEME_PASSPORT; j++)
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);
276 CloseHandle(This->wait);
277 CloseHandle(This->cancel);
278 CloseHandle(This->done);
279 HeapFree(GetProcessHeap(), 0, This);
282 return ref;
285 /*** IBackgroundCopyJob methods ***/
287 static HRESULT WINAPI BackgroundCopyJob_AddFileSet(
288 IBackgroundCopyJob3 *iface,
289 ULONG cFileCount,
290 BG_FILE_INFO *pFileSet)
292 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
293 HRESULT hr = S_OK;
294 ULONG i;
296 TRACE("(%p)->(%d %p)\n", This, cFileCount, pFileSet);
298 EnterCriticalSection(&This->cs);
300 for (i = 0; i < cFileCount; ++i)
302 BackgroundCopyFileImpl *file;
304 /* We should return E_INVALIDARG in these cases. */
305 FIXME("Check for valid filenames and supported protocols\n");
307 hr = BackgroundCopyFileConstructor(This, pFileSet[i].RemoteName, pFileSet[i].LocalName, &file);
308 if (hr != S_OK) break;
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;
316 LeaveCriticalSection(&This->cs);
318 return hr;
321 static HRESULT WINAPI BackgroundCopyJob_AddFile(
322 IBackgroundCopyJob3 *iface,
323 LPCWSTR RemoteUrl,
324 LPCWSTR LocalName)
326 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
327 BG_FILE_INFO file;
329 TRACE("(%p)->(%s %s)\n", This, debugstr_w(RemoteUrl), debugstr_w(LocalName));
331 file.RemoteName = (LPWSTR)RemoteUrl;
332 file.LocalName = (LPWSTR)LocalName;
333 return IBackgroundCopyJob3_AddFileSet(iface, 1, &file);
336 static HRESULT WINAPI BackgroundCopyJob_EnumFiles(
337 IBackgroundCopyJob3 *iface,
338 IEnumBackgroundCopyFiles **enum_files)
340 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
341 TRACE("(%p)->(%p)\n", This, enum_files);
342 return EnumBackgroundCopyFilesConstructor(This, enum_files);
345 static HRESULT WINAPI BackgroundCopyJob_Suspend(
346 IBackgroundCopyJob3 *iface)
348 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
349 FIXME("(%p): stub\n", This);
350 return E_NOTIMPL;
353 static HRESULT WINAPI BackgroundCopyJob_Resume(
354 IBackgroundCopyJob3 *iface)
356 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
357 HRESULT rv = S_OK;
359 TRACE("(%p)\n", This);
361 EnterCriticalSection(&globalMgr.cs);
362 if (is_job_done(This))
364 rv = BG_E_INVALID_STATE;
366 else if (This->jobProgress.FilesTransferred == This->jobProgress.FilesTotal)
368 rv = BG_E_EMPTY;
370 else if (This->state != BG_JOB_STATE_CONNECTING
371 && This->state != BG_JOB_STATE_TRANSFERRING)
373 This->state = BG_JOB_STATE_QUEUED;
374 SetEvent(globalMgr.jobEvent);
376 LeaveCriticalSection(&globalMgr.cs);
378 return rv;
381 static HRESULT WINAPI BackgroundCopyJob_Cancel(
382 IBackgroundCopyJob3 *iface)
384 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
385 HRESULT rv = S_OK;
387 TRACE("(%p)\n", This);
389 EnterCriticalSection(&This->cs);
391 if (is_job_done(This))
393 rv = BG_E_INVALID_STATE;
395 else
397 BackgroundCopyFileImpl *file;
399 if (This->state == BG_JOB_STATE_CONNECTING || This->state == BG_JOB_STATE_TRANSFERRING)
401 This->state = BG_JOB_STATE_CANCELLED;
402 SetEvent(This->cancel);
404 LeaveCriticalSection(&This->cs);
405 WaitForSingleObject(This->done, INFINITE);
406 EnterCriticalSection(&This->cs);
409 LIST_FOR_EACH_ENTRY(file, &This->files, BackgroundCopyFileImpl, entryFromJob)
411 if (file->tempFileName[0] && !DeleteFileW(file->tempFileName))
413 WARN("Couldn't delete %s (%u)\n", debugstr_w(file->tempFileName), GetLastError());
414 rv = BG_S_UNABLE_TO_DELETE_FILES;
416 if (file->info.LocalName && !DeleteFileW(file->info.LocalName))
418 WARN("Couldn't delete %s (%u)\n", debugstr_w(file->info.LocalName), GetLastError());
419 rv = BG_S_UNABLE_TO_DELETE_FILES;
422 This->state = BG_JOB_STATE_CANCELLED;
425 LeaveCriticalSection(&This->cs);
426 return rv;
429 static HRESULT WINAPI BackgroundCopyJob_Complete(
430 IBackgroundCopyJob3 *iface)
432 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
433 HRESULT rv = S_OK;
435 TRACE("(%p)\n", This);
437 EnterCriticalSection(&This->cs);
439 if (is_job_done(This))
441 rv = BG_E_INVALID_STATE;
443 else
445 BackgroundCopyFileImpl *file;
446 LIST_FOR_EACH_ENTRY(file, &This->files, BackgroundCopyFileImpl, entryFromJob)
448 if (file->fileProgress.Completed)
450 if (!MoveFileExW(file->tempFileName, file->info.LocalName,
451 (MOVEFILE_COPY_ALLOWED
452 | MOVEFILE_REPLACE_EXISTING
453 | MOVEFILE_WRITE_THROUGH)))
455 ERR("Couldn't rename file %s -> %s\n",
456 debugstr_w(file->tempFileName),
457 debugstr_w(file->info.LocalName));
458 rv = BG_S_PARTIAL_COMPLETE;
461 else
462 rv = BG_S_PARTIAL_COMPLETE;
466 This->state = BG_JOB_STATE_ACKNOWLEDGED;
467 LeaveCriticalSection(&This->cs);
469 return rv;
472 static HRESULT WINAPI BackgroundCopyJob_GetId(
473 IBackgroundCopyJob3 *iface,
474 GUID *pVal)
476 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
477 TRACE("(%p)->(%p)\n", This, pVal);
478 *pVal = This->jobId;
479 return S_OK;
482 static HRESULT WINAPI BackgroundCopyJob_GetType(
483 IBackgroundCopyJob3 *iface,
484 BG_JOB_TYPE *pVal)
486 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
488 TRACE("(%p)->(%p)\n", This, pVal);
490 if (!pVal)
491 return E_INVALIDARG;
493 *pVal = This->type;
494 return S_OK;
497 static HRESULT WINAPI BackgroundCopyJob_GetProgress(
498 IBackgroundCopyJob3 *iface,
499 BG_JOB_PROGRESS *pVal)
501 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
503 TRACE("(%p)->(%p)\n", This, pVal);
505 if (!pVal)
506 return E_INVALIDARG;
508 EnterCriticalSection(&This->cs);
509 pVal->BytesTotal = This->jobProgress.BytesTotal;
510 pVal->BytesTransferred = This->jobProgress.BytesTransferred;
511 pVal->FilesTotal = This->jobProgress.FilesTotal;
512 pVal->FilesTransferred = This->jobProgress.FilesTransferred;
513 LeaveCriticalSection(&This->cs);
515 return S_OK;
518 static HRESULT WINAPI BackgroundCopyJob_GetTimes(
519 IBackgroundCopyJob3 *iface,
520 BG_JOB_TIMES *pVal)
522 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
523 FIXME("(%p)->(%p): stub\n", This, pVal);
524 return E_NOTIMPL;
527 static HRESULT WINAPI BackgroundCopyJob_GetState(
528 IBackgroundCopyJob3 *iface,
529 BG_JOB_STATE *pVal)
531 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
533 TRACE("(%p)->(%p)\n", This, pVal);
535 if (!pVal)
536 return E_INVALIDARG;
538 /* Don't think we need a critical section for this */
539 *pVal = This->state;
540 return S_OK;
543 static HRESULT WINAPI BackgroundCopyJob_GetError(
544 IBackgroundCopyJob3 *iface,
545 IBackgroundCopyError **ppError)
547 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface);
549 TRACE("(%p)->(%p)\n", job, ppError);
551 if (!job->error.context) return BG_E_ERROR_INFORMATION_UNAVAILABLE;
553 return create_copy_error(job->error.context, job->error.code, job->error.file, ppError);
556 static HRESULT WINAPI BackgroundCopyJob_GetOwner(
557 IBackgroundCopyJob3 *iface,
558 LPWSTR *pVal)
560 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
561 FIXME("(%p)->(%p): stub\n", This, pVal);
562 return E_NOTIMPL;
565 static HRESULT WINAPI BackgroundCopyJob_SetDisplayName(
566 IBackgroundCopyJob3 *iface,
567 LPCWSTR Val)
569 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
570 FIXME("(%p)->(%s): stub\n", This, debugstr_w(Val));
571 return E_NOTIMPL;
574 static HRESULT WINAPI BackgroundCopyJob_GetDisplayName(
575 IBackgroundCopyJob3 *iface,
576 LPWSTR *pVal)
578 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
580 TRACE("(%p)->(%p)\n", This, pVal);
582 return return_strval(This->displayName, pVal);
585 static HRESULT WINAPI BackgroundCopyJob_SetDescription(
586 IBackgroundCopyJob3 *iface,
587 LPCWSTR Val)
589 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
590 static const int max_description_len = 1024;
591 HRESULT hr = S_OK;
592 int len;
594 TRACE("(%p)->(%s)\n", This, debugstr_w(Val));
596 if (!Val) return E_INVALIDARG;
598 len = strlenW(Val);
599 if (len > max_description_len) return BG_E_STRING_TOO_LONG;
601 EnterCriticalSection(&This->cs);
603 if (is_job_done(This))
605 hr = BG_E_INVALID_STATE;
607 else
609 HeapFree(GetProcessHeap(), 0, This->description);
610 if ((This->description = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR))))
611 strcpyW(This->description, Val);
612 else
613 hr = E_OUTOFMEMORY;
616 LeaveCriticalSection(&This->cs);
618 return hr;
621 static HRESULT WINAPI BackgroundCopyJob_GetDescription(
622 IBackgroundCopyJob3 *iface,
623 LPWSTR *pVal)
625 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
627 TRACE("(%p)->(%p)\n", This, pVal);
629 return return_strval(This->description, pVal);
632 static HRESULT WINAPI BackgroundCopyJob_SetPriority(
633 IBackgroundCopyJob3 *iface,
634 BG_JOB_PRIORITY Val)
636 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
637 FIXME("(%p)->(%d): stub\n", This, Val);
638 return S_OK;
641 static HRESULT WINAPI BackgroundCopyJob_GetPriority(
642 IBackgroundCopyJob3 *iface,
643 BG_JOB_PRIORITY *pVal)
645 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
646 FIXME("(%p)->(%p): stub\n", This, pVal);
647 return E_NOTIMPL;
650 static HRESULT WINAPI BackgroundCopyJob_SetNotifyFlags(
651 IBackgroundCopyJob3 *iface,
652 ULONG Val)
654 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
655 static const ULONG valid_flags = BG_NOTIFY_JOB_TRANSFERRED |
656 BG_NOTIFY_JOB_ERROR |
657 BG_NOTIFY_DISABLE |
658 BG_NOTIFY_JOB_MODIFICATION |
659 BG_NOTIFY_FILE_TRANSFERRED;
661 TRACE("(%p)->(0x%x)\n", This, Val);
663 if (is_job_done(This)) return BG_E_INVALID_STATE;
664 if (Val & ~valid_flags) return E_NOTIMPL;
665 This->notify_flags = Val;
666 return S_OK;
669 static HRESULT WINAPI BackgroundCopyJob_GetNotifyFlags(
670 IBackgroundCopyJob3 *iface,
671 ULONG *pVal)
673 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
675 TRACE("(%p)->(%p)\n", This, pVal);
677 if (!pVal) return E_INVALIDARG;
679 *pVal = This->notify_flags;
681 return S_OK;
684 static HRESULT WINAPI BackgroundCopyJob_SetNotifyInterface(
685 IBackgroundCopyJob3 *iface,
686 IUnknown *Val)
688 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
689 HRESULT hr = S_OK;
691 TRACE("(%p)->(%p)\n", This, Val);
693 if (is_job_done(This)) return BG_E_INVALID_STATE;
695 if (This->callback)
697 IBackgroundCopyCallback2_Release(This->callback);
698 This->callback = NULL;
699 This->callback2 = FALSE;
702 if (Val)
704 hr = IUnknown_QueryInterface(Val, &IID_IBackgroundCopyCallback2, (void**)&This->callback);
705 if (FAILED(hr))
706 hr = IUnknown_QueryInterface(Val, &IID_IBackgroundCopyCallback, (void**)&This->callback);
707 else
708 This->callback2 = TRUE;
711 return hr;
714 static HRESULT WINAPI BackgroundCopyJob_GetNotifyInterface(
715 IBackgroundCopyJob3 *iface,
716 IUnknown **pVal)
718 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
720 TRACE("(%p)->(%p)\n", This, pVal);
722 if (!pVal) return E_INVALIDARG;
724 *pVal = (IUnknown*)This->callback;
725 if (*pVal)
726 IUnknown_AddRef(*pVal);
728 return S_OK;
731 static HRESULT WINAPI BackgroundCopyJob_SetMinimumRetryDelay(
732 IBackgroundCopyJob3 *iface,
733 ULONG Seconds)
735 FIXME("%u\n", Seconds);
736 return S_OK;
739 static HRESULT WINAPI BackgroundCopyJob_GetMinimumRetryDelay(
740 IBackgroundCopyJob3 *iface,
741 ULONG *Seconds)
743 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
744 FIXME("(%p)->(%p): stub\n", This, Seconds);
745 *Seconds = 30;
746 return S_OK;
749 static HRESULT WINAPI BackgroundCopyJob_SetNoProgressTimeout(
750 IBackgroundCopyJob3 *iface,
751 ULONG Seconds)
753 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
754 FIXME("(%p)->(%d): stub\n", This, Seconds);
755 return S_OK;
758 static HRESULT WINAPI BackgroundCopyJob_GetNoProgressTimeout(
759 IBackgroundCopyJob3 *iface,
760 ULONG *Seconds)
762 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
763 FIXME("(%p)->(%p): stub\n", This, Seconds);
764 *Seconds = 900;
765 return S_OK;
768 static HRESULT WINAPI BackgroundCopyJob_GetErrorCount(
769 IBackgroundCopyJob3 *iface,
770 ULONG *Errors)
772 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
773 FIXME("(%p)->(%p): stub\n", This, Errors);
774 return E_NOTIMPL;
777 static HRESULT WINAPI BackgroundCopyJob_SetProxySettings(
778 IBackgroundCopyJob3 *iface,
779 BG_JOB_PROXY_USAGE ProxyUsage,
780 const WCHAR *ProxyList,
781 const WCHAR *ProxyBypassList)
783 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
784 FIXME("(%p)->(%d %s %s): stub\n", This, ProxyUsage, debugstr_w(ProxyList), debugstr_w(ProxyBypassList));
785 return E_NOTIMPL;
788 static HRESULT WINAPI BackgroundCopyJob_GetProxySettings(
789 IBackgroundCopyJob3 *iface,
790 BG_JOB_PROXY_USAGE *pProxyUsage,
791 LPWSTR *pProxyList,
792 LPWSTR *pProxyBypassList)
794 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
795 FIXME("(%p)->(%p %p %p): stub\n", This, pProxyUsage, pProxyList, pProxyBypassList);
796 return E_NOTIMPL;
799 static HRESULT WINAPI BackgroundCopyJob_TakeOwnership(
800 IBackgroundCopyJob3 *iface)
802 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
803 FIXME("(%p): stub\n", This);
804 return E_NOTIMPL;
807 static HRESULT WINAPI BackgroundCopyJob_SetNotifyCmdLine(
808 IBackgroundCopyJob3 *iface,
809 LPCWSTR prog,
810 LPCWSTR params)
812 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
813 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(prog), debugstr_w(params));
814 return E_NOTIMPL;
817 static HRESULT WINAPI BackgroundCopyJob_GetNotifyCmdLine(
818 IBackgroundCopyJob3 *iface,
819 LPWSTR *prog,
820 LPWSTR *params)
822 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
823 FIXME("(%p)->(%p %p): stub\n", This, prog, params);
824 return E_NOTIMPL;
827 static HRESULT WINAPI BackgroundCopyJob_GetReplyProgress(
828 IBackgroundCopyJob3 *iface,
829 BG_JOB_REPLY_PROGRESS *progress)
831 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
832 FIXME("(%p)->(%p): stub\n", This, progress);
833 return E_NOTIMPL;
836 static HRESULT WINAPI BackgroundCopyJob_GetReplyData(
837 IBackgroundCopyJob3 *iface,
838 byte **pBuffer,
839 UINT64 *pLength)
841 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
842 FIXME("(%p)->(%p %p): stub\n", This, pBuffer, pLength);
843 return E_NOTIMPL;
846 static HRESULT WINAPI BackgroundCopyJob_SetReplyFileName(
847 IBackgroundCopyJob3 *iface,
848 LPCWSTR filename)
850 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
851 FIXME("(%p)->(%s): stub\n", This, debugstr_w(filename));
852 return E_NOTIMPL;
855 static HRESULT WINAPI BackgroundCopyJob_GetReplyFileName(
856 IBackgroundCopyJob3 *iface,
857 LPWSTR *pFilename)
859 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
860 FIXME("(%p)->(%p): stub\n", This, pFilename);
861 return E_NOTIMPL;
864 static int index_from_target(BG_AUTH_TARGET target)
866 if (!target || target > BG_AUTH_TARGET_PROXY) return -1;
867 return target - 1;
870 static int index_from_scheme(BG_AUTH_SCHEME scheme)
872 if (!scheme || scheme > BG_AUTH_SCHEME_PASSPORT) return -1;
873 return scheme - 1;
876 static HRESULT WINAPI BackgroundCopyJob_SetCredentials(
877 IBackgroundCopyJob3 *iface,
878 BG_AUTH_CREDENTIALS *cred)
880 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface);
881 BG_AUTH_CREDENTIALS *new_cred;
882 int idx_target, idx_scheme;
884 TRACE("(%p)->(%p)\n", job, cred);
886 if ((idx_target = index_from_target(cred->Target)) < 0) return BG_E_INVALID_AUTH_TARGET;
887 if ((idx_scheme = index_from_scheme(cred->Scheme)) < 0) return BG_E_INVALID_AUTH_SCHEME;
888 new_cred = &job->http_options.creds[idx_target][idx_scheme];
890 EnterCriticalSection(&job->cs);
892 new_cred->Target = cred->Target;
893 new_cred->Scheme = cred->Scheme;
895 if (cred->Credentials.Basic.UserName)
897 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.UserName);
898 new_cred->Credentials.Basic.UserName = strdupW(cred->Credentials.Basic.UserName);
900 if (cred->Credentials.Basic.Password)
902 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.Password);
903 new_cred->Credentials.Basic.Password = strdupW(cred->Credentials.Basic.Password);
906 LeaveCriticalSection(&job->cs);
907 return S_OK;
910 static HRESULT WINAPI BackgroundCopyJob_RemoveCredentials(
911 IBackgroundCopyJob3 *iface,
912 BG_AUTH_TARGET target,
913 BG_AUTH_SCHEME scheme)
915 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface);
916 BG_AUTH_CREDENTIALS *new_cred;
917 int idx_target, idx_scheme;
919 TRACE("(%p)->(%u %u)\n", job, target, scheme);
921 if ((idx_target = index_from_target(target)) < 0) return BG_E_INVALID_AUTH_TARGET;
922 if ((idx_scheme = index_from_scheme(scheme)) < 0) return BG_E_INVALID_AUTH_SCHEME;
923 new_cred = &job->http_options.creds[idx_target][idx_scheme];
925 EnterCriticalSection(&job->cs);
927 new_cred->Target = new_cred->Scheme = 0;
928 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.UserName);
929 new_cred->Credentials.Basic.UserName = NULL;
930 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.Password);
931 new_cred->Credentials.Basic.Password = NULL;
933 LeaveCriticalSection(&job->cs);
934 return S_OK;
937 static HRESULT WINAPI BackgroundCopyJob_ReplaceRemotePrefix(
938 IBackgroundCopyJob3 *iface,
939 LPCWSTR OldPrefix,
940 LPCWSTR NewPrefix)
942 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
943 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(OldPrefix), debugstr_w(NewPrefix));
944 return S_OK;
947 static HRESULT WINAPI BackgroundCopyJob_AddFileWithRanges(
948 IBackgroundCopyJob3 *iface,
949 LPCWSTR RemoteUrl,
950 LPCWSTR LocalName,
951 DWORD RangeCount,
952 BG_FILE_RANGE Ranges[])
954 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
955 FIXME("(%p)->(%s %s %u %p): stub\n", This, debugstr_w(RemoteUrl), debugstr_w(LocalName), RangeCount, Ranges);
956 return S_OK;
959 static HRESULT WINAPI BackgroundCopyJob_SetFileACLFlags(
960 IBackgroundCopyJob3 *iface,
961 DWORD Flags)
963 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
964 FIXME("(%p)->(%x): stub\n", This, Flags);
965 return S_OK;
968 static HRESULT WINAPI BackgroundCopyJob_GetFileACLFlags(
969 IBackgroundCopyJob3 *iface,
970 DWORD *Flags)
972 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
973 FIXME("(%p)->(%p): stub\n", This, Flags);
974 return S_OK;
977 static const IBackgroundCopyJob3Vtbl BackgroundCopyJob3Vtbl =
979 BackgroundCopyJob_QueryInterface,
980 BackgroundCopyJob_AddRef,
981 BackgroundCopyJob_Release,
982 BackgroundCopyJob_AddFileSet,
983 BackgroundCopyJob_AddFile,
984 BackgroundCopyJob_EnumFiles,
985 BackgroundCopyJob_Suspend,
986 BackgroundCopyJob_Resume,
987 BackgroundCopyJob_Cancel,
988 BackgroundCopyJob_Complete,
989 BackgroundCopyJob_GetId,
990 BackgroundCopyJob_GetType,
991 BackgroundCopyJob_GetProgress,
992 BackgroundCopyJob_GetTimes,
993 BackgroundCopyJob_GetState,
994 BackgroundCopyJob_GetError,
995 BackgroundCopyJob_GetOwner,
996 BackgroundCopyJob_SetDisplayName,
997 BackgroundCopyJob_GetDisplayName,
998 BackgroundCopyJob_SetDescription,
999 BackgroundCopyJob_GetDescription,
1000 BackgroundCopyJob_SetPriority,
1001 BackgroundCopyJob_GetPriority,
1002 BackgroundCopyJob_SetNotifyFlags,
1003 BackgroundCopyJob_GetNotifyFlags,
1004 BackgroundCopyJob_SetNotifyInterface,
1005 BackgroundCopyJob_GetNotifyInterface,
1006 BackgroundCopyJob_SetMinimumRetryDelay,
1007 BackgroundCopyJob_GetMinimumRetryDelay,
1008 BackgroundCopyJob_SetNoProgressTimeout,
1009 BackgroundCopyJob_GetNoProgressTimeout,
1010 BackgroundCopyJob_GetErrorCount,
1011 BackgroundCopyJob_SetProxySettings,
1012 BackgroundCopyJob_GetProxySettings,
1013 BackgroundCopyJob_TakeOwnership,
1014 BackgroundCopyJob_SetNotifyCmdLine,
1015 BackgroundCopyJob_GetNotifyCmdLine,
1016 BackgroundCopyJob_GetReplyProgress,
1017 BackgroundCopyJob_GetReplyData,
1018 BackgroundCopyJob_SetReplyFileName,
1019 BackgroundCopyJob_GetReplyFileName,
1020 BackgroundCopyJob_SetCredentials,
1021 BackgroundCopyJob_RemoveCredentials,
1022 BackgroundCopyJob_ReplaceRemotePrefix,
1023 BackgroundCopyJob_AddFileWithRanges,
1024 BackgroundCopyJob_SetFileACLFlags,
1025 BackgroundCopyJob_GetFileACLFlags
1028 static inline BackgroundCopyJobImpl *impl_from_IBackgroundCopyJobHttpOptions(
1029 IBackgroundCopyJobHttpOptions *iface)
1031 return CONTAINING_RECORD(iface, BackgroundCopyJobImpl, IBackgroundCopyJobHttpOptions_iface);
1034 static HRESULT WINAPI http_options_QueryInterface(
1035 IBackgroundCopyJobHttpOptions *iface,
1036 REFIID riid,
1037 void **ppvObject)
1039 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1040 return IBackgroundCopyJob3_QueryInterface(&job->IBackgroundCopyJob3_iface, riid, ppvObject);
1043 static ULONG WINAPI http_options_AddRef(
1044 IBackgroundCopyJobHttpOptions *iface)
1046 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1047 return IBackgroundCopyJob3_AddRef(&job->IBackgroundCopyJob3_iface);
1050 static ULONG WINAPI http_options_Release(
1051 IBackgroundCopyJobHttpOptions *iface)
1053 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1054 return IBackgroundCopyJob3_Release(&job->IBackgroundCopyJob3_iface);
1057 static HRESULT WINAPI http_options_SetClientCertificateByID(
1058 IBackgroundCopyJobHttpOptions *iface,
1059 BG_CERT_STORE_LOCATION StoreLocation,
1060 LPCWSTR StoreName,
1061 BYTE *pCertHashBlob)
1063 FIXME("\n");
1064 return E_NOTIMPL;
1067 static HRESULT WINAPI http_options_SetClientCertificateByName(
1068 IBackgroundCopyJobHttpOptions *iface,
1069 BG_CERT_STORE_LOCATION StoreLocation,
1070 LPCWSTR StoreName,
1071 LPCWSTR SubjectName)
1073 FIXME("\n");
1074 return E_NOTIMPL;
1077 static HRESULT WINAPI http_options_RemoveClientCertificate(
1078 IBackgroundCopyJobHttpOptions *iface)
1080 FIXME("\n");
1081 return E_NOTIMPL;
1084 static HRESULT WINAPI http_options_GetClientCertificate(
1085 IBackgroundCopyJobHttpOptions *iface,
1086 BG_CERT_STORE_LOCATION *pStoreLocation,
1087 LPWSTR *pStoreName,
1088 BYTE **ppCertHashBlob,
1089 LPWSTR *pSubjectName)
1091 FIXME("\n");
1092 return E_NOTIMPL;
1095 static HRESULT WINAPI http_options_SetCustomHeaders(
1096 IBackgroundCopyJobHttpOptions *iface,
1097 LPCWSTR RequestHeaders)
1099 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1101 TRACE("(%p)->(%s)\n", iface, debugstr_w(RequestHeaders));
1103 EnterCriticalSection(&job->cs);
1105 if (RequestHeaders)
1107 WCHAR *headers = strdupW(RequestHeaders);
1108 if (!headers)
1110 LeaveCriticalSection(&job->cs);
1111 return E_OUTOFMEMORY;
1113 HeapFree(GetProcessHeap(), 0, job->http_options.headers);
1114 job->http_options.headers = headers;
1116 else
1118 HeapFree(GetProcessHeap(), 0, job->http_options.headers);
1119 job->http_options.headers = NULL;
1122 LeaveCriticalSection(&job->cs);
1123 return S_OK;
1126 static HRESULT WINAPI http_options_GetCustomHeaders(
1127 IBackgroundCopyJobHttpOptions *iface,
1128 LPWSTR *pRequestHeaders)
1130 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1132 TRACE("(%p)->(%p)\n", iface, pRequestHeaders);
1134 EnterCriticalSection(&job->cs);
1136 if (job->http_options.headers)
1138 WCHAR *headers = co_strdupW(job->http_options.headers);
1139 if (!headers)
1141 LeaveCriticalSection(&job->cs);
1142 return E_OUTOFMEMORY;
1144 *pRequestHeaders = headers;
1145 LeaveCriticalSection(&job->cs);
1146 return S_OK;
1149 *pRequestHeaders = NULL;
1150 LeaveCriticalSection(&job->cs);
1151 return S_FALSE;
1154 static HRESULT WINAPI http_options_SetSecurityFlags(
1155 IBackgroundCopyJobHttpOptions *iface,
1156 ULONG Flags)
1158 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1160 TRACE("(%p)->(0x%08x)\n", iface, Flags);
1162 job->http_options.flags = Flags;
1163 return S_OK;
1166 static HRESULT WINAPI http_options_GetSecurityFlags(
1167 IBackgroundCopyJobHttpOptions *iface,
1168 ULONG *pFlags)
1170 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1172 TRACE("(%p)->(%p)\n", iface, pFlags);
1174 *pFlags = job->http_options.flags;
1175 return S_OK;
1178 static const IBackgroundCopyJobHttpOptionsVtbl http_options_vtbl =
1180 http_options_QueryInterface,
1181 http_options_AddRef,
1182 http_options_Release,
1183 http_options_SetClientCertificateByID,
1184 http_options_SetClientCertificateByName,
1185 http_options_RemoveClientCertificate,
1186 http_options_GetClientCertificate,
1187 http_options_SetCustomHeaders,
1188 http_options_GetCustomHeaders,
1189 http_options_SetSecurityFlags,
1190 http_options_GetSecurityFlags
1193 HRESULT BackgroundCopyJobConstructor(LPCWSTR displayName, BG_JOB_TYPE type, GUID *job_id, BackgroundCopyJobImpl **job)
1195 HRESULT hr;
1196 BackgroundCopyJobImpl *This;
1197 int n;
1199 TRACE("(%s,%d,%p)\n", debugstr_w(displayName), type, job);
1201 This = HeapAlloc(GetProcessHeap(), 0, sizeof *This);
1202 if (!This)
1203 return E_OUTOFMEMORY;
1205 This->IBackgroundCopyJob3_iface.lpVtbl = &BackgroundCopyJob3Vtbl;
1206 This->IBackgroundCopyJobHttpOptions_iface.lpVtbl = &http_options_vtbl;
1207 InitializeCriticalSection(&This->cs);
1208 This->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BackgroundCopyJobImpl.cs");
1210 This->ref = 1;
1211 This->type = type;
1213 n = (strlenW(displayName) + 1) * sizeof *displayName;
1214 This->displayName = HeapAlloc(GetProcessHeap(), 0, n);
1215 if (!This->displayName)
1217 This->cs.DebugInfo->Spare[0] = 0;
1218 DeleteCriticalSection(&This->cs);
1219 HeapFree(GetProcessHeap(), 0, This);
1220 return E_OUTOFMEMORY;
1222 memcpy(This->displayName, displayName, n);
1224 hr = CoCreateGuid(&This->jobId);
1225 if (FAILED(hr))
1227 This->cs.DebugInfo->Spare[0] = 0;
1228 DeleteCriticalSection(&This->cs);
1229 HeapFree(GetProcessHeap(), 0, This->displayName);
1230 HeapFree(GetProcessHeap(), 0, This);
1231 return hr;
1233 *job_id = This->jobId;
1235 list_init(&This->files);
1236 This->jobProgress.BytesTotal = 0;
1237 This->jobProgress.BytesTransferred = 0;
1238 This->jobProgress.FilesTotal = 0;
1239 This->jobProgress.FilesTransferred = 0;
1241 This->state = BG_JOB_STATE_SUSPENDED;
1242 This->description = NULL;
1243 This->notify_flags = BG_NOTIFY_JOB_ERROR | BG_NOTIFY_JOB_TRANSFERRED;
1244 This->callback = NULL;
1245 This->callback2 = FALSE;
1247 This->error.context = 0;
1248 This->error.code = 0;
1249 This->error.file = NULL;
1251 memset(&This->http_options, 0, sizeof(This->http_options));
1253 This->wait = CreateEventW(NULL, FALSE, FALSE, NULL);
1254 This->cancel = CreateEventW(NULL, FALSE, FALSE, NULL);
1255 This->done = CreateEventW(NULL, FALSE, FALSE, NULL);
1257 *job = This;
1259 TRACE("created job %s:%p\n", debugstr_guid(&This->jobId), This);
1261 return S_OK;
1264 void processJob(BackgroundCopyJobImpl *job)
1266 for (;;)
1268 BackgroundCopyFileImpl *file;
1269 BOOL done = TRUE;
1271 EnterCriticalSection(&job->cs);
1272 LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob)
1273 if (!file->fileProgress.Completed)
1275 done = FALSE;
1276 break;
1278 LeaveCriticalSection(&job->cs);
1279 if (done)
1281 transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRED);
1282 return;
1285 if (!processFile(file, job))
1286 return;