[1/3] widl: Handle wire_marshal types

Dan Hipschman dsh at linux.ucla.edu
Wed Jun 13 18:13:04 CDT 2007


This patch adds the functionality to handle basic wire_marshal types,
which is needed for oaidl.idl.  It includes a simple test that passes
on XP and in wine.  A more complicated test is added in the third
patch.

Incidentally, this patch also gets marshalling of structure arguments
to work, but I'm sending the test case for that in a separate patch,
as it's not the primary purpose of this one.

---
 dlls/rpcrt4/tests/server.c   |   39 +++++++++
 dlls/rpcrt4/tests/server.idl |    2 +
 tools/widl/client.c          |    3 +-
 tools/widl/header.c          |   29 ++----
 tools/widl/parser.y          |   15 ++++
 tools/widl/proxy.c           |    7 +-
 tools/widl/server.c          |   15 +++-
 tools/widl/typegen.c         |  186 ++++++++++++++++++++++++++++++++++--------
 tools/widl/typegen.h         |    3 +
 tools/widl/widltypes.h       |   10 ++
 10 files changed, 246 insertions(+), 63 deletions(-)

diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index b65dc91..fbaa755 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -225,6 +225,13 @@ s_sum_cps(cps_t *cps)
   return sum;
 }
 
+int
+s_square_puint(puint_t p)
+{
+  int n = atoi(p);
+  return n * n;
+}
+
 void
 s_stop(void)
 {
@@ -388,12 +395,44 @@ free_list(test_list_t *list)
   HeapFree(GetProcessHeap(), 0, list);
 }
 
+ULONG __RPC_USER
+puint_t_UserSize(ULONG *flags, ULONG start, puint_t *p)
+{
+  return start + sizeof(int);
+}
+
+unsigned char * __RPC_USER
+puint_t_UserMarshal(ULONG *flags, unsigned char *buffer, puint_t *p)
+{
+  int n = atoi(*p);
+  memcpy(buffer, &n, sizeof n);
+  return buffer + sizeof n;
+}
+
+unsigned char * __RPC_USER
+puint_t_UserUnmarshal(ULONG *flags, unsigned char *buffer, puint_t *p)
+{
+  int n;
+  memcpy(&n, buffer, sizeof n);
+  *p = HeapAlloc(GetProcessHeap(), 0, 10);
+  sprintf(*p, "%d", n);
+  return buffer + sizeof n;
+}
+
+void __RPC_USER
+puint_t_UserFree(ULONG *flags, puint_t *p)
+{
+  HeapFree(GetProcessHeap(), 0, *p);
+}
+
 static void
 pointer_tests(void)
 {
+  static char p1[] = "11";
   test_list_t *list = make_list(make_list(make_list(null_list())));
 
   ok(test_list_length(list) == 3, "RPC test_list_length\n");
+  ok(square_puint(p1) == 121, "RPC square_puint\n");
 
   free_list(list);
 }
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
index a7b3df7..d6ed5f2 100644
--- a/dlls/rpcrt4/tests/server.idl
+++ b/dlls/rpcrt4/tests/server.idl
@@ -130,5 +130,7 @@ interface IServer
   int sum_cs(cs_t *cs);
   int sum_cps(cps_t *cps);
 
+  typedef [wire_marshal(int)] void *puint_t;
+  int square_puint(puint_t p);
   void stop(void);
 }
diff --git a/tools/widl/client.c b/tools/widl/client.c
index 2b020a1..6172cfe 100644
--- a/tools/widl/client.c
+++ b/tools/widl/client.c
@@ -305,7 +305,7 @@ static void write_stubdescriptor(type_t *iface, int expr_eval_routines)
     print_client("0,\n");
     print_client("0x50100a4, /* MIDL Version 5.1.164 */\n");
     print_client("0,\n");
-    print_client("0,\n");
+    print_client("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines");
     print_client("0,  /* notify & notify_flag routine table */\n");
     print_client("1,  /* Flags */\n");
     print_client("0,  /* Reserved3 */\n");
@@ -434,6 +434,7 @@ void write_client(ifref_list_t *ifaces)
             expr_eval_routines = write_expr_eval_routines(client, iface->iface->name);
             if (expr_eval_routines)
                 write_expr_eval_routine_list(client, iface->iface->name);
