- Support conformant arrays as in and out parameters.
- Fix message buffer size calculation for client and server.
Modified: trunk/reactos/tools/widl/ChangeLog
Modified: trunk/reactos/tools/widl/client.c
Modified: trunk/reactos/tools/widl/server.c

Modified: trunk/reactos/tools/widl/ChangeLog
--- trunk/reactos/tools/widl/ChangeLog	2005-07-30 19:06:53 UTC (rev 16902)
+++ trunk/reactos/tools/widl/ChangeLog	2005-07-30 19:31:52 UTC (rev 16903)
@@ -1,5 +1,13 @@
 ChangeLog
 
+2005-07-30 ekohl
+
+   tools/widl/client.c
+   tools/widl/server.c
+
+- Support conformant arrays as in and out parameters.
+- Fix message buffer size calculation for client and server.
+
 2005-07-25 ekohl
 
    tools/widl/client.c

Modified: trunk/reactos/tools/widl/client.c
--- trunk/reactos/tools/widl/client.c	2005-07-30 19:06:53 UTC (rev 16902)
+++ trunk/reactos/tools/widl/client.c	2005-07-30 19:31:52 UTC (rev 16903)
@@ -518,7 +518,7 @@
                     if (ptr_attr + ref_attr + unique_attr == 0)
                         ref_attr = 1;
 
