2 * Copyright 2005 Jacek Caban
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
37 #include "mshtml_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
41 struct BindStatusCallback
{
42 const IBindStatusCallbackVtbl
*lpBindStatusCallbackVtbl
;
52 #define STATUSCLB_THIS(iface) DEFINE_THIS(BindStatusCallback, BindStatusCallback, iface)
54 static HRESULT WINAPI
BindStatusCallback_QueryInterface(IBindStatusCallback
*iface
,
55 REFIID riid
, void **ppv
)
57 BindStatusCallback
*This
= STATUSCLB_THIS(iface
);
60 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
61 TRACE("(%p)->(IID_IUnknown, %p)\n", This
, ppv
);
62 *ppv
= STATUSCLB(This
);
63 }else if(IsEqualGUID(&IID_IBindStatusCallback
, riid
)) {
64 TRACE("(%p)->(IID_IBindStatusCallback, %p)\n", This
, ppv
);
65 *ppv
= STATUSCLB(This
);
69 IBindStatusCallback_AddRef(STATUSCLB(This
));
73 TRACE("Unsupported riid = %s\n", debugstr_guid(riid
));
77 static ULONG WINAPI
BindStatusCallback_AddRef(IBindStatusCallback
*iface
)
79 BindStatusCallback
*This
= STATUSCLB_THIS(iface
);
80 LONG ref
= InterlockedIncrement(&This
->ref
);
82 TRACE("(%p) ref = %ld\n", This
, ref
);
87 static ULONG WINAPI
BindStatusCallback_Release(IBindStatusCallback
*iface
)
89 BindStatusCallback
*This
= STATUSCLB_THIS(iface
);
90 LONG ref
= InterlockedDecrement(&This
->ref
);
92 TRACE("(%p) ref = %ld\n", This
, ref
);
95 if(This
->doc
->status_callback
== This
)
96 This
->doc
->status_callback
= NULL
;
97 IHTMLDocument2_Release(HTMLDOC(This
->doc
));
99 IStream_Release(This
->stream
);
100 CoTaskMemFree(This
->url
);
101 HeapFree(GetProcessHeap(), 0, This
);
107 static HRESULT WINAPI
BindStatusCallback_OnStartBinding(IBindStatusCallback
*iface
,
108 DWORD dwReserved
, IBinding
*pbind
)
110 BindStatusCallback
*This
= STATUSCLB_THIS(iface
);
112 TRACE("(%p)->(%ld %p)\n", This
, dwReserved
, pbind
);
114 This
->binding
= pbind
;
115 IBinding_AddRef(pbind
);
117 if(This
->doc
->nscontainer
&& This
->doc
->nscontainer
->stream
) {
118 nsACString strTextHtml
;
120 nsIURI
*uri
= get_nsIURI(This
->url
);
122 /* FIXME: Set it correctly */
123 nsACString_Init(&strTextHtml
, "text/html");
125 nsres
= nsIWebBrowserStream_OpenStream(This
->doc
->nscontainer
->stream
, uri
, &strTextHtml
);
127 ERR("OpenStream failed: %08lx\n", nsres
);
129 nsACString_Finish(&strTextHtml
);
136 static HRESULT WINAPI
BindStatusCallback_GetPriority(IBindStatusCallback
*iface
, LONG
*pnPriority
)
138 BindStatusCallback
*This
= STATUSCLB_THIS(iface
);
139 FIXME("(%p)->(%p)\n", This
, pnPriority
);
143 static HRESULT WINAPI
BindStatusCallback_OnLowResource(IBindStatusCallback
*iface
, DWORD reserved
)
145 BindStatusCallback
*This
= STATUSCLB_THIS(iface
);
146 FIXME("(%p)->(%ld)\n", This
, reserved
);
150 static HRESULT WINAPI
BindStatusCallback_OnProgress(IBindStatusCallback
*iface
, ULONG ulProgress
,
151 ULONG ulProgressMax
, ULONG ulStatusCode
, LPCWSTR szStatusText
)
153 BindStatusCallback
*This
= STATUSCLB_THIS(iface
);
154 TRACE("%p)->(%lu %lu %lu %s)\n", This
, ulProgress
, ulProgressMax
, ulStatusCode
,
155 debugstr_w(szStatusText
));
159 static HRESULT WINAPI
BindStatusCallback_OnStopBinding(IBindStatusCallback
*iface
,
160 HRESULT hresult
, LPCWSTR szError
)
162 BindStatusCallback
*This
= STATUSCLB_THIS(iface
);
164 TRACE("(%p)->(%08lx %s)\n", This
, hresult
, debugstr_w(szError
));
166 if(This
->doc
->nscontainer
&& This
->doc
->nscontainer
->stream
)
167 nsIWebBrowserStream_CloseStream(This
->doc
->nscontainer
->stream
);
169 IBinding_Release(This
->binding
);
170 This
->binding
= NULL
;
174 static HRESULT WINAPI
BindStatusCallback_GetBindInfo(IBindStatusCallback
*iface
,
175 DWORD
*grfBINDF
, BINDINFO
*pbindinfo
)
177 BindStatusCallback
*This
= STATUSCLB_THIS(iface
);
180 TRACE("(%p)->(%p %p)\n", This
, grfBINDF
, pbindinfo
);
182 *grfBINDF
= BINDF_ASYNCHRONOUS
| BINDF_ASYNCSTORAGE
| BINDF_PULLDATA
;
183 size
= pbindinfo
->cbSize
;
184 memset(pbindinfo
, 0, size
);
185 pbindinfo
->cbSize
= size
;
190 static HRESULT WINAPI
BindStatusCallback_OnDataAvailable(IBindStatusCallback
*iface
,
191 DWORD grfBSCF
, DWORD dwSize
, FORMATETC
*pformatetc
, STGMEDIUM
*pstgmed
)
193 BindStatusCallback
*This
= STATUSCLB_THIS(iface
);
195 TRACE("(%p)->(%08lx %ld %p %p)\n", This
, grfBSCF
, dwSize
, pformatetc
, pstgmed
);
198 This
->stream
= pstgmed
->u
.pstm
;
199 IStream_AddRef(This
->stream
);
202 if(This
->doc
->nscontainer
&& This
->doc
->nscontainer
->stream
) {
209 hres
= IStream_Read(This
->stream
, buf
, size
, &size
);
210 nsIWebBrowserStream_AppendToStream(This
->doc
->nscontainer
->stream
, buf
, size
);
211 }while(hres
== S_OK
);
217 static HRESULT WINAPI
BindStatusCallback_OnObjectAvailable(IBindStatusCallback
*iface
,
218 REFIID riid
, IUnknown
*punk
)
220 BindStatusCallback
*This
= STATUSCLB_THIS(iface
);
221 FIXME("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), punk
);
225 #undef STATUSCLB_THIS
227 static const IBindStatusCallbackVtbl BindStatusCallbackVtbl
= {
228 BindStatusCallback_QueryInterface
,
229 BindStatusCallback_AddRef
,
230 BindStatusCallback_Release
,
231 BindStatusCallback_OnStartBinding
,
232 BindStatusCallback_GetPriority
,
233 BindStatusCallback_OnLowResource
,
234 BindStatusCallback_OnProgress
,
235 BindStatusCallback_OnStopBinding
,
236 BindStatusCallback_GetBindInfo
,
237 BindStatusCallback_OnDataAvailable
,
238 BindStatusCallback_OnObjectAvailable
241 static BindStatusCallback
*BindStatusCallback_Create(HTMLDocument
*doc
, LPOLESTR url
)
243 BindStatusCallback
*ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(BindStatusCallback
));
245 ret
->lpBindStatusCallbackVtbl
= &BindStatusCallbackVtbl
;
250 IHTMLDocument2_AddRef(HTMLDOC(doc
));
255 /**********************************************************
256 * IPersistMoniker implementation
259 #define PERSISTMON_THIS(iface) DEFINE_THIS(HTMLDocument, PersistMoniker, iface)
261 static HRESULT WINAPI
PersistMoniker_QueryInterface(IPersistMoniker
*iface
, REFIID riid
,
264 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
265 return IHTMLDocument2_QueryInterface(HTMLDOC(This
), riid
, ppvObject
);
268 static ULONG WINAPI
PersistMoniker_AddRef(IPersistMoniker
*iface
)
270 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
271 return IHTMLDocument2_AddRef(HTMLDOC(This
));
274 static ULONG WINAPI
PersistMoniker_Release(IPersistMoniker
*iface
)
276 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
277 return IHTMLDocument2_Release(HTMLDOC(This
));
280 static HRESULT WINAPI
PersistMoniker_GetClassID(IPersistMoniker
*iface
, CLSID
*pClassID
)
282 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
283 return IPersist_GetClassID(PERSIST(This
), pClassID
);
286 static HRESULT WINAPI
PersistMoniker_IsDirty(IPersistMoniker
*iface
)
288 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
289 FIXME("(%p)\n", This
);
293 static nsIInputStream
*get_post_data_stream(IBindCtx
*bctx
)
295 nsIInputStream
*ret
= NULL
;
296 IBindStatusCallback
*callback
;
297 IHttpNegotiate
*http_negotiate
;
300 DWORD post_len
= 0, headers_len
= 0;
301 LPWSTR headers
= NULL
;
302 WCHAR emptystr
[] = {0};
306 static WCHAR _BSCB_Holder_
[] =
307 {'_','B','S','C','B','_','H','o','l','d','e','r','_',0};
310 /* FIXME: This should be done in URLMoniker */
314 hres
= IBindCtx_GetObjectParam(bctx
, _BSCB_Holder_
, (IUnknown
**)&callback
);
318 hres
= IBindStatusCallback_QueryInterface(callback
, &IID_IHttpNegotiate
,
319 (void**)&http_negotiate
);
320 if(SUCCEEDED(hres
)) {
321 hres
= IHttpNegotiate_BeginningTransaction(http_negotiate
, emptystr
,
322 emptystr
, 0, &headers
);
323 IHttpNegotiate_Release(http_negotiate
);
325 if(SUCCEEDED(hres
) && headers
)
326 headers_len
= WideCharToMultiByte(CP_ACP
, 0, headers
, -1, NULL
, 0, NULL
, NULL
);
329 memset(&bindinfo
, 0, sizeof(bindinfo
));
330 bindinfo
.cbSize
= sizeof(bindinfo
);
332 hres
= IBindStatusCallback_GetBindInfo(callback
, &bindf
, &bindinfo
);
334 if(SUCCEEDED(hres
) && bindinfo
.dwBindVerb
== BINDVERB_POST
)
335 post_len
= bindinfo
.cbStgmedData
;
337 if(headers_len
|| post_len
) {
338 int len
= headers_len
? headers_len
-1 : 0;
340 static const char content_length
[] = "Content-Length: %lu\r\n\r\n";
342 data
= HeapAlloc(GetProcessHeap(), 0, headers_len
+post_len
+sizeof(content_length
)+8);
345 WideCharToMultiByte(CP_ACP
, 0, headers
, -1, data
, -1, NULL
, NULL
);
346 CoTaskMemFree(headers
);
350 sprintf(data
+len
, content_length
, post_len
);
353 memcpy(data
+len
, bindinfo
.stgmedData
.u
.hGlobal
, post_len
);
356 TRACE("data = %s\n", debugstr_an(data
, len
+post_len
));
358 ret
= create_nsstream(data
, len
+post_len
);
361 ReleaseBindInfo(&bindinfo
);
362 IBindStatusCallback_Release(callback
);
367 static HRESULT WINAPI
PersistMoniker_Load(IPersistMoniker
*iface
, BOOL fFullyAvailable
,
368 IMoniker
*pimkName
, LPBC pibc
, DWORD grfMode
)
370 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
372 BindStatusCallback
*callback
;
378 TRACE("(%p)->(%x %p %p %08lx)\n", This
, fFullyAvailable
, pimkName
, pibc
, grfMode
);
381 IUnknown
*unk
= NULL
;
385 * "__PrecreatedObject"
386 * "BIND_CONTEXT_PARAM"
387 * "__HTMLLOADOPTIONS"
391 * "_ITransData_Object_"
395 IBindCtx_GetObjectParam(pibc
, (LPOLESTR
)SZ_HTML_CLIENTSITE_OBJECTPARAM
, &unk
);
397 IOleClientSite
*client
= NULL
;
399 hres
= IUnknown_QueryInterface(unk
, &IID_IOleClientSite
, (void**)&client
);
400 if(SUCCEEDED(hres
)) {
401 TRACE("Got client site %p\n", client
);
402 IOleObject_SetClientSite(OLEOBJ(This
), client
);
403 IOleClientSite_Release(client
);
406 IUnknown_Release(unk
);
410 HTMLDocument_LockContainer(This
, TRUE
);
412 hres
= IMoniker_GetDisplayName(pimkName
, pibc
, NULL
, &url
);
414 WARN("GetDiaplayName failed: %08lx\n", hres
);
418 TRACE("got url: %s\n", debugstr_w(url
));
421 IOleCommandTarget
*cmdtrg
= NULL
;
423 hres
= IOleClientSite_QueryInterface(This
->client
, &IID_IOleCommandTarget
,
425 if(SUCCEEDED(hres
)) {
430 IOleCommandTarget_Exec(cmdtrg
, &CGID_ShellDocView
, 37, 0, &var
, NULL
);
434 if(This
->nscontainer
&& !This
->nscontainer
->stream
) {
436 * This is a workaround for older Gecko that doesn't support nsIWebBrowserStream.
437 * It uses Gecko's LoadURI instead of IMoniker's BindToStorage. Should we improve
438 * it (to do so we'd have to use not frozen interfaces)?
441 nsIInputStream
*post_data_stream
= get_post_data_stream(pibc
);
443 This
->nscontainer
->load_call
= TRUE
;
444 nsres
= nsIWebNavigation_LoadURI(This
->nscontainer
->navigation
, url
,
445 LOAD_FLAGS_NONE
, NULL
, post_data_stream
, NULL
);
446 This
->nscontainer
->load_call
= FALSE
;
449 nsIInputStream_Release(post_data_stream
);
451 if(NS_SUCCEEDED(nsres
)) {
455 WARN("LoadURI failed: %08lx\n", nsres
);
459 /* FIXME: Use grfMode */
462 FIXME("not supported fFullyAvailable\n");
464 if(This
->status_callback
&& This
->status_callback
->binding
)
465 IBinding_Abort(This
->status_callback
->binding
);
467 callback
= This
->status_callback
= BindStatusCallback_Create(This
, url
);
471 RegisterBindStatusCallback(pbind
, STATUSCLB(callback
), NULL
, 0);
473 CreateAsyncBindCtx(0, STATUSCLB(callback
), NULL
, &pbind
);
476 hres
= IMoniker_BindToStorage(pimkName
, pbind
, NULL
, &IID_IStream
, (void**)&str
);
479 IBindCtx_Release(pbind
);
481 IStream_Release(str
);
483 WARN("BindToStorage failed: %08lx\n", hres
);
490 static HRESULT WINAPI
PersistMoniker_Save(IPersistMoniker
*iface
, IMoniker
*pimkName
,
491 LPBC pbc
, BOOL fRemember
)
493 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
494 FIXME("(%p)->(%p %p %x)\n", This
, pimkName
, pbc
, fRemember
);
498 static HRESULT WINAPI
PersistMoniker_SaveCompleted(IPersistMoniker
*iface
, IMoniker
*pimkName
, LPBC pibc
)
500 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
501 FIXME("(%p)->(%p %p)\n", This
, pimkName
, pibc
);
505 static HRESULT WINAPI
PersistMoniker_GetCurMoniker(IPersistMoniker
*iface
, IMoniker
**ppimkName
)
507 HTMLDocument
*This
= PERSISTMON_THIS(iface
);
508 FIXME("(%p)->(%p)\n", This
, ppimkName
);
512 static const IPersistMonikerVtbl PersistMonikerVtbl
= {
513 PersistMoniker_QueryInterface
,
514 PersistMoniker_AddRef
,
515 PersistMoniker_Release
,
516 PersistMoniker_GetClassID
,
517 PersistMoniker_IsDirty
,
520 PersistMoniker_SaveCompleted
,
521 PersistMoniker_GetCurMoniker
524 /**********************************************************
525 * IMonikerProp implementation
528 #define MONPROP_THIS(iface) DEFINE_THIS(HTMLDocument, MonikerProp, iface)
530 static HRESULT WINAPI
MonikerProp_QueryInterface(IMonikerProp
*iface
, REFIID riid
, void **ppvObject
)
532 HTMLDocument
*This
= MONPROP_THIS(iface
);
533 return IHTMLDocument2_QueryInterface(HTMLDOC(This
), riid
, ppvObject
);
536 static ULONG WINAPI
MonikerProp_AddRef(IMonikerProp
*iface
)
538 HTMLDocument
*This
= MONPROP_THIS(iface
);
539 return IHTMLDocument2_AddRef(HTMLDOC(This
));
542 static ULONG WINAPI
MonikerProp_Release(IMonikerProp
*iface
)
544 HTMLDocument
*This
= MONPROP_THIS(iface
);
545 return IHTMLDocument_Release(HTMLDOC(This
));
548 static HRESULT WINAPI
MonikerProp_PutProperty(IMonikerProp
*iface
, MONIKERPROPERTY mkp
, LPCWSTR val
)
550 HTMLDocument
*This
= MONPROP_THIS(iface
);
551 FIXME("(%p)->(%d %s)\n", This
, mkp
, debugstr_w(val
));
555 static const IMonikerPropVtbl MonikerPropVtbl
= {
556 MonikerProp_QueryInterface
,
559 MonikerProp_PutProperty
562 /**********************************************************
563 * IPersistFile implementation
566 #define PERSISTFILE_THIS(iface) DEFINE_THIS(HTMLDocument, PersistFile, iface)
568 static HRESULT WINAPI
PersistFile_QueryInterface(IPersistFile
*iface
, REFIID riid
, void **ppvObject
)
570 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
571 return IHTMLDocument2_QueryInterface(HTMLDOC(This
), riid
, ppvObject
);
574 static ULONG WINAPI
PersistFile_AddRef(IPersistFile
*iface
)
576 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
577 return IHTMLDocument2_AddRef(HTMLDOC(This
));
580 static ULONG WINAPI
PersistFile_Release(IPersistFile
*iface
)
582 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
583 return IHTMLDocument2_Release(HTMLDOC(This
));
586 static HRESULT WINAPI
PersistFile_GetClassID(IPersistFile
*iface
, CLSID
*pClassID
)
588 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
590 TRACE("(%p)->(%p)\n", This
, pClassID
);
595 memcpy(pClassID
, &CLSID_HTMLDocument
, sizeof(CLSID
));
599 static HRESULT WINAPI
PersistFile_IsDirty(IPersistFile
*iface
)
601 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
602 FIXME("(%p)\n", This
);
606 static HRESULT WINAPI
PersistFile_Load(IPersistFile
*iface
, LPCOLESTR pszFileName
, DWORD dwMode
)
608 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
609 FIXME("(%p)->(%s %08lx)\n", This
, debugstr_w(pszFileName
), dwMode
);
613 static HRESULT WINAPI
PersistFile_Save(IPersistFile
*iface
, LPCOLESTR pszFileName
, BOOL fRemember
)
615 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
616 FIXME("(%p)->(%s %x)\n", This
, debugstr_w(pszFileName
), fRemember
);
620 static HRESULT WINAPI
PersistFile_SaveCompleted(IPersistFile
*iface
, LPCOLESTR pszFileName
)
622 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
623 FIXME("(%p)->(%s)\n", This
, debugstr_w(pszFileName
));
627 static HRESULT WINAPI
PersistFile_GetCurFile(IPersistFile
*iface
, LPOLESTR
*pszFileName
)
629 HTMLDocument
*This
= PERSISTFILE_THIS(iface
);
630 FIXME("(%p)->(%p)\n", This
, pszFileName
);
634 static const IPersistFileVtbl PersistFileVtbl
= {
635 PersistFile_QueryInterface
,
638 PersistFile_GetClassID
,
642 PersistFile_SaveCompleted
,
643 PersistFile_GetCurFile
646 void HTMLDocument_Persist_Init(HTMLDocument
*This
)
648 This
->lpPersistMonikerVtbl
= &PersistMonikerVtbl
;
649 This
->lpPersistFileVtbl
= &PersistFileVtbl
;
650 This
->lpMonikerPropVtbl
= &MonikerPropVtbl
;
652 This
->status_callback
= NULL
;