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)->(%ld)\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)->(%ld)\n", error
, refs
);
101 if (error
->file
) IBackgroundCopyFile2_Release(error
->file
);
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%08lx\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 %08lx file %p\n", context
, code
, file
);
192 if (!(error
= malloc(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_IBackgroundCopyJob4(IBackgroundCopyJob4
*iface
)
212 return CONTAINING_RECORD(iface
, BackgroundCopyJobImpl
, IBackgroundCopyJob4_iface
);
215 static HRESULT WINAPI
BackgroundCopyJob_QueryInterface(IBackgroundCopyJob4
*iface
, REFIID riid
, void **obj
)
217 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
219 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
221 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
222 IsEqualGUID(riid
, &IID_IBackgroundCopyJob
) ||
223 IsEqualGUID(riid
, &IID_IBackgroundCopyJob2
) ||
224 IsEqualGUID(riid
, &IID_IBackgroundCopyJob3
) ||
225 IsEqualGUID(riid
, &IID_IBackgroundCopyJob4
))
227 *obj
= &job
->IBackgroundCopyJob4_iface
;
229 else if (IsEqualGUID(riid
, &IID_IBackgroundCopyJobHttpOptions
))
231 *obj
= &job
->IBackgroundCopyJobHttpOptions_iface
;
235 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
237 return E_NOINTERFACE
;
240 IBackgroundCopyJob4_AddRef(iface
);
244 static ULONG WINAPI
BackgroundCopyJob_AddRef(IBackgroundCopyJob4
*iface
)
246 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
247 ULONG refcount
= InterlockedIncrement(&job
->ref
);
248 TRACE("%p, refcount %ld.\n", iface
, refcount
);
252 static ULONG WINAPI
BackgroundCopyJob_Release(IBackgroundCopyJob4
*iface
)
254 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
255 ULONG i
, j
, ref
= InterlockedDecrement(&job
->ref
);
257 TRACE("%p, refcount %ld.\n", iface
, ref
);
261 job
->cs
.DebugInfo
->Spare
[0] = 0;
262 DeleteCriticalSection(&job
->cs
);
264 IBackgroundCopyCallback2_Release(job
->callback
);
265 free(job
->displayName
);
266 free(job
->description
);
267 free(job
->http_options
.headers
);
268 for (i
= 0; i
< BG_AUTH_TARGET_PROXY
; i
++)
270 for (j
= 0; j
< BG_AUTH_SCHEME_PASSPORT
; j
++)
272 BG_AUTH_CREDENTIALS
*cred
= &job
->http_options
.creds
[i
][j
];
273 free(cred
->Credentials
.Basic
.UserName
);
274 free(cred
->Credentials
.Basic
.Password
);
277 CloseHandle(job
->wait
);
278 CloseHandle(job
->cancel
);
279 CloseHandle(job
->done
);
286 /*** IBackgroundCopyJob methods ***/
288 static HRESULT WINAPI
BackgroundCopyJob_AddFileSet(IBackgroundCopyJob4
*iface
, ULONG cFileCount
, BG_FILE_INFO
*pFileSet
)
290 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
294 TRACE("%p, %lu, %p.\n", iface
, cFileCount
, pFileSet
);
296 EnterCriticalSection(&job
->cs
);
298 for (i
= 0; i
< cFileCount
; ++i
)
300 BackgroundCopyFileImpl
*file
;
302 /* We should return E_INVALIDARG in these cases. */
303 FIXME("Check for valid filenames and supported protocols\n");
305 hr
= BackgroundCopyFileConstructor(job
, pFileSet
[i
].RemoteName
, pFileSet
[i
].LocalName
, &file
);
306 if (hr
!= S_OK
) break;
308 /* Add a reference to the file to file list */
309 list_add_head(&job
->files
, &file
->entryFromJob
);
310 job
->jobProgress
.BytesTotal
= BG_SIZE_UNKNOWN
;
311 ++job
->jobProgress
.FilesTotal
;
314 LeaveCriticalSection(&job
->cs
);
319 static HRESULT WINAPI
BackgroundCopyJob_AddFile(IBackgroundCopyJob4
*iface
, LPCWSTR RemoteUrl
, LPCWSTR LocalName
)
323 TRACE("%p, %s, %s.\n", iface
, debugstr_w(RemoteUrl
), debugstr_w(LocalName
));
325 file
.RemoteName
= (LPWSTR
)RemoteUrl
;
326 file
.LocalName
= (LPWSTR
)LocalName
;
327 return IBackgroundCopyJob4_AddFileSet(iface
, 1, &file
);
330 static HRESULT WINAPI
BackgroundCopyJob_EnumFiles(IBackgroundCopyJob4
*iface
, IEnumBackgroundCopyFiles
**enum_files
)
332 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
333 TRACE("%p, %p.\n", iface
, enum_files
);
334 return EnumBackgroundCopyFilesConstructor(job
, enum_files
);
337 static HRESULT WINAPI
BackgroundCopyJob_Suspend(IBackgroundCopyJob4
*iface
)
339 FIXME("(%p): stub\n", iface
);
343 static HRESULT WINAPI
BackgroundCopyJob_Resume(IBackgroundCopyJob4
*iface
)
345 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
348 TRACE("%p.\n", iface
);
350 EnterCriticalSection(&globalMgr
.cs
);
351 if (is_job_done(job
))
353 hr
= BG_E_INVALID_STATE
;
355 else if (job
->jobProgress
.FilesTransferred
== job
->jobProgress
.FilesTotal
)
359 else if (job
->state
!= BG_JOB_STATE_CONNECTING
360 && job
->state
!= BG_JOB_STATE_TRANSFERRING
)
362 job
->state
= BG_JOB_STATE_QUEUED
;
363 job
->error
.context
= 0;
364 job
->error
.code
= S_OK
;
367 IBackgroundCopyFile2_Release(job
->error
.file
);
368 job
->error
.file
= NULL
;
370 SetEvent(globalMgr
.jobEvent
);
372 LeaveCriticalSection(&globalMgr
.cs
);
377 static HRESULT WINAPI
BackgroundCopyJob_Cancel(IBackgroundCopyJob4
*iface
)
379 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
382 TRACE("%p.\n", iface
);
384 EnterCriticalSection(&job
->cs
);
386 if (is_job_done(job
))
388 hr
= BG_E_INVALID_STATE
;
392 BackgroundCopyFileImpl
*file
;
394 if (job
->state
== BG_JOB_STATE_CONNECTING
|| job
->state
== BG_JOB_STATE_TRANSFERRING
)
396 job
->state
= BG_JOB_STATE_CANCELLED
;
397 SetEvent(job
->cancel
);
399 LeaveCriticalSection(&job
->cs
);
400 WaitForSingleObject(job
->done
, INFINITE
);
401 EnterCriticalSection(&job
->cs
);
404 LIST_FOR_EACH_ENTRY(file
, &job
->files
, BackgroundCopyFileImpl
, entryFromJob
)
406 if (file
->tempFileName
[0] && !DeleteFileW(file
->tempFileName
))
408 WARN("Couldn't delete %s (%lu)\n", debugstr_w(file
->tempFileName
), GetLastError());
409 hr
= BG_S_UNABLE_TO_DELETE_FILES
;
411 if (file
->info
.LocalName
&& !DeleteFileW(file
->info
.LocalName
))
413 WARN("Couldn't delete %s (%lu)\n", debugstr_w(file
->info
.LocalName
), GetLastError());
414 hr
= BG_S_UNABLE_TO_DELETE_FILES
;
417 job
->state
= BG_JOB_STATE_CANCELLED
;
420 LeaveCriticalSection(&job
->cs
);
424 static HRESULT WINAPI
BackgroundCopyJob_Complete(IBackgroundCopyJob4
*iface
)
426 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
429 TRACE("%p.\n", iface
);
431 EnterCriticalSection(&job
->cs
);
433 if (is_job_done(job
))
435 hr
= BG_E_INVALID_STATE
;
439 BackgroundCopyFileImpl
*file
;
440 LIST_FOR_EACH_ENTRY(file
, &job
->files
, BackgroundCopyFileImpl
, entryFromJob
)
442 if (file
->fileProgress
.Completed
)
444 if (!MoveFileExW(file
->tempFileName
, file
->info
.LocalName
,
445 (MOVEFILE_COPY_ALLOWED
446 | MOVEFILE_REPLACE_EXISTING
447 | MOVEFILE_WRITE_THROUGH
)))
449 ERR("Couldn't rename file %s -> %s\n",
450 debugstr_w(file
->tempFileName
),
451 debugstr_w(file
->info
.LocalName
));
452 hr
= BG_S_PARTIAL_COMPLETE
;
456 hr
= BG_S_PARTIAL_COMPLETE
;
460 job
->state
= BG_JOB_STATE_ACKNOWLEDGED
;
461 LeaveCriticalSection(&job
->cs
);
466 static HRESULT WINAPI
BackgroundCopyJob_GetId(IBackgroundCopyJob4
*iface
, GUID
*id
)
468 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
470 TRACE("%p, %p.\n", iface
, id
);
477 static HRESULT WINAPI
BackgroundCopyJob_GetType(IBackgroundCopyJob4
*iface
, BG_JOB_TYPE
*job_type
)
479 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
481 TRACE("%p, %p.\n", iface
, job_type
);
486 *job_type
= job
->type
;
490 static HRESULT WINAPI
BackgroundCopyJob_GetProgress(IBackgroundCopyJob4
*iface
, BG_JOB_PROGRESS
*progress
)
492 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
494 TRACE("%p, %p.\n", iface
, progress
);
499 EnterCriticalSection(&job
->cs
);
500 *progress
= job
->jobProgress
;
501 LeaveCriticalSection(&job
->cs
);
506 static HRESULT WINAPI
BackgroundCopyJob_GetTimes(IBackgroundCopyJob4
*iface
, BG_JOB_TIMES
*pVal
)
508 FIXME("%p, %p: stub\n", iface
, pVal
);
512 static HRESULT WINAPI
BackgroundCopyJob_GetState(IBackgroundCopyJob4
*iface
, BG_JOB_STATE
*state
)
514 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
516 TRACE("%p, %p.\n", iface
, state
);
521 /* Don't think we need a critical section for this */
526 static HRESULT WINAPI
BackgroundCopyJob_GetError(IBackgroundCopyJob4
*iface
, IBackgroundCopyError
**ppError
)
528 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
530 TRACE("%p, %p.\n", iface
, ppError
);
532 if (!job
->error
.context
) return BG_E_ERROR_INFORMATION_UNAVAILABLE
;
534 return create_copy_error(job
->error
.context
, job
->error
.code
, job
->error
.file
, ppError
);
537 static HRESULT WINAPI
BackgroundCopyJob_GetOwner(IBackgroundCopyJob4
*iface
, LPWSTR
*owner
)
539 FIXME("%p, %p: stub\n", iface
, owner
);
543 static HRESULT WINAPI
BackgroundCopyJob_SetDisplayName(IBackgroundCopyJob4
*iface
, LPCWSTR name
)
545 FIXME("%p, %s: stub\n", iface
, debugstr_w(name
));
549 static HRESULT WINAPI
BackgroundCopyJob_GetDisplayName(IBackgroundCopyJob4
*iface
, LPWSTR
*name
)
551 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
553 TRACE("%p, %p.\n", iface
, name
);
555 return return_strval(job
->displayName
, name
);
558 static HRESULT WINAPI
BackgroundCopyJob_SetDescription(IBackgroundCopyJob4
*iface
, LPCWSTR desc
)
560 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
561 static const int max_description_len
= 1024;
565 TRACE("%p, %s.\n", iface
, debugstr_w(desc
));
570 len
= lstrlenW(desc
);
571 if (len
> max_description_len
) return BG_E_STRING_TOO_LONG
;
573 EnterCriticalSection(&job
->cs
);
575 if (is_job_done(job
))
577 hr
= BG_E_INVALID_STATE
;
581 free(job
->description
);
582 if (!(job
->description
= wcsdup(desc
)))
586 LeaveCriticalSection(&job
->cs
);
591 static HRESULT WINAPI
BackgroundCopyJob_GetDescription(IBackgroundCopyJob4
*iface
, LPWSTR
*desc
)
593 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
595 TRACE("%p, %p.\n", iface
, desc
);
597 return return_strval(job
->description
, desc
);
600 static HRESULT WINAPI
BackgroundCopyJob_SetPriority(IBackgroundCopyJob4
*iface
, BG_JOB_PRIORITY priority
)
602 FIXME("%p, %d: stub\n", iface
, priority
);
606 static HRESULT WINAPI
BackgroundCopyJob_GetPriority(IBackgroundCopyJob4
*iface
, BG_JOB_PRIORITY
*priority
)
608 FIXME("%p, %p: stub\n", iface
, priority
);
612 static HRESULT WINAPI
BackgroundCopyJob_SetNotifyFlags(IBackgroundCopyJob4
*iface
, ULONG flags
)
614 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
615 static const ULONG valid_flags
= BG_NOTIFY_JOB_TRANSFERRED
|
616 BG_NOTIFY_JOB_ERROR
|
618 BG_NOTIFY_JOB_MODIFICATION
|
619 BG_NOTIFY_FILE_TRANSFERRED
;
621 TRACE("%p, %#lx.\n", iface
, flags
);
623 if (is_job_done(job
)) return BG_E_INVALID_STATE
;
624 if (flags
& ~valid_flags
) return E_NOTIMPL
;
625 job
->notify_flags
= flags
;
629 static HRESULT WINAPI
BackgroundCopyJob_GetNotifyFlags(IBackgroundCopyJob4
*iface
, ULONG
*flags
)
631 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
633 TRACE("%p, %p.\n", iface
, flags
);
635 if (!flags
) return E_INVALIDARG
;
637 *flags
= job
->notify_flags
;
642 static HRESULT WINAPI
BackgroundCopyJob_SetNotifyInterface(IBackgroundCopyJob4
*iface
, IUnknown
*callback
)
644 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
647 TRACE("%p, %p.\n", iface
, callback
);
649 if (is_job_done(job
)) return BG_E_INVALID_STATE
;
653 IBackgroundCopyCallback2_Release(job
->callback
);
654 job
->callback
= NULL
;
655 job
->callback2
= FALSE
;
660 hr
= IUnknown_QueryInterface(callback
, &IID_IBackgroundCopyCallback2
, (void **)&job
->callback
);
662 hr
= IUnknown_QueryInterface(callback
, &IID_IBackgroundCopyCallback
, (void**)&job
->callback
);
664 job
->callback2
= TRUE
;
670 static HRESULT WINAPI
BackgroundCopyJob_GetNotifyInterface(IBackgroundCopyJob4
*iface
, IUnknown
**callback
)
672 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
674 TRACE("%p, %p.\n", iface
, callback
);
676 if (!callback
) return E_INVALIDARG
;
678 *callback
= (IUnknown
*)job
->callback
;
680 IUnknown_AddRef(*callback
);
685 static HRESULT WINAPI
BackgroundCopyJob_SetMinimumRetryDelay(IBackgroundCopyJob4
*iface
, ULONG delay
)
687 FIXME("%p, %lu.\n", iface
, delay
);
691 static HRESULT WINAPI
BackgroundCopyJob_GetMinimumRetryDelay(IBackgroundCopyJob4
*iface
, ULONG
*delay
)
693 FIXME("%p, %p: stub\n", iface
, delay
);
698 static HRESULT WINAPI
BackgroundCopyJob_SetNoProgressTimeout(IBackgroundCopyJob4
*iface
, ULONG timeout
)
700 FIXME("%p, %lu.: stub\n", iface
, timeout
);
704 static HRESULT WINAPI
BackgroundCopyJob_GetNoProgressTimeout(IBackgroundCopyJob4
*iface
, ULONG
*timeout
)
706 FIXME("%p, %p: stub\n", iface
, timeout
);
711 static HRESULT WINAPI
BackgroundCopyJob_GetErrorCount(IBackgroundCopyJob4
*iface
, ULONG
*count
)
713 FIXME("%p, %p: stub\n", iface
, count
);
717 static HRESULT WINAPI
BackgroundCopyJob_SetProxySettings(IBackgroundCopyJob4
*iface
, BG_JOB_PROXY_USAGE proxy_usage
,
718 const WCHAR
*proxy_list
, const WCHAR
*proxy_bypass_list
)
720 FIXME("%p, %d, %s, %s: stub\n", iface
, proxy_usage
, debugstr_w(proxy_list
), debugstr_w(proxy_bypass_list
));
724 static HRESULT WINAPI
BackgroundCopyJob_GetProxySettings(IBackgroundCopyJob4
*iface
, BG_JOB_PROXY_USAGE
*proxy_usage
,
725 LPWSTR
*proxy_list
, LPWSTR
*proxy_bypass_list
)
727 FIXME("%p, %p, %p, %p: stub\n", iface
, proxy_usage
, proxy_list
, proxy_bypass_list
);
731 static HRESULT WINAPI
BackgroundCopyJob_TakeOwnership(IBackgroundCopyJob4
*iface
)
733 FIXME("%p: stub\n", iface
);
737 static HRESULT WINAPI
BackgroundCopyJob_SetNotifyCmdLine(IBackgroundCopyJob4
*iface
, LPCWSTR prog
, LPCWSTR params
)
739 FIXME("%p, %s, %s: stub\n", iface
, debugstr_w(prog
), debugstr_w(params
));
743 static HRESULT WINAPI
BackgroundCopyJob_GetNotifyCmdLine(IBackgroundCopyJob4
*iface
, LPWSTR
*prog
, LPWSTR
*params
)
745 FIXME("%p, %p, %p: stub\n", iface
, prog
, params
);
749 static HRESULT WINAPI
BackgroundCopyJob_GetReplyProgress(IBackgroundCopyJob4
*iface
, BG_JOB_REPLY_PROGRESS
*progress
)
751 FIXME("%p, %p: stub\n", iface
, progress
);
755 static HRESULT WINAPI
BackgroundCopyJob_GetReplyData(IBackgroundCopyJob4
*iface
, byte
**buffer
, UINT64
*length
)
757 FIXME("%p, %p, %p: stub\n", iface
, buffer
, length
);
761 static HRESULT WINAPI
BackgroundCopyJob_SetReplyFileName(IBackgroundCopyJob4
*iface
, LPCWSTR filename
)
763 FIXME("%p, %s: stub\n", iface
, debugstr_w(filename
));
767 static HRESULT WINAPI
BackgroundCopyJob_GetReplyFileName(IBackgroundCopyJob4
*iface
, LPWSTR
*filename
)
769 FIXME("%p, %p: stub\n", iface
, filename
);
773 static int index_from_target(BG_AUTH_TARGET target
)
775 if (!target
|| target
> BG_AUTH_TARGET_PROXY
) return -1;
779 static int index_from_scheme(BG_AUTH_SCHEME scheme
)
781 if (!scheme
|| scheme
> BG_AUTH_SCHEME_PASSPORT
) return -1;
785 static HRESULT WINAPI
BackgroundCopyJob_SetCredentials(IBackgroundCopyJob4
*iface
, BG_AUTH_CREDENTIALS
*cred
)
787 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
788 BG_AUTH_CREDENTIALS
*new_cred
;
789 int idx_target
, idx_scheme
;
791 TRACE("%p, %p.\n", iface
, cred
);
793 if ((idx_target
= index_from_target(cred
->Target
)) < 0) return BG_E_INVALID_AUTH_TARGET
;
794 if ((idx_scheme
= index_from_scheme(cred
->Scheme
)) < 0) return BG_E_INVALID_AUTH_SCHEME
;
795 new_cred
= &job
->http_options
.creds
[idx_target
][idx_scheme
];
797 EnterCriticalSection(&job
->cs
);
799 new_cred
->Target
= cred
->Target
;
800 new_cred
->Scheme
= cred
->Scheme
;
802 if (cred
->Credentials
.Basic
.UserName
)
804 free(new_cred
->Credentials
.Basic
.UserName
);
805 new_cred
->Credentials
.Basic
.UserName
= wcsdup(cred
->Credentials
.Basic
.UserName
);
807 if (cred
->Credentials
.Basic
.Password
)
809 free(new_cred
->Credentials
.Basic
.Password
);
810 new_cred
->Credentials
.Basic
.Password
= wcsdup(cred
->Credentials
.Basic
.Password
);
813 LeaveCriticalSection(&job
->cs
);
817 static HRESULT WINAPI
BackgroundCopyJob_RemoveCredentials(
818 IBackgroundCopyJob4
*iface
,
819 BG_AUTH_TARGET target
,
820 BG_AUTH_SCHEME scheme
)
822 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJob4(iface
);
823 BG_AUTH_CREDENTIALS
*new_cred
;
824 int idx_target
, idx_scheme
;
826 TRACE("%p, %u, %u.\n", iface
, target
, scheme
);
828 if ((idx_target
= index_from_target(target
)) < 0) return BG_E_INVALID_AUTH_TARGET
;
829 if ((idx_scheme
= index_from_scheme(scheme
)) < 0) return BG_E_INVALID_AUTH_SCHEME
;
830 new_cred
= &job
->http_options
.creds
[idx_target
][idx_scheme
];
832 EnterCriticalSection(&job
->cs
);
834 new_cred
->Target
= new_cred
->Scheme
= 0;
835 free(new_cred
->Credentials
.Basic
.UserName
);
836 new_cred
->Credentials
.Basic
.UserName
= NULL
;
837 free(new_cred
->Credentials
.Basic
.Password
);
838 new_cred
->Credentials
.Basic
.Password
= NULL
;
840 LeaveCriticalSection(&job
->cs
);
844 static HRESULT WINAPI
BackgroundCopyJob_ReplaceRemotePrefix(
845 IBackgroundCopyJob4
*iface
,
849 FIXME("%p, %s, %s: stub\n", iface
, debugstr_w(OldPrefix
), debugstr_w(NewPrefix
));
853 static HRESULT WINAPI
BackgroundCopyJob_AddFileWithRanges(
854 IBackgroundCopyJob4
*iface
,
858 BG_FILE_RANGE Ranges
[])
860 FIXME("%p, %s, %s, %lu, %p: stub\n", iface
, debugstr_w(RemoteUrl
), debugstr_w(LocalName
), RangeCount
, Ranges
);
864 static HRESULT WINAPI
BackgroundCopyJob_SetFileACLFlags(IBackgroundCopyJob4
*iface
, DWORD flags
)
866 FIXME("%p, %#lx: stub\n", iface
, flags
);
870 static HRESULT WINAPI
BackgroundCopyJob_GetFileACLFlags(IBackgroundCopyJob4
*iface
, DWORD
*flags
)
872 FIXME("%p, %p: stub\n", iface
, flags
);
876 static HRESULT WINAPI
BackgroundCopyJob_SetPeerCachingFlags(IBackgroundCopyJob4
*iface
, DWORD flags
)
878 FIXME("%p, %#lx.\n", iface
, flags
);
882 static HRESULT WINAPI
BackgroundCopyJob_GetPeerCachingFlags(IBackgroundCopyJob4
*iface
, DWORD
*flags
)
884 FIXME("%p, %p.\n", iface
, flags
);
888 static HRESULT WINAPI
BackgroundCopyJob_GetOwnerIntegrityLevel(IBackgroundCopyJob4
*iface
, ULONG
*level
)
890 FIXME("%p, %p.\n", iface
, level
);
894 static HRESULT WINAPI
BackgroundCopyJob_GetOwnerElevationState(IBackgroundCopyJob4
*iface
, BOOL
*elevated
)
896 FIXME("%p, %p.\n", iface
, elevated
);
900 static HRESULT WINAPI
BackgroundCopyJob_SetMaximumDownloadTime(IBackgroundCopyJob4
*iface
, ULONG timeout
)
902 FIXME("%p, %lu.\n", iface
, timeout
);
906 static HRESULT WINAPI
BackgroundCopyJob_GetMaximumDownloadTime(IBackgroundCopyJob4
*iface
, ULONG
*timeout
)
908 FIXME("%p, %p.\n", iface
, timeout
);
912 static const IBackgroundCopyJob4Vtbl BackgroundCopyJobVtbl
=
914 BackgroundCopyJob_QueryInterface
,
915 BackgroundCopyJob_AddRef
,
916 BackgroundCopyJob_Release
,
917 BackgroundCopyJob_AddFileSet
,
918 BackgroundCopyJob_AddFile
,
919 BackgroundCopyJob_EnumFiles
,
920 BackgroundCopyJob_Suspend
,
921 BackgroundCopyJob_Resume
,
922 BackgroundCopyJob_Cancel
,
923 BackgroundCopyJob_Complete
,
924 BackgroundCopyJob_GetId
,
925 BackgroundCopyJob_GetType
,
926 BackgroundCopyJob_GetProgress
,
927 BackgroundCopyJob_GetTimes
,
928 BackgroundCopyJob_GetState
,
929 BackgroundCopyJob_GetError
,
930 BackgroundCopyJob_GetOwner
,
931 BackgroundCopyJob_SetDisplayName
,
932 BackgroundCopyJob_GetDisplayName
,
933 BackgroundCopyJob_SetDescription
,
934 BackgroundCopyJob_GetDescription
,
935 BackgroundCopyJob_SetPriority
,
936 BackgroundCopyJob_GetPriority
,
937 BackgroundCopyJob_SetNotifyFlags
,
938 BackgroundCopyJob_GetNotifyFlags
,
939 BackgroundCopyJob_SetNotifyInterface
,
940 BackgroundCopyJob_GetNotifyInterface
,
941 BackgroundCopyJob_SetMinimumRetryDelay
,
942 BackgroundCopyJob_GetMinimumRetryDelay
,
943 BackgroundCopyJob_SetNoProgressTimeout
,
944 BackgroundCopyJob_GetNoProgressTimeout
,
945 BackgroundCopyJob_GetErrorCount
,
946 BackgroundCopyJob_SetProxySettings
,
947 BackgroundCopyJob_GetProxySettings
,
948 BackgroundCopyJob_TakeOwnership
,
949 BackgroundCopyJob_SetNotifyCmdLine
,
950 BackgroundCopyJob_GetNotifyCmdLine
,
951 BackgroundCopyJob_GetReplyProgress
,
952 BackgroundCopyJob_GetReplyData
,
953 BackgroundCopyJob_SetReplyFileName
,
954 BackgroundCopyJob_GetReplyFileName
,
955 BackgroundCopyJob_SetCredentials
,
956 BackgroundCopyJob_RemoveCredentials
,
957 BackgroundCopyJob_ReplaceRemotePrefix
,
958 BackgroundCopyJob_AddFileWithRanges
,
959 BackgroundCopyJob_SetFileACLFlags
,
960 BackgroundCopyJob_GetFileACLFlags
,
961 BackgroundCopyJob_SetPeerCachingFlags
,
962 BackgroundCopyJob_GetPeerCachingFlags
,
963 BackgroundCopyJob_GetOwnerIntegrityLevel
,
964 BackgroundCopyJob_GetOwnerElevationState
,
965 BackgroundCopyJob_SetMaximumDownloadTime
,
966 BackgroundCopyJob_GetMaximumDownloadTime
,
969 static inline BackgroundCopyJobImpl
*impl_from_IBackgroundCopyJobHttpOptions(
970 IBackgroundCopyJobHttpOptions
*iface
)
972 return CONTAINING_RECORD(iface
, BackgroundCopyJobImpl
, IBackgroundCopyJobHttpOptions_iface
);
975 static HRESULT WINAPI
http_options_QueryInterface(
976 IBackgroundCopyJobHttpOptions
*iface
,
980 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJobHttpOptions(iface
);
981 return IBackgroundCopyJob4_QueryInterface(&job
->IBackgroundCopyJob4_iface
, riid
, ppvObject
);
984 static ULONG WINAPI
http_options_AddRef(
985 IBackgroundCopyJobHttpOptions
*iface
)
987 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJobHttpOptions(iface
);
988 return IBackgroundCopyJob4_AddRef(&job
->IBackgroundCopyJob4_iface
);
991 static ULONG WINAPI
http_options_Release(
992 IBackgroundCopyJobHttpOptions
*iface
)
994 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJobHttpOptions(iface
);
995 return IBackgroundCopyJob4_Release(&job
->IBackgroundCopyJob4_iface
);
998 static HRESULT WINAPI
http_options_SetClientCertificateByID(
999 IBackgroundCopyJobHttpOptions
*iface
,
1000 BG_CERT_STORE_LOCATION StoreLocation
,
1002 BYTE
*pCertHashBlob
)
1008 static HRESULT WINAPI
http_options_SetClientCertificateByName(
1009 IBackgroundCopyJobHttpOptions
*iface
,
1010 BG_CERT_STORE_LOCATION StoreLocation
,
1012 LPCWSTR SubjectName
)
1018 static HRESULT WINAPI
http_options_RemoveClientCertificate(
1019 IBackgroundCopyJobHttpOptions
*iface
)
1025 static HRESULT WINAPI
http_options_GetClientCertificate(
1026 IBackgroundCopyJobHttpOptions
*iface
,
1027 BG_CERT_STORE_LOCATION
*pStoreLocation
,
1029 BYTE
**ppCertHashBlob
,
1030 LPWSTR
*pSubjectName
)
1036 static HRESULT WINAPI
http_options_SetCustomHeaders(
1037 IBackgroundCopyJobHttpOptions
*iface
,
1038 LPCWSTR RequestHeaders
)
1040 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJobHttpOptions(iface
);
1042 TRACE("(%p)->(%s)\n", iface
, debugstr_w(RequestHeaders
));
1044 EnterCriticalSection(&job
->cs
);
1048 WCHAR
*headers
= wcsdup(RequestHeaders
);
1051 LeaveCriticalSection(&job
->cs
);
1052 return E_OUTOFMEMORY
;
1054 free(job
->http_options
.headers
);
1055 job
->http_options
.headers
= headers
;
1059 free(job
->http_options
.headers
);
1060 job
->http_options
.headers
= NULL
;
1063 LeaveCriticalSection(&job
->cs
);
1067 static HRESULT WINAPI
http_options_GetCustomHeaders(
1068 IBackgroundCopyJobHttpOptions
*iface
,
1069 LPWSTR
*pRequestHeaders
)
1071 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJobHttpOptions(iface
);
1073 TRACE("(%p)->(%p)\n", iface
, pRequestHeaders
);
1075 EnterCriticalSection(&job
->cs
);
1077 if (job
->http_options
.headers
)
1079 WCHAR
*headers
= co_strdupW(job
->http_options
.headers
);
1082 LeaveCriticalSection(&job
->cs
);
1083 return E_OUTOFMEMORY
;
1085 *pRequestHeaders
= headers
;
1086 LeaveCriticalSection(&job
->cs
);
1090 *pRequestHeaders
= NULL
;
1091 LeaveCriticalSection(&job
->cs
);
1095 static HRESULT WINAPI
http_options_SetSecurityFlags(
1096 IBackgroundCopyJobHttpOptions
*iface
,
1099 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJobHttpOptions(iface
);
1101 TRACE("(%p)->(0x%08lx)\n", iface
, Flags
);
1103 job
->http_options
.flags
= Flags
;
1107 static HRESULT WINAPI
http_options_GetSecurityFlags(
1108 IBackgroundCopyJobHttpOptions
*iface
,
1111 BackgroundCopyJobImpl
*job
= impl_from_IBackgroundCopyJobHttpOptions(iface
);
1113 TRACE("(%p)->(%p)\n", iface
, pFlags
);
1115 *pFlags
= job
->http_options
.flags
;
1119 static const IBackgroundCopyJobHttpOptionsVtbl http_options_vtbl
=
1121 http_options_QueryInterface
,
1122 http_options_AddRef
,
1123 http_options_Release
,
1124 http_options_SetClientCertificateByID
,
1125 http_options_SetClientCertificateByName
,
1126 http_options_RemoveClientCertificate
,
1127 http_options_GetClientCertificate
,
1128 http_options_SetCustomHeaders
,
1129 http_options_GetCustomHeaders
,
1130 http_options_SetSecurityFlags
,
1131 http_options_GetSecurityFlags
1134 HRESULT
BackgroundCopyJobConstructor(LPCWSTR displayName
, BG_JOB_TYPE type
, GUID
*job_id
, BackgroundCopyJobImpl
**job
)
1137 BackgroundCopyJobImpl
*This
;
1139 TRACE("(%s,%d,%p)\n", debugstr_w(displayName
), type
, job
);
1141 This
= malloc(sizeof(*This
));
1143 return E_OUTOFMEMORY
;
1145 This
->IBackgroundCopyJob4_iface
.lpVtbl
= &BackgroundCopyJobVtbl
;
1146 This
->IBackgroundCopyJobHttpOptions_iface
.lpVtbl
= &http_options_vtbl
;
1147 InitializeCriticalSection(&This
->cs
);
1148 This
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": BackgroundCopyJobImpl.cs");
1153 This
->displayName
= wcsdup(displayName
);
1154 if (!This
->displayName
)
1156 This
->cs
.DebugInfo
->Spare
[0] = 0;
1157 DeleteCriticalSection(&This
->cs
);
1159 return E_OUTOFMEMORY
;
1162 hr
= CoCreateGuid(&This
->jobId
);
1165 This
->cs
.DebugInfo
->Spare
[0] = 0;
1166 DeleteCriticalSection(&This
->cs
);
1167 free(This
->displayName
);
1171 *job_id
= This
->jobId
;
1173 list_init(&This
->files
);
1174 This
->jobProgress
.BytesTotal
= 0;
1175 This
->jobProgress
.BytesTransferred
= 0;
1176 This
->jobProgress
.FilesTotal
= 0;
1177 This
->jobProgress
.FilesTransferred
= 0;
1179 This
->state
= BG_JOB_STATE_SUSPENDED
;
1180 This
->description
= NULL
;
1181 This
->notify_flags
= BG_NOTIFY_JOB_ERROR
| BG_NOTIFY_JOB_TRANSFERRED
;
1182 This
->callback
= NULL
;
1183 This
->callback2
= FALSE
;
1185 This
->error
.context
= 0;
1186 This
->error
.code
= S_OK
;
1187 This
->error
.file
= NULL
;
1189 memset(&This
->http_options
, 0, sizeof(This
->http_options
));
1191 This
->wait
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1192 This
->cancel
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1193 This
->done
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1197 TRACE("created job %s:%p\n", debugstr_guid(&This
->jobId
), This
);
1202 void processJob(BackgroundCopyJobImpl
*job
)
1206 BackgroundCopyFileImpl
*file
;
1209 EnterCriticalSection(&job
->cs
);
1210 LIST_FOR_EACH_ENTRY(file
, &job
->files
, BackgroundCopyFileImpl
, entryFromJob
)
1211 if (!file
->fileProgress
.Completed
)
1216 LeaveCriticalSection(&job
->cs
);
1219 transitionJobState(job
, BG_JOB_STATE_QUEUED
, BG_JOB_STATE_TRANSFERRED
);
1220 if (job
->callback
&& (job
->notify_flags
& BG_NOTIFY_JOB_TRANSFERRED
))
1222 TRACE("Calling JobTransferred -->\n");
1223 IBackgroundCopyCallback2_JobTransferred(job
->callback
, (IBackgroundCopyJob
*)&job
->IBackgroundCopyJob4_iface
);
1224 TRACE("Called JobTransferred <--\n");
1229 if (!processFile(file
, job
))