-                    if (sizeis_attr && out_attr)
+                    if (sizeis_attr)
                     {
                         unsigned char type_type = 0;
 
@@ -553,12 +553,17 @@
                             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");
+                            if (out_attr)
+                                print_client("0x54,          /* FC_DEREFERENCE */\n");
+                            else
+                                print_client("0x00,          /*  */\n");
 
                             fprintf(client, "#ifndef _ALPHA_\n");
-                            print_client("NdrFcShort(0x04),\n");
+                            print_client("NdrFcShort(0x%02X),\n",
+                                         get_var_stack_offset_32(func, ((var_t *)sizeis_attr)->name));
                             fprintf(client, "#else\n");
-                            print_client("NdrFcShort(0x08),\n");
+                            print_client("NdrFcShort(0x%02X),\n",
+                                         get_var_stack_offset_64(func, ((var_t *)sizeis_attr)->name));
                             fprintf(client, "#endif\n");
                             print_client("0x%02x,\n", get_base_type(var->type->type));
                             print_client("0x5b,          /* FC_END */\n");
@@ -566,16 +571,23 @@
                     }
                     else if (is_base_type(var->type))
                     {
-                        if (out_attr)
-                            print_client("0x11, 0x0c,    /* FC_RP [allocated_on_stack] [simple_pointer] */\n");
+                        if (out_attr && !in_attr)
+                        {
+                            if (ref_attr)
+                                print_client("0x11, 0x0c,    /* FC_RP [allocated_on_stack] [simple_pointer] */\n");
+                            else if (unique_attr)
+                                print_client("0x12, 0x0c,    /* FC_FP [allocated_on_stack] [simple_pointer] */\n");
+                            else if (ptr_attr)
+                                print_client("0x14, 0x0c,    /* FC_FP [allocated_on_stack] [simple_pointer] */\n");
+                        }
                         else
                         {
-                            if (ptr_attr)
-                                print_client("0x14, 0x08,    /* FC_FP [simple_pointer] */\n");
-                            else if (ref_attr)
+                            if (ref_attr)
                                 print_client("0x11, 0x08,    /* FC_RP [simple_pointer] */\n");
                             else if (unique_attr)
                                 print_client("0x12, 0x08,    /* FC_UP [simple_pointer] */\n");
+                            else if (ptr_attr)
+                                print_client("0x14, 0x08,    /* FC_FP [simple_pointer] */\n");
                         }
 
                         if (string_attr)
@@ -614,6 +626,7 @@
 
 static void print_message_buffer_size(func_t *func, unsigned int *type_offset)
 {
+    unsigned int local_type_offset = *type_offset;
     unsigned int alignment;
     int size;
     int last_size = -1;
@@ -622,8 +635,9 @@
     int string_attr;
     int nothing_printed = 1;
     int ptr_attr, ref_attr, unique_attr;
+    int padding = 0, first_padding = 0;
+    void *sizeis_attr;
     var_t *var;
-    unsigned int local_type_offset = *type_offset;
 
     print_client("_StubMsg.BufferLength =");
     if (func->args)
@@ -634,7 +648,6 @@
         {
             out_attr = is_attr(var->attrs, ATTR_OUT);
             in_attr = is_attr(var->attrs, ATTR_IN);
-            string_attr = is_attr(var->attrs, ATTR_STRING);
 
             /* set 'in' attribute if neither 'in' nor 'out' is found */
             if (!out_attr && !in_attr)
@@ -651,45 +664,34 @@
             if (!in_attr)
                 continue;
 
+            string_attr = is_attr(var->attrs, ATTR_STRING);
+            sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS);
+
             if (var->ptr_level == 1)
             {
-                if (unique_attr)
+                if (string_attr && !sizeis_attr)
                 {
-                    if (string_attr &&
-                        (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR))
+                    /* non-sized conformant string */
+                    if (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR)
                     {
-                        size = 16;
+                        size = (unique_attr) ? 16 : 12;
                         alignment = 0;
-                        if (last_size != -1)
-                            fprintf(client, " +");
-                        fprintf(client, " %dU", (size == 0) ? 0 : size + alignment);
-                        nothing_printed = 0;
                     }
-                    else
-                    {
-                        size = 8;
-                        alignment = 0;
-                        if (last_size != -1)
-                            fprintf(client, " +");
-                        fprintf(client, " %dU", (size == 0) ? 0 : size + alignment);
-                        nothing_printed = 0;
-                    }
                 }
-                else if (ref_attr)
+                else if (sizeis_attr && !string_attr)
                 {
-                    if (string_attr &&
-                        (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR))
+                    /* conformant arrays */
+                    size = 4;
+                    alignment = 0;
+                    if (padding != 0)
+                        padding = 1;
+                }
+                else if (!sizeis_attr && !string_attr)
+                {
+                    /* simple pointers */
+                    if (is_base_type(var->type))
                     {
-                        size = 12;
                         alignment = 0;
-                        if (last_size != -1)
-                            fprintf(client, " +");
-                        fprintf(client, " %dU", (size == 0) ? 0 : size + alignment);
-                        nothing_printed = 0;
-                    }
-                    else
-                    {
-                        alignment = 0;
                         switch (var->type->type)
                         {
                         case RPC_FC_BYTE:
@@ -726,28 +728,18 @@
                             size = 0;
                             break;
 
-                        case 0:
-                            printf("%s\n", __FUNCTION__);
-                            printf("ptr_level %d\n", var->ptr_level);
-                            printf("Type %p\n", var->type);
-                            printf("Type %x\n", var->type->type);
-                            printf("Type name: %s\n", var->type->name);
-                            printf("Tref %p\n", var->type->ref);
-                            printf("Tref->name %s\n", var->type->ref->name);
-                            printf("Tref->ref %p\n", var->type->ref->ref);
-                            return;
-
                         default:
                             error("%s:%d Unknown/unsupported type 0x%x\n",
                                   __FUNCTION__,__LINE__, var->type->type);
                             return;
                         }
-
-                        if (last_size != -1)
-                            fprintf(client, " +");
-                        fprintf(client, " %dU", (size == 0) ? 0 : size + alignment);
-                        nothing_printed = 0;
                     }
+                    else
+                    {
+                        /* simple pointer to a struct */
+                        size = 8;
+                        alignment = 0;
+                    }
                 }
             }
             else
@@ -800,11 +792,33 @@
                           __FUNCTION__,__LINE__, var->type->type);
                     return;
                 }
+            }
 
