| /* |
| * Background Copy Job Interface for BITS |
| * |
| * Copyright 2007 Google (Roy Shea) |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
| */ |
| |
| #include <stdarg.h> |
| |
| #include "windef.h" |
| #include "winbase.h" |
| #include "qmgr.h" |
| #include "wine/debug.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(qmgr); |
| |
| BOOL transitionJobState(BackgroundCopyJobImpl *job, BG_JOB_STATE from, BG_JOB_STATE to) |
| { |
| BOOL ret = FALSE; |
| |
| EnterCriticalSection(&globalMgr.cs); |
| if (job->state == from) |
| { |
| job->state = to; |
| ret = TRUE; |
| } |
| LeaveCriticalSection(&globalMgr.cs); |
| return ret; |
| } |
| |
| struct copy_error |
| { |
| IBackgroundCopyError IBackgroundCopyError_iface; |
| LONG refs; |
| BG_ERROR_CONTEXT context; |
| HRESULT code; |
| IBackgroundCopyFile2 *file; |
| }; |
| |
| static inline struct copy_error *impl_from_IBackgroundCopyError(IBackgroundCopyError *iface) |
| { |
| return CONTAINING_RECORD(iface, struct copy_error, IBackgroundCopyError_iface); |
| } |
| |
| static HRESULT WINAPI copy_error_QueryInterface( |
| IBackgroundCopyError *iface, |
| REFIID riid, |
| void **obj) |
| { |
| struct copy_error *error = impl_from_IBackgroundCopyError(iface); |
| |
| TRACE("(%p)->(%s %p)\n", error, debugstr_guid(riid), obj); |
| |
| if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IBackgroundCopyError)) |
| { |
| *obj = &error->IBackgroundCopyError_iface; |
| } |
| else |
| { |
| *obj = NULL; |
| WARN("interface %s not supported\n", debugstr_guid(riid)); |
| return E_NOINTERFACE; |
| } |
| |
| IBackgroundCopyError_AddRef(iface); |
| return S_OK; |
| } |
| |
| static ULONG WINAPI copy_error_AddRef( |
| IBackgroundCopyError *iface) |
| { |
| struct copy_error *error = impl_from_IBackgroundCopyError(iface); |
| LONG refs = InterlockedIncrement(&error->refs); |
| TRACE("(%p)->(%d)\n", error, refs); |
| return refs; |
| } |
| |
| static ULONG WINAPI copy_error_Release( |
| IBackgroundCopyError *iface) |
| { |
| struct copy_error *error = impl_from_IBackgroundCopyError(iface); |
| LONG refs = InterlockedDecrement(&error->refs); |
| |
| TRACE("(%p)->(%d)\n", error, refs); |
| |
| if (!refs) |
| { |
| if (error->file) IBackgroundCopyFile2_Release(error->file); |
| HeapFree(GetProcessHeap(), 0, error); |
| } |
| return refs; |
| } |
| |
| static HRESULT WINAPI copy_error_GetError( |
| IBackgroundCopyError *iface, |
| BG_ERROR_CONTEXT *pContext, |
| HRESULT *pCode) |
| { |
| struct copy_error *error = impl_from_IBackgroundCopyError(iface); |
| |
| TRACE("(%p)->(%p %p)\n", error, pContext, pCode); |
| |
| *pContext = error->context; |
| *pCode = error->code; |
| |
| TRACE("returning context %u error code 0x%08x\n", error->context, error->code); |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI copy_error_GetFile( |
| IBackgroundCopyError *iface, |
| IBackgroundCopyFile **pVal) |
| { |
| struct copy_error *error = impl_from_IBackgroundCopyError(iface); |
| |
| TRACE("(%p)->(%p)\n", error, pVal); |
| |
| if (error->file) |
| { |
| IBackgroundCopyFile2_AddRef(error->file); |
| *pVal = (IBackgroundCopyFile *)error->file; |
| return S_OK; |
| } |
| *pVal = NULL; |
| return BG_E_FILE_NOT_AVAILABLE; |
| } |
| |
| static HRESULT WINAPI copy_error_GetErrorDescription( |
| IBackgroundCopyError *iface, |
| DWORD LanguageId, |
| LPWSTR *pErrorDescription) |
| { |
| struct copy_error *error = impl_from_IBackgroundCopyError(iface); |
| FIXME("(%p)->(%p)\n", error, pErrorDescription); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI copy_error_GetErrorContextDescription( |
| IBackgroundCopyError *iface, |
| DWORD LanguageId, |
| LPWSTR *pContextDescription) |
| { |
| struct copy_error *error = impl_from_IBackgroundCopyError(iface); |
| FIXME("(%p)->(%p)\n", error, pContextDescription); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI copy_error_GetProtocol( |
| IBackgroundCopyError *iface, |
| LPWSTR *pProtocol) |
| { |
| struct copy_error *error = impl_from_IBackgroundCopyError(iface); |
| FIXME("(%p)->(%p)\n", error, pProtocol); |
| return E_NOTIMPL; |
| } |
| |
| static const IBackgroundCopyErrorVtbl copy_error_vtbl = |
| { |
| copy_error_QueryInterface, |
| copy_error_AddRef, |
| copy_error_Release, |
| copy_error_GetError, |
| copy_error_GetFile, |
| copy_error_GetErrorDescription, |
| copy_error_GetErrorContextDescription, |
| copy_error_GetProtocol |
| }; |
| |
| static HRESULT create_copy_error( |
| BG_ERROR_CONTEXT context, |
| HRESULT code, |
| IBackgroundCopyFile2 *file, |
| IBackgroundCopyError **obj) |
| { |
| struct copy_error *error; |
| |
| TRACE("context %u code %08x file %p\n", context, code, file); |
| |
| if (!(error = HeapAlloc(GetProcessHeap(), 0, sizeof(*error) ))) return E_OUTOFMEMORY; |
| error->IBackgroundCopyError_iface.lpVtbl = ©_error_vtbl; |
| error->refs = 1; |
| error->context = context; |
| error->code = code; |
| error->file = file; |
| if (error->file) IBackgroundCopyFile2_AddRef(error->file); |
| |
| *obj = &error->IBackgroundCopyError_iface; |
| TRACE("returning iface %p\n", *obj); |
| return S_OK; |
| } |
| |
| static inline BOOL is_job_done(const BackgroundCopyJobImpl *job) |
| { |
| return job->state == BG_JOB_STATE_CANCELLED || job->state == BG_JOB_STATE_ACKNOWLEDGED; |
| } |
| |
| static inline BackgroundCopyJobImpl *impl_from_IBackgroundCopyJob3(IBackgroundCopyJob3 *iface) |
| { |
| return CONTAINING_RECORD(iface, BackgroundCopyJobImpl, IBackgroundCopyJob3_iface); |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_QueryInterface( |
| IBackgroundCopyJob3 *iface, REFIID riid, void **obj) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| |
| TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj); |
| |
| if (IsEqualGUID(riid, &IID_IUnknown) || |
| IsEqualGUID(riid, &IID_IBackgroundCopyJob) || |
| IsEqualGUID(riid, &IID_IBackgroundCopyJob2) || |
| IsEqualGUID(riid, &IID_IBackgroundCopyJob3)) |
| { |
| *obj = &This->IBackgroundCopyJob3_iface; |
| } |
| else if (IsEqualGUID(riid, &IID_IBackgroundCopyJobHttpOptions)) |
| { |
| *obj = &This->IBackgroundCopyJobHttpOptions_iface; |
| } |
| else |
| { |
| *obj = NULL; |
| return E_NOINTERFACE; |
| } |
| |
| IBackgroundCopyJob3_AddRef(iface); |
| return S_OK; |
| } |
| |
| static ULONG WINAPI BackgroundCopyJob_AddRef(IBackgroundCopyJob3 *iface) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| ULONG ref = InterlockedIncrement(&This->ref); |
| TRACE("(%p)->(%d)\n", This, ref); |
| return ref; |
| } |
| |
| static ULONG WINAPI BackgroundCopyJob_Release(IBackgroundCopyJob3 *iface) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| ULONG i, j, ref = InterlockedDecrement(&This->ref); |
| |
| TRACE("(%p)->(%d)\n", This, ref); |
| |
| if (ref == 0) |
| { |
| This->cs.DebugInfo->Spare[0] = 0; |
| DeleteCriticalSection(&This->cs); |
| if (This->callback) |
| IBackgroundCopyCallback2_Release(This->callback); |
| HeapFree(GetProcessHeap(), 0, This->displayName); |
| HeapFree(GetProcessHeap(), 0, This->description); |
| HeapFree(GetProcessHeap(), 0, This->http_options.headers); |
| for (i = 0; i < BG_AUTH_TARGET_PROXY; i++) |
| { |
| for (j = 0; j < BG_AUTH_SCHEME_PASSPORT; j++) |
| { |
| BG_AUTH_CREDENTIALS *cred = &This->http_options.creds[i][j]; |
| HeapFree(GetProcessHeap(), 0, cred->Credentials.Basic.UserName); |
| HeapFree(GetProcessHeap(), 0, cred->Credentials.Basic.Password); |
| } |
| } |
| CloseHandle(This->wait); |
| CloseHandle(This->cancel); |
| CloseHandle(This->done); |
| HeapFree(GetProcessHeap(), 0, This); |
| } |
| |
| return ref; |
| } |
| |
| /*** IBackgroundCopyJob methods ***/ |
| |
| static HRESULT WINAPI BackgroundCopyJob_AddFileSet( |
| IBackgroundCopyJob3 *iface, |
| ULONG cFileCount, |
| BG_FILE_INFO *pFileSet) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| HRESULT hr = S_OK; |
| ULONG i; |
| |
| TRACE("(%p)->(%d %p)\n", This, cFileCount, pFileSet); |
| |
| EnterCriticalSection(&This->cs); |
| |
| for (i = 0; i < cFileCount; ++i) |
| { |
| BackgroundCopyFileImpl *file; |
| |
| /* We should return E_INVALIDARG in these cases. */ |
| FIXME("Check for valid filenames and supported protocols\n"); |
| |
| hr = BackgroundCopyFileConstructor(This, pFileSet[i].RemoteName, pFileSet[i].LocalName, &file); |
| if (hr != S_OK) break; |
| |
| /* Add a reference to the file to file list */ |
| list_add_head(&This->files, &file->entryFromJob); |
| This->jobProgress.BytesTotal = BG_SIZE_UNKNOWN; |
| ++This->jobProgress.FilesTotal; |
| } |
| |
| LeaveCriticalSection(&This->cs); |
| |
| return hr; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_AddFile( |
| IBackgroundCopyJob3 *iface, |
| LPCWSTR RemoteUrl, |
| LPCWSTR LocalName) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| BG_FILE_INFO file; |
| |
| TRACE("(%p)->(%s %s)\n", This, debugstr_w(RemoteUrl), debugstr_w(LocalName)); |
| |
| file.RemoteName = (LPWSTR)RemoteUrl; |
| file.LocalName = (LPWSTR)LocalName; |
| return IBackgroundCopyJob3_AddFileSet(iface, 1, &file); |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_EnumFiles( |
| IBackgroundCopyJob3 *iface, |
| IEnumBackgroundCopyFiles **enum_files) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| TRACE("(%p)->(%p)\n", This, enum_files); |
| return EnumBackgroundCopyFilesConstructor(This, enum_files); |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_Suspend( |
| IBackgroundCopyJob3 *iface) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p): stub\n", This); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_Resume( |
| IBackgroundCopyJob3 *iface) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| HRESULT rv = S_OK; |
| |
| TRACE("(%p)\n", This); |
| |
| EnterCriticalSection(&globalMgr.cs); |
| if (is_job_done(This)) |
| { |
| rv = BG_E_INVALID_STATE; |
| } |
| else if (This->jobProgress.FilesTransferred == This->jobProgress.FilesTotal) |
| { |
| rv = BG_E_EMPTY; |
| } |
| else if (This->state != BG_JOB_STATE_CONNECTING |
| && This->state != BG_JOB_STATE_TRANSFERRING) |
| { |
| This->state = BG_JOB_STATE_QUEUED; |
| This->error.context = 0; |
| This->error.code = S_OK; |
| if (This->error.file) |
| { |
| IBackgroundCopyFile2_Release(This->error.file); |
| This->error.file = NULL; |
| } |
| SetEvent(globalMgr.jobEvent); |
| } |
| LeaveCriticalSection(&globalMgr.cs); |
| |
| return rv; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_Cancel( |
| IBackgroundCopyJob3 *iface) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| HRESULT rv = S_OK; |
| |
| TRACE("(%p)\n", This); |
| |
| EnterCriticalSection(&This->cs); |
| |
| if (is_job_done(This)) |
| { |
| rv = BG_E_INVALID_STATE; |
| } |
| else |
| { |
| BackgroundCopyFileImpl *file; |
| |
| if (This->state == BG_JOB_STATE_CONNECTING || This->state == BG_JOB_STATE_TRANSFERRING) |
| { |
| This->state = BG_JOB_STATE_CANCELLED; |
| SetEvent(This->cancel); |
| |
| LeaveCriticalSection(&This->cs); |
| WaitForSingleObject(This->done, INFINITE); |
| EnterCriticalSection(&This->cs); |
| } |
| |
| LIST_FOR_EACH_ENTRY(file, &This->files, BackgroundCopyFileImpl, entryFromJob) |
| { |
| if (file->tempFileName[0] && !DeleteFileW(file->tempFileName)) |
| { |
| WARN("Couldn't delete %s (%u)\n", debugstr_w(file->tempFileName), GetLastError()); |
| rv = BG_S_UNABLE_TO_DELETE_FILES; |
| } |
| if (file->info.LocalName && !DeleteFileW(file->info.LocalName)) |
| { |
| WARN("Couldn't delete %s (%u)\n", debugstr_w(file->info.LocalName), GetLastError()); |
| rv = BG_S_UNABLE_TO_DELETE_FILES; |
| } |
| } |
| This->state = BG_JOB_STATE_CANCELLED; |
| } |
| |
| LeaveCriticalSection(&This->cs); |
| return rv; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_Complete( |
| IBackgroundCopyJob3 *iface) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| HRESULT rv = S_OK; |
| |
| TRACE("(%p)\n", This); |
| |
| EnterCriticalSection(&This->cs); |
| |
| if (is_job_done(This)) |
| { |
| rv = BG_E_INVALID_STATE; |
| } |
| else |
| { |
| BackgroundCopyFileImpl *file; |
| LIST_FOR_EACH_ENTRY(file, &This->files, BackgroundCopyFileImpl, entryFromJob) |
| { |
| if (file->fileProgress.Completed) |
| { |
| if (!MoveFileExW(file->tempFileName, file->info.LocalName, |
| (MOVEFILE_COPY_ALLOWED |
| | MOVEFILE_REPLACE_EXISTING |
| | MOVEFILE_WRITE_THROUGH))) |
| { |
| ERR("Couldn't rename file %s -> %s\n", |
| debugstr_w(file->tempFileName), |
| debugstr_w(file->info.LocalName)); |
| rv = BG_S_PARTIAL_COMPLETE; |
| } |
| } |
| else |
| rv = BG_S_PARTIAL_COMPLETE; |
| } |
| } |
| |
| This->state = BG_JOB_STATE_ACKNOWLEDGED; |
| LeaveCriticalSection(&This->cs); |
| |
| return rv; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetId( |
| IBackgroundCopyJob3 *iface, |
| GUID *pVal) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| TRACE("(%p)->(%p)\n", This, pVal); |
| *pVal = This->jobId; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetType( |
| IBackgroundCopyJob3 *iface, |
| BG_JOB_TYPE *pVal) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| |
| TRACE("(%p)->(%p)\n", This, pVal); |
| |
| if (!pVal) |
| return E_INVALIDARG; |
| |
| *pVal = This->type; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetProgress( |
| IBackgroundCopyJob3 *iface, |
| BG_JOB_PROGRESS *pVal) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| |
| TRACE("(%p)->(%p)\n", This, pVal); |
| |
| if (!pVal) |
| return E_INVALIDARG; |
| |
| EnterCriticalSection(&This->cs); |
| *pVal = This->jobProgress; |
| LeaveCriticalSection(&This->cs); |
| |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetTimes( |
| IBackgroundCopyJob3 *iface, |
| BG_JOB_TIMES *pVal) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%p): stub\n", This, pVal); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetState( |
| IBackgroundCopyJob3 *iface, |
| BG_JOB_STATE *pVal) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| |
| TRACE("(%p)->(%p)\n", This, pVal); |
| |
| if (!pVal) |
| return E_INVALIDARG; |
| |
| /* Don't think we need a critical section for this */ |
| *pVal = This->state; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetError( |
| IBackgroundCopyJob3 *iface, |
| IBackgroundCopyError **ppError) |
| { |
| BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface); |
| |
| TRACE("(%p)->(%p)\n", job, ppError); |
| |
| if (!job->error.context) return BG_E_ERROR_INFORMATION_UNAVAILABLE; |
| |
| return create_copy_error(job->error.context, job->error.code, job->error.file, ppError); |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetOwner( |
| IBackgroundCopyJob3 *iface, |
| LPWSTR *pVal) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%p): stub\n", This, pVal); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_SetDisplayName( |
| IBackgroundCopyJob3 *iface, |
| LPCWSTR Val) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%s): stub\n", This, debugstr_w(Val)); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetDisplayName( |
| IBackgroundCopyJob3 *iface, |
| LPWSTR *pVal) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| |
| TRACE("(%p)->(%p)\n", This, pVal); |
| |
| return return_strval(This->displayName, pVal); |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_SetDescription( |
| IBackgroundCopyJob3 *iface, |
| LPCWSTR Val) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| static const int max_description_len = 1024; |
| HRESULT hr = S_OK; |
| int len; |
| |
| TRACE("(%p)->(%s)\n", This, debugstr_w(Val)); |
| |
| if (!Val) return E_INVALIDARG; |
| |
| len = strlenW(Val); |
| if (len > max_description_len) return BG_E_STRING_TOO_LONG; |
| |
| EnterCriticalSection(&This->cs); |
| |
| if (is_job_done(This)) |
| { |
| hr = BG_E_INVALID_STATE; |
| } |
| else |
| { |
| HeapFree(GetProcessHeap(), 0, This->description); |
| if ((This->description = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR)))) |
| strcpyW(This->description, Val); |
| else |
| hr = E_OUTOFMEMORY; |
| } |
| |
| LeaveCriticalSection(&This->cs); |
| |
| return hr; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetDescription( |
| IBackgroundCopyJob3 *iface, |
| LPWSTR *pVal) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| |
| TRACE("(%p)->(%p)\n", This, pVal); |
| |
| return return_strval(This->description, pVal); |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_SetPriority( |
| IBackgroundCopyJob3 *iface, |
| BG_JOB_PRIORITY Val) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%d): stub\n", This, Val); |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetPriority( |
| IBackgroundCopyJob3 *iface, |
| BG_JOB_PRIORITY *pVal) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%p): stub\n", This, pVal); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_SetNotifyFlags( |
| IBackgroundCopyJob3 *iface, |
| ULONG Val) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| static const ULONG valid_flags = BG_NOTIFY_JOB_TRANSFERRED | |
| BG_NOTIFY_JOB_ERROR | |
| BG_NOTIFY_DISABLE | |
| BG_NOTIFY_JOB_MODIFICATION | |
| BG_NOTIFY_FILE_TRANSFERRED; |
| |
| TRACE("(%p)->(0x%x)\n", This, Val); |
| |
| if (is_job_done(This)) return BG_E_INVALID_STATE; |
| if (Val & ~valid_flags) return E_NOTIMPL; |
| This->notify_flags = Val; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetNotifyFlags( |
| IBackgroundCopyJob3 *iface, |
| ULONG *pVal) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| |
| TRACE("(%p)->(%p)\n", This, pVal); |
| |
| if (!pVal) return E_INVALIDARG; |
| |
| *pVal = This->notify_flags; |
| |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_SetNotifyInterface( |
| IBackgroundCopyJob3 *iface, |
| IUnknown *Val) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| HRESULT hr = S_OK; |
| |
| TRACE("(%p)->(%p)\n", This, Val); |
| |
| if (is_job_done(This)) return BG_E_INVALID_STATE; |
| |
| if (This->callback) |
| { |
| IBackgroundCopyCallback2_Release(This->callback); |
| This->callback = NULL; |
| This->callback2 = FALSE; |
| } |
| |
| if (Val) |
| { |
| hr = IUnknown_QueryInterface(Val, &IID_IBackgroundCopyCallback2, (void**)&This->callback); |
| if (FAILED(hr)) |
| hr = IUnknown_QueryInterface(Val, &IID_IBackgroundCopyCallback, (void**)&This->callback); |
| else |
| This->callback2 = TRUE; |
| } |
| |
| return hr; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetNotifyInterface( |
| IBackgroundCopyJob3 *iface, |
| IUnknown **pVal) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| |
| TRACE("(%p)->(%p)\n", This, pVal); |
| |
| if (!pVal) return E_INVALIDARG; |
| |
| *pVal = (IUnknown*)This->callback; |
| if (*pVal) |
| IUnknown_AddRef(*pVal); |
| |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_SetMinimumRetryDelay( |
| IBackgroundCopyJob3 *iface, |
| ULONG Seconds) |
| { |
| FIXME("%u\n", Seconds); |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetMinimumRetryDelay( |
| IBackgroundCopyJob3 *iface, |
| ULONG *Seconds) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%p): stub\n", This, Seconds); |
| *Seconds = 30; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_SetNoProgressTimeout( |
| IBackgroundCopyJob3 *iface, |
| ULONG Seconds) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%d): stub\n", This, Seconds); |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetNoProgressTimeout( |
| IBackgroundCopyJob3 *iface, |
| ULONG *Seconds) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%p): stub\n", This, Seconds); |
| *Seconds = 900; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetErrorCount( |
| IBackgroundCopyJob3 *iface, |
| ULONG *Errors) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%p): stub\n", This, Errors); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_SetProxySettings( |
| IBackgroundCopyJob3 *iface, |
| BG_JOB_PROXY_USAGE ProxyUsage, |
| const WCHAR *ProxyList, |
| const WCHAR *ProxyBypassList) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%d %s %s): stub\n", This, ProxyUsage, debugstr_w(ProxyList), debugstr_w(ProxyBypassList)); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetProxySettings( |
| IBackgroundCopyJob3 *iface, |
| BG_JOB_PROXY_USAGE *pProxyUsage, |
| LPWSTR *pProxyList, |
| LPWSTR *pProxyBypassList) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%p %p %p): stub\n", This, pProxyUsage, pProxyList, pProxyBypassList); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_TakeOwnership( |
| IBackgroundCopyJob3 *iface) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p): stub\n", This); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_SetNotifyCmdLine( |
| IBackgroundCopyJob3 *iface, |
| LPCWSTR prog, |
| LPCWSTR params) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(prog), debugstr_w(params)); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetNotifyCmdLine( |
| IBackgroundCopyJob3 *iface, |
| LPWSTR *prog, |
| LPWSTR *params) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%p %p): stub\n", This, prog, params); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetReplyProgress( |
| IBackgroundCopyJob3 *iface, |
| BG_JOB_REPLY_PROGRESS *progress) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%p): stub\n", This, progress); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetReplyData( |
| IBackgroundCopyJob3 *iface, |
| byte **pBuffer, |
| UINT64 *pLength) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%p %p): stub\n", This, pBuffer, pLength); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_SetReplyFileName( |
| IBackgroundCopyJob3 *iface, |
| LPCWSTR filename) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%s): stub\n", This, debugstr_w(filename)); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetReplyFileName( |
| IBackgroundCopyJob3 *iface, |
| LPWSTR *pFilename) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%p): stub\n", This, pFilename); |
| return E_NOTIMPL; |
| } |
| |
| static int index_from_target(BG_AUTH_TARGET target) |
| { |
| if (!target || target > BG_AUTH_TARGET_PROXY) return -1; |
| return target - 1; |
| } |
| |
| static int index_from_scheme(BG_AUTH_SCHEME scheme) |
| { |
| if (!scheme || scheme > BG_AUTH_SCHEME_PASSPORT) return -1; |
| return scheme - 1; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_SetCredentials( |
| IBackgroundCopyJob3 *iface, |
| BG_AUTH_CREDENTIALS *cred) |
| { |
| BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface); |
| BG_AUTH_CREDENTIALS *new_cred; |
| int idx_target, idx_scheme; |
| |
| TRACE("(%p)->(%p)\n", job, cred); |
| |
| if ((idx_target = index_from_target(cred->Target)) < 0) return BG_E_INVALID_AUTH_TARGET; |
| if ((idx_scheme = index_from_scheme(cred->Scheme)) < 0) return BG_E_INVALID_AUTH_SCHEME; |
| new_cred = &job->http_options.creds[idx_target][idx_scheme]; |
| |
| EnterCriticalSection(&job->cs); |
| |
| new_cred->Target = cred->Target; |
| new_cred->Scheme = cred->Scheme; |
| |
| if (cred->Credentials.Basic.UserName) |
| { |
| HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.UserName); |
| new_cred->Credentials.Basic.UserName = strdupW(cred->Credentials.Basic.UserName); |
| } |
| if (cred->Credentials.Basic.Password) |
| { |
| HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.Password); |
| new_cred->Credentials.Basic.Password = strdupW(cred->Credentials.Basic.Password); |
| } |
| |
| LeaveCriticalSection(&job->cs); |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_RemoveCredentials( |
| IBackgroundCopyJob3 *iface, |
| BG_AUTH_TARGET target, |
| BG_AUTH_SCHEME scheme) |
| { |
| BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface); |
| BG_AUTH_CREDENTIALS *new_cred; |
| int idx_target, idx_scheme; |
| |
| TRACE("(%p)->(%u %u)\n", job, target, scheme); |
| |
| if ((idx_target = index_from_target(target)) < 0) return BG_E_INVALID_AUTH_TARGET; |
| if ((idx_scheme = index_from_scheme(scheme)) < 0) return BG_E_INVALID_AUTH_SCHEME; |
| new_cred = &job->http_options.creds[idx_target][idx_scheme]; |
| |
| EnterCriticalSection(&job->cs); |
| |
| new_cred->Target = new_cred->Scheme = 0; |
| HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.UserName); |
| new_cred->Credentials.Basic.UserName = NULL; |
| HeapFree(GetProcessHeap(), 0, new_cred->Credentials.Basic.Password); |
| new_cred->Credentials.Basic.Password = NULL; |
| |
| LeaveCriticalSection(&job->cs); |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_ReplaceRemotePrefix( |
| IBackgroundCopyJob3 *iface, |
| LPCWSTR OldPrefix, |
| LPCWSTR NewPrefix) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%s %s): stub\n", This, debugstr_w(OldPrefix), debugstr_w(NewPrefix)); |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_AddFileWithRanges( |
| IBackgroundCopyJob3 *iface, |
| LPCWSTR RemoteUrl, |
| LPCWSTR LocalName, |
| DWORD RangeCount, |
| BG_FILE_RANGE Ranges[]) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%s %s %u %p): stub\n", This, debugstr_w(RemoteUrl), debugstr_w(LocalName), RangeCount, Ranges); |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_SetFileACLFlags( |
| IBackgroundCopyJob3 *iface, |
| DWORD Flags) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%x): stub\n", This, Flags); |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI BackgroundCopyJob_GetFileACLFlags( |
| IBackgroundCopyJob3 *iface, |
| DWORD *Flags) |
| { |
| BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); |
| FIXME("(%p)->(%p): stub\n", This, Flags); |
| return S_OK; |
| } |
| |
| static const IBackgroundCopyJob3Vtbl BackgroundCopyJob3Vtbl = |
| { |
| BackgroundCopyJob_QueryInterface, |
| BackgroundCopyJob_AddRef, |
| BackgroundCopyJob_Release, |
| BackgroundCopyJob_AddFileSet, |
| BackgroundCopyJob_AddFile, |
| BackgroundCopyJob_EnumFiles, |
| BackgroundCopyJob_Suspend, |
| BackgroundCopyJob_Resume, |
| BackgroundCopyJob_Cancel, |
| BackgroundCopyJob_Complete, |
| BackgroundCopyJob_GetId, |
| BackgroundCopyJob_GetType, |
| BackgroundCopyJob_GetProgress, |
| BackgroundCopyJob_GetTimes, |
| BackgroundCopyJob_GetState, |
| BackgroundCopyJob_GetError, |
| BackgroundCopyJob_GetOwner, |
| BackgroundCopyJob_SetDisplayName, |
| BackgroundCopyJob_GetDisplayName, |
| BackgroundCopyJob_SetDescription, |
| BackgroundCopyJob_GetDescription, |
| BackgroundCopyJob_SetPriority, |
| BackgroundCopyJob_GetPriority, |
| BackgroundCopyJob_SetNotifyFlags, |
| BackgroundCopyJob_GetNotifyFlags, |
| BackgroundCopyJob_SetNotifyInterface, |
| BackgroundCopyJob_GetNotifyInterface, |
| BackgroundCopyJob_SetMinimumRetryDelay, |
| BackgroundCopyJob_GetMinimumRetryDelay, |
| BackgroundCopyJob_SetNoProgressTimeout, |
| BackgroundCopyJob_GetNoProgressTimeout, |
| BackgroundCopyJob_GetErrorCount, |
| BackgroundCopyJob_SetProxySettings, |
| BackgroundCopyJob_GetProxySettings, |
| BackgroundCopyJob_TakeOwnership, |
| BackgroundCopyJob_SetNotifyCmdLine, |
| BackgroundCopyJob_GetNotifyCmdLine, |
| BackgroundCopyJob_GetReplyProgress, |
| BackgroundCopyJob_GetReplyData, |
| BackgroundCopyJob_SetReplyFileName, |
| BackgroundCopyJob_GetReplyFileName, |
| BackgroundCopyJob_SetCredentials, |
| BackgroundCopyJob_RemoveCredentials, |
| BackgroundCopyJob_ReplaceRemotePrefix, |
| BackgroundCopyJob_AddFileWithRanges, |
| BackgroundCopyJob_SetFileACLFlags, |
| BackgroundCopyJob_GetFileACLFlags |
| }; |
| |
| static inline BackgroundCopyJobImpl *impl_from_IBackgroundCopyJobHttpOptions( |
| IBackgroundCopyJobHttpOptions *iface) |
| { |
| return CONTAINING_RECORD(iface, BackgroundCopyJobImpl, IBackgroundCopyJobHttpOptions_iface); |
| } |
| |
| static HRESULT WINAPI http_options_QueryInterface( |
| IBackgroundCopyJobHttpOptions *iface, |
| REFIID riid, |
| void **ppvObject) |
| { |
| BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface); |
| return IBackgroundCopyJob3_QueryInterface(&job->IBackgroundCopyJob3_iface, riid, ppvObject); |
| } |
| |
| static ULONG WINAPI http_options_AddRef( |
| IBackgroundCopyJobHttpOptions *iface) |
| { |
| BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface); |
| return IBackgroundCopyJob3_AddRef(&job->IBackgroundCopyJob3_iface); |
| } |
| |
| static ULONG WINAPI http_options_Release( |
| IBackgroundCopyJobHttpOptions *iface) |
| { |
| BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface); |
| return IBackgroundCopyJob3_Release(&job->IBackgroundCopyJob3_iface); |
| } |
| |
| static HRESULT WINAPI http_options_SetClientCertificateByID( |
| IBackgroundCopyJobHttpOptions *iface, |
| BG_CERT_STORE_LOCATION StoreLocation, |
| LPCWSTR StoreName, |
| BYTE *pCertHashBlob) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI http_options_SetClientCertificateByName( |
| IBackgroundCopyJobHttpOptions *iface, |
| BG_CERT_STORE_LOCATION StoreLocation, |
| LPCWSTR StoreName, |
| LPCWSTR SubjectName) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI http_options_RemoveClientCertificate( |
| IBackgroundCopyJobHttpOptions *iface) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI http_options_GetClientCertificate( |
| IBackgroundCopyJobHttpOptions *iface, |
| BG_CERT_STORE_LOCATION *pStoreLocation, |
| LPWSTR *pStoreName, |
| BYTE **ppCertHashBlob, |
| LPWSTR *pSubjectName) |
| { |
| FIXME("\n"); |
| return E_NOTIMPL; |
| } |
| |
| static HRESULT WINAPI http_options_SetCustomHeaders( |
| IBackgroundCopyJobHttpOptions *iface, |
| LPCWSTR RequestHeaders) |
| { |
| BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface); |
| |
| TRACE("(%p)->(%s)\n", iface, debugstr_w(RequestHeaders)); |
| |
| EnterCriticalSection(&job->cs); |
| |
| if (RequestHeaders) |
| { |
| WCHAR *headers = strdupW(RequestHeaders); |
| if (!headers) |
| { |
| LeaveCriticalSection(&job->cs); |
| return E_OUTOFMEMORY; |
| } |
| HeapFree(GetProcessHeap(), 0, job->http_options.headers); |
| job->http_options.headers = headers; |
| } |
| else |
| { |
| HeapFree(GetProcessHeap(), 0, job->http_options.headers); |
| job->http_options.headers = NULL; |
| } |
| |
| LeaveCriticalSection(&job->cs); |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI http_options_GetCustomHeaders( |
| IBackgroundCopyJobHttpOptions *iface, |
| LPWSTR *pRequestHeaders) |
| { |
| BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface); |
| |
| TRACE("(%p)->(%p)\n", iface, pRequestHeaders); |
| |
| EnterCriticalSection(&job->cs); |
| |
| if (job->http_options.headers) |
| { |
| WCHAR *headers = co_strdupW(job->http_options.headers); |
| if (!headers) |
| { |
| LeaveCriticalSection(&job->cs); |
| return E_OUTOFMEMORY; |
| } |
| *pRequestHeaders = headers; |
| LeaveCriticalSection(&job->cs); |
| return S_OK; |
| } |
| |
| *pRequestHeaders = NULL; |
| LeaveCriticalSection(&job->cs); |
| return S_FALSE; |
| } |
| |
| static HRESULT WINAPI http_options_SetSecurityFlags( |
| IBackgroundCopyJobHttpOptions *iface, |
| ULONG Flags) |
| { |
| BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface); |
| |
| TRACE("(%p)->(0x%08x)\n", iface, Flags); |
| |
| job->http_options.flags = Flags; |
| return S_OK; |
| } |
| |
| static HRESULT WINAPI http_options_GetSecurityFlags( |
| IBackgroundCopyJobHttpOptions *iface, |
| ULONG *pFlags) |
| { |
| BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJobHttpOptions(iface); |
| |
| TRACE("(%p)->(%p)\n", iface, pFlags); |
| |
| *pFlags = job->http_options.flags; |
| return S_OK; |
| } |
| |
| static const IBackgroundCopyJobHttpOptionsVtbl http_options_vtbl = |
| { |
| http_options_QueryInterface, |
| http_options_AddRef, |
| http_options_Release, |
| http_options_SetClientCertificateByID, |
| http_options_SetClientCertificateByName, |
| http_options_RemoveClientCertificate, |
| http_options_GetClientCertificate, |
| http_options_SetCustomHeaders, |
| http_options_GetCustomHeaders, |
| http_options_SetSecurityFlags, |
| http_options_GetSecurityFlags |
| }; |
| |
| HRESULT BackgroundCopyJobConstructor(LPCWSTR displayName, BG_JOB_TYPE type, GUID *job_id, BackgroundCopyJobImpl **job) |
| { |
| HRESULT hr; |
| BackgroundCopyJobImpl *This; |
| |
| TRACE("(%s,%d,%p)\n", debugstr_w(displayName), type, job); |
| |
| This = HeapAlloc(GetProcessHeap(), 0, sizeof *This); |
| if (!This) |
| return E_OUTOFMEMORY; |
| |
| This->IBackgroundCopyJob3_iface.lpVtbl = &BackgroundCopyJob3Vtbl; |
| This->IBackgroundCopyJobHttpOptions_iface.lpVtbl = &http_options_vtbl; |
| InitializeCriticalSection(&This->cs); |
| This->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": BackgroundCopyJobImpl.cs"); |
| |
| This->ref = 1; |
| This->type = type; |
| |
| This->displayName = strdupW(displayName); |
| if (!This->displayName) |
| { |
| This->cs.DebugInfo->Spare[0] = 0; |
| DeleteCriticalSection(&This->cs); |
| HeapFree(GetProcessHeap(), 0, This); |
| return E_OUTOFMEMORY; |
| } |
| |
| hr = CoCreateGuid(&This->jobId); |
| if (FAILED(hr)) |
| { |
| This->cs.DebugInfo->Spare[0] = 0; |
| DeleteCriticalSection(&This->cs); |
| HeapFree(GetProcessHeap(), 0, This->displayName); |
| HeapFree(GetProcessHeap(), 0, This); |
| return hr; |
| } |
| *job_id = This->jobId; |
| |
| list_init(&This->files); |
| This->jobProgress.BytesTotal = 0; |
| This->jobProgress.BytesTransferred = 0; |
| This->jobProgress.FilesTotal = 0; |
| This->jobProgress.FilesTransferred = 0; |
| |
| This->state = BG_JOB_STATE_SUSPENDED; |
| This->description = NULL; |
| This->notify_flags = BG_NOTIFY_JOB_ERROR | BG_NOTIFY_JOB_TRANSFERRED; |
| This->callback = NULL; |
| This->callback2 = FALSE; |
| |
| This->error.context = 0; |
| This->error.code = S_OK; |
| This->error.file = NULL; |
| |
| memset(&This->http_options, 0, sizeof(This->http_options)); |
| |
| This->wait = CreateEventW(NULL, FALSE, FALSE, NULL); |
| This->cancel = CreateEventW(NULL, FALSE, FALSE, NULL); |
| This->done = CreateEventW(NULL, FALSE, FALSE, NULL); |
| |
| *job = This; |
| |
| TRACE("created job %s:%p\n", debugstr_guid(&This->jobId), This); |
| |
| return S_OK; |
| } |
| |
| void processJob(BackgroundCopyJobImpl *job) |
| { |
| for (;;) |
| { |
| BackgroundCopyFileImpl *file; |
| BOOL done = TRUE; |
| |
| EnterCriticalSection(&job->cs); |
| LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob) |
| if (!file->fileProgress.Completed) |
| { |
| done = FALSE; |
| break; |
| } |
| LeaveCriticalSection(&job->cs); |
| if (done) |
| { |
| transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRED); |
| return; |
| } |
| |
| if (!processFile(file, job)) |
| return; |
| } |
| } |