Commit b329a2ef authored by Dan Hipschman's avatar Dan Hipschman Committed by Alexandre Julliard

qmgr: Implement local file background "downloads."

parent 374fea0a
......@@ -170,3 +170,91 @@ HRESULT BackgroundCopyFileConstructor(BackgroundCopyJobImpl *owner,
*ppObj = &This->lpVtbl;
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)
{
BackgroundCopyFileImpl *file = (BackgroundCopyFileImpl *) 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);
}
BOOL processFile(BackgroundCopyFileImpl *file, BackgroundCopyJobImpl *job)
{
static WCHAR prefix[] = {'B','I','T', 0};
WCHAR tmpDir[MAX_PATH];
WCHAR tmpName[MAX_PATH];
if (!GetTempPathW(MAX_PATH, tmpDir))
{
ERR("Couldn't create temp file name: %d\n", GetLastError());
/* Guessing on what state this should give us */
transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSIENT_ERROR);
return FALSE;
}
if (!GetTempFileNameW(tmpDir, prefix, 0, tmpName))
{
ERR("Couldn't create temp file: %d\n", GetLastError());
/* Guessing on what state this should give us */
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;
file->fileProgress.Completed = FALSE;
LeaveCriticalSection(&job->cs);
TRACE("Transferring: %s -> %s -> %s\n",
debugstr_w(file->info.RemoteName),
debugstr_w(tmpName),
debugstr_w(file->info.LocalName));
transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRING);
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;
}
if (transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_QUEUED))
{
lstrcpyW(file->tempFileName, tmpName);
EnterCriticalSection(&job->cs);
file->fileProgress.Completed = TRUE;
job->jobProgress.FilesTransferred++;
LeaveCriticalSection(&job->cs);
return TRUE;
}
else
{
DeleteFileW(tmpName);
return FALSE;
}
}
......@@ -98,6 +98,7 @@ static HRESULT WINAPI BITS_IBackgroundCopyJob_AddFile(
file = (BackgroundCopyFileImpl *) pFile;
EnterCriticalSection(&This->cs);
list_add_head(&This->files, &file->entryFromJob);
This->jobProgress.BytesTotal = BG_SIZE_UNKNOWN;
++This->jobProgress.FilesTotal;
LeaveCriticalSection(&This->cs);
......@@ -485,3 +486,29 @@ HRESULT BackgroundCopyJobConstructor(LPCWSTR displayName, BG_JOB_TYPE type,
*ppObj = &This->lpVtbl;
return S_OK;
}
void processJob(BackgroundCopyJobImpl *job)
{
for (;;)
{
BackgroundCopyFileImpl *file;
BOOL done = TRUE;
EnterCriticalSection(&job->cs);
LIST_FOR_EACH_ENTRY(file, &job->files, BackgroundCopyFileImpl, entryFromJob)
if (!file->fileProgress.Completed)
{
done = FALSE;
break;
}
LeaveCriticalSection(&job->cs);
if (done)
{
transitionJobState(job, BG_JOB_STATE_QUEUED, BG_JOB_STATE_TRANSFERRED);
return;
}
if (!processFile(file, job))
return;
}
}
......@@ -189,11 +189,6 @@ DWORD WINAPI fileTransfer(void *param)
LeaveCriticalSection(&qmgr->cs);
if (haveJob)
{
FIXME("Actually process job %p; setting error state\n", job);
EnterCriticalSection(&qmgr->cs);
job->state = BG_JOB_STATE_ERROR;
LeaveCriticalSection(&qmgr->cs);
}
processJob(job);
}
}
......@@ -73,6 +73,7 @@ typedef struct
LONG ref;
BG_FILE_INFO info;
BG_FILE_PROGRESS fileProgress;
WCHAR tempFileName[MAX_PATH];
struct list entryFromJob;
BackgroundCopyJobImpl *owner;
} BackgroundCopyFileImpl;
......@@ -107,6 +108,8 @@ HRESULT BackgroundCopyFileConstructor(BackgroundCopyJobImpl *owner,
HRESULT EnumBackgroundCopyFilesConstructor(LPVOID *ppObj,
IBackgroundCopyJob* copyJob);
DWORD WINAPI fileTransfer(void *param);
void processJob(BackgroundCopyJobImpl *job);
BOOL processFile(BackgroundCopyFileImpl *file, BackgroundCopyJobImpl *job);
/* Little helper functions */
static inline char *
......@@ -117,4 +120,19 @@ qmgr_strdup(const char *s)
return d ? memcpy(d, s, n) : NULL;
}
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__ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment