[WLAN-BRINGUP]
[reactos.git] / dll / win32 / urlmon / download.c
index d81dffa..c20c87c 100644 (file)
 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
 
 typedef struct {
 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
 
 typedef struct {
-    const IBindStatusCallbackVtbl  *lpBindStatusCallbackVtbl;
-    const IServiceProviderVtbl     *lpServiceProviderVtbl;
+    IBindStatusCallback IBindStatusCallback_iface;
+    IServiceProvider    IServiceProvider_iface;
 
     LONG ref;
 
     IBindStatusCallback *callback;
 
     LONG ref;
 
     IBindStatusCallback *callback;
+    IBinding *binding;
     LPWSTR file_name;
     LPWSTR cache_file;
 } DownloadBSC;
 
     LPWSTR file_name;
     LPWSTR cache_file;
 } DownloadBSC;
 
-#define STATUSCLB(x)     ((IBindStatusCallback*)  &(x)->lpBindStatusCallbackVtbl)
-#define SERVPROV(x)      ((IServiceProvider*)     &(x)->lpServiceProviderVtbl)
+static inline DownloadBSC *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
+{
+    return CONTAINING_RECORD(iface, DownloadBSC, IBindStatusCallback_iface);
+}
 
 
-#define STATUSCLB_THIS(iface) DEFINE_THIS(DownloadBSC, BindStatusCallback, iface)
+static inline DownloadBSC *impl_from_IServiceProvider(IServiceProvider *iface)
+{
+    return CONTAINING_RECORD(iface, DownloadBSC, IServiceProvider_iface);
+}
 
 static HRESULT WINAPI DownloadBSC_QueryInterface(IBindStatusCallback *iface,
         REFIID riid, void **ppv)
 {
 
 static HRESULT WINAPI DownloadBSC_QueryInterface(IBindStatusCallback *iface,
         REFIID riid, void **ppv)
 {
-    DownloadBSC *This = STATUSCLB_THIS(iface);
+    DownloadBSC *This = impl_from_IBindStatusCallback(iface);
 
     *ppv = NULL;
 
     if(IsEqualGUID(&IID_IUnknown, riid)) {
         TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
 
     *ppv = NULL;
 
     if(IsEqualGUID(&IID_IUnknown, riid)) {
         TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
-        *ppv = STATUSCLB(This);
+        *ppv = &This->IBindStatusCallback_iface;
     }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
         TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
     }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
         TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
-        *ppv = STATUSCLB(This);
+        *ppv = &This->IBindStatusCallback_iface;
     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
         TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv);
     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
         TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv);
-        *ppv = SERVPROV(This);
+        *ppv = &This->IServiceProvider_iface;
     }
 
     if(*ppv) {
     }
 
     if(*ppv) {
@@ -66,7 +72,7 @@ static HRESULT WINAPI DownloadBSC_QueryInterface(IBindStatusCallback *iface,
 
 static ULONG WINAPI DownloadBSC_AddRef(IBindStatusCallback *iface)
 {
 
 static ULONG WINAPI DownloadBSC_AddRef(IBindStatusCallback *iface)
 {
-    DownloadBSC *This = STATUSCLB_THIS(iface);
+    DownloadBSC *This = impl_from_IBindStatusCallback(iface);
     LONG ref = InterlockedIncrement(&This->ref);
 
     TRACE("(%p) ref = %d\n", This, ref);
     LONG ref = InterlockedIncrement(&This->ref);
 
     TRACE("(%p) ref = %d\n", This, ref);
@@ -76,7 +82,7 @@ static ULONG WINAPI DownloadBSC_AddRef(IBindStatusCallback *iface)
 
 static ULONG WINAPI DownloadBSC_Release(IBindStatusCallback *iface)
 {
 
 static ULONG WINAPI DownloadBSC_Release(IBindStatusCallback *iface)
 {
-    DownloadBSC *This = STATUSCLB_THIS(iface);
+    DownloadBSC *This = impl_from_IBindStatusCallback(iface);
     LONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) ref = %d\n", This, ref);
     LONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) ref = %d\n", This, ref);
@@ -84,6 +90,8 @@ static ULONG WINAPI DownloadBSC_Release(IBindStatusCallback *iface)
     if(!ref) {
         if(This->callback)
             IBindStatusCallback_Release(This->callback);
     if(!ref) {
         if(This->callback)
             IBindStatusCallback_Release(This->callback);
+        if(This->binding)
+            IBinding_Release(This->binding);
         heap_free(This->file_name);
         heap_free(This->cache_file);
         heap_free(This);
         heap_free(This->file_name);
         heap_free(This->cache_file);
         heap_free(This);
@@ -95,102 +103,122 @@ static ULONG WINAPI DownloadBSC_Release(IBindStatusCallback *iface)
 static HRESULT WINAPI DownloadBSC_OnStartBinding(IBindStatusCallback *iface,
         DWORD dwReserved, IBinding *pbind)
 {
 static HRESULT WINAPI DownloadBSC_OnStartBinding(IBindStatusCallback *iface,
         DWORD dwReserved, IBinding *pbind)
 {
-    DownloadBSC *This = STATUSCLB_THIS(iface);
+    DownloadBSC *This = impl_from_IBindStatusCallback(iface);
+    HRESULT hres = S_OK;
 
     TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
 
 
     TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
 
-    if(This->callback)
-        IBindStatusCallback_OnStartBinding(This->callback, dwReserved, pbind);
+    if(This->callback) {
+        hres = IBindStatusCallback_OnStartBinding(This->callback, dwReserved, pbind);
 
 
-    return S_OK;
+        IBinding_AddRef(pbind);
+        This->binding = pbind;
+    }
+
+    /* Windows seems to ignore E_NOTIMPL if it's returned from the client. */
+    return hres == E_NOTIMPL ? S_OK : hres;
 }
 
 static HRESULT WINAPI DownloadBSC_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
 {
 }
 
 static HRESULT WINAPI DownloadBSC_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
 {
-    DownloadBSC *This = STATUSCLB_THIS(iface);
+    DownloadBSC *This = impl_from_IBindStatusCallback(iface);
     FIXME("(%p)->(%p)\n", This, pnPriority);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI DownloadBSC_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
 {
     FIXME("(%p)->(%p)\n", This, pnPriority);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI DownloadBSC_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
 {
-    DownloadBSC *This = STATUSCLB_THIS(iface);
+    DownloadBSC *This = impl_from_IBindStatusCallback(iface);
     FIXME("(%p)->(%d)\n", This, reserved);
     return E_NOTIMPL;
 }
 
     FIXME("(%p)->(%d)\n", This, reserved);
     return E_NOTIMPL;
 }
 
-static void on_progress(DownloadBSC *This, ULONG progress, ULONG progress_max, ULONG status_code, LPCWSTR status_text)
+static HRESULT on_progress(DownloadBSC *This, ULONG progress, ULONG progress_max, ULONG status_code, LPCWSTR status_text)
 {
     HRESULT hres;
 
     if(!This->callback)
 {
     HRESULT hres;
 
     if(!This->callback)
-        return;
+        return S_OK;
 
     hres = IBindStatusCallback_OnProgress(This->callback, progress, progress_max, status_code, status_text);
 
     hres = IBindStatusCallback_OnProgress(This->callback, progress, progress_max, status_code, status_text);
-    if(FAILED(hres))
-        FIXME("OnProgress failed: %08x\n", hres);
+    if(hres == E_ABORT) {
+        if(This->binding)
+            IBinding_Abort(This->binding);
+        else
+            FIXME("No binding, not sure what to do!\n");
+    }
+
+    return hres;
 }
 
 static HRESULT WINAPI DownloadBSC_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
         ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
 {
 }
 
 static HRESULT WINAPI DownloadBSC_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
         ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
 {
-    DownloadBSC *This = STATUSCLB_THIS(iface);
+    DownloadBSC *This = impl_from_IBindStatusCallback(iface);
+    HRESULT hres = S_OK;
 
     TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
             debugstr_w(szStatusText));
 
     switch(ulStatusCode) {
 
     TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
             debugstr_w(szStatusText));
 
     switch(ulStatusCode) {
+    case BINDSTATUS_CONNECTING:
     case BINDSTATUS_BEGINDOWNLOADDATA:
     case BINDSTATUS_DOWNLOADINGDATA:
     case BINDSTATUS_ENDDOWNLOADDATA:
     case BINDSTATUS_SENDINGREQUEST:
     case BINDSTATUS_MIMETYPEAVAILABLE:
     case BINDSTATUS_BEGINDOWNLOADDATA:
     case BINDSTATUS_DOWNLOADINGDATA:
     case BINDSTATUS_ENDDOWNLOADDATA:
     case BINDSTATUS_SENDINGREQUEST:
     case BINDSTATUS_MIMETYPEAVAILABLE:
-        on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
+        hres = on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
         break;
 
     case BINDSTATUS_CACHEFILENAMEAVAILABLE:
         break;
 
     case BINDSTATUS_CACHEFILENAMEAVAILABLE:
-        on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
+        hres = on_progress(This, ulProgress, ulProgressMax, ulStatusCode, szStatusText);
         This->cache_file = heap_strdupW(szStatusText);
         break;
 
         This->cache_file = heap_strdupW(szStatusText);
         break;
 
-    case BINDSTATUS_FINDINGRESOURCE:
-    case BINDSTATUS_CONNECTING:
+    case BINDSTATUS_FINDINGRESOURCE: /* FIXME */
         break;
 
     default:
         FIXME("Unsupported status %u\n", ulStatusCode);
     }
 
         break;
 
     default:
         FIXME("Unsupported status %u\n", ulStatusCode);
     }
 
-    return S_OK;
+    return hres;
 }
 
 static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface,
         HRESULT hresult, LPCWSTR szError)
 {
 }
 
 static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface,
         HRESULT hresult, LPCWSTR szError)
 {
-    DownloadBSC *This = STATUSCLB_THIS(iface);
+    DownloadBSC *This = impl_from_IBindStatusCallback(iface);
 
     TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
 
 
     TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
 
-    if(This->cache_file) {
-        BOOL b;
+    if(This->file_name) {
+        if(This->cache_file) {
+            BOOL b;
 
 
-        b = CopyFileW(This->cache_file, This->file_name, FALSE);
-        if(!b)
-            FIXME("CopyFile failed: %u\n", GetLastError());
-    }else {
-        FIXME("No cache file\n");
+            b = CopyFileW(This->cache_file, This->file_name, FALSE);
+            if(!b)
+                FIXME("CopyFile failed: %u\n", GetLastError());
+        }else {
+            FIXME("No cache file\n");
+        }
     }
 
     if(This->callback)
         IBindStatusCallback_OnStopBinding(This->callback, hresult, szError);
 
     }
 
     if(This->callback)
         IBindStatusCallback_OnStopBinding(This->callback, hresult, szError);
 
+    if(This->binding) {
+        IBinding_Release(This->binding);
+        This->binding = NULL;
+    }
+
     return S_OK;
 }
 
 static HRESULT WINAPI DownloadBSC_GetBindInfo(IBindStatusCallback *iface,
         DWORD *grfBINDF, BINDINFO *pbindinfo)
 {
     return S_OK;
 }
 
 static HRESULT WINAPI DownloadBSC_GetBindInfo(IBindStatusCallback *iface,
         DWORD *grfBINDF, BINDINFO *pbindinfo)
 {
-    DownloadBSC *This = STATUSCLB_THIS(iface);
+    DownloadBSC *This = impl_from_IBindStatusCallback(iface);
     DWORD bindf = 0;
 
     TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
     DWORD bindf = 0;
 
     TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
@@ -214,7 +242,7 @@ static HRESULT WINAPI DownloadBSC_GetBindInfo(IBindStatusCallback *iface,
 static HRESULT WINAPI DownloadBSC_OnDataAvailable(IBindStatusCallback *iface,
         DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
 {
 static HRESULT WINAPI DownloadBSC_OnDataAvailable(IBindStatusCallback *iface,
         DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
 {
-    DownloadBSC *This = STATUSCLB_THIS(iface);
+    DownloadBSC *This = impl_from_IBindStatusCallback(iface);
 
     TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
 
 
     TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
 
@@ -224,13 +252,11 @@ static HRESULT WINAPI DownloadBSC_OnDataAvailable(IBindStatusCallback *iface,
 static HRESULT WINAPI DownloadBSC_OnObjectAvailable(IBindStatusCallback *iface,
         REFIID riid, IUnknown *punk)
 {
 static HRESULT WINAPI DownloadBSC_OnObjectAvailable(IBindStatusCallback *iface,
         REFIID riid, IUnknown *punk)
 {
-    DownloadBSC *This = STATUSCLB_THIS(iface);
+    DownloadBSC *This = impl_from_IBindStatusCallback(iface);
     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
     return E_NOTIMPL;
 }
 
     FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
     return E_NOTIMPL;
 }
 
-#undef STATUSCLB_THIS
-
 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
     DownloadBSC_QueryInterface,
     DownloadBSC_AddRef,
 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
     DownloadBSC_QueryInterface,
     DownloadBSC_AddRef,
@@ -245,31 +271,29 @@ static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
     DownloadBSC_OnObjectAvailable
 };
 
     DownloadBSC_OnObjectAvailable
 };
 
-#define SERVPROV_THIS(iface) DEFINE_THIS(DownloadBSC, ServiceProvider, iface)
-
 static HRESULT WINAPI DwlServiceProvider_QueryInterface(IServiceProvider *iface,
         REFIID riid, void **ppv)
 {
 static HRESULT WINAPI DwlServiceProvider_QueryInterface(IServiceProvider *iface,
         REFIID riid, void **ppv)
 {
-    DownloadBSC *This = SERVPROV_THIS(iface);
-    return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
+    DownloadBSC *This = impl_from_IServiceProvider(iface);
+    return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
 }
 
 static ULONG WINAPI DwlServiceProvider_AddRef(IServiceProvider *iface)
 {
 }
 
 static ULONG WINAPI DwlServiceProvider_AddRef(IServiceProvider *iface)
 {
-    DownloadBSC *This = SERVPROV_THIS(iface);
-    return IBindStatusCallback_AddRef(STATUSCLB(This));
+    DownloadBSC *This = impl_from_IServiceProvider(iface);
+    return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
 }
 
 static ULONG WINAPI DwlServiceProvider_Release(IServiceProvider *iface)
 {
 }
 
 static ULONG WINAPI DwlServiceProvider_Release(IServiceProvider *iface)
 {
-    DownloadBSC *This = SERVPROV_THIS(iface);
-    return IBindStatusCallback_Release(STATUSCLB(This));
+    DownloadBSC *This = impl_from_IServiceProvider(iface);
+    return IBindStatusCallback_Release(&This->IBindStatusCallback_iface);
 }
 
 static HRESULT WINAPI DwlServiceProvider_QueryService(IServiceProvider *iface,
         REFGUID guidService, REFIID riid, void **ppv)
 {
 }
 
 static HRESULT WINAPI DwlServiceProvider_QueryService(IServiceProvider *iface,
         REFGUID guidService, REFIID riid, void **ppv)
 {
-    DownloadBSC *This = SERVPROV_THIS(iface);
+    DownloadBSC *This = impl_from_IServiceProvider(iface);
     IServiceProvider *serv_prov;
     HRESULT hres;
 
     IServiceProvider *serv_prov;
     HRESULT hres;
 
@@ -292,8 +316,6 @@ static HRESULT WINAPI DwlServiceProvider_QueryService(IServiceProvider *iface,
     return E_NOINTERFACE;
 }
 
     return E_NOINTERFACE;
 }
 
-#undef SERVPROV_THIS
-
 static const IServiceProviderVtbl ServiceProviderVtbl = {
     DwlServiceProvider_QueryInterface,
     DwlServiceProvider_AddRef,
 static const IServiceProviderVtbl ServiceProviderVtbl = {
     DwlServiceProvider_QueryInterface,
     DwlServiceProvider_AddRef,
@@ -301,21 +323,37 @@ static const IServiceProviderVtbl ServiceProviderVtbl = {
     DwlServiceProvider_QueryService
 };
 
     DwlServiceProvider_QueryService
 };
 
-static IBindStatusCallback *DownloadBSC_Create(IBindStatusCallback *callback, LPCWSTR file_name)
+static HRESULT DownloadBSC_Create(IBindStatusCallback *callback, LPCWSTR file_name, IBindStatusCallback **ret_callback)
 {
     DownloadBSC *ret = heap_alloc(sizeof(*ret));
 
 {
     DownloadBSC *ret = heap_alloc(sizeof(*ret));
 
-    ret->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl;
-    ret->lpServiceProviderVtbl    = &ServiceProviderVtbl;
+    ret->IBindStatusCallback_iface.lpVtbl = &BindStatusCallbackVtbl;
+    ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
     ret->ref = 1;
     ret->file_name = heap_strdupW(file_name);
     ret->cache_file = NULL;
     ret->ref = 1;
     ret->file_name = heap_strdupW(file_name);
     ret->cache_file = NULL;
+    ret->binding = NULL;
 
     if(callback)
         IBindStatusCallback_AddRef(callback);
     ret->callback = callback;
 
 
     if(callback)
         IBindStatusCallback_AddRef(callback);
     ret->callback = callback;
 
-    return STATUSCLB(ret);
+    *ret_callback = &ret->IBindStatusCallback_iface;
+    return S_OK;
+}
+
+HRESULT create_default_callback(IBindStatusCallback **ret)
+{
+    IBindStatusCallback *callback;
+    HRESULT hres;
+
+    hres = DownloadBSC_Create(NULL, NULL, &callback);
+    if(FAILED(hres))
+        return hres;
+
+    hres = wrap_callback(callback, ret);
+    IBindStatusCallback_Release(callback);
+    return hres;
 }
 
 /***********************************************************************
 }
 
 /***********************************************************************
@@ -348,7 +386,10 @@ HRESULT WINAPI URLDownloadToFileW(LPUNKNOWN pCaller, LPCWSTR szURL, LPCWSTR szFi
     if(pCaller)
         FIXME("pCaller not supported\n");
 
     if(pCaller)
         FIXME("pCaller not supported\n");
 
-    callback = DownloadBSC_Create(lpfnCB, szFileName);
+    hres = DownloadBSC_Create(lpfnCB, szFileName, &callback);
+    if(FAILED(hres))
+        return hres;
+
     hres = CreateAsyncBindCtx(0, callback, NULL, &bindctx);
     IBindStatusCallback_Release(callback);
     if(FAILED(hres))
     hres = CreateAsyncBindCtx(0, callback, NULL, &bindctx);
     IBindStatusCallback_Release(callback);
     if(FAILED(hres))