-                if (last_size != -1)
-                    fprintf(client, " +");
-                fprintf(client, " %dU", (size == 0) ? 0 : size + alignment);
-                nothing_printed = 0;
+            if (last_size != -1)
+                fprintf(client, " +");
+            fprintf(client, " %dU", (size == 0) ? 0 : size + alignment + first_padding + padding);
+            nothing_printed = 0;
+            if (first_padding != 0)
+                first_padding = 0;
+
+            /* set paddings */
+            if (var->ptr_level == 1)
+            {
+                if (string_attr && !sizeis_attr)
+                {
+                    /* non-sized conformant string */
+                    if (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR)
+                    {
+                        first_padding = 3;
+                        padding = 3;
+                    }
+                }
+                else if (sizeis_attr && !string_attr)
+                {
+                    /* conformant arrays */
+                    first_padding = 4;
+                    padding = 3;
+                }
             }
 
             last_size = size;
@@ -827,9 +841,8 @@
         {
             out_attr = is_attr(var->attrs, ATTR_OUT);
             in_attr = is_attr(var->attrs, ATTR_IN);
-            string_attr = is_attr(var->attrs, ATTR_STRING);
 
-            /* set 'in' attribute if neither 'in' nor 'out' is found */
+            /* default to 'in' attribute */
             if (!out_attr && !in_attr)
                 in_attr = 1;
 
@@ -841,12 +854,15 @@
             if (ptr_attr + ref_attr + unique_attr == 0)
                 ref_attr = 1;
 
+            string_attr = is_attr(var->attrs, ATTR_STRING);
+            sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS);
+
             if (in_attr)
             {
-                if (var->ptr_level == 0 &&
-                    var->type->type == RPC_FC_RP)
+                if (var->ptr_level == 0)
                 {
-                    if (var->type->ref->ref->type == RPC_FC_STRUCT)
+                    if (var->type->type == RPC_FC_RP &&
+                        var->type->ref->ref->type == RPC_FC_STRUCT)
                     {
                         print_client("NdrSimpleStructBufferSize(\n");
                         indent++;
@@ -858,36 +874,60 @@
                         indent--;
                     }
                 }
-                else if (var->ptr_level == 1 &&
-                         string_attr &&
-                         (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR))
+                else if (var->ptr_level == 1)
                 {
-                    if (ptr_attr)
+                    if (string_attr)
                     {
-                        /* FIXME: not supported yet */
+                        if ((var->type->type == RPC_FC_CHAR ||
+                             var->type->type == RPC_FC_WCHAR))
+                        {
+                            if (ptr_attr)
+                            {
+                                /* FIXME: not supported yet */
+                            }
+                            if (ref_attr)
+                            {
+                                print_client("NdrConformantStringBufferSize(\n");
+                                indent++;
+                                print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
+                                print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
+                                print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
+                                             local_type_offset + 2);
+                                nothing_printed = 1;
+                                indent--;
+                            }
+                            else if (unique_attr)
+                            {
+                                print_client("NdrPointerBufferSize(\n");
+                                indent++;
+                                print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
+                                print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
+                                print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
+                                             local_type_offset);
+                                nothing_printed = 1;
+                                indent--;
+                            }
+                        }
                     }
-                    if (ref_attr)
+                    else
                     {
-                        print_client("NdrConformantStringBufferSize(\n");
-                        indent++;
-                        print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
-                        print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
-                        print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
-                                     local_type_offset + 2);
-                        nothing_printed = 1;
-                        indent--;
+                        if (sizeis_attr)
+                        {
+                            fprintf(client, "\n");
+                            print_client("_StubMsg.MaxCount = %s;\n",
+                                         ((var_t *)sizeis_attr)->name);
+                            fprintf(client, "\n");
+
+                            print_client("NdrConformantArrayBufferSize(\n");
+                            indent++;
+                            print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
+                            print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
+                            print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
+                                         local_type_offset + 4);
+                            indent--;
+                            nothing_printed = 1;
+                        }
                     }
-                    else if (unique_attr)
-                    {
-                        print_client("NdrPointerBufferSize(\n");
-                        indent++;
-                        print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
-                        print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
-                        print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
-                                     local_type_offset);
-                        nothing_printed = 1;
-                        indent--;
-                    }
                 }
             }
 
