#include "qmgr.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(
- 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;
/* 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,
BackgroundCopyFileImpl **file)
{
BackgroundCopyFileImpl *This;
- int n;
TRACE("(%s, %s, %p)\n", debugstr_w(remoteName), debugstr_w(localName), file);
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;
+ DWORD written;
+
+ 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, &written, 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))
{
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;
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);