include: Print contents of VT_LPSTR and VT_LPWSTR variants in wine_dbgstr_variant.
[wine.git] / dlls / qmgr / job.c
bloba12e5111c5245224dc73d1e1165d740a30f2073b
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 This->error.context = 0;
375 This->error.code = S_OK;
376 if (This->error.file)
378 IBackgroundCopyFile2_Release(This->error.file);
379 This->error.file = NULL;
381 SetEvent(globalMgr.jobEvent);
383 LeaveCriticalSection(&globalMgr.cs);
385 return rv;
388 static HRESULT WINAPI BackgroundCopyJob_Cancel(
389 IBackgroundCopyJob3 *iface)
391 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
392 HRESULT rv = S_OK;
394 TRACE("(%p)\n", This);
396 EnterCriticalSection(&This->cs);
398 if (is_job_done(This))
400 rv = BG_E_INVALID_STATE;
402 else
404 BackgroundCopyFileImpl *file;
406 if (This->state == BG_JOB_STATE_CONNECTING || This->state == BG_JOB_STATE_TRANSFERRING)
408 This->state = BG_JOB_STATE_CANCELLED;
409 SetEvent(This->cancel);
411 LeaveCriticalSection(&This->cs);
412 WaitForSingleObject(This->done, INFINITE);
413 EnterCriticalSection(&This->cs);
416 LIST_FOR_EACH_ENTRY(file, &This->files, BackgroundCopyFileImpl, entryFromJob)
418 if (file->tempFileName[0] && !DeleteFileW(file->tempFileName))
420 WARN("Couldn't delete %s (%u)\n", debugstr_w(file->tempFileName), GetLastError());
421 rv = BG_S_UNABLE_TO_DELETE_FILES;
423 if (file->info.LocalName && !DeleteFileW(file->info.LocalName))
425 WARN("Couldn't delete %s (%u)\n", debugstr_w(file->info.LocalName), GetLastError());
426 rv = BG_S_UNABLE_TO_DELETE_FILES;
429 This->state = BG_JOB_STATE_CANCELLED;
432 LeaveCriticalSection(&This->cs);
433 return rv;
436 static HRESULT WINAPI BackgroundCopyJob_Complete(
437 IBackgroundCopyJob3 *iface)
439 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
440 HRESULT rv = S_OK;
442 TRACE("(%p)\n", This);
444 EnterCriticalSection(&This->cs);
446 if (is_job_done(This))
448 rv = BG_E_INVALID_STATE;
450 else
452 BackgroundCopyFileImpl *file;
453 LIST_FOR_EACH_ENTRY(file, &This->files, BackgroundCopyFileImpl, entryFromJob)
455 if (file->fileProgress.Completed)
457 if (!MoveFileExW(file->tempFileName, file->info.LocalName,
458 (MOVEFILE_COPY_ALLOWED
459 | MOVEFILE_REPLACE_EXISTING
460 | MOVEFILE_WRITE_THROUGH)))
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;
468 else
469 rv = BG_S_PARTIAL_COMPLETE;
473 This->state = BG_JOB_STATE_ACKNOWLEDGED;
474 LeaveCriticalSection(&This->cs);
476 return rv;
479 static HRESULT WINAPI BackgroundCopyJob_GetId(
480 IBackgroundCopyJob3 *iface,
481 GUID *pVal)
483 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
484 TRACE("(%p)->(%p)\n", This, pVal);
485 *pVal = This->jobId;
486 return S_OK;
489 static HRESULT WINAPI BackgroundCopyJob_GetType(
490 IBackgroundCopyJob3 *iface,
491 BG_JOB_TYPE *pVal)
493 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
495 TRACE("(%p)->(%p)\n", This, pVal);
497 if (!pVal)
498 return E_INVALIDARG;
500 *pVal = This->type;
501 return S_OK;
504 static HRESULT WINAPI BackgroundCopyJob_GetProgress(
505 IBackgroundCopyJob3 *iface,
506 BG_JOB_PROGRESS *pVal)
508 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
510 TRACE("(%p)->(%p)\n", This, pVal);
512 if (!pVal)
513 return E_INVALIDARG;
515 EnterCriticalSection(&This->cs);
516 *pVal = This->jobProgress;
517 LeaveCriticalSection(&This->cs);
519 return S_OK;
522 static HRESULT WINAPI BackgroundCopyJob_GetTimes(
523 IBackgroundCopyJob3 *iface,
524 BG_JOB_TIMES *pVal)
526 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
527 FIXME("(%p)->(%p): stub\n", This, pVal);
528 return E_NOTIMPL;
531 static HRESULT WINAPI BackgroundCopyJob_GetState(
532 IBackgroundCopyJob3 *iface,
533 BG_JOB_STATE *pVal)
535 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
537 TRACE("(%p)->(%p)\n", This, pVal);
539 if (!pVal)
540 return E_INVALIDARG;
542 /* Don't think we need a critical section for this */
543 *pVal = This->state;
544 return S_OK;
547 static HRESULT WINAPI BackgroundCopyJob_GetError(
548 IBackgroundCopyJob3 *iface,
549 IBackgroundCopyError **ppError)
551 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface);
553 TRACE("(%p)->(%p)\n", job, ppError);
555 if (!job->error.context) return BG_E_ERROR_INFORMATION_UNAVAILABLE;
557 return create_copy_error(job->error.context, job->error.code, job->error.file, ppError);
560 static HRESULT WINAPI BackgroundCopyJob_GetOwner(
561 IBackgroundCopyJob3 *iface,
562 LPWSTR *pVal)
564 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
565 FIXME("(%p)->(%p): stub\n", This, pVal);
566 return E_NOTIMPL;
569 static HRESULT WINAPI BackgroundCopyJob_SetDisplayName(
570 IBackgroundCopyJob3 *iface,
571 LPCWSTR Val)
573 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
574 FIXME("(%p)->(%s): stub\n", This, debugstr_w(Val));
575 return E_NOTIMPL;
578 static HRESULT WINAPI BackgroundCopyJob_GetDisplayName(
579 IBackgroundCopyJob3 *iface,
580 LPWSTR *pVal)
582 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
584 TRACE("(%p)->(%p)\n", This, pVal);
586 return return_strval(This->displayName, pVal);
589 static HRESULT WINAPI BackgroundCopyJob_SetDescription(
590 IBackgroundCopyJob3 *iface,
591 LPCWSTR Val)
593 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
594 static const int max_description_len = 1024;
595 HRESULT hr = S_OK;
596 int len;
598 TRACE("(%p)->(%s)\n", This, debugstr_w(Val));
600 if (!Val) return E_INVALIDARG;
602 len = strlenW(Val);
603 if (len > max_description_len) return BG_E_STRING_TOO_LONG;
605 EnterCriticalSection(&This->cs);
607 if (is_job_done(This))
609 hr = BG_E_INVALID_STATE;
611 else
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;
620 LeaveCriticalSection(&This->cs);
622 return hr;
625 static HRESULT WINAPI BackgroundCopyJob_GetDescription(
626 IBackgroundCopyJob3 *iface,
627 LPWSTR *pVal)
629 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
631 TRACE("(%p)->(%p)\n", This, pVal);
633 return return_strval(This->description, pVal);
636 static HRESULT WINAPI BackgroundCopyJob_SetPriority(
637 IBackgroundCopyJob3 *iface,
638 BG_JOB_PRIORITY Val)
640 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
641 FIXME("(%p)->(%d): stub\n", This, Val);
642 return S_OK;
645 static HRESULT WINAPI BackgroundCopyJob_GetPriority(
646 IBackgroundCopyJob3 *iface,
647 BG_JOB_PRIORITY *pVal)
649 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
650 FIXME("(%p)->(%p): stub\n", This, pVal);
651 return E_NOTIMPL;
654 static HRESULT WINAPI BackgroundCopyJob_SetNotifyFlags(
655 IBackgroundCopyJob3 *iface,
656 ULONG Val)
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;
665 TRACE("(%p)->(0x%x)\n", This, Val);
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;
673 static HRESULT WINAPI BackgroundCopyJob_GetNotifyFlags(
674 IBackgroundCopyJob3 *iface,
675 ULONG *pVal)
677 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
679 TRACE("(%p)->(%p)\n", This, pVal);
681 if (!pVal) return E_INVALIDARG;
683 *pVal = This->notify_flags;
685 return S_OK;
688 static HRESULT WINAPI BackgroundCopyJob_SetNotifyInterface(
689 IBackgroundCopyJob3 *iface,
690 IUnknown *Val)
692 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
693 HRESULT hr = S_OK;
695 TRACE("(%p)->(%p)\n", This, Val);
697 if (is_job_done(This)) return BG_E_INVALID_STATE;
699 if (This->callback)
701 IBackgroundCopyCallback2_Release(This->callback);
702 This->callback = NULL;
703 This->callback2 = FALSE;
706 if (Val)
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;
715 return hr;
718 static HRESULT WINAPI BackgroundCopyJob_GetNotifyInterface(
719 IBackgroundCopyJob3 *iface,
720 IUnknown **pVal)
722 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
724 TRACE("(%p)->(%p)\n", This, pVal);
726 if (!pVal) return E_INVALIDARG;
728 *pVal = (IUnknown*)This->callback;
729 if (*pVal)
730 IUnknown_AddRef(*pVal);
732 return S_OK;
735 static HRESULT WINAPI BackgroundCopyJob_SetMinimumRetryDelay(
736 IBackgroundCopyJob3 *iface,
737 ULONG Seconds)
739 FIXME("%u\n", Seconds);
740 return S_OK;
743 static HRESULT WINAPI BackgroundCopyJob_GetMinimumRetryDelay(
744 IBackgroundCopyJob3 *iface,
745 ULONG *Seconds)
747 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
748 FIXME("(%p)->(%p): stub\n", This, Seconds);
749 *Seconds = 30;
750 return S_OK;
753 static HRESULT WINAPI BackgroundCopyJob_SetNoProgressTimeout(
754 IBackgroundCopyJob3 *iface,
755 ULONG Seconds)
757 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
758 FIXME("(%p)->(%d): stub\n", This, Seconds);
759 return S_OK;
762 static HRESULT WINAPI BackgroundCopyJob_GetNoProgressTimeout(
763 IBackgroundCopyJob3 *iface,
764 ULONG *Seconds)
766 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
767 FIXME("(%p)->(%p): stub\n", This, Seconds);
768 *Seconds = 900;
769 return S_OK;
772 static HRESULT WINAPI BackgroundCopyJob_GetErrorCount(
773 IBackgroundCopyJob3 *iface,
774 ULONG *Errors)
776 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
777 FIXME("(%p)->(%p): stub\n", This, Errors);
778 return E_NOTIMPL;
781 static HRESULT WINAPI BackgroundCopyJob_SetProxySettings(
782 IBackgroundCopyJob3 *iface,
783 BG_JOB_PROXY_USAGE ProxyUsage,
784 const WCHAR *ProxyList,
785 const WCHAR *ProxyBypassList)
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;
792 static HRESULT WINAPI BackgroundCopyJob_GetProxySettings(
793 IBackgroundCopyJob3 *iface,
794 BG_JOB_PROXY_USAGE *pProxyUsage,
795 LPWSTR *pProxyList,
796 LPWSTR *pProxyBypassList)
798 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
799 FIXME("(%p)->(%p %p %p): stub\n", This, pProxyUsage, pProxyList, pProxyBypassList);
800 return E_NOTIMPL;
803 static HRESULT WINAPI BackgroundCopyJob_TakeOwnership(
804 IBackgroundCopyJob3 *iface)
806 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
807 FIXME("(%p): stub\n", This);
808 return E_NOTIMPL;
811 static HRESULT WINAPI BackgroundCopyJob_SetNotifyCmdLine(
812 IBackgroundCopyJob3 *iface,
813 LPCWSTR prog,
814 LPCWSTR params)
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;
821 static HRESULT WINAPI BackgroundCopyJob_GetNotifyCmdLine(
822 IBackgroundCopyJob3 *iface,
823 LPWSTR *prog,
824 LPWSTR *params)
826 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
827 FIXME("(%p)->(%p %p): stub\n", This, prog, params);
828 return E_NOTIMPL;
831 static HRESULT WINAPI BackgroundCopyJob_GetReplyProgress(
832 IBackgroundCopyJob3 *iface,
833 BG_JOB_REPLY_PROGRESS *progress)
835 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
836 FIXME("(%p)->(%p): stub\n", This, progress);
837 return E_NOTIMPL;
840 static HRESULT WINAPI BackgroundCopyJob_GetReplyData(
841 IBackgroundCopyJob3 *iface,
842 byte **pBuffer,
843 UINT64 *pLength)
845 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
846 FIXME("(%p)->(%p %p): stub\n", This, pBuffer, pLength);
847 return E_NOTIMPL;
850 static HRESULT WINAPI BackgroundCopyJob_SetReplyFileName(
851 IBackgroundCopyJob3 *iface,
852 LPCWSTR filename)
854 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
855 FIXME("(%p)->(%s): stub\n", This, debugstr_w(filename));
856 return E_NOTIMPL;
859 static HRESULT WINAPI BackgroundCopyJob_GetReplyFileName(
860 IBackgroundCopyJob3 *iface,
861 LPWSTR *pFilename)
863 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
864 FIXME("(%p)->(%p): stub\n", This, pFilename);
865 return E_NOTIMPL;
868 static int index_from_target(BG_AUTH_TARGET target)
870 if (!target || target > BG_AUTH_TARGET_PROXY) return -1;
871 return target - 1;
874 static int index_from_scheme(BG_AUTH_SCHEME scheme)
876 if (!scheme || scheme > BG_AUTH_SCHEME_PASSPORT) return -1;
877 return scheme - 1;
880 static HRESULT WINAPI BackgroundCopyJob_SetCredentials(
881 IBackgroundCopyJob3 *iface,
882 BG_AUTH_CREDENTIALS *cred)
884 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface);
885 BG_AUTH_CREDENTIALS *new_cred;
886 int idx_target, idx_scheme;
888 TRACE("(%p)->(%p)\n", job, cred);
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];
894 EnterCriticalSection(&job->cs);
896 new_cred->Target = cred->Target;
897 new_cred->Scheme = cred->Scheme;
899 if (cred->Credentials.Basic.UserName)
901 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.UserName);
902 new_cred->Credentials.Basic.UserName = strdupW(cred->Credentials.Basic.UserName);
904 if (cred->Credentials.Basic.Password)
906 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.Password);
907 new_cred->Credentials.Basic.Password = strdupW(cred->Credentials.Basic.Password);
910 LeaveCriticalSection(&job->cs);
911 return S_OK;
914 static HRESULT WINAPI BackgroundCopyJob_RemoveCredentials(
915 IBackgroundCopyJob3 *iface,
916 BG_AUTH_TARGET target,
917 BG_AUTH_SCHEME scheme)
919 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface);
920 BG_AUTH_CREDENTIALS *new_cred;
921 int idx_target, idx_scheme;
923 TRACE("(%p)->(%u %u)\n", job, target, scheme);
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];
929 EnterCriticalSection(&job->cs);
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;
937 LeaveCriticalSection(&job->cs);
938 return S_OK;
941 static HRESULT WINAPI BackgroundCopyJob_ReplaceRemotePrefix(
942 IBackgroundCopyJob3 *iface,
943 LPCWSTR OldPrefix,
944 LPCWSTR NewPrefix)
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;
951 static HRESULT WINAPI BackgroundCopyJob_AddFileWithRanges(
952 IBackgroundCopyJob3 *iface,
953 LPCWSTR RemoteUrl,
954 LPCWSTR LocalName,
955 DWORD RangeCount,
956 BG_FILE_RANGE Ranges[])
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;
963 static HRESULT WINAPI BackgroundCopyJob_SetFileACLFlags(
964 IBackgroundCopyJob3 *iface,
965 DWORD Flags)
967 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
968 FIXME("(%p)->(%x): stub\n", This, Flags);
969 return S_OK;
972 static HRESULT WINAPI BackgroundCopyJob_GetFileACLFlags(
973 IBackgroundCopyJob3 *iface,
974 DWORD *Flags)
976 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
977 FIXME("(%p)->(%p): stub\n", This, Flags);
978 return S_OK;
981 static const IBackgroundCopyJob3Vtbl BackgroundCopyJob3Vtbl =
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
1032 static inline BackgroundCopyJobImpl *impl_from_IBackgroundCopyJobHttpOptions(
1033 IBackgroundCopyJobHttpOptions *iface)
1035 return CONTAINING_RECORD(iface, BackgroundCopyJobImpl, IBackgroundCopyJobHttpOptions_iface);
1038 static HRESULT WINAPI http_options_QueryInterface(
1039 IBackgroundCopyJobHttpOptions *iface,
1040 REFIID riid,
1041 void **ppvObject)
1043 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1044 return IBackgroundCopyJob3_QueryInterface(&job->IBackgroundCopyJob3_iface, riid, ppvObject);
1047 static ULONG WINAPI http_options_AddRef(
1048 IBackgroundCopyJobHttpOptions *iface)
1050 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1051 return IBackgroundCopyJob3_AddRef(&job->IBackgroundCopyJob3_iface);
1054 static ULONG WINAPI http_options_Release(
1055 IBackgroundCopyJobHttpOptions *iface)
1057 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1058 return IBackgroundCopyJob3_Release(&job->IBackgroundCopyJob3_iface);
1061 static HRESULT WINAPI http_options_SetClientCertificateByID(
1062 IBackgroundCopyJobHttpOptions *iface,
1063 BG_CERT_STORE_LOCATION StoreLocation,
1064 LPCWSTR StoreName,
1065 BYTE *pCertHashBlob)
1067 FIXME("\n");
1068 return E_NOTIMPL;
1071 static HRESULT WINAPI http_options_SetClientCertificateByName(
1072 IBackgroundCopyJobHttpOptions *iface,
1073 BG_CERT_STORE_LOCATION StoreLocation,
1074 LPCWSTR StoreName,
1075 LPCWSTR SubjectName)
1077 FIXME("\n");
1078 return E_NOTIMPL;
1081 static HRESULT WINAPI http_options_RemoveClientCertificate(
1082 IBackgroundCopyJobHttpOptions *iface)
1084 FIXME("\n");
1085 return E_NOTIMPL;
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)
1095 FIXME("\n");
1096 return E_NOTIMPL;
1099 static HRESULT WINAPI http_options_SetCustomHeaders(
1100 IBackgroundCopyJobHttpOptions *iface,
1101 LPCWSTR RequestHeaders)
1103 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1105 TRACE("(%p)->(%s)\n", iface, debugstr_w(RequestHeaders));
1107 EnterCriticalSection(&job->cs);
1109 if (RequestHeaders)
1111 WCHAR *headers = strdupW(RequestHeaders);
1112 if (!headers)
1114 LeaveCriticalSection(&job->cs);
1115 return E_OUTOFMEMORY;
1117 HeapFree(GetProcessHeap(), 0, job->http_options.headers);
1118 job->http_options.headers = headers;
1120 else
1122 HeapFree(GetProcessHeap(), 0, job->http_options.headers);
1123 job->http_options.headers = NULL;
1126 LeaveCriticalSection(&job->cs);
1127 return S_OK;
1130 static HRESULT WINAPI http_options_GetCustomHeaders(
1131 IBackgroundCopyJobHttpOptions *iface,
1132 LPWSTR *pRequestHeaders)
1134 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1136 TRACE("(%p)->(%p)\n", iface, pRequestHeaders);
1138 EnterCriticalSection(&job->cs);
1140 if (job->http_options.headers)
1142 WCHAR *headers = co_strdupW(job->http_options.headers);
1143 if (!headers)
1145 LeaveCriticalSection(&job->cs);
1146 return E_OUTOFMEMORY;
1148 *pRequestHeaders = headers;
1149 LeaveCriticalSection(&job->cs);
1150 return S_OK;
1153 *pRequestHeaders = NULL;
1154 LeaveCriticalSection(&job->cs);
1155 return S_FALSE;
1158 static HRESULT WINAPI http_options_SetSecurityFlags(
1159 IBackgroundCopyJobHttpOptions *iface,
1160 ULONG Flags)
1162 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1164 TRACE("(%p)->(0x%08x)\n", iface, Flags);
1166 job->http_options.flags = Flags;
1167 return S_OK;
1170 static HRESULT WINAPI http_options_GetSecurityFlags(
1171 IBackgroundCopyJobHttpOptions *iface,
1172 ULONG *pFlags)
1174 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1176 TRACE("(%p)->(%p)\n", iface, pFlags);
1178 *pFlags = job->http_options.flags;
1179 return S_OK;
1182 static const IBackgroundCopyJobHttpOptionsVtbl http_options_vtbl =
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
1197 HRESULT BackgroundCopyJobConstructor(LPCWSTR displayName, BG_JOB_TYPE type, GUID *job_id, BackgroundCopyJobImpl **job)
1199 HRESULT hr;
1200 BackgroundCopyJobImpl *This;
1202 TRACE("(%s,%d,%p)\n", debugstr_w(displayName), type, job);
1204 This = HeapAlloc(GetProcessHeap(), 0, sizeof *This);
1205 if (!This)
1206 return E_OUTOFMEMORY;
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");
1213 This->ref = 1;
1214 This->type = type;
1216 This->displayName = strdupW(displayName);
1217 if (!This->displayName)
1219 This->cs.DebugInfo->Spare[0] = 0;
1220 DeleteCriticalSection(&This->cs);
1221 HeapFree(GetProcessHeap(), 0, This);
1222 return E_OUTOFMEMORY;
1225 hr = CoCreateGuid(&This->jobId);
1226 if (FAILED(hr))
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;
1234 *job_id = This->jobId;
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;
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;
1248 This->error.context = 0;
1249 This->error.code = S_OK;
1250 This->error.file = NULL;
1252 memset(&This->http_options, 0, sizeof(This->http_options));
1254 This->wait = CreateEventW(NULL, FALSE, FALSE, NULL);
1255 This->cancel = CreateEventW(NULL, FALSE, FALSE, NULL);
1256 This->done = CreateEventW(NULL, FALSE, FALSE, NULL);
1258 *job = This;
1260 TRACE("created job %s:%p\n", debugstr_guid(&This->jobId), This);
1262 return S_OK;
1265 void processJob(BackgroundCopyJobImpl *job)
1267 for (;;)
1269 BackgroundCopyFileImpl *file;
1270 BOOL done = TRUE;
1272 EnterCriticalSection(&job->cs);
1273 LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob)
1274 if (!file->fileProgress.Completed)
1276 done = FALSE;
1277 break;
1279 LeaveCriticalSection(&job->cs);
1280 if (done)
1282 transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRED);
1283 return;
1286 if (!processFile(file, job))
1287 return;