@@ -903,6 +943,7 @@
 
 static void marshall_in_arguments(func_t *func, unsigned int *type_offset)
 {
+    unsigned int local_type_offset = *type_offset;
     unsigned int alignment;
     unsigned int size;
     unsigned int last_size = 0;
@@ -910,8 +951,8 @@
     int out_attr;
     int string_attr;
     int ptr_attr, ref_attr, unique_attr;
+    void *sizeis_attr;
     var_t *var;
-    unsigned int local_type_offset = *type_offset;
 
     if (!func->args)
         return;
@@ -922,7 +963,6 @@
     {
         out_attr = is_attr(var->attrs, ATTR_OUT);
         in_attr = is_attr(var->attrs, ATTR_IN);
-        string_attr = is_attr(var->attrs, ATTR_STRING);
 
         /* set 'in' attribute if neither 'in' nor 'out' is set */
         if (!out_attr && !in_attr)
@@ -945,8 +985,28 @@
                 if (ptr_attr + ref_attr + unique_attr == 0)
                     ref_attr = 1;
 
-                if (ref_attr)
+                string_attr = is_attr(var->attrs, ATTR_STRING);
+                sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS);
+
+                if (sizeis_attr)
                 {
+                    print_client("_StubMsg.MaxCount = %s;\n",
+                                 ((var_t *)sizeis_attr)->name);
+                    fprintf(client, "\n");
+
+                    print_client("NdrConformantArrayMarshall(\n");
+                    indent++;
+                    print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
+                    print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
+                    print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
+                                 local_type_offset + 4);
+                    indent--;
+                    fprintf(client, "\n");
+                    print_client("_StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~0x3);\n");
+                    fprintf(client, "\n");
+                }
+                else if (ref_attr)
+                {
                     if (string_attr &&
                         (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR))
                     {
@@ -1192,6 +1252,8 @@
                         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 if (is_base_type(var->type))

Modified: trunk/reactos/tools/widl/server.c
--- trunk/reactos/tools/widl/server.c	2005-07-30 19:06:53 UTC (rev 16902)
+++ trunk/reactos/tools/widl/server.c	2005-07-30 19:31:52 UTC (rev 16903)
@@ -515,7 +515,7 @@
                     if (ptr_attr + ref_attr + unique_attr == 0)
                         ref_attr = 1;
 
-                    if (sizeis_attr != NULL && out_attr)
+                    if (sizeis_attr)
                     {
                         unsigned char type_type = 0;
 
@@ -550,12 +550,17 @@
                             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");
+                            if (out_attr)
+                                print_server("0x54           /* FC_DEREFERENCE */,\n");
+                            else
+                                print_server("0x00           /*  */,\n");
 
                             fprintf(server, "#ifndef _ALPHA_\n");
-                            print_server("NdrFcShort(0x04),\n");
+                            print_server("NdrFcShort(0x%02X),\n",
+                                         get_var_stack_offset_32(func, ((var_t *)sizeis_attr)->name));
                             fprintf(server, "#else\n");
-                            print_server("NdrFcShort(0x08),\n");
+                            print_server("NdrFcShort(0x%02X),\n",
+                                         get_var_stack_offset_64(func, ((var_t *)sizeis_attr)->name));
                             fprintf(server, "#endif\n");
                             print_server("0x%02x,\n", get_base_type(var->type->type));
                             print_server("0x5b,          /* FC_END */\n");
@@ -563,16 +568,23 @@
                     }
                     else if (is_base_type(var->type))
                     {
-                        if (out_attr)
-                            print_server("0x11, 0x0c,    /* FC_RP [allocated_on_stack] [simple_pointer] */\n");
+                        if (out_attr && !in_attr)
+                        {
+                            if (ref_attr)
+                                print_server("0x11, 0x0c,    /* FC_RP [allocated_on_stack] [simple_pointer] */\n");
+                            else if (unique_attr)
+                                print_server("0x12, 0x0c,    /* FC_FP [allocated_on_stack] [simple_pointer] */\n");
+                            else if (ptr_attr)
+                                print_server("0x14, 0x0c,    /* FC_FP [allocated_on_stack] [simple_pointer] */\n");
+                        }
                         else
                         {
-                            if (ptr_attr)
-                                print_server("0x14, 0x08,    /* FC_FP [simple_pointer] */\n");
-                            else if (ref_attr)
+                            if (ref_attr)
                                 print_server("0x11, 0x08,    /* FC_RP [simple_pointer] */\n");
                             else if (unique_attr)
                                 print_server("0x12, 0x08,    /* FC_UP [simple_pointer] */\n");
+                            else if (ptr_attr)
+                                print_server("0x14, 0x08,    /* FC_FP [simple_pointer] */\n");
                         }
 
                         if (string_attr)
@@ -623,8 +635,8 @@
     int empty_line;
     var_t *var;
 
-    int add_return = 0;
-    int start_new_line = 0;
+    int first_padding = 0;
+    int padding = 0;
     int add_plus = 0;
 
     unsigned int local_type_offset = *type_offset;
@@ -643,97 +655,104 @@
 
             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))
+                if (var->ptr_level == 1)
                 {
-                   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)
+                    if (sizeis_attr)
                     {
-                        print_server("_StubMsg.BufferLength +=");
+                        if (string_attr &&
+                            (var->type->type == RPC_FC_BYTE ||
+                             var->type->type == RPC_FC_CHAR ||
+                             var->type->type == RPC_FC_WCHAR))
+                        {
+                            size =12;
+                        }
+                        else
+                        {
+                            size = 4;
+                        }
                     }
-
-                    alignment = 0;
-                    switch (var->type->type)
+                    else if (is_base_type(var->type))
                     {
-                    case RPC_FC_BYTE:
-                    case RPC_FC_CHAR:
-                    case RPC_FC_SMALL:
-                        size = 1;
                         alignment = 0;
-                        break;
+                        switch (var->type->type)
+                        {
+                        case RPC_FC_BYTE:
+                        case RPC_FC_CHAR:
+                        case RPC_FC_SMALL:
+                            size = 1;
+                            alignment = 0;
+                            break;
 
-                    case RPC_FC_WCHAR:
-                    case RPC_FC_USHORT:
-                    case RPC_FC_SHORT:
-                        size = 2;
-                        if (last_size > 0 && last_size < 2)
-                            alignment += (2 - last_size);
-                        break;
+                        case RPC_FC_WCHAR:
+                        case RPC_FC_USHORT:
+                        case RPC_FC_SHORT:
+                            size = 2;
+                            if (last_size > 0 && last_size < 2)
+                                alignment += (2 - last_size);
+                            break;
 
-                    case RPC_FC_ULONG:
-                    case RPC_FC_LONG:
-                    case RPC_FC_FLOAT:
-                        size = 4;
-                        if (last_size > 0 && last_size < 4)
-                            alignment += (4 - last_size);
-                        break;
+                        case RPC_FC_ULONG:
+                        case RPC_FC_LONG:
+                        case RPC_FC_FLOAT:
+                            size = 4;
+                            if (last_size > 0 && last_size < 4)
+                                alignment += (4 - last_size);
+                            break;
 
-                    case RPC_FC_HYPER:
-                    case RPC_FC_DOUBLE:
-                        size = 8;
-                        if (last_size > 0 && last_size < 4)
-                            alignment += (4 - last_size);
-                        break;
+                        case RPC_FC_HYPER:
+                        case RPC_FC_DOUBLE:
+                            size = 8;
+                            if (last_size > 0 && last_size < 4)
+                                alignment += (4 - last_size);
+                            break;
 
-                    default:
-                        error("%s:%d Unknown/unsupported type 0x%x\n",
-                              __FUNCTION__,__LINE__, var->type->type);
-                        return;
+                        default:
+                            error("%s:%d Unknown/unsupported type 0x%x\n",
+                                  __FUNCTION__,__LINE__, var->type->type);
+                            return;
+                        }
                     }
+                }
+                else if (var->type->type == RPC_FC_RP)
+                {
+                    size = 12;
+                }
 
