Implement [string] attribute for pointers to char and wchar_t.
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-03-13 09:19:33 UTC (rev 14001)
+++ trunk/reactos/tools/widl/ChangeLog	2005-03-13 10:24:34 UTC (rev 14002)
@@ -5,6 +5,14 @@
    tools/widl/client.c
    tools/widl/server.c
 
+Implement [string] attribute for pointers to char and wchar_t.
+
+
+2005-03-12 ekohl
+
+   tools/widl/client.c
+   tools/widl/server.c
+
 Implement [in], [out] and [in, out] support for pointers to basic types.
 
 

Modified: trunk/reactos/tools/widl/client.c
--- trunk/reactos/tools/widl/client.c	2005-03-13 09:19:33 UTC (rev 14001)
+++ trunk/reactos/tools/widl/client.c	2005-03-13 10:24:34 UTC (rev 14002)
@@ -164,6 +164,7 @@
     func_t *func = iface->funcs;
     var_t *var;
     int out_attr;
+    int string_attr;
 
     print_client("static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
     print_client("{\n");
@@ -183,6 +184,7 @@
             while (var)
             {
                 out_attr = is_attr(var->attrs, ATTR_OUT);
+                string_attr = is_attr(var->attrs, ATTR_STRING);
 
                 if (var->ptr_level > 1)
                 {
@@ -199,7 +201,20 @@
                             print_client("0x11, 0x0c,    /* FC_RP [allocated_on_stack] [simple_pointer] */\n");
                         else
                             print_client("0x11, 0x08,    /* FC_RP [simple_pointer] */\n");
-                        print_client("0x%02x,          /* FC_<type> */\n", var->type->type);
+                        if (string_attr)
+                        {
+                            if (var->type->type == RPC_FC_CHAR)
+                                print_client("0x%02x,          /* FC_C_CSTRING */\n", RPC_FC_C_CSTRING);
+                            else if (var->type->type == RPC_FC_WCHAR)
+                                print_client("0x%02x,          /* FC_C_WSTRING */\n", RPC_FC_C_WSTRING);
+                            else
+                            {
+                                error("%s: Invalid type!\n", __FUNCTION__);
+                                return;
+                            }
+                        }
+                        else
+                            print_client("0x%02x,          /* FC_<type> */\n", var->type->type);
                         print_client("0x5c,          /* FC_PAD */\n");
                     }
                 }
@@ -229,9 +244,12 @@
     int last_size = -1;
     int in_attr;
     int out_attr;
+    int string_attr;
     int nothing_printed = 1;
     var_t *var;
+    unsigned int type_offset = 2;
 
+    print_client("_StubMsg.BufferLength =");
     if (func->args)
     {
         var = func->args;
@@ -240,6 +258,7 @@
         {
             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)
@@ -248,53 +267,65 @@
             if (!in_attr)
                 continue;
 
-            alignment = 0;
-            switch (var->type->type)
+            if (var->ptr_level == 1 &&
+                string_attr &&
+                (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR))
             {
-            case RPC_FC_BYTE:
-            case RPC_FC_CHAR:
-            case RPC_FC_SMALL:
-                size = 1;
+                size = 12;
                 alignment = 0;
-                break;
+                fprintf(client, " %dU", (size == 0) ? 0 : size + alignment);
+                nothing_printed = 0;
+            }
+            else
+            {
+                alignment = 0;
+                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;
 
-            case RPC_FC_IGNORE:
-                size = 0;
-                break;
+                case RPC_FC_IGNORE:
+                    size = 0;
+                    break;
 
-            default:
-                error("Unknown/unsupported type!");
-                return;
+                default:
+                    error("Unknown/unsupported 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);
-            nothing_printed = 0;
-
             last_size = size;
         }
     }
@@ -303,16 +334,65 @@
     {
         fprintf(client, " 0U");
     }
+    fprintf(client, ";\n");
+
+    /* get string size */
+    if (func->args)
+    {
+        nothing_printed = 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);
+
+            /* set 'in' attribute if neither 'in' nor 'out' is found */
+            if (!out_attr && !in_attr)
+                in_attr = 1;
+
+            if (!in_attr)
+                continue;
+
+            if (var->ptr_level == 1 &&
+                string_attr &&
+                (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR))
+            {
+                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", type_offset + 2);
+                nothing_printed = 1;
+                indent--;
+            }
+
+           /* calculate the next type offset */
+           if (var->ptr_level == 1)
+           {
+               if (is_base_type(var->type))
+               {
+                   type_offset += 4;
+               }
+           }
+        }
+
+        if (nothing_printed)
+            fprintf(client, "\n");
+    }
 }
 
 
 static void marshall_in_arguments(func_t *func)
 {
+    unsigned int type_offset = 2;
     unsigned int alignment;
     unsigned int size;
     unsigned int last_size = 0;
     int in_attr;
     int out_attr;
+    int string_attr;
     var_t *var;
 
     if (!func->args)
@@ -324,6 +404,7 @@
     {
         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)
@@ -339,63 +420,87 @@
             return;
         }
 
