ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

queryresult.c
Go to the documentation of this file.
00001 /*
00002  *    XPath query result node list implementation (TODO: XSLPattern support)
00003  *
00004  * Copyright 2005 Mike McCormack
00005  * Copyright 2007 Mikolaj Zalewski
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #define COBJMACROS
00023 
00024 #include "config.h"
00025 
00026 #include <stdarg.h>
00027 #include "windef.h"
00028 #include "winbase.h"
00029 #include "winuser.h"
00030 #include "ole2.h"
00031 #include "msxml2.h"
00032 
00033 #include "msxml_private.h"
00034 
00035 #include "wine/debug.h"
00036 
00037 /* This file implements the object returned by a XPath query. Note that this is
00038  * not the IXMLDOMNodeList returned by childNodes - it's implemented in nodelist.c.
00039  * They are different because the list returned by XPath queries:
00040  *  - is static - gives the results for the XML tree as it existed during the
00041  *    execution of the query
00042  *  - supports IXMLDOMSelection (TODO)
00043  *
00044  * TODO: XSLPattern support
00045  */
00046 
00047 WINE_DEFAULT_DEBUG_CHANNEL(msxml);
00048 
00049 #ifdef HAVE_LIBXML2
00050 
00051 #include <libxml/xpath.h>
00052 
00053 typedef struct _queryresult
00054 {
00055     DispatchEx dispex;
00056     const struct IXMLDOMNodeListVtbl *lpVtbl;
00057     LONG ref;
00058     xmlNodePtr node;
00059     xmlXPathObjectPtr result;
00060     int resultPos;
00061 } queryresult;
00062 
00063 static inline queryresult *impl_from_IXMLDOMNodeList( IXMLDOMNodeList *iface )
00064 {
00065     return (queryresult *)((char*)iface - FIELD_OFFSET(queryresult, lpVtbl));
00066 }
00067 
00068 #define XMLQUERYRES(x)  ((IXMLDOMNodeList*)&(x)->lpVtbl)
00069 
00070 static HRESULT WINAPI queryresult_QueryInterface(
00071     IXMLDOMNodeList *iface,
00072     REFIID riid,
00073     void** ppvObject )
00074 {
00075     queryresult *This = impl_from_IXMLDOMNodeList( iface );
00076 
00077     TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);
00078 
00079     if(!ppvObject)
00080         return E_INVALIDARG;
00081 
00082     if ( IsEqualGUID( riid, &IID_IUnknown ) ||
00083          IsEqualGUID( riid, &IID_IXMLDOMNodeList ) )
00084     {
00085         *ppvObject = iface;
00086     }
00087     else if(dispex_query_interface(&This->dispex, riid, ppvObject))
00088     {
00089         return *ppvObject ? S_OK : E_NOINTERFACE;
00090     }
00091     else
00092     {
00093         FIXME("interface %s not implemented\n", debugstr_guid(riid));
00094         *ppvObject = NULL;
00095         return E_NOINTERFACE;
00096     }
00097 
00098     IXMLDOMNodeList_AddRef( iface );
00099 
00100     return S_OK;
00101 }
00102 
00103 static ULONG WINAPI queryresult_AddRef(
00104     IXMLDOMNodeList *iface )
00105 {
00106     queryresult *This = impl_from_IXMLDOMNodeList( iface );
00107     return InterlockedIncrement( &This->ref );
00108 }
00109 
00110 static ULONG WINAPI queryresult_Release(
00111     IXMLDOMNodeList *iface )
00112 {
00113     queryresult *This = impl_from_IXMLDOMNodeList( iface );
00114     ULONG ref;
00115 
00116     ref = InterlockedDecrement(&This->ref);
00117     if ( ref == 0 )
00118     {
00119         xmlXPathFreeObject(This->result);
00120         xmldoc_release(This->node->doc);
00121         heap_free(This);
00122     }
00123 
00124     return ref;
00125 }
00126 
00127 static HRESULT WINAPI queryresult_GetTypeInfoCount(
00128     IXMLDOMNodeList *iface,
00129     UINT* pctinfo )
00130 {
00131     queryresult *This = impl_from_IXMLDOMNodeList( iface );
00132 
00133     TRACE("(%p)->(%p)\n", This, pctinfo);
00134 
00135     *pctinfo = 1;
00136 
00137     return S_OK;
00138 }
00139 
00140 static HRESULT WINAPI queryresult_GetTypeInfo(
00141     IXMLDOMNodeList *iface,
00142     UINT iTInfo,
00143     LCID lcid,
00144     ITypeInfo** ppTInfo )
00145 {
00146     queryresult *This = impl_from_IXMLDOMNodeList( iface );
00147     HRESULT hr;
00148 
00149     TRACE("(%p)->(%u %u %p)\n", This, iTInfo, lcid, ppTInfo);
00150 
00151     hr = get_typeinfo(IXMLDOMNodeList_tid, ppTInfo);
00152 
00153     return hr;
00154 }
00155 
00156 static HRESULT WINAPI queryresult_GetIDsOfNames(
00157     IXMLDOMNodeList *iface,
00158     REFIID riid,
00159     LPOLESTR* rgszNames,
00160     UINT cNames,
00161     LCID lcid,
00162     DISPID* rgDispId )
00163 {
00164     queryresult *This = impl_from_IXMLDOMNodeList( iface );
00165     ITypeInfo *typeinfo;
00166     HRESULT hr;
00167 
00168     TRACE("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), rgszNames, cNames,
00169           lcid, rgDispId);
00170 
00171     if(!rgszNames || cNames == 0 || !rgDispId)
00172         return E_INVALIDARG;
00173 
00174     hr = get_typeinfo(IXMLDOMNodeList_tid, &typeinfo);
00175     if(SUCCEEDED(hr))
00176     {
00177         hr = ITypeInfo_GetIDsOfNames(typeinfo, rgszNames, cNames, rgDispId);
00178         ITypeInfo_Release(typeinfo);
00179     }
00180 
00181     return hr;
00182 }
00183 
00184 static HRESULT WINAPI queryresult_Invoke(
00185     IXMLDOMNodeList *iface,
00186     DISPID dispIdMember,
00187     REFIID riid,
00188     LCID lcid,
00189     WORD wFlags,
00190     DISPPARAMS* pDispParams,
00191     VARIANT* pVarResult,
00192     EXCEPINFO* pExcepInfo,
00193     UINT* puArgErr )
00194 {
00195     queryresult *This = impl_from_IXMLDOMNodeList( iface );
00196     ITypeInfo *typeinfo;
00197     HRESULT hr;
00198 
00199     TRACE("(%p)->(%d %s %d %d %p %p %p %p)\n", This, dispIdMember, debugstr_guid(riid),
00200           lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
00201 
00202     hr = get_typeinfo(IXMLDOMNodeList_tid, &typeinfo);
00203     if(SUCCEEDED(hr))
00204     {
00205         hr = ITypeInfo_Invoke(typeinfo, &(This->lpVtbl), dispIdMember, wFlags, pDispParams,
00206                 pVarResult, pExcepInfo, puArgErr);
00207         ITypeInfo_Release(typeinfo);
00208     }
00209 
00210     return hr;
00211 }
00212 
00213 static HRESULT WINAPI queryresult_get_item(
00214         IXMLDOMNodeList* iface,
00215         LONG index,
00216         IXMLDOMNode** listItem)
00217 {
00218     queryresult *This = impl_from_IXMLDOMNodeList( iface );
00219 
00220     TRACE("(%p)->(%d %p)\n", This, index, listItem);
00221 
00222     if(!listItem)
00223         return E_INVALIDARG;
00224 
00225     *listItem = NULL;
00226 
00227     if (index < 0 || index >= xmlXPathNodeSetGetLength(This->result->nodesetval))
00228         return S_FALSE;
00229 
00230     *listItem = create_node(xmlXPathNodeSetItem(This->result->nodesetval, index));
00231     This->resultPos = index + 1;
00232 
00233     return S_OK;
00234 }
00235 
00236 static HRESULT WINAPI queryresult_get_length(
00237         IXMLDOMNodeList* iface,
00238         LONG* listLength)
00239 {
00240     queryresult *This = impl_from_IXMLDOMNodeList( iface );
00241 
00242     TRACE("(%p)->(%p)\n", This, listLength);
00243 
00244     if(!listLength)
00245         return E_INVALIDARG;
00246 
00247     *listLength = xmlXPathNodeSetGetLength(This->result->nodesetval);
00248     return S_OK;
00249 }
00250 
00251 static HRESULT WINAPI queryresult_nextNode(
00252         IXMLDOMNodeList* iface,
00253         IXMLDOMNode** nextItem)
00254 {
00255     queryresult *This = impl_from_IXMLDOMNodeList( iface );
00256 
00257     TRACE("(%p)->(%p)\n", This, nextItem );
00258 
00259     if(!nextItem)
00260         return E_INVALIDARG;
00261 
00262     *nextItem = NULL;
00263 
00264     if (This->resultPos >= xmlXPathNodeSetGetLength(This->result->nodesetval))
00265         return S_FALSE;
00266 
00267     *nextItem = create_node(xmlXPathNodeSetItem(This->result->nodesetval, This->resultPos));
00268     This->resultPos++;
00269     return S_OK;
00270 }
00271 
00272 static HRESULT WINAPI queryresult_reset(
00273         IXMLDOMNodeList* iface)
00274 {
00275     queryresult *This = impl_from_IXMLDOMNodeList( iface );
00276 
00277     TRACE("%p\n", This);
00278     This->resultPos = 0;
00279     return S_OK;
00280 }
00281 
00282 static HRESULT WINAPI queryresult__newEnum(
00283         IXMLDOMNodeList* iface,
00284         IUnknown** ppUnk)
00285 {
00286     queryresult *This = impl_from_IXMLDOMNodeList( iface );
00287     FIXME("(%p)->(%p)\n", This, ppUnk);
00288     return E_NOTIMPL;
00289 }
00290 
00291 
00292 static const struct IXMLDOMNodeListVtbl queryresult_vtbl =
00293 {
00294     queryresult_QueryInterface,
00295     queryresult_AddRef,
00296     queryresult_Release,
00297     queryresult_GetTypeInfoCount,
00298     queryresult_GetTypeInfo,
00299     queryresult_GetIDsOfNames,
00300     queryresult_Invoke,
00301     queryresult_get_item,
00302     queryresult_get_length,
00303     queryresult_nextNode,
00304     queryresult_reset,
00305     queryresult__newEnum,
00306 };
00307 
00308 static HRESULT queryresult_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid)
00309 {
00310     queryresult *This = impl_from_IXMLDOMNodeList( (IXMLDOMNodeList*)iface );
00311     WCHAR *ptr;
00312     int idx = 0;
00313 
00314     for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
00315         idx = idx*10 + (*ptr-'0');
00316     if(*ptr)
00317         return DISP_E_UNKNOWNNAME;
00318 
00319     if(idx >= xmlXPathNodeSetGetLength(This->result->nodesetval))
00320         return DISP_E_UNKNOWNNAME;
00321 
00322     *dispid = MSXML_DISPID_CUSTOM_MIN + idx;
00323     TRACE("ret %x\n", *dispid);
00324     return S_OK;
00325 }
00326 
00327 static HRESULT queryresult_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
00328         VARIANT *res, EXCEPINFO *ei)
00329 {
00330     queryresult *This = impl_from_IXMLDOMNodeList( (IXMLDOMNodeList*)iface );
00331 
00332     TRACE("(%p)->(%x %x %x %p %p %p)\n", This, id, lcid, flags, params, res, ei);
00333 
00334     V_VT(res) = VT_DISPATCH;
00335     V_DISPATCH(res) = NULL;
00336 
00337     switch(flags)
00338     {
00339         case INVOKE_PROPERTYGET:
00340         {
00341             IXMLDOMNode *disp = NULL;
00342 
00343             queryresult_get_item(XMLQUERYRES(This), id - MSXML_DISPID_CUSTOM_MIN, &disp);
00344             V_DISPATCH(res) = (IDispatch*)disp;
00345             break;
00346         }
00347         default:
00348         {
00349             FIXME("unimplemented flags %x\n", flags);
00350             break;
00351         }
00352     }
00353 
00354     TRACE("ret %p\n", V_DISPATCH(res));
00355 
00356     return S_OK;
00357 }
00358 
00359 static const dispex_static_data_vtbl_t queryresult_dispex_vtbl = {
00360     queryresult_get_dispid,
00361     queryresult_invoke
00362 };
00363 
00364 static const tid_t queryresult_iface_tids[] = {
00365     IXMLDOMNodeList_tid,
00366     0
00367 };
00368 static dispex_static_data_t queryresult_dispex = {
00369     &queryresult_dispex_vtbl,
00370     IXMLDOMSelection_tid,
00371     NULL,
00372     queryresult_iface_tids
00373 };
00374 
00375 HRESULT queryresult_create(xmlNodePtr node, LPWSTR szQuery, IXMLDOMNodeList **out)
00376 {
00377     queryresult *This = heap_alloc_zero(sizeof(queryresult));
00378     xmlXPathContextPtr ctxt = xmlXPathNewContext(node->doc);
00379     xmlChar *str = xmlChar_from_wchar(szQuery);
00380     HRESULT hr;
00381 
00382     TRACE("(%p, %s, %p)\n", node, wine_dbgstr_w(szQuery), out);
00383 
00384     *out = NULL;
00385     if (This == NULL || ctxt == NULL || str == NULL)
00386     {
00387         hr = E_OUTOFMEMORY;
00388         goto cleanup;
00389     }
00390 
00391     This->lpVtbl = &queryresult_vtbl;
00392     This->ref = 1;
00393     This->resultPos = 0;
00394     This->node = node;
00395     xmldoc_add_ref(This->node->doc);
00396 
00397     ctxt->node = node;
00398     This->result = xmlXPathEval(str, ctxt);
00399     if (!This->result || This->result->type != XPATH_NODESET)
00400     {
00401         hr = E_FAIL;
00402         goto cleanup;
00403     }
00404 
00405     init_dispex(&This->dispex, (IUnknown*)&This->lpVtbl, &queryresult_dispex);
00406 
00407     *out = (IXMLDOMNodeList *) &This->lpVtbl;
00408     hr = S_OK;
00409     TRACE("found %d matches\n", xmlXPathNodeSetGetLength(This->result->nodesetval));
00410 
00411 cleanup:
00412     if (This != NULL && FAILED(hr))
00413         IXMLDOMNodeList_Release( (IXMLDOMNodeList*) &This->lpVtbl );
00414     xmlXPathFreeContext(ctxt);
00415     heap_free(str);
00416     return hr;
00417 }
00418 
00419 #endif

Generated on Sat May 26 2012 04:23:57 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.