include: Define more wuapi interfaces to avoid undefined forward declarations.
[wine] / dlls / mshtml / tests / activex.c
1 /*
2  * Copyright 2010 Jacek Caban for CodeWeavers
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 #define COBJMACROS
20 #define CONST_VTABLE
21
22 #include <wine/test.h>
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "ole2.h"
29 #include "mshtml.h"
30 #include "docobj.h"
31 #include "hlink.h"
32 #include "mshtmhst.h"
33 #include "mshtml_test.h"
34
35 #define DEFINE_EXPECT(func) \
36     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
37
38 #define SET_EXPECT(func) \
39     do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
40
41 #define CHECK_EXPECT2(func) \
42     do { \
43         ok(expect_ ##func, "unexpected call " #func "\n"); \
44         called_ ## func = TRUE; \
45     }while(0)
46
47 #define CHECK_EXPECT(func) \
48     do { \
49         CHECK_EXPECT2(func); \
50         expect_ ## func = FALSE; \
51     }while(0)
52
53 #define CHECK_CALLED(func) \
54     do { \
55         ok(called_ ## func, "expected " #func "\n"); \
56         expect_ ## func = called_ ## func = FALSE; \
57     }while(0)
58
59 DEFINE_EXPECT(CreateInstance);
60 DEFINE_EXPECT(FreezeEvents_TRUE);
61 DEFINE_EXPECT(FreezeEvents_FALSE);
62 DEFINE_EXPECT(QuickActivate);
63
64 static HWND container_hwnd;
65
66 #define TESTACTIVEX_CLSID "{178fc163-f585-4e24-9c13-4bb7f6680746}"
67
68 static const GUID CLSID_TestActiveX =
69     {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xf6,0x68,0x07,0x46}};
70
71 static const char *debugstr_guid(REFIID riid)
72 {
73     static char buf[50];
74
75     sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
76             riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
77             riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
78             riid->Data4[5], riid->Data4[6], riid->Data4[7]);
79
80     return buf;
81 }
82
83 static const char object_ax_str[] =
84     "<html><head></head><body>"
85     "<object classid=\"clsid:" TESTACTIVEX_CLSID "\" width=\"300\" height=\"200\" id=\"objid\">"
86     "<param name=\"param_name\" value=\"param_value\">"
87     "</object>"
88     "</body></html>";
89
90 static const REFIID pluginhost_iids[] = {
91     &IID_IOleClientSite,
92     &IID_IAdviseSink,
93     &IID_IAdviseSinkEx,
94     &IID_IPropertyNotifySink,
95     &IID_IDispatch,
96     &IID_IOleWindow,
97     &IID_IOleInPlaceSite,
98     &IID_IOleInPlaceSiteEx,
99     &IID_IOleControlSite,
100     &IID_IBindHost,
101     &IID_IServiceProvider,
102     NULL
103 };
104
105 static const char *dbgstr_guid(REFIID riid)
106 {
107     static char buf[50];
108
109     sprintf(buf, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
110             riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
111             riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
112             riid->Data4[5], riid->Data4[6], riid->Data4[7]);
113
114     return buf;
115 }
116
117 static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2)
118 {
119     IUnknown *unk1, *unk2;
120
121     if(iface1 == iface2)
122         return TRUE;
123
124     IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk1);
125     IUnknown_Release(unk1);
126     IUnknown_QueryInterface(iface2, &IID_IUnknown, (void**)&unk2);
127     IUnknown_Release(unk2);
128
129     return unk1 == unk2;
130 }
131
132 #define test_ifaces(i,ids) _test_ifaces(__LINE__,i,ids)
133 static void _test_ifaces(unsigned line, IUnknown *iface, REFIID *iids)
134 {
135     const IID * const *piid;
136     IUnknown *unk;
137     HRESULT hres;
138
139      for(piid = iids; *piid; piid++) {
140         hres = IDispatch_QueryInterface(iface, *piid, (void**)&unk);
141         ok_(__FILE__,line) (hres == S_OK, "Could not get %s interface: %08x\n", dbgstr_guid(*piid), hres);
142         if(SUCCEEDED(hres))
143             IUnknown_Release(unk);
144     }
145 }
146
147 static HRESULT ax_qi(REFIID,void**);
148
149 static HRESULT WINAPI OleControl_QueryInterface(IOleControl *iface, REFIID riid, void **ppv)
150 {
151     return ax_qi(riid, ppv);
152 }
153
154 static ULONG WINAPI OleControl_AddRef(IOleControl *iface)
155 {
156     return 2;
157 }
158
159 static ULONG WINAPI OleControl_Release(IOleControl *iface)
160 {
161     return 1;
162 }
163
164 static HRESULT WINAPI OleControl_GetControlInfo(IOleControl *iface, CONTROLINFO *pCI)
165 {
166     ok(0, "unexpected call\n");
167     return E_NOTIMPL;
168 }
169
170 static HRESULT WINAPI OleControl_OnMnemonic(IOleControl *iface, MSG *mMsg)
171 {
172     ok(0, "unexpected call\n");
173     return E_NOTIMPL;
174 }
175
176 static HRESULT WINAPI OleControl_OnAmbientPropertyChange(IOleControl *iface, DISPID dispID)
177 {
178     ok(0, "unexpected call\n");
179     return E_NOTIMPL;
180 }
181
182 static HRESULT WINAPI OleControl_FreezeEvents(IOleControl *iface, BOOL bFreeze)
183 {
184     if(bFreeze)
185         CHECK_EXPECT2(FreezeEvents_TRUE);
186     else
187         CHECK_EXPECT2(FreezeEvents_FALSE);
188     return S_OK;
189 }
190
191 static const IOleControlVtbl OleControlVtbl = {
192     OleControl_QueryInterface,
193     OleControl_AddRef,
194     OleControl_Release,
195     OleControl_GetControlInfo,
196     OleControl_OnMnemonic,
197     OleControl_OnAmbientPropertyChange,
198     OleControl_FreezeEvents
199 };
200
201 static IOleControl OleControl = { &OleControlVtbl };
202
203 static HRESULT WINAPI QuickActivate_QueryInterface(IQuickActivate *iface, REFIID riid, void **ppv)
204 {
205     return ax_qi(riid, ppv);
206 }
207
208 static ULONG WINAPI QuickActivate_AddRef(IQuickActivate *iface)
209 {
210     return 2;
211 }
212
213 static ULONG WINAPI QuickActivate_Release(IQuickActivate *iface)
214 {
215     return 1;
216 }
217
218 static HRESULT WINAPI QuickActivate_QuickActivate(IQuickActivate *iface, QACONTAINER *container, QACONTROL *control)
219 {
220     CHECK_EXPECT(QuickActivate);
221
222     ok(container != NULL, "container == NULL\n");
223     ok(container->cbSize == sizeof(*container), "container->cbSize = %d\n", container->cbSize);
224     ok(container->pClientSite != NULL, "container->pClientSite == NULL\n");
225     ok(container->pAdviseSink != NULL, "container->pAdviseSink == NULL\n");
226     ok(container->pPropertyNotifySink != NULL, "container->pPropertyNotifySink == NULL\n");
227     ok(!container->pUnkEventSink, "container->pUnkEventSink != NULL\n");
228     ok(container->dwAmbientFlags == (QACONTAINER_SUPPORTSMNEMONICS|QACONTAINER_MESSAGEREFLECT|QACONTAINER_USERMODE),
229        "container->dwAmbientFlags = %x\n", container->dwAmbientFlags);
230     ok(!container->colorFore, "container->colorFore == 0\n"); /* FIXME */
231     todo_wine
232     ok(container->colorBack, "container->colorBack == 0\n"); /* FIXME */
233     todo_wine
234     ok(container->pFont != NULL, "container->pFont == NULL\n");
235     todo_wine
236     ok(container->pUndoMgr != NULL, "container->pUndoMgr == NULL\n");
237     ok(!container->dwAppearance, "container->dwAppearance = %x\n", container->dwAppearance);
238     ok(!container->lcid, "container->lcid = %x\n", container->lcid);
239     ok(!container->hpal, "container->hpal = %p\n", container->hpal);
240     ok(!container->pBindHost, "container->pBindHost != NULL\n");
241     ok(!container->pOleControlSite, "container->pOleControlSite != NULL\n");
242     ok(!container->pServiceProvider, "container->pServiceProvider != NULL\n");
243
244     ok(control->cbSize == sizeof(*control), "control->cbSize = %d\n", control->cbSize);
245     ok(!control->dwMiscStatus, "control->dwMiscStatus = %x\n", control->dwMiscStatus);
246     ok(!control->dwViewStatus, "control->dwViewStatus = %x\n", control->dwViewStatus);
247     ok(!control->dwEventCookie, "control->dwEventCookie = %x\n", control->dwEventCookie);
248     ok(!control->dwPropNotifyCookie, "control->dwPropNotifyCookie = %x\n", control->dwPropNotifyCookie);
249     ok(!control->dwPointerActivationPolicy, "control->dwPointerActivationPolicy = %x\n", control->dwPointerActivationPolicy);
250
251     ok(iface_cmp((IUnknown*)container->pClientSite, (IUnknown*)container->pAdviseSink),
252        "container->pClientSite != container->pAdviseSink\n");
253     ok(iface_cmp((IUnknown*)container->pClientSite, (IUnknown*)container->pPropertyNotifySink),
254        "container->pClientSite != container->pPropertyNotifySink\n");
255     test_ifaces((IUnknown*)container->pClientSite, pluginhost_iids);
256
257     return S_OK;
258 }
259
260 static HRESULT WINAPI QuickActivate_SetContentExtent(IQuickActivate *iface, LPSIZEL pSizel)
261 {
262     ok(0, "unexpected call\n");
263     return E_NOTIMPL;
264 }
265
266 static HRESULT WINAPI QuickActivate_GetContentExtent(IQuickActivate *iface, LPSIZEL pSizel)
267 {
268     ok(0, "unexpected call\n");
269     return E_NOTIMPL;
270 }
271
272 static const IQuickActivateVtbl QuickActivateVtbl = {
273     QuickActivate_QueryInterface,
274     QuickActivate_AddRef,
275     QuickActivate_Release,
276     QuickActivate_QuickActivate,
277     QuickActivate_GetContentExtent,
278     QuickActivate_SetContentExtent
279 };
280
281 static IQuickActivate QuickActivate = { &QuickActivateVtbl };
282
283 static HRESULT ax_qi(REFIID riid, void **ppv)
284 {
285     if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IOleControl)) {
286         *ppv = &OleControl;
287         return S_OK;
288     }
289
290     if(IsEqualGUID(riid, &IID_IQuickActivate)) {
291         *ppv = &QuickActivate;
292         return S_OK;
293     }
294
295     *ppv = NULL;
296     return E_NOINTERFACE;
297 }
298
299 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
300 {
301     *ppv = NULL;
302
303     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IClassFactory, riid)) {
304         *ppv = iface;
305         return S_OK;
306     }
307
308     if(IsEqualGUID(&IID_IMarshal, riid))
309         return E_NOINTERFACE;
310     if(IsEqualGUID(&CLSID_IdentityUnmarshal, riid))
311         return E_NOINTERFACE;
312     if(IsEqualGUID(&IID_IClassFactoryEx, riid))
313         return E_NOINTERFACE; /* TODO */
314
315     ok(0, "unexpected riid %s\n", debugstr_guid(riid));
316     return E_NOTIMPL;
317 }
318
319 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
320 {
321     return 2;
322 }
323
324 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
325 {
326     return 1;
327 }
328
329 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
330 {
331     CHECK_EXPECT(CreateInstance);
332
333     ok(!outer, "outer = %p\n", outer);
334     ok(IsEqualGUID(riid, &IID_IUnknown), "riid = %s\n", debugstr_guid(riid));
335
336     *ppv = &OleControl;
337     return S_OK;
338 }
339
340 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
341 {
342     ok(0, "unexpected call\n");
343     return S_OK;
344 }
345
346 static const IClassFactoryVtbl ClassFactoryVtbl = {
347     ClassFactory_QueryInterface,
348     ClassFactory_AddRef,
349     ClassFactory_Release,
350     ClassFactory_CreateInstance,
351     ClassFactory_LockServer
352 };
353
354 static HRESULT cs_qi(REFIID,void **);
355 static IOleDocumentView *view;
356
357 static HRESULT WINAPI InPlaceFrame_QueryInterface(IOleInPlaceFrame *iface, REFIID riid, void **ppv)
358 {
359     static const GUID undocumented_frame_iid = {0xfbece6c9,0x48d7,0x4a37,{0x8f,0xe3,0x6a,0xd4,0x27,0x2f,0xdd,0xac}};
360
361     if(!IsEqualGUID(&undocumented_frame_iid, riid))
362         ok(0, "unexpected riid %s\n", debugstr_guid(riid));
363
364     *ppv = NULL;
365     return E_NOINTERFACE;
366 }
367
368 static ULONG WINAPI InPlaceFrame_AddRef(IOleInPlaceFrame *iface)
369 {
370     return 2;
371 }
372
373 static ULONG WINAPI InPlaceFrame_Release(IOleInPlaceFrame *iface)
374 {
375     return 1;
376 }
377
378 static HRESULT WINAPI InPlaceFrame_GetWindow(IOleInPlaceFrame *iface, HWND *phwnd)
379 {
380     return E_NOTIMPL;
381 }
382
383 static HRESULT WINAPI InPlaceFrame_ContextSensitiveHelp(IOleInPlaceFrame *iface, BOOL fEnterMode)
384 {
385     return E_NOTIMPL;
386 }
387
388 static HRESULT WINAPI InPlaceFrame_GetBorder(IOleInPlaceFrame *iface, LPRECT lprectBorder)
389 {
390     return E_NOTIMPL;
391 }
392
393 static HRESULT WINAPI InPlaceFrame_RequestBorderSpace(IOleInPlaceFrame *iface,
394         LPCBORDERWIDTHS pborderwidths)
395 {
396     return E_NOTIMPL;
397 }
398
399 static HRESULT WINAPI InPlaceFrame_SetBorderSpace(IOleInPlaceFrame *iface,
400         LPCBORDERWIDTHS pborderwidths)
401 {
402     return S_OK;
403 }
404
405 static HRESULT WINAPI InPlaceUIWindow_SetActiveObject(IOleInPlaceFrame *iface,
406         IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
407 {
408     return S_OK;
409 }
410
411 static HRESULT WINAPI InPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface,
412         IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
413 {
414     return S_OK;
415 }
416
417 static HRESULT WINAPI InPlaceFrame_InsertMenus(IOleInPlaceFrame *iface, HMENU hmenuShared,
418         LPOLEMENUGROUPWIDTHS lpMenuWidths)
419 {
420     return E_NOTIMPL;
421 }
422
423 static HRESULT WINAPI InPlaceFrame_SetMenu(IOleInPlaceFrame *iface, HMENU hmenuShared,
424         HOLEMENU holemenu, HWND hwndActiveObject)
425 {
426     ok(0, "unexpected call\n");
427     return E_NOTIMPL;
428 }
429
430 static HRESULT WINAPI InPlaceFrame_RemoveMenus(IOleInPlaceFrame *iface, HMENU hmenuShared)
431 {
432     ok(0, "unexpected call\n");
433     return E_NOTIMPL;
434 }
435
436 static HRESULT WINAPI InPlaceFrame_SetStatusText(IOleInPlaceFrame *iface, LPCOLESTR pszStatusText)
437 {
438     return S_OK;
439 }
440
441 static HRESULT WINAPI InPlaceFrame_EnableModeless(IOleInPlaceFrame *iface, BOOL fEnable)
442 {
443     return E_NOTIMPL;
444 }
445
446 static HRESULT WINAPI InPlaceFrame_TranslateAccelerator(IOleInPlaceFrame *iface, LPMSG lpmsg, WORD wID)
447 {
448     ok(0, "unexpected call\n");
449     return E_NOTIMPL;
450 }
451
452 static const IOleInPlaceFrameVtbl InPlaceFrameVtbl = {
453     InPlaceFrame_QueryInterface,
454     InPlaceFrame_AddRef,
455     InPlaceFrame_Release,
456     InPlaceFrame_GetWindow,
457     InPlaceFrame_ContextSensitiveHelp,
458     InPlaceFrame_GetBorder,
459     InPlaceFrame_RequestBorderSpace,
460     InPlaceFrame_SetBorderSpace,
461     InPlaceFrame_SetActiveObject,
462     InPlaceFrame_InsertMenus,
463     InPlaceFrame_SetMenu,
464     InPlaceFrame_RemoveMenus,
465     InPlaceFrame_SetStatusText,
466     InPlaceFrame_EnableModeless,
467     InPlaceFrame_TranslateAccelerator
468 };
469
470 static IOleInPlaceFrame InPlaceFrame = { &InPlaceFrameVtbl };
471
472 static const IOleInPlaceFrameVtbl InPlaceUIWindowVtbl = {
473     InPlaceFrame_QueryInterface,
474     InPlaceFrame_AddRef,
475     InPlaceFrame_Release,
476     InPlaceFrame_GetWindow,
477     InPlaceFrame_ContextSensitiveHelp,
478     InPlaceFrame_GetBorder,
479     InPlaceFrame_RequestBorderSpace,
480     InPlaceFrame_SetBorderSpace,
481     InPlaceUIWindow_SetActiveObject,
482 };
483
484 static IOleInPlaceFrame InPlaceUIWindow = { &InPlaceUIWindowVtbl };
485
486 static HRESULT WINAPI InPlaceSite_QueryInterface(IOleInPlaceSite *iface, REFIID riid, void **ppv)
487 {
488     return cs_qi(riid, ppv);
489 }
490
491 static ULONG WINAPI InPlaceSite_AddRef(IOleInPlaceSite *iface)
492 {
493     return 2;
494 }
495
496 static ULONG WINAPI InPlaceSite_Release(IOleInPlaceSite *iface)
497 {
498     return 1;
499 }
500
501 static HRESULT WINAPI InPlaceSite_GetWindow(IOleInPlaceSite *iface, HWND *phwnd)
502 {
503     *phwnd = container_hwnd;
504     return S_OK;
505 }
506
507 static HRESULT WINAPI InPlaceSite_ContextSensitiveHelp(IOleInPlaceSite *iface, BOOL fEnterMode)
508 {
509     ok(0, "unexpected call\n");
510     return E_NOTIMPL;
511 }
512
513 static HRESULT WINAPI InPlaceSite_CanInPlaceActivate(IOleInPlaceSite *iface)
514 {
515     return S_OK;
516 }
517
518 static HRESULT WINAPI InPlaceSite_OnInPlaceActivate(IOleInPlaceSite *iface)
519 {
520     return S_OK;
521 }
522
523 static HRESULT WINAPI InPlaceSite_OnUIActivate(IOleInPlaceSite *iface)
524 {
525     return S_OK;
526 }
527
528 static HRESULT WINAPI InPlaceSite_GetWindowContext(IOleInPlaceSite *iface,
529         IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect,
530         LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
531 {
532     static const RECT rect = {0,0,500,500};
533
534     *ppFrame = &InPlaceFrame;
535     *ppDoc = (IOleInPlaceUIWindow*)&InPlaceUIWindow;
536     *lprcPosRect = rect;
537     *lprcClipRect = rect;
538
539     lpFrameInfo->cb = sizeof(*lpFrameInfo);
540     lpFrameInfo->fMDIApp = FALSE;
541     lpFrameInfo->hwndFrame = container_hwnd;
542     lpFrameInfo->haccel = NULL;
543     lpFrameInfo->cAccelEntries = 0;
544
545     return S_OK;
546 }
547
548 static HRESULT WINAPI InPlaceSite_Scroll(IOleInPlaceSite *iface, SIZE scrollExtant)
549 {
550     return E_NOTIMPL;
551 }
552
553 static HRESULT WINAPI InPlaceSite_OnUIDeactivate(IOleInPlaceSite *iface, BOOL fUndoable)
554 {
555     return S_OK;
556 }
557
558 static HRESULT WINAPI InPlaceSite_OnInPlaceDeactivate(IOleInPlaceSite *iface)
559 {
560     return S_OK;
561 }
562
563 static HRESULT WINAPI InPlaceSite_DiscardUndoState(IOleInPlaceSite *iface)
564 {
565     return E_NOTIMPL;
566 }
567
568 static HRESULT WINAPI InPlaceSite_DeactivateAndUndo(IOleInPlaceSite *iface)
569 {
570     return E_NOTIMPL;
571 }
572
573 static HRESULT WINAPI InPlaceSite_OnPosRectChange(IOleInPlaceSite *iface, LPCRECT lprcPosRect)
574 {
575     return E_NOTIMPL;
576 }
577
578 static const IOleInPlaceSiteVtbl InPlaceSiteVtbl = {
579     InPlaceSite_QueryInterface,
580     InPlaceSite_AddRef,
581     InPlaceSite_Release,
582     InPlaceSite_GetWindow,
583     InPlaceSite_ContextSensitiveHelp,
584     InPlaceSite_CanInPlaceActivate,
585     InPlaceSite_OnInPlaceActivate,
586     InPlaceSite_OnUIActivate,
587     InPlaceSite_GetWindowContext,
588     InPlaceSite_Scroll,
589     InPlaceSite_OnUIDeactivate,
590     InPlaceSite_OnInPlaceDeactivate,
591     InPlaceSite_DiscardUndoState,
592     InPlaceSite_DeactivateAndUndo,
593     InPlaceSite_OnPosRectChange,
594 };
595
596 static IOleInPlaceSite InPlaceSite = { &InPlaceSiteVtbl };
597
598 static HRESULT WINAPI ClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
599 {
600     return cs_qi(riid, ppv);
601 }
602
603 static ULONG WINAPI ClientSite_AddRef(IOleClientSite *iface)
604 {
605     return 2;
606 }
607
608 static ULONG WINAPI ClientSite_Release(IOleClientSite *iface)
609 {
610     return 1;
611 }
612
613 static HRESULT WINAPI ClientSite_SaveObject(IOleClientSite *iface)
614 {
615     ok(0, "unexpected call\n");
616     return E_NOTIMPL;
617 }
618
619 static HRESULT WINAPI ClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign, DWORD dwWhichMoniker,
620         IMoniker **ppmon)
621 {
622     ok(0, "unexpected call\n");
623     return E_NOTIMPL;
624 }
625
626 static HRESULT WINAPI ClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
627 {
628     return E_NOTIMPL;
629 }
630
631 static HRESULT WINAPI ClientSite_ShowObject(IOleClientSite *iface)
632 {
633     ok(0, "unexpected call\n");
634     return E_NOTIMPL;
635 }
636
637 static HRESULT WINAPI ClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow)
638 {
639     ok(0, "unexpected call\n");
640     return E_NOTIMPL;
641 }
642
643 static HRESULT WINAPI ClientSite_RequestNewObjectLayout(IOleClientSite *iface)
644 {
645     ok(0, "unexpected call\n");
646     return E_NOTIMPL;
647 }
648
649 static const IOleClientSiteVtbl ClientSiteVtbl = {
650     ClientSite_QueryInterface,
651     ClientSite_AddRef,
652     ClientSite_Release,
653     ClientSite_SaveObject,
654     ClientSite_GetMoniker,
655     ClientSite_GetContainer,
656     ClientSite_ShowObject,
657     ClientSite_OnShowWindow,
658     ClientSite_RequestNewObjectLayout
659 };
660
661 static IOleClientSite ClientSite = { &ClientSiteVtbl };
662
663 static HRESULT WINAPI DocumentSite_QueryInterface(IOleDocumentSite *iface, REFIID riid, void **ppv)
664 {
665     return cs_qi(riid, ppv);
666 }
667
668 static ULONG WINAPI DocumentSite_AddRef(IOleDocumentSite *iface)
669 {
670     return 2;
671 }
672
673 static ULONG WINAPI DocumentSite_Release(IOleDocumentSite *iface)
674 {
675     return 1;
676 }
677
678 static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocumentView *pViewToActivate)
679 {
680     RECT rect = {0,0,400,500};
681     IOleDocument *document;
682     HRESULT hres;
683
684     hres = IOleDocumentView_QueryInterface(pViewToActivate, &IID_IOleDocument, (void**)&document);
685     ok(hres == S_OK, "could not get IOleDocument: %08x\n", hres);
686
687     hres = IOleDocument_CreateView(document, &InPlaceSite, NULL, 0, &view);
688     IOleDocument_Release(document);
689     ok(hres == S_OK, "CreateView failed: %08x\n", hres);
690
691     hres = IOleDocumentView_SetInPlaceSite(view, &InPlaceSite);
692     ok(hres == S_OK, "SetInPlaceSite failed: %08x\n", hres);
693
694     hres = IOleDocumentView_UIActivate(view, TRUE);
695     ok(hres == S_OK, "UIActivate failed: %08x\n", hres);
696
697     hres = IOleDocumentView_SetRect(view, &rect);
698     ok(hres == S_OK, "SetRect failed: %08x\n", hres);
699
700     hres = IOleDocumentView_Show(view, TRUE);
701     ok(hres == S_OK, "Show failed: %08x\n", hres);
702
703     return S_OK;
704 }
705
706 static const IOleDocumentSiteVtbl DocumentSiteVtbl = {
707     DocumentSite_QueryInterface,
708     DocumentSite_AddRef,
709     DocumentSite_Release,
710     DocumentSite_ActivateMe
711 };
712
713 static IOleDocumentSite DocumentSite = { &DocumentSiteVtbl };
714
715 static HRESULT cs_qi(REFIID riid, void **ppv)
716 {
717     *ppv = NULL;
718
719     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IOleClientSite, riid))
720         *ppv = &ClientSite;
721     else if(IsEqualGUID(&IID_IOleDocumentSite, riid))
722         *ppv = &DocumentSite;
723     else if(IsEqualGUID(&IID_IOleWindow, riid) || IsEqualGUID(&IID_IOleInPlaceSite, riid))
724         *ppv = &InPlaceSite;
725
726     return *ppv ? S_OK : E_NOINTERFACE;
727 }
728
729 static IClassFactory activex_cf = { &ClassFactoryVtbl };
730 static IHTMLDocument2 *notif_doc;
731 static BOOL doc_complete;
732
733 static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface,
734         REFIID riid, void**ppv)
735 {
736     if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
737         *ppv = iface;
738         return S_OK;
739     }
740
741     ok(0, "unexpected call\n");
742     return E_NOINTERFACE;
743 }
744
745 static ULONG WINAPI PropertyNotifySink_AddRef(IPropertyNotifySink *iface)
746 {
747     return 2;
748 }
749
750 static ULONG WINAPI PropertyNotifySink_Release(IPropertyNotifySink *iface)
751 {
752     return 1;
753 }
754
755 static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
756 {
757     if(dispID == DISPID_READYSTATE){
758         BSTR state;
759         HRESULT hres;
760
761         static const WCHAR completeW[] = {'c','o','m','p','l','e','t','e',0};
762
763         hres = IHTMLDocument2_get_readyState(notif_doc, &state);
764         ok(hres == S_OK, "get_readyState failed: %08x\n", hres);
765
766         if(!lstrcmpW(state, completeW))
767             doc_complete = TRUE;
768
769         SysFreeString(state);
770     }
771
772     return S_OK;
773 }
774
775 static HRESULT WINAPI PropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
776 {
777     ok(0, "unexpected call\n");
778     return E_NOTIMPL;
779 }
780
781 static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
782     PropertyNotifySink_QueryInterface,
783     PropertyNotifySink_AddRef,
784     PropertyNotifySink_Release,
785     PropertyNotifySink_OnChanged,
786     PropertyNotifySink_OnRequestEdit
787 };
788
789 static IPropertyNotifySink PropertyNotifySink = { &PropertyNotifySinkVtbl };
790
791 static void doc_load_string(IHTMLDocument2 *doc, const char *str)
792 {
793     IPersistStreamInit *init;
794     IStream *stream;
795     HGLOBAL mem;
796     SIZE_T len;
797
798     notif_doc = doc;
799
800     doc_complete = FALSE;
801     len = strlen(str);
802     mem = GlobalAlloc(0, len);
803     memcpy(mem, str, len);
804     CreateStreamOnHGlobal(mem, TRUE, &stream);
805
806     IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init);
807
808     IPersistStreamInit_Load(init, stream);
809     IPersistStreamInit_Release(init);
810     IStream_Release(stream);
811 }
812
813 static void do_advise(IUnknown *unk, REFIID riid, IUnknown *unk_advise)
814 {
815     IConnectionPointContainer *container;
816     IConnectionPoint *cp;
817     DWORD cookie;
818     HRESULT hres;
819
820     hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&container);
821     ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres);
822
823     hres = IConnectionPointContainer_FindConnectionPoint(container, riid, &cp);
824     IConnectionPointContainer_Release(container);
825     ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres);
826
827     hres = IConnectionPoint_Advise(cp, unk_advise, &cookie);
828     IConnectionPoint_Release(cp);
829     ok(hres == S_OK, "Advise failed: %08x\n", hres);
830 }
831
832 static void set_client_site(IHTMLDocument2 *doc, BOOL set)
833 {
834     IOleObject *oleobj;
835     HRESULT hres;
836
837     if(!set && view) {
838         IOleDocumentView_Show(view, FALSE);
839         IOleDocumentView_CloseView(view, 0);
840         IOleDocumentView_SetInPlaceSite(view, NULL);
841         IOleDocumentView_Release(view);
842         view = NULL;
843     }
844
845     hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj);
846     ok(hres == S_OK, "Could not et IOleObject: %08x\n", hres);
847
848     hres = IOleObject_SetClientSite(oleobj, set ? &ClientSite : NULL);
849     ok(hres == S_OK, "SetClientSite failed: %08x\n", hres);
850
851     if(set) {
852         IHlinkTarget *hlink;
853
854         hres = IOleObject_QueryInterface(oleobj, &IID_IHlinkTarget, (void**)&hlink);
855         ok(hres == S_OK, "Could not get IHlinkTarget iface: %08x\n", hres);
856
857         hres = IHlinkTarget_Navigate(hlink, 0, NULL);
858         ok(hres == S_OK, "Navgate failed: %08x\n", hres);
859
860         IHlinkTarget_Release(hlink);
861     }
862
863     IOleObject_Release(oleobj);
864 }
865 static IHTMLDocument2 *create_document(void)
866 {
867     IHTMLDocument2 *doc;
868     HRESULT hres;
869
870     hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
871             &IID_IHTMLDocument2, (void**)&doc);
872     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
873
874     return doc;
875 }
876
877 static IHTMLDocument2 *create_doc(const char *str, BOOL *b)
878 {
879     IHTMLDocument2 *doc;
880     MSG msg;
881
882     doc = create_document();
883     set_client_site(doc, TRUE);
884     doc_load_string(doc, str);
885     do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink);
886
887     while((!doc_complete || (b && !*b)) && GetMessage(&msg, NULL, 0, 0)) {
888         TranslateMessage(&msg);
889         DispatchMessage(&msg);
890     }
891
892     return doc;
893 }
894
895 static void release_doc(IHTMLDocument2 *doc)
896 {
897     ULONG ref;
898
899     set_client_site(doc, FALSE);
900     ref = IHTMLDocument2_Release(doc);
901     ok(!ref, "ref = %d\n", ref);
902 }
903
904 static void test_object_ax(void)
905 {
906     IHTMLDocument2 *doc;
907
908     /*
909      * We pump messages until both document is loaded and plugin instance is created.
910      * Pumping until document is loaded should be enough, but Gecko loads plugins
911      * asynchronously and until we'll work around it, we need this hack.
912      */
913     SET_EXPECT(CreateInstance);
914     SET_EXPECT(FreezeEvents_TRUE);
915     SET_EXPECT(QuickActivate);
916     SET_EXPECT(FreezeEvents_FALSE);
917
918     doc = create_doc(object_ax_str, &called_CreateInstance);
919
920     CHECK_CALLED(CreateInstance);
921     todo_wine
922     CHECK_CALLED(FreezeEvents_TRUE);
923     CHECK_CALLED(QuickActivate);
924     todo_wine
925     CHECK_CALLED(FreezeEvents_FALSE);
926
927     release_doc(doc);
928 }
929
930 static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
931 {
932     return DefWindowProc(hwnd, msg, wParam, lParam);
933 }
934
935 static HWND create_container_window(void)
936 {
937     static const WCHAR html_document_testW[] =
938         {'H','T','M','L','D','o','c','u','m','e','n','t','T','e','s','t',0};
939     static WNDCLASSEXW wndclass = {
940         sizeof(WNDCLASSEXW),
941         0,
942         wnd_proc,
943         0, 0, NULL, NULL, NULL, NULL, NULL,
944         html_document_testW,
945         NULL
946     };
947
948     RegisterClassExW(&wndclass);
949     return CreateWindowW(html_document_testW, html_document_testW,
950             WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
951             515, 530, NULL, NULL, NULL, NULL);
952 }
953
954 static BOOL init_key(const char *key_name, const char *def_value, BOOL init)
955 {
956     HKEY hkey;
957     DWORD res;
958
959     if(!init) {
960         RegDeleteKey(HKEY_CLASSES_ROOT, key_name);
961         return TRUE;
962     }
963
964     res = RegCreateKeyA(HKEY_CLASSES_ROOT, key_name, &hkey);
965     if(res != ERROR_SUCCESS)
966         return FALSE;
967
968     if(def_value)
969         res = RegSetValueA(hkey, NULL, REG_SZ, def_value, strlen(def_value));
970
971     RegCloseKey(hkey);
972
973     return res == ERROR_SUCCESS;
974 }
975
976 static BOOL init_registry(BOOL init)
977 {
978     return init_key("TestActiveX\\CLSID", TESTACTIVEX_CLSID, init)
979         && init_key("CLSID\\"TESTACTIVEX_CLSID"\\Implemented Categories\\{7dd95801-9882-11cf-9fa9-00aa006c42c4}",
980                     NULL, init)
981         && init_key("CLSID\\"TESTACTIVEX_CLSID"\\Implemented Categories\\{7dd95802-9882-11cf-9fa9-00aa006c42c4}",
982                     NULL, init);
983 }
984
985 static BOOL register_activex(void)
986 {
987     DWORD regid;
988     HRESULT hres;
989
990     if(!init_registry(TRUE)) {
991         init_registry(FALSE);
992         return FALSE;
993     }
994
995     hres = CoRegisterClassObject(&CLSID_TestActiveX, (IUnknown*)&activex_cf,
996             CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &regid);
997     ok(hres == S_OK, "Could not register control: %08x\n", hres);
998
999     return TRUE;
1000 }
1001
1002 static BOOL check_ie(void)
1003 {
1004     IHTMLDocument5 *doc;
1005     HRESULT hres;
1006
1007     static const WCHAR xW[] = {'x',0};
1008     static const WCHAR yW[] = {'y',0};
1009
1010     if(!lstrcmpW(xW, yW))
1011         return FALSE;
1012
1013     hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
1014             &IID_IHTMLDocument5, (void**)&doc);
1015     if(FAILED(hres))
1016         return FALSE;
1017
1018     IHTMLDocument5_Release(doc);
1019     return TRUE;
1020 }
1021
1022 START_TEST(activex)
1023 {
1024     CoInitialize(NULL);
1025
1026     if(!check_ie()) {
1027         CoUninitialize();
1028         win_skip("Too old IE\n");
1029         return;
1030     }
1031
1032     if(is_ie_hardened()) {
1033         CoUninitialize();
1034         win_skip("IE running in Enhanced Security Configuration\n");
1035         return;
1036     }
1037
1038     container_hwnd = create_container_window();
1039     ShowWindow(container_hwnd, SW_SHOW);
1040
1041     if(register_activex()) {
1042         test_object_ax();
1043         init_registry(FALSE);
1044     }else {
1045         skip("Could not register ActiveX\n");
1046     }
1047
1048     DestroyWindow(container_hwnd);
1049     CoUninitialize();
1050 }