-        alignment = 0;
-        switch (var->type->type)
+        if (var->ptr_level == 1 &&
+            string_attr &&
+            (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR))
         {
-        case RPC_FC_BYTE:
-        case RPC_FC_CHAR:
-        case RPC_FC_SMALL:
-            size = 1;
+            print_client("NdrConformantStringMarshall(\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", type_offset + 2);
+            indent--;
+            fprintf(client, "\n");
+        }
+        else
+        {
             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;
 
-        case RPC_FC_IGNORE:
-            size = 0;
-            break;
+           case RPC_FC_IGNORE:
+                size = 0;
+                break;
 
-        default:
-            error("Unknown/unsupported type!");
-        }
+            default:
+                error("Unknown/unsupported type!");
+            }
 
-        if (size != 0)
-        {
-            if (alignment != 0)
-                print_client("_StubMsg.Buffer += %u;\n", alignment);
+            if (size != 0)
+            {
+                if (alignment != 0)
+                    print_client("_StubMsg.Buffer += %u;\n", alignment);
 
-            print_client("*((");
-            write_type(client, var->type, NULL, var->tname);
-            fprintf(client, " __RPC_FAR*)_StubMsg.Buffer)++ = ");
-            if (var->ptr_level == 1)
-                fprintf(client, "*");
-            write_name(client, var);
-            fprintf(client, ";\n");
-            fprintf(client, "\n");
+                print_client("*((");
+                write_type(client, var->type, NULL, var->tname);
+                fprintf(client, " __RPC_FAR*)_StubMsg.Buffer)++ = ");
+                if (var->ptr_level == 1)
+                    fprintf(client, "*");
+                write_name(client, var);
+                fprintf(client, ";\n");
+                fprintf(client, "\n");
 
-            last_size = size;
+                last_size = size;
+            }
         }
+
+        /* calculate the next type offset */
+        if (var->ptr_level == 1)
+        {
+            if (is_base_type(var->type))
+            {
+                type_offset += 4;
+            }
+        }
     }
 }
 
@@ -676,11 +781,8 @@
         }
 
         /* emit the message buffer size */
-        print_client("_StubMsg.BufferLength =");
         print_message_buffer_size(func);
-        fprintf(client, ";\n");
 
-
         print_client("NdrGetBuffer(\n");
         indent++;
         print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");

Modified: trunk/reactos/tools/widl/server.c
--- trunk/reactos/tools/widl/server.c	2005-03-13 09:19:33 UTC (rev 14001)
+++ trunk/reactos/tools/widl/server.c	2005-03-13 10:24:34 UTC (rev 14002)
@@ -169,6 +169,7 @@
     func_t *func = iface->funcs;
     var_t *var;
     int out_attr;
+    int string_attr;
 
     print_server("static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
     print_server("{\n");
@@ -188,6 +189,7 @@
             while (var)
             {
                 out_attr = is_attr(var->attrs, ATTR_OUT);
+                string_attr = is_attr(var->attrs, ATTR_STRING);
 
                 if (var->ptr_level > 1)
                 {
@@ -204,7 +206,20 @@
                             print_server("0x11, 0x0c,    /* FC_RP [allocated_on_stack] [simple_pointer] */\n");
                         else
                             print_server("0x11, 0x08,    /* FC_RP [simple_pointer] */\n");
-                        print_server("0x%02x,          /* FC_<type> */\n", var->type->type);
+                        if (string_attr)
+                        {
+                            if (var->type->type == RPC_FC_CHAR)
+                                print_server("0x%02x,          /* FC_C_CSTRING */\n", RPC_FC_C_CSTRING);
+                            else if (var->type->type == RPC_FC_WCHAR)
+                                print_server("0x%02x,          /* FC_C_WSTRING */\n", RPC_FC_C_WSTRING);
+                            else
+                            {
+                                error("%s: Invalid type!\n", __FUNCTION__);
+                                return;
+                            }
+                        }
+                        else
+                            print_server("0x%02x,          /* FC_<type> */\n", var->type->type);
                         print_server("0x5c,          /* FC_PAD */\n");
                     }
                 }
@@ -229,13 +244,17 @@
 
 static void print_message_buffer_size(func_t *func)
 {
-    unsigned int alignment;
-    int size;
+    unsigned int alignment = 0;
+    int size = 0;
     int last_size = -1;
     int in_attr;
     int out_attr;
+    int string_attr;
+    int empty_line;
     var_t *var;
 
+    fprintf(server, "\n");
+    print_server("_StubMsg.BufferLength =");
     if (func->args)
     {
         var = func->args;
@@ -286,6 +305,7 @@
             if (last_size != -1)
                 fprintf(server, " +");
             fprintf(server, " %dU", (size == 0) ? 0 : size + alignment);
+            printf("1: %dU", (size == 0) ? 0 : size + alignment);
 
             last_size = size;
         }
@@ -327,6 +347,39 @@
 
         fprintf(server, " %dU", (size == 0) ? 0 : size + alignment);
     }
+    fprintf(server, ";\n");
+
+    /* get string size */
+    if (func->args)
+    {
+        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);
+
+            /* set 'in' attribute if neither 'in' nor 'out' is found */
+            if (!out_attr && !in_attr)
+                in_attr = 1;
+
+            if (!in_attr)
+                continue;
+
+            if (var->ptr_level == 1 &&
+                string_attr &&
+                (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR))
+            {
+                print_server("_StubMsg.BufferLength += 16;\n");
+                empty_line = 1;
+            }
+        }
+
+        if (empty_line)
+            fprintf(server, "\n");
+    }
 }
 
 
