mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 08:25:03 +00:00
[QMGR] Sync with Wine Staging 1.7.47. CORE-9924
svn path=/trunk/; revision=68490
This commit is contained in:
parent
ba989e1c40
commit
c22de4d293
9 changed files with 1022 additions and 401 deletions
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -21,56 +21,62 @@
|
|||
#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;
|
||||
|
@ -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,47 +163,264 @@ 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
BackgroundCopyJobImpl *job = file->owner;
|
||||
|
@ -199,173 +440,37 @@ static DWORD CALLBACK copyProgressCallback(LARGE_INTEGER totalSize,
|
|||
: PROGRESS_CANCEL);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
static BOOL transfer_file_local(BackgroundCopyFileImpl *file, const WCHAR *tmpname)
|
||||
{
|
||||
IBindStatusCallback IBindStatusCallback_iface;
|
||||
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;
|
||||
static const WCHAR fileW[] = {'f','i','l','e',':','/','/',0};
|
||||
BackgroundCopyJobImpl *job = file->owner;
|
||||
ULONG64 diff;
|
||||
const WCHAR *ptr;
|
||||
BOOL ret;
|
||||
|
||||
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;
|
||||
job->jobProgress.BytesTransferred += diff;
|
||||
LeaveCriticalSection(&job->cs);
|
||||
transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRING);
|
||||
|
||||
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(
|
||||
IBindStatusCallback *iface,
|
||||
DWORD dwReserved,
|
||||
IBinding *pib)
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI DLBindStatusCallback_OnStopBinding(
|
||||
IBindStatusCallback *iface,
|
||||
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;
|
||||
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);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#include <winsvc.h>
|
||||
#include <objbase.h>
|
||||
#include <bits1_5.h>
|
||||
#include <bits2_0.h>
|
||||
#include <bits2_5.h>
|
||||
#include <bits3_0.h>
|
||||
|
||||
#include <wine/list.h>
|
||||
|
@ -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)
|
||||
{
|
||||
size_t n = strlen(s) + 1;
|
||||
char *d = HeapAlloc(GetProcessHeap(), 0, n);
|
||||
return d ? memcpy(d, s, n) : NULL;
|
||||
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)
|
||||
{
|
||||
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__ */
|
||||
|
|
|
@ -22,4 +22,6 @@
|
|||
|
||||
#define DO_NO_IMPORTS
|
||||
#include "bits1_5.idl"
|
||||
#include "bits2_0.idl"
|
||||
#include "bits2_5.idl"
|
||||
#include "bits3_0.idl"
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue