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 = ©_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