📄 recinfo.c
字号:
/*
* Copyright 2005 Jacek Caban
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "objbase.h"
#include "oaidl.h"
#include "oleauto.h"
#include "wine/unicode.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
typedef struct {
enum VARENUM vt;
VARKIND varkind;
ULONG offset;
BSTR name;
} fieldstr;
typedef struct {
const IRecordInfoVtbl *lpVtbl;
LONG ref;
GUID guid;
UINT lib_index;
WORD n_vars;
ULONG size;
BSTR name;
fieldstr *fields;
ITypeInfo *pTypeInfo;
} IRecordInfoImpl;
static HRESULT copy_to_variant(void *src, VARIANT *pvar, enum VARENUM vt)
{
TRACE("%p %p %d\n", src, pvar, vt);
#define CASE_COPY(x) \
case VT_ ## x: \
V_ ## x(pvar) = *(typeof(V_ ## x(pvar))*)src; \
break
switch(vt) {
CASE_COPY(I2);
CASE_COPY(I4);
CASE_COPY(R4);
CASE_COPY(R8);
CASE_COPY(CY);
CASE_COPY(DATE);
CASE_COPY(BSTR);
CASE_COPY(ERROR);
CASE_COPY(BOOL);
CASE_COPY(DECIMAL);
CASE_COPY(I1);
CASE_COPY(UI1);
CASE_COPY(UI2);
CASE_COPY(UI4);
CASE_COPY(I8);
CASE_COPY(UI8);
CASE_COPY(INT);
CASE_COPY(UINT);
CASE_COPY(INT_PTR);
CASE_COPY(UINT_PTR);
default:
FIXME("Not supported type: %d\n", vt);
return E_NOTIMPL;
};
#undef CASE_COPY
V_VT(pvar) = vt;
return S_OK;
}
static HRESULT copy_from_variant(VARIANT *src, void *dest, enum VARENUM vt)
{
VARIANT var;
HRESULT hres;
TRACE("(%p(%d) %p %d)\n", src, V_VT(src), dest, vt);
hres = VariantChangeType(&var, src, 0, vt);
if(FAILED(hres))
return hres;
#define CASE_COPY(x) \
case VT_ ## x: \
*(typeof(V_ ## x(&var))*)dest = V_ ## x(&var); \
break
switch(vt) {
CASE_COPY(I2);
CASE_COPY(I4);
CASE_COPY(R4);
CASE_COPY(R8);
CASE_COPY(CY);
CASE_COPY(DATE);
CASE_COPY(BSTR);
CASE_COPY(ERROR);
CASE_COPY(BOOL);
CASE_COPY(DECIMAL);
CASE_COPY(I1);
CASE_COPY(UI1);
CASE_COPY(UI2);
CASE_COPY(UI4);
CASE_COPY(I8);
CASE_COPY(UI8);
CASE_COPY(INT);
CASE_COPY(UINT);
CASE_COPY(INT_PTR);
CASE_COPY(UINT_PTR);
default:
FIXME("Not supported type: %d\n", V_VT(&var));
return E_NOTIMPL;
};
#undef CASE_COPY
return S_OK;
}
static HRESULT WINAPI IRecordInfoImpl_QueryInterface(IRecordInfo *iface, REFIID riid,
void **ppvObject)
{
TRACE("(%p)->(%s %p)\n", iface, debugstr_guid(riid), ppvObject);
if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IRecordInfo, riid)) {
*ppvObject = iface;
IRecordInfo_AddRef(iface);
return S_OK;
}
FIXME("Not supported interface: %s\n", debugstr_guid(riid));
return E_NOINTERFACE;
}
static ULONG WINAPI IRecordInfoImpl_AddRef(IRecordInfo *iface)
{
IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) -> %d\n", This, ref);
return ref;
}
static ULONG WINAPI IRecordInfoImpl_Release(IRecordInfo *iface)
{
IRecordInfoImpl *This = (IRecordInfoImpl*)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_RecordInit(IRecordInfo *iface, PVOID pvNew)
{
IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
TRACE("(%p)->(%p)\n", This, pvNew);
if(!pvNew)
return E_INVALIDARG;
memset(pvNew, 0, This->size);
return S_OK;
}
static HRESULT WINAPI IRecordInfoImpl_RecordClear(IRecordInfo *iface, PVOID pvExisting)
{
IRecordInfoImpl *This = (IRecordInfoImpl*)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:
/* NOTE: Windows implementatino reads DWORD (len) before string,
* but it seems to do nothing with this */
*(BSTR*)var = NULL;
break;
case VT_I2:
case VT_I4:
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:
break;
case VT_INT_PTR:
case VT_UINT_PTR:
*(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 = (IRecordInfoImpl*)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_GetGuid(IRecordInfo *iface, GUID *pguid)
{
IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
TRACE("(%p)->(%p)\n", This, pguid);
if(!pguid)
return E_INVALIDARG;
memcpy(pguid, &This->guid, sizeof(GUID));
return S_OK;
}
static HRESULT WINAPI IRecordInfoImpl_GetName(IRecordInfo *iface, BSTR *pbstrName)
{
IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
TRACE("(%p)->(%p)\n", This, pbstrName);
if(!pbstrName)
return E_INVALIDARG;
*pbstrName = SysAllocString(This->name);
return S_OK;
}
static HRESULT WINAPI IRecordInfoImpl_GetSize(IRecordInfo *iface, ULONG *pcbSize)
{
IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
TRACE("(%p)->(%p)\n", This, pcbSize);
if(!pcbSize)
return E_INVALIDARG;
*pcbSize = This->size;
return S_OK;
}
static HRESULT WINAPI IRecordInfoImpl_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo)
{
IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
TRACE("(%p)->(%p)\n", This, ppTypeInfo);
if(!ppTypeInfo)
return E_INVALIDARG;
ITypeInfo_AddRef(This->pTypeInfo);
*ppTypeInfo = This->pTypeInfo;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -