Dan Hipschman : qmgr: Transfer files given by URL (including HTTP, etc).

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


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

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

qmgr: Transfer files given by URL (including HTTP, etc).

---

 dlls/qmgr/Makefile.in |    2 +-
 dlls/qmgr/file.c      |   39 ++++++++++++++++++++++--
 dlls/qmgr/tests/job.c |   77 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 113 insertions(+), 5 deletions(-)

diff --git a/dlls/qmgr/Makefile.in b/dlls/qmgr/Makefile.in
index 30c699b..de636db 100644
--- a/dlls/qmgr/Makefile.in
+++ b/dlls/qmgr/Makefile.in
@@ -3,7 +3,7 @@ TOPOBJDIR = ../..
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = qmgr.dll
-IMPORTS   = advpack ole32 advapi32 kernel32
+IMPORTS   = advpack wininet urlmon ole32 advapi32 kernel32
 EXTRALIBS = -luuid
 
 C_SRCS = \
diff --git a/dlls/qmgr/file.c b/dlls/qmgr/file.c
index a874062..fea84ec 100644
--- a/dlls/qmgr/file.c
+++ b/dlls/qmgr/file.c
@@ -1,7 +1,7 @@
 /*
  * Queue Manager (BITS) File
  *
- * Copyright 2007 Google (Roy Shea)
+ * Copyright 2007, 2008 Google (Roy Shea, Dan Hipschman)
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -18,6 +18,16 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winuser.h"
+#include "winreg.h"
+#include "ole2.h"
+#include "urlmon.h"
+#include "wininet.h"
+
 #include "qmgr.h"
 #include "wine/debug.h"
 
@@ -204,6 +214,7 @@ BOOL processFile(BackgroundCopyFileImpl *file, BackgroundCopyJobImpl *job)
     static WCHAR prefix[] = {'B','I','T', 0};
     WCHAR tmpDir[MAX_PATH];
     WCHAR tmpName[MAX_PATH];
+    HRESULT hr;
 
     if (!GetTempPathW(MAX_PATH, tmpDir))
     {
@@ -233,10 +244,30 @@ BOOL processFile(BackgroundCopyFileImpl *file, BackgroundCopyJobImpl *job)
           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))
+
+    DeleteUrlCacheEntryW(file->info.RemoteName);
+    hr = URLDownloadToFileW(NULL, file->info.RemoteName, tmpName, 0, NULL);
+    if (SUCCEEDED(hr))
+    {
+        FIXME("Do progress updates correctly with IBindStatusCallback\n");
+        EnterCriticalSection(&job->cs);
+        file->fileProgress.BytesTotal = 0;
+        LeaveCriticalSection(&job->cs);
+    }
+    else if (hr == INET_E_DOWNLOAD_FAILURE)
+    {
+        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;
+        }
+    }
+    else
     {
-        ERR("Local file copy failed: error %d\n", GetLastError());
+        ERR("URLDownload failed: eh 0x%08x\n", hr);
         transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR);
         return FALSE;
     }
diff --git a/dlls/qmgr/tests/job.c b/dlls/qmgr/tests/job.c
index 726624a..971d885 100644
--- a/dlls/qmgr/tests/job.c
+++ b/dlls/qmgr/tests/job.c
@@ -377,6 +377,82 @@ static void test_CompleteLocal(void)
     ok(DeleteFileW(test_remotePathB), "DeleteFile\n");
 }
 
+/* Test a complete transfer for local files */
+static void test_CompleteLocalURL(void)
+{
+    static const WCHAR prot[] = {'f','i','l','e',':','/','/', 0};
+    static const int timeout_sec = 30;
+    WCHAR *urlA, *urlB;
+    HRESULT hres;
+    BG_JOB_STATE state;
+    int i;
+
+    DeleteFileW(test_localPathA);
+    DeleteFileW(test_localPathB);
+    makeFile(test_remotePathA, "This is a WINE test file for BITS\n");
+    makeFile(test_remotePathB, "This is another WINE test file for BITS\n");
+
+    urlA = HeapAlloc(GetProcessHeap(), 0,
+                     (7 + lstrlenW(test_remotePathA) + 1) * sizeof urlA[0]);
+    urlB = HeapAlloc(GetProcessHeap(), 0,
+                     (7 + lstrlenW(test_remotePathB) + 1) * sizeof urlB[0]);
+    if (!urlA || !urlB)
+    {
+        skip("Unable to allocate memory for URLs\n");
+        return;
+    }
+
+    lstrcpyW(urlA, prot);
+    lstrcatW(urlA, test_remotePathA);
+    lstrcpyW(urlB, prot);
+    lstrcatW(urlB, test_remotePathB);
+
+    hres = IBackgroundCopyJob_AddFile(test_job, urlA, test_localPathA);
+    if (hres != S_OK)
+    {
+        skip("Unable to add file to job\n");
+        return;
+    }
+
+    hres = IBackgroundCopyJob_AddFile(test_job, urlB, test_localPathB);
+    if (hres != S_OK)
+    {
+        skip("Unable to add file to job\n");
+        return;
+    }
+
+    hres = IBackgroundCopyJob_Resume(test_job);
+    ok(hres == S_OK, "IBackgroundCopyJob_Resume\n");
+
+    for (i = 0; i < timeout_sec; ++i)
+    {
+        hres = IBackgroundCopyJob_GetState(test_job, &state);
+        ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
+        ok(state == BG_JOB_STATE_QUEUED || state == BG_JOB_STATE_CONNECTING
+           || state == BG_JOB_STATE_TRANSFERRING || state == BG_JOB_STATE_TRANSFERRED,
+           "Bad state: %d\n", state);
+        if (state == BG_JOB_STATE_TRANSFERRED)
+            break;
+        Sleep(1000);
+    }
+
+    ok(i < timeout_sec, "BITS jobs timed out\n");
+    hres = IBackgroundCopyJob_Complete(test_job);
+    ok(hres == S_OK, "IBackgroundCopyJob_Complete\n");
+    hres = IBackgroundCopyJob_GetState(test_job, &state);
+    ok(hres == S_OK, "IBackgroundCopyJob_GetState\n");
+    ok(state == BG_JOB_STATE_ACKNOWLEDGED, "Bad state: %d\n", state);
+
+    compareFiles(test_remotePathA, test_localPathA);
+    compareFiles(test_remotePathB, test_localPathB);
+
+    ok(DeleteFileW(test_remotePathA), "DeleteFile\n");
+    ok(DeleteFileW(test_remotePathB), "DeleteFile\n");
+
+    HeapFree(GetProcessHeap(), 0, urlA);
+    HeapFree(GetProcessHeap(), 0, urlB);
+}
+
 typedef void (*test_t)(void);
 
 START_TEST(job)
@@ -391,6 +467,7 @@ START_TEST(job)
         test_GetState,
         test_ResumeEmpty,
         test_CompleteLocal,
+        test_CompleteLocalURL,
         0
     };
     const test_t *test;




More information about the wine-cvs mailing list