From cb880d7cc70f48804e052a3cd45d1e7804daa951 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 13 Feb 2006 13:26:00 +0100 Subject: [PATCH] mshtml: Handle IHlinkFrame service. --- dlls/mshtml/Makefile.in | 1 + dlls/mshtml/hlink.c | 256 +++++++++++++++++- dlls/mshtml/mshtml_private.h | 4 + dlls/mshtml/navigate.c | 496 +++++++++++++++++++++++++++++++++++ dlls/mshtml/nsio.c | 36 ++- 5 files changed, 788 insertions(+), 5 deletions(-) create mode 100644 dlls/mshtml/navigate.c diff --git a/dlls/mshtml/Makefile.in b/dlls/mshtml/Makefile.in index d369b3be081..44cc36a6ea4 100644 --- a/dlls/mshtml/Makefile.in +++ b/dlls/mshtml/Makefile.in @@ -13,6 +13,7 @@ C_SRCS = \ htmldoc.c \ htmldoc3.c \ main.c \ + navigate.c \ nsembed.c \ nsio.c \ nsservice.c\ diff --git a/dlls/mshtml/hlink.c b/dlls/mshtml/hlink.c index 5a045090751..3016917aefb 100644 --- a/dlls/mshtml/hlink.c +++ b/dlls/mshtml/hlink.c @@ -1,5 +1,5 @@ /* - * Copyright 2005 Jacek Caban + * Copyright 2005-2006 Jacek Caban for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,6 +28,7 @@ #include "ole2.h" #include "wine/debug.h" +#include "wine/unicode.h" #include "mshtml_private.h" @@ -116,3 +117,256 @@ void HTMLDocument_Hlink_Init(HTMLDocument *This) { This->lpHlinkTargetVtbl = &HlinkTargetVtbl; } + +typedef struct { + const IHlinkVtbl *lpHlinkVtbl; + + LONG ref; + + IMoniker *mon; + LPWSTR location; +} Hlink; + +#define HLINK(x) ((IHlink*) &(x)->lpHlinkVtbl) + +#define HLINK_THIS(iface) DEFINE_THIS(Hlink, Hlink, iface) + +static HRESULT WINAPI Hlink_QueryInterface(IHlink *iface, REFIID riid, void **ppv) +{ + Hlink *This = HLINK_THIS(iface); + + *ppv = NULL; + + if(IsEqualGUID(&IID_IUnknown, riid)) { + TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); + *ppv = HLINK(This); + }else if(IsEqualGUID(&IID_IHlink, riid)) { + TRACE("(%p)->(IID_IHlink %p)\n", This, ppv); + *ppv = HLINK(This); + } + + if(*ppv) { + IHlink_AddRef(HLINK(This)); + return S_OK; + } + + WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); + return E_NOINTERFACE; +} + +static ULONG WINAPI Hlink_AddRef(IHlink *iface) +{ + Hlink *This = HLINK_THIS(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + return ref; +} + +static ULONG WINAPI Hlink_Release(IHlink *iface) +{ + Hlink *This = HLINK_THIS(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + if(!ref) { + if(This->mon) + IMoniker_Release(This->mon); + HeapFree(GetProcessHeap(), 0, This->location); + HeapFree(GetProcessHeap(), 0, This); + } + + return ref; +} + +static HRESULT WINAPI Hlink_SetHlinkSite(IHlink *iface, IHlinkSite *pihlSite, DWORD dwSiteData) +{ + Hlink *This = HLINK_THIS(iface); + FIXME("(%p)->(%p %ld)\n", This, pihlSite, dwSiteData); + return E_NOTIMPL; +} + +static HRESULT WINAPI Hlink_GetHlinkSite(IHlink *iface, IHlinkSite **ppihlSite, + DWORD *pdwSiteData) +{ + Hlink *This = HLINK_THIS(iface); + + TRACE("(%p)->(%p %p)\n", This, ppihlSite, pdwSiteData); + + *ppihlSite = NULL; + return S_OK; +} + +static HRESULT WINAPI Hlink_SetMonikerReference(IHlink *iface, DWORD grfHLSETF, + IMoniker *pimkTarget, LPCWSTR pwzLocation) +{ + Hlink *This = HLINK_THIS(iface); + + TRACE("(%p)->(%08lx %p %s)\n", This, grfHLSETF, pimkTarget, debugstr_w(pwzLocation)); + + if(grfHLSETF) + FIXME("unsupported grfHLSETF=%08lx\n", grfHLSETF); + + if(This->mon) + IMoniker_Release(This->mon); + if(This->location) + HeapFree(GetProcessHeap(), 0, This->location); + + if(pimkTarget) + IMoniker_AddRef(pimkTarget); + This->mon = pimkTarget; + + if(pwzLocation) { + DWORD len = strlenW(pwzLocation)+1; + + This->location = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); + memcpy(This->location, pwzLocation, len*sizeof(WCHAR)); + }else { + This->location = NULL; + } + + return S_OK; +} + +static HRESULT WINAPI Hlink_GetMonikerReference(IHlink *iface, DWORD dwWhichRef, + IMoniker **ppimkTarget, LPWSTR *ppwzLocation) +{ + Hlink *This = HLINK_THIS(iface); + + TRACE("(%p)->(%ld %p %p)\n", This, dwWhichRef, ppimkTarget, ppwzLocation); + + if(dwWhichRef != 1) + FIXME("upsupported dwWhichRef = %ld\n", dwWhichRef); + + if(This->mon) + IMoniker_AddRef(This->mon); + *ppimkTarget = This->mon; + + if(This->location) { + DWORD len = strlenW(This->location)+1; + + *ppwzLocation = CoTaskMemAlloc(len*sizeof(WCHAR)); + memcpy(*ppwzLocation, This->location, len*sizeof(WCHAR)); + }else { + *ppwzLocation = NULL; + } + + return S_OK; +} + +static HRESULT WINAPI Hlink_SetStringReference(IHlink *iface, DWORD grfHLSETF, + LPCWSTR pwzTarget, LPCWSTR pwzLocation) +{ + Hlink *This = HLINK_THIS(iface); + FIXME("(%p)->(%08lx %s %s)\n", This, grfHLSETF, debugstr_w(pwzTarget), + debugstr_w(pwzLocation)); + return E_NOTIMPL; +} + +static HRESULT WINAPI Hlink_GetStringReference(IHlink *iface, DWORD dwWhichRef, + LPWSTR *ppwzTarget, LPWSTR *ppwzLocation) +{ + Hlink *This = HLINK_THIS(iface); + FIXME("(%p)->(%ld %p %p)\n", This, dwWhichRef, ppwzTarget, ppwzLocation); + return E_NOTIMPL; +} + +static HRESULT WINAPI Hlink_SetFriendlyName(IHlink *iface, LPCWSTR pwzFriendlyName) +{ + Hlink *This = HLINK_THIS(iface); + FIXME("(%p)->(%s)\n", This, debugstr_w(pwzFriendlyName)); + return E_NOTIMPL; +} + +static HRESULT WINAPI Hlink_GetFriendlyName(IHlink *iface, DWORD grfHLNAMEF, + LPWSTR *ppwzFriendlyName) +{ + Hlink *This = HLINK_THIS(iface); + + TRACE("(%p)->(%08lx %p)\n", This, grfHLNAMEF, ppwzFriendlyName); + + *ppwzFriendlyName = NULL; + return S_FALSE; +} + +static HRESULT WINAPI Hlink_SetTargetFrameName(IHlink *iface, LPCWSTR pwzTargetFrameName) +{ + Hlink *This = HLINK_THIS(iface); + FIXME("(%p)->(%s)\n", This, debugstr_w(pwzTargetFrameName)); + return E_NOTIMPL; +} + +static HRESULT WINAPI Hlink_GetTargetFrameName(IHlink *iface, LPWSTR *ppwzTargetFrameName) +{ + Hlink *This = HLINK_THIS(iface); + + TRACE("(%p)->(%p)\n", This, ppwzTargetFrameName); + + *ppwzTargetFrameName = NULL; + return S_FALSE; +} + +static HRESULT WINAPI Hlink_GetMiscStatus(IHlink *iface, DWORD *pdwStatus) +{ + Hlink *This = HLINK_THIS(iface); + FIXME("(%p)->(%p)\n", This, pdwStatus); + return E_NOTIMPL; +} + +static HRESULT WINAPI Hlink_Navigate(IHlink *iface, DWORD grfHLNF, LPBC pibc, + IBindStatusCallback *pibsc, IHlinkBrowseContext *pihlbc) +{ + Hlink *This = HLINK_THIS(iface); + FIXME("(%p)->(%08lx %p %p %p)\n", This, grfHLNF, pibc, pibsc, pihlbc); + return E_NOTIMPL; +} + +static HRESULT WINAPI Hlink_SetAdditionalParams(IHlink *iface, LPCWSTR pwzAdditionalParams) +{ + Hlink *This = HLINK_THIS(iface); + FIXME("(%p)->(%s)\n", This, debugstr_w(pwzAdditionalParams)); + return E_NOTIMPL; +} + +static HRESULT WINAPI Hlink_GetAdditionalParams(IHlink *iface, LPWSTR *ppwzAdditionalParams) +{ + Hlink *This = HLINK_THIS(iface); + FIXME("(%p)->(%p)\n", This, ppwzAdditionalParams); + return E_NOTIMPL; +} + +#undef HLINK_THIS + +static const IHlinkVtbl HlinkVtbl = { + Hlink_QueryInterface, + Hlink_AddRef, + Hlink_Release, + Hlink_SetHlinkSite, + Hlink_GetHlinkSite, + Hlink_SetMonikerReference, + Hlink_GetMonikerReference, + Hlink_SetStringReference, + Hlink_GetStringReference, + Hlink_SetFriendlyName, + Hlink_GetFriendlyName, + Hlink_SetTargetFrameName, + Hlink_GetTargetFrameName, + Hlink_GetMiscStatus, + Hlink_Navigate, + Hlink_SetAdditionalParams, + Hlink_GetAdditionalParams +}; + +IHlink *Hlink_Create(void) +{ + Hlink *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(Hlink)); + + ret->lpHlinkVtbl = &HlinkVtbl; + ret->ref = 1; + ret->mon = NULL; + ret->location = NULL; + + return HLINK(ret); +} diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index a4ab36fabf9..dea2b9613bf 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -147,6 +147,8 @@ void close_gecko(void); void register_nsservice(nsIComponentRegistrar*); void init_nsio(nsIComponentManager*,nsIComponentRegistrar*); +void hlink_frame_navigate(NSContainer*,IHlinkFrame*,LPCWSTR,nsIInputStream*); + nsIURI *get_nsIURI(LPCWSTR); nsACString *nsACString_Create(void); @@ -154,6 +156,8 @@ PRUint32 nsACString_GetData(const nsACString*,const char**,PRBool*); void nsACString_SetData(nsACString*,const char*); void nsACString_Destroy(nsACString*); +IHlink *Hlink_Create(void); + DEFINE_GUID(CLSID_AboutProtocol, 0x3050F406, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B); DEFINE_GUID(CLSID_JSProtocol, 0x3050F3B2, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B); DEFINE_GUID(CLSID_MailtoProtocol, 0x3050F3DA, 0x98B5, 0x11CF, 0xBB,0x82, 0x00,0xAA,0x00,0xBD,0xCE,0x0B); diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c new file mode 100644 index 00000000000..f2367ea83f2 --- /dev/null +++ b/dlls/mshtml/navigate.c @@ -0,0 +1,496 @@ +/* + * Copyright 2006 Jacek Caban for CodeWeavers + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "config.h" + +#include +#include + +#define COBJMACROS +#define NONAMELESSUNION +#define NONAMELESSSTRUCT + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "ole2.h" + +#include "wine/debug.h" +#include "wine/unicode.h" + +#include "mshtml_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mshtml); + +#define CONTENT_LENGTH "Content-Length" + +#define STATUSCLB_THIS(iface) DEFINE_THIS(BSCallback, BindStatusCallback, iface) + +typedef struct { + const IBindStatusCallbackVtbl *lpBindStatusCallbackVtbl; + const IServiceProviderVtbl *lpServiceProviderVtbl; + const IHttpNegotiate2Vtbl *lpHttpNegotiate2Vtbl; + const IInternetBindInfoVtbl *lpInternetBindInfoVtbl; + + LONG ref; + + LPWSTR headers; + HGLOBAL post_data; + ULONG post_data_len; +} BSCallback; + +#define HTTPNEG(x) ((IHttpNegotiate2*) &(x)->lpHttpNegotiate2Vtbl) +#define BINDINFO(x) ((IInternetBindInfo*) &(x)->lpInternetBindInfoVtbl); + +static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface, + REFIID riid, void **ppv) +{ + BSCallback *This = STATUSCLB_THIS(iface); + + *ppv = NULL; + if(IsEqualGUID(&IID_IUnknown, riid)) { + TRACE("(%p)->(IID_IUnknown, %p)\n", This, ppv); + *ppv = STATUSCLB(This); + }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) { + TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This, ppv); + *ppv = STATUSCLB(This); + }else if(IsEqualGUID(&IID_IServiceProvider, riid)) { + TRACE("(%p)->(IID_IServiceProvider %p)\n", This, ppv); + *ppv = SERVPROV(This); + }else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) { + TRACE("(%p)->(IID_IHttpNegotiate %p)\n", This, ppv); + *ppv = HTTPNEG(This); + }else if(IsEqualGUID(&IID_IHttpNegotiate2, riid)) { + TRACE("(%p)->(IID_IHttpNegotiate2 %p)\n", This, ppv); + *ppv = HTTPNEG(This); + }else if(IsEqualGUID(&IID_IInternetBindInfo, riid)) { + TRACE("(%p)->(IID_IInternetBindInfo %p)\n", This, ppv); + *ppv = BINDINFO(This); + } + + if(*ppv) { + IBindStatusCallback_AddRef(STATUSCLB(This)); + return S_OK; + } + + TRACE("Unsupported riid = %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface) +{ + BSCallback *This = STATUSCLB_THIS(iface); + LONG ref = InterlockedIncrement(&This->ref); + + TRACE("(%p) ref = %ld\n", This, ref); + + return ref; +} + +static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface) +{ + BSCallback *This = STATUSCLB_THIS(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref = %ld\n", This, ref); + + if(!ref) { + if(This->post_data) + GlobalFree(This->post_data); + HeapFree(GetProcessHeap(), 0, This->headers); + HeapFree(GetProcessHeap(), 0, This); + } + + return ref; +} + +static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, + DWORD dwReserved, IBinding *pbind) +{ + BSCallback *This = STATUSCLB_THIS(iface); + FIXME("(%p)->(%ld %p)\n", This, dwReserved, pbind); + return E_NOTIMPL; +} + +static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority) +{ + BSCallback *This = STATUSCLB_THIS(iface); + FIXME("(%p)->(%p)\n", This, pnPriority); + return E_NOTIMPL; +} + +static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved) +{ + BSCallback *This = STATUSCLB_THIS(iface); + FIXME("(%p)->(%ld)\n", This, reserved); + return E_NOTIMPL; +} + +static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress, + ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) +{ + BSCallback *This = STATUSCLB_THIS(iface); + TRACE("%p)->(%lu %lu %lu %s)\n", This, ulProgress, ulProgressMax, ulStatusCode, + debugstr_w(szStatusText)); + return S_OK; +} + +static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, + HRESULT hresult, LPCWSTR szError) +{ + BSCallback *This = STATUSCLB_THIS(iface); + FIXME("(%p)->(%08lx %s)\n", This, hresult, debugstr_w(szError)); + return E_NOTIMPL; +} + +static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, + DWORD *grfBINDF, BINDINFO *pbindinfo) +{ + BSCallback *This = STATUSCLB_THIS(iface); + DWORD size; + + TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo); + + *grfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE | BINDF_PULLDATA; + + size = pbindinfo->cbSize; + memset(pbindinfo, 0, size); + pbindinfo->cbSize = size; + + pbindinfo->cbStgmedData = This->post_data_len; + pbindinfo->dwCodePage = CP_UTF8; + pbindinfo->dwOptions = 0x00020000; + + if(This->post_data) { + pbindinfo->dwBindVerb = BINDVERB_POST; + + pbindinfo->stgmedData.tymed = TYMED_HGLOBAL; + pbindinfo->stgmedData.u.hGlobal = This->post_data; + pbindinfo->stgmedData.pUnkForRelease = (IUnknown*)STATUSCLB(This); + IBindStatusCallback_AddRef(STATUSCLB(This)); + } + + return S_OK; +} + +static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, + DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed) +{ + BSCallback *This = STATUSCLB_THIS(iface); + FIXME("(%p)->(%08lx %ld %p %p)\n", This, grfBSCF, dwSize, pformatetc, pstgmed); + return E_NOTIMPL; +} + +static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, + REFIID riid, IUnknown *punk) +{ + BSCallback *This = STATUSCLB_THIS(iface); + FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), punk); + return E_NOTIMPL; +} + +#undef STATUSCLB_THIS + +static const IBindStatusCallbackVtbl BindStatusCallbackVtbl = { + BindStatusCallback_QueryInterface, + BindStatusCallback_AddRef, + BindStatusCallback_Release, + BindStatusCallback_OnStartBinding, + BindStatusCallback_GetPriority, + BindStatusCallback_OnLowResource, + BindStatusCallback_OnProgress, + BindStatusCallback_OnStopBinding, + BindStatusCallback_GetBindInfo, + BindStatusCallback_OnDataAvailable, + BindStatusCallback_OnObjectAvailable +}; + +#define HTTPNEG_THIS(iface) DEFINE_THIS(BSCallback, HttpNegotiate2, iface) + +static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate2 *iface, + REFIID riid, void **ppv) +{ + BSCallback *This = HTTPNEG_THIS(iface); + return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv); +} + +static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate2 *iface) +{ + BSCallback *This = HTTPNEG_THIS(iface); + return IBindStatusCallback_AddRef(STATUSCLB(This)); +} + +static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate2 *iface) +{ + BSCallback *This = HTTPNEG_THIS(iface); + return IBindStatusCallback_Release(STATUSCLB(This)); +} + +static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate2 *iface, + LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders) +{ + BSCallback *This = HTTPNEG_THIS(iface); + DWORD size; + + TRACE("(%p)->(%s %s %ld %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders), + dwReserved, pszAdditionalHeaders); + + if(!This->headers) { + *pszAdditionalHeaders = NULL; + return S_OK; + } + + size = (strlenW(This->headers)+1)*sizeof(WCHAR); + *pszAdditionalHeaders = CoTaskMemAlloc(size); + memcpy(*pszAdditionalHeaders, This->headers, size); + + return S_OK; +} + +static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwResponseCode, + LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders) +{ + BSCallback *This = HTTPNEG_THIS(iface); + FIXME("(%p)->(%ld %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders), + debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders); + return E_NOTIMPL; +} + +static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface, + BYTE *pbSecurityId, DWORD *pcbSecurityId, DWORD_PTR dwReserved) +{ + BSCallback *This = HTTPNEG_THIS(iface); + FIXME("(%p)->(%p %p %ld)\n", This, pbSecurityId, pcbSecurityId, dwReserved); + return E_NOTIMPL; +} + +#undef HTTPNEG + +static const IHttpNegotiate2Vtbl HttpNegotiate2Vtbl = { + HttpNegotiate_QueryInterface, + HttpNegotiate_AddRef, + HttpNegotiate_Release, + HttpNegotiate_BeginningTransaction, + HttpNegotiate_OnResponse, + HttpNegotiate_GetRootSecurityId +}; + +#define BINDINFO_THIS(iface) DEFINE_THIS(BSCallback, InternetBindInfo, iface) + +static HRESULT WINAPI InternetBindInfo_QueryInterface(IInternetBindInfo *iface, + REFIID riid, void **ppv) +{ + BSCallback *This = BINDINFO_THIS(iface); + return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv); +} + +static ULONG WINAPI InternetBindInfo_AddRef(IInternetBindInfo *iface) +{ + BSCallback *This = BINDINFO_THIS(iface); + return IBindStatusCallback_AddRef(STATUSCLB(This)); +} + +static ULONG WINAPI InternetBindInfo_Release(IInternetBindInfo *iface) +{ + BSCallback *This = BINDINFO_THIS(iface); + return IBindStatusCallback_Release(STATUSCLB(This)); +} + +static HRESULT WINAPI InternetBindInfo_GetBindInfo(IInternetBindInfo *iface, + DWORD *grfBINDF, BINDINFO *pbindinfo) +{ + BSCallback *This = BINDINFO_THIS(iface); + FIXME("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo); + return E_NOTIMPL; +} + +static HRESULT WINAPI InternetBindInfo_GetBindString(IInternetBindInfo *iface, + ULONG ulStringType, LPOLESTR *ppwzStr, ULONG cEl, ULONG *pcElFetched) +{ + BSCallback *This = BINDINFO_THIS(iface); + FIXME("(%p)->(%lu %p %lu %p)\n", This, ulStringType, ppwzStr, cEl, pcElFetched); + return E_NOTIMPL; +} + +#undef BINDINFO_THIS + +static const IInternetBindInfoVtbl InternetBindInfoVtbl = { + InternetBindInfo_QueryInterface, + InternetBindInfo_AddRef, + InternetBindInfo_Release, + InternetBindInfo_GetBindInfo, + InternetBindInfo_GetBindString +}; + +#define SERVPROV_THIS(iface) DEFINE_THIS(BSCallback, ServiceProvider, iface) + +static HRESULT WINAPI BSCServiceProvider_QueryInterface(IServiceProvider *iface, + REFIID riid, void **ppv) +{ + BSCallback *This = SERVPROV_THIS(iface); + return IBindStatusCallback_QueryInterface(STATUSCLB(This), riid, ppv); +} + +static ULONG WINAPI BSCServiceProvider_AddRef(IServiceProvider *iface) +{ + BSCallback *This = SERVPROV_THIS(iface); + return IBindStatusCallback_AddRef(STATUSCLB(This)); +} + +static ULONG WINAPI BSCServiceProvider_Release(IServiceProvider *iface) +{ + BSCallback *This = SERVPROV_THIS(iface); + return IBindStatusCallback_Release(STATUSCLB(This)); +} + +static HRESULT WINAPI BSCServiceProvider_QueryService(IServiceProvider *iface, + REFGUID guidService, REFIID riid, void **ppv) +{ + BSCallback *This = SERVPROV_THIS(iface); + FIXME("(%p)->(%s %s %p)\n", This, debugstr_guid(guidService), debugstr_guid(riid), ppv); + return E_NOTIMPL; +} + +#undef SERVPROV_THIS + +static const IServiceProviderVtbl ServiceProviderVtbl = { + BSCServiceProvider_QueryInterface, + BSCServiceProvider_AddRef, + BSCServiceProvider_Release, + BSCServiceProvider_QueryService +}; + +static IBindStatusCallback *BSCallback_Create(HTMLDocument *doc, LPCOLESTR url, + HGLOBAL post_data, ULONG post_data_len, LPWSTR headers) +{ + BSCallback *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(BSCallback)); + + ret->lpBindStatusCallbackVtbl = &BindStatusCallbackVtbl; + ret->lpServiceProviderVtbl = &ServiceProviderVtbl; + ret->lpHttpNegotiate2Vtbl = &HttpNegotiate2Vtbl; + ret->lpInternetBindInfoVtbl = &InternetBindInfoVtbl; + ret->ref = 1; + ret->post_data = post_data; + ret->headers = headers; + ret->post_data_len = post_data_len; + + return STATUSCLB(ret); +} + +static void parse_post_data(nsIInputStream *post_data_stream, LPWSTR *headers_ret, + HGLOBAL *post_data_ret, ULONG *post_data_len_ret) +{ + PRUint32 post_data_len = 0, available = 0; + HGLOBAL post_data = NULL; + LPWSTR headers = NULL; + DWORD headers_len = 0, len; + const char *ptr, *ptr2; + + nsIInputStream_Available(post_data_stream, &available); + post_data = GlobalAlloc(0, available+1); + nsIInputStream_Read(post_data_stream, post_data, available, &post_data_len); + + ptr = ptr2 = post_data; + + while(*ptr && (*ptr != '\r' || ptr[1] != '\n')) { + while(*ptr && (*ptr != '\r' || ptr[1] != '\n')) + ptr++; + + if(!*ptr) { + FIXME("*ptr = 0\n"); + return; + } + + ptr += 2; + + if(ptr-ptr2 >= sizeof(CONTENT_LENGTH) + && CompareStringA(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, + CONTENT_LENGTH, sizeof(CONTENT_LENGTH)-1, + ptr2, sizeof(CONTENT_LENGTH)-1) == CSTR_EQUAL) { + ptr2 = ptr; + continue; + } + + len = MultiByteToWideChar(CP_ACP, 0, ptr2, ptr-ptr2, NULL, 0); + + if(headers) + headers = HeapReAlloc(GetProcessHeap(), 0, headers, + (headers_len+len+1)*sizeof(WCHAR)); + else + headers = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR)); + + len = MultiByteToWideChar(CP_ACP, 0, ptr2, ptr-ptr2, headers+headers_len, -1); + headers_len += len; + + ptr2 = ptr; + } + + headers[headers_len] = 0; + *headers_ret = headers; + + if(*ptr) + ptr += 2; + + if(!*ptr || !(ptr-(const char*)post_data)) { + GlobalFree(post_data); + return; + } + + if(headers_len) { + memmove(post_data, ptr, ptr-(const char*)post_data); + post_data_len -= ptr-(const char*)post_data; + post_data = GlobalReAlloc(post_data, post_data_len+1, 0); + } + + *((PBYTE)post_data+post_data_len) = 0; + + *post_data_ret = post_data; + *post_data_len_ret = post_data_len+1; +} + +void hlink_frame_navigate(NSContainer *container, IHlinkFrame *hlink_frame, + LPCWSTR uri, nsIInputStream *post_data_stream) +{ + IBindStatusCallback *callback; + IBindCtx *bindctx; + IMoniker *mon; + IHlink *hlink; + PRUint32 post_data_len = 0; + HGLOBAL post_data = NULL; + LPWSTR headers = NULL; + + if(post_data_stream) { + parse_post_data(post_data_stream, &headers, &post_data, &post_data_len); + TRACE("%s %s\n", debugstr_w(headers), debugstr_a(post_data)); + } + + callback = BSCallback_Create(container->doc, uri, post_data, post_data_len, headers); + CreateAsyncBindCtx(0, callback, NULL, &bindctx); + + hlink = Hlink_Create(); + + CreateURLMoniker(NULL, uri, &mon); + IHlink_SetMonikerReference(hlink, 0, mon, NULL); + + IHlinkFrame_Navigate(hlink_frame, 0, bindctx, callback, hlink); + + IBindCtx_Release(bindctx); + IBindStatusCallback_Release(callback); + IMoniker_Release(mon); + +} diff --git a/dlls/mshtml/nsio.c b/dlls/mshtml/nsio.c index 70b62472764..190ddd694a6 100644 --- a/dlls/mshtml/nsio.c +++ b/dlls/mshtml/nsio.c @@ -99,6 +99,34 @@ static BOOL exec_shldocvw_67(NSContainer *container, LPCWSTR url) return TRUE; } +static BOOL handle_uri(NSContainer *container, nsChannel *channel, LPCWSTR uri) +{ + IServiceProvider *service_provider; + HRESULT hres; + + if(!exec_shldocvw_67(container, uri)) + return FALSE; + + hres = IOleClientSite_QueryInterface(container->doc->client, &IID_IServiceProvider, + (void**)&service_provider); + if(SUCCEEDED(hres)) { + IHlinkFrame *hlink_frame; + + hres = IServiceProvider_QueryService(service_provider, &IID_IHlinkFrame, + &IID_IHlinkFrame, (void**)&hlink_frame); + if(SUCCEEDED(hres)) { + hlink_frame_navigate(container, hlink_frame, uri, channel->post_data_stream); + IHlinkFrame_Release(hlink_frame); + + return FALSE; + } + + IServiceProvider_Release(service_provider); + } + + return TRUE; +} + static BOOL before_async_open(nsChannel *This) { nsACString *uri_str; @@ -107,7 +135,7 @@ static BOOL before_async_open(nsChannel *This) const char *uria; LPWSTR uri; DWORD len; - BOOL ret = TRUE; + BOOL ret; nsIChannel_GetLoadFlags(This->channel, &load_flags); TRACE("load_flags = %08lx\n", load_flags); @@ -133,7 +161,7 @@ static BOOL before_async_open(nsChannel *This) MultiByteToWideChar(CP_ACP, 0, uria, -1, uri, len); nsACString_Destroy(uri_str); - ret = exec_shldocvw_67(container, uri); + ret = handle_uri(container, This, uri); nsIWebBrowserChrome_Release(NSWBCHROME(container)); HeapFree(GetProcessHeap(), 0, uri); @@ -710,8 +738,6 @@ static const nsIHttpChannelVtbl nsChannelVtbl = { nsChannel_IsNoCacheResponse }; -#define NSURI_THIS(iface) DEFINE_THIS(nsURI, WineURI, iface) - #define NSUPCHANNEL_THIS(iface) DEFINE_THIS(nsChannel, UploadChannel, iface) static nsresult NSAPI nsUploadChannel_QueryInterface(nsIUploadChannel *iface, nsIIDRef riid, @@ -784,6 +810,8 @@ static const nsIUploadChannelVtbl nsUploadChannelVtbl = { nsUploadChannel_GetUploadStream }; +#define NSURI_THIS(iface) DEFINE_THIS(nsURI, WineURI, iface) + static nsresult NSAPI nsURI_QueryInterface(nsIWineURI *iface, nsIIDRef riid, nsQIResult result) { nsURI *This = NSURI_THIS(iface);