Dan Hipschman : qmgr: Implement local file background "downloads."

Alexandre Julliard julliard at winehq.org
Fri Mar 14 08:29:23 CDT 2008


Module: wine
Branch: master
Commit: b329a2ef3cdb17f4b301adcbe5beddf57506ace6
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=b329a2ef3cdb17f4b301adcbe5beddf57506ace6

Author: Dan Hipschman <dsh at linux.ucla.edu>
Date:   Thu Mar 13 15:54:35 2008 -0700

qmgr: Implement local file background "downloads."

---

 dlls/qmgr/file.c |   88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 dlls/qmgr/job.c  |   27 ++++++++++++++++
 dlls/qmgr/qmgr.c |    7 +----
 dlls/qmgr/qmgr.h |   18 +++++++++++
 4 files changed, 134 insertions(+), 6 deletions(-)

diff --git a/dlls/qmgr/file.c b/dlls/qmgr/file.c
index f1ae06a..a874062 100644
--- a/dlls/qmgr/file.c
+++ b/dlls/qmgr/file.c
@@ -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;
+    }
+}
diff --git a/dlls/qmgr/job.c b/dlls/qmgr/job.c
index 2fbf1bc..3b94a79 100644
--- a/dlls/qmgr/job.c
+++ b/dlls/qmgr/job.c
@@ -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;
+    }
+}
diff --git a/dlls/qmgr/qmgr.c b/dlls/qmgr/qmgr.c
index 608e01a..4e3d259 100644
--- a/dlls/qmgr/qmgr.c
+++ b/dlls/qmgr/qmgr.c
@@ -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);
     }
 }
diff --git a/dlls/qmgr/qmgr.h b/dlls/qmgr/qmgr.h
index fce84d9..9530b97 100644
--- a/dlls/qmgr/qmgr.h
+++ b/dlls/qmgr/qmgr.h
@@ -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__ */




More information about the wine-cvs mailing list