diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c index b1a5df21259..95bd60b5658 100644 --- a/dlls/rpcrt4/tests/server.c +++ b/dlls/rpcrt4/tests/server.c @@ -286,6 +286,18 @@ s_enum_ord(e_t e) } } +double +s_square_encue(encue_t *eue) +{ + switch (eue->t) + { + case E1: return eue->tagged_union.i1 * eue->tagged_union.i1; + case E2: return eue->tagged_union.f2 * eue->tagged_union.f2; + default: + return 0.0; + } +} + void s_stop(void) { @@ -409,6 +421,7 @@ basic_tests(void) static void union_tests(void) { + encue_t eue; encu_t eu; sun_t su; int i; @@ -437,6 +450,14 @@ union_tests(void) eu.t = ENCU_F; eu.tagged_union.f = 3.0; ok(square_encu(&eu) == 9.0, "RPC square_encu\n"); + + eue.t = E1; + eue.tagged_union.i1 = 8; + ok(square_encue(&eue) == 64.0, "RPC square_encue\n"); + + eue.t = E2; + eue.tagged_union.f2 = 10.0; + ok(square_encue(&eue) == 100.0, "RPC square_encue\n"); } static test_list_t * diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl index 935c4bb33b4..c33f1794ab8 100644 --- a/dlls/rpcrt4/tests/server.idl +++ b/dlls/rpcrt4/tests/server.idl @@ -165,9 +165,16 @@ interface IServer E4 = 64 } e_t; + typedef union encue switch (e_t t) + { + case E1: int i1; + case E2: float f2; + } encue_t; + double square_encu(encu_t *eu); int sum_parr(int *a[3]); int sum_pcarr([size_is(n)] int *a[], int n); int enum_ord(e_t e); + double square_encue(encue_t *eue); void stop(void); } diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c index f3958dd267f..e8f6d1fe369 100644 --- a/tools/widl/typegen.c +++ b/tools/widl/typegen.c @@ -626,6 +626,7 @@ static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_ break; case RPC_FC_WCHAR: case RPC_FC_SHORT: + case RPC_FC_ENUM16: param_type = RPC_FC_SHORT; param_type_string = "FC_SHORT"; break; @@ -634,6 +635,7 @@ static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_ param_type_string = "FC_USHORT"; break; case RPC_FC_LONG: + case RPC_FC_ENUM32: param_type = RPC_FC_LONG; param_type_string = "FC_LONG"; break; @@ -1734,12 +1736,26 @@ static size_t write_union_tfs(FILE *file, type_t *type, unsigned int *tfsoff) { const var_t *sv = LIST_ENTRY(list_head(type->fields), const var_t, entry); const type_t *st = sv->type; - size_t ss = type_memsize(st, &align); - print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type)); - print_file(file, 2, "0x%x,\t/* Switch type= %s */\n", - (ss << 4) | st->type, string_of_type(st->type)); - *tfsoff += 2; + switch (st->type) + { + case RPC_FC_CHAR: + case RPC_FC_SMALL: + case RPC_FC_USMALL: + case RPC_FC_SHORT: + case RPC_FC_USHORT: + case RPC_FC_LONG: + case RPC_FC_ULONG: + case RPC_FC_ENUM16: + case RPC_FC_ENUM32: + print_file(file, 2, "0x%x,\t/* %s */\n", type->type, string_of_type(type->type)); + print_file(file, 2, "0x%x,\t/* Switch type= %s */\n", + 0x40 | st->type, string_of_type(st->type)); + *tfsoff += 2; + break; + default: + error("union switch type must be an integer, char, or enum\n"); + } } print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", size, size); print_file(file, 2, "NdrFcShort(0x%x),\t/* %d */\n", nbranch, nbranch);