mshtml: Added window global properties test.
[wine] / dlls / mshtml / persist.c
1 /*
2  * Copyright 2005 Jacek Caban
3  *
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.
8  *
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.
13  *
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
17  */
18
19 #include "config.h"
20
21 #include <stdarg.h>
22 #include <stdio.h>
23
24 #define COBJMACROS
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "ole2.h"
32 #include "shlguid.h"
33 #include "idispids.h"
34
35 #include "wine/debug.h"
36 #include "wine/unicode.h"
37
38 #include "mshtml_private.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
41
42 static BOOL use_gecko_script(LPCWSTR url)
43 {
44     static const WCHAR fileW[] = {'f','i','l','e',':'};
45     return strncmpiW(fileW, url, sizeof(fileW)/sizeof(WCHAR));
46 }
47
48 void set_current_mon(HTMLDocument *This, IMoniker *mon)
49 {
50     HRESULT hres;
51
52     if(This->mon) {
53         IMoniker_Release(This->mon);
54         This->mon = NULL;
55     }
56
57     if(This->url) {
58         CoTaskMemFree(This->url);
59         This->url = NULL;
60     }
61
62     if(!mon)
63         return;
64
65     IMoniker_AddRef(mon);
66     This->mon = mon;
67
68     hres = IMoniker_GetDisplayName(mon, NULL, NULL, &This->url);
69     if(FAILED(hres))
70         WARN("GetDisplayName failed: %08x\n", hres);
71
72     set_script_mode(This->window, use_gecko_script(This->url) ? SCRIPTMODE_GECKO : SCRIPTMODE_ACTIVESCRIPT);
73 }
74
75 static HRESULT set_moniker(HTMLDocument *This, IMoniker *mon, IBindCtx *pibc, BOOL *bind_complete)
76 {
77     nsChannelBSC *bscallback;
78     LPOLESTR url = NULL;
79     task_t *task;
80     HRESULT hres;
81     nsresult nsres;
82
83     if(pibc) {
84         IUnknown *unk = NULL;
85
86         /* FIXME:
87          * Use params:
88          * "__PrecreatedObject"
89          * "BIND_CONTEXT_PARAM"
90          * "__HTMLLOADOPTIONS"
91          * "__DWNBINDINFO"
92          * "URL Context"
93          * "CBinding Context"
94          * "_ITransData_Object_"
95          * "_EnumFORMATETC_"
96          */
97
98         IBindCtx_GetObjectParam(pibc, (LPOLESTR)SZ_HTML_CLIENTSITE_OBJECTPARAM, &unk);
99         if(unk) {
100             IOleClientSite *client = NULL;
101
102             hres = IUnknown_QueryInterface(unk, &IID_IOleClientSite, (void**)&client);
103             if(SUCCEEDED(hres)) {
104                 TRACE("Got client site %p\n", client);
105                 IOleObject_SetClientSite(OLEOBJ(This), client);
106                 IOleClientSite_Release(client);
107             }
108
109             IUnknown_Release(unk);
110         }
111     }
112
113     This->readystate = READYSTATE_LOADING;
114     call_property_onchanged(&This->cp_propnotif, DISPID_READYSTATE);
115     update_doc(This, UPDATE_TITLE);
116
117     HTMLDocument_LockContainer(This, TRUE);
118     
119     hres = IMoniker_GetDisplayName(mon, pibc, NULL, &url);
120     if(FAILED(hres)) {
121         WARN("GetDiaplayName failed: %08x\n", hres);
122         return hres;
123     }
124
125     TRACE("got url: %s\n", debugstr_w(url));
126
127     set_current_mon(This, mon);
128
129     if(This->client) {
130         VARIANT silent, offline;
131         IOleCommandTarget *cmdtrg = NULL;
132
133         hres = get_client_disp_property(This->client, DISPID_AMBIENT_SILENT, &silent);
134         if(SUCCEEDED(hres)) {
135             if(V_VT(&silent) != VT_BOOL)
136                 WARN("V_VT(silent) = %d\n", V_VT(&silent));
137             else if(V_BOOL(&silent))
138                 FIXME("silent == true\n");
139         }
140
141         hres = get_client_disp_property(This->client,
142                 DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, &offline);
143         if(SUCCEEDED(hres)) {
144             if(V_VT(&silent) != VT_BOOL)
145                 WARN("V_VT(offline) = %d\n", V_VT(&silent));
146             else if(V_BOOL(&silent))
147                 FIXME("offline == true\n");
148         }
149
150         hres = IOleClientSite_QueryInterface(This->client, &IID_IOleCommandTarget,
151                 (void**)&cmdtrg);
152         if(SUCCEEDED(hres)) {
153             VARIANT var;
154
155             V_VT(&var) = VT_I4;
156             V_I4(&var) = 0;
157             IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 37, 0, &var, NULL);
158
159             IOleCommandTarget_Release(cmdtrg);
160         }
161     }
162
163     bscallback = create_channelbsc(mon);
164
165     if(This->frame) {
166         task = heap_alloc(sizeof(task_t));
167
168         task->doc = This;
169         task->task_id = TASK_SETPROGRESS;
170         task->next = NULL;
171
172         push_task(task);
173     }
174
175     task = heap_alloc(sizeof(task_t));
176
177     task->doc = This;
178     task->task_id = TASK_SETDOWNLOADSTATE;
179     task->next = NULL;
180
181     push_task(task);
182
183     if(This->nscontainer) {
184         This->nscontainer->bscallback = bscallback;
185         nsres = nsIWebNavigation_LoadURI(This->nscontainer->navigation, url,
186                 LOAD_FLAGS_NONE, NULL, NULL, NULL);
187         This->nscontainer->bscallback = NULL;
188         if(NS_FAILED(nsres)) {
189             WARN("LoadURI failed: %08x\n", nsres);
190             IUnknown_Release((IUnknown*)bscallback);
191             CoTaskMemFree(url);
192             return E_FAIL;
193         }
194     }
195
196     set_document_bscallback(This, bscallback);
197     IUnknown_Release((IUnknown*)bscallback);
198     CoTaskMemFree(url);
199
200     if(bind_complete)
201         *bind_complete = FALSE;
202     return S_OK;
203 }
204
205 static HRESULT get_doc_string(HTMLDocument *This, char **str)
206 {
207     nsIDOMNode *nsnode;
208     LPCWSTR strw;
209     nsAString nsstr;
210     nsresult nsres;
211
212     if(!This->nsdoc) {
213         WARN("NULL nsdoc\n");
214         return E_UNEXPECTED;
215     }
216
217     nsres = nsIDOMHTMLDocument_QueryInterface(This->nsdoc, &IID_nsIDOMNode, (void**)&nsnode);
218     if(NS_FAILED(nsres)) {
219         ERR("Could not get nsIDOMNode failed: %08x\n", nsres);
220         return E_FAIL;
221     }
222
223     nsAString_Init(&nsstr, NULL);
224     nsnode_to_nsstring(nsnode, &nsstr);
225     nsIDOMNode_Release(nsnode);
226
227     nsAString_GetData(&nsstr, &strw);
228     TRACE("%s\n", debugstr_w(strw));
229
230     *str = heap_strdupWtoA(strw);
231
232     nsAString_Finish(&nsstr);
233
234     return S_OK;
235 }
236
237
238 /**********************************************************
239  * IPersistMoniker implementation
240  */
241
242 #define PERSISTMON_THIS(iface) DEFINE_THIS(HTMLDocument, PersistMoniker, iface)
243
244 static HRESULT WINAPI PersistMoniker_QueryInterface(IPersistMoniker *iface, REFIID riid,
245                                                             void **ppvObject)
246 {
247     HTMLDocument *This = PERSISTMON_THIS(iface);
248     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
249 }
250
251 static ULONG WINAPI PersistMoniker_AddRef(IPersistMoniker *iface)
252 {
253     HTMLDocument *This = PERSISTMON_THIS(iface);
254     return IHTMLDocument2_AddRef(HTMLDOC(This));
255 }
256
257 static ULONG WINAPI PersistMoniker_Release(IPersistMoniker *iface)
258 {
259     HTMLDocument *This = PERSISTMON_THIS(iface);
260     return IHTMLDocument2_Release(HTMLDOC(This));
261 }
262
263 static HRESULT WINAPI PersistMoniker_GetClassID(IPersistMoniker *iface, CLSID *pClassID)
264 {
265     HTMLDocument *This = PERSISTMON_THIS(iface);
266     return IPersist_GetClassID(PERSIST(This), pClassID);
267 }
268
269 static HRESULT WINAPI PersistMoniker_IsDirty(IPersistMoniker *iface)
270 {
271     HTMLDocument *This = PERSISTMON_THIS(iface);
272
273     TRACE("(%p)\n", This);
274
275     return IPersistStreamInit_IsDirty(PERSTRINIT(This));
276 }
277
278 static HRESULT WINAPI PersistMoniker_Load(IPersistMoniker *iface, BOOL fFullyAvailable,
279         IMoniker *pimkName, LPBC pibc, DWORD grfMode)
280 {
281     HTMLDocument *This = PERSISTMON_THIS(iface);
282     BOOL bind_complete = FALSE;
283     HRESULT hres;
284
285     TRACE("(%p)->(%x %p %p %08x)\n", This, fFullyAvailable, pimkName, pibc, grfMode);
286
287     hres = set_moniker(This, pimkName, pibc, &bind_complete);
288     if(FAILED(hres))
289         return hres;
290
291     if(!bind_complete)
292         return start_binding(This, (BSCallback*)This->bscallback, pibc);
293
294     return S_OK;
295 }
296
297 static HRESULT WINAPI PersistMoniker_Save(IPersistMoniker *iface, IMoniker *pimkName,
298         LPBC pbc, BOOL fRemember)
299 {
300     HTMLDocument *This = PERSISTMON_THIS(iface);
301     FIXME("(%p)->(%p %p %x)\n", This, pimkName, pbc, fRemember);
302     return E_NOTIMPL;
303 }
304
305 static HRESULT WINAPI PersistMoniker_SaveCompleted(IPersistMoniker *iface, IMoniker *pimkName, LPBC pibc)
306 {
307     HTMLDocument *This = PERSISTMON_THIS(iface);
308     FIXME("(%p)->(%p %p)\n", This, pimkName, pibc);
309     return E_NOTIMPL;
310 }
311
312 static HRESULT WINAPI PersistMoniker_GetCurMoniker(IPersistMoniker *iface, IMoniker **ppimkName)
313 {
314     HTMLDocument *This = PERSISTMON_THIS(iface);
315
316     TRACE("(%p)->(%p)\n", This, ppimkName);
317
318     if(!This->mon)
319         return E_UNEXPECTED;
320
321     IMoniker_AddRef(This->mon);
322     *ppimkName = This->mon;
323     return S_OK;
324 }
325
326 static const IPersistMonikerVtbl PersistMonikerVtbl = {
327     PersistMoniker_QueryInterface,
328     PersistMoniker_AddRef,
329     PersistMoniker_Release,
330     PersistMoniker_GetClassID,
331     PersistMoniker_IsDirty,
332     PersistMoniker_Load,
333     PersistMoniker_Save,
334     PersistMoniker_SaveCompleted,
335     PersistMoniker_GetCurMoniker
336 };
337
338 /**********************************************************
339  * IMonikerProp implementation
340  */
341
342 #define MONPROP_THIS(iface) DEFINE_THIS(HTMLDocument, MonikerProp, iface)
343
344 static HRESULT WINAPI MonikerProp_QueryInterface(IMonikerProp *iface, REFIID riid, void **ppvObject)
345 {
346     HTMLDocument *This = MONPROP_THIS(iface);
347     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
348 }
349
350 static ULONG WINAPI MonikerProp_AddRef(IMonikerProp *iface)
351 {
352     HTMLDocument *This = MONPROP_THIS(iface);
353     return IHTMLDocument2_AddRef(HTMLDOC(This));
354 }
355
356 static ULONG WINAPI MonikerProp_Release(IMonikerProp *iface)
357 {
358     HTMLDocument *This = MONPROP_THIS(iface);
359     return IHTMLDocument_Release(HTMLDOC(This));
360 }
361
362 static HRESULT WINAPI MonikerProp_PutProperty(IMonikerProp *iface, MONIKERPROPERTY mkp, LPCWSTR val)
363 {
364     HTMLDocument *This = MONPROP_THIS(iface);
365
366     TRACE("(%p)->(%d %s)\n", This, mkp, debugstr_w(val));
367
368     switch(mkp) {
369     case MIMETYPEPROP:
370         heap_free(This->mime);
371         This->mime = heap_strdupW(val);
372         break;
373
374     case CLASSIDPROP:
375         break;
376
377     default:
378         FIXME("mkp %d\n", mkp);
379         return E_NOTIMPL;
380     }
381
382     return S_OK;
383 }
384
385 static const IMonikerPropVtbl MonikerPropVtbl = {
386     MonikerProp_QueryInterface,
387     MonikerProp_AddRef,
388     MonikerProp_Release,
389     MonikerProp_PutProperty
390 };
391
392 /**********************************************************
393  * IPersistFile implementation
394  */
395
396 #define PERSISTFILE_THIS(iface) DEFINE_THIS(HTMLDocument, PersistFile, iface)
397
398 static HRESULT WINAPI PersistFile_QueryInterface(IPersistFile *iface, REFIID riid, void **ppvObject)
399 {
400     HTMLDocument *This = PERSISTFILE_THIS(iface);
401     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
402 }
403
404 static ULONG WINAPI PersistFile_AddRef(IPersistFile *iface)
405 {
406     HTMLDocument *This = PERSISTFILE_THIS(iface);
407     return IHTMLDocument2_AddRef(HTMLDOC(This));
408 }
409
410 static ULONG WINAPI PersistFile_Release(IPersistFile *iface)
411 {
412     HTMLDocument *This = PERSISTFILE_THIS(iface);
413     return IHTMLDocument2_Release(HTMLDOC(This));
414 }
415
416 static HRESULT WINAPI PersistFile_GetClassID(IPersistFile *iface, CLSID *pClassID)
417 {
418     HTMLDocument *This = PERSISTFILE_THIS(iface);
419
420     TRACE("(%p)->(%p)\n", This, pClassID);
421
422     if(!pClassID)
423         return E_INVALIDARG;
424
425     *pClassID = CLSID_HTMLDocument;
426     return S_OK;
427 }
428
429 static HRESULT WINAPI PersistFile_IsDirty(IPersistFile *iface)
430 {
431     HTMLDocument *This = PERSISTFILE_THIS(iface);
432
433     TRACE("(%p)\n", This);
434
435     return IPersistStreamInit_IsDirty(PERSTRINIT(This));
436 }
437
438 static HRESULT WINAPI PersistFile_Load(IPersistFile *iface, LPCOLESTR pszFileName, DWORD dwMode)
439 {
440     HTMLDocument *This = PERSISTFILE_THIS(iface);
441     FIXME("(%p)->(%s %08x)\n", This, debugstr_w(pszFileName), dwMode);
442     return E_NOTIMPL;
443 }
444
445 static HRESULT WINAPI PersistFile_Save(IPersistFile *iface, LPCOLESTR pszFileName, BOOL fRemember)
446 {
447     HTMLDocument *This = PERSISTFILE_THIS(iface);
448     char *str;
449     DWORD written=0;
450     HANDLE file;
451     HRESULT hres;
452
453     TRACE("(%p)->(%s %x)\n", This, debugstr_w(pszFileName), fRemember);
454
455     file = CreateFileW(pszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
456                        FILE_ATTRIBUTE_NORMAL, NULL);
457     if(file == INVALID_HANDLE_VALUE) {
458         WARN("Could not create file: %u\n", GetLastError());
459         return E_FAIL;
460     }
461
462     hres = get_doc_string(This, &str);
463     if(SUCCEEDED(hres))
464         WriteFile(file, str, strlen(str), &written, NULL);
465
466     CloseHandle(file);
467     return hres;
468 }
469
470 static HRESULT WINAPI PersistFile_SaveCompleted(IPersistFile *iface, LPCOLESTR pszFileName)
471 {
472     HTMLDocument *This = PERSISTFILE_THIS(iface);
473     FIXME("(%p)->(%s)\n", This, debugstr_w(pszFileName));
474     return E_NOTIMPL;
475 }
476
477 static HRESULT WINAPI PersistFile_GetCurFile(IPersistFile *iface, LPOLESTR *pszFileName)
478 {
479     HTMLDocument *This = PERSISTFILE_THIS(iface);
480     FIXME("(%p)->(%p)\n", This, pszFileName);
481     return E_NOTIMPL;
482 }
483
484 static const IPersistFileVtbl PersistFileVtbl = {
485     PersistFile_QueryInterface,
486     PersistFile_AddRef,
487     PersistFile_Release,
488     PersistFile_GetClassID,
489     PersistFile_IsDirty,
490     PersistFile_Load,
491     PersistFile_Save,
492     PersistFile_SaveCompleted,
493     PersistFile_GetCurFile
494 };
495
496 #define PERSTRINIT_THIS(iface) DEFINE_THIS(HTMLDocument, PersistStreamInit, iface)
497
498 static HRESULT WINAPI PersistStreamInit_QueryInterface(IPersistStreamInit *iface,
499                                                        REFIID riid, void **ppv)
500 {
501     HTMLDocument *This = PERSTRINIT_THIS(iface);
502     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppv);
503 }
504
505 static ULONG WINAPI PersistStreamInit_AddRef(IPersistStreamInit *iface)
506 {
507     HTMLDocument *This = PERSTRINIT_THIS(iface);
508     return IHTMLDocument2_AddRef(HTMLDOC(This));
509 }
510
511 static ULONG WINAPI PersistStreamInit_Release(IPersistStreamInit *iface)
512 {
513     HTMLDocument *This = PERSTRINIT_THIS(iface);
514     return IHTMLDocument2_Release(HTMLDOC(This));
515 }
516
517 static HRESULT WINAPI PersistStreamInit_GetClassID(IPersistStreamInit *iface, CLSID *pClassID)
518 {
519     HTMLDocument *This = PERSTRINIT_THIS(iface);
520     return IPersist_GetClassID(PERSIST(This), pClassID);
521 }
522
523 static HRESULT WINAPI PersistStreamInit_IsDirty(IPersistStreamInit *iface)
524 {
525     HTMLDocument *This = PERSTRINIT_THIS(iface);
526
527     TRACE("(%p)\n", This);
528
529     if(This->usermode == EDITMODE)
530         return editor_is_dirty(This);
531
532     return S_FALSE;
533 }
534
535 static HRESULT WINAPI PersistStreamInit_Load(IPersistStreamInit *iface, LPSTREAM pStm)
536 {
537     HTMLDocument *This = PERSTRINIT_THIS(iface);
538     IMoniker *mon;
539     HRESULT hres;
540
541     static const WCHAR about_blankW[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
542
543     TRACE("(%p)->(%p)\n", This, pStm);
544
545     hres = CreateURLMoniker(NULL, about_blankW, &mon);
546     if(FAILED(hres)) {
547         WARN("CreateURLMoniker failed: %08x\n", hres);
548         return hres;
549     }
550
551     hres = set_moniker(This, mon, NULL, NULL);
552     IMoniker_Release(mon);
553     if(FAILED(hres))
554         return hres;
555
556     return channelbsc_load_stream(This->bscallback, pStm);
557 }
558
559 static HRESULT WINAPI PersistStreamInit_Save(IPersistStreamInit *iface, LPSTREAM pStm,
560                                              BOOL fClearDirty)
561 {
562     HTMLDocument *This = PERSTRINIT_THIS(iface);
563     char *str;
564     DWORD written=0;
565     HRESULT hres;
566
567     TRACE("(%p)->(%p %x)\n", This, pStm, fClearDirty);
568
569     hres = get_doc_string(This, &str);
570     if(FAILED(hres))
571         return hres;
572
573     hres = IStream_Write(pStm, str, strlen(str), &written);
574     if(FAILED(hres))
575         FIXME("Write failed: %08x\n", hres);
576
577     heap_free(str);
578
579     if(fClearDirty)
580         set_dirty(This, VARIANT_FALSE);
581
582     return S_OK;
583 }
584
585 static HRESULT WINAPI PersistStreamInit_GetSizeMax(IPersistStreamInit *iface,
586                                                    ULARGE_INTEGER *pcbSize)
587 {
588     HTMLDocument *This = PERSTRINIT_THIS(iface);
589     FIXME("(%p)->(%p)\n", This, pcbSize);
590     return E_NOTIMPL;
591 }
592
593 static HRESULT WINAPI PersistStreamInit_InitNew(IPersistStreamInit *iface)
594 {
595     HTMLDocument *This = PERSTRINIT_THIS(iface);
596     FIXME("(%p)\n", This);
597     return E_NOTIMPL;
598 }
599
600 #undef PERSTRINIT_THIS
601
602 static const IPersistStreamInitVtbl PersistStreamInitVtbl = {
603     PersistStreamInit_QueryInterface,
604     PersistStreamInit_AddRef,
605     PersistStreamInit_Release,
606     PersistStreamInit_GetClassID,
607     PersistStreamInit_IsDirty,
608     PersistStreamInit_Load,
609     PersistStreamInit_Save,
610     PersistStreamInit_GetSizeMax,
611     PersistStreamInit_InitNew
612 };
613
614 /**********************************************************
615  * IPersistHistory implementation
616  */
617
618 #define PERSISTHIST_THIS(iface) DEFINE_THIS(HTMLDocument, PersistHistory, iface)
619
620 static HRESULT WINAPI PersistHistory_QueryInterface(IPersistHistory *iface, REFIID riid, void **ppvObject)
621 {
622     HTMLDocument *This = PERSISTHIST_THIS(iface);
623     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
624 }
625
626 static ULONG WINAPI PersistHistory_AddRef(IPersistHistory *iface)
627 {
628     HTMLDocument *This = PERSISTHIST_THIS(iface);
629     return IHTMLDocument2_AddRef(HTMLDOC(This));
630 }
631
632 static ULONG WINAPI PersistHistory_Release(IPersistHistory *iface)
633 {
634     HTMLDocument *This = PERSISTHIST_THIS(iface);
635     return IHTMLDocument2_Release(HTMLDOC(This));
636 }
637
638 static HRESULT WINAPI PersistHistory_GetClassID(IPersistHistory *iface, CLSID *pClassID)
639 {
640     HTMLDocument *This = PERSISTHIST_THIS(iface);
641     return IPersist_GetClassID(PERSIST(This), pClassID);
642 }
643
644 static HRESULT WINAPI PersistHistory_LoadHistory(IPersistHistory *iface, IStream *pStream, IBindCtx *pbc)
645 {
646     HTMLDocument *This = PERSISTHIST_THIS(iface);
647     FIXME("(%p)->(%p %p)\n", This, pStream, pbc);
648     return E_NOTIMPL;
649 }
650
651 static HRESULT WINAPI PersistHistory_SaveHistory(IPersistHistory *iface, IStream *pStream)
652 {
653     HTMLDocument *This = PERSISTHIST_THIS(iface);
654     FIXME("(%p)->(%p)\n", This, pStream);
655     return E_NOTIMPL;
656 }
657
658 static HRESULT WINAPI PersistHistory_SetPositionCookie(IPersistHistory *iface, DWORD dwPositioncookie)
659 {
660     HTMLDocument *This = PERSISTHIST_THIS(iface);
661     FIXME("(%p)->(%x)\n", This, dwPositioncookie);
662     return E_NOTIMPL;
663 }
664
665 static HRESULT WINAPI PersistHistory_GetPositionCookie(IPersistHistory *iface, DWORD *pdwPositioncookie)
666 {
667     HTMLDocument *This = PERSISTHIST_THIS(iface);
668     FIXME("(%p)->(%p)\n", This, pdwPositioncookie);
669     return E_NOTIMPL;
670 }
671
672 #undef PERSISTHIST_THIS
673
674 static const IPersistHistoryVtbl PersistHistoryVtbl = {
675     PersistHistory_QueryInterface,
676     PersistHistory_AddRef,
677     PersistHistory_Release,
678     PersistHistory_GetClassID,
679     PersistHistory_LoadHistory,
680     PersistHistory_SaveHistory,
681     PersistHistory_SetPositionCookie,
682     PersistHistory_GetPositionCookie
683 };
684
685 void HTMLDocument_Persist_Init(HTMLDocument *This)
686 {
687     This->lpPersistMonikerVtbl = &PersistMonikerVtbl;
688     This->lpPersistFileVtbl = &PersistFileVtbl;
689     This->lpMonikerPropVtbl = &MonikerPropVtbl;
690     This->lpPersistStreamInitVtbl = &PersistStreamInitVtbl;
691     This->lpPersistHistoryVtbl = &PersistHistoryVtbl;
692
693     This->bscallback = NULL;
694     This->mon = NULL;
695     This->url = NULL;
696     This->mime = NULL;
697 }