[QMGR] Sync with Wine Staging 1.7.47. CORE-9924

svn path=/trunk/; revision=68490
This commit is contained in:
Amine Khaldi 2015-07-20 22:48:28 +00:00
parent ba989e1c40
commit c22de4d293
9 changed files with 1022 additions and 401 deletions

View file

@ -25,7 +25,7 @@ set_source_files_properties(rsrc.rc PROPERTIES OBJECT_DEPENDS ${CMAKE_CURRENT_SO
add_idl_headers(qmgr_idlheader qmgr_local.idl) add_idl_headers(qmgr_idlheader qmgr_local.idl)
set_module_type(qmgr win32dll) set_module_type(qmgr win32dll)
target_link_libraries(qmgr uuid wine) 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_pch(qmgr qmgr.h SOURCE)
add_cd_file(TARGET qmgr DESTINATION reactos/system32 FOR all) add_cd_file(TARGET qmgr DESTINATION reactos/system32 FOR all)
add_dependencies(qmgr qmgr_idlheader) add_dependencies(qmgr qmgr_idlheader)

View file

@ -24,7 +24,7 @@ typedef struct
{ {
IEnumBackgroundCopyFiles IEnumBackgroundCopyFiles_iface; IEnumBackgroundCopyFiles IEnumBackgroundCopyFiles_iface;
LONG ref; LONG ref;
IBackgroundCopyFile **files; IBackgroundCopyFile2 **files;
ULONG numFiles; ULONG numFiles;
ULONG indexFiles; ULONG indexFiles;
} EnumBackgroundCopyFilesImpl; } EnumBackgroundCopyFilesImpl;
@ -72,7 +72,7 @@ static ULONG WINAPI EnumBackgroundCopyFiles_Release(IEnumBackgroundCopyFiles *if
if (ref == 0) if (ref == 0)
{ {
for(i = 0; i < This->numFiles; i++) 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->files);
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
} }
@ -87,7 +87,7 @@ static HRESULT WINAPI EnumBackgroundCopyFiles_Next(IEnumBackgroundCopyFiles *ifa
EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface); EnumBackgroundCopyFilesImpl *This = impl_from_IEnumBackgroundCopyFiles(iface);
ULONG fetched; ULONG fetched;
ULONG i; ULONG i;
IBackgroundCopyFile *file; IBackgroundCopyFile2 *file;
TRACE("(%p)->(%d %p %p)\n", This, celt, rgelt, pceltFetched); 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++) for (i = 0; i < fetched; i++)
{ {
file = This->files[This->indexFiles++]; file = This->files[This->indexFiles++];
IBackgroundCopyFile_AddRef(file); IBackgroundCopyFile2_AddRef(file);
rgelt[i] = file; rgelt[i] = (IBackgroundCopyFile *)file;
} }
return fetched == celt ? S_OK : S_FALSE; return fetched == celt ? S_OK : S_FALSE;
@ -212,8 +212,8 @@ HRESULT EnumBackgroundCopyFilesConstructor(BackgroundCopyJobImpl *job, IEnumBack
i = 0; i = 0;
LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob) LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob)
{ {
IBackgroundCopyFile_AddRef(&file->IBackgroundCopyFile_iface); IBackgroundCopyFile2_AddRef(&file->IBackgroundCopyFile2_iface);
This->files[i] = &file->IBackgroundCopyFile_iface; This->files[i] = &file->IBackgroundCopyFile2_iface;
++i; ++i;
} }
LeaveCriticalSection(&job->cs); LeaveCriticalSection(&job->cs);

View file

