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