+                if (size != 0)
+                {
                     if (add_plus)
                         fprintf(server, " +");
-                    fprintf(server, " %dU", (size == 0) ? 0 : size + alignment);
+                    fprintf(server, " %dU", size + alignment + first_padding + padding);
 
+                    if (first_padding != 0)
+                        first_padding = 0;
+
                     last_size = size;
-                    start_new_line = 0;
                     add_plus = 1;
                 }
-                else if (var->type->type == RPC_FC_RP)
+
+                /* set paddings */
+                if (var->ptr_level == 1)
                 {
-                    if (size == 0)
+                    if (sizeis_attr)
                     {
-                      fprintf(server, " 12U;\n");
+                        if (string_attr &&
+                            (var->type->type == RPC_FC_BYTE ||
+                             var->type->type == RPC_FC_CHAR ||
+                             var->type->type == RPC_FC_WCHAR))
+                        {
+                            first_padding = 3;
+                            if (var->type->type == RPC_FC_BYTE ||
+                                var->type->type == RPC_FC_CHAR)
+                                first_padding++;
+                            padding = 3;
+                        }
+                        else
+                        {
+                            first_padding = 4;
+                            padding = 3;
+                        }
                     }
-                    else if (last_size != 0)
-                    {
-                      fprintf(server, " + 12U;\n");
-                      last_size = 0;
-                    }
-
-                    fprintf(server,"\n");
-                    print_server("NdrSimpleStructBufferSize(\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); /* FIXME */
-                    indent--;
-                    fprintf(server,"\n");
-
-                    start_new_line = 1;
                 }
 
                 /* calculate the next type offset */
@@ -745,12 +764,6 @@
     /* return value size */
     if (!is_void(func->def->type, NULL))
     {
-        if (start_new_line)
-        {
-          print_server("_StubMsg.BufferLength +=");
-          add_plus = 0;
-        }
-
         switch(func->def->type->type)
         {
         case RPC_FC_BYTE:
@@ -783,8 +796,12 @@
         if (add_plus)
             fprintf(server, " +");
 
-        fprintf(server, " %dU", (size == 0) ? 0 : size + alignment + add_return);
+        fprintf(server, " %dU", size + alignment + first_padding + padding);
     }
+
+    if (size == 0)
+        fprintf(server, "0U");
+
     fprintf(server, ";\n");
 
 
@@ -808,24 +825,55 @@
 
             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))
