[WIN32K]
[reactos.git] / dll / win32 / oleaut32 / typelib2.c
index aa14d22..92d4ab0 100644 (file)
@@ -317,7 +317,7 @@ static int ctl2_find_guid(
     while (offset != -1) {
        guidentry = (MSFT_GuidEntry *)&This->typelib_segment_data[MSFT_SEG_GUID][offset];
 
-       if (!memcmp(guidentry, guid, sizeof(GUID))) return offset;
+        if (IsEqualGUID(guidentry, guid)) return offset;
 
        offset = guidentry->next_hash;
     }
@@ -797,71 +797,128 @@ static int ctl2_alloc_importfile(
 }
 
 /****************************************************************************
- *     ctl2_alloc_custdata
+ *      ctl2_encode_variant
  *
- *  Allocates and initializes a "custom data" value in a type library.
+ *  Encodes a variant, inline if possible or in custom data segment
  *
  * RETURNS
  *
- *  Success: The offset of the new custdata.
- *  Failure:
- *
- *    -1: Out of memory.
- *    -2: Unable to encode VARIANT data (typically a bug).
+ *  Success: S_OK
+ *  Failure: Error code from winerror.h
  */
-static int ctl2_alloc_custdata(
-       ICreateTypeLib2Impl *This, /* [I] The type library in which to encode the value. */
-       VARIANT *pVarVal)          /* [I] The value to encode. */
+static HRESULT ctl2_encode_variant(
+        ICreateTypeLib2Impl *This, /* [I] The typelib to allocate data in */
+        int *encoded_value,        /* [O] The encoded default value or data offset */
+        VARIANT *value,            /* [I] Default value to be encoded */
+        VARTYPE arg_type)          /* [I] Argument type */
 {
-    int offset;
+    VARIANT v;
+    HRESULT hres;
+    int mask = 0;
+
+    TRACE("%p %d %d\n", This, V_VT(value), arg_type);
+
+    if(arg_type == VT_INT)
+        arg_type = VT_I4;
+    if(arg_type == VT_UINT)
+        arg_type = VT_UI4;
 
-    TRACE("(%p,%p(%d))\n",This,pVarVal,V_VT(pVarVal));
+    v = *value;
+    if(V_VT(value) != arg_type) {
+        hres = VariantChangeType(&v, value, 0, arg_type);
+        if(FAILED(hres))
+            return hres;
+    }
 
-    switch (V_VT(pVarVal)) {
+    /* Check if default value can be stored in encoded_value */
+    switch(arg_type) {
+    case VT_I4:
     case VT_UI4:
+        mask = 0x3ffffff;
+        if(V_UI4(&v)>0x3ffffff)
+            break;
+    case VT_I1:
+    case VT_UI1:
+    case VT_BOOL:
+         if(!mask)
+             mask = 0xff;
+    case VT_I2:
+    case VT_UI2:
+        if(!mask)
+            mask = 0xffff;
+        *encoded_value = (V_UI4(&v)&mask) | ((0x80+0x4*arg_type)<<24);
+        return S_OK;
+    }
+
+    switch(arg_type) {
     case VT_I4:
     case VT_R4:
+    case VT_UI4:
     case VT_INT:
     case VT_UINT:
     case VT_HRESULT:
-       offset = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, 8, 0);
-       if (offset == -1) return offset;
+    case VT_PTR: {
+        /* Construct the data to be allocated */
+        int data[2];
+        data[0] = arg_type + (V_UI4(&v)<<16);
+        data[1] = (V_UI4(&v)>>16) + 0x57570000;
 
-       *((unsigned short *)&This->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = V_VT(pVarVal);
-       *((DWORD *)&This->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2]) = V_UI4(pVarVal);
-       break;
+        /* Check if the data was already allocated */
+        /* Currently the structures doesn't allow to do it in a nice way */
+        for(*encoded_value=0; *encoded_value<=This->typelib_segdir[MSFT_SEG_CUSTDATA].length-8; *encoded_value+=4)
+            if(!memcmp(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, 8))
+                return S_OK;
 
+        /* Allocate the data */
+        *encoded_value = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, 8, 0);
+        if(*encoded_value == -1)
+            return E_OUTOFMEMORY;
+
+        memcpy(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, 8);
+        return S_OK;
+    }
     case VT_BSTR: {
-           /* Construct the data */
-           UINT cp = CP_ACP;
-           int stringlen = SysStringLen(V_BSTR(pVarVal));
-           int len = 0;
-           if (stringlen > 0) {
-               GetLocaleInfoA(This->typelib_header.lcid, LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
-                       (LPSTR)&cp, sizeof(cp));
-               len = WideCharToMultiByte(cp, 0, V_BSTR(pVarVal), SysStringLen(V_BSTR(pVarVal)), NULL, 0, NULL, NULL);
-               if (!len)
-                   return -1;
-           }
+        /* Construct the data */
+        int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
+        char *data = HeapAlloc(GetProcessHeap(), 0, len);
 
-           offset = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, (6 + len + 3) & ~0x3, 0);
-           if (offset == -1) return offset;
+        if(!data)
+            return E_OUTOFMEMORY;
 
-           *((unsigned short *)&This->typelib_segment_data[MSFT_SEG_CUSTDATA][offset]) = V_VT(pVarVal);
-           *((DWORD *)&This->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+2]) = (DWORD)len;
-           if (stringlen > 0) {
-               WideCharToMultiByte(cp, 0, V_BSTR(pVarVal), SysStringLen(V_BSTR(pVarVal)),
-                       &This->typelib_segment_data[MSFT_SEG_CUSTDATA][offset+6], len, NULL, NULL);
-           }
-       }
-       break;
+        *((unsigned short*)data) = arg_type;
+        *((unsigned*)(data+2)) = SysStringLen(V_BSTR(&v));
+        for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
+            if(V_BSTR(&v)[i] <= 0x7f)
+                data[i+6] = V_BSTR(&v)[i];
+            else
+                data[i+6] = '?';
+        }
+        WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
+        for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
+            data[i] = 0x57;
+
+        /* Check if the data was already allocated */
+        for(*encoded_value=0; *encoded_value<=This->typelib_segdir[MSFT_SEG_CUSTDATA].length-len; *encoded_value+=4)
+            if(!memcmp(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, len)) {
+                HeapFree(GetProcessHeap(), 0, data);
+                return S_OK;
+            }
 
+        /* Allocate the data */
+        *encoded_value = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, len, 0);
+        if(*encoded_value == -1) {
+            HeapFree(GetProcessHeap(), 0, data);
+            return E_OUTOFMEMORY;
+        }
+
+        memcpy(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, len);
+        HeapFree(GetProcessHeap(), 0, data);
+        return S_OK;
+    }
     default:
-       FIXME("Unknown variable encoding vt %d.\n", V_VT(pVarVal));
-       return -2;
+        FIXME("Argument type not yet handled\n");
+        return E_NOTIMPL;
     }
-
-    return offset;
 }
 
 /****************************************************************************
@@ -881,11 +938,27 @@ static HRESULT ctl2_set_custdata(
        int *offset)               /* [I/O] The list of custom data to prepend to. */
 {
     MSFT_GuidEntry guidentry;
+    HRESULT status;
     int dataoffset;
     int guidoffset;
     int custoffset;
     int *custdata;
 
+    switch(V_VT(pVarVal))
+    {
+    case VT_I4:
+    case VT_R4:
+    case VT_UI4:
+    case VT_INT:
+    case VT_UINT:
+    case VT_HRESULT:
+    case VT_BSTR:
+       /* empty */
+       break;
+    default:
+       return DISP_E_BADVARTYPE;
+    }
+
     guidentry.guid = *guid;
 
     guidentry.hreftype = -1;
@@ -893,9 +966,10 @@ static HRESULT ctl2_set_custdata(
 
     guidoffset = ctl2_alloc_guid(This, &guidentry);
     if (guidoffset == -1) return E_OUTOFMEMORY;
-    dataoffset = ctl2_alloc_custdata(This, pVarVal);
-    if (dataoffset == -1) return E_OUTOFMEMORY;
-    if (dataoffset == -2) return DISP_E_BADVARTYPE;
+
+    status = ctl2_encode_variant(This, &dataoffset, pVarVal, V_VT(pVarVal));
+    if (status)
+       return status;
 
     custoffset = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATAGUID, 12, 0);
     if (custoffset == -1) return E_OUTOFMEMORY;
@@ -1006,65 +1080,49 @@ static int ctl2_encode_typedesc(
        break;
 
     case VT_PTR:
-       /* FIXME: Make with the error checking. */
-       FIXME("PTR vartype, may not work correctly.\n");
-
-       ctl2_encode_typedesc(This, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size);
-
-       for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
-           typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
-           if (((typedata[0] & 0xffff) == VT_PTR) && (typedata[1] == target_type)) break;
-       }
-
-       if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
-           int mix_field;
-           
-           if (target_type & 0x80000000) {
-               mix_field = ((target_type >> 16) & 0x3fff) | VT_BYREF;
-           } else {
-               typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
-               mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
-           }
-
-           typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
-           typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
-
-           typedata[0] = (mix_field << 16) | VT_PTR;
-           typedata[1] = target_type;
-       }
-
-       *encoded_tdesc = typeoffset;
-
-       *width = 4;
-       *alignment = 4;
-       *decoded_size = sizeof(TYPEDESC) + child_size;
-       break;
-
     case VT_SAFEARRAY:
        /* FIXME: Make with the error checking. */
