mshtml: Improved error handling in HTMLElement_Create calls.
[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
61 static HWND container_hwnd;
62
63 #define TESTACTIVEX_CLSID "{178fc163-f585-4e24-9c13-4bb7f6680746}"
64
65 static const GUID CLSID_TestActiveX =
66     {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xf6,0x68,0x07,0x46}};
67
68 static const char *debugstr_guid(REFIID riid)
69 {
70     static char buf[50];
71
72     sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
73             riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
74             riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
75             riid->Data4[5], riid->Data4[6], riid->Data4[7]);
76
77     return buf;
78 }
79
80 static const char object_ax_str[] =
81     "<html><head></head><body>"
82     "<object classid=\"clsid:" TESTACTIVEX_CLSID "\" width=\"300\" height=\"200\" id=\"objid\">"
83     "<param name=\"param_name\" value=\"param_value\">"
84     "</object>"
85     "</body></html>";
86
87 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
88 {
89     *ppv = NULL;
90
91     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IClassFactory, riid)) {
92         *ppv = iface;
93         return S_OK;
94     }
95
96     if(IsEqualGUID(&IID_IMarshal, riid))
97         return E_NOINTERFACE;
98     if(IsEqualGUID(&CLSID_IdentityUnmarshal, riid))
99         return E_NOINTERFACE;
100     if(IsEqualGUID(&IID_IClassFactoryEx, riid))
101         return E_NOINTERFACE; /* TODO */
102
103     ok(0, "unexpected riid %s\n", debugstr_guid(riid));
104     return E_NOTIMPL;
105 }
106
107 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
108 {
109     return 2;
110 }
111
112 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
113 {
114     return 1;
115 }
116
117 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
118 {
119     CHECK_EXPECT(CreateInstance);
120     ok(!outer, "outer = %p\n", outer);
121     ok(IsEqualGUID(riid, &IID_IUnknown), "riid = %s\n", debugstr_guid(riid));
122     return E_OUTOFMEMORY;
123 }
124
125 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
126 {
127     ok(0, "unexpected call\n");
128     return S_OK;
129 }
130
131 static const IClassFactoryVtbl ClassFactoryVtbl = {
132     ClassFactory_QueryInterface,
133     ClassFactory_AddRef,
134     ClassFactory_Release,
135     ClassFactory_CreateInstance,
136     ClassFactory_LockServer
137 };
138
139 static HRESULT cs_qi(REFIID,void **);
140 static IOleDocumentView *view;
141
142 static HRESULT WINAPI InPlaceFrame_QueryInterface(IOleInPlaceFrame *iface, REFIID riid, void **ppv)
143 {
144     static const GUID undocumented_frame_iid = {0xfbece6c9,0x48d7,0x4a37,{0x8f,0xe3,0x6a,0xd4,0x27,0x2f,0xdd,0xac}};
145
146     if(!IsEqualGUID(&undocumented_frame_iid, riid))
147         ok(0, "unexpected riid %s\n", debugstr_guid(riid));
148
149     *ppv = NULL;
150     return E_NOINTERFACE;
151 }
152
153 static ULONG WINAPI InPlaceFrame_AddRef(IOleInPlaceFrame *iface)
154 {
155     return 2;
156 }
157
158 static ULONG WINAPI InPlaceFrame_Release(IOleInPlaceFrame *iface)
159 {
160     return 1;
161 }
162
163 static HRESULT WINAPI InPlaceFrame_GetWindow(IOleInPlaceFrame *iface, HWND *phwnd)
164 {
165     return E_NOTIMPL;
166 }
167
168 static HRESULT WINAPI InPlaceFrame_ContextSensitiveHelp(IOleInPlaceFrame *iface, BOOL fEnterMode)
169 {
170     return E_NOTIMPL;
171 }
172
173 static HRESULT WINAPI InPlaceFrame_GetBorder(IOleInPlaceFrame *iface, LPRECT lprectBorder)
174 {
175     return E_NOTIMPL;
176 }
177
178 static HRESULT WINAPI InPlaceFrame_RequestBorderSpace(IOleInPlaceFrame *iface,
179         LPCBORDERWIDTHS pborderwidths)
180 {
181     return E_NOTIMPL;
182 }
183
184 static HRESULT WINAPI InPlaceFrame_SetBorderSpace(IOleInPlaceFrame *iface,
185         LPCBORDERWIDTHS pborderwidths)
186 {
187     return S_OK;
188 }
189
190 static HRESULT WINAPI InPlaceUIWindow_SetActiveObject(IOleInPlaceFrame *iface,
191         IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
192 {
193     return S_OK;
194 }
195
196 static HRESULT WINAPI InPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface,
197         IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
198 {
199     return S_OK;
200 }
201
202 static HRESULT WINAPI InPlaceFrame_InsertMenus(IOleInPlaceFrame *iface, HMENU hmenuShared,
203         LPOLEMENUGROUPWIDTHS lpMenuWidths)
204 {
205     return E_NOTIMPL;
206 }
207
208 static HRESULT WINAPI InPlaceFrame_SetMenu(IOleInPlaceFrame *iface, HMENU hmenuShared,
209         HOLEMENU holemenu, HWND hwndActiveObject)
210 {
211     ok(0, "unexpected call\n");
212     return E_NOTIMPL;
213 }
214
215 static HRESULT WINAPI InPlaceFrame_RemoveMenus(IOleInPlaceFrame *iface, HMENU hmenuShared)
216 {
217     ok(0, "unexpected call\n");
218     return E_NOTIMPL;
219 }
220
221 static HRESULT WINAPI InPlaceFrame_SetStatusText(IOleInPlaceFrame *iface, LPCOLESTR pszStatusText)
222 {
223     return S_OK;
224 }
225
226 static HRESULT WINAPI InPlaceFrame_EnableModeless(IOleInPlaceFrame *iface, BOOL fEnable)
227 {
228     return E_NOTIMPL;
229 }
230
231 static HRESULT WINAPI InPlaceFrame_TranslateAccelerator(IOleInPlaceFrame *iface, LPMSG lpmsg, WORD wID)
232 {
233     ok(0, "unexpected call\n");
234     return E_NOTIMPL;
235 }
236
237 static const IOleInPlaceFrameVtbl InPlaceFrameVtbl = {
238     InPlaceFrame_QueryInterface,
239     InPlaceFrame_AddRef,
240     InPlaceFrame_Release,
241     InPlaceFrame_GetWindow,
242     InPlaceFrame_ContextSensitiveHelp,
243     InPlaceFrame_GetBorder,
244     InPlaceFrame_RequestBorderSpace,
245     InPlaceFrame_SetBorderSpace,
246     InPlaceFrame_SetActiveObject,
247     InPlaceFrame_InsertMenus,
248     InPlaceFrame_SetMenu,
249     InPlaceFrame_RemoveMenus,
250     InPlaceFrame_SetStatusText,
251     InPlaceFrame_EnableModeless,
252     InPlaceFrame_TranslateAccelerator
253 };
254
255 static IOleInPlaceFrame InPlaceFrame = { &InPlaceFrameVtbl };
256
257 static const IOleInPlaceFrameVtbl InPlaceUIWindowVtbl = {
258     InPlaceFrame_QueryInterface,
259     InPlaceFrame_AddRef,
260     InPlaceFrame_Release,
261     InPlaceFrame_GetWindow,
262     InPlaceFrame_ContextSensitiveHelp,
263     InPlaceFrame_GetBorder,
264     InPlaceFrame_RequestBorderSpace,
265     InPlaceFrame_SetBorderSpace,
266     InPlaceUIWindow_SetActiveObject,
267 };
268
269 static IOleInPlaceFrame InPlaceUIWindow = { &InPlaceUIWindowVtbl };
270
271 static HRESULT WINAPI InPlaceSite_QueryInterface(IOleInPlaceSite *iface, REFIID riid, void **ppv)
272 {
273     return cs_qi(riid, ppv);
274 }
275
276 static ULONG WINAPI InPlaceSite_AddRef(IOleInPlaceSite *iface)
277 {
278     return 2;
279 }
280
281 static ULONG WINAPI InPlaceSite_Release(IOleInPlaceSite *iface)
282 {
283     return 1;
284 }
285
286 static HRESULT WINAPI InPlaceSite_GetWindow(IOleInPlaceSite *iface, HWND *phwnd)
287 {
288     *phwnd = container_hwnd;
289     return S_OK;
290 }
291
292 static HRESULT WINAPI InPlaceSite_ContextSensitiveHelp(IOleInPlaceSite *iface, BOOL fEnterMode)
293 {
294     ok(0, "unexpected call\n");
295     return E_NOTIMPL;
296 }
297
298 static HRESULT WINAPI InPlaceSite_CanInPlaceActivate(IOleInPlaceSite *iface)
299 {
300     return S_OK;
301 }
302
303 static HRESULT WINAPI InPlaceSite_OnInPlaceActivate(IOleInPlaceSite *iface)
304 {
305     return S_OK;
306 }
307
308 static HRESULT WINAPI InPlaceSite_OnUIActivate(IOleInPlaceSite *iface)
309 {
310     return S_OK;
311 }
312
313 static HRESULT WINAPI InPlaceSite_GetWindowContext(IOleInPlaceSite *iface,
314         IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect,
315         LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
316 {
317     static const RECT rect = {0,0,500,500};
318
319     *ppFrame = &InPlaceFrame;
320     *ppDoc = (IOleInPlaceUIWindow*)&InPlaceUIWindow;
321     *lprcPosRect = rect;
322     *lprcClipRect = rect;
323
324     lpFrameInfo->cb = sizeof(*lpFrameInfo);
325     lpFrameInfo->fMDIApp = FALSE;
326     lpFrameInfo->hwndFrame = container_hwnd;
327     lpFrameInfo->haccel = NULL;
328     lpFrameInfo->cAccelEntries = 0;
329
330     return S_OK;
331 }
332
333 static HRESULT WINAPI InPlaceSite_Scroll(IOleInPlaceSite *iface, SIZE scrollExtant)
334 {
335     return E_NOTIMPL;
336 }
337
338 static HRESULT WINAPI InPlaceSite_OnUIDeactivate(IOleInPlaceSite *iface, BOOL fUndoable)
339 {
340     return S_OK;
341 }
342
343 static HRESULT WINAPI InPlaceSite_OnInPlaceDeactivate(IOleInPlaceSite *iface)
344 {
345     return S_OK;
346 }
347
348 static HRESULT WINAPI InPlaceSite_DiscardUndoState(IOleInPlaceSite *iface)
349 {
350     return E_NOTIMPL;
351 }
352
353 static HRESULT WINAPI InPlaceSite_DeactivateAndUndo(IOleInPlaceSite *iface)
354 {
355     return E_NOTIMPL;
356 }
357
358 static HRESULT WINAPI InPlaceSite_OnPosRectChange(IOleInPlaceSite *iface, LPCRECT lprcPosRect)
359 {
360     return E_NOTIMPL;
361 }
362
363 static const IOleInPlaceSiteVtbl InPlaceSiteVtbl = {
364     InPlaceSite_QueryInterface,
365     InPlaceSite_AddRef,
366     InPlaceSite_Release,
367     InPlaceSite_GetWindow,
368     InPlaceSite_ContextSensitiveHelp,
369     InPlaceSite_CanInPlaceActivate,
370     InPlaceSite_OnInPlaceActivate,
371     InPlaceSite_OnUIActivate,
372     InPlaceSite_GetWindowContext,
373     InPlaceSite_Scroll,
374     InPlaceSite_OnUIDeactivate,
375     InPlaceSite_OnInPlaceDeactivate,
376     InPlaceSite_DiscardUndoState,
377     InPlaceSite_DeactivateAndUndo,
378     InPlaceSite_OnPosRectChange,
379 };
380
381 static IOleInPlaceSite InPlaceSite = { &InPlaceSiteVtbl };
382
383 static HRESULT WINAPI ClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
384 {
385     return cs_qi(riid, ppv);
386 }
387
388 static ULONG WINAPI ClientSite_AddRef(IOleClientSite *iface)
389 {
390     return 2;
391 }
392
393 static ULONG WINAPI ClientSite_Release(IOleClientSite *iface)
394 {
395     return 1;
396 }
397
398 static HRESULT WINAPI ClientSite_SaveObject(IOleClientSite *iface)
399 {
400     ok(0, "unexpected call\n");
401     return E_NOTIMPL;
402 }
403
404 static HRESULT WINAPI ClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign, DWORD dwWhichMoniker,
405         IMoniker **ppmon)
406 {
407     ok(0, "unexpected call\n");
408     return E_NOTIMPL;
409 }
410
411 static HRESULT WINAPI ClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
412 {
413     return E_NOTIMPL;
414 }
415
416 static HRESULT WINAPI ClientSite_ShowObject(IOleClientSite *iface)
417 {
418     ok(0, "unexpected call\n");
419     return E_NOTIMPL;
420 }
421
422 static HRESULT WINAPI ClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow)
423 {
424     ok(0, "unexpected call\n");
425     return E_NOTIMPL;
426 }
427
428 static HRESULT WINAPI ClientSite_RequestNewObjectLayout(IOleClientSite *iface)
429 {
430     ok(0, "unexpected call\n");
431     return E_NOTIMPL;
432 }
433
434 static const IOleClientSiteVtbl ClientSiteVtbl = {
435     ClientSite_QueryInterface,
436     ClientSite_AddRef,
437     ClientSite_Release,
438     ClientSite_SaveObject,
439     ClientSite_GetMoniker,
440     ClientSite_GetContainer,
441     ClientSite_ShowObject,
442     ClientSite_OnShowWindow,
443     ClientSite_RequestNewObjectLayout
444 };
445
446 static IOleClientSite ClientSite = { &ClientSiteVtbl };
447
448 static HRESULT WINAPI DocumentSite_QueryInterface(IOleDocumentSite *iface, REFIID riid, void **ppv)
449 {
450     return cs_qi(riid, ppv);
451 }
452
453 static ULONG WINAPI DocumentSite_AddRef(IOleDocumentSite *iface)
454 {
455     return 2;
456 }
457
458 static ULONG WINAPI DocumentSite_Release(IOleDocumentSite *iface)
459 {
460     return 1;
461 }
462
463 static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocumentView *pViewToActivate)
464 {
465     RECT rect = {0,0,400,500};
466     IOleDocument *document;
467     HRESULT hres;
468
469     hres = IOleDocumentView_QueryInterface(pViewToActivate, &IID_IOleDocument, (void**)&document);
470     ok(hres == S_OK, "could not get IOleDocument: %08x\n", hres);
471
472     hres = IOleDocument_CreateView(document, &InPlaceSite, NULL, 0, &view);
473     IOleDocument_Release(document);
474     ok(hres == S_OK, "CreateView failed: %08x\n", hres);
475
476     hres = IOleDocumentView_SetInPlaceSite(view, &InPlaceSite);
477     ok(hres == S_OK, "SetInPlaceSite failed: %08x\n", hres);
478
479     hres = IOleDocumentView_UIActivate(view, TRUE);
480     ok(hres == S_OK, "UIActivate failed: %08x\n", hres);
481
482     hres = IOleDocumentView_SetRect(view, &rect);
483     ok(hres == S_OK, "SetRect failed: %08x\n", hres);
484
485     hres = IOleDocumentView_Show(view, TRUE);
486     ok(hres == S_OK, "Show failed: %08x\n", hres);
487
488     return S_OK;
489 }
490
491 static const IOleDocumentSiteVtbl DocumentSiteVtbl = {
492     DocumentSite_QueryInterface,
493     DocumentSite_AddRef,
494     DocumentSite_Release,
495     DocumentSite_ActivateMe
496 };
497
498 static IOleDocumentSite DocumentSite = { &DocumentSiteVtbl };
499
500 static HRESULT cs_qi(REFIID riid, void **ppv)
501 {
502     *ppv = NULL;
503
504     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IOleClientSite, riid))
505         *ppv = &ClientSite;
506     else if(IsEqualGUID(&IID_IOleDocumentSite, riid))
507         *ppv = &DocumentSite;
508     else if(IsEqualGUID(&IID_IOleWindow, riid) || IsEqualGUID(&IID_IOleInPlaceSite, riid))
509         *ppv = &InPlaceSite;
510
511     return *ppv ? S_OK : E_NOINTERFACE;
512 }
513
514 static IClassFactory activex_cf = { &ClassFactoryVtbl };
515 static IHTMLDocument2 *notif_doc;
516 static BOOL doc_complete;
517
518 static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface,
519         REFIID riid, void**ppv)
520 {
521     if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
522         *ppv = iface;
523         return S_OK;
524     }
525
526     ok(0, "unexpected call\n");
527     return E_NOINTERFACE;
528 }
529
530 static ULONG WINAPI PropertyNotifySink_AddRef(IPropertyNotifySink *iface)
531 {
532     return 2;
533 }
534
535 static ULONG WINAPI PropertyNotifySink_Release(IPropertyNotifySink *iface)
536 {
537     return 1;
538 }
539
540 static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
541 {
542     if(dispID == DISPID_READYSTATE){
543         BSTR state;
544         HRESULT hres;
545
546         static const WCHAR completeW[] = {'c','o','m','p','l','e','t','e',0};
547
548         hres = IHTMLDocument2_get_readyState(notif_doc, &state);
549         ok(hres == S_OK, "get_readyState failed: %08x\n", hres);
550
551         if(!lstrcmpW(state, completeW))
552             doc_complete = TRUE;
553
554         SysFreeString(state);
555     }
556
557     return S_OK;
558 }
559
560 static HRESULT WINAPI PropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
561 {
562     ok(0, "unexpected call\n");
563     return E_NOTIMPL;
564 }
565
566 static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
567     PropertyNotifySink_QueryInterface,
568     PropertyNotifySink_AddRef,
569     PropertyNotifySink_Release,
570     PropertyNotifySink_OnChanged,
571     PropertyNotifySink_OnRequestEdit
572 };
573
574 static IPropertyNotifySink PropertyNotifySink = { &PropertyNotifySinkVtbl };
575
576 static void doc_load_string(IHTMLDocument2 *doc, const char *str)
577 {
578     IPersistStreamInit *init;
579     IStream *stream;
580     HGLOBAL mem;
581     SIZE_T len;
582
583     notif_doc = doc;
584
585     doc_complete = FALSE;
586     len = strlen(str);
587     mem = GlobalAlloc(0, len);
588     memcpy(mem, str, len);
589     CreateStreamOnHGlobal(mem, TRUE, &stream);
590
591     IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init);
592
593     IPersistStreamInit_Load(init, stream);
594     IPersistStreamInit_Release(init);
595     IStream_Release(stream);
596 }
597
598 static void do_advise(IUnknown *unk, REFIID riid, IUnknown *unk_advise)
599 {
600     IConnectionPointContainer *container;
601     IConnectionPoint *cp;
602     DWORD cookie;
603     HRESULT hres;
604
605     hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&container);
606     ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres);
607
608     hres = IConnectionPointContainer_FindConnectionPoint(container, riid, &cp);
609     IConnectionPointContainer_Release(container);
610     ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres);
611
612     hres = IConnectionPoint_Advise(cp, unk_advise, &cookie);
613     IConnectionPoint_Release(cp);
614     ok(hres == S_OK, "Advise failed: %08x\n", hres);
615 }
616
617 static void set_client_site(IHTMLDocument2 *doc, BOOL set)
618 {
619     IOleObject *oleobj;
620     HRESULT hres;
621
622     if(!set && view) {
623         IOleDocumentView_Show(view, FALSE);
624         IOleDocumentView_CloseView(view, 0);
625         IOleDocumentView_SetInPlaceSite(view, NULL);
626         IOleDocumentView_Release(view);
627         view = NULL;
628     }
629
630     hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj);
631     ok(hres == S_OK, "Could not et IOleObject: %08x\n", hres);
632
633     hres = IOleObject_SetClientSite(oleobj, set ? &ClientSite : NULL);
634     ok(hres == S_OK, "SetClientSite failed: %08x\n", hres);
635
636     if(set) {
637         IHlinkTarget *hlink;
638
639         hres = IOleObject_QueryInterface(oleobj, &IID_IHlinkTarget, (void**)&hlink);
640         ok(hres == S_OK, "Could not get IHlinkTarget iface: %08x\n", hres);
641
642         hres = IHlinkTarget_Navigate(hlink, 0, NULL);
643         ok(hres == S_OK, "Navgate failed: %08x\n", hres);
644
645         IHlinkTarget_Release(hlink);
646     }
647
648     IOleObject_Release(oleobj);
649 }
650 static IHTMLDocument2 *create_document(void)
651 {
652     IHTMLDocument2 *doc;
653     HRESULT hres;
654
655     hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
656             &IID_IHTMLDocument2, (void**)&doc);
657     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
658
659     return doc;
660 }
661
662 static IHTMLDocument2 *create_doc(const char *str)
663 {
664     IHTMLDocument2 *doc;
665     MSG msg;
666
667     doc = create_document();
668     set_client_site(doc, TRUE);
669     doc_load_string(doc, str);
670     do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink);
671
672     while(!doc_complete && GetMessage(&msg, NULL, 0, 0)) {
673         TranslateMessage(&msg);
674         DispatchMessage(&msg);
675     }
676
677     return doc;
678 }
679
680 static void release_doc(IHTMLDocument2 *doc)
681 {
682     ULONG ref;
683
684     set_client_site(doc, FALSE);
685     ref = IHTMLDocument2_Release(doc);
686     ok(!ref, "ref = %d\n", ref);
687 }
688
689 static void test_object_ax(void)
690 {
691     IHTMLDocument2 *doc;
692
693     SET_EXPECT(CreateInstance);
694     doc = create_doc(object_ax_str);
695     todo_wine
696     CHECK_CALLED(CreateInstance);
697
698     release_doc(doc);
699 }
700
701 static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
702 {
703     return DefWindowProc(hwnd, msg, wParam, lParam);
704 }
705
706 static HWND create_container_window(void)
707 {
708     static const WCHAR html_document_testW[] =
709         {'H','T','M','L','D','o','c','u','m','e','n','t','T','e','s','t',0};
710     static WNDCLASSEXW wndclass = {
711         sizeof(WNDCLASSEXW),
712         0,
713         wnd_proc,
714         0, 0, NULL, NULL, NULL, NULL, NULL,
715         html_document_testW,
716         NULL
717     };
718
719     RegisterClassExW(&wndclass);
720     return CreateWindowW(html_document_testW, html_document_testW,
721             WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
722             515, 530, NULL, NULL, NULL, NULL);
723 }
724
725 static BOOL init_key(const char *key_name, const char *def_value, BOOL init)
726 {
727     HKEY hkey;
728     DWORD res;
729
730     if(!init) {
731         RegDeleteKey(HKEY_CLASSES_ROOT, key_name);
732         return TRUE;
733     }
734
735     res = RegCreateKeyA(HKEY_CLASSES_ROOT, key_name, &hkey);
736     if(res != ERROR_SUCCESS)
737         return FALSE;
738
739     if(def_value)
740         res = RegSetValueA(hkey, NULL, REG_SZ, def_value, strlen(def_value));
741
742     RegCloseKey(hkey);
743
744     return res == ERROR_SUCCESS;
745 }
746
747 static BOOL init_registry(BOOL init)
748 {
749     return init_key("TestActiveX\\CLSID", TESTACTIVEX_CLSID, init)
750         && init_key("CLSID\\"TESTACTIVEX_CLSID"\\Implemented Categories\\{7dd95801-9882-11cf-9fa9-00aa006c42c4}",
751                     NULL, init)
752         && init_key("CLSID\\"TESTACTIVEX_CLSID"\\Implemented Categories\\{7dd95802-9882-11cf-9fa9-00aa006c42c4}",
753                     NULL, init);
754 }
755
756 static BOOL register_activex(void)
757 {
758     DWORD regid;
759     HRESULT hres;
760
761     if(!init_registry(TRUE)) {
762         init_registry(FALSE);
763         return FALSE;
764     }
765
766     hres = CoRegisterClassObject(&CLSID_TestActiveX, (IUnknown*)&activex_cf,
767             CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &regid);
768     ok(hres == S_OK, "Could not register control: %08x\n", hres);
769
770     return TRUE;
771 }
772
773 static BOOL check_ie(void)
774 {
775     IHTMLDocument5 *doc;
776     HRESULT hres;
777
778     static const WCHAR xW[] = {'x',0};
779     static const WCHAR yW[] = {'y',0};
780
781     if(!lstrcmpW(xW, yW))
782         return FALSE;
783
784     hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
785             &IID_IHTMLDocument5, (void**)&doc);
786     if(FAILED(hres))
787         return FALSE;
788
789     IHTMLDocument5_Release(doc);
790     return TRUE;
791 }
792
793 START_TEST(activex)
794 {
795     CoInitialize(NULL);
796
797     if(!check_ie()) {
798         CoUninitialize();
799         win_skip("Too old IE\n");
800         return;
801     }
802
803     if(is_ie_hardened()) {
804         CoUninitialize();
805         win_skip("IE running in Enhanced Security Configuration\n");
806         return;
807     }
808
809     container_hwnd = create_container_window();
810     ShowWindow(container_hwnd, SW_SHOW);
811
812     if(register_activex()) {
813         test_object_ax();
814         init_registry(FALSE);
815     }else {
816         skip("Could not register ActiveX\n");
817     }
818
819     DestroyWindow(container_hwnd);
820     CoUninitialize();
821 }