+                if (var->ptr_level == 1 && sizeis_attr != NULL)
                 {
-                    print_server("_StubMsg.MaxCount = %s;\n", ((var_t *)sizeis_attr)->name);
-                    fprintf(server, "\n");
-                    print_server("NdrConformantStringBufferSize(\n");
+                    if (string_attr)
+                    {
+                        if (var->type->type == RPC_FC_BYTE ||
+                            var->type->type == RPC_FC_CHAR ||
+                            var->type->type == RPC_FC_WCHAR)
+                        {
+                            print_server("_StubMsg.MaxCount = %s;\n", ((var_t *)sizeis_attr)->name);
+                            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--;
+                        }
+                    }
+                    else
+                    {
+                        if (((var_t *)sizeis_attr)->ptr_level == 0)
+                            print_server("_StubMsg.MaxCount = %s;\n", ((var_t *)sizeis_attr)->name);
+                        else
+                            print_server("_StubMsg.MaxCount = %s ? *%s : 0;\n",
+                                         ((var_t *)sizeis_attr)->name, ((var_t *)sizeis_attr)->name);
+                        fprintf(server, "\n");
+                        print_server("NdrConformantArrayBufferSize(\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;
+                }
+                else if (var->type->type == RPC_FC_RP)
+                {
+                    fprintf(server,"\n");
+                    print_server("NdrSimpleStructBufferSize(\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);
+                                 local_type_offset + 4); /* FIXME */
                     indent--;
-
-                    empty_line = 1;
+                    fprintf(server,"\n");
                 }
             }
 
@@ -873,6 +921,7 @@
 static void init_pointers (func_t *func)
 {
     var_t *var;
+    int count = 0;
 
     if (!func->args)
         return;
@@ -888,13 +937,15 @@
                 print_server("*(");
                 write_type(server, var->type, NULL, var->tname);
                 fprintf(server, "*)&%s = NULL;\n", var->name);
+                count++;
             }
         }
         else if (var->ptr_level == 1)
         {
-            fprintf(server, "%s = (", var->name);
+            print_server("%s = (", var->name);
             write_type(server, var->type, NULL, var->tname);
-            print_server(" __RPC_FAR *)0;\n");
+            fprintf(server, " __RPC_FAR *)0;\n");
+            count++;
         }
         else if (var->ptr_level > 1)
         {
@@ -904,12 +955,15 @@
 
         var = PREV_LINK(var);
     }
