#define ROUNDING(size, alignment) (((alignment) - 1) - (((size) + ((alignment) - 1)) & ((alignment) - 1)))
static const type_t *current_structure;
+static const var_t *current_func;
static const type_t *current_iface;
static struct list expr_eval_routines = LIST_INIT(expr_eval_routines);
struct expr_eval_routine
{
- struct list entry;
- const type_t *structure;
- unsigned int baseoff;
+ struct list entry;
+ const type_t *iface;
+ const type_t *cont_type;
+ char *name;
+ unsigned int baseoff;
const expr_t *expr;
};
TYPE_CONTEXT_CONTAINER_NO_POINTERS,
};
+/* parameter flags in Oif mode */
+static const unsigned short MustSize = 0x0001;
+static const unsigned short MustFree = 0x0002;
+static const unsigned short IsPipe = 0x0004;
+static const unsigned short IsIn = 0x0008;
+static const unsigned short IsOut = 0x0010;
+static const unsigned short IsReturn = 0x0020;
+static const unsigned short IsBasetype = 0x0040;
+static const unsigned short IsByValue = 0x0080;
+static const unsigned short IsSimpleRef = 0x0100;
+/* static const unsigned short IsDontCallFreeInst = 0x0200; */
+/* static const unsigned short SaveForAsyncFinish = 0x0400; */
+
static unsigned int field_memsize(const type_t *type, unsigned int *offset);
static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align);
static unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align);
const char *name, int write_ptr, unsigned int *tfsoff);
static const var_t *find_array_or_string_in_struct(const type_t *type);
static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
- type_t *type, int toplevel_param,
- const char *name, unsigned int *typestring_offset);
+ type_t *type, enum type_context context,
+ const char *name, unsigned int *typestring_offset);
+static unsigned int get_required_buffer_size_type( const type_t *type, const char *name,
+ const attr_list_t *attrs, int toplevel_param,
+ unsigned int *alignment );
+static unsigned int get_function_buffer_size( const var_t *func, enum pass pass );
static const char *string_of_type(unsigned char type)
{
return 0;
}
+static unsigned char get_basic_fc_signed(const type_t *type)
+{
+ switch (type_basic_get_type(type))
+ {
+ case TYPE_BASIC_INT8: return RPC_FC_SMALL;
+ case TYPE_BASIC_INT16: return RPC_FC_SHORT;
+ case TYPE_BASIC_INT32: return RPC_FC_LONG;
+ case TYPE_BASIC_INT64: return RPC_FC_HYPER;
+ case TYPE_BASIC_INT: return RPC_FC_LONG;
+ case TYPE_BASIC_INT3264: return RPC_FC_INT3264;
+ 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_HYPER: return RPC_FC_HYPER;
+ case TYPE_BASIC_FLOAT: return RPC_FC_FLOAT;
+ 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;
+ }
+ return 0;
+}
+
static inline unsigned int clamp_align(unsigned int align)
{
unsigned int packing = (pointer_size == 4) ? win32_packing : win64_packing;
return type_array_get_ptr_default_fc(type);
}
+static unsigned char get_pointer_fc_context( const type_t *type, const attr_list_t *attrs,
+ enum type_context context )
+{
+ int pointer_fc = get_pointer_fc(type, attrs, context == TYPE_CONTEXT_TOPLEVELPARAM);
+
+ if (pointer_fc == RPC_FC_UP && is_attr( attrs, ATTR_OUT ) &&
+ context == TYPE_CONTEXT_PARAM && is_object( current_iface ))
+ pointer_fc = RPC_FC_OP;
+
+ return pointer_fc;
+}
+
static unsigned char get_enum_fc(const type_t *type)
{
assert(type_get_type(type) == TYPE_ENUM);
return TGT_INVALID;
}
+static int cant_be_null(const var_t *v)
+{
+ switch (typegen_detect_type(v->type, v->attrs, TDT_IGNORE_STRINGS))
+ {
+ case TGT_ARRAY:
+ if (!type_array_is_decl_as_ptr( v->type )) return 0;
+ /* fall through */
+ case TGT_POINTER:
+ return (get_pointer_fc(v->type, v->attrs, TRUE) == RPC_FC_RP);
+ case TGT_CTXT_HANDLE_POINTER:
+ return TRUE;
+ default:
+ return 0;
+ }
+
+}
+
static int get_padding(const var_list_t *fields)
{
unsigned short offset = 0;
return ROUNDING(offset, salign);
}
+static unsigned int get_stack_size( const type_t *type, const attr_list_t *attrs, int *by_value )
+{
+ unsigned int stack_size;
+ int by_val;
+
+ switch (typegen_detect_type( type, attrs, TDT_ALL_TYPES ))
+ {
+ case TGT_BASIC:
+ case TGT_ENUM:
+ case TGT_RANGE:
+ case TGT_STRUCT:
+ case TGT_UNION:
+ case TGT_USER_TYPE:
+ stack_size = type_memsize( type );
+ by_val = (pointer_size < 8 || stack_size <= pointer_size); /* FIXME: should be platform-specific */
+ break;
+ default:
+ by_val = 0;
+ break;
+ }
+ if (!by_val) stack_size = pointer_size;
+ if (by_value) *by_value = by_val;
+ return ROUND_SIZE( stack_size, pointer_size );
+}
+
+static unsigned char get_contexthandle_flags( const type_t *iface, const attr_list_t *attrs,
+ const type_t *type )
+{
+ unsigned char flags = 0;
+
+ if (is_attr(iface->attrs, ATTR_STRICTCONTEXTHANDLE)) flags |= NDR_STRICT_CONTEXT_HANDLE;
+
+ if (is_ptr(type) &&
+ !is_attr( type->attrs, ATTR_CONTEXTHANDLE ) &&
+ !is_attr( attrs, ATTR_CONTEXTHANDLE ))
+ flags |= 0x80;
+
+ if (is_attr(attrs, ATTR_IN))
+ {
+ flags |= 0x40;
+ if (!is_attr(attrs, ATTR_OUT)) flags |= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL;
+ }
+ if (is_attr(attrs, ATTR_OUT)) flags |= 0x20;
+
+ return flags;
+}
+
+static unsigned int get_rpc_flags( const attr_list_t *attrs )
+{
+ unsigned int flags = 0;
+
+ if (is_attr( attrs, ATTR_IDEMPOTENT )) flags |= 0x0001;
+ if (is_attr( attrs, ATTR_BROADCAST )) flags |= 0x0002;
+ if (is_attr( attrs, ATTR_MAYBE )) flags |= 0x0004;
+ if (is_attr( attrs, ATTR_MESSAGE )) flags |= 0x0100;
+ if (is_attr( attrs, ATTR_ASYNC )) flags |= 0x4000;
+ return flags;
+}
+
unsigned char get_struct_fc(const type_t *type)
{
int has_pointer = 0;
type_get_type(t) != TYPE_ARRAY);
}
-static unsigned int write_procformatstring_type(FILE *file, int indent,
- const type_t *type,
- const attr_list_t *attrs,
- int is_return)
+static unsigned char get_parameter_fc( const type_t *type, const attr_list_t *attrs, int is_return,
+ unsigned short *flags, unsigned int *stack_size,
+ unsigned int *typestring_offset )
+{
+ unsigned int alignment, server_size = 0, buffer_size = 0;
+ unsigned char fc = 0;
+ int is_byval;
+ int is_in = is_attr(attrs, ATTR_IN);
+ int is_out = is_attr(attrs, ATTR_OUT);
+
+ if (is_return) is_out = TRUE;
+ else if (!is_in && !is_out) is_in = TRUE;
+
+ *flags = 0;
+ *stack_size = get_stack_size( type, attrs, &is_byval );
+ *typestring_offset = type->typestring_offset;
+
+ if (is_in) *flags |= IsIn;
+ if (is_out) *flags |= IsOut;
+ if (is_return) *flags |= IsReturn;
+
+ if (!is_string_type( attrs, type ))
+ buffer_size = get_required_buffer_size_type( type, NULL, attrs, TRUE, &alignment );
+
+ switch (typegen_detect_type( type, attrs, TDT_ALL_TYPES ))
+ {
+ case TGT_BASIC:
+ *flags |= IsBasetype;
+ fc = get_basic_fc_signed( type );
+ if (fc == RPC_FC_BIND_PRIMITIVE)
+ {
+ buffer_size = 4; /* actually 0 but avoids setting MustSize */
+ fc = RPC_FC_LONG;
+ }
+ break;
+ case TGT_ENUM:
+ *flags |= IsBasetype;
+ fc = get_enum_fc( type );
+ break;
+ case TGT_RANGE:
+ *flags |= IsByValue;
+ break;
+ case TGT_STRUCT:
+ case TGT_UNION:
+ case TGT_USER_TYPE:
+ *flags |= MustFree | (is_byval ? IsByValue : IsSimpleRef);
+ break;
+ case TGT_IFACE_POINTER:
+ *flags |= MustFree;
+ break;
+ case TGT_ARRAY:
+ *flags |= MustFree;
+ if (type_array_is_decl_as_ptr(type) && type->details.array.ptr_tfsoff &&
+ get_pointer_fc( type, attrs, !is_return ) == RPC_FC_RP)
+ *flags |= IsSimpleRef;
+ break;
+ case TGT_STRING:
+ *flags |= MustFree;
+ if (is_declptr( type ) && get_pointer_fc( type, attrs, !is_return ) == RPC_FC_RP)
+ {
+ /* skip over pointer description straight to string description */
+ if (is_conformant_array( type )) *typestring_offset += 4;
+ else *typestring_offset += 2;
+ *flags |= IsSimpleRef;
+ }
+ break;
+ case TGT_CTXT_HANDLE_POINTER:
+ *flags |= IsSimpleRef;
+ *typestring_offset += 4;
+ /* fall through */
+ case TGT_CTXT_HANDLE:
+ buffer_size = 20;
+ break;
+ case TGT_POINTER:
+ if (get_pointer_fc( type, attrs, !is_return ) == RPC_FC_RP)
+ {
+ const type_t *ref = type_pointer_get_ref( type );
+
+ if (!is_string_type( attrs, ref ))
+ buffer_size = get_required_buffer_size_type( ref, NULL, NULL, TRUE, &alignment );
+
+ switch (typegen_detect_type( ref, NULL, TDT_ALL_TYPES ))
+ {
+ case TGT_BASIC:
+ *flags |= IsSimpleRef | IsBasetype;
+ fc = get_basic_fc( ref );
+ if (!is_in && is_out) server_size = pointer_size;
+ break;
+ case TGT_ENUM:
+ if ((fc = get_enum_fc( ref )) == RPC_FC_ENUM32)
+ {
+ *flags |= IsSimpleRef | IsBasetype;
+ if (!is_in && is_out) server_size = pointer_size;
+ }
+ else
+ {
+ server_size = pointer_size;
+ }
+ break;
+ case TGT_UNION:
+ case TGT_USER_TYPE:
+ case TGT_RANGE:
+ *flags |= IsSimpleRef | MustFree;
+ *typestring_offset = ref->typestring_offset;
+ if (!is_in && is_out) server_size = type_memsize( ref );
+ break;
+ case TGT_STRING:
+ case TGT_POINTER:
+ case TGT_ARRAY:
+ case TGT_CTXT_HANDLE:
+ case TGT_CTXT_HANDLE_POINTER:
+ *flags |= MustFree;
+ server_size = pointer_size;
+ break;
+ case TGT_IFACE_POINTER:
+ *flags |= MustFree;
+ if (is_in && is_out) server_size = pointer_size;
+ break;
+ case TGT_STRUCT:
+ *flags |= IsSimpleRef | MustFree;
+ *typestring_offset = ref->typestring_offset;
+ switch (get_struct_fc(ref))
+ {
+ case RPC_FC_STRUCT:
+ case RPC_FC_PSTRUCT:
+ case RPC_FC_BOGUS_STRUCT:
+ if (!is_in && is_out) server_size = type_memsize( ref );
+ break;
+ default:
+ break;
+ }
+ break;
+ case TGT_INVALID:
+ assert(0);
+ }
+ }
+ else /* not ref pointer */
+ {
+ *flags |= MustFree;
+ }
+ break;
+ case TGT_INVALID:
+ assert(0);
+ }
+
+ if (!buffer_size) *flags |= MustSize;
+
+ if (server_size)
+ {
+ server_size = (server_size + 7) / 8;
+ if (server_size < 8) *flags |= server_size << 13;
+ }
+ return fc;
+}
+
+static unsigned char get_func_oi2_flags( const var_t *func )
+{
+ const var_t *var;
+ var_list_t *args = type_get_function_args( func->type );
+ type_t *ret_type = type_function_get_rettype( func->type );
+ unsigned char oi2_flags = 0x40; /* HasExtensions */
+ unsigned short flags;
+ unsigned int stack_size, typestring_offset;
+
+ if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
+ {
+ get_parameter_fc( var->type, var->attrs, 0, &flags, &stack_size, &typestring_offset );
+ if (flags & MustSize)
+ {
+ if (flags & IsIn) oi2_flags |= 0x02; /* ClientMustSize */
+ if (flags & IsOut) oi2_flags |= 0x01; /* ServerMustSize */
+ }
+ }
+
+ if (!is_void( ret_type ))
+ {
+ oi2_flags |= 0x04; /* HasRet */
+ get_parameter_fc( ret_type, NULL, 1, &flags, &stack_size, &typestring_offset );
+ if (flags & MustSize) oi2_flags |= 0x01; /* ServerMustSize */
+ }
+ return oi2_flags;
+}
+
+static unsigned int write_new_procformatstring_type(FILE *file, int indent,
+ const type_t *type,
+ const attr_list_t *attrs,
+ int is_return, unsigned int *stack_offset)
+{
+ char buffer[64];
+ unsigned int stack_size, typestring_offset;
+ unsigned short flags;
+ unsigned char fc = get_parameter_fc( type, attrs, is_return, &flags, &stack_size, &typestring_offset );
+
+ strcpy( buffer, "/* flags:" );
+ if (flags & MustSize) strcat( buffer, " must size," );
+ if (flags & MustFree) strcat( buffer, " must free," );
+ if (flags & IsPipe) strcat( buffer, " pipe," );
+ if (flags & IsIn) strcat( buffer, " in," );
+ if (flags & IsOut) strcat( buffer, " out," );
+ if (flags & IsReturn) strcat( buffer, " return," );
+ if (flags & IsBasetype) strcat( buffer, " base type," );
+ if (flags & IsByValue) strcat( buffer, " by value," );
+ if (flags & IsSimpleRef) strcat( buffer, " simple ref," );
+ if (flags >> 13) sprintf( buffer + strlen(buffer), " srv size=%u,", (flags >> 13) * 8 );
+ strcpy( buffer + strlen( buffer ) - 1, " */" );
+ print_file( file, indent, "NdrFcShort(0x%hx),\t%s\n", flags, buffer );
+ print_file( file, indent, "NdrFcShort(0x%hx), /* stack offset = %hu */\n",
+ *stack_offset, *stack_offset );
+ if (flags & IsBasetype)
+ {
+ print_file( file, indent, "0x%02x, /* %s */\n", fc, string_of_type(fc) );
+ print_file( file, indent, "0x0,\n" );
+ }
+ else
+ print_file( file, indent, "NdrFcShort(0x%x), /* type offset = %u */\n",
+ typestring_offset, typestring_offset );
+ *stack_offset += max( stack_size, pointer_size );
+ return 6;
+}
+
+static unsigned int write_old_procformatstring_type(FILE *file, int indent,
+ const type_t *type,
+ const attr_list_t *attrs,
+ int is_return, int is_interpreted)
{
unsigned int size;
}
else
{
- fc = get_basic_fc(type);
+ fc = get_basic_fc_signed(type);
if (fc == RPC_FC_BIND_PRIMITIVE)
fc = RPC_FC_IGNORE;
}
else
{
+ unsigned short offset = type->typestring_offset;
+
+ if (is_interpreted && is_array(type) &&
+ type_array_is_decl_as_ptr(type) &&
+ type->details.array.ptr_tfsoff)
+ offset = type->details.array.ptr_tfsoff;
+
if (is_return)
print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
else if (is_in && is_out)
else
print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
- print_file(file, indent, "0x01,\n");
- print_file(file, indent, "NdrFcShort(0x%x), /* type offset = %u */\n",
- type->typestring_offset, type->typestring_offset);
+ size = get_stack_size( type, attrs, NULL );
+ print_file(file, indent, "0x%02x,\n", size / pointer_size );
+ print_file(file, indent, "NdrFcShort(0x%x), /* type offset = %u */\n", offset, offset);
size = 4; /* includes param type prefix */
}
return size;
}
-static void write_procformatstring_func( FILE *file, int indent,
- const var_t *func, unsigned int *offset )
+int is_interpreted_func( const type_t *iface, const var_t *func )
+{
+ const char *str;
+ const var_t *var;
+ const var_list_t *args = type_get_function_args( func->type );
+ const type_t *ret_type = type_function_get_rettype( func->type );
+
+ if (type_get_type( ret_type ) == TYPE_BASIC)
+ {
+ switch (type_basic_get_type( ret_type ))
+ {
+ case TYPE_BASIC_INT64:
+ case TYPE_BASIC_HYPER:
+ /* return value must fit in a long_ptr */
+ if (pointer_size < 8) return 0;
+ break;
+ case TYPE_BASIC_FLOAT:
+ case TYPE_BASIC_DOUBLE:
+ /* floating point values can't be returned */
+ return 0;
+ default:
+ break;
+ }
+ }
+ if (get_stub_mode() != MODE_Oif && args)
+ {
+ LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
+ switch (type_get_type( var->type ))
+ {
+ case TYPE_BASIC:
+ switch (type_basic_get_type( var->type ))
+ {
+ /* floating point arguments are not supported in Oi mode */
+ case TYPE_BASIC_FLOAT: return 0;
+ case TYPE_BASIC_DOUBLE: return 0;
+ default: break;
+ }
+ break;
+ /* unions passed by value are not supported in Oi mode */
+ case TYPE_UNION: return 0;
+ case TYPE_ENCAPSULATED_UNION: return 0;
+ default: break;
+ }
+ }
+
+ if ((str = get_attrp( func->attrs, ATTR_OPTIMIZE ))) return !strcmp( str, "i" );
+ if ((str = get_attrp( iface->attrs, ATTR_OPTIMIZE ))) return !strcmp( str, "i" );
+ return (get_stub_mode() != MODE_Os);
+}
+
+static void write_proc_func_header( FILE *file, int indent, const type_t *iface,
+ const var_t *func, unsigned int *offset,
+ unsigned short num_proc )
+{
+ var_t *var;
+ var_list_t *args = type_get_function_args( func->type );
+ unsigned char explicit_fc, implicit_fc;
+ unsigned char handle_flags;
+ const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc );
+ unsigned char oi_flags = RPC_FC_PROC_OIF_RPCFLAGS | RPC_FC_PROC_OIF_NEWINIT;
+ unsigned int rpc_flags = get_rpc_flags( func->attrs );
+ unsigned int nb_args = 0;
+ unsigned int stack_size = 0;
+ unsigned short param_num = 0;
+ unsigned short handle_stack_offset = 0;
+ unsigned short handle_param_num = 0;
+
+ if (is_full_pointer_function( func )) oi_flags |= RPC_FC_PROC_OIF_FULLPTR;
+ if (is_object( iface ))
+ {
+ oi_flags |= RPC_FC_PROC_OIF_OBJECT;
+ if (get_stub_mode() == MODE_Oif) oi_flags |= RPC_FC_PROC_OIF_OBJ_V2;
+ stack_size += pointer_size;
+ }
+
+ if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry )
+ {
+ if (var == handle_var)
+ {
+ handle_stack_offset = stack_size;
+ handle_param_num = param_num;
+ }
+ stack_size += get_stack_size( var->type, var->attrs, NULL );
+ param_num++;
+ nb_args++;
+ }
+ if (!is_void( type_function_get_rettype( func->type )))
+ {
+ stack_size += pointer_size;
+ nb_args++;
+ }
+
+ print_file( file, 0, "/* %u (procedure %s::%s) */\n", *offset, iface->name, func->name );
+ print_file( file, indent, "0x%02x,\t/* %s */\n", implicit_fc,
+ implicit_fc ? string_of_type(implicit_fc) : "explicit handle" );
+ print_file( file, indent, "0x%02x,\n", oi_flags );
+ print_file( file, indent, "NdrFcLong(0x%x),\n", rpc_flags );
+ print_file( file, indent, "NdrFcShort(0x%hx),\t/* method %hu */\n", num_proc, num_proc );
+ print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack size = %hu */\n", stack_size, stack_size );
+ *offset += 10;
+
+ if (!implicit_fc)
+ {
+ switch (explicit_fc)
+ {
+ case RPC_FC_BIND_PRIMITIVE:
+ handle_flags = 0;
+ print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) );
+ print_file( file, indent, "0x%02x,\n", handle_flags );
+ print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n",
+ handle_stack_offset, handle_stack_offset );
+ *offset += 4;
+ break;
+ case RPC_FC_BIND_GENERIC:
+ handle_flags = type_memsize( handle_var->type );
+ print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) );
+ print_file( file, indent, "0x%02x,\n", handle_flags );
+ print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n",
+ handle_stack_offset, handle_stack_offset );
+ print_file( file, indent, "0x%02x,\n", get_generic_handle_offset( handle_var->type ) );
+ print_file( file, indent, "0x%x,\t/* FC_PAD */\n", RPC_FC_PAD);
+ *offset += 6;
+ break;
+ case RPC_FC_BIND_CONTEXT:
+ handle_flags = get_contexthandle_flags( iface, handle_var->attrs, handle_var->type );
+ print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) );
+ print_file( file, indent, "0x%02x,\n", handle_flags );
+ print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n",
+ handle_stack_offset, handle_stack_offset );
+ print_file( file, indent, "0x%02x,\n", get_context_handle_offset( handle_var->type ) );
+ print_file( file, indent, "0x%02x,\t/* param %hu */\n", handle_param_num, handle_param_num );
+ *offset += 6;
+ break;
+ }
+ }
+
+ if (get_stub_mode() == MODE_Oif)
+ {
+ unsigned char oi2_flags = get_func_oi2_flags( func );
+ unsigned char ext_flags = 0;
+ unsigned int size;
+
+ if (is_attr( func->attrs, ATTR_NOTIFY )) ext_flags |= 0x08; /* HasNotify */
+ if (is_attr( func->attrs, ATTR_NOTIFYFLAG )) ext_flags |= 0x10; /* HasNotify2 */
+
+ size = get_function_buffer_size( func, PASS_IN );
+ print_file( file, indent, "NdrFcShort(0x%x),\t/* client buffer = %hu */\n", size, size );
+ size = get_function_buffer_size( func, PASS_OUT );
+ print_file( file, indent, "NdrFcShort(0x%x),\t/* server buffer = %hu */\n", size, size );
+ print_file( file, indent, "0x%02x,\n", oi2_flags );
+ print_file( file, indent, "0x%02x,\t/* %u params */\n", nb_args, nb_args );
+ print_file( file, indent, "0x%02x,\n", pointer_size == 8 ? 10 : 8 );
+ print_file( file, indent, "0x%02x,\n", ext_flags );
+ print_file( file, indent, "NdrFcShort(0x0),\n" ); /* server corr hint */
+ print_file( file, indent, "NdrFcShort(0x0),\n" ); /* client corr hint */
+ print_file( file, indent, "NdrFcShort(0x0),\n" ); /* FIXME: notify index */
+ *offset += 14;
+ if (pointer_size == 8)
+ {
+ unsigned short pos = 0, fpu_mask = 0;
+
+ if (is_object( iface )) pos += 2;
+ if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry )
+ {
+ if (type_get_type( var->type ) == TYPE_BASIC)
+ {
+ switch (type_basic_get_type( var->type ))
+ {
+ case TYPE_BASIC_FLOAT: fpu_mask |= 1 << pos; break;
+ case TYPE_BASIC_DOUBLE: fpu_mask |= 2 << pos; break;
+ default: break;
+ }
+ }
+ pos += 2;
+ if (pos >= 16) break;
+ }
+ print_file( file, indent, "NdrFcShort(0x%x),\n", fpu_mask ); /* floating point mask */
+ *offset += 2;
+ }
+ }
+}
+
+static void write_procformatstring_func( FILE *file, int indent, const type_t *iface,
+ const var_t *func, unsigned int *offset,
+ unsigned short num_proc )
{
+ unsigned int stack_offset = is_object( iface ) ? pointer_size : 0;
+ int is_interpreted = is_interpreted_func( iface, func );
+ int is_new_style = is_interpreted && (get_stub_mode() == MODE_Oif);
+
+ if (is_interpreted) write_proc_func_header( file, indent, iface, func, offset, num_proc );
+
/* emit argument data */
if (type_get_function_args(func->type))
{
LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
{
print_file( file, 0, "/* %u (parameter %s) */\n", *offset, var->name );
- *offset += write_procformatstring_type(file, indent, var->type, var->attrs, FALSE);
+ if (is_new_style)
+ *offset += write_new_procformatstring_type(file, indent, var->type, var->attrs,
+ FALSE, &stack_offset);
+ else
+ *offset += write_old_procformatstring_type(file, indent, var->type, var->attrs,
+ FALSE, is_interpreted);
}
}
/* emit return value data */
if (is_void(type_function_get_rettype(func->type)))
{
- print_file(file, 0, "/* %u (void) */\n", *offset);
- print_file(file, indent, "0x5b, /* FC_END */\n");
- print_file(file, indent, "0x5c, /* FC_PAD */\n");
- *offset += 2;
+ if (!is_new_style)
+ {
+ print_file(file, 0, "/* %u (void) */\n", *offset);
+ print_file(file, indent, "0x5b, /* FC_END */\n");
+ print_file(file, indent, "0x5c, /* FC_PAD */\n");
+ *offset += 2;
+ }
}
else
{
print_file( file, 0, "/* %u (return value) */\n", *offset );
- *offset += write_procformatstring_type(file, indent, type_function_get_rettype(func->type), NULL, TRUE);
+ if (is_new_style)
+ *offset += write_new_procformatstring_type(file, indent, type_function_get_rettype(func->type),
+ NULL, TRUE, &stack_offset);
+ else
+ *offset += write_old_procformatstring_type(file, indent, type_function_get_rettype(func->type),
+ NULL, TRUE, is_interpreted);
}
}
if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE)
{
const statement_t *stmt_func;
- if (!pred(stmt->u.type))
- continue;
- STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(stmt->u.type))
+ const type_t *iface = stmt->u.type;
+ const type_t *parent = type_iface_get_inherit( iface );
+ int count = parent ? count_methods( parent ) : 0;
+
+ if (!pred(iface)) continue;
+ STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface))
{
- const var_t *func = stmt_func->u.var;
+ var_t *func = stmt_func->u.var;
if (is_local(func->attrs)) continue;
- write_procformatstring_func( file, indent, func, offset );
+ write_procformatstring_func( file, indent, iface, func, offset, count++ );
}
}
else if (stmt->type == STMT_LIBRARY)
print_file( file, indent, "};\n\n" );
}
-static int write_base_type(FILE *file, const type_t *type, int convert_to_signed_type, unsigned int *typestring_offset)
+static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
{
unsigned char fc;
if (type_get_type(type) == TYPE_BASIC)
- fc = get_basic_fc(type);
+ fc = get_basic_fc_signed(type);
else if (type_get_type(type) == TYPE_ENUM)
fc = get_enum_fc(type);
else
return 0;
- if (convert_to_signed_type)
- {
- switch(fc)
- {
- case RPC_FC_USMALL:
- fc = RPC_FC_SMALL;
- break;
- case RPC_FC_USHORT:
- fc = RPC_FC_SHORT;
- break;
- case RPC_FC_ULONG:
- fc = RPC_FC_LONG;
- break;
- }
- }
-
print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
*typestring_offset += 1;
return 1;
}
/* write conformance / variance descriptor */
-static unsigned int write_conf_or_var_desc(FILE *file, const type_t *structure,
+static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type,
unsigned int baseoff, const type_t *type,
const expr_t *expr)
{
unsigned char operator_type = 0;
unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
- const char *conftype_string = "";
+ const char *conftype_string = "field";
const expr_t *subexpr;
+ const type_t *iface = NULL;
+ const char *name;
if (!expr)
{
return 4;
}
- if (!structure)
+ if (!cont_type) /* top-level conformance */
{
- /* Top-level conformance calculations are done inline. */
- print_file (file, 2, "0x%x,\t/* Corr desc: parameter */\n",
- RPC_FC_TOP_LEVEL_CONFORMANCE);
- print_file (file, 2, "0x0,\n");
- print_file (file, 2, "NdrFcShort(0x0),\n");
- return 4;
+ conftype = RPC_FC_TOP_LEVEL_CONFORMANCE;
+ conftype_string = "parameter";
+ cont_type = current_func->type;
+ name = current_func->name;
+ iface = current_iface;
}
-
- if (is_ptr(type) || (is_array(type) && type_array_is_decl_as_ptr(type)))
+ else
{
- conftype = RPC_FC_POINTER_CONFORMANCE;
- conftype_string = "field pointer, ";
+ name = cont_type->name;
+ if (is_ptr(type) || (is_array(type) && type_array_is_decl_as_ptr(type)))
+ {
+ conftype = RPC_FC_POINTER_CONFORMANCE;
+ conftype_string = "field pointer";
+ }
}
subexpr = expr;
unsigned char param_type = 0;
unsigned int offset = 0;
const var_t *var;
- var_list_t *fields = type_struct_get_fields(structure);
+ struct expr_loc expr_loc;
- if (fields) LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
+ if (type_get_type(cont_type) == TYPE_FUNCTION)
{
- unsigned int size = field_memsize( var->type, &offset );
- if (var->name && !strcmp(var->name, subexpr->u.sval))
+ var_list_t *args = type_get_function_args( cont_type );
+
+ if (is_object( iface )) offset += pointer_size;
+ if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
{
- correlation_variable = var->type;
- break;
+ if (var->name && !strcmp(var->name, subexpr->u.sval))
+ {
+ expr_loc.v = var;
+ correlation_variable = var->type;
+ break;
+ }
+ offset += get_stack_size( var->type, var->attrs, NULL );
}
- offset += size;
}
- if (!correlation_variable)
- error("write_conf_or_var_desc: couldn't find variable %s in structure\n",
- subexpr->u.sval);
+ else
+ {
+ var_list_t *fields = type_struct_get_fields( cont_type );
- correlation_variable = expr_resolve_type(NULL, structure, expr);
+ if (fields) LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
+ {
+ unsigned int size = field_memsize( var->type, &offset );
+ if (var->name && !strcmp(var->name, subexpr->u.sval))
+ {
+ expr_loc.v = var;
+ correlation_variable = var->type;
+ break;
+ }
+ offset += size;
+ }
+ }
+
+ if (!correlation_variable)
+ error("write_conf_or_var_desc: couldn't find variable %s in %s\n", subexpr->u.sval, name);
+ expr_loc.attr = NULL;
+ correlation_variable = expr_resolve_type(&expr_loc, cont_type, expr);
offset -= baseoff;
return 0;
}
- print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
- conftype | param_type, conftype_string, string_of_type(param_type));
- print_file(file, 2, "0x%x, /* %s */\n", operator_type,
+ print_file(file, 2, "0x%x,\t/* Corr desc: %s %s, %s */\n",
+ conftype | param_type, conftype_string, subexpr->u.sval, string_of_type(param_type));
+ print_file(file, 2, "0x%x,\t/* %s */\n", operator_type,
operator_type ? string_of_type(operator_type) : "no operators");
print_file(file, 2, "NdrFcShort(0x%hx),\t/* offset = %d */\n",
(unsigned short)offset, offset);
}
- else
+ else if (!iface || is_interpreted_func( iface, current_func ))
{
unsigned int callback_offset = 0;
struct expr_eval_routine *eval;
LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
{
- if (eval->structure == structure ||
- (eval->structure->name && structure->name &&
- !strcmp(eval->structure->name, structure->name) &&
+ if (eval->cont_type == cont_type ||
+ (type_get_type( eval->cont_type ) == type_get_type( cont_type ) &&
+ eval->iface == iface &&
+ eval->name && name && !strcmp(eval->name, name) &&
!compare_expr(eval->expr, expr)))
{
found = 1;
if (!found)
{
eval = xmalloc (sizeof(*eval));
- eval->structure = structure;
+ eval->iface = iface;
+ eval->cont_type = cont_type;
+ eval->name = xstrdup( name );
eval->baseoff = baseoff;
eval->expr = expr;
list_add_tail (&expr_eval_routines, &eval->entry);
if (callback_offset > USHRT_MAX)
error("Maximum number of callback routines reached\n");
- print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string);
- print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
+ print_file(file, 2, "0x%x,\t/* Corr desc: %s in %s */\n", conftype, conftype_string, name);
+ print_file(file, 2, "0x%x,\t/* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)callback_offset, callback_offset);
}
+ else /* output a dummy corr desc that isn't used */
+ {
+ print_file(file, 2, "0x%x,\t/* Corr desc: unused for %s */\n", conftype, name);
+ print_file(file, 2, "0x0,\n" );
+ print_file(file, 2, "NdrFcShort(0x0),\n" );
+ }
return 4;
}
break;
case RPC_FC_INT3264:
case RPC_FC_UINT3264:
+ case RPC_FC_BIND_PRIMITIVE:
assert( pointer_size );
size = pointer_size;
if (size > *align) *align = size;
static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs,
const type_t *type,
- int toplevel_param,
+ enum type_context context,
unsigned int offset,
unsigned int *typeformat_offset)
{
int pointer_type;
unsigned char flags = 0;
- pointer_type = get_pointer_fc(type, attrs, toplevel_param);
+ pointer_type = get_pointer_fc_context(type, attrs, context);
in_attr = is_attr(attrs, ATTR_IN);
out_attr = is_attr(attrs, ATTR_OUT);
if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
flags |= RPC_FC_P_ONSTACK;
- if (is_ptr(type) && is_declptr(type_pointer_get_ref(type)))
- flags |= RPC_FC_P_DEREF;
+ if (is_ptr(type))
+ {
+ type_t *ref = type_pointer_get_ref(type);
+ if(is_declptr(ref) && !is_user_type(ref))
+ flags |= RPC_FC_P_DEREF;
+ }
print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
pointer_type,
return start_offset;
}
-static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs, const type_t *type, int toplevel_param)
+static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs,
+ const type_t *type, enum type_context context)
{
unsigned char fc;
unsigned char pointer_fc;
if (is_string_type(attrs, type))
error("write_simple_pointer: can't handle type %s which is a string type\n", type->name);
- pointer_fc = get_pointer_fc(type, attrs, toplevel_param);
+ pointer_fc = get_pointer_fc_context(type, attrs, context);
ref = type_pointer_get_ref(type);
if (type_get_type(ref) == TYPE_ENUM)
static unsigned int write_pointer_tfs(FILE *file, const attr_list_t *attrs,
type_t *type, unsigned int ref_offset,
- int toplevel_param,
+ enum type_context context,
unsigned int *typestring_offset)
{
unsigned int offset = *typestring_offset;
{
case TGT_BASIC:
case TGT_ENUM:
- *typestring_offset += write_simple_pointer(file, attrs, type,
- toplevel_param);
+ *typestring_offset += write_simple_pointer(file, attrs, type, context);
break;
default:
if (ref_offset)
- write_nonsimple_pointer(file, attrs, type,
- toplevel_param,
- ref_offset,
- typestring_offset);
+ write_nonsimple_pointer(file, attrs, type, context, ref_offset, typestring_offset);
break;
}
return FALSE;
}
-static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
+static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
{
unsigned int start, absoff, flags;
const char *name = NULL;
unsigned short funoff = user_type_offset(name);
short reloff;
+ if (processed(type)) return type->typestring_offset;
+
guard_rec(type);
if(user_type_has_variable_size(utype)) usize = 0;
reloff = absoff - *tfsoff;
print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, absoff);
*tfsoff += 2;
+ return start;
}
static void write_member_type(FILE *file, const type_t *cont,
print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
*tfsoff += 1;
}
- else if (!write_base_type(file, type, TRUE, tfsoff))
+ else if (!write_base_type(file, type, tfsoff))
error("Unsupported member type %d\n", type_get_type(type));
}
if (processed(ref))
{
- write_nonsimple_pointer(file, NULL, elem, FALSE, ref->typestring_offset, tfsoff);
+ write_nonsimple_pointer(file, NULL, elem, TYPE_CONTEXT_CONTAINER,
+ ref->typestring_offset, tfsoff);
return;
}
if (!is_string_type(NULL, elem) &&
(type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM))
{
- *tfsoff += write_simple_pointer(file, NULL, elem, FALSE);
+ *tfsoff += write_simple_pointer(file, NULL, elem, TYPE_CONTEXT_CONTAINER);
return;
}
}
type_t *ref = type_pointer_get_ref(type);
if (is_string_type(attrs, type))
- write_string_tfs(file, attrs, type, FALSE, NULL, typestring_offset);
+ write_string_tfs(file, attrs, type, TYPE_CONTEXT_CONTAINER, NULL, typestring_offset);
else if (processed(ref))
- write_nonsimple_pointer(file, attrs, type, FALSE, ref->typestring_offset, typestring_offset);
+ write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER,
+ ref->typestring_offset, typestring_offset);
else if (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM)
- *typestring_offset += write_simple_pointer(file, attrs, type, FALSE);
+ *typestring_offset += write_simple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER);
else
error("write_pointer_description_offsets: type format string unknown\n");
}
* pointer has to be written in-place here */
if (is_string_type(attrs, type))
offset += 4;
- write_nonsimple_pointer(file, attrs, type, FALSE, offset, typestring_offset);
+ write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER, offset, typestring_offset);
}
return 1;
}
static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
- type_t *type, int toplevel_param,
+ type_t *type, enum type_context context,
const char *name, unsigned int *typestring_offset)
{
unsigned int start_offset;
unsigned char rtype;
type_t *elem_type;
+ int is_processed = processed(type);
start_offset = *typestring_offset;
- update_tfsoff(type, start_offset, file);
if (is_declptr(type))
{
unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER;
- int pointer_type = get_pointer_fc(type, attrs, toplevel_param);
+ int pointer_type = get_pointer_fc_context(type, attrs, context);
if (!pointer_type)
pointer_type = RPC_FC_RP;
print_start_tfs_comment(file, type, *typestring_offset);
print_file(file, 2, "NdrFcShort(0x2),\n");
*typestring_offset += 2;
}
+ is_processed = FALSE;
}
if (is_array(type))
{
unsigned int dim = type_array_get_dim(type);
+ if (is_processed) return start_offset;
+
/* FIXME: multi-dimensional array */
if (0xffffu < dim)
error("array size for parameter %s exceeds %u bytes by %u bytes\n",
print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)dim, dim);
*typestring_offset += 2;
+ update_tfsoff(type, start_offset, file);
return start_offset;
}
else if (is_conformant_array(type))
: 0),
type, type_array_get_conformance(type));
+ update_tfsoff(type, start_offset, file);
return start_offset;
}
else
{
+ if (is_processed) return start_offset;
+
if (rtype == RPC_FC_WCHAR)
WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
else
print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
*typestring_offset += 2;
+ update_tfsoff(type, start_offset, file);
return start_offset;
}
}
unsigned char fc = get_struct_fc(type);
var_list_t *fields = type_struct_get_fields(type);
+ if (processed(type)) return type->typestring_offset;
+
guard_rec(type);
current_structure = type;
if (array && !processed(array->type))
{
if(is_string_type(array->attrs, array->type))
- write_string_tfs(file, array->attrs, array->type, FALSE, array->name, tfsoff);
+ write_string_tfs(file, array->attrs, array->type, TYPE_CONTEXT_CONTAINER, array->name, tfsoff);
else
write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
}
{
case TGT_POINTER:
if (is_string_type(f->attrs, ft))
- write_string_tfs(file, f->attrs, ft, FALSE, f->name, tfsoff);
+ write_string_tfs(file, f->attrs, ft, TYPE_CONTEXT_CONTAINER, f->name, tfsoff);
else
write_pointer_tfs(file, f->attrs, ft,
type_pointer_get_ref(ft)->typestring_offset,
- FALSE, tfsoff);
+ TYPE_CONTEXT_CONTAINER, tfsoff);
break;
case TGT_ARRAY:
if (type_array_is_decl_as_ptr(ft))
* pointer has to be written in-place here */
if (is_string_type(f->attrs, ft))
offset += 4;
- write_nonsimple_pointer(file, f->attrs, ft, FALSE, offset, tfsoff);
+ write_nonsimple_pointer(file, f->attrs, ft, TYPE_CONTEXT_CONTAINER, offset, tfsoff);
}
break;
default:
*tfsoff += 2;
}
-static unsigned int write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
+static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
+ type_t *type, unsigned int *tfsoff)
{
unsigned int start_offset;
unsigned int size;
short nodeftype = 0xffff;
var_t *f;
+ if (processed(type) &&
+ (type_get_type(type) == TYPE_ENCAPSULATED_UNION || !is_attr(type->attrs, ATTR_SWITCHTYPE)))
+ return type->typestring_offset;
+
guard_rec(type);
size = type_memsize(type);
if (type_get_type(st) == TYPE_BASIC)
{
- switch (get_basic_fc(st))
+ fc = get_basic_fc(st);
+ switch (fc)
{
case RPC_FC_CHAR:
case RPC_FC_SMALL:
case RPC_FC_USHORT:
case RPC_FC_LONG:
case RPC_FC_ULONG:
- fc = get_basic_fc(st);
break;
default:
fc = 0;
}
else if (is_attr(type->attrs, ATTR_SWITCHTYPE))
{
- static const expr_t dummy_expr; /* FIXME */
+ const expr_t *switch_is = get_attrp(attrs, ATTR_SWITCHIS);
const type_t *st = get_attrp(type->attrs, ATTR_SWITCHTYPE);
unsigned char fc;
if (type_get_type(st) == TYPE_BASIC)
{
- switch (get_basic_fc(st))
+ fc = get_basic_fc(st);
+ switch (fc)
{
case RPC_FC_CHAR:
case RPC_FC_SMALL:
case RPC_FC_ULONG:
case RPC_FC_ENUM16:
case RPC_FC_ENUM32:
- fc = get_basic_fc(st);
break;
default:
fc = 0;
print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
fc, string_of_type(fc));
*tfsoff += 2;
-
- *tfsoff += write_conf_or_var_desc(file, NULL, *tfsoff, st, &dummy_expr );
+ *tfsoff += write_conf_or_var_desc(file, current_structure, 0, st, switch_is );
print_file(file, 2, "NdrFcShort(0x2),\t/* Offset= 2 (%u) */\n", *tfsoff + 2);
*tfsoff += 2;
print_file(file, 0, "/* %u */\n", *tfsoff);
unsigned int start_offset = *typeformat_offset;
expr_t *iid = get_attrp(attrs, ATTR_IIDIS);
+ if (!iid && processed(type)) return type->typestring_offset;
+
print_start_tfs_comment(file, type, start_offset);
+ update_tfsoff(type, start_offset, file);
if (iid)
{
if (! uuid)
error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
- update_tfsoff(type, start_offset, file);
print_file(file, 2, "0x2f,\t/* FC_IP */\n");
print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
print_file(file, 2, "NdrFcLong(0x%08x),\n", uuid->Data1);
static unsigned int write_contexthandle_tfs(FILE *file,
const attr_list_t *attrs,
- const type_t *type,
+ type_t *type,
+ int toplevel_param,
unsigned int *typeformat_offset)
{
unsigned int start_offset = *typeformat_offset;
- unsigned char flags = 0;
+ unsigned char flags = get_contexthandle_flags( current_iface, attrs, type );
- if (is_attr(current_iface->attrs, ATTR_STRICTCONTEXTHANDLE))
- flags |= NDR_STRICT_CONTEXT_HANDLE;
+ print_start_tfs_comment(file, type, start_offset);
- if (is_ptr(type))
- flags |= 0x80;
- if (is_attr(attrs, ATTR_IN))
+ if (flags & 0x80) /* via ptr */
{
- flags |= 0x40;
- if (!is_attr(attrs, ATTR_OUT))
- flags |= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL;
+ int pointer_type = get_pointer_fc( type, attrs, toplevel_param );
+ if (!pointer_type) pointer_type = RPC_FC_RP;
+ *typeformat_offset += 4;
+ print_file(file, 2,"0x%x, 0x0,\t/* %s */\n", pointer_type, string_of_type(pointer_type) );
+ print_file(file, 2, "NdrFcShort(0x2),\t /* Offset= 2 (%u) */\n", *typeformat_offset);
+ print_file(file, 0, "/* %2u */\n", *typeformat_offset);
}
- if (is_attr(attrs, ATTR_OUT))
- flags |= 0x20;
- WRITE_FCTYPE(file, FC_BIND_CONTEXT, *typeformat_offset);
+ print_file(file, 2, "0x%02x,\t/* FC_BIND_CONTEXT */\n", RPC_FC_BIND_CONTEXT);
print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
/* return and can't be null values overlap */
if (((flags & 0x21) != 0x21) && (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL))
if (flags & 0x80)
print_file(file, 0, "via ptr, ");
print_file(file, 0, "*/\n");
- print_file(file, 2, "0, /* FIXME: rundown routine index*/\n");
+ print_file(file, 2, "0x%x,\t/* rundown routine */\n", get_context_handle_offset( type ));
print_file(file, 2, "0, /* FIXME: param num */\n");
*typeformat_offset += 4;
+ update_tfsoff( type, start_offset, file );
return start_offset;
}
print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_min->cval, range_min->cval);
print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_max->cval, range_max->cval);
+ update_tfsoff( type, start_offset, file );
*typeformat_offset += 10;
return start_offset;
{
case TGT_CTXT_HANDLE:
case TGT_CTXT_HANDLE_POINTER:
- return write_contexthandle_tfs(file, attrs, type, typeformat_offset);
+ return write_contexthandle_tfs(file, attrs, type,
+ context == TYPE_CONTEXT_TOPLEVELPARAM, typeformat_offset);
case TGT_USER_TYPE:
- write_user_tfs(file, type, typeformat_offset);
- return type->typestring_offset;
+ return write_user_tfs(file, type, typeformat_offset);
case TGT_STRING:
- return write_string_tfs(file, attrs, type,
- context == TYPE_CONTEXT_TOPLEVELPARAM,
- name, typeformat_offset);
+ return write_string_tfs(file, attrs, type, context, name, typeformat_offset);
case TGT_ARRAY:
{
unsigned int off;
int ptr_type;
ptr_type = get_pointer_fc(type, attrs,
context == TYPE_CONTEXT_TOPLEVELPARAM);
- if (ptr_type != RPC_FC_RP)
+ if (ptr_type != RPC_FC_RP || type_array_is_decl_as_ptr(type))
{
unsigned int absoff = type->typestring_offset;
short reloff = absoff - (*typeformat_offset + 2);
string_of_type(ptr_type));
print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
reloff, reloff, absoff);
+ if (ptr_type != RPC_FC_RP) update_tfsoff( type, off, file );
*typeformat_offset += 4;
}
+ type->details.array.ptr_tfsoff = off;
}
return off;
}
case TGT_STRUCT:
- if (processed(type)) return type->typestring_offset;
return write_struct_tfs(file, type, name, typeformat_offset);
case TGT_UNION:
- if (processed(type)) return type->typestring_offset;
- return write_union_tfs(file, type, typeformat_offset);
+ return write_union_tfs(file, attrs, type, typeformat_offset);
case TGT_ENUM:
case TGT_BASIC:
/* nothing to do */
case TGT_IFACE_POINTER:
return write_ip_tfs(file, attrs, type, typeformat_offset);
case TGT_POINTER:
- if (processed(type_pointer_get_ref(type)))
- offset = type_pointer_get_ref(type)->typestring_offset;
+ {
+ enum type_context ref_context;
+ if (context == TYPE_CONTEXT_TOPLEVELPARAM)
+ ref_context = TYPE_CONTEXT_PARAM;
+ else if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS)
+ ref_context = TYPE_CONTEXT_CONTAINER;
else
- {
- enum type_context ref_context;
- if (context == TYPE_CONTEXT_TOPLEVELPARAM)
- ref_context = TYPE_CONTEXT_PARAM;
- else if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS)
- ref_context = TYPE_CONTEXT_CONTAINER;
- else
- ref_context = context;
- offset = write_type_tfs(
- file, indent, attrs, type_pointer_get_ref(type), name,
- ref_context, typeformat_offset);
- }
+ ref_context = context;
+ offset = write_type_tfs( file, indent, attrs, type_pointer_get_ref(type), name,
+ ref_context, typeformat_offset);
if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS)
return 0;
- else
- return write_pointer_tfs(file, attrs, type, offset,
- context == TYPE_CONTEXT_TOPLEVELPARAM,
- typeformat_offset);
+ return write_pointer_tfs(file, attrs, type, offset, context, typeformat_offset);
+ }
case TGT_INVALID:
break;
}
STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(iface) )
{
const var_t *func = stmt_func->u.var;
- if (is_local(func->attrs)) continue;
+ current_func = func;
+ if (is_local(func->attrs)) continue;
- if (!is_void(type_function_get_rettype(func->type)))
- {
- update_tfsoff(type_function_get_rettype(func->type),
- write_type_tfs(
- file, 2, func->attrs,
- type_function_get_rettype(func->type),
- func->name, TYPE_CONTEXT_PARAM,
- typeformat_offset),
- file);
- }
+ if (!is_void(type_function_get_rettype(func->type)))
+ {
+ write_type_tfs( file, 2, func->attrs, type_function_get_rettype(func->type),
+ func->name, TYPE_CONTEXT_PARAM, typeformat_offset);
+ }
- if (type_get_function_args(func->type))
- LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
- update_tfsoff(
- var->type,
- write_type_tfs(
- file, 2, var->attrs, var->type, var->name,
- TYPE_CONTEXT_TOPLEVELPARAM,
- typeformat_offset),
- file);
+ if (type_get_function_args(func->type))
+ LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
+ write_type_tfs( file, 2, var->attrs, var->type, var->name,
+ TYPE_CONTEXT_TOPLEVELPARAM, typeformat_offset );
}
}
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|TDT_IGNORE_RANGES))
+ switch (typegen_detect_type(type, NULL, TDT_IGNORE_RANGES))
{
case TGT_USER_TYPE:
{
break;
case TGT_POINTER:
- if (get_pointer_fc(type, attrs, toplevel_param) == RPC_FC_RP)
{
+ unsigned int size, align;
const type_t *ref = type_pointer_get_ref(type);
- switch (typegen_detect_type(ref, NULL, TDT_ALL_TYPES))
+ if (is_string_type( attrs, ref )) break;
+ if (!(size = get_required_buffer_size_type( ref, name, NULL, FALSE, &align ))) break;
+ if (get_pointer_fc(type, attrs, toplevel_param) != RPC_FC_RP)
{
- 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)
- return get_required_buffer_size_type( ref, name, NULL, FALSE, alignment );
- break;
- case TGT_USER_TYPE:
- case TGT_CTXT_HANDLE:
- case TGT_CTXT_HANDLE_POINTER:
- case TGT_STRING:
- case TGT_POINTER:
- case TGT_ARRAY:
- case TGT_IFACE_POINTER:
- case TGT_UNION:
- case TGT_INVALID:
- break;
+ size += 4 + align;
+ align = 4;
}
+ *alignment = align;
+ return size;
}
- break;
case TGT_ARRAY:
if (get_pointer_fc(type, attrs, toplevel_param) == RPC_FC_RP)
- return type_array_get_dim(type) *
- get_required_buffer_size_type(type_array_get_element(type), name,
- NULL, FALSE, alignment);
+ {
+ switch (get_array_fc(type))
+ {
+ case RPC_FC_SMFARRAY:
+ case RPC_FC_LGFARRAY:
+ return type_array_get_dim(type) *
+ get_required_buffer_size_type(type_array_get_element(type), name,
+ NULL, FALSE, alignment);
+ }
+ }
+ break;
default:
break;
return x;
}
-static void write_parameter_conf_or_var_exprs(FILE *file, int indent, const char *local_var_prefix,
- enum remoting_phase phase, const var_t *var)
+void write_parameter_conf_or_var_exprs(FILE *file, int indent, const char *local_var_prefix,
+ enum remoting_phase phase, const var_t *var, int valid_variance)
{
const type_t *type = var->type;
/* get fundamental type for the argument */
if (type_array_has_variance(type))
{
print_file(file, indent, "__frame->_StubMsg.Offset = 0;\n"); /* FIXME */
- print_file(file, indent, "__frame->_StubMsg.ActualCount = (ULONG_PTR)");
- write_expr(file, type_array_get_variance(type), 1, 1, NULL, NULL, local_var_prefix);
- fprintf(file, ";\n\n");
+ if (valid_variance)
+ {
+ print_file(file, indent, "__frame->_StubMsg.ActualCount = (ULONG_PTR)");
+ write_expr(file, type_array_get_variance(type), 1, 1, NULL, NULL, local_var_prefix);
+ fprintf(file, ";\n\n");
+ }
+ else
+ print_file(file, indent, "__frame->_StubMsg.ActualCount = __frame->_StubMsg.MaxCount;\n\n");
}
}
break;
enum pass pass, enum remoting_phase phase, const var_t *var)
{
int in_attr, out_attr, pointer_type;
+ const char *type_str = NULL;
const type_t *type = var->type;
- unsigned int start_offset = type->typestring_offset;
+ unsigned int alignment, start_offset = type->typestring_offset;
if (is_ptr(type) || is_array(type))
pointer_type = get_pointer_fc(type, var->attrs, pass != PASS_RETURN);
break;
}
- write_parameter_conf_or_var_exprs(file, indent, local_var_prefix, phase, var);
+ if (phase == PHASE_BUFFERSIZE && get_required_buffer_size( var, &alignment, pass )) return;
+
+ write_parameter_conf_or_var_exprs(file, indent, local_var_prefix, phase, var, TRUE);
switch (typegen_detect_type(type, var->attrs, TDT_ALL_TYPES))
{
if (phase == PHASE_FREE || pass == PASS_RETURN ||
pointer_type != RPC_FC_RP)
{
- if (pointer_type == RPC_FC_RP && phase == PHASE_FREE &&
+ /* strings returned are assumed to be global and hence don't
+ * need freeing */
+ if (is_declptr(type) && !(phase == PHASE_FREE && pass == PASS_RETURN))
+ print_phase_function(file, indent, "Pointer", local_var_prefix,
+ phase, var, start_offset);
+ else if (pointer_type == RPC_FC_RP && phase == PHASE_FREE &&
!in_attr && is_conformant_array(type))
{
print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name);
indent++;
print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name);
}
- /* strings returned are assumed to be global and hence don't
- * need freeing */
- else if (is_declptr(type) &&
- !(phase == PHASE_FREE && pass == PASS_RETURN))
- print_phase_function(file, indent, "Pointer", local_var_prefix,
- phase, var, start_offset);
}
else
{
}
if (pointer_type != RPC_FC_RP) array_type = "Pointer";
- print_phase_function(file, indent, array_type, local_var_prefix, phase, var, start_offset);
+
if (phase == PHASE_FREE && pointer_type == RPC_FC_RP)
{
/* these are all unmarshalled by allocating memory */
((tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY) && in_attr) ||
(tc == RPC_FC_CARRAY && !in_attr))
{
+ if (type_array_is_decl_as_ptr(type) && type->details.array.ptr_tfsoff)
+ {
+ print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var,
+ type->details.array.ptr_tfsoff);
+ break;
+ }
+ print_phase_function(file, indent, array_type, local_var_prefix, phase, var, start_offset);
print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name);
indent++;
print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name);
+ break;
}
}
+ print_phase_function(file, indent, array_type, local_var_prefix, phase, var, start_offset);
break;
}
case TGT_BASIC:
print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset);
break;
case TGT_STRUCT:
- {
- const char *struct_type = NULL;
switch (get_struct_fc(ref))
{
case RPC_FC_STRUCT:
* pass and don't have any memory to free and so don't
* need a freeing pass */
if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL)
- struct_type = "SimpleStruct";
+ type_str = "SimpleStruct";
else if (phase == PHASE_FREE && pass == PASS_RETURN)
{
print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name);
}
break;
case RPC_FC_PSTRUCT:
- struct_type = "SimpleStruct";
+ type_str = "SimpleStruct";
break;
case RPC_FC_CSTRUCT:
case RPC_FC_CPSTRUCT:
- struct_type = "ConformantStruct";
+ type_str = "ConformantStruct";
break;
case RPC_FC_CVSTRUCT:
- struct_type = "ConformantVaryingStruct";
+ type_str = "ConformantVaryingStruct";
break;
case RPC_FC_BOGUS_STRUCT:
- struct_type = "ComplexStruct";
+ type_str = "ComplexStruct";
break;
default:
error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, get_struct_fc(ref));
}
- if (struct_type)
+ if (type_str)
{
if (phase == PHASE_FREE)
- struct_type = "Pointer";
+ type_str = "Pointer";
else
start_offset = ref->typestring_offset;
- print_phase_function(file, indent, struct_type, local_var_prefix, phase, var, start_offset);
+ print_phase_function(file, indent, type_str, local_var_prefix, phase, var, start_offset);
}
break;
- }
case TGT_UNION:
- {
- const char *union_type = NULL;
if (phase == PHASE_FREE)
- union_type = "Pointer";
+ type_str = "Pointer";
else
{
if (type_get_type(ref) == TYPE_UNION)
- union_type = "NonEncapsulatedUnion";
+ type_str = "NonEncapsulatedUnion";
else if (type_get_type(ref) == TYPE_ENCAPSULATED_UNION)
- union_type = "EncapsulatedUnion";
+ type_str = "EncapsulatedUnion";
start_offset = ref->typestring_offset;
}
- print_phase_function(file, indent, union_type, local_var_prefix,
+ print_phase_function(file, indent, type_str, local_var_prefix,
phase, var, start_offset);
break;
- }
+ case TGT_USER_TYPE:
+ if (phase != PHASE_FREE)
+ {
+ type_str = "UserMarshal";
+ start_offset = ref->typestring_offset;
+ }
+ else type_str = "Pointer";
+
+ print_phase_function(file, indent, type_str, local_var_prefix, phase, var, start_offset);
+ break;
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);
}
-unsigned int get_size_procformatstring_func(const var_t *func)
+unsigned int get_size_procformatstring_func(const type_t *iface, const var_t *func)
{
unsigned int offset = 0;
- write_procformatstring_func( NULL, 0, func, &offset );
+ write_procformatstring_func( NULL, 0, iface, func, &offset, 0 );
return offset;
}
{
const var_t *func = stmt_func->u.var;
if (!is_local(func->attrs))
- size += get_size_procformatstring_func( func );
+ size += get_size_procformatstring_func( iface, func );
}
}
return size;
if (type_array_has_conformance(var->type))
{
unsigned int size;
- type_t *type = var->type;
+ type_t *type;
fprintf(file, " = NdrAllocate(&__frame->_StubMsg, ");
- for ( ;
+ for (type = var->type;
+ is_array(type) && type_array_has_conformance(type);
+ type = type_array_get_element(type))
+ {
+ write_expr(file, type_array_get_conformance(type), TRUE,
+ TRUE, NULL, NULL, local_var_prefix);
+ fprintf(file, " * ");
+ }
+ size = type_memsize(type);
+ fprintf(file, "%u);\n", size);
+
+ print_file(file, indent, "memset(%s%s, 0, ", local_var_prefix, var->name);
+ for (type = var->type;
is_array(type) && type_array_has_conformance(type);
type = type_array_get_element(type))
{
case TGT_ENUM:
case TGT_POINTER:
case TGT_RANGE:
+ case TGT_IFACE_POINTER:
print_file(file, indent, "%s_W%u = 0;\n", local_var_prefix, i);
break;
+ case TGT_USER_TYPE:
+ print_file(file, indent, "memset(&%s_W%u, 0, sizeof(%s_W%u));\n",
+ local_var_prefix, i, local_var_prefix, i);
+ break;
case TGT_STRUCT:
case TGT_UNION:
- case TGT_USER_TYPE:
- case TGT_IFACE_POINTER:
case TGT_ARRAY:
case TGT_CTXT_HANDLE:
case TGT_CTXT_HANDLE_POINTER:
}
+void write_func_param_struct( FILE *file, const type_t *iface, const type_t *func,
+ const char *var_decl, int add_retval )
+{
+ type_t *rettype = type_function_get_rettype( func );
+ const var_list_t *args = type_get_function_args( func );
+ const var_t *arg;
+ int needs_packing;
+ unsigned int align = 0;
+
+ if (args)
+ LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
+ if (!is_array( arg->type )) type_memsize_and_alignment( arg->type, &align );
+
+ needs_packing = (align > pointer_size);
+
+ if (needs_packing) print_file( file, 0, "#include <pshpack%u.h>\n", pointer_size );
+ print_file(file, 1, "struct _PARAM_STRUCT\n" );
+ print_file(file, 1, "{\n" );
+ if (is_object( iface )) print_file(file, 2, "%s *This;\n", iface->name );
+
+ if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
+ {
+ print_file(file, 2, "%s", "");
+ write_type_left( file, (type_t *)arg->type, TRUE );
+ if (needs_space_after( arg->type )) fputc( ' ', file );
+ if (is_array( arg->type ) && !type_array_is_decl_as_ptr( arg->type )) fputc( '*', file );
+
+ /* FIXME: should check for large args being passed by pointer */
+ align = 0;
+ if (is_array( arg->type ) || is_ptr( arg->type )) align = pointer_size;
+ else type_memsize_and_alignment( arg->type, &align );
+
+ if (align >= pointer_size)
+ fprintf( file, "%s;\n", arg->name );
+ else
+ fprintf( file, "%s DECLSPEC_ALIGN(%u);\n", arg->name, pointer_size );
+ }
+ if (add_retval && !is_void( rettype ))
+ {
+ print_file(file, 2, "%s", "");
+ write_type_decl( file, rettype, "_RetVal" );
+ if (is_array( rettype ) || is_ptr( rettype ) || type_memsize( rettype ) == pointer_size)
+ fprintf( file, ";\n" );
+ else
+ fprintf( file, " DECLSPEC_ALIGN(%u);\n", pointer_size );
+ }
+ print_file(file, 1, "} %s;\n", var_decl );
+ if (needs_packing) print_file( file, 0, "#include <poppack.h>\n" );
+ print_file( file, 0, "\n" );
+}
+
+void write_pointer_checks( FILE *file, int indent, const var_t *func )
+{
+ const var_list_t *args = type_get_function_args( func->type );
+ const var_t *var;
+
+ if (!args) return;
+
+ LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
+ if (cant_be_null( var ))
+ print_file( file, indent, "if (!%s) RpcRaiseException(RPC_X_NULL_REF_POINTER);\n", var->name );
+}
+
int write_expr_eval_routines(FILE *file, const char *iface)
{
static const char *var_name = "pS";
LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
{
- const char *name = eval->structure->name;
+ const char *name = eval->name;
result = 1;
print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
- iface, name, callback_offset);
+ eval->iface ? eval->iface->name : iface, name, callback_offset);
print_file(file, 0, "{\n");
- print_file(file, 1, "%s", "");
- write_type_left(file, (type_t *)eval->structure, TRUE);
- fprintf(file, " *%s = (", var_name);
- write_type_left(file, (type_t *)eval->structure, TRUE);
- fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff);
+ if (type_get_type( eval->cont_type ) == TYPE_FUNCTION)
+ {
+ write_func_param_struct( file, eval->iface, eval->cont_type,
+ "*pS = (struct _PARAM_STRUCT *)pStubMsg->StackTop", FALSE );
+ }
+ else
+ {
+ print_file(file, 1, "%s", "");
+ write_type_left(file, (type_t *)eval->cont_type, TRUE);
+ fprintf(file, " *%s = (", var_name);
+ write_type_left(file, (type_t *)eval->cont_type, TRUE);
+ fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff);
+ }
print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
print_file(file, 1, "pStubMsg->MaxCount = (ULONG_PTR)");
- write_expr(file, eval->expr, 1, 1, var_name_expr, eval->structure, "");
+ write_expr(file, eval->expr, 1, 1, var_name_expr, eval->cont_type, "");
fprintf(file, ";\n");
print_file(file, 0, "}\n\n");
callback_offset++;
LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
{
- const char *name = eval->structure->name;
- print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, name, callback_offset);
+ print_file(file, 1, "%s_%sExprEval_%04u,\n",
+ eval->iface ? eval->iface->name : iface, eval->name, callback_offset);
callback_offset++;
list_remove(&eval->entry);
+ free(eval->name);
free(eval);
}
error("Invalid endpoint syntax '%s'\n", endpoint->str);
}
+void write_client_call_routine( FILE *file, const type_t *iface, const var_t *func,
+ const char *prefix, unsigned int proc_offset )
+{
+ type_t *rettype = type_function_get_rettype( func->type );
+ int has_ret = !is_void( rettype );
+ const var_list_t *args = type_get_function_args( func->type );
+ const var_t *arg;
+ int len, needs_params = 0;
+
+ /* we need a param structure if we have more than one arg */
+ if (pointer_size == 4 && args) needs_params = is_object( iface ) || list_count( args ) > 1;
+
+ print_file( file, 0, "{\n");
+ if (needs_params)
+ {
+ if (has_ret) print_file( file, 1, "%s", "CLIENT_CALL_RETURN _RetVal;\n" );
+ write_func_param_struct( file, iface, func->type, "__params", FALSE );
+ if (is_object( iface )) print_file( file, 1, "__params.This = This;\n" );
+ if (args)
+ LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
+ print_file( file, 1, "__params.%s = %s;\n", arg->name, arg->name );
+ }
+ else if (has_ret) print_file( file, 1, "%s", "CLIENT_CALL_RETURN _RetVal;\n\n" );
+
+ len = fprintf( file, " %s%s( ",
+ has_ret ? "_RetVal = " : "",
+ get_stub_mode() == MODE_Oif ? "NdrClientCall2" : "NdrClientCall" );
+ fprintf( file, "&%s_StubDesc,", prefix );
+ fprintf( file, "\n%*s&__MIDL_ProcFormatString.Format[%u]", len, "", proc_offset );
+ if (needs_params)
+ {
+ fprintf( file, ",\n%*s&__params", len, "" );
+ }
+ else if (pointer_size == 8)
+ {
+ if (is_object( iface )) fprintf( file, ",\n%*sThis", len, "" );
+ if (args)
+ LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
+ fprintf( file, ",\n%*s%s", len, "", arg->name );
+ }
+ else
+ {
+ if (is_object( iface )) fprintf( file, ",\n%*s&This", len, "" );
+ else if (args)
+ {
+ arg = LIST_ENTRY( list_head(args), const var_t, entry );
+ fprintf( file, ",\n%*s&%s", len, "", arg->name );
+ }
+ }
+ fprintf( file, " );\n" );
+ if (has_ret)
+ {
+ print_file( file, 1, "return (" );
+ write_type_decl_left(file, rettype);
+ fprintf( file, ")%s;\n", pointer_size == 8 ? "_RetVal.Simple" : "*(LONG_PTR *)&_RetVal" );
+ }
+ print_file( file, 0, "}\n\n");
+}
+
void write_exceptions( FILE *file )
{
fprintf( file, "#ifndef USE_COMPILER_EXCEPTIONS\n");