-       FIXME("SAFEARRAY vartype, may not work correctly.\n");
+       FIXME("PTR or SAFEARRAY vartype, may not work correctly.\n");
 
        ctl2_encode_typedesc(This, tdesc->u.lptdesc, &target_type, NULL, NULL, &child_size);
 
        for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
            typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
-           if (((typedata[0] & 0xffff) == VT_SAFEARRAY) && (typedata[1] == target_type)) break;
+           if (((typedata[0] & 0xffff) == tdesc->vt) && (typedata[1] == target_type)) break;
        }
 
        if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
            int mix_field;
            
            if (target_type & 0x80000000) {
-               mix_field = ((target_type >> 16) & VT_TYPEMASK) | VT_ARRAY;
+               mix_field = (target_type >> 16) & VT_TYPEMASK;
            } else {
                typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][target_type];
-               mix_field = ((typedata[0] >> 16) == 0x7fff)? 0x7fff: 0x7ffe;
+               switch((typedata[0]>>16) & ~VT_ARRAY)
+               {
+                   case VT_UI1:
+                   case VT_I1:
+                   case VT_UI2:
+                   case VT_I2:
+                   case VT_I4:
+                   case VT_UI4:
+                       mix_field = typedata[0]>>16;
+                       break;
+                   default:
+                       mix_field = 0x7fff;
+                       break;
+               }
            }
 
+           if (tdesc->vt == VT_PTR)
+               mix_field |= VT_BYREF;
+           else if (tdesc->vt == VT_SAFEARRAY)
+               mix_field |= VT_ARRAY;
+
            typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
            typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
 
-           typedata[0] = (mix_field << 16) | VT_SAFEARRAY;
+           typedata[0] = (mix_field << 16) | tdesc->vt;
            typedata[1] = target_type;
        }
 
@@ -1108,17 +1166,34 @@ static int ctl2_encode_typedesc(
        break;
       }
     case VT_USERDEFINED:
+      {
+       const MSFT_TypeInfoBase *basetype;
+       INT basevt = 0x7fff;
+
        TRACE("USERDEFINED.\n");
+       if (tdesc->u.hreftype % sizeof(*basetype) == 0 && tdesc->u.hreftype < This->typelib_segdir[MSFT_SEG_TYPEINFO].length)
+       {
+           basetype = (MSFT_TypeInfoBase*)&(This->typelib_segment_data[MSFT_SEG_TYPEINFO][tdesc->u.hreftype]);
+           switch(basetype->typekind & 0xf)
+           {
+               case TKIND_ENUM:
+                   basevt = VT_I4;
+                   break;
+               default:
+                   FIXME("USERDEFINED basetype %d not handled\n", basetype->typekind & 0xf);
+                   break;
+           }
+       }
        for (typeoffset = 0; typeoffset < This->typelib_segdir[MSFT_SEG_TYPEDESC].length; typeoffset += 8) {
            typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
-           if ((typedata[0] == ((0x7fff << 16) | VT_USERDEFINED)) && (typedata[1] == tdesc->u.hreftype)) break;
+           if ((typedata[0] == ((basevt << 16) | VT_USERDEFINED)) && (typedata[1] == tdesc->u.hreftype)) break;
        }
 
        if (typeoffset == This->typelib_segdir[MSFT_SEG_TYPEDESC].length) {
            typeoffset = ctl2_alloc_segment(This, MSFT_SEG_TYPEDESC, 8, 0);
            typedata = (void *)&This->typelib_segment_data[MSFT_SEG_TYPEDESC][typeoffset];
 
-           typedata[0] = (0x7fff << 16) | VT_USERDEFINED;
+           typedata[0] = (basevt << 16) | VT_USERDEFINED;
            typedata[1] = tdesc->u.hreftype;
        }
 
@@ -1126,6 +1201,7 @@ static int ctl2_encode_typedesc(
        *width = 0;
        *alignment = 1;
        break;
+      }
 
     default:
        FIXME("Unrecognized type %d.\n", tdesc->vt);
@@ -1196,131 +1272,6 @@ static HRESULT ctl2_find_typeinfo_from_offset(
     return TYPE_E_ELEMENTNOTFOUND;
 }
 
-/****************************************************************************
- *      ctl2_add_default_value
- *
- *  Adds default value of an argument
- *
- * RETURNS
- *
- *  Success: S_OK
- *  Failure: Error code from winerror.h
- */
-static HRESULT ctl2_add_default_value(
-        ICreateTypeLib2Impl *This, /* [I] The typelib to allocate data in */
-        int *encoded_value,        /* [O] The encoded default value or data offset */
-        VARIANT *value,            /* [I] Default value to be encoded */
-        VARTYPE arg_type)          /* [I] Argument type */
-{
-    VARIANT v;
-    HRESULT hres;
-    int mask = 0;
-
-    TRACE("%p %d %d\n", This, V_VT(value), arg_type);
-
-    if(arg_type == VT_INT)
-        arg_type = VT_I4;
-    if(arg_type == VT_UINT)
-        arg_type = VT_UI4;
-
-    v = *value;
-    if(V_VT(value) != arg_type) {
-        hres = VariantChangeType(&v, value, 0, arg_type);
-        if(FAILED(hres))
-            return hres;
-    }
-
-    /* Check if default value can be stored in encoded_value */
-    switch(arg_type) {
-    case VT_I4:
-    case VT_UI4:
-        mask = 0x3ffffff;
-        if(V_UI4(&v)>0x3ffffff)
-            break;
-    case VT_I1:
-    case VT_UI1:
-    case VT_BOOL:
-         if(!mask)
-             mask = 0xff;
-    case VT_I2:
-    case VT_UI2:
-        if(!mask)
-            mask = 0xffff;
-        *encoded_value = (V_UI4(&v)&mask) | ((0x80+0x4*arg_type)<<24);
-        return S_OK;
-    }
-
-    switch(arg_type) {
-    case VT_I4:
-    case VT_R4:
-    case VT_UI4:
-    case VT_INT:
-    case VT_UINT:
-    case VT_HRESULT:
-    case VT_PTR: {
-        /* Construct the data to be allocated */
-        int data[2];
-        data[0] = arg_type + (V_UI4(&v)<<16);
-        data[1] = (V_UI4(&v)>>16) + 0x57570000;
-
-        /* Check if the data was already allocated */
-        /* Currently the structures doesn't allow to do it in a nice way */
-        for(*encoded_value=0; *encoded_value<=This->typelib_segdir[MSFT_SEG_CUSTDATA].length-8; *encoded_value+=4)
-            if(!memcmp(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, 8))
-                return S_OK;
-
-        /* Allocate the data */
-        *encoded_value = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, 8, 0);
-        if(*encoded_value == -1)
-            return E_OUTOFMEMORY;
-
-        memcpy(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, 8);
-        return S_OK;
-    }
-    case VT_BSTR: {
-        /* Construct the data */
-        int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
-        char *data = HeapAlloc(GetProcessHeap(), 0, len);
-
-        if(!data)
-            return E_OUTOFMEMORY;
-
-        *((unsigned short*)data) = arg_type;
-        *((unsigned*)(data+2)) = SysStringLen(V_BSTR(&v));
-        for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
-            if(V_BSTR(&v)[i] <= 0x7f)
-                data[i+6] = V_BSTR(&v)[i];
-            else
-                data[i+6] = '?';
-        }
-        WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
-        for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
-            data[i] = 0x57;
-
-        /* Check if the data was already allocated */
-        for(*encoded_value=0; *encoded_value<=This->typelib_segdir[MSFT_SEG_CUSTDATA].length-len; *encoded_value+=4)
-            if(!memcmp(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, len)) {
-                HeapFree(GetProcessHeap(), 0, data);
-                return S_OK;
-            }
-
-        /* Allocate the data */
-        *encoded_value = ctl2_alloc_segment(This, MSFT_SEG_CUSTDATA, len, 0);
-        if(*encoded_value == -1) {
-            HeapFree(GetProcessHeap(), 0, data);
-            return E_OUTOFMEMORY;
-        }
-
-        memcpy(&This->typelib_segment_data[MSFT_SEG_CUSTDATA][*encoded_value], data, len);
-        HeapFree(GetProcessHeap(), 0, data);
-        return S_OK;
-    }
-    default:
-        FIXME("Argument type not yet handled\n");
-        return E_NOTIMPL;
-    }
-}
-
 /****************************************************************************
  *      funcrecord_reallochdr
  *
@@ -1744,7 +1695,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(
         impinfo.oGuid = guid_offset;
         *phRefType = ctl2_alloc_importinfo(This->typelib, &impinfo)+1;
 
-        if(!memcmp(&guid.guid, &IID_IDispatch, sizeof(GUID)))
+        if(IsEqualGUID(&guid.guid, &IID_IDispatch))
             This->typelib->typelib_header.dispatchpos = *phRefType;
     }
 
@@ -1855,7 +1806,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(
     if(num_defaults) {
         for (i = 0; i < pFuncDesc->cParams; i++)
             if(pFuncDesc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) {
-                hres = ctl2_add_default_value(This->typelib, typedata+6+i,
+                hres = ctl2_encode_variant(This->typelib, typedata+6+i,
                         &pFuncDesc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue,
                         pFuncDesc->lprgelemdescParam[i].tdesc.vt);
 
@@ -2077,6 +2028,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(
 {
     ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
 
+    HRESULT status = S_OK;
     CyclicList *insert;
     INT *typedata;
     int var_datawidth;
@@ -2130,7 +2082,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(
     /* fill out the basic type information */
     typedata[0] = 0x14 | (index << 16);
     typedata[2] = pVarDesc->wVarFlags;
