⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 recinfo.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * 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 + -