crypt32: Only free allocated handles.
[wine] / dlls / mshtml / tests / dom.c
1 /*
2  * Copyright 2007 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
32 static const char doc_str1[] = "<html><body>test</body></html>";
33
34 static const char *dbgstr_w(LPCWSTR str)
35 {
36     static char buf[512];
37     WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
38     return buf;
39 }
40
41 static int strcmp_wa(LPCWSTR strw, const char *stra)
42 {
43     WCHAR buf[512];
44     MultiByteToWideChar(CP_ACP, 0, stra, -1, buf, sizeof(buf)/sizeof(WCHAR));
45     return lstrcmpW(strw, buf);
46 }
47
48 static IHTMLDocument2 *create_document(void)
49 {
50     IHTMLDocument2 *doc;
51     HRESULT hres;
52
53     hres = CoCreateInstance(&CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
54             &IID_IHTMLDocument2, (void**)&doc);
55     ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
56
57     return doc;
58 }
59
60 static void test_node_name(IUnknown *unk, const char *exname)
61 {
62     IHTMLDOMNode *node;
63     BSTR name;
64     HRESULT hres;
65
66     hres = IUnknown_QueryInterface(unk, &IID_IHTMLDOMNode, (void**)&node);
67     ok(hres == S_OK, "QueryInterface(IID_IHTMLNode) failed: %08x\n", hres);
68
69     hres = IHTMLDOMNode_get_nodeName(node, &name);
70     IHTMLDOMNode_Release(node);
71     ok(hres == S_OK, "get_nodeName failed: %08x\n", hres);
72     ok(!strcmp_wa(name, exname), "got name: %s, expected HTML\n", dbgstr_w(name));
73
74     SysFreeString(name);
75 }
76
77 static void test_doc_elem(IHTMLDocument2 *doc)
78 {
79     IHTMLElement *elem;
80     IHTMLDocument3 *doc3;
81     HRESULT hres;
82
83     hres = IHTMLDocument2_QueryInterface(doc, &IID_IHTMLDocument3, (void**)&doc3);
84     ok(hres == S_OK, "QueryInterface(IID_IHTMLDocument3) failed: %08x\n", hres);
85
86     hres = IHTMLDocument3_get_documentElement(doc3, &elem);
87     IHTMLDocument3_Release(doc3);
88     ok(hres == S_OK, "get_documentElement failed: %08x\n", hres);
89
90     test_node_name((IUnknown*)elem, "HTML");
91
92     IHTMLElement_Release(elem);
93 }
94
95 static IHTMLDocument2 *notif_doc;
96 static BOOL doc_complete;
97
98 static HRESULT WINAPI PropertyNotifySink_QueryInterface(IPropertyNotifySink *iface,
99         REFIID riid, void**ppv)
100 {
101     if(IsEqualGUID(&IID_IPropertyNotifySink, riid)) {
102         *ppv = iface;
103         return S_OK;
104     }
105
106     ok(0, "unexpected call\n");
107     return E_NOINTERFACE;
108 }
109
110 static ULONG WINAPI PropertyNotifySink_AddRef(IPropertyNotifySink *iface)
111 {
112     return 2;
113 }
114
115 static ULONG WINAPI PropertyNotifySink_Release(IPropertyNotifySink *iface)
116 {
117     return 1;
118 }
119
120 static HRESULT WINAPI PropertyNotifySink_OnChanged(IPropertyNotifySink *iface, DISPID dispID)
121 {
122     if(dispID == DISPID_READYSTATE){
123         BSTR state;
124         HRESULT hres;
125
126         static const WCHAR completeW[] = {'c','o','m','p','l','e','t','e',0};
127
128         hres = IHTMLDocument2_get_readyState(notif_doc, &state);
129         ok(hres == S_OK, "get_readyState failed: %08x\n", hres);
130
131         if(!lstrcmpW(state, completeW))
132             doc_complete = TRUE;
133
134         SysFreeString(state);        
135     }
136
137     return S_OK;
138 }
139
140 static HRESULT WINAPI PropertyNotifySink_OnRequestEdit(IPropertyNotifySink *iface, DISPID dispID)
141 {
142     ok(0, "unexpected call\n");
143     return E_NOTIMPL;
144 }
145
146 static IPropertyNotifySinkVtbl PropertyNotifySinkVtbl = {
147     PropertyNotifySink_QueryInterface,
148     PropertyNotifySink_AddRef,
149     PropertyNotifySink_Release,
150     PropertyNotifySink_OnChanged,
151     PropertyNotifySink_OnRequestEdit
152 };
153
154 static IPropertyNotifySink PropertyNotifySink = { &PropertyNotifySinkVtbl };
155
156 static IHTMLDocument2 *create_doc_with_string(const char *str)
157 {
158     IPersistStreamInit *init;
159     IStream *stream;
160     IHTMLDocument2 *doc;
161     HGLOBAL mem;
162     SIZE_T len;
163
164     notif_doc = doc = create_document();
165     if(!doc)
166         return NULL;
167
168     doc_complete = FALSE;
169     len = strlen(str);
170     mem = GlobalAlloc(0, len);
171     memcpy(mem, str, len);
172     CreateStreamOnHGlobal(mem, TRUE, &stream);
173
174     IHTMLDocument2_QueryInterface(doc, &IID_IPersistStreamInit, (void**)&init);
175
176     IPersistStreamInit_Load(init, stream);
177     IPersistStreamInit_Release(init);
178     IStream_Release(stream);
179
180     return doc;
181 }
182
183 static void do_advise(IUnknown *unk, REFIID riid, IUnknown *unk_advise)
184 {
185     IConnectionPointContainer *container;
186     IConnectionPoint *cp;
187     DWORD cookie;
188     HRESULT hres;
189
190     hres = IUnknown_QueryInterface(unk, &IID_IConnectionPointContainer, (void**)&container);
191     ok(hres == S_OK, "QueryInterface(IID_IConnectionPointContainer) failed: %08x\n", hres);
192
193     hres = IConnectionPointContainer_FindConnectionPoint(container, riid, &cp);
194     IConnectionPointContainer_Release(container);
195     ok(hres == S_OK, "FindConnectionPoint failed: %08x\n", hres);
196
197     hres = IConnectionPoint_Advise(cp, unk_advise, &cookie);
198     IConnectionPoint_Release(cp);
199     ok(hres == S_OK, "Advise failed: %08x\n", hres);
200 }
201
202 typedef void (*domtest_t)(IHTMLDocument2*);
203
204 static void run_domtest(const char *str, domtest_t test)
205 {
206     IHTMLDocument2 *doc;
207     ULONG ref;
208     MSG msg;
209
210     doc = create_doc_with_string(str);
211     do_advise((IUnknown*)doc, &IID_IPropertyNotifySink, (IUnknown*)&PropertyNotifySink);
212
213     while(!doc_complete && GetMessage(&msg, NULL, 0, 0)) {
214         TranslateMessage(&msg);
215         DispatchMessage(&msg);
216     }
217
218     test(doc);
219
220     ref = IHTMLDocument2_Release(doc);
221     ok(!ref, "ref = %d\n", ref);
222 }
223
224 static void gecko_installer_workaround(BOOL disable)
225 {
226     HKEY hkey;
227     DWORD res;
228
229     static BOOL has_url = FALSE;
230     static char url[2048];
231
232     if(!disable && !has_url)
233         return;
234
235     res = RegOpenKey(HKEY_CURRENT_USER, "Software\\Wine\\MSHTML", &hkey);
236     if(res != ERROR_SUCCESS)
237         return;
238
239     if(disable) {
240         DWORD type, size = sizeof(url);
241
242         res = RegQueryValueEx(hkey, "GeckoUrl", NULL, &type, (PVOID)url, &size);
243         if(res == ERROR_SUCCESS && type == REG_SZ)
244             has_url = TRUE;
245
246         RegDeleteValue(hkey, "GeckoUrl");
247     }else {
248         RegSetValueEx(hkey, "GeckoUrl", 0, REG_SZ, (PVOID)url, lstrlenA(url)+1);
249     }
250
251     RegCloseKey(hkey);
252 }
253
254 START_TEST(dom)
255 {
256     gecko_installer_workaround(TRUE);
257     CoInitialize(NULL);
258
259     run_domtest(doc_str1, test_doc_elem);
260
261     CoUninitialize();
262     gecko_installer_workaround(FALSE);
263 }