wined3d: Make wined3d_device_set_vs_consts_b() consistent with wined3d_device_set_vs_...
[wine.git] / dlls / qmgr / job.c
blob33e3bd2573991a450a95deb7b8b1979d91450caf
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 = This->error.code = 0;
375 if (This->error.file)
377 IBackgroundCopyFile2_Release(This->error.file);
378 This->error.file = NULL;
380 SetEvent(globalMgr.jobEvent);
382 LeaveCriticalSection(&globalMgr.cs);
384 return rv;
387 static HRESULT WINAPI BackgroundCopyJob_Cancel(
388 IBackgroundCopyJob3 *iface)
390 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
391 HRESULT rv = S_OK;
393 TRACE("(%p)\n", This);
395 EnterCriticalSection(&This->cs);
397 if (is_job_done(This))
399 rv = BG_E_INVALID_STATE;
401 else
403 BackgroundCopyFileImpl *file;
405 if (This->state == BG_JOB_STATE_CONNECTING || This->state == BG_JOB_STATE_TRANSFERRING)
407 This->state = BG_JOB_STATE_CANCELLED;
408 SetEvent(This->cancel);
410 LeaveCriticalSection(&This->cs);
411 WaitForSingleObject(This->done, INFINITE);
412 EnterCriticalSection(&This->cs);
415 LIST_FOR_EACH_ENTRY(file, &This->files, BackgroundCopyFileImpl, entryFromJob)
417 if (file->tempFileName[0] && !DeleteFileW(file->tempFileName))
419 WARN("Couldn't delete %s (%u)\n", debugstr_w(file->tempFileName), GetLastError());
420 rv = BG_S_UNABLE_TO_DELETE_FILES;
422 if (file->info.LocalName && !DeleteFileW(file->info.LocalName))
424 WARN("Couldn't delete %s (%u)\n", debugstr_w(file->info.LocalName), GetLastError());
425 rv = BG_S_UNABLE_TO_DELETE_FILES;
428 This->state = BG_JOB_STATE_CANCELLED;
431 LeaveCriticalSection(&This->cs);
432 return rv;
435 static HRESULT WINAPI BackgroundCopyJob_Complete(
436 IBackgroundCopyJob3 *iface)
438 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
439 HRESULT rv = S_OK;
441 TRACE("(%p)\n", This);
443 EnterCriticalSection(&This->cs);
445 if (is_job_done(This))
447 rv = BG_E_INVALID_STATE;
449 else
451 BackgroundCopyFileImpl *file;
452 LIST_FOR_EACH_ENTRY(file, &This->files, BackgroundCopyFileImpl, entryFromJob)
454 if (file->fileProgress.Completed)
456 if (!MoveFileExW(file->tempFileName, file->info.LocalName,
457 (MOVEFILE_COPY_ALLOWED
458 | MOVEFILE_REPLACE_EXISTING
459 | MOVEFILE_WRITE_THROUGH)))
461 ERR("Couldn't rename file %s -> %s\n",
462 debugstr_w(file->tempFileName),
463 debugstr_w(file->info.LocalName));
464 rv = BG_S_PARTIAL_COMPLETE;
467 else
468 rv = BG_S_PARTIAL_COMPLETE;
472 This->state = BG_JOB_STATE_ACKNOWLEDGED;
473 LeaveCriticalSection(&This->cs);
475 return rv;
478 static HRESULT WINAPI BackgroundCopyJob_GetId(
479 IBackgroundCopyJob3 *iface,
480 GUID *pVal)
482 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
483 TRACE("(%p)->(%p)\n", This, pVal);
484 *pVal = This->jobId;
485 return S_OK;
488 static HRESULT WINAPI BackgroundCopyJob_GetType(
489 IBackgroundCopyJob3 *iface,
490 BG_JOB_TYPE *pVal)
492 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
494 TRACE("(%p)->(%p)\n", This, pVal);
496 if (!pVal)
497 return E_INVALIDARG;
499 *pVal = This->type;
500 return S_OK;
503 static HRESULT WINAPI BackgroundCopyJob_GetProgress(
504 IBackgroundCopyJob3 *iface,
505 BG_JOB_PROGRESS *pVal)
507 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
509 TRACE("(%p)->(%p)\n", This, pVal);
511 if (!pVal)
512 return E_INVALIDARG;
514 EnterCriticalSection(&This->cs);
515 *pVal = This->jobProgress;
516 LeaveCriticalSection(&This->cs);
518 return S_OK;
521 static HRESULT WINAPI BackgroundCopyJob_GetTimes(
522 IBackgroundCopyJob3 *iface,
523 BG_JOB_TIMES *pVal)
525 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
526 FIXME("(%p)->(%p): stub\n", This, pVal);
527 return E_NOTIMPL;
530 static HRESULT WINAPI BackgroundCopyJob_GetState(
531 IBackgroundCopyJob3 *iface,
532 BG_JOB_STATE *pVal)
534 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
536 TRACE("(%p)->(%p)\n", This, pVal);
538 if (!pVal)
539 return E_INVALIDARG;
541 /* Don't think we need a critical section for this */
542 *pVal = This->state;
543 return S_OK;
546 static HRESULT WINAPI BackgroundCopyJob_GetError(
547 IBackgroundCopyJob3 *iface,
548 IBackgroundCopyError **ppError)
550 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface);
552 TRACE("(%p)->(%p)\n", job, ppError);
554 if (!job->error.context) return BG_E_ERROR_INFORMATION_UNAVAILABLE;
556 return create_copy_error(job->error.context, job->error.code, job->error.file, ppError);
559 static HRESULT WINAPI BackgroundCopyJob_GetOwner(
560 IBackgroundCopyJob3 *iface,
561 LPWSTR *pVal)
563 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
564 FIXME("(%p)->(%p): stub\n", This, pVal);
565 return E_NOTIMPL;
568 static HRESULT WINAPI BackgroundCopyJob_SetDisplayName(
569 IBackgroundCopyJob3 *iface,
570 LPCWSTR Val)
572 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
573 FIXME("(%p)->(%s): stub\n", This, debugstr_w(Val));
574 return E_NOTIMPL;
577 static HRESULT WINAPI BackgroundCopyJob_GetDisplayName(
578 IBackgroundCopyJob3 *iface,
579 LPWSTR *pVal)
581 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
583 TRACE("(%p)->(%p)\n", This, pVal);
585 return return_strval(This->displayName, pVal);
588 static HRESULT WINAPI BackgroundCopyJob_SetDescription(
589 IBackgroundCopyJob3 *iface,
590 LPCWSTR Val)
592 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
593 static const int max_description_len = 1024;
594 HRESULT hr = S_OK;
595 int len;
597 TRACE("(%p)->(%s)\n", This, debugstr_w(Val));
599 if (!Val) return E_INVALIDARG;
601 len = strlenW(Val);
602 if (len > max_description_len) return BG_E_STRING_TOO_LONG;
604 EnterCriticalSection(&This->cs);
606 if (is_job_done(This))
608 hr = BG_E_INVALID_STATE;
610 else
612 HeapFree(GetProcessHeap(), 0, This->description);
613 if ((This->description = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR))))
614 strcpyW(This->description, Val);
615 else
616 hr = E_OUTOFMEMORY;
619 LeaveCriticalSection(&This->cs);
621 return hr;
624 static HRESULT WINAPI BackgroundCopyJob_GetDescription(
625 IBackgroundCopyJob3 *iface,
626 LPWSTR *pVal)
628 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
630 TRACE("(%p)->(%p)\n", This, pVal);
632 return return_strval(This->description, pVal);
635 static HRESULT WINAPI BackgroundCopyJob_SetPriority(
636 IBackgroundCopyJob3 *iface,
637 BG_JOB_PRIORITY Val)
639 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
640 FIXME("(%p)->(%d): stub\n", This, Val);
641 return S_OK;
644 static HRESULT WINAPI BackgroundCopyJob_GetPriority(
645 IBackgroundCopyJob3 *iface,
646 BG_JOB_PRIORITY *pVal)
648 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
649 FIXME("(%p)->(%p): stub\n", This, pVal);
650 return E_NOTIMPL;
653 static HRESULT WINAPI BackgroundCopyJob_SetNotifyFlags(
654 IBackgroundCopyJob3 *iface,
655 ULONG Val)
657 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
658 static const ULONG valid_flags = BG_NOTIFY_JOB_TRANSFERRED |
659 BG_NOTIFY_JOB_ERROR |
660 BG_NOTIFY_DISABLE |
661 BG_NOTIFY_JOB_MODIFICATION |
662 BG_NOTIFY_FILE_TRANSFERRED;
664 TRACE("(%p)->(0x%x)\n", This, Val);
666 if (is_job_done(This)) return BG_E_INVALID_STATE;
667 if (Val & ~valid_flags) return E_NOTIMPL;
668 This->notify_flags = Val;
669 return S_OK;
672 static HRESULT WINAPI BackgroundCopyJob_GetNotifyFlags(
673 IBackgroundCopyJob3 *iface,
674 ULONG *pVal)
676 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
678 TRACE("(%p)->(%p)\n", This, pVal);
680 if (!pVal) return E_INVALIDARG;
682 *pVal = This->notify_flags;
684 return S_OK;
687 static HRESULT WINAPI BackgroundCopyJob_SetNotifyInterface(
688 IBackgroundCopyJob3 *iface,
689 IUnknown *Val)
691 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
692 HRESULT hr = S_OK;
694 TRACE("(%p)->(%p)\n", This, Val);
696 if (is_job_done(This)) return BG_E_INVALID_STATE;
698 if (This->callback)
700 IBackgroundCopyCallback2_Release(This->callback);
701 This->callback = NULL;
702 This->callback2 = FALSE;
705 if (Val)
707 hr = IUnknown_QueryInterface(Val, &IID_IBackgroundCopyCallback2, (void**)&This->callback);
708 if (FAILED(hr))
709 hr = IUnknown_QueryInterface(Val, &IID_IBackgroundCopyCallback, (void**)&This->callback);
710 else
711 This->callback2 = TRUE;
714 return hr;
717 static HRESULT WINAPI BackgroundCopyJob_GetNotifyInterface(
718 IBackgroundCopyJob3 *iface,
719 IUnknown **pVal)
721 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
723 TRACE("(%p)->(%p)\n", This, pVal);
725 if (!pVal) return E_INVALIDARG;
727 *pVal = (IUnknown*)This->callback;
728 if (*pVal)
729 IUnknown_AddRef(*pVal);
731 return S_OK;
734 static HRESULT WINAPI BackgroundCopyJob_SetMinimumRetryDelay(
735 IBackgroundCopyJob3 *iface,
736 ULONG Seconds)
738 FIXME("%u\n", Seconds);
739 return S_OK;
742 static HRESULT WINAPI BackgroundCopyJob_GetMinimumRetryDelay(
743 IBackgroundCopyJob3 *iface,
744 ULONG *Seconds)
746 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
747 FIXME("(%p)->(%p): stub\n", This, Seconds);
748 *Seconds = 30;
749 return S_OK;
752 static HRESULT WINAPI BackgroundCopyJob_SetNoProgressTimeout(
753 IBackgroundCopyJob3 *iface,
754 ULONG Seconds)
756 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
757 FIXME("(%p)->(%d): stub\n", This, Seconds);
758 return S_OK;
761 static HRESULT WINAPI BackgroundCopyJob_GetNoProgressTimeout(
762 IBackgroundCopyJob3 *iface,
763 ULONG *Seconds)
765 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
766 FIXME("(%p)->(%p): stub\n", This, Seconds);
767 *Seconds = 900;
768 return S_OK;
771 static HRESULT WINAPI BackgroundCopyJob_GetErrorCount(
772 IBackgroundCopyJob3 *iface,
773 ULONG *Errors)
775 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
776 FIXME("(%p)->(%p): stub\n", This, Errors);
777 return E_NOTIMPL;
780 static HRESULT WINAPI BackgroundCopyJob_SetProxySettings(
781 IBackgroundCopyJob3 *iface,
782 BG_JOB_PROXY_USAGE ProxyUsage,
783 const WCHAR *ProxyList,
784 const WCHAR *ProxyBypassList)
786 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
787 FIXME("(%p)->(%d %s %s): stub\n", This, ProxyUsage, debugstr_w(ProxyList), debugstr_w(ProxyBypassList));
788 return E_NOTIMPL;
791 static HRESULT WINAPI BackgroundCopyJob_GetProxySettings(
792 IBackgroundCopyJob3 *iface,
793 BG_JOB_PROXY_USAGE *pProxyUsage,
794 LPWSTR *pProxyList,
795 LPWSTR *pProxyBypassList)
797 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
798 FIXME("(%p)->(%p %p %p): stub\n", This, pProxyUsage, pProxyList, pProxyBypassList);
799 return E_NOTIMPL;
802 static HRESULT WINAPI BackgroundCopyJob_TakeOwnership(
803 IBackgroundCopyJob3 *iface)
805 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
806 FIXME("(%p): stub\n", This);
807 return E_NOTIMPL;
810 static HRESULT WINAPI BackgroundCopyJob_SetNotifyCmdLine(
811 IBackgroundCopyJob3 *iface,
812 LPCWSTR prog,
813 LPCWSTR params)
815 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
816 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(prog), debugstr_w(params));
817 return E_NOTIMPL;
820 static HRESULT WINAPI BackgroundCopyJob_GetNotifyCmdLine(
821 IBackgroundCopyJob3 *iface,
822 LPWSTR *prog,
823 LPWSTR *params)
825 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
826 FIXME("(%p)->(%p %p): stub\n", This, prog, params);
827 return E_NOTIMPL;
830 static HRESULT WINAPI BackgroundCopyJob_GetReplyProgress(
831 IBackgroundCopyJob3 *iface,
832 BG_JOB_REPLY_PROGRESS *progress)
834 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
835 FIXME("(%p)->(%p): stub\n", This, progress);
836 return E_NOTIMPL;
839 static HRESULT WINAPI BackgroundCopyJob_GetReplyData(
840 IBackgroundCopyJob3 *iface,
841 byte **pBuffer,
842 UINT64 *pLength)
844 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
845 FIXME("(%p)->(%p %p): stub\n", This, pBuffer, pLength);
846 return E_NOTIMPL;
849 static HRESULT WINAPI BackgroundCopyJob_SetReplyFileName(
850 IBackgroundCopyJob3 *iface,
851 LPCWSTR filename)
853 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
854 FIXME("(%p)->(%s): stub\n", This, debugstr_w(filename));
855 return E_NOTIMPL;
858 static HRESULT WINAPI BackgroundCopyJob_GetReplyFileName(
859 IBackgroundCopyJob3 *iface,
860 LPWSTR *pFilename)
862 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
863 FIXME("(%p)->(%p): stub\n", This, pFilename);
864 return E_NOTIMPL;
867 static int index_from_target(BG_AUTH_TARGET target)
869 if (!target || target > BG_AUTH_TARGET_PROXY) return -1;
870 return target - 1;
873 static int index_from_scheme(BG_AUTH_SCHEME scheme)
875 if (!scheme || scheme > BG_AUTH_SCHEME_PASSPORT) return -1;
876 return scheme - 1;
879 static HRESULT WINAPI BackgroundCopyJob_SetCredentials(
880 IBackgroundCopyJob3 *iface,
881 BG_AUTH_CREDENTIALS *cred)
883 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface);
884 BG_AUTH_CREDENTIALS *new_cred;
885 int idx_target, idx_scheme;
887 TRACE("(%p)->(%p)\n", job, cred);
889 if ((idx_target = index_from_target(cred->Target)) < 0) return BG_E_INVALID_AUTH_TARGET;
890 if ((idx_scheme = index_from_scheme(cred->Scheme)) < 0) return BG_E_INVALID_AUTH_SCHEME;
891 new_cred = &job->http_options.creds[idx_target][idx_scheme];
893 EnterCriticalSection(&job->cs);
895 new_cred->Target = cred->Target;
896 new_cred->Scheme = cred->Scheme;
898 if (cred->Credentials.Basic.UserName)
900 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.UserName);
901 new_cred->Credentials.Basic.UserName = strdupW(cred->Credentials.Basic.UserName);
903 if (cred->Credentials.Basic.Password)
905 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.Password);
906 new_cred->Credentials.Basic.Password = strdupW(cred->Credentials.Basic.Password);
909 LeaveCriticalSection(&job->cs);
910 return S_OK;
913 static HRESULT WINAPI BackgroundCopyJob_RemoveCredentials(
914 IBackgroundCopyJob3 *iface,
915 BG_AUTH_TARGET target,
916 BG_AUTH_SCHEME scheme)
918 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface);
919 BG_AUTH_CREDENTIALS *new_cred;
920 int idx_target, idx_scheme;
922 TRACE("(%p)->(%u %u)\n", job, target, scheme);
924 if ((idx_target = index_from_target(target)) < 0) return BG_E_INVALID_AUTH_TARGET;
925 if ((idx_scheme = index_from_scheme(scheme)) < 0) return BG_E_INVALID_AUTH_SCHEME;
926 new_cred = &job->http_options.creds[idx_target][idx_scheme];
928 EnterCriticalSection(&job->cs);
930 new_cred->Target = new_cred->Scheme = 0;
931 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.UserName);
932 new_cred->Credentials.Basic.UserName = NULL;
933 HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.Password);
934 new_cred->Credentials.Basic.Password = NULL;
936 LeaveCriticalSection(&job->cs);
937 return S_OK;
940 static HRESULT WINAPI BackgroundCopyJob_ReplaceRemotePrefix(
941 IBackgroundCopyJob3 *iface,
942 LPCWSTR OldPrefix,
943 LPCWSTR NewPrefix)
945 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
946 FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(OldPrefix), debugstr_w(NewPrefix));
947 return S_OK;
950 static HRESULT WINAPI BackgroundCopyJob_AddFileWithRanges(
951 IBackgroundCopyJob3 *iface,
952 LPCWSTR RemoteUrl,
953 LPCWSTR LocalName,
954 DWORD RangeCount,
955 BG_FILE_RANGE Ranges[])
957 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
958 FIXME("(%p)->(%s %s %u %p): stub\n", This, debugstr_w(RemoteUrl), debugstr_w(LocalName), RangeCount, Ranges);
959 return S_OK;
962 static HRESULT WINAPI BackgroundCopyJob_SetFileACLFlags(
963 IBackgroundCopyJob3 *iface,
964 DWORD Flags)
966 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
967 FIXME("(%p)->(%x): stub\n", This, Flags);
968 return S_OK;
971 static HRESULT WINAPI BackgroundCopyJob_GetFileACLFlags(
972 IBackgroundCopyJob3 *iface,
973 DWORD *Flags)
975 BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
976 FIXME("(%p)->(%p): stub\n", This, Flags);
977 return S_OK;
980 static const IBackgroundCopyJob3Vtbl BackgroundCopyJob3Vtbl =
982 BackgroundCopyJob_QueryInterface,
983 BackgroundCopyJob_AddRef,
984 BackgroundCopyJob_Release,
985 BackgroundCopyJob_AddFileSet,
986 BackgroundCopyJob_AddFile,
987 BackgroundCopyJob_EnumFiles,
988 BackgroundCopyJob_Suspend,
989 BackgroundCopyJob_Resume,
990 BackgroundCopyJob_Cancel,
991 BackgroundCopyJob_Complete,
992 BackgroundCopyJob_GetId,
993 BackgroundCopyJob_GetType,
994 BackgroundCopyJob_GetProgress,
995 BackgroundCopyJob_GetTimes,
996 BackgroundCopyJob_GetState,
997 BackgroundCopyJob_GetError,
998 BackgroundCopyJob_GetOwner,
999 BackgroundCopyJob_SetDisplayName,
1000 BackgroundCopyJob_GetDisplayName,
1001 BackgroundCopyJob_SetDescription,
1002 BackgroundCopyJob_GetDescription,
1003 BackgroundCopyJob_SetPriority,
1004 BackgroundCopyJob_GetPriority,
1005 BackgroundCopyJob_SetNotifyFlags,
1006 BackgroundCopyJob_GetNotifyFlags,
1007 BackgroundCopyJob_SetNotifyInterface,
1008 BackgroundCopyJob_GetNotifyInterface,
1009 BackgroundCopyJob_SetMinimumRetryDelay,
1010 BackgroundCopyJob_GetMinimumRetryDelay,
1011 BackgroundCopyJob_SetNoProgressTimeout,
1012 BackgroundCopyJob_GetNoProgressTimeout,
1013 BackgroundCopyJob_GetErrorCount,
1014 BackgroundCopyJob_SetProxySettings,
1015 BackgroundCopyJob_GetProxySettings,
1016 BackgroundCopyJob_TakeOwnership,
1017 BackgroundCopyJob_SetNotifyCmdLine,
1018 BackgroundCopyJob_GetNotifyCmdLine,
1019 BackgroundCopyJob_GetReplyProgress,
1020 BackgroundCopyJob_GetReplyData,
1021 BackgroundCopyJob_SetReplyFileName,
1022 BackgroundCopyJob_GetReplyFileName,
1023 BackgroundCopyJob_SetCredentials,
1024 BackgroundCopyJob_RemoveCredentials,
1025 BackgroundCopyJob_ReplaceRemotePrefix,
1026 BackgroundCopyJob_AddFileWithRanges,
1027 BackgroundCopyJob_SetFileACLFlags,
1028 BackgroundCopyJob_GetFileACLFlags
1031 static inline BackgroundCopyJobImpl *impl_from_IBackgroundCopyJobHttpOptions(
1032 IBackgroundCopyJobHttpOptions *iface)
1034 return CONTAINING_RECORD(iface, BackgroundCopyJobImpl, IBackgroundCopyJobHttpOptions_iface);
1037 static HRESULT WINAPI http_options_QueryInterface(
1038 IBackgroundCopyJobHttpOptions *iface,
1039 REFIID riid,
1040 void **ppvObject)
1042 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1043 return IBackgroundCopyJob3_QueryInterface(&job->IBackgroundCopyJob3_iface, riid, ppvObject);
1046 static ULONG WINAPI http_options_AddRef(
1047 IBackgroundCopyJobHttpOptions *iface)
1049 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1050 return IBackgroundCopyJob3_AddRef(&job->IBackgroundCopyJob3_iface);
1053 static ULONG WINAPI http_options_Release(
1054 IBackgroundCopyJobHttpOptions *iface)
1056 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1057 return IBackgroundCopyJob3_Release(&job->IBackgroundCopyJob3_iface);
1060 static HRESULT WINAPI http_options_SetClientCertificateByID(
1061 IBackgroundCopyJobHttpOptions *iface,
1062 BG_CERT_STORE_LOCATION StoreLocation,
1063 LPCWSTR StoreName,
1064 BYTE *pCertHashBlob)
1066 FIXME("\n");
1067 return E_NOTIMPL;
1070 static HRESULT WINAPI http_options_SetClientCertificateByName(
1071 IBackgroundCopyJobHttpOptions *iface,
1072 BG_CERT_STORE_LOCATION StoreLocation,
1073 LPCWSTR StoreName,
1074 LPCWSTR SubjectName)
1076 FIXME("\n");
1077 return E_NOTIMPL;
1080 static HRESULT WINAPI http_options_RemoveClientCertificate(
1081 IBackgroundCopyJobHttpOptions *iface)
1083 FIXME("\n");
1084 return E_NOTIMPL;
1087 static HRESULT WINAPI http_options_GetClientCertificate(
1088 IBackgroundCopyJobHttpOptions *iface,
1089 BG_CERT_STORE_LOCATION *pStoreLocation,
1090 LPWSTR *pStoreName,
1091 BYTE **ppCertHashBlob,
1092 LPWSTR *pSubjectName)
1094 FIXME("\n");
1095 return E_NOTIMPL;
1098 static HRESULT WINAPI http_options_SetCustomHeaders(
1099 IBackgroundCopyJobHttpOptions *iface,
1100 LPCWSTR RequestHeaders)
1102 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1104 TRACE("(%p)->(%s)\n", iface, debugstr_w(RequestHeaders));
1106 EnterCriticalSection(&job->cs);
1108 if (RequestHeaders)
1110 WCHAR *headers = strdupW(RequestHeaders);
1111 if (!headers)
1113 LeaveCriticalSection(&job->cs);
1114 return E_OUTOFMEMORY;
1116 HeapFree(GetProcessHeap(), 0, job->http_options.headers);
1117 job->http_options.headers = headers;
1119 else
1121 HeapFree(GetProcessHeap(), 0, job->http_options.headers);
1122 job->http_options.headers = NULL;
1125 LeaveCriticalSection(&job->cs);
1126 return S_OK;
1129 static HRESULT WINAPI http_options_GetCustomHeaders(
1130 IBackgroundCopyJobHttpOptions *iface,
1131 LPWSTR *pRequestHeaders)
1133 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1135 TRACE("(%p)->(%p)\n", iface, pRequestHeaders);
1137 EnterCriticalSection(&job->cs);
1139 if (job->http_options.headers)
1141 WCHAR *headers = co_strdupW(job->http_options.headers);
1142 if (!headers)
1144 LeaveCriticalSection(&job->cs);
1145 return E_OUTOFMEMORY;
1147 *pRequestHeaders = headers;
1148 LeaveCriticalSection(&job->cs);
1149 return S_OK;
1152 *pRequestHeaders = NULL;
1153 LeaveCriticalSection(&job->cs);
1154 return S_FALSE;
1157 static HRESULT WINAPI http_options_SetSecurityFlags(
1158 IBackgroundCopyJobHttpOptions *iface,
1159 ULONG Flags)
1161 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1163 TRACE("(%p)->(0x%08x)\n", iface, Flags);
1165 job->http_options.flags = Flags;
1166 return S_OK;
1169 static HRESULT WINAPI http_options_GetSecurityFlags(
1170 IBackgroundCopyJobHttpOptions *iface,
1171 ULONG *pFlags)
1173 BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface);
1175 TRACE("(%p)->(%p)\n", iface, pFlags);
1177 *pFlags = job->http_options.flags;
1178 return S_OK;
1181 static const IBackgroundCopyJobHttpOptionsVtbl http_options_vtbl =
1183 http_options_QueryInterface,
1184 http_options_AddRef,
1185 http_options_Release,
1186 http_options_SetClientCertificateByID,
1187 http_options_SetClientCertificateByName,
1188 http_options_RemoveClientCertificate,
1189 http_options_GetClientCertificate,
1190 http_options_SetCustomHeaders,
1191 http_options_GetCustomHeaders,
1192 http_options_SetSecurityFlags,
1193 http_options_GetSecurityFlags
1196 HRESULT BackgroundCopyJobConstructor(LPCWSTR displayName, BG_JOB_TYPE type, GUID *job_id, BackgroundCopyJobImpl **job)
1198 HRESULT hr;
1199 BackgroundCopyJobImpl *This;
1201 TRACE("(%s,%d,%p)\n", debugstr_w(displayName), type, job);
1203 This = HeapAlloc(GetProcessHeap(), 0, sizeof *This);
1204 if (!This)
1205 return E_OUTOFMEMORY;
1207 This->IBackgroundCopyJob3_iface.lpVtbl = &BackgroundCopyJob3Vtbl;
1208 This->IBackgroundCopyJobHttpOptions_iface.lpVtbl = &http_options_vtbl;
1209 InitializeCriticalSection(&This->cs);
1210 This->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BackgroundCopyJobImpl.cs");
1212 This->ref = 1;
1213 This->type = type;
1215 This->displayName = strdupW(displayName);
1216 if (!This->displayName)
1218 This->cs.DebugInfo->Spare[0] = 0;
1219 DeleteCriticalSection(&This->cs);
1220 HeapFree(GetProcessHeap(), 0, This);
1221 return E_OUTOFMEMORY;
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;