- For bugs for in-string parameters.
- Implement out-string parameters (untested).
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-16 15:19:52 UTC (rev 16598)
+++ trunk/reactos/tools/widl/ChangeLog	2005-07-16 23:21:36 UTC (rev 16599)
@@ -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 @@
 
   tools/widl/server.h
   tools/widl/client.h
-  tools/widl/proxy.h  
+  tools/widl/proxy.h
 
 Deleted unneeded headers.
 

Modified: trunk/reactos/tools/widl/client.c
--- trunk/reactos/tools/widl/client.c	2005-07-16 15:19:52 UTC (rev 16598)
+++ trunk/reactos/tools/widl/client.c	2005-07-16 23:21:36 UTC (rev 16599)
@@ -56,6 +56,130 @@
 }
 
 
+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_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 @@
 {
     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,12 +526,59 @@
                     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");
                         else
@@ -401,8 +613,6 @@
             }
         }
 
-
-
         func = PREV_LINK(func);
     }
 
@@ -695,30 +905,7 @@
             }
 
             /* 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 @@
                         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 @@
         }
 
         /* 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 @@
     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 @@
         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,8 +1174,39 @@
                     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 @@
             }
 
             /* 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 @@
             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 @@
             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);
             }
         }

Modified: trunk/reactos/tools/widl/server.c
--- trunk/reactos/tools/widl/server.c	2005-07-16 15:19:52 UTC (rev 16598)
+++ trunk/reactos/tools/widl/server.c	2005-07-16 23:21:36 UTC (rev 16599)
@@ -61,6 +61,130 @@
 }
 
 
+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_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 @@
 {
     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,12 +523,59 @@
                     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");
                         else
@@ -420,9 +632,11 @@
     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,10 +651,27 @@
         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)
                     {
                         print_server("_StubMsg.BufferLength +=");
@@ -519,30 +750,7 @@
                 }
 
                 /* 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 @@
         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 @@
 
             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 @@
         }
         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 @@
                         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 @@
         }
 
         /* 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 @@
     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,8 +1165,30 @@
             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)
                 {
[truncated at 1000 lines; 306 more skipped]