case RPC_FC_C_WSTRING: return "FC_C_WSTRING";
case RPC_FC_CSTRING: return "FC_CSTRING";
case RPC_FC_WSTRING: return "FC_WSTRING";
+ case RPC_FC_INT3264: return "FC_INT3264";
+ case RPC_FC_UINT3264: return "FC_UINT3264";
default:
error("string_of_type: unknown type 0x%02x\n", type);
return NULL;
}
}
+static void *get_aliaschain_attrp(const type_t *type, enum attr_type attr)
+{
+ const type_t *t = type;
+ for (;;)
+ {
+ if (is_attr(t->attrs, attr))
+ return get_attrp(t->attrs, attr);
+ else if (type_is_alias(t))
+ t = type_alias_get_aliasee(t);
+ else return 0;
+ }
+}
+
unsigned char get_basic_fc(const type_t *type)
{
int sign = type_basic_get_sign(type);
case TYPE_BASIC_INT32: return (sign <= 0 ? RPC_FC_LONG : RPC_FC_ULONG);
case TYPE_BASIC_INT64: return RPC_FC_HYPER;
case TYPE_BASIC_INT: return (sign <= 0 ? RPC_FC_LONG : RPC_FC_ULONG);
+ case TYPE_BASIC_INT3264: return (sign <= 0 ? RPC_FC_INT3264 : RPC_FC_UINT3264);
case TYPE_BASIC_BYTE: return RPC_FC_BYTE;
case TYPE_BASIC_CHAR: return RPC_FC_CHAR;
case TYPE_BASIC_WCHAR: return RPC_FC_WCHAR;
case TYPE_BASIC_DOUBLE: return RPC_FC_DOUBLE;
case TYPE_BASIC_ERROR_STATUS_T: return RPC_FC_ERROR_STATUS_T;
case TYPE_BASIC_HANDLE: return RPC_FC_BIND_PRIMITIVE;
- default: return 0;
}
+ return 0;
}
static inline unsigned int clamp_align(unsigned int align)
switch (type_get_type(type))
{
case TYPE_BASIC:
+ if (!(flags & TDT_IGNORE_RANGES) &&
+ (is_attr(attrs, ATTR_RANGE) || is_aliaschain_attr(type, ATTR_RANGE)))
+ return TGT_RANGE;
return TGT_BASIC;
case TYPE_ENUM:
+ if (!(flags & TDT_IGNORE_RANGES) &&
+ (is_attr(attrs, ATTR_RANGE) || is_aliaschain_attr(type, ATTR_RANGE)))
+ return TGT_RANGE;
return TGT_ENUM;
case TYPE_POINTER:
if (type_get_type(type_pointer_get_ref(type)) == TYPE_INTERFACE ||
case TYPE_MODULE:
case TYPE_VOID:
case TYPE_ALIAS:
+ case TYPE_BITFIELD:
break;
}
return TGT_INVALID;
}
-static type_t *get_user_type(const type_t *t, const char **pname);
-
-static int type_contains_iface(const type_t *type)
-{
- enum typegen_type typegen_type;
- var_list_t *fields;
- const var_t *field;
-
- typegen_type = typegen_detect_type(type, type->attrs, TDT_IGNORE_STRINGS);
-
- switch(typegen_type)
- {
- case TGT_USER_TYPE:
- return type_contains_iface(get_user_type(type, NULL));
-
- case TGT_BASIC:
- case TGT_ENUM:
- return FALSE;
-
- case TGT_POINTER:
- return type_contains_iface(type_pointer_get_ref(type));
-
- case TGT_ARRAY:
- return type_contains_iface(type_array_get_element(type));
-
- case TGT_IFACE_POINTER:
- return TRUE;
-
- case TGT_STRUCT:
- fields = type_struct_get_fields(type);
- if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
- {
- if(type_contains_iface(field->type))
- return TRUE;
- }
- return FALSE;
-
- case TGT_UNION:
- fields = type_union_get_cases(type);
- if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
- {
- if(field->type && type_contains_iface(field->type))
- return TRUE;
- }
- return FALSE;
-
- case TGT_STRING:
- /* shouldn't get here because of TDT_IGNORE_STRINGS above. fall through */
- case TGT_INVALID:
- case TGT_CTXT_HANDLE:
- case TGT_CTXT_HANDLE_POINTER:
- /* checking after parsing should mean that we don't get here. if we do,
- * it's a checker bug */
- assert(0);
- }
- return FALSE;
-}
-
unsigned char get_struct_fc(const type_t *type)
{
int has_pointer = 0;
case TGT_IFACE_POINTER:
return RPC_FC_BOGUS_STRUCT;
case TGT_BASIC:
+ if (type_basic_get_type(t) == TYPE_BASIC_INT3264 && pointer_size != 4)
+ return RPC_FC_BOGUS_STRUCT;
break;
case TGT_ENUM:
if (get_enum_fc(t) == RPC_FC_ENUM16)
return RPC_FC_BOGUS_STRUCT;
break;
- case TGT_ARRAY:
- if(type_contains_iface(type_array_get_element(t)))
- return RPC_FC_BOGUS_STRUCT;
case TGT_POINTER:
+ case TGT_ARRAY:
if (get_pointer_fc(t, field->attrs, FALSE) == RPC_FC_RP || pointer_size != 4)
return RPC_FC_BOGUS_STRUCT;
has_pointer = 1;
}
break;
}
+ case TGT_RANGE:
+ return RPC_FC_BOGUS_STRUCT;
case TGT_STRING:
/* shouldn't get here because of TDT_IGNORE_STRINGS above. fall through */
case TGT_INVALID:
case TGT_USER_TYPE:
fc = RPC_FC_BOGUS_ARRAY;
break;
+ case TGT_BASIC:
+ if (type_basic_get_type(elem_type) == TYPE_BASIC_INT3264 &&
+ pointer_size != 4)
+ fc = RPC_FC_BOGUS_ARRAY;
+ break;
case TGT_STRUCT:
switch (get_struct_fc(elem_type))
{
if (get_pointer_fc(elem_type, NULL, FALSE) == RPC_FC_RP || pointer_size != 4)
fc = RPC_FC_BOGUS_ARRAY;
break;
- case TGT_BASIC:
+ case TGT_RANGE:
+ fc = RPC_FC_BOGUS_ARRAY;
+ break;
case TGT_CTXT_HANDLE:
case TGT_CTXT_HANDLE_POINTER:
case TGT_STRING:
case TGT_IFACE_POINTER:
case TGT_BASIC:
case TGT_ENUM:
+ case TGT_RANGE:
case TGT_INVALID:
break;
}
case TGT_IFACE_POINTER:
case TGT_BASIC:
case TGT_ENUM:
+ case TGT_RANGE:
case TGT_INVALID:
break;
}
size = 8;
if (size > *align) *align = size;
break;
+ case RPC_FC_INT3264:
+ case RPC_FC_UINT3264:
+ assert( pointer_size );
+ size = pointer_size;
+ if (size > *align) *align = size;
+ break;
default:
error("type_memsize: Unknown type 0x%x\n", get_basic_fc(t));
size = 0;
case TYPE_COCLASS:
case TYPE_MODULE:
case TYPE_FUNCTION:
+ case TYPE_BITFIELD:
/* these types should not be encountered here due to language
* restrictions (interface, void, coclass, module), logical
* restrictions (alias - due to type_get_type call above) or
- * checking restrictions (function). */
+ * checking restrictions (function, bitfield). */
assert(0);
}
return start_offset;
}
+static unsigned int write_range_tfs(FILE *file, const attr_list_t *attrs,
+ type_t *type, expr_list_t *range_list,
+ unsigned int *typeformat_offset)
+{
+ unsigned char fc;
+ unsigned int start_offset = *typeformat_offset;
+ const expr_t *range_min = LIST_ENTRY(list_head(range_list), const expr_t, entry);
+ const expr_t *range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry);
+
+ if (type_get_type(type) == TYPE_BASIC)
+ fc = get_basic_fc(type);
+ else
+ fc = get_enum_fc(type);
+
+ /* fc must fit in lower 4-bits of 8-bit field below */
+ assert(fc <= 0xf);
+
+ print_file(file, 0, "/* %u */\n", *typeformat_offset);
+ print_file(file, 2, "0x%x,\t/* FC_RANGE */\n", RPC_FC_RANGE);
+ print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
+ print_file(file, 2, "NdrFcLong(0x%lx),\t/* %lu */\n", range_min->cval, range_min->cval);
+ print_file(file, 2, "NdrFcLong(0x%lx),\t/* %lu */\n", range_max->cval, range_max->cval);
+ *typeformat_offset += 10;
+
+ return start_offset;
+}
+
static unsigned int write_typeformatstring_var(FILE *file, int indent, const var_t *func,
type_t *type, const var_t *var,
int toplevel_param,
case TGT_BASIC:
/* nothing to do */
return 0;
+ case TGT_RANGE:
+ {
+ expr_list_t *range_list = get_attrp(var->attrs, ATTR_RANGE);
+ if (!range_list)
+ range_list = get_aliaschain_attrp(type, ATTR_RANGE);
+ return write_range_tfs(file, var->attrs, type, range_list, typeformat_offset);
+ }
case TGT_IFACE_POINTER:
return write_ip_tfs(file, var->attrs, type, typeformat_offset);
case TGT_POINTER:
case TGT_BASIC:
/* nothing to do */
break;
+ case TGT_RANGE:
+ {
+ expr_list_t *range_list = get_attrp(attrs, ATTR_RANGE);
+ if (!range_list)
+ range_list = get_aliaschain_attrp(type, ATTR_RANGE);
+ write_range_tfs(file, attrs, type, range_list, tfsoff);
+ break;
+ }
case TGT_CTXT_HANDLE:
case TGT_CTXT_HANDLE_POINTER:
case TGT_INVALID:
const type_t *type, const char *name, const attr_list_t *attrs, int toplevel_param, unsigned int *alignment)
{
*alignment = 0;
- switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS))
+ switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS|TDT_IGNORE_RANGES))
{
case TGT_USER_TYPE:
{
*alignment = 8;
return 8;
+ case RPC_FC_INT3264:
+ case RPC_FC_UINT3264:
+ assert( pointer_size );
+ *alignment = pointer_size;
+ return pointer_size;
+
case RPC_FC_IGNORE:
case RPC_FC_BIND_PRIMITIVE:
return 0;
{
case TGT_BASIC:
case TGT_ENUM:
+ case TGT_RANGE:
return get_required_buffer_size_type( ref, name, NULL, FALSE, alignment );
case TGT_STRUCT:
if (get_struct_fc(ref) == RPC_FC_STRUCT)
type_t *type = var->type;
unsigned int size;
unsigned int alignment = 0;
- const type_t *ref;
/* no work to do for other phases, buffer sizing is done elsewhere */
if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
return;
- ref = is_ptr(type) ? type_pointer_get_ref(type) : type;
- if (type_get_type(ref) == TYPE_ENUM)
+ if (type_get_type(type) == TYPE_ENUM ||
+ (type_get_type(type) == TYPE_BASIC &&
+ type_basic_get_type(type) == TYPE_BASIC_INT3264 &&
+ pointer_size != 4))
{
- if (get_enum_fc(ref) == RPC_FC_ENUM32)
- {
- size = 4;
- alignment = 4;
- }
- else /* RPC_FC_ENUM16 */
- {
- size = 2;
- alignment = 2;
+ unsigned char fc;
+
+ if (type_get_type(type) == TYPE_ENUM)
+ fc = get_enum_fc(type);
+ else
+ fc = get_basic_fc(type);
+
+ if (phase == PHASE_MARSHAL)
+ print_file(file, indent, "NdrSimpleTypeMarshall(\n");
+ else
+ print_file(file, indent, "NdrSimpleTypeUnmarshall(\n");
+ print_file(file, indent+1, "&__frame->_StubMsg,\n");
+ print_file(file, indent+1, "(unsigned char *)&%s%s,\n",
+ local_var_prefix,
+ var->name);
+ print_file(file, indent+1, "0x%02x /* %s */);\n", fc, string_of_type(fc));
}
- }
else
{
+ const type_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : type;
switch (get_basic_fc(ref))
{
case RPC_FC_BYTE:
case RPC_FC_LONG:
case RPC_FC_FLOAT:
case RPC_FC_ERROR_STATUS_T:
+ /* pointer_size must be 4 if we got here in these two cases */
+ case RPC_FC_INT3264:
+ case RPC_FC_UINT3264:
size = 4;
alignment = 4;
break;
var->name, get_basic_fc(ref));
size = 0;
}
- }
if (phase == PHASE_MARSHAL)
print_file(file, indent, "MIDL_memset(__frame->_StubMsg.Buffer, 0, (0x%x - (ULONG_PTR)__frame->_StubMsg.Buffer) & 0x%x);\n", alignment, alignment - 1);
write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL);
fprintf(file, ");\n");
}
+}
/* returns whether the MaxCount, Offset or ActualCount members need to be
* filled in for the specified phase */
break;
}
case TGT_BASIC:
- if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL)
print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name);
break;
case TGT_ENUM:
- if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL)
+ print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name);
+ break;
+ case TGT_RANGE:
+ print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name);
+ /* Note: this goes beyond what MIDL does - it only supports arguments
+ * with the [range] attribute in Oicf mode */
+ if (phase == PHASE_UNMARSHAL)
{
- if (phase == PHASE_MARSHAL)
- print_file(file, indent, "NdrSimpleTypeMarshall(\n");
- else
- print_file(file, indent, "NdrSimpleTypeUnmarshall(\n");
- print_file(file, indent+1, "&__frame->_StubMsg,\n");
- print_file(file, indent+1, "(unsigned char *)&%s%s,\n",
- local_var_prefix,
- var->name);
- print_file(file, indent+1, "0x%02x /* %s */);\n", get_enum_fc(type), string_of_type(get_enum_fc(type)));
+ const expr_t *range_min;
+ const expr_t *range_max;
+ expr_list_t *range_list = get_attrp(var->attrs, ATTR_RANGE);
+ if (!range_list)
+ range_list = get_aliaschain_attrp(type, ATTR_RANGE);
+ range_min = LIST_ENTRY(list_head(range_list), const expr_t, entry);
+ range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry);
+
+ print_file(file, indent, "if ((%s%s < (", local_var_prefix, var->name);
+ write_type_decl(file, var->type, NULL);
+ fprintf(file, ")0x%lx) || (%s%s > (", range_min->cval, local_var_prefix, var->name);
+ write_type_decl(file, var->type, NULL);
+ fprintf(file, ")0x%lx))\n", range_max->cval);
+ print_file(file, indent, "{\n");
+ print_file(file, indent+1, "RpcRaiseException(RPC_S_INVALID_BOUND);\n");
+ print_file(file, indent, "}\n");
}
break;
case TGT_STRUCT:
case TGT_POINTER:
{
const type_t *ref = type_pointer_get_ref(type);
- if (pointer_type == RPC_FC_RP && !is_user_type(ref)) switch (type_get_type(ref))
+ if (pointer_type == RPC_FC_RP) switch (typegen_detect_type(ref, NULL, TDT_ALL_TYPES))
{
- case TYPE_BASIC:
- /* base types have known sizes, so don't need a sizing pass
- * and don't have any memory to free and so don't need a
- * freeing pass */
- if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL)
+ case TGT_BASIC:
print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name);
break;
- case TYPE_ENUM:
+ case TGT_ENUM:
/* base types have known sizes, so don't need a sizing pass
* and don't have any memory to free and so don't need a
* freeing pass */
if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL)
print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset);
break;
- case TYPE_STRUCT:
+ case TGT_STRUCT:
{
const char *struct_type = NULL;
switch (get_struct_fc(ref))
}
break;
}
- case TYPE_UNION:
- case TYPE_ENCAPSULATED_UNION:
+ case TGT_UNION:
{
const char *union_type = NULL;
if (phase == PHASE_FREE)
phase, var, start_offset);
break;
}
- case TYPE_POINTER:
- case TYPE_ARRAY:
+ case TGT_STRING:
+ case TGT_POINTER:
+ case TGT_ARRAY:
+ case TGT_RANGE:
+ case TGT_IFACE_POINTER:
+ case TGT_USER_TYPE:
+ case TGT_CTXT_HANDLE:
+ case TGT_CTXT_HANDLE_POINTER:
print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset);
break;
- case TYPE_VOID:
- case TYPE_ALIAS:
- case TYPE_MODULE:
- case TYPE_COCLASS:
- case TYPE_FUNCTION:
- case TYPE_INTERFACE:
+ case TGT_INVALID:
assert(0);
break;
}
case TGT_BASIC:
case TGT_ENUM:
case TGT_POINTER:
+ case TGT_RANGE:
print_file(file, indent, "%s_W%u = 0;\n", local_var_prefix, i);
break;
case TGT_STRUCT: