Commit | Line | Data |
---|---|---|
65293d8e MM |
1 | /* |
2 | * Node implementation | |
3 | * | |
4 | * Copyright 2005 Mike McCormack | |
5 | * | |
d1b21b5c | 6 | * This library is free software; you can redistribute it and/or |
65293d8e MM |
7 | * modify it under the terms of the GNU Lesser General Public |
8 | * License as published by the Free Software Foundation; either | |
9 | * version 2.1 of the License, or (at your option) any later version. | |
10 | * | |
d1b21b5c | 11 | * This library is distributed in the hope that it will be useful, |
65293d8e MM |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * Lesser General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU Lesser General Public | |
17 | * License along with this library; if not, write to the Free Software | |
360a3f91 | 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
65293d8e MM |
19 | */ |
20 | ||
21 | #include "config.h" | |
22 | ||
23 | #define COBJMACROS | |
24 | ||
25 | #include <stdarg.h> | |
23f192d2 | 26 | #include <assert.h> |
65293d8e MM |
27 | #include "windef.h" |
28 | #include "winbase.h" | |
29 | #include "winuser.h" | |
30 | #include "winnls.h" | |
31 | #include "ole2.h" | |
5b8be5dc | 32 | #include "msxml2.h" |
65293d8e MM |
33 | |
34 | #include "msxml_private.h" | |
35 | ||
36 | #include "wine/debug.h" | |
37 | ||
38 | WINE_DEFAULT_DEBUG_CHANNEL(msxml); | |
39 | ||
40 | #ifdef HAVE_LIBXML2 | |
41 | ||
3f6bb98f HD |
42 | static inline xmlnode *impl_from_InternalUnknown( IUnknown *iface ) |
43 | { | |
44 | return (xmlnode *)((char*)iface - FIELD_OFFSET(xmlnode, lpInternalUnkVtbl)); | |
45 | } | |
46 | ||
23f192d2 | 47 | xmlNodePtr xmlNodePtr_from_domnode( IXMLDOMNode *iface, xmlElementType type ) |
65293d8e MM |
48 | { |
49 | xmlnode *This; | |
50 | ||
51 | if ( !iface ) | |
52 | return NULL; | |
65293d8e | 53 | This = impl_from_IXMLDOMNode( iface ); |
23f192d2 | 54 | if ( !This->node ) |
65293d8e | 55 | return NULL; |
23f192d2 | 56 | if ( type && This->node->type != type ) |
65293d8e | 57 | return NULL; |
23f192d2 | 58 | return This->node; |
65293d8e MM |
59 | } |
60 | ||
3f6bb98f HD |
61 | void attach_xmlnode( IXMLDOMNode *node, xmlNodePtr xml ) |
62 | { | |
63 | xmlnode *This = impl_from_IXMLDOMNode( node ); | |
64 | ||
65 | if(This->node) | |
66 | xmldoc_release(This->node->doc); | |
67 | ||
68 | This->node = xml; | |
69 | if(This->node) | |
70 | xmldoc_add_ref(This->node->doc); | |
71 | ||
72 | return; | |
73 | } | |
74 | ||
65293d8e MM |
75 | static HRESULT WINAPI xmlnode_QueryInterface( |
76 | IXMLDOMNode *iface, | |
77 | REFIID riid, | |
78 | void** ppvObject ) | |
79 | { | |
3f6bb98f HD |
80 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
81 | TRACE("%p %s %p\n", This, debugstr_guid(riid), ppvObject); | |
65293d8e | 82 | |
3f6bb98f | 83 | return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObject); |
65293d8e MM |
84 | } |
85 | ||
86 | static ULONG WINAPI xmlnode_AddRef( | |
87 | IXMLDOMNode *iface ) | |
88 | { | |
89 | xmlnode *This = impl_from_IXMLDOMNode( iface ); | |
3f6bb98f | 90 | return IUnknown_AddRef(This->pUnkOuter); |
65293d8e MM |
91 | } |
92 | ||
93 | static ULONG WINAPI xmlnode_Release( | |
94 | IXMLDOMNode *iface ) | |
95 | { | |
96 | xmlnode *This = impl_from_IXMLDOMNode( iface ); | |
3f6bb98f | 97 | return IUnknown_Release(This->pUnkOuter); |
65293d8e MM |
98 | } |
99 | ||
100 | static HRESULT WINAPI xmlnode_GetTypeInfoCount( | |
101 | IXMLDOMNode *iface, | |
102 | UINT* pctinfo ) | |
103 | { | |
104 | FIXME("\n"); | |
105 | return E_NOTIMPL; | |
106 | } | |
107 | ||
108 | static HRESULT WINAPI xmlnode_GetTypeInfo( | |
109 | IXMLDOMNode *iface, | |
110 | UINT iTInfo, | |
111 | LCID lcid, | |
112 | ITypeInfo** ppTInfo ) | |
113 | { | |
114 | FIXME("\n"); | |
115 | return E_NOTIMPL; | |
116 | } | |
117 | ||
118 | static HRESULT WINAPI xmlnode_GetIDsOfNames( | |
119 | IXMLDOMNode *iface, | |
120 | REFIID riid, | |
121 | LPOLESTR* rgszNames, | |
122 | UINT cNames, | |
123 | LCID lcid, | |
124 | DISPID* rgDispId ) | |
125 | { | |
126 | FIXME("\n"); | |
127 | return E_NOTIMPL; | |
128 | } | |
129 | ||
130 | static HRESULT WINAPI xmlnode_Invoke( | |
131 | IXMLDOMNode *iface, | |
132 | DISPID dispIdMember, | |
133 | REFIID riid, | |
134 | LCID lcid, | |
135 | WORD wFlags, | |
136 | DISPPARAMS* pDispParams, | |
137 | VARIANT* pVarResult, | |
138 | EXCEPINFO* pExcepInfo, | |
139 | UINT* puArgErr ) | |
140 | { | |
141 | FIXME("\n"); | |
142 | return E_NOTIMPL; | |
143 | } | |
144 | ||
2b7ae268 | 145 | static HRESULT WINAPI xmlnode_get_nodeName( |
65293d8e MM |
146 | IXMLDOMNode *iface, |
147 | BSTR* name) | |
148 | { | |
a182e093 MM |
149 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
150 | const xmlChar *str; | |
151 | ||
152 | TRACE("%p\n", This ); | |
153 | ||
d148ca4e SH |
154 | if (!name) |
155 | return E_INVALIDARG; | |
156 | ||
a182e093 MM |
157 | if ( !This->node ) |
158 | return E_FAIL; | |
159 | ||
160 | switch( This->node->type ) | |
161 | { | |
0a80e7c0 ALH |
162 | case XML_CDATA_SECTION_NODE: |
163 | str = (const xmlChar*) "#cdata-section"; | |
164 | break; | |
165 | case XML_COMMENT_NODE: | |
166 | str = (const xmlChar*) "#comment"; | |
a182e093 | 167 | break; |
0a80e7c0 ALH |
168 | case XML_DOCUMENT_FRAG_NODE: |
169 | str = (const xmlChar*) "#document-fragment"; | |
170 | break; | |
171 | case XML_TEXT_NODE: | |
172 | str = (const xmlChar*) "#text"; | |
173 | break; | |
d148ca4e | 174 | case XML_DOCUMENT_NODE: |
0a80e7c0 ALH |
175 | str = (const xmlChar*) "#document"; |
176 | break; | |
177 | case XML_ATTRIBUTE_NODE: | |
178 | case XML_ELEMENT_NODE: | |
179 | str = This->node->name; | |
180 | break; | |
a182e093 | 181 | default: |
0a80e7c0 | 182 | FIXME("nodeName not mapped correctly (%d)\n", This->node->type); |
a182e093 MM |
183 | str = This->node->name; |
184 | break; | |
185 | } | |
186 | ||
187 | *name = bstr_from_xmlChar( str ); | |
188 | if (!*name) | |
189 | return S_FALSE; | |
190 | ||
191 | return S_OK; | |
65293d8e MM |
192 | } |
193 | ||
194 | BSTR bstr_from_xmlChar( const xmlChar *buf ) | |
195 | { | |
196 | DWORD len; | |
197 | LPWSTR str; | |
198 | BSTR bstr; | |
199 | ||
200 | if ( !buf ) | |
201 | return NULL; | |
202 | ||
203 | len = MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, NULL, 0 ); | |
204 | str = (LPWSTR) HeapAlloc( GetProcessHeap(), 0, len * sizeof (WCHAR) ); | |
205 | if ( !str ) | |
206 | return NULL; | |
207 | MultiByteToWideChar( CP_UTF8, 0, (LPCSTR) buf, -1, str, len ); | |
208 | bstr = SysAllocString( str ); | |
209 | HeapFree( GetProcessHeap(), 0, str ); | |
210 | return bstr; | |
211 | } | |
212 | ||
2b7ae268 | 213 | static HRESULT WINAPI xmlnode_get_nodeValue( |
65293d8e MM |
214 | IXMLDOMNode *iface, |
215 | VARIANT* value) | |
216 | { | |
217 | xmlnode *This = impl_from_IXMLDOMNode( iface ); | |
23f192d2 | 218 | HRESULT r = S_FALSE; |
65293d8e MM |
219 | |
220 | TRACE("%p %p\n", This, value); | |
221 | ||
7c1a7491 ALH |
222 | if(!value) |
223 | return E_INVALIDARG; | |
224 | ||
23f192d2 MM |
225 | V_BSTR(value) = NULL; |
226 | V_VT(value) = VT_NULL; | |
227 | ||
228 | switch ( This->node->type ) | |
65293d8e | 229 | { |
65293d8e | 230 | case XML_ATTRIBUTE_NODE: |
e7187ff3 HD |
231 | { |
232 | xmlChar *content = xmlNodeGetContent(This->node); | |
65293d8e | 233 | V_VT(value) = VT_BSTR; |
e7187ff3 HD |
234 | V_BSTR(value) = bstr_from_xmlChar( content ); |
235 | xmlFree(content); | |
23f192d2 | 236 | r = S_OK; |
65293d8e | 237 | break; |
e7187ff3 | 238 | } |
23f192d2 MM |
239 | case XML_TEXT_NODE: |
240 | V_VT(value) = VT_BSTR; | |
241 | V_BSTR(value) = bstr_from_xmlChar( This->node->content ); | |
242 | r = S_OK; | |
65293d8e MM |
243 | break; |
244 | case XML_ELEMENT_NODE: | |
245 | case XML_DOCUMENT_NODE: | |
23f192d2 | 246 | /* these seem to return NULL */ |
65293d8e | 247 | break; |
23f192d2 MM |
248 | case XML_PI_NODE: |
249 | default: | |
250 | FIXME("node %p type %d\n", This, This->node->type); | |
65293d8e MM |
251 | } |
252 | ||
253 | TRACE("%p returned %s\n", This, debugstr_w( V_BSTR(value) ) ); | |
254 | ||
23f192d2 | 255 | return r; |
65293d8e MM |
256 | } |
257 | ||
2b7ae268 | 258 | static HRESULT WINAPI xmlnode_put_nodeValue( |
65293d8e MM |
259 | IXMLDOMNode *iface, |
260 | VARIANT value) | |
261 | { | |
262 | FIXME("\n"); | |
263 | return E_NOTIMPL; | |
264 | } | |
265 | ||
2b7ae268 | 266 | static HRESULT WINAPI xmlnode_get_nodeType( |
65293d8e MM |
267 | IXMLDOMNode *iface, |
268 | DOMNodeType* type) | |
269 | { | |
23f192d2 MM |
270 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
271 | ||
272 | TRACE("%p %p\n", This, type); | |
273 | ||
274 | assert( NODE_ELEMENT == XML_ELEMENT_NODE ); | |
275 | assert( NODE_NOTATION == XML_NOTATION_NODE ); | |
276 | ||
277 | *type = This->node->type; | |
278 | ||
279 | return S_OK; | |
65293d8e MM |
280 | } |
281 | ||
dc2e14d9 MM |
282 | static HRESULT get_node( |
283 | xmlnode *This, | |
284 | const char *name, | |
285 | xmlNodePtr node, | |
286 | IXMLDOMNode **out ) | |
287 | { | |
288 | TRACE("%p->%s %p\n", This, name, node ); | |
289 | ||
290 | if ( !out ) | |
291 | return E_INVALIDARG; | |
292 | *out = create_node( node ); | |
293 | if (!*out) | |
294 | return S_FALSE; | |
295 | return S_OK; | |
296 | } | |
297 | ||
65293d8e MM |
298 | static HRESULT WINAPI xmlnode_get_parentNode( |
299 | IXMLDOMNode *iface, | |
300 | IXMLDOMNode** parent) | |
301 | { | |
dc2e14d9 MM |
302 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
303 | return get_node( This, "parent", This->node->parent, parent ); | |
65293d8e MM |
304 | } |
305 | ||
306 | static HRESULT WINAPI xmlnode_get_childNodes( | |
307 | IXMLDOMNode *iface, | |
308 | IXMLDOMNodeList** childList) | |
309 | { | |
310 | xmlnode *This = impl_from_IXMLDOMNode( iface ); | |
23f192d2 MM |
311 | |
312 | TRACE("%p %p\n", This, childList ); | |
313 | ||
314 | if ( !childList ) | |
315 | return E_INVALIDARG; | |
3d0c6627 | 316 | |
e1cbec75 MZ |
317 | *childList = create_children_nodelist(This->node); |
318 | if (*childList == NULL) | |
319 | return E_OUTOFMEMORY; | |
3d0c6627 | 320 | |
23f192d2 | 321 | return S_OK; |
65293d8e MM |
322 | } |
323 | ||
324 | static HRESULT WINAPI xmlnode_get_firstChild( | |
325 | IXMLDOMNode *iface, | |
326 | IXMLDOMNode** firstChild) | |
327 | { | |
dc2e14d9 MM |
328 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
329 | return get_node( This, "firstChild", This->node->children, firstChild ); | |
65293d8e MM |
330 | } |
331 | ||
332 | static HRESULT WINAPI xmlnode_get_lastChild( | |
333 | IXMLDOMNode *iface, | |
334 | IXMLDOMNode** lastChild) | |
335 | { | |
dc2e14d9 | 336 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
91ad27ea ALH |
337 | |
338 | TRACE("%p\n", This ); | |
339 | ||
340 | if (!lastChild) | |
341 | return E_INVALIDARG; | |
342 | ||
343 | switch( This->node->type ) | |
344 | { | |
345 | /* CDATASection, Comment, PI and Text Nodes do not support lastChild */ | |
346 | case XML_TEXT_NODE: | |
347 | case XML_CDATA_SECTION_NODE: | |
348 | case XML_PI_NODE: | |
349 | case XML_COMMENT_NODE: | |
350 | *lastChild = NULL; | |
351 | return S_FALSE; | |
352 | default: | |
353 | return get_node( This, "lastChild", This->node->last, lastChild ); | |
354 | } | |
65293d8e MM |
355 | } |
356 | ||
357 | static HRESULT WINAPI xmlnode_get_previousSibling( | |
358 | IXMLDOMNode *iface, | |
359 | IXMLDOMNode** previousSibling) | |
360 | { | |
dc2e14d9 | 361 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
2896c462 ALH |
362 | |
363 | TRACE("%p\n", This ); | |
364 | ||
365 | if (!previousSibling) | |
366 | return E_INVALIDARG; | |
367 | ||
368 | switch( This->node->type ) | |
369 | { | |
370 | /* Attribute, Document and Document Fragment Nodes do not support previousSibling */ | |
371 | case XML_DOCUMENT_NODE: | |
372 | case XML_DOCUMENT_FRAG_NODE: | |
373 | case XML_ATTRIBUTE_NODE: | |
374 | *previousSibling = NULL; | |
375 | return S_FALSE; | |
376 | default: | |
377 | return get_node( This, "previous", This->node->prev, previousSibling ); | |
378 | } | |
65293d8e MM |
379 | } |
380 | ||
381 | static HRESULT WINAPI xmlnode_get_nextSibling( | |
382 | IXMLDOMNode *iface, | |
383 | IXMLDOMNode** nextSibling) | |
384 | { | |
dc2e14d9 | 385 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
4e908f65 ALH |
386 | |
387 | TRACE("%p\n", This ); | |
388 | ||
389 | if (!nextSibling) | |
390 | return E_INVALIDARG; | |
391 | ||
392 | switch( This->node->type ) | |
393 | { | |
394 | /* Attribute, Document and Document Fragment Nodes do not support nextSibling */ | |
395 | case XML_DOCUMENT_NODE: | |
396 | case XML_DOCUMENT_FRAG_NODE: | |
397 | case XML_ATTRIBUTE_NODE: | |
398 | *nextSibling = NULL; | |
399 | return S_FALSE; | |
400 | default: | |
401 | return get_node( This, "next", This->node->next, nextSibling ); | |
402 | } | |
65293d8e MM |
403 | } |
404 | ||
405 | static HRESULT WINAPI xmlnode_get_attributes( | |
406 | IXMLDOMNode *iface, | |
407 | IXMLDOMNamedNodeMap** attributeMap) | |
408 | { | |
409 | xmlnode *This = impl_from_IXMLDOMNode( iface ); | |
23f192d2 | 410 | TRACE("%p\n", This); |
e906b136 ALH |
411 | |
412 | if (!attributeMap) | |
413 | return E_INVALIDARG; | |
414 | ||
415 | switch( This->node->type ) | |
416 | { | |
417 | /* Attribute, CDataSection, Comment, Documents, Documents Fragments, | |
418 | Entity and Text Nodes does not support get_attributes */ | |
419 | case XML_ATTRIBUTE_NODE: | |
bf4a43e1 | 420 | case XML_CDATA_SECTION_NODE: |
e906b136 ALH |
421 | case XML_COMMENT_NODE: |
422 | case XML_DOCUMENT_NODE: | |
423 | case XML_DOCUMENT_FRAG_NODE: | |
424 | case XML_ENTITY_NODE: | |
bfeb14d0 | 425 | case XML_ENTITY_REF_NODE: |
e906b136 ALH |
426 | case XML_TEXT_NODE: |
427 | *attributeMap = NULL; | |
428 | return S_FALSE; | |
429 | default: | |
430 | *attributeMap = create_nodemap( iface ); | |
431 | return S_OK; | |
432 | } | |
65293d8e MM |
433 | } |
434 | ||
435 | static HRESULT WINAPI xmlnode_insertBefore( | |
436 | IXMLDOMNode *iface, | |
437 | IXMLDOMNode* newChild, | |
438 | VARIANT refChild, | |
439 | IXMLDOMNode** outNewChild) | |
440 | { | |
50c64c04 HD |
441 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
442 | xmlNodePtr before_node, new_child_node; | |
443 | IXMLDOMNode *before = NULL, *new; | |
444 | HRESULT hr; | |
445 | ||
446 | TRACE("(%p)->(%p,var,%p)\n",This,newChild,outNewChild); | |
447 | ||
7fbf828a | 448 | if (!newChild) |
c75d739d PC |
449 | return E_INVALIDARG; |
450 | ||
50c64c04 HD |
451 | switch(V_VT(&refChild)) |
452 | { | |
453 | case VT_EMPTY: | |
454 | case VT_NULL: | |
455 | break; | |
456 | ||
457 | case VT_UNKNOWN: | |
458 | hr = IUnknown_QueryInterface(V_UNKNOWN(&refChild), &IID_IXMLDOMNode, (LPVOID)&before); | |
459 | if(FAILED(hr)) return hr; | |
460 | break; | |
461 | ||
462 | case VT_DISPATCH: | |
463 | hr = IDispatch_QueryInterface(V_DISPATCH(&refChild), &IID_IXMLDOMNode, (LPVOID)&before); | |
464 | if(FAILED(hr)) return hr; | |
465 | break; | |
466 | ||
467 | default: | |
468 | FIXME("refChild var type %x\n", V_VT(&refChild)); | |
469 | return E_FAIL; | |
470 | } | |
471 | ||
472 | IXMLDOMNode_QueryInterface(newChild, &IID_IXMLDOMNode, (LPVOID)&new); | |
473 | new_child_node = impl_from_IXMLDOMNode(new)->node; | |
474 | TRACE("new_child_node %p This->node %p\n", new_child_node, This->node); | |
475 | ||
476 | if(before) | |
477 | { | |
478 | before_node = impl_from_IXMLDOMNode(before)->node; | |
479 | xmlAddPrevSibling(before_node, new_child_node); | |
480 | IXMLDOMNode_Release(before); | |
481 | } | |
482 | else | |
483 | { | |
484 | xmlAddChild(This->node, new_child_node); | |
485 | } | |
486 | ||
487 | IXMLDOMNode_Release(new); | |
488 | IXMLDOMNode_AddRef(newChild); | |
7fbf828a ALH |
489 | if(outNewChild) |
490 | *outNewChild = newChild; | |
491 | ||
50c64c04 HD |
492 | TRACE("ret S_OK\n"); |
493 | return S_OK; | |
65293d8e MM |
494 | } |
495 | ||
496 | static HRESULT WINAPI xmlnode_replaceChild( | |
497 | IXMLDOMNode *iface, | |
498 | IXMLDOMNode* newChild, | |
499 | IXMLDOMNode* oldChild, | |
500 | IXMLDOMNode** outOldChild) | |
501 | { | |
502 | FIXME("\n"); | |
503 | return E_NOTIMPL; | |
504 | } | |
505 | ||
506 | static HRESULT WINAPI xmlnode_removeChild( | |
507 | IXMLDOMNode *iface, | |
508 | IXMLDOMNode* childNode, | |
509 | IXMLDOMNode** oldChild) | |
510 | { | |
187ab1c0 HD |
511 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
512 | xmlNode *ancestor, *child_node_ptr; | |
513 | HRESULT hr; | |
514 | IXMLDOMNode *child; | |
515 | ||
516 | TRACE("%p->(%p, %p)\n", This, childNode, oldChild); | |
517 | ||
518 | *oldChild = NULL; | |
a307901a HD |
519 | |
520 | if(!childNode) return E_INVALIDARG; | |
521 | ||
187ab1c0 HD |
522 | hr = IXMLDOMNode_QueryInterface(childNode, &IID_IXMLDOMNode, (LPVOID)&child); |
523 | if(FAILED(hr)) | |
524 | return hr; | |
525 | ||
526 | child_node_ptr = ancestor = impl_from_IXMLDOMNode(child)->node; | |
527 | while(ancestor->parent) | |
528 | { | |
529 | if(ancestor->parent == This->node) | |
530 | break; | |
531 | ancestor = ancestor->parent; | |
532 | } | |
533 | if(!ancestor->parent) | |
534 | { | |
535 | WARN("childNode %p is not a child of %p\n", childNode, iface); | |
536 | IXMLDOMNode_Release(child); | |
537 | return E_INVALIDARG; | |
538 | } | |
539 | ||
540 | xmlUnlinkNode(child_node_ptr); | |
541 | ||
542 | IXMLDOMNode_Release(child); | |
543 | IXMLDOMNode_AddRef(childNode); | |
544 | *oldChild = childNode; | |
545 | return S_OK; | |
65293d8e MM |
546 | } |
547 | ||
548 | static HRESULT WINAPI xmlnode_appendChild( | |
549 | IXMLDOMNode *iface, | |
550 | IXMLDOMNode* newChild, | |
551 | IXMLDOMNode** outNewChild) | |
552 | { | |
50c64c04 | 553 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
cdac6b50 | 554 | IXMLDOMNode *pAttr = NULL; |
50c64c04 HD |
555 | VARIANT var; |
556 | ||
557 | TRACE("(%p)->(%p,%p)\n", This, newChild, outNewChild); | |
cdac6b50 ALH |
558 | |
559 | /* Cannot Append an Attribute node. */ | |
560 | IUnknown_QueryInterface(newChild, &IID_IXMLDOMNode, (LPVOID*)&pAttr); | |
561 | if(pAttr) | |
562 | { | |
563 | xmlnode *ThisNew = impl_from_IXMLDOMNode( pAttr ); | |
564 | ||
565 | if(ThisNew->node->type == XML_ATTRIBUTE_NODE) | |
566 | { | |
567 | if(outNewChild) *outNewChild = NULL; | |
568 | ||
569 | IUnknown_Release(pAttr); | |
570 | ||
571 | return E_FAIL; | |
572 | } | |
573 | ||
574 | IUnknown_Release(pAttr); | |
575 | } | |
576 | ||
50c64c04 HD |
577 | VariantInit(&var); |
578 | return IXMLDOMNode_insertBefore(iface, newChild, var, outNewChild); | |
65293d8e MM |
579 | } |
580 | ||
581 | static HRESULT WINAPI xmlnode_hasChildNodes( | |
582 | IXMLDOMNode *iface, | |
583 | VARIANT_BOOL* hasChild) | |
584 | { | |
da3393d4 MM |
585 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
586 | ||
587 | TRACE("%p\n", This); | |
588 | ||
589 | if (!hasChild) | |
590 | return E_INVALIDARG; | |
591 | if (!This->node->children) | |
592 | { | |
593 | *hasChild = VARIANT_FALSE; | |
594 | return S_FALSE; | |
595 | } | |
596 | ||
597 | *hasChild = VARIANT_TRUE; | |
598 | return S_OK; | |
65293d8e MM |
599 | } |
600 | ||
601 | static HRESULT WINAPI xmlnode_get_ownerDocument( | |
602 | IXMLDOMNode *iface, | |
603 | IXMLDOMDocument** DOMDocument) | |
604 | { | |
605 | FIXME("\n"); | |
606 | return E_NOTIMPL; | |
607 | } | |
608 | ||
609 | static HRESULT WINAPI xmlnode_cloneNode( | |
610 | IXMLDOMNode *iface, | |
611 | VARIANT_BOOL deep, | |
612 | IXMLDOMNode** cloneRoot) | |
613 | { | |
86af5b97 ALH |
614 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
615 | xmlNodePtr pClone = NULL; | |
616 | IXMLDOMNode *pNode = NULL; | |
617 | ||
618 | TRACE("%p (%d)\n", This, deep); | |
619 | ||
620 | if(!cloneRoot) | |
621 | return E_INVALIDARG; | |
622 | ||
623 | pClone = xmlCopyNode(This->node, deep ? 1 : 2); | |
624 | if(pClone) | |
625 | { | |
626 | pClone->doc = This->node->doc; | |
627 | ||
628 | pNode = create_node(pClone); | |
629 | if(!pNode) | |
630 | { | |
631 | ERR("Copy failed\n"); | |
632 | return E_FAIL; | |
633 | } | |
634 | ||
635 | *cloneRoot = pNode; | |
636 | } | |
637 | else | |
638 | { | |
639 | ERR("Copy failed\n"); | |
640 | return E_FAIL; | |
641 | } | |
642 | ||
643 | return S_OK; | |
65293d8e MM |
644 | } |
645 | ||
2b7ae268 | 646 | static HRESULT WINAPI xmlnode_get_nodeTypeString( |
65293d8e MM |
647 | IXMLDOMNode *iface, |
648 | BSTR* xmlnodeType) | |
649 | { | |
055b5e44 ALH |
650 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
651 | const xmlChar *str; | |
652 | ||
653 | TRACE("%p\n", This ); | |
654 | ||
655 | if (!xmlnodeType) | |
656 | return E_INVALIDARG; | |
657 | ||
658 | if ( !This->node ) | |
659 | return E_FAIL; | |
660 | ||
661 | switch( This->node->type ) | |
662 | { | |
663 | case XML_ATTRIBUTE_NODE: | |
664 | str = (const xmlChar*) "attribute"; | |
665 | break; | |
666 | case XML_CDATA_SECTION_NODE: | |
667 | str = (const xmlChar*) "cdatasection"; | |
668 | break; | |
669 | case XML_COMMENT_NODE: | |
670 | str = (const xmlChar*) "comment"; | |
671 | break; | |
672 | case XML_DOCUMENT_NODE: | |
673 | str = (const xmlChar*) "document"; | |
674 | break; | |
675 | case XML_DOCUMENT_FRAG_NODE: | |
676 | str = (const xmlChar*) "documentfragment"; | |
677 | break; | |
678 | case XML_ELEMENT_NODE: | |
679 | str = (const xmlChar*) "element"; | |
680 | break; | |
681 | case XML_ENTITY_NODE: | |
682 | str = (const xmlChar*) "entity"; | |
683 | break; | |
684 | case XML_ENTITY_REF_NODE: | |
685 | str = (const xmlChar*) "entityreference"; | |
686 | break; | |
687 | case XML_NOTATION_NODE: | |
688 | str = (const xmlChar*) "notation"; | |
689 | break; | |
690 | case XML_PI_NODE: | |
691 | str = (const xmlChar*) "processinginstruction"; | |
692 | break; | |
693 | case XML_TEXT_NODE: | |
694 | str = (const xmlChar*) "text"; | |
695 | break; | |
696 | default: | |
697 | FIXME("nodeName not mapped correctly (%d)\n", This->node->type); | |
698 | str = This->node->name; | |
699 | break; | |
700 | } | |
701 | ||
702 | *xmlnodeType = bstr_from_xmlChar( str ); | |
703 | if (!*xmlnodeType) | |
704 | return S_FALSE; | |
705 | ||
706 | return S_OK; | |
65293d8e MM |
707 | } |
708 | ||
709 | static HRESULT WINAPI xmlnode_get_text( | |
710 | IXMLDOMNode *iface, | |
711 | BSTR* text) | |
712 | { | |
23f192d2 | 713 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
23f192d2 MM |
714 | BSTR str = NULL; |
715 | ||
716 | TRACE("%p\n", This); | |
717 | ||
718 | if ( !text ) | |
719 | return E_INVALIDARG; | |
720 | ||
04d5d0a6 HD |
721 | switch(This->node->type) |
722 | { | |
723 | case XML_ELEMENT_NODE: | |
724 | case XML_ATTRIBUTE_NODE: | |
725 | { | |
726 | xmlNodePtr child = This->node->children; | |
727 | if ( child && child->type == XML_TEXT_NODE ) | |
728 | str = bstr_from_xmlChar( child->content ); | |
729 | break; | |
730 | } | |
731 | ||
732 | case XML_TEXT_NODE: | |
d3a524cd RS |
733 | case XML_CDATA_SECTION_NODE: |
734 | case XML_PI_NODE: | |
735 | case XML_COMMENT_NODE: | |
04d5d0a6 HD |
736 | str = bstr_from_xmlChar( This->node->content ); |
737 | break; | |
23f192d2 | 738 | |
04d5d0a6 HD |
739 | default: |
740 | FIXME("Unhandled node type %d\n", This->node->type); | |
741 | } | |
c443674d ALH |
742 | |
743 | /* Always return a string. */ | |
744 | if (!str) str = SysAllocStringLen( NULL, 0 ); | |
745 | ||
23f192d2 MM |
746 | TRACE("%p %s\n", This, debugstr_w(str) ); |
747 | *text = str; | |
748 | ||
749 | return S_OK; | |
65293d8e MM |
750 | } |
751 | ||
752 | static HRESULT WINAPI xmlnode_put_text( | |
753 | IXMLDOMNode *iface, | |
754 | BSTR text) | |
755 | { | |
b2101b81 ALH |
756 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
757 | xmlChar *str = NULL; | |
758 | ||
759 | TRACE("%p\n", This); | |
760 | ||
761 | switch(This->node->type) | |
762 | { | |
763 | case XML_DOCUMENT_NODE: | |
764 | return E_FAIL; | |
765 | default: | |
766 | break; | |
767 | } | |
768 | ||
769 | str = xmlChar_from_wchar((WCHAR*)text); | |
770 | ||
771 | /* Escape the string. */ | |
772 | str = xmlEncodeEntitiesReentrant(This->node->doc, str); | |
773 | str = xmlEncodeSpecialChars(This->node->doc, str); | |
774 | ||
775 | xmlNodeSetContent(This->node, str); | |
776 | xmlFree(str); | |
777 | ||
778 | return S_OK; | |
65293d8e MM |
779 | } |
780 | ||
781 | static HRESULT WINAPI xmlnode_get_specified( | |
782 | IXMLDOMNode *iface, | |
783 | VARIANT_BOOL* isSpecified) | |
784 | { | |
785 | FIXME("\n"); | |
786 | return E_NOTIMPL; | |
787 | } | |
788 | ||
789 | static HRESULT WINAPI xmlnode_get_definition( | |
790 | IXMLDOMNode *iface, | |
791 | IXMLDOMNode** definitionNode) | |
792 | { | |
793 | FIXME("\n"); | |
794 | return E_NOTIMPL; | |
795 | } | |
796 | ||
2b7ae268 | 797 | static HRESULT WINAPI xmlnode_get_nodeTypedValue( |
65293d8e MM |
798 | IXMLDOMNode *iface, |
799 | VARIANT* typedValue) | |
800 | { | |
917a801d HD |
801 | FIXME("ignoring data type\n"); |
802 | return xmlnode_get_nodeValue(iface, typedValue); | |
65293d8e MM |
803 | } |
804 | ||
2b7ae268 | 805 | static HRESULT WINAPI xmlnode_put_nodeTypedValue( |
65293d8e MM |
806 | IXMLDOMNode *iface, |
807 | VARIANT typedValue) | |
808 | { | |
809 | FIXME("\n"); | |
810 | return E_NOTIMPL; | |
811 | } | |
812 | ||
813 | static HRESULT WINAPI xmlnode_get_dataType( | |
814 | IXMLDOMNode *iface, | |
815 | VARIANT* dataTypeName) | |
816 | { | |
e989d48f ALH |
817 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
818 | xmlChar *pVal; | |
819 | ||
820 | TRACE("iface %p\n", iface); | |
821 | ||
822 | if(!dataTypeName) | |
823 | return E_INVALIDARG; | |
824 | ||
8c3dd87f | 825 | /* Attribute, CDATA Section, Comment, Document, Document Fragment, |
e989d48f ALH |
826 | Entity, Notation, PI, and Text Node are non-typed. */ |
827 | V_BSTR(dataTypeName) = NULL; | |
828 | V_VT(dataTypeName) = VT_NULL; | |
829 | ||
830 | switch ( This->node->type ) | |
831 | { | |
e989d48f ALH |
832 | case XML_ELEMENT_NODE: |
833 | pVal = xmlGetNsProp(This->node, (xmlChar*)"dt", | |
834 | (xmlChar*)"urn:schemas-microsoft-com:datatypes"); | |
835 | if (pVal) | |
836 | { | |
837 | V_VT(dataTypeName) = VT_BSTR; | |
838 | V_BSTR(dataTypeName) = bstr_from_xmlChar( pVal ); | |
839 | xmlFree(pVal); | |
840 | } | |
841 | break; | |
842 | case XML_ENTITY_REF_NODE: | |
843 | FIXME("XML_ENTITY_REF_NODE should return a valid value.\n"); | |
844 | break; | |
845 | default: | |
846 | TRACE("Type %d returning NULL\n", This->node->type); | |
847 | } | |
848 | ||
849 | /* non-typed nodes return S_FALSE */ | |
850 | if(V_VT(dataTypeName) == VT_NULL) | |
851 | { | |
852 | return S_FALSE; | |
853 | } | |
854 | ||
855 | return S_OK; | |
65293d8e MM |
856 | } |
857 | ||
858 | static HRESULT WINAPI xmlnode_put_dataType( | |
859 | IXMLDOMNode *iface, | |
860 | BSTR dataTypeName) | |
861 | { | |
862 | FIXME("\n"); | |
863 | return E_NOTIMPL; | |
864 | } | |
865 | ||
866 | static HRESULT WINAPI xmlnode_get_xml( | |
867 | IXMLDOMNode *iface, | |
868 | BSTR* xmlString) | |
869 | { | |
11331847 ALH |
870 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
871 | xmlBufferPtr pXmlBuf; | |
872 | int nSize; | |
873 | ||
874 | TRACE("iface %p\n", iface); | |
875 | ||
876 | if(!xmlString) | |
877 | return E_INVALIDARG; | |
878 | ||
879 | *xmlString = NULL; | |
880 | ||
881 | pXmlBuf = xmlBufferCreate(); | |
882 | if(pXmlBuf) | |
883 | { | |
884 | nSize = xmlNodeDump(pXmlBuf, This->node->doc, This->node, 0, 0); | |
885 | if(nSize > 0) | |
886 | { | |
887 | const xmlChar *pContent; | |
888 | ||
889 | /* Attribute Nodes return a space infront of their name */ | |
890 | pContent = xmlBufferContent(pXmlBuf); | |
891 | if( ((char*)pContent)[0] == ' ') | |
892 | *xmlString = bstr_from_xmlChar(pContent+1); | |
893 | else | |
894 | *xmlString = bstr_from_xmlChar(pContent); | |
895 | ||
896 | ||
897 | xmlBufferFree(pXmlBuf); | |
898 | } | |
899 | } | |
900 | ||
901 | /* Always returns a string. */ | |
902 | if(*xmlString == NULL) *xmlString = SysAllocStringLen( NULL, 0 ); | |
903 | ||
904 | return S_OK; | |
65293d8e MM |
905 | } |
906 | ||
907 | static HRESULT WINAPI xmlnode_transformNode( | |
908 | IXMLDOMNode *iface, | |
909 | IXMLDOMNode* styleSheet, | |
910 | BSTR* xmlString) | |
911 | { | |
912 | FIXME("\n"); | |
913 | return E_NOTIMPL; | |
914 | } | |
915 | ||
916 | static HRESULT WINAPI xmlnode_selectNodes( | |
917 | IXMLDOMNode *iface, | |
918 | BSTR queryString, | |
919 | IXMLDOMNodeList** resultList) | |
920 | { | |
f3719a88 | 921 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
f3719a88 MM |
922 | |
923 | TRACE("%p %s %p\n", This, debugstr_w(queryString), resultList ); | |
924 | ||
e1cbec75 | 925 | return queryresult_create( This->node, queryString, resultList ); |
65293d8e MM |
926 | } |
927 | ||
928 | static HRESULT WINAPI xmlnode_selectSingleNode( | |
929 | IXMLDOMNode *iface, | |
930 | BSTR queryString, | |
931 | IXMLDOMNode** resultNode) | |
932 | { | |
c3687360 HD |
933 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
934 | IXMLDOMNodeList *list; | |
935 | HRESULT r; | |
936 | ||
937 | TRACE("%p %s %p\n", This, debugstr_w(queryString), resultNode ); | |
938 | ||
e1cbec75 | 939 | *resultNode = NULL; |
c3687360 | 940 | r = IXMLDOMNode_selectNodes(iface, queryString, &list); |
bce90cfb | 941 | if(r == S_OK) |
c3687360 HD |
942 | { |
943 | r = IXMLDOMNodeList_nextNode(list, resultNode); | |
944 | IXMLDOMNodeList_Release(list); | |
945 | } | |
946 | return r; | |
65293d8e MM |
947 | } |
948 | ||
949 | static HRESULT WINAPI xmlnode_get_parsed( | |
950 | IXMLDOMNode *iface, | |
951 | VARIANT_BOOL* isParsed) | |
952 | { | |
953 | FIXME("\n"); | |
954 | return E_NOTIMPL; | |
955 | } | |
956 | ||
957 | static HRESULT WINAPI xmlnode_get_namespaceURI( | |
958 | IXMLDOMNode *iface, | |
959 | BSTR* namespaceURI) | |
960 | { | |
961 | FIXME("\n"); | |
962 | return E_NOTIMPL; | |
963 | } | |
964 | ||
965 | static HRESULT WINAPI xmlnode_get_prefix( | |
966 | IXMLDOMNode *iface, | |
967 | BSTR* prefixString) | |
968 | { | |
969 | FIXME("\n"); | |
970 | return E_NOTIMPL; | |
971 | } | |
972 | ||
973 | static HRESULT WINAPI xmlnode_get_baseName( | |
974 | IXMLDOMNode *iface, | |
975 | BSTR* nameString) | |
976 | { | |
23f192d2 MM |
977 | xmlnode *This = impl_from_IXMLDOMNode( iface ); |
978 | BSTR str = NULL; | |
979 | HRESULT r = S_FALSE; | |
980 | ||
981 | TRACE("%p %p\n", This, nameString ); | |
982 | ||
983 | if ( !nameString ) | |
984 | return E_INVALIDARG; | |
985 | ||
986 | switch ( This->node->type ) | |
987 | { | |
988 | case XML_ELEMENT_NODE: | |
989 | case XML_ATTRIBUTE_NODE: | |
990 | str = bstr_from_xmlChar( This->node->name ); | |
991 | r = S_OK; | |
992 | break; | |
993 | case XML_TEXT_NODE: | |
994 | break; | |
995 | default: | |
996 | ERR("Unhandled type %d\n", This->node->type ); | |
997 | break; | |
998 | } | |
999 | ||
7ff24491 | 1000 | TRACE("returning %08x str = %s\n", r, debugstr_w( str ) ); |
23f192d2 MM |
1001 | |
1002 | *nameString = str; | |
1003 | return r; | |
65293d8e MM |
1004 | } |
1005 | ||
1006 | static HRESULT WINAPI xmlnode_transformNodeToObject( | |
1007 | IXMLDOMNode *iface, | |
1008 | IXMLDOMNode* stylesheet, | |
1009 | VARIANT outputObject) | |
1010 | { | |
1011 | FIXME("\n"); | |
1012 | return E_NOTIMPL; | |
1013 | } | |
1014 | ||
1015 | static const struct IXMLDOMNodeVtbl xmlnode_vtbl = | |
1016 | { | |
1017 | xmlnode_QueryInterface, | |
1018 | xmlnode_AddRef, | |
1019 | xmlnode_Release, | |
1020 | xmlnode_GetTypeInfoCount, | |
1021 | xmlnode_GetTypeInfo, | |
1022 | xmlnode_GetIDsOfNames, | |
1023 | xmlnode_Invoke, | |
2b7ae268 MM |
1024 | xmlnode_get_nodeName, |
1025 | xmlnode_get_nodeValue, | |
1026 | xmlnode_put_nodeValue, | |
1027 | xmlnode_get_nodeType, | |
65293d8e MM |
1028 | xmlnode_get_parentNode, |
1029 | xmlnode_get_childNodes, | |
1030 | xmlnode_get_firstChild, | |
1031 | xmlnode_get_lastChild, | |
1032 | xmlnode_get_previousSibling, | |
1033 | xmlnode_get_nextSibling, | |
1034 | xmlnode_get_attributes, | |
1035 | xmlnode_insertBefore, | |
1036 | xmlnode_replaceChild, | |
1037 | xmlnode_removeChild, | |
1038 | xmlnode_appendChild, | |
1039 | xmlnode_hasChildNodes, | |
1040 | xmlnode_get_ownerDocument, | |
1041 | xmlnode_cloneNode, | |
2b7ae268 | 1042 | xmlnode_get_nodeTypeString, |
65293d8e MM |
1043 | xmlnode_get_text, |
1044 | xmlnode_put_text, | |
1045 | xmlnode_get_specified, | |
1046 | xmlnode_get_definition, | |
2b7ae268 MM |
1047 | xmlnode_get_nodeTypedValue, |
1048 | xmlnode_put_nodeTypedValue, | |
65293d8e MM |
1049 | xmlnode_get_dataType, |
1050 | xmlnode_put_dataType, | |
1051 | xmlnode_get_xml, | |
1052 | xmlnode_transformNode, | |
1053 | xmlnode_selectNodes, | |
1054 | xmlnode_selectSingleNode, | |
1055 | xmlnode_get_parsed, | |
1056 | xmlnode_get_namespaceURI, | |
1057 | xmlnode_get_prefix, | |
1058 | xmlnode_get_baseName, | |
1059 | xmlnode_transformNodeToObject, | |
1060 | }; | |
1061 | ||
3f6bb98f HD |
1062 | static HRESULT WINAPI Internal_QueryInterface( |
1063 | IUnknown *iface, | |
1064 | REFIID riid, | |
1065 | void** ppvObject ) | |
65293d8e | 1066 | { |
3f6bb98f | 1067 | xmlnode *This = impl_from_InternalUnknown( iface ); |
65293d8e | 1068 | |
3f6bb98f | 1069 | TRACE("%p %s %p\n", iface, debugstr_guid(riid), ppvObject); |
23f192d2 | 1070 | |
23f192d2 | 1071 | |
3f6bb98f HD |
1072 | if ( IsEqualGUID( riid, &IID_IUnknown )) |
1073 | *ppvObject = iface; | |
1074 | else if ( IsEqualGUID( riid, &IID_IDispatch ) || | |
1075 | IsEqualGUID( riid, &IID_IXMLDOMNode ) ) | |
1076 | *ppvObject = &This->lpVtbl; | |
1077 | else | |
1078 | { | |
e1e1f792 | 1079 | FIXME("interface %s not implemented\n", debugstr_guid(riid)); |
3f6bb98f HD |
1080 | *ppvObject = NULL; |
1081 | return E_NOINTERFACE; | |
1082 | } | |
1083 | ||
1084 | IUnknown_AddRef( (IUnknown*)*ppvObject ); | |
23f192d2 | 1085 | |
3f6bb98f HD |
1086 | return S_OK; |
1087 | } | |
1088 | ||
1089 | static ULONG WINAPI Internal_AddRef( | |
1090 | IUnknown *iface ) | |
1091 | { | |
1092 | xmlnode *This = impl_from_InternalUnknown( iface ); | |
1093 | return InterlockedIncrement( &This->ref ); | |
1094 | } | |
1095 | ||
1096 | static ULONG WINAPI Internal_Release( | |
1097 | IUnknown *iface ) | |
1098 | { | |
1099 | xmlnode *This = impl_from_InternalUnknown( iface ); | |
1100 | ULONG ref; | |
1101 | ||
1102 | ref = InterlockedDecrement( &This->ref ); | |
1103 | if ( ref == 0 ) | |
23f192d2 | 1104 | { |
a48bb7b3 HD |
1105 | if( This->node ) |
1106 | xmldoc_release( This->node->doc ); | |
3f6bb98f | 1107 | HeapFree( GetProcessHeap(), 0, This ); |
c868b451 | 1108 | } |
23f192d2 | 1109 | |
3f6bb98f HD |
1110 | return ref; |
1111 | } | |
1112 | ||
1113 | static const struct IUnknownVtbl internal_unk_vtbl = | |
1114 | { | |
1115 | Internal_QueryInterface, | |
1116 | Internal_AddRef, | |
1117 | Internal_Release | |
1118 | }; | |
1119 | ||
1120 | IUnknown *create_basic_node( xmlNodePtr node, IUnknown *pUnkOuter ) | |
1121 | { | |
1122 | xmlnode *This; | |
1123 | ||
1124 | This = HeapAlloc( GetProcessHeap(), 0, sizeof *This ); | |
1125 | if ( !This ) | |
1126 | return NULL; | |
1127 | ||
1128 | if(node) | |
1129 | xmldoc_add_ref( node->doc ); | |
65293d8e MM |
1130 | |
1131 | This->lpVtbl = &xmlnode_vtbl; | |
3f6bb98f HD |
1132 | This->lpInternalUnkVtbl = &internal_unk_vtbl; |
1133 | ||
1134 | if(pUnkOuter) | |
1135 | This->pUnkOuter = pUnkOuter; /* Don't take a ref on outer Unknown */ | |
1136 | else | |
1137 | This->pUnkOuter = (IUnknown *)&This->lpInternalUnkVtbl; | |
1138 | ||
65293d8e | 1139 | This->ref = 1; |
23f192d2 MM |
1140 | This->node = node; |
1141 | ||
3f6bb98f | 1142 | return (IUnknown*)&This->lpInternalUnkVtbl; |
65293d8e MM |
1143 | } |
1144 | ||
3f6bb98f HD |
1145 | IXMLDOMNode *create_node( xmlNodePtr node ) |
1146 | { | |
1147 | IUnknown *pUnk; | |
1148 | IXMLDOMNode *ret; | |
1149 | HRESULT hr; | |
1150 | ||
1151 | if ( !node ) | |
1152 | return NULL; | |
1153 | ||
1154 | TRACE("type %d\n", node->type); | |
1155 | switch(node->type) | |
1156 | { | |
1157 | case XML_ELEMENT_NODE: | |
09ddab14 | 1158 | pUnk = create_element( node, NULL ); |
3f6bb98f | 1159 | break; |
a545fee7 HD |
1160 | case XML_ATTRIBUTE_NODE: |
1161 | pUnk = create_attribute( node ); | |
1162 | break; | |
5d629e7c HD |
1163 | case XML_TEXT_NODE: |
1164 | pUnk = create_text( node ); | |
1165 | break; | |
a545fee7 HD |
1166 | case XML_COMMENT_NODE: |
1167 | pUnk = create_comment( node ); | |
1168 | break; | |
3f6bb98f HD |
1169 | case XML_DOCUMENT_NODE: |
1170 | ERR("shouldn't be here!\n"); | |
1171 | return NULL; | |
1172 | default: | |
1173 | FIXME("only creating basic node for type %d\n", node->type); | |
1174 | pUnk = create_basic_node( node, NULL ); | |
1175 | } | |
1176 | ||
1177 | hr = IUnknown_QueryInterface(pUnk, &IID_IXMLDOMNode, (LPVOID*)&ret); | |
1178 | IUnknown_Release(pUnk); | |
1179 | if(FAILED(hr)) return NULL; | |
1180 | return ret; | |
1181 | } | |
65293d8e | 1182 | #endif |