widl: Add padding to the end of complex structures

Dan Hipschman dsh at linux.ucla.edu
Thu Sep 13 20:04:32 CDT 2007


This patch adds padding to the end of complex structures.  This is needed
by oaidl.idl:

$ fgrep -c STRUCTPAD dlls/oleaut32/oaidl_p.c
6

Tested on wine and windows.

---
 dlls/rpcrt4/tests/server.c   |   11 +++++++++++
 dlls/rpcrt4/tests/server.idl |    8 ++++++++
 tools/widl/parser.y          |    3 +++
 tools/widl/typegen.c         |   36 ++++++++++++++++++++++++++++++++++++
 tools/widl/typegen.h         |    1 +
 5 files changed, 59 insertions(+), 0 deletions(-)

diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index cd21468..879e0d1 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -344,6 +344,12 @@ s_sum_aligns(aligns_t *a)
   return a->c + a->i + a->s + a->d;
 }
 
+int
+s_sum_padded(padded_t *p)
+{
+  return p->i + p->c;
+}
+
 void
 s_stop(void)
 {
@@ -392,6 +398,7 @@ basic_tests(void)
   static aligns_t aligns = {3, 4, 5, 6.0};
   pints_t pints;
   ptypes_t ptypes;
+  padded_t padded;
   int i1, i2, i3, *pi2, *pi3, **ppi3;
   double u, v;
   float s, t;
@@ -465,6 +472,10 @@ basic_tests(void)
   ok(enum_ord(E4) == 4, "RPC enum_ord\n");
 
   ok(sum_aligns(&aligns) == 18.0, "RPC sum_aligns\n");
+
+  padded.i = -3;
+  padded.c = 8;
+  ok(sum_padded(&padded) == 5, "RPC sum_padded\n");
 }
 
 static void
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
index 3ee40ae..d84637c 100644
--- a/dlls/rpcrt4/tests/server.idl
+++ b/dlls/rpcrt4/tests/server.idl
@@ -200,5 +200,13 @@ interface IServer
 
   double sum_aligns(aligns_t *a);
 
+  typedef struct
+  {
+    int i;
+    char c;
+  } padded_t;
+
+  int sum_padded(padded_t *p);
+
   void stop(void);
 }
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index 5b4c5ff..5d99c5a 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -1679,6 +1679,9 @@ static int get_struct_type(var_list_t *fields)
   int has_variance = 0;
   var_t *field;
 
+  if (get_padding(fields))
+    return RPC_FC_BOGUS_STRUCT;
+
   if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry )
   {
     type_t *t = field->type;
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index f0c298b..02b2cbc 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -726,6 +726,29 @@ static size_t union_memsize(const var_list_t *fields, unsigned int *pmaxa)
     return maxs;
 }
 
+int get_padding(const var_list_t *fields)
+{
+    unsigned short offset = 0;
+    int salign = -1;
+    const var_t *f;
+
+    if (!fields)
+        return 0;
+
+    LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
+    {
+        type_t *ft = f->type;
+        unsigned int align = 0;
+        size_t size = type_memsize(ft, &align);
+        if (salign == -1)
+            salign = align;
+        offset = (offset + (align - 1)) & ~(align - 1);
+        offset += size;
+    }
+
+    return ((offset + (salign - 1)) & ~(salign - 1)) - offset;
+}
+
 size_t type_memsize(const type_t *t, unsigned int *align)
 {
     size_t size = 0;
@@ -1518,6 +1541,8 @@ static void write_struct_members(FILE *file, const type_t *type,
 {
     const var_t *field;
     unsigned short offset = 0;
+    int salign = -1;
+    int padding;
 
     if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
     {
@@ -1526,6 +1551,8 @@ static void write_struct_members(FILE *file, const type_t *type,
         {
             unsigned int align = 0;
             size_t size = type_memsize(ft, &align);
+            if (salign == -1)
+                salign = align;
             if ((align - 1) & offset)
             {
                 unsigned char fc = 0;
@@ -1549,6 +1576,15 @@ static void write_struct_members(FILE *file, const type_t *type,
         }
     }
 
+    padding = ((offset + (salign - 1)) & ~(salign - 1)) - offset;
+    if (padding)
+    {
+        print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
+                   RPC_FC_STRUCTPAD1 + padding - 1,
+                   padding);
+        *typestring_offset += 1;
+    }
+
     write_end(file, typestring_offset);
 }
 
diff --git a/tools/widl/typegen.h b/tools/widl/typegen.h
index eefecd7..448e503 100644
--- a/tools/widl/typegen.h
+++ b/tools/widl/typegen.h
@@ -55,3 +55,4 @@ size_t type_memsize(const type_t *t, unsigned int *align);
 int decl_indirect(const type_t *t);
 void write_parameters_init(FILE *file, int indent, const func_t *func);
 void print(FILE *file, int indent, const char *format, va_list ap);
+int get_padding(const var_list_t *fields);



More information about the wine-patches mailing list