Support pointers to simple types as input arguments.
Modified: trunk/reactos/tools/widl/ChangeLog
Modified: trunk/reactos/tools/widl/client.c
Modified: trunk/reactos/tools/widl/header.c
Modified: trunk/reactos/tools/widl/header.h
Modified: trunk/reactos/tools/widl/server.c

Modified: trunk/reactos/tools/widl/ChangeLog
--- trunk/reactos/tools/widl/ChangeLog	2005-03-06 10:44:38 UTC (rev 13849)
+++ trunk/reactos/tools/widl/ChangeLog	2005-03-06 12:36:05 UTC (rev 13850)
@@ -1,4 +1,15 @@
 ChangeLog
+
+2005-03-06 ekohl
+
+   tools/widl/client.c
+   tools/widl/header.c
+   tools/widl/header.h
+   tools/widl/server.c
+
+Support pointers to simple types as input arguments.
+
+
 2005-02-27 sedwards
 
   tools/widl/y.tab.c

Modified: trunk/reactos/tools/widl/client.c
--- trunk/reactos/tools/widl/client.c	2005-03-06 10:44:38 UTC (rev 13849)
+++ trunk/reactos/tools/widl/client.c	2005-03-06 12:36:05 UTC (rev 13850)
@@ -60,6 +60,7 @@
 {
     func_t *func = iface->funcs;
     var_t *var;
+    unsigned int type_offset = 2;
 
     print_client("static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
     print_client("{\n");
@@ -78,54 +79,38 @@
             while (NEXT_LINK(var)) var = NEXT_LINK(var);
             while (var)
             {
-                switch(var->type->type)
+                if (var->ptr_level == 0)
                 {
-                case RPC_FC_BYTE:
-                    print_client("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_client("0x%02x,    /* FC_BYTE */\n", RPC_FC_BYTE);
-                    break;
-                case RPC_FC_CHAR:
-                    print_client("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_client("0x%02x,    /* FC_CHAR */\n", RPC_FC_CHAR);
-                    break;
-                case RPC_FC_WCHAR:
-                    print_client("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_client("0x%02x,    /* FC_WCHAR */\n", RPC_FC_WCHAR);
-                    break;
-                case RPC_FC_USHORT:
-                case RPC_FC_SHORT:
-                    print_client("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_client("0x%02x,    /* FC_USHORT */\n", RPC_FC_SHORT);
-                    break;
-                case RPC_FC_ULONG:
-                case RPC_FC_LONG:
-                    print_client("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_client("0x%02x,    /* FC_LONG */\n", RPC_FC_LONG);
-                    break;
-                case RPC_FC_HYPER:
-                    print_client("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_client("0x%02x,    /* FC_HYPER */\n", RPC_FC_HYPER);
-                    break;
-                case RPC_FC_IGNORE:
-                    print_client("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_client("0x%02x,    /* FC_IGNORE */\n", RPC_FC_IGNORE);
-                    break;
-                case RPC_FC_SMALL:
-                    print_client("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_client("0x%02x,    /* FC_SMALL */\n", RPC_FC_SMALL);
-                    break;
-                case RPC_FC_FLOAT:
-                    print_client("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_client("0x%02x,    /* FC_FLOAT */\n", RPC_FC_FLOAT);
-                    break;
-                case RPC_FC_DOUBLE:
-                    print_client("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_client("0x%02x,    /* FC_DOUBLE */\n", RPC_FC_DOUBLE);
-                    break;
-                default:
-                    error("Unknown/unsupported type\n");
-                    return;
+                    if (is_base_type(var->type))
+                    {
+                        print_client("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
+                        print_client("0x%02x,    /* FC_<type> */\n", var->type->type);
+                    }
+                    else
+                    {
+                        error("Unknown/unsupported type\n");
+                        return;
+                    }
                 }
+                else if (var->ptr_level == 1)
+                {
+                    if (is_base_type(var->type))
+                    {
+                        print_client("0x4d,    /* FC_IN_PARAM */\n");
+                        fprintf(client, "#ifndef _ALPHA_\n");
+                        print_client("0x01,\n");
+                        fprintf(client, "#else\n");
+                        print_client("0x02,\n");
+                        fprintf(client, "#endif\n");
+                        print_client("NdrFcShort(0x%x),\n", type_offset);
+                        type_offset += 4;
+                    }
+                    else
+                    {
+                        error("Unknown/unsupported type\n");
+                        return;
+                    }
+                }
 
                 var = PREV_LINK(var);
             }
@@ -138,58 +123,15 @@
             print_client("0x5b,    /* FC_END */\n");
             print_client("0x5c,    /* FC_PAD */\n");
         }
+        else if (is_base_type(var->type))
+        {
+            print_client("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
+            print_client("0x%02x,    /* FC_<type> */\n", var->type->type);
+        }
         else
         {
-            switch(var->type->type)
-            {
-            case RPC_FC_BYTE:
-                print_client("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_client("0x%02x,    /* FC_BYTE */\n", var->type->type);
-                break;
-            case RPC_FC_CHAR:
-                print_client("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_client("0x%02x,    /* FC_CHAR */\n", var->type->type);
-                break;
-            case RPC_FC_WCHAR:
-                print_client("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_client("0x%02x,    /* FC_WCHAR */\n", var->type->type);
-                break;
-            case RPC_FC_USHORT:
-                print_client("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_client("0x%02x,    /* FC_USHORT */\n", var->type->type);
-                break;
-            case RPC_FC_SHORT:
-                print_client("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_client("0x%02x,    /* FC_SHORT */\n", var->type->type);
-                break;
-            case RPC_FC_ULONG:
-                print_client("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_client("0x%02x,    /* FC_ULONG */\n", var->type->type);
-                break;
-            case RPC_FC_LONG:
-                print_client("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_client("0x%02x,    /* FC_LONG */\n", var->type->type);
-                break;
-            case RPC_FC_HYPER:
-                print_client("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_client("0x%02x,    /* FC_HYPER */\n", var->type->type);
-                break;
-            case RPC_FC_SMALL:
-                print_client("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_client("0x%02x,    /* FC_SMALL */\n", RPC_FC_SMALL);
-                break;
-            case RPC_FC_FLOAT:
-                print_client("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_client("0x%02x,    /* FC_FLOAT */\n", RPC_FC_FLOAT);
-                break;
-            case RPC_FC_DOUBLE:
-                print_client("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_client("0x%02x,    /* FC_DOUBLE */\n", RPC_FC_DOUBLE);
-                break;
-            default:
-                error("Unknown/unsupported type\n");
-                return;
-            }
+            error("Unknown/unsupported type\n");
+            return;
         }
 
         func = PREV_LINK(func);
@@ -204,8 +146,11 @@
 }
 
 
-static void write_typeformatstring(void)
+static void write_typeformatstring(type_t *iface)
 {
+    func_t *func = iface->funcs;
+    var_t *var;
+
     print_client("static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
     print_client("{\n");
     indent++;
@@ -213,6 +158,42 @@
     print_client("{\n");
     indent++;
     print_client("NdrFcShort(0x0),\n");
+
+    while (NEXT_LINK(func)) func = NEXT_LINK(func);
+    while (func)
+    {
+        if (func->args)
+        {
+            var = func->args;
+            while (NEXT_LINK(var)) var = NEXT_LINK(var);
+            while (var)
+            {
+                if (var->ptr_level > 1)
+                {
+                    error("Function '%s' argument '%s': Pointer level %d not supported!\n",
+                          func->def->name, var->name, var->ptr_level);
+                    return;
+                }
+
+                if (var->ptr_level == 1)
+                {
+                    if (is_base_type(var->type))
+                    {
+                        print_client("0x11, 0x08,    /* FC_RP [simple_pointer] */\n");
+                        print_client("0x%02x,          /* FC_<type> */\n", var->type->type);
+                        print_client("0x5c,          /* FC_PAD */\n");
+                    }
+                }
+
+                var = PREV_LINK(var);
+            }
+        }
+
+
+
+        func = PREV_LINK(func);
+    }
+
     print_client("0x0\n");
     indent--;
     print_client("}\n");
@@ -227,6 +208,8 @@
     unsigned int alignment;
     int size;
     int last_size = -1;
+    int in_attr;
+    int out_attr;
     var_t *var;
 
     if (!func->args)
@@ -237,8 +220,18 @@
 
     var = func->args;
     while (NEXT_LINK(var)) var = NEXT_LINK(var);
-    while (var)
+    for (; var; var = PREV_LINK(var))
     {
+        out_attr = is_attr(var->attrs, ATTR_OUT);
+        in_attr = is_attr(var->attrs, ATTR_IN);
+
+        /* set 'in' attribute if neither 'in' nor 'out' is found */
+        if (!out_attr && !in_attr)
+            in_attr = 1;
+
+        if (!in_attr)
+            continue;
+
         alignment = 0;
         switch (var->type->type)
         {
@@ -253,7 +246,7 @@
         case RPC_FC_USHORT:
         case RPC_FC_SHORT:
             size = 2;
-            if (last_size != -1 && last_size < 2)
+            if (last_size > 0 && last_size < 2)
                 alignment += (2 - last_size);
             break;
 
@@ -261,14 +254,14 @@
         case RPC_FC_LONG:
         case RPC_FC_FLOAT:
             size = 4;
-            if (last_size != -1 && last_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 != -1 && last_size < 4)
+            if (last_size > 0 && last_size < 4)
                 alignment += (4 - last_size);
             break;
 
@@ -285,17 +278,17 @@
         fprintf(client, " %dU", (size == 0) ? 0 : size + alignment);
 
         last_size = size;
-
-        var = PREV_LINK(var);
     }
 }
 
 
-static void marshall_arguments(func_t *func)
+static void marshall_in_arguments(func_t *func)
 {
     unsigned int alignment;
     unsigned int size;
     unsigned int last_size = 0;
+    int in_attr;
+    int out_attr;
     var_t *var;
 
     if (!func->args)
@@ -303,8 +296,25 @@
 
     var = func->args;
     while (NEXT_LINK(var)) var = NEXT_LINK(var);
-    while (var)
+    for (; var; var = PREV_LINK(var))
     {
+        out_attr = is_attr(var->attrs, ATTR_OUT);
+        in_attr = is_attr(var->attrs, ATTR_IN);
+
+        /* set 'in' attribute if neither 'in' nor 'out' is set */
+        if (!out_attr && !in_attr)
+            in_attr = 1;
+
+        if (!in_attr)
+            continue;
+
+        if (var->ptr_level > 1)
+        {
+            error("Function '%s' argument '%s': Pointer level %d not supported!\n",
+                  func->def->name, var->name, var->ptr_level);
+            return;
+        }
+
         alignment = 0;
         switch (var->type->type)
         {
@@ -319,7 +329,7 @@
         case RPC_FC_USHORT:
         case RPC_FC_SHORT:
             size = 2;
-            if (last_size != 0 && last_size < 2)
+            if (last_size > 0 && last_size < 2)
                 alignment = (2 - last_size);
             break;
 
@@ -327,14 +337,14 @@
         case RPC_FC_LONG:
         case RPC_FC_FLOAT:
             size = 4;
-            if (last_size != 0 && last_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)
+            if (last_size > 0 && last_size < 4)
                 alignment = (4 - last_size);
             break;
 
@@ -352,15 +362,47 @@
                 print_client("_StubMsg.Buffer += %u;\n", alignment);
 
             print_client("*((");
-            write_type(client, var->type, var, var->tname);
+            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;
         }
+    }
+}
 
+
+static void check_pointers(func_t *func)
+{
+    var_t *var;
+
+    if (!func->args)
+        return;
+
+    var = func->args;
+    while (NEXT_LINK(var)) var = NEXT_LINK(var);
+    while (var)
+    {
+        if (var->ptr_level == 1)
+        {
+            print_client("if (!%s)\n", var->name);
+            print_client("{\n");
+            indent++;
+            print_client("RpcRaiseException(RPC_X_NULL_REF_POINTER);\n");
+            indent--;
+            print_client("}\n");
+            fprintf(client, "\n");
+        }
+        else if (var->ptr_level > 1)
+        {
+            error("Pointer level %d not supported!\n", var->ptr_level);
+            return;
+        }
+
         var = PREV_LINK(var);
     }
 }
@@ -426,6 +468,10 @@
         print_client("RPC_MESSAGE _RpcMessage;\n");
         print_client("MIDL_STUB_MESSAGE _StubMsg;\n");
         fprintf(client, "\n");
+
+        /* check pointers */
+        check_pointers(func);
+
         print_client("RpcTryFinally\n");
         print_client("{\n");
         indent++;
@@ -467,8 +513,8 @@
         indent--;
         fprintf(client, "\n");
 
-        /* marshal arguments */
-        marshall_arguments(func);
+        /* marshal in arguments */
+        marshall_in_arguments(func);
 
         /* send/recieve message */
         print_client("NdrSendReceive(\n");
@@ -477,7 +523,7 @@
         print_client("(unsigned char __RPC_FAR *)_StubMsg.Buffer);\n");
         indent--;
 
-        /* unmarshal return value */
+        /* convert data representation */
         if (!is_void(def->type, NULL))
         {
             fprintf(client, "\n");
@@ -503,7 +549,19 @@
             while (NEXT_LINK(var)) var = NEXT_LINK(var);
             while (var)
             {
-                proc_offset += 2; /* FIXME */
+                switch (var->ptr_level)
+                {
+                case 0:
+                    if (is_base_type(var->type))
+                        proc_offset += 2;
+                    break;
+
+                case 1:
+                    if (is_base_type(var->type))
+                        proc_offset += 4;
+                    break;
+                }
+
                 var = PREV_LINK(var);
             }
         }
@@ -633,14 +691,47 @@
 }
 
 
-static void write_formatstringsdecl(type_t *iface)
+static int get_type_format_string_size(type_t *iface)
 {
-    int byte_count = 1;
+    int size = 3;
     func_t *func;
     var_t *var;
 
-    print_client("#define TYPE_FORMAT_STRING_SIZE %d\n", 3); /* FIXME */
+    /* determine the proc format string size */
+    func = iface->funcs;
+    while (NEXT_LINK(func)) func = NEXT_LINK(func);
+    while (func)
+    {
+        /* argument list size */
+        if (func->args)
+        {
+            var = func->args;
+            while (NEXT_LINK(var)) var = NEXT_LINK(var);
+            while (var)
+            {
+                if (var->ptr_level == 1)
+                {
+                    if (is_base_type(var->type))
+                        size += 4;
+                }
 
+                var = PREV_LINK(var);
+            }
+        }
+
+        func = PREV_LINK(func);
+    }
+
+    return size;
+}
+
+
+static int get_proc_format_string_size(type_t *iface)
+{
+    int size = 1;
+    func_t *func;
+    var_t *var;
+
     /* determine the proc format string size */
     func = iface->funcs;
     while (NEXT_LINK(func)) func = NEXT_LINK(func);
@@ -653,18 +744,40 @@
             while (NEXT_LINK(var)) var = NEXT_LINK(var);
             while (var)
             {
-                byte_count += 2; /* FIXME: determine real size */
+                switch (var->ptr_level)
+                {
+                case 0:
+                    if (is_base_type(var->type))
+                        size += 2;
+                    break;
+
+                case 1:
+                    if (is_base_type(var->type))
+                        size += 4;
+                    break;
+                }
+
                 var = PREV_LINK(var);
             }
         }
 
         /* return value size */
-        byte_count += 2; /* FIXME: determine real size */
+        size += 2;
         func = PREV_LINK(func);
     }
 
-    print_client("#define PROC_FORMAT_STRING_SIZE %d\n", byte_count);
+    return size;
+}
 
+
+static void write_formatstringsdecl(type_t *iface)
+{
+    print_client("#define TYPE_FORMAT_STRING_SIZE %d\n",
+                 get_type_format_string_size(iface));
+
+    print_client("#define PROC_FORMAT_STRING_SIZE %d\n",
+                 get_proc_format_string_size(iface));
+
     fprintf(client, "\n");
     write_formatdesc("TYPE");
     write_formatdesc("PROC");
@@ -741,7 +854,7 @@
         fprintf(client, "\n");
 
         write_procformatstring(iface->iface);
-        write_typeformatstring();
+        write_typeformatstring(iface->iface);
 
         fprintf(client, "\n");
 

Modified: trunk/reactos/tools/widl/header.c
--- trunk/reactos/tools/widl/header.c	2005-03-06 10:44:38 UTC (rev 13849)
+++ trunk/reactos/tools/widl/header.c	2005-03-06 12:36:05 UTC (rev 13850)
@@ -45,6 +45,18 @@
   if (delta > 0) indentation += delta;
 }
 
+int is_base_type(type_t *t)
+{
+  return (t->type == RPC_FC_BYTE || t->type == RPC_FC_CHAR ||
+          t->type == RPC_FC_SMALL || t->type == RPC_FC_USMALL ||
+          t->type == RPC_FC_WCHAR || t->type == RPC_FC_SHORT ||
+          t->type == RPC_FC_USHORT || t->type == RPC_FC_LONG ||
+          t->type == RPC_FC_ULONG || t->type == RPC_FC_FLOAT ||
+          t->type == RPC_FC_HYPER || t->type == RPC_FC_DOUBLE ||
+          t->type == RPC_FC_ENUM16 || t->type == RPC_FC_ENUM32 ||
+          t->type == RPC_FC_IGNORE);
+}
+
 int is_attr(attr_t *a, enum attr_type t)
 {
   while (a) {

Modified: trunk/reactos/tools/widl/header.h
--- trunk/reactos/tools/widl/header.h	2005-03-06 10:44:38 UTC (rev 13849)
+++ trunk/reactos/tools/widl/header.h	2005-03-06 12:36:05 UTC (rev 13850)
@@ -21,6 +21,7 @@
 #ifndef __WIDL_HEADER_H
 #define __WIDL_HEADER_H
 
+extern int is_base_type(type_t *t);
 extern int is_attr(attr_t *a, enum attr_type t);
 extern void *get_attrp(attr_t *a, enum attr_type t);
 extern unsigned long get_attrv(attr_t *a, enum attr_type t);

Modified: trunk/reactos/tools/widl/server.c
--- trunk/reactos/tools/widl/server.c	2005-03-06 10:44:38 UTC (rev 13849)
+++ trunk/reactos/tools/widl/server.c	2005-03-06 12:36:05 UTC (rev 13850)
@@ -65,6 +65,7 @@
 {
     func_t *func = iface->funcs;
     var_t *var;
+    unsigned int type_offset = 2;
 
     print_server("static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
     print_server("{\n");
@@ -83,59 +84,38 @@
             while (NEXT_LINK(var)) var = NEXT_LINK(var);
             while (var)
             {
-                switch(var->type->type)
+                if (var->ptr_level == 0)
                 {
-                case RPC_FC_BYTE:
-                    print_server("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_server("0x%02x,    /* FC_BYTE */\n", var->type->type);
-                    break;
-                case RPC_FC_CHAR:
-                    print_server("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_server("0x%02x,    /* FC_CHAR */\n", var->type->type);
-                    break;
-                case RPC_FC_WCHAR:
-                    print_server("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_server("0x%02x,    /* FC_WCHAR */\n", var->type->type);
-                    break;
-                case RPC_FC_USHORT:
-                    print_server("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_server("0x%02x,    /* FC_USHORT */\n", var->type->type);
-                    break;
-                case RPC_FC_SHORT:
-                    print_server("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_server("0x%02x,    /* FC_SHORT */\n", var->type->type);
-                    break;
-                case RPC_FC_ULONG:
-                    print_server("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_server("0x%02x,    /* FC_ULONG */\n", var->type->type);
-                    break;
-                case RPC_FC_LONG:
-                    print_server("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_server("0x%02x,    /* FC_LONG */\n", var->type->type);
-                    break;
-                case RPC_FC_HYPER:
-                    print_server("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_server("0x%02x,    /* FC_HYPER */\n", var->type->type);
-                    break;
-                case RPC_FC_IGNORE:
-                    print_server("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_server("0x%02x,    /* FC_IGNORE */\n", var->type->type);
-                    break;
-                case RPC_FC_SMALL:
-                    print_server("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_server("0x%02x,    /* FC_SMALL */\n", RPC_FC_SMALL);
-                    break;
-                case RPC_FC_FLOAT:
-                    print_server("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_server("0x%02x,    /* FC_FLOAT */\n", RPC_FC_FLOAT);
-                    break;
-                case RPC_FC_DOUBLE:
-                    print_server("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
-                    print_server("0x%02x,    /* FC_DOUBLE */\n", RPC_FC_DOUBLE);
-                    break;
-                default:
-                    error("Unknown/unsupported type\n");
+                    if (is_base_type(var->type))
+                    {
+                        print_server("0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
+                        print_server("0x%02x,    /* FC_<type> */\n", var->type->type);
+                    }
+                    else
+                    {
+                        error("Unknown/unsupported type\n");
+                        return;
+                    }
                 }
+                else if (var->ptr_level == 1)
+                {
+                    if (is_base_type(var->type))
+                    {
+                        print_server("0x4d,    /* FC_IN_PARAM */\n");
+                        fprintf(server, "#ifndef _ALPHA_\n");
+                        print_server("0x01,\n");
+                        fprintf(server, "#else\n");
+                        print_server("0x02,\n");
+                        fprintf(server, "#endif\n");
+                        print_server("NdrFcShort(0x%x),\n", type_offset);
+                        type_offset += 4;
+                    }
+                    else
+                    {
+                        error("Unknown/unsupported type\n");
+                        return;
+                    }
+                }
 
                 var = PREV_LINK(var);
             }
@@ -148,57 +128,15 @@
             print_server("0x5b,    /* FC_END */\n");
             print_server("0x5c,    /* FC_PAD */\n");
         }
+        else if (is_base_type(var->type))
+        {
+            print_server("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
+            print_server("0x%02x,    /* FC_<type> */\n", var->type->type);
+        }
         else
         {
-            switch(var->type->type)
-            {
-            case RPC_FC_BYTE:
-                print_server("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_server("0x%02x,    /* FC_BYTE */\n", var->type->type);
-                break;
-            case RPC_FC_CHAR:
-                print_server("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_server("0x%02x,    /* FC_CHAR */\n", var->type->type);
-                break;
-            case RPC_FC_WCHAR:
-                print_server("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_server("0x%02x,    /* FC_WCHAR */\n", var->type->type);
-                break;
-            case RPC_FC_USHORT:
-                print_server("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_server("0x%02x,    /* FC_USHORT */\n", var->type->type);
-                break;
-            case RPC_FC_SHORT:
-                print_server("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_server("0x%02x,    /* FC_SHORT */\n", var->type->type);
-                break;
-            case RPC_FC_ULONG:
-                print_server("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_server("0x%02x,    /* FC_ULONG */\n", var->type->type);
-                break;
-            case RPC_FC_LONG:
-                print_server("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_server("0x%02x,    /* FC_LONG */\n", var->type->type);
-                break;
-            case RPC_FC_HYPER:
-                print_server("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_server("0x%02x,    /* FC_HYPER */\n", var->type->type);
-                break;
-            case RPC_FC_SMALL:
-                print_server("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_server("0x%02x,    /* FC_SMALL */\n", RPC_FC_SMALL);
-                break;
-            case RPC_FC_FLOAT:
-                print_server("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_server("0x%02x,    /* FC_FLOAT */\n", RPC_FC_FLOAT);
-                break;
-            case RPC_FC_DOUBLE:
-                print_server("0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
-                print_server("0x%02x,    /* FC_DOUBLE */\n", RPC_FC_DOUBLE);
-                break;
-            default:
-                error("Unknown/unsupported type\n");
-            }
+            error("Unknown/unsupported type\n");
+            return;
         }
 
         func = PREV_LINK(func);
@@ -213,8 +151,11 @@
 }
 
 
-static void write_typeformatstring(void)
+static void write_typeformatstring(type_t *iface)
 {
+    func_t *func = iface->funcs;
+    var_t *var;
+
     print_server("static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
     print_server("{\n");
     indent++;
@@ -222,6 +163,42 @@
     print_server("{\n");
     indent++;
     print_server("NdrFcShort(0x0),\n");
+
+    while (NEXT_LINK(func)) func = NEXT_LINK(func);
+    while (func)
+    {
+        if (func->args)
+        {
+            var = func->args;
+            while (NEXT_LINK(var)) var = NEXT_LINK(var);
+            while (var)
+            {
+                if (var->ptr_level > 1)
+                {
+                    error("Function '%s' argument '%s': Pointer level %d not supported!\n",
+                          func->def->name, var->name, var->ptr_level);
+                    return;
+                }
+
+                if (var->ptr_level == 1)
+                {
+                    if (is_base_type(var->type))
+                    {
+                        print_server("0x11, 0x08,    /* FC_RP [simple_pointer] */\n");
+                        print_server("0x%02x,          /* FC_<type> */\n", var->type->type);
+                        print_server("0x5c,          /* FC_PAD */\n");
+                    }
+                }
+
+                var = PREV_LINK(var);
+            }
+        }
+
+
+
+        func = PREV_LINK(func);
+    }
+
     print_server("0x0\n");
     indent--;
     print_server("}\n");
@@ -260,6 +237,35 @@
 }
 
 
+static void init_pointers (func_t *func)
+{
+    var_t *var;
+
+    if (!func->args)
+        return;
+
+    var = func->args;
+    while (NEXT_LINK(var)) var = NEXT_LINK(var);
+    while (var)
+    {
+        if (var->ptr_level == 1)
+        {
+            print_server("(");
+            write_type(server, var->type, NULL, var->tname);
+            fprintf(server, " __RPC_FAR *)%s = 0;\n", var->name);
+        }
+        else if (var->ptr_level > 1)
+        {
+            error("Pointer level %d not supported!\n", var->ptr_level);
+            return;
+        }
+
+        var = PREV_LINK(var);
+    }
+    fprintf(server, "\n");
+}
+
+
 static void unmarshall_arguments(func_t *func)
 {
     unsigned int alignment;
@@ -320,12 +326,32 @@
             if (alignment != 0)
                 print_server("_StubMsg.Buffer += %u;\n", alignment);
 
-            print_server("");
-            write_name(server, var);
-            fprintf(server, " = *((");
-            write_type(server, var->type, var, var->tname);
-            fprintf(server, " __RPC_FAR*)_StubMsg.Buffer)++;\n");
-            fprintf(server, "\n");
+            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;
         }
@@ -424,6 +450,8 @@
             fprintf(server, "\n");
         }
 
+        init_pointers(func);
+
         print_server("RpcTryFinally\n");
         print_server("{\n");
         indent++;
@@ -666,15 +694,47 @@
     print_server("\n");
 }
 
+static int get_type_format_string_size(type_t *iface)
+{
+    int size = 3;
+    func_t *func;
+    var_t *var;
 
-static void write_formatstringsdecl(type_t *iface)
+    /* determine the proc format string size */
+    func = iface->funcs;
+    while (NEXT_LINK(func)) func = NEXT_LINK(func);
+    while (func)
+    {
+        /* argument list size */
+        if (func->args)
+        {
+            var = func->args;
+            while (NEXT_LINK(var)) var = NEXT_LINK(var);
+            while (var)
+            {
+                if (var->ptr_level == 1)
+                {
+                    if (is_base_type(var->type))
+                        size += 4;
+                }
+
+                var = PREV_LINK(var);
+            }
+        }
+
+        func = PREV_LINK(func);
+    }
+
+    return size;
+}
+
+
+static int get_proc_format_string_size(type_t *iface)
 {
+    int size = 1;
     func_t *func;
     var_t *var;
-    int byte_count = 1;
 
-    print_server("#define TYPE_FORMAT_STRING_SIZE %d\n", 3); /* FIXME */
-
     /* determine the proc format string size */
     func = iface->funcs;
     while (NEXT_LINK(func)) func = NEXT_LINK(func);
@@ -687,17 +747,40 @@
             while (NEXT_LINK(var)) var = NEXT_LINK(var);
             while (var)
             {
-                byte_count += 2; /* FIXME: determine real size */
+                switch (var->ptr_level)
+                {
+                case 0:
+                    if (is_base_type(var->type))
+                        size += 2;
+                    break;
+
+                case 1:
+                    if (is_base_type(var->type))
+                        size += 4;
+                    break;
+                }
+
                 var = PREV_LINK(var);
             }
         }
 
         /* return value size */
-        byte_count += 2; /* FIXME: determine real size */
+        size += 2;
         func = PREV_LINK(func);
     }
-    print_server("#define PROC_FORMAT_STRING_SIZE %d\n", byte_count);
 
+    return size;
+}
+
+
[truncated at 1000 lines; 20 more skipped]