+            write_user_quad_list(client);
             write_stubdescriptor(iface->iface, expr_eval_routines);
         }
     }
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 2751ed9..6f2da32 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -285,25 +285,18 @@ void write_type(FILE *h, type_t *t, int is_field, const char *fmt, ...)
   write_type_right(h, t, is_field);
 }
 
-
-struct user_type
-{
-    struct user_type *next;
-    char name[1];
-};
-
-static struct user_type *user_type_list;
+user_type_list_t user_type_list = LIST_INIT(user_type_list);
 
 static int user_type_registered(const char *name)
 {
-  struct user_type *ut;
-  for (ut = user_type_list; ut; ut = ut->next)
+  user_type_t *ut;
+  LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
     if (!strcmp(name, ut->name))
-        return 1;
+      return 1;
   return 0;
 }
 
-static void check_for_user_types(const var_list_t *list)
+void check_for_user_types(const var_list_t *list)
 {
   const var_t *v;
 
@@ -318,10 +311,9 @@ static void check_for_user_types(const var_list_t *list)
       if (is_attr(type->attrs, ATTR_WIREMARSHAL)) {
         if (!user_type_registered(name))
         {
-          struct user_type *ut = xmalloc(sizeof(struct user_type) + strlen(name));
-          strcpy(ut->name, name);
-          ut->next = user_type_list;
-          user_type_list = ut;
+          user_type_t *ut = xmalloc(sizeof *ut);
+          ut->name = xstrdup(name);
+          list_add_tail(&user_type_list, &ut->entry);
         }
         /* don't carry on parsing fields within this type as we are already
          * using a wire marshaled type */
@@ -337,8 +329,8 @@ static void check_for_user_types(const var_list_t *list)
 
 void write_user_types(void)
 {
-  struct user_type *ut;
-  for (ut = user_type_list; ut; ut = ut->next)
+  user_type_t *ut;
+  LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
   {
     const char *name = ut->name;
     fprintf(header, "ULONG           __RPC_USER %s_UserSize     (ULONG *, ULONG, %s *);\n", name, name);
@@ -668,7 +660,6 @@ static void write_method_proto(const type_t *iface)
       fprintf(header, "    IRpcChannelBuffer* pRpcChannelBuffer,\n");
       fprintf(header, "    PRPC_MESSAGE pRpcMessage,\n");
       fprintf(header, "    DWORD* pdwStubPhase);\n");
-      check_for_user_types(cur->args);
     }
     if (cas) {
       const func_t *m;
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index b582673..a991cad 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -125,6 +125,7 @@ static int compute_method_indexes(type_t *iface);
 static char *gen_name(void);
 static void process_typedefs(var_list_t *names);
 static void check_arg(var_t *arg);
+static void check_all_user_types(ifref_list_t *ifaces);
 
 #define tsENUM   1
 #define tsSTRUCT 2
@@ -275,6 +276,7 @@ static void check_arg(var_t *arg);
 %%
 
 input:   gbl_statements				{ fix_incomplete();
+						  check_all_user_types($1);
 						  write_proxies($1);
 						  write_client($1);
 						  write_server($1);
@@ -1932,3 +1934,16 @@ static void check_arg(var_t *arg)
   if (t->type == 0 && ! is_var_ptr(arg))
     yyerror("argument '%s' has void type", arg->name);
 }
+
+static void check_all_user_types(ifref_list_t *ifrefs)
+{
+  const ifref_t *ifref;
+  const func_t *f;
+
+  if (ifrefs) LIST_FOR_EACH_ENTRY(ifref, ifrefs, const ifref_t, entry)
+  {
+    const func_list_t *fs = ifref->iface->funcs;
+    if (fs) LIST_FOR_EACH_ENTRY(f, fs, const func_t, entry)
+      check_for_user_types(f->args);
+  }
+}
diff --git a/tools/widl/proxy.c b/tools/widl/proxy.c
index d057856..72f1f9d 100644
--- a/tools/widl/proxy.c
+++ b/tools/widl/proxy.c
@@ -85,7 +85,7 @@ static void write_stubdesc(void)
   print_proxy( "0,\n");
   print_proxy( "0x50100a4, /* MIDL Version 5.1.164 */\n");
   print_proxy( "0,\n");
-  print_proxy( "0,\n");
+  print_proxy("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines");
   print_proxy( "0,  /* notify & notify_flag routine table */\n");
   print_proxy( "1,  /* Flags */\n");
   print_proxy( "0,  /* Reserved3 */\n");
@@ -373,9 +373,7 @@ static void gen_stub(type_t *iface, const func_t *cur, const char *cas,
   print_proxy("NdrStubInitialize(_pRpcMessage, &_StubMsg, &Object_StubDesc, _pRpcChannelBuffer);\n");
   fprintf(proxy, "\n");
 
-  if (cur->args)
-      LIST_FOR_EACH_ENTRY( arg, cur->args, const var_t, entry )
-          print_proxy("%s = 0;\n", arg->name);
+  write_parameters_init(cur);
 
   print_proxy("RpcTryFinally\n");
   print_proxy("{\n");
@@ -589,6 +587,7 @@ void write_proxies(ifref_list_t *ifaces)
           if (is_object(cur->iface->attrs) && !is_local(cur->iface->attrs))
               write_proxy(cur->iface, &proc_offset);
 
+  write_user_quad_list(proxy);
   write_stubdesc();
 
   print_proxy( "#if !defined(__RPC_WIN32__)\n");
diff --git a/tools/widl/server.c b/tools/widl/server.c
index 40a771d..f85a5bb 100644
--- a/tools/widl/server.c
+++ b/tools/widl/server.c
@@ -61,7 +61,7 @@ static int print_server(const char *format, ...)
 }
 
 
-static void write_parameters_init(const func_t *func)
+void write_parameters_init(const func_t *func)
 {
     const var_t *var;
 
@@ -69,8 +69,14 @@ static void write_parameters_init(const func_t *func)
         return;
 
     LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
-        if (var->type->type != RPC_FC_BIND_PRIMITIVE)
-            print_server("%s = 0;\n", var->name);
+    {
+        const type_t *t = var->type;
+        const char *n = var->name;
+        if (decl_indirect(t))
+            print_server("MIDL_memset(&%s, 0, sizeof %s);\n", n, n);
+        else if (is_ptr(t) || is_array(t))
+            print_server("%s = 0;\n", n);
+    }
 
     fprintf(server, "\n");
 }
@@ -337,7 +343,7 @@ static void write_stubdescriptor(type_t *iface, int expr_eval_routines)
     print_server("0,\n");
     print_server("0x50100a4, /* MIDL Version 5.1.164 */\n");
     print_server("0,\n");
-    print_server("0,\n");
+    print_server("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines");
     print_server("0,  /* notify & notify_flag routine table */\n");
     print_server("1,  /* Flags */\n");
     print_server("0,  /* Reserved3 */\n");
@@ -454,6 +460,7 @@ void write_server(ifref_list_t *ifaces)
             if (expr_eval_routines)
                 write_expr_eval_routine_list(server, iface->iface->name);
 
+            write_user_quad_list(server);
             write_stubdescriptor(iface->iface, expr_eval_routines);
             write_dispatchtable(iface->iface);
         }
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index e3d5292..de9ae54 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -137,6 +137,20 @@ int is_union(unsigned char type)
     }
 }
 
+static unsigned short user_type_offset(const char *name)
+{
+    user_type_t *ut;
+    unsigned short off = 0;
+    LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
+    {
+        if (strcmp(name, ut->name) == 0)
+            return off;
+        ++off;
+    }
+    error("user_type_offset: couldn't find type (%s)\n", name);
+    return 0;
+}
+
 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
 {
     type->typestring_offset = offset;
@@ -154,10 +168,34 @@ static void guard_rec(type_t *type)
         type->typestring_offset = 1;
 }
 
+static type_t *get_user_type(const type_t *t, const char **pname)
+{
+    for (;;)
+    {
+        type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
+        if (ut)
+        {
+            if (pname)
+                *pname = t->name;
+            return ut;
+        }
+
+        if (t->kind == TKIND_ALIAS)
+            t = t->orig;
+        else
+            return 0;
+    }
+}
+
+static int is_user_type(const type_t *t)
+{
+    return get_user_type(t, NULL) != NULL;
+}
+
 static int is_embedded_complex(const type_t *type)
 {
     unsigned char tc = type->type;
-    return is_struct(tc) || is_union(tc) || is_array(type);
+    return is_struct(tc) || is_union(tc) || is_array(type) || is_user_type(type);
 }
 
 static int compare_expr(const expr_t *a, const expr_t *b)
@@ -257,20 +295,6 @@ void write_formatstringsdecl(FILE *f, int indent, ifref_list_t *ifaces, int for_
     print_file(f, indent, "\n");
 }
 
-static int is_user_derived(const var_t *v)
-{
-    const type_t *type = v->type;
-
-    if (v->attrs && is_attr( v->attrs, ATTR_WIREMARSHAL )) return 1;
-
-    while (type)
-    {
-        if (type->attrs && is_attr( type->attrs, ATTR_WIREMARSHAL )) return 1;
-        type = type->ref;
-    }
-    return 0;
-}
-
 static inline int is_base_type(unsigned char type)
 {
     switch (type)
@@ -299,6 +323,14 @@ static inline int is_base_type(unsigned char type)
     }
 }
 
