diff --git a/dll/win32/urlmon/binding.c b/dll/win32/urlmon/binding.c index 88b3c1cc5f9..c2879b21c5f 100644 --- a/dll/win32/urlmon/binding.c +++ b/dll/win32/urlmon/binding.c @@ -792,20 +792,31 @@ static HRESULT WINAPI Binding_QueryInterface(IBinding *iface, REFIID riid, void TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv); *ppv = &This->IServiceProvider_iface; }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) { + IWinInetInfo *wininet_info; + HRESULT hres; + TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv); /* NOTE: This violidates COM rules, but tests prove that we should do it */ - if(!This->protocol->wininet_info) - return E_NOINTERFACE; - - *ppv = &This->IWinInetHttpInfo_iface; + hres = IInternetProtocolEx_QueryInterface(&This->protocol->IInternetProtocolEx_iface, + &IID_IWinInetInfo, (void**)&wininet_info); + if(SUCCEEDED(hres)) { + IWinInetInfo_Release(wininet_info); + *ppv = &This->IWinInetHttpInfo_iface; + } }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) { + IWinInetHttpInfo *http_info; + HRESULT hres; + TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv); - if(!This->protocol->wininet_http_info) - return E_NOINTERFACE; - - *ppv = &This->IWinInetHttpInfo_iface; + /* NOTE: This violidates COM rules, but tests prove that we should do it */ + hres = IInternetProtocolEx_QueryInterface(&This->protocol->IInternetProtocolEx_iface, + &IID_IWinInetHttpInfo, (void**)&http_info); + if(SUCCEEDED(hres)) { + IWinInetHttpInfo_Release(http_info); + *ppv = &This->IWinInetHttpInfo_iface; + } } if(*ppv) { @@ -1305,26 +1316,38 @@ static HRESULT WINAPI WinInetHttpInfo_QueryOption(IWinInetHttpInfo *iface, DWORD void *pBuffer, DWORD *pcbBuffer) { Binding *This = impl_from_IWinInetHttpInfo(iface); + IWinInetInfo *wininet_info; + HRESULT hres; + TRACE("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer); - if(!This->protocol->wininet_info) + hres = IInternetProtocolEx_QueryInterface(&This->protocol->IInternetProtocolEx_iface, + &IID_IWinInetInfo, (void**)&wininet_info); + if(FAILED(hres)) return E_FAIL; - return IWinInetInfo_QueryOption(This->protocol->wininet_info, - dwOption, pBuffer, pcbBuffer); + hres = IWinInetInfo_QueryOption(wininet_info, dwOption, pBuffer, pcbBuffer); + IWinInetInfo_Release(wininet_info); + return hres; } static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption, void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved) { Binding *This = impl_from_IWinInetHttpInfo(iface); + IWinInetHttpInfo *http_info; + HRESULT hres; + TRACE("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved); - if(!This->protocol->wininet_http_info) + hres = IInternetProtocolEx_QueryInterface(&This->protocol->IInternetProtocolEx_iface, + &IID_IWinInetHttpInfo, (void**)&http_info); + if(FAILED(hres)) return E_FAIL; - return IWinInetHttpInfo_QueryInfo(This->protocol->wininet_http_info, - dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved); + hres = IWinInetHttpInfo_QueryInfo(http_info, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved); + IWinInetHttpInfo_Release(http_info); + return hres; } static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = { @@ -1474,7 +1497,7 @@ static HRESULT Binding_Create(IMoniker *mon, Binding *binding_ctx, IUri *uri, IB ret->protocol = binding_ctx->protocol; IInternetProtocolEx_AddRef(&ret->protocol->IInternetProtocolEx_iface); }else { - hres = create_binding_protocol(TRUE, &ret->protocol); + hres = create_binding_protocol(&ret->protocol); if(FAILED(hres)) { WARN("Could not get protocol handler\n"); IBinding_Release(&ret->IBinding_iface); diff --git a/dll/win32/urlmon/bindprot.c b/dll/win32/urlmon/bindprot.c index 47c972b1e3e..42d3d219252 100644 --- a/dll/win32/urlmon/bindprot.c +++ b/dll/win32/urlmon/bindprot.c @@ -283,32 +283,11 @@ static HRESULT WINAPI BindProtocol_QueryInterface(IInternetProtocolEx *iface, RE }else if(IsEqualGUID(&IID_IInternetProtocolSink, riid)) { TRACE("(%p)->(IID_IInternetProtocolSink %p)\n", This, ppv); *ppv = &This->IInternetProtocolSink_iface; - }else if(IsEqualGUID(&IID_IWinInetInfo, riid)) { - TRACE("(%p)->(IID_IWinInetInfo %p)\n", This, ppv); - - if(This->protocol) { - IWinInetInfo *inet_info; - HRESULT hres; - - hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetInfo, (void**)&inet_info); - if(SUCCEEDED(hres)) { - *ppv = &This->IWinInetHttpInfo_iface; - IWinInetInfo_Release(inet_info); - } - } - }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) { - TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv); - - if(This->protocol) { - IWinInetHttpInfo *http_info; - HRESULT hres; - - hres = IInternetProtocol_QueryInterface(This->protocol, &IID_IWinInetHttpInfo, (void**)&http_info); - if(SUCCEEDED(hres)) { - *ppv = &This->IWinInetHttpInfo_iface; - IWinInetHttpInfo_Release(http_info); - } - } + }else if(This->protocol_unk) { + HRESULT hres; + hres = IUnknown_QueryInterface(This->protocol_unk, riid, ppv); + TRACE("(%p) aggregated handler returned %08x for %s\n", This, hres, debugstr_guid(riid)); + return hres; }else { WARN("not supported interface %s\n", debugstr_guid(riid)); } @@ -330,14 +309,6 @@ static ULONG WINAPI BindProtocol_AddRef(IInternetProtocolEx *iface) static void release_protocol_handler(BindProtocol *This) { - if(This->wininet_info) { - IWinInetInfo_Release(This->wininet_info); - This->wininet_info = NULL; - } - if(This->wininet_http_info) { - IWinInetHttpInfo_Release(This->wininet_http_info); - This->wininet_http_info = NULL; - } if(This->protocol) { IInternetProtocol_Release(This->protocol); This->protocol = NULL; @@ -351,6 +322,10 @@ static void release_protocol_handler(BindProtocol *This) IInternetProtocolSink_Release(This->protocol_sink_handler); This->protocol_sink_handler = &This->default_protocol_handler.IInternetProtocolSink_iface; } + if(This->protocol_unk) { + IUnknown_Release(This->protocol_unk); + This->protocol_unk = NULL; + } } static ULONG WINAPI BindProtocol_Release(IInternetProtocolEx *iface) @@ -497,8 +472,8 @@ static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr IInternetProtocolEx *protocolex; IInternetPriority *priority; IServiceProvider *service_provider; - BOOL urlmon_protocol = FALSE; CLSID clsid = IID_NULL; + IUnknown *protocol_unk = NULL; LPOLESTR clsid_str; HRESULT hres; @@ -527,28 +502,21 @@ static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr if(!protocol) { IClassFactory *cf; - IUnknown *unk; - hres = get_protocol_handler(pUri, &clsid, &urlmon_protocol, &cf); + hres = get_protocol_handler(pUri, &clsid, &cf); if(FAILED(hres)) return hres; - if(This->from_urlmon) { - hres = IClassFactory_CreateInstance(cf, NULL, &IID_IInternetProtocol, (void**)&protocol); - IClassFactory_Release(cf); - if(FAILED(hres)) - return hres; - }else { - hres = IClassFactory_CreateInstance(cf, (IUnknown*)&This->IInternetBindInfo_iface, - &IID_IUnknown, (void**)&unk); - IClassFactory_Release(cf); - if(FAILED(hres)) - return hres; + hres = IClassFactory_CreateInstance(cf, (IUnknown*)&This->IInternetBindInfo_iface, + &IID_IUnknown, (void**)&protocol_unk); + IClassFactory_Release(cf); + if(FAILED(hres)) + return hres; - hres = IUnknown_QueryInterface(unk, &IID_IInternetProtocol, (void**)&protocol); - IUnknown_Release(unk); - if(FAILED(hres)) - return hres; + hres = IUnknown_QueryInterface(protocol_unk, &IID_IInternetProtocol, (void**)&protocol); + if(FAILED(hres)) { + IUnknown_Release(protocol_unk); + return hres; } } @@ -556,22 +524,21 @@ static HRESULT WINAPI BindProtocol_StartEx(IInternetProtocolEx *iface, IUri *pUr IInternetProtocolSink_ReportProgress(pOIProtSink, BINDSTATUS_PROTOCOLCLASSID, clsid_str); CoTaskMemFree(clsid_str); + This->protocol_unk = protocol_unk; This->protocol = protocol; - if(urlmon_protocol) { - IInternetProtocol_QueryInterface(protocol, &IID_IWinInetInfo, (void**)&This->wininet_info); - IInternetProtocol_QueryInterface(protocol, &IID_IWinInetHttpInfo, (void**)&This->wininet_http_info); - } + if(!protocol_unk) + protocol_unk = (IUnknown*)protocol; set_binding_sink(This, pOIProtSink, pOIBindInfo); - hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetPriority, (void**)&priority); + hres = IUnknown_QueryInterface(protocol_unk, &IID_IInternetPriority, (void**)&priority); if(SUCCEEDED(hres)) { IInternetPriority_SetPriority(priority, This->priority); IInternetPriority_Release(priority); } - hres = IInternetProtocol_QueryInterface(protocol, &IID_IInternetProtocolEx, (void**)&protocolex); + hres = IUnknown_QueryInterface(protocol_unk, &IID_IInternetProtocolEx, (void**)&protocolex); if(SUCCEEDED(hres)) { hres = IInternetProtocolEx_StartEx(protocolex, pUri, &This->IInternetProtocolSink_iface, &This->IInternetBindInfo_iface, 0, NULL); @@ -687,13 +654,25 @@ static HRESULT WINAPI ProtocolHandler_Start(IInternetProtocol *iface, LPCWSTR sz static HRESULT WINAPI ProtocolHandler_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData) { BindProtocol *This = impl_from_IInternetProtocol(iface); + IInternetProtocol *protocol = NULL; HRESULT hres; TRACE("(%p)->(%p)\n", This, pProtocolData); - hres = IInternetProtocol_Continue(This->protocol, pProtocolData); + /* FIXME: This should not be needed. */ + if(!This->protocol) { + if(!This->protocol_unk) + return E_FAIL; + hres = IUnknown_QueryInterface(This->protocol_unk, &IID_IInternetProtocol, (void**)&protocol); + if(FAILED(hres)) + return E_FAIL; + } + + hres = IInternetProtocol_Continue(protocol ? protocol : This->protocol, pProtocolData); heap_free(pProtocolData); + if(protocol) + IInternetProtocol_Release(protocol); return hres; } @@ -722,7 +701,11 @@ static HRESULT WINAPI ProtocolHandler_Terminate(IInternetProtocol *iface, DWORD /* This may get released in Terminate call. */ IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface); - IInternetProtocol_Terminate(This->protocol, 0); + if(This->protocol) { + IInternetProtocol_Terminate(This->protocol, 0); + IInternetProtocol_Release(This->protocol); + This->protocol = NULL; + } set_binding_sink(This, NULL, NULL); @@ -778,14 +761,28 @@ static HRESULT WINAPI ProtocolHandler_Read(IInternetProtocol *iface, void *pv, } if(read < cb) { + IInternetProtocol *protocol; ULONG cread = 0; + /* FIXME: We shouldn't need it, but out binding code currently depends on it. */ + if(!This->protocol && This->protocol_unk) { + hres = IUnknown_QueryInterface(This->protocol_unk, &IID_IInternetProtocol, + (void**)&protocol); + if(FAILED(hres)) + return E_ABORT; + }else { + protocol = This->protocol; + } + if(is_apartment_thread(This)) This->continue_call++; - hres = IInternetProtocol_Read(This->protocol, (BYTE*)pv+read, cb-read, &cread); + hres = IInternetProtocol_Read(protocol, (BYTE*)pv+read, cb-read, &cread); if(is_apartment_thread(This)) This->continue_call--; read += cread; + + if(!This->protocol) + IInternetProtocol_Release(protocol); } *pcbRead = read; @@ -1391,53 +1388,6 @@ static const IInternetProtocolSinkVtbl InternetProtocolSinkVtbl = { BPInternetProtocolSink_ReportResult }; -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 = impl_from_IWinInetHttpInfo(iface); - return IInternetProtocolEx_QueryInterface(&This->IInternetProtocolEx_iface, riid, ppv); -} - -static ULONG WINAPI WinInetHttpInfo_AddRef(IWinInetHttpInfo *iface) -{ - BindProtocol *This = impl_from_IWinInetHttpInfo(iface); - return IInternetProtocolEx_AddRef(&This->IInternetProtocolEx_iface); -} - -static ULONG WINAPI WinInetHttpInfo_Release(IWinInetHttpInfo *iface) -{ - 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 = impl_from_IWinInetHttpInfo(iface); - FIXME("(%p)->(%x %p %p)\n", This, dwOption, pBuffer, pcbBuffer); - return E_NOTIMPL; -} - -static HRESULT WINAPI WinInetHttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption, - void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved) -{ - BindProtocol *This = impl_from_IWinInetHttpInfo(iface); - FIXME("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved); - return E_NOTIMPL; -} - -static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = { - WinInetHttpInfo_QueryInterface, - WinInetHttpInfo_AddRef, - WinInetHttpInfo_Release, - WinInetHttpInfo_QueryOption, - WinInetHttpInfo_QueryInfo -}; - static inline BindProtocol *impl_from_IServiceProvider(IServiceProvider *iface) { return CONTAINING_RECORD(iface, BindProtocol, IServiceProvider_iface); @@ -1482,7 +1432,7 @@ static const IServiceProviderVtbl ServiceProviderVtbl = { BPServiceProvider_QueryService }; -HRESULT create_binding_protocol(BOOL from_urlmon, BindProtocol **protocol) +HRESULT create_binding_protocol(BindProtocol **protocol) { BindProtocol *ret = heap_alloc_zero(sizeof(BindProtocol)); @@ -1491,13 +1441,11 @@ HRESULT create_binding_protocol(BOOL from_urlmon, BindProtocol **protocol) 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; ret->default_protocol_handler.IInternetProtocolSink_iface.lpVtbl = &InternetProtocolSinkHandlerVtbl; ret->ref = 1; - ret->from_urlmon = from_urlmon; ret->apartment_thread = GetCurrentThreadId(); ret->notif_hwnd = get_notif_hwnd(); ret->protocol_handler = &ret->default_protocol_handler.IInternetProtocol_iface; diff --git a/dll/win32/urlmon/file.c b/dll/win32/urlmon/file.c index bba7be1079d..9e7f3cf184e 100644 --- a/dll/win32/urlmon/file.c +++ b/dll/win32/urlmon/file.c @@ -25,9 +25,12 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon); typedef struct { + IUnknown IUnknown_outer; IInternetProtocolEx IInternetProtocolEx_iface; IInternetPriority IInternetPriority_iface; + IUnknown *outer; + HANDLE file; ULONG size; LONG priority; @@ -35,6 +38,11 @@ typedef struct { LONG ref; } FileProtocol; +static inline FileProtocol *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, FileProtocol, IUnknown_outer); +} + static inline FileProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface) { return CONTAINING_RECORD(iface, FileProtocol, IInternetProtocolEx_iface); @@ -45,14 +53,14 @@ static inline FileProtocol *impl_from_IInternetPriority(IInternetPriority *iface return CONTAINING_RECORD(iface, FileProtocol, IInternetPriority_iface); } -static HRESULT WINAPI FileProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv) +static HRESULT WINAPI FileProtocolUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) { - FileProtocol *This = impl_from_IInternetProtocolEx(iface); + FileProtocol *This = impl_from_IUnknown(iface); *ppv = NULL; if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); - *ppv = &This->IInternetProtocolEx_iface; + *ppv = &This->IUnknown_outer; }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) { TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv); *ppv = &This->IInternetProtocolEx_iface; @@ -68,7 +76,7 @@ static HRESULT WINAPI FileProtocol_QueryInterface(IInternetProtocolEx *iface, RE } if(*ppv) { - IInternetProtocolEx_AddRef(iface); + IUnknown_AddRef((IUnknown*)*ppv); return S_OK; } @@ -76,17 +84,17 @@ static HRESULT WINAPI FileProtocol_QueryInterface(IInternetProtocolEx *iface, RE return E_NOINTERFACE; } -static ULONG WINAPI FileProtocol_AddRef(IInternetProtocolEx *iface) +static ULONG WINAPI FileProtocolUnk_AddRef(IUnknown *iface) { - FileProtocol *This = impl_from_IInternetProtocolEx(iface); + FileProtocol *This = impl_from_IUnknown(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); return ref; } -static ULONG WINAPI FileProtocol_Release(IInternetProtocolEx *iface) +static ULONG WINAPI FileProtocolUnk_Release(IUnknown *iface) { - FileProtocol *This = impl_from_IInternetProtocolEx(iface); + FileProtocol *This = impl_from_IUnknown(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); @@ -102,6 +110,33 @@ static ULONG WINAPI FileProtocol_Release(IInternetProtocolEx *iface) return ref; } +static const IUnknownVtbl FileProtocolUnkVtbl = { + FileProtocolUnk_QueryInterface, + FileProtocolUnk_AddRef, + FileProtocolUnk_Release +}; + +static HRESULT WINAPI FileProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv) +{ + FileProtocol *This = impl_from_IInternetProtocolEx(iface); + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + return IUnknown_QueryInterface(This->outer, riid, ppv); +} + +static ULONG WINAPI FileProtocol_AddRef(IInternetProtocolEx *iface) +{ + FileProtocol *This = impl_from_IInternetProtocolEx(iface); + TRACE("(%p)\n", This); + return IUnknown_AddRef(This->outer); +} + +static ULONG WINAPI FileProtocol_Release(IInternetProtocolEx *iface) +{ + FileProtocol *This = impl_from_IInternetProtocolEx(iface); + TRACE("(%p)\n", This); + return IUnknown_Release(This->outer); +} + static HRESULT WINAPI FileProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) @@ -383,22 +418,24 @@ static const IInternetPriorityVtbl FilePriorityVtbl = { FilePriority_GetPriority }; -HRESULT FileProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) +HRESULT FileProtocol_Construct(IUnknown *outer, LPVOID *ppobj) { FileProtocol *ret; - TRACE("(%p %p)\n", pUnkOuter, ppobj); + TRACE("(%p %p)\n", outer, ppobj); URLMON_LockModule(); ret = heap_alloc(sizeof(FileProtocol)); + ret->IUnknown_outer.lpVtbl = &FileProtocolUnkVtbl; ret->IInternetProtocolEx_iface.lpVtbl = &FileProtocolExVtbl; ret->IInternetPriority_iface.lpVtbl = &FilePriorityVtbl; ret->file = INVALID_HANDLE_VALUE; ret->priority = 0; ret->ref = 1; + ret->outer = outer ? outer : (IUnknown*)&ret->IUnknown_outer; - *ppobj = &ret->IInternetProtocolEx_iface; + *ppobj = &ret->IUnknown_outer; return S_OK; } diff --git a/dll/win32/urlmon/ftp.c b/dll/win32/urlmon/ftp.c index da1efe202de..aef4a6cf16c 100644 --- a/dll/win32/urlmon/ftp.c +++ b/dll/win32/urlmon/ftp.c @@ -28,13 +28,20 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon); typedef struct { Protocol base; + IUnknown IUnknown_outer; IInternetProtocolEx IInternetProtocolEx_iface; IInternetPriority IInternetPriority_iface; IWinInetHttpInfo IWinInetHttpInfo_iface; LONG ref; + IUnknown *outer; } FtpProtocol; +static inline FtpProtocol *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, FtpProtocol, IUnknown_outer); +} + static inline FtpProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface) { return CONTAINING_RECORD(iface, FtpProtocol, IInternetProtocolEx_iface); @@ -115,14 +122,13 @@ static const ProtocolVtbl AsyncProtocolVtbl = { FtpProtocol_on_error }; -static HRESULT WINAPI FtpProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv) +static HRESULT WINAPI FtpProtocolUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) { - FtpProtocol *This = impl_from_IInternetProtocolEx(iface); + FtpProtocol *This = impl_from_IUnknown(iface); - *ppv = NULL; if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); - *ppv = &This->IInternetProtocolEx_iface; + *ppv = &This->IUnknown_outer; }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) { TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv); *ppv = &This->IInternetProtocolEx_iface; @@ -141,28 +147,27 @@ static HRESULT WINAPI FtpProtocol_QueryInterface(IInternetProtocolEx *iface, REF }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) { TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv); *ppv = &This->IWinInetHttpInfo_iface; + }else { + *ppv = NULL; + WARN("not supported interface %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; } - if(*ppv) { - IInternetProtocolEx_AddRef(iface); - return S_OK; - } - - WARN("not supported interface %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; } -static ULONG WINAPI FtpProtocol_AddRef(IInternetProtocolEx *iface) +static ULONG WINAPI FtpProtocolUnk_AddRef(IUnknown *iface) { - FtpProtocol *This = impl_from_IInternetProtocolEx(iface); + FtpProtocol *This = impl_from_IUnknown(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); return ref; } -static ULONG WINAPI FtpProtocol_Release(IInternetProtocolEx *iface) +static ULONG WINAPI FtpProtocolUnk_Release(IUnknown *iface) { - FtpProtocol *This = impl_from_IInternetProtocolEx(iface); + FtpProtocol *This = impl_from_IUnknown(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); @@ -177,6 +182,33 @@ static ULONG WINAPI FtpProtocol_Release(IInternetProtocolEx *iface) return ref; } +static const IUnknownVtbl FtpProtocolUnkVtbl = { + FtpProtocolUnk_QueryInterface, + FtpProtocolUnk_AddRef, + FtpProtocolUnk_Release +}; + +static HRESULT WINAPI FtpProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv) +{ + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + return IUnknown_QueryInterface(This->outer, riid, ppv); +} + +static ULONG WINAPI FtpProtocol_AddRef(IInternetProtocolEx *iface) +{ + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); + TRACE("(%p)\n", This); + return IUnknown_AddRef(This->outer); +} + +static ULONG WINAPI FtpProtocol_Release(IInternetProtocolEx *iface) +{ + FtpProtocol *This = impl_from_IInternetProtocolEx(iface); + TRACE("(%p)\n", This); + return IUnknown_Release(This->outer); +} + static HRESULT WINAPI FtpProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) @@ -416,23 +448,24 @@ static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = { HttpInfo_QueryInfo }; -HRESULT FtpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) +HRESULT FtpProtocol_Construct(IUnknown *outer, void **ppv) { FtpProtocol *ret; - TRACE("(%p %p)\n", pUnkOuter, ppobj); + TRACE("(%p %p)\n", outer, ppv); URLMON_LockModule(); ret = heap_alloc_zero(sizeof(FtpProtocol)); ret->base.vtbl = &AsyncProtocolVtbl; + ret->IUnknown_outer.lpVtbl = &FtpProtocolUnkVtbl; ret->IInternetProtocolEx_iface.lpVtbl = &FtpProtocolVtbl; ret->IInternetPriority_iface.lpVtbl = &FtpPriorityVtbl; ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl; ret->ref = 1; + ret->outer = outer ? outer : &ret->IUnknown_outer; - *ppobj = &ret->IInternetProtocolEx_iface; - + *ppv = &ret->IUnknown_outer; return S_OK; } diff --git a/dll/win32/urlmon/http.c b/dll/win32/urlmon/http.c index 9cc6117aaaa..5fcbd541743 100644 --- a/dll/win32/urlmon/http.c +++ b/dll/win32/urlmon/http.c @@ -32,6 +32,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon); typedef struct { Protocol base; + IUnknown IUnknown_outer; IInternetProtocolEx IInternetProtocolEx_iface; IInternetPriority IInternetPriority_iface; IWinInetHttpInfo IWinInetHttpInfo_iface; @@ -41,8 +42,14 @@ typedef struct { WCHAR *full_header; LONG ref; + IUnknown *outer; } HttpProtocol; +static inline HttpProtocol *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, HttpProtocol, IUnknown_outer); +} + static inline HttpProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface) { return CONTAINING_RECORD(iface, HttpProtocol, IInternetProtocolEx_iface); @@ -624,14 +631,13 @@ static const ProtocolVtbl AsyncProtocolVtbl = { HttpProtocol_on_error }; -static HRESULT WINAPI HttpProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv) +static HRESULT WINAPI HttpProtocolUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) { - HttpProtocol *This = impl_from_IInternetProtocolEx(iface); + HttpProtocol *This = impl_from_IUnknown(iface); - *ppv = NULL; if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); - *ppv = &This->IInternetProtocolEx_iface; + *ppv = &This->IUnknown_outer; }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) { TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv); *ppv = &This->IInternetProtocolEx_iface; @@ -650,28 +656,27 @@ static HRESULT WINAPI HttpProtocol_QueryInterface(IInternetProtocolEx *iface, RE }else if(IsEqualGUID(&IID_IWinInetHttpInfo, riid)) { TRACE("(%p)->(IID_IWinInetHttpInfo %p)\n", This, ppv); *ppv = &This->IWinInetHttpInfo_iface; + }else { + *ppv = NULL; + WARN("not supported interface %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; } - if(*ppv) { - IInternetProtocolEx_AddRef(iface); - return S_OK; - } - - WARN("not supported interface %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; } -static ULONG WINAPI HttpProtocol_AddRef(IInternetProtocolEx *iface) +static ULONG WINAPI HttpProtocolUnk_AddRef(IUnknown *iface) { - HttpProtocol *This = impl_from_IInternetProtocolEx(iface); + HttpProtocol *This = impl_from_IUnknown(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); return ref; } -static ULONG WINAPI HttpProtocol_Release(IInternetProtocolEx *iface) +static ULONG WINAPI HttpProtocolUnk_Release(IUnknown *iface) { - HttpProtocol *This = impl_from_IInternetProtocolEx(iface); + HttpProtocol *This = impl_from_IUnknown(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); @@ -686,6 +691,33 @@ static ULONG WINAPI HttpProtocol_Release(IInternetProtocolEx *iface) return ref; } +static const IUnknownVtbl HttpProtocolUnkVtbl = { + HttpProtocolUnk_QueryInterface, + HttpProtocolUnk_AddRef, + HttpProtocolUnk_Release +}; + +static HRESULT WINAPI HttpProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv) +{ + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + return IUnknown_QueryInterface(This->outer, riid, ppv); +} + +static ULONG WINAPI HttpProtocol_AddRef(IInternetProtocolEx *iface) +{ + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); + TRACE("(%p)\n", This); + return IUnknown_AddRef(This->outer); +} + +static ULONG WINAPI HttpProtocol_Release(IInternetProtocolEx *iface) +{ + HttpProtocol *This = impl_from_IInternetProtocolEx(iface); + TRACE("(%p)\n", This); + return IUnknown_Release(This->outer); +} + static HRESULT WINAPI HttpProtocol_Start(IInternetProtocolEx *iface, LPCWSTR szUrl, IInternetProtocolSink *pOIProtSink, IInternetBindInfo *pOIBindInfo, DWORD grfPI, HANDLE_PTR dwReserved) @@ -926,7 +958,7 @@ static const IWinInetHttpInfoVtbl WinInetHttpInfoVtbl = { HttpInfo_QueryInfo }; -static HRESULT create_http_protocol(BOOL https, void **ppobj) +static HRESULT create_http_protocol(BOOL https, IUnknown *outer, void **ppobj) { HttpProtocol *ret; @@ -935,29 +967,31 @@ static HRESULT create_http_protocol(BOOL https, void **ppobj) return E_OUTOFMEMORY; ret->base.vtbl = &AsyncProtocolVtbl; + ret->IUnknown_outer.lpVtbl = &HttpProtocolUnkVtbl; ret->IInternetProtocolEx_iface.lpVtbl = &HttpProtocolVtbl; ret->IInternetPriority_iface.lpVtbl = &HttpPriorityVtbl; ret->IWinInetHttpInfo_iface.lpVtbl = &WinInetHttpInfoVtbl; ret->https = https; ret->ref = 1; + ret->outer = outer ? outer : &ret->IUnknown_outer; - *ppobj = &ret->IInternetProtocolEx_iface; + *ppobj = &ret->IUnknown_outer; URLMON_LockModule(); return S_OK; } -HRESULT HttpProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) +HRESULT HttpProtocol_Construct(IUnknown *outer, void **ppv) { - TRACE("(%p %p)\n", pUnkOuter, ppobj); + TRACE("(%p %p)\n", outer, ppv); - return create_http_protocol(FALSE, ppobj); + return create_http_protocol(FALSE, outer, ppv); } -HRESULT HttpSProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) +HRESULT HttpSProtocol_Construct(IUnknown *outer, void **ppv) { - TRACE("(%p %p)\n", pUnkOuter, ppobj); + TRACE("(%p %p)\n", outer, ppv); - return create_http_protocol(TRUE, ppobj); + return create_http_protocol(TRUE, outer, ppv); } diff --git a/dll/win32/urlmon/mk.c b/dll/win32/urlmon/mk.c index 984f381de3b..d73a00c7716 100644 --- a/dll/win32/urlmon/mk.c +++ b/dll/win32/urlmon/mk.c @@ -25,26 +25,32 @@ WINE_DEFAULT_DEBUG_CHANNEL(urlmon); typedef struct { + IUnknown IUnknown_outer; IInternetProtocolEx IInternetProtocolEx_iface; LONG ref; + IUnknown *outer; IStream *stream; } MkProtocol; +static inline MkProtocol *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, MkProtocol, IUnknown_outer); +} + static inline MkProtocol *impl_from_IInternetProtocolEx(IInternetProtocolEx *iface) { return CONTAINING_RECORD(iface, MkProtocol, IInternetProtocolEx_iface); } -static HRESULT WINAPI MkProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv) +static HRESULT WINAPI MkProtocolUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) { - MkProtocol *This = impl_from_IInternetProtocolEx(iface); + MkProtocol *This = impl_from_IUnknown(iface); - *ppv = NULL; if(IsEqualGUID(&IID_IUnknown, riid)) { TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); - *ppv = &This->IInternetProtocolEx_iface; + *ppv = &This->IUnknown_outer; }else if(IsEqualGUID(&IID_IInternetProtocolRoot, riid)) { TRACE("(%p)->(IID_IInternetProtocolRoot %p)\n", This, ppv); *ppv = &This->IInternetProtocolEx_iface; @@ -54,28 +60,27 @@ static HRESULT WINAPI MkProtocol_QueryInterface(IInternetProtocolEx *iface, REFI }else if(IsEqualGUID(&IID_IInternetProtocolEx, riid)) { TRACE("(%p)->(IID_IInternetProtocolEx %p)\n", This, ppv); *ppv = &This->IInternetProtocolEx_iface; + }else { + *ppv = NULL; + WARN("not supported interface %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; } - if(*ppv) { - IInternetProtocolEx_AddRef(iface); - return S_OK; - } - - WARN("not supported interface %s\n", debugstr_guid(riid)); - return E_NOINTERFACE; + IUnknown_AddRef((IUnknown*)*ppv); + return S_OK; } -static ULONG WINAPI MkProtocol_AddRef(IInternetProtocolEx *iface) +static ULONG WINAPI MkProtocolUnk_AddRef(IUnknown *iface) { - MkProtocol *This = impl_from_IInternetProtocolEx(iface); + MkProtocol *This = impl_from_IUnknown(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); return ref; } -static ULONG WINAPI MkProtocol_Release(IInternetProtocolEx *iface) +static ULONG WINAPI MkProtocolUnk_Release(IUnknown *iface) { - MkProtocol *This = impl_from_IInternetProtocolEx(iface); + MkProtocol *This = impl_from_IUnknown(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); @@ -92,6 +97,33 @@ static ULONG WINAPI MkProtocol_Release(IInternetProtocolEx *iface) return ref; } +static const IUnknownVtbl MkProtocolUnkVtbl = { + MkProtocolUnk_QueryInterface, + MkProtocolUnk_AddRef, + MkProtocolUnk_Release +}; + +static HRESULT WINAPI MkProtocol_QueryInterface(IInternetProtocolEx *iface, REFIID riid, void **ppv) +{ + MkProtocol *This = impl_from_IInternetProtocolEx(iface); + TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + return IUnknown_QueryInterface(This->outer, riid, ppv); +} + +static ULONG WINAPI MkProtocol_AddRef(IInternetProtocolEx *iface) +{ + MkProtocol *This = impl_from_IInternetProtocolEx(iface); + TRACE("(%p)\n", This); + return IUnknown_AddRef(This->outer); +} + +static ULONG WINAPI MkProtocol_Release(IInternetProtocolEx *iface) +{ + MkProtocol *This = impl_from_IInternetProtocolEx(iface); + TRACE("(%p)\n", This); + return IUnknown_Release(This->outer); +} + static HRESULT report_result(IInternetProtocolSink *sink, HRESULT hres, DWORD dwError) { IInternetProtocolSink_ReportResult(sink, hres, dwError, NULL); @@ -330,24 +362,25 @@ static const IInternetProtocolExVtbl MkProtocolVtbl = { MkProtocol_StartEx }; -HRESULT MkProtocol_Construct(IUnknown *pUnkOuter, LPVOID *ppobj) +HRESULT MkProtocol_Construct(IUnknown *outer, void **ppv) { MkProtocol *ret; - TRACE("(%p %p)\n", pUnkOuter, ppobj); + TRACE("(%p %p)\n", outer, ppv); URLMON_LockModule(); ret = heap_alloc(sizeof(MkProtocol)); + ret->IUnknown_outer.lpVtbl = &MkProtocolUnkVtbl; ret->IInternetProtocolEx_iface.lpVtbl = &MkProtocolVtbl; ret->ref = 1; + ret->outer = outer ? outer : &ret->IUnknown_outer; ret->stream = NULL; /* NOTE: - * Native returns NULL ppobj and S_OK in CreateInstance if called with IID_IUnknown riid. + * Native returns NULL ppobj and S_OK in CreateInstance if called with IID_IUnknown riid and no outer. */ - *ppobj = &ret->IInternetProtocolEx_iface; - + *ppv = &ret->IUnknown_outer; return S_OK; } diff --git a/dll/win32/urlmon/session.c b/dll/win32/urlmon/session.c index 1df483f130a..dea1c9f121c 100644 --- a/dll/win32/urlmon/session.c +++ b/dll/win32/urlmon/session.c @@ -219,7 +219,7 @@ IInternetProtocolInfo *get_protocol_info(LPCWSTR url) return ret; } -HRESULT get_protocol_handler(IUri *uri, CLSID *clsid, BOOL *urlmon_protocol, IClassFactory **ret) +HRESULT get_protocol_handler(IUri *uri, CLSID *clsid, IClassFactory **ret) { name_space *ns; BSTR scheme; @@ -240,20 +240,11 @@ HRESULT get_protocol_handler(IUri *uri, CLSID *clsid, BOOL *urlmon_protocol, ICl IClassFactory_AddRef(*ret); if(clsid) *clsid = ns->clsid; - if(urlmon_protocol) - *urlmon_protocol = ns->urlmon; } LeaveCriticalSection(&session_cs); - if(*ret) { - hres = S_OK; - }else { - if(urlmon_protocol) - *urlmon_protocol = FALSE; - hres = get_protocol_cf(scheme, SysStringLen(scheme), clsid, ret); - } - + hres = *ret ? S_OK : get_protocol_cf(scheme, SysStringLen(scheme), clsid, ret); SysFreeString(scheme); return hres; } @@ -448,7 +439,7 @@ static HRESULT WINAPI InternetSession_CreateBinding(IInternetSession *iface, if(pBC || pUnkOuter || ppUnk || dwOption) FIXME("Unsupported arguments\n"); - hres = create_binding_protocol(FALSE, &protocol); + hres = create_binding_protocol(&protocol); if(FAILED(hres)) return hres; diff --git a/dll/win32/urlmon/urlmon_main.c b/dll/win32/urlmon/urlmon_main.c index c4f1cec5fa0..5968a6ce55f 100644 --- a/dll/win32/urlmon/urlmon_main.c +++ b/dll/win32/urlmon/urlmon_main.c @@ -303,19 +303,31 @@ static ULONG WINAPI CF_Release(IClassFactory *iface) } -static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *pOuter, - REFIID riid, LPVOID *ppobj) +static HRESULT WINAPI CF_CreateInstance(IClassFactory *iface, IUnknown *outer, + REFIID riid, void **ppv) { ClassFactory *This = impl_from_IClassFactory(iface); + IUnknown *unk; HRESULT hres; - LPUNKNOWN punk; - TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); + TRACE("(%p)->(%p %s %p)\n", This, outer, debugstr_guid(riid), ppv); - *ppobj = NULL; - if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) { - hres = IUnknown_QueryInterface(punk, riid, ppobj); - IUnknown_Release(punk); + if(outer && !IsEqualGUID(riid, &IID_IUnknown)) { + *ppv = NULL; + return CLASS_E_NOAGGREGATION; + } + + hres = This->pfnCreateInstance(outer, (void**)&unk); + if(FAILED(hres)) { + *ppv = NULL; + return hres; + } + + if(!IsEqualGUID(riid, &IID_IUnknown)) { + hres = IUnknown_QueryInterface(unk, riid, ppv); + IUnknown_Release(unk); + }else { + *ppv = unk; } return hres; } diff --git a/dll/win32/urlmon/urlmon_main.h b/dll/win32/urlmon/urlmon_main.h index a4a1c78d524..39dbe2f5726 100644 --- a/dll/win32/urlmon/urlmon_main.h +++ b/dll/win32/urlmon/urlmon_main.h @@ -66,7 +66,7 @@ static inline void URLMON_UnlockModule(void) { InterlockedDecrement( &URLMON_ref extern HINSTANCE urlmon_instance; IInternetProtocolInfo *get_protocol_info(LPCWSTR) DECLSPEC_HIDDEN; -HRESULT get_protocol_handler(IUri*,CLSID*,BOOL*,IClassFactory**) DECLSPEC_HIDDEN; +HRESULT get_protocol_handler(IUri*,CLSID*,IClassFactory**) DECLSPEC_HIDDEN; IInternetProtocol *get_mime_filter(LPCWSTR) DECLSPEC_HIDDEN; BOOL is_registered_protocol(LPCWSTR) DECLSPEC_HIDDEN; HRESULT register_namespace(IClassFactory*,REFIID,LPCWSTR,BOOL) DECLSPEC_HIDDEN; @@ -172,13 +172,11 @@ typedef struct { IInternetPriority IInternetPriority_iface; IServiceProvider IServiceProvider_iface; IInternetProtocolSink IInternetProtocolSink_iface; - IWinInetHttpInfo IWinInetHttpInfo_iface; LONG ref; + IUnknown *protocol_unk; IInternetProtocol *protocol; - IWinInetInfo *wininet_info; - IWinInetHttpInfo *wininet_http_info; IInternetBindInfo *bind_info; IInternetProtocolSink *protocol_sink; @@ -196,7 +194,6 @@ typedef struct { BOOL reported_result; BOOL reported_mime; - BOOL from_urlmon; DWORD pi; DWORD bscf; @@ -217,7 +214,7 @@ typedef struct { BSTR display_uri; } BindProtocol; -HRESULT create_binding_protocol(BOOL,BindProtocol**) DECLSPEC_HIDDEN; +HRESULT create_binding_protocol(BindProtocol**) DECLSPEC_HIDDEN; void set_binding_sink(BindProtocol*,IInternetProtocolSink*,IInternetBindInfo*) DECLSPEC_HIDDEN; typedef struct { diff --git a/media/doc/README.WINE b/media/doc/README.WINE index 32a8639dc3a..6ebb064c602 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -188,7 +188,7 @@ reactos/dll/win32/traffic # Synced to WineStaging-3.3 reactos/dll/win32/twain_32 # Synced to WineStaging-3.3 reactos/dll/win32/updspapi # Synced to WineStaging-3.3 reactos/dll/win32/url # Synced to WineStaging-3.3 -reactos/dll/win32/urlmon # Synced to WineStaging-3.3 +reactos/dll/win32/urlmon # Synced to WineStaging-3.9 reactos/dll/win32/usp10 # Synced to WineStaging-3.3 reactos/dll/win32/uxtheme # Forked reactos/dll/win32/vbscript # Synced to WineStaging-3.3