More implementation of IRecordInfo

Jacek Caban jack at itma.pwr.wroc.pl
Tue Mar 8 13:45:01 CST 2005


This time with patch :)

This patch makes IRecordInfo almost complete.
If anyone knows any application using it I could test on,
please let me know.

Changelog:
    More implementation of IRecordInfo

-------------- next part --------------
Index: dlls/oleaut32/recinfo.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/recinfo.c,v
retrieving revision 1.1
diff -u -p -r1.1 recinfo.c
--- dlls/oleaut32/recinfo.c	7 Mar 2005 19:22:48 -0000	1.1
+++ dlls/oleaut32/recinfo.c	8 Mar 2005 19:02:02 -0000
@@ -28,23 +28,118 @@
 #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 {
     IRecordInfoVtbl *lpVtbl;
     ULONG ref;
 
     GUID guid;
-    TYPEATTR typeattr;
     UINT lib_index;
+    WORD n_vars;
+    ULONG size;
     BSTR name;
-    BSTR *field_names;
+    fieldstr *fields;
     ITypeInfo *pTypeInfo;
 } IRecordInfoImpl;
 
-static HRESULT WINAPI IRecordInfoImpl_QueryInterface(IRecordInfo *iface, REFIID riid, void **ppvObject)
+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);
 
@@ -72,11 +167,13 @@ static ULONG WINAPI IRecordInfoImpl_Rele
     ULONG ref = InterlockedDecrement(&This->ref);
 
     TRACE("(%p) -> %ld\n", This, ref);
+
     if(!ref) {
         int i;
-        for(i=0; i<This->typeattr.cVars; i++)
-            HeapFree(GetProcessHeap(), 0, This->field_names[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);
     }
@@ -86,27 +183,86 @@ static ULONG WINAPI IRecordInfoImpl_Rele
 static HRESULT WINAPI IRecordInfoImpl_RecordInit(IRecordInfo *iface, PVOID pvNew)
 {
     IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
-    FIXME("(%p)->(%p) stub\n", This, pvNew);
-    return E_NOTIMPL;
+    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;
-    FIXME("(%p)->(%p) stub\n", This, pvExisting);
-    return E_NOTIMPL;
+    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)
+static HRESULT WINAPI IRecordInfoImpl_RecordCopy(IRecordInfo *iface, PVOID pvExisting,
+                                                PVOID pvNew)
 {
     IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
-    FIXME("(%p)->(%p %p) stub\n", This, pvExisting, pvNew);
-    return E_NOTIMPL;
+
+    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)
@@ -121,6 +277,7 @@ static HRESULT WINAPI IRecordInfoImpl_Ge
     IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
 
     TRACE("(%p)->(%p)\n", This, pbstrName);
+
     if(!pbstrName)
         return E_INVALIDARG;
 
@@ -137,7 +294,7 @@ static HRESULT WINAPI IRecordInfoImpl_Ge
     if(!pcbSize)
         return E_INVALIDARG;
     
-    *pcbSize = This->typeattr.cbSizeInstance;
+    *pcbSize = This->size;
     return S_OK;
 }
 