@ -24,7 +24,7 @@ typedef struct
{ {
IEnumBackgroundCopyJobs IEnumBackgroundCopyJobs_iface; IEnumBackgroundCopyJobs IEnumBackgroundCopyJobs_iface;
LONG ref; LONG ref;
IBackgroundCopyJob **jobs; IBackgroundCopyJob3 **jobs;
ULONG numJobs; ULONG numJobs;
ULONG indexJobs; ULONG indexJobs;
} EnumBackgroundCopyJobsImpl; } EnumBackgroundCopyJobsImpl;
@ -72,7 +72,7 @@ static ULONG WINAPI EnumBackgroundCopyJobs_Release(IEnumBackgroundCopyJobs *ifac
if (ref == 0) { if (ref == 0) {
for(i = 0; i < This->numJobs; i++) 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->jobs);
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
} }
@ -86,7 +86,7 @@ static HRESULT WINAPI EnumBackgroundCopyJobs_Next(IEnumBackgroundCopyJobs *iface
EnumBackgroundCopyJobsImpl *This = impl_from_IEnumBackgroundCopyJobs(iface); EnumBackgroundCopyJobsImpl *This = impl_from_IEnumBackgroundCopyJobs(iface);
ULONG fetched; ULONG fetched;
ULONG i; ULONG i;
IBackgroundCopyJob *job; IBackgroundCopyJob3 *job;
TRACE("(%p)->(%d %p %p)\n", This, celt, rgelt, pceltFetched); 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) for (i = 0; i < fetched; ++i)
{ {
job = This->jobs[This->indexJobs++]; job = This->jobs[This->indexJobs++];
IBackgroundCopyJob_AddRef(job); IBackgroundCopyJob3_AddRef(job);
rgelt[i] = job; rgelt[i] = (IBackgroundCopyJob *)job;
} }
return fetched == celt ? S_OK : S_FALSE; return fetched == celt ? S_OK : S_FALSE;
@ -210,9 +210,8 @@ HRESULT enum_copy_job_create(BackgroundCopyManagerImpl *qmgr, IEnumBackgroundCop
i = 0; i = 0;
LIST_FOR_EACH_ENTRY(job, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr) LIST_FOR_EACH_ENTRY(job, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr)
{ {
IBackgroundCopyJob *job_iface = (IBackgroundCopyJob*)&job->IBackgroundCopyJob2_iface; IBackgroundCopyJob3_AddRef(&job->IBackgroundCopyJob3_iface);
IBackgroundCopyJob_AddRef(job_iface); This->jobs[i++] = &job->IBackgroundCopyJob3_iface;
This->jobs[i++] = job_iface;
} }
LeaveCriticalSection(&qmgr->cs); LeaveCriticalSection(&qmgr->cs);

View file

@ -21,56 +21,62 @@
#include "qmgr.h" #include "qmgr.h"
#include <urlmon.h> #include <urlmon.h>
#include <wininet.h> #include <winhttp.h>
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( static HRESULT WINAPI BackgroundCopyFile_QueryInterface(
IBackgroundCopyFile* iface, IBackgroundCopyFile2 *iface,
REFIID riid, REFIID riid,
void **obj) 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) if (IsEqualGUID(riid, &IID_IUnknown) ||
|| IsEqualGUID(riid, &IID_IBackgroundCopyFile)) IsEqualGUID(riid, &IID_IBackgroundCopyFile) ||
IsEqualGUID(riid, &IID_IBackgroundCopyFile2))
{ {
*obj = iface; *obj = iface;
IBackgroundCopyFile_AddRef(iface); }
return S_OK; else
{
*obj = NULL;
return E_NOINTERFACE;
} }
*obj = NULL; IBackgroundCopyFile2_AddRef(iface);
return E_NOINTERFACE; return S_OK;
} }
static ULONG WINAPI BackgroundCopyFile_AddRef(IBackgroundCopyFile* iface) static ULONG WINAPI BackgroundCopyFile_AddRef(
IBackgroundCopyFile2 *iface)
{ {
BackgroundCopyFileImpl *This = impl_from_IBackgroundCopyFile(iface); BackgroundCopyFileImpl *file = impl_from_IBackgroundCopyFile2(iface);
ULONG ref = InterlockedIncrement(&This->ref); ULONG ref = InterlockedIncrement(&file->ref);
TRACE("(%p)->(%d)\n", This, ref); TRACE("(%p)->(%d)\n", file, ref);
return ref; return ref;
} }
static ULONG WINAPI BackgroundCopyFile_Release( static ULONG WINAPI BackgroundCopyFile_Release(
IBackgroundCopyFile* iface) IBackgroundCopyFile2 *iface)
{ {
BackgroundCopyFileImpl *This = impl_from_IBackgroundCopyFile(iface); BackgroundCopyFileImpl *file = impl_from_IBackgroundCopyFile2(iface);
ULONG ref = InterlockedDecrement(&This->ref); ULONG ref = InterlockedDecrement(&file->ref);
TRACE("(%p)->(%d)\n", This, ref); TRACE("(%p)->(%d)\n", file, ref);
if (ref == 0) if (ref == 0)
{ {
IBackgroundCopyJob2_Release(&This->owner->IBackgroundCopyJob2_iface); IBackgroundCopyJob3_Release(&file->owner->IBackgroundCopyJob3_iface);
HeapFree(GetProcessHeap(), 0, This->info.LocalName); HeapFree(GetProcessHeap(), 0, file->info.LocalName);
HeapFree(GetProcessHeap(), 0, This->info.RemoteName); HeapFree(GetProcessHeap(), 0, file->info.RemoteName);
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, file);
} }
return ref; return ref;
@ -78,52 +84,71 @@ static ULONG WINAPI BackgroundCopyFile_Release(
/* Get the remote name of a background copy file */ /* Get the remote name of a background copy file */
static HRESULT WINAPI BackgroundCopyFile_GetRemoteName( static HRESULT WINAPI BackgroundCopyFile_GetRemoteName(
IBackgroundCopyFile* iface, IBackgroundCopyFile2 *iface,
LPWSTR *pVal) 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( static HRESULT WINAPI BackgroundCopyFile_GetLocalName(
IBackgroundCopyFile* iface, IBackgroundCopyFile2 *iface,
LPWSTR *pVal) 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( static HRESULT WINAPI BackgroundCopyFile_GetProgress(
IBackgroundCopyFile* iface, IBackgroundCopyFile2 *iface,
BG_FILE_PROGRESS *pVal) 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); EnterCriticalSection(&file->owner->cs);
pVal->BytesTotal = This->fileProgress.BytesTotal; *pVal = file->fileProgress;
pVal->BytesTransferred = This->fileProgress.BytesTransferred; LeaveCriticalSection(&file->owner->cs);
pVal->Completed = This->fileProgress.Completed;
LeaveCriticalSection(&This->owner->cs);
return S_OK; 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_QueryInterface,
BackgroundCopyFile_AddRef, BackgroundCopyFile_AddRef,
BackgroundCopyFile_Release, BackgroundCopyFile_Release,
BackgroundCopyFile_GetRemoteName, BackgroundCopyFile_GetRemoteName,
BackgroundCopyFile_GetLocalName, BackgroundCopyFile_GetLocalName,
BackgroundCopyFile_GetProgress BackgroundCopyFile_GetProgress,
BackgroundCopyFile_GetFileRanges,
BackgroundCopyFile_SetRemoteName
}; };
HRESULT BackgroundCopyFileConstructor(BackgroundCopyJobImpl *owner, HRESULT BackgroundCopyFileConstructor(BackgroundCopyJobImpl *owner,
@ -131,7 +156,6 @@ HRESULT BackgroundCopyFileConstructor(BackgroundCopyJobImpl *owner,
BackgroundCopyFileImpl **file) BackgroundCopyFileImpl **file)
{ {
BackgroundCopyFileImpl *This; BackgroundCopyFileImpl *This;
int n;
TRACE("(%s, %s, %p)\n", debugstr_w(remoteName), debugstr_w(localName), file); TRACE("(%s, %s, %p)\n", debugstr_w(remoteName), debugstr_w(localName), file);
@ -139,47 +163,264 @@ HRESULT BackgroundCopyFileConstructor(BackgroundCopyJobImpl *owner,
if (!This) if (!This)
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
n = (lstrlenW(remoteName) + 1) * sizeof(WCHAR); This->info.RemoteName = strdupW(remoteName);
This->info.RemoteName = HeapAlloc(GetProcessHeap(), 0, n);
if (!This->info.RemoteName) if (!This->info.RemoteName)
{ {
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
memcpy(This->info.RemoteName, remoteName, n);
n = (lstrlenW(localName) + 1) * sizeof(WCHAR); This->info.LocalName = strdupW(localName);
This->info.LocalName = HeapAlloc(GetProcessHeap(), 0, n);
if (!This->info.LocalName) if (!This->info.LocalName)
{ {
HeapFree(GetProcessHeap(), 0, This->info.RemoteName); HeapFree(GetProcessHeap(), 0, This->info.RemoteName);
HeapFree(GetProcessHeap(), 0, This); HeapFree(GetProcessHeap(), 0, This);
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
memcpy(This->info.LocalName, localName, n);
This->IBackgroundCopyFile_iface.lpVtbl = &BackgroundCopyFileVtbl; This->IBackgroundCopyFile2_iface.lpVtbl = &BackgroundCopyFile2Vtbl;
This->ref = 1; This->ref = 1;
This->fileProgress.BytesTotal = BG_SIZE_UNKNOWN; This->fileProgress.BytesTotal = BG_SIZE_UNKNOWN;
This->fileProgress.BytesTransferred = 0; This->fileProgress.BytesTransferred = 0;
This->fileProgress.Completed = FALSE; This->fileProgress.Completed = FALSE;
This->owner = owner; This->owner = owner;
IBackgroundCopyJob2_AddRef(&owner->IBackgroundCopyJob2_iface); This->read_size = 0;
This->tempFileName[0] = 0;
IBackgroundCopyJob3_AddRef(&owner->IBackgroundCopyJob3_iface);
*file = This; *file = This;
return S_OK; return S_OK;
} }
static DWORD CALLBACK copyProgressCallback(LARGE_INTEGER totalSize, static HRESULT error_from_http_response(DWORD code)
LARGE_INTEGER totalTransferred, {
LARGE_INTEGER streamSize, switch (code)
LARGE_INTEGER streamTransferred, {
DWORD streamNum, case 200: return S_OK;
DWORD reason, case 400: return BG_E_HTTP_ERROR_400;
HANDLE srcFile, case 401: return BG_E_HTTP_ERROR_401;
HANDLE dstFile, case 404: return BG_E_HTTP_ERROR_404;
LPVOID obj) 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;
}
}
static void CALLBACK progress_callback_http(HINTERNET handle, DWORD_PTR context, DWORD status,
LPVOID buf, DWORD buflen)
{
BackgroundCopyFileImpl *file = (BackgroundCopyFileImpl *)context;
BackgroundCopyJobImpl *job = file->owner;
TRACE("%p, %p, %x, %p, %u\n", handle, file, status, buf, buflen);
switch (status)
{
case WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE:
{
DWORD code, len, size;
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:
{
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;
}
SetEvent(job->wait);
}
static DWORD wait_for_completion(BackgroundCopyJobImpl *job)
{
HANDLE handles[2] = {job->wait, job->cancel};
DWORD error = ERROR_SUCCESS;
switch (WaitForMultipleObjects(2, handles, FALSE, INFINITE))
{
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 error;
}
static UINT target_from_index(UINT index)
{
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 UINT scheme_from_index(UINT index)
{
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 BOOL set_request_credentials(HINTERNET req, BackgroundCopyJobImpl *job)
{
UINT i, j;
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 BOOL transfer_file_http(BackgroundCopyFileImpl *file, URL_COMPONENTSW *uc,
const WCHAR *tmpfile)
{
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 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)
{ {
BackgroundCopyFileImpl *file = obj; BackgroundCopyFileImpl *file = obj;
BackgroundCopyJobImpl *job = file->owner; BackgroundCopyJobImpl *job = file->owner;
@ -199,173 +440,37 @@ static DWORD CALLBACK copyProgressCallback(LARGE_INTEGER totalSize,
: PROGRESS_CANCEL); : PROGRESS_CANCEL);
} }
typedef struct static BOOL transfer_file_local(BackgroundCopyFileImpl *file, const WCHAR *tmpname)
{ {
IBindStatusCallback IBindStatusCallback_iface; static const WCHAR fileW[] = {'f','i','l','e',':','/','/',0};
BackgroundCopyFileImpl *file;
LONG ref;
} DLBindStatusCallback;
static inline DLBindStatusCallback *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
{
return CONTAINING_RECORD(iface, DLBindStatusCallback, IBindStatusCallback_iface);
}
static HRESULT WINAPI DLBindStatusCallback_QueryInterface(
IBindStatusCallback *iface,
REFIID riid,
void **ppvObject)
{
DLBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
if (IsEqualGUID(riid, &IID_IUnknown)
|| IsEqualGUID(riid, &IID_IBindStatusCallback))
{
*ppvObject = &This->IBindStatusCallback_iface;
IBindStatusCallback_AddRef(iface);
return S_OK;
}
*ppvObject = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI DLBindStatusCallback_AddRef(IBindStatusCallback *iface)
{
DLBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI DLBindStatusCallback_Release(IBindStatusCallback *iface)
{
DLBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
ULONG ref = InterlockedDecrement(&This->ref);
if (ref == 0)
{
IBackgroundCopyFile_Release(&This->file->IBackgroundCopyFile_iface);
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}
static HRESULT WINAPI DLBindStatusCallback_GetBindInfo(
IBindStatusCallback *iface,
DWORD *grfBINDF,
BINDINFO *pbindinfo)
{
return E_NOTIMPL;
}
static HRESULT WINAPI DLBindStatusCallback_GetPriority(
IBindStatusCallback *iface,
LONG *pnPriority)
{
return E_NOTIMPL;
}
static HRESULT WINAPI DLBindStatusCallback_OnDataAvailable(
IBindStatusCallback *iface,
DWORD grfBSCF,
DWORD dwSize,
FORMATETC *pformatetc,
STGMEDIUM *pstgmed)
{
return E_NOTIMPL;
}
static HRESULT WINAPI DLBindStatusCallback_OnLowResource(
IBindStatusCallback *iface,
DWORD reserved)
{
return E_NOTIMPL;
}
static HRESULT WINAPI DLBindStatusCallback_OnObjectAvailable(
IBindStatusCallback *iface,
REFIID riid,
IUnknown *punk)
{
return E_NOTIMPL;
}
static HRESULT WINAPI DLBindStatusCallback_OnProgress(
IBindStatusCallback *iface,
ULONG progress,
ULONG progressMax,
ULONG statusCode,
LPCWSTR statusText)
{
DLBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
BackgroundCopyFileImpl *file = This->file;
BackgroundCopyJobImpl *job = file->owner; BackgroundCopyJobImpl *job = file->owner;
ULONG64 diff; const WCHAR *ptr;
BOOL ret;
EnterCriticalSection(&job->cs); transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRING);
diff = (file->fileProgress.BytesTotal == BG_SIZE_UNKNOWN
? progress
: progress - file->fileProgress.BytesTransferred);
file->fileProgress.BytesTotal = progressMax ? progressMax : BG_SIZE_UNKNOWN;
file->fileProgress.BytesTransferred = progress;
job->jobProgress.BytesTransferred += diff;
LeaveCriticalSection(&job->cs);
return S_OK; if (strlenW(file->info.RemoteName) > 7 && !memicmpW(file->info.RemoteName, fileW, 7))
} ptr = file->info.RemoteName + 7;
else
ptr = file->info.RemoteName;
static HRESULT WINAPI DLBindStatusCallback_OnStartBinding( if (!(ret = CopyFileExW(ptr, tmpname, progress_callback_local, file, NULL, 0)))
IBindStatusCallback *iface, {
DWORD dwReserved, WARN("Local file copy failed: error %u\n", GetLastError());
IBinding *pib) transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR);
{ }
return E_NOTIMPL;
}
static HRESULT WINAPI DLBindStatusCallback_OnStopBinding( SetEvent(job->done);
IBindStatusCallback *iface, return ret;
HRESULT hresult,
LPCWSTR szError)
{
return E_NOTIMPL;
}
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
};
static DLBindStatusCallback *DLBindStatusCallbackConstructor(
BackgroundCopyFileImpl *file)
{
DLBindStatusCallback *This = HeapAlloc(GetProcessHeap(), 0, sizeof *This);
if (!This)
return NULL;
This->IBindStatusCallback_iface.lpVtbl = &DLBindStatusCallback_Vtbl;
IBackgroundCopyFile_AddRef(&file->IBackgroundCopyFile_iface);
This->file = file;
This->ref = 1;
return This;
} }
BOOL processFile(BackgroundCopyFileImpl *file, BackgroundCopyJobImpl *job) BOOL processFile(BackgroundCopyFileImpl *file, BackgroundCopyJobImpl *job)
{ {
static const WCHAR prefix[] = {'B','I','T', 0}; static const WCHAR prefix[] = {'B','I','T', 0};
DLBindStatusCallback *callbackObj; WCHAR tmpDir[MAX_PATH], tmpName[MAX_PATH];
WCHAR tmpDir[MAX_PATH]; WCHAR host[MAX_PATH], path[MAX_PATH];
WCHAR tmpName[MAX_PATH]; URL_COMPONENTSW uc;
HRESULT hr; BOOL ret;
if (!GetTempPathW(MAX_PATH, tmpDir)) if (!GetTempPathW(MAX_PATH, tmpDir))
{ {
@ -383,14 +488,6 @@ BOOL processFile(BackgroundCopyFileImpl *file, BackgroundCopyJobImpl *job)
return FALSE; 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); EnterCriticalSection(&job->cs);
file->fileProgress.BytesTotal = BG_SIZE_UNKNOWN; file->fileProgress.BytesTotal = BG_SIZE_UNKNOWN;
file->fileProgress.BytesTransferred = 0; file->fileProgress.BytesTransferred = 0;
@ -402,31 +499,35 @@ BOOL processFile(BackgroundCopyFileImpl *file, BackgroundCopyJobImpl *job)
debugstr_w(tmpName), debugstr_w(tmpName),
debugstr_w(file->info.LocalName)); debugstr_w(file->info.LocalName));
transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRING); uc.dwStructSize = sizeof(uc);
uc.nScheme = 0;
DeleteUrlCacheEntryW(file->info.RemoteName); uc.lpszScheme = NULL;
hr = URLDownloadToFileW(NULL, file->info.RemoteName, tmpName, 0, uc.dwSchemeLength = 0;
&callbackObj->IBindStatusCallback_iface); uc.lpszUserName = NULL;
IBindStatusCallback_Release(&callbackObj->IBindStatusCallback_iface); uc.dwUserNameLength = 0;
if (hr == INET_E_DOWNLOAD_FAILURE) 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"); TRACE("WinHttpCrackUrl failed, trying local file copy\n");
if (!CopyFileExW(file->info.RemoteName, tmpName, copyProgressCallback, if (!transfer_file_local(file, tmpName)) return FALSE;
file, NULL, 0))
{
ERR("Local file copy failed: error %d\n", GetLastError());
transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR);
return FALSE;
}
} }
else if (FAILED(hr)) else if (!transfer_file_http(file, &uc, tmpName))
{ {
ERR("URLDownload failed: eh 0x%08x\n", hr); WARN("HTTP transfer failed\n");
transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR);
return FALSE; 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); lstrcpyW(file->tempFileName, tmpName);

File diff suppressed because it is too large Load diff

View file

@ -63,7 +63,7 @@ static HRESULT WINAPI BackgroundCopyManager_CreateJob(IBackgroundCopyManager *if
return hres; return hres;
/* Add a reference to the job to job list */ /* Add a reference to the job to job list */
*ppJob = (IBackgroundCopyJob*)&job->IBackgroundCopyJob2_iface; *ppJob = (IBackgroundCopyJob *)&job->IBackgroundCopyJob3_iface;
IBackgroundCopyJob_AddRef(*ppJob); IBackgroundCopyJob_AddRef(*ppJob);
EnterCriticalSection(&globalMgr.cs); EnterCriticalSection(&globalMgr.cs);
list_add_head(&globalMgr.jobs, &job->entryFromQmgr); list_add_head(&globalMgr.jobs, &job->entryFromQmgr);
@ -90,8 +90,8 @@ static HRESULT WINAPI BackgroundCopyManager_GetJob(IBackgroundCopyManager *iface
{ {
if (IsEqualGUID(&cur->jobId, jobID)) if (IsEqualGUID(&cur->jobId, jobID))
{ {
*job = (IBackgroundCopyJob*)&cur->IBackgroundCopyJob2_iface; *job = (IBackgroundCopyJob *)&cur->IBackgroundCopyJob3_iface;
IBackgroundCopyJob2_AddRef(&cur->IBackgroundCopyJob2_iface); IBackgroundCopyJob3_AddRef(&cur->IBackgroundCopyJob3_iface);
hr = S_OK; hr = S_OK;
break; break;
} }
@ -161,7 +161,7 @@ DWORD WINAPI fileTransfer(void *param)
LIST_FOR_EACH_ENTRY_SAFE(job, jobCur, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr) LIST_FOR_EACH_ENTRY_SAFE(job, jobCur, &qmgr->jobs, BackgroundCopyJobImpl, entryFromQmgr)
{ {
list_remove(&job->entryFromQmgr); list_remove(&job->entryFromQmgr);
IBackgroundCopyJob2_Release(&job->IBackgroundCopyJob2_iface); IBackgroundCopyJob3_Release(&job->IBackgroundCopyJob3_iface);
} }
return 0; return 0;
} }
@ -176,7 +176,7 @@ DWORD WINAPI fileTransfer(void *param)
if (job->state == BG_JOB_STATE_ACKNOWLEDGED || job->state == BG_JOB_STATE_CANCELLED) if (job->state == BG_JOB_STATE_ACKNOWLEDGED || job->state == BG_JOB_STATE_CANCELLED)
{ {
list_remove(&job->entryFromQmgr); list_remove(&job->entryFromQmgr);
IBackgroundCopyJob2_Release(&job->IBackgroundCopyJob2_iface); IBackgroundCopyJob3_Release(&job->IBackgroundCopyJob3_iface);
} }
else if (job->state == BG_JOB_STATE_QUEUED) else if (job->state == BG_JOB_STATE_QUEUED)
{ {

View file

@ -34,6 +34,8 @@
#include <winsvc.h> #include <winsvc.h>
#include <objbase.h> #include <objbase.h>
#include <bits1_5.h> #include <bits1_5.h>
#include <bits2_0.h>
#include <bits2_5.h>
#include <bits3_0.h> #include <bits3_0.h>
#include <wine/list.h> #include <wine/list.h>
@ -45,7 +47,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
/* Background copy job vtbl and related data */ /* Background copy job vtbl and related data */
typedef struct typedef struct
{ {
IBackgroundCopyJob2 IBackgroundCopyJob2_iface; IBackgroundCopyJob3 IBackgroundCopyJob3_iface;
IBackgroundCopyJobHttpOptions IBackgroundCopyJobHttpOptions_iface;
LONG ref; LONG ref;
LPWSTR displayName; LPWSTR displayName;
LPWSTR description; LPWSTR description;
@ -60,18 +63,34 @@ typedef struct
/* Protects file list, and progress */ /* Protects file list, and progress */
CRITICAL_SECTION cs; CRITICAL_SECTION cs;
struct list entryFromQmgr; 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; } BackgroundCopyJobImpl;
/* Background copy file vtbl and related data */ /* Background copy file vtbl and related data */
typedef struct typedef struct
{ {
IBackgroundCopyFile IBackgroundCopyFile_iface; IBackgroundCopyFile2 IBackgroundCopyFile2_iface;
LONG ref; LONG ref;
BG_FILE_INFO info; BG_FILE_INFO info;
BG_FILE_PROGRESS fileProgress; BG_FILE_PROGRESS fileProgress;
WCHAR tempFileName[MAX_PATH]; WCHAR tempFileName[MAX_PATH];
struct list entryFromJob; struct list entryFromJob;
BackgroundCopyJobImpl *owner; BackgroundCopyJobImpl *owner;
DWORD read_size;
} BackgroundCopyFileImpl; } BackgroundCopyFileImpl;
/* Background copy manager vtbl and related data */ /* Background copy manager vtbl and related data */
@ -105,14 +124,21 @@ HRESULT EnumBackgroundCopyFilesConstructor(BackgroundCopyJobImpl*, IEnumBackgrou
DWORD WINAPI fileTransfer(void *param) DECLSPEC_HIDDEN; DWORD WINAPI fileTransfer(void *param) DECLSPEC_HIDDEN;
void processJob(BackgroundCopyJobImpl *job) DECLSPEC_HIDDEN; void processJob(BackgroundCopyJobImpl *job) DECLSPEC_HIDDEN;
BOOL processFile(BackgroundCopyFileImpl *file, 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 */ /* Little helper functions */
static inline char * static inline WCHAR *strdupW(const WCHAR *src)
qmgr_strdup(const char *s)
{ {
size_t n = strlen(s) + 1; WCHAR *dst = HeapAlloc(GetProcessHeap(), 0, (strlenW(src) + 1) * sizeof(WCHAR));
char *d = HeapAlloc(GetProcessHeap(), 0, n); if (dst) strcpyW(dst, src);
return d ? memcpy(d, s, n) : NULL; return dst;
}
static inline WCHAR *co_strdupW(const WCHAR *src)
{
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) 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; 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__ */ #endif /* __QMGR_H__ */

View file

@ -22,4 +22,6 @@
#define DO_NO_IMPORTS #define DO_NO_IMPORTS
#include "bits1_5.idl" #include "bits1_5.idl"
#include "bits2_0.idl"
#include "bits2_5.idl"
#include "bits3_0.idl" #include "bits3_0.idl"

View file

@ -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/printui # Synced to WineStaging-1.7.37
reactos/dll/win32/propsys # 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/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/qmgrprxy # Synced to WineStaging-1.7.37
reactos/dll/win32/query # 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 reactos/dll/win32/rasapi32 # Synced to WineStaging-1.7.37