msi: Only specifically resolve the TARGETDIR directory once.
[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
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
36
37 #include "mshtml_private.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
40
41 /**********************************************************
42  * IPersistMoniker implementation
43  */
44
45 #define PERSISTMON_THIS(iface) DEFINE_THIS(HTMLDocument, PersistMoniker, iface)
46
47 static HRESULT WINAPI PersistMoniker_QueryInterface(IPersistMoniker *iface, REFIID riid,
48                                                             void **ppvObject)
49 {
50     HTMLDocument *This = PERSISTMON_THIS(iface);
51     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
52 }
53
54 static ULONG WINAPI PersistMoniker_AddRef(IPersistMoniker *iface)
55 {
56     HTMLDocument *This = PERSISTMON_THIS(iface);
57     return IHTMLDocument2_AddRef(HTMLDOC(This));
58 }
59
60 static ULONG WINAPI PersistMoniker_Release(IPersistMoniker *iface)
61 {
62     HTMLDocument *This = PERSISTMON_THIS(iface);
63     return IHTMLDocument2_Release(HTMLDOC(This));
64 }
65
66 static HRESULT WINAPI PersistMoniker_GetClassID(IPersistMoniker *iface, CLSID *pClassID)
67 {
68     HTMLDocument *This = PERSISTMON_THIS(iface);
69     return IPersist_GetClassID(PERSIST(This), pClassID);
70 }
71
72 static HRESULT WINAPI PersistMoniker_IsDirty(IPersistMoniker *iface)
73 {
74     HTMLDocument *This = PERSISTMON_THIS(iface);
75     FIXME("(%p)\n", This);
76     return E_NOTIMPL;
77 }
78
79 static nsIInputStream *get_post_data_stream(IBindCtx *bctx)
80 {
81     nsIInputStream *ret = NULL;
82     IBindStatusCallback *callback;
83     IHttpNegotiate *http_negotiate;
84     BINDINFO bindinfo;
85     DWORD bindf = 0;
86     DWORD post_len = 0, headers_len = 0;
87     LPWSTR headers = NULL;
88     WCHAR emptystr[] = {0};
89     char *data;
90     HRESULT hres;
91
92     static WCHAR _BSCB_Holder_[] =
93         {'_','B','S','C','B','_','H','o','l','d','e','r','_',0};
94
95
96     /* FIXME: This should be done in URLMoniker */
97     if(!bctx)
98         return NULL;
99
100     hres = IBindCtx_GetObjectParam(bctx, _BSCB_Holder_, (IUnknown**)&callback);
101     if(FAILED(hres))
102         return NULL;
103
104     hres = IBindStatusCallback_QueryInterface(callback, &IID_IHttpNegotiate,
105                                               (void**)&http_negotiate);
106     if(SUCCEEDED(hres)) {
107         hres = IHttpNegotiate_BeginningTransaction(http_negotiate, emptystr,
108                                                    emptystr, 0, &headers);
109         IHttpNegotiate_Release(http_negotiate);
110
111         if(SUCCEEDED(hres) && headers)
112             headers_len = WideCharToMultiByte(CP_ACP, 0, headers, -1, NULL, 0, NULL, NULL);
113     }
114
115     memset(&bindinfo, 0, sizeof(bindinfo));
116     bindinfo.cbSize = sizeof(bindinfo);
117
118     hres = IBindStatusCallback_GetBindInfo(callback, &bindf, &bindinfo);
119
120     if(SUCCEEDED(hres) && bindinfo.dwBindVerb == BINDVERB_POST)
121         post_len = bindinfo.cbStgmedData;
122
123     if(headers_len || post_len) {
124         int len = headers_len ? headers_len-1 : 0;
125
126         static const char content_length[] = "Content-Length: %lu\r\n\r\n";
127
128         data = mshtml_alloc(headers_len+post_len+sizeof(content_length)+8);
129
130         if(headers_len) {
131             WideCharToMultiByte(CP_ACP, 0, headers, -1, data, -1, NULL, NULL);
132             CoTaskMemFree(headers);
133         }
134
135         if(post_len) {
136             sprintf(data+len, content_length, post_len);
137             len = strlen(data);
138
139             memcpy(data+len, bindinfo.stgmedData.u.hGlobal, post_len);
140         }
141
142         TRACE("data = %s\n", debugstr_an(data, len+post_len));
143
144         ret = create_nsstream(data, len+post_len);
145     }
146
147     ReleaseBindInfo(&bindinfo);
148     IBindStatusCallback_Release(callback);
149
150     return ret;
151 }
152
153 static HRESULT WINAPI PersistMoniker_Load(IPersistMoniker *iface, BOOL fFullyAvailable,
154         IMoniker *pimkName, LPBC pibc, DWORD grfMode)
155 {
156     HTMLDocument *This = PERSISTMON_THIS(iface);
157     BSCallback *bscallback;
158     LPOLESTR url = NULL;
159     task_t *task;
160     HRESULT hres;
161     nsresult nsres;
162
163     TRACE("(%p)->(%x %p %p %08lx)\n", This, fFullyAvailable, pimkName, pibc, grfMode);
164
165     if(pibc) {
166         IUnknown *unk = NULL;
167
168         /* FIXME:
169          * Use params:
170          * "__PrecreatedObject"
171          * "BIND_CONTEXT_PARAM"
172          * "__HTMLLOADOPTIONS"
173          * "__DWNBINDINFO"
174          * "URL Context"
175          * "CBinding Context"
176          * "_ITransData_Object_"
177          * "_EnumFORMATETC_"
178          */
179
180         IBindCtx_GetObjectParam(pibc, (LPOLESTR)SZ_HTML_CLIENTSITE_OBJECTPARAM, &unk);
181         if(unk) {
182             IOleClientSite *client = NULL;
183
184             hres = IUnknown_QueryInterface(unk, &IID_IOleClientSite, (void**)&client);
185             if(SUCCEEDED(hres)) {
186                 TRACE("Got client site %p\n", client);
187                 IOleObject_SetClientSite(OLEOBJ(This), client);
188                 IOleClientSite_Release(client);
189             }
190
191             IUnknown_Release(unk);
192         }
193     }
194
195     call_property_onchanged(This->cp_propnotif, DISPID_READYSTATE);
196
197     HTMLDocument_LockContainer(This, TRUE);
198     
199     hres = IMoniker_GetDisplayName(pimkName, pibc, NULL, &url);
200     if(FAILED(hres)) {
201         WARN("GetDiaplayName failed: %08lx\n", hres);
202         return hres;
203     }
204
205     TRACE("got url: %s\n", debugstr_w(url));
206
207     if(This->client) {
208         IOleCommandTarget *cmdtrg = NULL;
209
210         hres = IOleClientSite_QueryInterface(This->client, &IID_IOleCommandTarget,
211                 (void**)&cmdtrg);
212         if(SUCCEEDED(hres)) {
213             VARIANT var;
214
215             V_VT(&var) = VT_I4;
216             V_I4(&var) = 0;
217             IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 37, 0, &var, NULL);
218         }
219     }
220
221     bscallback = create_bscallback(pimkName);
222
223     task = mshtml_alloc(sizeof(task_t));
224
225     task->doc = This;
226     task->task_id = TASK_SETDOWNLOADSTATE;
227     task->next = NULL;
228
229     push_task(task);
230
231     if(This->nscontainer) {
232         nsIInputStream *post_data_stream = get_post_data_stream(pibc);
233
234         This->nscontainer->bscallback = bscallback;
235         nsres = nsIWebNavigation_LoadURI(This->nscontainer->navigation, url,
236                 LOAD_FLAGS_NONE, NULL, post_data_stream, NULL);
237         This->nscontainer->bscallback = NULL;
238
239         if(post_data_stream)
240             nsIInputStream_Release(post_data_stream);
241
242         if(!bscallback->nschannel)
243             ERR("bscallback->nschannel == NULL\n");
244
245         if(NS_SUCCEEDED(nsres)) {
246             /* FIXME: don't return here (URL Moniker needs to be good enough) */
247
248             IBindStatusCallback_Release(STATUSCLB(bscallback));
249             CoTaskMemFree(url);
250             return S_OK;
251         }else if(nsres != WINE_NS_LOAD_FROM_MONIKER) {
252             WARN("LoadURI failed: %08lx\n", nsres);
253         }
254     }
255
256     set_document_bscallback(This, bscallback);
257     hres = start_binding(bscallback);
258
259     IBindStatusCallback_Release(STATUSCLB(bscallback));
260     CoTaskMemFree(url);
261
262     return hres;
263 }
264
265 static HRESULT WINAPI PersistMoniker_Save(IPersistMoniker *iface, IMoniker *pimkName,
266         LPBC pbc, BOOL fRemember)
267 {
268     HTMLDocument *This = PERSISTMON_THIS(iface);
269     FIXME("(%p)->(%p %p %x)\n", This, pimkName, pbc, fRemember);
270     return E_NOTIMPL;
271 }
272
273 static HRESULT WINAPI PersistMoniker_SaveCompleted(IPersistMoniker *iface, IMoniker *pimkName, LPBC pibc)
274 {
275     HTMLDocument *This = PERSISTMON_THIS(iface);
276     FIXME("(%p)->(%p %p)\n", This, pimkName, pibc);
277     return E_NOTIMPL;
278 }
279
280 static HRESULT WINAPI PersistMoniker_GetCurMoniker(IPersistMoniker *iface, IMoniker **ppimkName)
281 {
282     HTMLDocument *This = PERSISTMON_THIS(iface);
283     FIXME("(%p)->(%p)\n", This, ppimkName);
284     return E_NOTIMPL;
285 }
286
287 static const IPersistMonikerVtbl PersistMonikerVtbl = {
288     PersistMoniker_QueryInterface,
289     PersistMoniker_AddRef,
290     PersistMoniker_Release,
291     PersistMoniker_GetClassID,
292     PersistMoniker_IsDirty,
293     PersistMoniker_Load,
294     PersistMoniker_Save,
295     PersistMoniker_SaveCompleted,
296     PersistMoniker_GetCurMoniker
297 };
298
299 /**********************************************************
300  * IMonikerProp implementation
301  */
302
303 #define MONPROP_THIS(iface) DEFINE_THIS(HTMLDocument, MonikerProp, iface)
304
305 static HRESULT WINAPI MonikerProp_QueryInterface(IMonikerProp *iface, REFIID riid, void **ppvObject)
306 {
307     HTMLDocument *This = MONPROP_THIS(iface);
308     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
309 }
310
311 static ULONG WINAPI MonikerProp_AddRef(IMonikerProp *iface)
312 {
313     HTMLDocument *This = MONPROP_THIS(iface);
314     return IHTMLDocument2_AddRef(HTMLDOC(This));
315 }
316
317 static ULONG WINAPI MonikerProp_Release(IMonikerProp *iface)
318 {
319     HTMLDocument *This = MONPROP_THIS(iface);
320     return IHTMLDocument_Release(HTMLDOC(This));
321 }
322
323 static HRESULT WINAPI MonikerProp_PutProperty(IMonikerProp *iface, MONIKERPROPERTY mkp, LPCWSTR val)
324 {
325     HTMLDocument *This = MONPROP_THIS(iface);
326     FIXME("(%p)->(%d %s)\n", This, mkp, debugstr_w(val));
327     return E_NOTIMPL;
328 }
329
330 static const IMonikerPropVtbl MonikerPropVtbl = {
331     MonikerProp_QueryInterface,
332     MonikerProp_AddRef,
333     MonikerProp_Release,
334     MonikerProp_PutProperty
335 };
336
337 /**********************************************************
338  * IPersistFile implementation
339  */
340
341 #define PERSISTFILE_THIS(iface) DEFINE_THIS(HTMLDocument, PersistFile, iface)
342
343 static HRESULT WINAPI PersistFile_QueryInterface(IPersistFile *iface, REFIID riid, void **ppvObject)
344 {
345     HTMLDocument *This = PERSISTFILE_THIS(iface);
346     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppvObject);
347 }
348
349 static ULONG WINAPI PersistFile_AddRef(IPersistFile *iface)
350 {
351     HTMLDocument *This = PERSISTFILE_THIS(iface);
352     return IHTMLDocument2_AddRef(HTMLDOC(This));
353 }
354
355 static ULONG WINAPI PersistFile_Release(IPersistFile *iface)
356 {
357     HTMLDocument *This = PERSISTFILE_THIS(iface);
358     return IHTMLDocument2_Release(HTMLDOC(This));
359 }
360
361 static HRESULT WINAPI PersistFile_GetClassID(IPersistFile *iface, CLSID *pClassID)
362 {
363     HTMLDocument *This = PERSISTFILE_THIS(iface);
364
365     TRACE("(%p)->(%p)\n", This, pClassID);
366
367     if(!pClassID)
368         return E_INVALIDARG;
369
370     memcpy(pClassID, &CLSID_HTMLDocument, sizeof(CLSID));
371     return S_OK;
372 }
373
374 static HRESULT WINAPI PersistFile_IsDirty(IPersistFile *iface)
375 {
376     HTMLDocument *This = PERSISTFILE_THIS(iface);
377     FIXME("(%p)\n", This);
378     return E_NOTIMPL;
379 }
380
381 static HRESULT WINAPI PersistFile_Load(IPersistFile *iface, LPCOLESTR pszFileName, DWORD dwMode)
382 {
383     HTMLDocument *This = PERSISTFILE_THIS(iface);
384     FIXME("(%p)->(%s %08lx)\n", This, debugstr_w(pszFileName), dwMode);
385     return E_NOTIMPL;
386 }
387
388 static HRESULT WINAPI PersistFile_Save(IPersistFile *iface, LPCOLESTR pszFileName, BOOL fRemember)
389 {
390     HTMLDocument *This = PERSISTFILE_THIS(iface);
391     FIXME("(%p)->(%s %x)\n", This, debugstr_w(pszFileName), fRemember);
392     return E_NOTIMPL;
393 }
394
395 static HRESULT WINAPI PersistFile_SaveCompleted(IPersistFile *iface, LPCOLESTR pszFileName)
396 {
397     HTMLDocument *This = PERSISTFILE_THIS(iface);
398     FIXME("(%p)->(%s)\n", This, debugstr_w(pszFileName));
399     return E_NOTIMPL;
400 }
401
402 static HRESULT WINAPI PersistFile_GetCurFile(IPersistFile *iface, LPOLESTR *pszFileName)
403 {
404     HTMLDocument *This = PERSISTFILE_THIS(iface);
405     FIXME("(%p)->(%p)\n", This, pszFileName);
406     return E_NOTIMPL;
407 }
408
409 static const IPersistFileVtbl PersistFileVtbl = {
410     PersistFile_QueryInterface,
411     PersistFile_AddRef,
412     PersistFile_Release,
413     PersistFile_GetClassID,
414     PersistFile_IsDirty,
415     PersistFile_Load,
416     PersistFile_Save,
417     PersistFile_SaveCompleted,
418     PersistFile_GetCurFile
419 };
420
421 #define PERSTRINIT_THIS(iface) DEFINE_THIS(HTMLDocument, PersistStreamInit, iface)
422
423 static HRESULT WINAPI PersistStreamInit_QueryInterface(IPersistStreamInit *iface,
424                                                        REFIID riid, void **ppv)
425 {
426     HTMLDocument *This = PERSTRINIT_THIS(iface);
427     return IHTMLDocument2_QueryInterface(HTMLDOC(This), riid, ppv);
428 }
429
430 static ULONG WINAPI PersistStreamInit_AddRef(IPersistStreamInit *iface)
431 {
432     HTMLDocument *This = PERSTRINIT_THIS(iface);
433     return IHTMLDocument2_AddRef(HTMLDOC(This));
434 }
435
436 static ULONG WINAPI PersistStreamInit_Release(IPersistStreamInit *iface)
437 {
438     HTMLDocument *This = PERSTRINIT_THIS(iface);
439     return IHTMLDocument2_AddRef(HTMLDOC(This));
440 }
441
442 static HRESULT WINAPI PersistStreamInit_GetClassID(IPersistStreamInit *iface, CLSID *pClassID)
443 {
444     HTMLDocument *This = PERSTRINIT_THIS(iface);
445     return IPersist_GetClassID(PERSIST(This), pClassID);
446 }
447
448 static HRESULT WINAPI PersistStreamInit_IsDirty(IPersistStreamInit *iface)
449 {
450     HTMLDocument *This = PERSTRINIT_THIS(iface);
451     FIXME("(%p)\n", This);
452     return E_NOTIMPL;
453 }
454
455 static HRESULT WINAPI PersistStreamInit_Load(IPersistStreamInit *iface, LPSTREAM pStm)
456 {
457     HTMLDocument *This = PERSTRINIT_THIS(iface);
458     FIXME("(%p)->(%p)\n", This, pStm);
459     return E_NOTIMPL;
460 }
461
462 static HRESULT WINAPI PersistStreamInit_Save(IPersistStreamInit *iface, LPSTREAM pStm,
463                                              BOOL fClearDirty)
464 {
465     HTMLDocument *This = PERSTRINIT_THIS(iface);
466     FIXME("(%p)->(%p %x)\n", This, pStm, fClearDirty);
467     return E_NOTIMPL;
468 }
469
470 static HRESULT WINAPI PersistStreamInit_GetSizeMax(IPersistStreamInit *iface,
471                                                    ULARGE_INTEGER *pcbSize)
472 {
473     HTMLDocument *This = PERSTRINIT_THIS(iface);
474     FIXME("(%p)->(%p)\n", This, pcbSize);
475     return E_NOTIMPL;
476 }
477
478 static HRESULT WINAPI PersistStreamInit_InitNew(IPersistStreamInit *iface)
479 {
480     HTMLDocument *This = PERSTRINIT_THIS(iface);
481     FIXME("(%p)\n", This);
482     return E_NOTIMPL;
483 }
484
485 #undef PERSTRINIT_THIS
486
487 static const IPersistStreamInitVtbl PersistStreamInitVtbl = {
488     PersistStreamInit_QueryInterface,
489     PersistStreamInit_AddRef,
490     PersistStreamInit_Release,
491     PersistStreamInit_GetClassID,
492     PersistStreamInit_IsDirty,
493     PersistStreamInit_Load,
494     PersistStreamInit_Save,
495     PersistStreamInit_GetSizeMax,
496     PersistStreamInit_InitNew
497 };
498
499 void HTMLDocument_Persist_Init(HTMLDocument *This)
500 {
501     This->lpPersistMonikerVtbl = &PersistMonikerVtbl;
502     This->lpPersistFileVtbl = &PersistFileVtbl;
503     This->lpMonikerPropVtbl = &MonikerPropVtbl;
504     This->lpPersistStreamInitVtbl = &PersistStreamInitVtbl;
505
506     This->bscallback = NULL;
507 }