msxml3: Forward IDispatch to IDispatchEx when supported.
[wine/multimedia.git] / dlls / msxml3 / selection.c
blobaba8e7dcd365e59d7f6cd9ae7154c5b2bd19faa5
1 /*
2 * XPath/XSLPattern query result node list implementation
4 * Copyright 2005 Mike McCormack
5 * Copyright 2007 Mikolaj Zalewski
6 * Copyright 2010 Adam Martinson for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define COBJMACROS
25 #include "config.h"
27 #include <stdarg.h>
28 #ifdef HAVE_LIBXML2
29 # include <libxml/parser.h>
30 # include <libxml/xmlerror.h>
31 # include <libxml/xpath.h>
32 # include <libxml/xpathInternals.h>
33 #endif
35 #include "windef.h"
36 #include "winbase.h"
37 #include "winuser.h"
38 #include "ole2.h"
39 #include "msxml6.h"
40 #include "msxml2did.h"
42 #include "msxml_private.h"
44 #include "wine/debug.h"
46 /* This file implements the object returned by a XPath query. Note that this is
47 * not the IXMLDOMNodeList returned by childNodes - it's implemented in nodelist.c.
48 * They are different because the list returned by XPath queries:
49 * - is static - gives the results for the XML tree as it existed during the
50 * execution of the query
51 * - supports IXMLDOMSelection
55 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
57 #ifdef HAVE_LIBXML2
59 int registerNamespaces(xmlXPathContextPtr ctxt);
60 xmlChar* XSLPattern_to_XPath(xmlXPathContextPtr ctxt, xmlChar const* xslpat_str);
62 typedef struct _enumvariant
64 IEnumVARIANT IEnumVARIANT_iface;
65 LONG ref;
67 IXMLDOMSelection *selection;
68 BOOL own;
70 LONG pos;
71 } enumvariant;
73 typedef struct _domselection
75 DispatchEx dispex;
76 IXMLDOMSelection IXMLDOMSelection_iface;
77 LONG ref;
78 xmlNodePtr node;
79 xmlXPathObjectPtr result;
80 int resultPos;
81 IEnumVARIANT *enumvariant;
82 } domselection;
84 static inline domselection *impl_from_IXMLDOMSelection( IXMLDOMSelection *iface )
86 return CONTAINING_RECORD(iface, domselection, IXMLDOMSelection_iface);
89 static inline enumvariant *impl_from_IEnumVARIANT( IEnumVARIANT *iface )
91 return CONTAINING_RECORD(iface, enumvariant, IEnumVARIANT_iface);
94 static HRESULT create_enumvariant(IXMLDOMSelection*, BOOL, IUnknown**);
96 static HRESULT WINAPI domselection_QueryInterface(
97 IXMLDOMSelection *iface,
98 REFIID riid,
99 void** ppvObject )
101 domselection *This = impl_from_IXMLDOMSelection( iface );
103 TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);
105 if(!ppvObject)
106 return E_INVALIDARG;
108 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
109 IsEqualGUID( riid, &IID_IXMLDOMNodeList ) ||
110 IsEqualGUID( riid, &IID_IXMLDOMSelection ))
112 *ppvObject = &This->IXMLDOMSelection_iface;
114 else if (IsEqualGUID( riid, &IID_IEnumVARIANT ))
116 if (!This->enumvariant)
118 HRESULT hr = create_enumvariant(iface, FALSE, (IUnknown**)&This->enumvariant);
119 if (FAILED(hr)) return hr;
122 return IEnumVARIANT_QueryInterface(This->enumvariant, &IID_IEnumVARIANT, ppvObject);
124 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
126 return *ppvObject ? S_OK : E_NOINTERFACE;
128 else
130 TRACE("interface %s not implemented\n", debugstr_guid(riid));
131 *ppvObject = NULL;
132 return E_NOINTERFACE;
135 IXMLDOMSelection_AddRef( iface );
137 return S_OK;
140 static ULONG WINAPI domselection_AddRef(
141 IXMLDOMSelection *iface )
143 domselection *This = impl_from_IXMLDOMSelection( iface );
144 ULONG ref = InterlockedIncrement( &This->ref );
145 TRACE("(%p)->(%d)\n", This, ref);
146 return ref;
149 static ULONG WINAPI domselection_Release(
150 IXMLDOMSelection *iface )
152 domselection *This = impl_from_IXMLDOMSelection( iface );
153 ULONG ref = InterlockedDecrement(&This->ref);
155 TRACE("(%p)->(%d)\n", This, ref);
156 if ( ref == 0 )
158 xmlXPathFreeObject(This->result);
159 xmldoc_release(This->node->doc);
160 if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant);
161 release_dispex(&This->dispex);
162 heap_free(This);
165 return ref;
168 static HRESULT WINAPI domselection_GetTypeInfoCount(
169 IXMLDOMSelection *iface,
170 UINT* pctinfo )
172 domselection *This = impl_from_IXMLDOMSelection( iface );
173 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
176 static HRESULT WINAPI domselection_GetTypeInfo(
177 IXMLDOMSelection *iface,
178 UINT iTInfo,
179 LCID lcid,
180 ITypeInfo** ppTInfo )
182 domselection *This = impl_from_IXMLDOMSelection( iface );
183 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
184 iTInfo, lcid, ppTInfo);
187 static HRESULT WINAPI domselection_GetIDsOfNames(
188 IXMLDOMSelection *iface,
189 REFIID riid,
190 LPOLESTR* rgszNames,
191 UINT cNames,
192 LCID lcid,
193 DISPID* rgDispId )
195 domselection *This = impl_from_IXMLDOMSelection( iface );
196 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
197 riid, rgszNames, cNames, lcid, rgDispId);
200 static HRESULT WINAPI domselection_Invoke(
201 IXMLDOMSelection *iface,
202 DISPID dispIdMember,
203 REFIID riid,
204 LCID lcid,
205 WORD wFlags,
206 DISPPARAMS* pDispParams,
207 VARIANT* pVarResult,
208 EXCEPINFO* pExcepInfo,
209 UINT* puArgErr )
211 domselection *This = impl_from_IXMLDOMSelection( iface );
212 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
213 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
216 static HRESULT WINAPI domselection_get_item(
217 IXMLDOMSelection* iface,
218 LONG index,
219 IXMLDOMNode** listItem)
221 domselection *This = impl_from_IXMLDOMSelection( iface );
223 TRACE("(%p)->(%d %p)\n", This, index, listItem);
225 if(!listItem)
226 return E_INVALIDARG;
228 *listItem = NULL;
230 if (index < 0 || index >= xmlXPathNodeSetGetLength(This->result->nodesetval))
231 return S_FALSE;
233 *listItem = create_node(xmlXPathNodeSetItem(This->result->nodesetval, index));
234 This->resultPos = index + 1;
236 return S_OK;
239 static HRESULT WINAPI domselection_get_length(
240 IXMLDOMSelection* iface,
241 LONG* listLength)
243 domselection *This = impl_from_IXMLDOMSelection( iface );
245 TRACE("(%p)->(%p)\n", This, listLength);
247 if(!listLength)
248 return E_INVALIDARG;
250 *listLength = xmlXPathNodeSetGetLength(This->result->nodesetval);
251 return S_OK;
254 static HRESULT WINAPI domselection_nextNode(
255 IXMLDOMSelection* iface,
256 IXMLDOMNode** nextItem)
258 domselection *This = impl_from_IXMLDOMSelection( iface );
260 TRACE("(%p)->(%p)\n", This, nextItem );
262 if(!nextItem)
263 return E_INVALIDARG;
265 *nextItem = NULL;
267 if (This->resultPos >= xmlXPathNodeSetGetLength(This->result->nodesetval))
268 return S_FALSE;
270 *nextItem = create_node(xmlXPathNodeSetItem(This->result->nodesetval, This->resultPos));
271 This->resultPos++;
272 return S_OK;
275 static HRESULT WINAPI domselection_reset(
276 IXMLDOMSelection* iface)
278 domselection *This = impl_from_IXMLDOMSelection( iface );
280 TRACE("%p\n", This);
281 This->resultPos = 0;
282 return S_OK;
285 static HRESULT WINAPI domselection_get__newEnum(
286 IXMLDOMSelection* iface,
287 IUnknown** ppUnk)
289 domselection *This = impl_from_IXMLDOMSelection( iface );
291 TRACE("(%p)->(%p)\n", This, ppUnk);
293 return create_enumvariant(iface, TRUE, ppUnk);
296 static HRESULT WINAPI domselection_get_expr(
297 IXMLDOMSelection* iface,
298 BSTR *p)
300 domselection *This = impl_from_IXMLDOMSelection( iface );
301 FIXME("(%p)->(%p)\n", This, p);
302 return E_NOTIMPL;
305 static HRESULT WINAPI domselection_put_expr(
306 IXMLDOMSelection* iface,
307 BSTR p)
309 domselection *This = impl_from_IXMLDOMSelection( iface );
310 FIXME("(%p)->(%s)\n", This, debugstr_w(p));
311 return E_NOTIMPL;
314 static HRESULT WINAPI domselection_get_context(
315 IXMLDOMSelection* iface,
316 IXMLDOMNode **node)
318 domselection *This = impl_from_IXMLDOMSelection( iface );
319 FIXME("(%p)->(%p)\n", This, node);
320 return E_NOTIMPL;
323 static HRESULT WINAPI domselection_putref_context(
324 IXMLDOMSelection* iface,
325 IXMLDOMNode *node)
327 domselection *This = impl_from_IXMLDOMSelection( iface );
328 FIXME("(%p)->(%p)\n", This, node);
329 return E_NOTIMPL;
332 static HRESULT WINAPI domselection_peekNode(
333 IXMLDOMSelection* iface,
334 IXMLDOMNode **node)
336 domselection *This = impl_from_IXMLDOMSelection( iface );
337 FIXME("(%p)->(%p)\n", This, node);
338 return E_NOTIMPL;
341 static HRESULT WINAPI domselection_matches(
342 IXMLDOMSelection* iface,
343 IXMLDOMNode *node,
344 IXMLDOMNode **out_node)
346 domselection *This = impl_from_IXMLDOMSelection( iface );
347 FIXME("(%p)->(%p %p)\n", This, node, out_node);
348 return E_NOTIMPL;
351 static HRESULT WINAPI domselection_removeNext(
352 IXMLDOMSelection* iface,
353 IXMLDOMNode **node)
355 domselection *This = impl_from_IXMLDOMSelection( iface );
356 FIXME("(%p)->(%p)\n", This, node);
357 return E_NOTIMPL;
360 static HRESULT WINAPI domselection_removeAll(
361 IXMLDOMSelection* iface)
363 domselection *This = impl_from_IXMLDOMSelection( iface );
364 FIXME("(%p)\n", This);
365 return E_NOTIMPL;
368 static HRESULT WINAPI domselection_clone(
369 IXMLDOMSelection* iface,
370 IXMLDOMSelection **node)
372 domselection *This = impl_from_IXMLDOMSelection( iface );
373 FIXME("(%p)->(%p)\n", This, node);
374 return E_NOTIMPL;
377 static HRESULT WINAPI domselection_getProperty(
378 IXMLDOMSelection* iface,
379 BSTR p,
380 VARIANT *var)
382 domselection *This = impl_from_IXMLDOMSelection( iface );
383 FIXME("(%p)->(%s %p)\n", This, debugstr_w(p), var);
384 return E_NOTIMPL;
387 static HRESULT WINAPI domselection_setProperty(
388 IXMLDOMSelection* iface,
389 BSTR p,
390 VARIANT var)
392 domselection *This = impl_from_IXMLDOMSelection( iface );
393 FIXME("(%p)->(%s %s)\n", This, debugstr_w(p), debugstr_variant(&var));
394 return E_NOTIMPL;
397 static const struct IXMLDOMSelectionVtbl domselection_vtbl =
399 domselection_QueryInterface,
400 domselection_AddRef,
401 domselection_Release,
402 domselection_GetTypeInfoCount,
403 domselection_GetTypeInfo,
404 domselection_GetIDsOfNames,
405 domselection_Invoke,
406 domselection_get_item,
407 domselection_get_length,
408 domselection_nextNode,
409 domselection_reset,
410 domselection_get__newEnum,
411 domselection_get_expr,
412 domselection_put_expr,
413 domselection_get_context,
414 domselection_putref_context,
415 domselection_peekNode,
416 domselection_matches,
417 domselection_removeNext,
418 domselection_removeAll,
419 domselection_clone,
420 domselection_getProperty,
421 domselection_setProperty
424 /* IEnumVARIANT support */
425 static HRESULT WINAPI enumvariant_QueryInterface(
426 IEnumVARIANT *iface,
427 REFIID riid,
428 void** ppvObject )
430 enumvariant *This = impl_from_IEnumVARIANT( iface );
432 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
434 *ppvObject = NULL;
436 if ( IsEqualGUID( riid, &IID_IUnknown ) ||
437 IsEqualGUID( riid, &IID_IEnumVARIANT ))
439 *ppvObject = &This->IEnumVARIANT_iface;
441 else
442 return IXMLDOMSelection_QueryInterface(This->selection, riid, ppvObject);
444 IEnumVARIANT_AddRef( iface );
446 return S_OK;
449 static ULONG WINAPI enumvariant_AddRef(IEnumVARIANT *iface )
451 enumvariant *This = impl_from_IEnumVARIANT( iface );
452 ULONG ref = InterlockedIncrement( &This->ref );
453 TRACE("(%p)->(%d)\n", This, ref);
454 return ref;
457 static ULONG WINAPI enumvariant_Release(IEnumVARIANT *iface )
459 enumvariant *This = impl_from_IEnumVARIANT( iface );
460 ULONG ref = InterlockedDecrement(&This->ref);
462 TRACE("(%p)->(%d)\n", This, ref);
463 if ( ref == 0 )
465 if (This->own) IXMLDOMSelection_Release(This->selection);
466 heap_free(This);
469 return ref;
472 static HRESULT WINAPI enumvariant_Next(
473 IEnumVARIANT *iface,
474 ULONG celt,
475 VARIANT *var,
476 ULONG *fetched)
478 enumvariant *This = impl_from_IEnumVARIANT( iface );
479 IXMLDOMNode *node;
480 ULONG ret_count = 0;
482 TRACE("(%p)->(%u %p %p)\n", This, celt, var, fetched);
484 if (fetched) *fetched = 0;
486 if (celt && !var) return E_INVALIDARG;
488 for (; celt > 0; celt--, var++, This->pos++)
490 IDispatch *disp = NULL;
491 HRESULT hr;
493 node = NULL;
494 hr = IXMLDOMSelection_get_item(This->selection, This->pos, &node);
495 if (hr != S_OK) break;
497 IXMLDOMNode_QueryInterface(node, &IID_IDispatch, (void**)&disp);
498 IXMLDOMNode_Release(node);
500 V_VT(var) = VT_DISPATCH;
501 V_DISPATCH(var) = disp;
503 ret_count++;
506 if (fetched) (*fetched)++;
508 /* we need to advance one step more for some reason */
509 if (ret_count)
510 IXMLDOMSelection_nextNode(This->selection, &node);
512 return celt == 0 ? S_OK : S_FALSE;
515 static HRESULT WINAPI enumvariant_Skip(
516 IEnumVARIANT *iface,
517 ULONG celt)
519 enumvariant *This = impl_from_IEnumVARIANT( iface );
520 FIXME("(%p)->(%u): stub\n", This, celt);
521 return E_NOTIMPL;
524 static HRESULT WINAPI enumvariant_Reset(IEnumVARIANT *iface)
526 enumvariant *This = impl_from_IEnumVARIANT( iface );
527 FIXME("(%p): stub\n", This);
528 return E_NOTIMPL;
531 static HRESULT WINAPI enumvariant_Clone(
532 IEnumVARIANT *iface, IEnumVARIANT **ppenum)
534 enumvariant *This = impl_from_IEnumVARIANT( iface );
535 FIXME("(%p)->(%p): stub\n", This, ppenum);
536 return E_NOTIMPL;
539 static const struct IEnumVARIANTVtbl EnumVARIANTVtbl =
541 enumvariant_QueryInterface,
542 enumvariant_AddRef,
543 enumvariant_Release,
544 enumvariant_Next,
545 enumvariant_Skip,
546 enumvariant_Reset,
547 enumvariant_Clone
550 static HRESULT create_enumvariant(IXMLDOMSelection *selection, BOOL own, IUnknown **penum)
552 enumvariant *This;
554 This = heap_alloc(sizeof(enumvariant));
555 if (!This) return E_OUTOFMEMORY;
557 This->IEnumVARIANT_iface.lpVtbl = &EnumVARIANTVtbl;
558 This->ref = 0;
559 This->selection = selection;
560 This->own = own;
561 This->pos = 0;
563 if (This->own)
564 IXMLDOMSelection_AddRef(selection);
566 return IEnumVARIANT_QueryInterface(&This->IEnumVARIANT_iface, &IID_IUnknown, (void**)penum);
569 static HRESULT domselection_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid)
571 WCHAR *ptr;
572 int idx = 0;
574 for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
575 idx = idx*10 + (*ptr-'0');
576 if(*ptr)
577 return DISP_E_UNKNOWNNAME;
579 *dispid = DISPID_DOM_COLLECTION_BASE + idx;
580 TRACE("ret %x\n", *dispid);
581 return S_OK;
584 static HRESULT domselection_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
585 VARIANT *res, EXCEPINFO *ei)
587 domselection *This = impl_from_IXMLDOMSelection( (IXMLDOMSelection*)iface );
589 TRACE("(%p)->(%x %x %x %p %p %p)\n", This, id, lcid, flags, params, res, ei);
591 V_VT(res) = VT_DISPATCH;
592 V_DISPATCH(res) = NULL;
594 if (id < DISPID_DOM_COLLECTION_BASE || id > DISPID_DOM_COLLECTION_MAX)
595 return DISP_E_UNKNOWNNAME;
597 switch(flags)
599 case INVOKE_PROPERTYGET:
601 IXMLDOMNode *disp = NULL;
603 domselection_get_item(&This->IXMLDOMSelection_iface, id - DISPID_DOM_COLLECTION_BASE, &disp);
604 V_DISPATCH(res) = (IDispatch*)disp;
605 break;
607 default:
609 FIXME("unimplemented flags %x\n", flags);
610 break;
614 TRACE("ret %p\n", V_DISPATCH(res));
616 return S_OK;
619 static const dispex_static_data_vtbl_t domselection_dispex_vtbl = {
620 domselection_get_dispid,
621 domselection_invoke
624 static const tid_t domselection_iface_tids[] = {
625 IXMLDOMSelection_tid,
628 static dispex_static_data_t domselection_dispex = {
629 &domselection_dispex_vtbl,
630 IXMLDOMSelection_tid,
631 NULL,
632 domselection_iface_tids
635 #define XSLPATTERN_CHECK_ARGS(n) \
636 if (nargs != n) { \
637 FIXME("XSLPattern syntax error: Expected %i arguments, got %i\n", n, nargs); \
638 xmlXPathSetArityError(pctx); \
639 return; \
643 static void XSLPattern_index(xmlXPathParserContextPtr pctx, int nargs)
645 XSLPATTERN_CHECK_ARGS(0);
647 xmlXPathPositionFunction(pctx, 0);
648 xmlXPathReturnNumber(pctx, xmlXPathPopNumber(pctx) - 1.0);
651 static void XSLPattern_end(xmlXPathParserContextPtr pctx, int nargs)
653 double pos, last;
654 XSLPATTERN_CHECK_ARGS(0);
656 xmlXPathPositionFunction(pctx, 0);
657 pos = xmlXPathPopNumber(pctx);
658 xmlXPathLastFunction(pctx, 0);
659 last = xmlXPathPopNumber(pctx);
660 xmlXPathReturnBoolean(pctx, pos == last);
663 static void XSLPattern_nodeType(xmlXPathParserContextPtr pctx, int nargs)
665 XSLPATTERN_CHECK_ARGS(0);
666 xmlXPathReturnNumber(pctx, pctx->context->node->type);
669 static void XSLPattern_OP_IEq(xmlXPathParserContextPtr pctx, int nargs)
671 xmlChar *arg1, *arg2;
672 XSLPATTERN_CHECK_ARGS(2);
674 arg2 = xmlXPathPopString(pctx);
675 arg1 = xmlXPathPopString(pctx);
676 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) == 0);
677 xmlFree(arg1);
678 xmlFree(arg2);
681 static void XSLPattern_OP_INEq(xmlXPathParserContextPtr pctx, int nargs)
683 xmlChar *arg1, *arg2;
684 XSLPATTERN_CHECK_ARGS(2);
686 arg2 = xmlXPathPopString(pctx);
687 arg1 = xmlXPathPopString(pctx);
688 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) != 0);
689 xmlFree(arg1);
690 xmlFree(arg2);
693 static void XSLPattern_OP_ILt(xmlXPathParserContextPtr pctx, int nargs)
695 xmlChar *arg1, *arg2;
696 XSLPATTERN_CHECK_ARGS(2);
698 arg2 = xmlXPathPopString(pctx);
699 arg1 = xmlXPathPopString(pctx);
700 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) < 0);
701 xmlFree(arg1);
702 xmlFree(arg2);
705 static void XSLPattern_OP_ILEq(xmlXPathParserContextPtr pctx, int nargs)
707 xmlChar *arg1, *arg2;
708 XSLPATTERN_CHECK_ARGS(2);
710 arg2 = xmlXPathPopString(pctx);
711 arg1 = xmlXPathPopString(pctx);
712 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) <= 0);
713 xmlFree(arg1);
714 xmlFree(arg2);
717 static void XSLPattern_OP_IGt(xmlXPathParserContextPtr pctx, int nargs)
719 xmlChar *arg1, *arg2;
720 XSLPATTERN_CHECK_ARGS(2);
722 arg2 = xmlXPathPopString(pctx);
723 arg1 = xmlXPathPopString(pctx);
724 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) > 0);
725 xmlFree(arg1);
726 xmlFree(arg2);
729 static void XSLPattern_OP_IGEq(xmlXPathParserContextPtr pctx, int nargs)
731 xmlChar *arg1, *arg2;
732 XSLPATTERN_CHECK_ARGS(2);
734 arg2 = xmlXPathPopString(pctx);
735 arg1 = xmlXPathPopString(pctx);
736 xmlXPathReturnBoolean(pctx, xmlStrcasecmp(arg1, arg2) >= 0);
737 xmlFree(arg1);
738 xmlFree(arg2);
741 static void query_serror(void* ctx, xmlErrorPtr err)
743 LIBXML2_CALLBACK_SERROR(domselection_create, err);
746 HRESULT create_selection(xmlNodePtr node, xmlChar* query, IXMLDOMNodeList **out)
748 domselection *This = heap_alloc(sizeof(domselection));
749 xmlXPathContextPtr ctxt = xmlXPathNewContext(node->doc);
750 HRESULT hr;
752 TRACE("(%p, %s, %p)\n", node, wine_dbgstr_a((char const*)query), out);
754 *out = NULL;
755 if (!This || !ctxt || !query)
757 xmlXPathFreeContext(ctxt);
758 heap_free(This);
759 return E_OUTOFMEMORY;
762 This->IXMLDOMSelection_iface.lpVtbl = &domselection_vtbl;
763 This->ref = 1;
764 This->resultPos = 0;
765 This->node = node;
766 This->enumvariant = NULL;
767 init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMSelection_iface, &domselection_dispex);
768 xmldoc_add_ref(This->node->doc);
770 ctxt->error = query_serror;
771 ctxt->node = node;
772 registerNamespaces(ctxt);
774 if (is_xpathmode(This->node->doc))
776 xmlXPathRegisterAllFunctions(ctxt);
777 This->result = xmlXPathEvalExpression(query, ctxt);
779 else
781 xmlChar* pattern_query = XSLPattern_to_XPath(ctxt, query);
783 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"not", xmlXPathNotFunction);
784 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"boolean", xmlXPathBooleanFunction);
786 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"index", XSLPattern_index);
787 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"end", XSLPattern_end);
788 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"nodeType", XSLPattern_nodeType);
790 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IEq", XSLPattern_OP_IEq);
791 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_INEq", XSLPattern_OP_INEq);
792 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_ILt", XSLPattern_OP_ILt);
793 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_ILEq", XSLPattern_OP_ILEq);
794 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IGt", XSLPattern_OP_IGt);
795 xmlXPathRegisterFunc(ctxt, (xmlChar const*)"OP_IGEq", XSLPattern_OP_IGEq);
797 This->result = xmlXPathEvalExpression(pattern_query, ctxt);
798 xmlFree(pattern_query);
801 if (!This->result || This->result->type != XPATH_NODESET)
803 hr = E_FAIL;
804 goto cleanup;
807 *out = (IXMLDOMNodeList*)&This->IXMLDOMSelection_iface;
808 hr = S_OK;
809 TRACE("found %d matches\n", xmlXPathNodeSetGetLength(This->result->nodesetval));
811 cleanup:
812 if (This && FAILED(hr))
813 IXMLDOMSelection_Release( &This->IXMLDOMSelection_iface );
814 xmlXPathFreeContext(ctxt);
815 return hr;
818 #endif