server: Don't round up the header size for image mappings.
[wine] / tools / widl / typegen.c
1 /*
2  * Format String Generator for IDL Compiler
3  *
4  * Copyright 2005 Eric Kohl
5  * Copyright 2005 Robert Shearman
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #include <string.h>
31 #include <assert.h>
32 #include <ctype.h>
33 #include <signal.h>
34
35 #include "widl.h"
36 #include "utils.h"
37 #include "parser.h"
38 #include "header.h"
39 #include "windef.h"
40
41 #include "widl.h"
42 #include "typegen.h"
43
44 static size_t get_size_typeformatstring_type(const type_t *type, int ptr_level,
45     const expr_t *array, const char *name);
46
47 static int print_file(FILE *file, int indent, const char *format, ...)
48 {
49     va_list va;
50     int i, r;
51
52     if (!file) return 0;
53
54     va_start(va, format);
55     for (i = 0; i < indent; i++)
56         fprintf(file, "    ");
57     r = vfprintf(file, format, va);
58     va_end(va);
59     return r;
60 }
61
62 static inline int type_has_ref(const type_t *type)
63 {
64     return (type->type == 0 && type->ref);
65 }
66
67 static inline int is_base_type(unsigned char type)
68 {
69     switch (type)
70     {
71     case RPC_FC_BYTE:
72     case RPC_FC_CHAR:
73     case RPC_FC_USMALL:
74     case RPC_FC_SMALL:
75     case RPC_FC_WCHAR:
76     case RPC_FC_USHORT:
77     case RPC_FC_SHORT:
78     case RPC_FC_ULONG:
79     case RPC_FC_LONG:
80     case RPC_FC_HYPER:
81     case RPC_FC_IGNORE:
82     case RPC_FC_FLOAT:
83     case RPC_FC_DOUBLE:
84     case RPC_FC_ENUM16:
85     case RPC_FC_ENUM32:
86     case RPC_FC_ERROR_STATUS_T:
87         return TRUE;
88
89     default:
90         return FALSE;
91     }
92 }
93
94 static size_t write_procformatstring_type(FILE *file, int indent,
95     const type_t *type, int ptr_level, const expr_t *array, const char *name,
96     int is_in, int is_out, int is_return, unsigned int *type_offset)
97 {
98     size_t size;
99
100     if (ptr_level == 0 && type_has_ref(type))
101         return write_procformatstring_type(file, indent, type->ref, ptr_level,
102                                            array, name, is_in, is_out,
103                                            is_return, type_offset);
104
105     if (ptr_level == 0 && !array && is_base_type(type->type))
106     {
107         if (is_return)
108             print_file(file, indent, "0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
109         else
110             print_file(file, indent, "0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
111
112         switch(type->type)
113         {
114 #define CASE_BASETYPE(fctype) \
115         case RPC_##fctype: \
116             print_file(file, indent, "0x%02x,    /* " #fctype " */\n", RPC_##fctype); \
117             size = 2; /* includes param type prefix */ \
118             break
119
120         CASE_BASETYPE(FC_BYTE);
121         CASE_BASETYPE(FC_CHAR);
122         CASE_BASETYPE(FC_WCHAR);
123         CASE_BASETYPE(FC_USHORT);
124         CASE_BASETYPE(FC_SHORT);
125         CASE_BASETYPE(FC_ULONG);
126         CASE_BASETYPE(FC_LONG);
127         CASE_BASETYPE(FC_HYPER);
128         CASE_BASETYPE(FC_IGNORE);
129         CASE_BASETYPE(FC_USMALL);
130         CASE_BASETYPE(FC_SMALL);
131         CASE_BASETYPE(FC_FLOAT);
132         CASE_BASETYPE(FC_DOUBLE);
133         CASE_BASETYPE(FC_ERROR_STATUS_T);
134 #undef CASE_BASETYPE
135         default:
136             error("Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
137             size = 0;
138         }
139     }
140     else
141     {
142         if (is_return)
143             print_file(file, indent, "0x52,    /* FC_RETURN_PARAM */\n");
144         else if (is_in && is_out)
145             print_file(file, indent, "0x50,    /* FC_IN_OUT_PARAM */\n");
146         else if (is_out)
147             print_file(file, indent, "0x51,    /* FC_OUT_PARAM */\n");
148         else
149             print_file(file, indent, "0x4d,    /* FC_IN_PARAM */\n");
150
151         print_file(file, indent, "0x01,\n");
152         print_file(file, indent, "NdrFcShort(0x%x),\n", *type_offset);
153         size = 4; /* includes param type prefix */
154     }
155     *type_offset += get_size_typeformatstring_type(type, ptr_level, array, name);
156     return size;
157 }
158
159 void write_procformatstring(FILE *file, type_t *iface)
160 {
161     int indent = 0;
162     var_t *var;
163     unsigned int type_offset = 2;
164
165     print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
166     print_file(file, indent, "{\n");
167     indent++;
168     print_file(file, indent, "0,\n");
169     print_file(file, indent, "{\n");
170     indent++;
171
172     if (iface->funcs)
173     {
174         func_t *func = iface->funcs;
175         while (NEXT_LINK(func)) func = NEXT_LINK(func);
176         for (; func; func = PREV_LINK(func))
177         {
178             /* emit argument data */
179             if (func->args)
180             {
181                 var = func->args;
182                 while (NEXT_LINK(var)) var = NEXT_LINK(var);
183                 while (var)
184                 {
185                     int is_in = is_attr(var->attrs, ATTR_IN);
186                     int is_out = is_attr(var->attrs, ATTR_OUT);
187
188                     if (!is_in && !is_out) is_in = TRUE;
189                     write_procformatstring_type(file, indent, var->type,
190                         var->ptr_level, var->array, var->name,
191                         is_in, is_out, FALSE, &type_offset);
192
193                     var = PREV_LINK(var);
194                 }
195             }
196
197             /* emit return value data */
198             var = func->def;
199             if (is_void(var->type, NULL))
200             {
201                 print_file(file, indent, "0x5b,    /* FC_END */\n");
202                 print_file(file, indent, "0x5c,    /* FC_PAD */\n");
203             }
204             else
205                 write_procformatstring_type(file, indent, var->type,
206                     var->ptr_level, var->array, var->name, FALSE, FALSE, TRUE,
207                     &type_offset);
208         }
209     }
210
211     print_file(file, indent, "0x0\n");
212     indent--;
213     print_file(file, indent, "}\n");
214     indent--;
215     print_file(file, indent, "};\n");
216     print_file(file, indent, "\n");
217 }
218
219
220 static size_t write_typeformatstring_type(FILE *file, int indent,
221     const type_t *type, int ptr_level, const expr_t *array, const char *name)
222 {
223     if (ptr_level == 0 && type_has_ref(type))
224         return write_typeformatstring_type(file, indent,
225             type->ref, 0 /* FIXME */, array, name);
226
227     /* basic types don't need a type format string */
228     if (ptr_level == 0 && !array && is_base_type(type->type))
229         return 0;
230
231     if ((ptr_level == 1 && !type_has_ref(type)) ||
232         (ptr_level == 0 && array && !NEXT_LINK(array)))
233     {
234         switch (type->type)
235         {
236 #define CASE_BASETYPE(fctype) \
237         case RPC_##fctype: \
238             print_file(file, indent, "0x11, 0x08,    /* FC_RP [simple_pointer] */\n"); \
239             print_file(file, indent, "0x%02x,    /* " #fctype " */\n", RPC_##fctype); \
240             print_file(file, indent, "0x5c,          /* FC_PAD */\n"); \
241             return 4
242         CASE_BASETYPE(FC_BYTE);
243         CASE_BASETYPE(FC_CHAR);
244         CASE_BASETYPE(FC_SMALL);
245         CASE_BASETYPE(FC_USMALL);
246         CASE_BASETYPE(FC_WCHAR);
247         CASE_BASETYPE(FC_SHORT);
248         CASE_BASETYPE(FC_USHORT);
249         CASE_BASETYPE(FC_LONG);
250         CASE_BASETYPE(FC_ULONG);
251         CASE_BASETYPE(FC_FLOAT);
252         CASE_BASETYPE(FC_HYPER);
253         CASE_BASETYPE(FC_DOUBLE);
254         CASE_BASETYPE(FC_ENUM16);
255         CASE_BASETYPE(FC_ENUM32);
256         CASE_BASETYPE(FC_IGNORE);
257         CASE_BASETYPE(FC_ERROR_STATUS_T);
258         default:
259             error("write_typeformatstring_var: Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
260         }
261     }
262     error("write_typeformatstring_var: Pointer level %d not supported for variable %s\n", ptr_level, name);
263     return 0;
264 }
265
266
267 void write_typeformatstring(FILE *file, type_t *iface)
268 {
269     int indent = 0;
270     var_t *var;
271
272     print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
273     print_file(file, indent, "{\n");
274     indent++;
275     print_file(file, indent, "0,\n");
276     print_file(file, indent, "{\n");
277     indent++;
278     print_file(file, indent, "NdrFcShort(0x0),\n");
279
280     if (iface->funcs)
281     {
282         func_t *func = iface->funcs;
283         while (NEXT_LINK(func)) func = NEXT_LINK(func);
284         for (; func; func = PREV_LINK(func))
285         {
286             if (func->args)
287             {
288                 var = func->args;
289                 while (NEXT_LINK(var)) var = NEXT_LINK(var);
290                 while (var)
291                 {
292                     write_typeformatstring_type(file, indent, var->type,
293                         var->ptr_level, var->array, var->name);
294                     var = PREV_LINK(var);
295                 }
296             }
297         }
298     }
299
300     print_file(file, indent, "0x0\n");
301     indent--;
302     print_file(file, indent, "}\n");
303     indent--;
304     print_file(file, indent, "};\n");
305     print_file(file, indent, "\n");
306 }
307
308 static unsigned int get_required_buffer_size_type(
309     const type_t *type, int ptr_level, const expr_t *array,
310     const char *name, unsigned int *alignment)
311 {
312     *alignment = 0;
313     if (ptr_level == 0 && !array && !type_has_ref(type))
314     {
315         switch (type->type)
316         {
317         case RPC_FC_BYTE:
318         case RPC_FC_CHAR:
319         case RPC_FC_USMALL:
320         case RPC_FC_SMALL:
321             return 1;
322
323         case RPC_FC_WCHAR:
324         case RPC_FC_USHORT:
325         case RPC_FC_SHORT:
326             *alignment = 2;
327             return 2;
328
329         case RPC_FC_ULONG:
330         case RPC_FC_LONG:
331         case RPC_FC_FLOAT:
332         case RPC_FC_ERROR_STATUS_T:
333             *alignment = 4;
334             return 4;
335
336         case RPC_FC_HYPER:
337         case RPC_FC_DOUBLE:
338             *alignment = 8;
339             return 8;
340
341         case RPC_FC_STRUCT:
342         {
343             size_t size = 0;
344             const var_t *field;
345             for (field = type->fields; field; field = NEXT_LINK(field))
346             {
347                 unsigned int alignment;
348                 size += get_required_buffer_size_type(
349                     field->type, field->ptr_level, field->array, field->name,
350                     &alignment);
351             }
352             return size;
353         }
354
355         default:
356             error("get_required_buffer_size: Unknown/unsupported type: %s (0x%02x)\n", name, type->type);
357             return 0;
358         }
359     }
360     if (ptr_level == 0 && type_has_ref(type))
361         return get_required_buffer_size_type(type->ref, 0 /* FIXME */, array, name, alignment);
362     return 0;
363 }
364
365 unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment)
366 {
367     return get_required_buffer_size_type(var->type, var->ptr_level, var->array, var->name, alignment);
368 }
369
370 void marshall_arguments(FILE *file, int indent, func_t *func,
371                         unsigned int *type_offset, enum pass pass)
372 {
373     unsigned int last_size = 0;
374     var_t *var;
375
376     if (!func->args)
377         return;
378
379     var = func->args;
380     while (NEXT_LINK(var)) var = NEXT_LINK(var);
381     for (; var; *type_offset += get_size_typeformatstring_var(var), var = PREV_LINK(var))
382     {
383         int in_attr = is_attr(var->attrs, ATTR_IN);
384         int out_attr = is_attr(var->attrs, ATTR_OUT);
385
386         if (!in_attr && !out_attr)
387             in_attr = 1;
388
389         switch (pass)
390         {
391         case PASS_IN:
392             if (!in_attr)
393                 continue;
394             break;
395         case PASS_OUT:
396             if (!out_attr)
397                 continue;
398             break;
399         case PASS_RETURN:
400             break;
401         }
402
403         if (var->ptr_level == 0 && !var->array)
404         {
405             unsigned int size;
406             unsigned int alignment = 0;
407             switch (var->type->type)
408             {
409             case RPC_FC_BYTE:
410             case RPC_FC_CHAR:
411             case RPC_FC_SMALL:
412             case RPC_FC_USMALL:
413                 size = 1;
414                 alignment = 0;
415                 break;
416
417             case RPC_FC_WCHAR:
418             case RPC_FC_USHORT:
419             case RPC_FC_SHORT:
420                 size = 2;
421                 if (last_size != 0 && last_size < 2)
422                     alignment = (2 - last_size);
423                 break;
424
425             case RPC_FC_ULONG:
426             case RPC_FC_LONG:
427             case RPC_FC_FLOAT:
428             case RPC_FC_ERROR_STATUS_T:
429                 size = 4;
430                 if (last_size != 0 && last_size < 4)
431                     alignment = (4 - last_size);
432                 break;
433
434             case RPC_FC_HYPER:
435             case RPC_FC_DOUBLE:
436                 size = 8;
437                 if (last_size != 0 && last_size < 4)
438                     alignment = (4 - last_size);
439                 break;
440
441             default:
442                 error("marshall_arguments: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, var->type->type);
443                 size = 0;
444             }
445
446             if (alignment != 0)
447                 print_file(file, indent, "_StubMsg.Buffer += %u;\n", alignment);
448
449             print_file(file, indent, "*(");
450             write_type(file, var->type, var, var->tname);
451             fprintf(file, " *)_StubMsg.Buffer = ");
452             write_name(file, var);
453             fprintf(file, ";\n");
454             fprintf(file, "_StubMsg.Buffer += sizeof(");
455             write_type(file, var->type, var, var->tname);
456             fprintf(file, ");\n");
457
458             last_size = size;
459         }
460         else if ((var->ptr_level == 1 && !var->array) ||
461             (var->ptr_level == 0 && var->array))
462         {
463             if (is_attr(var->attrs, ATTR_STRING))
464             {
465                 switch (var->type->type)
466                 {
467                 case RPC_FC_CHAR:
468                 case RPC_FC_WCHAR:
469                     print_file(file, indent,
470                         "NdrConformantStringMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
471                         var->name, *type_offset);
472                     break;
473                 default:
474                     error("marshall_arguments: Unsupported [string] type: %s (0x%02x, ptr_level: 1)\n", var->name, var->type->type);
475                 }
476             }
477             else if (var->array)
478             {
479                 const expr_t *length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
480                 const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
481                 const char *array_type;
482                 int has_length = length_is && (length_is->type != EXPR_VOID);
483                 int has_size = size_is && (size_is->type != EXPR_VOID) && !var->array->is_const;
484
485                 if (NEXT_LINK(var->array)) /* multi-dimensional array */
486                     array_type = "ComplexArray";
487                 else
488                 {
489                     if (!has_length && !has_size)
490                         array_type = "FixedArray";
491                     else if (has_length && !has_size)
492                     {
493                         print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
494                         print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
495                         write_expr(file, length_is, 1);
496                         fprintf(file, ";\n\n");
497                         array_type = "VaryingArray";
498                     }
499                     else if (!has_length && has_size)
500                     {
501                         print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
502                         write_expr(file, size_is ? size_is : var->array, 1);
503                         fprintf(file, ";\n\n");
504                         array_type = "ConformantArray";
505                     }
506                     else
507                     {
508                         print_file(file, indent, "_StubMsg.MaxCount = (unsigned long)");
509                         write_expr(file, size_is ? size_is : var->array, 1);
510                         fprintf(file, ";\n");
511                         print_file(file, indent, "_StubMsg.Offset = (unsigned long)0;\n"); /* FIXME */
512                         print_file(file, indent, "_StubMsg.ActualCount = (unsigned long)");
513                         write_expr(file, length_is, 1);
514                         fprintf(file, ";\n\n");
515                         array_type = "ConformantVaryingArray";
516                     }
517                 }
518
519                 print_file(file, indent,
520                     "Ndr%sMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
521                     array_type, var->name, *type_offset);
522             }
523             else
524             {
525                 const char *ndrtype;
526
527                 switch (var->type->type)
528                 {
529                 case RPC_FC_STRUCT:
530                     ndrtype = "SimpleStruct";
531                     break;
532                 case RPC_FC_CSTRUCT:
533                 case RPC_FC_CPSTRUCT:
534                     ndrtype = "ConformantStruct";
535                     break;
536                 case RPC_FC_CVSTRUCT:
537                     ndrtype = "ConformantVaryingStruct";
538                     break;
539                 case RPC_FC_BOGUS_STRUCT:
540                     ndrtype = "ComplexStruct";
541                     break;
542                 default:
543                     error("marshall_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n",
544                         var->name, var->type->type, var->ptr_level);
545                     ndrtype = NULL;
546                 }
547
548                 print_file(file, indent,
549                     "Ndr%sMarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d]);\n",
550                     ndrtype, var->name, *type_offset);
551             }
552             last_size = 1;
553         }
554         else
555         {
556             error("marshall_arguments: Pointer level %d not supported for variable %s\n", var->ptr_level, var->name);
557             last_size = 1;
558         }
559         fprintf(file, "\n");
560     }
561 }
562
563 void unmarshall_arguments(FILE *file, int indent, func_t *func,
564                           unsigned int *type_offset, enum pass pass)
565 {
566     unsigned int last_size = 0;
567     var_t *var;
568
569     if (!func->args)
570         return;
571
572     var = func->args;
573     while (NEXT_LINK(var)) var = NEXT_LINK(var);
574     for (; var; *type_offset += get_size_typeformatstring_var(var), var = PREV_LINK(var))
575     {
576         int in_attr = is_attr(var->attrs, ATTR_IN);
577         int out_attr = is_attr(var->attrs, ATTR_OUT);
578
579         if (!in_attr && !out_attr)
580             in_attr = 1;
581
582         switch (pass)
583         {
584         case PASS_IN:
585             if (!in_attr)
586                 continue;
587             break;
588         case PASS_OUT:
589             if (!out_attr)
590                 continue;
591             break;
592         case PASS_RETURN:
593             break;
594         }
595
596         if (var->ptr_level == 0 && !var->array)
597         {
598             unsigned int size;
599             unsigned int alignment = 0;
600
601             switch (var->type->type)
602             {
603             case RPC_FC_BYTE:
604             case RPC_FC_CHAR:
605             case RPC_FC_SMALL:
606             case RPC_FC_USMALL:
607                 size = 1;
608                 alignment = 0;
609                 break;
610
611             case RPC_FC_WCHAR:
612             case RPC_FC_USHORT:
613             case RPC_FC_SHORT:
614                 size = 2;
615                 if (last_size != 0 && last_size < 2)
616                     alignment = (2 - last_size);
617                 break;
618
619             case RPC_FC_ULONG:
620             case RPC_FC_LONG:
621             case RPC_FC_FLOAT:
622             case RPC_FC_ERROR_STATUS_T:
623                 size = 4;
624                 if (last_size != 0 && last_size < 4)
625                     alignment = (4 - last_size);
626                 break;
627
628             case RPC_FC_HYPER:
629             case RPC_FC_DOUBLE:
630                 size = 8;
631                 if (last_size != 0 && last_size < 4)
632                     alignment = (4 - last_size);
633                 break;
634
635             default:
636                 error("unmarshall_arguments: Unsupported type: %s (0x%02x, ptr_level: 0)\n", var->name, var->type->type);
637                 size = 0;
638             }
639
640             if (alignment != 0)
641                 print_file(file, indent, "_StubMsg.Buffer += %u;\n", alignment);
642
643             print_file(file, indent, "");
644             write_name(file, var);
645             fprintf(file, " = *(");
646             write_type(file, var->type, var, var->tname);
647             fprintf(file, " *)_StubMsg.Buffer;\n");
648             fprintf(file, "_StubMsg.Buffer += sizeof(");
649             write_type(file, var->type, var, var->tname);
650             fprintf(file, ");\n");
651
652             last_size = size;
653         }
654         else if ((var->ptr_level == 1 && !var->array) ||
655             (var->ptr_level == 0 && var->array))
656         {
657             if (is_attr(var->attrs, ATTR_STRING))
658             {
659                 switch (var->type->type)
660                 {
661                 case RPC_FC_CHAR:
662                 case RPC_FC_WCHAR:
663                     print_file(file, indent,
664                         "NdrConformantStringUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
665                         var->name, *type_offset);
666                     break;
667                 default:
668                     error("unmarshall_arguments: Unsupported [string] type: %s (0x%02x, ptr_level: %d)\n",
669                         var->name, var->type->type, var->ptr_level);
670                 }
671             }
672             else if (var->array)
673             {
674                 const expr_t *length_is = get_attrp(var->attrs, ATTR_LENGTHIS);
675                 const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
676                 const char *array_type;
677                 int has_length = length_is && (length_is->type != EXPR_VOID);
678                 int has_size = size_is && (size_is->type != EXPR_VOID) && !var->array->is_const;
679
680                 if (NEXT_LINK(var->array)) /* multi-dimensional array */
681                     array_type = "ComplexArray";
682                 else
683                 {
684                     if (!has_length && !has_size)
685                         array_type = "FixedArray";
686                     else if (has_length && !has_size)
687                         array_type = "VaryingArray";
688                     else if (!has_length && has_size)
689                         array_type = "ConformantArray";
690                     else
691                         array_type = "ConformantVaryingArray";
692                 }
693
694                 print_file(file, indent,
695                     "Ndr%sUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
696                     array_type, var->name, *type_offset);
697             }
698             else
699             {
700                 const char *ndrtype;
701
702                 switch (var->type->type)
703                 {
704                 case RPC_FC_STRUCT:
705                     ndrtype = "SimpleStruct";
706                     break;
707                 case RPC_FC_CSTRUCT:
708                 case RPC_FC_CPSTRUCT:
709                     ndrtype = "ConformantStruct";
710                     break;
711                 case RPC_FC_CVSTRUCT:
712                     ndrtype = "ConformantVaryingStruct";
713                     break;
714                 case RPC_FC_BOGUS_STRUCT:
715                     ndrtype = "ComplexStruct";
716                     break;
717                 default:
718                     error("unmarshall_arguments: Unsupported type: %s (0x%02x, ptr_level: %d)\n",
719                         var->name, var->type->type, var->ptr_level);
720                     ndrtype = NULL;
721                 }
722
723                 print_file(file, indent,
724                     "Ndr%sUnmarshall(&_StubMsg, (unsigned char *)%s, &__MIDL_TypeFormatString.Format[%d], 0);\n",
725                     ndrtype, var->name, *type_offset);
726             }
727             last_size = 1;
728         }
729         else
730         {
731             error("unmarshall_arguments: Pointer level %d not supported for variable %s\n", var->ptr_level, var->name);
732             last_size = 1;
733         }
734         fprintf(file, "\n");
735     }
736 }
737
738
739 static size_t get_size_typeformatstring_type(const type_t *type, int ptr_level,
740     const expr_t *array, const char *name)
741 {
742     return write_typeformatstring_type(NULL, 0, type, ptr_level, array, name);
743 }
744
745
746 size_t get_size_procformatstring_var(var_t *var)
747 {
748     unsigned int type_offset = 2;
749     return write_procformatstring_type(NULL, 0, var->type,
750         var->ptr_level, var->array, var->name, FALSE, FALSE, FALSE, &type_offset);
751 }
752
753
754 size_t get_size_typeformatstring_var(var_t *var)
755 {
756     return write_typeformatstring_type(NULL, 0, var->type, var->ptr_level,
757         var->array, var->name);
758 }