1 /* 2 * Copyright 2012 Piotr 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 #define COBJMACROS 19 #define CONST_VTABLE 20 21 #include <stdio.h> 22 #include <assert.h> 23 24 #include "windows.h" 25 #include "ole2.h" 26 #include "mshtml.h" 27 #include "mshtmdid.h" 28 #include "initguid.h" 29 #include "perhist.h" 30 #include "docobj.h" 31 #include "urlmon.h" 32 #include "xmlparser.h" 33 34 #include "wine/test.h" 35 36 HRESULT (WINAPI *pCreateURLMoniker)(IMoniker*, LPCWSTR, IMoniker**); 37 38 static const char xmlview_html[] = 39 "\r\n" 40 "<BODY><H2>Generated HTML</H2>\r\n" 41 "<TABLE>\r\n" 42 "<TBODY>\r\n" 43 "<TR bgColor=green>\r\n" 44 "<TH>Title</TH>\r\n" 45 "<TH>Value</TH></TR>\r\n" 46 "<TR>\r\n" 47 "<TD>title1</TD>\r\n" 48 "<TD>value1</TD></TR>\r\n" 49 "<TR>\r\n" 50 "<TD>title2</TD>\r\n" 51 "<TD>value2</TD></TR></TBODY></TABLE></BODY>"; 52 53 IHTMLDocument2 *html_doc; 54 BOOL loaded; 55 56 static int html_src_compare(LPCWSTR strw, const char *stra) 57 { 58 char buf[2048], *p1; 59 const char *p2; 60 61 WideCharToMultiByte(CP_ACP, 0, strw, -1, buf, sizeof(buf), NULL, NULL); 62 63 p1 = buf; 64 p2 = stra; 65 while(1) { 66 while(*p1=='\r' || *p1=='\n' || *p1=='\"') p1++; 67 while(*p2=='\r' || *p2=='\n') p2++; 68 69 if(!*p1 || !*p2 || tolower(*p1)!=tolower(*p2)) 70 break; 71 72 p1++; 73 p2++; 74 } 75 76 return *p1 != *p2; 77 } 78 79 static HRESULT WINAPI HTMLEvents_QueryInterface(IDispatch *iface, REFIID riid, void **ppv) 80 { 81 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IDispatch, riid)) { 82 *ppv = iface; 83 return S_OK; 84 } 85 86 ok(0, "Unexpected call\n"); 87 return E_NOINTERFACE; 88 } 89 90 static ULONG WINAPI HTMLEvents_AddRef(IDispatch *iface) 91 { 92 return 2; 93 } 94 95 static ULONG WINAPI HTMLEvents_Release(IDispatch *iface) 96 { 97 return 1; 98 } 99 100 static HRESULT WINAPI HTMLEvents_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo) 101 { 102 ok(0, "unexpected call\n"); 103 return E_NOTIMPL; 104 } 105 106 static HRESULT WINAPI HTMLEvents_GetTypeInfo(IDispatch *iface, UINT iTInfo, LCID lcid, 107 ITypeInfo **ppTInfo) 108 { 109 ok(0, "unexpected call\n"); 110 return E_NOTIMPL; 111 } 112 113 static HRESULT WINAPI HTMLEvents_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *rgszNames, 114 UINT cNames, LCID lcid, DISPID *rgDispId) 115 { 116 ok(0, "unexpected call\n"); 117 return E_NOTIMPL; 118 } 119 120 static HRESULT WINAPI HTMLEvents_Invoke(IDispatch *iface, DISPID dispIdMember, REFIID riid, 121 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, 122 EXCEPINFO *pExcepInfo, UINT *puArgErr) 123 { 124 if(dispIdMember == DISPID_HTMLDOCUMENTEVENTS2_ONREADYSTATECHANGE) { 125 static const WCHAR completeW[] = {'c','o','m','p','l','e','t','e',0}; 126 HRESULT hr; 127 BSTR state; 128 129 hr = IHTMLDocument2_get_readyState(html_doc, &state); 130 ok(hr == S_OK, "got 0x%08x\n", hr); 131 if(!memcmp(state, completeW, sizeof(completeW))) 132 loaded = TRUE; 133 SysFreeString(state); 134 } 135 136 return S_OK; 137 } 138 139 static const IDispatchVtbl HTMLEventsVtbl = { 140 HTMLEvents_QueryInterface, 141 HTMLEvents_AddRef, 142 HTMLEvents_Release, 143 HTMLEvents_GetTypeInfoCount, 144 HTMLEvents_GetTypeInfo, 145 HTMLEvents_GetIDsOfNames, 146 HTMLEvents_Invoke 147 }; 148 149 static IDispatch HTMLEvents = { &HTMLEventsVtbl }; 150 151 static void test_QueryInterface(void) 152 { 153 IUnknown *xmlview, *unk; 154 IHTMLDocument *htmldoc; 155 HRESULT hres; 156 157 hres = CoCreateInstance(&CLSID_XMLView, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, 158 &IID_IUnknown, (void**)&xmlview); 159 if(FAILED(hres)) { 160 win_skip("Failed to create XMLView instance\n"); 161 return; 162 } 163 ok(hres == S_OK, "CoCreateInstance returned %x, expected S_OK\n", hres); 164 165 hres = IUnknown_QueryInterface(xmlview, &IID_IPersistMoniker, (void**)&unk); 166 ok(hres == S_OK, "QueryInterface(IID_IPersistMoniker) returned %x, expected S_OK\n", hres); 167 IUnknown_Release(unk); 168 169 hres = IUnknown_QueryInterface(xmlview, &IID_IPersistHistory, (void**)&unk); 170 ok(hres == S_OK, "QueryInterface(IID_IPersistHistory) returned %x, expected S_OK\n", hres); 171 IUnknown_Release(unk); 172 173 hres = IUnknown_QueryInterface(xmlview, &IID_IOleCommandTarget, (void**)&unk); 174 ok(hres == S_OK, "QueryInterface(IID_IOleCommandTarget) returned %x, expected S_OK\n", hres); 175 IUnknown_Release(unk); 176 177 hres = IUnknown_QueryInterface(xmlview, &IID_IOleObject, (void**)&unk); 178 ok(hres == S_OK, "QueryInterface(IID_IOleObject) returned %x, expected S_OK\n", hres); 179 IUnknown_Release(unk); 180 181 hres = IUnknown_QueryInterface(xmlview, &IID_IHTMLDocument, (void**)&htmldoc); 182 ok(hres == S_OK, "QueryInterface(IID_IHTMLDocument) returned %x, expected S_OK\n", hres); 183 hres = IHTMLDocument_QueryInterface(htmldoc, &IID_IUnknown, (void**)&unk); 184 ok(hres == S_OK, "QueryInterface(IID_IUnknown) returned %x, expected S_OK\n", hres); 185 ok(unk == xmlview, "Aggregation is not working as expected\n"); 186 IUnknown_Release(unk); 187 IHTMLDocument_Release(htmldoc); 188 189 IUnknown_Release(xmlview); 190 } 191 192 static void test_Load(void) 193 { 194 static const WCHAR xmlview_xmlW[] = {'/','x','m','l','/','x','m','l','v','i','e','w','.','x','m','l',0}; 195 static const WCHAR res[] = {'r','e','s',':','/','/',0}; 196 197 WCHAR buf[1024]; 198 IPersistMoniker *pers_mon; 199 IConnectionPointContainer *cpc; 200 IConnectionPoint *cp; 201 IMoniker *mon; 202 IBindCtx *bctx; 203 IHTMLElement *elem; 204 HRESULT hres; 205 MSG msg; 206 BSTR source; 207 208 lstrcpyW(buf, res); 209 GetModuleFileNameW(NULL, buf+lstrlenW(buf), (sizeof(buf)-sizeof(res))/sizeof(WCHAR)); 210 lstrcatW(buf, xmlview_xmlW); 211 212 if(!pCreateURLMoniker) { 213 win_skip("CreateURLMoniker not available\n"); 214 return; 215 } 216 217 hres = CoCreateInstance(&CLSID_XMLView, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER, 218 &IID_IPersistMoniker, (void**)&pers_mon); 219 if(FAILED(hres)) { 220 win_skip("Failed to create XMLView instance\n"); 221 return; 222 } 223 ok(hres == S_OK, "CoCreateInstance returned %x, expected S_OK\n", hres); 224 225 hres = IPersistMoniker_QueryInterface(pers_mon, &IID_IHTMLDocument2, (void**)&html_doc); 226 ok(hres == S_OK, "QueryInterface(HTMLDocument2) returned %x, expected S_OK\n", hres); 227 hres = IPersistMoniker_QueryInterface(pers_mon, &IID_IConnectionPointContainer, (void**)&cpc); 228 ok(hres == S_OK, "QueryInterface(IConnectionPointContainer) returned %x, expected S_OK\n", hres); 229 hres = IConnectionPointContainer_FindConnectionPoint(cpc, &IID_IDispatch, &cp); 230 ok(hres == S_OK, "FindConnectionPoint returned %x, expected S_OK\n", hres); 231 hres = IConnectionPoint_Advise(cp, (IUnknown*)&HTMLEvents, NULL); 232 ok(hres == S_OK, "Advise returned %x, expected S_OK\n", hres); 233 IConnectionPoint_Release(cp); 234 IConnectionPointContainer_Release(cpc); 235 236 hres = CreateBindCtx(0, &bctx); 237 ok(hres == S_OK, "CreateBindCtx returned %x, expected S_OK\n", hres); 238 hres = pCreateURLMoniker(NULL, buf, &mon); 239 ok(hres == S_OK, "CreateUrlMoniker returned %x, expected S_OK\n", hres); 240 loaded = FALSE; 241 hres = IPersistMoniker_Load(pers_mon, TRUE, mon, bctx, 0); 242 ok(hres == S_OK, "Load returned %x, expected S_OK\n", hres); 243 IBindCtx_Release(bctx); 244 IMoniker_Release(mon); 245 246 while(!loaded && GetMessageA(&msg, NULL, 0, 0)) { 247 TranslateMessage(&msg); 248 DispatchMessageA(&msg); 249 } 250 251 hres = IHTMLDocument2_get_body(html_doc, &elem); 252 ok(hres == S_OK, "get_body returned %x, expected S_OK\n", hres); 253 hres = IHTMLElement_get_outerHTML(elem, &source); 254 ok(hres == S_OK, "get_outerHTML returned %x, expected S_OK\n", hres); 255 ok(!html_src_compare(source, xmlview_html), "Incorrect HTML source: %s\n", wine_dbgstr_w(source)); 256 IHTMLElement_Release(elem); 257 SysFreeString(source); 258 259 IHTMLDocument2_Release(html_doc); 260 html_doc = NULL; 261 IPersistMoniker_Release(pers_mon); 262 } 263 264 START_TEST(xmlview) 265 { 266 HMODULE urlmon = LoadLibraryA("urlmon.dll"); 267 pCreateURLMoniker = (void*)GetProcAddress(urlmon, "CreateURLMoniker"); 268 269 CoInitialize(NULL); 270 test_QueryInterface(); 271 test_Load(); 272 CoUninitialize(); 273 } 274