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 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
);
387 static HRESULT WINAPI
BackgroundCopyJob_Cancel(
388 IBackgroundCopyJob3
*iface
)
390 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
393 TRACE("(%p)\n", This
);
395 EnterCriticalSection(&This
->cs
);
397 if (is_job_done(This
))
399 rv
= BG_E_INVALID_STATE
;
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
);
435 static HRESULT WINAPI
BackgroundCopyJob_Complete(
436 IBackgroundCopyJob3
*iface
)
438 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
441 TRACE("(%p)\n", This
);
443 EnterCriticalSection(&This
->cs
);
445 if (is_job_done(This
))
447 rv
= BG_E_INVALID_STATE
;
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
;
468 rv
= BG_S_PARTIAL_COMPLETE
;
472 This
->state
= BG_JOB_STATE_ACKNOWLEDGED
;
473 LeaveCriticalSection(&This
->cs
);
478 static HRESULT WINAPI
BackgroundCopyJob_GetId(
479 IBackgroundCopyJob3
*iface
,
482 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
483 TRACE("(%p)->(%p)\n", This
, pVal
);
488 static HRESULT WINAPI
BackgroundCopyJob_GetType(
489 IBackgroundCopyJob3
*iface
,
492 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
494 TRACE("(%p)->(%p)\n", This
, pVal
);
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
);
514 EnterCriticalSection(&This
->cs
);
515 *pVal
= This
->jobProgress
;
516 LeaveCriticalSection(&This
->cs
);
521 static HRESULT WINAPI
BackgroundCopyJob_GetTimes(
522 IBackgroundCopyJob3
*iface
,
525 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
526 FIXME("(%p)->(%p): stub\n", This
, pVal
);
530 static HRESULT WINAPI
BackgroundCopyJob_GetState(
531 IBackgroundCopyJob3
*iface
,
534 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
536 TRACE("(%p)->(%p)\n", This
, pVal
);
541 /* Don't think we need a critical section for this */
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
,
563 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
564 FIXME("(%p)->(%p): stub\n", This
, pVal
);
568 static HRESULT WINAPI
BackgroundCopyJob_SetDisplayName(
569 IBackgroundCopyJob3
*iface
,
572 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
573 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(Val
));
577 static HRESULT WINAPI
BackgroundCopyJob_GetDisplayName(
578 IBackgroundCopyJob3
*iface
,
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
,
592 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
593 static const int max_description_len
= 1024;
597 TRACE("(%p)->(%s)\n", This
, debugstr_w(Val
));
599 if (!Val
) return E_INVALIDARG
;
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
;
612 HeapFree(GetProcessHeap(), 0, This
->description
);
613 if ((This
->description
= HeapAlloc(GetProcessHeap(), 0, (len
+1)*sizeof(WCHAR
))))
614 strcpyW(This
->description
, Val
);
619 LeaveCriticalSection(&This
->cs
);
624 static HRESULT WINAPI
BackgroundCopyJob_GetDescription(
625 IBackgroundCopyJob3
*iface
,
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
,
639 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
640 FIXME("(%p)->(%d): stub\n", This
, Val
);
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
);
653 static HRESULT WINAPI
BackgroundCopyJob_SetNotifyFlags(
654 IBackgroundCopyJob3
*iface
,
657 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
658 static const ULONG valid_flags
= BG_NOTIFY_JOB_TRANSFERRED
|
659 BG_NOTIFY_JOB_ERROR
|
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
;
672 static HRESULT WINAPI
BackgroundCopyJob_GetNotifyFlags(
673 IBackgroundCopyJob3
*iface
,
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
;
687 static HRESULT WINAPI
BackgroundCopyJob_SetNotifyInterface(
688 IBackgroundCopyJob3
*iface
,
691 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
694 TRACE("(%p)->(%p)\n", This
, Val
);
696 if (is_job_done(This
)) return BG_E_INVALID_STATE
;
700 IBackgroundCopyCallback2_Release(This
->callback
);
701 This
->callback
= NULL
;
702 This
->callback2
= FALSE
;
707 hr
= IUnknown_QueryInterface(Val
, &IID_IBackgroundCopyCallback2
, (void**)&This
->callback
);
709 hr
= IUnknown_QueryInterface(Val
, &IID_IBackgroundCopyCallback
, (void**)&This
->callback
);
711 This
->callback2
= TRUE
;
717 static HRESULT WINAPI
BackgroundCopyJob_GetNotifyInterface(
718 IBackgroundCopyJob3
*iface
,
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
;
729 IUnknown_AddRef(*pVal
);
734 static HRESULT WINAPI
BackgroundCopyJob_SetMinimumRetryDelay(
735 IBackgroundCopyJob3
*iface
,
738 FIXME("%u\n", Seconds
);
742 static HRESULT WINAPI
BackgroundCopyJob_GetMinimumRetryDelay(
743 IBackgroundCopyJob3
*iface
,
746 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
747 FIXME("(%p)->(%p): stub\n", This
, Seconds
);
752 static HRESULT WINAPI
BackgroundCopyJob_SetNoProgressTimeout(
753 IBackgroundCopyJob3
*iface
,
756 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
757 FIXME("(%p)->(%d): stub\n", This
, Seconds
);
761 static HRESULT WINAPI
BackgroundCopyJob_GetNoProgressTimeout(
762 IBackgroundCopyJob3
*iface
,
765 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
766 FIXME("(%p)->(%p): stub\n", This
, Seconds
);
771 static HRESULT WINAPI
BackgroundCopyJob_GetErrorCount(
772 IBackgroundCopyJob3
*iface
,
775 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
776 FIXME("(%p)->(%p): stub\n", This
, Errors
);
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
));
791 static HRESULT WINAPI
BackgroundCopyJob_GetProxySettings(
792 IBackgroundCopyJob3
*iface
,
793 BG_JOB_PROXY_USAGE
*pProxyUsage
,
795 LPWSTR
*pProxyBypassList
)
797 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
798 FIXME("(%p)->(%p %p %p): stub\n", This
, pProxyUsage
, pProxyList
, pProxyBypassList
);
802 static HRESULT WINAPI
BackgroundCopyJob_TakeOwnership(
803 IBackgroundCopyJob3
*iface
)
805 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
806 FIXME("(%p): stub\n", This
);
810 static HRESULT WINAPI
BackgroundCopyJob_SetNotifyCmdLine(
811 IBackgroundCopyJob3
*iface
,
815 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
816 FIXME("(%p)->(%s %s): stub\n", This
, debugstr_w(prog
), debugstr_w(params
));
820 static HRESULT WINAPI
BackgroundCopyJob_GetNotifyCmdLine(
821 IBackgroundCopyJob3
*iface
,
825 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
826 FIXME("(%p)->(%p %p): stub\n", This
, prog
, params
);
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
);
839 static HRESULT WINAPI
BackgroundCopyJob_GetReplyData(
840 IBackgroundCopyJob3
*iface
,
844 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
845 FIXME("(%p)->(%p %p): stub\n", This
, pBuffer
, pLength
);
849 static HRESULT WINAPI
BackgroundCopyJob_SetReplyFileName(
850 IBackgroundCopyJob3
*iface
,
853 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
854 FIXME("(%p)->(%s): stub\n", This
, debugstr_w(filename
));
858 static HRESULT WINAPI
BackgroundCopyJob_GetReplyFileName(
859 IBackgroundCopyJob3
*iface
,
862 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
863 FIXME("(%p)->(%p): stub\n", This
, pFilename
);
867 static int index_from_target(BG_AUTH_TARGET target
)
869 if (!target
|| target
> BG_AUTH_TARGET_PROXY
) return -1;
873 static int index_from_scheme(BG_AUTH_SCHEME scheme
)
875 if (!scheme
|| scheme
> BG_AUTH_SCHEME_PASSPORT
) return -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
);
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
);
940 static HRESULT WINAPI
BackgroundCopyJob_ReplaceRemotePrefix(
941 IBackgroundCopyJob3
*iface
,
945 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
946 FIXME("(%p)->(%s %s): stub\n", This
, debugstr_w(OldPrefix
), debugstr_w(NewPrefix
));
950 static HRESULT WINAPI
BackgroundCopyJob_AddFileWithRanges(
951 IBackgroundCopyJob3
*iface
,
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
);
962 static HRESULT WINAPI
BackgroundCopyJob_SetFileACLFlags(
963 IBackgroundCopyJob3
*iface
,
966 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
967 FIXME("(%p)->(%x): stub\n", This
, Flags
);
971 static HRESULT WINAPI
BackgroundCopyJob_GetFileACLFlags(
972 IBackgroundCopyJob3
*iface
,
975 BackgroundCopyJobImpl
*This
= impl_from_IBackgroundCopyJob3(iface
);
976 FIXME("(%p)->(%p): stub\n", This
, Flags
);
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
,
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
,
1064 BYTE
*pCertHashBlob
)
1070 static HRESULT WINAPI
http_options_SetClientCertificateByName(
1071 IBackgroundCopyJobHttpOptions
*iface
,
1072 BG_CERT_STORE_LOCATION StoreLocation
,
1074 LPCWSTR SubjectName
)
1080 static HRESULT WINAPI
http_options_RemoveClientCertificate(
1081 IBackgroundCopyJobHttpOptions
*iface
)
1087 static HRESULT WINAPI
http_options_GetClientCertificate(
1088 IBackgroundCopyJobHttpOptions
*iface
,
1089 BG_CERT_STORE_LOCATION
*pStoreLocation
,
1091 BYTE
**ppCertHashBlob
,
1092 LPWSTR
*pSubjectName
)
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
);
1110 WCHAR
*headers
= strdupW(RequestHeaders
);
1113 LeaveCriticalSection(&job
->cs
);
1114 return E_OUTOFMEMORY
;
1116 HeapFree(GetProcessHeap(), 0, job
->http_options
.headers
);
1117 job
->http_options
.headers
= headers
;
1121 HeapFree(GetProcessHeap(), 0, job
->http_options
.headers
);
1122 job
->http_options
.headers
= NULL
;
1125 LeaveCriticalSection(&job
->cs
);
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
);
1144 LeaveCriticalSection(&job
->cs
);
1145 return E_OUTOFMEMORY
;
1147 *pRequestHeaders
= headers
;
1148 LeaveCriticalSection(&job
->cs
);
1152 *pRequestHeaders
= NULL
;
1153 LeaveCriticalSection(&job
->cs
);
1157 static HRESULT WINAPI
http_options_SetSecurityFlags(
1158 IBackgroundCopyJobHttpOptions
*iface
,
1161 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJobHttpOptions(iface
);
1163 TRACE("(%p)->(0x%08x)\n", iface
, Flags
);
1165 job
->http_options
.flags
= Flags
;
1169 static HRESULT WINAPI
http_options_GetSecurityFlags(
1170 IBackgroundCopyJobHttpOptions
*iface
,
1173 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJobHttpOptions(iface
);
1175 TRACE("(%p)->(%p)\n", iface
, pFlags
);
1177 *pFlags
= job
->http_options
.flags
;
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
)
1199 BackgroundCopyJobImpl
*This
;
1201 TRACE("(%s,%d,%p)\n", debugstr_w(displayName
), type
, job
);
1203 This
= HeapAlloc(GetProcessHeap(), 0, sizeof *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");
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
);
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
))