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
26 #include "wine/debug.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(qmgr
);
30 BOOL
transitionJobState(BackgroundCopyJobImpl
*job
, BG_JOB_STATE from
, BG_JOB_STATE to
)
34 EnterCriticalSection(&globalMgr
.cs
);
35 if (job
->state
== from
)
40 LeaveCriticalSection(&globalMgr
.cs
);
46 IBackgroundCopyError IBackgroundCopyError_iface
;
48 BG_ERROR_CONTEXT context
;
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
,
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
;
74 WARN("interface %s not supported\n", debugstr_guid(riid
));
78 IBackgroundCopyError_AddRef(iface
);
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
);
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
);
101 if (error
->file
) IBackgroundCopyFile2_Release(error
->file
);
102 HeapFree(GetProcessHeap(), 0, error
);
107 static HRESULT WINAPI
copy_error_GetError(
108 IBackgroundCopyError
*iface
,
109 BG_ERROR_CONTEXT
*pContext
,
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
);
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
);
133 IBackgroundCopyFile2_AddRef(error
->file
);
134 *pVal
= (IBackgroundCopyFile
*)error
->file
;
138 return BG_E_FILE_NOT_AVAILABLE
;
141 static HRESULT WINAPI
copy_error_GetErrorDescription(
142 IBackgroundCopyError
*iface
,
144 LPWSTR
*pErrorDescription
)
146 struct copy_error
*error
= impl_from_IBackgroundCopyError(iface
);
147 FIXME("(%p)->(%p)\n", error
, pErrorDescription
);
151 static HRESULT WINAPI
copy_error_GetErrorContextDescription(
152 IBackgroundCopyError
*iface
,
154 LPWSTR
*pContextDescription
)
156 struct copy_error
*error
= impl_from_IBackgroundCopyError(iface
);
157 FIXME("(%p)->(%p)\n", error
, pContextDescription
);
161 static HRESULT WINAPI
copy_error_GetProtocol(
162 IBackgroundCopyError
*iface
,
165 struct copy_error
*error
= impl_from_IBackgroundCopyError(iface
);
166 FIXME("(%p)->(%p)\n", error
, pProtocol
);
170 static const IBackgroundCopyErrorVtbl copy_error_vtbl
=
172 copy_error_QueryInterface
,
177 copy_error_GetErrorDescription
,
178 copy_error_GetErrorContextDescription
,
179 copy_error_GetProtocol
182 static HRESULT
create_copy_error(
183 BG_ERROR_CONTEXT context
,
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
= ©_error_vtbl
;
195 error
->context
= context
;
198 if (error
->file
) IBackgroundCopyFile2_AddRef(error
->file
);
200 *obj
= &error
->IBackgroundCopyError_iface
;
201 TRACE("returning iface %p\n", *obj
);
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
;
236 return E_NOINTERFACE
;
239 IBackgroundCopyJob3_AddRef(iface
);
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
);
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
);
260 This
->cs
.DebugInfo
->Spare
[0] = 0;
261 DeleteCriticalSection(&This
->cs
);
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
);
285 /*** IBackgroundCopyJob methods ***/
287 static HRESULT WINAPI
BackgroundCopyJob_AddFileSet(
288 IBackgroundCopyJob3
*iface
,
290 BG_FILE_INFO
*pFileSet
)
292 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
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
);
321 static HRESULT WINAPI
BackgroundCopyJob_AddFile(
322 IBackgroundCopyJob3
*iface
,
326 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
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
);
353 static HRESULT WINAPI
BackgroundCopyJob_Resume(
354 IBackgroundCopyJob3
*iface
)
356 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
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
)
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
);
381 static HRESULT WINAPI
BackgroundCopyJob_Cancel(
382 IBackgroundCopyJob3
*iface
)
384 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
387 TRACE("(%p)\n", This
);
389 EnterCriticalSection(&This
->cs
);
391 if (is_job_done(This
))
393 rv
= BG_E_INVALID_STATE
;
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
);
429 static HRESULT WINAPI
BackgroundCopyJob_Complete(
430 IBackgroundCopyJob3
*iface
)
432 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
435 TRACE("(%p)\n", This
);
437 EnterCriticalSection(&This
->cs
);
439 if (is_job_done(This
))
441 rv
= BG_E_INVALID_STATE
;
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
;
462 rv
= BG_S_PARTIAL_COMPLETE
;
466 This
->state
= BG_JOB_STATE_ACKNOWLEDGED
;
467 LeaveCriticalSection(&This
->cs
);
472 static HRESULT WINAPI
BackgroundCopyJob_GetId(
473 IBackgroundCopyJob3
*iface
,
476 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
477 TRACE("(%p)->(%p)\n", This
, pVal
);
482 static HRESULT WINAPI
BackgroundCopyJob_GetType(
483 IBackgroundCopyJob3
*iface
,
486 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
488 TRACE("(%p)->(%p)\n", This
, pVal
);
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
);
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
);
518 static HRESULT WINAPI
BackgroundCopyJob_GetTimes(
519 IBackgroundCopyJob3
*iface
,
522 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
523 FIXME("(%p)->(%p): stub\n", This
, pVal
);
527 static HRESULT WINAPI
BackgroundCopyJob_GetState(
528 IBackgroundCopyJob3
*iface
,
531 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
533 TRACE("(%p)->(%p)\n", This
, pVal
);
538 /* Don't think we need a critical section for this */
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
,
560 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
561 FIXME("(%p)->(%p): stub\n", This
, pVal
);
565 static HRESULT WINAPI
BackgroundCopyJob_SetDisplayName(
566 IBackgroundCopyJob3
*iface
,
569 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
570 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(Val
));
574 static HRESULT WINAPI
BackgroundCopyJob_GetDisplayName(
575 IBackgroundCopyJob3
*iface
,
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
,
589 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
590 static const int max_description_len
= 1024;
594 TRACE("(%p)->(%s)\n", This
, debugstr_w(Val
));
596 if (!Val
) return E_INVALIDARG
;
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
;
609 HeapFree(GetProcessHeap(), 0, This
->description
);
610 if ((This
->description
= HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
))))
611 strcpyW(This
->description
, Val
);
616 LeaveCriticalSection(&This
->cs
);
621 static HRESULT WINAPI
BackgroundCopyJob_GetDescription(
622 IBackgroundCopyJob3
*iface
,
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
,
636 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
637 FIXME("(%p)->(%d): stub\n", This
, Val
);
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
);
650 static HRESULT WINAPI
BackgroundCopyJob_SetNotifyFlags(
651 IBackgroundCopyJob3
*iface
,
654 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
655 static const ULONG valid_flags
= BG_NOTIFY_JOB_TRANSFERRED
|
656 BG_NOTIFY_JOB_ERROR
|
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
;
669 static HRESULT WINAPI
BackgroundCopyJob_GetNotifyFlags(
670 IBackgroundCopyJob3
*iface
,
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
;
684 static HRESULT WINAPI
BackgroundCopyJob_SetNotifyInterface(
685 IBackgroundCopyJob3
*iface
,
688 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
691 TRACE("(%p)->(%p)\n", This
, Val
);
693 if (is_job_done(This
)) return BG_E_INVALID_STATE
;
697 IBackgroundCopyCallback2_Release(This
->callback
);
698 This
->callback
= NULL
;
699 This
->callback2
= FALSE
;
704 hr
= IUnknown_QueryInterface(Val
, &IID_IBackgroundCopyCallback2
, (void**)&This
->callback
);
706 hr
= IUnknown_QueryInterface(Val
, &IID_IBackgroundCopyCallback
, (void**)&This
->callback
);
708 This
->callback2
= TRUE
;
714 static HRESULT WINAPI
BackgroundCopyJob_GetNotifyInterface(
715 IBackgroundCopyJob3
*iface
,
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
;
726 IUnknown_AddRef(*pVal
);
731 static HRESULT WINAPI
BackgroundCopyJob_SetMinimumRetryDelay(
732 IBackgroundCopyJob3
*iface
,
735 FIXME("%u\n", Seconds
);
739 static HRESULT WINAPI
BackgroundCopyJob_GetMinimumRetryDelay(
740 IBackgroundCopyJob3
*iface
,
743 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
744 FIXME("(%p)->(%p): stub\n", This
, Seconds
);
749 static HRESULT WINAPI
BackgroundCopyJob_SetNoProgressTimeout(
750 IBackgroundCopyJob3
*iface
,
753 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
754 FIXME("(%p)->(%d): stub\n", This
, Seconds
);
758 static HRESULT WINAPI
BackgroundCopyJob_GetNoProgressTimeout(
759 IBackgroundCopyJob3
*iface
,
762 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
763 FIXME("(%p)->(%p): stub\n", This
, Seconds
);
768 static HRESULT WINAPI
BackgroundCopyJob_GetErrorCount(
769 IBackgroundCopyJob3
*iface
,
772 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
773 FIXME("(%p)->(%p): stub\n", This
, Errors
);
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
));
788 static HRESULT WINAPI
BackgroundCopyJob_GetProxySettings(
789 IBackgroundCopyJob3
*iface
,
790 BG_JOB_PROXY_USAGE
*pProxyUsage
,
792 LPWSTR
*pProxyBypassList
)
794 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
795 FIXME("(%p)->(%p %p %p): stub\n", This
, pProxyUsage
, pProxyList
, pProxyBypassList
);
799 static HRESULT WINAPI
BackgroundCopyJob_TakeOwnership(
800 IBackgroundCopyJob3
*iface
)
802 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
803 FIXME("(%p): stub\n", This
);
807 static HRESULT WINAPI
BackgroundCopyJob_SetNotifyCmdLine(
808 IBackgroundCopyJob3
*iface
,
812 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
813 FIXME("(%p)->(%s %s): stub\n", This
, debugstr_w(prog
), debugstr_w(params
));
817 static HRESULT WINAPI
BackgroundCopyJob_GetNotifyCmdLine(
818 IBackgroundCopyJob3
*iface
,
822 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
823 FIXME("(%p)->(%p %p): stub\n", This
, prog
, params
);
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
);
836 static HRESULT WINAPI
BackgroundCopyJob_GetReplyData(
837 IBackgroundCopyJob3
*iface
,
841 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
842 FIXME("(%p)->(%p %p): stub\n", This
, pBuffer
, pLength
);
846 static HRESULT WINAPI
BackgroundCopyJob_SetReplyFileName(
847 IBackgroundCopyJob3
*iface
,
850 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
851 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(filename
));
855 static HRESULT WINAPI
BackgroundCopyJob_GetReplyFileName(
856 IBackgroundCopyJob3
*iface
,
859 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
860 FIXME("(%p)->(%p): stub\n", This
, pFilename
);
864 static int index_from_target(BG_AUTH_TARGET target
)
866 if (!target
|| target
> BG_AUTH_TARGET_PROXY
) return -1;
870 static int index_from_scheme(BG_AUTH_SCHEME scheme
)
872 if (!scheme
|| scheme
> BG_AUTH_SCHEME_PASSPORT
) return -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
);
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
);
937 static HRESULT WINAPI
BackgroundCopyJob_ReplaceRemotePrefix(
938 IBackgroundCopyJob3
*iface
,
942 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
943 FIXME("(%p)->(%s %s): stub\n", This
, debugstr_w(OldPrefix
), debugstr_w(NewPrefix
));
947 static HRESULT WINAPI
BackgroundCopyJob_AddFileWithRanges(
948 IBackgroundCopyJob3
*iface
,
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
);
959 static HRESULT WINAPI
BackgroundCopyJob_SetFileACLFlags(
960 IBackgroundCopyJob3
*iface
,
963 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
964 FIXME("(%p)->(%x): stub\n", This
, Flags
);
968 static HRESULT WINAPI
BackgroundCopyJob_GetFileACLFlags(
969 IBackgroundCopyJob3
*iface
,
972 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
973 FIXME("(%p)->(%p): stub\n", This
, Flags
);
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
,
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
,
1061 BYTE
*pCertHashBlob
)
1067 static HRESULT WINAPI
http_options_SetClientCertificateByName(
1068 IBackgroundCopyJobHttpOptions
*iface
,
1069 BG_CERT_STORE_LOCATION StoreLocation
,
1071 LPCWSTR SubjectName
)
1077 static HRESULT WINAPI
http_options_RemoveClientCertificate(
1078 IBackgroundCopyJobHttpOptions
*iface
)
1084 static HRESULT WINAPI
http_options_GetClientCertificate(
1085 IBackgroundCopyJobHttpOptions
*iface
,
1086 BG_CERT_STORE_LOCATION
*pStoreLocation
,
1088 BYTE
**ppCertHashBlob
,
1089 LPWSTR
*pSubjectName
)
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
);
1107 WCHAR
*headers
= strdupW(RequestHeaders
);
1110 LeaveCriticalSection(&job
->cs
);
1111 return E_OUTOFMEMORY
;
1113 HeapFree(GetProcessHeap(), 0, job
->http_options
.headers
);
1114 job
->http_options
.headers
= headers
;
1118 HeapFree(GetProcessHeap(), 0, job
->http_options
.headers
);
1119 job
->http_options
.headers
= NULL
;
1122 LeaveCriticalSection(&job
->cs
);
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
);
1141 LeaveCriticalSection(&job
->cs
);
1142 return E_OUTOFMEMORY
;
1144 *pRequestHeaders
= headers
;
1145 LeaveCriticalSection(&job
->cs
);
1149 *pRequestHeaders
= NULL
;
1150 LeaveCriticalSection(&job
->cs
);
1154 static HRESULT WINAPI
http_options_SetSecurityFlags(
1155 IBackgroundCopyJobHttpOptions
*iface
,
1158 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJobHttpOptions(iface
);
1160 TRACE("(%p)->(0x%08x)\n", iface
, Flags
);
1162 job
->http_options
.flags
= Flags
;
1166 static HRESULT WINAPI
http_options_GetSecurityFlags(
1167 IBackgroundCopyJobHttpOptions
*iface
,
1170 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJobHttpOptions(iface
);
1172 TRACE("(%p)->(%p)\n", iface
, pFlags
);
1174 *pFlags
= job
->http_options
.flags
;
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
)
1196 BackgroundCopyJobImpl
*This
;
1199 TRACE("(%s,%d,%p)\n", debugstr_w(displayName
), type
, job
);
1201 This
= HeapAlloc(GetProcessHeap(), 0, sizeof *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");
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
);
1227 This
->cs
.DebugInfo
->Spare
[0] = 0;
1228 DeleteCriticalSection(&This
->cs
);
1229 HeapFree(GetProcessHeap(), 0, This
->displayName
);
1230 HeapFree(GetProcessHeap(), 0, This
);
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
);
1259 TRACE("created job %s:%p\n", debugstr_guid(&This
->jobId
), This
);
1264 void processJob(BackgroundCopyJobImpl
*job
)
1268 BackgroundCopyFileImpl
*file
;
1271 EnterCriticalSection(&job
->cs
);
1272 LIST_FOR_EACH_ENTRY(file
, &job
->files
, BackgroundCopyFileImpl
, entryFromJob
)
1273 if (!file
->fileProgress
.Completed
)
1278 LeaveCriticalSection(&job
->cs
);
1281 transitionJobState(job
, BG_JOB_STATE_QUEUED
, BG_JOB_STATE_TRANSFERRED
);
1285 if (!processFile(file
, job
))