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;
}
}
/****************************************************************************
- * 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;
}
/****************************************************************************
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;
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;
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;
}
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;
}
*width = 0;
*alignment = 1;
break;
+ }
default:
FIXME("Unrecognized type %d.\n", tdesc->vt);
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
*
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;
}
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);
{
ICreateTypeInfo2Impl *This = (ICreateTypeInfo2Impl *)iface;
+ HRESULT status = S_OK;
CyclicList *insert;
INT *typedata;
int var_datawidth;
/* 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;
&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;
}
/******************************************************************************
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;