static HRESULT WINAPI IRecordInfoImpl_RecordInit(IRecordInfo *iface, PVOID pvNew) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); TRACE("(%p)->(%p)\n", This, pvNew); if(!pvNew) return E_INVALIDARG; memset(pvNew, 0, This->size); return S_OK; }
static HRESULT WINAPI IRecordInfoImpl_GetSize(IRecordInfo *iface, ULONG *pcbSize) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); TRACE("(%p)->(%p)\n", This, pcbSize); if(!pcbSize) return E_INVALIDARG; *pcbSize = This->size; return S_OK; }
static HRESULT WINAPI IRecordInfoImpl_GetName(IRecordInfo *iface, BSTR *pbstrName) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); TRACE("(%p)->(%p)\n", This, pbstrName); if(!pbstrName) return E_INVALIDARG; *pbstrName = SysAllocString(This->name); return S_OK; }
static HRESULT WINAPI IRecordInfoImpl_GetGuid(IRecordInfo *iface, GUID *pguid) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); TRACE("(%p)->(%p)\n", This, pguid); if(!pguid) return E_INVALIDARG; *pguid = This->guid; return S_OK; }
static PVOID WINAPI IRecordInfoImpl_RecordCreate(IRecordInfo *iface) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); void *record; TRACE("(%p)\n", This); record = HeapAlloc(GetProcessHeap(), 0, This->size); IRecordInfo_RecordInit(iface, record); TRACE("created record at %p\n", record); return record; }
static HRESULT WINAPI IRecordInfoImpl_RecordCreateCopy(IRecordInfo *iface, PVOID pvSource, PVOID *ppvDest) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); TRACE("(%p)->(%p %p)\n", This, pvSource, ppvDest); if(!pvSource || !ppvDest) return E_INVALIDARG; *ppvDest = IRecordInfo_RecordCreate(iface); return IRecordInfo_RecordCopy(iface, pvSource, *ppvDest); }
static HRESULT WINAPI IRecordInfoImpl_RecordCopy(IRecordInfo *iface, PVOID pvExisting, PVOID pvNew) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); TRACE("(%p)->(%p %p)\n", This, pvExisting, pvNew); if(!pvExisting || !pvNew) return E_INVALIDARG; memcpy(pvExisting, pvNew, This->size); return S_OK; }
static HRESULT WINAPI IRecordInfoImpl_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); TRACE("(%p)->(%p)\n", This, ppTypeInfo); if(!ppTypeInfo) return E_INVALIDARG; ITypeInfo_AddRef(This->pTypeInfo); *ppTypeInfo = This->pTypeInfo; return S_OK; }
static BOOL WINAPI IRecordInfoImpl_IsMatchingType(IRecordInfo *iface, IRecordInfo *info2) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); GUID guid2; TRACE( "(%p)->(%p)\n", This, info2 ); IRecordInfo_GetGuid( info2, &guid2 ); if (IsEqualGUID( &This->guid, &guid2 )) return TRUE; FIXME( "records have different guids (%s %s) but could still match\n", debugstr_guid( &This->guid ), debugstr_guid( &guid2 ) ); return FALSE; }
static HRESULT WINAPI IRecordInfoImpl_RecordDestroy(IRecordInfo *iface, PVOID pvRecord) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); HRESULT hres; TRACE("(%p)->(%p)\n", This, pvRecord); hres = IRecordInfo_RecordClear(iface, pvRecord); if(FAILED(hres)) return hres; if(!HeapFree(GetProcessHeap(), 0, pvRecord)) return E_INVALIDARG; return S_OK; }
static ULONG WINAPI IRecordInfoImpl_Release(IRecordInfo *iface) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) -> %d\n", This, ref); if(!ref) { int i; for(i=0; i<This->n_vars; i++) SysFreeString(This->fields[i].name); HeapFree(GetProcessHeap(), 0, This->name); HeapFree(GetProcessHeap(), 0, This->fields); ITypeInfo_Release(This->pTypeInfo); HeapFree(GetProcessHeap(), 0, This); } return ref; }
static HRESULT WINAPI IRecordInfoImpl_PutFieldNoCopy(IRecordInfo *iface, ULONG wFlags, PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); int i; FIXME("(%p)->(%08x %p %s %p) stub\n", This, wFlags, pvData, debugstr_w(szFieldName), pvarField); if(!pvData || !szFieldName || !pvarField || (wFlags != INVOKE_PROPERTYPUTREF && wFlags != INVOKE_PROPERTYPUT)) return E_INVALIDARG; for(i=0; i<This->n_vars; i++) if(!strcmpW(This->fields[i].name, szFieldName)) break; if(i == This->n_vars) return TYPE_E_FIELDNOTFOUND; return E_NOTIMPL; }
static HRESULT WINAPI IRecordInfoImpl_GetField(IRecordInfo *iface, PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); int i; TRACE("(%p)->(%p %s %p)\n", This, pvData, debugstr_w(szFieldName), pvarField); if(!pvData || !szFieldName || !pvarField) return E_INVALIDARG; for(i=0; i<This->n_vars; i++) if(!strcmpW(This->fields[i].name, szFieldName)) break; if(i == This->n_vars) return TYPE_E_FIELDNOTFOUND; VariantClear(pvarField); return copy_to_variant(((PBYTE)pvData)+This->fields[i].offset, pvarField, This->fields[i].vt); }
static HRESULT WINAPI IRecordInfoImpl_GetFieldNames(IRecordInfo *iface, ULONG *pcNames, BSTR *rgBstrNames) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); ULONG n = This->n_vars, i; TRACE("(%p)->(%p %p)\n", This, pcNames, rgBstrNames); if(!pcNames) return E_INVALIDARG; if(*pcNames < n) n = *pcNames; if(rgBstrNames) { for(i=0; i<n; i++) rgBstrNames[i] = SysAllocString(This->fields[i].name); } *pcNames = n; return S_OK; }
static HRESULT WINAPI IRecordInfoImpl_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); int i; TRACE("(%p)->(%p %s %p %p)\n", This, pvData, debugstr_w(szFieldName), pvarField, ppvDataCArray); if(!pvData || !szFieldName || !pvarField) return E_INVALIDARG; for(i=0; i<This->n_vars; i++) if(!strcmpW(This->fields[i].name, szFieldName)) break; if(i == This->n_vars) return TYPE_E_FIELDNOTFOUND; VariantClear(pvarField); V_VT(pvarField) = VT_BYREF|This->fields[i].vt; V_BYREF(pvarField) = ((PBYTE)pvData)+This->fields[i].offset; *ppvDataCArray = NULL; return S_OK; }
static HRESULT WINAPI IRecordInfoImpl_RecordClear(IRecordInfo *iface, PVOID pvExisting) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); int i; PVOID var; TRACE("(%p)->(%p)\n", This, pvExisting); if(!pvExisting) return E_INVALIDARG; for(i=0; i<This->n_vars; i++) { if(This->fields[i].varkind != VAR_PERINSTANCE) { ERR("varkind != VAR_PERINSTANCE\n"); continue; } var = ((PBYTE)pvExisting)+This->fields[i].offset; switch(This->fields[i].vt) { case VT_BSTR: SysFreeString(*(BSTR*)var); *(BSTR*)var = NULL; break; case VT_I2: case VT_I4: case VT_R4: case VT_R8: case VT_CY: case VT_DATE: case VT_ERROR: case VT_BOOL: case VT_DECIMAL: case VT_I1: case VT_UI1: case VT_UI2: case VT_UI4: case VT_I8: case VT_UI8: case VT_INT: case VT_UINT: case VT_HRESULT: break; case VT_INT_PTR: case VT_UINT_PTR: *(void**)var = NULL; break; case VT_SAFEARRAY: SafeArrayDestroy(var); break; case VT_UNKNOWN: case VT_DISPATCH: { IUnknown *unk = *(IUnknown**)var; if (unk) IUnknown_Release(unk); *(void**)var = NULL; break; } default: FIXME("Not supported vt = %d\n", This->fields[i].vt); break; } } return S_OK; }
static HRESULT WINAPI IRecordInfoImpl_RecordCopy(IRecordInfo *iface, PVOID pvExisting, PVOID pvNew) { IRecordInfoImpl *This = impl_from_IRecordInfo(iface); HRESULT hr = S_OK; int i; TRACE("(%p)->(%p %p)\n", This, pvExisting, pvNew); if(!pvExisting || !pvNew) return E_INVALIDARG; /* release already stored data */ IRecordInfo_RecordClear(iface, pvNew); for (i = 0; i < This->n_vars; i++) { void *src, *dest; if (This->fields[i].varkind != VAR_PERINSTANCE) { ERR("varkind != VAR_PERINSTANCE\n"); continue; } src = ((BYTE*)pvExisting) + This->fields[i].offset; dest = ((BYTE*)pvNew) + This->fields[i].offset; switch (This->fields[i].vt) { case VT_BSTR: { BSTR src_str = *(BSTR*)src; if (src_str) { BSTR str = SysAllocString(*(BSTR*)src); if (!str) hr = E_OUTOFMEMORY; *(BSTR*)dest = str; } else *(BSTR*)dest = NULL; break; } case VT_UNKNOWN: case VT_DISPATCH: { IUnknown *unk = *(IUnknown**)src; *(IUnknown**)dest = unk; if (unk) IUnknown_AddRef(unk); break; } case VT_SAFEARRAY: hr = SafeArrayCopy(src, dest); break; default: { /* copy directly for types that don't need deep copy */ int len = get_type_size(NULL, This->fields[i].vt); memcpy(dest, src, len); break; } } if (FAILED(hr)) break; } if (FAILED(hr)) IRecordInfo_RecordClear(iface, pvNew); return hr; }