+int decl_indirect(const type_t *t)
+{
+    return is_user_type(t)
+        || (!is_base_type(t->type)
+            && !is_ptr(t)
+            && !is_array(t));
+}
+
 static size_t write_procformatstring_var(FILE *file, int indent,
                                          const var_t *var, int is_return)
 {
@@ -794,6 +826,48 @@ static int processed(const type_t *type)
     return type->typestring_offset && !type->tfswrite;
 }
 
+static void write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
+{
+    unsigned int start, absoff;
+    unsigned int align = 0, ualign = 0;
+    const char *name;
+    type_t *utype = get_user_type(type, &name);
+    size_t usize = type_memsize(utype, &ualign);
+    size_t size = type_memsize(type, &align);
+    unsigned short funoff = user_type_offset(name);
+    short reloff;
+
+    guard_rec(type);
+
+    if (is_base_type(utype->type))
+    {
+        absoff = *tfsoff;
+        print_file(file, 0, "/* %d */\n", absoff);
+        print_file(file, 2, "0x%x,\t/* %s */\n", utype->type, string_of_type(utype->type));
+        print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
+        *tfsoff += 2;
+    }
+    else
+    {
+        if (!processed(utype))
+            write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
+        absoff = utype->typestring_offset;
+    }
+
+    start = *tfsoff;
+    update_tfsoff(type, start, file);
+    print_file(file, 0, "/* %d */\n", start);
+    print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL);
+    print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
+    print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
+    print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", usize, usize);
+    print_file(file, 2, "NdrFcShort(0x%lx),\t/* %lu */\n", size, size);
+    *tfsoff += 8;
+    reloff = absoff - *tfsoff;
+    print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%lu) */\n", reloff, reloff, absoff);
+    *tfsoff += 2;
+}
+
 static void write_member_type(FILE *file, type_t *type, const var_t *field,
                               unsigned int *corroff, unsigned int *tfsoff)
 {
@@ -1396,6 +1470,12 @@ static size_t write_typeformatstring_var(FILE *file, int indent, const func_t *f
     int pointer_type;
     size_t offset;
 
+    if (is_user_type(type))
+    {
+        write_user_tfs(file, type, typeformat_offset);
+        return type->typestring_offset;
+    }
+
     if (type == var->type)      /* top-level pointers */
     {
         int pointer_attr = get_attrv(var->attrs, ATTR_POINTERTYPE);
@@ -1482,8 +1562,13 @@ static void set_tfswrite(type_t *type, int val)
 {
     while (type->tfswrite != val)
     {
+        type_t *utype = get_user_type(type, NULL);
+
         type->tfswrite = val;
 
+        if (utype)
+            set_tfswrite(utype, val);
+
         if (type->kind == TKIND_ALIAS)
             type = type->orig;
         else if (is_ptr(type) || is_array(type))
@@ -1508,7 +1593,11 @@ static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *ty
 {
     int retmask = 0;
 
-    if (is_ptr(type))
+    if (is_user_type(type))
+    {
+        write_user_tfs(file, type, tfsoff);
+    }
+    else if (is_ptr(type))
     {
         type_t *ref = type->ref;
 
@@ -1795,7 +1884,7 @@ static unsigned int get_function_buffer_size( const func_t *func, enum pass pass
 
 static void print_phase_function(FILE *file, int indent, const char *type,
                                  enum remoting_phase phase,
-                                 const char *varname, unsigned int type_offset)
+                                 const var_t *var, unsigned int type_offset)
 {
     const char *function;
     switch (phase)
@@ -1820,9 +1909,11 @@ static void print_phase_function(FILE *file, int indent, const char *type,
     print_file(file, indent, "Ndr%s%s(\n", type, function);
     indent++;
     print_file(file, indent, "&_StubMsg,\n");
-    print_file(file, indent, "%s%s,\n",
-               (phase == PHASE_UNMARSHAL) ? "(unsigned char **)&" : "(unsigned char *)",
-               varname);
+    print_file(file, indent, "%s%s%s%s,\n",
+               (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
+               (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
+               (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
+               var->name);
     print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
                type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
     if (phase == PHASE_UNMARSHAL)
@@ -1971,14 +2062,14 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
 
         rtype = type->type;
 
-        if (is_user_derived( var ))
+        if (is_user_type(var->type))
         {
-            print_phase_function(file, indent, "UserMarshal", phase, var->name, start_offset);
+            print_phase_function(file, indent, "UserMarshal", phase, var, start_offset);
         }
         else if (is_string_type(var->attrs, var->type))
         {
             if (is_array(type) && !is_conformant_array(type))
-                print_phase_function(file, indent, "NonConformantString", phase, var->name, start_offset);
+                print_phase_function(file, indent, "NonConformantString", phase, var, start_offset);
             else
             {
                 if (type->size_is && is_size_needed_for_phase(phase))
@@ -1989,9 +2080,9 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
                 }
 
                 if ((phase == PHASE_FREE) || (pointer_type == RPC_FC_UP))
-                    print_phase_function(file, indent, "Pointer", phase, var->name, start_offset);
+                    print_phase_function(file, indent, "Pointer", phase, var, start_offset);
                 else
-                    print_phase_function(file, indent, "ConformantString", phase, var->name,
+                    print_phase_function(file, indent, "ConformantString", phase, var,
                                          start_offset + (type->size_is ? 4 : 2));
             }
         }
@@ -2049,9 +2140,9 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
             else if (phase != PHASE_FREE)
             {
                 if (pointer_type == RPC_FC_UP)
-                    print_phase_function(file, indent, "Pointer", phase, var->name, start_offset);
+                    print_phase_function(file, indent, "Pointer", phase, var, start_offset);
                 else
-                    print_phase_function(file, indent, array_type, phase, var->name, start_offset);
+                    print_phase_function(file, indent, array_type, phase, var, start_offset);
             }
         }
         else if (!is_ptr(var->type) && is_base_type(rtype))
@@ -2064,17 +2155,17 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
             {
             case RPC_FC_STRUCT:
             case RPC_FC_PSTRUCT:
-                print_phase_function(file, indent, "SimpleStruct", phase, var->name, start_offset);
+                print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset);
                 break;
             case RPC_FC_CSTRUCT:
             case RPC_FC_CPSTRUCT:
-                print_phase_function(file, indent, "ConformantStruct", phase, var->name, start_offset);
+                print_phase_function(file, indent, "ConformantStruct", phase, var, start_offset);
                 break;
             case RPC_FC_CVSTRUCT:
-                print_phase_function(file, indent, "ConformantVaryingStruct", phase, var->name, start_offset);
+                print_phase_function(file, indent, "ConformantVaryingStruct", phase, var, start_offset);
                 break;
             case RPC_FC_BOGUS_STRUCT:
-                print_phase_function(file, indent, "ComplexStruct", phase, var->name, start_offset);
+                print_phase_function(file, indent, "ComplexStruct", phase, var, start_offset);
                 break;
             case RPC_FC_RP:
                 if (is_base_type( var->type->ref->type ))
@@ -2084,14 +2175,14 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
                 else if (var->type->ref->type == RPC_FC_STRUCT)
                 {
                     if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
-                        print_phase_function(file, indent, "SimpleStruct", phase, var->name, start_offset + 4);
+                        print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
                 }
                 else
                 {
                     const var_t *iid;
                     if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
                         print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
-                    print_phase_function(file, indent, "Pointer", phase, var->name, start_offset);
+                    print_phase_function(file, indent, "Pointer", phase, var, start_offset);
                 }
                 break;
             default:
@@ -2107,14 +2198,14 @@ void write_remoting_arguments(FILE *file, int indent, const func_t *func,
             else if (last_ptr(var->type) && (pointer_type == RPC_FC_RP) && (rtype == RPC_FC_STRUCT))
             {
                 if (phase != PHASE_BUFFERSIZE && phase != PHASE_FREE)
-                    print_phase_function(file, indent, "SimpleStruct", phase, var->name, start_offset + 4);
+                    print_phase_function(file, indent, "SimpleStruct", phase, var, start_offset + 4);
             }
             else
             {
                 const var_t *iid;
                 if ((iid = get_attrp( var->attrs, ATTR_IIDIS )))
                     print_file( file, indent, "_StubMsg.MaxCount = (unsigned long)%s;\n", iid->name );
-                print_phase_function(file, indent, "Pointer", phase, var->name, start_offset);
+                print_phase_function(file, indent, "Pointer", phase, var, start_offset);
             }
         }
         fprintf(file, "\n");
@@ -2308,6 +2399,10 @@ void declare_stub_args( FILE *file, int indent, const func_t *func )
             write_name(file, var);
         write_type_right(file, var->type, FALSE);
         fprintf(file, ";\n");
+
+        if (decl_indirect(var->type))
+            print_file(file, indent, "void *_p_%s = &%s;\n",
+                       var->name, var->name);
     }
 }
 
@@ -2414,6 +2509,27 @@ void write_expr_eval_routine_list(FILE *file, const char *iface)
     fprintf(file, "};\n\n");
 }
 
+void write_user_quad_list(FILE *file)
+{
+    user_type_t *ut;
+
+    if (list_empty(&user_type_list))
+        return;
+
+    fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
+    fprintf(file, "{\n");
+    LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
+    {
+        const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ",";
+        print_file(file, 1, "{\n");
+        print_file(file, 2, "%s_UserSize,\n", ut->name);
+        print_file(file, 2, "%s_UserMarshal,\n", ut->name);
+        print_file(file, 2, "%s_UserUnmarshal,\n", ut->name);
+        print_file(file, 2, "%s_UserFree\n", ut->name);
+        print_file(file, 1, "}%s\n", sep);
+    }
+    fprintf(file, "};\n\n");
+}
 
 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
 {
diff --git a/tools/widl/typegen.h b/tools/widl/typegen.h
index 6877a22..be97d01 100644
--- a/tools/widl/typegen.h
+++ b/tools/widl/typegen.h
@@ -48,5 +48,8 @@ void assign_stub_out_args( FILE *file, int indent, const func_t *func );
 void declare_stub_args( FILE *file, int indent, const func_t *func );
 int write_expr_eval_routines(FILE *file, const char *iface);
 void write_expr_eval_routine_list(FILE *file, const char *iface);
+void write_user_quad_list(FILE *file);
 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list );
 size_t type_memsize(const type_t *t, unsigned int *align);
+int decl_indirect(const type_t *t);
+void write_parameters_init(const func_t *func);
diff --git a/tools/widl/widltypes.h b/tools/widl/widltypes.h
index 0fe453b..6235620 100644
--- a/tools/widl/widltypes.h
+++ b/tools/widl/widltypes.h
@@ -46,6 +46,7 @@ typedef struct _typelib_entry_t typelib_entry_t;
 typedef struct _importlib_t importlib_t;
 typedef struct _importinfo_t importinfo_t;
 typedef struct _typelib_t typelib_t;
+typedef struct _user_type_t user_type_t;
 
 typedef struct list attr_list_t;
 typedef struct list str_list_t;
@@ -55,6 +56,7 @@ typedef struct list var_list_t;
 typedef struct list pident_list_t;
 typedef struct list ifref_list_t;
 typedef struct list array_dims_t;
+typedef struct list user_type_list_t;
 
 enum attr_type
 {
@@ -295,6 +297,14 @@ struct _typelib_t {
     struct list importlibs;
 };
 
+struct _user_type_t {
+    struct list entry;
+    const char *name;
+};
+
+extern user_type_list_t user_type_list;
+void check_for_user_types(const var_list_t *list);
+
 void init_types(void);
 
 type_t *duptype(type_t *t, int dupname);



More information about the wine-patches mailing list