crypt32: Fixed day/month mismatch in time encoding routines.
[wine] / dlls / shdocvw / iexplore.c
1 /*
2  * SHDOCVW - Internet Explorer main frame window
3  *
4  * Copyright 2006 Mike McCormack (for CodeWeavers)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #define COBJMACROS
22
23 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "winuser.h"
27 #include "wingdi.h"
28 #include "winnls.h"
29 #include "ole2.h"
30 #include "exdisp.h"
31 #include "oleidl.h"
32
33 #include "shdocvw.h"
34
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
38
39 typedef struct tag_ieoc {
40     const IOleContainerVtbl *lpVtbl;
41     LONG ref;
42 } ieoc;
43
44 static ieoc *ieoc_from_IOleContainer(IOleContainer *iface)
45 {
46     return (ieoc*) iface;
47 }
48
49 static HRESULT WINAPI
50 ic_QueryInterface(IOleContainer *iface, REFIID riid, void **ppv)
51 {
52     if (IsEqualGUID(riid, &IID_IUnknown) ||
53         IsEqualGUID(riid, &IID_IOleClientSite))
54     {
55         IUnknown_AddRef(iface);
56         *ppv = iface;
57         return S_OK;
58     }
59     return E_NOINTERFACE;
60 }
61
62 static ULONG WINAPI ic_AddRef(IOleContainer *iface)
63 {
64     ieoc *This = ieoc_from_IOleContainer(iface);
65     return InterlockedIncrement(&This->ref);
66 }
67
68 static ULONG WINAPI ic_Release(IOleContainer *iface)
69 {
70     ieoc *This = ieoc_from_IOleContainer(iface);
71     LONG ref = InterlockedDecrement(&This->ref);
72     if (!ref)
73     {
74         HeapFree(GetProcessHeap(), 0, This);
75         SHDOCVW_UnlockModule();
76     }
77     TRACE("refcount = %ld\n", ref);
78     return ref;
79 }
80
81 static HRESULT WINAPI
82 ic_ParseDisplayName(IOleContainer *iface, IBindCtx *pbc, LPOLESTR pszDisplayName,
83                     ULONG *pchEaten, IMoniker **ppmkOut)
84 {
85     FIXME("\n");
86     return E_NOTIMPL;
87 }
88
89 static HRESULT WINAPI
90 ic_EnumObjects(IOleContainer *iface, DWORD grfFlags, IEnumUnknown **ppenum)
91 {
92     FIXME("\n");
93     return E_NOTIMPL;
94 }
95
96 static HRESULT WINAPI ic_LockContainer(IOleContainer *iface, BOOL fLock)
97 {
98     FIXME("\n");
99     return E_NOTIMPL;
100 }
101
102 static const IOleContainerVtbl ocVtbl =
103 {
104     ic_QueryInterface,
105     ic_AddRef,
106     ic_Release,
107     ic_ParseDisplayName,
108     ic_EnumObjects,
109     ic_LockContainer,
110 };
111
112 static IOleContainer * get_container(void)
113 {
114     IOleContainer *This;
115     ieoc *oc;
116
117     oc = HeapAlloc(GetProcessHeap(), 0, sizeof *oc);
118     oc->lpVtbl = &ocVtbl;
119     oc->ref = 0;
120
121     This = (IOleContainer*) oc;
122     IOleContainer_AddRef(This);
123     SHDOCVW_LockModule();
124
125     return This;
126 }
127
128 /**********************/
129
130 typedef struct tag_iecs {
131     const IOleClientSiteVtbl *lpVtbl;
132     const IOleInPlaceSiteVtbl *lpInPlaceVtbl;
133     LONG ref;
134     IOleContainer *container;
135     HWND hwnd;
136     IOleObject *oo;
137 } iecs;
138
139 static iecs *iecs_from_IOleClientSite(IOleClientSite *iface)
140 {
141     return (iecs*) iface;
142 }
143
144 static iecs *iecs_from_IOleInPlaceSite(IOleInPlaceSite *iface)
145 {
146     return (iecs*) (((char*)iface) - FIELD_OFFSET(iecs,lpInPlaceVtbl));
147 }
148
149 static ULONG WINAPI iecs_AddRef(iecs *This)
150 {
151     return InterlockedIncrement(&This->ref);
152 }
153
154 static ULONG WINAPI iecs_Release(iecs *This)
155 {
156     LONG ref = InterlockedDecrement(&This->ref);
157     if (!ref)
158     {
159         if (This->hwnd)
160             DestroyWindow(This->hwnd);
161         IOleContainer_Release(This->container);
162         HeapFree(GetProcessHeap(), 0, This);
163         SHDOCVW_UnlockModule();
164     }
165     return ref;
166 }
167
168 static HRESULT WINAPI
169 iecs_QueryInterface(iecs *This, REFIID riid, void **ppv)
170 {
171     if (IsEqualGUID(riid, &IID_IUnknown) ||
172         IsEqualGUID(riid, &IID_IOleClientSite))
173     {
174         iecs_AddRef(This);
175         *ppv = &This->lpVtbl;;
176         return S_OK;
177     }
178     if (IsEqualGUID(riid, &IID_IOleInPlaceSite) ||
179         IsEqualGUID(riid, &IID_IOleWindow))
180     {
181         iecs_AddRef(This);
182         *ppv = &This->lpInPlaceVtbl;
183         return S_OK;
184     }
185     FIXME("unknown interface %s\n", debugstr_guid(riid));
186     return E_NOINTERFACE;
187 }
188
189 static HRESULT WINAPI
190 cs_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
191 {
192     iecs *This = iecs_from_IOleClientSite(iface);
193     return iecs_QueryInterface(This, riid, ppv);
194 }
195
196 static ULONG WINAPI cs_AddRef(IOleClientSite *iface)
197 {
198     iecs *This = iecs_from_IOleClientSite(iface);
199     return iecs_AddRef(This);
200 }
201
202 static ULONG WINAPI cs_Release(IOleClientSite *iface)
203 {
204     iecs *This = iecs_from_IOleClientSite(iface);
205     return iecs_Release(This);
206 }
207
208 static HRESULT WINAPI cs_SaveObject(IOleClientSite *iface)
209 {
210     FIXME("\n");
211     return E_NOTIMPL;
212 }
213
214 static HRESULT WINAPI cs_GetMoniker(IOleClientSite *iface, DWORD dwAssign,
215                                     DWORD dwWhichMoniker, IMoniker **ppmk)
216 {
217     FIXME("\n");
218     return E_NOTIMPL;
219 }
220
221 static HRESULT WINAPI
222 cs_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
223 {
224     iecs *This = iecs_from_IOleClientSite(iface);
225
226     TRACE("\n");
227
228     IOleContainer_AddRef(This->container);
229     *ppContainer = This->container;
230     return S_OK;
231 }
232
233 static HRESULT WINAPI cs_ShowObject(IOleClientSite *iface)
234 {
235     FIXME("\n");
236     return E_NOTIMPL;
237 }
238
239 static HRESULT WINAPI cs_OnShowWindow(IOleClientSite *iface, BOOL fShow)
240 {
241     FIXME("\n");
242     return E_NOTIMPL;
243 }
244
245 static HRESULT WINAPI cs_RequestNewObjectLayout(IOleClientSite *iface)
246 {
247     FIXME("\n");
248     return E_NOTIMPL;
249 }
250
251 static const IOleClientSiteVtbl csVtbl =
252 {
253     cs_QueryInterface,
254     cs_AddRef,
255     cs_Release,
256     cs_SaveObject,
257     cs_GetMoniker,
258     cs_GetContainer,
259     cs_ShowObject,
260     cs_OnShowWindow,
261     cs_RequestNewObjectLayout,
262 };
263
264 static HRESULT WINAPI
265 is_QueryInterface(IOleInPlaceSite *iface, REFIID riid, void **ppv)
266 {
267     iecs *This = iecs_from_IOleInPlaceSite(iface);
268     return iecs_QueryInterface(This, riid, ppv);
269 }
270
271 static ULONG WINAPI is_AddRef(IOleInPlaceSite *iface)
272 {
273     iecs *This = iecs_from_IOleInPlaceSite(iface);
274     return iecs_AddRef(This);
275 }
276
277 static ULONG WINAPI is_Release(IOleInPlaceSite *iface)
278 {
279     iecs *This = iecs_from_IOleInPlaceSite(iface);
280     return iecs_Release(This);
281 }
282
283 static HRESULT WINAPI is_getWindow(IOleInPlaceSite *iface, HWND *phwnd)
284 {
285     iecs *This = iecs_from_IOleInPlaceSite(iface);
286
287     TRACE("\n");
288
289     *phwnd = This->hwnd;
290     return S_OK;
291 }
292
293 static HRESULT WINAPI
294 is_ContextSensitiveHelp(IOleInPlaceSite *iface, BOOL fEnterMode)
295 {
296     FIXME("\n");
297     return E_NOTIMPL;
298 }
299
300 static HRESULT WINAPI is_CanInPlaceActivate(IOleInPlaceSite *iface)
301 {
302     FIXME("\n");
303     return S_OK;
304 }
305
306 static HRESULT WINAPI is_OnInPlaceActivate(IOleInPlaceSite *iface)
307 {
308     TRACE("\n");
309     return S_OK;
310 }
311
312 static HRESULT WINAPI is_OnUIActivate(IOleInPlaceSite *iface)
313 {
314     FIXME("\n");
315     return E_NOTIMPL;
316 }
317
318 static HRESULT WINAPI
319 is_GetWindowContext(IOleInPlaceSite *iface, IOleInPlaceFrame **ppFrame,
320                     IOleInPlaceUIWindow ** ppDoc, LPRECT lprcPosRect,
321                     LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
322 {
323     iecs *This = iecs_from_IOleInPlaceSite(iface);
324
325     TRACE("%p\n", This);
326
327     *ppFrame = NULL;
328     *ppDoc = NULL;
329     GetClientRect(This->hwnd, lprcPosRect);
330     GetClientRect(This->hwnd, lprcClipRect);
331     if (lpFrameInfo->cb != sizeof *lpFrameInfo)
332         ERR("frame info wrong size\n");
333     lpFrameInfo->cAccelEntries = 0;
334     lpFrameInfo->fMDIApp = FALSE;
335     lpFrameInfo->haccel = 0;
336     lpFrameInfo->hwndFrame = This->hwnd;
337
338     return S_OK;
339 }
340
341 static HRESULT WINAPI is_Scroll(IOleInPlaceSite *iface, SIZE scrollExtent)
342 {
343     FIXME("\n");
344     return E_NOTIMPL;
345 }
346
347 static HRESULT WINAPI is_OnUIDeactivate(IOleInPlaceSite *iface, BOOL fUndoable)
348 {
349     FIXME("\n");
350     return E_NOTIMPL;
351 }
352
353 static HRESULT WINAPI is_OnInPlaceDeactivate(IOleInPlaceSite *iface)
354 {
355     FIXME("\n");
356     return E_NOTIMPL;
357 }
358
359 static HRESULT WINAPI is_DiscardUndoState(IOleInPlaceSite *iface)
360 {
361     FIXME("\n");
362     return E_NOTIMPL;
363 }
364
365 static const IOleInPlaceSiteVtbl isVtbl =
366 {
367     is_QueryInterface,
368     is_AddRef,
369     is_Release,
370     is_getWindow,
371     is_ContextSensitiveHelp,
372     is_CanInPlaceActivate,
373     is_OnInPlaceActivate,
374     is_OnUIActivate,
375     is_GetWindowContext,
376     is_Scroll,
377     is_OnUIDeactivate,
378     is_OnInPlaceDeactivate,
379     is_DiscardUndoState,
380 };
381
382 static const WCHAR szIEWinFrame[] = { 'I','E','F','r','a','m','e',0 };
383
384 static LRESULT iewnd_OnCreate(HWND hwnd, LPCREATESTRUCTW lpcs)
385 {
386     SetWindowLongPtrW(hwnd, 0, (LONG_PTR) lpcs->lpCreateParams);
387     return 0;
388 }
389
390 static LRESULT iewnd_OnSize(iecs *This, INT width, INT height)
391 {
392     SIZEL sz;
393
394     TRACE("%p %d %d\n", This, width, height);
395
396     sz.cx = width;
397     sz.cy = height;
398     IOleObject_SetExtent(This->oo, DVASPECT_CONTENT, &sz);
399     return 0;
400 }
401
402 static LRESULT iewnd_OnDestroy(iecs *This)
403 {
404     TRACE("%p\n", This);
405
406     This->hwnd = NULL;
407     IOleObject_Close(This->oo, OLECLOSE_NOSAVE);
408     IOleObject_Release(This->oo);
409     This->oo = NULL;
410     PostQuitMessage(0);
411
412     return 0;
413 }
414
415 static LRESULT CALLBACK
416 ie_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
417 {
418     iecs *This = (iecs*) GetWindowLongPtrW(hwnd, 0);
419
420     switch (msg)
421     {
422     case WM_CREATE:
423         return iewnd_OnCreate(hwnd, (LPCREATESTRUCTW)lparam);
424     case WM_DESTROY:
425         return iewnd_OnDestroy(This);
426     case WM_SIZE:
427         return iewnd_OnSize(This, LOWORD(lparam), HIWORD(lparam));
428     }
429     return DefWindowProcW(hwnd, msg, wparam, lparam);
430 }
431
432 static IOleClientSite * get_client_site(IOleObject *oo, HWND *phwnd)
433 {
434     static const WCHAR winname[] = {
435         'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r',0};
436     IOleClientSite *This;
437     HWND hwnd;
438     iecs *cs;
439
440     cs = HeapAlloc(GetProcessHeap(), 0, sizeof *cs);
441     if (!cs)
442         return NULL;
443
444     cs->ref = 0;
445     cs->lpVtbl = &csVtbl;
446     cs->lpInPlaceVtbl = &isVtbl;
447     cs->container = get_container();
448     cs->oo = oo;
449
450     hwnd = CreateWindowW(szIEWinFrame, winname, WS_VISIBLE|WS_OVERLAPPEDWINDOW,
451         CW_USEDEFAULT, CW_USEDEFAULT,
452         CW_USEDEFAULT, CW_USEDEFAULT,
453         NULL, NULL, shdocvw_hinstance, cs);
454     if (!hwnd)
455     {
456         HeapFree(GetProcessHeap(), 0, cs);
457         return NULL;
458     }
459
460     IOleObject_AddRef(oo);
461     cs->hwnd = hwnd;
462     *phwnd = hwnd;
463
464     This = (IOleClientSite*) cs;
465     IOleClientSite_AddRef(This);
466     SHDOCVW_LockModule();
467
468     return This;
469 }
470
471 void register_iewindow_class(void)
472 {
473     WNDCLASSW wc;
474
475     memset(&wc, 0, sizeof wc);
476     wc.style = 0;
477     wc.lpfnWndProc = ie_window_proc;
478     wc.cbClsExtra = 0;
479     wc.cbWndExtra = sizeof(iecs *);
480     wc.hInstance = shdocvw_hinstance;
481     wc.hIcon = 0;
482     wc.hCursor = LoadCursorW(0, MAKEINTRESOURCEW(IDI_APPLICATION));
483     wc.hbrBackground = 0;
484     wc.lpszClassName = szIEWinFrame;
485     wc.lpszMenuName = NULL;
486
487     RegisterClassW(&wc);
488 }
489
490 void unregister_iewindow_class(void)
491 {
492     UnregisterClassW(szIEWinFrame, shdocvw_hinstance);
493 }
494
495 BOOL create_ie_window(LPCWSTR url)
496 {
497     IWebBrowser2 *wb = NULL;
498     IOleObject *oo = NULL;
499     IOleClientSite *cs = NULL;
500     HRESULT r;
501     MSG msg;
502     RECT rcClient = { 0,0,100,100 };
503     BSTR bstrUrl;
504     HWND hwnd = NULL;
505
506     /* create the web browser */
507     r = CoCreateInstance(&CLSID_WebBrowser, NULL, CLSCTX_INPROC_SERVER,
508                         &IID_IWebBrowser2, (LPVOID)&wb);
509     if (FAILED(r))
510         goto error;
511
512     /* get its IOleObject interface */
513     r = IWebBrowser2_QueryInterface(wb, &IID_IOleObject, (void**) &oo);
514     if (FAILED(r))
515         goto error;
516
517     /* create the window frame for the browser object */
518     cs = get_client_site(oo, &hwnd);
519     if (!cs)
520         goto error;
521
522     /* attach the browser to the window frame */
523     r = IOleObject_SetClientSite(oo, cs);
524     if (FAILED(r))
525         goto error;
526
527     /* activate the browser */
528     r = IOleObject_DoVerb(oo, OLEIVERB_INPLACEACTIVATE, &msg, cs, 0, hwnd, &rcClient);
529     if (FAILED(r))
530         goto error;
531
532     /* navigate to the first page */
533     bstrUrl = SysAllocString(url);
534     IWebBrowser2_Navigate(wb, bstrUrl, NULL, NULL, NULL, NULL);
535
536     /* run the message loop for this thread */
537     while (GetMessageW(&msg, 0, 0, 0))
538     {
539         TranslateMessage(&msg);
540         DispatchMessageW(&msg);
541     }
542
543     r = S_OK;
544
545     /* clean up */
546 error:
547     if (cs)
548         IOleClientSite_Release(cs);
549     if (oo)
550         IOleObject_Release(oo);
551     if (wb)
552         IOleObject_Release(wb);
553
554     return r;
555 }