rpcrt4, widl: Make pointer layouts compatible with windows; fix conformant array tests.

Dan Hipschman dsh at linux.ucla.edu
Wed Oct 10 17:29:54 CDT 2007


This patch fixes the three conformant array tests that fail, but in order
to do so in a way that they pass on Windows, I needed to tweak the RPC
engine a little bit.  Wine's rpcrt4 adds the array offset and memory offset
entries in the pointer layout, but Windows does not.  For example:  Given
the type:

    struct
    {
        int n;
        [size_is(n)] int *p[];
    } s_t;

MIDL will generate a pointer layout like this:

                        0x48,           /* FC_VARIABLE_REPEAT */
                        0x49,           /* FC_FIXED_OFFSET */
/* 26 */        NdrFcShort( 0x4 ),      /* 4 */
/* 28 */        NdrFcShort( 0x4 ),      /* 4 */
/* 30 */        NdrFcShort( 0x1 ),      /* 1 */
/* 32 */        NdrFcShort( 0x4 ),      /* 4 */
/* 34 */        NdrFcShort( 0x4 ),      /* 4 */
/* 36 */        0x12, 0x8,      /* FC_UP [simple_pointer] */
/* 38 */        0x8,            /* FC_LONG */
                        0x5c,           /* FC_PAD */

So the offset to the array and memory offset are both four (these are the
second and forth 'NdrFcShort's respectively), but when marshalling, the
offsets need to be relative to the beginning of the structure.  Hence, we
can't add these.  I've simply taken the array offset out of the computation.
I'm not really sure what it's used for, actually.  In fact, I don't think
it's used at all since I can manually change it to any arbitrary value I
want and the tests will still pass just fine on Windows.

This patch also adds two new tests.  All the tests pass on wine and Windows,
and I've run the tests in ole32 and oleaut32 (including the second set of
commits from today).

This is basically a resend of this patch:
http://www.winehq.org/pipermail/wine-patches/2007-September/044364.html ,
except it doesn't crash ole32 (which was being caused by incorrect pointer
layouts), and it's got the additional changes mentioned above.  Most of
the comments on the original patch still apply, though.

---
 dlls/rpcrt4/ndr_marshall.c   |   59 ++++-----------------
 dlls/rpcrt4/tests/server.c   |   76 ++++++++++++++++++++++++++-
 dlls/rpcrt4/tests/server.idl |   15 +++++
 tools/widl/typegen.c         |  119 +++++++++++++++++++++++-------------------
 4 files changed, 164 insertions(+), 105 deletions(-)