@@ -361,12 +414,14 @@
 
 static void unmarshall_in_arguments(func_t *func)
 {
+    unsigned int type_offset = 2;
     unsigned int alignment;
     unsigned int size;
     unsigned int last_size = 0;
     var_t *var;
     int in_attr;
     int out_attr;
+    int string_attr;
 
     if (!func->args)
         return;
@@ -377,6 +432,7 @@
     {
         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)
@@ -385,80 +441,105 @@
         if (!in_attr)
             continue;
 
-        alignment = 0;
-        switch (var->type->type)
+        if (var->ptr_level == 1 &&
+            string_attr &&
+            (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR))
         {
-        case RPC_FC_BYTE:
-        case RPC_FC_CHAR:
-        case RPC_FC_SMALL:
-            size = 1;
+            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", type_offset + 2);
+            print_server("(unsigned char)0);\n");
+            indent--;
+            fprintf(server, "\n");
+        }
+        else
+        {
             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;
 
-        case RPC_FC_IGNORE:
-            size = 0;
-            break;
+            case RPC_FC_IGNORE:
+                size = 0;
+                break;
 
-        default:
-            error("Unknown/unsupported type!");
+            default:
+                error("Unknown/unsupported type!");
+            }
+
+            if (size != 0)
+            {
+                if (alignment != 0)
+                    print_server("_StubMsg.Buffer += %u;\n", alignment);
+
+                if (var->ptr_level == 0)
+                {
+                    print_server("");
+                    write_name(server, var);
+                    fprintf(server, " = *((");
+                    write_type(server, var->type, NULL, var->tname);
+                    fprintf(server, " __RPC_FAR*)_StubMsg.Buffer)++;\n");
+                    fprintf(server, "\n");
+                }
+                else if (var->ptr_level == 1)
+                {
+                    print_server("");
+                    write_name(server, var);
+                    fprintf(server, " = (");
+                    write_type(server, var->type, NULL, var->tname);
+                    fprintf(server, " __RPC_FAR*)_StubMsg.Buffer;\n");
+                    print_server("_StubMsg.Buffer += sizeof(");
+                    write_type(server, var->type, NULL, var->tname);
+                    fprintf(server, ");\n");
+                    fprintf(server, "\n");
+                }
+                else
+                {
+                    error("Pointer level %d is not supported!\n", var->ptr_level);
+                    return;
+                }
+
+                last_size = size;
+            }
         }
 
-        if (size != 0)
+        /* calculate the next type offset */
+        if (var->ptr_level == 1)
         {
-            if (alignment != 0)
-                print_server("_StubMsg.Buffer += %u;\n", alignment);
-
-            if (var->ptr_level == 0)
+            if (is_base_type(var->type))
             {
-                print_server("");
-                write_name(server, var);
-                fprintf(server, " = *((");
-                write_type(server, var->type, NULL, var->tname);
-                fprintf(server, " __RPC_FAR*)_StubMsg.Buffer)++;\n");
-                fprintf(server, "\n");
+                type_offset += 4;
             }
-            else if (var->ptr_level == 1)
-            {
-                print_server("");
-                write_name(server, var);
-                fprintf(server, " = (");
-                write_type(server, var->type, NULL, var->tname);
-                fprintf(server, " __RPC_FAR*)_StubMsg.Buffer;\n");
-                print_server("_StubMsg.Buffer += sizeof(");
-                write_type(server, var->type, NULL, var->tname);
-                fprintf(server, ");\n");
-                fprintf(server, "\n");
-            }
-            else
-            {
-                error("Pointer level %d is not supported!\n", var->ptr_level);
-                return;
-            }
-
-            last_size = size;
         }
     }
 }
@@ -825,10 +906,7 @@
         /* allocate and fill the return message buffer */
         if (use_return_buffer(func))
         {
-            fprintf(server, "\n");
-            print_server("_StubMsg.BufferLength =");
             print_message_buffer_size(func);
-            fprintf(server, ";\n");
             print_server("_pRpcMessage->BufferLength = _StubMsg.BufferLength;\n");
             fprintf(server, "\n");
             print_server("_Status = I_RpcGetBuffer(_pRpcMessage);\n");