diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c index 32735a9c392..b6b25656fa7 100644 --- a/dlls/rpcrt4/tests/server.c +++ b/dlls/rpcrt4/tests/server.c @@ -329,6 +329,12 @@ s_sum_toplev_conf_cond(int *x, int a, int b, int c) return sum; } +double +s_sum_aligns(aligns_t *a) +{ + return a->c + a->i + a->s + a->d; +} + void s_stop(void) { @@ -374,6 +380,7 @@ basic_tests(void) static pvectors_t pvecs = {&vec1, &pvec2}; static sp_inner_t spi = {42}; static sp_t sp = {-13, &spi}; + static aligns_t aligns = {3, 4, 5, 6.0}; pints_t pints; ptypes_t ptypes; int i1, i2, i3, *pi2, *pi3, **ppi3; @@ -447,6 +454,8 @@ basic_tests(void) ok(enum_ord(E2) == 2, "RPC enum_ord\n"); ok(enum_ord(E3) == 3, "RPC enum_ord\n"); ok(enum_ord(E4) == 4, "RPC enum_ord\n"); + + ok(sum_aligns(&aligns) == 18.0, "RPC sum_aligns\n"); } static void diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl index 59c9477efe4..0a8c0d3731f 100644 --- a/dlls/rpcrt4/tests/server.idl +++ b/dlls/rpcrt4/tests/server.idl @@ -189,5 +189,15 @@ interface IServer int sum_toplev_conf_2n([size_is(n * 2)] int *x, int n); int sum_toplev_conf_cond([size_is(c ? a : b)] int *x, int a, int b, int c); + typedef struct + { + char c; + int i; + short s; + double d; + } aligns_t; + + double sum_aligns(aligns_t *a); + void stop(void); } diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index 2907706e387..0ec03d9411d 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -98,6 +98,8 @@ const char *string_of_type(unsigned char type) case RPC_FC_CARRAY: return "FC_CARRAY"; case RPC_FC_CVARRAY: return "FC_CVARRAY"; case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY"; + case RPC_FC_ALIGNM4: return "RPC_FC_ALIGNM4"; + case RPC_FC_ALIGNM8: return "RPC_FC_ALIGNM8"; default: error("string_of_type: unknown type 0x%02x\n", type); return NULL; @@ -682,13 +684,25 @@ static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_ static size_t fields_memsize(const var_list_t *fields, unsigned int *align) { + int have_align = FALSE; size_t size = 0; const var_t *v; if (!fields) return 0; LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry ) - size += type_memsize(v->type, align); + { + unsigned int falign = 0; + size_t fsize = type_memsize(v->type, &falign); + if (!have_align) + { + *align = falign; + have_align = TRUE; + } + size = (size + (falign - 1)) & ~(falign - 1); + size += fsize; + } + size = (size + (*align - 1)) & ~(*align - 1); return size; } @@ -1508,12 +1522,36 @@ static void write_struct_members(FILE *file, const type_t *type, unsigned int *corroff, unsigned int *typestring_offset) { const var_t *field; + unsigned short offset = 0; if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry ) { type_t *ft = field->type; if (!ft->declarray || !is_conformant_array(ft)) + { + unsigned int align = 0; + size_t size = type_memsize(ft, &align); + if ((align - 1) & offset) + { + unsigned char fc = 0; + switch (align) + { + case 4: + fc = RPC_FC_ALIGNM4; + break; + case 8: + fc = RPC_FC_ALIGNM8; + break; + default: + error("write_struct_members: cannot align type %d", ft->type); + } + print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); + offset = (offset + (align - 1)) & ~(align - 1); + *typestring_offset += 1; + } write_member_type(file, ft, field, corroff, typestring_offset); + offset += size; + } } write_end(file, typestring_offset);