[URLMON]
authorCameron Gutman <aicommander@gmail.com>
Sun, 5 Jun 2011 21:29:41 +0000 (21:29 +0000)
committerCameron Gutman <aicommander@gmail.com>
Sun, 5 Jun 2011 21:29:41 +0000 (21:29 +0000)
- Sync to wine 1.3.21

svn path=/trunk/; revision=52103

28 files changed:
reactos/dll/win32/urlmon/CMakeLists.txt
reactos/dll/win32/urlmon/bindctx.c
reactos/dll/win32/urlmon/binding.c
reactos/dll/win32/urlmon/bindprot.c
reactos/dll/win32/urlmon/download.c
reactos/dll/win32/urlmon/ftp.c
reactos/dll/win32/urlmon/gopher.c
reactos/dll/win32/urlmon/http.c
reactos/dll/win32/urlmon/internet.c
reactos/dll/win32/urlmon/mimefilter.c
reactos/dll/win32/urlmon/mk.c
reactos/dll/win32/urlmon/protocol.c
reactos/dll/win32/urlmon/protproxy.c
reactos/dll/win32/urlmon/regsvr.c [deleted file]
reactos/dll/win32/urlmon/rsrc.rc
reactos/dll/win32/urlmon/sec_mgr.c
reactos/dll/win32/urlmon/session.c
reactos/dll/win32/urlmon/umon.c
reactos/dll/win32/urlmon/umstream.c
reactos/dll/win32/urlmon/uri.c
reactos/dll/win32/urlmon/urlmon.inf
reactos/dll/win32/urlmon/urlmon.rbuild
reactos/dll/win32/urlmon/urlmon.rgs [new file with mode: 0644]
reactos/dll/win32/urlmon/urlmon.spec
reactos/dll/win32/urlmon/urlmon_main.c
reactos/dll/win32/urlmon/urlmon_main.h
reactos/dll/win32/urlmon/urlmon_urlmon.idl
reactos/include/psdk/urlmon.idl

index 76abc28..941e625 100644 (file)
@@ -27,7 +27,6 @@ list(APPEND SOURCE
     mk.c
     protocol.c
     protproxy.c
-    regsvr.c
     sec_mgr.c
     session.c
     umon.c
index b08eb80..1af7fa7 100644 (file)
@@ -28,10 +28,10 @@ static WCHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_
 extern IID IID_IBindStatusCallbackHolder;
 
 typedef struct {
-    const IBindStatusCallbackExVtbl  *lpBindStatusCallbackExVtbl;
-    const IServiceProviderVtbl       *lpServiceProviderVtbl;
-    const IHttpNegotiate2Vtbl        *lpHttpNegotiate2Vtbl;
-    const IAuthenticateVtbl          *lpAuthenticateVtbl;
+    IBindStatusCallbackEx IBindStatusCallbackEx_iface;
+    IServiceProvider      IServiceProvider_iface;
+    IHttpNegotiate2       IHttpNegotiate2_iface;
+    IAuthenticate         IAuthenticate_iface;
 
     LONG ref;
 
@@ -39,12 +39,6 @@ typedef struct {
     IServiceProvider *serv_prov;
 } BindStatusCallback;
 
-#define STATUSCLB(x)     ((IBindStatusCallback*)  &(x)->lpBindStatusCallbackExVtbl)
-#define STATUSCLBEX(x)   ((IBindStatusCallbackEx*)&(x)->lpBindStatusCallbackExVtbl)
-#define SERVPROV(x)      ((IServiceProvider*)     &(x)->lpServiceProviderVtbl)
-#define HTTPNEG2(x)      ((IHttpNegotiate2*)      &(x)->lpHttpNegotiate2Vtbl)
-#define AUTHENTICATE(x)  ((IAuthenticate*)        &(x)->lpAuthenticateVtbl)
-
 static void *get_callback_iface(BindStatusCallback *This, REFIID riid)
 {
     void *ret;
@@ -57,39 +51,42 @@ static void *get_callback_iface(BindStatusCallback *This, REFIID riid)
     return SUCCEEDED(hres) ? ret : NULL;
 }
 
-#define STATUSCLB_THIS(iface) DEFINE_THIS(BindStatusCallback, BindStatusCallbackEx, iface)
+static inline BindStatusCallback *impl_from_IBindStatusCallbackEx(IBindStatusCallbackEx *iface)
+{
+    return CONTAINING_RECORD(iface, BindStatusCallback, IBindStatusCallbackEx_iface);
+}
 
 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallbackEx *iface,
         REFIID riid, void **ppv)
 {
-    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
 
     *ppv = NULL;
 
     if(IsEqualGUID(&IID_IUnknown, riid)) {
         TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv);
-        *ppv = STATUSCLB(This);
+        *ppv = &This->IBindStatusCallbackEx_iface;
     }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
         TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
-        *ppv = STATUSCLB(This);
+        *ppv = &This->IBindStatusCallbackEx_iface;
     }else if(IsEqualGUID(&IID_IBindStatusCallbackEx, riid)) {
         TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv);
-        *ppv = STATUSCLBEX(This);
+        *ppv = &This->IBindStatusCallbackEx_iface;
     }else if(IsEqualGUID(&IID_IBindStatusCallbackHolder, riid)) {
         TRACE("(%p)->(IID_IBindStatusCallbackHolder, %p)\n", This, ppv);
         *ppv = This;
     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
         TRACE("(%p)->(IID_IServiceProvider, %p)\n", This, ppv);
-        *ppv = SERVPROV(This);
+        *ppv = &This->IServiceProvider_iface;
     }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) {
         TRACE("(%p)->(IID_IHttpNegotiate, %p)\n", This, ppv);
-        *ppv = HTTPNEG2(This);
+        *ppv = &This->IHttpNegotiate2_iface;
     }else if(IsEqualGUID(&IID_IHttpNegotiate2, riid)) {
         TRACE("(%p)->(IID_IHttpNegotiate2, %p)\n", This, ppv);
-        *ppv = HTTPNEG2(This);
+        *ppv = &This->IHttpNegotiate2_iface;
     }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
         TRACE("(%p)->(IID_IAuthenticate, %p)\n", This, ppv);
-        *ppv = AUTHENTICATE(This);
+        *ppv = &This->IAuthenticate_iface;
     }
 
     if(*ppv) {
@@ -103,7 +100,7 @@ static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallbackEx *i
 
 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallbackEx *iface)
 {
-    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
     LONG ref = InterlockedIncrement(&This->ref);
 
     TRACE("(%p) ref = %d\n", This, ref);
@@ -113,7 +110,7 @@ static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallbackEx *iface)
 
 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallbackEx *iface)
 {
-    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
     LONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) ref = %d\n", This, ref);
@@ -131,7 +128,7 @@ static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallbackEx *iface)
 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallbackEx *iface,
         DWORD dwReserved, IBinding *pbind)
 {
-    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
 
     TRACE("(%p)->(%d %p)\n", This, dwReserved, pbind);
 
@@ -140,7 +137,7 @@ static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallbackEx *i
 
 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallbackEx *iface, LONG *pnPriority)
 {
-    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
 
     TRACE("(%p)->(%p)\n", This, pnPriority);
 
@@ -149,7 +146,7 @@ static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallbackEx *ifac
 
 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallbackEx *iface, DWORD reserved)
 {
-    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
 
     TRACE("(%p)->(%d)\n", This, reserved);
 
@@ -159,7 +156,7 @@ static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallbackEx *if
 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallbackEx *iface, ULONG ulProgress,
         ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
 {
-    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
 
     TRACE("%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode,
             debugstr_w(szStatusText));
@@ -171,7 +168,7 @@ static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallbackEx *iface
 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallbackEx *iface,
         HRESULT hresult, LPCWSTR szError)
 {
-    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
 
     TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
 
@@ -181,7 +178,7 @@ static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallbackEx *if
 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallbackEx *iface,
         DWORD *grfBINDF, BINDINFO *pbindinfo)
 {
-    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
     IBindStatusCallbackEx *bscex;
     HRESULT hres;
 
@@ -203,7 +200,7 @@ static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallbackEx *ifac
 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallbackEx *iface,
         DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
 {
-    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
 
     TRACE("(%p)->(%08x %d %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed);
 
@@ -213,7 +210,7 @@ static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallbackEx *
 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallbackEx *iface,
         REFIID riid, IUnknown *punk)
 {
-    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
 
     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk);
 
@@ -223,7 +220,7 @@ static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallbackEx
 static HRESULT WINAPI BindStatusCallback_GetBindInfoEx(IBindStatusCallbackEx *iface, DWORD *grfBINDF,
         BINDINFO *pbindinfo, DWORD *grfBINDF2, DWORD *pdwReserved)
 {
-    BindStatusCallback *This = STATUSCLB_THIS(iface);
+    BindStatusCallback *This = impl_from_IBindStatusCallbackEx(iface);
     IBindStatusCallbackEx *bscex;
     HRESULT hres;
 
@@ -240,8 +237,6 @@ static HRESULT WINAPI BindStatusCallback_GetBindInfoEx(IBindStatusCallbackEx *if
     return hres;
 }
 
-#undef STATUSCLB_THIS
-
 static const IBindStatusCallbackExVtbl BindStatusCallbackExVtbl = {
     BindStatusCallback_QueryInterface,
     BindStatusCallback_AddRef,
@@ -257,46 +252,49 @@ static const IBindStatusCallbackExVtbl BindStatusCallbackExVtbl = {
     BindStatusCallback_GetBindInfoEx
 };
 
-#define SERVPROV_THIS(iface) DEFINE_THIS(BindStatusCallback, ServiceProvider, iface)
+static inline BindStatusCallback *impl_from_IServiceProvider(IServiceProvider *iface)
+{
+    return CONTAINING_RECORD(iface, BindStatusCallback, IServiceProvider_iface);
+}
 
 static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface,
         REFIID riid, void **ppv)
 {
-    BindStatusCallback *This = SERVPROV_THIS(iface);
-    return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
+    BindStatusCallback *This = impl_from_IServiceProvider(iface);
+    return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
 }
 
 static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface)
 {
-    BindStatusCallback *This = SERVPROV_THIS(iface);
-    return IBindStatusCallback_AddRef(STATUSCLB(This));
+    BindStatusCallback *This = impl_from_IServiceProvider(iface);
+    return IBindStatusCallback_AddRef(&This->IBindStatusCallbackEx_iface);
 }
 
 static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface)
 {
-    BindStatusCallback *This = SERVPROV_THIS(iface);
-    return IBindStatusCallback_Release(STATUSCLB(This));
+    BindStatusCallback *This = impl_from_IServiceProvider(iface);
+    return IBindStatusCallback_Release(&This->IBindStatusCallbackEx_iface);
 }
 
 static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface,
         REFGUID guidService, REFIID riid, void **ppv)
 {
-    BindStatusCallback *This = SERVPROV_THIS(iface);
+    BindStatusCallback *This = impl_from_IServiceProvider(iface);
     HRESULT hres;
 
     if(IsEqualGUID(&IID_IHttpNegotiate, guidService)) {
         TRACE("(%p)->(IID_IHttpNegotiate %s %p)\n", This, debugstr_guid(riid), ppv);
-        return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
+        return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
     }
 
     if(IsEqualGUID(&IID_IHttpNegotiate2, guidService)) {
         TRACE("(%p)->(IID_IHttpNegotiate2 %s %p)\n", This, debugstr_guid(riid), ppv);
-        return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
+        return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
     }
 
     if(IsEqualGUID(&IID_IAuthenticate, guidService)) {
         TRACE("(%p)->(IID_IAuthenticate %s %p)\n", This, debugstr_guid(riid), ppv);
-        return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
+        return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
     }
 
     TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
@@ -314,8 +312,6 @@ static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface,
     return E_NOINTERFACE;
 }
 
-#undef SERVPROV_THIS
-
 static const IServiceProviderVtbl BSCServiceProviderVtbl = {
     BSCServiceProvider_QueryInterface,
     BSCServiceProvider_AddRef,
@@ -323,31 +319,34 @@ static const IServiceProviderVtbl BSCServiceProviderVtbl = {
     BSCServiceProvider_QueryService
 };
 
-#define HTTPNEG2_THIS(iface) DEFINE_THIS(BindStatusCallback, HttpNegotiate2, iface)
+static inline BindStatusCallback *impl_from_IHttpNegotiate2(IHttpNegotiate2 *iface)
+{
+    return CONTAINING_RECORD(iface, BindStatusCallback, IHttpNegotiate2_iface);
+}
 
 static HRESULT WINAPI BSCHttpNegotiate_QueryInterface(IHttpNegotiate2 *iface,
         REFIID riid, void **ppv)
 {
-    BindStatusCallback *This = HTTPNEG2_THIS(iface);
-    return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv);
+    BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
+    return IBindStatusCallback_QueryInterface(&This->IBindStatusCallbackEx_iface, riid, ppv);
 }
 
 static ULONG WINAPI BSCHttpNegotiate_AddRef(IHttpNegotiate2 *iface)
 {
-    BindStatusCallback *This = HTTPNEG2_THIS(iface);
-    return IBindStatusCallback_AddRef(STATUSCLB(This));
+    BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
+    return IBindStatusCallback_AddRef(&This->IBindStatusCallbackEx_iface);
 }
 
 static ULONG WINAPI BSCHttpNegotiate_Release(IHttpNegotiate2 *iface)
 {
-    BindStatusCallback *This = HTTPNEG2_THIS(iface);
-    return IBindStatusCallback_Release(STATUSCLB(This));
+    BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
+    return IBindStatusCallback_Release(&This->IBindStatusCallbackEx_iface);
 }
 
 static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface,
         LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
 {
-    BindStatusCallback *This = HTTPNEG2_THIS(iface);
+    BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
     IHttpNegotiate *http_negotiate;
     HRESULT hres = S_OK;
 
@@ -370,7 +369,7 @@ static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD
         LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders,
         LPWSTR *pszAdditionalRequestHeaders)
 {
-    BindStatusCallback *This = HTTPNEG2_THIS(iface);
+    BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
     LPWSTR additional_headers = NULL;
     IHttpNegotiate *http_negotiate;
     HRESULT hres = S_OK;
@@ -396,7 +395,7 @@ static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD
 static HRESULT WINAPI BSCHttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
         BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved)
 {
-    BindStatusCallback *This = HTTPNEG2_THIS(iface);
+    BindStatusCallback *This = impl_from_IHttpNegotiate2(iface);
     IHttpNegotiate2 *http_negotiate2;
     HRESULT hres = E_FAIL;
 
@@ -412,8 +411,6 @@ static HRESULT WINAPI BSCHttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface,
     return hres;
 }
 
-#undef HTTPNEG2_THIS
-
 static const IHttpNegotiate2Vtbl BSCHttpNegotiateVtbl = {
     BSCHttpNegotiate_QueryInterface,
     BSCHttpNegotiate_AddRef,
@@ -423,36 +420,37 @@ static const IHttpNegotiate2Vtbl BSCHttpNegotiateVtbl = {
     BSCHttpNegotiate_GetRootSecurityId
 };
 
-#define AUTHENTICATE_THIS(iface)  DEFINE_THIS(BindStatusCallback, Authenticate, iface)
+static inline BindStatusCallback *impl_from_IAuthenticate(IAuthenticate *iface)
+{
+    return CONTAINING_RECORD(iface, BindStatusCallback, IAuthenticate_iface);
+}
 
 static HRESULT WINAPI BSCAuthenticate_QueryInterface(IAuthenticate *iface, REFIID riid, void **ppv)
 {
-    BindStatusCallback *This = AUTHENTICATE_THIS(iface);
-    return IBindStatusCallback_QueryInterface(AUTHENTICATE(This), riid, ppv);
+    BindStatusCallback *This = impl_from_IAuthenticate(iface);
+    return IBindStatusCallback_QueryInterface(&This->IAuthenticate_iface, riid, ppv);
 }
 
 static ULONG WINAPI BSCAuthenticate_AddRef(IAuthenticate *iface)
 {
-    BindStatusCallback *This = AUTHENTICATE_THIS(iface);
-    return IBindStatusCallback_AddRef(STATUSCLB(This));
+    BindStatusCallback *This = impl_from_IAuthenticate(iface);
+    return IBindStatusCallback_AddRef(&This->IBindStatusCallbackEx_iface);
 }
 
 static ULONG WINAPI BSCAuthenticate_Release(IAuthenticate *iface)
 {
-    BindStatusCallback *This = AUTHENTICATE_THIS(iface);
-    return IBindStatusCallback_Release(STATUSCLB(This));
+    BindStatusCallback *This = impl_from_IAuthenticate(iface);
+    return IBindStatusCallback_Release(&This->IBindStatusCallbackEx_iface);
 }
 
 static HRESULT WINAPI BSCAuthenticate_Authenticate(IAuthenticate *iface,
         HWND *phwnd, LPWSTR *pszUsername, LPWSTR *pszPassword)
 {
-    BindStatusCallback *This = AUTHENTICATE_THIS(iface);
+    BindStatusCallback *This = impl_from_IAuthenticate(iface);
     FIXME("(%p)->(%p %p %p)\n", This, phwnd, pszUsername, pszPassword);
     return E_NOTIMPL;
 }
 
-#undef AUTHENTICATE_THIS
-
 static const IAuthenticateVtbl BSCAuthenticateVtbl = {
     BSCAuthenticate_QueryInterface,
     BSCAuthenticate_AddRef,
@@ -485,15 +483,15 @@ HRESULT wrap_callback(IBindStatusCallback *bsc, IBindStatusCallback **ret_iface)
     if(!ret)
         return E_OUTOFMEMORY;
 
-    ret->lpBindStatusCallbackExVtbl = &BindStatusCallbackExVtbl;
-    ret->lpServiceProviderVtbl    = &BSCServiceProviderVtbl;
-    ret->lpHttpNegotiate2Vtbl     = &BSCHttpNegotiateVtbl;
-    ret->lpAuthenticateVtbl       = &BSCAuthenticateVtbl;
+    ret->IBindStatusCallbackEx_iface.lpVtbl = &BindStatusCallbackExVtbl;
+    ret->IServiceProvider_iface.lpVtbl = &BSCServiceProviderVtbl;
+    ret->IHttpNegotiate2_iface.lpVtbl = &BSCHttpNegotiateVtbl;
+    ret->IAuthenticate_iface.lpVtbl = &BSCAuthenticateVtbl;
 
     ret->ref = 1;
     set_callback(ret, bsc);
 
-    *ret_iface = STATUSCLB(ret);
+    *ret_iface = (IBindStatusCallback*)&ret->IBindStatusCallbackEx_iface;
     return S_OK;
 }
 
@@ -541,7 +539,7 @@ HRESULT WINAPI RegisterBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pb
                 set_callback(holder, pbsc);
 
                 IBindStatusCallback_Release(bsc);
-                IBindStatusCallback_Release(STATUSCLB(holder));
+                IBindStatusCallback_Release(&holder->IBindStatusCallbackEx_iface);
                 return S_OK;
             }else {
                 prev = bsc;
@@ -605,7 +603,7 @@ HRESULT WINAPI RevokeBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc
     if(SUCCEEDED(hres)) {
         if(pbsc == holder->callback)
             dorevoke = TRUE;
-        IBindStatusCallback_Release(STATUSCLB(holder));
+        IBindStatusCallback_Release(&holder->IBindStatusCallbackEx_iface);
     }else if(pbsc == callback) {
         dorevoke = TRUE;
     }
@@ -618,32 +616,33 @@ HRESULT WINAPI RevokeBindStatusCallback(IBindCtx *pbc, IBindStatusCallback *pbsc
 }
 
 typedef struct {
-    const IBindCtxVtbl *lpBindCtxVtbl;
+    IBindCtx IBindCtx_iface;
 
     LONG ref;
 
     IBindCtx *bindctx;
 } AsyncBindCtx;
 
-#define BINDCTX(x)  ((IBindCtx*)  &(x)->lpBindCtxVtbl)
-
-#define BINDCTX_THIS(iface) DEFINE_THIS(AsyncBindCtx, BindCtx, iface)
+static inline AsyncBindCtx *impl_from_IBindCtx(IBindCtx *iface)
+{
+    return CONTAINING_RECORD(iface, AsyncBindCtx, IBindCtx_iface);
+}
 
 static HRESULT WINAPI AsyncBindCtx_QueryInterface(IBindCtx *iface, REFIID riid, void **ppv)
 {
-    AsyncBindCtx *This = BINDCTX_THIS(iface);
+    AsyncBindCtx *This = impl_from_IBindCtx(iface);
 
     *ppv = NULL;
 
     if(IsEqualGUID(riid, &IID_IUnknown)) {
         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
-        *ppv = BINDCTX(This);
+        *ppv = &This->IBindCtx_iface;
     }else if(IsEqualGUID(riid, &IID_IBindCtx)) {
         TRACE("(%p)->(IID_IBindCtx %p)\n", This, ppv);
-        *ppv = BINDCTX(This);
+        *ppv = &This->IBindCtx_iface;
     }else if(IsEqualGUID(riid, &IID_IAsyncBindCtx)) {
         TRACE("(%p)->(IID_IAsyncBindCtx %p)\n", This, ppv);
-        *ppv = BINDCTX(This);
+        *ppv = &This->IBindCtx_iface;
     }
 
     if(*ppv) {
@@ -657,7 +656,7 @@ static HRESULT WINAPI AsyncBindCtx_QueryInterface(IBindCtx *iface, REFIID riid,
 
 static ULONG WINAPI AsyncBindCtx_AddRef(IBindCtx *iface)
 {
-    AsyncBindCtx *This = BINDCTX_THIS(iface);
+    AsyncBindCtx *This = impl_from_IBindCtx(iface);
     LONG ref = InterlockedIncrement(&This->ref);
 
     TRACE("(%p) ref=%d\n", This, ref);
@@ -667,7 +666,7 @@ static ULONG WINAPI AsyncBindCtx_AddRef(IBindCtx *iface)
 
 static ULONG WINAPI AsyncBindCtx_Release(IBindCtx *iface)
 {
-    AsyncBindCtx *This = BINDCTX_THIS(iface);
+    AsyncBindCtx *This = impl_from_IBindCtx(iface);
     LONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) ref=%d\n", This, ref);
@@ -682,7 +681,7 @@ static ULONG WINAPI AsyncBindCtx_Release(IBindCtx *iface)
 
 static HRESULT WINAPI AsyncBindCtx_RegisterObjectBound(IBindCtx *iface, IUnknown *punk)
 {
-    AsyncBindCtx *This = BINDCTX_THIS(iface);
+    AsyncBindCtx *This = impl_from_IBindCtx(iface);
 
     TRACE("(%p)->(%p)\n", This, punk);
 
@@ -691,7 +690,7 @@ static HRESULT WINAPI AsyncBindCtx_RegisterObjectBound(IBindCtx *iface, IUnknown
 
 static HRESULT WINAPI AsyncBindCtx_RevokeObjectBound(IBindCtx *iface, IUnknown *punk)
 {
-    AsyncBindCtx *This = BINDCTX_THIS(iface);
+    AsyncBindCtx *This = impl_from_IBindCtx(iface);
 
     TRACE("(%p %p)\n", This, punk);
 
@@ -700,7 +699,7 @@ static HRESULT WINAPI AsyncBindCtx_RevokeObjectBound(IBindCtx *iface, IUnknown *
 
 static HRESULT WINAPI AsyncBindCtx_ReleaseBoundObjects(IBindCtx *iface)
 {
-    AsyncBindCtx *This = BINDCTX_THIS(iface);
+    AsyncBindCtx *This = impl_from_IBindCtx(iface);
 
     TRACE("(%p)\n", This);
 
@@ -709,7 +708,7 @@ static HRESULT WINAPI AsyncBindCtx_ReleaseBoundObjects(IBindCtx *iface)
 
 static HRESULT WINAPI AsyncBindCtx_SetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts)
 {
-    AsyncBindCtx *This = BINDCTX_THIS(iface);
+    AsyncBindCtx *This = impl_from_IBindCtx(iface);
 
     TRACE("(%p)->(%p)\n", This, pbindopts);
 
@@ -718,7 +717,7 @@ static HRESULT WINAPI AsyncBindCtx_SetBindOptions(IBindCtx *iface, BIND_OPTS *pb
 
 static HRESULT WINAPI AsyncBindCtx_GetBindOptions(IBindCtx *iface, BIND_OPTS *pbindopts)
 {
-    AsyncBindCtx *This = BINDCTX_THIS(iface);
+    AsyncBindCtx *This = impl_from_IBindCtx(iface);
 
     TRACE("(%p)->(%p)\n", This, pbindopts);
 
@@ -727,7 +726,7 @@ static HRESULT WINAPI AsyncBindCtx_GetBindOptions(IBindCtx *iface, BIND_OPTS *pb
 
 static HRESULT WINAPI AsyncBindCtx_GetRunningObjectTable(IBindCtx *iface, IRunningObjectTable **pprot)
 {
-    AsyncBindCtx *This = BINDCTX_THIS(iface);
+    AsyncBindCtx *This = impl_from_IBindCtx(iface);
 
     TRACE("(%p)->(%p)\n", This, pprot);
 
@@ -736,7 +735,7 @@ static HRESULT WINAPI AsyncBindCtx_GetRunningObjectTable(IBindCtx *iface, IRunni
 
 static HRESULT WINAPI AsyncBindCtx_RegisterObjectParam(IBindCtx *iface, LPOLESTR pszkey, IUnknown *punk)
 {
-    AsyncBindCtx *This = BINDCTX_THIS(iface);
+    AsyncBindCtx *This = impl_from_IBindCtx(iface);
 
     TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk);
 
@@ -745,7 +744,7 @@ static HRESULT WINAPI AsyncBindCtx_RegisterObjectParam(IBindCtx *iface, LPOLESTR
 
 static HRESULT WINAPI AsyncBindCtx_GetObjectParam(IBindCtx* iface, LPOLESTR pszkey, IUnknown **punk)
 {
-    AsyncBindCtx *This = BINDCTX_THIS(iface);
+    AsyncBindCtx *This = impl_from_IBindCtx(iface);
 
     TRACE("(%p)->(%s %p)\n", This, debugstr_w(pszkey), punk);
 
@@ -754,7 +753,7 @@ static HRESULT WINAPI AsyncBindCtx_GetObjectParam(IBindCtx* iface, LPOLESTR pszk
 
 static HRESULT WINAPI AsyncBindCtx_RevokeObjectParam(IBindCtx *iface, LPOLESTR pszkey)
 {
-    AsyncBindCtx *This = BINDCTX_THIS(iface);
+    AsyncBindCtx *This = impl_from_IBindCtx(iface);
 
     TRACE("(%p)->(%s)\n", This, debugstr_w(pszkey));
 
@@ -763,15 +762,13 @@ static HRESULT WINAPI AsyncBindCtx_RevokeObjectParam(IBindCtx *iface, LPOLESTR p
 
 static HRESULT WINAPI AsyncBindCtx_EnumObjectParam(IBindCtx *iface, IEnumString **pszkey)
 {
-    AsyncBindCtx *This = BINDCTX_THIS(iface);
+    AsyncBindCtx *This = impl_from_IBindCtx(iface);
 
     TRACE("(%p)->(%p)\n", This, pszkey);
 
     return IBindCtx_EnumObjectParam(This->bindctx, pszkey);
 }
 
-#undef BINDCTX_THIS
-
 static const IBindCtxVtbl AsyncBindCtxVtbl =
 {
     AsyncBindCtx_QueryInterface,
@@ -878,16 +875,16 @@ HRESULT WINAPI CreateAsyncBindCtxEx(IBindCtx *ibind, DWORD options,
 
     ret = heap_alloc(sizeof(AsyncBindCtx));
 
-    ret->lpBindCtxVtbl = &AsyncBindCtxVtbl;
+    ret->IBindCtx_iface.lpVtbl = &AsyncBindCtxVtbl;
     ret->ref = 1;
     ret->bindctx = bindctx;
 
-    hres = init_bindctx(BINDCTX(ret), options, callback, format);
+    hres = init_bindctx(&ret->IBindCtx_iface, options, callback, format);
     if(FAILED(hres)) {
-        IBindCtx_Release(BINDCTX(ret));
+        IBindCtx_Release(&ret->IBindCtx_iface);
         return hres;
     }
 
-    *pbind = BINDCTX(ret);
+    *pbind = &ret->IBindCtx_iface;
     return S_OK;
 }
index 699bf98..5504f6f 100644 (file)
@@ -27,27 +27,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
 static WCHAR cbinding_contextW[] = {'C','B','i','n','d','i','n','g',' ','C','o','n','t','e','x','t',0};
 static WCHAR bscb_holderW[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
 
-typedef struct Binding Binding;
-
-struct _task_header_t;
-
-typedef void (*task_proc_t)(Binding*, struct _task_header_t*);
-
-typedef struct _task_header_t {
-    task_proc_t proc;
-    struct _task_header_t *next;
-} task_header_t;
-
 typedef struct {
-    const IUnknownVtbl *lpUnknownVtbl;
+    IUnknown IUnknown_iface;
 
     LONG ref;
 
     IInternetProtocolEx *protocol;
 
-    BYTE buf[1024*8];
-    DWORD size;
-    BOOL init;
     HANDLE file;
     HRESULT hres;
 
@@ -66,8 +52,6 @@ struct _stgmed_obj_t {
     const stgmed_obj_vtbl *vtbl;
 };
 
-#define STGMEDUNK(x)  ((IUnknown*) &(x)->lpUnknownVtbl)
-
 typedef enum {
     BEFORE_DOWNLOAD,
     DOWNLOADING,
@@ -79,19 +63,20 @@ typedef enum {
 #define BINDING_OBJAVAIL  0x0004
 #define BINDING_ABORTED   0x0008
 
-struct Binding {
-    const IBindingVtbl               *lpBindingVtbl;
-    const IInternetProtocolSinkVtbl  *lpIInternetProtocolSinkVtbl;
-    const IInternetBindInfoVtbl      *lpInternetBindInfoVtbl;
-    const IWinInetHttpInfoVtbl       *lpWinInetHttpInfoVtbl;
-    const IServiceProviderVtbl       *lpServiceProviderVtbl;
+typedef struct {
+    IBinding              IBinding_iface;
+    IInternetProtocolSink IInternetProtocolSink_iface;
+    IInternetBindInfo     IInternetBindInfo_iface;
+    IWinInetHttpInfo      IWinInetHttpInfo_iface;
+    IServiceProvider      IServiceProvider_iface;
 
     LONG ref;
 
     IBindStatusCallback *callback;
-    IInternetProtocolEx *protocol;
     IServiceProvider *service_provider;
 
+    BindProtocol *protocol;
+
     stgmed_buf_t *stgmed_buf;
     stgmed_obj_t *stgmed_obj;
 
@@ -114,29 +99,7 @@ struct Binding {
     HWND notif_hwnd;
 
     CRITICAL_SECTION section;
-};
-
-#define BINDING(x)   ((IBinding*)               &(x)->lpBindingVtbl)
-#define BINDINF(x)   ((IInternetBindInfo*)      &(x)->lpInternetBindInfoVtbl)
-#define INETINFO(x)  ((IWinInetHttpInfo*)       &(x)->lpWinInetHttpInfoVtbl)
-#define SERVPROV(x)  ((IServiceProvider*)       &(x)->lpServiceProviderVtbl)
-
-#define STREAM(x) ((IStream*) &(x)->lpStreamVtbl)
-#define HTTPNEG2(x) ((IHttpNegotiate2*) &(x)->lpHttpNegotiate2Vtbl)
-
-static void fill_stgmed_buffer(stgmed_buf_t *buf)
-{
-    DWORD read = 0;
-
-    if(sizeof(buf->buf) == buf->size)
-        return;
-
-    buf->hres = IInternetProtocol_Read(buf->protocol, buf->buf+buf->size,
-            sizeof(buf->buf)-buf->size, &read);
-    buf->size += read;
-    if(read > 0)
-        buf->init = TRUE;
-}
+} Binding;
 
 static void read_protocol_data(stgmed_buf_t *stgmed_buf)
 {
@@ -144,10 +107,6 @@ static void read_protocol_data(stgmed_buf_t *stgmed_buf)
     DWORD read;
     HRESULT hres;
 
-    fill_stgmed_buffer(stgmed_buf);
-    if(stgmed_buf->size < sizeof(stgmed_buf->buf))
-        return;
-
     do hres = IInternetProtocol_Read(stgmed_buf->protocol, buf, sizeof(buf), &read);
     while(hres == S_OK);
 }
@@ -212,7 +171,7 @@ static void mime_available(Binding *This, LPCWSTR mime)
 static void stop_binding(Binding *binding, HRESULT hres, LPCWSTR str)
 {
     if(binding->state & BINDING_LOCKED) {
-        IInternetProtocol_UnlockRequest(binding->protocol);
+        IInternetProtocolEx_UnlockRequest(&binding->protocol->IInternetProtocolEx_iface);
         binding->state &= ~BINDING_LOCKED;
     }
 
@@ -281,7 +240,7 @@ static void load_doc_mon(Binding *binding, IPersistMoniker *persist)
     }
 
     IBindCtx_RevokeObjectParam(bctx, bscb_holderW);
-    IBindCtx_RegisterObjectParam(bctx, cbinding_contextW, (IUnknown*)BINDING(binding));
+    IBindCtx_RegisterObjectParam(bctx, cbinding_contextW, (IUnknown*)&binding->IBinding_iface);
 
     hres = IPersistMoniker_Load(persist, binding->download_state == END_DOWNLOAD, binding->mon, bctx, 0x12);
     IBindCtx_RevokeObjectParam(bctx, cbinding_contextW);
@@ -354,7 +313,7 @@ static void create_object(Binding *binding)
 
     stop_binding(binding, hres, NULL);
     if(FAILED(hres))
-        IInternetProtocol_Terminate(binding->protocol, 0);
+        IInternetProtocolEx_Terminate(&binding->protocol->IInternetProtocolEx_iface, 0);
 }
 
 static void cache_file_available(Binding *This, const WCHAR *file_name)
@@ -370,19 +329,22 @@ static void cache_file_available(Binding *This, const WCHAR *file_name)
     }
 }
 
-#define STGMEDUNK_THIS(iface) DEFINE_THIS(stgmed_buf_t, Unknown, iface)
+static inline stgmed_buf_t *impl_from_IUnknown(IUnknown *iface)
+{
+    return CONTAINING_RECORD(iface, stgmed_buf_t, IUnknown_iface);
+}
 
 static HRESULT WINAPI StgMedUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
 {
-    stgmed_buf_t *This = STGMEDUNK_THIS(iface);
+    stgmed_buf_t *This = impl_from_IUnknown(iface);
 
     *ppv = NULL;
 
     if(IsEqualGUID(riid, &IID_IUnknown)) {
         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
 
-        *ppv = STGMEDUNK(This);
-        IUnknown_AddRef(STGMEDUNK(This));
+        *ppv = &This->IUnknown_iface;
+        IUnknown_AddRef(&This->IUnknown_iface);
         return S_OK;
     }
 
@@ -392,7 +354,7 @@ static HRESULT WINAPI StgMedUnk_QueryInterface(IUnknown *iface, REFIID riid, voi
 
 static ULONG WINAPI StgMedUnk_AddRef(IUnknown *iface)
 {
-    stgmed_buf_t *This = STGMEDUNK_THIS(iface);
+    stgmed_buf_t *This = impl_from_IUnknown(iface);
     LONG ref = InterlockedIncrement(&This->ref);
 
     TRACE("(%p) ref=%d\n", This, ref);
@@ -402,7 +364,7 @@ static ULONG WINAPI StgMedUnk_AddRef(IUnknown *iface)
 
 static ULONG WINAPI StgMedUnk_Release(IUnknown *iface)
 {
-    stgmed_buf_t *This = STGMEDUNK_THIS(iface);
+    stgmed_buf_t *This = impl_from_IUnknown(iface);
     LONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) ref=%d\n", This, ref);
@@ -420,8 +382,6 @@ static ULONG WINAPI StgMedUnk_Release(IUnknown *iface)
     return ref;
 }
 
-#undef STGMEDUNK_THIS
-
 static const IUnknownVtbl StgMedUnkVtbl = {
     StgMedUnk_QueryInterface,
     StgMedUnk_AddRef,
@@ -432,10 +392,8 @@ static stgmed_buf_t *create_stgmed_buf(IInternetProtocolEx *protocol)
 {
     stgmed_buf_t *ret = heap_alloc(sizeof(*ret));
 
-    ret->lpUnknownVtbl = &StgMedUnkVtbl;
+    ret->IUnknown_iface.lpVtbl = &StgMedUnkVtbl;
     ret->ref = 1;
-    ret->size = 0;
-    ret->init = FALSE;
     ret->file = INVALID_HANDLE_VALUE;
     ret->hres = S_OK;
     ret->cache_file = NULL;
@@ -450,35 +408,38 @@ static stgmed_buf_t *create_stgmed_buf(IInternetProtocolEx *protocol)
 
 typedef struct {
     stgmed_obj_t stgmed_obj;
-    const IStreamVtbl *lpStreamVtbl;
+    IStream IStream_iface;
 
     LONG ref;
 
     stgmed_buf_t *buf;
 } ProtocolStream;
 
-#define STREAM_THIS(iface) DEFINE_THIS(ProtocolStream, Stream, iface)
+static inline ProtocolStream *impl_from_IStream(IStream *iface)
+{
+    return CONTAINING_RECORD(iface, ProtocolStream, IStream_iface);
+}
 
 static HRESULT WINAPI ProtocolStream_QueryInterface(IStream *iface,
                                                           REFIID riid, void **ppv)
 {
-    ProtocolStream *This = STREAM_THIS(iface);
+    ProtocolStream *This = impl_from_IStream(iface);
 
     *ppv = NULL;
 
     if(IsEqualGUID(&IID_IUnknown, riid)) {
         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
-        *ppv = STREAM(This);
+        *ppv = &This->IStream_iface;
     }else if(IsEqualGUID(&IID_ISequentialStream, riid)) {
         TRACE("(%p)->(IID_ISequentialStream %p)\n", This, ppv);
-        *ppv = STREAM(This);
+        *ppv = &This->IStream_iface;
     }else if(IsEqualGUID(&IID_IStream, riid)) {
         TRACE("(%p)->(IID_IStream %p)\n", This, ppv);
-        *ppv = STREAM(This);
+        *ppv = &This->IStream_iface;
     }
 
     if(*ppv) {
-        IStream_AddRef(STREAM(This));
+        IStream_AddRef(&This->IStream_iface);
         return S_OK;
     }
 
@@ -488,7 +449,7 @@ static HRESULT WINAPI ProtocolStream_QueryInterface(IStream *iface,
 
 static ULONG WINAPI ProtocolStream_AddRef(IStream *iface)
 {
-    ProtocolStream *This = STREAM_THIS(iface);
+    ProtocolStream *This = impl_from_IStream(iface);
     LONG ref = InterlockedIncrement(&This->ref);
 
     TRACE("(%p) ref=%d\n", This, ref);
@@ -498,13 +459,13 @@ static ULONG WINAPI ProtocolStream_AddRef(IStream *iface)
 
 static ULONG WINAPI ProtocolStream_Release(IStream *iface)
 {
-    ProtocolStream *This = STREAM_THIS(iface);
+    ProtocolStream *This = impl_from_IStream(iface);
     LONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) ref=%d\n", This, ref);
 
     if(!ref) {
-        IUnknown_Release(STGMEDUNK(This->buf));
+        IUnknown_Release(&This->buf->IUnknown_iface);
         heap_free(This);
 
         URLMON_UnlockModule();
@@ -516,56 +477,33 @@ static ULONG WINAPI ProtocolStream_Release(IStream *iface)
 static HRESULT WINAPI ProtocolStream_Read(IStream *iface, void *pv,
                                           ULONG cb, ULONG *pcbRead)
 {
-    ProtocolStream *This = STREAM_THIS(iface);
-    DWORD read = 0, pread = 0;
+    ProtocolStream *This = impl_from_IStream(iface);
+    DWORD read = 0;
     HRESULT hres;
 
     TRACE("(%p)->(%p %d %p)\n", This, pv, cb, pcbRead);
 
-    if(This->buf->file != INVALID_HANDLE_VALUE) {
-        if (!ReadFile(This->buf->file, pv, cb, &read, NULL))
-            return INET_E_DOWNLOAD_FAILURE;
-
-        if(pcbRead)
-            *pcbRead = read;
-        return read ? S_OK : S_FALSE;
-    }
-
-    if(This->buf->size) {
-        read = cb;
-
-        if(read > This->buf->size)
-            read = This->buf->size;
-
-        memcpy(pv, This->buf->buf, read);
-
-        if(read < This->buf->size)
-            memmove(This->buf->buf, This->buf->buf+read, This->buf->size-read);
-        This->buf->size -= read;
-    }
-
-    if(read == cb) {
-        if (pcbRead)
-            *pcbRead = read;
-        return S_OK;
+    if(This->buf->file == INVALID_HANDLE_VALUE) {
+        hres = This->buf->hres = IInternetProtocol_Read(This->buf->protocol, (PBYTE)pv, cb, &read);
+    }else {
+        hres = ReadFile(This->buf->file, pv, cb, &read, NULL) ? S_OK : INET_E_DOWNLOAD_FAILURE;
     }
 
-    hres = This->buf->hres = IInternetProtocol_Read(This->buf->protocol, (PBYTE)pv+read, cb-read, &pread);
     if (pcbRead)
-        *pcbRead = read + pread;
+        *pcbRead = read;
 
     if(hres == E_PENDING)
         return E_PENDING;
     else if(FAILED(hres))
         FIXME("Read failed: %08x\n", hres);
 
-    return read || pread ? S_OK : S_FALSE;
+    return read ? S_OK : S_FALSE;
 }
 
 static HRESULT WINAPI ProtocolStream_Write(IStream *iface, const void *pv,
                                           ULONG cb, ULONG *pcbWritten)
 {
-    ProtocolStream *This = STREAM_THIS(iface);
+    ProtocolStream *This = impl_from_IStream(iface);
 
     TRACE("(%p)->(%p %d %p)\n", This, pv, cb, pcbWritten);
 
@@ -575,14 +513,14 @@ static HRESULT WINAPI ProtocolStream_Write(IStream *iface, const void *pv,
 static HRESULT WINAPI ProtocolStream_Seek(IStream *iface, LARGE_INTEGER dlibMove,
                                          DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
 {
-    ProtocolStream *This = STREAM_THIS(iface);
+    ProtocolStream *This = impl_from_IStream(iface);
     FIXME("(%p)->(%d %08x %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI ProtocolStream_SetSize(IStream *iface, ULARGE_INTEGER libNewSize)
 {
-    ProtocolStream *This = STREAM_THIS(iface);
+    ProtocolStream *This = impl_from_IStream(iface);
     FIXME("(%p)->(%d)\n", This, libNewSize.u.LowPart);
     return E_NOTIMPL;
 }
@@ -590,14 +528,14 @@ static HRESULT WINAPI ProtocolStream_SetSize(IStream *iface, ULARGE_INTEGER libN
 static HRESULT WINAPI ProtocolStream_CopyTo(IStream *iface, IStream *pstm,
         ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten)
 {
-    ProtocolStream *This = STREAM_THIS(iface);
+    ProtocolStream *This = impl_from_IStream(iface);
     FIXME("(%p)->(%p %d %p %p)\n", This, pstm, cb.u.LowPart, pcbRead, pcbWritten);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI ProtocolStream_Commit(IStream *iface, DWORD grfCommitFlags)
 {
-    ProtocolStream *This = STREAM_THIS(iface);
+    ProtocolStream *This = impl_from_IStream(iface);
 
     TRACE("(%p)->(%08x)\n", This, grfCommitFlags);
 
@@ -606,7 +544,7 @@ static HRESULT WINAPI ProtocolStream_Commit(IStream *iface, DWORD grfCommitFlags
 
 static HRESULT WINAPI ProtocolStream_Revert(IStream *iface)
 {
-    ProtocolStream *This = STREAM_THIS(iface);
+    ProtocolStream *This = impl_from_IStream(iface);
 
     TRACE("(%p)\n", This);
 
@@ -616,7 +554,7 @@ static HRESULT WINAPI ProtocolStream_Revert(IStream *iface)
 static HRESULT WINAPI ProtocolStream_LockRegion(IStream *iface, ULARGE_INTEGER libOffset,
                                                ULARGE_INTEGER cb, DWORD dwLockType)
 {
-    ProtocolStream *This = STREAM_THIS(iface);
+    ProtocolStream *This = impl_from_IStream(iface);
     FIXME("(%p)->(%d %d %d)\n", This, libOffset.u.LowPart, cb.u.LowPart, dwLockType);
     return E_NOTIMPL;
 }
@@ -624,7 +562,7 @@ static HRESULT WINAPI ProtocolStream_LockRegion(IStream *iface, ULARGE_INTEGER l
 static HRESULT WINAPI ProtocolStream_UnlockRegion(IStream *iface,
         ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType)
 {
-    ProtocolStream *This = STREAM_THIS(iface);
+    ProtocolStream *This = impl_from_IStream(iface);
     FIXME("(%p)->(%d %d %d)\n", This, libOffset.u.LowPart, cb.u.LowPart, dwLockType);
     return E_NOTIMPL;
 }
@@ -632,7 +570,7 @@ static HRESULT WINAPI ProtocolStream_UnlockRegion(IStream *iface,
 static HRESULT WINAPI ProtocolStream_Stat(IStream *iface, STATSTG *pstatstg,
                                          DWORD dwStatFlag)
 {
-    ProtocolStream *This = STREAM_THIS(iface);
+    ProtocolStream *This = impl_from_IStream(iface);
     TRACE("(%p)->(%p %08x)\n", This, pstatstg, dwStatFlag);
 
     if(!pstatstg)
@@ -661,13 +599,11 @@ static HRESULT WINAPI ProtocolStream_Stat(IStream *iface, STATSTG *pstatstg,
 
 static HRESULT WINAPI ProtocolStream_Clone(IStream *iface, IStream **ppstm)
 {
-    ProtocolStream *This = STREAM_THIS(iface);
+    ProtocolStream *This = impl_from_IStream(iface);
     FIXME("(%p)->(%p)\n", This, ppstm);
     return E_NOTIMPL;
 }
 
-#undef STREAM_THIS
-
 static const IStreamVtbl ProtocolStreamVtbl = {
     ProtocolStream_QueryInterface,
     ProtocolStream_AddRef,
@@ -688,7 +624,7 @@ static const IStreamVtbl ProtocolStreamVtbl = {
 static void stgmed_stream_release(stgmed_obj_t *obj)
 {
     ProtocolStream *stream = (ProtocolStream*)obj;
-    IStream_Release(STREAM(stream));
+    IStream_Release(&stream->IStream_iface);
 }
 
 static HRESULT stgmed_stream_fill_stgmed(stgmed_obj_t *obj, STGMEDIUM *stgmed)
@@ -696,8 +632,8 @@ static HRESULT stgmed_stream_fill_stgmed(stgmed_obj_t *obj, STGMEDIUM *stgmed)
     ProtocolStream *stream = (ProtocolStream*)obj;
 
     stgmed->tymed = TYMED_ISTREAM;
-    stgmed->u.pstm = STREAM(stream);
-    stgmed->pUnkForRelease = STGMEDUNK(stream->buf);
+    stgmed->u.pstm = &stream->IStream_iface;
+    stgmed->pUnkForRelease = &stream->buf->IUnknown_iface;
 
     return S_OK;
 }
@@ -707,11 +643,11 @@ static HRESULT stgmed_stream_get_result(stgmed_obj_t *obj, DWORD bindf, void **r
     ProtocolStream *stream = (ProtocolStream*)obj;
 
     if(!(bindf & BINDF_ASYNCHRONOUS) && stream->buf->file == INVALID_HANDLE_VALUE
-       && (stream->buf->hres != S_FALSE || stream->buf->size))
+       && stream->buf->hres != S_FALSE)
         return INET_E_DATA_NOT_AVAILABLE;
 
-    IStream_AddRef(STREAM(stream));
-    *result = STREAM(stream);
+    IStream_AddRef(&stream->IStream_iface);
+    *result = &stream->IStream_iface;
     return S_OK;
 }
 
@@ -731,10 +667,10 @@ static stgmed_obj_t *create_stgmed_stream(stgmed_buf_t *buf)
     ProtocolStream *ret = heap_alloc(sizeof(ProtocolStream));
 
     ret->stgmed_obj.vtbl = &stgmed_stream_vtbl;
-    ret->lpStreamVtbl = &ProtocolStreamVtbl;
+    ret->IStream_iface.lpVtbl = &ProtocolStreamVtbl;
     ret->ref = 1;
 
-    IUnknown_AddRef(STGMEDUNK(buf));
+    IUnknown_AddRef(&buf->IUnknown_iface);
     ret->buf = buf;
 
     URLMON_LockModule();
@@ -746,7 +682,7 @@ static void stgmed_file_release(stgmed_obj_t *obj)
 {
     stgmed_file_obj_t *file_obj = (stgmed_file_obj_t*)obj;
 
-    IUnknown_Release(STGMEDUNK(file_obj->buf));
+    IUnknown_Release(&file_obj->buf->IUnknown_iface);
     heap_free(file_obj);
 }
 
@@ -763,7 +699,7 @@ static HRESULT stgmed_file_fill_stgmed(stgmed_obj_t *obj, STGMEDIUM *stgmed)
 
     stgmed->tymed = TYMED_FILE;
     stgmed->u.lpszFileName = file_obj->buf->cache_file;
-    stgmed->pUnkForRelease = STGMEDUNK(file_obj->buf);
+    stgmed->pUnkForRelease = &file_obj->buf->IUnknown_iface;
 
     return S_OK;
 }
@@ -785,64 +721,57 @@ static stgmed_obj_t *create_stgmed_file(stgmed_buf_t *buf)
 
     ret->stgmed_obj.vtbl = &stgmed_file_vtbl;
 
-    IUnknown_AddRef(STGMEDUNK(buf));
+    IUnknown_AddRef(&buf->IUnknown_iface);
     ret->buf = buf;
 
     return &ret->stgmed_obj;
 }
 
-#define BINDING_THIS(iface) DEFINE_THIS(Binding, Binding, iface)
+static inline Binding *impl_from_IBinding(IBinding *iface)
+{
+    return CONTAINING_RECORD(iface, Binding, IBinding_iface);
+}
 
 static HRESULT WINAPI Binding_QueryInterface(IBinding *iface, REFIID riid, void **ppv)
 {
-    Binding *This = BINDING_THIS(iface);
+    Binding *This = impl_from_IBinding(iface);
 
     *ppv = NULL;
 
     if(IsEqualGUID(&IID_IUnknown, riid)) {
         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
-        *ppv = BINDING(This);
+        *ppv = &This->IBinding_iface;
     }else if(IsEqualGUID(&IID_IBinding, riid)) {
         TRACE("(%p)->(IID_IBinding %p)\n", This, ppv);
-        *ppv = BINDING(This);
+        *ppv = &This->IBinding_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
         TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
-        *ppv = PROTSINK(This);
+        *ppv = &This->IInternetProtocolSink_iface;
     }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
         TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
-        *ppv = BINDINF(This);
+        *ppv = &This->IInternetBindInfo_iface;
     }else if(IsEqualGUID(&IID_IServiceProvider, riid)) {
         TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv);
-        *ppv = SERVPROV(This);
+        *ppv = &This->IServiceProvider_iface;
     }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
         TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv);
 
         /* NOTE: This violidates COM rules, but tests prove that we should do it */
-        if(!get_wininet_info(This->protocol))
+        if(!This->protocol->wininet_info)
            return E_NOINTERFACE;
 
-        *ppv = INETINFO(This);
+        *ppv = &This->IWinInetHttpInfo_iface;
     }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) {
-        IWinInetHttpInfo *http_info;
-        IWinInetInfo *info;
-        HRESULT hres;
-
         TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv);
 
-        info = get_wininet_info(This->protocol);
-        if(!info)
-            return E_NOINTERFACE;
-
-        hres = IWinInetInfo_QueryInterface(info, &IID_IWinInetHttpInfo, (void**)&http_info);
-        if(FAILED(hres))
+        if(!This->protocol->wininet_http_info)
             return E_NOINTERFACE;
 
-        IWinInetHttpInfo_Release(http_info);
-        *ppv = INETINFO(This);
+        *ppv = &This->IWinInetHttpInfo_iface;
     }
 
     if(*ppv) {
-        IBinding_AddRef(BINDING(This));
+        IBinding_AddRef(&This->IBinding_iface);
         return S_OK;
     }
 
@@ -852,7 +781,7 @@ static HRESULT WINAPI Binding_QueryInterface(IBinding *iface, REFIID riid, void
 
 static ULONG WINAPI Binding_AddRef(IBinding *iface)
 {
-    Binding *This = BINDING_THIS(iface);
+    Binding *This = impl_from_IBinding(iface);
     LONG ref = InterlockedIncrement(&This->ref);
 
     TRACE("(%p) ref=%d\n", This, ref);
@@ -862,7 +791,7 @@ static ULONG WINAPI Binding_AddRef(IBinding *iface)
 
 static ULONG WINAPI Binding_Release(IBinding *iface)
 {
-    Binding *This = BINDING_THIS(iface);
+    Binding *This = impl_from_IBinding(iface);
     LONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) ref=%d\n", This, ref);
@@ -875,11 +804,11 @@ static ULONG WINAPI Binding_Release(IBinding *iface)
         if(This->callback)
             IBindStatusCallback_Release(This->callback);
         if(This->protocol)
-            IInternetProtocol_Release(This->protocol);
+            IInternetProtocolEx_Release(&This->protocol->IInternetProtocolEx_iface);
         if(This->service_provider)
             IServiceProvider_Release(This->service_provider);
         if(This->stgmed_buf)
-            IUnknown_Release(STGMEDUNK(This->stgmed_buf));
+            IUnknown_Release(&This->stgmed_buf->IUnknown_iface);
         if(This->stgmed_obj)
             This->stgmed_obj->vtbl->release(This->stgmed_obj);
         if(This->obj)
@@ -903,7 +832,7 @@ static ULONG WINAPI Binding_Release(IBinding *iface)
 
 static HRESULT WINAPI Binding_Abort(IBinding *iface)
 {
-    Binding *This = BINDING_THIS(iface);
+    Binding *This = impl_from_IBinding(iface);
     HRESULT hres;
 
     TRACE("(%p)\n", This);
@@ -911,7 +840,8 @@ static HRESULT WINAPI Binding_Abort(IBinding *iface)
     if(This->state & BINDING_ABORTED)
         return E_FAIL;
 
-    hres = IInternetProtocol_Abort(This->protocol, E_ABORT, ERROR_SUCCESS);
+    hres = IInternetProtocolEx_Abort(&This->protocol->IInternetProtocolEx_iface, E_ABORT,
+            ERROR_SUCCESS);
     if(FAILED(hres))
         return hres;
 
@@ -921,28 +851,28 @@ static HRESULT WINAPI Binding_Abort(IBinding *iface)
 
 static HRESULT WINAPI Binding_Suspend(IBinding *iface)
 {
-    Binding *This = BINDING_THIS(iface);
+    Binding *This = impl_from_IBinding(iface);
     FIXME("(%p)\n", This);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI Binding_Resume(IBinding *iface)
 {
-    Binding *This = BINDING_THIS(iface);
+    Binding *This = impl_from_IBinding(iface);
     FIXME("(%p)\n", This);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI Binding_SetPriority(IBinding *iface, LONG nPriority)
 {
-    Binding *This = BINDING_THIS(iface);
+    Binding *This = impl_from_IBinding(iface);
     FIXME("(%p)->(%d)\n", This, nPriority);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI Binding_GetPriority(IBinding *iface, LONG *pnPriority)
 {
-    Binding *This = BINDING_THIS(iface);
+    Binding *This = impl_from_IBinding(iface);
     FIXME("(%p)->(%p)\n", This, pnPriority);
     return E_NOTIMPL;
 }
@@ -950,11 +880,23 @@ static HRESULT WINAPI Binding_GetPriority(IBinding *iface, LONG *pnPriority)
 static HRESULT WINAPI Binding_GetBindResult(IBinding *iface, CLSID *pclsidProtocol,
         DWORD *pdwResult, LPOLESTR *pszResult, DWORD *pdwReserved)
 {
-    Binding *This = BINDING_THIS(iface);
+    Binding *This = impl_from_IBinding(iface);
     FIXME("(%p)->(%p %p %p %p)\n", This, pclsidProtocol, pdwResult, pszResult, pdwReserved);
     return E_NOTIMPL;
 }
 
+static const IBindingVtbl BindingVtbl = {
+    Binding_QueryInterface,
+    Binding_AddRef,
+    Binding_Release,
+    Binding_Abort,
+    Binding_Suspend,
+    Binding_Resume,
+    Binding_SetPriority,
+    Binding_GetPriority,
+    Binding_GetBindResult
+};
+
 static Binding *get_bctx_binding(IBindCtx *bctx)
 {
     IBinding *binding;
@@ -965,54 +907,44 @@ static Binding *get_bctx_binding(IBindCtx *bctx)
     if(FAILED(hres))
         return NULL;
 
-    hres = IUnknown_QueryInterface(unk, &IID_IBinding, (void*)&binding);
+    hres = IUnknown_QueryInterface(unk, &IID_IBinding, (void**)&binding);
     IUnknown_Release(unk);
     if(FAILED(hres))
         return NULL;
 
-    /* FIXME!!! */
-    return BINDING_THIS(binding);
+    if (binding->lpVtbl != &BindingVtbl)
+        return NULL;
+    return impl_from_IBinding(binding);
 }
 
-#undef BINDING_THIS
-
-static const IBindingVtbl BindingVtbl = {
-    Binding_QueryInterface,
-    Binding_AddRef,
-    Binding_Release,
-    Binding_Abort,
-    Binding_Suspend,
-    Binding_Resume,
-    Binding_SetPriority,
-    Binding_GetPriority,
-    Binding_GetBindResult
-};
-
-#define PROTSINK_THIS(iface) DEFINE_THIS(Binding, IInternetProtocolSink, iface)
+static inline Binding *impl_from_IInternetProtocolSink(IInternetProtocolSink *iface)
+{
+    return CONTAINING_RECORD(iface, Binding, IInternetProtocolSink_iface);
+}
 
 static HRESULT WINAPI InternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
         REFIID riid, void **ppv)
 {
-    Binding *This = PROTSINK_THIS(iface);
-    return IBinding_QueryInterface(BINDING(This), riid, ppv);
+    Binding *This = impl_from_IInternetProtocolSink(iface);
+    return IBinding_QueryInterface(&This->IBinding_iface, riid, ppv);
 }
 
 static ULONG WINAPI InternetProtocolSink_AddRef(IInternetProtocolSink *iface)
 {
-    Binding *This = PROTSINK_THIS(iface);
-    return IBinding_AddRef(BINDING(This));
+    Binding *This = impl_from_IInternetProtocolSink(iface);
+    return IBinding_AddRef(&This->IBinding_iface);
 }
 
 static ULONG WINAPI InternetProtocolSink_Release(IInternetProtocolSink *iface)
 {
-    Binding *This = PROTSINK_THIS(iface);
-    return IBinding_Release(BINDING(This));
+    Binding *This = impl_from_IInternetProtocolSink(iface);
+    return IBinding_Release(&This->IBinding_iface);
 }
 
 static HRESULT WINAPI InternetProtocolSink_Switch(IInternetProtocolSink *iface,
         PROTOCOLDATA *pProtocolData)
 {
-    Binding *This = PROTSINK_THIS(iface);
+    Binding *This = impl_from_IInternetProtocolSink(iface);
 
     WARN("(%p)->(%p)\n", This, pProtocolData);
 
@@ -1029,7 +961,7 @@ static void on_progress(Binding *This, ULONG progress, ULONG progress_max,
 static HRESULT WINAPI InternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
         ULONG ulStatusCode, LPCWSTR szStatusText)
 {
-    Binding *This = PROTSINK_THIS(iface);
+    Binding *This = impl_from_IInternetProtocolSink(iface);
 
     TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
 
@@ -1046,7 +978,6 @@ static HRESULT WINAPI InternetProtocolSink_ReportProgress(IInternetProtocolSink
         on_progress(This, 0, 0, BINDSTATUS_REDIRECTING, szStatusText);
         break;
     case BINDSTATUS_BEGINDOWNLOADDATA:
-        fill_stgmed_buffer(This->stgmed_buf);
         break;
     case BINDSTATUS_SENDINGREQUEST:
         on_progress(This, 0, 0, BINDSTATUS_SENDINGREQUEST, szStatusText);
@@ -1086,13 +1017,16 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres
 
     TRACE("(%p)->(%d %u %u)\n", This, bscf, progress, progress_max);
 
-    if(This->download_state == END_DOWNLOAD || (This->state & (BINDING_STOPPED|BINDING_ABORTED)))
+    if(This->download_state == END_DOWNLOAD || (This->state & BINDING_ABORTED)) {
+        read_protocol_data(This->stgmed_buf);
+        return;
+    }
+
+    if(This->state & BINDING_STOPPED)
         return;
 
     if(This->stgmed_buf->file != INVALID_HANDLE_VALUE)
         read_protocol_data(This->stgmed_buf);
-    else if(This->download_state == BEFORE_DOWNLOAD)
-        fill_stgmed_buffer(This->stgmed_buf);
 
     if(This->download_state == BEFORE_DOWNLOAD) {
         This->download_state = DOWNLOADING;
@@ -1119,16 +1053,17 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres
 
     if(This->to_object) {
         if(!(This->state & BINDING_OBJAVAIL)) {
-            IBinding_AddRef(BINDING(This));
+            IBinding_AddRef(&This->IBinding_iface);
             create_object(This);
-            IBinding_Release(BINDING(This));
+            IBinding_Release(&This->IBinding_iface);
         }
     }else {
         STGMEDIUM stgmed;
         HRESULT hres;
 
         if(!(This->state & BINDING_LOCKED)) {
-            HRESULT hres = IInternetProtocol_LockRequest(This->protocol, 0);
+            HRESULT hres = IInternetProtocolEx_LockRequest(
+                    &This->protocol->IInternetProtocolEx_iface, 0);
             if(SUCCEEDED(hres))
                 This->state |= BINDING_LOCKED;
         }
@@ -1153,7 +1088,7 @@ static void report_data(Binding *This, DWORD bscf, ULONG progress, ULONG progres
 static HRESULT WINAPI InternetProtocolSink_ReportData(IInternetProtocolSink *iface,
         DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
 {
-    Binding *This = PROTSINK_THIS(iface);
+    Binding *This = impl_from_IInternetProtocolSink(iface);
 
     TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
 
@@ -1164,17 +1099,15 @@ static HRESULT WINAPI InternetProtocolSink_ReportData(IInternetProtocolSink *ifa
 static HRESULT WINAPI InternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
         HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
 {
-    Binding *This = PROTSINK_THIS(iface);
+    Binding *This = impl_from_IInternetProtocolSink(iface);
 
     TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
 
     stop_binding(This, hrResult, szResult);
-    IInternetProtocol_Terminate(This->protocol, 0);
+    IInternetProtocolEx_Terminate(&This->protocol->IInternetProtocolEx_iface, 0);
     return S_OK;
 }
 
-#undef PROTSINK_THIS
-
 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
     InternetProtocolSink_QueryInterface,
     InternetProtocolSink_AddRef,
@@ -1185,31 +1118,34 @@ static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
     InternetProtocolSink_ReportResult
 };
 
-#define BINDINF_THIS(iface) DEFINE_THIS(Binding, InternetBindInfo, iface)
+static inline Binding *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
+{
+    return CONTAINING_RECORD(iface, Binding, IInternetBindInfo_iface);
+}
 
 static HRESULT WINAPI InternetBindInfo_QueryInterface(IInternetBindInfo *iface,
         REFIID riid, void **ppv)
 {
-    Binding *This = BINDINF_THIS(iface);
-    return IBinding_QueryInterface(BINDING(This), riid, ppv);
+    Binding *This = impl_from_IInternetBindInfo(iface);
+    return IBinding_QueryInterface(&This->IBinding_iface, riid, ppv);
 }
 
 static ULONG WINAPI InternetBindInfo_AddRef(IInternetBindInfo *iface)
 {
-    Binding *This = BINDINF_THIS(iface);
-    return IBinding_AddRef(BINDING(This));
+    Binding *This = impl_from_IInternetBindInfo(iface);
+    return IBinding_AddRef(&This->IBinding_iface);
 }
 
 static ULONG WINAPI InternetBindInfo_Release(IInternetBindInfo *iface)
 {
-    Binding *This = BINDINF_THIS(iface);
-    return IBinding_Release(BINDING(This));
+    Binding *This = impl_from_IInternetBindInfo(iface);
+    return IBinding_Release(&This->IBinding_iface);
 }
 
 static HRESULT WINAPI InternetBindInfo_GetBindInfo(IInternetBindInfo *iface,
         DWORD *grfBINDF, BINDINFO *pbindinfo)
 {
-    Binding *This = BINDINF_THIS(iface);
+    Binding *This = impl_from_IInternetBindInfo(iface);
 
     TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
 
@@ -1232,7 +1168,7 @@ static HRESULT WINAPI InternetBindInfo_GetBindInfo(IInternetBindInfo *iface,
 static HRESULT WINAPI InternetBindInfo_GetBindString(IInternetBindInfo *iface,
         ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
 {
-    Binding *This = BINDINF_THIS(iface);
+    Binding *This = impl_from_IInternetBindInfo(iface);
 
     TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
 
@@ -1280,8 +1216,6 @@ static HRESULT WINAPI InternetBindInfo_GetBindString(IInternetBindInfo *iface,
     return E_NOTIMPL;
 }
 
-#undef BINDF_THIS
-
 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
     InternetBindInfo_QueryInterface,
     InternetBindInfo_AddRef,
@@ -1290,43 +1224,54 @@ static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
     InternetBindInfo_GetBindString
 };
 
-#define INETINFO_THIS(iface) DEFINE_THIS(Binding, WinInetHttpInfo, iface)
+static inline Binding *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface)
+{
+    return CONTAINING_RECORD(iface, Binding, IWinInetHttpInfo_iface);
+}
 
 static HRESULT WINAPI WinInetHttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv)
 {
-    Binding *This = INETINFO_THIS(iface);
-    return IBinding_QueryInterface(BINDING(This), riid, ppv);
+    Binding *This = impl_from_IWinInetHttpInfo(iface);
+    return IBinding_QueryInterface(&This->IBinding_iface, riid, ppv);
 }
 
 static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface)
 {
-    Binding *This = INETINFO_THIS(iface);
-    return IBinding_AddRef(BINDING(This));
+    Binding *This = impl_from_IWinInetHttpInfo(iface);
+    return IBinding_AddRef(&This->IBinding_iface);
 }
 
 static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface)
 {
-    Binding *This = INETINFO_THIS(iface);
-    return IBinding_Release(BINDING(This));
+    Binding *This = impl_from_IWinInetHttpInfo(iface);
+    return IBinding_Release(&This->IBinding_iface);
 }
 
 static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption,
         void *pBuffer, DWORD *pcbBuffer)
 {
-    Binding *This = INETINFO_THIS(iface);
-    FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
-    return E_NOTIMPL;
+    Binding *This = impl_from_IWinInetHttpInfo(iface);
+    TRACE("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
+
+    if(!This->protocol->wininet_info)
+        return E_FAIL;
+
+    return IWinInetInfo_QueryOption(This->protocol->wininet_info,
+            dwOption, pBuffer, pcbBuffer);
 }
 
 static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
         void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
 {
-    Binding *This = INETINFO_THIS(iface);
-    FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
-    return E_NOTIMPL;
-}
+    Binding *This = impl_from_IWinInetHttpInfo(iface);
+    TRACE("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
+
+    if(!This->protocol->wininet_http_info)
+        return E_FAIL;
 
-#undef INETINFO_THIS
+    return IWinInetHttpInfo_QueryInfo(This->protocol->wininet_http_info,
+            dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
+}
 
 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
     WinInetHttpInfo_QueryInterface,
@@ -1336,31 +1281,34 @@ static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
     WinInetHttpInfo_QueryInfo
 };
 
-#define SERVPROV_THIS(iface) DEFINE_THIS(Binding, ServiceProvider, iface)
+static inline Binding *impl_from_IServiceProvider(IServiceProvider *iface)
+{
+    return CONTAINING_RECORD(iface, Binding, IServiceProvider_iface);
+}
 
 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface,
         REFIID riid, void **ppv)
 {
-    Binding *This = SERVPROV_THIS(iface);
-    return IBinding_QueryInterface(BINDING(This), riid, ppv);
+    Binding *This = impl_from_IServiceProvider(iface);
+    return IBinding_QueryInterface(&This->IBinding_iface, riid, ppv);
 }
 
 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
 {
-    Binding *This = SERVPROV_THIS(iface);
-    return IBinding_AddRef(BINDING(This));
+    Binding *This = impl_from_IServiceProvider(iface);
+    return IBinding_AddRef(&This->IBinding_iface);
 }
 
 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
 {
-    Binding *This = SERVPROV_THIS(iface);
-    return IBinding_Release(BINDING(This));
+    Binding *This = impl_from_IServiceProvider(iface);
+    return IBinding_Release(&This->IBinding_iface);
 }
 
 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface,
         REFGUID guidService, REFIID riid, void **ppv)
 {
-    Binding *This = SERVPROV_THIS(iface);
+    Binding *This = impl_from_IServiceProvider(iface);
     HRESULT hres;
 
     TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
@@ -1373,11 +1321,9 @@ static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface,
     }
 
     WARN("unknown service %s\n", debugstr_guid(guidService));
-    return E_NOTIMPL;
+    return E_NOINTERFACE;
 }
 
-#undef SERVPROV_THIS
-
 static const IServiceProviderVtbl ServiceProviderVtbl = {
     ServiceProvider_QueryInterface,
     ServiceProvider_AddRef,
@@ -1431,11 +1377,11 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, IUri *uri, IB
 
     ret = heap_alloc_zero(sizeof(Binding));
 
-    ret->lpBindingVtbl              = &BindingVtbl;
-    ret->lpIInternetProtocolSinkVtbl = &InternetProtocolSinkVtbl;
-    ret->lpInternetBindInfoVtbl     = &InternetBindInfoVtbl;
-    ret->lpWinInetHttpInfoVtbl      = &WinInetHttpInfoVtbl;
-    ret->lpServiceProviderVtbl      = &ServiceProviderVtbl;
+    ret->IBinding_iface.lpVtbl = &BindingVtbl;
+    ret->IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkVtbl;
+    ret->IInternetBindInfo_iface.lpVtbl = &InternetBindInfoVtbl;
+    ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl;
+    ret->IServiceProvider_iface.lpVtbl = &ServiceProviderVtbl;
 
     ret->ref = 1;
 
@@ -1463,7 +1409,7 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, IUri *uri, IB
     hres = get_callback(pbc, &ret->callback);
     if(FAILED(hres)) {
         WARN("Could not get IBindStatusCallback\n");
-        IBinding_Release(BINDING(ret));
+        IBinding_Release(&ret->IBinding_iface);
         return hres;
     }
 
@@ -1472,12 +1418,12 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, IUri *uri, IB
 
     if(binding_ctx) {
         ret->protocol = binding_ctx->protocol;
-        IInternetProtocol_AddRef(ret->protocol);
+        IInternetProtocolEx_AddRef(&ret->protocol->IInternetProtocolEx_iface);
     }else {
         hres = create_binding_protocol(TRUE, &ret->protocol);
         if(FAILED(hres)) {
             WARN("Could not get protocol handler\n");
-            IBinding_Release(BINDING(ret));
+            IBinding_Release(&ret->IBinding_iface);
             return hres;
         }
     }
@@ -1485,7 +1431,7 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, IUri *uri, IB
     hres = IBindStatusCallback_GetBindInfo(ret->callback, &ret->bindf, &ret->bindinfo);
     if(FAILED(hres)) {
         WARN("GetBindInfo failed: %08x\n", hres);
-        IBinding_Release(BINDING(ret));
+        IBinding_Release(&ret->IBinding_iface);
         return hres;
     }
 
@@ -1496,7 +1442,7 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, IUri *uri, IB
     if(to_obj)
         ret->bindinfo.dwOptions |= 0x100000;
 
-    if(!(ret->bindf & BINDF_ASYNCHRONOUS)) {
+    if(!(ret->bindf & BINDF_ASYNCHRONOUS) || !(ret->bindf & BINDF_PULLDATA)) {
         ret->bindf |= BINDF_NEEDFILE;
         ret->use_cache_file = TRUE;
     }else if(!is_urlmon_protocol(uri)) {
@@ -1505,16 +1451,16 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, IUri *uri, IB
 
     hres = IUri_GetDisplayUri(uri, &ret->url);
     if(FAILED(hres)) {
-        IBinding_Release(BINDING(ret));
+        IBinding_Release(&ret->IBinding_iface);
         return hres;
     }
 
     if(binding_ctx) {
         ret->stgmed_buf = binding_ctx->stgmed_buf;
-        IUnknown_AddRef(STGMEDUNK(ret->stgmed_buf));
+        IUnknown_AddRef(&ret->stgmed_buf->IUnknown_iface);
         ret->clipboard_format = binding_ctx->clipboard_format;
     }else {
-        ret->stgmed_buf = create_stgmed_buf(ret->protocol);
+        ret->stgmed_buf = create_stgmed_buf(&ret->protocol->IInternetProtocolEx_iface);
     }
 
     if(to_obj) {
@@ -1526,7 +1472,7 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, IUri *uri, IB
         ret->stgmed_obj = create_stgmed_file(ret->stgmed_buf);
     }else {
         FIXME("Unsupported riid %s\n", debugstr_guid(riid));
-        IBinding_Release(BINDING(ret));
+        IBinding_Release(&ret->IBinding_iface);
         return E_NOTIMPL;
     }
 
@@ -1545,29 +1491,34 @@ static HRESULT start_binding(IMoniker *mon, Binding *binding_ctx, IUri *uri, IBi
     if(FAILED(hres))
         return hres;
 
-    hres = IBindStatusCallback_OnStartBinding(binding->callback, 0, BINDING(binding));
+    hres = IBindStatusCallback_OnStartBinding(binding->callback, 0, &binding->IBinding_iface);
     if(FAILED(hres)) {
         WARN("OnStartBinding failed: %08x\n", hres);
-        stop_binding(binding, INET_E_DOWNLOAD_FAILURE, NULL);
-        IBinding_Release(BINDING(binding));
+        if(hres != E_ABORT && hres != E_NOTIMPL)
+            hres = INET_E_DOWNLOAD_FAILURE;
+
+        stop_binding(binding, hres, NULL);
+        IBinding_Release(&binding->IBinding_iface);
         return hres;
     }
 
     if(binding_ctx) {
-        set_binding_sink(binding->protocol, PROTSINK(binding), BINDINF(binding));
+        set_binding_sink(binding->protocol, &binding->IInternetProtocolSink_iface,
+                &binding->IInternetBindInfo_iface);
         if(binding_ctx->redirect_url)
             IBindStatusCallback_OnProgress(binding->callback, 0, 0, BINDSTATUS_REDIRECTING, binding_ctx->redirect_url);
         report_data(binding, BSCF_FIRSTDATANOTIFICATION | (binding_ctx->download_state == END_DOWNLOAD ? BSCF_LASTDATANOTIFICATION : 0),
                 0, 0);
     }else {
-        hres = IInternetProtocolEx_StartEx(binding->protocol, uri, PROTSINK(binding),
-                 BINDINF(binding), PI_APARTMENTTHREADED|PI_MIMEVERIFICATION, 0);
+        hres = IInternetProtocolEx_StartEx(&binding->protocol->IInternetProtocolEx_iface, uri,
+                &binding->IInternetProtocolSink_iface, &binding->IInternetBindInfo_iface,
+                PI_APARTMENTTHREADED|PI_MIMEVERIFICATION, 0);
 
         TRACE("start ret %08x\n", hres);
 
         if(FAILED(hres) && hres != E_PENDING) {
             stop_binding(binding, hres, NULL);
-            IBinding_Release(BINDING(binding));
+            IBinding_Release(&binding->IBinding_iface);
 
             return hres;
         }
@@ -1591,19 +1542,17 @@ HRESULT bind_to_storage(IUri *uri, IBindCtx *pbc, REFIID riid, void **ppv)
     Binding *binding = NULL, *binding_ctx;
     HRESULT hres;
 
-    *ppv = NULL;
-
     binding_ctx = get_bctx_binding(pbc);
 
     hres = start_binding(NULL, binding_ctx, uri, pbc, FALSE, riid, &binding);
     if(binding_ctx)
-        IBinding_Release(BINDING(binding_ctx));
+        IBinding_Release(&binding_ctx->IBinding_iface);
     if(FAILED(hres))
         return hres;
 
-    if(binding->hres == S_OK && binding->stgmed_buf->init) {
+    if(binding->hres == S_OK && binding->download_state != BEFORE_DOWNLOAD /* FIXME */) {
         if((binding->state & BINDING_STOPPED) && (binding->state & BINDING_LOCKED))
-            IInternetProtocol_UnlockRequest(binding->protocol);
+            IInternetProtocolEx_UnlockRequest(&binding->protocol->IInternetProtocolEx_iface);
 
         hres = binding->stgmed_obj->vtbl->get_result(binding->stgmed_obj, binding->bindf, ppv);
     }else if(binding->bindf & BINDF_ASYNCHRONOUS) {
@@ -1612,7 +1561,7 @@ HRESULT bind_to_storage(IUri *uri, IBindCtx *pbc, REFIID riid, void **ppv)
         hres = FAILED(binding->hres) ? binding->hres : S_OK;
     }
 
-    IBinding_Release(BINDING(binding));
+    IBinding_Release(&binding->IBinding_iface);
 
     return hres;
 }
@@ -1638,7 +1587,7 @@ HRESULT bind_to_object(IMoniker *mon, IUri *uri, IBindCtx *pbc, REFIID riid, voi
         hres = S_OK;
     }
 
-    IBinding_Release(BINDING(binding));
+    IBinding_Release(&binding->IBinding_iface);
 
     return hres;
 }
index 0549712..45cf14c 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
 
-typedef struct BindProtocol BindProtocol;
+typedef void (*task_proc_t)(BindProtocol*,task_header_t*);
 
-struct _task_header_t;
-
-typedef void (*task_proc_t)(BindProtocol*,struct _task_header_t*);
-
-typedef struct _task_header_t {
+struct _task_header_t {
     task_proc_t proc;
-    struct _task_header_t *next;
-} task_header_t;
-
-struct BindProtocol {
-    const IInternetProtocolExVtbl    *lpIInternetProtocolExVtbl;
-    const IInternetBindInfoVtbl      *lpInternetBindInfoVtbl;
-    const IInternetPriorityVtbl      *lpInternetPriorityVtbl;
-    const IServiceProviderVtbl       *lpServiceProviderVtbl;
-    const IInternetProtocolSinkVtbl  *lpIInternetProtocolSinkVtbl;
-    const IWinInetHttpInfoVtbl       *lpIWinInetHttpInfoVtbl;
-
-    LONG ref;
-
-    IInternetProtocol *protocol;
-    IInternetBindInfo *bind_info;
-    IInternetProtocolSink *protocol_sink;
-    IServiceProvider *service_provider;
-    IWinInetInfo *wininet_info;
-
-    struct {
-        IInternetProtocol IInternetProtocol_iface;
-    } default_protocol_handler;
-    IInternetProtocol *protocol_handler;
-
-    LONG priority;
-
-    BOOL reported_result;
-    BOOL reported_mime;
-    BOOL from_urlmon;
-    DWORD pi;
-
-    DWORD apartment_thread;
-    HWND notif_hwnd;
-    DWORD continue_call;
-
-    CRITICAL_SECTION section;
-    task_header_t *task_queue_head, *task_queue_tail;
-
-    BYTE *buf;
-    DWORD buf_size;
-    LPWSTR mime;
-    IUri *uri;
-    ProtocolProxy *filter_proxy;
+    task_header_t *next;
 };
 
-#define BINDINFO(x)  ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl)
-#define PRIORITY(x)  ((IInternetPriority*) &(x)->lpInternetPriorityVtbl)
-#define HTTPINFO(x)  ((IWinInetHttpInfo*)  &(x)->lpIWinInetHttpInfoVtbl)
-#define SERVPROV(x)  ((IServiceProvider*)  &(x)->lpServiceProviderVtbl)
-#define PROTOCOLEX(x)  ((IInternetProtocolEx*)  &(x)->lpIInternetProtocolExVtbl)
-
-#define PROTOCOLHANDLER(x)  ((IInternetProtocol*)  &(x)->lpIInternetProtocolHandlerVtbl)
-
 #define BUFFER_SIZE     2048
 #define MIME_TEST_SIZE  255
 
@@ -115,7 +61,7 @@ static LRESULT WINAPI notif_wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM
             This->continue_call--;
         }
 
-        IInternetProtocolEx_Release(PROTOCOLEX(This));
+        IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
         return 0;
     }
     case WM_MK_RELEASE: {
@@ -214,7 +160,7 @@ static void push_task(BindProtocol *This, task_header_t *task, task_proc_t proc)
     LeaveCriticalSection(&This->section);
 
     if(do_post) {
-        IInternetProtocolEx_AddRef(PROTOCOLEX(This));
+        IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
         PostMessageW(This->notif_hwnd, WM_MK_CONTINUE, 0, (LPARAM)This);
     }
 }
@@ -248,9 +194,10 @@ static HRESULT handle_mime_filter(BindProtocol *This, IInternetProtocol *mime_fi
     IInternetProtocol_AddRef(mime_filter);
     This->protocol_handler = mime_filter;
 
-    filter_data.pProtocol = PROTOCOL(filter_proxy);
-    hres = IInternetProtocol_Start(mime_filter, mime, PROTSINK(filter_proxy), BINDINFO(This),
-            PI_FILTER_MODE|PI_FORCE_ASYNC, (HANDLE_PTR)&filter_data);
+    filter_data.pProtocol = &filter_proxy->IInternetProtocol_iface;
+    hres = IInternetProtocol_Start(mime_filter, mime, &filter_proxy->IInternetProtocolSink_iface,
+            &This->IInternetBindInfo_iface, PI_FILTER_MODE|PI_FORCE_ASYNC,
+            (HANDLE_PTR)&filter_data);
     if(FAILED(hres)) {
         IInternetProtocolSink_Release(old_sink);
         return hres;
@@ -291,39 +238,42 @@ static void mime_available(BindProtocol *This, LPCWSTR mime, BOOL verified)
     }
 }
 
-#define PROTOCOL_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolEx, iface)
+static inline BindProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface)
+{
+    return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolEx_iface);
+}
 
 static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
 {
-    BindProtocol *This = PROTOCOL_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolEx(iface);
 
     *ppv = NULL;
     if(IsEqualGUID(&IID_IUnknown, riid)) {
         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
-        *ppv = PROTOCOLEX(This);
+        *ppv = &This->IInternetProtocolEx_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
-        *ppv = PROTOCOLEX(This);
+        *ppv = &This->IInternetProtocolEx_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
         TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
-        *ppv = PROTOCOLEX(This);
+        *ppv = &This->IInternetProtocolEx_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
         TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv);
-        *ppv = PROTOCOLEX(This);
+        *ppv = &This->IInternetProtocolEx_iface;
     }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) {
         TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv);
-        *ppv = BINDINFO(This);
+        *ppv = &This->IInternetBindInfo_iface;
     }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
         TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
-        *ppv = PRIORITY(This);
+        *ppv = &This->IInternetPriority_iface;
     }else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
         FIXME("(%p)->(IID_IAuthenticate %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;
     }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
         TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
-        *ppv = PROTSINK(This);
+        *ppv = &This->IInternetProtocolSink_iface;
     }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) {
         TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv);
 
@@ -333,7 +283,7 @@ static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocolEx *iface, RE
 
             hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetInfo, (void**)&inet_info);
             if(SUCCEEDED(hres)) {
-                *ppv = HTTPINFO(This);
+                *ppv = &This->IWinInetHttpInfo_iface;
                 IWinInetInfo_Release(inet_info);
             }
         }
@@ -346,7 +296,7 @@ static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocolEx *iface, RE
 
             hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetHttpInfo, (void**)&http_info);
             if(SUCCEEDED(hres)) {
-                *ppv = HTTPINFO(This);
+                *ppv = &This->IWinInetHttpInfo_iface;
                 IWinInetHttpInfo_Release(http_info);
             }
         }
@@ -363,7 +313,7 @@ static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocolEx *iface, RE
 
 static ULONG WINAPI BindProtocol_AddRef(IInternetProtocolEx *iface)
 {
-    BindProtocol *This = PROTOCOL_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolEx(iface);
     LONG ref = InterlockedIncrement(&This->ref);
     TRACE("(%p) ref=%d\n", This, ref);
     return ref;
@@ -371,7 +321,7 @@ static ULONG WINAPI BindProtocol_AddRef(IInternetProtocolEx *iface)
 
 static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface)
 {
-    BindProtocol *This = PROTOCOL_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolEx(iface);
     LONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) ref=%d\n", This, ref);
@@ -379,6 +329,8 @@ static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface)
     if(!ref) {
         if(This->wininet_info)
             IWinInetInfo_Release(This->wininet_info);
+        if(This->wininet_http_info)
+            IWinInetHttpInfo_Release(This->wininet_http_info);
         if(This->protocol)
             IInternetProtocol_Release(This->protocol);
         if(This->bind_info)
@@ -386,11 +338,11 @@ static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface)
         if(This->protocol_handler && This->protocol_handler != &This->default_protocol_handler.IInternetProtocol_iface)
             IInternetProtocol_Release(This->protocol_handler);
         if(This->filter_proxy)
-            IInternetProtocol_Release(PROTOCOL(This->filter_proxy));
+            IInternetProtocol_Release(&This->filter_proxy->IInternetProtocol_iface);
         if(This->uri)
             IUri_Release(This->uri);
 
-        set_binding_sink(PROTOCOLEX(This), NULL, NULL);
+        set_binding_sink(This, NULL, NULL);
 
         if(This->notif_hwnd)
             release_notif_hwnd(This->notif_hwnd);
@@ -409,7 +361,7 @@ static HRESULT WINAPI BindProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szU
         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
         DWORD grfPI, HANDLE_PTR dwReserved)
 {
-    BindProtocol *This = PROTOCOL_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolEx(iface);
     IUri *uri;
     HRESULT hres;
 
@@ -420,8 +372,8 @@ static HRESULT WINAPI BindProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szU
     if(FAILED(hres))
         return hres;
 
-    hres = IInternetProtocolEx_StartEx(PROTOCOLEX(This), uri, pOIProtSink, pOIBindInfo,
-            grfPI, (HANDLE*)dwReserved);
+    hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink,
+            pOIBindInfo, grfPI, (HANDLE*)dwReserved);
 
     IUri_Release(uri);
     return hres;
@@ -429,7 +381,7 @@ static HRESULT WINAPI BindProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szU
 
 static HRESULT WINAPI BindProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
 {
-    BindProtocol *This = PROTOCOL_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolEx(iface);
 
     TRACE("(%p)->(%p)\n", This, pProtocolData);
 
@@ -439,7 +391,7 @@ static HRESULT WINAPI BindProtocol_Continue(IInternetProtocolEx *iface, PROTOCOL
 static HRESULT WINAPI BindProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
         DWORD dwOptions)
 {
-    BindProtocol *This = PROTOCOL_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolEx(iface);
 
     TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
 
@@ -448,7 +400,7 @@ static HRESULT WINAPI BindProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrR
 
 static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
 {
-    BindProtocol *This = PROTOCOL_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolEx(iface);
 
     TRACE("(%p)->(%08x)\n", This, dwOptions);
 
@@ -457,14 +409,14 @@ static HRESULT WINAPI BindProtocol_Terminate(IInternetProtocolEx *iface, DWORD d
 
 static HRESULT WINAPI BindProtocol_Suspend(IInternetProtocolEx *iface)
 {
-    BindProtocol *This = PROTOCOL_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolEx(iface);
     FIXME("(%p)\n", This);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI BindProtocol_Resume(IInternetProtocolEx *iface)
 {
-    BindProtocol *This = PROTOCOL_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolEx(iface);
     FIXME("(%p)\n", This);
     return E_NOTIMPL;
 }
@@ -472,7 +424,7 @@ static HRESULT WINAPI BindProtocol_Resume(IInternetProtocolEx *iface)
 static HRESULT WINAPI BindProtocol_Read(IInternetProtocolEx *iface, void *pv,
         ULONG cb, ULONG *pcbRead)
 {
-    BindProtocol *This = PROTOCOL_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolEx(iface);
 
     TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
 
@@ -484,14 +436,14 @@ static HRESULT WINAPI BindProtocol_Read(IInternetProtocolEx *iface, void *pv,
 static HRESULT WINAPI BindProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
         DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
 {
-    BindProtocol *This = PROTOCOL_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolEx(iface);
     FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
 {
-    BindProtocol *This = PROTOCOL_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolEx(iface);
 
     TRACE("(%p)->(%08x)\n", This, dwOptions);
 
@@ -500,7 +452,7 @@ static HRESULT WINAPI BindProtocol_LockRequest(IInternetProtocolEx *iface, DWORD
 
 static HRESULT WINAPI BindProtocol_UnlockRequest(IInternetProtocolEx *iface)
 {
-    BindProtocol *This = PROTOCOL_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolEx(iface);
 
     TRACE("(%p)\n", This);
 
@@ -511,7 +463,7 @@ static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr
         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
         DWORD grfPI, HANDLE *dwReserved)
 {
-    BindProtocol *This = PROTOCOL_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolEx(iface);
     IInternetProtocol *protocol = NULL;
     IInternetProtocolEx *protocolex;
     IInternetPriority *priority;
@@ -554,7 +506,7 @@ static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr
             if(FAILED(hres))
                 return hres;
         }else {
-            hres = IClassFactory_CreateInstance(cf, (IUnknown*)BINDINFO(This),
+            hres = IClassFactory_CreateInstance(cf, (IUnknown*)&This->IInternetBindInfo_iface,
                     &IID_IUnknown, (void**)&unk);
             IClassFactory_Release(cf);
             if(FAILED(hres))
@@ -573,10 +525,12 @@ static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr
 
     This->protocol = protocol;
 
-    if(urlmon_protocol)
+    if(urlmon_protocol) {
         IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info);
+        IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&This->wininet_http_info);
+    }
 
-    set_binding_sink(PROTOCOLEX(This), pOIProtSink, pOIBindInfo);
+    set_binding_sink(This, pOIProtSink, pOIBindInfo);
 
     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority);
     if(SUCCEEDED(hres)) {
@@ -586,7 +540,8 @@ static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr
 
     hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&protocolex);
     if(SUCCEEDED(hres)) {
-        hres = IInternetProtocolEx_StartEx(protocolex, pUri, PROTSINK(This), BINDINFO(This), 0, NULL);
+        hres = IInternetProtocolEx_StartEx(protocolex, pUri, &This->IInternetProtocolSink_iface,
+                &This->IInternetBindInfo_iface, 0, NULL);
         IInternetProtocolEx_Release(protocolex);
     }else {
         BSTR display_uri;
@@ -595,16 +550,16 @@ static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr
         if(FAILED(hres))
             return hres;
 
-        hres = IInternetProtocol_Start(protocol, display_uri, PROTSINK(This), BINDINFO(This), 0, 0);
+        hres = IInternetProtocol_Start(protocol, display_uri, &This->IInternetProtocolSink_iface,
+                &This->IInternetBindInfo_iface, 0, 0);
         SysFreeString(display_uri);
     }
 
     return hres;
 }
 
-void set_binding_sink(IInternetProtocolEx *bind_protocol, IInternetProtocolSink *sink, IInternetBindInfo *bind_info)
+void set_binding_sink(BindProtocol *This, IInternetProtocolSink *sink, IInternetBindInfo *bind_info)
 {
-    BindProtocol *This = PROTOCOL_THIS(bind_protocol);
     IInternetProtocolSink *prev_sink;
     IServiceProvider *service_provider = NULL;
 
@@ -627,15 +582,6 @@ void set_binding_sink(IInternetProtocolEx *bind_protocol, IInternetProtocolSink
         IInternetBindInfo_Release(bind_info);
 }
 
-IWinInetInfo *get_wininet_info(IInternetProtocolEx *bind_protocol)
-{
-    BindProtocol *This = PROTOCOL_THIS(bind_protocol);
-
-    return This->wininet_info;
-}
-
-#undef PROTOCOL_THIS
-
 static const IInternetProtocolExVtbl BindProtocolVtbl = {
     BindProtocol_QueryInterface,
     BindProtocol_AddRef,
@@ -667,13 +613,13 @@ static HRESULT WINAPI ProtocolHandler_QueryInterface(IInternetProtocol *iface, R
 static ULONG WINAPI ProtocolHandler_AddRef(IInternetProtocol *iface)
 {
     BindProtocol *This = impl_from_IInternetProtocol(iface);
-    return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
+    return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
 }
 
 static ULONG WINAPI ProtocolHandler_Release(IInternetProtocol *iface)
 {
     BindProtocol *This = impl_from_IInternetProtocol(iface);
-    return IInternetProtocolEx_Release(PROTOCOLEX(This));
+    return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
 }
 
 static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR szUrl,
@@ -722,11 +668,11 @@ static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD
     IInternetProtocol_Terminate(This->protocol, 0);
 
     if(This->filter_proxy) {
-        IInternetProtocol_Release(PROTOCOL(This->filter_proxy));
+        IInternetProtocol_Release(&This->filter_proxy->IInternetProtocol_iface);
         This->filter_proxy = NULL;
     }
 
-    set_binding_sink(PROTOCOLEX(This), NULL, NULL);
+    set_binding_sink(This, NULL, NULL);
 
     if(This->bind_info) {
         IInternetBindInfo_Release(This->bind_info);
@@ -826,31 +772,34 @@ static const IInternetProtocolVtbl InternetProtocolHandlerVtbl = {
     ProtocolHandler_UnlockRequest
 };
 
-#define BINDINFO_THIS(iface) DEFINE_THIS(BindProtocol, InternetBindInfo, iface)
+static inline BindProtocol *impl_from_IInternetBindInfo(IInternetBindInfo *iface)
+{
+    return CONTAINING_RECORD(iface, BindProtocol, IInternetBindInfo_iface);
+}
 
 static HRESULT WINAPI BindInfo_QueryInterface(IInternetBindInfo *iface,
         REFIID riid, void **ppv)
 {
-    BindProtocol *This = BINDINFO_THIS(iface);
-    return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
+    BindProtocol *This = impl_from_IInternetBindInfo(iface);
+    return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
 }
 
 static ULONG WINAPI BindInfo_AddRef(IInternetBindInfo *iface)
 {
-    BindProtocol *This = BINDINFO_THIS(iface);
-    return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
+    BindProtocol *This = impl_from_IInternetBindInfo(iface);
+    return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
 }
 
 static ULONG WINAPI BindInfo_Release(IInternetBindInfo *iface)
 {
-    BindProtocol *This = BINDINFO_THIS(iface);
-    return IInternetProtocolEx_Release(PROTOCOLEX(This));
+    BindProtocol *This = impl_from_IInternetBindInfo(iface);
+    return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
 }
 
 static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
         DWORD *grfBINDF, BINDINFO *pbindinfo)
 {
-    BindProtocol *This = BINDINFO_THIS(iface);
+    BindProtocol *This = impl_from_IInternetBindInfo(iface);
     HRESULT hres;
 
     TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
@@ -868,15 +817,13 @@ static HRESULT WINAPI BindInfo_GetBindInfo(IInternetBindInfo *iface,
 static HRESULT WINAPI BindInfo_GetBindString(IInternetBindInfo *iface,
         ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched)
 {
-    BindProtocol *This = BINDINFO_THIS(iface);
+    BindProtocol *This = impl_from_IInternetBindInfo(iface);
 
     TRACE("(%p)->(%d %p %d %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched);
 
     return IInternetBindInfo_GetBindString(This->bind_info, ulStringType, ppwzStr, cEl, pcElFetched);
 }
 
-#undef BINDFO_THIS
-
 static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
     BindInfo_QueryInterface,
     BindInfo_AddRef,
@@ -885,30 +832,33 @@ static const IInternetBindInfoVtbl InternetBindInfoVtbl = {
     BindInfo_GetBindString
 };
 
-#define PRIORITY_THIS(iface) DEFINE_THIS(BindProtocol, InternetPriority, iface)
+static inline BindProtocol *impl_from_IInternetPriority(IInternetPriority *iface)
+{
+    return CONTAINING_RECORD(iface, BindProtocol, IInternetPriority_iface);
+}
 
 static HRESULT WINAPI InternetPriority_QueryInterface(IInternetPriority *iface,
         REFIID riid, void **ppv)
 {
-    BindProtocol *This = PRIORITY_THIS(iface);
-    return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
+    BindProtocol *This = impl_from_IInternetPriority(iface);
+    return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
 }
 
 static ULONG WINAPI InternetPriority_AddRef(IInternetPriority *iface)
 {
-    BindProtocol *This = PRIORITY_THIS(iface);
-    return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
+    BindProtocol *This = impl_from_IInternetPriority(iface);
+    return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
 }
 
 static ULONG WINAPI InternetPriority_Release(IInternetPriority *iface)
 {
-    BindProtocol *This = PRIORITY_THIS(iface);
-    return IInternetProtocolEx_Release(PROTOCOLEX(This));
+    BindProtocol *This = impl_from_IInternetPriority(iface);
+    return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
 }
 
 static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
 {
-    BindProtocol *This = PRIORITY_THIS(iface);
+    BindProtocol *This = impl_from_IInternetPriority(iface);
 
     TRACE("(%p)->(%d)\n", This, nPriority);
 
@@ -918,7 +868,7 @@ static HRESULT WINAPI InternetPriority_SetPriority(IInternetPriority *iface, LON
 
 static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
 {
-    BindProtocol *This = PRIORITY_THIS(iface);
+    BindProtocol *This = impl_from_IInternetPriority(iface);
 
     TRACE("(%p)->(%p)\n", This, pnPriority);
 
@@ -926,8 +876,6 @@ static HRESULT WINAPI InternetPriority_GetPriority(IInternetPriority *iface, LON
     return S_OK;
 }
 
-#undef PRIORITY_THIS
-
 static const IInternetPriorityVtbl InternetPriorityVtbl = {
     InternetPriority_QueryInterface,
     InternetPriority_AddRef,
@@ -937,25 +885,28 @@ static const IInternetPriorityVtbl InternetPriorityVtbl = {
 
 };
 
-#define PROTSINK_THIS(iface) DEFINE_THIS(BindProtocol, IInternetProtocolSink, iface)
+static inline BindProtocol *impl_from_IInternetProtocolSink(IInternetProtocolSink *iface)
+{
+    return CONTAINING_RECORD(iface, BindProtocol, IInternetProtocolSink_iface);
+}
 
 static HRESULT WINAPI BPInternetProtocolSink_QueryInterface(IInternetProtocolSink *iface,
         REFIID riid, void **ppv)
 {
-    BindProtocol *This = PROTSINK_THIS(iface);
-    return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
+    BindProtocol *This = impl_from_IInternetProtocolSink(iface);
+    return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
 }
 
 static ULONG WINAPI BPInternetProtocolSink_AddRef(IInternetProtocolSink *iface)
 {
-    BindProtocol *This = PROTSINK_THIS(iface);
-    return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
+    BindProtocol *This = impl_from_IInternetProtocolSink(iface);
+    return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
 }
 
 static ULONG WINAPI BPInternetProtocolSink_Release(IInternetProtocolSink *iface)
 {
-    BindProtocol *This = PROTSINK_THIS(iface);
-    return IInternetProtocolEx_Release(PROTOCOLEX(This));
+    BindProtocol *This = impl_from_IInternetProtocolSink(iface);
+    return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
 }
 
 typedef struct {
@@ -975,7 +926,7 @@ static void switch_proc(BindProtocol *bind, task_header_t *t)
 static HRESULT WINAPI BPInternetProtocolSink_Switch(IInternetProtocolSink *iface,
         PROTOCOLDATA *pProtocolData)
 {
-    BindProtocol *This = PROTSINK_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolSink(iface);
     PROTOCOLDATA *data;
 
     TRACE("(%p)->(%p)\n", This, pProtocolData);
@@ -1015,7 +966,6 @@ static void report_progress(BindProtocol *This, ULONG status_code, LPCWSTR statu
     case BINDSTATUS_FINDINGRESOURCE:
     case BINDSTATUS_CONNECTING:
     case BINDSTATUS_REDIRECTING:
-    case BINDSTATUS_BEGINDOWNLOADDATA:
     case BINDSTATUS_SENDINGREQUEST:
     case BINDSTATUS_CACHEFILENAMEAVAILABLE:
     case BINDSTATUS_DIRECTBIND:
@@ -1024,6 +974,11 @@ static void report_progress(BindProtocol *This, ULONG status_code, LPCWSTR statu
             IInternetProtocolSink_ReportProgress(This->protocol_sink, status_code, status_text);
         break;
 
+    case BINDSTATUS_BEGINDOWNLOADDATA:
+        if(This->protocol_sink)
+            IInternetProtocolSink_ReportData(This->protocol_sink, This->bscf, This->progress, This->progress_max);
+        break;
+
     case BINDSTATUS_MIMETYPEAVAILABLE:
         mime_available(This, status_text, FALSE);
         break;
@@ -1057,7 +1012,7 @@ static void on_progress_proc(BindProtocol *This, task_header_t *t)
 static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSink *iface,
         ULONG ulStatusCode, LPCWSTR szStatusText)
 {
-    BindProtocol *This = PROTSINK_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolSink(iface);
 
     TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
 
@@ -1079,6 +1034,10 @@ static HRESULT WINAPI BPInternetProtocolSink_ReportProgress(IInternetProtocolSin
 
 static HRESULT report_data(BindProtocol *This, DWORD bscf, ULONG progress, ULONG progress_max)
 {
+    This->bscf = bscf;
+    This->progress = progress;
+    This->progress_max = progress_max;
+
     if(!This->protocol_sink)
         return S_OK;
 
@@ -1161,7 +1120,7 @@ static void report_data_proc(BindProtocol *This, task_header_t *t)
 static HRESULT WINAPI BPInternetProtocolSink_ReportData(IInternetProtocolSink *iface,
         DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
 {
-    BindProtocol *This = PROTSINK_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolSink(iface);
 
     TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
 
@@ -1208,7 +1167,7 @@ static void report_result_proc(BindProtocol *This, task_header_t *t)
 static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink *iface,
         HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
 {
-    BindProtocol *This = PROTSINK_THIS(iface);
+    BindProtocol *This = impl_from_IInternetProtocolSink(iface);
 
     TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
 
@@ -1235,8 +1194,6 @@ static HRESULT WINAPI BPInternetProtocolSink_ReportResult(IInternetProtocolSink
     return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
 }
 
-#undef PROTSINK_THIS
-
 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
     BPInternetProtocolSink_QueryInterface,
     BPInternetProtocolSink_AddRef,
@@ -1247,30 +1204,33 @@ static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
     BPInternetProtocolSink_ReportResult
 };
 
-#define INETINFO_THIS(iface) DEFINE_THIS(BindProtocol, IWinInetHttpInfo, iface)
+static inline BindProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface)
+{
+    return CONTAINING_RECORD(iface, BindProtocol, IWinInetHttpInfo_iface);
+}
 
 static HRESULT WINAPI WinInetHttpInfo_QueryInterface(IWinInetHttpInfo *iface, REFIID riid, void **ppv)
 {
-    BindProtocol *This = INETINFO_THIS(iface);
-    return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
+    BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
+    return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
 }
 
 static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface)
 {
-    BindProtocol *This = INETINFO_THIS(iface);
-    return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
+    BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
+    return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
 }
 
 static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface)
 {
-    BindProtocol *This = INETINFO_THIS(iface);
-    return IInternetProtocolEx_Release(PROTOCOLEX(This));
+    BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
+    return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
 }
 
 static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOption,
         void *pBuffer, DWORD *pcbBuffer)
 {
-    BindProtocol *This = INETINFO_THIS(iface);
+    BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
     FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
     return E_NOTIMPL;
 }
@@ -1278,13 +1238,11 @@ static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD
 static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
         void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
 {
-    BindProtocol *This = INETINFO_THIS(iface);
+    BindProtocol *This = impl_from_IWinInetHttpInfo(iface);
     FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
     return E_NOTIMPL;
 }
 
-#undef INETINFO_THIS
-
 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
     WinInetHttpInfo_QueryInterface,
     WinInetHttpInfo_AddRef,
@@ -1293,31 +1251,34 @@ static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
     WinInetHttpInfo_QueryInfo
 };
 
-#define SERVPROV_THIS(iface) DEFINE_THIS(BindProtocol, ServiceProvider, iface)
+static inline BindProtocol *impl_from_IServiceProvider(IServiceProvider *iface)
+{
+    return CONTAINING_RECORD(iface, BindProtocol, IServiceProvider_iface);
+}
 
 static HRESULT WINAPI BPServiceProvider_QueryInterface(IServiceProvider *iface,
         REFIID riid, void **ppv)
 {
-    BindProtocol *This = SERVPROV_THIS(iface);
-    return IInternetProtocolEx_QueryInterface(PROTOCOLEX(This), riid, ppv);
+    BindProtocol *This = impl_from_IServiceProvider(iface);
+    return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv);
 }
 
 static ULONG WINAPI BPServiceProvider_AddRef(IServiceProvider *iface)
 {
-    BindProtocol *This = SERVPROV_THIS(iface);
-    return IInternetProtocolEx_AddRef(PROTOCOLEX(This));
+    BindProtocol *This = impl_from_IServiceProvider(iface);
+    return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface);
 }
 
 static ULONG WINAPI BPServiceProvider_Release(IServiceProvider *iface)
 {
-    BindProtocol *This = SERVPROV_THIS(iface);
-    return IInternetProtocolEx_Release(PROTOCOLEX(This));
+    BindProtocol *This = impl_from_IServiceProvider(iface);
+    return IInternetProtocolEx_Release(&This->IInternetProtocolEx_iface);
 }
 
 static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
         REFGUID guidService, REFIID riid, void **ppv)
 {
-    BindProtocol *This = SERVPROV_THIS(iface);
+    BindProtocol *This = impl_from_IServiceProvider(iface);
 
     TRACE("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv);
 
@@ -1327,8 +1288,6 @@ static HRESULT WINAPI BPServiceProvider_QueryService(IServiceProvider *iface,
     return IServiceProvider_QueryService(This->service_provider, guidService, riid, ppv);
 }
 
-#undef SERVPROV_THIS
-
 static const IServiceProviderVtbl ServiceProviderVtbl = {
     BPServiceProvider_QueryInterface,
     BPServiceProvider_AddRef,
@@ -1336,16 +1295,16 @@ static const IServiceProviderVtbl ServiceProviderVtbl = {
     BPServiceProvider_QueryService
 };
 
-HRESULT create_binding_protocol(BOOL from_urlmon, IInternetProtocolEx **protocol)
+HRESULT create_binding_protocol(BOOL from_urlmon, BindProtocol **protocol)
 {
     BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol));
 
-    ret->lpIInternetProtocolExVtbl      = &BindProtocolVtbl;
-    ret->lpInternetBindInfoVtbl         = &InternetBindInfoVtbl;
-    ret->lpInternetPriorityVtbl         = &InternetPriorityVtbl;
-    ret->lpServiceProviderVtbl          = &ServiceProviderVtbl;
-    ret->lpIInternetProtocolSinkVtbl    = &InternetProtocolSinkVtbl;
-    ret->lpIWinInetHttpInfoVtbl         = &WinInetHttpInfoVtbl;
+    ret->IInternetProtocolEx_iface.lpVtbl   = &BindProtocolVtbl;
+    ret->IInternetBindInfo_iface.lpVtbl     = &InternetBindInfoVtbl;
+    ret->IInternetPriority_iface.lpVtbl     = &InternetPriorityVtbl;
+    ret->IServiceProvider_iface.lpVtbl      = &ServiceProviderVtbl;
+    ret->IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkVtbl;
+    ret->IWinInetHttpInfo_iface.lpVtbl      = &WinInetHttpInfoVtbl;
 
     ret->default_protocol_handler.IInternetProtocol_iface.lpVtbl = &InternetProtocolHandlerVtbl;
 
@@ -1358,6 +1317,6 @@ HRESULT create_binding_protocol(BOOL from_urlmon, IInternetProtocolEx **protocol
 
     URLMON_LockModule();
 
-    *protocol = PROTOCOLEX(ret);
+    *protocol = ret;
     return S_OK;
 }
index 9759e71..c20c87c 100644 (file)
@@ -28,6 +28,7 @@ typedef struct {
     LONG ref;
 
     IBindStatusCallback *callback;
+    IBinding *binding;
     LPWSTR file_name;
     LPWSTR cache_file;
 } DownloadBSC;
@@ -89,6 +90,8 @@ static ULONG WINAPI DownloadBSC_Release(IBindStatusCallback *iface)
     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);
@@ -101,13 +104,19 @@ static HRESULT WINAPI DownloadBSC_OnStartBinding(IBindStatusCallback *iface,
         DWORD dwReserved, IBinding *pbind)
 {
     DownloadBSC *This = impl_from_IBindStatusCallback(iface);
+    HRESULT hres = S_OK;
 
     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)
@@ -132,6 +141,13 @@ static HRESULT on_progress(DownloadBSC *This, ULONG progress, ULONG progress_max
         return S_OK;
 
     hres = IBindStatusCallback_OnProgress(This->callback, progress, progress_max, status_code, status_text);
+    if(hres == E_ABORT) {
+        if(This->binding)
+            IBinding_Abort(This->binding);
+        else
+            FIXME("No binding, not sure what to do!\n");
+    }
+
     return hres;
 }
 
@@ -191,6 +207,11 @@ static HRESULT WINAPI DownloadBSC_OnStopBinding(IBindStatusCallback *iface,
     if(This->callback)
         IBindStatusCallback_OnStopBinding(This->callback, hresult, szError);
 
+    if(This->binding) {
+        IBinding_Release(This->binding);
+        This->binding = NULL;
+    }
+
     return S_OK;
 }
 
@@ -311,6 +332,7 @@ static HRESULT DownloadBSC_Create(IBindStatusCallback *callback, LPCWSTR file_na
     ret->ref = 1;
     ret->file_name = heap_strdupW(file_name);
     ret->cache_file = NULL;
+    ret->binding = NULL;
 
     if(callback)
         IBindStatusCallback_AddRef(callback);
index deb611b..04cf49c 100644 (file)
@@ -50,12 +50,15 @@ static inline FtpProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface)
     return CONTAINING_RECORD(iface, FtpProtocol, IWinInetHttpInfo_iface);
 }
 
-#define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(FtpProtocol, base, iface)
+static inline FtpProtocol *impl_from_Protocol(Protocol *prot)
+{
+    return CONTAINING_RECORD(prot, FtpProtocol, base);
+}
 
 static HRESULT FtpProtocol_open_request(Protocol *prot, IUri *uri, DWORD request_flags,
         HINTERNET internet_session, IInternetBindInfo *bind_info)
 {
-    FtpProtocol *This = ASYNCPROTOCOL_THIS(prot);
+    FtpProtocol *This = impl_from_Protocol(prot);
     BSTR url;
     HRESULT hres;
 
@@ -82,7 +85,7 @@ static HRESULT FtpProtocol_end_request(Protocol *prot)
 
 static HRESULT FtpProtocol_start_downloading(Protocol *prot)
 {
-    FtpProtocol *This = ASYNCPROTOCOL_THIS(prot);
+    FtpProtocol *This = impl_from_Protocol(prot);
     DWORD size;
     BOOL res;
 
@@ -99,13 +102,17 @@ static void FtpProtocol_close_connection(Protocol *prot)
 {
 }
 
-#undef ASYNCPROTOCOL_THIS
+static void FtpProtocol_on_error(Protocol *prot, DWORD error)
+{
+    FIXME("(%p) %d - stub\n", prot, error);
+}
 
 static const ProtocolVtbl AsyncProtocolVtbl = {
     FtpProtocol_open_request,
     FtpProtocol_end_request,
     FtpProtocol_start_downloading,
-    FtpProtocol_close_connection
+    FtpProtocol_close_connection,
+    FtpProtocol_on_error
 };
 
 static HRESULT WINAPI FtpProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
@@ -377,16 +384,28 @@ static HRESULT WINAPI HttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOpti
         void *pBuffer, DWORD *pcbBuffer)
 {
     FtpProtocol *This = impl_from_IWinInetHttpInfo(iface);
-    FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
-    return E_NOTIMPL;
+    TRACE("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
+
+    if(!This->base.request)
+        return E_FAIL;
+
+    if(!InternetQueryOptionW(This->base.request, dwOption, pBuffer, pcbBuffer))
+        return S_FALSE;
+    return S_OK;
 }
 
 static HRESULT WINAPI HttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
         void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
 {
     FtpProtocol *This = impl_from_IWinInetHttpInfo(iface);
-    FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
-    return E_NOTIMPL;
+    TRACE("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
+
+    if(!This->base.request)
+        return E_FAIL;
+
+    if(!HttpQueryInfoW(This->base.request, dwOption, pBuffer, pcbBuffer, pdwFlags))
+        return S_FALSE;
+    return S_OK;
 }
 
 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
index da241e9..4087ed5 100644 (file)
@@ -24,20 +24,21 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
 typedef struct {
     Protocol base;
 
-    const IInternetProtocolVtbl  *lpIInternetProtocolVtbl;
-    const IInternetPriorityVtbl  *lpInternetPriorityVtbl;
+    IInternetProtocol IInternetProtocol_iface;
+    IInternetPriority IInternetPriority_iface;
 
     LONG ref;
 } GopherProtocol;
 
-#define PRIORITY(x)  ((IInternetPriority*)  &(x)->lpInternetPriorityVtbl)
-
-#define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(GopherProtocol, base, iface)
+static inline GopherProtocol *impl_from_Protocol(Protocol *prot)
+{
+    return CONTAINING_RECORD(prot, GopherProtocol, base);
+}
 
 static HRESULT GopherProtocol_open_request(Protocol *prot, IUri *uri, DWORD request_flags,
         HINTERNET internet_session, IInternetBindInfo *bind_info)
 {
-    GopherProtocol *This = ASYNCPROTOCOL_THIS(prot);
+    GopherProtocol *This = impl_from_Protocol(prot);
     BSTR url;
     HRESULT hres;
 
@@ -70,34 +71,41 @@ static void GopherProtocol_close_connection(Protocol *prot)
 {
 }
 
-#undef ASYNCPROTOCOL_THIS
+static void GopherProtocol_on_error(Protocol *prot, DWORD error)
+{
+    FIXME("(%p) %d - stub\n", prot, error);
+}
 
 static const ProtocolVtbl AsyncProtocolVtbl = {
     GopherProtocol_open_request,
     GopherProtocol_end_request,
     GopherProtocol_start_downloading,
-    GopherProtocol_close_connection
+    GopherProtocol_close_connection,
+    GopherProtocol_on_error
 };
 
-#define PROTOCOL_THIS(iface) DEFINE_THIS(GopherProtocol, IInternetProtocol, iface)
+static inline GopherProtocol *impl_from_IInternetProtocol(IInternetProtocol *iface)
+{
+    return CONTAINING_RECORD(iface, GopherProtocol, IInternetProtocol_iface);
+}
 
 static HRESULT WINAPI GopherProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
 {
-    GopherProtocol *This = PROTOCOL_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetProtocol(iface);
 
     *ppv = NULL;
     if(IsEqualGUID(&IID_IUnknown, riid)) {
         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
-        *ppv = PROTOCOL(This);
+        *ppv = &This->IInternetProtocol_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
-        *ppv = PROTOCOL(This);
+        *ppv = &This->IInternetProtocol_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
         TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
-        *ppv = PROTOCOL(This);
+        *ppv = &This->IInternetProtocol_iface;
     }else if(IsEqualGUID(&IID_IInternetPriority, riid)) {
         TRACE("(%p)->(IID_IInternetPriority %p)\n", This, ppv);
-        *ppv = PRIORITY(This);
+        *ppv = &This->IInternetPriority_iface;
     }
 
     if(*ppv) {
@@ -111,7 +119,7 @@ static HRESULT WINAPI GopherProtocol_QueryInterface(IInternetProtocol *iface, RE
 
 static ULONG WINAPI GopherProtocol_AddRef(IInternetProtocol *iface)
 {
-    GopherProtocol *This = PROTOCOL_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetProtocol(iface);
     LONG ref = InterlockedIncrement(&This->ref);
     TRACE("(%p) ref=%d\n", This, ref);
     return ref;
@@ -119,7 +127,7 @@ static ULONG WINAPI GopherProtocol_AddRef(IInternetProtocol *iface)
 
 static ULONG WINAPI GopherProtocol_Release(IInternetProtocol *iface)
 {
-    GopherProtocol *This = PROTOCOL_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetProtocol(iface);
     LONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) ref=%d\n", This, ref);
@@ -137,7 +145,7 @@ static HRESULT WINAPI GopherProtocol_Start(IInternetProtocol *iface, LPCWSTR szU
         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
         DWORD grfPI, HANDLE_PTR dwReserved)
 {
-    GopherProtocol *This = PROTOCOL_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetProtocol(iface);
     IUri *uri;
     HRESULT hres;
 
@@ -148,7 +156,8 @@ static HRESULT WINAPI GopherProtocol_Start(IInternetProtocol *iface, LPCWSTR szU
     if(FAILED(hres))
         return hres;
 
-    hres = protocol_start(&This->base, PROTOCOL(This), uri, pOIProtSink, pOIBindInfo);
+    hres = protocol_start(&This->base, &This->IInternetProtocol_iface, uri, pOIProtSink,
+            pOIBindInfo);
 
     IUri_Release(uri);
     return hres;
@@ -156,7 +165,7 @@ static HRESULT WINAPI GopherProtocol_Start(IInternetProtocol *iface, LPCWSTR szU
 
 static HRESULT WINAPI GopherProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
 {
-    GopherProtocol *This = PROTOCOL_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetProtocol(iface);
 
     TRACE("(%p)->(%p)\n", This, pProtocolData);
 
@@ -166,7 +175,7 @@ static HRESULT WINAPI GopherProtocol_Continue(IInternetProtocol *iface, PROTOCOL
 static HRESULT WINAPI GopherProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
         DWORD dwOptions)
 {
-    GopherProtocol *This = PROTOCOL_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetProtocol(iface);
 
     TRACE("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
 
@@ -175,7 +184,7 @@ static HRESULT WINAPI GopherProtocol_Abort(IInternetProtocol *iface, HRESULT hrR
 
 static HRESULT WINAPI GopherProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
 {
-    GopherProtocol *This = PROTOCOL_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetProtocol(iface);
 
     TRACE("(%p)->(%08x)\n", This, dwOptions);
 
@@ -185,14 +194,14 @@ static HRESULT WINAPI GopherProtocol_Terminate(IInternetProtocol *iface, DWORD d
 
 static HRESULT WINAPI GopherProtocol_Suspend(IInternetProtocol *iface)
 {
-    GopherProtocol *This = PROTOCOL_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)\n", This);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI GopherProtocol_Resume(IInternetProtocol *iface)
 {
-    GopherProtocol *This = PROTOCOL_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)\n", This);
     return E_NOTIMPL;
 }
@@ -200,7 +209,7 @@ static HRESULT WINAPI GopherProtocol_Resume(IInternetProtocol *iface)
 static HRESULT WINAPI GopherProtocol_Read(IInternetProtocol *iface, void *pv,
         ULONG cb, ULONG *pcbRead)
 {
-    GopherProtocol *This = PROTOCOL_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetProtocol(iface);
 
     TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
 
@@ -210,14 +219,14 @@ static HRESULT WINAPI GopherProtocol_Read(IInternetProtocol *iface, void *pv,
 static HRESULT WINAPI GopherProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
         DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
 {
-    GopherProtocol *This = PROTOCOL_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI GopherProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
 {
-    GopherProtocol *This = PROTOCOL_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetProtocol(iface);
 
     TRACE("(%p)->(%08x)\n", This, dwOptions);
 
@@ -226,15 +235,13 @@ static HRESULT WINAPI GopherProtocol_LockRequest(IInternetProtocol *iface, DWORD
 
 static HRESULT WINAPI GopherProtocol_UnlockRequest(IInternetProtocol *iface)
 {
-    GopherProtocol *This = PROTOCOL_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetProtocol(iface);
 
     TRACE("(%p)\n", This);
 
     return protocol_unlock_request(&This->base);
 }
 
-#undef PROTOCOL_THIS
-
 static const IInternetProtocolVtbl GopherProtocolVtbl = {
     GopherProtocol_QueryInterface,
     GopherProtocol_AddRef,
@@ -251,29 +258,32 @@ static const IInternetProtocolVtbl GopherProtocolVtbl = {
     GopherProtocol_UnlockRequest
 };
 
-#define PRIORITY_THIS(iface) DEFINE_THIS(GopherProtocol, InternetPriority, iface)
+static inline GopherProtocol *impl_from_IInternetPriority(IInternetPriority *iface)
+{
+    return CONTAINING_RECORD(iface, GopherProtocol, IInternetPriority_iface);
+}
 
 static HRESULT WINAPI GopherPriority_QueryInterface(IInternetPriority *iface, REFIID riid, void **ppv)
 {
-    GopherProtocol *This = PRIORITY_THIS(iface);
-    return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
+    GopherProtocol *This = impl_from_IInternetPriority(iface);
+    return IInternetProtocol_QueryInterface(&This->IInternetProtocol_iface, riid, ppv);
 }
 
 static ULONG WINAPI GopherPriority_AddRef(IInternetPriority *iface)
 {
-    GopherProtocol *This = PRIORITY_THIS(iface);
-    return IInternetProtocol_AddRef(PROTOCOL(This));
+    GopherProtocol *This = impl_from_IInternetPriority(iface);
+    return IInternetProtocol_AddRef(&This->IInternetProtocol_iface);
 }
 
 static ULONG WINAPI GopherPriority_Release(IInternetPriority *iface)
 {
-    GopherProtocol *This = PRIORITY_THIS(iface);
-    return IInternetProtocol_Release(PROTOCOL(This));
+    GopherProtocol *This = impl_from_IInternetPriority(iface);
+    return IInternetProtocol_Release(&This->IInternetProtocol_iface);
 }
 
 static HRESULT WINAPI GopherPriority_SetPriority(IInternetPriority *iface, LONG nPriority)
 {
-    GopherProtocol *This = PRIORITY_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetPriority(iface);
 
     TRACE("(%p)->(%d)\n", This, nPriority);
 
@@ -283,7 +293,7 @@ static HRESULT WINAPI GopherPriority_SetPriority(IInternetPriority *iface, LONG
 
 static HRESULT WINAPI GopherPriority_GetPriority(IInternetPriority *iface, LONG *pnPriority)
 {
-    GopherProtocol *This = PRIORITY_THIS(iface);
+    GopherProtocol *This = impl_from_IInternetPriority(iface);
 
     TRACE("(%p)->(%p)\n", This, pnPriority);
 
@@ -291,8 +301,6 @@ static HRESULT WINAPI GopherPriority_GetPriority(IInternetPriority *iface, LONG
     return S_OK;
 }
 
-#undef PRIORITY_THIS
-
 static const IInternetPriorityVtbl GopherPriorityVtbl = {
     GopherPriority_QueryInterface,
     GopherPriority_AddRef,
@@ -312,11 +320,11 @@ HRESULT GopherProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
     ret = heap_alloc_zero(sizeof(GopherProtocol));
 
     ret->base.vtbl = &AsyncProtocolVtbl;
-    ret->lpIInternetProtocolVtbl = &GopherProtocolVtbl;
-    ret->lpInternetPriorityVtbl  = &GopherPriorityVtbl;
+    ret->IInternetProtocol_iface.lpVtbl = &GopherProtocolVtbl;
+    ret->IInternetPriority_iface.lpVtbl = &GopherPriorityVtbl;
     ret->ref = 1;
 
-    *ppobj = PROTOCOL(ret);
+    *ppobj = &ret->IInternetProtocol_iface;
 
     return S_OK;
 }
index 2aaefb0..5a606ca 100644 (file)
@@ -36,7 +36,7 @@ typedef struct {
 
     BOOL https;
     IHttpNegotiate *http_negotiate;
-    LPWSTR full_header;
+    WCHAR *full_header;
 
     LONG ref;
 } HttpProtocol;
@@ -56,9 +56,8 @@ static inline HttpProtocol *impl_from_IWinInetHttpInfo(IWinInetHttpInfo *iface)
     return CONTAINING_RECORD(iface, HttpProtocol, IWinInetHttpInfo_iface);
 }
 
-/* Default headers from native */
-static const WCHAR wszHeaders[] = {'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g',
-                                   ':',' ','g','z','i','p',',',' ','d','e','f','l','a','t','e',0};
+static const WCHAR default_headersW[] = {
+    'A','c','c','e','p','t','-','E','n','c','o','d','i','n','g',':',' ','g','z','i','p',',',' ','d','e','f','l','a','t','e',0};
 
 static LPWSTR query_http_info(HttpProtocol *This, DWORD option)
 {
@@ -80,13 +79,196 @@ static LPWSTR query_http_info(HttpProtocol *This, DWORD option)
     return ret;
 }
 
-#define ASYNCPROTOCOL_THIS(iface) DEFINE_THIS2(HttpProtocol, base, iface)
+static inline BOOL set_security_flag(HttpProtocol *This, DWORD new_flag)
+{
+    DWORD flags, size = sizeof(flags);
+    BOOL res;
+
+    res = InternetQueryOptionW(This->base.request, INTERNET_OPTION_SECURITY_FLAGS, &flags, &size);
+    if(res) {
+        flags |= new_flag;
+        res = InternetSetOptionW(This->base.request, INTERNET_OPTION_SECURITY_FLAGS, &flags, size);
+    }
+    if(!res)
+        ERR("Failed to set security flag(s): %x\n", new_flag);
+
+    return res;
+}
+
+static inline HRESULT internet_error_to_hres(DWORD error)
+{
+    switch(error)
+    {
+    case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
+    case ERROR_INTERNET_SEC_CERT_CN_INVALID:
+    case ERROR_INTERNET_INVALID_CA:
+    case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
+        return INET_E_INVALID_CERTIFICATE;
+    case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
+    case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR:
+    case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION:
+        return INET_E_REDIRECT_FAILED;
+    default:
+        return INET_E_DOWNLOAD_FAILURE;
+    }
+}
+
+static HRESULT handle_http_error(HttpProtocol *This, DWORD error)
+{
+    IServiceProvider *serv_prov;
+    IWindowForBindingUI *wfb_ui;
+    IHttpSecurity *http_security;
+    BOOL security_problem;
+    HRESULT hres;
+
+    switch(error) {
+    case ERROR_INTERNET_SEC_CERT_DATE_INVALID:
+    case ERROR_INTERNET_SEC_CERT_CN_INVALID:
+    case ERROR_INTERNET_HTTP_TO_HTTPS_ON_REDIR:
+    case ERROR_INTERNET_HTTPS_TO_HTTP_ON_REDIR:
+    case ERROR_HTTP_REDIRECT_NEEDS_CONFIRMATION:
+    case ERROR_INTERNET_INVALID_CA:
+    case ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED:
+        security_problem = TRUE;
+        break;
+    default:
+        security_problem = FALSE;
+    }
+
+    hres = IInternetProtocolSink_QueryInterface(This->base.protocol_sink, &IID_IServiceProvider,
+                                                (void**)&serv_prov);
+    if(FAILED(hres)) {
+        ERR("Failed to get IServiceProvider.\n");
+        return E_ABORT;
+    }
+
+    if(security_problem) {
+        hres = IServiceProvider_QueryService(serv_prov, &IID_IHttpSecurity, &IID_IHttpSecurity,
+                                             (void**)&http_security);
+        if(SUCCEEDED(hres)) {
+            hres = IHttpSecurity_OnSecurityProblem(http_security, error);
+            IHttpSecurity_Release(http_security);
+
+            if(hres != S_FALSE)
+            {
+                BOOL res = FALSE;
+
+                IServiceProvider_Release(serv_prov);
+
+                if(hres == S_OK) {
+                    if(error == ERROR_INTERNET_SEC_CERT_DATE_INVALID)
+                        res = set_security_flag(This, SECURITY_FLAG_IGNORE_CERT_DATE_INVALID);
+                    else if(error == ERROR_INTERNET_SEC_CERT_CN_INVALID)
+                        res = set_security_flag(This, SECURITY_FLAG_IGNORE_CERT_CN_INVALID);
+                    else if(error == ERROR_INTERNET_INVALID_CA)
+                        res = set_security_flag(This, SECURITY_FLAG_IGNORE_UNKNOWN_CA);
+
+                    if(res)
+                        return RPC_E_RETRY;
+
+                    FIXME("Don't know how to ignore error %d\n", error);
+                    return E_ABORT;
+                }
+
+                if(hres == E_ABORT)
+                    return E_ABORT;
+                if(hres == RPC_E_RETRY)
+                    return RPC_E_RETRY;
+
+                return internet_error_to_hres(error);
+            }
+        }
+    }
+
+    hres = IServiceProvider_QueryService(serv_prov, &IID_IWindowForBindingUI, &IID_IWindowForBindingUI,
+                                         (void**)&wfb_ui);
+    if(SUCCEEDED(hres)) {
+        HWND hwnd;
+        const IID *iid_reason;
+
+        if(security_problem)
+            iid_reason = &IID_IHttpSecurity;
+        else if(error == ERROR_INTERNET_INCORRECT_PASSWORD)
+            iid_reason = &IID_IAuthenticate;
+        else
+            iid_reason = &IID_IWindowForBindingUI;
+
+        hres = IWindowForBindingUI_GetWindow(wfb_ui, iid_reason, &hwnd);
+        if(SUCCEEDED(hres) && hwnd)
+        {
+            DWORD res;
+
+            res = InternetErrorDlg(hwnd, This->base.request, error,
+                                   FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS | FLAGS_ERROR_UI_FLAGS_GENERATE_DATA,
+                                   NULL);
+
+            if(res == ERROR_INTERNET_FORCE_RETRY || res == ERROR_SUCCESS)
+                hres = RPC_E_RETRY;
+            else
+                hres = E_FAIL;
+        }
+        IWindowForBindingUI_Release(wfb_ui);
+    }
+
+    IServiceProvider_Release(serv_prov);
+
+    if(hres == RPC_E_RETRY)
+        return hres;
+
+    return internet_error_to_hres(error);
+}
+
+static ULONG send_http_request(HttpProtocol *This)
+{
+    INTERNET_BUFFERSW send_buffer = {sizeof(INTERNET_BUFFERSW)};
+    BOOL res;
+
+    send_buffer.lpcszHeader = This->full_header;
+    send_buffer.dwHeadersLength = send_buffer.dwHeadersTotal = strlenW(This->full_header);
+
+    if(This->base.bind_info.dwBindVerb != BINDVERB_GET) {
+        switch(This->base.bind_info.stgmedData.tymed) {
+        case TYMED_HGLOBAL:
+            /* Native does not use GlobalLock/GlobalUnlock, so we won't either */
+            send_buffer.lpvBuffer = This->base.bind_info.stgmedData.u.hGlobal;
+            send_buffer.dwBufferLength = send_buffer.dwBufferTotal = This->base.bind_info.cbstgmedData;
+            break;
+        case TYMED_ISTREAM: {
+            LARGE_INTEGER offset;
+
+            send_buffer.dwBufferTotal = This->base.bind_info.cbstgmedData;
+            if(!This->base.post_stream) {
+                This->base.post_stream = This->base.bind_info.stgmedData.u.pstm;
+                IStream_AddRef(This->base.post_stream);
+            }
+
+            offset.QuadPart = 0;
+            IStream_Seek(This->base.post_stream, offset, STREAM_SEEK_SET, NULL);
+            break;
+        }
+        default:
+            FIXME("Unsupported This->base.bind_info.stgmedData.tymed %d\n", This->base.bind_info.stgmedData.tymed);
+        }
+    }
+
+    if(This->base.post_stream)
+        res = HttpSendRequestExW(This->base.request, &send_buffer, NULL, 0, 0);
+    else
+        res = HttpSendRequestW(This->base.request, send_buffer.lpcszHeader, send_buffer.dwHeadersLength,
+                send_buffer.lpvBuffer, send_buffer.dwBufferLength);
+
+    return res ? 0 : GetLastError();
+}
+
+static inline HttpProtocol *impl_from_Protocol(Protocol *prot)
+{
+    return CONTAINING_RECORD(prot, HttpProtocol, base);
+}
 
 static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD request_flags,
         HINTERNET internet_session, IInternetBindInfo *bind_info)
 {
-    HttpProtocol *This = ASYNCPROTOCOL_THIS(prot);
-    INTERNET_BUFFERSW send_buffer = {sizeof(INTERNET_BUFFERSW)};
+    HttpProtocol *This = impl_from_Protocol(prot);
     LPWSTR addl_header = NULL, post_cookie = NULL;
     IServiceProvider *service_provider = NULL;
     IHttpNegotiate2 *http_negotiate2 = NULL;
@@ -94,8 +276,8 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques
     LPOLESTR accept_mimes[257];
     const WCHAR **accept_types;
     BYTE security_id[512];
-    DWORD len = 0, port;
-    ULONG num;
+    DWORD len, port;
+    ULONG num, error;
     BOOL res, b;
     HRESULT hres;
 
@@ -188,7 +370,7 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques
         return hres;
     }
 
-    hres = IHttpNegotiate_BeginningTransaction(This->http_negotiate, url, wszHeaders,
+    hres = IHttpNegotiate_BeginningTransaction(This->http_negotiate, url, default_headersW,
             0, &addl_header);
     SysFreeString(url);
     if(hres != S_OK) {
@@ -197,18 +379,19 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques
         return hres;
     }
 
-    if(addl_header) {
-        int len_addl_header = strlenW(addl_header);
+    len = addl_header ? strlenW(addl_header) : 0;
 
-        This->full_header = heap_alloc(len_addl_header*sizeof(WCHAR)+sizeof(wszHeaders));
-
-        lstrcpyW(This->full_header, addl_header);
-        lstrcpyW(&This->full_header[len_addl_header], wszHeaders);
-        CoTaskMemFree(addl_header);
-    }else {
-        This->full_header = (LPWSTR)wszHeaders;
+    This->full_header = heap_alloc(len*sizeof(WCHAR)+sizeof(default_headersW));
+    if(!This->full_header) {
+        IServiceProvider_Release(service_provider);
+        return E_OUTOFMEMORY;
     }
 
+    if(len)
+        memcpy(This->full_header, addl_header, len*sizeof(WCHAR));
+    CoTaskMemFree(addl_header);
+    memcpy(This->full_header+len, default_headersW, sizeof(default_headersW));
+
     hres = IServiceProvider_QueryService(service_provider, &IID_IHttpNegotiate2,
             &IID_IHttpNegotiate2, (void **)&http_negotiate2);
     IServiceProvider_Release(service_provider);
@@ -236,48 +419,23 @@ static HRESULT HttpProtocol_open_request(Protocol *prot, IUri *uri, DWORD reques
         }
     }
 
-    send_buffer.lpcszHeader = This->full_header;
-    send_buffer.dwHeadersLength = send_buffer.dwHeadersTotal = strlenW(This->full_header);
-
-    if(This->base.bind_info.dwBindVerb != BINDVERB_GET) {
-        switch(This->base.bind_info.stgmedData.tymed) {
-        case TYMED_HGLOBAL:
-            /* Native does not use GlobalLock/GlobalUnlock, so we won't either */
-            send_buffer.lpvBuffer = This->base.bind_info.stgmedData.u.hGlobal;
-            send_buffer.dwBufferLength = send_buffer.dwBufferTotal = This->base.bind_info.cbstgmedData;
-            break;
-        case TYMED_ISTREAM: {
-            LARGE_INTEGER offset;
-
-            send_buffer.dwBufferTotal = This->base.bind_info.cbstgmedData;
-            This->base.post_stream = This->base.bind_info.stgmedData.u.pstm;
-            IStream_AddRef(This->base.post_stream);
-
-            offset.QuadPart = 0;
-            IStream_Seek(This->base.post_stream, offset, STREAM_SEEK_SET, NULL);
-            break;
-        }
-        default:
-            FIXME("Unsupported This->base.bind_info.stgmedData.tymed %d\n", This->base.bind_info.stgmedData.tymed);
-        }
-    }
-
     b = TRUE;
     res = InternetSetOptionW(This->base.request, INTERNET_OPTION_HTTP_DECODING, &b, sizeof(b));
     if(!res)
         WARN("InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %08x\n", GetLastError());
 
-    if(This->base.post_stream)
-        res = HttpSendRequestExW(This->base.request, &send_buffer, NULL, 0, 0);
-    else
-        res = HttpSendRequestW(This->base.request, send_buffer.lpcszHeader, send_buffer.dwHeadersLength,
-                send_buffer.lpvBuffer, send_buffer.dwBufferLength);
-    if(!res && GetLastError() != ERROR_IO_PENDING) {
-        WARN("HttpSendRequest failed: %d\n", GetLastError());
-        return INET_E_DOWNLOAD_FAILURE;
-    }
+    do {
+        error = send_http_request(This);
 
-    return S_OK;
+        if(error == ERROR_IO_PENDING || error == ERROR_SUCCESS)
+            return S_OK;
+
+        hres = handle_http_error(This, error);
+
+    } while(hres == RPC_E_RETRY);
+
+    WARN("HttpSendRequest failed: %d\n", error);
+    return hres;
 }
 
 static HRESULT HttpProtocol_end_request(Protocol *protocol)
@@ -295,7 +453,7 @@ static HRESULT HttpProtocol_end_request(Protocol *protocol)
 
 static HRESULT HttpProtocol_start_downloading(Protocol *prot)
 {
-    HttpProtocol *This = ASYNCPROTOCOL_THIS(prot);
+    HttpProtocol *This = impl_from_Protocol(prot);
     LPWSTR content_type, content_length, ranges;
     DWORD len = sizeof(DWORD);
     DWORD status_code;
@@ -363,27 +521,49 @@ static HRESULT HttpProtocol_start_downloading(Protocol *prot)
 
 static void HttpProtocol_close_connection(Protocol *prot)
 {
-    HttpProtocol *This = ASYNCPROTOCOL_THIS(prot);
+    HttpProtocol *This = impl_from_Protocol(prot);
 
     if(This->http_negotiate) {
         IHttpNegotiate_Release(This->http_negotiate);
-        This->http_negotiate = 0;
+        This->http_negotiate = NULL;
     }
 
     if(This->full_header) {
-        if(This->full_header != wszHeaders)
-            heap_free(This->full_header);
-        This->full_header = 0;
+        heap_free(This->full_header);
+        This->full_header = NULL;
     }
 }
 
-#undef ASYNCPROTOCOL_THIS
+static void HttpProtocol_on_error(Protocol *prot, DWORD error)
+{
+    HttpProtocol *This = impl_from_Protocol(prot);
+    HRESULT hres;
+
+    TRACE("(%p) %d\n", prot, error);
+
+    if(prot->flags & FLAG_FIRST_CONTINUE_COMPLETE) {
+        FIXME("Not handling error %d\n", error);
+        return;
+    }
+
+    while((hres = handle_http_error(This, error)) == RPC_E_RETRY) {
+        error = send_http_request(This);
+
+        if(error == ERROR_IO_PENDING || error == ERROR_SUCCESS)
+            return;
+    }
+
+    protocol_abort(prot, hres);
+    protocol_close_connection(prot);
+    return;
+}
 
 static const ProtocolVtbl AsyncProtocolVtbl = {
     HttpProtocol_open_request,
     HttpProtocol_end_request,
     HttpProtocol_start_downloading,
-    HttpProtocol_close_connection
+    HttpProtocol_close_connection,
+    HttpProtocol_on_error
 };
 
 static HRESULT WINAPI HttpProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
@@ -655,16 +835,31 @@ static HRESULT WINAPI HttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD dwOpti
         void *pBuffer, DWORD *pcbBuffer)
 {
     HttpProtocol *This = impl_from_IWinInetHttpInfo(iface);
-    FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
-    return E_NOTIMPL;
+    TRACE("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer);
+
+    if(!This->base.request)
+        return E_FAIL;
+
+    if(!InternetQueryOptionW(This->base.request, dwOption, pBuffer, pcbBuffer))
+        return S_FALSE;
+    return S_OK;
 }
 
 static HRESULT WINAPI HttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
         void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
 {
     HttpProtocol *This = impl_from_IWinInetHttpInfo(iface);
-    FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
-    return E_NOTIMPL;
+    TRACE("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);
+
+    if(!This->base.request)
+        return E_FAIL;
+
+    if(!HttpQueryInfoW(This->base.request, dwOption, pBuffer, pcbBuffer, pdwFlags)) {
+        if(pBuffer)
+            memset(pBuffer, 0, *pcbBuffer);
+        return S_OK;
+    }
+    return S_OK;
 }
 
 static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = {
index 3d41def..3832c52 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2005 Jacek Caban
+ * Copyright 2011 Thomas Mullaly for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
 
 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
 
+static const WCHAR feature_control_keyW[] =
+    {'S','o','f','t','w','a','r','e','\\',
+     'M','i','c','r','o','s','o','f','t','\\',
+     'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r','\\',
+     'M','a','i','n','\\',
+     'F','e','a','t','u','r','e','C','o','n','t','r','o','l',0};
+
+static const WCHAR feature_object_cachingW[] =
+    {'F','E','A','T','U','R','E','_','O','B','J','E','C','T','_','C','A','C','H','I','N','G',0};
+static const WCHAR feature_zone_elevationW[] =
+    {'F','E','A','T','U','R','E','_','Z','O','N','E','_','E','L','E','V','A','T','I','O','N',0};
+static const WCHAR feature_mime_handlingW[] =
+    {'F','E','A','T','U','R','E','_','M','I','M','E','_','H','A','N','D','L','I','N','G',0};
+static const WCHAR feature_mime_sniffingW[] =
+    {'F','E','A','T','U','R','E','_','M','I','M','E','_','S','N','I','F','F','I','N','G',0};
+static const WCHAR feature_window_restrictionsW[] =
+    {'F','E','A','T','U','R','E','_','W','I','N','D','O','W','_','R','E','S','T','R','I','C','T','I','O','N','S',0};
+static const WCHAR feature_weboc_popupmanagementW[] =
+    {'F','E','A','T','U','R','E','_','W','E','B','O','C','_','P','O','P','U','P','M','A','N','A','G','E','M','E','N','T',0};
+static const WCHAR feature_behaviorsW[] =
+    {'F','E','A','T','U','R','E','_','B','E','H','A','V','I','O','R','S',0};
+static const WCHAR feature_disable_mk_protocolW[] =
+    {'F','E','A','T','U','R','E','_','D','I','S','A','B','L','E','_','M','K','_','P','R','O','T','O','C','O','L',0};
+static const WCHAR feature_localmachine_lockdownW[] =
+    {'F','E','A','T','U','R','E','_','L','O','C','A','L','M','A','C','H','I','N','E','_','L','O','C','K','D','O','W','N',0};
+static const WCHAR feature_securitybandW[] =
+    {'F','E','A','T','U','R','E','_','S','E','C','U','R','I','T','Y','B','A','N','D',0};
+static const WCHAR feature_restrict_activexinstallW[] =
+    {'F','E','A','T','U','R','E','_','R','E','S','T','R','I','C','T','_','A','C','T','I','V','E','X','I','N','S','T','A','L','L',0};
+static const WCHAR feature_validate_navigate_urlW[] =
+    {'F','E','A','T','U','R','E','_','V','A','L','I','D','A','T','E','_','N','A','V','I','G','A','T','E','_','U','R','L',0};
+static const WCHAR feature_restrict_filedownloadW[] =
+    {'F','E','A','T','U','R','E','_','R','E','S','T','R','I','C','T','_','F','I','L','E','D','O','W','N','L','O','A','D',0};
+static const WCHAR feature_addon_managementW[] =
+    {'F','E','A','T','U','R','E','_','A','D','D','O','N','_','M','A','N','A','G','E','M','E','N','T',0};
+static const WCHAR feature_protocol_lockdownW[] =
+    {'F','E','A','T','U','R','E','_','P','R','O','T','O','C','O','L','_','L','O','C','K','D','O','W','N',0};
+static const WCHAR feature_http_username_password_disableW[] =
+    {'F','E','A','T','U','R','E','_','H','T','T','P','_','U','S','E','R','N','A','M','E','_',
+     'P','A','S','S','W','O','R','D','_','D','I','S','A','B','L','E',0};
+static const WCHAR feature_safe_bindtoobjectW[] =
+    {'F','E','A','T','U','R','E','_','S','A','F','E','_','B','I','N','D','T','O','O','B','J','E','C','T',0};
+static const WCHAR feature_unc_savedfilecheckW[] =
+    {'F','E','A','T','U','R','E','_','U','N','C','_','S','A','V','E','D','F','I','L','E','C','H','E','C','K',0};
+static const WCHAR feature_get_url_dom_filepath_unencodedW[] =
+    {'F','E','A','T','U','R','E','_','G','E','T','_','U','R','L','_','D','O','M','_',
+     'F','I','L','E','P','A','T','H','_','U','N','E','N','C','O','D','E','D',0};
+static const WCHAR feature_tabbed_browsingW[] =
+    {'F','E','A','T','U','R','E','_','T','A','B','B','E','D','_','B','R','O','W','S','I','N','G',0};
+static const WCHAR feature_ssluxW[] =
+    {'F','E','A','T','U','R','E','_','S','S','L','U','X',0};
+static const WCHAR feature_disable_navigation_soundsW[] =
+    {'F','E','A','T','U','R','E','_','D','I','S','A','B','L','E','_','N','A','V','I','G','A','T','I','O','N','_',
+     'S','O','U','N','D','S',0};
+static const WCHAR feature_disable_legacy_compressionW[] =
+    {'F','E','A','T','U','R','E','_','D','I','S','A','B','L','E','_','L','E','G','A','C','Y','_',
+     'C','O','M','P','R','E','S','S','I','O','N',0};
+static const WCHAR feature_force_addr_and_statusW[] =
+    {'F','E','A','T','U','R','E','_','F','O','R','C','E','_','A','D','D','R','_','A','N','D','_',
+     'S','T','A','T','U','S',0};
+static const WCHAR feature_xmlhttpW[] =
+    {'F','E','A','T','U','R','E','_','X','M','L','H','T','T','P',0};
+static const WCHAR feature_disable_telnet_protocolW[] =
+    {'F','E','A','T','U','R','E','_','D','I','S','A','B','L','E','_','T','E','L','N','E','T','_',
+     'P','R','O','T','O','C','O','L',0};
+static const WCHAR feature_feedsW[] =
+    {'F','E','A','T','U','R','E','_','F','E','E','D','S',0};
+static const WCHAR feature_block_input_promptsW[] =
+    {'F','E','A','T','U','R','E','_','B','L','O','C','K','_','I','N','P','U','T','_','P','R','O','M','P','T','S',0};
+
+static CRITICAL_SECTION process_features_cs;
+static CRITICAL_SECTION_DEBUG process_features_cs_dbg =
+{
+    0, 0, &process_features_cs,
+    { &process_features_cs_dbg.ProcessLocksList, &process_features_cs_dbg.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": process features") }
+};
+static CRITICAL_SECTION process_features_cs = { &process_features_cs_dbg, -1, 0, 0, 0, 0 };
+
+typedef struct feature_control {
+    LPCWSTR feature_name;
+    BOOL    enabled;
+    BOOL    check_registry;
+} feature_control;
+
+/* IMPORTANT!!!
+ *
+ * This array is indexed using INTERNETFEATURELIST values, so everything must
+ * appear in the same order as it does in INTERNETFEATURELIST.
+ */
+static feature_control process_feature_controls[FEATURE_ENTRY_COUNT] = {
+    {feature_object_cachingW,                   TRUE ,TRUE},
+    {feature_zone_elevationW,                   FALSE,TRUE},
+    {feature_mime_handlingW,                    FALSE,TRUE},
+    {feature_mime_sniffingW,                    FALSE,TRUE},
+    {feature_window_restrictionsW,              FALSE,TRUE},
+    {feature_weboc_popupmanagementW,            FALSE,TRUE},
+    {feature_behaviorsW,                        TRUE ,TRUE},
+    {feature_disable_mk_protocolW,              TRUE ,TRUE},
+    {feature_localmachine_lockdownW,            FALSE,TRUE},
+    {feature_securitybandW,                     FALSE,TRUE},
+    {feature_restrict_activexinstallW,          FALSE,TRUE},
+    {feature_validate_navigate_urlW,            FALSE,TRUE},
+    {feature_restrict_filedownloadW,            FALSE,TRUE},
+    {feature_addon_managementW,                 FALSE,TRUE},
+    {feature_protocol_lockdownW,                FALSE,TRUE},
+    {feature_http_username_password_disableW,   FALSE,TRUE},
+    {feature_safe_bindtoobjectW,                FALSE,TRUE},
+    {feature_unc_savedfilecheckW,               FALSE,TRUE},
+    {feature_get_url_dom_filepath_unencodedW,   TRUE ,TRUE},
+    {feature_tabbed_browsingW,                  FALSE,TRUE},
+    {feature_ssluxW,                            FALSE,TRUE},
+    {feature_disable_navigation_soundsW,        FALSE,TRUE},
+    {feature_disable_legacy_compressionW,       TRUE ,TRUE},
+    {feature_force_addr_and_statusW,            FALSE,TRUE},
+    {feature_xmlhttpW,                          TRUE ,TRUE},
+    {feature_disable_telnet_protocolW,          FALSE,TRUE},
+    {feature_feedsW,                            FALSE,TRUE},
+    {feature_block_input_promptsW,              FALSE,TRUE}
+};
+
 static HRESULT parse_schema(LPCWSTR url, DWORD flags, LPWSTR result, DWORD size, DWORD *rsize)
 {
     WCHAR *ptr;
@@ -397,20 +519,182 @@ HRESULT WINAPI CoInternetQueryInfo(LPCWSTR pwzUrl, QUERYOPTION QueryOption,
     return S_OK;
 }
 
+static void set_feature_on_process(INTERNETFEATURELIST feature, BOOL enable)
+{
+    EnterCriticalSection(&process_features_cs);
+
+    process_feature_controls[feature].enabled = enable;
+    process_feature_controls[feature].check_registry = FALSE;
+
+    LeaveCriticalSection(&process_features_cs);
+}
+
+static HRESULT set_internet_feature(INTERNETFEATURELIST feature, DWORD flags, BOOL enable)
+{
+    const DWORD supported_flags = SET_FEATURE_ON_PROCESS;
+
+    if(feature >= FEATURE_ENTRY_COUNT)
+        return E_FAIL;
+
+    if(flags & ~supported_flags) {
+        FIXME("Unsupported flags: %08x\n", flags & ~supported_flags);
+        return E_NOTIMPL;
+    }
+
+    if(flags & SET_FEATURE_ON_PROCESS)
+        set_feature_on_process(feature, enable);
+
+    return S_OK;
+}
+
+static BOOL get_feature_from_reg(HKEY feature_control, LPCWSTR feature_name, LPCWSTR process_name, BOOL *enabled)
+{
+    BOOL ret = FALSE;
+    HKEY feature;
+    DWORD res;
+
+    static const WCHAR wildcardW[] = {'*',0};
+
+    res = RegOpenKeyW(feature_control, feature_name, &feature);
+    if(res == ERROR_SUCCESS) {
+        DWORD type, value, size;
+
+        size = sizeof(DWORD);
+        res = RegQueryValueExW(feature, process_name, NULL, &type, (BYTE*)&value, &size);
+        if(type != REG_DWORD)
+            WARN("Unexpected registry value type %d (expected REG_DWORD) for %s\n", type, debugstr_w(process_name));
+
+        if(res == ERROR_SUCCESS && type == REG_DWORD) {
+            *enabled = value == 1;
+            ret = TRUE;
+        } else {
+            size = sizeof(DWORD);
+            res = RegQueryValueExW(feature, wildcardW, NULL, &type, (BYTE*)&value, &size);
+            if(type != REG_DWORD)
+                WARN("Unexpected registry value type %d (expected REG_DWORD) for %s\n", type, debugstr_w(wildcardW));
+
+            if(res == ERROR_SUCCESS && type == REG_DWORD) {
+                *enabled = value == 1;
+                ret = TRUE;
+            }
+        }
+        RegCloseKey(feature);
+    }
+
+    return ret;
+}
+
+/* Assumes 'process_features_cs' is held. */
+static HRESULT load_process_feature(INTERNETFEATURELIST feature)
+{
+    DWORD res;
+    HKEY feature_control;
+    WCHAR module_name[MAX_PATH];
+    LPCWSTR process_name, feature_name;
+    HRESULT hres = S_FALSE;
+    BOOL check_hklm = FALSE;
+    BOOL enabled;
+
+    if (!GetModuleFileNameW(NULL, module_name, sizeof(module_name)/sizeof(WCHAR))) {
+        ERR("Failed to get module file name: %u\n", GetLastError());
+        return E_UNEXPECTED;
+    }
+
+    process_name = strrchrW(module_name, '\\');
+    if(!process_name) {
+        ERR("Invalid module file name: %s\n", debugstr_w(module_name));
+        return E_UNEXPECTED;
+    }
+
+    /* Skip past the '\\' in front of the filename. */
+    ++process_name;
+
+    feature_name = process_feature_controls[feature].feature_name;
+
+    res = RegOpenKeyW(HKEY_CURRENT_USER, feature_control_keyW, &feature_control);
+    if(res == ERROR_SUCCESS) {
+        if(get_feature_from_reg(feature_control, feature_name, process_name, &enabled)) {
+            hres = enabled ? S_OK : S_FALSE;
+            process_feature_controls[feature].enabled = enabled;
+        } else
+            /* We didn't find anything in HKCU, so check HKLM. */
+            check_hklm = TRUE;
+
+        RegCloseKey(feature_control);
+    }
+
+    if(check_hklm) {
+        res = RegOpenKeyW(HKEY_LOCAL_MACHINE, feature_control_keyW, &feature_control);
+        if(res == ERROR_SUCCESS) {
+            if(get_feature_from_reg(feature_control, feature_name, process_name, &enabled)) {
+                hres = enabled ? S_OK : S_FALSE;
+                process_feature_controls[feature].enabled = enabled;
+            }
+            RegCloseKey(feature_control);
+        }
+    }
+
+    /* Don't bother checking the registry again for this feature. */
+    process_feature_controls[feature].check_registry = FALSE;
+
+    return hres;
+}
+
+static HRESULT get_feature_from_process(INTERNETFEATURELIST feature)
+{
+    HRESULT hres;
+
+    EnterCriticalSection(&process_features_cs);
+
+    /* Try loading the feature from the registry, if it hasn't already
+     * been done.
+     */
+    if(process_feature_controls[feature].check_registry) {
+        hres = load_process_feature(feature);
+        if(FAILED(hres)) {
+            LeaveCriticalSection(&process_features_cs);
+            return hres;
+        }
+    }
+
+    hres = process_feature_controls[feature].enabled ? S_OK : S_FALSE;
+
+    LeaveCriticalSection(&process_features_cs);
+
+    return hres;
+}
+
+static HRESULT get_internet_feature(INTERNETFEATURELIST feature, DWORD flags)
+{
+    HRESULT hres;
+
+    if(feature >= FEATURE_ENTRY_COUNT)
+        return E_FAIL;
+
+    if(flags == GET_FEATURE_FROM_PROCESS)
+        hres = get_feature_from_process(feature);
+    else {
+        FIXME("Unsupported flags: %08x\n", flags);
+        hres = E_NOTIMPL;
+    }
+
+    return hres;
+}
+
 /***********************************************************************
  *             CoInternetSetFeatureEnabled (URLMON.@)
  */
-HRESULT WINAPI CoInternetSetFeatureEnabled(INTERNETFEATURELIST feature, DWORD flags, BOOL enable)
+HRESULT WINAPI CoInternetSetFeatureEnabled(INTERNETFEATURELIST FeatureEntry, DWORD dwFlags, BOOL fEnable)
 {
-    FIXME("%d, 0x%08x, %x, stub\n", feature, flags, enable);
-    return E_NOTIMPL;
+    TRACE("(%d, %08x, %x)\n", FeatureEntry, dwFlags, fEnable);
+    return set_internet_feature(FeatureEntry, dwFlags, fEnable);
 }
 
 /***********************************************************************
  *             CoInternetIsFeatureEnabled (URLMON.@)
  */
-HRESULT WINAPI CoInternetIsFeatureEnabled(INTERNETFEATURELIST feature, DWORD flags)
+HRESULT WINAPI CoInternetIsFeatureEnabled(INTERNETFEATURELIST FeatureEntry, DWORD dwFlags)
 {
-    FIXME("%d, 0x%08x, stub\n", feature, flags);
-    return E_NOTIMPL;
+    TRACE("(%d, %08x)\n", FeatureEntry, dwFlags);
+    return get_internet_feature(FeatureEntry, dwFlags);
 }
index ee6f50f..1fe5246 100644 (file)
 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
 
 typedef struct {
-    const IInternetProtocolVtbl      *lpIInternetProtocolVtbl;
-    const IInternetProtocolSinkVtbl  *lpIInternetProtocolSinkVtbl;
+    IInternetProtocol     IInternetProtocol_iface;
+    IInternetProtocolSink IInternetProtocolSink_iface;
 
     LONG ref;
 } MimeFilter;
 
-#define PROTOCOL(x)      ((IInternetProtocol*)      &(x)->lpIInternetProtocolVtbl)
-#define PROTOCOLSINK(x)  ((IInternetProtocolSink*)  &(x)->lpIInternetProtocolSinkVtbl)
-
-#define PROTOCOL_THIS(iface) DEFINE_THIS(MimeFilter, IInternetProtocol, iface)
+static inline MimeFilter *impl_from_IInternetProtocol(IInternetProtocol *iface)
+{
+    return CONTAINING_RECORD(iface, MimeFilter, IInternetProtocol_iface);
+}
 
 static HRESULT WINAPI MimeFilterProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
 {
-    MimeFilter *This = PROTOCOL_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocol(iface);
 
     *ppv = NULL;
     if(IsEqualGUID(&IID_IUnknown, riid)) {
         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
-        *ppv = PROTOCOL(This);
+        *ppv = &This->IInternetProtocol_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
-        *ppv = PROTOCOL(This);
+        *ppv = &This->IInternetProtocol_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
         TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
-        *ppv = PROTOCOL(This);
+        *ppv = &This->IInternetProtocol_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
         TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
-        *ppv = PROTOCOLSINK(This);
+        *ppv = &This->IInternetProtocolSink_iface;
     }
 
     if(*ppv) {
@@ -63,7 +63,7 @@ static HRESULT WINAPI MimeFilterProtocol_QueryInterface(IInternetProtocol *iface
 
 static ULONG WINAPI MimeFilterProtocol_AddRef(IInternetProtocol *iface)
 {
-    MimeFilter *This = PROTOCOL_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocol(iface);
     LONG ref = InterlockedIncrement(&This->ref);
     TRACE("(%p) ref=%d\n", This, ref);
     return ref;
@@ -71,7 +71,7 @@ static ULONG WINAPI MimeFilterProtocol_AddRef(IInternetProtocol *iface)
 
 static ULONG WINAPI MimeFilterProtocol_Release(IInternetProtocol *iface)
 {
-    MimeFilter *This = PROTOCOL_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocol(iface);
     LONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) ref=%d\n", This, ref);
@@ -89,7 +89,7 @@ static HRESULT WINAPI MimeFilterProtocol_Start(IInternetProtocol *iface, LPCWSTR
         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
         DWORD grfPI, HANDLE_PTR dwReserved)
 {
-    MimeFilter *This = PROTOCOL_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
           pOIBindInfo, grfPI, dwReserved);
     return E_NOTIMPL;
@@ -97,7 +97,7 @@ static HRESULT WINAPI MimeFilterProtocol_Start(IInternetProtocol *iface, LPCWSTR
 
 static HRESULT WINAPI MimeFilterProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
 {
-    MimeFilter *This = PROTOCOL_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)->(%p)\n", This, pProtocolData);
     return E_NOTIMPL;
 }
@@ -105,28 +105,28 @@ static HRESULT WINAPI MimeFilterProtocol_Continue(IInternetProtocol *iface, PROT
 static HRESULT WINAPI MimeFilterProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
         DWORD dwOptions)
 {
-    MimeFilter *This = PROTOCOL_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI MimeFilterProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
 {
-    MimeFilter *This = PROTOCOL_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)->(%08x)\n", This, dwOptions);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI MimeFilterProtocol_Suspend(IInternetProtocol *iface)
 {
-    MimeFilter *This = PROTOCOL_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)\n", This);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI MimeFilterProtocol_Resume(IInternetProtocol *iface)
 {
-    MimeFilter *This = PROTOCOL_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)\n", This);
     return E_NOTIMPL;
 }
@@ -134,7 +134,7 @@ static HRESULT WINAPI MimeFilterProtocol_Resume(IInternetProtocol *iface)
 static HRESULT WINAPI MimeFilterProtocol_Read(IInternetProtocol *iface, void *pv,
         ULONG cb, ULONG *pcbRead)
 {
-    MimeFilter *This = PROTOCOL_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
     return E_NOTIMPL;
 }
@@ -142,27 +142,25 @@ static HRESULT WINAPI MimeFilterProtocol_Read(IInternetProtocol *iface, void *pv
 static HRESULT WINAPI MimeFilterProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
         DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
 {
-    MimeFilter *This = PROTOCOL_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI MimeFilterProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
 {
-    MimeFilter *This = PROTOCOL_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)->(%08x)\n", This, dwOptions);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI MimeFilterProtocol_UnlockRequest(IInternetProtocol *iface)
 {
-    MimeFilter *This = PROTOCOL_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)\n", This);
     return E_NOTIMPL;
 }
 
-#undef PROTOCOL_THIS
-
 static const IInternetProtocolVtbl MimeFilterProtocolVtbl = {
     MimeFilterProtocol_QueryInterface,
     MimeFilterProtocol_AddRef,
@@ -179,31 +177,34 @@ static const IInternetProtocolVtbl MimeFilterProtocolVtbl = {
     MimeFilterProtocol_UnlockRequest
 };
 
-#define PROTSINK_THIS(iface) DEFINE_THIS(MimeFilter, IInternetProtocolSink, iface)
+static inline MimeFilter *impl_from_IInternetProtocolSink(IInternetProtocolSink *iface)
+{
+    return CONTAINING_RECORD(iface, MimeFilter, IInternetProtocolSink_iface);
+}
 
 static HRESULT WINAPI MimeFilterSink_QueryInterface(IInternetProtocolSink *iface,
         REFIID riid, void **ppv)
 {
-    MimeFilter *This = PROTSINK_THIS(iface);
-    return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
+    MimeFilter *This = impl_from_IInternetProtocolSink(iface);
+    return IInternetProtocol_QueryInterface(&This->IInternetProtocol_iface, riid, ppv);
 }
 
 static ULONG WINAPI MimeFilterSink_AddRef(IInternetProtocolSink *iface)
 {
-    MimeFilter *This = PROTSINK_THIS(iface);
-    return IInternetProtocol_AddRef(PROTOCOL(This));
+    MimeFilter *This = impl_from_IInternetProtocolSink(iface);
+    return IInternetProtocol_AddRef(&This->IInternetProtocol_iface);
 }
 
 static ULONG WINAPI MimeFilterSink_Release(IInternetProtocolSink *iface)
 {
-    MimeFilter *This = PROTSINK_THIS(iface);
-    return IInternetProtocol_Release(PROTOCOL(This));
+    MimeFilter *This = impl_from_IInternetProtocolSink(iface);
+    return IInternetProtocol_Release(&This->IInternetProtocol_iface);
 }
 
 static HRESULT WINAPI MimeFilterSink_Switch(IInternetProtocolSink *iface,
         PROTOCOLDATA *pProtocolData)
 {
-    MimeFilter *This = PROTSINK_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocolSink(iface);
     FIXME("(%p)->(%p)\n", This, pProtocolData);
     return E_NOTIMPL;
 }
@@ -211,7 +212,7 @@ static HRESULT WINAPI MimeFilterSink_Switch(IInternetProtocolSink *iface,
 static HRESULT WINAPI MimeFilterSink_ReportProgress(IInternetProtocolSink *iface,
         ULONG ulStatusCode, LPCWSTR szStatusText)
 {
-    MimeFilter *This = PROTSINK_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocolSink(iface);
     FIXME("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
     return E_NOTIMPL;
 }
@@ -219,7 +220,7 @@ static HRESULT WINAPI MimeFilterSink_ReportProgress(IInternetProtocolSink *iface
 static HRESULT WINAPI MimeFilterSink_ReportData(IInternetProtocolSink *iface,
         DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
 {
-    MimeFilter *This = PROTSINK_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocolSink(iface);
     FIXME("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
     return E_NOTIMPL;
 }
@@ -227,13 +228,11 @@ static HRESULT WINAPI MimeFilterSink_ReportData(IInternetProtocolSink *iface,
 static HRESULT WINAPI MimeFilterSink_ReportResult(IInternetProtocolSink *iface,
         HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
 {
-    MimeFilter *This = PROTSINK_THIS(iface);
+    MimeFilter *This = impl_from_IInternetProtocolSink(iface);
     FIXME("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
     return E_NOTIMPL;
 }
 
-#undef PROTSINK_THIS
-
 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
     MimeFilterSink_QueryInterface,
     MimeFilterSink_AddRef,
@@ -254,10 +253,10 @@ HRESULT MimeFilter_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
 
     ret = heap_alloc_zero(sizeof(MimeFilter));
 
-    ret->lpIInternetProtocolVtbl     = &MimeFilterProtocolVtbl;
-    ret->lpIInternetProtocolSinkVtbl = &InternetProtocolSinkVtbl;
+    ret->IInternetProtocol_iface.lpVtbl = &MimeFilterProtocolVtbl;
+    ret->IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkVtbl;
     ret->ref = 1;
 
-    *ppobj = PROTOCOL(ret);
+    *ppobj = &ret->IInternetProtocol_iface;
     return S_OK;
 }
index 0befe5c..46b4ddc 100644 (file)
 #include "urlmon_main.h"
 #include "wine/debug.h"
 
+#define NO_SHLWAPI_REG
+#include "shlwapi.h"
+
 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
 
 typedef struct {
-    const IInternetProtocolVtbl  *lpIInternetProtocolVtbl;
+    IInternetProtocolEx IInternetProtocolEx_iface;
 
     LONG ref;
 
     IStream *stream;
 } MkProtocol;
 
-#define PROTOCOL_THIS(iface) DEFINE_THIS(MkProtocol, IInternetProtocol, iface)
+static inline MkProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface)
+{
+    return CONTAINING_RECORD(iface, MkProtocol, IInternetProtocolEx_iface);
+}
 
-static HRESULT WINAPI MkProtocol_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
+static HRESULT WINAPI MkProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv)
 {
-    MkProtocol *This = PROTOCOL_THIS(iface);
+    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
 
     *ppv = NULL;
     if(IsEqualGUID(&IID_IUnknown, riid)) {
         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
-        *ppv = PROTOCOL(This);
+        *ppv = &This->IInternetProtocolEx_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
-        *ppv = PROTOCOL(This);
+        *ppv = &This->IInternetProtocolEx_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
         TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
-        *ppv = PROTOCOL(This);
+        *ppv = &This->IInternetProtocolEx_iface;
+    }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) {
+        TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv);
+        *ppv = &This->IInternetProtocolEx_iface;
     }
 
     if(*ppv) {
@@ -56,17 +65,17 @@ static HRESULT WINAPI MkProtocol_QueryInterface(IInternetProtocol *iface, REFIID
     return E_NOINTERFACE;
 }
 
-static ULONG WINAPI MkProtocol_AddRef(IInternetProtocol *iface)
+static ULONG WINAPI MkProtocol_AddRef(IInternetProtocolEx *iface)
 {
-    MkProtocol *This = PROTOCOL_THIS(iface);
+    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
     LONG ref = InterlockedIncrement(&This->ref);
     TRACE("(%p) ref=%d\n", This, ref);
     return ref;
 }
 
-static ULONG WINAPI MkProtocol_Release(IInternetProtocol *iface)
+static ULONG WINAPI MkProtocol_Release(IInternetProtocolEx *iface)
 {
-    MkProtocol *This = PROTOCOL_THIS(iface);
+    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
     LONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) ref=%d\n", This, ref);
@@ -89,27 +98,128 @@ static HRESULT report_result(IInternetProtocolSink *sink, HRESULT hres, DWORD dw
     return hres;
 }
 
-static HRESULT WINAPI MkProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
+static HRESULT WINAPI MkProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl,
         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
         DWORD grfPI, HANDLE_PTR dwReserved)
 {
-    MkProtocol *This = PROTOCOL_THIS(iface);
+    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
+    HRESULT hres;
+    IUri *uri;
+
+    TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
+            pOIBindInfo, grfPI, dwReserved);
+
+    hres = CreateUri(szUrl, 0, 0, &uri);
+    if(FAILED(hres))
+        return hres;
+
+    hres = IInternetProtocolEx_StartEx(&This->IInternetProtocolEx_iface, uri, pOIProtSink,
+            pOIBindInfo, grfPI, (HANDLE*)dwReserved);
+
+    IUri_Release(uri);
+    return hres;
+}
+
+static HRESULT WINAPI MkProtocol_Continue(IInternetProtocolEx *iface, PROTOCOLDATA *pProtocolData)
+{
+    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
+    FIXME("(%p)->(%p)\n", This, pProtocolData);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MkProtocol_Abort(IInternetProtocolEx *iface, HRESULT hrReason,
+        DWORD dwOptions)
+{
+    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
+    FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MkProtocol_Terminate(IInternetProtocolEx *iface, DWORD dwOptions)
+{
+    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
+
+    TRACE("(%p)->(%08x)\n", This, dwOptions);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI MkProtocol_Suspend(IInternetProtocolEx *iface)
+{
+    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
+    FIXME("(%p)\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MkProtocol_Resume(IInternetProtocolEx *iface)
+{
+    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
+    FIXME("(%p)\n", This);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MkProtocol_Read(IInternetProtocolEx *iface, void *pv,
+        ULONG cb, ULONG *pcbRead)
+{
+    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
+
+    TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
+
+    if(!This->stream)
+        return E_FAIL;
+
+    return IStream_Read(This->stream, pv, cb, pcbRead);
+}
+
+static HRESULT WINAPI MkProtocol_Seek(IInternetProtocolEx *iface, LARGE_INTEGER dlibMove,
+        DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
+{
+    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
+    FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI MkProtocol_LockRequest(IInternetProtocolEx *iface, DWORD dwOptions)
+{
+    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
+
+    TRACE("(%p)->(%08x)\n", This, dwOptions);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI MkProtocol_UnlockRequest(IInternetProtocolEx *iface)
+{
+    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
+
+    TRACE("(%p)\n", This);
+
+    return S_OK;
+}
+
+static HRESULT WINAPI MkProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUri,
+        IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
+        DWORD grfPI, HANDLE *dwReserved)
+{
+    MkProtocol *This = impl_from_IInternetProtocolEx(iface);
+    LPWSTR mime, progid, display_name, colon_ptr;
+    DWORD path_size = INTERNET_MAX_URL_LENGTH;
+    DWORD bindf=0, eaten=0, scheme=0, len;
+    BSTR url, path_tmp, path = NULL;
     IParseDisplayName *pdn;
-    IMoniker *mon;
-    LPWSTR mime, progid, display_name;
-    LPCWSTR ptr, ptr2;
     BINDINFO bindinfo;
     STATSTG statstg;
-    DWORD bindf=0, eaten=0, len;
-    CLSID clsid;
+    IMoniker *mon;
     HRESULT hres;
+    CLSID clsid;
 
-    static const WCHAR wszMK[] = {'m','k',':','@'};
-
-    TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
+    TRACE("(%p)->(%p %p %p %08x %p)\n", This, pUri, pOIProtSink,
             pOIBindInfo, grfPI, dwReserved);
 
-    if(strncmpiW(szUrl, wszMK, sizeof(wszMK)/sizeof(WCHAR)))
+    hres = IUri_GetScheme(pUri, &scheme);
+    if(FAILED(hres))
+        return hres;
+    if(scheme != URL_SCHEME_MK)
         return INET_E_INVALID_URL;
 
     memset(&bindinfo, 0, sizeof(bindinfo));
@@ -124,35 +234,56 @@ static HRESULT WINAPI MkProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
 
     IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_SENDINGREQUEST, NULL);
 
-    hres = FindMimeFromData(NULL, szUrl, NULL, 0, NULL, 0, &mime, 0);
+    hres = IUri_GetDisplayUri(pUri, &url);
+    if(FAILED(hres))
+        return hres;
+    hres = FindMimeFromData(NULL, url, NULL, 0, NULL, 0, &mime, 0);
+    SysFreeString(url);
     if(SUCCEEDED(hres)) {
         IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_MIMETYPEAVAILABLE, mime);
         CoTaskMemFree(mime);
     }
 
-    ptr2 = szUrl + sizeof(wszMK)/sizeof(WCHAR);
-    ptr = strchrW(ptr2, ':');
-    if(!ptr)
+    hres = IUri_GetPath(pUri, &path_tmp);
+    if(FAILED(hres))
+        return hres;
+    path = heap_alloc(path_size);
+    hres = UrlUnescapeW((LPWSTR)path_tmp, path, &path_size, 0);
+    SysFreeString(path_tmp);
+    if (FAILED(hres))
+    {
+        heap_free(path);
         return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, ERROR_INVALID_PARAMETER);
+    }
+    progid = path+1; /* skip '@' symbol */
+    colon_ptr = strchrW(path, ':');
+    if(!colon_ptr)
+    {
+        heap_free(path);
+        return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, ERROR_INVALID_PARAMETER);
+    }
+
+    len = strlenW(path);
+    display_name = heap_alloc((len+1)*sizeof(WCHAR));
+    memcpy(display_name, path, (len+1)*sizeof(WCHAR));
 
-    progid = heap_alloc((ptr-ptr2+1)*sizeof(WCHAR));
-    memcpy(progid, ptr2, (ptr-ptr2)*sizeof(WCHAR));
-    progid[ptr-ptr2] = 0;
+    progid[colon_ptr-progid] = 0; /* overwrite ':' with NULL terminator */
     hres = CLSIDFromProgID(progid, &clsid);
-    heap_free(progid);
+    heap_free(path);
     if(FAILED(hres))
+    {
+        heap_free(display_name);
         return report_result(pOIProtSink, INET_E_RESOURCE_NOT_FOUND, ERROR_INVALID_PARAMETER);
+    }
 
     hres = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
             &IID_IParseDisplayName, (void**)&pdn);
     if(FAILED(hres)) {
         WARN("Could not create object %s\n", debugstr_guid(&clsid));
+        heap_free(display_name);
         return report_result(pOIProtSink, hres, ERROR_INVALID_PARAMETER);
     }
 
-    len = strlenW(--ptr2);
-    display_name = heap_alloc((len+1)*sizeof(WCHAR));
-    memcpy(display_name, ptr2, (len+1)*sizeof(WCHAR));
     hres = IParseDisplayName_ParseDisplayName(pdn, NULL /* FIXME */, display_name, &eaten, &mon);
     heap_free(display_name);
     IParseDisplayName_Release(pdn);
@@ -182,90 +313,10 @@ static HRESULT WINAPI MkProtocol_Start(IInternetProtocol *iface, LPCWSTR szUrl,
     IInternetProtocolSink_ReportData(pOIProtSink,
             BSCF_FIRSTDATANOTIFICATION | BSCF_LASTDATANOTIFICATION,
             statstg.cbSize.u.LowPart, statstg.cbSize.u.LowPart);
-
     return report_result(pOIProtSink, S_OK, ERROR_SUCCESS);
 }
 
-static HRESULT WINAPI MkProtocol_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
-{
-    MkProtocol *This = PROTOCOL_THIS(iface);
-    FIXME("(%p)->(%p)\n", This, pProtocolData);
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI MkProtocol_Abort(IInternetProtocol *iface, HRESULT hrReason,
-        DWORD dwOptions)
-{
-    MkProtocol *This = PROTOCOL_THIS(iface);
-    FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI MkProtocol_Terminate(IInternetProtocol *iface, DWORD dwOptions)
-{
-    MkProtocol *This = PROTOCOL_THIS(iface);
-
-    TRACE("(%p)->(%08x)\n", This, dwOptions);
-
-    return S_OK;
-}
-
-static HRESULT WINAPI MkProtocol_Suspend(IInternetProtocol *iface)
-{
-    MkProtocol *This = PROTOCOL_THIS(iface);
-    FIXME("(%p)\n", This);
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI MkProtocol_Resume(IInternetProtocol *iface)
-{
-    MkProtocol *This = PROTOCOL_THIS(iface);
-    FIXME("(%p)\n", This);
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI MkProtocol_Read(IInternetProtocol *iface, void *pv,
-        ULONG cb, ULONG *pcbRead)
-{
-    MkProtocol *This = PROTOCOL_THIS(iface);
-
-    TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
-
-    if(!This->stream)
-        return E_FAIL;
-
-    return IStream_Read(This->stream, pv, cb, pcbRead);
-}
-
-static HRESULT WINAPI MkProtocol_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
-        DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
-{
-    MkProtocol *This = PROTOCOL_THIS(iface);
-    FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
-    return E_NOTIMPL;
-}
-
-static HRESULT WINAPI MkProtocol_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
-{
-    MkProtocol *This = PROTOCOL_THIS(iface);
-
-    TRACE("(%p)->(%08x)\n", This, dwOptions);
-
-    return S_OK;
-}
-
-static HRESULT WINAPI MkProtocol_UnlockRequest(IInternetProtocol *iface)
-{
-    MkProtocol *This = PROTOCOL_THIS(iface);
-
-    TRACE("(%p)\n", This);
-
-    return S_OK;
-}
-
-#undef PROTOCOL_THIS
-
-static const IInternetProtocolVtbl MkProtocolVtbl = {
+static const IInternetProtocolExVtbl MkProtocolVtbl = {
     MkProtocol_QueryInterface,
     MkProtocol_AddRef,
     MkProtocol_Release,
@@ -278,7 +329,8 @@ static const IInternetProtocolVtbl MkProtocolVtbl = {
     MkProtocol_Read,
     MkProtocol_Seek,
     MkProtocol_LockRequest,
-    MkProtocol_UnlockRequest
+    MkProtocol_UnlockRequest,
+    MkProtocol_StartEx
 };
 
 HRESULT MkProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
@@ -291,14 +343,14 @@ HRESULT MkProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj)
 
     ret = heap_alloc(sizeof(MkProtocol));
 
-    ret->lpIInternetProtocolVtbl = &MkProtocolVtbl;
+    ret->IInternetProtocolEx_iface.lpVtbl = &MkProtocolVtbl;
     ret->ref = 1;
     ret->stream = NULL;
 
     /* NOTE:
      * Native returns NULL ppobj and S_OK in CreateInstance if called with IID_IUnknown riid.
      */
-    *ppobj = PROTOCOL(ret);
+    *ppobj = &ret->IInternetProtocolEx_iface;
 
     return S_OK;
 }
index 669343b..326564b 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
 
-/* Flags are needed for, among other things, return HRESULTs from the Read function
- * to conform to native. For example, Read returns:
- *
- * 1. E_PENDING if called before the request has completed,
- *        (flags = 0)
- * 2. S_FALSE after all data has been read and S_OK has been reported,
- *        (flags = FLAG_REQUEST_COMPLETE | FLAG_ALL_DATA_READ | FLAG_RESULT_REPORTED)
- * 3. INET_E_DATA_NOT_AVAILABLE if InternetQueryDataAvailable fails. The first time
- *    this occurs, INET_E_DATA_NOT_AVAILABLE will also be reported to the sink,
- *        (flags = FLAG_REQUEST_COMPLETE)
- *    but upon subsequent calls to Read no reporting will take place, yet
- *    InternetQueryDataAvailable will still be called, and, on failure,
- *    INET_E_DATA_NOT_AVAILABLE will still be returned.
- *        (flags = FLAG_REQUEST_COMPLETE | FLAG_RESULT_REPORTED)
- *
- * FLAG_FIRST_DATA_REPORTED and FLAG_LAST_DATA_REPORTED are needed for proper
- * ReportData reporting. For example, if OnResponse returns S_OK, Continue will
- * report BSCF_FIRSTDATANOTIFICATION, and when all data has been read Read will
- * report BSCF_INTERMEDIATEDATANOTIFICATION|BSCF_LASTDATANOTIFICATION. However,
- * if OnResponse does not return S_OK, Continue will not report data, and Read
- * will report BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION when all
- * data has been read.
- */
-#define FLAG_REQUEST_COMPLETE         0x0001
-#define FLAG_FIRST_CONTINUE_COMPLETE  0x0002
-#define FLAG_FIRST_DATA_REPORTED      0x0004
-#define FLAG_ALL_DATA_READ            0x0008
-#define FLAG_LAST_DATA_REPORTED       0x0010
-#define FLAG_RESULT_REPORTED          0x0020
-
 static inline HRESULT report_progress(Protocol *protocol, ULONG status_code, LPCWSTR status_text)
 {
     return IInternetProtocolSink_ReportProgress(protocol->protocol_sink, status_code, status_text);
@@ -106,25 +76,27 @@ static void request_complete(Protocol *protocol, INTERNET_ASYNC_RESULT *ar)
 
     TRACE("(%p)->(%p)\n", protocol, ar);
 
-    if(!ar->dwResult) {
-        WARN("request failed: %d\n", ar->dwError);
-        return;
-    }
-
-    protocol->flags |= FLAG_REQUEST_COMPLETE;
-
-    if(!protocol->request) {
-        TRACE("setting request handle %p\n", (HINTERNET)ar->dwResult);
-        protocol->request = (HINTERNET)ar->dwResult;
-    }
-
     /* PROTOCOLDATA same as native */
     memset(&data, 0, sizeof(data));
     data.dwState = 0xf1000000;
-    if(protocol->flags & FLAG_FIRST_CONTINUE_COMPLETE)
-        data.pData = (LPVOID)BINDSTATUS_ENDDOWNLOADCOMPONENTS;
-    else
-        data.pData = (LPVOID)BINDSTATUS_DOWNLOADINGDATA;
+
+    if(ar->dwResult) {
+        protocol->flags |= FLAG_REQUEST_COMPLETE;
+
+        if(!protocol->request) {
+            TRACE("setting request handle %p\n", (HINTERNET)ar->dwResult);
+            protocol->request = (HINTERNET)ar->dwResult;
+        }
+
+        if(protocol->flags & FLAG_FIRST_CONTINUE_COMPLETE)
+            data.pData = (LPVOID)BINDSTATUS_ENDDOWNLOADCOMPONENTS;
+        else
+            data.pData = (LPVOID)BINDSTATUS_DOWNLOADINGDATA;
+
+    }else {
+        protocol->flags |= FLAG_ERROR;
+        data.pData = (LPVOID)ar->dwError;
+    }
 
     if (protocol->bindf & BINDF_FROMURLMON)
         IInternetProtocolSink_Switch(protocol->protocol_sink, &data);
@@ -331,6 +303,12 @@ HRESULT protocol_continue(Protocol *protocol, PROTOCOLDATA *data)
         return S_OK;
     }
 
+    if(protocol->flags & FLAG_ERROR) {
+        protocol->flags &= ~FLAG_ERROR;
+        protocol->vtbl->on_error(protocol, (DWORD)data->pData);
+        return S_OK;
+    }
+
     if(protocol->post_stream)
         return write_post_stream(protocol);
 
@@ -357,7 +335,7 @@ HRESULT protocol_continue(Protocol *protocol, PROTOCOLDATA *data)
         protocol->flags |= FLAG_FIRST_CONTINUE_COMPLETE;
     }
 
-    if(data->pData >= (LPVOID)BINDSTATUS_DOWNLOADINGDATA) {
+    if(data->pData >= (LPVOID)BINDSTATUS_DOWNLOADINGDATA && !protocol->available_bytes) {
         BOOL res;
 
         /* InternetQueryDataAvailable may immediately fork and perform its asynchronous
@@ -389,33 +367,33 @@ HRESULT protocol_read(Protocol *protocol, void *buf, ULONG size, ULONG *read_ret
         return S_FALSE;
     }
 
-    if(!(protocol->flags & FLAG_REQUEST_COMPLETE)) {
+    if(!(protocol->flags & FLAG_REQUEST_COMPLETE) || !protocol->available_bytes) {
         *read_ret = 0;
         return E_PENDING;
     }
 
-    while(read < size) {
-        if(protocol->available_bytes) {
-            ULONG len;
+    while(read < size && protocol->available_bytes) {
+        ULONG len;
 
-            res = InternetReadFile(protocol->request, ((BYTE *)buf)+read,
-                    protocol->available_bytes > size-read ? size-read : protocol->available_bytes, &len);
-            if(!res) {
-                WARN("InternetReadFile failed: %d\n", GetLastError());
-                hres = INET_E_DOWNLOAD_FAILURE;
-                report_result(protocol, hres);
-                break;
-            }
+        res = InternetReadFile(protocol->request, ((BYTE *)buf)+read,
+                protocol->available_bytes > size-read ? size-read : protocol->available_bytes, &len);
+        if(!res) {
+            WARN("InternetReadFile failed: %d\n", GetLastError());
+            hres = INET_E_DOWNLOAD_FAILURE;
+            report_result(protocol, hres);
+            break;
+        }
 
-            if(!len) {
-                all_data_read(protocol);
-                break;
-            }
+        if(!len) {
+            all_data_read(protocol);
+            break;
+        }
+
+        read += len;
+        protocol->current_position += len;
+        protocol->available_bytes -= len;
 
-            read += len;
-            protocol->current_position += len;
-            protocol->available_bytes -= len;
-        }else {
+        if(!protocol->available_bytes) {
             /* InternetQueryDataAvailable may immediately fork and perform its asynchronous
              * read, so clear the flag _before_ calling so it does not incorrectly get cleared
              * after the status callback is called */
index c3d64c4..06a8586 100644 (file)
 
 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
 
-#define PROTOCOL_THIS(iface) DEFINE_THIS(ProtocolProxy, IInternetProtocol, iface)
+static inline ProtocolProxy *impl_from_IInternetProtocol(IInternetProtocol *iface)
+{
+    return CONTAINING_RECORD(iface, ProtocolProxy, IInternetProtocol_iface);
+}
 
 static HRESULT WINAPI ProtocolProxy_QueryInterface(IInternetProtocol *iface, REFIID riid, void **ppv)
 {
-    ProtocolProxy *This = PROTOCOL_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
 
     *ppv = NULL;
     if(IsEqualGUID(&IID_IUnknown, riid)) {
         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
-        *ppv = PROTOCOL(This);
+        *ppv = &This->IInternetProtocol_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) {
         TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv);
-        *ppv = PROTOCOL(This);
+        *ppv = &This->IInternetProtocol_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocol, riid)) {
         TRACE("(%p)->(IID_IInternetProtocol %p)\n", This, ppv);
-        *ppv = PROTOCOL(This);
+        *ppv = &This->IInternetProtocol_iface;
     }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) {
         TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv);
-        *ppv = PROTSINK(This);
+        *ppv = &This->IInternetProtocolSink_iface;
     }
 
     if(*ppv) {
@@ -53,7 +56,7 @@ static HRESULT WINAPI ProtocolProxy_QueryInterface(IInternetProtocol *iface, REF
 
 static ULONG WINAPI ProtocolProxy_AddRef(IInternetProtocol *iface)
 {
-    ProtocolProxy *This = PROTOCOL_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
     LONG ref = InterlockedIncrement(&This->ref);
     TRACE("(%p) ref=%d\n", This, ref);
     return ref;
@@ -61,7 +64,7 @@ static ULONG WINAPI ProtocolProxy_AddRef(IInternetProtocol *iface)
 
 static ULONG WINAPI ProtocolProxy_Release(IInternetProtocol *iface)
 {
-    ProtocolProxy *This = PROTOCOL_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
     LONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) ref=%d\n", This, ref);
@@ -84,7 +87,7 @@ static HRESULT WINAPI ProtocolProxy_Start(IInternetProtocol *iface, LPCWSTR szUr
         IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo,
         DWORD grfPI, HANDLE_PTR dwReserved)
 {
-    ProtocolProxy *This = PROTOCOL_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
 
     TRACE("(%p)->(%s %p %p %08x %lx)\n", This, debugstr_w(szUrl), pOIProtSink,
           pOIBindInfo, grfPI, dwReserved);
@@ -94,7 +97,7 @@ static HRESULT WINAPI ProtocolProxy_Start(IInternetProtocol *iface, LPCWSTR szUr
 
 static HRESULT WINAPI ProtocolProxy_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData)
 {
-    ProtocolProxy *This = PROTOCOL_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
 
     TRACE("(%p)->(%p)\n", This, pProtocolData);
 
@@ -104,14 +107,14 @@ static HRESULT WINAPI ProtocolProxy_Continue(IInternetProtocol *iface, PROTOCOLD
 static HRESULT WINAPI ProtocolProxy_Abort(IInternetProtocol *iface, HRESULT hrReason,
         DWORD dwOptions)
 {
-    ProtocolProxy *This = PROTOCOL_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)->(%08x %08x)\n", This, hrReason, dwOptions);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI ProtocolProxy_Terminate(IInternetProtocol *iface, DWORD dwOptions)
 {
-    ProtocolProxy *This = PROTOCOL_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
 
     TRACE("(%p)->(%08x)\n", This, dwOptions);
 
@@ -120,14 +123,14 @@ static HRESULT WINAPI ProtocolProxy_Terminate(IInternetProtocol *iface, DWORD dw
 
 static HRESULT WINAPI ProtocolProxy_Suspend(IInternetProtocol *iface)
 {
-    ProtocolProxy *This = PROTOCOL_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)\n", This);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI ProtocolProxy_Resume(IInternetProtocol *iface)
 {
-    ProtocolProxy *This = PROTOCOL_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)\n", This);
     return E_NOTIMPL;
 }
@@ -135,7 +138,7 @@ static HRESULT WINAPI ProtocolProxy_Resume(IInternetProtocol *iface)
 static HRESULT WINAPI ProtocolProxy_Read(IInternetProtocol *iface, void *pv,
         ULONG cb, ULONG *pcbRead)
 {
-    ProtocolProxy *This = PROTOCOL_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
 
     TRACE("(%p)->(%p %u %p)\n", This, pv, cb, pcbRead);
 
@@ -145,14 +148,14 @@ static HRESULT WINAPI ProtocolProxy_Read(IInternetProtocol *iface, void *pv,
 static HRESULT WINAPI ProtocolProxy_Seek(IInternetProtocol *iface, LARGE_INTEGER dlibMove,
         DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition)
 {
-    ProtocolProxy *This = PROTOCOL_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
     FIXME("(%p)->(%d %d %p)\n", This, dlibMove.u.LowPart, dwOrigin, plibNewPosition);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI ProtocolProxy_LockRequest(IInternetProtocol *iface, DWORD dwOptions)
 {
-    ProtocolProxy *This = PROTOCOL_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
 
     TRACE("(%p)->(%08x)\n", This, dwOptions);
 
@@ -161,15 +164,13 @@ static HRESULT WINAPI ProtocolProxy_LockRequest(IInternetProtocol *iface, DWORD
 
 static HRESULT WINAPI ProtocolProxy_UnlockRequest(IInternetProtocol *iface)
 {
-    ProtocolProxy *This = PROTOCOL_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocol(iface);
 
     TRACE("(%p)\n", This);
 
     return IInternetProtocol_UnlockRequest(This->protocol);
 }
 
-#undef PROTOCOL_THIS
-
 static const IInternetProtocolVtbl ProtocolProxyVtbl = {
     ProtocolProxy_QueryInterface,
     ProtocolProxy_AddRef,
@@ -186,31 +187,34 @@ static const IInternetProtocolVtbl ProtocolProxyVtbl = {
     ProtocolProxy_UnlockRequest
 };
 
-#define PROTSINK_THIS(iface) DEFINE_THIS(ProtocolProxy, IInternetProtocolSink, iface)
+static inline ProtocolProxy *impl_from_IInternetProtocolSink(IInternetProtocolSink *iface)
+{
+    return CONTAINING_RECORD(iface, ProtocolProxy, IInternetProtocolSink_iface);
+}
 
 static HRESULT WINAPI ProtocolProxySink_QueryInterface(IInternetProtocolSink *iface,
         REFIID riid, void **ppv)
 {
-    ProtocolProxy *This = PROTSINK_THIS(iface);
-    return IInternetProtocol_QueryInterface(PROTOCOL(This), riid, ppv);
+    ProtocolProxy *This = impl_from_IInternetProtocolSink(iface);
+    return IInternetProtocol_QueryInterface(&This->IInternetProtocol_iface, riid, ppv);
 }
 
 static ULONG WINAPI ProtocolProxySink_AddRef(IInternetProtocolSink *iface)
 {
-    ProtocolProxy *This = PROTSINK_THIS(iface);
-    return IInternetProtocol_AddRef(PROTOCOL(This));
+    ProtocolProxy *This = impl_from_IInternetProtocolSink(iface);
+    return IInternetProtocol_AddRef(&This->IInternetProtocol_iface);
 }
 
 static ULONG WINAPI ProtocolProxySink_Release(IInternetProtocolSink *iface)
 {
-    ProtocolProxy *This = PROTSINK_THIS(iface);
-    return IInternetProtocol_Release(PROTOCOL(This));
+    ProtocolProxy *This = impl_from_IInternetProtocolSink(iface);
+    return IInternetProtocol_Release(&This->IInternetProtocol_iface);
 }
 
 static HRESULT WINAPI ProtocolProxySink_Switch(IInternetProtocolSink *iface,
         PROTOCOLDATA *pProtocolData)
 {
-    ProtocolProxy *This = PROTSINK_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocolSink(iface);
 
     TRACE("(%p)->(%p)\n", This, pProtocolData);
 
@@ -220,7 +224,7 @@ static HRESULT WINAPI ProtocolProxySink_Switch(IInternetProtocolSink *iface,
 static HRESULT WINAPI ProtocolProxySink_ReportProgress(IInternetProtocolSink *iface,
         ULONG ulStatusCode, LPCWSTR szStatusText)
 {
-    ProtocolProxy *This = PROTSINK_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocolSink(iface);
 
     TRACE("(%p)->(%u %s)\n", This, ulStatusCode, debugstr_w(szStatusText));
 
@@ -238,7 +242,7 @@ static HRESULT WINAPI ProtocolProxySink_ReportProgress(IInternetProtocolSink *if
 static HRESULT WINAPI ProtocolProxySink_ReportData(IInternetProtocolSink *iface,
         DWORD grfBSCF, ULONG ulProgress, ULONG ulProgressMax)
 {
-    ProtocolProxy *This = PROTSINK_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocolSink(iface);
 
     TRACE("(%p)->(%d %u %u)\n", This, grfBSCF, ulProgress, ulProgressMax);
 
@@ -248,15 +252,13 @@ static HRESULT WINAPI ProtocolProxySink_ReportData(IInternetProtocolSink *iface,
 static HRESULT WINAPI ProtocolProxySink_ReportResult(IInternetProtocolSink *iface,
         HRESULT hrResult, DWORD dwError, LPCWSTR szResult)
 {
-    ProtocolProxy *This = PROTSINK_THIS(iface);
+    ProtocolProxy *This = impl_from_IInternetProtocolSink(iface);
 
     TRACE("(%p)->(%08x %d %s)\n", This, hrResult, dwError, debugstr_w(szResult));
 
     return IInternetProtocolSink_ReportResult(This->protocol_sink, hrResult, dwError, szResult);
 }
 
-#undef PROTSINK_THIS
-
 static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = {
     ProtocolProxySink_QueryInterface,
     ProtocolProxySink_AddRef,
@@ -275,8 +277,8 @@ HRESULT create_protocol_proxy(IInternetProtocol *protocol, IInternetProtocolSink
     if(!sink)
         return E_OUTOFMEMORY;
 
-    sink->lpIInternetProtocolVtbl     = &ProtocolProxyVtbl;
-    sink->lpIInternetProtocolSinkVtbl = &InternetProtocolSinkVtbl;
+    sink->IInternetProtocol_iface.lpVtbl = &ProtocolProxyVtbl;
+    sink->IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkVtbl;
     sink->ref = 1;
 
     IInternetProtocol_AddRef(protocol);
diff --git a/reactos/dll/win32/urlmon/regsvr.c b/reactos/dll/win32/urlmon/regsvr.c
deleted file mode 100644 (file)
index 6e417ac..0000000
+++ /dev/null
@@ -1,609 +0,0 @@
-/*
- *     self-registerable dll functions for urlmon.dll
- *
- * Copyright (C) 2003 John K. Hohm
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-#include <stdio.h>
-
-#include "urlmon_main.h"
-
-#include "winreg.h"
-#include "advpub.h"
-
-#include "wine/debug.h"
-#include "wine/unicode.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
-
-/*
- * Near the bottom of this file are the exported DllRegisterServer and
- * DllUnregisterServer, which make all this worthwhile.
- */
-
-/***********************************************************************
- *             interface for self-registering
- */
-struct regsvr_interface
-{
-    IID const *iid;            /* NULL for end of list */
-    LPCSTR name;               /* can be NULL to omit */
-    IID const *base_iid;       /* can be NULL to omit */
-    int num_methods;           /* can be <0 to omit */
-    CLSID const *ps_clsid;     /* can be NULL to omit */
-    CLSID const *ps_clsid32;   /* can be NULL to omit */
-};
-
-static HRESULT register_interfaces(struct regsvr_interface const *list);
-static HRESULT unregister_interfaces(struct regsvr_interface const *list);
-
-struct regsvr_coclass
-{
-    CLSID const *clsid;                /* NULL for end of list */
-    LPCSTR name;               /* can be NULL to omit */
-    LPCSTR ips;                        /* can be NULL to omit */
-    LPCSTR ips32;              /* can be NULL to omit */
-    LPCSTR ips32_tmodel;       /* can be NULL to omit */
-    LPCSTR progid;             /* can be NULL to omit */
-    LPCSTR viprogid;           /* can be NULL to omit */
-    LPCSTR progid_extra;       /* can be NULL to omit */
-};
-
-static HRESULT register_coclasses(struct regsvr_coclass const *list);
-static HRESULT unregister_coclasses(struct regsvr_coclass const *list);
-
-/***********************************************************************
- *             static string constants
- */
-static WCHAR const interface_keyname[10] = {
-    'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 };
-static WCHAR const base_ifa_keyname[14] = {
-    'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c',
-    'e', 0 };
-static WCHAR const num_methods_keyname[11] = {
-    'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 };
-static WCHAR const ps_clsid_keyname[15] = {
-    'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
-    'i', 'd', 0 };
-static WCHAR const ps_clsid32_keyname[17] = {
-    'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's',
-    'i', 'd', '3', '2', 0 };
-static WCHAR const clsid_keyname[6] = {
-    'C', 'L', 'S', 'I', 'D', 0 };
-static WCHAR const curver_keyname[7] = {
-    'C', 'u', 'r', 'V', 'e', 'r', 0 };
-static WCHAR const ips_keyname[13] = {
-    'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
-    0 };
-static WCHAR const ips32_keyname[15] = {
-    'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r',
-    '3', '2', 0 };
-static WCHAR const progid_keyname[7] = {
-    'P', 'r', 'o', 'g', 'I', 'D', 0 };
-static WCHAR const viprogid_keyname[25] = {
-    'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p',
-    'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D',
-    0 };
-static char const tmodel_valuename[] = "ThreadingModel";
-
-/***********************************************************************
- *             static helper functions
- */
-static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid);
-static LONG register_key_defvalueW(HKEY base, WCHAR const *name,
-                                  WCHAR const *value);
-static LONG register_key_defvalueA(HKEY base, WCHAR const *name,
-                                  char const *value);
-static LONG register_progid(WCHAR const *clsid,
-                           char const *progid, char const *curver_progid,
-                           char const *name, char const *extra);
-
-/***********************************************************************
- *             register_interfaces
- */
-static HRESULT register_interfaces(struct regsvr_interface const *list)
-{
-    LONG res = ERROR_SUCCESS;
-    HKEY interface_key;
-
-    res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0,
-                         KEY_READ | KEY_WRITE, NULL, &interface_key, NULL);
-    if (res != ERROR_SUCCESS) goto error_return;
-
-    for (; res == ERROR_SUCCESS && list->iid; ++list) {
-       WCHAR buf[39];
-       HKEY iid_key;
-
-       StringFromGUID2(list->iid, buf, 39);
-       res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0,
-                             KEY_READ | KEY_WRITE, NULL, &iid_key, NULL);
-       if (res != ERROR_SUCCESS) goto error_close_interface_key;
-
-       if (list->name) {
-           res = RegSetValueExA(iid_key, NULL, 0, REG_SZ,
-                                (CONST BYTE*)(list->name),
-                                strlen(list->name) + 1);
-           if (res != ERROR_SUCCESS) goto error_close_iid_key;
-       }
-
-       if (list->base_iid) {
-           res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid);
-           if (res != ERROR_SUCCESS) goto error_close_iid_key;
-       }
-
-       if (0 <= list->num_methods) {
-           static WCHAR const fmt[3] = { '%', 'd', 0 };
-           HKEY key;
-
-           res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0,
-                                 KEY_READ | KEY_WRITE, NULL, &key, NULL);
-           if (res != ERROR_SUCCESS) goto error_close_iid_key;
-
-           sprintfW(buf, fmt, list->num_methods);
-           res = RegSetValueExW(key, NULL, 0, REG_SZ,
-                                (CONST BYTE*)buf,
-                                (lstrlenW(buf) + 1) * sizeof(WCHAR));
-           RegCloseKey(key);
-
-           if (res != ERROR_SUCCESS) goto error_close_iid_key;
-       }
-
-       if (list->ps_clsid) {
-           res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid);
-           if (res != ERROR_SUCCESS) goto error_close_iid_key;
-       }
-
-       if (list->ps_clsid32) {
-           res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32);
-           if (res != ERROR_SUCCESS) goto error_close_iid_key;
-       }
-
-    error_close_iid_key:
-       RegCloseKey(iid_key);
-    }
-
-error_close_interface_key:
-    RegCloseKey(interface_key);
-error_return:
-    return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
-}
-
-/***********************************************************************
- *             unregister_interfaces
- */
-static HRESULT unregister_interfaces(struct regsvr_interface const *list)
-{
-    LONG res = ERROR_SUCCESS;
-    HKEY interface_key;
-
-    res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0,
-                       KEY_READ | KEY_WRITE, &interface_key);
-    if (res == ERROR_FILE_NOT_FOUND) return S_OK;
-    if (res != ERROR_SUCCESS) goto error_return;
-
-    for (; res == ERROR_SUCCESS && list->iid; ++list) {
-       WCHAR buf[39];
-
-       StringFromGUID2(list->iid, buf, 39);
-       res = RegDeleteTreeW(interface_key, buf);
-       if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
-    }
-
-    RegCloseKey(interface_key);
-error_return:
-    return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
-}
-
-/***********************************************************************
- *             register_coclasses
- */
-static HRESULT register_coclasses(struct regsvr_coclass const *list)
-{
-    LONG res = ERROR_SUCCESS;
-    HKEY coclass_key;
-
-    res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0,
-                         KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL);
-    if (res != ERROR_SUCCESS) goto error_return;
-
-    for (; res == ERROR_SUCCESS && list->clsid; ++list) {
-       WCHAR buf[39];
-       HKEY clsid_key;
-
-       StringFromGUID2(list->clsid, buf, 39);
-       res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0,
-                             KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL);
-       if (res != ERROR_SUCCESS) goto error_close_coclass_key;
-
-       if (list->name) {
-           res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ,
-                                (CONST BYTE*)(list->name),
-                                strlen(list->name) + 1);
-           if (res != ERROR_SUCCESS) goto error_close_clsid_key;
-       }
-
-       if (list->ips) {
-           res = register_key_defvalueA(clsid_key, ips_keyname, list->ips);
-           if (res != ERROR_SUCCESS) goto error_close_clsid_key;
-       }
-
-       if (list->ips32) {
-           HKEY ips32_key;
-
-           res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0,
-                                 KEY_READ | KEY_WRITE, NULL,
-                                 &ips32_key, NULL);
-           if (res != ERROR_SUCCESS) goto error_close_clsid_key;
-
-           res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ,
-                                (CONST BYTE*)list->ips32,
-                                lstrlenA(list->ips32) + 1);
-           if (res == ERROR_SUCCESS && list->ips32_tmodel)
-               res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ,
-                                    (CONST BYTE*)list->ips32_tmodel,
-                                    strlen(list->ips32_tmodel) + 1);
-           RegCloseKey(ips32_key);
-           if (res != ERROR_SUCCESS) goto error_close_clsid_key;
-       }
-
-       if (list->progid) {
-           res = register_key_defvalueA(clsid_key, progid_keyname,
-                                        list->progid);
-           if (res != ERROR_SUCCESS) goto error_close_clsid_key;
-
-           res = register_progid(buf, list->progid, NULL,
-                                 list->name, list->progid_extra);
-           if (res != ERROR_SUCCESS) goto error_close_clsid_key;
-       }
-
-       if (list->viprogid) {
-           res = register_key_defvalueA(clsid_key, viprogid_keyname,
-                                        list->viprogid);
-           if (res != ERROR_SUCCESS) goto error_close_clsid_key;
-
-           res = register_progid(buf, list->viprogid, list->progid,
-                                 list->name, list->progid_extra);
-           if (res != ERROR_SUCCESS) goto error_close_clsid_key;
-       }
-
-    error_close_clsid_key:
-       RegCloseKey(clsid_key);
-    }
-
-error_close_coclass_key:
-    RegCloseKey(coclass_key);
-error_return:
-    return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
-}
-
-/***********************************************************************
- *             unregister_coclasses
- */
-static HRESULT unregister_coclasses(struct regsvr_coclass const *list)
-{
-    LONG res = ERROR_SUCCESS;
-    HKEY coclass_key;
-
-    res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0,
-                       KEY_READ | KEY_WRITE, &coclass_key);
-    if (res == ERROR_FILE_NOT_FOUND) return S_OK;
-    if (res != ERROR_SUCCESS) goto error_return;
-
-    for (; res == ERROR_SUCCESS && list->clsid; ++list) {
-       WCHAR buf[39];
-
-       StringFromGUID2(list->clsid, buf, 39);
-       res = RegDeleteTreeW(coclass_key, buf);
-       if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
-       if (res != ERROR_SUCCESS) goto error_close_coclass_key;
-
-       if (list->progid) {
-           res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid);
-           if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
-           if (res != ERROR_SUCCESS) goto error_close_coclass_key;
-       }
-
-       if (list->viprogid) {
-           res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid);
-           if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS;
-           if (res != ERROR_SUCCESS) goto error_close_coclass_key;
-       }
-    }
-
-error_close_coclass_key:
-    RegCloseKey(coclass_key);
-error_return:
-    return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK;
-}
-
-/***********************************************************************
- *             regsvr_key_guid
- */
-static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid)
-{
-    WCHAR buf[39];
-
-    StringFromGUID2(guid, buf, 39);
-    return register_key_defvalueW(base, name, buf);
-}
-
-/***********************************************************************
- *             regsvr_key_defvalueW
- */
-static LONG register_key_defvalueW(
-    HKEY base,
-    WCHAR const *name,
-    WCHAR const *value)
-{
-    LONG res;
-    HKEY key;
-
-    res = RegCreateKeyExW(base, name, 0, NULL, 0,
-                         KEY_READ | KEY_WRITE, NULL, &key, NULL);
-    if (res != ERROR_SUCCESS) return res;
-    res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
-                        (lstrlenW(value) + 1) * sizeof(WCHAR));
-    RegCloseKey(key);
-    return res;
-}
-
-/***********************************************************************
- *             regsvr_key_defvalueA
- */
-static LONG register_key_defvalueA(
-    HKEY base,
-    WCHAR const *name,
-    char const *value)
-{
-    LONG res;
-    HKEY key;
-
-    res = RegCreateKeyExW(base, name, 0, NULL, 0,
-                         KEY_READ | KEY_WRITE, NULL, &key, NULL);
-    if (res != ERROR_SUCCESS) return res;
-    res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value,
-                        lstrlenA(value) + 1);
-    RegCloseKey(key);
-    return res;
-}
-
-/***********************************************************************
- *             regsvr_progid
- */
-static LONG register_progid(
-    WCHAR const *clsid,
-    char const *progid,
-    char const *curver_progid,
-    char const *name,
-    char const *extra)
-{
-    LONG res;
-    HKEY progid_key;
-
-    res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0,
-                         NULL, 0, KEY_READ | KEY_WRITE, NULL,
-                         &progid_key, NULL);
-    if (res != ERROR_SUCCESS) return res;
-
-    if (name) {
-       res = RegSetValueExA(progid_key, NULL, 0, REG_SZ,
-                            (CONST BYTE*)name, strlen(name) + 1);
-       if (res != ERROR_SUCCESS) goto error_close_progid_key;
-    }
-
-    if (clsid) {
-       res = register_key_defvalueW(progid_key, clsid_keyname, clsid);
-       if (res != ERROR_SUCCESS) goto error_close_progid_key;
-    }
-
-    if (curver_progid) {
-       res = register_key_defvalueA(progid_key, curver_keyname,
-                                    curver_progid);
-       if (res != ERROR_SUCCESS) goto error_close_progid_key;
-    }
-
-    if (extra) {
-       HKEY extra_key;
-
-       res = RegCreateKeyExA(progid_key, extra, 0,
-                             NULL, 0, KEY_READ | KEY_WRITE, NULL,
-                             &extra_key, NULL);
-       if (res == ERROR_SUCCESS)
-           RegCloseKey(extra_key);
-    }
-
-error_close_progid_key:
-    RegCloseKey(progid_key);
-    return res;
-}
-
-/***********************************************************************
- *             coclass list
- */
-static struct regsvr_coclass const coclass_list[] = {
-    {   &CLSID_StdURLMoniker,
-       "URL Moniker",
-       NULL,
-       "urlmon.dll",
-       "Apartment"
-    },
-    {   &CLSID_CdlProtocol,
-        "CDL: Asynchronous Pluggable Protocol Handler",
-        NULL,
-        "urlmon.dll",
-        "Apartment"
-    },
-    {   &CLSID_FileProtocol,
-        "file:, local: Asynchronous Pluggable Protocol Handler",
-        NULL,
-        "urlmon.dll",
-        "Apartment"
-    },
-    {   &CLSID_FtpProtocol,
-        "ftp: Asynchronous Pluggable Protocol Handler",
-        NULL,
-        "urlmon.dll",
-        "Apartment"
-    },
-    {   &CLSID_GopherProtocol,
-        "gopher: Asynchronous Pluggable Protocol Handler",
-        NULL,
-        "urlmon.dll",
-        "Apartment"
-    },
-    {   &CLSID_HttpProtocol,
-        "http: Asynchronous Pluggable Protocol Handler",
-        NULL,
-        "urlmon.dll",
-        "Apartment"
-    },
-    {   &CLSID_HttpSProtocol,
-        "https: Asynchronous Pluggable Protocol Handler",
-        NULL,
-        "urlmon.dll",
-        "Apartment"
-    },
-    {   &CLSID_MkProtocol,
-        "mk: Asynchronous Pluggable Protocol Handler",
-        NULL,
-        "urlmon.dll",
-        "Apartment"
-    },
-    {   &CLSID_InternetSecurityManager,
-        "Security Manager",
-        NULL,
-        "urlmon.dll",
-        "Both"
-    },
-    {   &CLSID_InternetZoneManager,
-        "URL Zone Manager",
-        NULL,
-        "urlmon.dll",
-        "Both"
-    },
-    {   &CLSID_PSFactoryBuffer,
-        "URLMoniker ProxyStub Factory",
-        NULL,
-        "urlmon.dll",
-        "Apartment"
-    },
-    { NULL }                   /* list terminator */
-};
-
-/***********************************************************************
- *             interface list
- */
-
-static struct regsvr_interface const interface_list[] = {
-    { NULL }                   /* list terminator */
-};
-
-/***********************************************************************
- *              register_inf
- */
-
-#define INF_SET_CLSID(clsid)                  \
-    do                                        \
-    {                                         \
-        static CHAR name[] = #clsid;          \
-                                              \
-        pse[i].pszName = name;                \
-        clsids[i++] = &clsid;                 \
-    } while (0)
-
-static HRESULT register_inf(BOOL doregister)
-{
-    HRESULT hres;
-    HMODULE hAdvpack;
-    HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable);
-    STRTABLEA strtable;
-    STRENTRYA pse[8];
-    static CLSID const *clsids[8];
-    unsigned int i = 0;
-
-    static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0};
-
-    INF_SET_CLSID(CLSID_CdlProtocol);
-    INF_SET_CLSID(CLSID_FileProtocol);
-    INF_SET_CLSID(CLSID_FtpProtocol);
-    INF_SET_CLSID(CLSID_GopherProtocol);
-    INF_SET_CLSID(CLSID_HttpProtocol);
-    INF_SET_CLSID(CLSID_HttpSProtocol);
-    INF_SET_CLSID(CLSID_MkProtocol);
-    INF_SET_CLSID(CLSID_DeCompMimeFilter);
-
-    for(i = 0; i < sizeof(pse)/sizeof(pse[0]); i++) {
-        pse[i].pszValue = heap_alloc(39);
-        sprintf(pse[i].pszValue, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
-                clsids[i]->Data1, clsids[i]->Data2, clsids[i]->Data3, clsids[i]->Data4[0],
-                clsids[i]->Data4[1], clsids[i]->Data4[2], clsids[i]->Data4[3], clsids[i]->Data4[4],
-                clsids[i]->Data4[5], clsids[i]->Data4[6], clsids[i]->Data4[7]);
-    }
-
-    strtable.cEntries = sizeof(pse)/sizeof(pse[0]);
-    strtable.pse = pse;
-
-    hAdvpack = LoadLibraryW(wszAdvpack);
-    pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall");
-
-    hres = pRegInstall(hProxyDll, doregister ? "RegisterDll" : "UnregisterDll", &strtable);
-
-    for(i=0; i < sizeof(pse)/sizeof(pse[0]); i++)
-        heap_free(pse[i].pszValue);
-
-    return hres;
-}
-
-#undef INF_SET_CLSID
-
-/***********************************************************************
- *             DllRegisterServer (URLMON.@)
- */
-HRESULT WINAPI DllRegisterServer(void)
-{
-    HRESULT hr;
-
-    TRACE("\n");
-
-    hr = URLMON_DllRegisterServer();
-    if(SUCCEEDED(hr))
-        hr = register_coclasses(coclass_list);
-    if(SUCCEEDED(hr))
-       hr = register_interfaces(interface_list);
-    if(SUCCEEDED(hr))
-        hr = register_inf(TRUE);
-    return hr;
-}
-
-/***********************************************************************
- *             DllUnregisterServer (URLMON.@)
- */
-HRESULT WINAPI DllUnregisterServer(void)
-{
-    HRESULT hr;
-
-    TRACE("\n");
-
-    hr = URLMON_DllUnregisterServer();
-    if(SUCCEEDED(hr))
-        hr = unregister_coclasses(coclass_list);
-    if(SUCCEEDED(hr))
-       hr = unregister_interfaces(interface_list);
-    if(SUCCEEDED(hr))
-        hr = register_inf(FALSE);
-    return hr;
-}
index c87ea81..c86575d 100644 (file)
@@ -16,6 +16,9 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+/* @makedep: urlmon.rgs */
+1 WINE_REGISTRY urlmon.rgs
+
 /* @makedep: urlmon.inf */
 REGINST REGINST urlmon.inf
 
index 6b12a9a..7b4bb35 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (c) 2004 Huw D M Davies
  * Copyright 2004 Jacek Caban
  * Copyright 2009 Detlef Riekenberg
+ * Copyright 2011 Thomas Mullaly for CodeWeavers
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -26,6 +27,9 @@
 #include "winreg.h"
 #include "wininet.h"
 
+#define NO_SHLWAPI_REG
+#include "shlwapi.h"
+
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
@@ -45,6 +49,13 @@ static const WCHAR wszZonesKey[] = {'S','o','f','t','w','a','r','e','\\',
                                     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
                                     'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
                                     'Z','o','n','e','s','\\',0};
+static const WCHAR wszZoneMapDomainsKey[] = {'S','o','f','t','w','a','r','e','\\',
+                                             'M','i','c','r','o','s','o','f','t','\\',
+                                             'W','i','n','d','o','w','s','\\',
+                                             'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
+                                             'I','n','t','e','r','n','e','t',' ','S','e','t','t','i','n','g','s','\\',
+                                             'Z','o','n','e','M','a','p','\\',
+                                             'D','o','m','a','i','n','s',0};
 
 /********************************************************************
  * get_string_from_reg [internal]
@@ -140,6 +151,350 @@ static HRESULT get_zone_from_reg(LPCWSTR schema, DWORD *zone)
     return S_OK;
 }
 
+/********************************************************************
+ * matches_domain_pattern [internal]
+ *
+ * Checks if the given string matches the specified domain pattern.
+ *
+ * This function looks for explicit wildcard domain components iff
+ * they appear at the very beginning of the 'pattern' string
+ *
+ *  pattern = "*.google.com"
+ */
+static BOOL matches_domain_pattern(LPCWSTR pattern, LPCWSTR str, BOOL implicit_wildcard, LPCWSTR *matched)
+{
+    BOOL matches = FALSE;
+    DWORD pattern_len = strlenW(pattern);
+    DWORD str_len = strlenW(str);
+
+    TRACE("(%d) Checking if %s matches %s\n", implicit_wildcard, debugstr_w(str), debugstr_w(pattern));
+
+    *matched = NULL;
+    if(str_len >= pattern_len) {
+        /* Check if there's an explicit wildcard in the pattern. */
+        if(pattern[0] == '*' && pattern[1] == '.') {
+            /* Make sure that 'str' matches the wildcard pattern.
+             *
+             * Example:
+             *  pattern = "*.google.com"
+             *
+             * So in this case 'str' would have to end with ".google.com" in order
+             * to map to this pattern.
+             */
+            if(str_len >= pattern_len+1 && !strcmpiW(str+(str_len-pattern_len+1), pattern+1)) {
+                /* Check if there's another '.' inside of the "unmatched" portion
+                 * of 'str'.
+                 *
+                 * Example:
+                 *  pattern = "*.google.com"
+                 *  str     = "test.testing.google.com"
+                 *
+                 * The currently matched portion is ".google.com" in 'str', we need
+                 * see if there's a '.' inside of the unmatched portion ("test.testing"), because
+                 * if there is and 'implicit_wildcard' isn't set, then this isn't
+                 * a match.
+                 */
+                const WCHAR *ptr;
+                if(str_len > pattern_len+1 && (ptr = memrchrW(str, '.', str_len-pattern_len-2))) {
+                    if(implicit_wildcard) {
+                        matches = TRUE;
+                        *matched = ptr+1;
+                    }
+                } else {
+                    matches = TRUE;
+                    *matched = str;
+                }
+            }
+        } else if(implicit_wildcard && str_len > pattern_len) {
+            /* When the pattern has an implicit wildcard component, it means
+             * that anything goes in 'str' as long as it ends with the pattern
+             * and that the beginning of the match has a '.' before it.
+             *
+             * Example:
+             *  pattern = "google.com"
+             *  str     = "www.google.com"
+             *
+             * Implicitly matches the pattern, where as:
+             *
+             *  pattern = "google.com"
+             *  str     = "wwwgoogle.com"
+             *
+             * Doesn't match the pattern.
+             */
+            if(str_len > pattern_len) {
+                if(str[str_len-pattern_len-1] == '.' && !strcmpiW(str+(str_len-pattern_len), pattern)) {
+                    matches = TRUE;
+                    *matched = str+(str_len-pattern_len);
+                }
+            }
+        } else {
+            /* The pattern doesn't have an implicit wildcard, or an explicit wildcard,
+             * so 'str' has to be an exact match to the 'pattern'.
+             */
+            if(!strcmpiW(str, pattern)) {
+                matches = TRUE;
+                *matched = str;
+            }
+        }
+    }
+
+    if(matches)
+        TRACE("Found a match: matched=%s\n", debugstr_w(*matched));
+    else
+        TRACE("No match found\n");
+
+    return matches;
+}
+
+static BOOL get_zone_for_scheme(HKEY key, LPCWSTR schema, DWORD *zone)
+{
+    static const WCHAR wildcardW[] = {'*',0};
+
+    DWORD res;
+    DWORD size = sizeof(DWORD);
+    DWORD type;
+
+    /* See if the key contains a value for the scheme first. */
+    res = RegQueryValueExW(key, schema, NULL, &type, (BYTE*)zone, &size);
+    if(type != REG_DWORD)
+        WARN("Unexpected value type %d for value %s, expected REG_DWORD\n", type, debugstr_w(schema));
+
+    if(res != ERROR_SUCCESS || type != REG_DWORD) {
+        /* Try to get the zone for the wildcard scheme. */
+        size = sizeof(DWORD);
+        res = RegQueryValueExW(key, wildcardW, NULL, &type, (BYTE*)zone, &size);
+        if(type != REG_DWORD)
+            WARN("Unexpected value type %d for value %s, expected REG_DWORD\n", type, debugstr_w(wildcardW));
+    }
+
+    return res == ERROR_SUCCESS && type == REG_DWORD;
+}
+
+/********************************************************************
+ * search_domain_for_zone [internal]
+ *
+ * Searches the specified 'domain' registry key to see if 'host' maps into it, or any
+ * of it's subdomain registry keys.
+ *
+ * Returns S_OK if a match is found, S_FALSE if no matches were found, or an error code.
+ */
+static HRESULT search_domain_for_zone(HKEY domains, LPCWSTR domain, DWORD domain_len, LPCWSTR schema,
+                                      LPCWSTR host, DWORD host_len, DWORD *zone)
+{
+    BOOL found = FALSE;
+    HKEY domain_key;
+    DWORD res;
+    LPCWSTR matched;
+
+    if(host_len >= domain_len && matches_domain_pattern(domain, host, TRUE, &matched)) {
+        res = RegOpenKeyW(domains, domain, &domain_key);
+        if(res != ERROR_SUCCESS) {
+            ERR("Failed to open domain key %s: %d\n", debugstr_w(domain), res);
+            return E_UNEXPECTED;
+        }
+
+        if(matched == host)
+            found = get_zone_for_scheme(domain_key, schema, zone);
+        else {
+            INT domain_offset;
+            DWORD subdomain_count, subdomain_len;
+            BOOL check_domain = TRUE;
+
+            find_domain_name(domain, domain_len, &domain_offset);
+
+            res = RegQueryInfoKeyW(domain_key, NULL, NULL, NULL, &subdomain_count, &subdomain_len,
+                                   NULL, NULL, NULL, NULL, NULL, NULL);
+            if(res != ERROR_SUCCESS) {
+                ERR("Unable to query info for key %s: %d\n", debugstr_w(domain), res);
+                RegCloseKey(domain_key);
+                return E_UNEXPECTED;
+            }
+
+            if(subdomain_count) {
+                WCHAR *subdomain;
+                WCHAR *component;
+                DWORD i;
+
+                subdomain = heap_alloc((subdomain_len+1)*sizeof(WCHAR));
+                if(!subdomain) {
+                    RegCloseKey(domain_key);
+                    return E_OUTOFMEMORY;
+                }
+
+                component = heap_strndupW(host, matched-host-1);
+                if(!component) {
+                    heap_free(subdomain);
+                    RegCloseKey(domain_key);
+                    return E_OUTOFMEMORY;
+                }
+
+                for(i = 0; i < subdomain_count; ++i) {
+                    DWORD len = subdomain_len+1;
+                    const WCHAR *sub_matched;
+
+                    res = RegEnumKeyExW(domain_key, i, subdomain, &len, NULL, NULL, NULL, NULL);
+                    if(res != ERROR_SUCCESS) {
+                        heap_free(component);
+                        heap_free(subdomain);
+                        RegCloseKey(domain_key);
+                        return E_UNEXPECTED;
+                    }
+
+                    if(matches_domain_pattern(subdomain, component, FALSE, &sub_matched)) {
+                        HKEY subdomain_key;
+
+                        res = RegOpenKeyW(domain_key, subdomain, &subdomain_key);
+                        if(res != ERROR_SUCCESS) {
+                            ERR("Unable to open subdomain key %s of %s: %d\n", debugstr_w(subdomain),
+                                debugstr_w(domain), res);
+                            heap_free(component);
+                            heap_free(subdomain);
+                            RegCloseKey(domain_key);
+                            return E_UNEXPECTED;
+                        }
+
+                        found = get_zone_for_scheme(subdomain_key, schema, zone);
+                        check_domain = FALSE;
+                        RegCloseKey(subdomain_key);
+                        break;
+                    }
+                }
+                heap_free(subdomain);
+                heap_free(component);
+            }
+
+            /* There's a chance that 'host' implicitly mapped into 'domain', in
+             * which case we check to see if 'domain' contains zone information.
+             *
+             * This can only happen if 'domain' is it's own domain name.
+             *  Example:
+             *      "google.com" (domain name = "google.com")
+             *
+             *  So if:
+             *      host = "www.google.com"
+             *
+             *  Then host would map directly into the "google.com" domain key.
+             *
+             * If 'domain' has more than just it's domain name, or it does not
+             * have a domain name, then we don't perform the check. The reason
+             * for this is that these domains don't allow implicit mappings.
+             *  Example:
+             *      domain = "org" (has no domain name)
+             *      host   = "www.org"
+             *
+             *  The mapping would only happen if the "org" key had an explicit subkey
+             *  called "www".
+             */
+            if(check_domain && !domain_offset && !strchrW(host, matched-host-1))
+                found = get_zone_for_scheme(domain_key, schema, zone);
+        }
+        RegCloseKey(domain_key);
+    }
+
+    return found ? S_OK : S_FALSE;
+}
+
+static HRESULT search_for_domain_mapping(HKEY domains, LPCWSTR schema, LPCWSTR host, DWORD host_len, DWORD *zone)
+{
+    WCHAR *domain;
+    DWORD domain_count, domain_len, i;
+    DWORD res;
+    HRESULT hres = S_FALSE;
+
+    res = RegQueryInfoKeyW(domains, NULL, NULL, NULL, &domain_count, &domain_len,
+                           NULL, NULL, NULL, NULL, NULL, NULL);
+    if(res != ERROR_SUCCESS) {
+        WARN("Failed to retrieve information about key\n");
+        return E_UNEXPECTED;
+    }
+
+    if(!domain_count)
+        return S_FALSE;
+
+    domain = heap_alloc((domain_len+1)*sizeof(WCHAR));
+    if(!domain)
+        return E_OUTOFMEMORY;
+
+    for(i = 0; i < domain_count; ++i) {
+        DWORD len = domain_len+1;
+
+        res = RegEnumKeyExW(domains, i, domain, &len, NULL, NULL, NULL, NULL);
+        if(res != ERROR_SUCCESS) {
+            heap_free(domain);
+            return E_UNEXPECTED;
+        }
+
+        hres = search_domain_for_zone(domains, domain, len, schema, host, host_len, zone);
+        if(FAILED(hres) || hres == S_OK)
+            break;
+    }
+
+    heap_free(domain);
+    return hres;
+}
+
+static HRESULT get_zone_from_domains(LPCWSTR url, LPCWSTR schema, DWORD *zone)
+{
+    HRESULT hres;
+    WCHAR *host_name;
+    DWORD host_len = lstrlenW(url)+1;
+    DWORD res;
+    HKEY domains;
+
+    host_name = heap_alloc(host_len*sizeof(WCHAR));
+    if(!host_name)
+        return E_OUTOFMEMORY;
+
+    hres = CoInternetParseUrl(url, PARSE_DOMAIN, 0, host_name, host_len, &host_len, 0);
+    if(hres == S_FALSE) {
+        WCHAR *tmp = heap_realloc(host_name, (host_len+1)*sizeof(WCHAR));
+        if(!tmp) {
+            heap_free(host_name);
+            return E_OUTOFMEMORY;
+        }
+
+        host_name = tmp;
+        hres = CoInternetParseUrl(url, PARSE_DOMAIN, 0, host_name, host_len+1, &host_len, 0);
+    }
+
+    /* Windows doesn't play nice with unknown scheme types when it tries
+     * to check if a host name maps into any domains.
+     *
+     * The reason is with how CoInternetParseUrl handles unknown scheme types
+     * when it's parsing the domain of a URL (IE it always returns E_FAIL).
+     *
+     * Windows doesn't compenstate for this and simply doesn't check if
+     * the URL maps into any domains.
+     */
+    if(hres != S_OK) {
+        heap_free(host_name);
+        if(hres == E_FAIL)
+            return S_FALSE;
+        return hres;
+    }
+
+    /* First try CURRENT_USER. */
+    res = RegOpenKeyW(HKEY_CURRENT_USER, wszZoneMapDomainsKey, &domains);
+    if(res == ERROR_SUCCESS) {
+        hres = search_for_domain_mapping(domains, schema, host_name, host_len, zone);
+        RegCloseKey(domains);
+    } else
+        WARN("Failed to open HKCU's %s key\n", debugstr_w(wszZoneMapDomainsKey));
+
+    /* If that doesn't work try LOCAL_MACHINE. */
+    if(hres == S_FALSE) {
+        res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszZoneMapDomainsKey, &domains);
+        if(res == ERROR_SUCCESS) {
+            hres = search_for_domain_mapping(domains, schema, host_name, host_len, zone);
+            RegCloseKey(domains);
+        } else
+            WARN("Failed to open HKLM's %s key\n", debugstr_w(wszZoneMapDomainsKey));
+    }
+
+    heap_free(host_name);
+    return hres;
+}
+
 static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url)
 {
     LPWSTR secur_url;
@@ -147,7 +502,7 @@ static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url)
     DWORD size=0;
     HRESULT hres;
 
-    *zone = -1;
+    *zone = URLZONE_INVALID;
 
     hres = CoInternetGetSecurityUrl(url, &secur_url, PSU_SECURITY_URL_ONLY, 0);
     if(hres != S_OK) {
@@ -190,11 +545,11 @@ static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url)
             case DRIVE_FIXED:
             case DRIVE_CDROM:
             case DRIVE_RAMDISK:
-                *zone = 0;
+                *zone = URLZONE_LOCAL_MACHINE;
                 hres = S_OK;
                 break;
             case DRIVE_REMOTE:
-                *zone = 3;
+                *zone = URLZONE_INTERNET;
                 hres = S_OK;
                 break;
             default:
@@ -203,9 +558,10 @@ static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url)
         }
     }
 
-    if(*zone == -1) {
-        WARN("domains are not yet implemented\n");
-        hres = get_zone_from_reg(schema, zone);
+    if(*zone == URLZONE_INVALID) {
+        hres = get_zone_from_domains(secur_url, schema, zone);
+        if(hres == S_FALSE)
+            hres = get_zone_from_reg(schema, zone);
     }
 
     if(FAILED(hres) || !ret_url)
@@ -218,9 +574,9 @@ static HRESULT map_url_to_zone(LPCWSTR url, DWORD *zone, LPWSTR *ret_url)
 
 static HRESULT open_zone_key(HKEY parent_key, DWORD zone, HKEY *hkey)
 {
-    static const WCHAR wszFormat[] = {'%','s','%','l','d',0};
+    static const WCHAR wszFormat[] = {'%','s','%','u',0};
 
-    WCHAR key_name[sizeof(wszZonesKey)/sizeof(WCHAR)+8];
+    WCHAR key_name[sizeof(wszZonesKey)/sizeof(WCHAR)+12];
     DWORD res;
 
     wsprintfW(key_name, wszFormat, wszZonesKey, zone);
@@ -439,7 +795,7 @@ static HRESULT WINAPI SecManagerImpl_MapUrlToZone(IInternetSecurityManager *ifac
     }
 
     if(!pwszUrl) {
-        *pdwZone = -1;
+        *pdwZone = URLZONE_INVALID;
         return E_INVALIDARG;
     }
 
@@ -864,8 +1220,42 @@ static HRESULT WINAPI ZoneMgrImpl_SetZoneAttributes(IInternetZoneManagerEx2* ifa
                                                     DWORD dwZone,
                                                     ZONEATTRIBUTES* pZoneAttributes)
 {
-    FIXME("(%p)->(%08x %p) stub\n", iface, dwZone, pZoneAttributes);
-    return E_NOTIMPL;
+    ZoneMgrImpl* This = impl_from_IInternetZoneManagerEx2(iface);
+    HRESULT hr;
+    HKEY hcu;
+
+    TRACE("(%p)->(%d %p)\n", This, dwZone, pZoneAttributes);
+
+    if (!pZoneAttributes)
+        return E_INVALIDARG;
+
+    hr = open_zone_key(HKEY_CURRENT_USER, dwZone, &hcu);
+    if (FAILED(hr))
+        return S_OK;  /* IE6 returned E_FAIL here */
+
+    /* cbSize is ignored */
+    RegSetValueExW(hcu, displaynameW, 0, REG_SZ, (LPBYTE) pZoneAttributes->szDisplayName,
+                    (lstrlenW(pZoneAttributes->szDisplayName)+1)* sizeof(WCHAR));
+
+    RegSetValueExW(hcu, descriptionW, 0, REG_SZ, (LPBYTE) pZoneAttributes->szDescription,
+                    (lstrlenW(pZoneAttributes->szDescription)+1)* sizeof(WCHAR));
+
+    RegSetValueExW(hcu, iconW, 0, REG_SZ, (LPBYTE) pZoneAttributes->szIconPath,
+                    (lstrlenW(pZoneAttributes->szIconPath)+1)* sizeof(WCHAR));
+
+    RegSetValueExW(hcu, minlevelW, 0, REG_DWORD,
+                    (const BYTE*) &pZoneAttributes->dwTemplateMinLevel, sizeof(DWORD));
+
+    RegSetValueExW(hcu, currentlevelW, 0, REG_DWORD,
+                    (const BYTE*) &pZoneAttributes->dwTemplateCurrentLevel, sizeof(DWORD));
+
+    RegSetValueExW(hcu, recommendedlevelW, 0, REG_DWORD,
+                    (const BYTE*) &pZoneAttributes->dwTemplateRecommended, sizeof(DWORD));
+
+    RegSetValueExW(hcu, flagsW, 0, REG_DWORD, (const BYTE*) &pZoneAttributes->dwFlags, sizeof(DWORD));
+    RegCloseKey(hcu);
+    return S_OK;
+
 }
 
 /********************************************************************
@@ -1243,86 +1633,209 @@ HRESULT WINAPI CoInternetCreateZoneManager(IServiceProvider* pSP, IInternetZoneM
     return ZoneMgrImpl_Construct(NULL, (void**)ppZM);
 }
 
+static HRESULT parse_security_url(const WCHAR *url, PSUACTION action, WCHAR **result) {
+    IInternetProtocolInfo *protocol_info;
+    WCHAR *tmp, *new_url = NULL, *alloc_url = NULL;
+    DWORD size, new_size;
+    HRESULT hres = S_OK, parse_hres;
+
+    while(1) {
+        TRACE("parsing %s\n", debugstr_w(url));
+
+        protocol_info = get_protocol_info(url);
+        if(!protocol_info)
+            break;
+
+        size = strlenW(url)+1;
+        new_url = CoTaskMemAlloc(size*sizeof(WCHAR));
+        if(!new_url) {
+            hres = E_OUTOFMEMORY;
+            break;
+        }
+
+        new_size = 0;
+        parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_URL, 0, new_url, size, &new_size, 0);
+        if(parse_hres == S_FALSE) {
+            if(!new_size) {
+                hres = E_UNEXPECTED;
+                break;
+            }
+
+            tmp = CoTaskMemRealloc(new_url, new_size*sizeof(WCHAR));
+            if(!tmp) {
+                hres = E_OUTOFMEMORY;
+                break;
+            }
+            new_url = tmp;
+            parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_URL, 0, new_url,
+                    new_size, &new_size, 0);
+            if(parse_hres == S_FALSE) {
+                hres = E_FAIL;
+                break;
+            }
+        }
+
+        if(parse_hres != S_OK || !strcmpW(url, new_url))
+            break;
+
+        CoTaskMemFree(alloc_url);
+        url = alloc_url = new_url;
+        new_url = NULL;
+    }
+
+    CoTaskMemFree(new_url);
+
+    if(hres != S_OK) {
+        WARN("failed: %08x\n", hres);
+        CoTaskMemFree(alloc_url);
+        return hres;
+    }
+
+    if(action == PSU_DEFAULT && (protocol_info = get_protocol_info(url))) {
+        size = strlenW(url)+1;
+        new_url = CoTaskMemAlloc(size * sizeof(WCHAR));
+        if(new_url) {
+            new_size = 0;
+            parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_DOMAIN, 0,
+                    new_url, size, &new_size, 0);
+            if(parse_hres == S_FALSE) {
+                if(new_size) {
+                    tmp = CoTaskMemRealloc(new_url, new_size*sizeof(WCHAR));
+                    if(tmp) {
+                        new_url = tmp;
+                        parse_hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_DOMAIN, 0, new_url,
+                                new_size, &new_size, 0);
+                        if(parse_hres == S_FALSE)
+                            hres = E_FAIL;
+                    }else {
+                        hres = E_OUTOFMEMORY;
+                    }
+                }else {
+                    hres = E_UNEXPECTED;
+                }
+            }
+
+            if(hres == S_OK && parse_hres == S_OK) {
+                CoTaskMemFree(alloc_url);
+                url = alloc_url = new_url;
+                new_url = NULL;
+            }
+
+            CoTaskMemFree(new_url);
+        }else {
+            hres = E_OUTOFMEMORY;
+        }
+        IInternetProtocolInfo_Release(protocol_info);
+    }
+
+    if(FAILED(hres)) {
+        WARN("failed %08x\n", hres);
+        CoTaskMemFree(alloc_url);
+        return hres;
+    }
+
+    if(!alloc_url) {
+        size = strlenW(url)+1;
+        alloc_url = CoTaskMemAlloc(size * sizeof(WCHAR));
+        if(!alloc_url)
+            return E_OUTOFMEMORY;
+        memcpy(alloc_url, url, size * sizeof(WCHAR));
+    }
+
+    *result = alloc_url;
+    return S_OK;
+}
+
 /********************************************************************
  *      CoInternetGetSecurityUrl (URLMON.@)
  */
 HRESULT WINAPI CoInternetGetSecurityUrl(LPCWSTR pwzUrl, LPWSTR *ppwzSecUrl, PSUACTION psuAction, DWORD dwReserved)
 {
-    WCHAR buf1[INTERNET_MAX_URL_LENGTH], buf2[INTERNET_MAX_URL_LENGTH];
-    LPWSTR url, domain;
-    DWORD len;
+    WCHAR *secure_url;
     HRESULT hres;
 
     TRACE("(%p,%p,%u,%u)\n", pwzUrl, ppwzSecUrl, psuAction, dwReserved);
 
-    url = buf1;
-    domain = buf2;
-    strcpyW(url, pwzUrl);
-
-    while(1) {
-        hres = CoInternetParseUrl(url, PARSE_SECURITY_URL, 0, domain, INTERNET_MAX_URL_LENGTH, &len, 0);
-        if(hres!=S_OK || !strcmpW(url, domain))
-            break;
+    hres = parse_security_url(pwzUrl, psuAction, &secure_url);
+    if(FAILED(hres))
+        return hres;
 
-        if(url == buf1) {
-            url = buf2;
-            domain = buf1;
-        } else {
-            url = buf1;
-            domain = buf2;
+    if(psuAction != PSU_SECURITY_URL_ONLY) {
+        PARSEDURLW parsed_url = { sizeof(parsed_url) };
+        DWORD size;
+
+        /* FIXME: Use helpers from uri.c */
+        if(SUCCEEDED(ParseURLW(secure_url, &parsed_url))) {
+            WCHAR *new_url;
+
+            switch(parsed_url.nScheme) {
+            case URL_SCHEME_FTP:
+            case URL_SCHEME_HTTP:
+            case URL_SCHEME_HTTPS:
+                size = strlenW(secure_url)+1;
+                new_url = CoTaskMemAlloc(size * sizeof(WCHAR));
+                if(new_url)
+                    hres = UrlGetPartW(secure_url, new_url, &size, URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME);
+                else
+                    hres = E_OUTOFMEMORY;
+                CoTaskMemFree(secure_url);
+                if(hres != S_OK) {
+                    WARN("UrlGetPart failed: %08x\n", hres);
+                    CoTaskMemFree(new_url);
+                    return FAILED(hres) ? hres : E_FAIL;
+                }
+                secure_url = new_url;
+            }
         }
     }
 
-    if(psuAction==PSU_SECURITY_URL_ONLY) {
-        len = lstrlenW(url)+1;
-        *ppwzSecUrl = CoTaskMemAlloc(len*sizeof(WCHAR));
-        if(!*ppwzSecUrl)
-            return E_OUTOFMEMORY;
+    *ppwzSecUrl = secure_url;
+    return S_OK;
+}
 
-        memcpy(*ppwzSecUrl, url, len*sizeof(WCHAR));
-        return S_OK;
-    }
+/********************************************************************
+ *      CoInternetGetSecurityUrlEx (URLMON.@)
+ */
+HRESULT WINAPI CoInternetGetSecurityUrlEx(IUri *pUri, IUri **ppSecUri, PSUACTION psuAction, DWORD_PTR dwReserved)
+{
+    URL_SCHEME scheme_type;
+    BSTR secure_uri;
+    WCHAR *ret_url;
+    HRESULT hres;
 
-    hres = CoInternetParseUrl(url, PARSE_SECURITY_DOMAIN, 0, domain,
-            INTERNET_MAX_URL_LENGTH, &len, 0);
-    if(SUCCEEDED(hres)) {
-        len++;
-        *ppwzSecUrl = CoTaskMemAlloc(len*sizeof(WCHAR));
-        if(!*ppwzSecUrl)
-            return E_OUTOFMEMORY;
+    TRACE("(%p,%p,%u,%u)\n", pUri, ppSecUri, psuAction, (DWORD)dwReserved);
 
-        memcpy(*ppwzSecUrl, domain, len*sizeof(WCHAR));
-        return S_OK;
-    }
+    if(!pUri || !ppSecUri)
+        return E_INVALIDARG;
 
-    hres = CoInternetParseUrl(url, PARSE_SCHEMA, 0, domain,
-            INTERNET_MAX_URL_LENGTH, &len, 0);
-    if(hres == S_OK){
-        const WCHAR fileW[] = {'f','i','l','e',0};
-        if(!strcmpW(domain, fileW)){
-            hres = CoInternetParseUrl(url, PARSE_ROOTDOCUMENT, 0, domain, INTERNET_MAX_URL_LENGTH, &len, 0);
-        }else{
-            domain[len] = ':';
-            hres = CoInternetParseUrl(url, PARSE_DOMAIN, 0, domain+len+1,
-                    INTERNET_MAX_URL_LENGTH-len-1, &len, 0);
-            if(hres == S_OK) {
-                len = lstrlenW(domain)+1;
-                *ppwzSecUrl = CoTaskMemAlloc(len*sizeof(WCHAR));
-                if(!*ppwzSecUrl)
-                    return E_OUTOFMEMORY;
+    hres = IUri_GetDisplayUri(pUri, &secure_uri);
+    if(FAILED(hres))
+        return hres;
 
-                memcpy(*ppwzSecUrl, domain, len*sizeof(WCHAR));
-                return S_OK;
-            }
-        }
-    }else
+    hres = parse_security_url(secure_uri, psuAction, &ret_url);
+    SysFreeString(secure_uri);
+    if(FAILED(hres))
         return hres;
 
-    len = lstrlenW(url)+1;
-    *ppwzSecUrl = CoTaskMemAlloc(len*sizeof(WCHAR));
-    if(!*ppwzSecUrl)
-        return E_OUTOFMEMORY;
+    hres = CreateUri(ret_url, Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, 0, ppSecUri);
+    if(FAILED(hres)) {
+        CoTaskMemFree(ret_url);
+        return hres;
+    }
 
-    memcpy(*ppwzSecUrl, url, len*sizeof(WCHAR));
-    return S_OK;
+    /* File URIs have to hierarchical. */
+    hres = IUri_GetScheme(pUri, (DWORD*)&scheme_type);
+    if(SUCCEEDED(hres) && scheme_type == URL_SCHEME_FILE) {
+        const WCHAR *tmp = ret_url;
+
+        /* Check and see if a "//" is after the scheme name. */
+        tmp += sizeof(fileW)/sizeof(WCHAR);
+        if(*tmp != '/' || *(tmp+1) != '/')
+            hres = E_INVALIDARG;
+    }
+
+    if(SUCCEEDED(hres))
+        hres = CreateUri(ret_url, Uri_CREATE_ALLOW_IMPLICIT_WILDCARD_SCHEME, 0, ppSecUri);
+    CoTaskMemFree(ret_url);
+    return hres;
 }
index 72a3e2a..fc36c0b 100644 (file)
@@ -424,7 +424,7 @@ static HRESULT WINAPI InternetSession_CreateBinding(IInternetSession *iface,
         LPBC pBC, LPCWSTR szUrl, IUnknown *pUnkOuter, IUnknown **ppUnk,
         IInternetProtocol **ppOInetProt, DWORD dwOption)
 {
-    IInternetProtocolEx *protocol;
+    BindProtocol *protocol;
     HRESULT hres;
 
     TRACE("(%p %s %p %p %p %08x)\n", pBC, debugstr_w(szUrl), pUnkOuter, ppUnk,
@@ -437,7 +437,7 @@ static HRESULT WINAPI InternetSession_CreateBinding(IInternetSession *iface,
     if(FAILED(hres))
         return hres;
 
-    *ppOInetProt = (IInternetProtocol*)protocol;
+    *ppOInetProt = (IInternetProtocol*)&protocol->IInternetProtocolEx_iface;
     return S_OK;
 }
 
index fbb00a4..8ef740f 100644 (file)
 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
 
 typedef struct {
-    const IMonikerVtbl *lpIMonikerVtbl;
+    IMoniker      IMoniker_iface;
+    IUriContainer IUriContainer_iface;
 
     LONG ref;
 
     LPOLESTR URLName; /* URL string identified by this URLmoniker */
 } URLMoniker;
 
-#define MONIKER_THIS(iface) DEFINE_THIS(URLMoniker, IMoniker, iface)
+static inline URLMoniker *impl_from_IMoniker(IMoniker *iface)
+{
+    return CONTAINING_RECORD(iface, URLMoniker, IMoniker_iface);
+}
 
 static HRESULT WINAPI URLMoniker_QueryInterface(IMoniker *iface, REFIID riid, void **ppv)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
 
     if(!ppv)
        return E_INVALIDARG;
@@ -63,6 +67,9 @@ static HRESULT WINAPI URLMoniker_QueryInterface(IMoniker *iface, REFIID riid, vo
     }else if(IsEqualIID(&IID_IAsyncMoniker, riid)) {
         TRACE("(%p)->(IID_IAsyncMoniker %p)\n", This, ppv);
         *ppv = iface;
+    }else if(IsEqualIID(&IID_IUriContainer, riid)) {
+        TRACE("(%p)->(IID_IUriContainer %p)\n", This, ppv);
+        *ppv = &This->IUriContainer_iface;
     }else {
         WARN("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppv);
         *ppv = NULL;
@@ -75,7 +82,7 @@ static HRESULT WINAPI URLMoniker_QueryInterface(IMoniker *iface, REFIID riid, vo
 
 static ULONG WINAPI URLMoniker_AddRef(IMoniker *iface)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     ULONG refCount = InterlockedIncrement(&This->ref);
 
     TRACE("(%p) ref=%u\n",This, refCount);
@@ -85,7 +92,7 @@ static ULONG WINAPI URLMoniker_AddRef(IMoniker *iface)
 
 static ULONG WINAPI URLMoniker_Release(IMoniker *iface)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     ULONG refCount = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) ref=%u\n",This, refCount);
@@ -102,7 +109,7 @@ static ULONG WINAPI URLMoniker_Release(IMoniker *iface)
 
 static HRESULT WINAPI URLMoniker_GetClassID(IMoniker *iface, CLSID *pClassID)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
 
     TRACE("(%p,%p)\n", This, pClassID);
 
@@ -116,7 +123,7 @@ static HRESULT WINAPI URLMoniker_GetClassID(IMoniker *iface, CLSID *pClassID)
 
 static HRESULT WINAPI URLMoniker_IsDirty(IMoniker *iface)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
 
     TRACE("(%p)\n",This);
 
@@ -128,7 +135,7 @@ static HRESULT WINAPI URLMoniker_IsDirty(IMoniker *iface)
 
 static HRESULT WINAPI URLMoniker_Load(IMoniker* iface,IStream* pStm)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     HRESULT res;
     ULONG size;
     ULONG got;
@@ -164,7 +171,7 @@ static HRESULT WINAPI URLMoniker_Load(IMoniker* iface,IStream* pStm)
 
 static HRESULT WINAPI URLMoniker_Save(IMoniker *iface, IStream* pStm, BOOL fClearDirty)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     HRESULT res;
     ULONG size;
 
@@ -184,7 +191,7 @@ static HRESULT WINAPI URLMoniker_Save(IMoniker *iface, IStream* pStm, BOOL fClea
 
 static HRESULT WINAPI URLMoniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER *pcbSize)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
 
     TRACE("(%p,%p)\n",This,pcbSize);
 
@@ -198,7 +205,7 @@ static HRESULT WINAPI URLMoniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER *pcb
 static HRESULT WINAPI URLMoniker_BindToObject(IMoniker *iface, IBindCtx* pbc, IMoniker *pmkToLeft,
         REFIID riid, void **ppv)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     IRunningObjectTable *obj_tbl;
     IUri *uri;
     HRESULT hres;
@@ -224,12 +231,16 @@ static HRESULT WINAPI URLMoniker_BindToObject(IMoniker *iface, IBindCtx* pbc, IM
 static HRESULT WINAPI URLMoniker_BindToStorage(IMoniker* iface, IBindCtx* pbc,
         IMoniker* pmkToLeft, REFIID riid, void **ppvObject)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     IUri *uri;
     HRESULT hres;
 
     TRACE("(%p)->(%p %p %s %p)\n", This, pbc, pmkToLeft, debugstr_guid(riid), ppvObject);
 
+    if(ppvObject) *ppvObject = NULL;
+
+    if(!pbc || !ppvObject) return E_INVALIDARG;
+
     if(pmkToLeft)
         FIXME("Unsupported pmkToLeft\n");
 
@@ -246,8 +257,8 @@ static HRESULT WINAPI URLMoniker_BindToStorage(IMoniker* iface, IBindCtx* pbc,
 static HRESULT WINAPI URLMoniker_Reduce(IMoniker *iface, IBindCtx *pbc,
         DWORD dwReduceHowFar, IMoniker **ppmkToLeft, IMoniker **ppmkReduced)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
-    
+    URLMoniker *This = impl_from_IMoniker(iface);
+
     TRACE("(%p,%p,%d,%p,%p)\n", This, pbc, dwReduceHowFar, ppmkToLeft, ppmkReduced);
 
     if(!ppmkReduced)
@@ -261,14 +272,14 @@ static HRESULT WINAPI URLMoniker_Reduce(IMoniker *iface, IBindCtx *pbc,
 static HRESULT WINAPI URLMoniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight,
         BOOL fOnlyIfNotGeneric, IMoniker **ppmkComposite)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     FIXME("(%p)->(%p,%d,%p): stub\n",This,pmkRight,fOnlyIfNotGeneric,ppmkComposite);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI URLMoniker_Enum(IMoniker *iface, BOOL fForward, IEnumMoniker **ppenumMoniker)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
 
     TRACE("(%p,%d,%p)\n", This, fForward, ppenumMoniker);
 
@@ -282,7 +293,7 @@ static HRESULT WINAPI URLMoniker_Enum(IMoniker *iface, BOOL fForward, IEnumMonik
 
 static HRESULT WINAPI URLMoniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoniker)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     CLSID clsid;
     LPOLESTR urlPath;
     IBindCtx* bind;
@@ -316,7 +327,7 @@ static HRESULT WINAPI URLMoniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoni
 
 static HRESULT WINAPI URLMoniker_Hash(IMoniker *iface, DWORD *pdwHash)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     int  h = 0,i,skip,len;
     int  off = 0;
     LPOLESTR val;
@@ -347,7 +358,7 @@ static HRESULT WINAPI URLMoniker_Hash(IMoniker *iface, DWORD *pdwHash)
 static HRESULT WINAPI URLMoniker_IsRunning(IMoniker* iface, IBindCtx* pbc,
         IMoniker *pmkToLeft, IMoniker *pmkNewlyRunning)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     FIXME("(%p)->(%p,%p,%p): stub\n",This,pbc,pmkToLeft,pmkNewlyRunning);
     return E_NOTIMPL;
 }
@@ -355,28 +366,28 @@ static HRESULT WINAPI URLMoniker_IsRunning(IMoniker* iface, IBindCtx* pbc,
 static HRESULT WINAPI URLMoniker_GetTimeOfLastChange(IMoniker *iface,
         IBindCtx *pbc, IMoniker *pmkToLeft, FILETIME *pFileTime)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     FIXME("(%p)->(%p,%p,%p): stub\n", This, pbc, pmkToLeft, pFileTime);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI URLMoniker_Inverse(IMoniker *iface, IMoniker **ppmk)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     TRACE("(%p,%p)\n",This,ppmk);
     return MK_E_NOINVERSE;
 }
 
 static HRESULT WINAPI URLMoniker_CommonPrefixWith(IMoniker *iface, IMoniker *pmkOther, IMoniker **ppmkPrefix)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     FIXME("(%p)->(%p,%p): stub\n",This,pmkOther,ppmkPrefix);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI URLMoniker_RelativePathTo(IMoniker *iface, IMoniker *pmOther, IMoniker **ppmkRelPath)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     FIXME("(%p)->(%p,%p): stub\n",This,pmOther,ppmkRelPath);
     return E_NOTIMPL;
 }
@@ -384,7 +395,7 @@ static HRESULT WINAPI URLMoniker_RelativePathTo(IMoniker *iface, IMoniker *pmOth
 static HRESULT WINAPI URLMoniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
         LPOLESTR *ppszDisplayName)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     int len;
     
     TRACE("(%p,%p,%p,%p)\n", This, pbc, pmkToLeft, ppszDisplayName);
@@ -409,14 +420,14 @@ static HRESULT WINAPI URLMoniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
 static HRESULT WINAPI URLMoniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
         LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
     FIXME("(%p)->(%p,%p,%p,%p,%p): stub\n",This,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);
     return E_NOTIMPL;
 }
 
 static HRESULT WINAPI URLMoniker_IsSystemMoniker(IMoniker *iface, DWORD *pwdMksys)
 {
-    URLMoniker *This = MONIKER_THIS(iface);
+    URLMoniker *This = impl_from_IMoniker(iface);
 
     TRACE("(%p,%p)\n",This,pwdMksys);
 
@@ -454,6 +465,46 @@ static const IMonikerVtbl URLMonikerVtbl =
     URLMoniker_IsSystemMoniker
 };
 
+static inline URLMoniker *impl_from_IUriContainer(IUriContainer *iface)
+{
+    return CONTAINING_RECORD(iface, URLMoniker, IUriContainer_iface);
+}
+
+static HRESULT WINAPI UriContainer_QueryInterface(IUriContainer *iface, REFIID riid, void **ppv)
+{
+    URLMoniker *This = impl_from_IUriContainer(iface);
+    return IMoniker_QueryInterface(&This->IMoniker_iface, riid, ppv);
+}
+
+static ULONG WINAPI UriContainer_AddRef(IUriContainer *iface)
+{
+    URLMoniker *This = impl_from_IUriContainer(iface);
+    return IMoniker_AddRef(&This->IMoniker_iface);
+}
+
+static ULONG WINAPI UriContainer_Release(IUriContainer *iface)
+{
+    URLMoniker *This = impl_from_IUriContainer(iface);
+    return IMoniker_Release(&This->IMoniker_iface);
+}
+
+static HRESULT WINAPI UriContainer_GetIUri(IUriContainer *iface, IUri **ppIUri)
+{
+    URLMoniker *This = impl_from_IUriContainer(iface);
+
+    FIXME("(%p)->(%p)\n", This, ppIUri);
+
+    *ppIUri = NULL;
+    return S_FALSE;
+}
+
+static const IUriContainerVtbl UriContainerVtbl = {
+    UriContainer_QueryInterface,
+    UriContainer_AddRef,
+    UriContainer_Release,
+    UriContainer_GetIUri
+};
+
 static URLMoniker *alloc_moniker(void)
 {
     URLMoniker *ret;
@@ -462,7 +513,8 @@ static URLMoniker *alloc_moniker(void)
     if(!ret)
         return NULL;
 
-    ret->lpIMonikerVtbl = &URLMonikerVtbl;
+    ret->IMoniker_iface.lpVtbl = &URLMonikerVtbl;
+    ret->IUriContainer_iface.lpVtbl = &UriContainerVtbl;
     ret->ref = 1;
     ret->URLName = NULL;
 
@@ -557,8 +609,8 @@ HRESULT WINAPI CreateURLMonikerEx(IMoniker *pmkContext, LPCWSTR szURL, IMoniker
     hres = URLMoniker_Init(obj, lefturl, szURL);
     CoTaskMemFree(lefturl);
     if(SUCCEEDED(hres))
-       hres = URLMoniker_QueryInterface((IMoniker*)obj, &IID_IMoniker, (void**)ppmk);
-    IMoniker_Release((IMoniker*)obj);
+        hres = URLMoniker_QueryInterface(&obj->IMoniker_iface, &IID_IMoniker, (void**)ppmk);
+    IMoniker_Release(&obj->IMoniker_iface);
     return hres;
 }
 
index 5a942f6..792cd64 100644 (file)
@@ -32,11 +32,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
 
 typedef struct ProxyBindStatusCallback
 {
-    const IBindStatusCallbackVtbl *lpVtbl;
+    IBindStatusCallback IBindStatusCallback_iface;
 
     IBindStatusCallback *pBSC;
 } ProxyBindStatusCallback;
 
+static inline ProxyBindStatusCallback *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
+{
+    return CONTAINING_RECORD(iface, ProxyBindStatusCallback, IBindStatusCallback_iface);
+}
+
 static HRESULT WINAPI ProxyBindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
 {
     if (IsEqualGUID(&IID_IBindStatusCallback, riid) ||
@@ -64,7 +69,7 @@ static ULONG WINAPI ProxyBindStatusCallback_Release(IBindStatusCallback *iface)
 static HRESULT WINAPI ProxyBindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
                                                IBinding *pib)
 {
-    ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
+    ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
 
     if(This->pBSC)
         return IBindStatusCallback_OnStartBinding(This->pBSC, dwReserved, pib);
@@ -74,7 +79,7 @@ static HRESULT WINAPI ProxyBindStatusCallback_OnStartBinding(IBindStatusCallback
 
 static HRESULT WINAPI ProxyBindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
 {
-    ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
+    ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
 
     if(This->pBSC)
         return IBindStatusCallback_GetPriority(This->pBSC, pnPriority);
@@ -84,7 +89,7 @@ static HRESULT WINAPI ProxyBindStatusCallback_GetPriority(IBindStatusCallback *i
 
 static HRESULT WINAPI ProxyBindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
 {
-    ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
+    ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
 
     if(This->pBSC)
         return IBindStatusCallback_OnLowResource(This->pBSC, reserved);
@@ -95,7 +100,7 @@ static HRESULT WINAPI ProxyBindStatusCallback_OnLowResource(IBindStatusCallback
 static HRESULT WINAPI ProxyBindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
                                            ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
 {
-    ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
+    ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
 
     if(This->pBSC)
         return IBindStatusCallback_OnProgress(This->pBSC, ulProgress,
@@ -107,7 +112,7 @@ static HRESULT WINAPI ProxyBindStatusCallback_OnProgress(IBindStatusCallback *if
 
 static HRESULT WINAPI ProxyBindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
 {
-    ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
+    ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
 
     if(This->pBSC)
         return IBindStatusCallback_OnStopBinding(This->pBSC, hresult, szError);
@@ -117,7 +122,7 @@ static HRESULT WINAPI ProxyBindStatusCallback_OnStopBinding(IBindStatusCallback
 
 static HRESULT WINAPI ProxyBindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
 {
-    ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
+    ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
 
     if(This->pBSC)
         return IBindStatusCallback_GetBindInfo(This->pBSC, grfBINDF, pbindinfo);
@@ -128,7 +133,7 @@ static HRESULT WINAPI ProxyBindStatusCallback_GetBindInfo(IBindStatusCallback *i
 static HRESULT WINAPI ProxyBindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
                                                               DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
 {
-    ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
+    ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
 
     if(This->pBSC)
         return IBindStatusCallback_OnDataAvailable(This->pBSC, grfBSCF, dwSize,
@@ -139,7 +144,7 @@ static HRESULT WINAPI ProxyBindStatusCallback_OnDataAvailable(IBindStatusCallbac
 
 static HRESULT WINAPI ProxyBindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
 {
-    ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
+    ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
 
     if(This->pBSC)
         return IBindStatusCallback_OnObjectAvailable(This->pBSC, riid, punk);
@@ -170,7 +175,7 @@ static const IBindStatusCallbackVtbl BlockingBindStatusCallbackVtbl =
 
 static HRESULT WINAPI AsyncBindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
 {
-    ProxyBindStatusCallback *This = (ProxyBindStatusCallback *)iface;
+    ProxyBindStatusCallback *This = impl_from_IBindStatusCallback(iface);
     HRESULT hr = IBindStatusCallback_GetBindInfo(This->pBSC, grfBINDF, pbindinfo);
     *grfBINDF |= BINDF_PULLDATA | BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE;
     return hr;
@@ -276,10 +281,10 @@ HRESULT WINAPI URLOpenBlockingStreamW(LPUNKNOWN pCaller, LPCWSTR szURL,
     if (!szURL || !ppStream)
         return E_INVALIDARG;
 
-    blocking_bsc.lpVtbl = &BlockingBindStatusCallbackVtbl;
+    blocking_bsc.IBindStatusCallback_iface.lpVtbl = &BlockingBindStatusCallbackVtbl;
     blocking_bsc.pBSC = lpfnCB;
 
-    return URLStartDownload(szURL, ppStream, (IBindStatusCallback *)&blocking_bsc);
+    return URLStartDownload(szURL, ppStream, &blocking_bsc.IBindStatusCallback_iface);
 }
 
 /***********************************************************************
@@ -326,10 +331,10 @@ HRESULT WINAPI URLOpenStreamW(LPUNKNOWN pCaller, LPCWSTR szURL, DWORD dwReserved
     if (!szURL)
         return E_INVALIDARG;
 
-    async_bsc.lpVtbl = &AsyncBindStatusCallbackVtbl;
+    async_bsc.IBindStatusCallback_iface.lpVtbl = &AsyncBindStatusCallbackVtbl;
     async_bsc.pBSC = lpfnCB;
 
-    hr = URLStartDownload(szURL, &pStream, (IBindStatusCallback *)&async_bsc);
+    hr = URLStartDownload(szURL, &pStream, &async_bsc.IBindStatusCallback_iface);
     if (SUCCEEDED(hr) && pStream)
         IStream_Release(pStream);
 
index 681327f..f12f826 100644 (file)
@@ -258,11 +258,11 @@ static Uri *get_uri_obj(IUri *uri)
 }
 
 static inline BOOL is_alpha(WCHAR val) {
-       return ((val >= 'a' && val <= 'z') || (val >= 'A' && val <= 'Z'));
+    return ((val >= 'a' && val <= 'z') || (val >= 'A' && val <= 'Z'));
 }
 
 static inline BOOL is_num(WCHAR val) {
-       return (val >= '0' && val <= '9');
+    return (val >= '0' && val <= '9');
 }
 
 static inline BOOL is_drive_path(const WCHAR *str) {
@@ -350,6 +350,11 @@ static inline BOOL is_path_delim(WCHAR val) {
     return (!val || val == '#' || val == '?');
 }
 
+static inline BOOL is_slash(WCHAR c)
+{
+    return c == '/' || c == '\\';
+}
+
 static BOOL is_default_port(URL_SCHEME scheme, DWORD port) {
     DWORD i;
 
@@ -592,21 +597,6 @@ static inline void pct_encode_val(WCHAR val, WCHAR *dest) {
     dest[2] = hexDigits[val & 0xf];
 }
 
-/* Scans the range of characters [str, end] and returns the last occurrence
- * of 'ch' or returns NULL.
- */
-static const WCHAR *str_last_of(const WCHAR *str, const WCHAR *end, WCHAR ch) {
-    const WCHAR *ptr = end;
-
-    while(ptr >= str) {
-        if(*ptr == ch)
-            return ptr;
-        --ptr;
-    }
-
-    return NULL;
-}
-
 /* Attempts to parse the domain name from the host.
  *
  * This function also includes the Top-level Domain (TLD) name
@@ -614,10 +604,10 @@ static const WCHAR *str_last_of(const WCHAR *str, const WCHAR *end, WCHAR ch) {
  * a valid domain name it will assign 'domain_start' the offset
  * into 'host' where the domain name starts.
  *
- * It's implied that if a domain name its range is implied to be
+ * It's implied that if there is a domain name its range is:
  * [host+domain_start, host+host_len).
  */
-static void find_domain_name(const WCHAR *host, DWORD host_len,
+void find_domain_name(const WCHAR *host, DWORD host_len,
                              INT *domain_start) {
     const WCHAR *last_tld, *sec_last_tld, *end;
 
@@ -631,12 +621,12 @@ static void find_domain_name(const WCHAR *host, DWORD host_len,
     if(host_len < 4)
         return;
 
-    last_tld = str_last_of(host, end, '.');
+    last_tld = memrchrW(host, '.', host_len);
     if(!last_tld)
         /* http://hostname -> has no domain name. */
         return;
 
-    sec_last_tld = str_last_of(host, last_tld-1, '.');
+    sec_last_tld = memrchrW(host, '.', last_tld-host);
     if(!sec_last_tld) {
         /* If the '.' is at the beginning of the host there
          * has to be at least 3 characters in the TLD for it
@@ -687,7 +677,7 @@ static void find_domain_name(const WCHAR *host, DWORD host_len,
         if(last_tld - (sec_last_tld+1) == 3) {
             for(i = 0; i < sizeof(recognized_tlds)/sizeof(recognized_tlds[0]); ++i) {
                 if(!StrCmpNIW(sec_last_tld+1, recognized_tlds[i].tld_name, 3)) {
-                    const WCHAR *domain = str_last_of(host, sec_last_tld-1, '.');
+                    const WCHAR *domain = memrchrW(host, '.', sec_last_tld-host);
 
                     if(!domain)
                         *domain_start = 0;
@@ -705,7 +695,7 @@ static void find_domain_name(const WCHAR *host, DWORD host_len,
              * part of the TLD.
              *  Ex: www.google.fo.uk -> google.fo.uk as the domain name.
              */
-            const WCHAR *domain = str_last_of(host, sec_last_tld-1, '.');
+            const WCHAR *domain = memrchrW(host, '.', sec_last_tld-host);
 
             if(!domain)
                 *domain_start = 0;
@@ -727,8 +717,6 @@ static void find_domain_name(const WCHAR *host, DWORD host_len,
 /* Removes the dot segments from a hierarchical URIs path component. This
  * function performs the removal in place.
  *
- * This is a modified version of Qt's QUrl function "removeDotsFromPath".
- *
  * This function returns the new length of the path string.
  */
 static DWORD remove_dot_segments(WCHAR *path, DWORD path_len) {
@@ -738,48 +726,46 @@ static DWORD remove_dot_segments(WCHAR *path, DWORD path_len) {
     DWORD len;
 
     while(in < end) {
-        /* A.  if the input buffer begins with a prefix of "/./" or "/.",
-         *     where "." is a complete path segment, then replace that
-         *     prefix with "/" in the input buffer; otherwise,
+        /* Move the first path segment in the input buffer to the end of
+         * the output buffer, and any subsequent characters up to, including
+         * the next "/" character (if any) or the end of the input buffer.
          */
-        if(in <= end - 3 && in[0] == '/' && in[1] == '.' && in[2] == '/') {
-            in += 2;
-            continue;
-        } else if(in == end - 2 && in[0] == '/' && in[1] == '.') {
-            *out++ = '/';
-            in += 2;
+        while(in < end && !is_slash(*in))
+            *out++ = *in++;
+        if(in == end)
             break;
-        }
+        *out++ = *in++;
 
-        /* B.  if the input buffer begins with a prefix of "/../" or "/..",
-         *     where ".." is a complete path segment, then replace that
-         *     prefix with "/" in the input buffer and remove the last
-         *     segment and its preceding "/" (if any) from the output
-         *     buffer; otherwise,
-         */
-        if(in <= end - 4 && in[0] == '/' && in[1] == '.' && in[2] == '.' && in[3] == '/') {
-            while(out > path && *(--out) != '/');
+        while(in < end) {
+            if(*in != '.')
+                break;
 
-            in += 3;
-            continue;
-        } else if(in == end - 3 && in[0] == '/' && in[1] == '.' && in[2] == '.') {
-            while(out > path && *(--out) != '/');
+            /* Handle ending "/." */
+            if(in + 1 == end) {
+                ++in;
+                break;
+            }
 
-            if(*out == '/')
-                ++out;
+            /* Handle "/./" */
+            if(is_slash(in[1])) {
+                in += 2;
+                continue;
+            }
 
-            in += 3;
-            break;
-        }
+            /* If we don't have "/../" or ending "/.." */
+            if(in[1] != '.' || (in + 2 != end && !is_slash(in[2])))
+                break;
 
-        /* C.  move the first path segment in the input buffer to the end of
-         *     the output buffer, including the initial "/" character (if
-         *     any) and any subsequent characters up to, but not including,
-         *     the next "/" character or the end of the input buffer.
-         */
-        *out++ = *in++;
-        while(in < end && *in != '/')
-            *out++ = *in++;
+            /* Find the slash preceding out pointer and move out pointer to it */
+            if(out > path+1 && is_slash(*--out))
+                --out;
+            while(out > path && !is_slash(*(--out)));
+            if(is_slash(*out))
+                ++out;
+            in += 2;
+            if(in != end)
+                ++in;
+        }
     }
 
     len = out - path;
@@ -809,12 +795,12 @@ static INT find_file_extension(const WCHAR *path, DWORD path_len) {
  *
  * NOTES:
  *  Windows will expand an elision if the elision only represents 1 h16
- *  component of the URI.
+ *  component of the address.
  *
  *  Ex: [1::2:3:4:5:6:7] -> [1:0:2:3:4:5:6:7]
  *
  *  If the IPv6 address contains an IPv4 address, the IPv4 address is also
- *  considered for being included as part of an elision if all it's components
+ *  considered for being included as part of an elision if all its components
  *  are zeros.
  *
  *  Ex: [1:2:3:4:5:6:0.0.0.0] -> [1:2:3:4:5:6::]
@@ -987,7 +973,7 @@ static USHORT h16tous(h16 component) {
     return ret;
 }
 
-/* Converts an IPv6 address into it's 128 bits (16 bytes) numerical value.
+/* Converts an IPv6 address into its 128 bits (16 bytes) numerical value.
  *
  * This function assumes that the ipv6_address has already been validated.
  */
@@ -998,7 +984,7 @@ static BOOL ipv6_to_number(const ipv6_address *address, USHORT number[8]) {
     for(i = 0; i < address->h16_count; ++i) {
         if(address->elision) {
             if(address->components[i].str > address->elision && !already_passed_elision) {
-                /* Means we just passed the elision and need to add it's values to
+                /* Means we just passed the elision and need to add its values to
                  * 'number' before we do anything else.
                  */
                 DWORD j = 0;
@@ -1016,7 +1002,6 @@ static BOOL ipv6_to_number(const ipv6_address *address, USHORT number[8]) {
     if(!already_passed_elision && address->elision) {
         for(i = 0; i < address->elision_size; i+=2)
             number[cur_component++] = 0;
-        already_passed_elision = TRUE;
     }
 
     if(address->ipv4) {
@@ -1818,7 +1803,7 @@ static BOOL parse_ipv6address(const WCHAR **ptr, parse_data *data, DWORD flags)
 
     TRACE("(%p %p %x): Found valid IPv6 literal %s len=%d\n",
         ptr, data, flags, debugstr_wn(start, *ptr-start),
-        *ptr-start);
+        (int)(*ptr-start));
     return TRUE;
 }
 
@@ -1860,7 +1845,7 @@ static BOOL parse_ipvfuture(const WCHAR **ptr, parse_data *data, DWORD flags) {
     data->host_type = Uri_HOST_UNKNOWN;
 
     TRACE("(%p %p %x): Parsed IPvFuture address %s len=%d\n", ptr, data, flags,
-        debugstr_wn(start, *ptr-start), *ptr-start);
+          debugstr_wn(start, *ptr-start), (int)(*ptr-start));
 
     return TRUE;
 }
@@ -3151,10 +3136,17 @@ static BOOL canonicalize_path_opaque(const parse_data *data, Uri *uri, DWORD fla
         }
     }
 
+    if(data->scheme_type == URL_SCHEME_MK && !computeOnly && !(flags & Uri_CREATE_NO_CANONICALIZE)) {
+        DWORD new_len = remove_dot_segments(uri->canon_uri + uri->path_start,
+                                            uri->canon_len - uri->path_start);
+        uri->canon_len = uri->path_start + new_len;
+    }
+
     uri->path_len = uri->canon_len - uri->path_start;
 
-    TRACE("(%p %p %x %d): Canonicalized opaque URI path %s len=%d\n", data, uri, flags, computeOnly,
-        debugstr_wn(uri->canon_uri+uri->path_start, uri->path_len), uri->path_len);
+    if(!computeOnly)
+        TRACE("(%p %p %x %d): Canonicalized opaque URI path %s len=%d\n", data, uri, flags, computeOnly,
+            debugstr_wn(uri->canon_uri+uri->path_start, uri->path_len), uri->path_len);
     return TRUE;
 }
 
@@ -3436,7 +3428,7 @@ static HRESULT canonicalize_uri(const parse_data *data, Uri *uri, DWORD flags) {
     INT len;
 
     uri->canon_uri = NULL;
-    len = uri->canon_size = uri->canon_len = 0;
+    uri->canon_size = uri->canon_len = 0;
 
     TRACE("(%p %p %x): beginning to canonicalize URI %s.\n", data, uri, flags, debugstr_w(data->uri));
 
@@ -5007,10 +4999,10 @@ static ULONG WINAPI UriBuilderFactory_Release(IUriBuilderFactory *iface)
     return ref;
 }
 
-static HRESULT WINAPI UriBuilderFactory_CreateInitializedIUriBuilder(IUriBuilderFactory *iface,
-                                                              DWORD dwFlags,
-                                                              DWORD_PTR dwReserved,
-                                                              IUriBuilder **ppIUriBuilder)
+static HRESULT WINAPI UriBuilderFactory_CreateIUriBuilder(IUriBuilderFactory *iface,
+                                                          DWORD dwFlags,
+                                                          DWORD_PTR dwReserved,
+                                                          IUriBuilder **ppIUriBuilder)
 {
     Uri *This = impl_from_IUriBuilderFactory(iface);
     TRACE("(%p)->(%08x %08x %p)\n", This, dwFlags, (DWORD)dwReserved, ppIUriBuilder);
@@ -5026,10 +5018,10 @@ static HRESULT WINAPI UriBuilderFactory_CreateInitializedIUriBuilder(IUriBuilder
     return CreateIUriBuilder(NULL, 0, 0, ppIUriBuilder);
 }
 
-static HRESULT WINAPI UriBuilderFactory_CreateIUriBuilder(IUriBuilderFactory *iface,
-                                                   DWORD dwFlags,
-                                                   DWORD_PTR dwReserved,
-                                                   IUriBuilder **ppIUriBuilder)
+static HRESULT WINAPI UriBuilderFactory_CreateInitializedIUriBuilder(IUriBuilderFactory *iface,
+                                                                     DWORD dwFlags,
+                                                                     DWORD_PTR dwReserved,
+                                                                     IUriBuilder **ppIUriBuilder)
 {
     Uri *This = impl_from_IUriBuilderFactory(iface);
     TRACE("(%p)->(%08x %08x %p)\n", This, dwFlags, (DWORD)dwReserved, ppIUriBuilder);
@@ -5049,8 +5041,8 @@ static const IUriBuilderFactoryVtbl UriBuilderFactoryVtbl = {
     UriBuilderFactory_QueryInterface,
     UriBuilderFactory_AddRef,
     UriBuilderFactory_Release,
-    UriBuilderFactory_CreateInitializedIUriBuilder,
-    UriBuilderFactory_CreateIUriBuilder
+    UriBuilderFactory_CreateIUriBuilder,
+    UriBuilderFactory_CreateInitializedIUriBuilder
 };
 
 static Uri* create_uri_obj(void) {
@@ -5795,10 +5787,10 @@ static HRESULT merge_paths(parse_data *data, const WCHAR *base, DWORD base_len,
         /* Find the characters the will be copied over from
          * the base path.
          */
-        end = str_last_of(base, base+(base_len-1), '/');
+        end = memrchrW(base, '/', base_len);
         if(!end && data->scheme_type == URL_SCHEME_FILE)
             /* Try looking for a '\\'. */
-            end = str_last_of(base, base+(base_len-1), '\\');
+            end = memrchrW(base, '\\', base_len);
     }
 
     if(end) {
@@ -6002,7 +5994,7 @@ static HRESULT combine_uri(Uri *base, Uri *relative, DWORD flags, IUri **result,
                 DWORD new_len = remove_dot_segments(path+offset,path_len-offset);
 
                 if(new_len != path_len) {
-                    WCHAR *tmp = heap_realloc(path, (path_offset+new_len+1)*sizeof(WCHAR));
+                    WCHAR *tmp = heap_realloc(path, (offset+new_len+1)*sizeof(WCHAR));
                     if(!tmp) {
                         heap_free(path);
                         *result = NULL;
@@ -6015,6 +6007,11 @@ static HRESULT combine_uri(Uri *base, Uri *relative, DWORD flags, IUri **result,
                 }
             }
 
+            if(relative->query_start > -1) {
+                data.query = relative->canon_uri+relative->query_start;
+                data.query_len = relative->query_len;
+            }
+
             /* Make sure the path component is valid. */
             ptr = path;
             pptr = &ptr;
index c9debb4..77bb8f2 100644 (file)
@@ -3,43 +3,11 @@ Signature="$CHICAGO$"
 
 
 [RegisterDll]
-AddReg=Classes.Reg, Protocols.Reg, ZoneMap.Reg, Zones.Reg, Misc.Reg
+AddReg=ZoneMap.Reg, Zones.Reg
 
 
 [UnregisterDll]
-DelReg=Classes.Reg, Protocols.Reg, ZoneMap.Reg, Zones.Reg, Misc.Reg
-
-
-[Classes.Reg]
-
-;; CLSID_DeCompMimeFilter
-HKCR,"CLSID\%CLSID_DeCompMimeFilter%",,,"AP lzdhtml encoding/decoding Filter"
-HKCR,"CLSID\%CLSID_DeCompMimeFilter%\InProcServer32",,,"%MODULE%"
-HKCR,"CLSID\%CLSID_DeCompMimeFilter%\InProcServer32","ThreadingModel",,"Apartment"
-
-
-[Protocols.Reg]
-HKCR,"PROTOCOLS\Handler\cdl",,,"CDL: Asynchronous Pluggable Protocol Handler"
-HKCR,"PROTOCOLS\Handler\cdl","CLSID",,"%CLSID_CdlProtocol%"
-HKCR,"PROTOCOLS\Handler\file",,,"file:, local: Asynchronous Pluggable Protocol Handler"
-HKCR,"PROTOCOLS\Handler\file","CLSID",,"%CLSID_FileProtocol%"
-HKCR,"PROTOCOLS\Handler\local",,,"file:, local: Asynchronous Pluggable Protocol Handler"
-HKCR,"PROTOCOLS\Handler\local","CLSID",,"%CLSID_FileProtocol%"
-HKCR,"PROTOCOLS\Handler\ftp",,,"ftp: Asynchronous Pluggable Protocol Handler"
-HKCR,"PROTOCOLS\Handler\ftp","CLSID",,"%CLSID_FtpProtocol%"
-HKCR,"PROTOCOLS\Handler\gopher",,,"gopher: Asynchronous Pluggable Protocol Handler"
-HKCR,"PROTOCOLS\Handler\gopher","CLSID",,"%CLSID_GopherProtocol%"
-HKCR,"PROTOCOLS\Handler\http",,,"http: Asynchronous Pluggable Protocol Handler"
-HKCR,"PROTOCOLS\Handler\http","CLSID",,"%CLSID_HttpProtocol%"
-HKCR,"PROTOCOLS\Handler\https",,,"https: Asynchronous Pluggable Protocol Handler"
-HKCR,"PROTOCOLS\Handler\https","CLSID",,"%CLSID_HttpsProtocol%"
-HKCR,"PROTOCOLS\Handler\mk",,,"mk: Asynchronous Pluggable Protocol Handler"
-HKCR,"PROTOCOLS\Filter\deflate",,,"AP Deflate Encoding/Decoding Filter"
-HKCR,"PROTOCOLS\Filter\deflate","CLSID",,"%CLSID_DeCompMimeFilter%"
-HKCR,"PROTOCOLS\Filter\gzip",,,"AP Deflate Encoding/Decoding Filter"
-HKCR,"PROTOCOLS\Filter\gzip","CLSID",,"%CLSID_DeCompMimeFilter%"
-HKCR,"PROTOCOLS\Filter\lzdhtml",,,"AP Deflate Encoding/Decoding Filter"
-HKCR,"PROTOCOLS\Filter\lzdhtml","CLSID",,"%CLSID_DeCompMimeFilter%"
+DelReg=ZoneMap.Reg, Zones.Reg
 
 
 [ZoneMap.Reg]
@@ -459,16 +427,7 @@ HKCU,"%ZONES_UNTRUSTED%","1E05",0x10003,0x10000
 HKLM,"%ZONES_UNTRUSTED%","1E05",0x10003,0x10000
 
 
-[Misc.Reg]
-HKCU,"%INTERNET_SETTINGS%","User Agent",,"%USER_AGENT%"
-
-
 [Strings]
-MODULE="urlmon.dll"
-
-USER_AGENT="Mozilla/4.0 (compatible; MSIE 8.0; Win32)"
-INTERNET_SETTINGS="Software\Microsoft\Windows\CurrentVersion\Internet Settings"
-
 PATH_ZONEMAP="Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap"
 PATH_ZONEMAP_PROTOCOLS="Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\ProtocolDefaults"
 PATH_ZONEMAP_DOMAINS="Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains"
index ffca7d9..c858689 100644 (file)
@@ -22,7 +22,6 @@
        <file>mk.c</file>
        <file>protocol.c</file>
        <file>protproxy.c</file>
-       <file>regsvr.c</file>
        <file>sec_mgr.c</file>
        <file>session.c</file>
        <file>umon.c</file>
diff --git a/reactos/dll/win32/urlmon/urlmon.rgs b/reactos/dll/win32/urlmon/urlmon.rgs
new file mode 100644 (file)
index 0000000..868baad
--- /dev/null
@@ -0,0 +1,123 @@
+HKCR
+{
+    NoRemove PROTOCOLS
+    {
+        NoRemove Handler
+        {
+            ForceRemove cdl = s 'CDL: Asynchronous Pluggable Protocol Handler'
+            {
+                val CLSID = s '{3dd53d40-7b8b-11d0-b013-00aa0059ce02}'
+            }
+            ForceRemove file = s 'file:, local: Asynchronous Pluggable Protocol Handler'
+            {
+                val CLSID = s '{79eac9e7-baf9-11ce-8c82-00aa004ba90b}'
+            }
+            ForceRemove local = s 'file:, local: Asynchronous Pluggable Protocol Handler'
+            {
+                val CLSID = s '{79eac9e7-baf9-11ce-8c82-00aa004ba90b}'
+            }
+            ForceRemove ftp = s 'ftp: Asynchronous Pluggable Protocol Handler'
+            {
+                val CLSID = s '{79eac9e3-baf9-11ce-8c82-00aa004ba90b}'
+            }
+            ForceRemove gopher = s 'gopher: Asynchronous Pluggable Protocol Handler'
+            {
+                val CLSID = s '{79eac9e4-baf9-11ce-8c82-00aa004ba90b}'
+            }
+            ForceRemove http = s 'http: Asynchronous Pluggable Protocol Handler'
+            {
+                val CLSID = s '{79eac9e2-baf9-11ce-8c82-00aa004ba90b}'
+            }
+            ForceRemove https = s 'https: Asynchronous Pluggable Protocol Handler'
+            {
+                val CLSID = s '{79eac9e5-baf9-11ce-8c82-00aa004ba90b}'
+            }
+            ForceRemove mk = s 'mk: Asynchronous Pluggable Protocol Handler'
+            {
+                val CLSID = s '{79eac9e6-baf9-11ce-8c82-00aa004ba90b}'
+            }
+        }
+        NoRemove Filter
+        {
+            ForceRemove deflate = s 'AP Deflate Encoding/Decoding Filter'
+            {
+                val CLSID = s '{8f6b0360-b80d-11d0-a9b3-006097942311}'
+            }
+            ForceRemove gzip = s 'AP Deflate Encoding/Decoding Filter'
+            {
+                val CLSID = s '{8f6b0360-b80d-11d0-a9b3-006097942311}'
+            }
+            ForceRemove lzdhtml = s 'AP Deflate Encoding/Decoding Filter'
+            {
+                val CLSID = s '{8f6b0360-b80d-11d0-a9b3-006097942311}'
+            }
+        }
+    }
+}
+HKCU
+{
+    NoRemove Software
+    {
+        NoRemove Microsoft
+        {
+            NoRemove Windows
+            {
+                NoRemove CurrentVersion
+                {
+                    NoRemove 'Internet Settings'
+                    {
+                        val 'User Agent' = s 'Mozilla/4.0 (compatible; MSIE 8.0; Win32)'
+                    }
+                }
+            }
+            NoRemove 'Internet Explorer'
+            {
+                NoRemove Main
+                {
+                    FeatureControl
+                }
+            }
+        }
+    }
+}
+HKLM
+{
+    NoRemove Software
+    {
+        NoRemove Microsoft
+        {
+            NoRemove 'Internet Explorer'
+            {
+                NoRemove Main
+                {
+                    FeatureControl
+                    {
+                        FEATURE_OBJECT_CACHING
+                        FEATURE_ZONE_ELEVATION
+                        FEATURE_MIME_HANDLING
+                        FEATURE_MIME_SNIFFING
+                        FEATURE_WINDOW_RESTRICTIONS
+                        FEATURE_WEBOC_POPUPMANAGEMENT
+                        FEATURE_BEHAVIORS
+                        FEATURE_DISABLE_MK_PROTOCOL
+                        FEATURE_LOCALMACHINE_LOCKDOWN
+                        FEATURE_SECURITYBAND
+                        FEATURE_RESTRICT_ACTIVEXINSTALL
+                        FEATURE_VALIDATE_NAVIGATE_URL
+                        FEATURE_RESTRICT_FILEDOWNLOAD
+                        FEATURE_ADDON_MANAGEMENT
+                        FEATURE_PROTOCOL_LOCKDOWN
+                        FEATURE_HTTP_USERNAME_PASSWORD_DISABLE
+                        FEATURE_SAFE_BINDTOOBJECT
+                        FEATURE_UNC_SAVEDFILECHECK
+                        FEATURE_SSLUX
+                        FEATURE_DISABLE_LEGACY_COMPRESSION
+                        FEATURE_FORCE_ADDR_AND_STATUS
+                        FEATURE_DISABLE_TELNET_PROTOCOL
+                        FEATURE_FEEDS
+                    }
+                }
+            }
+        }
+    }
+}
index 9d3de3a..58b3f33 100644 (file)
@@ -18,6 +18,7 @@
 @ stdcall CoInternetCreateZoneManager(ptr ptr long)
 @ stub CoInternetGetProtocolFlags
 @ stdcall CoInternetGetSecurityUrl(ptr ptr long long)
+@ stdcall CoInternetGetSecurityUrlEx(ptr ptr long long)
 @ stdcall CoInternetGetSession(long ptr long)
 @ stdcall CoInternetIsFeatureEnabled(long long)
 @ stdcall CoInternetParseUrl(wstr long long wstr long ptr long)
@@ -57,6 +58,7 @@
 @ stdcall HlinkNavigateString(ptr wstr)
 @ stdcall HlinkSimpleNavigateToMoniker(ptr wstr wstr ptr ptr ptr long long)
 @ stdcall HlinkSimpleNavigateToString(wstr wstr wstr ptr ptr ptr long long)
+@ stub IEInstallScope
 @ stdcall IsAsyncMoniker(ptr)
 @ stdcall IsLoggingEnabledA(str)
 @ stdcall IsLoggingEnabledW(wstr)
@@ -89,3 +91,6 @@
 @ stdcall UrlMkSetSessionOption(long ptr long long)
 @ stub WriteHitLogging
 @ stub ZonesReInit
+
+410 stdcall @(long long) URLMON_410
+423 stdcall @(long long long long) URLMON_423
index 6ecd1de..01442c1 100644 (file)
@@ -26,6 +26,8 @@
 
 #define NO_SHLWAPI_REG
 #include "shlwapi.h"
+#include "advpub.h"
+
 #include "wine/debug.h"
 
 #include "urlmon.h"
@@ -187,12 +189,15 @@ HRESULT WINAPI DllCanUnloadNow(void)
  * Urlmon ClassFactory
  */
 typedef struct {
-    const IClassFactoryVtbl *lpClassFactoryVtbl;
+    IClassFactory IClassFactory_iface;
 
     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
 } ClassFactory;
 
-#define CLASSFACTORY(x)  ((IClassFactory*)  &(x)->lpClassFactoryVtbl)
+static inline ClassFactory *impl_from_IClassFactory(IClassFactory *iface)
+{
+    return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface);
+}
 
 static HRESULT WINAPI CF_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppv)
 {
@@ -231,7 +236,7 @@ static ULONG WINAPI CF_Release(IClassFactory *iface)
 static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter,
                                         REFIID riid, LPVOID *ppobj)
 {
-    ClassFactory *This = (ClassFactory*)iface;
+    ClassFactory *This = impl_from_IClassFactory(iface);
     HRESULT hres;
     LPUNKNOWN punk;
     
@@ -266,27 +271,27 @@ static const IClassFactoryVtbl ClassFactoryVtbl =
     CF_LockServer
 };
 
-static const ClassFactory FileProtocolCF =
-    { &ClassFactoryVtbl, FileProtocol_Construct};
-static const ClassFactory FtpProtocolCF =
-    { &ClassFactoryVtbl, FtpProtocol_Construct};
-static const ClassFactory GopherProtocolCF =
-    { &ClassFactoryVtbl, GopherProtocol_Construct};
-static const ClassFactory HttpProtocolCF =
-    { &ClassFactoryVtbl, HttpProtocol_Construct};
-static const ClassFactory HttpSProtocolCF =
-    { &ClassFactoryVtbl, HttpSProtocol_Construct};
-static const ClassFactory MkProtocolCF =
-    { &ClassFactoryVtbl, MkProtocol_Construct};
-static const ClassFactory SecurityManagerCF =
-    { &ClassFactoryVtbl, SecManagerImpl_Construct};
-static const ClassFactory ZoneManagerCF =
-    { &ClassFactoryVtbl, ZoneMgrImpl_Construct};
-static const ClassFactory StdURLMonikerCF =
-    { &ClassFactoryVtbl, StdURLMoniker_Construct};
-static const ClassFactory MimeFilterCF =
-    { &ClassFactoryVtbl, MimeFilter_Construct};
+static ClassFactory FileProtocolCF =
+    { { &ClassFactoryVtbl }, FileProtocol_Construct};
+static ClassFactory FtpProtocolCF =
+    { { &ClassFactoryVtbl }, FtpProtocol_Construct};
+static ClassFactory GopherProtocolCF =
+    { { &ClassFactoryVtbl }, GopherProtocol_Construct};
+static ClassFactory HttpProtocolCF =
+    { { &ClassFactoryVtbl }, HttpProtocol_Construct};
+static ClassFactory HttpSProtocolCF =
+    { { &ClassFactoryVtbl }, HttpSProtocol_Construct};
+static ClassFactory MkProtocolCF =
+    { { &ClassFactoryVtbl }, MkProtocol_Construct};
+static ClassFactory SecurityManagerCF =
+    { { &ClassFactoryVtbl }, SecManagerImpl_Construct};
+static ClassFactory ZoneManagerCF =
+    { { &ClassFactoryVtbl }, ZoneMgrImpl_Construct};
+static ClassFactory StdURLMonikerCF =
+    { { &ClassFactoryVtbl }, StdURLMoniker_Construct};
+static ClassFactory MimeFilterCF =
+    { { &ClassFactoryVtbl }, MimeFilter_Construct};
+
 struct object_creation_info
 {
     const CLSID *clsid;
@@ -303,16 +308,16 @@ static const WCHAR wszMk[]   = {'m','k',0};
 
 static const struct object_creation_info object_creation[] =
 {
-    { &CLSID_FileProtocol,            CLASSFACTORY(&FileProtocolCF),    wszFile },
-    { &CLSID_FtpProtocol,             CLASSFACTORY(&FtpProtocolCF),     wszFtp  },
-    { &CLSID_GopherProtocol,          CLASSFACTORY(&GopherProtocolCF),  wszGopher },
-    { &CLSID_HttpProtocol,            CLASSFACTORY(&HttpProtocolCF),    wszHttp },
-    { &CLSID_HttpSProtocol,           CLASSFACTORY(&HttpSProtocolCF),   wszHttps },
-    { &CLSID_MkProtocol,              CLASSFACTORY(&MkProtocolCF),      wszMk },
-    { &CLSID_InternetSecurityManager, CLASSFACTORY(&SecurityManagerCF), NULL    },
-    { &CLSID_InternetZoneManager,     CLASSFACTORY(&ZoneManagerCF),     NULL    },
-    { &CLSID_StdURLMoniker,           CLASSFACTORY(&StdURLMonikerCF),   NULL    },
-    { &CLSID_DeCompMimeFilter,        CLASSFACTORY(&MimeFilterCF),      NULL    }
+    { &CLSID_FileProtocol,            &FileProtocolCF.IClassFactory_iface,    wszFile },
+    { &CLSID_FtpProtocol,             &FtpProtocolCF.IClassFactory_iface,     wszFtp  },
+    { &CLSID_GopherProtocol,          &GopherProtocolCF.IClassFactory_iface,  wszGopher },
+    { &CLSID_HttpProtocol,            &HttpProtocolCF.IClassFactory_iface,    wszHttp },
+    { &CLSID_HttpSProtocol,           &HttpSProtocolCF.IClassFactory_iface,   wszHttps },
+    { &CLSID_MkProtocol,              &MkProtocolCF.IClassFactory_iface,      wszMk },
+    { &CLSID_InternetSecurityManager, &SecurityManagerCF.IClassFactory_iface, NULL    },
+    { &CLSID_InternetZoneManager,     &ZoneManagerCF.IClassFactory_iface,     NULL    },
+    { &CLSID_StdURLMoniker,           &StdURLMonikerCF.IClassFactory_iface,   NULL    },
+    { &CLSID_DeCompMimeFilter,        &MimeFilterCF.IClassFactory_iface,      NULL    }
 };
 
 static void init_session(BOOL init)
@@ -366,6 +371,44 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
     return CLASS_E_CLASSNOTAVAILABLE;
 }
 
+static HRESULT register_inf(BOOL doregister)
+{
+    HRESULT (WINAPI *pRegInstall)(HMODULE hm, LPCSTR pszSection, const STRTABLEA* pstTable);
+    HMODULE hAdvpack;
+
+    static const WCHAR wszAdvpack[] = {'a','d','v','p','a','c','k','.','d','l','l',0};
+
+    hAdvpack = LoadLibraryW(wszAdvpack);
+    pRegInstall = (void *)GetProcAddress(hAdvpack, "RegInstall");
+
+    return pRegInstall(hProxyDll, doregister ? "RegisterDll" : "UnregisterDll", NULL);
+}
+
+/***********************************************************************
+ *             DllRegisterServer (URLMON.@)
+ */
+HRESULT WINAPI DllRegisterServer(void)
+{
+    HRESULT hr;
+
+    TRACE("\n");
+
+    hr = URLMON_DllRegisterServer();
+    return SUCCEEDED(hr) ? register_inf(TRUE) : hr;
+}
+
+/***********************************************************************
+ *             DllUnregisterServer (URLMON.@)
+ */
+HRESULT WINAPI DllUnregisterServer(void)
+{
+    HRESULT hr;
+
+    TRACE("\n");
+
+    hr = URLMON_DllUnregisterServer();
+    return SUCCEEDED(hr) ? register_inf(FALSE) : hr;
+}
 
 /***********************************************************************
  *             DllRegisterServerEx (URLMON.@)
@@ -383,7 +426,7 @@ HRESULT WINAPI DllRegisterServerEx(void)
  * Determines if a specified string is a valid URL.
  *
  * PARAMS
- *  pBC        [I] ignored, must be NULL.
+ *  pBC        [I] ignored, should be NULL.
  *  szURL      [I] string that represents the URL in question.
  *  dwReserved [I] reserved and must be zero.
  *
@@ -399,7 +442,7 @@ HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
 {
     FIXME("(%p, %s, %d): stub\n", pBC, debugstr_w(szURL), dwReserved);
 
-    if (pBC || dwReserved || !szURL)
+    if (dwReserved || !szURL)
         return E_INVALIDARG;
 
     return S_OK;
@@ -862,3 +905,23 @@ BOOL WINAPI IsLoggingEnabledW(LPCWSTR url)
     FIXME("(%s)\n", debugstr_w(url));
     return FALSE;
 }
+
+/***********************************************************************
+ *           URLMON_410 (URLMON.410)
+ *    Undocumented, added in IE8
+ */
+BOOL WINAPI URLMON_410(DWORD unknown1, DWORD unknown2)
+{
+    FIXME("stub: %d %d\n", unknown1, unknown2);
+    return FALSE;
+}
+
+/***********************************************************************
+ *           URLMON_423 (URLMON.423)
+ *    Undocumented, added in IE8
+ */
+BOOL WINAPI URLMON_423(DWORD unknown1, DWORD unknown2, DWORD unknown3, DWORD unknown4)
+{
+    FIXME("stub: %d %d %d %d\n", unknown1, unknown2, unknown3, unknown4);
+    return FALSE;
+}
index ea33f15..b60d678 100644 (file)
 #include "wine/list.h"
 
 extern HINSTANCE hProxyDll DECLSPEC_HIDDEN;
-extern HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
-extern HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
-extern HRESULT StdURLMoniker_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
-extern HRESULT FileProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
-extern HRESULT HttpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
-extern HRESULT HttpSProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
-extern HRESULT FtpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
-extern HRESULT GopherProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
-extern HRESULT MkProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
-extern HRESULT MimeFilter_Construct(IUnknown *pUnkOuter, LPVOID *ppobj);
+extern HRESULT SecManagerImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPEC_HIDDEN;
+extern HRESULT ZoneMgrImpl_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPEC_HIDDEN;
+extern HRESULT StdURLMoniker_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPEC_HIDDEN;
+extern HRESULT FileProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPEC_HIDDEN;
+extern HRESULT HttpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPEC_HIDDEN;
+extern HRESULT HttpSProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPEC_HIDDEN;
+extern HRESULT FtpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPEC_HIDDEN;
+extern HRESULT GopherProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPEC_HIDDEN;
+extern HRESULT MkProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPEC_HIDDEN;
+extern HRESULT MimeFilter_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) DECLSPEC_HIDDEN;
 
 extern BOOL WINAPI URLMON_DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI URLMON_DllGetClassObject(REFCLSID rclsid, REFIID iid,LPVOID *ppv) DECLSPEC_HIDDEN;
@@ -58,30 +58,24 @@ extern GUID const CLSID_PSFactoryBuffer DECLSPEC_HIDDEN;
 /**********************************************************************
  * Dll lifetime tracking declaration for urlmon.dll
  */
-extern LONG URLMON_refCount;
+extern LONG URLMON_refCount DECLSPEC_HIDDEN;
 static inline void URLMON_LockModule(void) { InterlockedIncrement( &URLMON_refCount ); }
 static inline void URLMON_UnlockModule(void) { InterlockedDecrement( &URLMON_refCount ); }
 
-#define DEFINE_THIS2(cls,ifc,iface) ((cls*)((BYTE*)(iface)-offsetof(cls,ifc)))
-#define DEFINE_THIS(cls,ifc,iface) DEFINE_THIS2(cls,lp ## ifc ## Vtbl,iface)
+IInternetProtocolInfo *get_protocol_info(LPCWSTR) DECLSPEC_HIDDEN;
+HRESULT get_protocol_handler(IUri*,CLSID*,BOOL*,IClassFactory**) DECLSPEC_HIDDEN;
+IInternetProtocol *get_mime_filter(LPCWSTR) DECLSPEC_HIDDEN;
+BOOL is_registered_protocol(LPCWSTR) DECLSPEC_HIDDEN;
+void register_urlmon_namespace(IClassFactory*,REFIID,LPCWSTR,BOOL) DECLSPEC_HIDDEN;
+HINTERNET get_internet_session(IInternetBindInfo*) DECLSPEC_HIDDEN;
+LPWSTR get_useragent(void) DECLSPEC_HIDDEN;
+void free_session(void) DECLSPEC_HIDDEN;
 
-IInternetProtocolInfo *get_protocol_info(LPCWSTR);
-HRESULT get_protocol_handler(IUri*,CLSID*,BOOL*,IClassFactory**);
-IInternetProtocol *get_mime_filter(LPCWSTR);
-BOOL is_registered_protocol(LPCWSTR);
-void register_urlmon_namespace(IClassFactory*,REFIID,LPCWSTR,BOOL);
-HINTERNET get_internet_session(IInternetBindInfo*);
-LPWSTR get_useragent(void);
-void free_session(void);
+HRESULT bind_to_storage(IUri*,IBindCtx*,REFIID,void**) DECLSPEC_HIDDEN;
+HRESULT bind_to_object(IMoniker*,IUri*,IBindCtx*,REFIID,void**ppv) DECLSPEC_HIDDEN;
 
-HRESULT bind_to_storage(IUri*,IBindCtx*,REFIID,void**);
-HRESULT bind_to_object(IMoniker*,IUri*,IBindCtx*,REFIID,void**ppv);
-
-HRESULT create_binding_protocol(BOOL,IInternetProtocolEx**);
-void set_binding_sink(IInternetProtocolEx*,IInternetProtocolSink*,IInternetBindInfo*);
-IWinInetInfo *get_wininet_info(IInternetProtocolEx*);
-HRESULT create_default_callback(IBindStatusCallback**);
-HRESULT wrap_callback(IBindStatusCallback*,IBindStatusCallback**);
+HRESULT create_default_callback(IBindStatusCallback**) DECLSPEC_HIDDEN;
+HRESULT wrap_callback(IBindStatusCallback*,IBindStatusCallback**) DECLSPEC_HIDDEN;
 
 typedef struct ProtocolVtbl ProtocolVtbl;
 
@@ -113,19 +107,53 @@ struct ProtocolVtbl {
     HRESULT (*end_request)(Protocol*);
     HRESULT (*start_downloading)(Protocol*);
     void (*close_connection)(Protocol*);
+    void (*on_error)(Protocol*,DWORD);
 };
 
-HRESULT protocol_start(Protocol*,IInternetProtocol*,IUri*,IInternetProtocolSink*,IInternetBindInfo*);
-HRESULT protocol_continue(Protocol*,PROTOCOLDATA*);
-HRESULT protocol_read(Protocol*,void*,ULONG,ULONG*);
-HRESULT protocol_lock_request(Protocol*);
-HRESULT protocol_unlock_request(Protocol*);
-HRESULT protocol_abort(Protocol*,HRESULT);
-void protocol_close_connection(Protocol*);
+/* Flags are needed for, among other things, return HRESULTs from the Read function
+ * to conform to native. For example, Read returns:
+ *
+ * 1. E_PENDING if called before the request has completed,
+ *        (flags = 0)
+ * 2. S_FALSE after all data has been read and S_OK has been reported,
+ *        (flags = FLAG_REQUEST_COMPLETE | FLAG_ALL_DATA_READ | FLAG_RESULT_REPORTED)
+ * 3. INET_E_DATA_NOT_AVAILABLE if InternetQueryDataAvailable fails. The first time
+ *    this occurs, INET_E_DATA_NOT_AVAILABLE will also be reported to the sink,
+ *        (flags = FLAG_REQUEST_COMPLETE)
+ *    but upon subsequent calls to Read no reporting will take place, yet
+ *    InternetQueryDataAvailable will still be called, and, on failure,
+ *    INET_E_DATA_NOT_AVAILABLE will still be returned.
+ *        (flags = FLAG_REQUEST_COMPLETE | FLAG_RESULT_REPORTED)
+ *
+ * FLAG_FIRST_DATA_REPORTED and FLAG_LAST_DATA_REPORTED are needed for proper
+ * ReportData reporting. For example, if OnResponse returns S_OK, Continue will
+ * report BSCF_FIRSTDATANOTIFICATION, and when all data has been read Read will
+ * report BSCF_INTERMEDIATEDATANOTIFICATION|BSCF_LASTDATANOTIFICATION. However,
+ * if OnResponse does not return S_OK, Continue will not report data, and Read
+ * will report BSCF_FIRSTDATANOTIFICATION|BSCF_LASTDATANOTIFICATION when all
+ * data has been read.
+ */
+#define FLAG_REQUEST_COMPLETE         0x0001
+#define FLAG_FIRST_CONTINUE_COMPLETE  0x0002
+#define FLAG_FIRST_DATA_REPORTED      0x0004
+#define FLAG_ALL_DATA_READ            0x0008
+#define FLAG_LAST_DATA_REPORTED       0x0010
+#define FLAG_RESULT_REPORTED          0x0020
+#define FLAG_ERROR                    0x0040
+
+HRESULT protocol_start(Protocol*,IInternetProtocol*,IUri*,IInternetProtocolSink*,IInternetBindInfo*) DECLSPEC_HIDDEN;
+HRESULT protocol_continue(Protocol*,PROTOCOLDATA*) DECLSPEC_HIDDEN;
+HRESULT protocol_read(Protocol*,void*,ULONG,ULONG*) DECLSPEC_HIDDEN;
+HRESULT protocol_lock_request(Protocol*) DECLSPEC_HIDDEN;
+HRESULT protocol_unlock_request(Protocol*) DECLSPEC_HIDDEN;
+HRESULT protocol_abort(Protocol*,HRESULT) DECLSPEC_HIDDEN;
+void protocol_close_connection(Protocol*) DECLSPEC_HIDDEN;
+
+void find_domain_name(const WCHAR*,DWORD,INT*) DECLSPEC_HIDDEN;
 
 typedef struct {
-    const IInternetProtocolVtbl      *lpIInternetProtocolVtbl;
-    const IInternetProtocolSinkVtbl  *lpIInternetProtocolSinkVtbl;
+    IInternetProtocol     IInternetProtocol_iface;
+    IInternetProtocolSink IInternetProtocolSink_iface;
 
     LONG ref;
 
@@ -133,10 +161,59 @@ typedef struct {
     IInternetProtocol *protocol;
 } ProtocolProxy;
 
-#define PROTOCOL(x)  ((IInternetProtocol*)       &(x)->lpIInternetProtocolVtbl)
-#define PROTSINK(x)  ((IInternetProtocolSink*)   &(x)->lpIInternetProtocolSinkVtbl)
+HRESULT create_protocol_proxy(IInternetProtocol*,IInternetProtocolSink*,ProtocolProxy**) DECLSPEC_HIDDEN;
+
+typedef struct _task_header_t task_header_t;
+
+typedef struct {
+    IInternetProtocolEx   IInternetProtocolEx_iface;
+    IInternetBindInfo     IInternetBindInfo_iface;
+    IInternetPriority     IInternetPriority_iface;
+    IServiceProvider      IServiceProvider_iface;
+    IInternetProtocolSink IInternetProtocolSink_iface;
+    IWinInetHttpInfo      IWinInetHttpInfo_iface;
+
+    LONG ref;
+
+    IInternetProtocol *protocol;
+    IInternetBindInfo *bind_info;
+    IInternetProtocolSink *protocol_sink;
+    IServiceProvider *service_provider;
+    IWinInetInfo *wininet_info;
+    IWinInetHttpInfo *wininet_http_info;
+
+    struct {
+        IInternetProtocol IInternetProtocol_iface;
+    } default_protocol_handler;
+    IInternetProtocol *protocol_handler;
+
+    LONG priority;
+
+    BOOL reported_result;
+    BOOL reported_mime;
+    BOOL from_urlmon;
+    DWORD pi;
+
+    DWORD bscf;
+    ULONG progress;
+    ULONG progress_max;
+
+    DWORD apartment_thread;
+    HWND notif_hwnd;
+    DWORD continue_call;
+
+    CRITICAL_SECTION section;
+    task_header_t *task_queue_head, *task_queue_tail;
+
+    BYTE *buf;
+    DWORD buf_size;
+    LPWSTR mime;
+    IUri *uri;
+    ProtocolProxy *filter_proxy;
+}  BindProtocol;
 
-HRESULT create_protocol_proxy(IInternetProtocol*,IInternetProtocolSink*,ProtocolProxy**);
+HRESULT create_binding_protocol(BOOL,BindProtocol**) DECLSPEC_HIDDEN;
+void set_binding_sink(BindProtocol*,IInternetProtocolSink*,IInternetBindInfo*) DECLSPEC_HIDDEN;
 
 typedef struct {
     HWND notif_hwnd;
@@ -145,10 +222,10 @@ typedef struct {
     struct list entry;
 } tls_data_t;
 
-tls_data_t *get_tls_data(void);
+tls_data_t *get_tls_data(void) DECLSPEC_HIDDEN;
 
-HWND get_notif_hwnd(void);
-void release_notif_hwnd(HWND);
+HWND get_notif_hwnd(void) DECLSPEC_HIDDEN;
+void release_notif_hwnd(HWND) DECLSPEC_HIDDEN;
 
 static inline void *heap_alloc(size_t len)
 {
index d45ba07..ad23dee 100644 (file)
  */
 
 #include "urlmon.idl"
+
+[
+    helpstring("URL Moniker"),
+    threading(apartment),
+    uuid(79eac9e0-baf9-11ce-8c82-00aa004ba90b)
+]
+coclass StdURLMoniker { interface IMoniker; }
+
+[
+    helpstring("http: Asynchronous Pluggable Protocol Handler"),
+    threading(apartment),
+    uuid(79eac9e2-baf9-11ce-8c82-00aa004ba90b)
+]
+coclass HttpProtocol { interface IInternetProtocolEx; interface IInternetPriority; }
+
+[
+    helpstring("ftp: Asynchronous Pluggable Protocol Handler"),
+    threading(apartment),
+    uuid(79eac9e3-baf9-11ce-8c82-00aa004ba90b)
+]
+coclass FtpProtocol { interface IInternetProtocolEx; interface IInternetPriority; }
+
+[
+    helpstring("gopher: Asynchronous Pluggable Protocol Handler"),
+    threading(apartment),
+    uuid(79eac9e4-baf9-11ce-8c82-00aa004ba90b)
+]
+coclass GopherProtocol { interface IInternetProtocolEx; interface IInternetPriority; }
+
+[
+    helpstring("https: Asynchronous Pluggable Protocol Handler"),
+    threading(apartment),
+    uuid(79eac9e5-baf9-11ce-8c82-00aa004ba90b)
+]
+coclass HttpsProtocol { interface IInternetProtocolEx; interface IInternetPriority; }
+
+[
+    helpstring("mk: Asynchronous Pluggable Protocol Handler"),
+    threading(apartment),
+    uuid(79eac9e6-baf9-11ce-8c82-00aa004ba90b)
+]
+coclass MkProtocol { interface IInternetProtocolEx; interface IInternetPriority; }
+
+[
+    helpstring("file:, local: Asynchronous Pluggable Protocol Handler"),
+    threading(apartment),
+    uuid(79eac9e7-baf9-11ce-8c82-00aa004ba90b)
+]
+coclass FileProtocol { interface IInternetProtocolEx; interface IInternetPriority; }
+
+[
+    helpstring("CDL: Asynchronous Pluggable Protocol Handler"),
+    threading(apartment),
+    uuid(3dd53d40-7b8b-11d0-b013-00aa0059ce02)
+]
+coclass CdlProtocol { interface IInternetProtocolEx; interface IInternetPriority; }
+
+[
+    helpstring("Security Manager"),
+    threading(both),
+    uuid(7b8a2d94-0ac9-11d1-896c-00c04fb6bfc4)
+]
+coclass InternetSecurityManager { interface IInternetSecurityManager; }
+
+[
+    helpstring("URL Zone Manager"),
+    threading(both),
+    uuid(7b8a2d95-0ac9-11d1-896c-00c04fb6bfc4)
+]
+coclass InternetZoneManager { interface IInternetZoneManagerEx2; }
+
+[
+    helpstring("URLMoniker ProxyStub Factory"),
+    threading(apartment),
+    uuid(79eac9f1-baf9-11ce-8c82-00aa004ba90b)
+]
+coclass PSFactoryBuffer { interface IPSFactoryBuffer; }
+
+[
+    helpstring("AP lzdhtml encoding/decoding Filter"),
+    threading(apartment),
+    uuid(8f6b0360-b80d-11d0-a9b3-006097942311)
+]
+coclass DeCompMimeFilter { interface IInternetProtocol; interface IInternetProtocolSink; }
index d2a46a0..2ea4063 100644 (file)
@@ -1511,13 +1511,27 @@ typedef enum _tagINTERNETFEATURELIST
     FEATURE_DISABLE_TELNET_PROTOCOL,
     FEATURE_FEEDS,
     FEATURE_BLOCK_INPUT_PROMPTS,
-    FEATURE_DOMSTORAGE,
-    FEATURE_XDOMAINREQUEST,
-    FEATURE_DATAURI,
-    FEATURE_AJAX_CONNECTIONSERVICES,
     FEATURE_ENTRY_COUNT
 } INTERNETFEATURELIST;
 
+cpp_quote("#define SET_FEATURE_ON_THREAD                0x00000001")
+cpp_quote("#define SET_FEATURE_ON_PROCESS               0x00000002")
+cpp_quote("#define SET_FEATURE_IN_REGISTRY              0x00000004")
+cpp_quote("#define SET_FEATURE_ON_THREAD_LOCALMACHINE   0x00000008")
+cpp_quote("#define SET_FEATURE_ON_THREAD_INTRANET       0x00000010")
+cpp_quote("#define SET_FEATURE_ON_THREAD_TRUSTED        0x00000020")
+cpp_quote("#define SET_FEATURE_ON_THREAD_INTERNET       0x00000040")
+cpp_quote("#define SET_FEATURE_ON_THREAD_RESTRICTED     0x00000080")
+
+cpp_quote("#define GET_FEATURE_FROM_THREAD              0x00000001")
+cpp_quote("#define GET_FEATURE_FROM_PROCESS             0x00000002")
+cpp_quote("#define GET_FEATURE_FROM_REGISTRY            0x00000004")
+cpp_quote("#define GET_FEATURE_FROM_THREAD_LOCALMACHINE 0x00000008")
+cpp_quote("#define GET_FEATURE_FROM_THREAD_INTRANET     0x00000010")
+cpp_quote("#define GET_FEATURE_FROM_THREAD_TRUSTED      0x00000020")
+cpp_quote("#define GET_FEATURE_FROM_THREAD_INTERNET     0x00000040")
+cpp_quote("#define GET_FEATURE_FROM_THREAD_RESTRICTED   0x00000080")
+
 typedef struct _tagPROTOCOLFILTERDATA {
     DWORD cbSize;
     IInternetProtocolSink *pProtocolSink;
@@ -1839,16 +1853,16 @@ cpp_quote("HRESULT WINAPI CreateIUriBuilder(IUri*,DWORD,DWORD_PTR,IUriBuilder**)
 ]
 interface IUriBuilderFactory : IUnknown
 {
-    HRESULT CreateInitializedIUriBuilder(
+    HRESULT CreateIUriBuilder(
         [in]  DWORD dwFlags,
         [in]  DWORD_PTR dwReserved,
         [out] IUriBuilder **ppIUriBuilder);
 
-    HRESULT CreateIUriBuilder(
+    HRESULT CreateInitializedIUriBuilder(
         [in]  DWORD dwFlags,
         [in]  DWORD_PTR dwReserved,
         [out] IUriBuilder **ppIUriBuilder);
-};
+}
 
 /*****************************************************************************
  * IInternetProtocolEx interface
@@ -1964,6 +1978,7 @@ cpp_quote("HRESULT WINAPI CoInternetParseIUri(IUri*,PARSEACTION,DWORD,LPWSTR,DWO
 cpp_quote("HRESULT WINAPI CoInternetQueryInfo(LPCWSTR,QUERYOPTION,DWORD,LPVOID,DWORD,DWORD*,DWORD);")
 cpp_quote("HRESULT WINAPI CoInternetSetFeatureEnabled(INTERNETFEATURELIST,DWORD,BOOL);")
 cpp_quote("HRESULT WINAPI CoInternetGetSecurityUrl(LPCWSTR,LPWSTR*,PSUACTION,DWORD);")
+cpp_quote("HRESULT WINAPI CoInternetGetSecurityUrlEx(IUri*,IUri**,PSUACTION,DWORD_PTR);")
 cpp_quote("HRESULT WINAPI CreateFormatEnumerator(UINT,FORMATETC*,IEnumFORMATETC**);")
 cpp_quote("HRESULT WINAPI GetSoftwareUpdateInfo( LPCWSTR szDistUnit, LPSOFTDISTINFO psdi);")
 cpp_quote("HRESULT WINAPI FaultInIEFeature(HWND,uCLSSPEC*,QUERYCONTEXT*,DWORD);")