From c22de4d293cf9c2595c58f4d68d7e33890084a21 Mon Sep 17 00:00:00 2001 From: Amine Khaldi Date: Mon, 20 Jul 2015 22:48:28 +0000 Subject: [PATCH] [QMGR] Sync with Wine Staging 1.7.47. CORE-9924 svn path=/trunk/; revision=68490 --- reactos/dll/win32/qmgr/CMakeLists.txt | 2 +- reactos/dll/win32/qmgr/enum_files.c | 14 +- reactos/dll/win32/qmgr/enum_jobs.c | 15 +- reactos/dll/win32/qmgr/file.c | 541 +++++++++++-------- reactos/dll/win32/qmgr/job.c | 736 ++++++++++++++++++++++---- reactos/dll/win32/qmgr/qmgr.c | 10 +- reactos/dll/win32/qmgr/qmgr.h | 55 +- reactos/dll/win32/qmgr/qmgr_local.idl | 2 + reactos/media/doc/README.WINE | 2 +- 9 files changed, 999 insertions(+), 378 deletions(-) diff --git a/reactos/dll/win32/qmgr/CMakeLists.txt b/reactos/dll/win32/qmgr/CMakeLists.txt index c1695c288b9..8d962e5e418 100644 --- a/reactos/dll/win32/qmgr/CMakeLists.txt +++ b/reactos/dll/win32/qmgr/CMakeLists.txt @@ -25,7 +25,7 @@ set_source_files_properties(rsrc.rc PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_SO add_idl_headers(qmgr_idlheader qmgr_local.idl) set_module_type(qmgr win32dll) target_link_libraries(qmgr uuid wine) -add_importlibs(qmgr ole32 wininet urlmon advapi32 msvcrt kernel32 ntdll) +add_importlibs(qmgr winhttp ole32 advapi32 msvcrt kernel32 ntdll) add_pch(qmgr qmgr.h SOURCE) add_cd_file(TARGET qmgr DESTINATION reactos/system32 FOR all) add_dependencies(qmgr qmgr_idlheader) diff --git a/reactos/dll/win32/qmgr/enum_files.c b/reactos/dll/win32/qmgr/enum_files.c index c7648a7db9a..8945370ee90 100644 --- a/reactos/dll/win32/qmgr/enum_files.c +++ b/reactos/dll/win32/qmgr/enum_files.c @@ -24,7 +24,7 @@ typedef struct { IEnumBackgroundCopyFiles IEnumBackgroundCopyFiles_iface; LONG ref; - IBackgroundCopyFile **files; + IBackgroundCopyFile2 **files; ULONG numFiles; ULONG indexFiles; } EnumBackgroundCopyFilesImpl; @@ -72,7 +72,7 @@ static ULONG WINAPI EnumBackgroundCopyFiles_Release(IEnumBackgroundCopyFiles *if if (ref == 0) { for(i = 0; i < This->numFiles; i++) - IBackgroundCopyFile_Release(This->files[i]); + IBackgroundCopyFile2_Release(This->files[i]); HeapFree(GetProcessHeap(), 0, This->files); HeapFree(GetProcessHeap(), 0, This); } @@ -87,7 +87,7 @@ static HRESULT WINAPI EnumBackgroundCopyFiles_Next(IEnumBackgroundCopyFiles *ifa EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface); ULONG fetched; ULONG i; - IBackgroundCopyFile *file; + IBackgroundCopyFile2 *file; TRACE("(%p)->(%d %p %p)\n", This, celt, rgelt, pceltFetched); @@ -113,8 +113,8 @@ static HRESULT WINAPI EnumBackgroundCopyFiles_Next(IEnumBackgroundCopyFiles *ifa for (i = 0; i < fetched; i++) { file = This->files[This->indexFiles++]; - IBackgroundCopyFile_AddRef(file); - rgelt[i] = file; + IBackgroundCopyFile2_AddRef(file); + rgelt[i] = (IBackgroundCopyFile *)file; } return fetched == celt ? S_OK : S_FALSE; @@ -212,8 +212,8 @@ HRESULT EnumBackgroundCopyFilesConstructor(BackgroundCopyJobImpl *job, IEnumBack i = 0; LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob) { - IBackgroundCopyFile_AddRef(&file->IBackgroundCopyFile_iface); - This->files[i] = &file->IBackgroundCopyFile_iface; + IBackgroundCopyFile2_AddRef(&file->IBackgroundCopyFile2_iface); + This->files[i] = &file->IBackgroundCopyFile2_iface; ++i; } LeaveCriticalSection(&job->cs); diff --git a/reactos/dll/win32/qmgr/enum_jobs.c b/reactos/dll/win32/qmgr/enum_jobs.c index 5dd5d3b083d..c942547fb90 100644 --- a/reactos/dll/win32/qmgr/enum_jobs.c +++ b/reactos/dll/win32/qmgr/enum_jobs.c @@ -24,7 +24,7 @@ typedef struct { IEnumBackgroundCopyJobs IEnumBackgroundCopyJobs_iface; LONG ref; - IBackgroundCopyJob **jobs; + IBackgroundCopyJob3 **jobs; ULONG numJobs; ULONG indexJobs; } EnumBackgroundCopyJobsImpl; @@ -72,7 +72,7 @@ static ULONG WINAPI EnumBackgroundCopyJobs_Release(IEnumBackgroundCopyJobs *ifac if (ref == 0) { for(i = 0; i < This->numJobs; i++) - IBackgroundCopyJob_Release(This->jobs[i]); + IBackgroundCopyJob3_Release(This->jobs[i]); HeapFree(GetProcessHeap(), 0, This->jobs); HeapFree(GetProcessHeap(), 0, This); } @@ -86,7 +86,7 @@ static HRESULT WINAPI EnumBackgroundCopyJobs_Next(IEnumBackgroundCopyJobs *iface EnumBackgroundCopyJobsImpl *This = impl_from_IEnumBackgroundCopyJobs(iface); ULONG fetched; ULONG i; - IBackgroundCopyJob *job; + IBackgroundCopyJob3 *job; TRACE("(%p)->(%d %p %p)\n", This, celt, rgelt, pceltFetched); @@ -109,8 +109,8 @@ static HRESULT WINAPI EnumBackgroundCopyJobs_Next(IEnumBackgroundCopyJobs *iface for (i = 0; i < fetched; ++i) { job = This->jobs[This->indexJobs++]; - IBackgroundCopyJob_AddRef(job); - rgelt[i] = job; + IBackgroundCopyJob3_AddRef(job); + rgelt[i] = (IBackgroundCopyJob *)job; } return fetched == celt ? S_OK : S_FALSE; @@ -210,9 +210,8 @@ HRESULT enum_copy_job_create(BackgroundCopyManagerImpl *qmgr, IEnumBackgroundCop i = 0; LIST_FOR_EACH_ENTRY(job, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr) { - IBackgroundCopyJob *job_iface = (IBackgroundCopyJob*)&job->IBackgroundCopyJob2_iface; - IBackgroundCopyJob_AddRef(job_iface); - This->jobs[i++] = job_iface; + IBackgroundCopyJob3_AddRef(&job->IBackgroundCopyJob3_iface); + This->jobs[i++] = &job->IBackgroundCopyJob3_iface; } LeaveCriticalSection(&qmgr->cs); diff --git a/reactos/dll/win32/qmgr/file.c b/reactos/dll/win32/qmgr/file.c index 1aee9b8700b..cb4c3a479b0 100644 --- a/reactos/dll/win32/qmgr/file.c +++ b/reactos/dll/win32/qmgr/file.c @@ -21,56 +21,62 @@ #include "qmgr.h" #include -#include +#include -static inline BackgroundCopyFileImpl *impl_from_IBackgroundCopyFile(IBackgroundCopyFile *iface) +static inline BackgroundCopyFileImpl *impl_from_IBackgroundCopyFile2( + IBackgroundCopyFile2 *iface) { - return CONTAINING_RECORD(iface, BackgroundCopyFileImpl, IBackgroundCopyFile_iface); + return CONTAINING_RECORD(iface, BackgroundCopyFileImpl, IBackgroundCopyFile2_iface); } static HRESULT WINAPI BackgroundCopyFile_QueryInterface( - IBackgroundCopyFile* iface, + IBackgroundCopyFile2 *iface, REFIID riid, void **obj) { - BackgroundCopyFileImpl *This = impl_from_IBackgroundCopyFile(iface); + BackgroundCopyFileImpl *file = impl_from_IBackgroundCopyFile2(iface); - TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), obj); + TRACE("(%p)->(%s %p)\n", file, debugstr_guid(riid), obj); - if (IsEqualGUID(riid, &IID_IUnknown) - || IsEqualGUID(riid, &IID_IBackgroundCopyFile)) + if (IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IBackgroundCopyFile) || + IsEqualGUID(riid, &IID_IBackgroundCopyFile2)) { *obj = iface; - IBackgroundCopyFile_AddRef(iface); - return S_OK; + } + else + { + *obj = NULL; + return E_NOINTERFACE; } - *obj = NULL; - return E_NOINTERFACE; + IBackgroundCopyFile2_AddRef(iface); + return S_OK; } -static ULONG WINAPI BackgroundCopyFile_AddRef(IBackgroundCopyFile* iface) +static ULONG WINAPI BackgroundCopyFile_AddRef( + IBackgroundCopyFile2 *iface) { - BackgroundCopyFileImpl *This = impl_from_IBackgroundCopyFile(iface); - ULONG ref = InterlockedIncrement(&This->ref); - TRACE("(%p)->(%d)\n", This, ref); + BackgroundCopyFileImpl *file = impl_from_IBackgroundCopyFile2(iface); + ULONG ref = InterlockedIncrement(&file->ref); + TRACE("(%p)->(%d)\n", file, ref); return ref; } static ULONG WINAPI BackgroundCopyFile_Release( - IBackgroundCopyFile* iface) + IBackgroundCopyFile2 *iface) { - BackgroundCopyFileImpl *This = impl_from_IBackgroundCopyFile(iface); - ULONG ref = InterlockedDecrement(&This->ref); + BackgroundCopyFileImpl *file = impl_from_IBackgroundCopyFile2(iface); + ULONG ref = InterlockedDecrement(&file->ref); - TRACE("(%p)->(%d)\n", This, ref); + TRACE("(%p)->(%d)\n", file, ref); if (ref == 0) { - IBackgroundCopyJob2_Release(&This->owner->IBackgroundCopyJob2_iface); - HeapFree(GetProcessHeap(), 0, This->info.LocalName); - HeapFree(GetProcessHeap(), 0, This->info.RemoteName); - HeapFree(GetProcessHeap(), 0, This); + IBackgroundCopyJob3_Release(&file->owner->IBackgroundCopyJob3_iface); + HeapFree(GetProcessHeap(), 0, file->info.LocalName); + HeapFree(GetProcessHeap(), 0, file->info.RemoteName); + HeapFree(GetProcessHeap(), 0, file); } return ref; @@ -78,52 +84,71 @@ static ULONG WINAPI BackgroundCopyFile_Release( /* Get the remote name of a background copy file */ static HRESULT WINAPI BackgroundCopyFile_GetRemoteName( - IBackgroundCopyFile* iface, + IBackgroundCopyFile2 *iface, LPWSTR *pVal) { - BackgroundCopyFileImpl *This = impl_from_IBackgroundCopyFile(iface); + BackgroundCopyFileImpl *file = impl_from_IBackgroundCopyFile2(iface); - TRACE("(%p)->(%p)\n", This, pVal); + TRACE("(%p)->(%p)\n", file, pVal); - return return_strval(This->info.RemoteName, pVal); + return return_strval(file->info.RemoteName, pVal); } static HRESULT WINAPI BackgroundCopyFile_GetLocalName( - IBackgroundCopyFile* iface, + IBackgroundCopyFile2 *iface, LPWSTR *pVal) { - BackgroundCopyFileImpl *This = impl_from_IBackgroundCopyFile(iface); + BackgroundCopyFileImpl *file = impl_from_IBackgroundCopyFile2(iface); - TRACE("(%p)->(%p)\n", This, pVal); + TRACE("(%p)->(%p)\n", file, pVal); - return return_strval(This->info.LocalName, pVal); + return return_strval(file->info.LocalName, pVal); } static HRESULT WINAPI BackgroundCopyFile_GetProgress( - IBackgroundCopyFile* iface, + IBackgroundCopyFile2 *iface, BG_FILE_PROGRESS *pVal) { - BackgroundCopyFileImpl *This = impl_from_IBackgroundCopyFile(iface); + BackgroundCopyFileImpl *file = impl_from_IBackgroundCopyFile2(iface); - TRACE("(%p)->(%p)\n", This, pVal); + TRACE("(%p)->(%p)\n", file, pVal); - EnterCriticalSection(&This->owner->cs); - pVal->BytesTotal = This->fileProgress.BytesTotal; - pVal->BytesTransferred = This->fileProgress.BytesTransferred; - pVal->Completed = This->fileProgress.Completed; - LeaveCriticalSection(&This->owner->cs); + EnterCriticalSection(&file->owner->cs); + *pVal = file->fileProgress; + LeaveCriticalSection(&file->owner->cs); return S_OK; } -static const IBackgroundCopyFileVtbl BackgroundCopyFileVtbl = +static HRESULT WINAPI BackgroundCopyFile_GetFileRanges( + IBackgroundCopyFile2 *iface, + DWORD *RangeCount, + BG_FILE_RANGE **Ranges) +{ + BackgroundCopyFileImpl *file = impl_from_IBackgroundCopyFile2(iface); + FIXME("(%p)->(%p %p)\n", file, RangeCount, Ranges); + return E_NOTIMPL; +} + +static HRESULT WINAPI BackgroundCopyFile_SetRemoteName( + IBackgroundCopyFile2 *iface, + LPCWSTR Val) +{ + BackgroundCopyFileImpl *file = impl_from_IBackgroundCopyFile2(iface); + FIXME("(%p)->(%s)\n", file, debugstr_w(Val)); + return E_NOTIMPL; +} + +static const IBackgroundCopyFile2Vtbl BackgroundCopyFile2Vtbl = { BackgroundCopyFile_QueryInterface, BackgroundCopyFile_AddRef, BackgroundCopyFile_Release, BackgroundCopyFile_GetRemoteName, BackgroundCopyFile_GetLocalName, - BackgroundCopyFile_GetProgress + BackgroundCopyFile_GetProgress, + BackgroundCopyFile_GetFileRanges, + BackgroundCopyFile_SetRemoteName }; HRESULT BackgroundCopyFileConstructor(BackgroundCopyJobImpl *owner, @@ -131,7 +156,6 @@ HRESULT BackgroundCopyFileConstructor(BackgroundCopyJobImpl *owner, BackgroundCopyFileImpl **file) { BackgroundCopyFileImpl *This; - int n; TRACE("(%s, %s, %p)\n", debugstr_w(remoteName), debugstr_w(localName), file); @@ -139,233 +163,314 @@ HRESULT BackgroundCopyFileConstructor(BackgroundCopyJobImpl *owner, if (!This) return E_OUTOFMEMORY; - n = (lstrlenW(remoteName) + 1) * sizeof(WCHAR); - This->info.RemoteName = HeapAlloc(GetProcessHeap(), 0, n); + This->info.RemoteName = strdupW(remoteName); if (!This->info.RemoteName) { HeapFree(GetProcessHeap(), 0, This); return E_OUTOFMEMORY; } - memcpy(This->info.RemoteName, remoteName, n); - n = (lstrlenW(localName) + 1) * sizeof(WCHAR); - This->info.LocalName = HeapAlloc(GetProcessHeap(), 0, n); + This->info.LocalName = strdupW(localName); if (!This->info.LocalName) { HeapFree(GetProcessHeap(), 0, This->info.RemoteName); HeapFree(GetProcessHeap(), 0, This); return E_OUTOFMEMORY; } - memcpy(This->info.LocalName, localName, n); - This->IBackgroundCopyFile_iface.lpVtbl = &BackgroundCopyFileVtbl; + This->IBackgroundCopyFile2_iface.lpVtbl = &BackgroundCopyFile2Vtbl; This->ref = 1; This->fileProgress.BytesTotal = BG_SIZE_UNKNOWN; This->fileProgress.BytesTransferred = 0; This->fileProgress.Completed = FALSE; This->owner = owner; - IBackgroundCopyJob2_AddRef(&owner->IBackgroundCopyJob2_iface); + This->read_size = 0; + This->tempFileName[0] = 0; + IBackgroundCopyJob3_AddRef(&owner->IBackgroundCopyJob3_iface); *file = This; return S_OK; } -static DWORD CALLBACK copyProgressCallback(LARGE_INTEGER totalSize, - LARGE_INTEGER totalTransferred, - LARGE_INTEGER streamSize, - LARGE_INTEGER streamTransferred, - DWORD streamNum, - DWORD reason, - HANDLE srcFile, - HANDLE dstFile, - LPVOID obj) +static HRESULT error_from_http_response(DWORD code) { - BackgroundCopyFileImpl *file = obj; - BackgroundCopyJobImpl *job = file->owner; - ULONG64 diff; - - EnterCriticalSection(&job->cs); - diff = (file->fileProgress.BytesTotal == BG_SIZE_UNKNOWN - ? totalTransferred.QuadPart - : totalTransferred.QuadPart - file->fileProgress.BytesTransferred); - file->fileProgress.BytesTotal = totalSize.QuadPart; - file->fileProgress.BytesTransferred = totalTransferred.QuadPart; - job->jobProgress.BytesTransferred += diff; - LeaveCriticalSection(&job->cs); - - return (job->state == BG_JOB_STATE_TRANSFERRING - ? PROGRESS_CONTINUE - : PROGRESS_CANCEL); + switch (code) + { + case 200: return S_OK; + case 400: return BG_E_HTTP_ERROR_400; + case 401: return BG_E_HTTP_ERROR_401; + case 404: return BG_E_HTTP_ERROR_404; + case 407: return BG_E_HTTP_ERROR_407; + case 414: return BG_E_HTTP_ERROR_414; + case 501: return BG_E_HTTP_ERROR_501; + case 503: return BG_E_HTTP_ERROR_503; + case 504: return BG_E_HTTP_ERROR_504; + case 505: return BG_E_HTTP_ERROR_505; + default: + FIXME("unhandled response code %u\n", code); + return S_OK; + } } -typedef struct +static void CALLBACK progress_callback_http(HINTERNET handle, DWORD_PTR context, DWORD status, + LPVOID buf, DWORD buflen) { - IBindStatusCallback IBindStatusCallback_iface; - BackgroundCopyFileImpl *file; - LONG ref; -} DLBindStatusCallback; + BackgroundCopyFileImpl *file = (BackgroundCopyFileImpl *)context; + BackgroundCopyJobImpl *job = file->owner; -static inline DLBindStatusCallback *impl_from_IBindStatusCallback(IBindStatusCallback *iface) -{ - return CONTAINING_RECORD(iface, DLBindStatusCallback, IBindStatusCallback_iface); -} + TRACE("%p, %p, %x, %p, %u\n", handle, file, status, buf, buflen); -static HRESULT WINAPI DLBindStatusCallback_QueryInterface( - IBindStatusCallback *iface, - REFIID riid, - void **ppvObject) -{ - DLBindStatusCallback *This = impl_from_IBindStatusCallback(iface); + switch (status) + { + case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE: + { + DWORD code, len, size; - if (IsEqualGUID(riid, &IID_IUnknown) - || IsEqualGUID(riid, &IID_IBindStatusCallback)) + size = sizeof(code); + if (WinHttpQueryHeaders(handle, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, + NULL, &code, &size, NULL)) + { + if ((job->error.code = error_from_http_response(code))) + { + EnterCriticalSection(&job->cs); + + job->error.context = BG_ERROR_CONTEXT_REMOTE_FILE; + if (job->error.file) IBackgroundCopyFile2_Release(job->error.file); + job->error.file = &file->IBackgroundCopyFile2_iface; + IBackgroundCopyFile2_AddRef(job->error.file); + + LeaveCriticalSection(&job->cs); + transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR); + } + else + { + EnterCriticalSection(&job->cs); + + job->error.context = 0; + if (job->error.file) + { + IBackgroundCopyFile2_Release(job->error.file); + job->error.file = NULL; + } + + LeaveCriticalSection(&job->cs); + } + } + size = sizeof(len); + if (WinHttpQueryHeaders(handle, WINHTTP_QUERY_CONTENT_LENGTH|WINHTTP_QUERY_FLAG_NUMBER, + NULL, &len, &size, NULL)) + { + file->fileProgress.BytesTotal = len; + } + break; + } + case WINHTTP_CALLBACK_STATUS_READ_COMPLETE: { - *ppvObject = &This->IBindStatusCallback_iface; - IBindStatusCallback_AddRef(iface); - return S_OK; + file->read_size = buflen; + break; + } + case WINHTTP_CALLBACK_STATUS_REQUEST_ERROR: + { + WINHTTP_ASYNC_RESULT *result = (WINHTTP_ASYNC_RESULT *)buf; + job->error.code = result->dwError; + transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR); + break; + } + default: break; } - *ppvObject = NULL; - return E_NOINTERFACE; -} - -static ULONG WINAPI DLBindStatusCallback_AddRef(IBindStatusCallback *iface) -{ - DLBindStatusCallback *This = impl_from_IBindStatusCallback(iface); - return InterlockedIncrement(&This->ref); + SetEvent(job->wait); } -static ULONG WINAPI DLBindStatusCallback_Release(IBindStatusCallback *iface) +static DWORD wait_for_completion(BackgroundCopyJobImpl *job) { - DLBindStatusCallback *This = impl_from_IBindStatusCallback(iface); - ULONG ref = InterlockedDecrement(&This->ref); + HANDLE handles[2] = {job->wait, job->cancel}; + DWORD error = ERROR_SUCCESS; - if (ref == 0) + switch (WaitForMultipleObjects(2, handles, FALSE, INFINITE)) { - IBackgroundCopyFile_Release(&This->file->IBackgroundCopyFile_iface); - HeapFree(GetProcessHeap(), 0, This); + case WAIT_OBJECT_0: + break; + + case WAIT_OBJECT_0 + 1: + error = ERROR_CANCELLED; + transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_CANCELLED); + break; + + default: + error = GetLastError(); + transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR); + break; } - return ref; + return error; } -static HRESULT WINAPI DLBindStatusCallback_GetBindInfo( - IBindStatusCallback *iface, - DWORD *grfBINDF, - BINDINFO *pbindinfo) +static UINT target_from_index(UINT index) { - return E_NOTIMPL; + switch (index) + { + case 0: return WINHTTP_AUTH_TARGET_SERVER; + case 1: return WINHTTP_AUTH_TARGET_PROXY; + default: + ERR("unhandled index %u\n", index); + break; + } + return 0; } -static HRESULT WINAPI DLBindStatusCallback_GetPriority( - IBindStatusCallback *iface, - LONG *pnPriority) +static UINT scheme_from_index(UINT index) { - return E_NOTIMPL; + switch (index) + { + case 0: return WINHTTP_AUTH_SCHEME_BASIC; + case 1: return WINHTTP_AUTH_SCHEME_NTLM; + case 2: return WINHTTP_AUTH_SCHEME_PASSPORT; + case 3: return WINHTTP_AUTH_SCHEME_DIGEST; + case 4: return WINHTTP_AUTH_SCHEME_NEGOTIATE; + default: + ERR("unhandled index %u\n", index); + break; + } + return 0; } -static HRESULT WINAPI DLBindStatusCallback_OnDataAvailable( - IBindStatusCallback *iface, - DWORD grfBSCF, - DWORD dwSize, - FORMATETC *pformatetc, - STGMEDIUM *pstgmed) +static BOOL set_request_credentials(HINTERNET req, BackgroundCopyJobImpl *job) { - return E_NOTIMPL; -} + UINT i, j; -static HRESULT WINAPI DLBindStatusCallback_OnLowResource( - IBindStatusCallback *iface, - DWORD reserved) -{ - return E_NOTIMPL; + for (i = 0; i < BG_AUTH_TARGET_PROXY; i++) + { + UINT target = target_from_index(i); + for (j = 0; j < BG_AUTH_SCHEME_PASSPORT; j++) + { + UINT scheme = scheme_from_index(j); + const WCHAR *username = job->http_options.creds[i][j].Credentials.Basic.UserName; + const WCHAR *password = job->http_options.creds[i][j].Credentials.Basic.Password; + + if (!username) continue; + if (!WinHttpSetCredentials(req, target, scheme, username, password, NULL)) return FALSE; + } + } + return TRUE; } -static HRESULT WINAPI DLBindStatusCallback_OnObjectAvailable( - IBindStatusCallback *iface, - REFIID riid, - IUnknown *punk) +static BOOL transfer_file_http(BackgroundCopyFileImpl *file, URL_COMPONENTSW *uc, + const WCHAR *tmpfile) { - return E_NOTIMPL; + BackgroundCopyJobImpl *job = file->owner; + HANDLE handle; + HINTERNET ses, con = NULL, req = NULL; + DWORD flags = (uc->nScheme == INTERNET_SCHEME_HTTPS) ? WINHTTP_FLAG_SECURE : 0; + char buf[4096]; + BOOL ret = FALSE; + + transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_CONNECTING); + + if (!(ses = WinHttpOpen(NULL, 0, NULL, NULL, WINHTTP_FLAG_ASYNC))) return FALSE; + WinHttpSetStatusCallback(ses, progress_callback_http, WINHTTP_CALLBACK_FLAG_ALL_COMPLETIONS, 0); + if (!WinHttpSetOption(ses, WINHTTP_OPTION_CONTEXT_VALUE, &file, sizeof(file))) goto done; + + if (!(con = WinHttpConnect(ses, uc->lpszHostName, uc->nPort, 0))) goto done; + if (!(req = WinHttpOpenRequest(con, NULL, uc->lpszUrlPath, NULL, NULL, NULL, flags))) goto done; + if (!set_request_credentials(req, job)) goto done; + + if (!(WinHttpSendRequest(req, job->http_options.headers, ~0u, NULL, 0, 0, (DWORD_PTR)file))) goto done; + if (wait_for_completion(job) || job->error.code) goto done; + + if (!(WinHttpReceiveResponse(req, NULL))) goto done; + if (wait_for_completion(job) || job->error.code) goto done; + + transitionJobState(job, BG_JOB_STATE_CONNECTING, BG_JOB_STATE_TRANSFERRING); + + handle = CreateFileW(tmpfile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (handle == INVALID_HANDLE_VALUE) goto done; + + for (;;) + { + file->read_size = 0; + if (!(ret = WinHttpReadData(req, buf, sizeof(buf), NULL))) break; + if (wait_for_completion(job) || job->error.code) + { + ret = FALSE; + break; + } + if (!file->read_size) break; + if (!(ret = WriteFile(handle, buf, file->read_size, NULL, NULL))) break; + + EnterCriticalSection(&job->cs); + file->fileProgress.BytesTransferred += file->read_size; + job->jobProgress.BytesTransferred += file->read_size; + LeaveCriticalSection(&job->cs); + } + + CloseHandle(handle); + +done: + WinHttpCloseHandle(req); + WinHttpCloseHandle(con); + WinHttpCloseHandle(ses); + if (!ret) DeleteFileW(tmpfile); + + SetEvent(job->done); + return ret; } -static HRESULT WINAPI DLBindStatusCallback_OnProgress( - IBindStatusCallback *iface, - ULONG progress, - ULONG progressMax, - ULONG statusCode, - LPCWSTR statusText) +static DWORD CALLBACK progress_callback_local(LARGE_INTEGER totalSize, LARGE_INTEGER totalTransferred, + LARGE_INTEGER streamSize, LARGE_INTEGER streamTransferred, + DWORD streamNum, DWORD reason, HANDLE srcFile, + HANDLE dstFile, LPVOID obj) { - DLBindStatusCallback *This = impl_from_IBindStatusCallback(iface); - BackgroundCopyFileImpl *file = This->file; + BackgroundCopyFileImpl *file = obj; BackgroundCopyJobImpl *job = file->owner; ULONG64 diff; EnterCriticalSection(&job->cs); diff = (file->fileProgress.BytesTotal == BG_SIZE_UNKNOWN - ? progress - : progress - file->fileProgress.BytesTransferred); - file->fileProgress.BytesTotal = progressMax ? progressMax : BG_SIZE_UNKNOWN; - file->fileProgress.BytesTransferred = progress; + ? totalTransferred.QuadPart + : totalTransferred.QuadPart - file->fileProgress.BytesTransferred); + file->fileProgress.BytesTotal = totalSize.QuadPart; + file->fileProgress.BytesTransferred = totalTransferred.QuadPart; job->jobProgress.BytesTransferred += diff; LeaveCriticalSection(&job->cs); - return S_OK; + return (job->state == BG_JOB_STATE_TRANSFERRING + ? PROGRESS_CONTINUE + : PROGRESS_CANCEL); } -static HRESULT WINAPI DLBindStatusCallback_OnStartBinding( - IBindStatusCallback *iface, - DWORD dwReserved, - IBinding *pib) +static BOOL transfer_file_local(BackgroundCopyFileImpl *file, const WCHAR *tmpname) { - return E_NOTIMPL; -} + static const WCHAR fileW[] = {'f','i','l','e',':','/','/',0}; + BackgroundCopyJobImpl *job = file->owner; + const WCHAR *ptr; + BOOL ret; -static HRESULT WINAPI DLBindStatusCallback_OnStopBinding( - IBindStatusCallback *iface, - HRESULT hresult, - LPCWSTR szError) -{ - return E_NOTIMPL; -} + transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRING); -static const IBindStatusCallbackVtbl DLBindStatusCallback_Vtbl = -{ - DLBindStatusCallback_QueryInterface, - DLBindStatusCallback_AddRef, - DLBindStatusCallback_Release, - DLBindStatusCallback_OnStartBinding, - DLBindStatusCallback_GetPriority, - DLBindStatusCallback_OnLowResource, - DLBindStatusCallback_OnProgress, - DLBindStatusCallback_OnStopBinding, - DLBindStatusCallback_GetBindInfo, - DLBindStatusCallback_OnDataAvailable, - DLBindStatusCallback_OnObjectAvailable -}; + if (strlenW(file->info.RemoteName) > 7 && !memicmpW(file->info.RemoteName, fileW, 7)) + ptr = file->info.RemoteName + 7; + else + ptr = file->info.RemoteName; -static DLBindStatusCallback *DLBindStatusCallbackConstructor( - BackgroundCopyFileImpl *file) -{ - DLBindStatusCallback *This = HeapAlloc(GetProcessHeap(), 0, sizeof *This); - if (!This) - return NULL; + if (!(ret = CopyFileExW(ptr, tmpname, progress_callback_local, file, NULL, 0))) + { + WARN("Local file copy failed: error %u\n", GetLastError()); + transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR); + } - This->IBindStatusCallback_iface.lpVtbl = &DLBindStatusCallback_Vtbl; - IBackgroundCopyFile_AddRef(&file->IBackgroundCopyFile_iface); - This->file = file; - This->ref = 1; - return This; + SetEvent(job->done); + return ret; } BOOL processFile(BackgroundCopyFileImpl *file, BackgroundCopyJobImpl *job) { static const WCHAR prefix[] = {'B','I','T', 0}; - DLBindStatusCallback *callbackObj; - WCHAR tmpDir[MAX_PATH]; - WCHAR tmpName[MAX_PATH]; - HRESULT hr; + WCHAR tmpDir[MAX_PATH], tmpName[MAX_PATH]; + WCHAR host[MAX_PATH], path[MAX_PATH]; + URL_COMPONENTSW uc; + BOOL ret; if (!GetTempPathW(MAX_PATH, tmpDir)) { @@ -383,14 +488,6 @@ BOOL processFile(BackgroundCopyFileImpl *file, BackgroundCopyJobImpl *job) return FALSE; } - callbackObj = DLBindStatusCallbackConstructor(file); - if (!callbackObj) - { - ERR("Out of memory\n"); - transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSIENT_ERROR); - return FALSE; - } - EnterCriticalSection(&job->cs); file->fileProgress.BytesTotal = BG_SIZE_UNKNOWN; file->fileProgress.BytesTransferred = 0; @@ -402,31 +499,35 @@ BOOL processFile(BackgroundCopyFileImpl *file, BackgroundCopyJobImpl *job) debugstr_w(tmpName), debugstr_w(file->info.LocalName)); - transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRING); - - DeleteUrlCacheEntryW(file->info.RemoteName); - hr = URLDownloadToFileW(NULL, file->info.RemoteName, tmpName, 0, - &callbackObj->IBindStatusCallback_iface); - IBindStatusCallback_Release(&callbackObj->IBindStatusCallback_iface); - if (hr == INET_E_DOWNLOAD_FAILURE) + uc.dwStructSize = sizeof(uc); + uc.nScheme = 0; + uc.lpszScheme = NULL; + uc.dwSchemeLength = 0; + uc.lpszUserName = NULL; + uc.dwUserNameLength = 0; + uc.lpszPassword = NULL; + uc.dwPasswordLength = 0; + uc.lpszHostName = host; + uc.dwHostNameLength = sizeof(host)/sizeof(host[0]); + uc.nPort = 0; + uc.lpszUrlPath = path; + uc.dwUrlPathLength = sizeof(path)/sizeof(path[0]); + uc.lpszExtraInfo = NULL; + uc.dwExtraInfoLength = 0; + ret = WinHttpCrackUrl(file->info.RemoteName, 0, 0, &uc); + if (!ret) { - TRACE("URLDownload failed, trying local file copy\n"); - if (!CopyFileExW(file->info.RemoteName, tmpName, copyProgressCallback, - file, NULL, 0)) - { - ERR("Local file copy failed: error %d\n", GetLastError()); - transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR); - return FALSE; - } + TRACE("WinHttpCrackUrl failed, trying local file copy\n"); + if (!transfer_file_local(file, tmpName)) return FALSE; } - else if (FAILED(hr)) + else if (!transfer_file_http(file, &uc, tmpName)) { - ERR("URLDownload failed: eh 0x%08x\n", hr); - transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR); + WARN("HTTP transfer failed\n"); return FALSE; } - if (transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_QUEUED)) + if (transitionJobState(job, BG_JOB_STATE_CONNECTING, BG_JOB_STATE_QUEUED) || + transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_QUEUED)) { lstrcpyW(file->tempFileName, tmpName); diff --git a/reactos/dll/win32/qmgr/job.c b/reactos/dll/win32/qmgr/job.c index 911def76657..a9351c76751 100644 --- a/reactos/dll/win32/qmgr/job.c +++ b/reactos/dll/win32/qmgr/job.c @@ -20,48 +20,231 @@ #include "qmgr.h" +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_IBackgroundCopyJob2(IBackgroundCopyJob2 *iface) +static inline BackgroundCopyJobImpl *impl_from_IBackgroundCopyJob3(IBackgroundCopyJob3 *iface) { - return CONTAINING_RECORD(iface, BackgroundCopyJobImpl, IBackgroundCopyJob2_iface); + return CONTAINING_RECORD(iface, BackgroundCopyJobImpl, IBackgroundCopyJob3_iface); } static HRESULT WINAPI BackgroundCopyJob_QueryInterface( - IBackgroundCopyJob2 *iface, REFIID riid, void **obj) + IBackgroundCopyJob3 *iface, REFIID riid, void **obj) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + 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)) + if (IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IBackgroundCopyJob) || + IsEqualGUID(riid, &IID_IBackgroundCopyJob2) || + IsEqualGUID(riid, &IID_IBackgroundCopyJob3)) { - *obj = iface; - IBackgroundCopyJob2_AddRef(iface); - return S_OK; + *obj = &This->IBackgroundCopyJob3_iface; + } + else if (IsEqualGUID(riid, &IID_IBackgroundCopyJobHttpOptions)) + { + *obj = &This->IBackgroundCopyJobHttpOptions_iface; + } + else + { + *obj = NULL; + return E_NOINTERFACE; } - *obj = NULL; - return E_NOINTERFACE; + IBackgroundCopyJob3_AddRef(iface); + return S_OK; } -static ULONG WINAPI BackgroundCopyJob_AddRef(IBackgroundCopyJob2 *iface) +static ULONG WINAPI BackgroundCopyJob_AddRef(IBackgroundCopyJob3 *iface) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(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(IBackgroundCopyJob2 *iface) +static ULONG WINAPI BackgroundCopyJob_Release(IBackgroundCopyJob3 *iface) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); - ULONG ref = InterlockedDecrement(&This->ref); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); + ULONG i, j, ref = InterlockedDecrement(&This->ref); TRACE("(%p)->(%d)\n", This, ref); @@ -73,6 +256,19 @@ static ULONG WINAPI BackgroundCopyJob_Release(IBackgroundCopyJob2 *iface) 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); } @@ -82,11 +278,11 @@ static ULONG WINAPI BackgroundCopyJob_Release(IBackgroundCopyJob2 *iface) /*** IBackgroundCopyJob methods ***/ static HRESULT WINAPI BackgroundCopyJob_AddFileSet( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, ULONG cFileCount, BG_FILE_INFO *pFileSet) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); HRESULT hr = S_OK; ULONG i; @@ -116,41 +312,41 @@ static HRESULT WINAPI BackgroundCopyJob_AddFileSet( } static HRESULT WINAPI BackgroundCopyJob_AddFile( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, LPCWSTR RemoteUrl, LPCWSTR LocalName) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + 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 IBackgroundCopyJob2_AddFileSet(iface, 1, &file); + return IBackgroundCopyJob3_AddFileSet(iface, 1, &file); } static HRESULT WINAPI BackgroundCopyJob_EnumFiles( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, IEnumBackgroundCopyFiles **enum_files) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); TRACE("(%p)->(%p)\n", This, enum_files); return EnumBackgroundCopyFilesConstructor(This, enum_files); } static HRESULT WINAPI BackgroundCopyJob_Suspend( - IBackgroundCopyJob2 *iface) + IBackgroundCopyJob3 *iface) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p): stub\n", This); return E_NOTIMPL; } static HRESULT WINAPI BackgroundCopyJob_Resume( - IBackgroundCopyJob2 *iface) + IBackgroundCopyJob3 *iface) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); HRESULT rv = S_OK; TRACE("(%p)\n", This); @@ -176,17 +372,57 @@ static HRESULT WINAPI BackgroundCopyJob_Resume( } static HRESULT WINAPI BackgroundCopyJob_Cancel( - IBackgroundCopyJob2 *iface) + IBackgroundCopyJob3 *iface) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); - FIXME("(%p): stub\n", This); - return E_NOTIMPL; + 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( - IBackgroundCopyJob2 *iface) + IBackgroundCopyJob3 *iface) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); HRESULT rv = S_OK; TRACE("(%p)\n", This); @@ -227,20 +463,20 @@ static HRESULT WINAPI BackgroundCopyJob_Complete( } static HRESULT WINAPI BackgroundCopyJob_GetId( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, GUID *pVal) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); TRACE("(%p)->(%p)\n", This, pVal); *pVal = This->jobId; return S_OK; } static HRESULT WINAPI BackgroundCopyJob_GetType( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, BG_JOB_TYPE *pVal) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); TRACE("(%p)->(%p)\n", This, pVal); @@ -252,10 +488,10 @@ static HRESULT WINAPI BackgroundCopyJob_GetType( } static HRESULT WINAPI BackgroundCopyJob_GetProgress( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, BG_JOB_PROGRESS *pVal) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); TRACE("(%p)->(%p)\n", This, pVal); @@ -263,29 +499,26 @@ static HRESULT WINAPI BackgroundCopyJob_GetProgress( return E_INVALIDARG; EnterCriticalSection(&This->cs); - pVal->BytesTotal = This->jobProgress.BytesTotal; - pVal->BytesTransferred = This->jobProgress.BytesTransferred; - pVal->FilesTotal = This->jobProgress.FilesTotal; - pVal->FilesTransferred = This->jobProgress.FilesTransferred; + *pVal = This->jobProgress; LeaveCriticalSection(&This->cs); return S_OK; } static HRESULT WINAPI BackgroundCopyJob_GetTimes( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, BG_JOB_TIMES *pVal) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p)->(%p): stub\n", This, pVal); return E_NOTIMPL; } static HRESULT WINAPI BackgroundCopyJob_GetState( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, BG_JOB_STATE *pVal) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); TRACE("(%p)->(%p)\n", This, pVal); @@ -298,37 +531,41 @@ static HRESULT WINAPI BackgroundCopyJob_GetState( } static HRESULT WINAPI BackgroundCopyJob_GetError( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, IBackgroundCopyError **ppError) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); - FIXME("(%p)->(%p): stub\n", This, ppError); - return E_NOTIMPL; + 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( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, LPWSTR *pVal) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p)->(%p): stub\n", This, pVal); return E_NOTIMPL; } static HRESULT WINAPI BackgroundCopyJob_SetDisplayName( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, LPCWSTR Val) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p)->(%s): stub\n", This, debugstr_w(Val)); return E_NOTIMPL; } static HRESULT WINAPI BackgroundCopyJob_GetDisplayName( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, LPWSTR *pVal) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); TRACE("(%p)->(%p)\n", This, pVal); @@ -336,10 +573,10 @@ static HRESULT WINAPI BackgroundCopyJob_GetDisplayName( } static HRESULT WINAPI BackgroundCopyJob_SetDescription( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, LPCWSTR Val) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); static const int max_description_len = 1024; HRESULT hr = S_OK; int len; @@ -372,10 +609,10 @@ static HRESULT WINAPI BackgroundCopyJob_SetDescription( } static HRESULT WINAPI BackgroundCopyJob_GetDescription( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, LPWSTR *pVal) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); TRACE("(%p)->(%p)\n", This, pVal); @@ -383,28 +620,28 @@ static HRESULT WINAPI BackgroundCopyJob_GetDescription( } static HRESULT WINAPI BackgroundCopyJob_SetPriority( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, BG_JOB_PRIORITY Val) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p)->(%d): stub\n", This, Val); return S_OK; } static HRESULT WINAPI BackgroundCopyJob_GetPriority( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, BG_JOB_PRIORITY *pVal) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p)->(%p): stub\n", This, pVal); return E_NOTIMPL; } static HRESULT WINAPI BackgroundCopyJob_SetNotifyFlags( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, ULONG Val) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); static const ULONG valid_flags = BG_NOTIFY_JOB_TRANSFERRED | BG_NOTIFY_JOB_ERROR | BG_NOTIFY_DISABLE | @@ -420,10 +657,10 @@ static HRESULT WINAPI BackgroundCopyJob_SetNotifyFlags( } static HRESULT WINAPI BackgroundCopyJob_GetNotifyFlags( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, ULONG *pVal) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); TRACE("(%p)->(%p)\n", This, pVal); @@ -435,10 +672,10 @@ static HRESULT WINAPI BackgroundCopyJob_GetNotifyFlags( } static HRESULT WINAPI BackgroundCopyJob_SetNotifyInterface( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, IUnknown *Val) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); HRESULT hr = S_OK; TRACE("(%p)->(%p)\n", This, Val); @@ -465,10 +702,10 @@ static HRESULT WINAPI BackgroundCopyJob_SetNotifyInterface( } static HRESULT WINAPI BackgroundCopyJob_GetNotifyInterface( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, IUnknown **pVal) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); TRACE("(%p)->(%p)\n", This, pVal); @@ -482,7 +719,7 @@ static HRESULT WINAPI BackgroundCopyJob_GetNotifyInterface( } static HRESULT WINAPI BackgroundCopyJob_SetMinimumRetryDelay( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, ULONG Seconds) { FIXME("%u\n", Seconds); @@ -490,150 +727,244 @@ static HRESULT WINAPI BackgroundCopyJob_SetMinimumRetryDelay( } static HRESULT WINAPI BackgroundCopyJob_GetMinimumRetryDelay( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, ULONG *Seconds) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p)->(%p): stub\n", This, Seconds); *Seconds = 30; return S_OK; } static HRESULT WINAPI BackgroundCopyJob_SetNoProgressTimeout( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, ULONG Seconds) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p)->(%d): stub\n", This, Seconds); return S_OK; } static HRESULT WINAPI BackgroundCopyJob_GetNoProgressTimeout( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, ULONG *Seconds) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p)->(%p): stub\n", This, Seconds); *Seconds = 900; return S_OK; } static HRESULT WINAPI BackgroundCopyJob_GetErrorCount( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, ULONG *Errors) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p)->(%p): stub\n", This, Errors); return E_NOTIMPL; } static HRESULT WINAPI BackgroundCopyJob_SetProxySettings( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, BG_JOB_PROXY_USAGE ProxyUsage, const WCHAR *ProxyList, const WCHAR *ProxyBypassList) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + 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( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, BG_JOB_PROXY_USAGE *pProxyUsage, LPWSTR *pProxyList, LPWSTR *pProxyBypassList) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + 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( - IBackgroundCopyJob2 *iface) + IBackgroundCopyJob3 *iface) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p): stub\n", This); return E_NOTIMPL; } static HRESULT WINAPI BackgroundCopyJob_SetNotifyCmdLine( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, LPCWSTR prog, LPCWSTR params) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + 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( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, LPWSTR *prog, LPWSTR *params) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p)->(%p %p): stub\n", This, prog, params); return E_NOTIMPL; } static HRESULT WINAPI BackgroundCopyJob_GetReplyProgress( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, BG_JOB_REPLY_PROGRESS *progress) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p)->(%p): stub\n", This, progress); return E_NOTIMPL; } static HRESULT WINAPI BackgroundCopyJob_GetReplyData( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, byte **pBuffer, UINT64 *pLength) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p)->(%p %p): stub\n", This, pBuffer, pLength); return E_NOTIMPL; } static HRESULT WINAPI BackgroundCopyJob_SetReplyFileName( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, LPCWSTR filename) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface); FIXME("(%p)->(%s): stub\n", This, debugstr_w(filename)); return E_NOTIMPL; } static HRESULT WINAPI BackgroundCopyJob_GetReplyFileName( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, LPWSTR *pFilename) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); + 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( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, BG_AUTH_CREDENTIALS *cred) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); - FIXME("(%p)->(%p): stub\n", This, 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( - IBackgroundCopyJob2 *iface, + IBackgroundCopyJob3 *iface, BG_AUTH_TARGET target, BG_AUTH_SCHEME scheme) { - BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob2(iface); - FIXME("(%p)->(%d %d): stub\n", This, target, 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 const IBackgroundCopyJob2Vtbl BackgroundCopyJobVtbl = +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, @@ -677,14 +1008,182 @@ static const IBackgroundCopyJob2Vtbl BackgroundCopyJobVtbl = BackgroundCopyJob_SetReplyFileName, BackgroundCopyJob_GetReplyFileName, BackgroundCopyJob_SetCredentials, - BackgroundCopyJob_RemoveCredentials + 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; - int n; TRACE("(%s,%d,%p)\n", debugstr_w(displayName), type, job); @@ -692,15 +1191,15 @@ HRESULT BackgroundCopyJobConstructor(LPCWSTR displayName, BG_JOB_TYPE type, GUID if (!This) return E_OUTOFMEMORY; - This->IBackgroundCopyJob2_iface.lpVtbl = &BackgroundCopyJobVtbl; + 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; - n = (strlenW(displayName) + 1) * sizeof *displayName; - This->displayName = HeapAlloc(GetProcessHeap(), 0, n); + This->displayName = strdupW(displayName); if (!This->displayName) { This->cs.DebugInfo->Spare[0] = 0; @@ -708,7 +1207,6 @@ HRESULT BackgroundCopyJobConstructor(LPCWSTR displayName, BG_JOB_TYPE type, GUID HeapFree(GetProcessHeap(), 0, This); return E_OUTOFMEMORY; } - memcpy(This->displayName, displayName, n); hr = CoCreateGuid(&This->jobId); if (FAILED(hr)) @@ -733,6 +1231,16 @@ HRESULT BackgroundCopyJobConstructor(LPCWSTR displayName, BG_JOB_TYPE type, GUID This->callback = NULL; This->callback2 = FALSE; + This->error.context = 0; + This->error.code = 0; + 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); diff --git a/reactos/dll/win32/qmgr/qmgr.c b/reactos/dll/win32/qmgr/qmgr.c index 69c5c3ae96a..f0c8462c549 100644 --- a/reactos/dll/win32/qmgr/qmgr.c +++ b/reactos/dll/win32/qmgr/qmgr.c @@ -63,7 +63,7 @@ static HRESULT WINAPI BackgroundCopyManager_CreateJob(IBackgroundCopyManager *if return hres; /* Add a reference to the job to job list */ - *ppJob = (IBackgroundCopyJob*)&job->IBackgroundCopyJob2_iface; + *ppJob = (IBackgroundCopyJob *)&job->IBackgroundCopyJob3_iface; IBackgroundCopyJob_AddRef(*ppJob); EnterCriticalSection(&globalMgr.cs); list_add_head(&globalMgr.jobs, &job->entryFromQmgr); @@ -90,8 +90,8 @@ static HRESULT WINAPI BackgroundCopyManager_GetJob(IBackgroundCopyManager *iface { if (IsEqualGUID(&cur->jobId, jobID)) { - *job = (IBackgroundCopyJob*)&cur->IBackgroundCopyJob2_iface; - IBackgroundCopyJob2_AddRef(&cur->IBackgroundCopyJob2_iface); + *job = (IBackgroundCopyJob *)&cur->IBackgroundCopyJob3_iface; + IBackgroundCopyJob3_AddRef(&cur->IBackgroundCopyJob3_iface); hr = S_OK; break; } @@ -161,7 +161,7 @@ DWORD WINAPI fileTransfer(void *param) LIST_FOR_EACH_ENTRY_SAFE(job, jobCur, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr) { list_remove(&job->entryFromQmgr); - IBackgroundCopyJob2_Release(&job->IBackgroundCopyJob2_iface); + IBackgroundCopyJob3_Release(&job->IBackgroundCopyJob3_iface); } return 0; } @@ -176,7 +176,7 @@ DWORD WINAPI fileTransfer(void *param) if (job->state == BG_JOB_STATE_ACKNOWLEDGED || job->state == BG_JOB_STATE_CANCELLED) { list_remove(&job->entryFromQmgr); - IBackgroundCopyJob2_Release(&job->IBackgroundCopyJob2_iface); + IBackgroundCopyJob3_Release(&job->IBackgroundCopyJob3_iface); } else if (job->state == BG_JOB_STATE_QUEUED) { diff --git a/reactos/dll/win32/qmgr/qmgr.h b/reactos/dll/win32/qmgr/qmgr.h index ae8668502e8..4615e13cddc 100644 --- a/reactos/dll/win32/qmgr/qmgr.h +++ b/reactos/dll/win32/qmgr/qmgr.h @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include #include @@ -45,7 +47,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(qmgr); /* Background copy job vtbl and related data */ typedef struct { - IBackgroundCopyJob2 IBackgroundCopyJob2_iface; + IBackgroundCopyJob3 IBackgroundCopyJob3_iface; + IBackgroundCopyJobHttpOptions IBackgroundCopyJobHttpOptions_iface; LONG ref; LPWSTR displayName; LPWSTR description; @@ -60,18 +63,34 @@ typedef struct /* Protects file list, and progress */ CRITICAL_SECTION cs; struct list entryFromQmgr; + struct + { + WCHAR *headers; + ULONG flags; + BG_AUTH_CREDENTIALS creds[BG_AUTH_TARGET_PROXY][BG_AUTH_SCHEME_PASSPORT]; + } http_options; + struct + { + BG_ERROR_CONTEXT context; + HRESULT code; + IBackgroundCopyFile2 *file; + } error; + HANDLE wait; + HANDLE cancel; + HANDLE done; } BackgroundCopyJobImpl; /* Background copy file vtbl and related data */ typedef struct { - IBackgroundCopyFile IBackgroundCopyFile_iface; + IBackgroundCopyFile2 IBackgroundCopyFile2_iface; LONG ref; BG_FILE_INFO info; BG_FILE_PROGRESS fileProgress; WCHAR tempFileName[MAX_PATH]; struct list entryFromJob; BackgroundCopyJobImpl *owner; + DWORD read_size; } BackgroundCopyFileImpl; /* Background copy manager vtbl and related data */ @@ -105,14 +124,21 @@ HRESULT EnumBackgroundCopyFilesConstructor(BackgroundCopyJobImpl*, IEnumBackgrou DWORD WINAPI fileTransfer(void *param) DECLSPEC_HIDDEN; void processJob(BackgroundCopyJobImpl *job) DECLSPEC_HIDDEN; BOOL processFile(BackgroundCopyFileImpl *file, BackgroundCopyJobImpl *job) DECLSPEC_HIDDEN; +BOOL transitionJobState(BackgroundCopyJobImpl *job, BG_JOB_STATE from, BG_JOB_STATE to) DECLSPEC_HIDDEN; /* Little helper functions */ -static inline char * -qmgr_strdup(const char *s) +static inline WCHAR *strdupW(const WCHAR *src) +{ + WCHAR *dst = HeapAlloc(GetProcessHeap(), 0, (strlenW(src) + 1) * sizeof(WCHAR)); + if (dst) strcpyW(dst, src); + return dst; +} + +static inline WCHAR *co_strdupW(const WCHAR *src) { - size_t n = strlen(s) + 1; - char *d = HeapAlloc(GetProcessHeap(), 0, n); - return d ? memcpy(d, s, n) : NULL; + WCHAR *dst = CoTaskMemAlloc((strlenW(src) + 1) * sizeof(WCHAR)); + if (dst) strcpyW(dst, src); + return dst; } static inline HRESULT return_strval(const WCHAR *str, WCHAR **ret) @@ -128,19 +154,4 @@ static inline HRESULT return_strval(const WCHAR *str, WCHAR **ret) return S_OK; } -static inline BOOL -transitionJobState(BackgroundCopyJobImpl *job, BG_JOB_STATE fromState, - BG_JOB_STATE toState) -{ - BOOL rv = FALSE; - EnterCriticalSection(&globalMgr.cs); - if (job->state == fromState) - { - job->state = toState; - rv = TRUE; - } - LeaveCriticalSection(&globalMgr.cs); - return rv; -} - #endif /* __QMGR_H__ */ diff --git a/reactos/dll/win32/qmgr/qmgr_local.idl b/reactos/dll/win32/qmgr/qmgr_local.idl index edbe71eacde..110d479ab92 100644 --- a/reactos/dll/win32/qmgr/qmgr_local.idl +++ b/reactos/dll/win32/qmgr/qmgr_local.idl @@ -22,4 +22,6 @@ #define DO_NO_IMPORTS #include "bits1_5.idl" +#include "bits2_0.idl" +#include "bits2_5.idl" #include "bits3_0.idl" diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index d626ca08382..e7d6ce44e9c 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -159,7 +159,7 @@ reactos/dll/win32/powrprof # Forked at Wine-1.0rc5 reactos/dll/win32/printui # Synced to WineStaging-1.7.37 reactos/dll/win32/propsys # Synced to WineStaging-1.7.37 reactos/dll/win32/pstorec # Synced to WineStaging-1.7.37 -reactos/dll/win32/qmgr # Synced to WineStaging-1.7.37 +reactos/dll/win32/qmgr # Synced to WineStaging-1.7.47 reactos/dll/win32/qmgrprxy # Synced to WineStaging-1.7.37 reactos/dll/win32/query # Synced to WineStaging-1.7.37 reactos/dll/win32/rasapi32 # Synced to WineStaging-1.7.37 -- 2.17.1