[MSHTML]
[reactos.git] / reactos / dll / win32 / mshtml / htmlnode.c
1 /*
2 * Copyright 2006 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 #include "mshtml_private.h"
20
21 static HTMLDOMNode *get_node_obj(IHTMLDOMNode*);
22 static HRESULT create_node(HTMLDocumentNode*,nsIDOMNode*,HTMLDOMNode**);
23
24 typedef struct {
25 DispatchEx dispex;
26 IHTMLDOMChildrenCollection IHTMLDOMChildrenCollection_iface;
27
28 LONG ref;
29
30 /* FIXME: implement weak reference */
31 HTMLDocumentNode *doc;
32
33 nsIDOMNodeList *nslist;
34 } HTMLDOMChildrenCollection;
35
36 static inline HTMLDOMChildrenCollection *impl_from_IHTMLDOMChildrenCollection(IHTMLDOMChildrenCollection *iface)
37 {
38 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, IHTMLDOMChildrenCollection_iface);
39 }
40
41 static HRESULT WINAPI HTMLDOMChildrenCollection_QueryInterface(IHTMLDOMChildrenCollection *iface, REFIID riid, void **ppv)
42 {
43 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
44
45 *ppv = NULL;
46
47 if(IsEqualGUID(&IID_IUnknown, riid)) {
48 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
49 *ppv = &This->IHTMLDOMChildrenCollection_iface;
50 }else if(IsEqualGUID(&IID_IHTMLDOMChildrenCollection, riid)) {
51 TRACE("(%p)->(IID_IHTMLDOMChildrenCollection %p)\n", This, ppv);
52 *ppv = &This->IHTMLDOMChildrenCollection_iface;
53 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
54 return *ppv ? S_OK : E_NOINTERFACE;
55 }
56
57 if(*ppv) {
58 IUnknown_AddRef((IUnknown*)*ppv);
59 return S_OK;
60 }
61
62 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
63 return E_NOINTERFACE;
64 }
65
66 static ULONG WINAPI HTMLDOMChildrenCollection_AddRef(IHTMLDOMChildrenCollection *iface)
67 {
68 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
69 LONG ref = InterlockedIncrement(&This->ref);
70
71 TRACE("(%p) ref=%d\n", This, ref);
72
73 return ref;
74 }
75
76 static ULONG WINAPI HTMLDOMChildrenCollection_Release(IHTMLDOMChildrenCollection *iface)
77 {
78 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
79 LONG ref = InterlockedDecrement(&This->ref);
80
81 TRACE("(%p) ref=%d\n", This, ref);
82
83 if(!ref) {
84 htmldoc_release(&This->doc->basedoc);
85 nsIDOMNodeList_Release(This->nslist);
86 heap_free(This);
87 }
88
89 return ref;
90 }
91
92 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfoCount(IHTMLDOMChildrenCollection *iface, UINT *pctinfo)
93 {
94 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
95 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
96 }
97
98 static HRESULT WINAPI HTMLDOMChildrenCollection_GetTypeInfo(IHTMLDOMChildrenCollection *iface, UINT iTInfo,
99 LCID lcid, ITypeInfo **ppTInfo)
100 {
101 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
102 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
103 }
104
105 static HRESULT WINAPI HTMLDOMChildrenCollection_GetIDsOfNames(IHTMLDOMChildrenCollection *iface, REFIID riid,
106 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
107 {
108 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
109 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
110 lcid, rgDispId);
111 }
112
113 static HRESULT WINAPI HTMLDOMChildrenCollection_Invoke(IHTMLDOMChildrenCollection *iface, DISPID dispIdMember,
114 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
115 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
116 {
117 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
118 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
119 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
120 }
121
122 static HRESULT WINAPI HTMLDOMChildrenCollection_get_length(IHTMLDOMChildrenCollection *iface, LONG *p)
123 {
124 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
125 UINT32 length=0;
126
127 TRACE("(%p)->(%p)\n", This, p);
128
129 nsIDOMNodeList_GetLength(This->nslist, &length);
130 *p = length;
131 return S_OK;
132 }
133
134 static HRESULT WINAPI HTMLDOMChildrenCollection__newEnum(IHTMLDOMChildrenCollection *iface, IUnknown **p)
135 {
136 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
137 FIXME("(%p)->(%p)\n", This, p);
138 return E_NOTIMPL;
139 }
140
141 static HRESULT WINAPI HTMLDOMChildrenCollection_item(IHTMLDOMChildrenCollection *iface, LONG index, IDispatch **ppItem)
142 {
143 HTMLDOMChildrenCollection *This = impl_from_IHTMLDOMChildrenCollection(iface);
144 nsIDOMNode *nsnode = NULL;
145 HTMLDOMNode *node;
146 UINT32 length=0;
147 nsresult nsres;
148 HRESULT hres;
149
150 TRACE("(%p)->(%d %p)\n", This, index, ppItem);
151
152 if (ppItem)
153 *ppItem = NULL;
154 else
155 return E_POINTER;
156
157 nsIDOMNodeList_GetLength(This->nslist, &length);
158 if(index < 0 || index >= length)
159 return E_INVALIDARG;
160
161 nsres = nsIDOMNodeList_Item(This->nslist, index, &nsnode);
162 if(NS_FAILED(nsres) || !nsnode) {
163 ERR("Item failed: %08x\n", nsres);
164 return E_FAIL;
165 }
166
167 hres = get_node(This->doc, nsnode, TRUE, &node);
168 if(FAILED(hres))
169 return hres;
170
171 *ppItem = (IDispatch*)&node->IHTMLDOMNode_iface;
172 return S_OK;
173 }
174
175 static const IHTMLDOMChildrenCollectionVtbl HTMLDOMChildrenCollectionVtbl = {
176 HTMLDOMChildrenCollection_QueryInterface,
177 HTMLDOMChildrenCollection_AddRef,
178 HTMLDOMChildrenCollection_Release,
179 HTMLDOMChildrenCollection_GetTypeInfoCount,
180 HTMLDOMChildrenCollection_GetTypeInfo,
181 HTMLDOMChildrenCollection_GetIDsOfNames,
182 HTMLDOMChildrenCollection_Invoke,
183 HTMLDOMChildrenCollection_get_length,
184 HTMLDOMChildrenCollection__newEnum,
185 HTMLDOMChildrenCollection_item
186 };
187
188 static inline HTMLDOMChildrenCollection *impl_from_DispatchEx(DispatchEx *iface)
189 {
190 return CONTAINING_RECORD(iface, HTMLDOMChildrenCollection, dispex);
191 }
192
193 #define DISPID_CHILDCOL_0 MSHTML_DISPID_CUSTOM_MIN
194
195 static HRESULT HTMLDOMChildrenCollection_get_dispid(DispatchEx *dispex, BSTR name, DWORD flags, DISPID *dispid)
196 {
197 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
198 WCHAR *ptr;
199 DWORD idx=0;
200 UINT32 len = 0;
201
202 for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
203 idx = idx*10 + (*ptr-'0');
204 if(*ptr)
205 return DISP_E_UNKNOWNNAME;
206
207 nsIDOMNodeList_GetLength(This->nslist, &len);
208 if(idx >= len)
209 return DISP_E_UNKNOWNNAME;
210
211 *dispid = DISPID_CHILDCOL_0 + idx;
212 TRACE("ret %x\n", *dispid);
213 return S_OK;
214 }
215
216 static HRESULT HTMLDOMChildrenCollection_invoke(DispatchEx *dispex, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
217 VARIANT *res, EXCEPINFO *ei, IServiceProvider *caller)
218 {
219 HTMLDOMChildrenCollection *This = impl_from_DispatchEx(dispex);
220
221 TRACE("(%p)->(%x %x %x %p %p %p %p)\n", This, id, lcid, flags, params, res, ei, caller);
222
223 switch(flags) {
224 case DISPATCH_PROPERTYGET: {
225 IDispatch *disp = NULL;
226 HRESULT hres;
227
228 hres = IHTMLDOMChildrenCollection_item(&This->IHTMLDOMChildrenCollection_iface,
229 id - DISPID_CHILDCOL_0, &disp);
230 if(FAILED(hres))
231 return hres;
232
233 V_VT(res) = VT_DISPATCH;
234 V_DISPATCH(res) = disp;
235 break;
236 }
237
238 default:
239 FIXME("unimplemented flags %x\n", flags);
240 return E_NOTIMPL;
241 }
242
243 return S_OK;
244 }
245
246 static const dispex_static_data_vtbl_t HTMLDOMChildrenCollection_dispex_vtbl = {
247 NULL,
248 HTMLDOMChildrenCollection_get_dispid,
249 HTMLDOMChildrenCollection_invoke,
250 NULL
251 };
252
253 static const tid_t HTMLDOMChildrenCollection_iface_tids[] = {
254 IHTMLDOMChildrenCollection_tid,
255 0
256 };
257
258 static dispex_static_data_t HTMLDOMChildrenCollection_dispex = {
259 &HTMLDOMChildrenCollection_dispex_vtbl,
260 DispDOMChildrenCollection_tid,
261 NULL,
262 HTMLDOMChildrenCollection_iface_tids
263 };
264
265 static IHTMLDOMChildrenCollection *create_child_collection(HTMLDocumentNode *doc, nsIDOMNodeList *nslist)
266 {
267 HTMLDOMChildrenCollection *ret;
268
269 ret = heap_alloc_zero(sizeof(*ret));
270 if(!ret)
271 return NULL;
272
273 ret->IHTMLDOMChildrenCollection_iface.lpVtbl = &HTMLDOMChildrenCollectionVtbl;
274 ret->ref = 1;
275
276 nsIDOMNodeList_AddRef(nslist);
277 ret->nslist = nslist;
278
279 htmldoc_addref(&doc->basedoc);
280 ret->doc = doc;
281
282 init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLDOMChildrenCollection_iface,
283 &HTMLDOMChildrenCollection_dispex);
284
285 return &ret->IHTMLDOMChildrenCollection_iface;
286 }
287
288 static inline HTMLDOMNode *impl_from_IHTMLDOMNode(IHTMLDOMNode *iface)
289 {
290 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode_iface);
291 }
292
293 static HRESULT WINAPI HTMLDOMNode_QueryInterface(IHTMLDOMNode *iface,
294 REFIID riid, void **ppv)
295 {
296 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
297
298 return This->vtbl->qi(This, riid, ppv);
299 }
300
301 static ULONG WINAPI HTMLDOMNode_AddRef(IHTMLDOMNode *iface)
302 {
303 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
304 LONG ref = ccref_incr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface);
305
306 TRACE("(%p) ref=%d\n", This, ref);
307
308 return ref;
309 }
310
311 static ULONG WINAPI HTMLDOMNode_Release(IHTMLDOMNode *iface)
312 {
313 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
314 LONG ref = ccref_decr(&This->ccref, (nsISupports*)&This->IHTMLDOMNode_iface);
315
316 TRACE("(%p) ref=%d\n", This, ref);
317
318 if(!ref) {
319 This->vtbl->destructor(This);
320 release_dispex(&This->dispex);
321 heap_free(This);
322 }
323
324 return ref;
325 }
326
327 static HRESULT WINAPI HTMLDOMNode_GetTypeInfoCount(IHTMLDOMNode *iface, UINT *pctinfo)
328 {
329 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
330 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
331 }
332
333 static HRESULT WINAPI HTMLDOMNode_GetTypeInfo(IHTMLDOMNode *iface, UINT iTInfo,
334 LCID lcid, ITypeInfo **ppTInfo)
335 {
336 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
337 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
338 }
339
340 static HRESULT WINAPI HTMLDOMNode_GetIDsOfNames(IHTMLDOMNode *iface, REFIID riid,
341 LPOLESTR *rgszNames, UINT cNames,
342 LCID lcid, DISPID *rgDispId)
343 {
344 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
345 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
346 lcid, rgDispId);
347 }
348
349 static HRESULT WINAPI HTMLDOMNode_Invoke(IHTMLDOMNode *iface, DISPID dispIdMember,
350 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
351 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
352 {
353 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
354 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
355 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
356 }
357
358 static HRESULT WINAPI HTMLDOMNode_get_nodeType(IHTMLDOMNode *iface, LONG *p)
359 {
360 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
361 UINT16 type = -1;
362
363 TRACE("(%p)->(%p)\n", This, p);
364
365 nsIDOMNode_GetNodeType(This->nsnode, &type);
366
367 switch(type) {
368 case ELEMENT_NODE:
369 *p = 1;
370 break;
371 case TEXT_NODE:
372 *p = 3;
373 break;
374 case COMMENT_NODE:
375 case DOCUMENT_TYPE_NODE:
376 *p = 8;
377 break;
378 case DOCUMENT_NODE:
379 *p = 9;
380 break;
381 case DOCUMENT_FRAGMENT_NODE:
382 *p = 11;
383 break;
384 default:
385 /*
386 * FIXME:
387 * According to MSDN only ELEMENT_NODE and TEXT_NODE are supported.
388 * It needs more tests.
389 */
390 FIXME("type %u\n", type);
391 *p = 0;
392 }
393
394 return S_OK;
395 }
396
397 static HRESULT WINAPI HTMLDOMNode_get_parentNode(IHTMLDOMNode *iface, IHTMLDOMNode **p)
398 {
399 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
400 HTMLDOMNode *node;
401 nsIDOMNode *nsnode;
402 nsresult nsres;
403 HRESULT hres;
404
405 TRACE("(%p)->(%p)\n", This, p);
406
407 nsres = nsIDOMNode_GetParentNode(This->nsnode, &nsnode);
408 if(NS_FAILED(nsres)) {
409 ERR("GetParentNode failed: %08x\n", nsres);
410 return E_FAIL;
411 }
412
413 if(!nsnode) {
414 *p = NULL;
415 return S_OK;
416 }
417
418 hres = get_node(This->doc, nsnode, TRUE, &node);
419 nsIDOMNode_Release(nsnode);
420 if(FAILED(hres))
421 return hres;
422
423 *p = &node->IHTMLDOMNode_iface;
424 return S_OK;
425 }
426
427 static HRESULT WINAPI HTMLDOMNode_hasChildNodes(IHTMLDOMNode *iface, VARIANT_BOOL *fChildren)
428 {
429 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
430 cpp_bool has_child = FALSE;
431 nsresult nsres;
432
433 TRACE("(%p)->(%p)\n", This, fChildren);
434
435 nsres = nsIDOMNode_HasChildNodes(This->nsnode, &has_child);
436 if(NS_FAILED(nsres))
437 ERR("HasChildNodes failed: %08x\n", nsres);
438
439 *fChildren = has_child ? VARIANT_TRUE : VARIANT_FALSE;
440 return S_OK;
441 }
442
443 static HRESULT WINAPI HTMLDOMNode_get_childNodes(IHTMLDOMNode *iface, IDispatch **p)
444 {
445 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
446 nsIDOMNodeList *nslist;
447 nsresult nsres;
448
449 TRACE("(%p)->(%p)\n", This, p);
450
451 nsres = nsIDOMNode_GetChildNodes(This->nsnode, &nslist);
452 if(NS_FAILED(nsres)) {
453 ERR("GetChildNodes failed: %08x\n", nsres);
454 return E_FAIL;
455 }
456
457 *p = (IDispatch*)create_child_collection(This->doc, nslist);
458 nsIDOMNodeList_Release(nslist);
459
460 return *p ? S_OK : E_OUTOFMEMORY;
461 }
462
463 static HRESULT WINAPI HTMLDOMNode_get_attributes(IHTMLDOMNode *iface, IDispatch **p)
464 {
465 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
466 HTMLAttributeCollection *col;
467 HRESULT hres;
468
469 TRACE("(%p)->(%p)\n", This, p);
470
471 if(This->vtbl->get_attr_col) {
472 hres = This->vtbl->get_attr_col(This, &col);
473 if(FAILED(hres))
474 return hres;
475
476 *p = (IDispatch*)&col->IHTMLAttributeCollection_iface;
477 return S_OK;
478 }
479
480 *p = NULL;
481 return S_OK;
482 }
483
484 static HRESULT WINAPI HTMLDOMNode_insertBefore(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
485 VARIANT refChild, IHTMLDOMNode **node)
486 {
487 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
488 HTMLDOMNode *new_child, *node_obj, *ref_node = NULL;
489 nsIDOMNode *nsnode;
490 nsresult nsres;
491 HRESULT hres = S_OK;
492
493 TRACE("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node);
494
495 new_child = get_node_obj(newChild);
496 if(!new_child) {
497 ERR("invalid newChild\n");
498 return E_INVALIDARG;
499 }
500
501 switch(V_VT(&refChild)) {
502 case VT_NULL:
503 break;
504 case VT_DISPATCH: {
505 IHTMLDOMNode *ref_iface;
506
507 if(!V_DISPATCH(&refChild))
508 break;
509
510 hres = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IHTMLDOMNode, (void**)&ref_iface);
511 if(FAILED(hres))
512 break;
513
514 ref_node = get_node_obj(ref_iface);
515 IHTMLDOMNode_Release(ref_iface);
516 if(!ref_node) {
517 ERR("unvalid node\n");
518 hres = E_FAIL;
519 break;
520 }
521 break;
522 }
523 default:
524 FIXME("unimplemented refChild %s\n", debugstr_variant(&refChild));
525 hres = E_NOTIMPL;
526 }
527
528 if(SUCCEEDED(hres)) {
529 nsres = nsIDOMNode_InsertBefore(This->nsnode, new_child->nsnode, ref_node ? ref_node->nsnode : NULL, &nsnode);
530 if(NS_FAILED(nsres)) {
531 ERR("InsertBefore failed: %08x\n", nsres);
532 hres = E_FAIL;
533 }
534 }
535 node_release(new_child);
536 if(ref_node)
537 node_release(ref_node);
538 if(FAILED(hres))
539 return hres;
540
541 hres = get_node(This->doc, nsnode, TRUE, &node_obj);
542 nsIDOMNode_Release(nsnode);
543 if(FAILED(hres))
544 return hres;
545
546 *node = &node_obj->IHTMLDOMNode_iface;
547 return S_OK;
548 }
549
550 static HRESULT WINAPI HTMLDOMNode_removeChild(IHTMLDOMNode *iface, IHTMLDOMNode *oldChild,
551 IHTMLDOMNode **node)
552 {
553 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
554 HTMLDOMNode *node_obj;
555 nsIDOMNode *nsnode;
556 nsresult nsres;
557 HRESULT hres;
558
559 TRACE("(%p)->(%p %p)\n", This, oldChild, node);
560
561 node_obj = get_node_obj(oldChild);
562 if(!node_obj)
563 return E_FAIL;
564
565 nsres = nsIDOMNode_RemoveChild(This->nsnode, node_obj->nsnode, &nsnode);
566 node_release(node_obj);
567 if(NS_FAILED(nsres)) {
568 ERR("RemoveChild failed: %08x\n", nsres);
569 return E_FAIL;
570 }
571
572 hres = get_node(This->doc, nsnode, TRUE, &node_obj);
573 nsIDOMNode_Release(nsnode);
574 if(FAILED(hres))
575 return hres;
576
577 /* FIXME: Make sure that node != newChild */
578 *node = &node_obj->IHTMLDOMNode_iface;
579 return S_OK;
580 }
581
582 static HRESULT WINAPI HTMLDOMNode_replaceChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
583 IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
584 {
585 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
586 HTMLDOMNode *node_new, *node_old, *ret_node;
587 nsIDOMNode *nsnode;
588 nsresult nsres;
589 HRESULT hres;
590
591 TRACE("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
592
593 node_new = get_node_obj(newChild);
594 if(!node_new)
595 return E_FAIL;
596
597 node_old = get_node_obj(oldChild);
598 if(!node_old) {
599 node_release(node_new);
600 return E_FAIL;
601 }
602
603 nsres = nsIDOMNode_ReplaceChild(This->nsnode, node_new->nsnode, node_old->nsnode, &nsnode);
604 node_release(node_new);
605 node_release(node_old);
606 if(NS_FAILED(nsres))
607 return E_FAIL;
608
609 hres = get_node(This->doc, nsnode, TRUE, &ret_node);
610 nsIDOMNode_Release(nsnode);
611 if(FAILED(hres))
612 return hres;
613
614 *node = &ret_node->IHTMLDOMNode_iface;
615 return S_OK;
616 }
617
618 static HRESULT WINAPI HTMLDOMNode_cloneNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
619 IHTMLDOMNode **clonedNode)
620 {
621 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
622 HTMLDOMNode *new_node;
623 nsIDOMNode *nsnode;
624 nsresult nsres;
625 HRESULT hres;
626
627 TRACE("(%p)->(%x %p)\n", This, fDeep, clonedNode);
628
629 nsres = nsIDOMNode_CloneNode(This->nsnode, fDeep != VARIANT_FALSE, 1, &nsnode);
630 if(NS_FAILED(nsres) || !nsnode) {
631 ERR("CloneNode failed: %08x\n", nsres);
632 return E_FAIL;
633 }
634
635 hres = This->vtbl->clone(This, nsnode, &new_node);
636 if(FAILED(hres))
637 return hres;
638
639 *clonedNode = &new_node->IHTMLDOMNode_iface;
640 return S_OK;
641 }
642
643 static HRESULT WINAPI HTMLDOMNode_removeNode(IHTMLDOMNode *iface, VARIANT_BOOL fDeep,
644 IHTMLDOMNode **removed)
645 {
646 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
647 FIXME("(%p)->(%x %p)\n", This, fDeep, removed);
648 return E_NOTIMPL;
649 }
650
651 static HRESULT WINAPI HTMLDOMNode_swapNode(IHTMLDOMNode *iface, IHTMLDOMNode *otherNode,
652 IHTMLDOMNode **swappedNode)
653 {
654 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
655 FIXME("(%p)->(%p %p)\n", This, otherNode, swappedNode);
656 return E_NOTIMPL;
657 }
658
659 static HRESULT WINAPI HTMLDOMNode_replaceNode(IHTMLDOMNode *iface, IHTMLDOMNode *replacement,
660 IHTMLDOMNode **replaced)
661 {
662 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
663 FIXME("(%p)->(%p %p)\n", This, replacement, replaced);
664 return E_NOTIMPL;
665 }
666
667 static HRESULT WINAPI HTMLDOMNode_appendChild(IHTMLDOMNode *iface, IHTMLDOMNode *newChild,
668 IHTMLDOMNode **node)
669 {
670 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
671 HTMLDOMNode *node_obj;
672 nsIDOMNode *nsnode;
673 nsresult nsres;
674 HRESULT hres;
675
676 TRACE("(%p)->(%p %p)\n", This, newChild, node);
677
678 node_obj = get_node_obj(newChild);
679 if(!node_obj)
680 return E_FAIL;
681
682 nsres = nsIDOMNode_AppendChild(This->nsnode, node_obj->nsnode, &nsnode);
683 node_release(node_obj);
684 if(NS_FAILED(nsres)) {
685 ERR("AppendChild failed: %08x\n", nsres);
686 return E_FAIL;
687 }
688
689 hres = get_node(This->doc, nsnode, TRUE, &node_obj);
690 nsIDOMNode_Release(nsnode);
691 if(FAILED(hres))
692 return hres;
693
694 /* FIXME: Make sure that node != newChild */
695 *node = &node_obj->IHTMLDOMNode_iface;
696 return S_OK;
697 }
698
699 static HRESULT WINAPI HTMLDOMNode_get_nodeName(IHTMLDOMNode *iface, BSTR *p)
700 {
701 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
702 nsAString name;
703 nsresult nsres;
704
705 TRACE("(%p)->(%p)\n", This, p);
706
707 nsAString_Init(&name, NULL);
708 nsres = nsIDOMNode_GetNodeName(This->nsnode, &name);
709 return return_nsstr(nsres, &name, p);
710 }
711
712 static HRESULT WINAPI HTMLDOMNode_put_nodeValue(IHTMLDOMNode *iface, VARIANT v)
713 {
714 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
715
716 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
717
718 switch(V_VT(&v)) {
719 case VT_BSTR: {
720 nsAString val_str;
721
722 nsAString_InitDepend(&val_str, V_BSTR(&v));
723 nsIDOMNode_SetNodeValue(This->nsnode, &val_str);
724 nsAString_Finish(&val_str);
725
726 return S_OK;
727 }
728
729 default:
730 FIXME("unsupported value %s\n", debugstr_variant(&v));
731 }
732
733 return E_NOTIMPL;
734 }
735
736 static HRESULT WINAPI HTMLDOMNode_get_nodeValue(IHTMLDOMNode *iface, VARIANT *p)
737 {
738 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
739 const PRUnichar *val;
740 nsAString val_str;
741
742 TRACE("(%p)->(%p)\n", This, p);
743
744 nsAString_Init(&val_str, NULL);
745 nsIDOMNode_GetNodeValue(This->nsnode, &val_str);
746 nsAString_GetData(&val_str, &val);
747
748 if(*val) {
749 V_VT(p) = VT_BSTR;
750 V_BSTR(p) = SysAllocString(val);
751 }else {
752 V_VT(p) = VT_NULL;
753 }
754
755 nsAString_Finish(&val_str);
756
757 return S_OK;
758 }
759
760 static HRESULT WINAPI HTMLDOMNode_get_firstChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
761 {
762 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
763 nsIDOMNode *nschild = NULL;
764 HTMLDOMNode *node;
765 HRESULT hres;
766
767 TRACE("(%p)->(%p)\n", This, p);
768
769 nsIDOMNode_GetFirstChild(This->nsnode, &nschild);
770 if(!nschild) {
771 *p = NULL;
772 return S_OK;
773 }
774
775 hres = get_node(This->doc, nschild, TRUE, &node);
776 nsIDOMNode_Release(nschild);
777 if(FAILED(hres))
778 return hres;
779
780 *p = &node->IHTMLDOMNode_iface;
781 return S_OK;
782 }
783
784 static HRESULT WINAPI HTMLDOMNode_get_lastChild(IHTMLDOMNode *iface, IHTMLDOMNode **p)
785 {
786 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
787 nsIDOMNode *nschild = NULL;
788 HTMLDOMNode *node;
789 HRESULT hres;
790
791 TRACE("(%p)->(%p)\n", This, p);
792
793 nsIDOMNode_GetLastChild(This->nsnode, &nschild);
794 if(!nschild) {
795 *p = NULL;
796 return S_OK;
797 }
798
799 hres = get_node(This->doc, nschild, TRUE, &node);
800 nsIDOMNode_Release(nschild);
801 if(FAILED(hres))
802 return hres;
803
804 *p = &node->IHTMLDOMNode_iface;
805 return S_OK;
806 }
807
808 static HRESULT WINAPI HTMLDOMNode_get_previousSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
809 {
810 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
811 nsIDOMNode *nschild = NULL;
812 HTMLDOMNode *node;
813 HRESULT hres;
814
815 TRACE("(%p)->(%p)\n", This, p);
816
817 nsIDOMNode_GetPreviousSibling(This->nsnode, &nschild);
818 if(!nschild) {
819 *p = NULL;
820 return S_OK;
821 }
822
823 hres = get_node(This->doc, nschild, TRUE, &node);
824 nsIDOMNode_Release(nschild);
825 if(FAILED(hres))
826 return hres;
827
828 *p = &node->IHTMLDOMNode_iface;
829 return S_OK;
830 }
831
832 static HRESULT WINAPI HTMLDOMNode_get_nextSibling(IHTMLDOMNode *iface, IHTMLDOMNode **p)
833 {
834 HTMLDOMNode *This = impl_from_IHTMLDOMNode(iface);
835 nsIDOMNode *nssibling = NULL;
836 HTMLDOMNode *node;
837 HRESULT hres;
838
839 TRACE("(%p)->(%p)\n", This, p);
840
841 nsIDOMNode_GetNextSibling(This->nsnode, &nssibling);
842 if(!nssibling) {
843 *p = NULL;
844 return S_OK;
845 }
846
847 hres = get_node(This->doc, nssibling, TRUE, &node);
848 nsIDOMNode_Release(nssibling);
849 if(FAILED(hres))
850 return hres;
851
852 *p = &node->IHTMLDOMNode_iface;
853 return S_OK;
854 }
855
856 static const IHTMLDOMNodeVtbl HTMLDOMNodeVtbl = {
857 HTMLDOMNode_QueryInterface,
858 HTMLDOMNode_AddRef,
859 HTMLDOMNode_Release,
860 HTMLDOMNode_GetTypeInfoCount,
861 HTMLDOMNode_GetTypeInfo,
862 HTMLDOMNode_GetIDsOfNames,
863 HTMLDOMNode_Invoke,
864 HTMLDOMNode_get_nodeType,
865 HTMLDOMNode_get_parentNode,
866 HTMLDOMNode_hasChildNodes,
867 HTMLDOMNode_get_childNodes,
868 HTMLDOMNode_get_attributes,
869 HTMLDOMNode_insertBefore,
870 HTMLDOMNode_removeChild,
871 HTMLDOMNode_replaceChild,
872 HTMLDOMNode_cloneNode,
873 HTMLDOMNode_removeNode,
874 HTMLDOMNode_swapNode,
875 HTMLDOMNode_replaceNode,
876 HTMLDOMNode_appendChild,
877 HTMLDOMNode_get_nodeName,
878 HTMLDOMNode_put_nodeValue,
879 HTMLDOMNode_get_nodeValue,
880 HTMLDOMNode_get_firstChild,
881 HTMLDOMNode_get_lastChild,
882 HTMLDOMNode_get_previousSibling,
883 HTMLDOMNode_get_nextSibling
884 };
885
886 static HTMLDOMNode *get_node_obj(IHTMLDOMNode *iface)
887 {
888 HTMLDOMNode *ret;
889
890 if(iface->lpVtbl != &HTMLDOMNodeVtbl)
891 return NULL;
892
893 ret = impl_from_IHTMLDOMNode(iface);
894 node_addref(ret);
895 return ret;
896 }
897
898 static inline HTMLDOMNode *impl_from_IHTMLDOMNode2(IHTMLDOMNode2 *iface)
899 {
900 return CONTAINING_RECORD(iface, HTMLDOMNode, IHTMLDOMNode2_iface);
901 }
902
903 static HRESULT WINAPI HTMLDOMNode2_QueryInterface(IHTMLDOMNode2 *iface,
904 REFIID riid, void **ppv)
905 {
906 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
907
908 return IHTMLDOMNode_QueryInterface(&This->IHTMLDOMNode_iface, riid, ppv);
909 }
910
911 static ULONG WINAPI HTMLDOMNode2_AddRef(IHTMLDOMNode2 *iface)
912 {
913 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
914
915 return IHTMLDOMNode_AddRef(&This->IHTMLDOMNode_iface);
916 }
917
918 static ULONG WINAPI HTMLDOMNode2_Release(IHTMLDOMNode2 *iface)
919 {
920 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
921
922 return IHTMLDOMNode_Release(&This->IHTMLDOMNode_iface);
923 }
924
925 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfoCount(IHTMLDOMNode2 *iface, UINT *pctinfo)
926 {
927 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
928 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
929 }
930
931 static HRESULT WINAPI HTMLDOMNode2_GetTypeInfo(IHTMLDOMNode2 *iface, UINT iTInfo,
932 LCID lcid, ITypeInfo **ppTInfo)
933 {
934 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
935 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
936 }
937
938 static HRESULT WINAPI HTMLDOMNode2_GetIDsOfNames(IHTMLDOMNode2 *iface, REFIID riid,
939 LPOLESTR *rgszNames, UINT cNames,
940 LCID lcid, DISPID *rgDispId)
941 {
942 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
943 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
944 lcid, rgDispId);
945 }
946
947 static HRESULT WINAPI HTMLDOMNode2_Invoke(IHTMLDOMNode2 *iface, DISPID dispIdMember,
948 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
949 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
950 {
951 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
952 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
953 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
954 }
955
956 static HRESULT WINAPI HTMLDOMNode2_get_ownerDocument(IHTMLDOMNode2 *iface, IDispatch **p)
957 {
958 HTMLDOMNode *This = impl_from_IHTMLDOMNode2(iface);
959
960 TRACE("(%p)->(%p)\n", This, p);
961
962 /* FIXME: Better check for document node */
963 if(This == &This->doc->node) {
964 *p = NULL;
965 }else {
966 *p = (IDispatch*)&This->doc->basedoc.IHTMLDocument2_iface;
967 IDispatch_AddRef(*p);
968 }
969 return S_OK;
970 }
971
972 static const IHTMLDOMNode2Vtbl HTMLDOMNode2Vtbl = {
973 HTMLDOMNode2_QueryInterface,
974 HTMLDOMNode2_AddRef,
975 HTMLDOMNode2_Release,
976 HTMLDOMNode2_GetTypeInfoCount,
977 HTMLDOMNode2_GetTypeInfo,
978 HTMLDOMNode2_GetIDsOfNames,
979 HTMLDOMNode2_Invoke,
980 HTMLDOMNode2_get_ownerDocument
981 };
982
983 static nsXPCOMCycleCollectionParticipant node_ccp;
984
985 HRESULT HTMLDOMNode_QI(HTMLDOMNode *This, REFIID riid, void **ppv)
986 {
987 *ppv = NULL;
988
989 if(IsEqualGUID(&IID_IUnknown, riid)) {
990 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
991 *ppv = &This->IHTMLDOMNode_iface;
992 }else if(IsEqualGUID(&IID_IDispatch, riid)) {
993 TRACE("(%p)->(IID_IDispatch %p)\n", This, ppv);
994 *ppv = &This->IHTMLDOMNode_iface;
995 }else if(IsEqualGUID(&IID_IDispatchEx, riid)) {
996 if(This->dispex.data) {
997 TRACE("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
998 *ppv = &This->dispex.IDispatchEx_iface;
999 }else {
1000 FIXME("(%p)->(IID_IDispatchEx %p)\n", This, ppv);
1001 return E_NOINTERFACE;
1002 }
1003 }else if(IsEqualGUID(&IID_IHTMLDOMNode, riid)) {
1004 TRACE("(%p)->(IID_IHTMLDOMNode %p)\n", This, ppv);
1005 *ppv = &This->IHTMLDOMNode_iface;
1006 }else if(IsEqualGUID(&IID_IHTMLDOMNode2, riid)) {
1007 TRACE("(%p)->(IID_IHTMLDOMNode2 %p)\n", This, ppv);
1008 *ppv = &This->IHTMLDOMNode2_iface;
1009 }else if(IsEqualGUID(&IID_nsXPCOMCycleCollectionParticipant, riid)) {
1010 TRACE("(%p)->(IID_nsXPCOMCycleCollectionParticipant %p)\n", This, ppv);
1011 *ppv = &node_ccp;
1012 return NS_OK;
1013 }else if(IsEqualGUID(&IID_nsCycleCollectionISupports, riid)) {
1014 TRACE("(%p)->(IID_nsCycleCollectionISupports %p)\n", This, ppv);
1015 *ppv = &This->IHTMLDOMNode_iface;
1016 return NS_OK;
1017 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
1018 return *ppv ? S_OK : E_NOINTERFACE;
1019 }
1020
1021 if(*ppv) {
1022 IUnknown_AddRef((IUnknown*)*ppv);
1023 return S_OK;
1024 }
1025
1026 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
1027 return E_NOINTERFACE;
1028 }
1029
1030 void HTMLDOMNode_destructor(HTMLDOMNode *This)
1031 {
1032 if(This->nsnode)
1033 nsIDOMNode_Release(This->nsnode);
1034 if(This->doc && &This->doc->node != This)
1035 htmldoc_release(&This->doc->basedoc);
1036 if(This->event_target)
1037 release_event_target(This->event_target);
1038 }
1039
1040 static HRESULT HTMLDOMNode_clone(HTMLDOMNode *This, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1041 {
1042 return create_node(This->doc, nsnode, ret);
1043 }
1044
1045 static const cpc_entry_t HTMLDOMNode_cpc[] = {{NULL}};
1046
1047 static const NodeImplVtbl HTMLDOMNodeImplVtbl = {
1048 HTMLDOMNode_QI,
1049 HTMLDOMNode_destructor,
1050 HTMLDOMNode_cpc,
1051 HTMLDOMNode_clone
1052 };
1053
1054 void HTMLDOMNode_Init(HTMLDocumentNode *doc, HTMLDOMNode *node, nsIDOMNode *nsnode)
1055 {
1056 nsresult nsres;
1057
1058 node->IHTMLDOMNode_iface.lpVtbl = &HTMLDOMNodeVtbl;
1059 node->IHTMLDOMNode2_iface.lpVtbl = &HTMLDOMNode2Vtbl;
1060
1061 ccref_init(&node->ccref, 1);
1062
1063 if(&doc->node != node)
1064 htmldoc_addref(&doc->basedoc);
1065 node->doc = doc;
1066
1067 nsIDOMNode_AddRef(nsnode);
1068 node->nsnode = nsnode;
1069
1070 nsres = nsIDOMNode_SetMshtmlNode(nsnode, (nsISupports*)&node->IHTMLDOMNode_iface);
1071 assert(nsres == NS_OK);
1072 }
1073
1074 static HRESULT create_node(HTMLDocumentNode *doc, nsIDOMNode *nsnode, HTMLDOMNode **ret)
1075 {
1076 UINT16 node_type;
1077 HRESULT hres;
1078
1079 nsIDOMNode_GetNodeType(nsnode, &node_type);
1080
1081 switch(node_type) {
1082 case ELEMENT_NODE: {
1083 HTMLElement *elem;
1084 hres = HTMLElement_Create(doc, nsnode, FALSE, &elem);
1085 if(FAILED(hres))
1086 return hres;
1087 *ret = &elem->node;
1088 break;
1089 }
1090 case TEXT_NODE:
1091 hres = HTMLDOMTextNode_Create(doc, nsnode, ret);
1092 if(FAILED(hres))
1093 return hres;
1094 break;
1095 /* doctype nodes are represented as comment nodes (at least in quirks mode) */
1096 case DOCUMENT_TYPE_NODE:
1097 case COMMENT_NODE: {
1098 HTMLElement *comment;
1099 hres = HTMLCommentElement_Create(doc, nsnode, &comment);
1100 if(FAILED(hres))
1101 return hres;
1102 *ret = &comment->node;
1103 break;
1104 }
1105 case ATTRIBUTE_NODE:
1106 ERR("Called on attribute node\n");
1107 return E_UNEXPECTED;
1108 default: {
1109 HTMLDOMNode *node;
1110
1111 node = heap_alloc_zero(sizeof(HTMLDOMNode));
1112 if(!node)
1113 return E_OUTOFMEMORY;
1114
1115 node->vtbl = &HTMLDOMNodeImplVtbl;
1116 HTMLDOMNode_Init(doc, node, nsnode);
1117 *ret = node;
1118 }
1119 }
1120
1121 TRACE("type %d ret %p\n", node_type, *ret);
1122 return S_OK;
1123 }
1124
1125 static void NSAPI HTMLDOMNode_unmark_if_purple(void *p)
1126 {
1127 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1128 ccref_unmark_if_purple(&This->ccref);
1129 }
1130
1131 static nsresult NSAPI HTMLDOMNode_traverse(void *ccp, void *p, nsCycleCollectionTraversalCallback *cb)
1132 {
1133 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1134
1135 TRACE("%p\n", This);
1136
1137 describe_cc_node(&This->ccref, "HTMLDOMNode", cb);
1138
1139 if(This->nsnode)
1140 note_cc_edge((nsISupports*)This->nsnode, "This->nsnode", cb);
1141 if(This->doc && &This->doc->node != This)
1142 note_cc_edge((nsISupports*)&This->doc->node.IHTMLDOMNode_iface, "This->doc", cb);
1143 dispex_traverse(&This->dispex, cb);
1144
1145 if(This->vtbl->traverse)
1146 This->vtbl->traverse(This, cb);
1147
1148 return NS_OK;
1149 }
1150
1151 static nsresult NSAPI HTMLDOMNode_unlink(void *p)
1152 {
1153 HTMLDOMNode *This = impl_from_IHTMLDOMNode(p);
1154
1155 TRACE("%p\n", This);
1156
1157 if(This->vtbl->unlink)
1158 This->vtbl->unlink(This);
1159
1160 dispex_unlink(&This->dispex);
1161
1162 if(This->nsnode) {
1163 nsIDOMNode *nsnode = This->nsnode;
1164 This->nsnode = NULL;
1165 nsIDOMNode_Release(nsnode);
1166 }
1167
1168 if(This->doc && &This->doc->node != This) {
1169 HTMLDocument *doc = &This->doc->basedoc;
1170 This->doc = NULL;
1171 htmldoc_release(doc);
1172 }else {
1173 This->doc = NULL;
1174 }
1175
1176 return NS_OK;
1177 }
1178
1179 void init_node_cc(void)
1180 {
1181 static const CCObjCallback node_ccp_callback = {
1182 HTMLDOMNode_unmark_if_purple,
1183 HTMLDOMNode_traverse,
1184 HTMLDOMNode_unlink
1185 };
1186
1187 ccp_init(&node_ccp, &node_ccp_callback);
1188 }
1189
1190 HRESULT get_node(HTMLDocumentNode *This, nsIDOMNode *nsnode, BOOL create, HTMLDOMNode **ret)
1191 {
1192 nsISupports *unk = NULL;
1193 nsresult nsres;
1194
1195 nsres = nsIDOMNode_GetMshtmlNode(nsnode, &unk);
1196 assert(nsres == NS_OK);
1197
1198 if(unk) {
1199 *ret = get_node_obj((IHTMLDOMNode*)unk);
1200 nsISupports_Release(unk);
1201 return NS_OK;
1202 }
1203
1204 if(!create) {
1205 *ret = NULL;
1206 return S_OK;
1207 }
1208
1209 return create_node(This, nsnode, ret);
1210 }