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
22 #define NONAMELESSUNION
23 #define NONAMELESSSTRUCT
31 #include "wine/unicode.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
44 const IRecordInfoVtbl
*lpVtbl
;
56 static HRESULT
copy_to_variant(void *src
, VARIANT
*pvar
, enum VARENUM vt
)
58 TRACE("%p %p %d\n", src
, pvar
, vt
);
60 #define CASE_COPY(x) \
62 V_ ## x(pvar) = *(typeof(V_ ## x(pvar))*)src; \
87 FIXME("Not supported type: %d\n", vt
);
96 static HRESULT
copy_from_variant(VARIANT
*src
, void *dest
, enum VARENUM vt
)
101 TRACE("(%p(%d) %p %d)\n", src
, V_VT(src
), dest
, vt
);
103 hres
= VariantChangeType(&var
, src
, 0, vt
);
107 #define CASE_COPY(x) \
109 *(typeof(V_ ## x(&var))*)dest = V_ ## x(&var); \
134 FIXME("Not supported type: %d\n", V_VT(&var
));
141 static HRESULT WINAPI
IRecordInfoImpl_QueryInterface(IRecordInfo
*iface
, REFIID riid
,
144 TRACE("(%p)->(%s %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
146 if(IsEqualGUID(&IID_IUnknown
, riid
) || IsEqualGUID(&IID_IRecordInfo
, riid
)) {
148 IRecordInfo_AddRef(iface
);
152 FIXME("Not supported interface: %s\n", debugstr_guid(riid
));
153 return E_NOINTERFACE
;
156 static ULONG WINAPI
IRecordInfoImpl_AddRef(IRecordInfo
*iface
)
158 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
159 ULONG ref
= InterlockedIncrement(&This
->ref
);
160 TRACE("(%p) -> %d\n", This
, ref
);
164 static ULONG WINAPI
IRecordInfoImpl_Release(IRecordInfo
*iface
)
166 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
167 ULONG ref
= InterlockedDecrement(&This
->ref
);
169 TRACE("(%p) -> %d\n", This
, ref
);
173 for(i
=0; i
<This
->n_vars
; i
++)
174 SysFreeString(This
->fields
[i
].name
);
175 HeapFree(GetProcessHeap(), 0, This
->name
);
176 HeapFree(GetProcessHeap(), 0, This
->fields
);
177 ITypeInfo_Release(This
->pTypeInfo
);
178 HeapFree(GetProcessHeap(), 0, This
);
183 static HRESULT WINAPI
IRecordInfoImpl_RecordInit(IRecordInfo
*iface
, PVOID pvNew
)
185 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
186 TRACE("(%p)->(%p)\n", This
, pvNew
);
191 memset(pvNew
, 0, This
->size
);
195 static HRESULT WINAPI
IRecordInfoImpl_RecordClear(IRecordInfo
*iface
, PVOID pvExisting
)
197 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
201 TRACE("(%p)->(%p)\n", This
, pvExisting
);
206 for(i
=0; i
<This
->n_vars
; i
++) {
207 if(This
->fields
[i
].varkind
!= VAR_PERINSTANCE
) {
208 ERR("varkind != VAR_PERINSTANCE\n");
211 var
= ((PBYTE
)pvExisting
)+This
->fields
[i
].offset
;
212 switch(This
->fields
[i
].vt
) {
214 /* NOTE: Windows implementatino reads DWORD (len) before string,
215 * but it seems to do nothing with this */
240 FIXME("Not supported vt = %d\n", This
->fields
[i
].vt
);
248 static HRESULT WINAPI
IRecordInfoImpl_RecordCopy(IRecordInfo
*iface
, PVOID pvExisting
,
251 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
253 TRACE("(%p)->(%p %p)\n", This
, pvExisting
, pvNew
);
255 if(!pvExisting
|| !pvNew
)
258 memcpy(pvExisting
, pvNew
, This
->size
);
262 static HRESULT WINAPI
IRecordInfoImpl_GetGuid(IRecordInfo
*iface
, GUID
*pguid
)
264 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
266 TRACE("(%p)->(%p)\n", This
, pguid
);
271 memcpy(pguid
, &This
->guid
, sizeof(GUID
));
275 static HRESULT WINAPI
IRecordInfoImpl_GetName(IRecordInfo
*iface
, BSTR
*pbstrName
)
277 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
279 TRACE("(%p)->(%p)\n", This
, pbstrName
);
284 *pbstrName
= SysAllocString(This
->name
);
288 static HRESULT WINAPI
IRecordInfoImpl_GetSize(IRecordInfo
*iface
, ULONG
*pcbSize
)
290 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
292 TRACE("(%p)->(%p)\n", This
, pcbSize
);
297 *pcbSize
= This
->size
;
301 static HRESULT WINAPI
IRecordInfoImpl_GetTypeInfo(IRecordInfo
*iface
, ITypeInfo
**ppTypeInfo
)
303 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
305 TRACE("(%p)->(%p)\n", This
, ppTypeInfo
);
310 ITypeInfo_AddRef(This
->pTypeInfo
);
311 *ppTypeInfo
= This
->pTypeInfo
;
316 static HRESULT WINAPI
IRecordInfoImpl_GetField(IRecordInfo
*iface
, PVOID pvData
,
317 LPCOLESTR szFieldName
, VARIANT
*pvarField
)
319 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
322 TRACE("(%p)->(%p %s %p)\n", This
, pvData
, debugstr_w(szFieldName
), pvarField
);
324 if(!pvData
|| !szFieldName
|| !pvarField
)
327 for(i
=0; i
<This
->n_vars
; i
++)
328 if(!strcmpW(This
->fields
[i
].name
, szFieldName
))
330 if(i
== This
->n_vars
)
331 return TYPE_E_FIELDNOTFOUND
;
333 VariantClear(pvarField
);
334 return copy_to_variant(((PBYTE
)pvData
)+This
->fields
[i
].offset
, pvarField
,
338 static HRESULT WINAPI
IRecordInfoImpl_GetFieldNoCopy(IRecordInfo
*iface
, PVOID pvData
,
339 LPCOLESTR szFieldName
, VARIANT
*pvarField
, PVOID
*ppvDataCArray
)
341 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
344 TRACE("(%p)->(%p %s %p %p)\n", This
, pvData
, debugstr_w(szFieldName
), pvarField
, ppvDataCArray
);
346 if(!pvData
|| !szFieldName
|| !pvarField
)
349 for(i
=0; i
<This
->n_vars
; i
++)
350 if(!strcmpW(This
->fields
[i
].name
, szFieldName
))
352 if(i
== This
->n_vars
)
353 return TYPE_E_FIELDNOTFOUND
;
355 VariantClear(pvarField
);
356 V_VT(pvarField
) = VT_BYREF
|This
->fields
[i
].vt
;
357 V_BYREF(pvarField
) = ((PBYTE
)pvData
)+This
->fields
[i
].offset
;
358 *ppvDataCArray
= NULL
;
362 static HRESULT WINAPI
IRecordInfoImpl_PutField(IRecordInfo
*iface
, ULONG wFlags
, PVOID pvData
,
363 LPCOLESTR szFieldName
, VARIANT
*pvarField
)
365 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
368 TRACE("(%p)->(%08x %p %s %p)\n", This
, wFlags
, pvData
, debugstr_w(szFieldName
),
371 if(!pvData
|| !szFieldName
|| !pvarField
372 || (wFlags
!= INVOKE_PROPERTYPUTREF
&& wFlags
!= INVOKE_PROPERTYPUT
))
375 if(wFlags
== INVOKE_PROPERTYPUTREF
) {
376 FIXME("wFlag == INVOKE_PROPERTYPUTREF not supported\n");
380 for(i
=0; i
<This
->n_vars
; i
++)
381 if(!strcmpW(This
->fields
[i
].name
, szFieldName
))
383 if(i
== This
->n_vars
)
384 return TYPE_E_FIELDNOTFOUND
;
386 return copy_from_variant(pvarField
, ((PBYTE
)pvData
)+This
->fields
[i
].offset
,
390 static HRESULT WINAPI
IRecordInfoImpl_PutFieldNoCopy(IRecordInfo
*iface
, ULONG wFlags
,
391 PVOID pvData
, LPCOLESTR szFieldName
, VARIANT
*pvarField
)
393 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
396 FIXME("(%p)->(%08x %p %s %p) stub\n", This
, wFlags
, pvData
, debugstr_w(szFieldName
), pvarField
);
398 if(!pvData
|| !szFieldName
|| !pvarField
399 || (wFlags
!= INVOKE_PROPERTYPUTREF
&& wFlags
!= INVOKE_PROPERTYPUT
))
402 for(i
=0; i
<This
->n_vars
; i
++)
403 if(!strcmpW(This
->fields
[i
].name
, szFieldName
))
405 if(i
== This
->n_vars
)
406 return TYPE_E_FIELDNOTFOUND
;
411 static HRESULT WINAPI
IRecordInfoImpl_GetFieldNames(IRecordInfo
*iface
, ULONG
*pcNames
,
414 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
415 ULONG n
= This
->n_vars
;
418 TRACE("(%p)->(%p %p)\n", This
, pcNames
, rgBstrNames
);
428 rgBstrNames
[i
] = SysAllocString(This
->fields
[i
].name
);
435 static BOOL WINAPI
IRecordInfoImpl_IsMatchingType(IRecordInfo
*iface
, IRecordInfo
*pRecordInfo
)
437 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
439 FIXME("(%p)->(%p) stub\n", This
, pRecordInfo
);
444 static PVOID WINAPI
IRecordInfoImpl_RecordCreate(IRecordInfo
*iface
)
446 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
448 TRACE("(%p)\n", This
);
450 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->size
);
453 static HRESULT WINAPI
IRecordInfoImpl_RecordCreateCopy(IRecordInfo
*iface
, PVOID pvSource
,
456 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
458 TRACE("(%p)->(%p %p)\n", This
, pvSource
, ppvDest
);
460 if(!pvSource
|| !ppvDest
)
463 *ppvDest
= IRecordInfo_RecordCreate(iface
);
464 return IRecordInfo_RecordCopy(iface
, pvSource
, *ppvDest
);
467 static HRESULT WINAPI
IRecordInfoImpl_RecordDestroy(IRecordInfo
*iface
, PVOID pvRecord
)
469 IRecordInfoImpl
*This
= (IRecordInfoImpl
*)iface
;
471 TRACE("(%p)->(%p)\n", This
, pvRecord
);
473 if(!HeapFree(GetProcessHeap(), 0, pvRecord
))
479 static const IRecordInfoVtbl IRecordInfoImplVtbl
= {
480 IRecordInfoImpl_QueryInterface
,
481 IRecordInfoImpl_AddRef
,
482 IRecordInfoImpl_Release
,
483 IRecordInfoImpl_RecordInit
,
484 IRecordInfoImpl_RecordClear
,
485 IRecordInfoImpl_RecordCopy
,
486 IRecordInfoImpl_GetGuid
,
487 IRecordInfoImpl_GetName
,
488 IRecordInfoImpl_GetSize
,
489 IRecordInfoImpl_GetTypeInfo
,
490 IRecordInfoImpl_GetField
,
491 IRecordInfoImpl_GetFieldNoCopy
,
492 IRecordInfoImpl_PutField
,
493 IRecordInfoImpl_PutFieldNoCopy
,
494 IRecordInfoImpl_GetFieldNames
,
495 IRecordInfoImpl_IsMatchingType
,
496 IRecordInfoImpl_RecordCreate
,
497 IRecordInfoImpl_RecordCreateCopy
,
498 IRecordInfoImpl_RecordDestroy
501 /******************************************************************************
502 * GetRecordInfoFromGuids [OLEAUT32.322]
506 * Failure: E_INVALIDARG, if any argument is invalid.
508 HRESULT WINAPI
GetRecordInfoFromGuids(REFGUID rGuidTypeLib
, ULONG uVerMajor
,
509 ULONG uVerMinor
, LCID lcid
, REFGUID rGuidTypeInfo
, IRecordInfo
** ppRecInfo
)
511 ITypeInfo
*pTypeInfo
;
515 TRACE("(%p,%d,%d,%d,%p,%p)\n", rGuidTypeLib
, uVerMajor
, uVerMinor
,
516 lcid
, rGuidTypeInfo
, ppRecInfo
);
518 hres
= LoadRegTypeLib(rGuidTypeLib
, uVerMajor
, uVerMinor
, lcid
, &pTypeLib
);
520 WARN("LoadRegTypeLib failed!\n");
524 hres
= ITypeLib_GetTypeInfoOfGuid(pTypeLib
, rGuidTypeInfo
, &pTypeInfo
);
525 ITypeLib_Release(pTypeLib
);
527 WARN("GetTypeInfoOfGuid failed!\n");
531 hres
= GetRecordInfoFromTypeInfo(pTypeInfo
, ppRecInfo
);
532 ITypeInfo_Release(pTypeInfo
);
536 /******************************************************************************
537 * GetRecordInfoFromTypeInfo [OLEAUT32.332]
539 HRESULT WINAPI
GetRecordInfoFromTypeInfo(ITypeInfo
* pTI
, IRecordInfo
** ppRecInfo
) {
542 IRecordInfoImpl
*ret
;
543 ITypeInfo
*pTypeInfo
;
547 TRACE("(%p %p)\n", pTI
, ppRecInfo
);
549 if(!pTI
|| !ppRecInfo
)
552 hres
= ITypeInfo_GetTypeAttr(pTI
, &typeattr
);
553 if(FAILED(hres
) || !typeattr
) {
554 WARN("GetTypeAttr failed: %08x\n", hres
);
558 if(typeattr
->typekind
== TKIND_ALIAS
) {
559 hres
= ITypeInfo_GetRefTypeInfo(pTI
, typeattr
->tdescAlias
.u
.hreftype
, &pTypeInfo
);
560 memcpy(&guid
, &typeattr
->guid
, sizeof(GUID
));
561 ITypeInfo_ReleaseTypeAttr(pTI
, typeattr
);
563 WARN("GetRefTypeInfo failed: %08x\n", hres
);
566 ITypeInfo_GetTypeAttr(pTypeInfo
, &typeattr
);
569 ITypeInfo_AddRef(pTypeInfo
);
570 memcpy(&guid
, &typeattr
->guid
, sizeof(GUID
));
573 if(typeattr
->typekind
!= TKIND_RECORD
) {
574 WARN("typekind != TKIND_RECORD\n");
575 ITypeInfo_ReleaseTypeAttr(pTypeInfo
, typeattr
);
576 ITypeInfo_Release(pTypeInfo
);
580 ret
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ret
));
581 ret
->lpVtbl
= &IRecordInfoImplVtbl
;
583 ret
->pTypeInfo
= pTypeInfo
;
584 ret
->n_vars
= typeattr
->cVars
;
585 ret
->size
= typeattr
->cbSizeInstance
;
586 ITypeInfo_ReleaseTypeAttr(pTypeInfo
, typeattr
);
588 memcpy(&ret
->guid
, &guid
, sizeof(GUID
));
590 /* NOTE: Windows implementation calls ITypeInfo::GetCantainingTypeLib and
591 * ITypeLib::GetLibAttr, but we currently don't need this.
594 hres
= ITypeInfo_GetDocumentation(pTypeInfo
, MEMBERID_NIL
, &ret
->name
, NULL
, NULL
, NULL
);
596 WARN("ITypeInfo::GetDocumentation failed\n");
600 ret
->fields
= HeapAlloc(GetProcessHeap(), 0, ret
->n_vars
*sizeof(VARDESC
));
601 for(i
= 0; i
<ret
->n_vars
; i
++) {
603 hres
= ITypeInfo_GetVarDesc(pTypeInfo
, i
, &vardesc
);
605 WARN("GetVarDesc failed\n");
608 ret
->fields
[i
].vt
= vardesc
->elemdescVar
.tdesc
.vt
;
609 ret
->fields
[i
].varkind
= vardesc
->varkind
;
610 ret
->fields
[i
].offset
= vardesc
->u
.oInst
;
611 hres
= ITypeInfo_GetDocumentation(pTypeInfo
, vardesc
->memid
, &ret
->fields
[i
].name
,
614 WARN("GetDocumentation failed: %08x\n", hres
);
615 ITypeInfo_ReleaseVarDesc(pTypeInfo
, vardesc
);
618 *ppRecInfo
= (IRecordInfo
*)ret
;