[MSXML3]
[reactos.git] / reactos / dll / win32 / msxml3 / nodemap.c
1 /*
2 * Node map implementation
3 *
4 * Copyright 2005 Mike McCormack
5 *
6 * This library is free software; you can redistribute it and/or
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 *
11 * This library is distributed in the hope that it will be useful,
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
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "precomp.h"
22
23 #include <msxml2did.h>
24
25 #ifdef HAVE_LIBXML2
26
27 typedef struct
28 {
29 DispatchEx dispex;
30 IXMLDOMNamedNodeMap IXMLDOMNamedNodeMap_iface;
31 ISupportErrorInfo ISupportErrorInfo_iface;
32 LONG ref;
33
34 xmlNodePtr node;
35 LONG iterator;
36 IEnumVARIANT *enumvariant;
37
38 const struct nodemap_funcs *funcs;
39 } xmlnodemap;
40
41 static HRESULT nodemap_get_item(IUnknown *iface, LONG index, VARIANT *item)
42 {
43 V_VT(item) = VT_DISPATCH;
44 return IXMLDOMNamedNodeMap_get_item((IXMLDOMNamedNodeMap*)iface, index, (IXMLDOMNode**)&V_DISPATCH(item));
45 }
46
47 static const struct enumvariant_funcs nodemap_enumvariant = {
48 nodemap_get_item,
49 NULL
50 };
51
52 static inline xmlnodemap *impl_from_IXMLDOMNamedNodeMap( IXMLDOMNamedNodeMap *iface )
53 {
54 return CONTAINING_RECORD(iface, xmlnodemap, IXMLDOMNamedNodeMap_iface);
55 }
56
57 static inline xmlnodemap *impl_from_ISupportErrorInfo( ISupportErrorInfo *iface )
58 {
59 return CONTAINING_RECORD(iface, xmlnodemap, ISupportErrorInfo_iface);
60 }
61
62 static HRESULT WINAPI xmlnodemap_QueryInterface(
63 IXMLDOMNamedNodeMap *iface,
64 REFIID riid, void** ppvObject )
65 {
66 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
67 TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);
68
69 if( IsEqualGUID( riid, &IID_IUnknown ) ||
70 IsEqualGUID( riid, &IID_IDispatch ) ||
71 IsEqualGUID( riid, &IID_IXMLDOMNamedNodeMap ) )
72 {
73 *ppvObject = iface;
74 }
75 else if (IsEqualGUID( riid, &IID_IEnumVARIANT ))
76 {
77 if (!This->enumvariant)
78 {
79 HRESULT hr = create_enumvariant((IUnknown*)iface, FALSE, &nodemap_enumvariant, &This->enumvariant);
80 if (FAILED(hr)) return hr;
81 }
82
83 return IEnumVARIANT_QueryInterface(This->enumvariant, &IID_IEnumVARIANT, ppvObject);
84 }
85 else if (dispex_query_interface(&This->dispex, riid, ppvObject))
86 {
87 return *ppvObject ? S_OK : E_NOINTERFACE;
88 }
89 else if( IsEqualGUID( riid, &IID_ISupportErrorInfo ))
90 {
91 *ppvObject = &This->ISupportErrorInfo_iface;
92 }
93 else
94 {
95 TRACE("interface %s not implemented\n", debugstr_guid(riid));
96 *ppvObject = NULL;
97 return E_NOINTERFACE;
98 }
99
100 IXMLDOMNamedNodeMap_AddRef( iface );
101
102 return S_OK;
103 }
104
105 static ULONG WINAPI xmlnodemap_AddRef(
106 IXMLDOMNamedNodeMap *iface )
107 {
108 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
109 ULONG ref = InterlockedIncrement( &This->ref );
110 TRACE("(%p)->(%d)\n", This, ref);
111 return ref;
112 }
113
114 static ULONG WINAPI xmlnodemap_Release(
115 IXMLDOMNamedNodeMap *iface )
116 {
117 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
118 ULONG ref = InterlockedDecrement( &This->ref );
119
120 TRACE("(%p)->(%d)\n", This, ref);
121 if ( ref == 0 )
122 {
123 xmldoc_release( This->node->doc );
124 if (This->enumvariant) IEnumVARIANT_Release(This->enumvariant);
125 heap_free( This );
126 }
127
128 return ref;
129 }
130
131 static HRESULT WINAPI xmlnodemap_GetTypeInfoCount(
132 IXMLDOMNamedNodeMap *iface,
133 UINT* pctinfo )
134 {
135 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
136 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
137 }
138
139 static HRESULT WINAPI xmlnodemap_GetTypeInfo(
140 IXMLDOMNamedNodeMap *iface,
141 UINT iTInfo, LCID lcid,
142 ITypeInfo** ppTInfo )
143 {
144 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
145 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface,
146 iTInfo, lcid, ppTInfo);
147 }
148
149 static HRESULT WINAPI xmlnodemap_GetIDsOfNames(
150 IXMLDOMNamedNodeMap *iface,
151 REFIID riid, LPOLESTR* rgszNames,
152 UINT cNames, LCID lcid, DISPID* rgDispId )
153 {
154 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
155 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface,
156 riid, rgszNames, cNames, lcid, rgDispId);
157 }
158
159 static HRESULT WINAPI xmlnodemap_Invoke(
160 IXMLDOMNamedNodeMap *iface,
161 DISPID dispIdMember, REFIID riid, LCID lcid,
162 WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult,
163 EXCEPINFO* pExcepInfo, UINT* puArgErr )
164 {
165 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
166 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface,
167 dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
168 }
169
170 static HRESULT WINAPI xmlnodemap_getNamedItem(
171 IXMLDOMNamedNodeMap *iface,
172 BSTR name,
173 IXMLDOMNode** item)
174 {
175 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
176
177 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), item );
178
179 return This->funcs->get_named_item(This->node, name, item);
180 }
181
182 static HRESULT WINAPI xmlnodemap_setNamedItem(
183 IXMLDOMNamedNodeMap *iface,
184 IXMLDOMNode* newItem,
185 IXMLDOMNode** namedItem)
186 {
187 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
188
189 TRACE("(%p)->(%p %p)\n", This, newItem, namedItem );
190
191 return This->funcs->set_named_item(This->node, newItem, namedItem);
192 }
193
194 static HRESULT WINAPI xmlnodemap_removeNamedItem(
195 IXMLDOMNamedNodeMap *iface,
196 BSTR name,
197 IXMLDOMNode** namedItem)
198 {
199 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
200
201 TRACE("(%p)->(%s %p)\n", This, debugstr_w(name), namedItem );
202
203 return This->funcs->remove_named_item(This->node, name, namedItem);
204 }
205
206 static HRESULT WINAPI xmlnodemap_get_item(
207 IXMLDOMNamedNodeMap *iface,
208 LONG index,
209 IXMLDOMNode** item)
210 {
211 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
212
213 TRACE("(%p)->(%d %p)\n", This, index, item);
214
215 return This->funcs->get_item(This->node, index, item);
216 }
217
218 static HRESULT WINAPI xmlnodemap_get_length(
219 IXMLDOMNamedNodeMap *iface,
220 LONG *length)
221 {
222 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
223
224 TRACE("(%p)->(%p)\n", This, length);
225
226 return This->funcs->get_length(This->node, length);
227 }
228
229 static HRESULT WINAPI xmlnodemap_getQualifiedItem(
230 IXMLDOMNamedNodeMap *iface,
231 BSTR baseName,
232 BSTR namespaceURI,
233 IXMLDOMNode** item)
234 {
235 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
236
237 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(baseName), debugstr_w(namespaceURI), item);
238
239 return This->funcs->get_qualified_item(This->node, baseName, namespaceURI, item);
240 }
241
242 static HRESULT WINAPI xmlnodemap_removeQualifiedItem(
243 IXMLDOMNamedNodeMap *iface,
244 BSTR baseName,
245 BSTR namespaceURI,
246 IXMLDOMNode** item)
247 {
248 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
249
250 TRACE("(%p)->(%s %s %p)\n", This, debugstr_w(baseName), debugstr_w(namespaceURI), item);
251
252 return This->funcs->remove_qualified_item(This->node, baseName, namespaceURI, item);
253 }
254
255 static HRESULT WINAPI xmlnodemap_nextNode(
256 IXMLDOMNamedNodeMap *iface,
257 IXMLDOMNode** nextItem)
258 {
259 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
260
261 TRACE("(%p)->(%p: %d)\n", This, nextItem, This->iterator);
262
263 return This->funcs->next_node(This->node, &This->iterator, nextItem);
264 }
265
266 static HRESULT WINAPI xmlnodemap_reset(
267 IXMLDOMNamedNodeMap *iface )
268 {
269 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
270
271 TRACE("(%p)->(%d)\n", This, This->iterator);
272
273 This->iterator = 0;
274
275 return S_OK;
276 }
277
278 static HRESULT WINAPI xmlnodemap__newEnum(
279 IXMLDOMNamedNodeMap *iface,
280 IUnknown** enumv)
281 {
282 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( iface );
283 TRACE("(%p)->(%p)\n", This, enumv);
284 return create_enumvariant((IUnknown*)iface, TRUE, &nodemap_enumvariant, (IEnumVARIANT**)enumv);
285 }
286
287 static const struct IXMLDOMNamedNodeMapVtbl XMLDOMNamedNodeMapVtbl =
288 {
289 xmlnodemap_QueryInterface,
290 xmlnodemap_AddRef,
291 xmlnodemap_Release,
292 xmlnodemap_GetTypeInfoCount,
293 xmlnodemap_GetTypeInfo,
294 xmlnodemap_GetIDsOfNames,
295 xmlnodemap_Invoke,
296 xmlnodemap_getNamedItem,
297 xmlnodemap_setNamedItem,
298 xmlnodemap_removeNamedItem,
299 xmlnodemap_get_item,
300 xmlnodemap_get_length,
301 xmlnodemap_getQualifiedItem,
302 xmlnodemap_removeQualifiedItem,
303 xmlnodemap_nextNode,
304 xmlnodemap_reset,
305 xmlnodemap__newEnum,
306 };
307
308 static HRESULT WINAPI support_error_QueryInterface(
309 ISupportErrorInfo *iface,
310 REFIID riid, void** ppvObject )
311 {
312 xmlnodemap *This = impl_from_ISupportErrorInfo( iface );
313 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppvObject);
314 return IXMLDOMNamedNodeMap_QueryInterface(&This->IXMLDOMNamedNodeMap_iface, riid, ppvObject);
315 }
316
317 static ULONG WINAPI support_error_AddRef(
318 ISupportErrorInfo *iface )
319 {
320 xmlnodemap *This = impl_from_ISupportErrorInfo( iface );
321 return IXMLDOMNamedNodeMap_AddRef(&This->IXMLDOMNamedNodeMap_iface);
322 }
323
324 static ULONG WINAPI support_error_Release(
325 ISupportErrorInfo *iface )
326 {
327 xmlnodemap *This = impl_from_ISupportErrorInfo( iface );
328 return IXMLDOMNamedNodeMap_Release(&This->IXMLDOMNamedNodeMap_iface);
329 }
330
331 static HRESULT WINAPI support_error_InterfaceSupportsErrorInfo(
332 ISupportErrorInfo *iface,
333 REFIID riid )
334 {
335 xmlnodemap *This = impl_from_ISupportErrorInfo( iface );
336 TRACE("(%p)->(%s)\n", This, debugstr_guid(riid));
337 return IsEqualGUID(riid, &IID_IXMLDOMNamedNodeMap) ? S_OK : S_FALSE;
338 }
339
340 static const struct ISupportErrorInfoVtbl SupportErrorInfoVtbl =
341 {
342 support_error_QueryInterface,
343 support_error_AddRef,
344 support_error_Release,
345 support_error_InterfaceSupportsErrorInfo
346 };
347
348 static HRESULT xmlnodemap_get_dispid(IUnknown *iface, BSTR name, DWORD flags, DISPID *dispid)
349 {
350 WCHAR *ptr;
351 int idx = 0;
352
353 for(ptr = name; *ptr && isdigitW(*ptr); ptr++)
354 idx = idx*10 + (*ptr-'0');
355 if(*ptr)
356 return DISP_E_UNKNOWNNAME;
357
358 *dispid = DISPID_DOM_COLLECTION_BASE + idx;
359 TRACE("ret %x\n", *dispid);
360 return S_OK;
361 }
362
363 static HRESULT xmlnodemap_invoke(IUnknown *iface, DISPID id, LCID lcid, WORD flags, DISPPARAMS *params,
364 VARIANT *res, EXCEPINFO *ei)
365 {
366 xmlnodemap *This = impl_from_IXMLDOMNamedNodeMap( (IXMLDOMNamedNodeMap*)iface );
367
368 TRACE("(%p)->(%x %x %x %p %p %p)\n", This, id, lcid, flags, params, res, ei);
369
370 V_VT(res) = VT_DISPATCH;
371 V_DISPATCH(res) = NULL;
372
373 if (id < DISPID_DOM_COLLECTION_BASE || id > DISPID_DOM_COLLECTION_MAX)
374 return DISP_E_UNKNOWNNAME;
375
376 switch(flags)
377 {
378 case INVOKE_PROPERTYGET:
379 {
380 IXMLDOMNode *disp = NULL;
381
382 IXMLDOMNamedNodeMap_get_item(&This->IXMLDOMNamedNodeMap_iface, id - DISPID_DOM_COLLECTION_BASE, &disp);
383 V_DISPATCH(res) = (IDispatch*)disp;
384 break;
385 }
386 default:
387 {
388 FIXME("unimplemented flags %x\n", flags);
389 break;
390 }
391 }
392
393 TRACE("ret %p\n", V_DISPATCH(res));
394
395 return S_OK;
396 }
397
398 static const dispex_static_data_vtbl_t xmlnodemap_dispex_vtbl = {
399 xmlnodemap_get_dispid,
400 xmlnodemap_invoke
401 };
402
403 static const tid_t xmlnodemap_iface_tids[] = {
404 IXMLDOMNamedNodeMap_tid,
405 0
406 };
407
408 static dispex_static_data_t xmlnodemap_dispex = {
409 &xmlnodemap_dispex_vtbl,
410 IXMLDOMNamedNodeMap_tid,
411 NULL,
412 xmlnodemap_iface_tids
413 };
414
415 IXMLDOMNamedNodeMap *create_nodemap(xmlNodePtr node, const struct nodemap_funcs *funcs)
416 {
417 xmlnodemap *This;
418
419 This = heap_alloc( sizeof *This );
420 if ( !This )
421 return NULL;
422
423 This->IXMLDOMNamedNodeMap_iface.lpVtbl = &XMLDOMNamedNodeMapVtbl;
424 This->ISupportErrorInfo_iface.lpVtbl = &SupportErrorInfoVtbl;
425 This->node = node;
426 This->ref = 1;
427 This->iterator = 0;
428 This->enumvariant = NULL;
429 This->funcs = funcs;
430
431 init_dispex(&This->dispex, (IUnknown*)&This->IXMLDOMNamedNodeMap_iface, &xmlnodemap_dispex);
432
433 xmldoc_add_ref(node->doc);
434
435 return &This->IXMLDOMNamedNodeMap_iface;
436 }
437
438 #endif