Hans Leidekker : qmgr: Implement IBackgroundCopyError.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Jun 5 06:46:12 CDT 2015


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

Author: Hans Leidekker <hans at codeweavers.com>
Date:   Fri Jun  5 10:35:09 2015 +0200

qmgr: Implement IBackgroundCopyError.

---

 dlls/qmgr/file.c |  50 +++++++++++++++-
 dlls/qmgr/job.c  | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 dlls/qmgr/qmgr.h |   6 ++
 3 files changed, 226 insertions(+), 5 deletions(-)

diff --git a/dlls/qmgr/file.c b/dlls/qmgr/file.c
index 1ed34d3..f00fa3f 100644
--- a/dlls/qmgr/file.c
+++ b/dlls/qmgr/file.c
@@ -424,13 +424,53 @@ static HRESULT WINAPI http_negotiate_BeginningTransaction(
     return E_NOTIMPL;
 }
 
+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 HRESULT WINAPI http_negotiate_OnResponse(
     IHttpNegotiate *iface, DWORD code, LPCWSTR resp_headers, LPCWSTR req_headers, LPWSTR *add_reqheaders)
 {
     DLBindStatusCallback *callback = impl_from_IHttpNegotiate(iface);
-    FIXME("(%p)->(%d %s %s %p)\n", callback, code, debugstr_w(resp_headers), debugstr_w(req_headers),
+    BackgroundCopyJobImpl *job = callback->file->owner;
+
+    TRACE("(%p)->(%d %s %s %p)\n", callback, code, debugstr_w(resp_headers), debugstr_w(req_headers),
           add_reqheaders);
-    return E_NOTIMPL;
+
+    if ((job->error.code = error_from_http_response(code)))
+    {
+        job->error.context = BG_ERROR_CONTEXT_REMOTE_FILE;
+        if (job->error.file) IBackgroundCopyFile2_Release(job->error.file);
+        job->error.file = &callback->file->IBackgroundCopyFile2_iface;
+        IBackgroundCopyFile2_AddRef(job->error.file);
+    }
+    else
+    {
+        job->error.context = 0;
+        if (job->error.file)
+        {
+            IBackgroundCopyFile2_Release(job->error.file);
+            job->error.file = NULL;
+        }
+    }
+    *add_reqheaders = NULL;
+    return S_OK;
 }
 
 static const IHttpNegotiateVtbl http_negotiate_vtbl =
@@ -523,6 +563,12 @@ BOOL processFile(BackgroundCopyFileImpl *file, BackgroundCopyJobImpl *job)
         transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR);
         return FALSE;
     }
+    else if (job->error.code)
+    {
+        ERR("transfer error: 0x%08x\n", job->error.code);
+        transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_ERROR);
+        return FALSE;
+    }
 
     if (transitionJobState(job, BG_JOB_STATE_TRANSFERRING, BG_JOB_STATE_QUEUED))
     {
diff --git a/dlls/qmgr/job.c b/dlls/qmgr/job.c
index 912c23e..d342041 100644
--- a/dlls/qmgr/job.c
+++ b/dlls/qmgr/job.c
@@ -27,6 +27,167 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(qmgr);
 
+struct copy_error
+{
+    IBackgroundCopyError  IBackgroundCopyError_iface;
+    LONG                  refs;
+    BG_ERROR_CONTEXT      context;
+    HRESULT               code;
+    IBackgroundCopyFile2 *file;
+};
+
+static inline struct copy_error *impl_from_IBackgroundCopyError(IBackgroundCopyError *iface)
+{
+    return CONTAINING_RECORD(iface, struct copy_error, IBackgroundCopyError_iface);
+}
+
+static HRESULT WINAPI copy_error_QueryInterface(
+    IBackgroundCopyError *iface,
+    REFIID riid,
+    void **obj)
+{
+    struct copy_error *error = impl_from_IBackgroundCopyError(iface);
+
+    TRACE("(%p)->(%s %p)\n", error, debugstr_guid(riid), obj);
+
+    if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IBackgroundCopyError))
+    {
+        *obj = &error->IBackgroundCopyError_iface;
+    }
+    else
+    {
+        *obj = NULL;
+        WARN("interface %s not supported\n", debugstr_guid(riid));
+        return E_NOINTERFACE;
+    }
+
+    IBackgroundCopyError_AddRef(iface);
+    return S_OK;
+}
+
+static ULONG WINAPI copy_error_AddRef(
+    IBackgroundCopyError *iface)
+{
+    struct copy_error *error = impl_from_IBackgroundCopyError(iface);
+    LONG refs = InterlockedIncrement(&error->refs);
+    TRACE("(%p)->(%d)\n", error, refs);
+    return refs;
+}
+
+static ULONG WINAPI copy_error_Release(
+    IBackgroundCopyError *iface)
+{
+    struct copy_error *error = impl_from_IBackgroundCopyError(iface);
+    LONG refs = InterlockedDecrement(&error->refs);
+
+    TRACE("(%p)->(%d)\n", error, refs);
+
+    if (!refs)
+    {
+        if (error->file) IBackgroundCopyFile2_Release(error->file);
+        HeapFree(GetProcessHeap(), 0, error);
+    }
+    return refs;
+}
+
+static HRESULT WINAPI copy_error_GetError(
+    IBackgroundCopyError *iface,
+    BG_ERROR_CONTEXT *pContext,
+    HRESULT *pCode)
+{
+    struct copy_error *error = impl_from_IBackgroundCopyError(iface);
+
+    TRACE("(%p)->(%p %p)\n", error, pContext, pCode);
+
+    *pContext = error->context;
+    *pCode = error->code;
+
+    TRACE("returning context %u error code 0x%08x\n", error->context, error->code);
+    return S_OK;
+}
+
+static HRESULT WINAPI copy_error_GetFile(
+    IBackgroundCopyError *iface,
+    IBackgroundCopyFile **pVal)
+{
+    struct copy_error *error = impl_from_IBackgroundCopyError(iface);
+
+    TRACE("(%p)->(%p)\n", error, pVal);
+
+    if (error->file)
+    {
+        IBackgroundCopyFile2_AddRef(error->file);
+        *pVal = (IBackgroundCopyFile *)error->file;
+        return S_OK;
+    }
+    *pVal = NULL;
+    return BG_E_FILE_NOT_AVAILABLE;
+}
+
+static HRESULT WINAPI copy_error_GetErrorDescription(
+    IBackgroundCopyError *iface,
+    DWORD LanguageId,
+    LPWSTR *pErrorDescription)
+{
+    struct copy_error *error = impl_from_IBackgroundCopyError(iface);
+    FIXME("(%p)->(%p)\n", error, pErrorDescription);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI copy_error_GetErrorContextDescription(
+    IBackgroundCopyError *iface,
+    DWORD LanguageId,
+    LPWSTR *pContextDescription)
+{
+    struct copy_error *error = impl_from_IBackgroundCopyError(iface);
+    FIXME("(%p)->(%p)\n", error, pContextDescription);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI copy_error_GetProtocol(
+    IBackgroundCopyError *iface,
+    LPWSTR *pProtocol)
+{
+    struct copy_error *error = impl_from_IBackgroundCopyError(iface);
+    FIXME("(%p)->(%p)\n", error, pProtocol);
+    return E_NOTIMPL;
+}
+
+static const IBackgroundCopyErrorVtbl copy_error_vtbl =
+{
+    copy_error_QueryInterface,
+    copy_error_AddRef,
+    copy_error_Release,
+    copy_error_GetError,
+    copy_error_GetFile,
+    copy_error_GetErrorDescription,
+    copy_error_GetErrorContextDescription,
+    copy_error_GetProtocol
+};
+
+static HRESULT create_copy_error(
+    BG_ERROR_CONTEXT context,
+    HRESULT code,
+    IBackgroundCopyFile2 *file,
+    IBackgroundCopyError **obj)
+{
+    struct copy_error *error;
+
+    TRACE("context %u code %08x file %p\n", context, code, file);
+
+    if (!(error = HeapAlloc(GetProcessHeap(), 0, sizeof(*error) ))) return E_OUTOFMEMORY;
+    error->IBackgroundCopyError_iface.lpVtbl = &copy_error_vtbl;
+    error->refs    = 1;
+    error->context = context;
+    error->code    = code;
+    error->file    = file;
+    if (error->file) IBackgroundCopyFile2_AddRef(error->file);
+
+    *obj = &error->IBackgroundCopyError_iface;
+    TRACE("returning iface %p\n", *obj);
+    return S_OK;
+}
+
 static inline BOOL is_job_done(const BackgroundCopyJobImpl *job)
 {
     return job->state == BG_JOB_STATE_CANCELLED || job->state == BG_JOB_STATE_ACKNOWLEDGED;
@@ -312,9 +473,13 @@ static HRESULT WINAPI BackgroundCopyJob_GetError(
     IBackgroundCopyJob3 *iface,
     IBackgroundCopyError **ppError)
 {
-    BackgroundCopyJobImpl *This = impl_from_IBackgroundCopyJob3(iface);
-    FIXME("(%p)->(%p): stub\n", This, ppError);
-    return E_NOTIMPL;
+    BackgroundCopyJobImpl *job = impl_from_IBackgroundCopyJob3(iface);
+
+    TRACE("(%p)->(%p)\n", job, ppError);
+
+    if (!job->error.context) return BG_E_ERROR_INFORMATION_UNAVAILABLE;
+
+    return create_copy_error(job->error.context, job->error.code, job->error.file, ppError);
 }
 
 static HRESULT WINAPI BackgroundCopyJob_GetOwner(
@@ -788,6 +953,10 @@ HRESULT BackgroundCopyJobConstructor(LPCWSTR displayName, BG_JOB_TYPE type, GUID
     This->callback = NULL;
     This->callback2 = FALSE;
 
+    This->error.context = 0;
+    This->error.code = 0;
+    This->error.file = NULL;
+
     *job = This;
 
     TRACE("created job %s:%p\n", debugstr_guid(&This->jobId), This);
diff --git a/dlls/qmgr/qmgr.h b/dlls/qmgr/qmgr.h
index 87145fd..80a3e97 100644
--- a/dlls/qmgr/qmgr.h
+++ b/dlls/qmgr/qmgr.h
@@ -51,6 +51,12 @@ typedef struct
     /* Protects file list, and progress */
     CRITICAL_SECTION cs;
     struct list entryFromQmgr;
+    struct
+    {
+        BG_ERROR_CONTEXT      context;
+        HRESULT               code;
+        IBackgroundCopyFile2 *file;
+    } error;
 } BackgroundCopyJobImpl;
 
 /* Background copy file vtbl and related data */




More information about the wine-cvs mailing list