-    typedata[3] = (sizeof(VARDESC) << 16) | 0;
+    typedata[3] = (sizeof(VARDESC) << 16) | pVarDesc->varkind;
 
     /* update the index data */
     insert->indice = 0x40000000 + index;
@@ -2142,44 +2094,52 @@ static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(
                         &typedata[1], &var_datawidth, &var_alignment,
                         &var_type_size);
 
-    /* pad out starting position to data width */
-    This->datawidth += var_alignment - 1;
-    This->datawidth &= ~(var_alignment - 1);
-    typedata[4] = This->datawidth;
-    
-    /* add the new variable to the total data width */
-    This->datawidth += var_datawidth;
-    if(This->dual)
-        This->dual->datawidth = This->datawidth;
+    if (pVarDesc->varkind != VAR_CONST)
+    {
+       /* pad out starting position to data width */
+       This->datawidth += var_alignment - 1;
+       This->datawidth &= ~(var_alignment - 1);
+       typedata[4] = This->datawidth;
+
+       /* add the new variable to the total data width */
+       This->datawidth += var_datawidth;
+       if(This->dual)
+           This->dual->datawidth = This->datawidth;
+
+       /* add type description size to total required allocation */
+       typedata[3] += var_type_size << 16;
+
+       /* fix type alignment */
+       alignment = (This->typeinfo->typekind >> 11) & 0x1f;
+       if (alignment < var_alignment) {
+           alignment = var_alignment;
+           This->typeinfo->typekind &= ~0xf800;
+           This->typeinfo->typekind |= alignment << 11;
+       }
 
-    /* add type description size to total required allocation */
-    typedata[3] += var_type_size << 16;
+       /* ??? */
+       if (!This->typeinfo->res2) This->typeinfo->res2 = 0x1a;
+       if ((index == 0) || (index == 1) || (index == 2) || (index == 4) || (index == 9)) {
+           This->typeinfo->res2 <<= 1;
+       }
 
-    /* fix type alignment */
-    alignment = (This->typeinfo->typekind >> 11) & 0x1f;
-    if (alignment < var_alignment) {
-       alignment = var_alignment;
-       This->typeinfo->typekind &= ~0xf800;
-       This->typeinfo->typekind |= alignment << 11;
-    }
+       /* ??? */
+       if (This->typeinfo->res3 == -1) This->typeinfo->res3 = 0;
+       This->typeinfo->res3 += 0x2c;
 
-    /* ??? */
-    if (!This->typeinfo->res2) This->typeinfo->res2 = 0x1a;
-    if ((index == 0) || (index == 1) || (index == 2) || (index == 4) || (index == 9)) {
-       This->typeinfo->res2 <<= 1;
+       /* pad data width to alignment */
+       This->typeinfo->size = (This->datawidth + (alignment - 1)) & ~(alignment - 1);
+    } else {
+       VARIANT *value = pVarDesc->DUMMYUNIONNAME.lpvarValue;
+       status = ctl2_encode_variant(This->typelib, typedata+4, value, V_VT(value));
+        /* ??? native sets size 0x34 */
+       typedata[3] += 0x10 << 16;
     }
 
-    /* ??? */
-    if (This->typeinfo->res3 == -1) This->typeinfo->res3 = 0;
-    This->typeinfo->res3 += 0x2c;
-
     /* increment the number of variable elements */
     This->typeinfo->cElement += 0x10000;
 
-    /* pad data width to alignment */
-    This->typeinfo->size = (This->datawidth + (alignment - 1)) & ~(alignment - 1);
-
-    return S_OK;
+    return status;
 }
 
 /******************************************************************************
@@ -2509,7 +2469,7 @@ static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(
                 return hres;
             }
 
-            if(!memcmp(&typeattr->guid, &IID_IDispatch, sizeof(IDispatch)))
+            if(IsEqualGUID(&typeattr->guid, &IID_IDispatch))
                 This->typeinfo->flags |= TYPEFLAG_FDISPATCHABLE;
 
             This->typeinfo->datatype2 += (typeattr->cFuncs<<16) + 1;