-    fprintf(server, "\n");
+
+    if (count > 0)
+        fprintf(server, "\n");
 }
 
 
 static void unmarshall_in_arguments(func_t *func, unsigned int *type_offset)
 {
+    unsigned int local_type_offset = *type_offset;
     unsigned int alignment;
     unsigned int size;
     unsigned int last_size = 0;
@@ -917,7 +971,7 @@
     int in_attr, out_attr;
     int string_attr;
     int ptr_attr, ref_attr, unique_attr;
-    unsigned int local_type_offset = *type_offset;
+    void *sizeis_attr;
 
     if (!func->args)
         return;
@@ -928,12 +982,14 @@
     {
         out_attr = is_attr(var->attrs, ATTR_OUT);
         in_attr = is_attr(var->attrs, ATTR_IN);
-        string_attr = is_attr(var->attrs, ATTR_STRING);
 
         /* set 'in' attribute if neither 'in' nor 'out' is set */
         if (!out_attr && !in_attr)
             in_attr = 1;
 
+        string_attr = is_attr(var->attrs, ATTR_STRING);
+        sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS);
+
         if (in_attr)
         {
             if (var->ptr_level == 1)
@@ -946,21 +1002,37 @@
 
                 if (ref_attr)
                 {
-                    if (string_attr &&
-                        (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR))
+                    if (string_attr)
                     {
-                        print_server("NdrConformantStringUnmarshall(\n");
-                        indent++;
-                        print_server("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
-                        print_server("(unsigned char __RPC_FAR * __RPC_FAR *)&%s,\n", var->name);
-                        print_server("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u],\n",
-                                     local_type_offset + 2);
-                        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");
+                        if (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR)
+                        {
+                            print_server("NdrConformantStringUnmarshall(\n");
+                            indent++;
+                            print_server("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
+                            print_server("(unsigned char __RPC_FAR * __RPC_FAR *)&%s,\n", var->name);
+                            print_server("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u],\n",
+                                         local_type_offset + 2);
+                            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 if (sizeis_attr)
+                    {
+                            print_server("NdrConformantArrayUnmarshall(\n");
+                            indent++;
+                            print_server("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
+                            print_server("(unsigned char __RPC_FAR * __RPC_FAR *)&%s,\n", var->name);
+                            print_server("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u],\n",
+                                         local_type_offset + 4);
+                            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
                     {
                         alignment = 0;
@@ -1173,6 +1245,26 @@
                         print_server("_StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~0x3);\n");
                         fprintf(server, "\n");
                     }
+                    else
+                    {
+                        fprintf(server, "\n");
+                        if (((var_t *)sizeis_attr)->ptr_level == 0)
+                            print_server("_StubMsg.MaxCount = %s;\n", ((var_t *)sizeis_attr)->name);
+                        else
+                            print_server("_StubMsg.MaxCount = %s ? *%s : 0;\n",
+                                         ((var_t *)sizeis_attr)->name, ((var_t *)sizeis_attr)->name);
+                        fprintf(server, "\n");
+                        print_server("NdrConformantArrayMarshall(\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))
                 {
@@ -1575,8 +1667,12 @@
                     {
                         print_server("");
                         write_name(server, var);
-                        fprintf(server, " = NdrAllocate(&_StubMsg, %s * %d);\n",
-                                ((var_t *)sizeis_attr)->name, get_type_size(var->type, 1));
+                        if (((var_t *)sizeis_attr)->ptr_level == 0)
+                            fprintf(server, " = NdrAllocate(&_StubMsg, %s * %d);\n",
+                                    ((var_t *)sizeis_attr)->name, get_type_size(var->type, 1));
+                        else if (((var_t *)sizeis_attr)->ptr_level == 1)
+                            fprintf(server, " = NdrAllocate(&_StubMsg, *%s * %d);\n",
+                                    ((var_t *)sizeis_attr)->name, get_type_size(var->type, 1));
                         sep = 1;
                     }
                     else