mshtml: Added PluginHost's IAdviseSinkEx stub implementation.
[wine.git] / dlls / mshtml / tests / activex.c
blob384b738497526f4e5358ebce5334da4f2a046d58
1 /*
2 * Copyright 2010 Jacek Caban for CodeWeavers
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.
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.
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
19 #define COBJMACROS
20 #define CONST_VTABLE
22 #include <wine/test.h>
23 #include <stdarg.h>
24 #include <stdio.h>
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"
35 #define DEFINE_EXPECT(func) \
36 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
38 #define SET_EXPECT(func) \
39 do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
41 #define CHECK_EXPECT2(func) \
42 do { \
43 ok(expect_ ##func, "unexpected call " #func "\n"); \
44 called_ ## func = TRUE; \
45 }while(0)
47 #define CHECK_EXPECT(func) \
48 do { \
49 CHECK_EXPECT2(func); \
50 expect_ ## func = FALSE; \
51 }while(0)
53 #define CHECK_CALLED(func) \
54 do { \
55 ok(called_ ## func, "expected " #func "\n"); \
56 expect_ ## func = called_ ## func = FALSE; \
57 }while(0)
59 DEFINE_EXPECT(CreateInstance);
60 DEFINE_EXPECT(FreezeEvents_TRUE);
61 DEFINE_EXPECT(FreezeEvents_FALSE);
62 DEFINE_EXPECT(QuickActivate);
64 static HWND container_hwnd;
66 #define TESTACTIVEX_CLSID "{178fc163-f585-4e24-9c13-4bb7f6680746}"
68 static const GUID CLSID_TestActiveX =
69 {0x178fc163,0xf585,0x4e24,{0x9c,0x13,0x4b,0xb7,0xf6,0x68,0x07,0x46}};
71 static const char *debugstr_guid(REFIID riid)
73 static char buf[50];
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]);
80 return buf;
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>";
90 static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2)
92 IUnknown *unk1, *unk2;
94 if(iface1 == iface2)
95 return TRUE;
97 IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk1);
98 IUnknown_Release(unk1);
99 IUnknown_QueryInterface(iface2, &IID_IUnknown, (void**)&unk2);
100 IUnknown_Release(unk2);
102 return unk1 == unk2;
105 static HRESULT ax_qi(REFIID,void**);
107 static HRESULT WINAPI OleControl_QueryInterface(IOleControl *iface, REFIID riid, void **ppv)
109 return ax_qi(riid, ppv);
112 static ULONG WINAPI OleControl_AddRef(IOleControl *iface)
114 return 2;
117 static ULONG WINAPI OleControl_Release(IOleControl *iface)
119 return 1;
122 static HRESULT WINAPI OleControl_GetControlInfo(IOleControl *iface, CONTROLINFO *pCI)
124 ok(0, "unexpected call\n");
125 return E_NOTIMPL;
128 static HRESULT WINAPI OleControl_OnMnemonic(IOleControl *iface, MSG *mMsg)
130 ok(0, "unexpected call\n");
131 return E_NOTIMPL;
134 static HRESULT WINAPI OleControl_OnAmbientPropertyChange(IOleControl *iface, DISPID dispID)
136 ok(0, "unexpected call\n");
137 return E_NOTIMPL;
140 static HRESULT WINAPI OleControl_FreezeEvents(IOleControl *iface, BOOL bFreeze)
142 if(bFreeze)
143 CHECK_EXPECT2(FreezeEvents_TRUE);
144 else
145 CHECK_EXPECT2(FreezeEvents_FALSE);
146 return S_OK;
149 static const IOleControlVtbl OleControlVtbl = {
150 OleControl_QueryInterface,
151 OleControl_AddRef,
152 OleControl_Release,
153 OleControl_GetControlInfo,
154 OleControl_OnMnemonic,
155 OleControl_OnAmbientPropertyChange,
156 OleControl_FreezeEvents
159 static IOleControl OleControl = { &OleControlVtbl };
161 static HRESULT WINAPI QuickActivate_QueryInterface(IQuickActivate *iface, REFIID riid, void **ppv)
163 return ax_qi(riid, ppv);
166 static ULONG WINAPI QuickActivate_AddRef(IQuickActivate *iface)
168 return 2;
171 static ULONG WINAPI QuickActivate_Release(IQuickActivate *iface)
173 return 1;
176 static HRESULT WINAPI QuickActivate_QuickActivate(IQuickActivate *iface, QACONTAINER *container, QACONTROL *control)
178 CHECK_EXPECT(QuickActivate);
180 ok(container != NULL, "container == NULL\n");
181 ok(container->cbSize == sizeof(*container), "container->cbSize = %d\n", container->cbSize);
182 ok(container->pClientSite != NULL, "container->pClientSite == NULL\n");
183 ok(container->pAdviseSink != NULL, "container->pAdviseSink == NULL\n");
184 todo_wine
185 ok(container->pPropertyNotifySink != NULL, "container->pPropertyNotifySink == NULL\n");
186 ok(!container->pUnkEventSink, "container->pUnkEventSink != NULL\n");
187 ok(container->dwAmbientFlags == (QACONTAINER_SUPPORTSMNEMONICS|QACONTAINER_MESSAGEREFLECT|QACONTAINER_USERMODE),
188 "container->dwAmbientFlags = %x\n", container->dwAmbientFlags);
189 ok(!container->colorFore, "container->colorFore == 0\n"); /* FIXME */
190 todo_wine
191 ok(container->colorBack, "container->colorBack == 0\n"); /* FIXME */
192 todo_wine
193 ok(container->pFont != NULL, "container->pFont == NULL\n");
194 todo_wine
195 ok(container->pUndoMgr != NULL, "container->pUndoMgr == NULL\n");
196 ok(!container->dwAppearance, "container->dwAppearance = %x\n", container->dwAppearance);
197 ok(!container->lcid, "container->lcid = %x\n", container->lcid);
198 ok(!container->hpal, "container->hpal = %p\n", container->hpal);
199 ok(!container->pBindHost, "container->pBindHost != NULL\n");
200 ok(!container->pOleControlSite, "container->pOleControlSite != NULL\n");
201 ok(!container->pServiceProvider, "container->pServiceProvider != NULL\n");
203 ok(control->cbSize == sizeof(*control), "control->cbSize = %d\n", control->cbSize);
204 ok(!control->dwMiscStatus, "control->dwMiscStatus = %x\n", control->dwMiscStatus);
205 ok(!control->dwViewStatus, "control->dwViewStatus = %x\n", control->dwViewStatus);
206 ok(!control->dwEventCookie, "control->dwEventCookie = %x\n", control->dwEventCookie);
207 ok(!control->dwPropNotifyCookie, "control->dwPropNotifyCookie = %x\n", control->dwPropNotifyCookie);
208 ok(!control->dwPointerActivationPolicy, "control->dwPointerActivationPolicy = %x\n", control->dwPointerActivationPolicy);
210 ok(iface_cmp((IUnknown*)container->pClientSite, (IUnknown*)container->pAdviseSink),
211 "container->pClientSite != container->pAdviseSink\n");
213 return S_OK;
216 static HRESULT WINAPI QuickActivate_SetContentExtent(IQuickActivate *iface, LPSIZEL pSizel)
218 ok(0, "unexpected call\n");
219 return E_NOTIMPL;
222 static HRESULT WINAPI QuickActivate_GetContentExtent(IQuickActivate *iface, LPSIZEL pSizel)
224 ok(0, "unexpected call\n");
225 return E_NOTIMPL;
228 static const IQuickActivateVtbl QuickActivateVtbl = {
229 QuickActivate_QueryInterface,
230 QuickActivate_AddRef,
231 QuickActivate_Release,
232 QuickActivate_QuickActivate,
233 QuickActivate_GetContentExtent,
234 QuickActivate_SetContentExtent
237 static IQuickActivate QuickActivate = { &QuickActivateVtbl };
239 static HRESULT ax_qi(REFIID riid, void **ppv)
241 if(IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IOleControl)) {
242 *ppv = &OleControl;
243 return S_OK;
246 if(IsEqualGUID(riid, &IID_IQuickActivate)) {
247 *ppv = &QuickActivate;
248 return S_OK;
251 *ppv = NULL;
252 return E_NOINTERFACE;
255 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppv)
257 *ppv = NULL;
259 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IClassFactory, riid)) {
260 *ppv = iface;
261 return S_OK;
264 if(IsEqualGUID(&IID_IMarshal, riid))
265 return E_NOINTERFACE;
266 if(IsEqualGUID(&CLSID_IdentityUnmarshal, riid))
267 return E_NOINTERFACE;
268 if(IsEqualGUID(&IID_IClassFactoryEx, riid))
269 return E_NOINTERFACE; /* TODO */
271 ok(0, "unexpected riid %s\n", debugstr_guid(riid));
272 return E_NOTIMPL;
275 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
277 return 2;
280 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
282 return 1;
285 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
287 CHECK_EXPECT(CreateInstance);
289 ok(!outer, "outer = %p\n", outer);
290 ok(IsEqualGUID(riid, &IID_IUnknown), "riid = %s\n", debugstr_guid(riid));
292 *ppv = &OleControl;
293 return S_OK;
296 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL dolock)
298 ok(0, "unexpected call\n");
299 return S_OK;
302 static const IClassFactoryVtbl ClassFactoryVtbl = {
303 ClassFactory_QueryInterface,
304 ClassFactory_AddRef,
305 ClassFactory_Release,
306 ClassFactory_CreateInstance,
307 ClassFactory_LockServer
310 static HRESULT cs_qi(REFIID,void **);
311 static IOleDocumentView *view;
313 static HRESULT WINAPI InPlaceFrame_QueryInterface(IOleInPlaceFrame *iface, REFIID riid, void **ppv)
315 static const GUID undocumented_frame_iid = {0xfbece6c9,0x48d7,0x4a37,{0x8f,0xe3,0x6a,0xd4,0x27,0x2f,0xdd,0xac}};
317 if(!IsEqualGUID(&undocumented_frame_iid, riid))
318 ok(0, "unexpected riid %s\n", debugstr_guid(riid));
320 *ppv = NULL;
321 return E_NOINTERFACE;
324 static ULONG WINAPI InPlaceFrame_AddRef(IOleInPlaceFrame *iface)
326 return 2;
329 static ULONG WINAPI InPlaceFrame_Release(IOleInPlaceFrame *iface)
331 return 1;
334 static HRESULT WINAPI InPlaceFrame_GetWindow(IOleInPlaceFrame *iface, HWND *phwnd)
336 return E_NOTIMPL;
339 static HRESULT WINAPI InPlaceFrame_ContextSensitiveHelp(IOleInPlaceFrame *iface, BOOL fEnterMode)
341 return E_NOTIMPL;
344 static HRESULT WINAPI InPlaceFrame_GetBorder(IOleInPlaceFrame *iface, LPRECT lprectBorder)
346 return E_NOTIMPL;
349 static HRESULT WINAPI InPlaceFrame_RequestBorderSpace(IOleInPlaceFrame *iface,
350 LPCBORDERWIDTHS pborderwidths)
352 return E_NOTIMPL;
355 static HRESULT WINAPI InPlaceFrame_SetBorderSpace(IOleInPlaceFrame *iface,
356 LPCBORDERWIDTHS pborderwidths)
358 return S_OK;
361 static HRESULT WINAPI InPlaceUIWindow_SetActiveObject(IOleInPlaceFrame *iface,
362 IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
364 return S_OK;
367 static HRESULT WINAPI InPlaceFrame_SetActiveObject(IOleInPlaceFrame *iface,
368 IOleInPlaceActiveObject *pActiveObject, LPCOLESTR pszObjName)
370 return S_OK;
373 static HRESULT WINAPI InPlaceFrame_InsertMenus(IOleInPlaceFrame *iface, HMENU hmenuShared,
374 LPOLEMENUGROUPWIDTHS lpMenuWidths)
376 return E_NOTIMPL;
379 static HRESULT WINAPI InPlaceFrame_SetMenu(IOleInPlaceFrame *iface, HMENU hmenuShared,
380 HOLEMENU holemenu, HWND hwndActiveObject)
382 ok(0, "unexpected call\n");
383 return E_NOTIMPL;
386 static HRESULT WINAPI InPlaceFrame_RemoveMenus(IOleInPlaceFrame *iface, HMENU hmenuShared)
388 ok(0, "unexpected call\n");
389 return E_NOTIMPL;
392 static HRESULT WINAPI InPlaceFrame_SetStatusText(IOleInPlaceFrame *iface, LPCOLESTR pszStatusText)
394 return S_OK;
397 static HRESULT WINAPI InPlaceFrame_EnableModeless(IOleInPlaceFrame *iface, BOOL fEnable)
399 return E_NOTIMPL;
402 static HRESULT WINAPI InPlaceFrame_TranslateAccelerator(IOleInPlaceFrame *iface, LPMSG lpmsg, WORD wID)
404 ok(0, "unexpected call\n");
405 return E_NOTIMPL;
408 static const IOleInPlaceFrameVtbl InPlaceFrameVtbl = {
409 InPlaceFrame_QueryInterface,
410 InPlaceFrame_AddRef,
411 InPlaceFrame_Release,
412 InPlaceFrame_GetWindow,
413 InPlaceFrame_ContextSensitiveHelp,
414 InPlaceFrame_GetBorder,
415 InPlaceFrame_RequestBorderSpace,
416 InPlaceFrame_SetBorderSpace,
417 InPlaceFrame_SetActiveObject,
418 InPlaceFrame_InsertMenus,
419 InPlaceFrame_SetMenu,
420 InPlaceFrame_RemoveMenus,
421 InPlaceFrame_SetStatusText,
422 InPlaceFrame_EnableModeless,
423 InPlaceFrame_TranslateAccelerator
426 static IOleInPlaceFrame InPlaceFrame = { &InPlaceFrameVtbl };
428 static const IOleInPlaceFrameVtbl InPlaceUIWindowVtbl = {
429 InPlaceFrame_QueryInterface,
430 InPlaceFrame_AddRef,
431 InPlaceFrame_Release,
432 InPlaceFrame_GetWindow,
433 InPlaceFrame_ContextSensitiveHelp,
434 InPlaceFrame_GetBorder,
435 InPlaceFrame_RequestBorderSpace,
436 InPlaceFrame_SetBorderSpace,
437 InPlaceUIWindow_SetActiveObject,
440 static IOleInPlaceFrame InPlaceUIWindow = { &InPlaceUIWindowVtbl };
442 static HRESULT WINAPI InPlaceSite_QueryInterface(IOleInPlaceSite *iface, REFIID riid, void **ppv)
444 return cs_qi(riid, ppv);
447 static ULONG WINAPI InPlaceSite_AddRef(IOleInPlaceSite *iface)
449 return 2;
452 static ULONG WINAPI InPlaceSite_Release(IOleInPlaceSite *iface)
454 return 1;
457 static HRESULT WINAPI InPlaceSite_GetWindow(IOleInPlaceSite *iface, HWND *phwnd)
459 *phwnd = container_hwnd;
460 return S_OK;
463 static HRESULT WINAPI InPlaceSite_ContextSensitiveHelp(IOleInPlaceSite *iface, BOOL fEnterMode)
465 ok(0, "unexpected call\n");
466 return E_NOTIMPL;
469 static HRESULT WINAPI InPlaceSite_CanInPlaceActivate(IOleInPlaceSite *iface)
471 return S_OK;
474 static HRESULT WINAPI InPlaceSite_OnInPlaceActivate(IOleInPlaceSite *iface)
476 return S_OK;
479 static HRESULT WINAPI InPlaceSite_OnUIActivate(IOleInPlaceSite *iface)
481 return S_OK;
484 static HRESULT WINAPI InPlaceSite_GetWindowContext(IOleInPlaceSite *iface,
485 IOleInPlaceFrame **ppFrame, IOleInPlaceUIWindow **ppDoc, LPRECT lprcPosRect,
486 LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO lpFrameInfo)
488 static const RECT rect = {0,0,500,500};
490 *ppFrame = &InPlaceFrame;
491 *ppDoc = (IOleInPlaceUIWindow*)&InPlaceUIWindow;
492 *lprcPosRect = rect;
493 *lprcClipRect = rect;
495 lpFrameInfo->cb = sizeof(*lpFrameInfo);
496 lpFrameInfo->fMDIApp = FALSE;
497 lpFrameInfo->hwndFrame = container_hwnd;
498 lpFrameInfo->haccel = NULL;
499 lpFrameInfo->cAccelEntries = 0;
501 return S_OK;
504 static HRESULT WINAPI InPlaceSite_Scroll(IOleInPlaceSite *iface, SIZE scrollExtant)
506 return E_NOTIMPL;
509 static HRESULT WINAPI InPlaceSite_OnUIDeactivate(IOleInPlaceSite *iface, BOOL fUndoable)
511 return S_OK;
514 static HRESULT WINAPI InPlaceSite_OnInPlaceDeactivate(IOleInPlaceSite *iface)
516 return S_OK;
519 static HRESULT WINAPI InPlaceSite_DiscardUndoState(IOleInPlaceSite *iface)
521 return E_NOTIMPL;
524 static HRESULT WINAPI InPlaceSite_DeactivateAndUndo(IOleInPlaceSite *iface)
526 return E_NOTIMPL;
529 static HRESULT WINAPI InPlaceSite_OnPosRectChange(IOleInPlaceSite *iface, LPCRECT lprcPosRect)
531 return E_NOTIMPL;
534 static const IOleInPlaceSiteVtbl InPlaceSiteVtbl = {
535 InPlaceSite_QueryInterface,
536 InPlaceSite_AddRef,
537 InPlaceSite_Release,
538 InPlaceSite_GetWindow,
539 InPlaceSite_ContextSensitiveHelp,
540 InPlaceSite_CanInPlaceActivate,
541 InPlaceSite_OnInPlaceActivate,
542 InPlaceSite_OnUIActivate,
543 InPlaceSite_GetWindowContext,
544 InPlaceSite_Scroll,
545 InPlaceSite_OnUIDeactivate,
546 InPlaceSite_OnInPlaceDeactivate,
547 InPlaceSite_DiscardUndoState,
548 InPlaceSite_DeactivateAndUndo,
549 InPlaceSite_OnPosRectChange,
552 static IOleInPlaceSite InPlaceSite = { &InPlaceSiteVtbl };
554 static HRESULT WINAPI ClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv)
556 return cs_qi(riid, ppv);
559 static ULONG WINAPI ClientSite_AddRef(IOleClientSite *iface)
561 return 2;
564 static ULONG WINAPI ClientSite_Release(IOleClientSite *iface)
566 return 1;
569 static HRESULT WINAPI ClientSite_SaveObject(IOleClientSite *iface)
571 ok(0, "unexpected call\n");
572 return E_NOTIMPL;
575 static HRESULT WINAPI ClientSite_GetMoniker(IOleClientSite *iface, DWORD dwAssign, DWORD dwWhichMoniker,
576 IMoniker **ppmon)
578 ok(0, "unexpected call\n");
579 return E_NOTIMPL;
582 static HRESULT WINAPI ClientSite_GetContainer(IOleClientSite *iface, IOleContainer **ppContainer)
584 return E_NOTIMPL;
587 static HRESULT WINAPI ClientSite_ShowObject(IOleClientSite *iface)
589 ok(0, "unexpected call\n");
590 return E_NOTIMPL;
593 static HRESULT WINAPI ClientSite_OnShowWindow(IOleClientSite *iface, BOOL fShow)
595 ok(0, "unexpected call\n");
596 return E_NOTIMPL;
599 static HRESULT WINAPI ClientSite_RequestNewObjectLayout(IOleClientSite *iface)
601 ok(0, "unexpected call\n");
602 return E_NOTIMPL;
605 static const IOleClientSiteVtbl ClientSiteVtbl = {
606 ClientSite_QueryInterface,
607 ClientSite_AddRef,
608 ClientSite_Release,
609 ClientSite_SaveObject,
610 ClientSite_GetMoniker,
611 ClientSite_GetContainer,
612 ClientSite_ShowObject,
613 ClientSite_OnShowWindow,
614 ClientSite_RequestNewObjectLayout
617 static IOleClientSite ClientSite = { &ClientSiteVtbl };
619 static HRESULT WINAPI DocumentSite_QueryInterface(IOleDocumentSite *iface, REFIID riid, void **ppv)
621 return cs_qi(riid, ppv);
624 static ULONG WINAPI DocumentSite_AddRef(IOleDocumentSite *iface)
626 return 2;
629 static ULONG WINAPI DocumentSite_Release(IOleDocumentSite *iface)
631 return 1;
634 static HRESULT WINAPI DocumentSite_ActivateMe(IOleDocumentSite *iface, IOleDocumentView *pViewToActivate)
636 RECT rect = {0,0,400,500};
637 IOleDocument *document;
638 HRESULT hres;
640 hres = IOleDocumentView_QueryInterface(pViewToActivate, &IID_IOleDocument, (void**)&document);
641 ok(hres == S_OK, "could not get IOleDocument: %08x\n", hres);
643 hres = IOleDocument_CreateView(document, &InPlaceSite, NULL, 0, &view);
644 IOleDocument_Release(document);
645 ok(hres == S_OK, "CreateView failed: %08x\n", hres);
647 hres = IOleDocumentView_SetInPlaceSite(view, &InPlaceSite);
648 ok(hres == S_OK, "SetInPlaceSite failed: %08x\n", hres);
650 hres = IOleDocumentView_UIActivate(view, TRUE);
651 ok(hres == S_OK, "UIActivate failed: %08x\n", hres);
653 hres = IOleDocumentView_SetRect(view, &rect);
654 ok(hres == S_OK, "SetRect failed: %08x\n", hres);
656 hres = IOleDocumentView_Show(view, TRUE);
657 ok(hres == S_OK, "Show failed: %08x\n", hres);
659 return S_OK;
662 static const IOleDocumentSiteVtbl DocumentSiteVtbl = {
663 DocumentSite_QueryInterface,
664 DocumentSite_AddRef,
665 DocumentSite_Release,
666 DocumentSite_ActivateMe
669 static IOleDocumentSite DocumentSite = { &DocumentSiteVtbl };
671 static HRESULT cs_qi(REFIID riid, void **ppv)
673 *ppv = NULL;
675 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IOleClientSite, riid))
676 *ppv = &ClientSite;
677 else if(IsEqualGUID(&IID_IOleDocumentSite, riid))
678 *ppv = &DocumentSite;
679 else if(IsEqualGUID(&IID_IOleWindow, riid) || IsEqualGUID(&IID_IOleInPlaceSite, riid))
680 *ppv = &InPlaceSite;
682 return *ppv ? S_OK : E_NOINTERFACE;
685 static IClassFactory activex_cf = { &ClassFactoryVtbl };
686 static IHTMLDocument2 *notif_doc;
687 static BOOL doc_complete;
689 static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface,
690 REFIID riid, void**ppv)
692 if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
693 *ppv = iface;
694 return S_OK;
697 ok(0, "unexpected call\n");
698 return E_NOINTERFACE;
701 static ULONG WINAPI PropertyNotifySink_AddRef(IPropertyNotifySink *iface)
703 return 2;
706 static ULONG WINAPI PropertyNotifySink_Release(IPropertyNotifySink *iface)
708 return 1;
711 static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
713 if(dispID == DISPID_READYSTATE){
714 BSTR state;
715 HRESULT hres;
717 static const WCHAR completeW[] = {'c','o','m','p','l','e','t','e',0};
719 hres = IHTMLDocument2_get_readyState(notif_doc, &state);
720 ok(hres == S_OK, "get_readyState failed: %08x\n", hres);
722 if(!lstrcmpW(state, completeW))
723 doc_complete = TRUE;
725 SysFreeString(state);
728 return S_OK;
731 static HRESULT WINAPI PropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
733 ok(0, "unexpected call\n");
734 return E_NOTIMPL;
737 static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
738 PropertyNotifySink_QueryInterface,
739 PropertyNotifySink_AddRef,
740 PropertyNotifySink_Release,
741 PropertyNotifySink_OnChanged,
742 PropertyNotifySink_OnRequestEdit
745 static IPropertyNotifySink PropertyNotifySink = { &PropertyNotifySinkVtbl };
747 static void doc_load_string(IHTMLDocument2 *doc, const char *str)
749 IPersistStreamInit *init;
750 IStream *stream;
751 HGLOBAL mem;
752 SIZE_T len;
754 notif_doc = doc;
756 doc_complete = FALSE;
757 len = strlen(str);
758 mem = GlobalAlloc(0, len);
759 memcpy(mem, str, len);
760 CreateStreamOnHGlobal(mem, TRUE, &stream);
762 IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init);
764 IPersistStreamInit_Load(init, stream);
765 IPersistStreamInit_Release(init);
766 IStream_Release(stream);
769 static void do_advise(IUnknown *unk, REFIID riid, IUnknown *unk_advise)
771 IConnectionPointContainer *container;
772 IConnectionPoint *cp;
773 DWORD cookie;
774 HRESULT hres;
776 hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&container);
777 ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres);
779 hres = IConnectionPointContainer_FindConnectionPoint(container, riid, &cp);
780 IConnectionPointContainer_Release(container);
781 ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres);
783 hres = IConnectionPoint_Advise(cp, unk_advise, &cookie);
784 IConnectionPoint_Release(cp);
785 ok(hres == S_OK, "Advise failed: %08x\n", hres);
788 static void set_client_site(IHTMLDocument2 *doc, BOOL set)
790 IOleObject *oleobj;
791 HRESULT hres;
793 if(!set && view) {
794 IOleDocumentView_Show(view, FALSE);
795 IOleDocumentView_CloseView(view, 0);
796 IOleDocumentView_SetInPlaceSite(view, NULL);
797 IOleDocumentView_Release(view);
798 view = NULL;
801 hres = IHTMLDocument2_QueryInterface(doc, &IID_IOleObject, (void**)&oleobj);
802 ok(hres == S_OK, "Could not et IOleObject: %08x\n", hres);
804 hres = IOleObject_SetClientSite(oleobj, set ? &ClientSite : NULL);
805 ok(hres == S_OK, "SetClientSite failed: %08x\n", hres);
807 if(set) {
808 IHlinkTarget *hlink;
810 hres = IOleObject_QueryInterface(oleobj, &IID_IHlinkTarget, (void**)&hlink);
811 ok(hres == S_OK, "Could not get IHlinkTarget iface: %08x\n", hres);
813 hres = IHlinkTarget_Navigate(hlink, 0, NULL);
814 ok(hres == S_OK, "Navgate failed: %08x\n", hres);
816 IHlinkTarget_Release(hlink);
819 IOleObject_Release(oleobj);
821 static IHTMLDocument2 *create_document(void)
823 IHTMLDocument2 *doc;
824 HRESULT hres;
826 hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
827 &IID_IHTMLDocument2, (void**)&doc);
828 ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
830 return doc;
833 static IHTMLDocument2 *create_doc(const char *str, BOOL *b)
835 IHTMLDocument2 *doc;
836 MSG msg;
838 doc = create_document();
839 set_client_site(doc, TRUE);
840 doc_load_string(doc, str);
841 do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink);
843 while((!doc_complete || (b && !*b)) && GetMessage(&msg, NULL, 0, 0)) {
844 TranslateMessage(&msg);
845 DispatchMessage(&msg);
848 return doc;
851 static void release_doc(IHTMLDocument2 *doc)
853 ULONG ref;
855 set_client_site(doc, FALSE);
856 ref = IHTMLDocument2_Release(doc);
857 ok(!ref, "ref = %d\n", ref);
860 static void test_object_ax(void)
862 IHTMLDocument2 *doc;
865 * We pump messages until both document is loaded and plugin instance is created.
866 * Pumping until document is loaded should be enough, but Gecko loads plugins
867 * asynchronously and until we'll work around it, we need this hack.
869 SET_EXPECT(CreateInstance);
870 SET_EXPECT(FreezeEvents_TRUE);
871 SET_EXPECT(QuickActivate);
872 SET_EXPECT(FreezeEvents_FALSE);
874 doc = create_doc(object_ax_str, &called_CreateInstance);
876 CHECK_CALLED(CreateInstance);
877 todo_wine
878 CHECK_CALLED(FreezeEvents_TRUE);
879 CHECK_CALLED(QuickActivate);
880 todo_wine
881 CHECK_CALLED(FreezeEvents_FALSE);
883 release_doc(doc);
886 static LRESULT WINAPI wnd_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
888 return DefWindowProc(hwnd, msg, wParam, lParam);
891 static HWND create_container_window(void)
893 static const WCHAR html_document_testW[] =
894 {'H','T','M','L','D','o','c','u','m','e','n','t','T','e','s','t',0};
895 static WNDCLASSEXW wndclass = {
896 sizeof(WNDCLASSEXW),
898 wnd_proc,
899 0, 0, NULL, NULL, NULL, NULL, NULL,
900 html_document_testW,
901 NULL
904 RegisterClassExW(&wndclass);
905 return CreateWindowW(html_document_testW, html_document_testW,
906 WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
907 515, 530, NULL, NULL, NULL, NULL);
910 static BOOL init_key(const char *key_name, const char *def_value, BOOL init)
912 HKEY hkey;
913 DWORD res;
915 if(!init) {
916 RegDeleteKey(HKEY_CLASSES_ROOT, key_name);
917 return TRUE;
920 res = RegCreateKeyA(HKEY_CLASSES_ROOT, key_name, &hkey);
921 if(res != ERROR_SUCCESS)
922 return FALSE;
924 if(def_value)
925 res = RegSetValueA(hkey, NULL, REG_SZ, def_value, strlen(def_value));
927 RegCloseKey(hkey);
929 return res == ERROR_SUCCESS;
932 static BOOL init_registry(BOOL init)
934 return init_key("TestActiveX\\CLSID", TESTACTIVEX_CLSID, init)
935 && init_key("CLSID\\"TESTACTIVEX_CLSID"\\Implemented Categories\\{7dd95801-9882-11cf-9fa9-00aa006c42c4}",
936 NULL, init)
937 && init_key("CLSID\\"TESTACTIVEX_CLSID"\\Implemented Categories\\{7dd95802-9882-11cf-9fa9-00aa006c42c4}",
938 NULL, init);
941 static BOOL register_activex(void)
943 DWORD regid;
944 HRESULT hres;
946 if(!init_registry(TRUE)) {
947 init_registry(FALSE);
948 return FALSE;
951 hres = CoRegisterClassObject(&CLSID_TestActiveX, (IUnknown*)&activex_cf,
952 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &regid);
953 ok(hres == S_OK, "Could not register control: %08x\n", hres);
955 return TRUE;
958 static BOOL check_ie(void)
960 IHTMLDocument5 *doc;
961 HRESULT hres;
963 static const WCHAR xW[] = {'x',0};
964 static const WCHAR yW[] = {'y',0};
966 if(!lstrcmpW(xW, yW))
967 return FALSE;
969 hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
970 &IID_IHTMLDocument5, (void**)&doc);
971 if(FAILED(hres))
972 return FALSE;
974 IHTMLDocument5_Release(doc);
975 return TRUE;
978 START_TEST(activex)
980 CoInitialize(NULL);
982 if(!check_ie()) {
983 CoUninitialize();
984 win_skip("Too old IE\n");
985 return;
988 if(is_ie_hardened()) {
989 CoUninitialize();
990 win_skip("IE running in Enhanced Security Configuration\n");
991 return;
994 container_hwnd = create_container_window();
995 ShowWindow(container_hwnd, SW_SHOW);
997 if(register_activex()) {
998 test_object_ax();
999 init_registry(FALSE);
1000 }else {
1001 skip("Could not register ActiveX\n");
1004 DestroyWindow(container_hwnd);
1005 CoUninitialize();