@@ -160,39 +317,104 @@ static HRESULT WINAPI IRecordInfoImpl_Ge
                                                 LPCOLESTR szFieldName, VARIANT *pvarField)
 {
     IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
-    FIXME("(%p)->(%p %s %p) stub\n", This, pvData, debugstr_w(szFieldName), pvarField);
-    return E_NOTIMPL;
+    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_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData, LPCOLESTR szFieldName,
-                                                    VARIANT *pvarField, PVOID *ppvDataCArray)
+static HRESULT WINAPI IRecordInfoImpl_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData,
+                            LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray)
 {
     IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
-    FIXME("(%p)->(%p %s %p %p) stub\n", This, pvData, debugstr_w(szFieldName), pvarField, ppvDataCArray);
-    return E_NOTIMPL;
+    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_PutField(IRecordInfo *iface, ULONG wFlags, PVOID pvData, LPCOLESTR szFieldName,
-                                               VARIANT *pvarField)
+static HRESULT WINAPI IRecordInfoImpl_PutField(IRecordInfo *iface, ULONG wFlags, PVOID pvData,
+                                            LPCOLESTR szFieldName, VARIANT *pvarField)
 {
     IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
-    FIXME("(%p)->(%08lx %p %s %p) stub\n", This, wFlags, pvData, debugstr_w(szFieldName), pvarField);
-    return E_NOTIMPL;
+    int i;
+
+    TRACE("(%p)->(%08lx %p %s %p)\n", This, wFlags, pvData, debugstr_w(szFieldName),
+                                    pvarField);
+
+    if(!pvData || !szFieldName || !pvarField
+            || (wFlags != INVOKE_PROPERTYPUTREF && wFlags != INVOKE_PROPERTYPUT))
+        return E_INVALIDARG;
+
+    if(wFlags == INVOKE_PROPERTYPUTREF) {
+        FIXME("wFlag == INVOKE_PROPERTYPUTREF not supported\n");
+        return E_NOTIMPL;
+    }
+
+    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 copy_from_variant(pvarField, ((PBYTE)pvData)+This->fields[i].offset,
+            This->fields[i].vt);
 }
 
-static HRESULT WINAPI IRecordInfoImpl_PutFieldNoCopy(IRecordInfo *iface, ULONG wFlags, PVOID pvData, LPCOLESTR szFieldName,
-                                                     VARIANT *pvarField)
+static HRESULT WINAPI IRecordInfoImpl_PutFieldNoCopy(IRecordInfo *iface, ULONG wFlags,
+                PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
 {
     IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
+    int i;
+
     FIXME("(%p)->(%08lx %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_GetFieldNames(IRecordInfo *iface, ULONG *pcNames, BSTR *rgBstrNames)
+static HRESULT WINAPI IRecordInfoImpl_GetFieldNames(IRecordInfo *iface, ULONG *pcNames,
+                                                BSTR *rgBstrNames)
 {
     IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
-    ULONG n = This->typeattr.cVars;
+    ULONG n = This->n_vars;
     int i;
+
     TRACE("(%p)->(%p %p)\n", This, pcNames, rgBstrNames);
 
     if(!pcNames)
@@ -203,7 +425,7 @@ static HRESULT WINAPI IRecordInfoImpl_Ge
 
     if(rgBstrNames) {
         for(i=0; i<n; i++)
-            rgBstrNames[i] = SysAllocString(This->field_names[i]);
+            rgBstrNames[i] = SysAllocString(This->fields[i].name);
     }
     
     *pcNames = n;
@@ -213,29 +435,45 @@ static HRESULT WINAPI IRecordInfoImpl_Ge
 static BOOL WINAPI IRecordInfoImpl_IsMatchingType(IRecordInfo *iface, IRecordInfo *pRecordInfo)
 {
     IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
+
     FIXME("(%p)->(%p) stub\n", This, pRecordInfo);
+
     return FALSE;
 }
 
 static PVOID WINAPI IRecordInfoImpl_RecordCreate(IRecordInfo *iface)
 {
     IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
-    FIXME("(%p) stub\n", This);
-    return NULL;
+
+    TRACE("(%p)\n", This);
+
+    return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->size);
 }
 
-static HRESULT WINAPI IRecordInfoImpl_RecordCreateCopy(IRecordInfo *iface, PVOID pvSource, PVOID *ppvDest)
+static HRESULT WINAPI IRecordInfoImpl_RecordCreateCopy(IRecordInfo *iface, PVOID pvSource,
+                                                    PVOID *ppvDest)
 {
     IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
-    FIXME("(%p)->(%p %p) stub\n", This, pvSource, ppvDest);
-    return E_NOTIMPL;
+
+    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_RecordDestroy(IRecordInfo *iface, PVOID pvRecord)
 {
     IRecordInfoImpl *This = (IRecordInfoImpl*)iface;
-    FIXME("(%p)->(%p) stub\n", This, pvRecord);
-    return E_NOTIMPL;
+
+    TRACE("(%p)->(%p)\n", This, pvRecord);
+
+    if(!HeapFree(GetProcessHeap(), 0, pvRecord))
+        return E_INVALIDARG;
+
+    return S_OK;
 }
 
 static IRecordInfoVtbl IRecordInfoImplVtbl = {
@@ -343,10 +581,12 @@ HRESULT WINAPI GetRecordInfoFromTypeInfo
     ret->lpVtbl = &IRecordInfoImplVtbl;
     ret->ref = 1;
     ret->pTypeInfo = pTypeInfo;
-    memcpy(&ret->guid, &guid, sizeof(GUID));
-    memcpy(&ret->typeattr, typeattr, sizeof(TYPEATTR));
+    ret->n_vars = typeattr->cVars;
+    ret->size = typeattr->cbSizeInstance;
     ITypeInfo_ReleaseTypeAttr(pTypeInfo, typeattr);
 
+    memcpy(&ret->guid, &guid, sizeof(GUID));
+
     /* NOTE: Windows implementation calls ITypeInfo::GetCantainingTypeLib and
      *       ITypeLib::GetLibAttr, but we currently don't need this.
      */
@@ -357,15 +597,19 @@ HRESULT WINAPI GetRecordInfoFromTypeInfo
         ret->name = NULL;
     }
 
-    ret->field_names = HeapAlloc(GetProcessHeap(), 0, ret->typeattr.cVars*sizeof(BSTR));
-    for(i = 0; i<ret->typeattr.cVars; i++) {
+    ret->fields = HeapAlloc(GetProcessHeap(), 0, ret->n_vars*sizeof(VARDESC));
+    for(i = 0; i<ret->n_vars; i++) {
         VARDESC *vardesc;
         hres = ITypeInfo_GetVarDesc(pTypeInfo, i, &vardesc);
         if(FAILED(hres)) {
             WARN("GetVarDesc failed\n");
             continue;
         }
-        hres = ITypeInfo_GetDocumentation(pTypeInfo, vardesc->memid, ret->field_names+i, NULL, NULL, NULL);
+        ret->fields[i].vt = vardesc->elemdescVar.tdesc.vt;
+        ret->fields[i].varkind = vardesc->varkind;
+        ret->fields[i].offset = vardesc->u.oInst;
+        hres = ITypeInfo_GetDocumentation(pTypeInfo, vardesc->memid, &ret->fields[i].name,
+                NULL, NULL, NULL);
         if(FAILED(hres))
             WARN("GetDocumentation failed: %08lx\n", hres);
         ITypeInfo_ReleaseVarDesc(pTypeInfo, vardesc);


More information about the wine-patches mailing list