diff --git a/reactos/tools/widl/ChangeLog b/reactos/tools/widl/ChangeLog index dbd7b3a74bf..6c3d395b3cb 100644 --- a/reactos/tools/widl/ChangeLog +++ b/reactos/tools/widl/ChangeLog @@ -1,12 +1,20 @@ ChangeLog -2004-05-08 weiden +2005-07-17 ekohl + + tools/widl/client.c + tools/widl/server.c + +Fix bugs for in-string parameters. +Implement out-string parameters (untested). + +2005-05-08 weiden tools/widl/server.c Don't generate lvalue assignment code. -2004-05-08 weiden +2005-05-08 weiden tools/widl/client.c tools/widl/proxy.c @@ -154,7 +162,7 @@ Merge in Winehq changes to reduce noise. tools/widl/server.h tools/widl/client.h - tools/widl/proxy.h + tools/widl/proxy.h Deleted unneeded headers. diff --git a/reactos/tools/widl/client.c b/reactos/tools/widl/client.c index aec81d0b2c6..d4b879d284b 100644 --- a/reactos/tools/widl/client.c +++ b/reactos/tools/widl/client.c @@ -56,6 +56,130 @@ static int print_client( const char *format, ... ) } +static unsigned int +get_var_stack_offset_32(func_t *func, char *name) +{ + unsigned int offset = 0; + var_t *var; + + var = func->args; + while (NEXT_LINK(var)) var = NEXT_LINK(var); + while (var) + { + if (!strcmp(var->name, name)) + return offset; + + if (var->type->type == RPC_FC_DOUBLE || + var->type->type == RPC_FC_HYPER) + offset += 8; + else + offset += 4; + + var = PREV_LINK(var); + } + + return 0; +} + + +static unsigned int +get_var_stack_offset_64(func_t *func, char *name) +{ + unsigned int offset = 0; + var_t *var; + + var = func->args; + while (NEXT_LINK(var)) var = NEXT_LINK(var); + while (var) + { + if (!strcmp(var->name, name)) + return offset; + + offset += 8; + + var = PREV_LINK(var); + } + + return 0; +} + + +static unsigned int +get_var_type_offset(var_t *var) +{ + unsigned int toffset = 0; + void *size_is_attr; + int string_attr; + + if (var->ptr_level == 0) + { + if ((var->type->type == RPC_FC_RP) && + (var->type->ref->ref->type == RPC_FC_STRUCT)) + { + var_t *field = var->type->ref->ref->fields; + int tsize = 9; + + while (NEXT_LINK(field)) field = NEXT_LINK(field); + while (field) + { + tsize++; + field = PREV_LINK(field); + } + if (tsize % 2) + tsize++; + + toffset += tsize; + } + } + else if (var->ptr_level == 1) + { + size_is_attr = get_attrp(var->attrs, ATTR_SIZEIS); + string_attr = is_attr(var->attrs, ATTR_STRING); + + if (size_is_attr) + { + if (string_attr) + { + if (var->type->type == RPC_FC_BYTE || + var->type->type == RPC_FC_CHAR || + var->type->type == RPC_FC_WCHAR) + toffset += 10; + } + else + { + if (is_base_type(var->type)) + toffset += 14; + } + } + else + { + if (is_base_type(var->type)) + toffset += 4; + } + } + + return toffset; +} + + +static type_t *get_type_by_name(func_t *func, char *name) +{ + var_t *var; + + var = func->args; + while (NEXT_LINK(var)) var = NEXT_LINK(var); + while (var) + { + if (!strcmp(var->name, name)) + return var->type; + + var = PREV_LINK(var); + } + + return NULL; +} + + static unsigned char get_base_type(unsigned char type) { @@ -134,6 +258,45 @@ static int get_type_size(type_t *type, int alignment) } +static int get_type_alignment(type_t *type) +{ + int size; + + switch(type->type) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + size = 1; + break; + + case RPC_FC_WCHAR: + case RPC_FC_USHORT: + case RPC_FC_SHORT: + size = 2; + break; + + case RPC_FC_ULONG: + case RPC_FC_LONG: + case RPC_FC_FLOAT: + size = 4; + break; + + case RPC_FC_HYPER: + case RPC_FC_DOUBLE: + size = 8; + break; + + default: + error("%s:%d Unknown/unsupported type 0x%x\n", + __FUNCTION__,__LINE__, type->type); + return 0; + } + + return size; +} + + static void write_procformatstring(type_t *iface) { func_t *func = iface->funcs; @@ -281,9 +444,11 @@ static void write_typeformatstring(type_t *iface) { func_t *func = iface->funcs; var_t *var; + type_t *type; int in_attr, out_attr; int string_attr; int ptr_attr, ref_attr, unique_attr; + void *sizeis_attr; print_client("const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n"); print_client("{\n"); @@ -361,11 +526,58 @@ static void write_typeformatstring(type_t *iface) ptr_attr = is_attr(var->attrs, ATTR_PTR); ref_attr = is_attr(var->attrs, ATTR_REF); unique_attr = is_attr(var->attrs, ATTR_UNIQUE); + sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS); if (ptr_attr + ref_attr + unique_attr == 0) ref_attr = 1; - if (is_base_type(var->type)) + if (sizeis_attr && out_attr) + { + unsigned char type_type = 0; + + type = get_type_by_name(func, ((expr_t *)sizeis_attr)->u.sval); + if (type != NULL) + type_type = type->type; + + print_client("0x11, 0x00, /* FC_RP */\n"); + print_client("NdrFcShort(0x02),\n"); + + if (string_attr) + { + if (var->type->type == RPC_FC_WCHAR) + print_client("0x25, /* FC_C_WSTRING */\n"); + else + print_client("0x22, /* FC_C_CSTRING */\n"); + print_client("0x44, /* FC_STRING_SIZED */\n"); + print_client("0x%02x,\n", 0x20 + type_type); + print_client("0x00,\n"); + + fprintf(client, "#ifndef _APLHA_\n"); + print_client("NdrFcShort(0x%02X),\n", + get_var_stack_offset_32(func, ((expr_t *)sizeis_attr)->u.sval)); + fprintf(client, "#else\n"); + print_client("NdrFcShort(0x%02X),\n", + get_var_stack_offset_64(func, ((expr_t *)sizeis_attr)->u.sval)); + fprintf(client, "#endif\n"); + } + else + { + print_client("0x1b, /* FC_CARRAY */\n"); + print_client("0x%02x,\n", get_type_alignment(var->type) - 1); + print_client("NdrFcShort(0x%02x),\n", get_type_size(var->type, 1)); + print_client("0x%02x,\n", 0x20 + type_type); + print_client("0x00,\n"); + + fprintf(client, "#ifndef _APLHA_\n"); + print_client("NdrFcShort(0x04),\n"); + fprintf(client, "#else\n"); + print_client("NdrFcShort(0x08),\n"); + fprintf(client, "#endif\n"); + print_client("0x%02x,\n", get_base_type(var->type->type)); + print_client("0x5b, /* FC_END */\n"); + } + } + else if (is_base_type(var->type)) { if (out_attr) print_client("0x11, 0x0c, /* FC_RP [allocated_on_stack] [simple_pointer] */\n"); @@ -401,8 +613,6 @@ static void write_typeformatstring(type_t *iface) } } - - func = PREV_LINK(func); } @@ -695,30 +905,7 @@ static void print_message_buffer_size(func_t *func, unsigned int *type_offset) } /* calculate the next type offset */ - if (var->ptr_level == 0) - { - if ((var->type->type == RPC_FC_RP) && - (var->type->ref->ref->type == RPC_FC_STRUCT)) - { - var_t *field = var->type->ref->ref->fields; - int tsize = 9; - - while (NEXT_LINK(field)) field = NEXT_LINK(field); - while (field) - { - tsize++; - field = PREV_LINK(field); - } - if (tsize % 2) - tsize++; - - local_type_offset += tsize; - } - } - else if (var->ptr_level == 1) - { - local_type_offset += 4; - } + local_type_offset += get_var_type_offset(var); } if (nothing_printed) @@ -783,6 +970,8 @@ static void marshall_in_arguments(func_t *func, unsigned int *type_offset) print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n", *type_offset + 2); indent--; fprintf(client, "\n"); + print_client("_StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~0x3);\n"); + fprintf(client, "\n"); } else { @@ -946,30 +1135,7 @@ static void marshall_in_arguments(func_t *func, unsigned int *type_offset) } /* calculate the next type offset */ - if (var->ptr_level == 0) - { - if ((var->type->type == RPC_FC_RP) && - (var->type->ref->ref->type == RPC_FC_STRUCT)) - { - var_t *field = var->type->ref->ref->fields; - int tsize = 9; - - while (NEXT_LINK(field)) field = NEXT_LINK(field); - while (field) - { - tsize++; - field = PREV_LINK(field); - } - if (tsize % 2) - tsize++; - - local_type_offset += tsize; - } - } - else if (var->ptr_level == 1) - { - local_type_offset += 4; - } + local_type_offset += get_var_type_offset(var); } } @@ -980,6 +1146,8 @@ static void unmarshall_out_arguments(func_t *func, unsigned int *type_offset) unsigned int size; unsigned int last_size = 0; int out_attr; + int string_attr; + void *sizeis_attr; var_t *var; var_t *def; unsigned int local_type_offset = *type_offset; @@ -994,6 +1162,9 @@ static void unmarshall_out_arguments(func_t *func, unsigned int *type_offset) for (; var; var = PREV_LINK(var)) { out_attr = is_attr(var->attrs, ATTR_OUT); + sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS); + string_attr = is_attr(var->attrs, ATTR_STRING); + if (out_attr) { if (var->ptr_level > 1) @@ -1003,7 +1174,38 @@ static void unmarshall_out_arguments(func_t *func, unsigned int *type_offset) return; } - if (is_base_type(var->type)) + if (sizeis_attr != NULL) + { + if (string_attr) + { + fprintf(client, "\n"); + print_client("NdrConformantStringUnmarshall(\n"); + indent++; + print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n"); + print_client("(unsigned char __RPC_FAR * __RPC_FAR *)&%s,\n", var->name); + print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u],\n", + *type_offset + 4); + print_client("(unsigned char)0);\n"); + indent--; + fprintf(client, "\n"); + print_client("_StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~0x3);\n"); + fprintf(client, "\n"); + } + else + { + fprintf(client, "\n"); + print_client("NdrConformantArrayUnmarshall(\n"); + indent++; + print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n"); + print_client("(unsigned char __RPC_FAR * __RPC_FAR *)&%s,\n", var->name); + print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u],\n", + *type_offset + 4); + print_client("(unsigned char)0);\n"); + indent--; + fprintf(client, "\n"); + } + } + else if (is_base_type(var->type)) { alignment = 0; switch (var->type->type) @@ -1095,30 +1297,7 @@ static void unmarshall_out_arguments(func_t *func, unsigned int *type_offset) } /* calculate the next type offset */ - if (var->ptr_level == 0) - { - if ((var->type->type == RPC_FC_RP) && - (var->type->ref->ref->type == RPC_FC_STRUCT)) - { - var_t *field = var->type->ref->ref->fields; - int tsize = 9; - - while (NEXT_LINK(field)) field = NEXT_LINK(field); - while (field) - { - tsize++; - field = PREV_LINK(field); - } - if (tsize % 2) - tsize++; - - local_type_offset += tsize; - } - } - else if (var->ptr_level == 1) - { - local_type_offset += 4; - } + local_type_offset += get_var_type_offset(var); } } @@ -1394,30 +1573,8 @@ static void write_function_stubs(type_t *iface) while (NEXT_LINK(var)) var = NEXT_LINK(var); while (var) { - if (var->ptr_level == 0) - { - if ((var->type->type == RPC_FC_RP) && - (var->type->ref->ref->type == RPC_FC_STRUCT)) - { - var_t *field = var->type->ref->ref->fields; - int tsize = 9; + type_offset += get_var_type_offset(var); - while (NEXT_LINK(field)) field = NEXT_LINK(field); - while (field) - { - tsize++; - field = PREV_LINK(field); - } - if (tsize % 2) - tsize++; - - type_offset += tsize; - } - } - else if (var->ptr_level == 1) - { - type_offset += 4; - } var = PREV_LINK(var); } } @@ -1596,30 +1753,7 @@ static int get_type_format_string_size(type_t *iface) while (NEXT_LINK(var)) var = NEXT_LINK(var); while (var) { - if (var->ptr_level == 0) - { - if (var->type->type == RPC_FC_RP) - { - var_t *field = var->type->ref->ref->fields; - int tsize = 9; - - while (NEXT_LINK(field)) field = NEXT_LINK(field); - while (field) - { - tsize ++; - field = PREV_LINK(field); - } - if (tsize % 2) - tsize++; - size += tsize; - } - } - else if (var->ptr_level == 1) - { - if (is_base_type(var->type)) - size += 4; - } - + size += get_var_type_offset(var); var = PREV_LINK(var); } } diff --git a/reactos/tools/widl/server.c b/reactos/tools/widl/server.c index 8509291e9b0..0f1a9496643 100644 --- a/reactos/tools/widl/server.c +++ b/reactos/tools/widl/server.c @@ -61,6 +61,130 @@ static int print_server(const char *format, ...) } +static unsigned int +get_var_stack_offset_32(func_t *func, char *name) +{ + unsigned int offset = 0; + var_t *var; + + var = func->args; + while (NEXT_LINK(var)) var = NEXT_LINK(var); + while (var) + { + if (!strcmp(var->name, name)) + return offset; + + if (var->type->type == RPC_FC_DOUBLE || + var->type->type == RPC_FC_HYPER) + offset += 8; + else + offset += 4; + + var = PREV_LINK(var); + } + + return 0; +} + + +static unsigned int +get_var_stack_offset_64(func_t *func, char *name) +{ + unsigned int offset = 0; + var_t *var; + + var = func->args; + while (NEXT_LINK(var)) var = NEXT_LINK(var); + while (var) + { + if (!strcmp(var->name, name)) + return offset; + + offset += 8; + + var = PREV_LINK(var); + } + + return 0; +} + + +static unsigned int +get_var_type_offset(var_t *var) +{ + unsigned int toffset = 0; + void *size_is_attr; + int string_attr; + + if (var->ptr_level == 0) + { + if ((var->type->type == RPC_FC_RP) && + (var->type->ref->ref->type == RPC_FC_STRUCT)) + { + var_t *field = var->type->ref->ref->fields; + int tsize = 9; + + while (NEXT_LINK(field)) field = NEXT_LINK(field); + while (field) + { + tsize++; + field = PREV_LINK(field); + } + if (tsize % 2) + tsize++; + + toffset += tsize; + } + } + else if (var->ptr_level == 1) + { + size_is_attr = get_attrp(var->attrs, ATTR_SIZEIS); + string_attr = is_attr(var->attrs, ATTR_STRING); + + if (size_is_attr) + { + if (string_attr) + { + if (var->type->type == RPC_FC_BYTE || + var->type->type == RPC_FC_CHAR || + var->type->type == RPC_FC_WCHAR) + toffset += 10; + } + else + { + if (is_base_type(var->type)) + toffset += 14; + } + } + else + { + if (is_base_type(var->type)) + toffset += 4; + } + } + + return toffset; +} + + +static type_t *get_type_by_name(func_t *func, char *name) +{ + var_t *var; + + var = func->args; + while (NEXT_LINK(var)) var = NEXT_LINK(var); + while (var) + { + if (!strcmp(var->name, name)) + return var->type; + + var = PREV_LINK(var); + } + + return NULL; +} + + static unsigned char get_base_type(unsigned char type) { @@ -139,6 +263,45 @@ static int get_type_size(type_t *type, int alignment) } +static int get_type_alignment(type_t *type) +{ + int size; + + switch(type->type) + { + case RPC_FC_BYTE: + case RPC_FC_CHAR: + case RPC_FC_SMALL: + size = 1; + break; + + case RPC_FC_WCHAR: + case RPC_FC_USHORT: + case RPC_FC_SHORT: + size = 2; + break; + + case RPC_FC_ULONG: + case RPC_FC_LONG: + case RPC_FC_FLOAT: + size = 4; + break; + + case RPC_FC_HYPER: + case RPC_FC_DOUBLE: + size = 8; + break; + + default: + error("%s:%d Unknown/unsupported type 0x%x\n", + __FUNCTION__,__LINE__, type->type); + return 0; + } + + return size; +} + + static void write_procformatstring(type_t *iface) { func_t *func = iface->funcs; @@ -278,9 +441,11 @@ static void write_typeformatstring(type_t *iface) { func_t *func = iface->funcs; var_t *var; + type_t *type; int in_attr, out_attr; int string_attr; int ptr_attr, ref_attr, unique_attr; + void *sizeis_attr; print_server("const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n"); print_server("{\n"); @@ -358,11 +523,58 @@ static void write_typeformatstring(type_t *iface) ptr_attr = is_attr(var->attrs, ATTR_PTR); ref_attr = is_attr(var->attrs, ATTR_REF); unique_attr = is_attr(var->attrs, ATTR_UNIQUE); + sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS); if (ptr_attr + ref_attr + unique_attr == 0) ref_attr = 1; - if (is_base_type(var->type)) + if (sizeis_attr != NULL && out_attr) + { + unsigned char type_type = 0; + + type = get_type_by_name(func, ((expr_t *)sizeis_attr)->u.sval); + if (type != NULL) + type_type = type->type; + + print_server("0x11, 0x00, /* FC_RP */\n"); + print_server("NdrFcShort(0x02),\n"); + + if (string_attr) + { + if (var->type->type == RPC_FC_WCHAR) + print_server("0x25, /* FC_C_WSTRING */\n"); + else + print_server("0x22, /* FC_C_CSTRING */\n"); + print_server("0x44, /* FC_STRING_SIZED */\n"); + print_server("0x%02x,\n", 0x20 + type_type); + print_server("0x00,\n"); + + fprintf(server, "#ifndef _APLHA_\n"); + print_server("NdrFcShort(0x%02X),\n", + get_var_stack_offset_32(func, ((expr_t *)sizeis_attr)->u.sval)); + fprintf(server, "#else\n"); + print_server("NdrFcShort(0x%02X),\n", + get_var_stack_offset_64(func, ((expr_t *)sizeis_attr)->u.sval)); + fprintf(server, "#endif\n"); + } + else + { + print_server("0x1b, /* FC_CARRAY */\n"); + print_server("0x%02x,\n", get_type_alignment(var->type) - 1); + print_server("NdrFcShort(0x%02x),\n", get_type_size(var->type, 1)); + print_server("0x%02x,\n", 0x20 + type_type); + print_server("0x00,\n"); + + fprintf(server, "#ifndef _APLHA_\n"); + print_server("NdrFcShort(0x04),\n"); + fprintf(server, "#else\n"); + print_server("NdrFcShort(0x08),\n"); + fprintf(server, "#endif\n"); + print_server("0x%02x,\n", get_base_type(var->type->type)); + print_server("0x5b, /* FC_END */\n"); + } + } + else if (is_base_type(var->type)) { if (out_attr) print_server("0x11, 0x0c, /* FC_RP [allocated_on_stack] [simple_pointer] */\n"); @@ -420,9 +632,11 @@ static void print_message_buffer_size(func_t *func, unsigned int *type_offset) int in_attr; int out_attr; int string_attr; + void *sizeis_attr; int empty_line; var_t *var; + int add_return = 0; int start_new_line = 0; int add_plus = 0; @@ -437,9 +651,26 @@ static void print_message_buffer_size(func_t *func, unsigned int *type_offset) for (; var; var = PREV_LINK(var)) { out_attr = is_attr(var->attrs, ATTR_OUT); + string_attr = is_attr(var->attrs, ATTR_STRING); + sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS); + if (out_attr) { - if (is_base_type(var->type)) + if (var->ptr_level == 1 && + string_attr && + sizeis_attr != NULL && + (var->type->type == RPC_FC_BYTE || + var->type->type == RPC_FC_CHAR || + var->type->type == RPC_FC_WCHAR)) + { + fprintf(server, " 12U"); + add_return = 6; + if (var->type->type == RPC_FC_BYTE || + var->type->type == RPC_FC_CHAR) + add_return++; + add_plus = 1; + } + else if (is_base_type(var->type)) { if (start_new_line) { @@ -519,30 +750,7 @@ static void print_message_buffer_size(func_t *func, unsigned int *type_offset) } /* calculate the next type offset */ - if (var->ptr_level == 0) - { - if ((var->type->type == RPC_FC_RP) && - (var->type->ref->ref->type == RPC_FC_STRUCT)) - { - var_t *field = var->type->ref->ref->fields; - int tsize = 9; - - while (NEXT_LINK(field)) field = NEXT_LINK(field); - while (field) - { - tsize++; - field = PREV_LINK(field); - } - if (tsize % 2) - tsize++; - - local_type_offset += tsize; - } - } - else if (var->ptr_level == 1) - { - local_type_offset += 4; - } + local_type_offset += get_var_type_offset(var); } } } @@ -588,10 +796,60 @@ static void print_message_buffer_size(func_t *func, unsigned int *type_offset) if (add_plus) fprintf(server, " +"); - fprintf(server, " %dU", (size == 0) ? 0 : size + alignment); + fprintf(server, " %dU", (size == 0) ? 0 : size + alignment + add_return); } fprintf(server, ";\n"); + + if (func->args) + { + local_type_offset = *type_offset; + + empty_line = 0; + var = func->args; + while (NEXT_LINK(var)) var = NEXT_LINK(var); + for (; var; var = PREV_LINK(var)) + { + out_attr = is_attr(var->attrs, ATTR_OUT); + in_attr = is_attr(var->attrs, ATTR_IN); + string_attr = is_attr(var->attrs, ATTR_STRING); + sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS); + + /* set 'in' attribute if neither 'in' nor 'out' is found */ + if (!out_attr && !in_attr) + in_attr = 1; + + if (out_attr) + { + if (var->ptr_level == 1 && + string_attr && + sizeis_attr != NULL && + (var->type->type == RPC_FC_BYTE || + var->type->type == RPC_FC_CHAR || + var->type->type == RPC_FC_WCHAR)) + { + print_server("_StubMsg.MaxCount = %s;\n", ((expr_t *)sizeis_attr)->u.sval); + fprintf(server, "\n"); + print_server("NdrConformantStringBufferSize(\n"); + indent++; + print_server("(PMIDL_STUB_MESSAGE)&_StubMsg,\n"); + print_server("(unsigned char __RPC_FAR *)%s,\n", var->name); + print_server("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n", + local_type_offset + 4); + indent--; + + empty_line = 1; + } + + /* calculate the next type offset */ + local_type_offset += get_var_type_offset(var); + } + } + + if (empty_line) + fprintf(server, "\n"); + } + /* get string size */ if (func->args) { @@ -610,7 +868,9 @@ static void print_message_buffer_size(func_t *func, unsigned int *type_offset) if (var->ptr_level == 1 && string_attr && - (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR)) + (var->type->type == RPC_FC_BYTE || + var->type->type == RPC_FC_CHAR || + var->type->type == RPC_FC_WCHAR)) { print_server("_StubMsg.BufferLength += 16;\n"); empty_line = 1; @@ -645,9 +905,9 @@ static void init_pointers (func_t *func) } else if (var->ptr_level == 1) { - print_server("*("); + print_server("("); write_type(server, var->type, NULL, var->tname); - fprintf(server, " __RPC_FAR *)&%s = 0;\n", var->name); + fprintf(server, " __RPC_FAR *)%s = 0;\n", var->name); } else if (var->ptr_level > 1) { @@ -711,6 +971,8 @@ static void unmarshall_in_arguments(func_t *func, unsigned int *type_offset) print_server("(unsigned char)0);\n"); indent--; fprintf(server, "\n"); + print_server("_StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~0x3);\n"); + fprintf(server, "\n"); } else { @@ -874,30 +1136,7 @@ static void unmarshall_in_arguments(func_t *func, unsigned int *type_offset) } /* calculate the next type offset */ - if (var->ptr_level == 0) - { - if ((var->type->type == RPC_FC_RP) && - (var->type->ref->ref->type == RPC_FC_STRUCT)) - { - var_t *field = var->type->ref->ref->fields; - int tsize = 9; - - while (NEXT_LINK(field)) field = NEXT_LINK(field); - while (field) - { - tsize++; - field = PREV_LINK(field); - } - if (tsize % 2) - tsize++; - - local_type_offset += tsize; - } - } - else if (var->ptr_level == 1) - { - local_type_offset += 4; - } + local_type_offset += get_var_type_offset(var); } } @@ -910,6 +1149,8 @@ static void marshall_out_arguments(func_t *func, unsigned int *type_offset) var_t *var; var_t *def; int out_attr; + int string_attr; + void *sizeis_attr; unsigned int local_type_offset = *type_offset; def = func->def; @@ -924,7 +1165,29 @@ static void marshall_out_arguments(func_t *func, unsigned int *type_offset) out_attr = is_attr(var->attrs, ATTR_OUT); if (out_attr) { - if (is_base_type(var->type)) + sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS); + string_attr = is_attr(var->attrs, ATTR_STRING); + + if (sizeis_attr != NULL) + { + if (string_attr) + { + fprintf(server, "\n"); + print_server("_StubMsg.MaxCount = %s;\n", ((expr_t *)sizeis_attr)->u.sval); + fprintf(server, "\n"); + print_server("NdrConformantStringMarshall(\n"); + indent++; + print_server("(PMIDL_STUB_MESSAGE)&_StubMsg,\n"); + print_server("(unsigned char __RPC_FAR *)%s,\n", var->name); + print_server("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n", + local_type_offset + 4); + indent--; + fprintf(server, "\n"); + print_server("_StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~0x3);\n"); + fprintf(server, "\n"); + } + } + else if (is_base_type(var->type)) { alignment = 0; switch (var->type->type) @@ -1010,30 +1273,7 @@ static void marshall_out_arguments(func_t *func, unsigned int *type_offset) } /* calculate the next type offset */ - if (var->ptr_level == 0) - { - if ((var->type->type == RPC_FC_RP) && - (var->type->ref->ref->type == RPC_FC_STRUCT)) - { - var_t *field = var->type->ref->ref->fields; - int tsize = 9; - - while (NEXT_LINK(field)) field = NEXT_LINK(field); - while (field) - { - tsize++; - field = PREV_LINK(field); - } - if (tsize % 2) - tsize++; - - local_type_offset += tsize; - } - } - else if (var->ptr_level == 1) - { - local_type_offset += 4; - } + local_type_offset += get_var_type_offset(var); } } @@ -1107,6 +1347,67 @@ static int use_return_buffer(func_t *func) } +static void cleanup_return_buffer(func_t *func, unsigned int *type_offset) +{ + var_t *var; + int string_attr; + void *sizeis_attr; + unsigned int local_type_offset = *type_offset; + + if (func->args) + { + int first_arg = 1; + + var = func->args; + while (NEXT_LINK(var)) var = NEXT_LINK(var); + while (var) + { + sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS); + string_attr = is_attr(var->attrs, ATTR_STRING); + + if (sizeis_attr != NULL) + { + if (first_arg == 0) + fprintf(server, "\n"); + + indent++; + if (string_attr) + { + print_server("_StubMsg.MaxCount = %s;\n", ((expr_t *)sizeis_attr)->u.sval); + fprintf(server, "\n"); + print_server("NdrPointerFree(\n"); + indent++; + print_server("&_StubMsg,\n"); + print_server("(unsigned char __RPC_FAR *)%s,\n", var->name); + print_server("&__MIDL_TypeFormatString.Format[%u]);\n", + local_type_offset); + indent--; + } + else + { + print_server("if ("); + write_name(server, var); + fprintf(server, ")\n"); + indent++; + print_server("_StubMsg.pfnFree("); + write_name(server, var); + fprintf(server, ");\n"); + indent--; + } + indent--; + + first_arg = 0; + } + + /* calculate the next type offset */ + local_type_offset += get_var_type_offset(var); + + var = PREV_LINK(var); + } + } +} + + static void write_function_stubs(type_t *iface) { int explicit_handle = is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE); @@ -1118,6 +1419,7 @@ static void write_function_stubs(type_t *iface) unsigned int i, sep; int in_attr; int out_attr; + void *size_is_attr; while (NEXT_LINK(func)) func = NEXT_LINK(func); while (func) @@ -1173,9 +1475,11 @@ static void write_function_stubs(type_t *iface) { in_attr = is_attr(var->attrs, ATTR_IN); out_attr = is_attr(var->attrs, ATTR_OUT); + size_is_attr = get_attrp(var->attrs, ATTR_SIZEIS); + if (!out_attr && !in_attr) in_attr = 1; - if (!in_attr) + if (!in_attr && !size_is_attr) { if (var->type->type == RPC_FC_RP) { @@ -1275,22 +1579,36 @@ static void write_function_stubs(type_t *iface) out_attr = is_attr(var->attrs, ATTR_OUT); if (!out_attr && !in_attr) in_attr = 1; + + size_is_attr = get_attrp(var->attrs, ATTR_SIZEIS); + if (!in_attr) { - if (var->type->type == RPC_FC_RP) + if (size_is_attr != NULL) { print_server(""); write_name(server, var); - fprintf(server, " = &_%sW;\n", var->name); + fprintf(server, " = NdrAllocate(&_StubMsg, %s * %d);\n", + ((expr_t *)size_is_attr)->u.sval, get_type_size(var->type, 1)); sep = 1; } else { - print_server(""); - write_name(server, var); - fprintf(server, " = &_W%u;\n", i); - i++; - sep = 1; + if (var->type->type == RPC_FC_RP) + { + print_server(""); + write_name(server, var); + fprintf(server, " = &_%sW;\n", var->name); + sep = 1; + } + else + { + print_server(""); + write_name(server, var); + fprintf(server, " = &_W%u;\n", i); + i++; + sep = 1; + } } } @@ -1356,6 +1674,9 @@ static void write_function_stubs(type_t *iface) print_server("}\n"); print_server("RpcFinally\n"); print_server("{\n"); + + cleanup_return_buffer(func, &type_offset); + print_server("}\n"); print_server("RpcEndFinally\n"); @@ -1376,30 +1697,8 @@ static void write_function_stubs(type_t *iface) while (NEXT_LINK(var)) var = NEXT_LINK(var); while (var) { - if (var->ptr_level == 0) - { - if ((var->type->type == RPC_FC_RP) && - (var->type->ref->ref->type == RPC_FC_STRUCT)) - { - var_t *field = var->type->ref->ref->fields; - int tsize = 9; + type_offset += get_var_type_offset(var); - while (NEXT_LINK(field)) field = NEXT_LINK(field); - while (field) - { - tsize++; - field = PREV_LINK(field); - } - if (tsize % 2) - tsize++; - - type_offset += tsize; - } - } - else if (var->ptr_level == 1) - { - type_offset += 4; - } var = PREV_LINK(var); } } @@ -1411,7 +1710,19 @@ static void write_function_stubs(type_t *iface) while (NEXT_LINK(var)) var = NEXT_LINK(var); while (var) { - proc_offset += 2; /* FIXME */ + switch (var->ptr_level) + { + case 0: + if (is_base_type(var->type)) + proc_offset += 2; + break; + + case 1: + if (is_base_type(var->type)) + proc_offset += 4; + break; + } + var = PREV_LINK(var); } } @@ -1528,6 +1839,7 @@ static void write_serverinterfacedecl(type_t *iface) fprintf(server, "\n"); } + static void write_formatdesc( const char *str ) { print_server("typedef struct _MIDL_%s_FORMAT_STRING\n", str ); @@ -1540,13 +1852,14 @@ static void write_formatdesc( const char *str ) print_server("\n"); } + static int get_type_format_string_size(type_t *iface) { int size = 3; func_t *func; var_t *var; - /* determine the proc format string size */ + /* determine the type format string size */ func = iface->funcs; while (NEXT_LINK(func)) func = NEXT_LINK(func); while (func) @@ -1558,30 +1871,7 @@ static int get_type_format_string_size(type_t *iface) while (NEXT_LINK(var)) var = NEXT_LINK(var); while (var) { - if (var->ptr_level == 0) - { - if (var->type->type == RPC_FC_RP) - { - var_t *field = var->type->ref->ref->fields; - int tsize = 9; - - while (NEXT_LINK(field)) field = NEXT_LINK(field); - while (field) - { - tsize ++; - field = PREV_LINK(field); - } - if (tsize % 2) - tsize++; - size += tsize; - } - } - else if (var->ptr_level == 1) - { - if (is_base_type(var->type)) - size += 4; - } - + size += get_var_type_offset(var); var = PREV_LINK(var); } }