[MSHTA] Implement MSHTA.exe (#577) CORE-12813
[reactos.git] / dll / win32 / mshtml / htmlattr.c
1 /*
2 * Copyright 2011 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 inline HTMLDOMAttribute *impl_from_IHTMLDOMAttribute(IHTMLDOMAttribute *iface)
22 {
23 return CONTAINING_RECORD(iface, HTMLDOMAttribute, IHTMLDOMAttribute_iface);
24 }
25
26 static HRESULT WINAPI HTMLDOMAttribute_QueryInterface(IHTMLDOMAttribute *iface,
27 REFIID riid, void **ppv)
28 {
29 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
30
31 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
32
33 if(IsEqualGUID(&IID_IUnknown, riid)) {
34 *ppv = &This->IHTMLDOMAttribute_iface;
35 }else if(IsEqualGUID(&IID_IHTMLDOMAttribute, riid)) {
36 *ppv = &This->IHTMLDOMAttribute_iface;
37 }else if(IsEqualGUID(&IID_IHTMLDOMAttribute2, riid)) {
38 *ppv = &This->IHTMLDOMAttribute2_iface;
39 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
40 return *ppv ? S_OK : E_NOINTERFACE;
41 }else {
42 WARN("%s not supported\n", debugstr_mshtml_guid(riid));
43 *ppv = NULL;
44 return E_NOINTERFACE;
45 }
46
47 IUnknown_AddRef((IUnknown*)*ppv);
48 return S_OK;
49 }
50
51 static ULONG WINAPI HTMLDOMAttribute_AddRef(IHTMLDOMAttribute *iface)
52 {
53 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
54 LONG ref = InterlockedIncrement(&This->ref);
55
56 TRACE("(%p) ref=%d\n", This, ref);
57
58 return ref;
59 }
60
61 static ULONG WINAPI HTMLDOMAttribute_Release(IHTMLDOMAttribute *iface)
62 {
63 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
64 LONG ref = InterlockedDecrement(&This->ref);
65
66 TRACE("(%p) ref=%d\n", This, ref);
67
68 if(!ref) {
69 assert(!This->elem);
70 release_dispex(&This->dispex);
71 heap_free(This->name);
72 heap_free(This);
73 }
74
75 return ref;
76 }
77
78 static HRESULT WINAPI HTMLDOMAttribute_GetTypeInfoCount(IHTMLDOMAttribute *iface, UINT *pctinfo)
79 {
80 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
81 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
82 }
83
84 static HRESULT WINAPI HTMLDOMAttribute_GetTypeInfo(IHTMLDOMAttribute *iface, UINT iTInfo,
85 LCID lcid, ITypeInfo **ppTInfo)
86 {
87 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
88 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
89 }
90
91 static HRESULT WINAPI HTMLDOMAttribute_GetIDsOfNames(IHTMLDOMAttribute *iface, REFIID riid,
92 LPOLESTR *rgszNames, UINT cNames,
93 LCID lcid, DISPID *rgDispId)
94 {
95 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
96 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
97 lcid, rgDispId);
98 }
99
100 static HRESULT WINAPI HTMLDOMAttribute_Invoke(IHTMLDOMAttribute *iface, DISPID dispIdMember,
101 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
102 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
103 {
104 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
105 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
106 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
107 }
108
109 static HRESULT WINAPI HTMLDOMAttribute_get_nodeName(IHTMLDOMAttribute *iface, BSTR *p)
110 {
111 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
112
113 TRACE("(%p)->(%p)\n", This, p);
114
115 if(!This->elem) {
116 if(!This->name) {
117 FIXME("No name available\n");
118 return E_FAIL;
119 }
120
121 *p = SysAllocString(This->name);
122 return *p ? S_OK : E_OUTOFMEMORY;
123 }
124
125 return IDispatchEx_GetMemberName(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, p);
126 }
127
128 static HRESULT WINAPI HTMLDOMAttribute_put_nodeValue(IHTMLDOMAttribute *iface, VARIANT v)
129 {
130 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
131 DISPID dispidNamed = DISPID_PROPERTYPUT;
132 DISPPARAMS dp = {&v, &dispidNamed, 1, 1};
133 EXCEPINFO ei;
134 VARIANT ret;
135
136 TRACE("(%p)->(%s)\n", This, debugstr_variant(&v));
137
138 if(!This->elem) {
139 FIXME("NULL This->elem\n");
140 return E_UNEXPECTED;
141 }
142
143 memset(&ei, 0, sizeof(ei));
144
145 return IDispatchEx_InvokeEx(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, LOCALE_SYSTEM_DEFAULT,
146 DISPATCH_PROPERTYPUT, &dp, &ret, &ei, NULL);
147 }
148
149 static HRESULT WINAPI HTMLDOMAttribute_get_nodeValue(IHTMLDOMAttribute *iface, VARIANT *p)
150 {
151 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
152
153 TRACE("(%p)->(%p)\n", This, p);
154
155 if(!This->elem) {
156 FIXME("NULL This->elem\n");
157 return E_UNEXPECTED;
158 }
159
160 return get_elem_attr_value_by_dispid(This->elem, This->dispid, 0, p);
161 }
162
163 static HRESULT WINAPI HTMLDOMAttribute_get_specified(IHTMLDOMAttribute *iface, VARIANT_BOOL *p)
164 {
165 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute(iface);
166 nsIDOMAttr *nsattr;
167 nsAString nsname;
168 BSTR name;
169 nsresult nsres;
170 HRESULT hres;
171
172 TRACE("(%p)->(%p)\n", This, p);
173
174 if(!This->elem || !This->elem->nselem) {
175 FIXME("NULL This->elem\n");
176 return E_UNEXPECTED;
177 }
178
179 if(get_dispid_type(This->dispid) != DISPEXPROP_BUILTIN) {
180 *p = VARIANT_TRUE;
181 return S_OK;
182 }
183
184 hres = IDispatchEx_GetMemberName(&This->elem->node.event_target.dispex.IDispatchEx_iface, This->dispid, &name);
185 if(FAILED(hres))
186 return hres;
187
188 /* FIXME: This is not exactly right, we have some attributes that don't map directly to Gecko attributes. */
189 nsAString_InitDepend(&nsname, name);
190 nsres = nsIDOMHTMLElement_GetAttributeNode(This->elem->nselem, &nsname, &nsattr);
191 nsAString_Finish(&nsname);
192 SysFreeString(name);
193 if(NS_FAILED(nsres))
194 return E_FAIL;
195
196 /* If the Gecko attribute node can be found, we know that the attribute is specified.
197 There is no point in calling GetSpecified */
198 if(nsattr) {
199 nsIDOMAttr_Release(nsattr);
200 *p = VARIANT_TRUE;
201 }else {
202 *p = VARIANT_FALSE;
203 }
204 return S_OK;
205 }
206
207 static const IHTMLDOMAttributeVtbl HTMLDOMAttributeVtbl = {
208 HTMLDOMAttribute_QueryInterface,
209 HTMLDOMAttribute_AddRef,
210 HTMLDOMAttribute_Release,
211 HTMLDOMAttribute_GetTypeInfoCount,
212 HTMLDOMAttribute_GetTypeInfo,
213 HTMLDOMAttribute_GetIDsOfNames,
214 HTMLDOMAttribute_Invoke,
215 HTMLDOMAttribute_get_nodeName,
216 HTMLDOMAttribute_put_nodeValue,
217 HTMLDOMAttribute_get_nodeValue,
218 HTMLDOMAttribute_get_specified
219 };
220
221 static inline HTMLDOMAttribute *impl_from_IHTMLDOMAttribute2(IHTMLDOMAttribute2 *iface)
222 {
223 return CONTAINING_RECORD(iface, HTMLDOMAttribute, IHTMLDOMAttribute2_iface);
224 }
225
226 static HRESULT WINAPI HTMLDOMAttribute2_QueryInterface(IHTMLDOMAttribute2 *iface, REFIID riid, void **ppv)
227 {
228 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
229 return IHTMLDOMAttribute_QueryInterface(&This->IHTMLDOMAttribute_iface, riid, ppv);
230 }
231
232 static ULONG WINAPI HTMLDOMAttribute2_AddRef(IHTMLDOMAttribute2 *iface)
233 {
234 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
235 return IHTMLDOMAttribute_AddRef(&This->IHTMLDOMAttribute_iface);
236 }
237
238 static ULONG WINAPI HTMLDOMAttribute2_Release(IHTMLDOMAttribute2 *iface)
239 {
240 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
241 return IHTMLDOMAttribute_Release(&This->IHTMLDOMAttribute_iface);
242 }
243
244 static HRESULT WINAPI HTMLDOMAttribute2_GetTypeInfoCount(IHTMLDOMAttribute2 *iface, UINT *pctinfo)
245 {
246 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
247 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
248 }
249
250 static HRESULT WINAPI HTMLDOMAttribute2_GetTypeInfo(IHTMLDOMAttribute2 *iface, UINT iTInfo,
251 LCID lcid, ITypeInfo **ppTInfo)
252 {
253 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
254 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
255 }
256
257 static HRESULT WINAPI HTMLDOMAttribute2_GetIDsOfNames(IHTMLDOMAttribute2 *iface, REFIID riid,
258 LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
259 {
260 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
261 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
262 lcid, rgDispId);
263 }
264
265 static HRESULT WINAPI HTMLDOMAttribute2_Invoke(IHTMLDOMAttribute2 *iface, DISPID dispIdMember,
266 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
267 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
268 {
269 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
270 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
271 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
272 }
273
274 static HRESULT WINAPI HTMLDOMAttribute2_get_name(IHTMLDOMAttribute2 *iface, BSTR *p)
275 {
276 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
277 FIXME("(%p)->(%p)\n", This, p);
278 return E_NOTIMPL;
279 }
280
281 static HRESULT WINAPI HTMLDOMAttribute2_put_value(IHTMLDOMAttribute2 *iface, BSTR v)
282 {
283 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
284 FIXME("(%p)->(%s)\n", This, debugstr_w(v));
285 return E_NOTIMPL;
286 }
287
288 static HRESULT WINAPI HTMLDOMAttribute2_get_value(IHTMLDOMAttribute2 *iface, BSTR *p)
289 {
290 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
291 VARIANT val;
292 HRESULT hres;
293
294 TRACE("(%p)->(%p)\n", This, p);
295
296 if(!This->elem) {
297 FIXME("NULL This->elem\n");
298 return E_UNEXPECTED;
299 }
300
301 hres = get_elem_attr_value_by_dispid(This->elem, This->dispid, ATTRFLAG_ASSTRING, &val);
302 if(FAILED(hres))
303 return hres;
304
305 assert(V_VT(&val) == VT_BSTR);
306 *p = V_BSTR(&val);
307 if(!*p && !(*p = SysAllocStringLen(NULL, 0)))
308 return E_OUTOFMEMORY;
309 return S_OK;
310 }
311
312 static HRESULT WINAPI HTMLDOMAttribute2_get_expando(IHTMLDOMAttribute2 *iface, VARIANT_BOOL *p)
313 {
314 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
315
316 TRACE("(%p)->(%p)\n", This, p);
317
318 *p = get_dispid_type(This->dispid) == DISPEXPROP_BUILTIN ? VARIANT_FALSE : VARIANT_TRUE;
319 return S_OK;
320 }
321
322 static HRESULT WINAPI HTMLDOMAttribute2_get_nodeType(IHTMLDOMAttribute2 *iface, LONG *p)
323 {
324 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
325 FIXME("(%p)->(%p)\n", This, p);
326 return E_NOTIMPL;
327 }
328
329 static HRESULT WINAPI HTMLDOMAttribute2_get_parentNode(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p)
330 {
331 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
332 FIXME("(%p)->(%p)\n", This, p);
333 return E_NOTIMPL;
334 }
335
336 static HRESULT WINAPI HTMLDOMAttribute2_get_childNodes(IHTMLDOMAttribute2 *iface, IDispatch **p)
337 {
338 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
339 FIXME("(%p)->(%p)\n", This, p);
340 return E_NOTIMPL;
341 }
342
343 static HRESULT WINAPI HTMLDOMAttribute2_get_firstChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p)
344 {
345 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
346 FIXME("(%p)->(%p)\n", This, p);
347 return E_NOTIMPL;
348 }
349
350 static HRESULT WINAPI HTMLDOMAttribute2_get_lastChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p)
351 {
352 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
353 FIXME("(%p)->(%p)\n", This, p);
354 return E_NOTIMPL;
355 }
356
357 static HRESULT WINAPI HTMLDOMAttribute2_get_previousSibling(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p)
358 {
359 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
360 FIXME("(%p)->(%p)\n", This, p);
361 return E_NOTIMPL;
362 }
363
364 static HRESULT WINAPI HTMLDOMAttribute2_get_nextSibling(IHTMLDOMAttribute2 *iface, IHTMLDOMNode **p)
365 {
366 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
367 FIXME("(%p)->(%p)\n", This, p);
368 return E_NOTIMPL;
369 }
370
371 static HRESULT WINAPI HTMLDOMAttribute2_get_attributes(IHTMLDOMAttribute2 *iface, IDispatch **p)
372 {
373 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
374 FIXME("(%p)->(%p)\n", This, p);
375 return E_NOTIMPL;
376 }
377
378 static HRESULT WINAPI HTMLDOMAttribute2_get_ownerDocument(IHTMLDOMAttribute2 *iface, IDispatch **p)
379 {
380 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
381 FIXME("(%p)->(%p)\n", This, p);
382 return E_NOTIMPL;
383 }
384
385 static HRESULT WINAPI HTMLDOMAttribute2_insertBefore(IHTMLDOMAttribute2 *iface, IHTMLDOMNode *newChild,
386 VARIANT refChild, IHTMLDOMNode **node)
387 {
388 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
389 FIXME("(%p)->(%p %s %p)\n", This, newChild, debugstr_variant(&refChild), node);
390 return E_NOTIMPL;
391 }
392
393 static HRESULT WINAPI HTMLDOMAttribute2_replaceChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode *newChild,
394 IHTMLDOMNode *oldChild, IHTMLDOMNode **node)
395 {
396 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
397 FIXME("(%p)->(%p %p %p)\n", This, newChild, oldChild, node);
398 return E_NOTIMPL;
399 }
400
401 static HRESULT WINAPI HTMLDOMAttribute2_removeChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode *oldChild,
402 IHTMLDOMNode **node)
403 {
404 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
405 FIXME("(%p)->(%p %p)\n", This, oldChild, node);
406 return E_NOTIMPL;
407 }
408
409 static HRESULT WINAPI HTMLDOMAttribute2_appendChild(IHTMLDOMAttribute2 *iface, IHTMLDOMNode *newChild,
410 IHTMLDOMNode **node)
411 {
412 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
413 FIXME("(%p)->(%p %p)\n", This, newChild, node);
414 return E_NOTIMPL;
415 }
416
417 static HRESULT WINAPI HTMLDOMAttribute2_hasChildNodes(IHTMLDOMAttribute2 *iface, VARIANT_BOOL *fChildren)
418 {
419 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
420 FIXME("(%p)->(%p)\n", This, fChildren);
421 return E_NOTIMPL;
422 }
423
424 static HRESULT WINAPI HTMLDOMAttribute2_cloneNode(IHTMLDOMAttribute2 *iface, VARIANT_BOOL fDeep,
425 IHTMLDOMAttribute **clonedNode)
426 {
427 HTMLDOMAttribute *This = impl_from_IHTMLDOMAttribute2(iface);
428 FIXME("(%p)->(%x %p)\n", This, fDeep, clonedNode);
429 return E_NOTIMPL;
430 }
431
432 static const IHTMLDOMAttribute2Vtbl HTMLDOMAttribute2Vtbl = {
433 HTMLDOMAttribute2_QueryInterface,
434 HTMLDOMAttribute2_AddRef,
435 HTMLDOMAttribute2_Release,
436 HTMLDOMAttribute2_GetTypeInfoCount,
437 HTMLDOMAttribute2_GetTypeInfo,
438 HTMLDOMAttribute2_GetIDsOfNames,
439 HTMLDOMAttribute2_Invoke,
440 HTMLDOMAttribute2_get_name,
441 HTMLDOMAttribute2_put_value,
442 HTMLDOMAttribute2_get_value,
443 HTMLDOMAttribute2_get_expando,
444 HTMLDOMAttribute2_get_nodeType,
445 HTMLDOMAttribute2_get_parentNode,
446 HTMLDOMAttribute2_get_childNodes,
447 HTMLDOMAttribute2_get_firstChild,
448 HTMLDOMAttribute2_get_lastChild,
449 HTMLDOMAttribute2_get_previousSibling,
450 HTMLDOMAttribute2_get_nextSibling,
451 HTMLDOMAttribute2_get_attributes,
452 HTMLDOMAttribute2_get_ownerDocument,
453 HTMLDOMAttribute2_insertBefore,
454 HTMLDOMAttribute2_replaceChild,
455 HTMLDOMAttribute2_removeChild,
456 HTMLDOMAttribute2_appendChild,
457 HTMLDOMAttribute2_hasChildNodes,
458 HTMLDOMAttribute2_cloneNode
459 };
460
461 static const tid_t HTMLDOMAttribute_iface_tids[] = {
462 IHTMLDOMAttribute_tid,
463 IHTMLDOMAttribute2_tid,
464 0
465 };
466 static dispex_static_data_t HTMLDOMAttribute_dispex = {
467 NULL,
468 DispHTMLDOMAttribute_tid,
469 0,
470 HTMLDOMAttribute_iface_tids
471 };
472
473 HRESULT HTMLDOMAttribute_Create(const WCHAR *name, HTMLElement *elem, DISPID dispid, HTMLDOMAttribute **attr)
474 {
475 HTMLAttributeCollection *col;
476 HTMLDOMAttribute *ret;
477 HRESULT hres;
478
479 ret = heap_alloc_zero(sizeof(*ret));
480 if(!ret)
481 return E_OUTOFMEMORY;
482
483 ret->IHTMLDOMAttribute_iface.lpVtbl = &HTMLDOMAttributeVtbl;
484 ret->IHTMLDOMAttribute2_iface.lpVtbl = &HTMLDOMAttribute2Vtbl;
485 ret->ref = 1;
486 ret->dispid = dispid;
487 ret->elem = elem;
488
489 init_dispex(&ret->dispex, (IUnknown*)&ret->IHTMLDOMAttribute_iface,
490 &HTMLDOMAttribute_dispex);
491
492 /* For attributes attached to an element, (elem,dispid) pair should be valid used for its operation. */
493 if(elem) {
494 hres = HTMLElement_get_attr_col(&elem->node, &col);
495 if(FAILED(hres)) {
496 IHTMLDOMAttribute_Release(&ret->IHTMLDOMAttribute_iface);
497 return hres;
498 }
499 IHTMLAttributeCollection_Release(&col->IHTMLAttributeCollection_iface);
500
501 list_add_tail(&elem->attrs->attrs, &ret->entry);
502 }
503
504 /* For detached attributes we may still do most operations if we have its name available. */
505 if(name) {
506 ret->name = heap_strdupW(name);
507 if(!ret->name) {
508 IHTMLDOMAttribute_Release(&ret->IHTMLDOMAttribute_iface);
509 return E_OUTOFMEMORY;
510 }
511 }
512
513 *attr = ret;
514 return S_OK;
515 }