diff --git a/dlls/rpcrt4/ndr_marshall.c b/dlls/rpcrt4/ndr_marshall.c
index e238dae..7be2ee6 100644
--- a/dlls/rpcrt4/ndr_marshall.c
+++ b/dlls/rpcrt4/ndr_marshall.c
@@ -1156,8 +1156,7 @@ static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
                                                PFORMAT_STRING pFormat)
 {
   unsigned char *Mark = pStubMsg->BufferMark;
-  unsigned long Offset = pStubMsg->Offset;
-  unsigned ofs, rep, count, stride, xofs;
+  unsigned rep, count, stride;
   unsigned i;
   unsigned char *saved_buffer = NULL;
 
@@ -1180,32 +1179,26 @@ static unsigned char * EmbeddedPointerMarshall(PMIDL_STUB_MESSAGE pStubMsg,
     case RPC_FC_NO_REPEAT:
       rep = 1;
       stride = 0;
-      ofs = 0;
       count = 1;
-      xofs = 0;
       pFormat += 2;
       break;
     case RPC_FC_FIXED_REPEAT:
       rep = *(const WORD*)&pFormat[2];
       stride = *(const WORD*)&pFormat[4];
-      ofs = *(const WORD*)&pFormat[6];
       count = *(const WORD*)&pFormat[8];
-      xofs = 0;
       pFormat += 10;
       break;
     case RPC_FC_VARIABLE_REPEAT:
       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
       stride = *(const WORD*)&pFormat[2];
-      ofs = *(const WORD*)&pFormat[4];
       count = *(const WORD*)&pFormat[6];
-      xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
       pFormat += 8;
       break;
     }
     for (i = 0; i < rep; i++) {
       PFORMAT_STRING info = pFormat;
-      unsigned char *membase = pMemory + ofs + (i * stride);
-      unsigned char *bufbase = Mark + ofs + (i * stride);
+      unsigned char *membase = pMemory + (i * stride);
+      unsigned char *bufbase = Mark + (i * stride);
       unsigned u;
 
       for (u=0; u<count; u++,info+=8) {
@@ -1241,8 +1234,7 @@ static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
                                                  unsigned char fMustAlloc)
 {
   unsigned char *Mark = pStubMsg->BufferMark;
-  unsigned long Offset = pStubMsg->Offset;
-  unsigned ofs, rep, count, stride, xofs;
+  unsigned rep, count, stride;
   unsigned i;
   unsigned char *saved_buffer = NULL;
 
@@ -1266,33 +1258,26 @@ static unsigned char * EmbeddedPointerUnmarshall(PMIDL_STUB_MESSAGE pStubMsg,
     case RPC_FC_NO_REPEAT:
       rep = 1;
       stride = 0;
-      ofs = 0;
       count = 1;
-      xofs = 0;
       pFormat += 2;
       break;
     case RPC_FC_FIXED_REPEAT:
       rep = *(const WORD*)&pFormat[2];
       stride = *(const WORD*)&pFormat[4];
-      ofs = *(const WORD*)&pFormat[6];
       count = *(const WORD*)&pFormat[8];
-      xofs = 0;
       pFormat += 10;
       break;
     case RPC_FC_VARIABLE_REPEAT:
       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
       stride = *(const WORD*)&pFormat[2];
-      ofs = *(const WORD*)&pFormat[4];
       count = *(const WORD*)&pFormat[6];
-      xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
       pFormat += 8;
       break;
     }
-    /* ofs doesn't seem to matter in this context */
     for (i = 0; i < rep; i++) {
       PFORMAT_STRING info = pFormat;
-      unsigned char *membase = *ppMemory + ofs + (i * stride);
-      unsigned char *bufbase = Mark + ofs + (i * stride);
+      unsigned char *membase = *ppMemory + (i * stride);
+      unsigned char *bufbase = Mark + (i * stride);
       unsigned u;
 
       for (u=0; u<count; u++,info+=8) {
@@ -1320,8 +1305,7 @@ static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
                                       unsigned char *pMemory,
                                       PFORMAT_STRING pFormat)
 {
-  unsigned long Offset = pStubMsg->Offset;
-  unsigned ofs, rep, count, stride, xofs;
+  unsigned rep, count, stride;
   unsigned i;
   ULONG saved_buffer_length = 0;
 
@@ -1346,31 +1330,25 @@ static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
     case RPC_FC_NO_REPEAT:
       rep = 1;
       stride = 0;
-      ofs = 0;
       count = 1;
-      xofs = 0;
       pFormat += 2;
       break;
     case RPC_FC_FIXED_REPEAT:
       rep = *(const WORD*)&pFormat[2];
       stride = *(const WORD*)&pFormat[4];
-      ofs = *(const WORD*)&pFormat[6];
       count = *(const WORD*)&pFormat[8];
-      xofs = 0;
       pFormat += 10;
       break;
     case RPC_FC_VARIABLE_REPEAT:
       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
       stride = *(const WORD*)&pFormat[2];
-      ofs = *(const WORD*)&pFormat[4];
       count = *(const WORD*)&pFormat[6];
-      xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
       pFormat += 8;
       break;
     }
     for (i = 0; i < rep; i++) {
       PFORMAT_STRING info = pFormat;
-      unsigned char *membase = pMemory + ofs + (i * stride);
+      unsigned char *membase = pMemory + (i * stride);
       unsigned u;
 
       for (u=0; u<count; u++,info+=8) {
@@ -1398,9 +1376,8 @@ static void EmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg,
 static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
                                                PFORMAT_STRING pFormat)
 {
-  unsigned long Offset = pStubMsg->Offset;
   unsigned char *Mark = pStubMsg->BufferMark;
-  unsigned ofs, rep, count, stride, xofs;
+  unsigned rep, count, stride;
   unsigned i;
 
   TRACE("(%p,%p)\n", pStubMsg, pFormat);
@@ -1419,32 +1396,25 @@ static unsigned long EmbeddedPointerMemorySize(PMIDL_STUB_MESSAGE pStubMsg,
     case RPC_FC_NO_REPEAT:
       rep = 1;
       stride = 0;
-      ofs = 0;
       count = 1;
-      xofs = 0;
       pFormat += 2;
       break;
     case RPC_FC_FIXED_REPEAT:
       rep = *(const WORD*)&pFormat[2];
       stride = *(const WORD*)&pFormat[4];
-      ofs = *(const WORD*)&pFormat[6];
       count = *(const WORD*)&pFormat[8];
-      xofs = 0;
       pFormat += 10;
       break;
     case RPC_FC_VARIABLE_REPEAT:
       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
       stride = *(const WORD*)&pFormat[2];
-      ofs = *(const WORD*)&pFormat[4];
       count = *(const WORD*)&pFormat[6];
-      xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
       pFormat += 8;
       break;
     }
-    /* ofs doesn't seem to matter in this context */
     for (i = 0; i < rep; i++) {
       PFORMAT_STRING info = pFormat;
-      unsigned char *bufbase = Mark + ofs + (i * stride);
+      unsigned char *bufbase = Mark + (i * stride);
       unsigned u;
       for (u=0; u<count; u++,info+=8) {
         unsigned char *bufptr = bufbase + *(const SHORT*)&info[2];
@@ -1464,8 +1434,7 @@ static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
                                 unsigned char *pMemory,
                                 PFORMAT_STRING pFormat)
 {
-  unsigned long Offset = pStubMsg->Offset;
-  unsigned ofs, rep, count, stride, xofs;
+  unsigned rep, count, stride;
   unsigned i;
 
   TRACE("(%p,%p,%p)\n", pStubMsg, pMemory, pFormat);
@@ -1479,25 +1448,19 @@ static void EmbeddedPointerFree(PMIDL_STUB_MESSAGE pStubMsg,
     case RPC_FC_NO_REPEAT:
       rep = 1;
       stride = 0;
-      ofs = 0;
       count = 1;
-      xofs = 0;
       pFormat += 2;
       break;
     case RPC_FC_FIXED_REPEAT:
       rep = *(const WORD*)&pFormat[2];
       stride = *(const WORD*)&pFormat[4];
-      ofs = *(const WORD*)&pFormat[6];
       count = *(const WORD*)&pFormat[8];
-      xofs = 0;
       pFormat += 10;
       break;
     case RPC_FC_VARIABLE_REPEAT:
       rep = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? pStubMsg->ActualCount : pStubMsg->MaxCount;
       stride = *(const WORD*)&pFormat[2];
-      ofs = *(const WORD*)&pFormat[4];
       count = *(const WORD*)&pFormat[6];
-      xofs = (pFormat[1] == RPC_FC_VARIABLE_OFFSET) ? Offset * stride : 0;
       pFormat += 8;
       break;
     }
diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index 55da875..6fe1ce5 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -402,6 +402,35 @@ s_wstr_struct_len(wstr_struct_t *s)
   return lstrlenW(s->s);
 }
 
+int
+s_sum_doub_carr(doub_carr_t *dc)
+{
+  int i, j;
+  int sum = 0;
+  for (i = 0; i < dc->n; ++i)
+    for (j = 0; j < dc->a[i]->n; ++j)
+      sum += dc->a[i]->a[j];
+  return sum;
+}
+
+void
+s_make_pyramid_doub_carr(unsigned char n, doub_carr_t **dc)
+{
+  doub_carr_t *t;
+  int i, j;
+  t = MIDL_user_allocate(FIELD_OFFSET(doub_carr_t, a[n]));
+  t->n = n;
+  for (i = 0; i < n; ++i)
+  {
+    int v = i + 1;
+    t->a[i] = MIDL_user_allocate(FIELD_OFFSET(doub_carr_1_t, a[v]));
+    t->a[i]->n = v;
+    for (j = 0; j < v; ++j)
+      t->a[i]->a[j] = j + 1;
+  }
+  *dc = t;
+}
+
 void
 s_stop(void)
 {
@@ -714,6 +743,25 @@ pointer_tests(void)
   free_list(list);
 }
 
+static int
+check_pyramid_doub_carr(doub_carr_t *dc)
+{
+  int i, j;
+  for (i = 0; i < dc->n; ++i)
+    for (j = 0; j < dc->a[i]->n; ++j)
+      if (dc->a[i]->a[j] != j + 1)
+        return FALSE;
+  return TRUE;
+}
+
+static void
+free_pyramid_doub_carr(doub_carr_t *dc)
+{
+  int i;
+  for (i = 0; i < dc->n; ++i)
+    MIDL_user_free(dc->a[i]);
+}
+
 static void
 array_tests(void)
 {
@@ -730,6 +778,7 @@ array_tests(void)
   cs_t *cs;
   int n;
   int ca[5] = {1, -2, 3, -4, 5};
+  doub_carr_t *dc;
 
   ok(cstr_length(str1, sizeof str1) == strlen(str1), "RPC cstr_length\n");
 
@@ -765,22 +814,43 @@ array_tests(void)
   cps.ca1 = &c[2];
   cps.n = 3;
   cps.ca2 = &c[3];
-  todo_wine ok(sum_cps(&cps) == 53, "RPC sum_cps\n");
+  ok(sum_cps(&cps) == 53, "RPC sum_cps\n");
 
   cpsc.a = 4;
   cpsc.b = 5;
   cpsc.c = 1;
   cpsc.ca = c;
-  todo_wine ok(sum_cpsc(&cpsc) == 6, "RPC sum_cpsc\n");
+  ok(sum_cpsc(&cpsc) == 6, "RPC sum_cpsc\n");
   cpsc.a = 4;
   cpsc.b = 5;
   cpsc.c = 0;
   cpsc.ca = c;
-  todo_wine ok(sum_cpsc(&cpsc) == 10, "RPC sum_cpsc\n");
+  ok(sum_cpsc(&cpsc) == 10, "RPC sum_cpsc\n");
 
   ok(sum_toplev_conf_2n(c, 3) == 15, "RPC sum_toplev_conf_2n\n");
   ok(sum_toplev_conf_cond(c, 5, 6, 1) == 10, "RPC sum_toplev_conf_cond\n");
   ok(sum_toplev_conf_cond(c, 5, 6, 0) == 15, "RPC sum_toplev_conf_cond\n");
+
+  dc = malloc(FIELD_OFFSET(doub_carr_t, a[2]));
+  dc->n = 2;
+  dc->a[0] = malloc(FIELD_OFFSET(doub_carr_1_t, a[3]));
+  dc->a[0]->n = 3;
+  dc->a[0]->a[0] = 5;
+  dc->a[0]->a[1] = 1;
+  dc->a[0]->a[2] = 8;
+  dc->a[1] = malloc(FIELD_OFFSET(doub_carr_1_t, a[2]));
+  dc->a[1]->n = 2;
+  dc->a[1]->a[0] = 2;
+  dc->a[1]->a[1] = 3;
+  ok(sum_doub_carr(dc) == 19, "RPC sum_doub_carr\n");
+  free(dc->a[0]);
+  free(dc->a[1]);
+  free(dc);
+
+  dc = NULL;
+  make_pyramid_doub_carr(4, &dc);
+  ok(check_pyramid_doub_carr(dc), "RPC make_pyramid_doub_carr\n");
+  free_pyramid_doub_carr(dc);
 }
 
 static void
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
index 69ae1d6..6233a1f 100644
--- a/dlls/rpcrt4/tests/server.idl
+++ b/dlls/rpcrt4/tests/server.idl
@@ -250,5 +250,20 @@ cpp_quote("#endif")
   int str_struct_len(str_struct_t *s);
   int wstr_struct_len(wstr_struct_t *s);
 
+  typedef struct
+  {
+    unsigned int n;
+    [size_is(n)] byte a[];
+  } doub_carr_1_t;
+
+  typedef struct
+  {
+    int n;
+    [size_is(n)] doub_carr_1_t *a[];
+  } doub_carr_t;
+
+  int sum_doub_carr(doub_carr_t *dc);
+  void make_pyramid_doub_carr(unsigned char n, [out] doub_carr_t **dc);
+
   void stop(void);
 }
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index f3ca74f..2d6e119 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -51,6 +51,7 @@ struct expr_eval_routine
 {
     struct list entry;
     const type_t *structure;
+    unsigned int baseoff;
     const expr_t *expr;
 };
 
@@ -58,6 +59,7 @@ static size_t fields_memsize(const var_list_t *fields, unsigned int *align);
 static size_t write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff);
 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
                                 const char *name, int write_ptr, unsigned int *tfsoff);
+static const var_t *find_array_or_string_in_struct(const type_t *type);
 
 const char *string_of_type(unsigned char type)
 {
@@ -503,9 +505,12 @@ static int write_base_type(FILE *file, const type_t *type, unsigned int *typestr
 
 /* write conformance / variance descriptor */
 static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
-                                     unsigned int baseoff, const expr_t *expr)
+                                     unsigned int baseoff, const type_t *type,
+                                     const expr_t *expr)
 {
     unsigned char operator_type = 0;
+    unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
+    const char *conftype_string = "";
     const char *operator_string = "no operators";
     const expr_t *subexpr;
 
@@ -540,6 +545,12 @@ static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
         return 4;
     }
 
+    if (is_ptr(type) || (is_array(type) && !type->declarray))
+    {
+        conftype = RPC_FC_POINTER_CONFORMANCE;
+        conftype_string = "field pointer, ";
+    }
+
     subexpr = expr;
     switch (subexpr->type)
     {
@@ -649,8 +660,8 @@ static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
                 correlation_variable_type);
         }
 
-        print_file(file, 2, "0x%x, /* Corr desc: %s */\n",
-                   RPC_FC_NORMAL_CONFORMANCE | param_type, string_of_type(param_type));
+        print_file(file, 2, "0x%x, /* Corr desc: %s%s */\n",
+                   conftype | param_type, conftype_string, string_of_type(param_type));
         print_file(file, 2, "0x%x, /* %s */\n", operator_type, operator_string);
         print_file(file, 2, "NdrFcShort(0x%x), /* offset = %d */\n",
                    offset, offset);
@@ -676,6 +687,7 @@ static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
         {
             eval = xmalloc (sizeof(*eval));
             eval->structure = structure;
+            eval->baseoff = baseoff;
             eval->expr = expr;
             list_add_tail (&expr_eval_routines, &eval->entry);
         }
@@ -683,7 +695,7 @@ static size_t write_conf_or_var_desc(FILE *file, const type_t *structure,
         if (callback_offset > USHRT_MAX)
             error("Maximum number of callback routines reached\n");
 
-        print_file(file, 2, "0x%x, /* Corr desc: */\n", RPC_FC_NORMAL_CONFORMANCE);
+        print_file(file, 2, "0x%x, /* Corr desc: %s */\n", conftype, conftype_string);
         print_file(file, 2, "0x%x, /* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
         print_file(file, 2, "NdrFcShort(0x%x), /* %u */\n", callback_offset, callback_offset);
     }
@@ -949,7 +961,7 @@ static void write_member_type(FILE *file, const type_t *cont,
                               const attr_list_t *attrs, const type_t *type,
                               unsigned int *corroff, unsigned int *tfsoff)
 {
-    if (is_embedded_complex(type))
+    if (is_embedded_complex(type) && !is_conformant_array(type))
     {
         size_t absoff;
         short reloff;
@@ -972,7 +984,7 @@ static void write_member_type(FILE *file, const type_t *cont,
                    reloff, reloff, absoff);
         *tfsoff += 4;
     }
-    else if (is_ptr(type))
+    else if (is_ptr(type) || is_conformant_array(type))
     {
         unsigned char fc = (cont->type == RPC_FC_BOGUS_STRUCT
                             ? RPC_FC_POINTER
@@ -1012,7 +1024,7 @@ static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
             print_file(file, 0, "/* %d */\n", *tfsoff);
             print_file(file, 2, "0x%x,\t/* %s */\n", ft->type, string_of_type(ft->type));
             print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
-            write_conf_or_var_desc(file, current_structure, offset,
+            write_conf_or_var_desc(file, current_structure, offset, ft,
                                    get_attrp(f->attrs, ATTR_SWITCHIS));
             print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
                        reloff, reloff, absoff);
@@ -1032,7 +1044,7 @@ static int write_no_repeat_pointer_descriptions(
     int written = 0;
     unsigned int align;
 
-    if (is_ptr(type))
+    if (is_ptr(type) || (!type->declarray && is_conformant_array(type)))
     {
         print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
         print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
@@ -1042,10 +1054,18 @@ static int write_no_repeat_pointer_descriptions(
         print_file(file, 2, "NdrFcShort(0x%x), /* Buffer offset = %d */\n", *offset_in_buffer, *offset_in_buffer);
         *typestring_offset += 6;
 
-        if (processed(type->ref) || is_base_type(type->ref->type))
+        if (is_ptr(type))
             write_pointer_tfs(file, type, typestring_offset);
         else
-            error("write_pointer_description: type format string unknown\n");
+        {
+            unsigned absoff = type->typestring_offset;
+            short reloff = absoff - (*typestring_offset + 2);
+            /* FIXME: get pointer attributes from field */
+            print_file(file, 2, "0x%02x, 0x0,\t/* %s */\n", RPC_FC_UP, "FC_UP");
+            print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
+                       reloff, reloff, absoff);
+            *typestring_offset += 4;
+        }
 
         align = 0;
         *offset_in_memory += type_memsize(type, &align);
@@ -1207,8 +1227,7 @@ static int write_fixed_array_pointer_descriptions(
  * it is the number of type format characters written */
 static int write_conformant_array_pointer_descriptions(
     FILE *file, const attr_list_t *attrs, type_t *type,
-    size_t *offset_in_memory, size_t *offset_in_buffer,
-    unsigned int *typestring_offset)
+    size_t offset_in_memory, unsigned int *typestring_offset)
 {
     unsigned int align;
     int pointer_count = 0;
@@ -1223,8 +1242,8 @@ static int write_conformant_array_pointer_descriptions(
         if (pointer_count > 0)
         {
             unsigned int increment_size;
-            size_t offset_of_array_pointer_mem = 0;
-            size_t offset_of_array_pointer_buf = 0;
+            size_t offset_of_array_pointer_mem = offset_in_memory;
+            size_t offset_of_array_pointer_buf = offset_in_memory;
 
             align = 0;
             increment_size = type_memsize(type->ref, &align);
@@ -1235,7 +1254,7 @@ static int write_conformant_array_pointer_descriptions(
             print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
             print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET);
             print_file(file, 2, "NdrFcShort(0x%x), /* Increment = %d */\n", increment_size, increment_size);
-            print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", *offset_in_memory, *offset_in_memory);
+            print_file(file, 2, "NdrFcShort(0x%x), /* Offset to array = %d */\n", offset_in_memory, offset_in_memory);
             print_file(file, 2, "NdrFcShort(0x%x), /* Number of pointers = %d */\n", pointer_count, pointer_count);
             *typestring_offset += 8;
 
@@ -1244,26 +1263,6 @@ static int write_conformant_array_pointer_descriptions(
                 &offset_of_array_pointer_buf, typestring_offset);
         }
     }
-    else if (is_struct(type->type))
-    {
-        const var_t *v;
-        LIST_FOR_EACH_ENTRY( v, type->fields, const var_t, entry )
-        {
-            pointer_count += write_conformant_array_pointer_descriptions(
-                file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
-                typestring_offset);
-        }
-    }
-    else
-    {
-        align = 0;
-        if (offset_in_memory)
-            *offset_in_memory += type_memsize(type, &align);
-        /* FIXME: is there a case where these two are different? */
-        align = 0;
-        if (offset_in_buffer)
-            *offset_in_buffer += type_memsize(type, &align);
-    }
 
     return pointer_count;
 }
@@ -1343,11 +1342,14 @@ static void write_pointer_description(FILE *file, type_t *type,
 
     /* pass 1: search for single instance of a pointer (i.e. don't descend
      * into arrays) */
-    offset_in_memory = 0;
-    offset_in_buffer = 0;
-    write_no_repeat_pointer_descriptions(
-        file, type,
-        &offset_in_memory, &offset_in_buffer, typestring_offset);
+    if (!is_array(type))
+    {
+        offset_in_memory = 0;
+        offset_in_buffer = 0;
+        write_no_repeat_pointer_descriptions(
+            file, type,
+            &offset_in_memory, &offset_in_buffer, typestring_offset);
+    }
 
     /* pass 2: search for pointers in fixed arrays */
     offset_in_memory = 0;
@@ -1358,11 +1360,18 @@ static void write_pointer_description(FILE *file, type_t *type,
 
     /* pass 3: search for pointers in conformant only arrays (but don't descend
      * into conformant varying or varying arrays) */
-    offset_in_memory = 0;
-    offset_in_buffer = 0;
-    write_conformant_array_pointer_descriptions(
-        file, NULL, type,
-        &offset_in_memory, &offset_in_buffer, typestring_offset);
+    if ((!type->declarray || !current_structure) && is_conformant_array(type))
+        write_conformant_array_pointer_descriptions(
+            file, NULL, type, 0, typestring_offset);
+    else if (type->type == RPC_FC_CPSTRUCT)
+    {
+        unsigned int align = 0;
+        type_t *carray = find_array_or_string_in_struct(type)->type;
+        write_conformant_array_pointer_descriptions(
+            file, NULL, carray,
+            type_memsize(type, &align),
+            typestring_offset);
+    }
 
    /* pass 4: search for pointers in varying arrays */
     offset_in_memory = 0;
@@ -1447,7 +1456,7 @@ static size_t write_string_tfs(FILE *file, const attr_list_t *attrs,
             (type->declarray && current_structure
              ? type_memsize(current_structure, &align)
              : 0),
-            type->size_is);
+            type, type->size_is);
 
         return start_offset;
     }
@@ -1517,7 +1526,7 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type
         if (is_conformant_array(type))
             *typestring_offset
                 += write_conf_or_var_desc(file, current_structure, baseoff,
-                                          size_is);
+                                          type, size_is);
 
         if (type->type == RPC_FC_SMVARRAY || type->type == RPC_FC_LGVARRAY)
         {
@@ -1542,9 +1551,9 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type
         if (length_is)
             *typestring_offset
                 += write_conf_or_var_desc(file, current_structure, baseoff,
-                                          length_is);
+                                          type, length_is);
 
-        if (has_pointer)
+        if (has_pointer && (!type->declarray || !current_structure))
         {
             print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
             print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
@@ -1564,10 +1573,10 @@ static size_t write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type
         *typestring_offset += 2;
         *typestring_offset
             += write_conf_or_var_desc(file, current_structure, baseoff,
-                                      size_is);
+                                      type, size_is);
         *typestring_offset
             += write_conf_or_var_desc(file, current_structure, baseoff,
-                                      length_is);
+                                      type, length_is);
         write_member_type(file, type, NULL, type->ref, NULL, typestring_offset);
         write_end(file, typestring_offset);
     }
@@ -1922,7 +1931,8 @@ static size_t write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
         expr.is_const = FALSE;
         print_file(file, 2, "0x2f,  /* FC_IP */\n");
         print_file(file, 2, "0x5c,  /* FC_PAD */\n");
-        *typeformat_offset += write_conf_or_var_desc(file, NULL, 0, &expr) + 2;
+        *typeformat_offset
+            += write_conf_or_var_desc(file, NULL, 0, type, &expr) + 2;
     }
     else
     {
@@ -2132,6 +2142,8 @@ static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *ty
     else if (is_array(type))
     {
         write_array_tfs(file, attrs, type, name, tfsoff);
+        if (is_conformant_array(type))
+            retmask |= 1;
     }
     else if (is_struct(type->type))
     {
@@ -3033,14 +3045,13 @@ int write_expr_eval_routines(FILE *file, const char *iface)
     {
         const char *name = eval->structure->name;
         const var_list_t *fields = eval->structure->fields;
-        unsigned align = 0;
         result = 1;
 
         print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
                    iface, name, callback_offset);
         print_file(file, 0, "{\n");
         print_file (file, 1, "%s *%s = (%s *)(pStubMsg->StackTop - %u);\n",
-                    name, var_name, name, type_memsize (eval->structure, &align));
+                    name, var_name, name, eval->baseoff);
         print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
         print_file(file, 1, "pStubMsg->MaxCount = (unsigned long)");
         write_struct_expr(file, eval->expr, 1, fields, var_name);



More information about the wine-patches mailing list