d3d9/tests: Accept AMD GPU sysmem sample failure in test_mipmap_upload.
[wine.git] / dlls / oleaut32 / recinfo.c
blob7d46d6c42995f7bbdfc389615d9d35d4dd856d3b
1 /*
2 * Copyright 2005 Jacek Caban
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.
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.
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
19 #include <stdarg.h>
21 #define COBJMACROS
22 #define NONAMELESSUNION
24 #include "windef.h"
25 #include "winbase.h"
26 #include "objbase.h"
27 #include "oaidl.h"
28 #include "oleauto.h"
29 #include "variant.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(ole);
35 typedef struct {
36 enum VARENUM vt;
37 VARKIND varkind;
38 ULONG offset;
39 BSTR name;
40 } fieldstr;
42 typedef struct {
43 IRecordInfo IRecordInfo_iface;
44 LONG ref;
46 GUID guid;
47 UINT lib_index;
48 WORD n_vars;
49 ULONG size;
50 BSTR name;
51 fieldstr *fields;
52 ITypeInfo *pTypeInfo;
53 } IRecordInfoImpl;
55 static inline IRecordInfoImpl *impl_from_IRecordInfo(IRecordInfo *iface)
57 return CONTAINING_RECORD(iface, IRecordInfoImpl, IRecordInfo_iface);
60 static HRESULT copy_to_variant(void *src, VARIANT *pvar, enum VARENUM vt)
62 TRACE("%p %p %d\n", src, pvar, vt);
64 #define CASE_COPY(x) \
65 case VT_ ## x: \
66 memcpy(&V_ ## x(pvar), src, sizeof(V_ ## x(pvar))); \
67 break
69 switch(vt) {
70 CASE_COPY(I2);
71 CASE_COPY(I4);
72 CASE_COPY(R4);
73 CASE_COPY(R8);
74 CASE_COPY(CY);
75 CASE_COPY(DATE);
76 CASE_COPY(BSTR);
77 CASE_COPY(ERROR);
78 CASE_COPY(BOOL);
79 CASE_COPY(DECIMAL);
80 CASE_COPY(I1);
81 CASE_COPY(UI1);
82 CASE_COPY(UI2);
83 CASE_COPY(UI4);
84 CASE_COPY(I8);
85 CASE_COPY(UI8);
86 CASE_COPY(INT);
87 CASE_COPY(UINT);
88 CASE_COPY(INT_PTR);
89 CASE_COPY(UINT_PTR);
90 default:
91 FIXME("Not supported type: %d\n", vt);
92 return E_NOTIMPL;
94 #undef CASE_COPY
96 V_VT(pvar) = vt;
97 return S_OK;
100 static HRESULT copy_from_variant(VARIANT *src, void *dest, enum VARENUM vt)
102 VARIANT var;
103 HRESULT hres;
105 TRACE("(%p(%d) %p %d)\n", src, V_VT(src), dest, vt);
107 hres = VariantChangeType(&var, src, 0, vt);
108 if(FAILED(hres))
109 return hres;
111 #define CASE_COPY(x) \
112 case VT_ ## x: \
113 memcpy(dest, &V_ ## x(&var), sizeof(V_ ## x(&var))); \
114 break
116 switch(vt) {
117 CASE_COPY(I2);
118 CASE_COPY(I4);
119 CASE_COPY(R4);
120 CASE_COPY(R8);
121 CASE_COPY(CY);
122 CASE_COPY(DATE);
123 CASE_COPY(BSTR);
124 CASE_COPY(ERROR);
125 CASE_COPY(BOOL);
126 CASE_COPY(DECIMAL);
127 CASE_COPY(I1);
128 CASE_COPY(UI1);
129 CASE_COPY(UI2);
130 CASE_COPY(UI4);
131 CASE_COPY(I8);
132 CASE_COPY(UI8);
133 CASE_COPY(INT);
134 CASE_COPY(UINT);
135 CASE_COPY(INT_PTR);
136 CASE_COPY(UINT_PTR);
137 default:
138 FIXME("Not supported type: %d\n", V_VT(&var));
139 return E_NOTIMPL;
141 #undef CASE_COPY
142 return S_OK;
145 static HRESULT WINAPI IRecordInfoImpl_QueryInterface(IRecordInfo *iface, REFIID riid,
146 void **ppvObject)
148 TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);
150 *ppvObject = NULL;
152 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IRecordInfo, riid)) {
153 *ppvObject = iface;
154 IRecordInfo_AddRef(iface);
155 return S_OK;
158 FIXME("Not supported interface: %s\n", debugstr_guid(riid));
159 return E_NOINTERFACE;
162 static ULONG WINAPI IRecordInfoImpl_AddRef(IRecordInfo *iface)
164 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
165 ULONG ref = InterlockedIncrement(&This->ref);
166 TRACE("%p, refcount %lu.\n", iface, ref);
167 return ref;
170 static ULONG WINAPI IRecordInfoImpl_Release(IRecordInfo *iface)
172 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
173 ULONG ref = InterlockedDecrement(&This->ref);
175 TRACE("%p, refcount %lu.\n", iface, ref);
177 if(!ref) {
178 int i;
179 for(i=0; i<This->n_vars; i++)
180 SysFreeString(This->fields[i].name);
181 SysFreeString(This->name);
182 HeapFree(GetProcessHeap(), 0, This->fields);
183 ITypeInfo_Release(This->pTypeInfo);
184 HeapFree(GetProcessHeap(), 0, This);
186 return ref;
189 static HRESULT WINAPI IRecordInfoImpl_RecordInit(IRecordInfo *iface, PVOID pvNew)
191 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
192 TRACE("(%p)->(%p)\n", This, pvNew);
194 if(!pvNew)
195 return E_INVALIDARG;
197 memset(pvNew, 0, This->size);
198 return S_OK;
201 static HRESULT WINAPI IRecordInfoImpl_RecordClear(IRecordInfo *iface, PVOID pvExisting)
203 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
204 int i;
205 PVOID var;
207 TRACE("(%p)->(%p)\n", This, pvExisting);
209 if(!pvExisting)
210 return E_INVALIDARG;
212 for(i=0; i<This->n_vars; i++) {
213 if(This->fields[i].varkind != VAR_PERINSTANCE) {
214 ERR("varkind != VAR_PERINSTANCE\n");
215 continue;
217 var = ((PBYTE)pvExisting)+This->fields[i].offset;
218 switch(This->fields[i].vt) {
219 case VT_BSTR:
220 SysFreeString(*(BSTR*)var);
221 *(BSTR*)var = NULL;
222 break;
223 case VT_I2:
224 case VT_I4:
225 case VT_R4:
226 case VT_R8:
227 case VT_CY:
228 case VT_DATE:
229 case VT_ERROR:
230 case VT_BOOL:
231 case VT_DECIMAL:
232 case VT_I1:
233 case VT_UI1:
234 case VT_UI2:
235 case VT_UI4:
236 case VT_I8:
237 case VT_UI8:
238 case VT_INT:
239 case VT_UINT:
240 case VT_HRESULT:
241 break;
242 case VT_INT_PTR:
243 case VT_UINT_PTR:
244 *(void**)var = NULL;
245 break;
246 case VT_SAFEARRAY:
247 SafeArrayDestroy(var);
248 break;
249 case VT_UNKNOWN:
250 case VT_DISPATCH:
252 IUnknown *unk = *(IUnknown**)var;
253 if (unk)
254 IUnknown_Release(unk);
255 *(void**)var = NULL;
256 break;
258 default:
259 FIXME("Not supported vt = %d\n", This->fields[i].vt);
260 break;
264 return S_OK;
267 static HRESULT WINAPI IRecordInfoImpl_RecordCopy(IRecordInfo *iface, void *src_rec, void *dest_rec)
269 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
270 HRESULT hr = S_OK;
271 int i;
273 TRACE("(%p)->(%p %p)\n", This, src_rec, dest_rec);
275 if(!src_rec || !dest_rec)
276 return E_INVALIDARG;
278 /* release already stored data */
279 IRecordInfo_RecordClear(iface, dest_rec);
281 for (i = 0; i < This->n_vars; i++)
283 void *src, *dest;
285 if (This->fields[i].varkind != VAR_PERINSTANCE) {
286 ERR("varkind != VAR_PERINSTANCE\n");
287 continue;
290 src = ((BYTE*)src_rec) + This->fields[i].offset;
291 dest = ((BYTE*)dest_rec) + This->fields[i].offset;
292 switch (This->fields[i].vt)
294 case VT_BSTR:
296 BSTR src_str = *(BSTR*)src;
298 if (src_str)
300 BSTR str = SysAllocString(*(BSTR*)src);
301 if (!str) hr = E_OUTOFMEMORY;
303 *(BSTR*)dest = str;
305 else
306 *(BSTR*)dest = NULL;
307 break;
309 case VT_UNKNOWN:
310 case VT_DISPATCH:
312 IUnknown *unk = *(IUnknown**)src;
313 *(IUnknown**)dest = unk;
314 if (unk) IUnknown_AddRef(unk);
315 break;
317 case VT_SAFEARRAY:
318 hr = SafeArrayCopy(src, dest);
319 break;
320 default:
322 /* copy directly for types that don't need deep copy */
323 int len = get_type_size(NULL, This->fields[i].vt);
324 memcpy(dest, src, len);
325 break;
329 if (FAILED(hr)) break;
332 if (FAILED(hr))
333 IRecordInfo_RecordClear(iface, dest_rec);
335 return hr;
338 static HRESULT WINAPI IRecordInfoImpl_GetGuid(IRecordInfo *iface, GUID *pguid)
340 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
342 TRACE("(%p)->(%p)\n", This, pguid);
344 if(!pguid)
345 return E_INVALIDARG;
347 *pguid = This->guid;
348 return S_OK;
351 static HRESULT WINAPI IRecordInfoImpl_GetName(IRecordInfo *iface, BSTR *pbstrName)
353 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
355 TRACE("(%p)->(%p)\n", This, pbstrName);
357 if(!pbstrName)
358 return E_INVALIDARG;
360 *pbstrName = SysAllocString(This->name);
361 return S_OK;
364 static HRESULT WINAPI IRecordInfoImpl_GetSize(IRecordInfo *iface, ULONG *pcbSize)
366 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
368 TRACE("(%p)->(%p)\n", This, pcbSize);
370 if(!pcbSize)
371 return E_INVALIDARG;
373 *pcbSize = This->size;
374 return S_OK;
377 static HRESULT WINAPI IRecordInfoImpl_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo)
379 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
381 TRACE("(%p)->(%p)\n", This, ppTypeInfo);
383 if(!ppTypeInfo)
384 return E_INVALIDARG;
386 ITypeInfo_AddRef(This->pTypeInfo);
387 *ppTypeInfo = This->pTypeInfo;
389 return S_OK;
392 static HRESULT WINAPI IRecordInfoImpl_GetField(IRecordInfo *iface, PVOID pvData,
393 LPCOLESTR szFieldName, VARIANT *pvarField)
395 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
396 int i;
398 TRACE("(%p)->(%p %s %p)\n", This, pvData, debugstr_w(szFieldName), pvarField);
400 if(!pvData || !szFieldName || !pvarField)
401 return E_INVALIDARG;
403 for(i=0; i<This->n_vars; i++)
404 if(!wcscmp(This->fields[i].name, szFieldName))
405 break;
406 if(i == This->n_vars)
407 return TYPE_E_FIELDNOTFOUND;
409 VariantClear(pvarField);
410 return copy_to_variant(((PBYTE)pvData)+This->fields[i].offset, pvarField,
411 This->fields[i].vt);
414 static HRESULT WINAPI IRecordInfoImpl_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData,
415 LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray)
417 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
418 int i;
420 TRACE("(%p)->(%p %s %p %p)\n", This, pvData, debugstr_w(szFieldName), pvarField, ppvDataCArray);
422 if(!pvData || !szFieldName || !pvarField)
423 return E_INVALIDARG;
425 for(i=0; i<This->n_vars; i++)
426 if(!wcscmp(This->fields[i].name, szFieldName))
427 break;
428 if(i == This->n_vars)
429 return TYPE_E_FIELDNOTFOUND;
431 VariantClear(pvarField);
432 V_VT(pvarField) = VT_BYREF|This->fields[i].vt;
433 V_BYREF(pvarField) = ((PBYTE)pvData)+This->fields[i].offset;
434 *ppvDataCArray = NULL;
435 return S_OK;
438 static HRESULT WINAPI IRecordInfoImpl_PutField(IRecordInfo *iface, ULONG wFlags, PVOID pvData,
439 LPCOLESTR szFieldName, VARIANT *pvarField)
441 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
442 int i;
444 TRACE("%p, %#lx, %p, %s, %p.\n", iface, wFlags, pvData, debugstr_w(szFieldName), pvarField);
446 if(!pvData || !szFieldName || !pvarField
447 || (wFlags != INVOKE_PROPERTYPUTREF && wFlags != INVOKE_PROPERTYPUT))
448 return E_INVALIDARG;
450 if(wFlags == INVOKE_PROPERTYPUTREF) {
451 FIXME("wFlag == INVOKE_PROPERTYPUTREF not supported\n");
452 return E_NOTIMPL;
455 for(i=0; i<This->n_vars; i++)
456 if(!wcscmp(This->fields[i].name, szFieldName))
457 break;
458 if(i == This->n_vars)
459 return TYPE_E_FIELDNOTFOUND;
461 return copy_from_variant(pvarField, ((PBYTE)pvData)+This->fields[i].offset,
462 This->fields[i].vt);
465 static HRESULT WINAPI IRecordInfoImpl_PutFieldNoCopy(IRecordInfo *iface, ULONG wFlags,
466 PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
468 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
469 int i;
471 FIXME("%p, %#lx, %p, %s, %p stub\n", iface, wFlags, pvData, debugstr_w(szFieldName), pvarField);
473 if(!pvData || !szFieldName || !pvarField
474 || (wFlags != INVOKE_PROPERTYPUTREF && wFlags != INVOKE_PROPERTYPUT))
475 return E_INVALIDARG;
477 for(i=0; i<This->n_vars; i++)
478 if(!wcscmp(This->fields[i].name, szFieldName))
479 break;
480 if(i == This->n_vars)
481 return TYPE_E_FIELDNOTFOUND;
483 return E_NOTIMPL;
486 static HRESULT WINAPI IRecordInfoImpl_GetFieldNames(IRecordInfo *iface, ULONG *pcNames,
487 BSTR *rgBstrNames)
489 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
490 ULONG n = This->n_vars, i;
492 TRACE("(%p)->(%p %p)\n", This, pcNames, rgBstrNames);
494 if(!pcNames)
495 return E_INVALIDARG;
497 if(*pcNames < n)
498 n = *pcNames;
500 if(rgBstrNames) {
501 for(i=0; i<n; i++)
502 rgBstrNames[i] = SysAllocString(This->fields[i].name);
505 *pcNames = n;
506 return S_OK;
509 static BOOL WINAPI IRecordInfoImpl_IsMatchingType(IRecordInfo *iface, IRecordInfo *info2)
511 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
512 GUID guid2;
514 TRACE( "(%p)->(%p)\n", This, info2 );
516 IRecordInfo_GetGuid( info2, &guid2 );
517 return IsEqualGUID( &This->guid, &guid2 );
520 static PVOID WINAPI IRecordInfoImpl_RecordCreate(IRecordInfo *iface)
522 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
523 void *record;
525 TRACE("(%p)\n", This);
527 record = HeapAlloc(GetProcessHeap(), 0, This->size);
528 IRecordInfo_RecordInit(iface, record);
529 TRACE("created record at %p\n", record);
530 return record;
533 static HRESULT WINAPI IRecordInfoImpl_RecordCreateCopy(IRecordInfo *iface, PVOID pvSource,
534 PVOID *ppvDest)
536 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
538 TRACE("(%p)->(%p %p)\n", This, pvSource, ppvDest);
540 if(!pvSource || !ppvDest)
541 return E_INVALIDARG;
543 *ppvDest = IRecordInfo_RecordCreate(iface);
544 return IRecordInfo_RecordCopy(iface, pvSource, *ppvDest);
547 static HRESULT WINAPI IRecordInfoImpl_RecordDestroy(IRecordInfo *iface, PVOID pvRecord)
549 IRecordInfoImpl *This = impl_from_IRecordInfo(iface);
550 HRESULT hres;
552 TRACE("(%p)->(%p)\n", This, pvRecord);
554 hres = IRecordInfo_RecordClear(iface, pvRecord);
555 if(FAILED(hres))
556 return hres;
558 if(!HeapFree(GetProcessHeap(), 0, pvRecord))
559 return E_INVALIDARG;
561 return S_OK;
564 static const IRecordInfoVtbl IRecordInfoImplVtbl = {
565 IRecordInfoImpl_QueryInterface,
566 IRecordInfoImpl_AddRef,
567 IRecordInfoImpl_Release,
568 IRecordInfoImpl_RecordInit,
569 IRecordInfoImpl_RecordClear,
570 IRecordInfoImpl_RecordCopy,
571 IRecordInfoImpl_GetGuid,
572 IRecordInfoImpl_GetName,
573 IRecordInfoImpl_GetSize,
574 IRecordInfoImpl_GetTypeInfo,
575 IRecordInfoImpl_GetField,
576 IRecordInfoImpl_GetFieldNoCopy,
577 IRecordInfoImpl_PutField,
578 IRecordInfoImpl_PutFieldNoCopy,
579 IRecordInfoImpl_GetFieldNames,
580 IRecordInfoImpl_IsMatchingType,
581 IRecordInfoImpl_RecordCreate,
582 IRecordInfoImpl_RecordCreateCopy,
583 IRecordInfoImpl_RecordDestroy
586 /******************************************************************************
587 * GetRecordInfoFromGuids [OLEAUT32.322]
589 * RETURNS
590 * Success: S_OK
591 * Failure: E_INVALIDARG, if any argument is invalid.
593 HRESULT WINAPI GetRecordInfoFromGuids(REFGUID rGuidTypeLib, ULONG uVerMajor,
594 ULONG uVerMinor, LCID lcid, REFGUID rGuidTypeInfo, IRecordInfo** ppRecInfo)
596 ITypeInfo *pTypeInfo;
597 ITypeLib *pTypeLib;
598 HRESULT hres;
600 TRACE("%p, %lu, %lu, %#lx, %s, %p.\n", rGuidTypeLib, uVerMajor, uVerMinor,
601 lcid, debugstr_guid(rGuidTypeInfo), ppRecInfo);
603 hres = LoadRegTypeLib(rGuidTypeLib, uVerMajor, uVerMinor, lcid, &pTypeLib);
604 if(FAILED(hres)) {
605 WARN("LoadRegTypeLib failed!\n");
606 return hres;
609 hres = ITypeLib_GetTypeInfoOfGuid(pTypeLib, rGuidTypeInfo, &pTypeInfo);
610 ITypeLib_Release(pTypeLib);
611 if(FAILED(hres)) {
612 WARN("GetTypeInfoOfGuid failed!\n");
613 return hres;
616 hres = GetRecordInfoFromTypeInfo(pTypeInfo, ppRecInfo);
617 ITypeInfo_Release(pTypeInfo);
618 return hres;
621 /******************************************************************************
622 * GetRecordInfoFromTypeInfo [OLEAUT32.332]
624 HRESULT WINAPI GetRecordInfoFromTypeInfo(ITypeInfo* pTI, IRecordInfo** ppRecInfo) {
625 HRESULT hres;
626 TYPEATTR *typeattr;
627 IRecordInfoImpl *ret;
628 ITypeInfo *pTypeInfo;
629 int i;
630 GUID guid;
632 TRACE("(%p %p)\n", pTI, ppRecInfo);
634 if(!pTI || !ppRecInfo)
635 return E_INVALIDARG;
637 hres = ITypeInfo_GetTypeAttr(pTI, &typeattr);
638 if(FAILED(hres) || !typeattr) {
639 WARN("GetTypeAttr failed: %#lx.\n", hres);
640 return hres;
643 if(typeattr->typekind == TKIND_ALIAS) {
644 hres = ITypeInfo_GetRefTypeInfo(pTI, typeattr->tdescAlias.u.hreftype, &pTypeInfo);
645 guid = typeattr->guid;
646 ITypeInfo_ReleaseTypeAttr(pTI, typeattr);
647 if(FAILED(hres)) {
648 WARN("GetRefTypeInfo failed: %#lx.\n", hres);
649 return hres;
651 hres = ITypeInfo_GetTypeAttr(pTypeInfo, &typeattr);
652 if(FAILED(hres)) {
653 ITypeInfo_Release(pTypeInfo);
654 WARN("GetTypeAttr failed for referenced type: %#lx.\n", hres);
655 return hres;
657 }else {
658 pTypeInfo = pTI;
659 ITypeInfo_AddRef(pTypeInfo);
660 guid = typeattr->guid;
663 if(typeattr->typekind != TKIND_RECORD) {
664 WARN("typekind != TKIND_RECORD\n");
665 ITypeInfo_ReleaseTypeAttr(pTypeInfo, typeattr);
666 ITypeInfo_Release(pTypeInfo);
667 return E_INVALIDARG;
670 ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret));
671 ret->IRecordInfo_iface.lpVtbl = &IRecordInfoImplVtbl;
672 ret->ref = 1;
673 ret->pTypeInfo = pTypeInfo;
674 ret->n_vars = typeattr->cVars;
675 ret->size = typeattr->cbSizeInstance;
676 ITypeInfo_ReleaseTypeAttr(pTypeInfo, typeattr);
678 ret->guid = guid;
680 /* NOTE: Windows implementation calls ITypeInfo::GetCantainingTypeLib and
681 * ITypeLib::GetLibAttr, but we currently don't need this.
684 hres = ITypeInfo_GetDocumentation(pTypeInfo, MEMBERID_NIL, &ret->name, NULL, NULL, NULL);
685 if(FAILED(hres)) {
686 WARN("ITypeInfo::GetDocumentation failed\n");
687 ret->name = NULL;
690 ret->fields = HeapAlloc(GetProcessHeap(), 0, ret->n_vars*sizeof(fieldstr));
691 for(i = 0; i<ret->n_vars; i++) {
692 VARDESC *vardesc;
693 hres = ITypeInfo_GetVarDesc(pTypeInfo, i, &vardesc);
694 if(FAILED(hres)) {
695 WARN("GetVarDesc failed\n");
696 continue;
698 ret->fields[i].vt = vardesc->elemdescVar.tdesc.vt;
699 ret->fields[i].varkind = vardesc->varkind;
700 ret->fields[i].offset = vardesc->u.oInst;
701 hres = ITypeInfo_GetDocumentation(pTypeInfo, vardesc->memid, &ret->fields[i].name,
702 NULL, NULL, NULL);
703 if(FAILED(hres))
704 WARN("GetDocumentation failed: %#lx.\n", hres);
705 TRACE("field=%s, offset=%ld\n", debugstr_w(ret->fields[i].name), ret->fields[i].offset);
706 ITypeInfo_ReleaseVarDesc(pTypeInfo, vardesc);
709 *ppRecInfo = &ret->IRecordInfo_iface;
711 return S_OK;