wintrust: Implement WintrustLoadFunctionPointers.
[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 HRESULT get_doc_string(HTMLDocument *This, char **str, DWORD *len)
43 {
44     nsIDOMDocument *nsdoc;
45     nsIDOMNode *nsnode;
46     LPCWSTR strw;
47     nsAString nsstr;
48     nsresult nsres;
49
50     if(!This->nscontainer) {
51         WARN("no nscontainer, returning NULL\n");
52         return S_OK;
53     }
54
55     nsres = nsIWebNavigation_GetDocument(This->nscontainer->navigation, &nsdoc);
56     if(NS_FAILED(nsres)) {
57         ERR("GetDocument failed: %08x\n", nsres);
58         return E_FAIL;
59     }
60
61     nsres = nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMNode, (void**)&nsnode);
62     nsIDOMDocument_Release(nsdoc);
63     if(NS_FAILED(nsres)) {
64         ERR("Could not get nsIDOMNode failed: %08x\n", nsres);
65         return E_FAIL;
66     }
67
68     nsAString_Init(&nsstr, NULL);
69     nsnode_to_nsstring(nsnode, &nsstr);
70     nsIDOMNode_Release(nsnode);
71
72     nsAString_GetData(&nsstr, &strw, NULL);
73     TRACE("%s\n", debugstr_w(strw));
74
75     *len = WideCharToMultiByte(CP_ACP, 0, strw, -1, NULL, 0, NULL, NULL);
76     *str = mshtml_alloc(*len);
77     WideCharToMultiByte(CP_ACP, 0, strw, -1, *str, *len, NULL, NULL);
78
79     nsAString_Finish(&nsstr);
80
81     return S_OK;
82 }
83
84 /**********************************************************
85  * IPersistMoniker implementation
86  */
87
88 #define PERSISTMON_THIS(iface) DEFINE_THIS(HTMLDocument, PersistMoniker, iface)
89
90 static HRESULT WINAPI PersistMoniker_QueryInterface(IPersistMoniker *iface, REFIID riid,
91                                                             void **ppvObject)
92 {
93     HTMLDocument *This = PERSISTMON_THIS(iface);
94     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
95 }
96
97 static ULONG WINAPI PersistMoniker_AddRef(IPersistMoniker *iface)
98 {
99     HTMLDocument *This = PERSISTMON_THIS(iface);
100     return IHTMLDocument2_AddRef(HTMLDOC(This));
101 }
102
103 static ULONG WINAPI PersistMoniker_Release(IPersistMoniker *iface)
104 {
105     HTMLDocument *This = PERSISTMON_THIS(iface);
106     return IHTMLDocument2_Release(HTMLDOC(This));
107 }
108
109 static HRESULT WINAPI PersistMoniker_GetClassID(IPersistMoniker *iface, CLSID *pClassID)
110 {
111     HTMLDocument *This = PERSISTMON_THIS(iface);
112     return IPersist_GetClassID(PERSIST(This), pClassID);
113 }
114
115 static HRESULT WINAPI PersistMoniker_IsDirty(IPersistMoniker *iface)
116 {
117     HTMLDocument *This = PERSISTMON_THIS(iface);
118     FIXME("(%p)\n", This);
119     return E_NOTIMPL;
120 }
121
122 static nsIInputStream *get_post_data_stream(IBindCtx *bctx)
123 {
124     nsIInputStream *ret = NULL;
125     IBindStatusCallback *callback;
126     IHttpNegotiate *http_negotiate;
127     BINDINFO bindinfo;
128     DWORD bindf = 0;
129     DWORD post_len = 0, headers_len = 0;
130     LPWSTR headers = NULL;
131     WCHAR emptystr[] = {0};
132     char *data;
133     HRESULT hres;
134
135     static WCHAR _BSCB_Holder_[] =
136         {'_','B','S','C','B','_','H','o','l','d','e','r','_',0};
137
138
139     /* FIXME: This should be done in URLMoniker */
140     if(!bctx)
141         return NULL;
142
143     hres = IBindCtx_GetObjectParam(bctx, _BSCB_Holder_, (IUnknown**)&callback);
144     if(FAILED(hres))
145         return NULL;
146
147     hres = IBindStatusCallback_QueryInterface(callback, &IID_IHttpNegotiate,
148                                               (void**)&http_negotiate);
149     if(SUCCEEDED(hres)) {
150         hres = IHttpNegotiate_BeginningTransaction(http_negotiate, emptystr,
151                                                    emptystr, 0, &headers);
152         IHttpNegotiate_Release(http_negotiate);
153
154         if(SUCCEEDED(hres) && headers)
155             headers_len = WideCharToMultiByte(CP_ACP, 0, headers, -1, NULL, 0, NULL, NULL);
156     }
157
158     memset(&bindinfo, 0, sizeof(bindinfo));
159     bindinfo.cbSize = sizeof(bindinfo);
160
161     hres = IBindStatusCallback_GetBindInfo(callback, &bindf, &bindinfo);
162
163     if(SUCCEEDED(hres) && bindinfo.dwBindVerb == BINDVERB_POST)
164         post_len = bindinfo.cbstgmedData;
165
166     if(headers_len || post_len) {
167         int len = headers_len ? headers_len-1 : 0;
168
169         static const char content_length[] = "Content-Length: %u\r\n\r\n";
170
171         data = mshtml_alloc(headers_len+post_len+sizeof(content_length)+8);
172
173         if(headers_len) {
174             WideCharToMultiByte(CP_ACP, 0, headers, -1, data, -1, NULL, NULL);
175             CoTaskMemFree(headers);
176         }
177
178         if(post_len) {
179             sprintf(data+len, content_length, post_len);
180             len = strlen(data);
181
182             memcpy(data+len, bindinfo.stgmedData.u.hGlobal, post_len);
183         }
184
185         TRACE("data = %s\n", debugstr_an(data, len+post_len));
186
187         ret = create_nsstream(data, len+post_len);
188     }
189
190     ReleaseBindInfo(&bindinfo);
191     IBindStatusCallback_Release(callback);
192
193     return ret;
194 }
195
196 static HRESULT WINAPI PersistMoniker_Load(IPersistMoniker *iface, BOOL fFullyAvailable,
197         IMoniker *pimkName, LPBC pibc, DWORD grfMode)
198 {
199     HTMLDocument *This = PERSISTMON_THIS(iface);
200     BSCallback *bscallback;
201     LPOLESTR url = NULL;
202     task_t *task;
203     HRESULT hres;
204     nsresult nsres;
205
206     TRACE("(%p)->(%x %p %p %08x)\n", This, fFullyAvailable, pimkName, pibc, grfMode);
207
208     if(pibc) {
209         IUnknown *unk = NULL;
210
211         /* FIXME:
212          * Use params:
213          * "__PrecreatedObject"
214          * "BIND_CONTEXT_PARAM"
215          * "__HTMLLOADOPTIONS"
216          * "__DWNBINDINFO"
217          * "URL Context"
218          * "CBinding Context"
219          * "_ITransData_Object_"
220          * "_EnumFORMATETC_"
221          */
222
223         IBindCtx_GetObjectParam(pibc, (LPOLESTR)SZ_HTML_CLIENTSITE_OBJECTPARAM, &unk);
224         if(unk) {
225             IOleClientSite *client = NULL;
226
227             hres = IUnknown_QueryInterface(unk, &IID_IOleClientSite, (void**)&client);
228             if(SUCCEEDED(hres)) {
229                 TRACE("Got client site %p\n", client);
230                 IOleObject_SetClientSite(OLEOBJ(This), client);
231                 IOleClientSite_Release(client);
232             }
233
234             IUnknown_Release(unk);
235         }
236     }
237
238     This->readystate = READYSTATE_LOADING;
239     call_property_onchanged(This->cp_propnotif, DISPID_READYSTATE);
240
241     HTMLDocument_LockContainer(This, TRUE);
242     
243     hres = IMoniker_GetDisplayName(pimkName, pibc, NULL, &url);
244     if(FAILED(hres)) {
245         WARN("GetDiaplayName failed: %08x\n", hres);
246         return hres;
247     }
248
249     TRACE("got url: %s\n", debugstr_w(url));
250
251     if(This->client) {
252         IOleCommandTarget *cmdtrg = NULL;
253
254         hres = IOleClientSite_QueryInterface(This->client, &IID_IOleCommandTarget,
255                 (void**)&cmdtrg);
256         if(SUCCEEDED(hres)) {
257             VARIANT var;
258
259             V_VT(&var) = VT_I4;
260             V_I4(&var) = 0;
261             IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 37, 0, &var, NULL);
262
263             IOleCommandTarget_Release(cmdtrg);
264         }
265     }
266
267     if(This->client) {
268         VARIANT silent, offline;
269
270         hres = get_client_disp_property(This->client, DISPID_AMBIENT_SILENT, &silent);
271         if(SUCCEEDED(hres)) {
272             if(V_VT(&silent) != VT_BOOL)
273                 WARN("V_VT(silent) = %d\n", V_VT(&silent));
274             else if(V_BOOL(&silent))
275                 FIXME("silent == true\n");
276         }
277
278         hres = get_client_disp_property(This->client,
279                 DISPID_AMBIENT_OFFLINEIFNOTCONNECTED, &offline);
280         if(SUCCEEDED(hres)) {
281             if(V_VT(&silent) != VT_BOOL)
282                 WARN("V_VT(offline) = %d\n", V_VT(&silent));
283             else if(V_BOOL(&silent))
284                 FIXME("offline == true\n");
285         }
286     }
287
288     bscallback = create_bscallback(pimkName);
289
290     if(This->frame) {
291         task = mshtml_alloc(sizeof(task_t));
292
293         task->doc = This;
294         task->task_id = TASK_SETPROGRESS;
295         task->next = NULL;
296
297         push_task(task);
298     }
299
300     task = mshtml_alloc(sizeof(task_t));
301
302     task->doc = This;
303     task->task_id = TASK_SETDOWNLOADSTATE;
304     task->next = NULL;
305
306     push_task(task);
307
308     if(This->nscontainer) {
309         nsIInputStream *post_data_stream = get_post_data_stream(pibc);
310
311         This->nscontainer->bscallback = bscallback;
312         nsres = nsIWebNavigation_LoadURI(This->nscontainer->navigation, url,
313                 LOAD_FLAGS_NONE, NULL, post_data_stream, NULL);
314         This->nscontainer->bscallback = NULL;
315
316         if(post_data_stream)
317             nsIInputStream_Release(post_data_stream);
318
319         if(NS_SUCCEEDED(nsres)) {
320             /* FIXME: don't return here (URL Moniker needs to be good enough) */
321
322             IBindStatusCallback_Release(STATUSCLB(bscallback));
323             CoTaskMemFree(url);
324             return S_OK;
325         }else if(nsres != WINE_NS_LOAD_FROM_MONIKER) {
326             WARN("LoadURI failed: %08x\n", nsres);
327         }
328     }
329
330     set_document_bscallback(This, bscallback);
331     hres = start_binding(bscallback);
332
333     IBindStatusCallback_Release(STATUSCLB(bscallback));
334     CoTaskMemFree(url);
335
336     return hres;
337 }
338
339 static HRESULT WINAPI PersistMoniker_Save(IPersistMoniker *iface, IMoniker *pimkName,
340         LPBC pbc, BOOL fRemember)
341 {
342     HTMLDocument *This = PERSISTMON_THIS(iface);
343     FIXME("(%p)->(%p %p %x)\n", This, pimkName, pbc, fRemember);
344     return E_NOTIMPL;
345 }
346
347 static HRESULT WINAPI PersistMoniker_SaveCompleted(IPersistMoniker *iface, IMoniker *pimkName, LPBC pibc)
348 {
349     HTMLDocument *This = PERSISTMON_THIS(iface);
350     FIXME("(%p)->(%p %p)\n", This, pimkName, pibc);
351     return E_NOTIMPL;
352 }
353
354 static HRESULT WINAPI PersistMoniker_GetCurMoniker(IPersistMoniker *iface, IMoniker **ppimkName)
355 {
356     HTMLDocument *This = PERSISTMON_THIS(iface);
357     FIXME("(%p)->(%p)\n", This, ppimkName);
358     return E_NOTIMPL;
359 }
360
361 static const IPersistMonikerVtbl PersistMonikerVtbl = {
362     PersistMoniker_QueryInterface,
363     PersistMoniker_AddRef,
364     PersistMoniker_Release,
365     PersistMoniker_GetClassID,
366     PersistMoniker_IsDirty,
367     PersistMoniker_Load,
368     PersistMoniker_Save,
369     PersistMoniker_SaveCompleted,
370     PersistMoniker_GetCurMoniker
371 };
372
373 /**********************************************************
374  * IMonikerProp implementation
375  */
376
377 #define MONPROP_THIS(iface) DEFINE_THIS(HTMLDocument, MonikerProp, iface)
378
379 static HRESULT WINAPI MonikerProp_QueryInterface(IMonikerProp *iface, REFIID riid, void **ppvObject)
380 {
381     HTMLDocument *This = MONPROP_THIS(iface);
382     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
383 }
384
385 static ULONG WINAPI MonikerProp_AddRef(IMonikerProp *iface)
386 {
387     HTMLDocument *This = MONPROP_THIS(iface);
388     return IHTMLDocument2_AddRef(HTMLDOC(This));
389 }
390
391 static ULONG WINAPI MonikerProp_Release(IMonikerProp *iface)
392 {
393     HTMLDocument *This = MONPROP_THIS(iface);
394     return IHTMLDocument_Release(HTMLDOC(This));
395 }
396
397 static HRESULT WINAPI MonikerProp_PutProperty(IMonikerProp *iface, MONIKERPROPERTY mkp, LPCWSTR val)
398 {
399     HTMLDocument *This = MONPROP_THIS(iface);
400     FIXME("(%p)->(%d %s)\n", This, mkp, debugstr_w(val));
401     return E_NOTIMPL;
402 }
403
404 static const IMonikerPropVtbl MonikerPropVtbl = {
405     MonikerProp_QueryInterface,
406     MonikerProp_AddRef,
407     MonikerProp_Release,
408     MonikerProp_PutProperty
409 };
410
411 /**********************************************************
412  * IPersistFile implementation
413  */
414
415 #define PERSISTFILE_THIS(iface) DEFINE_THIS(HTMLDocument, PersistFile, iface)
416
417 static HRESULT WINAPI PersistFile_QueryInterface(IPersistFile *iface, REFIID riid, void **ppvObject)
418 {
419     HTMLDocument *This = PERSISTFILE_THIS(iface);
420     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
421 }
422
423 static ULONG WINAPI PersistFile_AddRef(IPersistFile *iface)
424 {
425     HTMLDocument *This = PERSISTFILE_THIS(iface);
426     return IHTMLDocument2_AddRef(HTMLDOC(This));
427 }
428
429 static ULONG WINAPI PersistFile_Release(IPersistFile *iface)
430 {
431     HTMLDocument *This = PERSISTFILE_THIS(iface);
432     return IHTMLDocument2_Release(HTMLDOC(This));
433 }
434
435 static HRESULT WINAPI PersistFile_GetClassID(IPersistFile *iface, CLSID *pClassID)
436 {
437     HTMLDocument *This = PERSISTFILE_THIS(iface);
438
439     TRACE("(%p)->(%p)\n", This, pClassID);
440
441     if(!pClassID)
442         return E_INVALIDARG;
443
444     memcpy(pClassID, &CLSID_HTMLDocument, sizeof(CLSID));
445     return S_OK;
446 }
447
448 static HRESULT WINAPI PersistFile_IsDirty(IPersistFile *iface)
449 {
450     HTMLDocument *This = PERSISTFILE_THIS(iface);
451     FIXME("(%p)\n", This);
452     return E_NOTIMPL;
453 }
454
455 static HRESULT WINAPI PersistFile_Load(IPersistFile *iface, LPCOLESTR pszFileName, DWORD dwMode)
456 {
457     HTMLDocument *This = PERSISTFILE_THIS(iface);
458     FIXME("(%p)->(%s %08x)\n", This, debugstr_w(pszFileName), dwMode);
459     return E_NOTIMPL;
460 }
461
462 static HRESULT WINAPI PersistFile_Save(IPersistFile *iface, LPCOLESTR pszFileName, BOOL fRemember)
463 {
464     HTMLDocument *This = PERSISTFILE_THIS(iface);
465     char *str;
466     DWORD len, written=0;
467     HANDLE file;
468     HRESULT hres;
469
470     TRACE("(%p)->(%s %x)\n", This, debugstr_w(pszFileName), fRemember);
471
472     file = CreateFileW(pszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
473                        FILE_ATTRIBUTE_NORMAL, NULL);
474     if(file == INVALID_HANDLE_VALUE) {
475         WARN("Could not create file: %u\n", GetLastError());
476         return E_FAIL;
477     }
478
479     hres = get_doc_string(This, &str, &len);
480     if(FAILED(hres))
481         return hres;
482
483     WriteFile(file, str, len, &written, NULL);
484     CloseHandle(file);
485     return S_OK;
486 }
487
488 static HRESULT WINAPI PersistFile_SaveCompleted(IPersistFile *iface, LPCOLESTR pszFileName)
489 {
490     HTMLDocument *This = PERSISTFILE_THIS(iface);
491     FIXME("(%p)->(%s)\n", This, debugstr_w(pszFileName));
492     return E_NOTIMPL;
493 }
494
495 static HRESULT WINAPI PersistFile_GetCurFile(IPersistFile *iface, LPOLESTR *pszFileName)
496 {
497     HTMLDocument *This = PERSISTFILE_THIS(iface);
498     FIXME("(%p)->(%p)\n", This, pszFileName);
499     return E_NOTIMPL;
500 }
501
502 static const IPersistFileVtbl PersistFileVtbl = {
503     PersistFile_QueryInterface,
504     PersistFile_AddRef,
505     PersistFile_Release,
506     PersistFile_GetClassID,
507     PersistFile_IsDirty,
508     PersistFile_Load,
509     PersistFile_Save,
510     PersistFile_SaveCompleted,
511     PersistFile_GetCurFile
512 };
513
514 #define PERSTRINIT_THIS(iface) DEFINE_THIS(HTMLDocument, PersistStreamInit, iface)
515
516 static HRESULT WINAPI PersistStreamInit_QueryInterface(IPersistStreamInit *iface,
517                                                        REFIID riid, void **ppv)
518 {
519     HTMLDocument *This = PERSTRINIT_THIS(iface);
520     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppv);
521 }
522
523 static ULONG WINAPI PersistStreamInit_AddRef(IPersistStreamInit *iface)
524 {
525     HTMLDocument *This = PERSTRINIT_THIS(iface);
526     return IHTMLDocument2_AddRef(HTMLDOC(This));
527 }
528
529 static ULONG WINAPI PersistStreamInit_Release(IPersistStreamInit *iface)
530 {
531     HTMLDocument *This = PERSTRINIT_THIS(iface);
532     return IHTMLDocument2_AddRef(HTMLDOC(This));
533 }
534
535 static HRESULT WINAPI PersistStreamInit_GetClassID(IPersistStreamInit *iface, CLSID *pClassID)
536 {
537     HTMLDocument *This = PERSTRINIT_THIS(iface);
538     return IPersist_GetClassID(PERSIST(This), pClassID);
539 }
540
541 static HRESULT WINAPI PersistStreamInit_IsDirty(IPersistStreamInit *iface)
542 {
543     HTMLDocument *This = PERSTRINIT_THIS(iface);
544     FIXME("(%p)\n", This);
545     return E_NOTIMPL;
546 }
547
548 static HRESULT WINAPI PersistStreamInit_Load(IPersistStreamInit *iface, LPSTREAM pStm)
549 {
550     HTMLDocument *This = PERSTRINIT_THIS(iface);
551     FIXME("(%p)->(%p)\n", This, pStm);
552     return E_NOTIMPL;
553 }
554
555 static HRESULT WINAPI PersistStreamInit_Save(IPersistStreamInit *iface, LPSTREAM pStm,
556                                              BOOL fClearDirty)
557 {
558     HTMLDocument *This = PERSTRINIT_THIS(iface);
559     char *str;
560     DWORD len, written=0;
561     HRESULT hres;
562
563     WARN("(%p)->(%p %x) needs more work\n", This, pStm, fClearDirty);
564
565     hres = get_doc_string(This, &str, &len);
566     if(FAILED(hres))
567         return hres;
568
569
570     hres = IStream_Write(pStm, str, len, &written);
571     if(FAILED(hres))
572         FIXME("Write failed: %08x\n", hres);
573
574     mshtml_free(str);
575     return S_OK;
576 }
577
578 static HRESULT WINAPI PersistStreamInit_GetSizeMax(IPersistStreamInit *iface,
579                                                    ULARGE_INTEGER *pcbSize)
580 {
581     HTMLDocument *This = PERSTRINIT_THIS(iface);
582     FIXME("(%p)->(%p)\n", This, pcbSize);
583     return E_NOTIMPL;
584 }
585
586 static HRESULT WINAPI PersistStreamInit_InitNew(IPersistStreamInit *iface)
587 {
588     HTMLDocument *This = PERSTRINIT_THIS(iface);
589     FIXME("(%p)\n", This);
590     return E_NOTIMPL;
591 }
592
593 #undef PERSTRINIT_THIS
594
595 static const IPersistStreamInitVtbl PersistStreamInitVtbl = {
596     PersistStreamInit_QueryInterface,
597     PersistStreamInit_AddRef,
598     PersistStreamInit_Release,
599     PersistStreamInit_GetClassID,
600     PersistStreamInit_IsDirty,
601     PersistStreamInit_Load,
602     PersistStreamInit_Save,
603     PersistStreamInit_GetSizeMax,
604     PersistStreamInit_InitNew
605 };
606
607 void HTMLDocument_Persist_Init(HTMLDocument *This)
608 {
609     This->lpPersistMonikerVtbl = &PersistMonikerVtbl;
610     This->lpPersistFileVtbl = &PersistFileVtbl;
611     This->lpMonikerPropVtbl = &MonikerPropVtbl;
612     This->lpPersistStreamInitVtbl = &PersistStreamInitVtbl;
613
614     This->bscallback = NULL;
615 }