widl: Add a -O option to specify stub style.
[wine] / tools / widl / typegen.c
1 /*
2  * Format String Generator for IDL Compiler
3  *
4  * Copyright 2005-2006 Eric Kohl
5  * Copyright 2005-2006 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 <limits.h>
34
35 #include "widl.h"
36 #include "utils.h"
37 #include "parser.h"
38 #include "header.h"
39 #include "typetree.h"
40
41 #include "typegen.h"
42 #include "expr.h"
43
44 /* round size up to multiple of alignment */
45 #define ROUND_SIZE(size, alignment) (((size) + ((alignment) - 1)) & ~((alignment) - 1))
46 /* value to add on to round size up to a multiple of alignment */
47 #define ROUNDING(size, alignment) (((alignment) - 1) - (((size) + ((alignment) - 1)) & ((alignment) - 1)))
48
49 static const type_t *current_structure;
50 static const var_t *current_func;
51 static const type_t *current_iface;
52
53 static struct list expr_eval_routines = LIST_INIT(expr_eval_routines);
54 struct expr_eval_routine
55 {
56     struct list   entry;
57     const type_t *iface;
58     const type_t *cont_type;
59     char         *name;
60     unsigned int  baseoff;
61     const expr_t *expr;
62 };
63
64 enum type_context
65 {
66     TYPE_CONTEXT_TOPLEVELPARAM,
67     TYPE_CONTEXT_PARAM,
68     TYPE_CONTEXT_CONTAINER,
69     TYPE_CONTEXT_CONTAINER_NO_POINTERS,
70 };
71
72 static unsigned int field_memsize(const type_t *type, unsigned int *offset);
73 static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align);
74 static unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align);
75 static unsigned int write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff);
76 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
77                                 const char *name, int write_ptr, unsigned int *tfsoff);
78 static const var_t *find_array_or_string_in_struct(const type_t *type);
79 static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
80                                type_t *type, int toplevel_param,
81                                const char *name, unsigned int *typestring_offset);
82
83 static const char *string_of_type(unsigned char type)
84 {
85     switch (type)
86     {
87     case RPC_FC_BYTE: return "FC_BYTE";
88     case RPC_FC_CHAR: return "FC_CHAR";
89     case RPC_FC_SMALL: return "FC_SMALL";
90     case RPC_FC_USMALL: return "FC_USMALL";
91     case RPC_FC_WCHAR: return "FC_WCHAR";
92     case RPC_FC_SHORT: return "FC_SHORT";
93     case RPC_FC_USHORT: return "FC_USHORT";
94     case RPC_FC_LONG: return "FC_LONG";
95     case RPC_FC_ULONG: return "FC_ULONG";
96     case RPC_FC_FLOAT: return "FC_FLOAT";
97     case RPC_FC_HYPER: return "FC_HYPER";
98     case RPC_FC_DOUBLE: return "FC_DOUBLE";
99     case RPC_FC_ENUM16: return "FC_ENUM16";
100     case RPC_FC_ENUM32: return "FC_ENUM32";
101     case RPC_FC_IGNORE: return "FC_IGNORE";
102     case RPC_FC_ERROR_STATUS_T: return "FC_ERROR_STATUS_T";
103     case RPC_FC_RP: return "FC_RP";
104     case RPC_FC_UP: return "FC_UP";
105     case RPC_FC_OP: return "FC_OP";
106     case RPC_FC_FP: return "FC_FP";
107     case RPC_FC_ENCAPSULATED_UNION: return "FC_ENCAPSULATED_UNION";
108     case RPC_FC_NON_ENCAPSULATED_UNION: return "FC_NON_ENCAPSULATED_UNION";
109     case RPC_FC_STRUCT: return "FC_STRUCT";
110     case RPC_FC_PSTRUCT: return "FC_PSTRUCT";
111     case RPC_FC_CSTRUCT: return "FC_CSTRUCT";
112     case RPC_FC_CPSTRUCT: return "FC_CPSTRUCT";
113     case RPC_FC_CVSTRUCT: return "FC_CVSTRUCT";
114     case RPC_FC_BOGUS_STRUCT: return "FC_BOGUS_STRUCT";
115     case RPC_FC_SMFARRAY: return "FC_SMFARRAY";
116     case RPC_FC_LGFARRAY: return "FC_LGFARRAY";
117     case RPC_FC_SMVARRAY: return "FC_SMVARRAY";
118     case RPC_FC_LGVARRAY: return "FC_LGVARRAY";
119     case RPC_FC_CARRAY: return "FC_CARRAY";
120     case RPC_FC_CVARRAY: return "FC_CVARRAY";
121     case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY";
122     case RPC_FC_ALIGNM2: return "FC_ALIGNM2";
123     case RPC_FC_ALIGNM4: return "FC_ALIGNM4";
124     case RPC_FC_ALIGNM8: return "FC_ALIGNM8";
125     case RPC_FC_POINTER: return "FC_POINTER";
126     case RPC_FC_C_CSTRING: return "FC_C_CSTRING";
127     case RPC_FC_C_WSTRING: return "FC_C_WSTRING";
128     case RPC_FC_CSTRING: return "FC_CSTRING";
129     case RPC_FC_WSTRING: return "FC_WSTRING";
130     case RPC_FC_BYTE_COUNT_POINTER: return "FC_BYTE_COUNT_POINTER";
131     case RPC_FC_TRANSMIT_AS: return "FC_TRANSMIT_AS";
132     case RPC_FC_REPRESENT_AS: return "FC_REPRESENT_AS";
133     case RPC_FC_IP: return "FC_IP";
134     case RPC_FC_BIND_CONTEXT: return "FC_BIND_CONTEXT";
135     case RPC_FC_BIND_GENERIC: return "FC_BIND_GENERIC";
136     case RPC_FC_BIND_PRIMITIVE: return "FC_BIND_PRIMITIVE";
137     case RPC_FC_AUTO_HANDLE: return "FC_AUTO_HANDLE";
138     case RPC_FC_CALLBACK_HANDLE: return "FC_CALLBACK_HANDLE";
139     case RPC_FC_STRUCTPAD1: return "FC_STRUCTPAD1";
140     case RPC_FC_STRUCTPAD2: return "FC_STRUCTPAD2";
141     case RPC_FC_STRUCTPAD3: return "FC_STRUCTPAD3";
142     case RPC_FC_STRUCTPAD4: return "FC_STRUCTPAD4";
143     case RPC_FC_STRUCTPAD5: return "FC_STRUCTPAD5";
144     case RPC_FC_STRUCTPAD6: return "FC_STRUCTPAD6";
145     case RPC_FC_STRUCTPAD7: return "FC_STRUCTPAD7";
146     case RPC_FC_STRING_SIZED: return "FC_STRING_SIZED";
147     case RPC_FC_NO_REPEAT: return "FC_NO_REPEAT";
148     case RPC_FC_FIXED_REPEAT: return "FC_FIXED_REPEAT";
149     case RPC_FC_VARIABLE_REPEAT: return "FC_VARIABLE_REPEAT";
150     case RPC_FC_FIXED_OFFSET: return "FC_FIXED_OFFSET";
151     case RPC_FC_VARIABLE_OFFSET: return "FC_VARIABLE_OFFSET";
152     case RPC_FC_PP: return "FC_PP";
153     case RPC_FC_EMBEDDED_COMPLEX: return "FC_EMBEDDED_COMPLEX";
154     case RPC_FC_DEREFERENCE: return "FC_DEREFERENCE";
155     case RPC_FC_DIV_2: return "FC_DIV_2";
156     case RPC_FC_MULT_2: return "FC_MULT_2";
157     case RPC_FC_ADD_1: return "FC_ADD_1";
158     case RPC_FC_SUB_1: return "FC_SUB_1";
159     case RPC_FC_CALLBACK: return "FC_CALLBACK";
160     case RPC_FC_CONSTANT_IID: return "FC_CONSTANT_IID";
161     case RPC_FC_END: return "FC_END";
162     case RPC_FC_PAD: return "FC_PAD";
163     case RPC_FC_USER_MARSHAL: return "FC_USER_MARSHAL";
164     case RPC_FC_RANGE: return "FC_RANGE";
165     case RPC_FC_INT3264: return "FC_INT3264";
166     case RPC_FC_UINT3264: return "FC_UINT3264";
167     default:
168         error("string_of_type: unknown type 0x%02x\n", type);
169         return NULL;
170     }
171 }
172
173 static void *get_aliaschain_attrp(const type_t *type, enum attr_type attr)
174 {
175     const type_t *t = type;
176     for (;;)
177     {
178         if (is_attr(t->attrs, attr))
179             return get_attrp(t->attrs, attr);
180         else if (type_is_alias(t))
181             t = type_alias_get_aliasee(t);
182         else return NULL;
183     }
184 }
185
186 unsigned char get_basic_fc(const type_t *type)
187 {
188     int sign = type_basic_get_sign(type);
189     switch (type_basic_get_type(type))
190     {
191     case TYPE_BASIC_INT8: return (sign <= 0 ? RPC_FC_SMALL : RPC_FC_USMALL);
192     case TYPE_BASIC_INT16: return (sign <= 0 ? RPC_FC_SHORT : RPC_FC_USHORT);
193     case TYPE_BASIC_INT32: return (sign <= 0 ? RPC_FC_LONG : RPC_FC_ULONG);
194     case TYPE_BASIC_INT64: return RPC_FC_HYPER;
195     case TYPE_BASIC_INT: return (sign <= 0 ? RPC_FC_LONG : RPC_FC_ULONG);
196     case TYPE_BASIC_INT3264: return (sign <= 0 ? RPC_FC_INT3264 : RPC_FC_UINT3264);
197     case TYPE_BASIC_BYTE: return RPC_FC_BYTE;
198     case TYPE_BASIC_CHAR: return RPC_FC_CHAR;
199     case TYPE_BASIC_WCHAR: return RPC_FC_WCHAR;
200     case TYPE_BASIC_HYPER: return RPC_FC_HYPER;
201     case TYPE_BASIC_FLOAT: return RPC_FC_FLOAT;
202     case TYPE_BASIC_DOUBLE: return RPC_FC_DOUBLE;
203     case TYPE_BASIC_ERROR_STATUS_T: return RPC_FC_ERROR_STATUS_T;
204     case TYPE_BASIC_HANDLE: return RPC_FC_BIND_PRIMITIVE;
205     }
206     return 0;
207 }
208
209 static inline unsigned int clamp_align(unsigned int align)
210 {
211     unsigned int packing = (pointer_size == 4) ? win32_packing : win64_packing;
212     if(align > packing) align = packing;
213     return align;
214 }
215
216 unsigned char get_pointer_fc(const type_t *type, const attr_list_t *attrs, int toplevel_param)
217 {
218     const type_t *t;
219     int pointer_type;
220
221     assert(is_ptr(type) || is_array(type));
222
223     pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
224     if (pointer_type)
225         return pointer_type;
226
227     for (t = type; type_is_alias(t); t = type_alias_get_aliasee(t))
228     {
229         pointer_type = get_attrv(t->attrs, ATTR_POINTERTYPE);
230         if (pointer_type)
231             return pointer_type;
232     }
233
234     if (toplevel_param)
235         return RPC_FC_RP;
236     else if (is_ptr(type))
237         return type_pointer_get_default_fc(type);
238     else
239         return type_array_get_ptr_default_fc(type);
240 }
241
242 static unsigned char get_enum_fc(const type_t *type)
243 {
244     assert(type_get_type(type) == TYPE_ENUM);
245     if (is_aliaschain_attr(type, ATTR_V1ENUM))
246         return RPC_FC_ENUM32;
247     else
248         return RPC_FC_ENUM16;
249 }
250
251 static type_t *get_user_type(const type_t *t, const char **pname)
252 {
253     for (;;)
254     {
255         type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
256         if (ut)
257         {
258             if (pname)
259                 *pname = t->name;
260             return ut;
261         }
262
263         if (type_is_alias(t))
264             t = type_alias_get_aliasee(t);
265         else
266             return NULL;
267     }
268 }
269
270 static int is_user_type(const type_t *t)
271 {
272     return get_user_type(t, NULL) != NULL;
273 }
274
275 enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *attrs, unsigned int flags)
276 {
277     if (is_user_type(type))
278         return TGT_USER_TYPE;
279
280     if (is_aliaschain_attr(type, ATTR_CONTEXTHANDLE))
281         return TGT_CTXT_HANDLE;
282
283     if (!(flags & TDT_IGNORE_STRINGS) && is_string_type(attrs, type))
284         return TGT_STRING;
285
286     switch (type_get_type(type))
287     {
288     case TYPE_BASIC:
289         if (!(flags & TDT_IGNORE_RANGES) &&
290             (is_attr(attrs, ATTR_RANGE) || is_aliaschain_attr(type, ATTR_RANGE)))
291             return TGT_RANGE;
292         return TGT_BASIC;
293     case TYPE_ENUM:
294         if (!(flags & TDT_IGNORE_RANGES) &&
295             (is_attr(attrs, ATTR_RANGE) || is_aliaschain_attr(type, ATTR_RANGE)))
296             return TGT_RANGE;
297         return TGT_ENUM;
298     case TYPE_POINTER:
299         if (type_get_type(type_pointer_get_ref(type)) == TYPE_INTERFACE ||
300             (type_get_type(type_pointer_get_ref(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS)))
301             return TGT_IFACE_POINTER;
302         else if (is_aliaschain_attr(type_pointer_get_ref(type), ATTR_CONTEXTHANDLE))
303             return TGT_CTXT_HANDLE_POINTER;
304         else
305             return TGT_POINTER;
306     case TYPE_STRUCT:
307         return TGT_STRUCT;
308     case TYPE_ENCAPSULATED_UNION:
309     case TYPE_UNION:
310         return TGT_UNION;
311     case TYPE_ARRAY:
312         return TGT_ARRAY;
313     case TYPE_FUNCTION:
314     case TYPE_COCLASS:
315     case TYPE_INTERFACE:
316     case TYPE_MODULE:
317     case TYPE_VOID:
318     case TYPE_ALIAS:
319     case TYPE_BITFIELD:
320         break;
321     }
322     return TGT_INVALID;
323 }
324
325 static int get_padding(const var_list_t *fields)
326 {
327     unsigned short offset = 0;
328     unsigned int salign = 1;
329     const var_t *f;
330
331     if (!fields)
332         return 0;
333
334     LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
335     {
336         type_t *ft = f->type;
337         unsigned int align = 0;
338         unsigned int size = type_memsize_and_alignment(ft, &align);
339         align = clamp_align(align);
340         if (align > salign) salign = align;
341         offset = ROUND_SIZE(offset, align);
342         offset += size;
343     }
344
345     return ROUNDING(offset, salign);
346 }
347
348 static unsigned int get_stack_size( const type_t *type, const attr_list_t *attrs, int *by_value )
349 {
350     unsigned int stack_size;
351     int by_val;
352
353     switch (typegen_detect_type( type, attrs, TDT_ALL_TYPES ))
354     {
355     case TGT_BASIC:
356     case TGT_ENUM:
357     case TGT_RANGE:
358     case TGT_STRUCT:
359     case TGT_UNION:
360     case TGT_USER_TYPE:
361         stack_size = type_memsize( type );
362         by_val = (pointer_size < 8 || stack_size <= pointer_size); /* FIXME: should be platform-specific */
363         break;
364     default:
365         by_val = 0;
366         break;
367     }
368     if (!by_val) stack_size = pointer_size;
369     if (by_value) *by_value = by_val;
370     return ROUND_SIZE( stack_size, pointer_size );
371 }
372
373 static unsigned char get_contexthandle_flags( const type_t *iface, const attr_list_t *attrs,
374                                               const type_t *type )
375 {
376     unsigned char flags = 0;
377
378     if (is_attr(iface->attrs, ATTR_STRICTCONTEXTHANDLE)) flags |= NDR_STRICT_CONTEXT_HANDLE;
379
380     if (is_ptr(type) &&
381         !is_attr( type->attrs, ATTR_CONTEXTHANDLE ) &&
382         !is_attr( attrs, ATTR_CONTEXTHANDLE ))
383         flags |= 0x80;
384
385     if (is_attr(attrs, ATTR_IN))
386     {
387         flags |= 0x40;
388         if (!is_attr(attrs, ATTR_OUT)) flags |= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL;
389     }
390     if (is_attr(attrs, ATTR_OUT)) flags |= 0x20;
391
392     return flags;
393 }
394
395 unsigned char get_struct_fc(const type_t *type)
396 {
397   int has_pointer = 0;
398   int has_conformance = 0;
399   int has_variance = 0;
400   var_t *field;
401   var_list_t *fields;
402
403   fields = type_struct_get_fields(type);
404
405   if (get_padding(fields))
406     return RPC_FC_BOGUS_STRUCT;
407
408   if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry )
409   {
410     type_t *t = field->type;
411     enum typegen_type typegen_type;
412
413     typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS);
414
415     if (typegen_type == TGT_ARRAY && !type_array_is_decl_as_ptr(t))
416     {
417         if (is_string_type(field->attrs, field->type))
418         {
419             if (is_conformant_array(t))
420                 has_conformance = 1;
421             has_variance = 1;
422             continue;
423         }
424
425         if (is_array(type_array_get_element(field->type)))
426             return RPC_FC_BOGUS_STRUCT;
427
428         if (type_array_has_conformance(field->type))
429         {
430             has_conformance = 1;
431             if (list_next(fields, &field->entry))
432                 error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n",
433                         field->name);
434         }
435         if (type_array_has_variance(t))
436             has_variance = 1;
437
438         t = type_array_get_element(t);
439         typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS);
440     }
441
442     switch (typegen_type)
443     {
444     case TGT_USER_TYPE:
445     case TGT_IFACE_POINTER:
446         return RPC_FC_BOGUS_STRUCT;
447     case TGT_BASIC:
448         if (type_basic_get_type(t) == TYPE_BASIC_INT3264 && pointer_size != 4)
449             return RPC_FC_BOGUS_STRUCT;
450         break;
451     case TGT_ENUM:
452         if (get_enum_fc(t) == RPC_FC_ENUM16)
453             return RPC_FC_BOGUS_STRUCT;
454         break;
455     case TGT_POINTER:
456     case TGT_ARRAY:
457         if (get_pointer_fc(t, field->attrs, FALSE) == RPC_FC_RP || pointer_size != 4)
458             return RPC_FC_BOGUS_STRUCT;
459         has_pointer = 1;
460         break;
461     case TGT_UNION:
462         return RPC_FC_BOGUS_STRUCT;
463     case TGT_STRUCT:
464     {
465         unsigned char fc = get_struct_fc(t);
466         switch (fc)
467         {
468         case RPC_FC_STRUCT:
469             break;
470         case RPC_FC_CVSTRUCT:
471             has_conformance = 1;
472             has_variance = 1;
473             has_pointer = 1;
474             break;
475
476         case RPC_FC_CPSTRUCT:
477             has_conformance = 1;
478             if (list_next( fields, &field->entry ))
479                 error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n",
480                         field->name);
481             has_pointer = 1;
482             break;
483
484         case RPC_FC_CSTRUCT:
485             has_conformance = 1;
486             if (list_next( fields, &field->entry ))
487                 error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n",
488                       field->name);
489             break;
490
491         case RPC_FC_PSTRUCT:
492             has_pointer = 1;
493             break;
494
495         default:
496             error_loc("Unknown struct member %s with type (0x%02x)\n", field->name, fc);
497             /* fallthru - treat it as complex */
498
499         /* as soon as we see one of these these members, it's bogus... */
500         case RPC_FC_BOGUS_STRUCT:
501             return RPC_FC_BOGUS_STRUCT;
502         }
503         break;
504     }
505     case TGT_RANGE:
506         return RPC_FC_BOGUS_STRUCT;
507     case TGT_STRING:
508         /* shouldn't get here because of TDT_IGNORE_STRINGS above. fall through */
509     case TGT_INVALID:
510     case TGT_CTXT_HANDLE:
511     case TGT_CTXT_HANDLE_POINTER:
512         /* checking after parsing should mean that we don't get here. if we do,
513          * it's a checker bug */
514         assert(0);
515     }
516   }
517
518   if( has_variance )
519   {
520     if ( has_conformance )
521       return RPC_FC_CVSTRUCT;
522     else
523       return RPC_FC_BOGUS_STRUCT;
524   }
525   if( has_conformance && has_pointer )
526     return RPC_FC_CPSTRUCT;
527   if( has_conformance )
528     return RPC_FC_CSTRUCT;
529   if( has_pointer )
530     return RPC_FC_PSTRUCT;
531   return RPC_FC_STRUCT;
532 }
533
534 static unsigned char get_array_fc(const type_t *type)
535 {
536     unsigned char fc;
537     const expr_t *size_is;
538     const type_t *elem_type;
539
540     elem_type = type_array_get_element(type);
541     size_is = type_array_get_conformance(type);
542
543     if (!size_is)
544     {
545         unsigned int size = type_memsize(elem_type);
546         if (size * type_array_get_dim(type) > 0xffffuL)
547             fc = RPC_FC_LGFARRAY;
548         else
549             fc = RPC_FC_SMFARRAY;
550     }
551     else
552         fc = RPC_FC_CARRAY;
553
554     if (type_array_has_variance(type))
555     {
556         if (fc == RPC_FC_SMFARRAY)
557             fc = RPC_FC_SMVARRAY;
558         else if (fc == RPC_FC_LGFARRAY)
559             fc = RPC_FC_LGVARRAY;
560         else if (fc == RPC_FC_CARRAY)
561             fc = RPC_FC_CVARRAY;
562     }
563
564     switch (typegen_detect_type(elem_type, NULL, TDT_IGNORE_STRINGS))
565     {
566     case TGT_USER_TYPE:
567         fc = RPC_FC_BOGUS_ARRAY;
568         break;
569     case TGT_BASIC:
570         if (type_basic_get_type(elem_type) == TYPE_BASIC_INT3264 &&
571             pointer_size != 4)
572             fc = RPC_FC_BOGUS_ARRAY;
573         break;
574     case TGT_STRUCT:
575         switch (get_struct_fc(elem_type))
576         {
577         case RPC_FC_BOGUS_STRUCT:
578             fc = RPC_FC_BOGUS_ARRAY;
579             break;
580         }
581         break;
582     case TGT_ENUM:
583         /* is 16-bit enum - if so, wire size differs from mem size and so
584          * the array cannot be block copied, which means the array is complex */
585         if (get_enum_fc(elem_type) == RPC_FC_ENUM16)
586             fc = RPC_FC_BOGUS_ARRAY;
587         break;
588     case TGT_UNION:
589     case TGT_IFACE_POINTER:
590         fc = RPC_FC_BOGUS_ARRAY;
591         break;
592     case TGT_POINTER:
593         /* ref pointers cannot just be block copied. unique pointers to
594          * interfaces need special treatment. either case means the array is
595          * complex */
596         if (get_pointer_fc(elem_type, NULL, FALSE) == RPC_FC_RP || pointer_size != 4)
597             fc = RPC_FC_BOGUS_ARRAY;
598         break;
599     case TGT_RANGE:
600         fc = RPC_FC_BOGUS_ARRAY;
601         break;
602     case TGT_CTXT_HANDLE:
603     case TGT_CTXT_HANDLE_POINTER:
604     case TGT_STRING:
605     case TGT_INVALID:
606     case TGT_ARRAY:
607         /* nothing to do for everything else */
608         break;
609     }
610
611     return fc;
612 }
613
614 static int is_non_complex_struct(const type_t *type)
615 {
616     return (type_get_type(type) == TYPE_STRUCT &&
617             get_struct_fc(type) != RPC_FC_BOGUS_STRUCT);
618 }
619
620 static int type_has_pointers(const type_t *type)
621 {
622     switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS))
623     {
624     case TGT_USER_TYPE:
625         return FALSE;
626     case TGT_POINTER:
627         return TRUE;
628     case TGT_ARRAY:
629         return type_array_is_decl_as_ptr(type) || type_has_pointers(type_array_get_element(type));
630     case TGT_STRUCT:
631     {
632         var_list_t *fields = type_struct_get_fields(type);
633         const var_t *field;
634         if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
635         {
636             if (type_has_pointers(field->type))
637                 return TRUE;
638         }
639         break;
640     }
641     case TGT_UNION:
642     {
643         var_list_t *fields;
644         const var_t *field;
645         fields = type_union_get_cases(type);
646         if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
647         {
648             if (field->type && type_has_pointers(field->type))
649                 return TRUE;
650         }
651         break;
652     }
653     case TGT_CTXT_HANDLE:
654     case TGT_CTXT_HANDLE_POINTER:
655     case TGT_STRING:
656     case TGT_IFACE_POINTER:
657     case TGT_BASIC:
658     case TGT_ENUM:
659     case TGT_RANGE:
660     case TGT_INVALID:
661         break;
662     }
663
664     return FALSE;
665 }
666
667 static int type_has_full_pointer(const type_t *type, const attr_list_t *attrs,
668                                  int toplevel_param)
669 {
670     switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS))
671     {
672     case TGT_USER_TYPE:
673         return FALSE;
674     case TGT_POINTER:
675         if (get_pointer_fc(type, attrs, toplevel_param) == RPC_FC_FP)
676             return TRUE;
677         else
678             return FALSE;
679     case TGT_ARRAY:
680         if (get_pointer_fc(type, attrs, toplevel_param) == RPC_FC_FP)
681             return TRUE;
682         else
683             return type_has_full_pointer(type_array_get_element(type), NULL, FALSE);
684     case TGT_STRUCT:
685     {
686         var_list_t *fields = type_struct_get_fields(type);
687         const var_t *field;
688         if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
689         {
690             if (type_has_full_pointer(field->type, field->attrs, FALSE))
691                 return TRUE;
692         }
693         break;
694     }
695     case TGT_UNION:
696     {
697         var_list_t *fields;
698         const var_t *field;
699         fields = type_union_get_cases(type);
700         if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
701         {
702             if (field->type && type_has_full_pointer(field->type, field->attrs, FALSE))
703                 return TRUE;
704         }
705         break;
706     }
707     case TGT_CTXT_HANDLE:
708     case TGT_CTXT_HANDLE_POINTER:
709     case TGT_STRING:
710     case TGT_IFACE_POINTER:
711     case TGT_BASIC:
712     case TGT_ENUM:
713     case TGT_RANGE:
714     case TGT_INVALID:
715         break;
716     }
717
718     return FALSE;
719 }
720
721 static unsigned short user_type_offset(const char *name)
722 {
723     user_type_t *ut;
724     unsigned short off = 0;
725     LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
726     {
727         if (strcmp(name, ut->name) == 0)
728             return off;
729         ++off;
730     }
731     error("user_type_offset: couldn't find type (%s)\n", name);
732     return 0;
733 }
734
735 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
736 {
737     type->typestring_offset = offset;
738     if (file) type->tfswrite = FALSE;
739 }
740
741 static void guard_rec(type_t *type)
742 {
743     /* types that contain references to themselves (like a linked list),
744        need to be shielded from infinite recursion when writing embedded
745        types  */
746     if (type->typestring_offset)
747         type->tfswrite = FALSE;
748     else
749         type->typestring_offset = 1;
750 }
751
752 static int is_embedded_complex(const type_t *type)
753 {
754     switch (typegen_detect_type(type, NULL, TDT_ALL_TYPES))
755     {
756     case TGT_USER_TYPE:
757     case TGT_STRUCT:
758     case TGT_UNION:
759     case TGT_ARRAY:
760     case TGT_IFACE_POINTER:
761         return TRUE;
762     default:
763         return FALSE;
764     }
765 }
766
767 static const char *get_context_handle_type_name(const type_t *type)
768 {
769     const type_t *t;
770     for (t = type;
771          is_ptr(t) || type_is_alias(t);
772          t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t))
773         if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
774             return t->name;
775     assert(0);
776     return NULL;
777 }
778
779 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
780     do { \
781         if (file) \
782             fprintf(file, "/* %2u */\n", typestring_offset); \
783         print_file((file), 2, "0x%02x,    /* " #fctype " */\n", RPC_##fctype); \
784     } \
785     while (0)
786
787 static void print_file(FILE *file, int indent, const char *format, ...) __attribute__((format (printf, 3, 4)));
788 static void print_file(FILE *file, int indent, const char *format, ...)
789 {
790     va_list va;
791     va_start(va, format);
792     print(file, indent, format, va);
793     va_end(va);
794 }
795
796 void print(FILE *file, int indent, const char *format, va_list va)
797 {
798     if (file)
799     {
800         if (format[0] != '\n')
801             while (0 < indent--)
802                 fprintf(file, "    ");
803         vfprintf(file, format, va);
804     }
805 }
806
807
808 static void write_var_init(FILE *file, int indent, const type_t *t, const char *n, const char *local_var_prefix)
809 {
810     if (decl_indirect(t))
811     {
812         print_file(file, indent, "MIDL_memset(&%s%s, 0, sizeof(%s%s));\n",
813                    local_var_prefix, n, local_var_prefix, n);
814         print_file(file, indent, "%s_p_%s = &%s%s;\n", local_var_prefix, n, local_var_prefix, n);
815     }
816     else if (is_ptr(t) || is_array(t))
817         print_file(file, indent, "%s%s = 0;\n", local_var_prefix, n);
818 }
819
820 void write_parameters_init(FILE *file, int indent, const var_t *func, const char *local_var_prefix)
821 {
822     const var_t *var;
823
824     if (!is_void(type_function_get_rettype(func->type)))
825         write_var_init(file, indent, type_function_get_rettype(func->type), "_RetVal", local_var_prefix);
826
827     if (!type_get_function_args(func->type))
828         return;
829
830     LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
831         write_var_init(file, indent, var->type, var->name, local_var_prefix);
832
833     fprintf(file, "\n");
834 }
835
836 static void write_formatdesc(FILE *f, int indent, const char *str)
837 {
838     print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
839     print_file(f, indent, "{\n");
840     print_file(f, indent + 1, "short Pad;\n");
841     print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
842     print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
843     print_file(f, indent, "\n");
844 }
845
846 void write_formatstringsdecl(FILE *f, int indent, const statement_list_t *stmts, type_pred_t pred)
847 {
848     clear_all_offsets();
849
850     print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
851                get_size_typeformatstring(stmts, pred));
852
853     print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
854                get_size_procformatstring(stmts, pred));
855
856     fprintf(f, "\n");
857     write_formatdesc(f, indent, "TYPE");
858     write_formatdesc(f, indent, "PROC");
859     fprintf(f, "\n");
860     print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
861     print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
862     print_file(f, indent, "\n");
863 }
864
865 int decl_indirect(const type_t *t)
866 {
867     if (is_user_type(t))
868         return TRUE;
869     return (type_get_type(t) != TYPE_BASIC &&
870             type_get_type(t) != TYPE_ENUM &&
871             type_get_type(t) != TYPE_POINTER &&
872             type_get_type(t) != TYPE_ARRAY);
873 }
874
875 static unsigned int write_procformatstring_type(FILE *file, int indent,
876                                                 const type_t *type,
877                                                 const attr_list_t *attrs,
878                                                 int is_return)
879 {
880     unsigned int size;
881
882     int is_in = is_attr(attrs, ATTR_IN);
883     int is_out = is_attr(attrs, ATTR_OUT);
884
885     if (!is_in && !is_out) is_in = TRUE;
886
887     if (type_get_type(type) == TYPE_BASIC ||
888         type_get_type(type) == TYPE_ENUM)
889     {
890         unsigned char fc;
891
892         if (is_return)
893             print_file(file, indent, "0x53,    /* FC_RETURN_PARAM_BASETYPE */\n");
894         else
895             print_file(file, indent, "0x4e,    /* FC_IN_PARAM_BASETYPE */\n");
896
897         if (type_get_type(type) == TYPE_ENUM)
898         {
899             fc = get_enum_fc(type);
900         }
901         else
902         {
903             fc = get_basic_fc(type);
904
905             if (fc == RPC_FC_BIND_PRIMITIVE)
906                 fc = RPC_FC_IGNORE;
907         }
908
909         print_file(file, indent, "0x%02x,    /* %s */\n",
910                    fc, string_of_type(fc));
911         size = 2; /* includes param type prefix */
912     }
913     else
914     {
915         if (is_return)
916             print_file(file, indent, "0x52,    /* FC_RETURN_PARAM */\n");
917         else if (is_in && is_out)
918             print_file(file, indent, "0x50,    /* FC_IN_OUT_PARAM */\n");
919         else if (is_out)
920             print_file(file, indent, "0x51,    /* FC_OUT_PARAM */\n");
921         else
922             print_file(file, indent, "0x4d,    /* FC_IN_PARAM */\n");
923
924         size = get_stack_size( type, attrs, NULL );
925         print_file(file, indent, "0x%02x,\n", size / pointer_size );
926         print_file(file, indent, "NdrFcShort(0x%x),     /* type offset = %u */\n",
927                    type->typestring_offset, type->typestring_offset);
928         size = 4; /* includes param type prefix */
929     }
930     return size;
931 }
932
933 int is_interpreted_func( const type_t *iface, const var_t *func )
934 {
935     const char *str;
936     const var_t *var;
937     const var_list_t *args = type_get_function_args( func->type );
938     const type_t *ret_type = type_function_get_rettype( func->type );
939
940     if (type_get_type( ret_type ) == TYPE_BASIC)
941     {
942         switch (type_basic_get_type( ret_type ))
943         {
944         case TYPE_BASIC_INT64:
945         case TYPE_BASIC_HYPER:
946             /* return value must fit in a long_ptr */
947             if (pointer_size < 8) return 0;
948             break;
949         case TYPE_BASIC_FLOAT:
950         case TYPE_BASIC_DOUBLE:
951             /* floating point values can't be returned */
952             return 0;
953         default:
954             break;
955         }
956     }
957     /* unions passed by value are not supported */
958     if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
959                   if (type_get_type( var->type ) == TYPE_UNION ||
960                       type_get_type( var->type ) == TYPE_ENCAPSULATED_UNION)
961                       return 0;
962
963     if ((str = get_attrp( func->attrs, ATTR_OPTIMIZE ))) return !strcmp( str, "i" );
964     if ((str = get_attrp( iface->attrs, ATTR_OPTIMIZE ))) return !strcmp( str, "i" );
965     return (stub_mode != MODE_Os);
966 }
967
968 static void write_procformatstring_func( FILE *file, int indent,
969                                          const var_t *func, unsigned int *offset )
970 {
971     /* emit argument data */
972     if (type_get_function_args(func->type))
973     {
974         const var_t *var;
975         LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
976         {
977             print_file( file, 0, "/* %u (parameter %s) */\n", *offset, var->name );
978             *offset += write_procformatstring_type(file, indent, var->type, var->attrs, FALSE);
979         }
980     }
981
982     /* emit return value data */
983     if (is_void(type_function_get_rettype(func->type)))
984     {
985         print_file(file, 0, "/* %u (void) */\n", *offset);
986         print_file(file, indent, "0x5b,    /* FC_END */\n");
987         print_file(file, indent, "0x5c,    /* FC_PAD */\n");
988         *offset += 2;
989     }
990     else
991     {
992         print_file( file, 0, "/* %u (return value) */\n", *offset );
993         *offset += write_procformatstring_type(file, indent, type_function_get_rettype(func->type), NULL, TRUE);
994     }
995 }
996
997 static void write_procformatstring_stmts(FILE *file, int indent, const statement_list_t *stmts,
998                                          type_pred_t pred, unsigned int *offset)
999 {
1000     const statement_t *stmt;
1001     if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
1002     {
1003         if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE)
1004         {
1005             const statement_t *stmt_func;
1006             if (!pred(stmt->u.type))
1007                 continue;
1008             STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(stmt->u.type))
1009             {
1010                 const var_t *func = stmt_func->u.var;
1011                 if (is_local(func->attrs)) continue;
1012                 write_procformatstring_func( file, indent, func, offset );
1013             }
1014         }
1015         else if (stmt->type == STMT_LIBRARY)
1016             write_procformatstring_stmts(file, indent, stmt->u.lib->stmts, pred, offset);
1017     }
1018 }
1019
1020 void write_procformatstring(FILE *file, const statement_list_t *stmts, type_pred_t pred)
1021 {
1022     int indent = 0;
1023     unsigned int offset = 0;
1024
1025     print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
1026     print_file(file, indent, "{\n");
1027     indent++;
1028     print_file(file, indent, "0,\n");
1029     print_file(file, indent, "{\n");
1030     indent++;
1031
1032     write_procformatstring_stmts(file, indent, stmts, pred, &offset);
1033
1034     print_file(file, indent, "0x0\n");
1035     indent--;
1036     print_file(file, indent, "}\n");
1037     indent--;
1038     print_file(file, indent, "};\n");
1039     print_file(file, indent, "\n");
1040 }
1041
1042 void write_procformatstring_offsets( FILE *file, const type_t *iface )
1043 {
1044     const statement_t *stmt;
1045     int indent = 0;
1046
1047     print_file( file, indent,  "static const unsigned short %s_FormatStringOffsetTable[] =\n",
1048                 iface->name );
1049     print_file( file, indent,  "{\n" );
1050     indent++;
1051     STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
1052     {
1053         var_t *func = stmt->u.var;
1054         if (is_local( func->attrs )) continue;
1055         print_file( file, indent,  "%u,  /* %s */\n", func->procstring_offset, func->name );
1056     }
1057     indent--;
1058     print_file( file, indent,  "};\n\n" );
1059 }
1060
1061 static int write_base_type(FILE *file, const type_t *type, int convert_to_signed_type, unsigned int *typestring_offset)
1062 {
1063     unsigned char fc;
1064
1065     if (type_get_type(type) == TYPE_BASIC)
1066         fc = get_basic_fc(type);
1067     else if (type_get_type(type) == TYPE_ENUM)
1068         fc = get_enum_fc(type);
1069     else
1070         return 0;
1071
1072     if (convert_to_signed_type)
1073     {
1074         switch(fc)
1075         {
1076         case RPC_FC_USMALL:
1077             fc = RPC_FC_SMALL;
1078             break;
1079         case RPC_FC_USHORT:
1080             fc = RPC_FC_SHORT;
1081             break;
1082         case RPC_FC_ULONG:
1083             fc = RPC_FC_LONG;
1084             break;
1085         }
1086     }
1087
1088     print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
1089     *typestring_offset += 1;
1090     return 1;
1091 }
1092
1093 /* write conformance / variance descriptor */
1094 static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type,
1095                                            unsigned int baseoff, const type_t *type,
1096                                            const expr_t *expr)
1097 {
1098     unsigned char operator_type = 0;
1099     unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE;
1100     const char *conftype_string = "field";
1101     const expr_t *subexpr;
1102     const type_t *iface = NULL;
1103     const char *name;
1104
1105     if (!expr)
1106     {
1107         print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
1108         return 4;
1109     }
1110
1111     if (expr->is_const)
1112     {
1113         if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
1114             error("write_conf_or_var_desc: constant value %d is greater than "
1115                   "the maximum constant size of %d\n", expr->cval,
1116                   UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
1117
1118         print_file(file, 2, "0x%x, /* Corr desc: constant, val = %d */\n",
1119                    RPC_FC_CONSTANT_CONFORMANCE, expr->cval);
1120         print_file(file, 2, "0x%x,\n", expr->cval >> 16);
1121         print_file(file, 2, "NdrFcShort(0x%hx),\n", (unsigned short)expr->cval);
1122
1123         return 4;
1124     }
1125
1126     if (!cont_type)  /* top-level conformance */
1127     {
1128         conftype = RPC_FC_TOP_LEVEL_CONFORMANCE;
1129         conftype_string = "parameter";
1130         cont_type = current_func->type;
1131         name = current_func->name;
1132         iface = current_iface;
1133     }
1134     else
1135     {
1136         name = cont_type->name;
1137         if (is_ptr(type) || (is_array(type) && type_array_is_decl_as_ptr(type)))
1138         {
1139             conftype = RPC_FC_POINTER_CONFORMANCE;
1140             conftype_string = "field pointer";
1141         }
1142     }
1143
1144     subexpr = expr;
1145     switch (subexpr->type)
1146     {
1147     case EXPR_PPTR:
1148         subexpr = subexpr->ref;
1149         operator_type = RPC_FC_DEREFERENCE;
1150         break;
1151     case EXPR_DIV:
1152         if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
1153         {
1154             subexpr = subexpr->ref;
1155             operator_type = RPC_FC_DIV_2;
1156         }
1157         break;
1158     case EXPR_MUL:
1159         if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
1160         {
1161             subexpr = subexpr->ref;
1162             operator_type = RPC_FC_MULT_2;
1163         }
1164         break;
1165     case EXPR_SUB:
1166         if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
1167         {
1168             subexpr = subexpr->ref;
1169             operator_type = RPC_FC_SUB_1;
1170         }
1171         break;
1172     case EXPR_ADD:
1173         if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
1174         {
1175             subexpr = subexpr->ref;
1176             operator_type = RPC_FC_ADD_1;
1177         }
1178         break;
1179     default:
1180         break;
1181     }
1182
1183     if (subexpr->type == EXPR_IDENTIFIER)
1184     {
1185         const type_t *correlation_variable = NULL;
1186         unsigned char param_type = 0;
1187         unsigned int offset = 0;
1188         const var_t *var;
1189         struct expr_loc expr_loc;
1190
1191         if (type_get_type(cont_type) == TYPE_FUNCTION)
1192         {
1193             var_list_t *args = type_get_function_args( cont_type );
1194
1195             if (is_object( iface )) offset += pointer_size;
1196             if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
1197             {
1198                 if (var->name && !strcmp(var->name, subexpr->u.sval))
1199                 {
1200                     expr_loc.v = var;
1201                     correlation_variable = var->type;
1202                     break;
1203                 }
1204                 offset += get_stack_size( var->type, var->attrs, NULL );
1205             }
1206         }
1207         else
1208         {
1209             var_list_t *fields = type_struct_get_fields( cont_type );
1210
1211             if (fields) LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
1212             {
1213                 unsigned int size = field_memsize( var->type, &offset );
1214                 if (var->name && !strcmp(var->name, subexpr->u.sval))
1215                 {
1216                     expr_loc.v = var;
1217                     correlation_variable = var->type;
1218                     break;
1219                 }
1220                 offset += size;
1221             }
1222         }
1223
1224         if (!correlation_variable)
1225             error("write_conf_or_var_desc: couldn't find variable %s in %s\n", subexpr->u.sval, name);
1226         expr_loc.attr = NULL;
1227         correlation_variable = expr_resolve_type(&expr_loc, cont_type, expr);
1228
1229         offset -= baseoff;
1230
1231         if (type_get_type(correlation_variable) == TYPE_BASIC)
1232         {
1233             switch (get_basic_fc(correlation_variable))
1234             {
1235             case RPC_FC_CHAR:
1236             case RPC_FC_SMALL:
1237                 param_type = RPC_FC_SMALL;
1238                 break;
1239             case RPC_FC_BYTE:
1240             case RPC_FC_USMALL:
1241                 param_type = RPC_FC_USMALL;
1242                 break;
1243             case RPC_FC_WCHAR:
1244             case RPC_FC_SHORT:
1245                 param_type = RPC_FC_SHORT;
1246                 break;
1247             case RPC_FC_USHORT:
1248                 param_type = RPC_FC_USHORT;
1249                 break;
1250             case RPC_FC_LONG:
1251                 param_type = RPC_FC_LONG;
1252                 break;
1253             case RPC_FC_ULONG:
1254                 param_type = RPC_FC_ULONG;
1255                 break;
1256             default:
1257                 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
1258                       get_basic_fc(correlation_variable));
1259             }
1260         }
1261         else if (type_get_type(correlation_variable) == TYPE_ENUM)
1262         {
1263             if (get_enum_fc(correlation_variable) == RPC_FC_ENUM32)
1264                 param_type = RPC_FC_LONG;
1265             else
1266                 param_type = RPC_FC_SHORT;
1267         }
1268         else if (type_get_type(correlation_variable) == TYPE_POINTER)
1269         {
1270             if (pointer_size == 8)
1271                 param_type = RPC_FC_HYPER;
1272             else
1273                 param_type = RPC_FC_LONG;
1274         }
1275         else
1276         {
1277             error("write_conf_or_var_desc: non-arithmetic type used as correlation variable %s\n",
1278                   subexpr->u.sval);
1279             return 0;
1280         }
1281
1282         print_file(file, 2, "0x%x,\t/* Corr desc: %s %s, %s */\n",
1283                    conftype | param_type, conftype_string, subexpr->u.sval, string_of_type(param_type));
1284         print_file(file, 2, "0x%x,\t/* %s */\n", operator_type,
1285                    operator_type ? string_of_type(operator_type) : "no operators");
1286         print_file(file, 2, "NdrFcShort(0x%hx),\t/* offset = %d */\n",
1287                    (unsigned short)offset, offset);
1288     }
1289     else if (!iface || is_interpreted_func( iface, current_func ))
1290     {
1291         unsigned int callback_offset = 0;
1292         struct expr_eval_routine *eval;
1293         int found = 0;
1294
1295         LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
1296         {
1297             if (eval->cont_type == cont_type ||
1298                 (type_get_type( eval->cont_type ) == type_get_type( cont_type ) &&
1299                  eval->iface == iface &&
1300                  eval->name && name && !strcmp(eval->name, name) &&
1301                  !compare_expr(eval->expr, expr)))
1302             {
1303                 found = 1;
1304                 break;
1305             }
1306             callback_offset++;
1307         }
1308
1309         if (!found)
1310         {
1311             eval = xmalloc (sizeof(*eval));
1312             eval->iface = iface;
1313             eval->cont_type = cont_type;
1314             eval->name = xstrdup( name );
1315             eval->baseoff = baseoff;
1316             eval->expr = expr;
1317             list_add_tail (&expr_eval_routines, &eval->entry);
1318         }
1319
1320         if (callback_offset > USHRT_MAX)
1321             error("Maximum number of callback routines reached\n");
1322
1323         print_file(file, 2, "0x%x,\t/* Corr desc: %s in %s */\n", conftype, conftype_string, name);
1324         print_file(file, 2, "0x%x,\t/* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK");
1325         print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)callback_offset, callback_offset);
1326     }
1327     else  /* output a dummy corr desc that isn't used */
1328     {
1329         print_file(file, 2, "0x%x,\t/* Corr desc: unused for %s */\n", conftype, name);
1330         print_file(file, 2, "0x0,\n" );
1331         print_file(file, 2, "NdrFcShort(0x0),\n" );
1332     }
1333     return 4;
1334 }
1335
1336 /* return size and start offset of a data field based on current offset */
1337 static unsigned int field_memsize(const type_t *type, unsigned int *offset)
1338 {
1339     unsigned int align = 0;
1340     unsigned int size = type_memsize_and_alignment( type, &align );
1341
1342     *offset = ROUND_SIZE( *offset, align );
1343     return size;
1344 }
1345
1346 static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align)
1347 {
1348     unsigned int size = 0;
1349     unsigned int max_align;
1350     const var_t *v;
1351
1352     if (!fields) return 0;
1353     LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
1354     {
1355         unsigned int falign = 0;
1356         unsigned int fsize = type_memsize_and_alignment(v->type, &falign);
1357         if (*align < falign) *align = falign;
1358         falign = clamp_align(falign);
1359         size = ROUND_SIZE(size, falign);
1360         size += fsize;
1361     }
1362
1363     max_align = clamp_align(*align);
1364     size = ROUND_SIZE(size, max_align);
1365
1366     return size;
1367 }
1368
1369 static unsigned int union_memsize(const var_list_t *fields, unsigned int *pmaxa)
1370 {
1371     unsigned int size, maxs = 0;
1372     unsigned int align = *pmaxa;
1373     const var_t *v;
1374
1375     if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
1376     {
1377         /* we could have an empty default field with NULL type */
1378         if (v->type)
1379         {
1380             size = type_memsize_and_alignment(v->type, &align);
1381             if (maxs < size) maxs = size;
1382             if (*pmaxa < align) *pmaxa = align;
1383         }
1384     }
1385
1386     return maxs;
1387 }
1388
1389 static unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align)
1390 {
1391     unsigned int size = 0;
1392
1393     switch (type_get_type(t))
1394     {
1395     case TYPE_BASIC:
1396         switch (get_basic_fc(t))
1397         {
1398         case RPC_FC_BYTE:
1399         case RPC_FC_CHAR:
1400         case RPC_FC_USMALL:
1401         case RPC_FC_SMALL:
1402             size = 1;
1403             if (size > *align) *align = size;
1404             break;
1405         case RPC_FC_WCHAR:
1406         case RPC_FC_USHORT:
1407         case RPC_FC_SHORT:
1408             size = 2;
1409             if (size > *align) *align = size;
1410             break;
1411         case RPC_FC_ULONG:
1412         case RPC_FC_LONG:
1413         case RPC_FC_ERROR_STATUS_T:
1414         case RPC_FC_FLOAT:
1415             size = 4;
1416             if (size > *align) *align = size;
1417             break;
1418         case RPC_FC_HYPER:
1419         case RPC_FC_DOUBLE:
1420             size = 8;
1421             if (size > *align) *align = size;
1422             break;
1423         case RPC_FC_INT3264:
1424         case RPC_FC_UINT3264:
1425         case RPC_FC_BIND_PRIMITIVE:
1426             assert( pointer_size );
1427             size = pointer_size;
1428             if (size > *align) *align = size;
1429             break;
1430         default:
1431             error("type_memsize: Unknown type 0x%x\n", get_basic_fc(t));
1432             size = 0;
1433         }
1434         break;
1435     case TYPE_ENUM:
1436         switch (get_enum_fc(t))
1437         {
1438         case RPC_FC_ENUM16:
1439         case RPC_FC_ENUM32:
1440             size = 4;
1441             if (size > *align) *align = size;
1442             break;
1443         default:
1444             error("type_memsize: Unknown enum type\n");
1445             size = 0;
1446         }
1447         break;
1448     case TYPE_STRUCT:
1449         size = fields_memsize(type_struct_get_fields(t), align);
1450         break;
1451     case TYPE_ENCAPSULATED_UNION:
1452         size = fields_memsize(type_encapsulated_union_get_fields(t), align);
1453         break;
1454     case TYPE_UNION:
1455         size = union_memsize(type_union_get_cases(t), align);
1456         break;
1457     case TYPE_POINTER:
1458         assert( pointer_size );
1459         size = pointer_size;
1460         if (size > *align) *align = size;
1461         break;
1462     case TYPE_ARRAY:
1463         if (!type_array_is_decl_as_ptr(t))
1464         {
1465             if (is_conformant_array(t))
1466             {
1467                 type_memsize_and_alignment(type_array_get_element(t), align);
1468                 size = 0;
1469             }
1470             else
1471                 size = type_array_get_dim(t) *
1472                     type_memsize_and_alignment(type_array_get_element(t), align);
1473         }
1474         else /* declared as a pointer */
1475         {
1476             assert( pointer_size );
1477             size = pointer_size;
1478             if (size > *align) *align = size;
1479         }
1480         break;
1481     case TYPE_INTERFACE:
1482     case TYPE_ALIAS:
1483     case TYPE_VOID:
1484     case TYPE_COCLASS:
1485     case TYPE_MODULE:
1486     case TYPE_FUNCTION:
1487     case TYPE_BITFIELD:
1488         /* these types should not be encountered here due to language
1489          * restrictions (interface, void, coclass, module), logical
1490          * restrictions (alias - due to type_get_type call above) or
1491          * checking restrictions (function, bitfield). */
1492         assert(0);
1493     }
1494
1495     return size;
1496 }
1497
1498 unsigned int type_memsize(const type_t *t)
1499 {
1500     unsigned int align = 0;
1501     return type_memsize_and_alignment( t, &align );
1502 }
1503
1504 static unsigned int type_buffer_alignment(const type_t *t)
1505 {
1506     const var_list_t *fields;
1507     const var_t *var;
1508     unsigned int max = 0, align;
1509
1510     switch (type_get_type(t))
1511     {
1512     case TYPE_BASIC:
1513         switch (get_basic_fc(t))
1514         {
1515         case RPC_FC_BYTE:
1516         case RPC_FC_CHAR:
1517         case RPC_FC_USMALL:
1518         case RPC_FC_SMALL:
1519             return 1;
1520         case RPC_FC_WCHAR:
1521         case RPC_FC_USHORT:
1522         case RPC_FC_SHORT:
1523             return 2;
1524         case RPC_FC_ULONG:
1525         case RPC_FC_LONG:
1526         case RPC_FC_ERROR_STATUS_T:
1527         case RPC_FC_FLOAT:
1528         case RPC_FC_INT3264:
1529         case RPC_FC_UINT3264:
1530             return 4;
1531         case RPC_FC_HYPER:
1532         case RPC_FC_DOUBLE:
1533             return 8;
1534         default:
1535             error("type_buffer_alignment: Unknown type 0x%x\n", get_basic_fc(t));
1536         }
1537         break;
1538     case TYPE_ENUM:
1539         switch (get_enum_fc(t))
1540         {
1541         case RPC_FC_ENUM16:
1542             return 2;
1543         case RPC_FC_ENUM32:
1544             return 4;
1545         default:
1546             error("type_buffer_alignment: Unknown enum type\n");
1547         }
1548         break;
1549     case TYPE_STRUCT:
1550         if (!(fields = type_struct_get_fields(t))) break;
1551         LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
1552         {
1553             if (!var->type) continue;
1554             align = type_buffer_alignment( var->type );
1555             if (max < align) max = align;
1556         }
1557         break;
1558     case TYPE_ENCAPSULATED_UNION:
1559         if (!(fields = type_encapsulated_union_get_fields(t))) break;
1560         LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
1561         {
1562             if (!var->type) continue;
1563             align = type_buffer_alignment( var->type );
1564             if (max < align) max = align;
1565         }
1566         break;
1567     case TYPE_UNION:
1568         if (!(fields = type_union_get_cases(t))) break;
1569         LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
1570         {
1571             if (!var->type) continue;
1572             align = type_buffer_alignment( var->type );
1573             if (max < align) max = align;
1574         }
1575         break;
1576     case TYPE_ARRAY:
1577         if (!type_array_is_decl_as_ptr(t))
1578             return type_buffer_alignment( type_array_get_element(t) );
1579         /* else fall through */
1580     case TYPE_POINTER:
1581         return 4;
1582     case TYPE_INTERFACE:
1583     case TYPE_ALIAS:
1584     case TYPE_VOID:
1585     case TYPE_COCLASS:
1586     case TYPE_MODULE:
1587     case TYPE_FUNCTION:
1588     case TYPE_BITFIELD:
1589         /* these types should not be encountered here due to language
1590          * restrictions (interface, void, coclass, module), logical
1591          * restrictions (alias - due to type_get_type call above) or
1592          * checking restrictions (function, bitfield). */
1593         assert(0);
1594     }
1595     return max;
1596 }
1597
1598 int is_full_pointer_function(const var_t *func)
1599 {
1600     const var_t *var;
1601     if (type_has_full_pointer(type_function_get_rettype(func->type), func->attrs, TRUE))
1602         return TRUE;
1603     if (!type_get_function_args(func->type))
1604         return FALSE;
1605     LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
1606         if (type_has_full_pointer( var->type, var->attrs, TRUE ))
1607             return TRUE;
1608     return FALSE;
1609 }
1610
1611 void write_full_pointer_init(FILE *file, int indent, const var_t *func, int is_server)
1612 {
1613     print_file(file, indent, "__frame->_StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,%s);\n",
1614                    is_server ? "XLAT_SERVER" : "XLAT_CLIENT");
1615     fprintf(file, "\n");
1616 }
1617
1618 void write_full_pointer_free(FILE *file, int indent, const var_t *func)
1619 {
1620     print_file(file, indent, "NdrFullPointerXlatFree(__frame->_StubMsg.FullPtrXlatTables);\n");
1621     fprintf(file, "\n");
1622 }
1623
1624 static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs,
1625                                             const type_t *type,
1626                                             int toplevel_param,
1627                                             unsigned int offset,
1628                                             unsigned int *typeformat_offset)
1629 {
1630     unsigned int start_offset = *typeformat_offset;
1631     short reloff = offset - (*typeformat_offset + 2);
1632     int in_attr, out_attr;
1633     int pointer_type;
1634     unsigned char flags = 0;
1635
1636     pointer_type = get_pointer_fc(type, attrs, toplevel_param);
1637
1638     in_attr = is_attr(attrs, ATTR_IN);
1639     out_attr = is_attr(attrs, ATTR_OUT);
1640     if (!in_attr && !out_attr) in_attr = 1;
1641
1642     if (out_attr && !in_attr && pointer_type == RPC_FC_RP)
1643         flags |= RPC_FC_P_ONSTACK;
1644
1645     if (is_ptr(type))
1646     {
1647         type_t *ref = type_pointer_get_ref(type);
1648         if(is_declptr(ref) && !is_user_type(ref))
1649             flags |= RPC_FC_P_DEREF;
1650     }
1651
1652     print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
1653                pointer_type,
1654                flags,
1655                string_of_type(pointer_type));
1656     if (file)
1657     {
1658         if (flags & RPC_FC_P_ONSTACK)
1659             fprintf(file, " [allocated_on_stack]");
1660         if (flags & RPC_FC_P_DEREF)
1661             fprintf(file, " [pointer_deref]");
1662         fprintf(file, " */\n");
1663     }
1664
1665     print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, offset);
1666     *typeformat_offset += 4;
1667
1668     return start_offset;
1669 }
1670
1671 static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs, const type_t *type, int toplevel_param)
1672 {
1673     unsigned char fc;
1674     unsigned char pointer_fc;
1675     const type_t *ref;
1676     int in_attr = is_attr(attrs, ATTR_IN);
1677     int out_attr = is_attr(attrs, ATTR_OUT);
1678     unsigned char flags = RPC_FC_P_SIMPLEPOINTER;
1679
1680     /* for historical reasons, write_simple_pointer also handled string types,
1681      * but no longer does. catch bad uses of the function with this check */
1682     if (is_string_type(attrs, type))
1683         error("write_simple_pointer: can't handle type %s which is a string type\n", type->name);
1684
1685     pointer_fc = get_pointer_fc(type, attrs, toplevel_param);
1686
1687     ref = type_pointer_get_ref(type);
1688     if (type_get_type(ref) == TYPE_ENUM)
1689         fc = get_enum_fc(ref);
1690     else
1691         fc = get_basic_fc(ref);
1692
1693     if (out_attr && !in_attr)
1694         flags |= RPC_FC_P_ONSTACK;
1695
1696     print_file(file, 2, "0x%02x, 0x%x,\t/* %s %s[simple_pointer] */\n",
1697                pointer_fc, flags, string_of_type(pointer_fc),
1698                flags & RPC_FC_P_ONSTACK ? "[allocated_on_stack] " : "");
1699     print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
1700     print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
1701     return 4;
1702 }
1703
1704 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
1705 {
1706     print_file(file, 0, "/* %u (", tfsoff);
1707     write_type_decl(file, t, NULL);
1708     print_file(file, 0, ") */\n");
1709 }
1710
1711 static unsigned int write_pointer_tfs(FILE *file, const attr_list_t *attrs,
1712                                       type_t *type, unsigned int ref_offset,
1713                                       int toplevel_param,
1714                                       unsigned int *typestring_offset)
1715 {
1716     unsigned int offset = *typestring_offset;
1717     type_t *ref = type_pointer_get_ref(type);
1718
1719     print_start_tfs_comment(file, type, offset);
1720     update_tfsoff(type, offset, file);
1721
1722     switch (typegen_detect_type(ref, attrs, TDT_ALL_TYPES))
1723     {
1724     case TGT_BASIC:
1725     case TGT_ENUM:
1726         *typestring_offset += write_simple_pointer(file, attrs, type,
1727                                                    toplevel_param);
1728         break;
1729     default:
1730         if (ref_offset)
1731             write_nonsimple_pointer(file, attrs, type,
1732                                     toplevel_param,
1733                                     ref_offset,
1734                                     typestring_offset);
1735         break;
1736     }
1737
1738     return offset;
1739 }
1740
1741 static int processed(const type_t *type)
1742 {
1743     return type->typestring_offset && !type->tfswrite;
1744 }
1745
1746 static int user_type_has_variable_size(const type_t *t)
1747 {
1748     if (is_ptr(t))
1749         return TRUE;
1750     else if (type_get_type(t) == TYPE_STRUCT)
1751     {
1752         switch (get_struct_fc(t))
1753         {
1754         case RPC_FC_PSTRUCT:
1755         case RPC_FC_CSTRUCT:
1756         case RPC_FC_CPSTRUCT:
1757         case RPC_FC_CVSTRUCT:
1758             return TRUE;
1759         }
1760     }
1761     /* Note: Since this only applies to user types, we can't have a conformant
1762        array here, and strings should get filed under pointer in this case.  */
1763     return FALSE;
1764 }
1765
1766 static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
1767 {
1768     unsigned int start, absoff, flags;
1769     const char *name = NULL;
1770     type_t *utype = get_user_type(type, &name);
1771     unsigned int usize = type_memsize(utype);
1772     unsigned int ualign = type_buffer_alignment(utype);
1773     unsigned int size = type_memsize(type);
1774     unsigned short funoff = user_type_offset(name);
1775     short reloff;
1776
1777     if (processed(type)) return type->typestring_offset;
1778
1779     guard_rec(type);
1780
1781     if(user_type_has_variable_size(utype)) usize = 0;
1782
1783     if (type_get_type(utype) == TYPE_BASIC ||
1784         type_get_type(utype) == TYPE_ENUM)
1785     {
1786         unsigned char fc;
1787
1788         if (type_get_type(utype) == TYPE_ENUM)
1789             fc = get_enum_fc(utype);
1790         else
1791             fc = get_basic_fc(utype);
1792
1793         absoff = *tfsoff;
1794         print_start_tfs_comment(file, utype, absoff);
1795         print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1796         print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
1797         *tfsoff += 2;
1798     }
1799     else
1800     {
1801         if (!processed(utype))
1802             write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
1803         absoff = utype->typestring_offset;
1804     }
1805
1806     if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == RPC_FC_RP)
1807         flags = 0x40;
1808     else if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == RPC_FC_UP)
1809         flags = 0x80;
1810     else
1811         flags = 0;
1812
1813     start = *tfsoff;
1814     update_tfsoff(type, start, file);
1815     print_start_tfs_comment(file, type, start);
1816     print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL);
1817     print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
1818                flags | (ualign - 1), ualign - 1, flags);
1819     print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
1820     print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)size, size);
1821     print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)usize, usize);
1822     *tfsoff += 8;
1823     reloff = absoff - *tfsoff;
1824     print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, absoff);
1825     *tfsoff += 2;
1826     return start;
1827 }
1828
1829 static void write_member_type(FILE *file, const type_t *cont,
1830                               int cont_is_complex, const attr_list_t *attrs,
1831                               const type_t *type, unsigned int *corroff,
1832                               unsigned int *tfsoff)
1833 {
1834     if (is_embedded_complex(type) && !is_conformant_array(type))
1835     {
1836         unsigned int absoff;
1837         short reloff;
1838
1839         if (type_get_type(type) == TYPE_UNION && is_attr(attrs, ATTR_SWITCHIS))
1840         {
1841             absoff = *corroff;
1842             *corroff += 8;
1843         }
1844         else
1845         {
1846             absoff = type->typestring_offset;
1847         }
1848         reloff = absoff - (*tfsoff + 2);
1849
1850         print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
1851         /* padding is represented using FC_STRUCTPAD* types, so presumably
1852          * this is left over in the format for historical purposes in MIDL
1853          * or rpcrt4. */
1854         print_file(file, 2, "0x0,\n");
1855         print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
1856                    reloff, reloff, absoff);
1857         *tfsoff += 4;
1858     }
1859     else if (is_ptr(type) || is_conformant_array(type))
1860     {
1861         unsigned char fc = cont_is_complex ? RPC_FC_POINTER : RPC_FC_LONG;
1862         print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
1863         *tfsoff += 1;
1864     }
1865     else if (!write_base_type(file, type, TRUE, tfsoff))
1866         error("Unsupported member type %d\n", type_get_type(type));
1867 }
1868
1869 static void write_array_element_type(FILE *file, const type_t *type,
1870                                      int cont_is_complex, unsigned int *tfsoff)
1871 {
1872     type_t *elem = type_array_get_element(type);
1873
1874     if (!is_embedded_complex(elem) && is_ptr(elem))
1875     {
1876         type_t *ref = type_pointer_get_ref(elem);
1877
1878         if (processed(ref))
1879         {
1880             write_nonsimple_pointer(file, NULL, elem, FALSE, ref->typestring_offset, tfsoff);
1881             return;
1882         }
1883         if (!is_string_type(NULL, elem) &&
1884             (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM))
1885         {
1886             *tfsoff += write_simple_pointer(file, NULL, elem, FALSE);
1887             return;
1888         }
1889     }
1890     return write_member_type(file, type, cont_is_complex, NULL, elem, NULL, tfsoff);
1891 }
1892
1893 static void write_end(FILE *file, unsigned int *tfsoff)
1894 {
1895     if (*tfsoff % 2 == 0)
1896     {
1897         print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD);
1898         *tfsoff += 1;
1899     }
1900     print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END);
1901     *tfsoff += 1;
1902 }
1903
1904 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
1905 {
1906     unsigned int offset = 0;
1907     var_list_t *fs = type_struct_get_fields(type);
1908     var_t *f;
1909
1910     if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry)
1911     {
1912         type_t *ft = f->type;
1913         unsigned int size = field_memsize( ft, &offset );
1914         if (type_get_type(ft) == TYPE_UNION && is_attr(f->attrs, ATTR_SWITCHIS))
1915         {
1916             short reloff;
1917             unsigned int absoff = ft->typestring_offset;
1918             if (is_attr(ft->attrs, ATTR_SWITCHTYPE))
1919                 absoff += 8; /* we already have a corr descr, skip it */
1920             reloff = absoff - (*tfsoff + 6);
1921             print_file(file, 0, "/* %d */\n", *tfsoff);
1922             print_file(file, 2, "0x%x,\t/* FC_NON_ENCAPSULATED_UNION */\n", RPC_FC_NON_ENCAPSULATED_UNION);
1923             print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG);
1924             write_conf_or_var_desc(file, current_structure, offset, ft,
1925                                    get_attrp(f->attrs, ATTR_SWITCHIS));
1926             print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n",
1927                        reloff, reloff, absoff);
1928             *tfsoff += 8;
1929         }
1930         offset += size;
1931     }
1932 }
1933
1934 static int write_pointer_description_offsets(
1935     FILE *file, const attr_list_t *attrs, type_t *type,
1936     unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
1937     unsigned int *typestring_offset)
1938 {
1939     int written = 0;
1940
1941     if ((is_ptr(type) && type_get_type(type_pointer_get_ref(type)) != TYPE_INTERFACE) ||
1942         (is_array(type) && type_array_is_decl_as_ptr(type)))
1943     {
1944         if (offset_in_memory && offset_in_buffer)
1945         {
1946             unsigned int memsize;
1947
1948             /* pointer instance
1949              *
1950              * note that MSDN states that for pointer layouts in structures,
1951              * this is a negative offset from the end of the structure, but
1952              * this statement is incorrect. all offsets are positive */
1953             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Memory offset = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory);
1954             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Buffer offset = %d */\n", (unsigned short)*offset_in_buffer, *offset_in_buffer);
1955
1956             memsize = type_memsize(type);
1957             *offset_in_memory += memsize;
1958             /* increment these separately as in the case of conformant (varying)
1959              * structures these start at different values */
1960             *offset_in_buffer += memsize;
1961         }
1962         *typestring_offset += 4;
1963
1964         if (is_ptr(type))
1965         {
1966             type_t *ref = type_pointer_get_ref(type);
1967
1968             if (is_string_type(attrs, type))
1969                 write_string_tfs(file, attrs, type, FALSE, NULL, typestring_offset);
1970             else if (processed(ref))
1971                 write_nonsimple_pointer(file, attrs, type, FALSE, ref->typestring_offset, typestring_offset);
1972             else if (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM)
1973                 *typestring_offset += write_simple_pointer(file, attrs, type, FALSE);
1974             else
1975                 error("write_pointer_description_offsets: type format string unknown\n");
1976         }
1977         else
1978         {
1979             unsigned int offset = type->typestring_offset;
1980             /* skip over the pointer that is written for strings, since a
1981              * pointer has to be written in-place here */
1982             if (is_string_type(attrs, type))
1983                 offset += 4;
1984             write_nonsimple_pointer(file, attrs, type, FALSE, offset, typestring_offset);
1985         }
1986
1987         return 1;
1988     }
1989
1990     if (is_array(type))
1991     {
1992         return write_pointer_description_offsets(
1993             file, attrs, type_array_get_element(type), offset_in_memory,
1994             offset_in_buffer, typestring_offset);
1995     }
1996     else if (is_non_complex_struct(type))
1997     {
1998         /* otherwise search for interesting fields to parse */
1999         const var_t *v;
2000         LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry )
2001         {
2002             if (offset_in_memory && offset_in_buffer)
2003             {
2004                 unsigned int padding;
2005                 unsigned int align = 0;
2006                 type_memsize_and_alignment(v->type, &align);
2007                 padding = ROUNDING(*offset_in_memory, align);
2008                 *offset_in_memory += padding;
2009                 *offset_in_buffer += padding;
2010             }
2011             written += write_pointer_description_offsets(
2012                 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
2013                 typestring_offset);
2014         }
2015     }
2016     else
2017     {
2018         if (offset_in_memory && offset_in_buffer)
2019         {
2020             unsigned int memsize = type_memsize(type);
2021             *offset_in_memory += memsize;
2022             /* increment these separately as in the case of conformant (varying)
2023              * structures these start at different values */
2024             *offset_in_buffer += memsize;
2025         }
2026     }
2027
2028     return written;
2029 }
2030
2031 static int write_no_repeat_pointer_descriptions(
2032     FILE *file, const attr_list_t *attrs, type_t *type,
2033     unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2034     unsigned int *typestring_offset)
2035 {
2036     int written = 0;
2037
2038     if (is_ptr(type) ||
2039         (is_conformant_array(type) && type_array_is_decl_as_ptr(type)))
2040     {
2041         print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT);
2042         print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
2043         *typestring_offset += 2;
2044
2045         return write_pointer_description_offsets(file, attrs, type,
2046                        offset_in_memory, offset_in_buffer, typestring_offset);
2047     }
2048
2049     if (is_non_complex_struct(type))
2050     {
2051         const var_t *v;
2052         LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry )
2053         {
2054             if (offset_in_memory && offset_in_buffer)
2055             {
2056                 unsigned int padding;
2057                 unsigned int align = 0;
2058                 type_memsize_and_alignment(v->type, &align);
2059                 padding = ROUNDING(*offset_in_memory, align);
2060                 *offset_in_memory += padding;
2061                 *offset_in_buffer += padding;
2062             }
2063             written += write_no_repeat_pointer_descriptions(
2064                 file, v->attrs, v->type,
2065                 offset_in_memory, offset_in_buffer, typestring_offset);
2066         }
2067     }
2068     else
2069     {
2070         unsigned int memsize = type_memsize(type);
2071         *offset_in_memory += memsize;
2072         /* increment these separately as in the case of conformant (varying)
2073          * structures these start at different values */
2074         *offset_in_buffer += memsize;
2075     }
2076
2077     return written;
2078 }
2079
2080 /* Note: if file is NULL return value is number of pointers to write, else
2081  * it is the number of type format characters written */
2082 static int write_fixed_array_pointer_descriptions(
2083     FILE *file, const attr_list_t *attrs, type_t *type,
2084     unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2085     unsigned int *typestring_offset)
2086 {
2087     int pointer_count = 0;
2088
2089     if (type_get_type(type) == TYPE_ARRAY &&
2090         !type_array_has_conformance(type) && !type_array_has_variance(type))
2091     {
2092         unsigned int temp = 0;
2093         /* unfortunately, this needs to be done in two passes to avoid
2094          * writing out redundant FC_FIXED_REPEAT descriptions */
2095         pointer_count = write_pointer_description_offsets(
2096             NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
2097         if (pointer_count > 0)
2098         {
2099             unsigned int increment_size;
2100             unsigned int offset_of_array_pointer_mem = 0;
2101             unsigned int offset_of_array_pointer_buf = 0;
2102
2103             increment_size = type_memsize(type_array_get_element(type));
2104
2105             print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT);
2106             print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD);
2107             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Iterations = %d */\n", (unsigned short)type_array_get_dim(type), type_array_get_dim(type));
2108             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
2109             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory);
2110             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count);
2111             *typestring_offset += 10;
2112
2113             pointer_count = write_pointer_description_offsets(
2114                 file, attrs, type, &offset_of_array_pointer_mem,
2115                 &offset_of_array_pointer_buf, typestring_offset);
2116         }
2117     }
2118     else if (type_get_type(type) == TYPE_STRUCT)
2119     {
2120         const var_t *v;
2121         LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry )
2122         {
2123             if (offset_in_memory && offset_in_buffer)
2124             {
2125                 unsigned int padding;
2126                 unsigned int align = 0;
2127                 type_memsize_and_alignment(v->type, &align);
2128                 padding = ROUNDING(*offset_in_memory, align);
2129                 *offset_in_memory += padding;
2130                 *offset_in_buffer += padding;
2131             }
2132             pointer_count += write_fixed_array_pointer_descriptions(
2133                 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
2134                 typestring_offset);
2135         }
2136     }
2137     else
2138     {
2139         if (offset_in_memory && offset_in_buffer)
2140         {
2141             unsigned int memsize;
2142             memsize = type_memsize(type);
2143             *offset_in_memory += memsize;
2144             /* increment these separately as in the case of conformant (varying)
2145              * structures these start at different values */
2146             *offset_in_buffer += memsize;
2147         }
2148     }
2149
2150     return pointer_count;
2151 }
2152
2153 /* Note: if file is NULL return value is number of pointers to write, else
2154  * it is the number of type format characters written */
2155 static int write_conformant_array_pointer_descriptions(
2156     FILE *file, const attr_list_t *attrs, type_t *type,
2157     unsigned int offset_in_memory, unsigned int *typestring_offset)
2158 {
2159     int pointer_count = 0;
2160
2161     if (is_conformant_array(type) && !type_array_has_variance(type))
2162     {
2163         unsigned int temp = 0;
2164         /* unfortunately, this needs to be done in two passes to avoid
2165          * writing out redundant FC_VARIABLE_REPEAT descriptions */
2166         pointer_count = write_pointer_description_offsets(
2167             NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
2168         if (pointer_count > 0)
2169         {
2170             unsigned int increment_size;
2171             unsigned int offset_of_array_pointer_mem = offset_in_memory;
2172             unsigned int offset_of_array_pointer_buf = offset_in_memory;
2173
2174             increment_size = type_memsize(type_array_get_element(type));
2175
2176             if (increment_size > USHRT_MAX)
2177                 error("array size of %u bytes is too large\n", increment_size);
2178
2179             print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
2180             print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET);
2181             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
2182             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)offset_in_memory, offset_in_memory);
2183             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count);
2184             *typestring_offset += 8;
2185
2186             pointer_count = write_pointer_description_offsets(
2187                 file, attrs, type_array_get_element(type),
2188                 &offset_of_array_pointer_mem, &offset_of_array_pointer_buf,
2189                 typestring_offset);
2190         }
2191     }
2192
2193     return pointer_count;
2194 }
2195
2196 /* Note: if file is NULL return value is number of pointers to write, else
2197  * it is the number of type format characters written */
2198 static int write_varying_array_pointer_descriptions(
2199     FILE *file, const attr_list_t *attrs, type_t *type,
2200     unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2201     unsigned int *typestring_offset)
2202 {
2203     int pointer_count = 0;
2204
2205     if (is_array(type) && type_array_has_variance(type))
2206     {
2207         unsigned int temp = 0;
2208         /* unfortunately, this needs to be done in two passes to avoid
2209          * writing out redundant FC_VARIABLE_REPEAT descriptions */
2210         pointer_count = write_pointer_description_offsets(
2211             NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
2212         if (pointer_count > 0)
2213         {
2214             unsigned int increment_size;
2215
2216             increment_size = type_memsize(type_array_get_element(type));
2217
2218             if (increment_size > USHRT_MAX)
2219                 error("array size of %u bytes is too large\n", increment_size);
2220
2221             print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT);
2222             print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET);
2223             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
2224             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory);
2225             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count);
2226             *typestring_offset += 8;
2227
2228             pointer_count = write_pointer_description_offsets(
2229                 file, attrs, type_array_get_element(type), offset_in_memory,
2230                 offset_in_buffer, typestring_offset);
2231         }
2232     }
2233     else if (type_get_type(type) == TYPE_STRUCT)
2234     {
2235         const var_t *v;
2236         LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry )
2237         {
2238             if (offset_in_memory && offset_in_buffer)
2239             {
2240                 unsigned int align = 0, padding;
2241
2242                 if (is_array(v->type) && type_array_has_variance(v->type))
2243                 {
2244                     *offset_in_buffer = ROUND_SIZE(*offset_in_buffer, 4);
2245                     /* skip over variance and offset in buffer */
2246                     *offset_in_buffer += 8;
2247                 }
2248
2249                 type_memsize_and_alignment(v->type, &align);
2250                 padding = ROUNDING(*offset_in_memory, align);
2251                 *offset_in_memory += padding;
2252                 *offset_in_buffer += padding;
2253             }
2254             pointer_count += write_varying_array_pointer_descriptions(
2255                 file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
2256                 typestring_offset);
2257         }
2258     }
2259     else
2260     {
2261         if (offset_in_memory && offset_in_buffer)
2262         {
2263             unsigned int memsize = type_memsize(type);
2264             *offset_in_memory += memsize;
2265             /* increment these separately as in the case of conformant (varying)
2266              * structures these start at different values */
2267             *offset_in_buffer += memsize;
2268         }
2269     }
2270
2271     return pointer_count;
2272 }
2273
2274 static void write_pointer_description(FILE *file, type_t *type,
2275                                       unsigned int *typestring_offset)
2276 {
2277     unsigned int offset_in_buffer;
2278     unsigned int offset_in_memory;
2279
2280     /* pass 1: search for single instance of a pointer (i.e. don't descend
2281      * into arrays) */
2282     if (!is_array(type))
2283     {
2284         offset_in_memory = 0;
2285         offset_in_buffer = 0;
2286         write_no_repeat_pointer_descriptions(
2287             file, NULL, type,
2288             &offset_in_memory, &offset_in_buffer, typestring_offset);
2289     }
2290
2291     /* pass 2: search for pointers in fixed arrays */
2292     offset_in_memory = 0;
2293     offset_in_buffer = 0;
2294     write_fixed_array_pointer_descriptions(
2295         file, NULL, type,
2296         &offset_in_memory, &offset_in_buffer, typestring_offset);
2297
2298     /* pass 3: search for pointers in conformant only arrays (but don't descend
2299      * into conformant varying or varying arrays) */
2300     if (is_conformant_array(type) &&
2301         (type_array_is_decl_as_ptr(type) || !current_structure))
2302         write_conformant_array_pointer_descriptions(
2303             file, NULL, type, 0, typestring_offset);
2304     else if (type_get_type(type) == TYPE_STRUCT &&
2305              get_struct_fc(type) == RPC_FC_CPSTRUCT)
2306     {
2307         type_t *carray = find_array_or_string_in_struct(type)->type;
2308         write_conformant_array_pointer_descriptions( file, NULL, carray,
2309                                                      type_memsize(type), typestring_offset);
2310     }
2311
2312     /* pass 4: search for pointers in varying arrays */
2313     offset_in_memory = 0;
2314     offset_in_buffer = 0;
2315     write_varying_array_pointer_descriptions(
2316             file, NULL, type,
2317             &offset_in_memory, &offset_in_buffer, typestring_offset);
2318 }
2319
2320 int is_declptr(const type_t *t)
2321 {
2322   return is_ptr(t) || (type_get_type(t) == TYPE_ARRAY && type_array_is_decl_as_ptr(t));
2323 }
2324
2325 static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
2326                                      type_t *type, int toplevel_param,
2327                                      const char *name, unsigned int *typestring_offset)
2328 {
2329     unsigned int start_offset;
2330     unsigned char rtype;
2331     type_t *elem_type;
2332     int is_processed = processed(type);
2333
2334     start_offset = *typestring_offset;
2335
2336     if (is_declptr(type))
2337     {
2338         unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER;
2339         int pointer_type = get_pointer_fc(type, attrs, toplevel_param);
2340         if (!pointer_type)
2341             pointer_type = RPC_FC_RP;
2342         print_start_tfs_comment(file, type, *typestring_offset);
2343         print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
2344                    pointer_type, flag, string_of_type(pointer_type),
2345                    flag ? " [simple_pointer]" : "");
2346         *typestring_offset += 2;
2347         if (!flag)
2348         {
2349             print_file(file, 2, "NdrFcShort(0x2),\n");
2350             *typestring_offset += 2;
2351         }
2352         is_processed = FALSE;
2353     }
2354
2355     if (is_array(type))
2356         elem_type = type_array_get_element(type);
2357     else
2358         elem_type = type_pointer_get_ref(type);
2359
2360     if (type_get_type(elem_type) != TYPE_BASIC)
2361     {
2362         error("write_string_tfs: Unimplemented for non-basic type %s\n", name);
2363         return start_offset;
2364     }
2365
2366     rtype = get_basic_fc(elem_type);
2367     if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR))
2368     {
2369         error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
2370         return start_offset;
2371     }
2372
2373     if (type_get_type(type) == TYPE_ARRAY && !type_array_has_conformance(type))
2374     {
2375         unsigned int dim = type_array_get_dim(type);
2376
2377         if (is_processed) return start_offset;
2378
2379         /* FIXME: multi-dimensional array */
2380         if (0xffffu < dim)
2381             error("array size for parameter %s exceeds %u bytes by %u bytes\n",
2382                   name, 0xffffu, dim - 0xffffu);
2383
2384         if (rtype == RPC_FC_WCHAR)
2385             WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
2386         else
2387             WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
2388         print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
2389         *typestring_offset += 2;
2390
2391         print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)dim, dim);
2392         *typestring_offset += 2;
2393
2394         update_tfsoff(type, start_offset, file);
2395         return start_offset;
2396     }
2397     else if (is_conformant_array(type))
2398     {
2399         if (rtype == RPC_FC_WCHAR)
2400             WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
2401         else
2402             WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
2403         print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED);
2404         *typestring_offset += 2;
2405
2406         *typestring_offset += write_conf_or_var_desc(
2407             file, current_structure,
2408             (!type_array_is_decl_as_ptr(type) && current_structure
2409              ? type_memsize(current_structure)
2410              : 0),
2411             type, type_array_get_conformance(type));
2412
2413         update_tfsoff(type, start_offset, file);
2414         return start_offset;
2415     }
2416     else
2417     {
2418         if (is_processed) return start_offset;
2419
2420         if (rtype == RPC_FC_WCHAR)
2421             WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
2422         else
2423             WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
2424         print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
2425         *typestring_offset += 2;
2426
2427         update_tfsoff(type, start_offset, file);
2428         return start_offset;
2429     }
2430 }
2431
2432 static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
2433                                     const char *name, unsigned int *typestring_offset)
2434 {
2435     const expr_t *length_is = type_array_get_variance(type);
2436     const expr_t *size_is = type_array_get_conformance(type);
2437     unsigned int align;
2438     unsigned int size;
2439     unsigned int start_offset;
2440     unsigned char fc;
2441     int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
2442     unsigned int baseoff
2443         = !type_array_is_decl_as_ptr(type) && current_structure
2444         ? type_memsize(current_structure)
2445         : 0;
2446
2447     if (!pointer_type)
2448         pointer_type = RPC_FC_RP;
2449
2450     write_embedded_types(file, attrs, type_array_get_element(type), name, FALSE, typestring_offset);
2451
2452     size = type_memsize(is_conformant_array(type) ? type_array_get_element(type) : type);
2453     align = type_buffer_alignment(is_conformant_array(type) ? type_array_get_element(type) : type);
2454     fc = get_array_fc(type);
2455
2456     start_offset = *typestring_offset;
2457     update_tfsoff(type, start_offset, file);
2458     print_start_tfs_comment(file, type, start_offset);
2459     print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
2460     print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
2461     *typestring_offset += 2;
2462
2463     align = 0;
2464     if (fc != RPC_FC_BOGUS_ARRAY)
2465     {
2466         if (fc == RPC_FC_LGFARRAY || fc == RPC_FC_LGVARRAY)
2467         {
2468             print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", size, size);
2469             *typestring_offset += 4;
2470         }
2471         else
2472         {
2473             print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)size, size);
2474             *typestring_offset += 2;
2475         }
2476
2477         if (is_conformant_array(type))
2478             *typestring_offset
2479                 += write_conf_or_var_desc(file, current_structure, baseoff,
2480                                           type, size_is);
2481
2482         if (fc == RPC_FC_SMVARRAY || fc == RPC_FC_LGVARRAY)
2483         {
2484             unsigned int elsize = type_memsize(type_array_get_element(type));
2485             unsigned int dim = type_array_get_dim(type);
2486
2487             if (fc == RPC_FC_LGVARRAY)
2488             {
2489                 print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", dim, dim);
2490                 *typestring_offset += 4;
2491             }
2492             else
2493             {
2494                 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)dim, dim);
2495                 *typestring_offset += 2;
2496             }
2497
2498             print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)elsize, elsize);
2499             *typestring_offset += 2;
2500         }
2501
2502         if (length_is)
2503             *typestring_offset
2504                 += write_conf_or_var_desc(file, current_structure, baseoff,
2505                                           type, length_is);
2506
2507         if (type_has_pointers(type_array_get_element(type)) &&
2508             (type_array_is_decl_as_ptr(type) || !current_structure))
2509         {
2510             print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
2511             print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
2512             *typestring_offset += 2;
2513             write_pointer_description(file, type, typestring_offset);
2514             print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
2515             *typestring_offset += 1;
2516         }
2517
2518         write_array_element_type(file, type, FALSE, typestring_offset);
2519         write_end(file, typestring_offset);
2520     }
2521     else
2522     {
2523         unsigned int dim = size_is ? 0 : type_array_get_dim(type);
2524         print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)dim, dim);
2525         *typestring_offset += 2;
2526         *typestring_offset
2527             += write_conf_or_var_desc(file, current_structure, baseoff,
2528                                       type, size_is);
2529         *typestring_offset
2530             += write_conf_or_var_desc(file, current_structure, baseoff,
2531                                       type, length_is);
2532
2533         write_array_element_type(file, type, TRUE, typestring_offset);
2534         write_end(file, typestring_offset);
2535     }
2536
2537     return start_offset;
2538 }
2539
2540 static const var_t *find_array_or_string_in_struct(const type_t *type)
2541 {
2542     const var_list_t *fields = type_struct_get_fields(type);
2543     const var_t *last_field;
2544     const type_t *ft;
2545
2546     if (!fields || list_empty(fields))
2547         return NULL;
2548
2549     last_field = LIST_ENTRY( list_tail(fields), const var_t, entry );
2550     ft = last_field->type;
2551
2552     if (is_conformant_array(ft) && !type_array_is_decl_as_ptr(ft))
2553         return last_field;
2554
2555     if (type_get_type(ft) == TYPE_STRUCT)
2556         return find_array_or_string_in_struct(ft);
2557     else
2558         return NULL;
2559 }
2560
2561 static void write_struct_members(FILE *file, const type_t *type,
2562                                  int is_complex, unsigned int *corroff,
2563                                  unsigned int *typestring_offset)
2564 {
2565     const var_t *field;
2566     unsigned short offset = 0;
2567     unsigned int salign = 1;
2568     int padding;
2569     var_list_t *fields = type_struct_get_fields(type);
2570
2571     if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
2572     {
2573         type_t *ft = field->type;
2574         unsigned int align = 0;
2575         unsigned int size = type_memsize_and_alignment(ft, &align);
2576         align = clamp_align(align);
2577         if (salign < align) salign = align;
2578
2579         if (!is_conformant_array(ft) || type_array_is_decl_as_ptr(ft))
2580         {
2581             if ((align - 1) & offset)
2582             {
2583                 unsigned char fc = 0;
2584                 switch (align)
2585                 {
2586                 case 2:
2587                     fc = RPC_FC_ALIGNM2;
2588                     break;
2589                 case 4:
2590                     fc = RPC_FC_ALIGNM4;
2591                     break;
2592                 case 8:
2593                     fc = RPC_FC_ALIGNM8;
2594                     break;
2595                 default:
2596                     error("write_struct_members: cannot align type %d\n", type_get_type(ft));
2597                 }
2598                 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
2599                 offset = ROUND_SIZE(offset, align);
2600                 *typestring_offset += 1;
2601             }
2602             write_member_type(file, type, is_complex, field->attrs, field->type, corroff,
2603                               typestring_offset);
2604             offset += size;
2605         }
2606     }
2607
2608     padding = ROUNDING(offset, salign);
2609     if (padding)
2610     {
2611         print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
2612                    RPC_FC_STRUCTPAD1 + padding - 1,
2613                    padding);
2614         *typestring_offset += 1;
2615     }
2616
2617     write_end(file, typestring_offset);
2618 }
2619
2620 static unsigned int write_struct_tfs(FILE *file, type_t *type,
2621                                      const char *name, unsigned int *tfsoff)
2622 {
2623     const type_t *save_current_structure = current_structure;
2624     unsigned int total_size;
2625     const var_t *array;
2626     unsigned int start_offset;
2627     unsigned int align;
2628     unsigned int corroff;
2629     var_t *f;
2630     unsigned char fc = get_struct_fc(type);
2631     var_list_t *fields = type_struct_get_fields(type);
2632
2633     if (processed(type)) return type->typestring_offset;
2634
2635     guard_rec(type);
2636     current_structure = type;
2637
2638     total_size = type_memsize(type);
2639     align = type_buffer_alignment(type);
2640     if (total_size > USHRT_MAX)
2641         error("structure size for %s exceeds %d bytes by %d bytes\n",
2642               name, USHRT_MAX, total_size - USHRT_MAX);
2643
2644     if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
2645         write_embedded_types(file, f->attrs, f->type, f->name, FALSE, tfsoff);
2646
2647     array = find_array_or_string_in_struct(type);
2648     if (array && !processed(array->type))
2649     {
2650         if(is_string_type(array->attrs, array->type))
2651             write_string_tfs(file, array->attrs, array->type, FALSE, array->name, tfsoff);
2652         else
2653             write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
2654     }
2655
2656     corroff = *tfsoff;
2657     write_descriptors(file, type, tfsoff);
2658
2659     start_offset = *tfsoff;
2660     update_tfsoff(type, start_offset, file);
2661     print_start_tfs_comment(file, type, start_offset);
2662     print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
2663     print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
2664     print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)total_size, total_size);
2665     *tfsoff += 4;
2666
2667     if (array)
2668     {
2669         unsigned int absoff = array->type->typestring_offset;
2670         short reloff = absoff - *tfsoff;
2671         print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2672                    reloff, reloff, absoff);
2673         *tfsoff += 2;
2674     }
2675     else if (fc == RPC_FC_BOGUS_STRUCT)
2676     {
2677         print_file(file, 2, "NdrFcShort(0x0),\n");
2678         *tfsoff += 2;
2679     }
2680
2681     if (fc == RPC_FC_BOGUS_STRUCT)
2682     {
2683         /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
2684            nothing is written to file yet.  On the actual writing pass,
2685            this will have been updated.  */
2686         unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff;
2687         int reloff = absoff - *tfsoff;
2688         assert( reloff >= 0 );
2689         print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %d (%u) */\n",
2690                    (unsigned short)reloff, reloff, absoff);
2691         *tfsoff += 2;
2692     }
2693     else if ((fc == RPC_FC_PSTRUCT) ||
2694              (fc == RPC_FC_CPSTRUCT) ||
2695              (fc == RPC_FC_CVSTRUCT && type_has_pointers(type)))
2696     {
2697         print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP);
2698         print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD);
2699         *tfsoff += 2;
2700         write_pointer_description(file, type, tfsoff);
2701         print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END);
2702         *tfsoff += 1;
2703     }
2704
2705     write_struct_members(file, type, fc == RPC_FC_BOGUS_STRUCT, &corroff,
2706                          tfsoff);
2707
2708     if (fc == RPC_FC_BOGUS_STRUCT)
2709     {
2710         const var_t *f;
2711
2712         type->ptrdesc = *tfsoff;
2713         if (fields) LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
2714         {
2715             type_t *ft = f->type;
2716             switch (typegen_detect_type(ft, f->attrs, TDT_IGNORE_STRINGS))
2717             {
2718             case TGT_POINTER:
2719                 if (is_string_type(f->attrs, ft))
2720                     write_string_tfs(file, f->attrs, ft, FALSE, f->name, tfsoff);
2721                 else
2722                     write_pointer_tfs(file, f->attrs, ft,
2723                                       type_pointer_get_ref(ft)->typestring_offset,
2724                                       FALSE, tfsoff);
2725                 break;
2726             case TGT_ARRAY:
2727                 if (type_array_is_decl_as_ptr(ft))
2728                 {
2729                     unsigned int offset;
2730
2731                     print_file(file, 0, "/* %d */\n", *tfsoff);
2732
2733                     offset = ft->typestring_offset;
2734                     /* skip over the pointer that is written for strings, since a
2735                      * pointer has to be written in-place here */
2736                     if (is_string_type(f->attrs, ft))
2737                         offset += 4;
2738                     write_nonsimple_pointer(file, f->attrs, ft, FALSE, offset, tfsoff);
2739                 }
2740                 break;
2741             default:
2742                 break;
2743             }
2744         }
2745         if (type->ptrdesc == *tfsoff)
2746             type->ptrdesc = 0;
2747     }
2748
2749     current_structure = save_current_structure;
2750     return start_offset;
2751 }
2752
2753 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
2754 {
2755     if (t == NULL)
2756     {
2757         print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
2758     }
2759     else
2760     {
2761         if (type_get_type(t) == TYPE_BASIC || type_get_type(t) == TYPE_ENUM)
2762         {
2763             unsigned char fc;
2764             if (type_get_type(t) == TYPE_BASIC)
2765                 fc = get_basic_fc(t);
2766             else
2767                 fc = get_enum_fc(t);
2768             print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
2769                        fc, string_of_type(fc));
2770         }
2771         else if (t->typestring_offset)
2772         {
2773             short reloff = t->typestring_offset - *tfsoff;
2774             print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %d (%d) */\n",
2775                        reloff, reloff, t->typestring_offset);
2776         }
2777         else
2778             error("write_branch_type: type unimplemented %d\n", type_get_type(t));
2779     }
2780
2781     *tfsoff += 2;
2782 }
2783
2784 static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
2785                                     type_t *type, unsigned int *tfsoff)
2786 {
2787     unsigned int start_offset;
2788     unsigned int size;
2789     var_list_t *fields;
2790     unsigned int nbranch = 0;
2791     type_t *deftype = NULL;
2792     short nodeftype = 0xffff;
2793     var_t *f;
2794
2795     if (processed(type) &&
2796         (type_get_type(type) == TYPE_ENCAPSULATED_UNION || !is_attr(type->attrs, ATTR_SWITCHTYPE)))
2797         return type->typestring_offset;
2798
2799     guard_rec(type);
2800
2801     size = type_memsize(type);
2802
2803     fields = type_union_get_cases(type);
2804
2805     if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
2806     {
2807         expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
2808         if (cases)
2809             nbranch += list_count(cases);
2810         if (f->type)
2811             write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
2812     }
2813
2814     start_offset = *tfsoff;
2815     update_tfsoff(type, start_offset, file);
2816     print_start_tfs_comment(file, type, start_offset);
2817     if (type_get_type(type) == TYPE_ENCAPSULATED_UNION)
2818     {
2819         const var_t *sv = type_union_get_switch_value(type);
2820         const type_t *st = sv->type;
2821         unsigned char fc;
2822
2823         if (type_get_type(st) == TYPE_BASIC)
2824         {
2825             switch (get_basic_fc(st))
2826             {
2827             case RPC_FC_CHAR:
2828             case RPC_FC_SMALL:
2829             case RPC_FC_BYTE:
2830             case RPC_FC_USMALL:
2831             case RPC_FC_WCHAR:
2832             case RPC_FC_SHORT:
2833             case RPC_FC_USHORT:
2834             case RPC_FC_LONG:
2835             case RPC_FC_ULONG:
2836                 fc = get_basic_fc(st);
2837                 break;
2838             default:
2839                 fc = 0;
2840                 error("union switch type must be an integer, char, or enum\n");
2841             }
2842         }
2843         else if (type_get_type(st) == TYPE_ENUM)
2844             fc = get_enum_fc(st);
2845         else
2846             error("union switch type must be an integer, char, or enum\n");
2847
2848         print_file(file, 2, "0x%x,\t/* FC_ENCAPSULATED_UNION */\n", RPC_FC_ENCAPSULATED_UNION);
2849         print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
2850                    0x40 | fc, string_of_type(fc));
2851         *tfsoff += 2;
2852     }
2853     else if (is_attr(type->attrs, ATTR_SWITCHTYPE))
2854     {
2855         const expr_t *switch_is = get_attrp(attrs, ATTR_SWITCHIS);
2856         const type_t *st = get_attrp(type->attrs, ATTR_SWITCHTYPE);
2857         unsigned char fc;
2858
2859         if (type_get_type(st) == TYPE_BASIC)
2860         {
2861             switch (get_basic_fc(st))
2862             {
2863             case RPC_FC_CHAR:
2864             case RPC_FC_SMALL:
2865             case RPC_FC_USMALL:
2866             case RPC_FC_SHORT:
2867             case RPC_FC_USHORT:
2868             case RPC_FC_LONG:
2869             case RPC_FC_ULONG:
2870             case RPC_FC_ENUM16:
2871             case RPC_FC_ENUM32:
2872                 fc = get_basic_fc(st);
2873                 break;
2874             default:
2875                 fc = 0;
2876                 error("union switch type must be an integer, char, or enum\n");
2877             }
2878         }
2879         else if (type_get_type(st) == TYPE_ENUM)
2880             fc = get_enum_fc(st);
2881         else
2882             error("union switch type must be an integer, char, or enum\n");
2883
2884         print_file(file, 2, "0x%x,\t/* FC_NON_ENCAPSULATED_UNION */\n", RPC_FC_NON_ENCAPSULATED_UNION);
2885         print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
2886                    fc, string_of_type(fc));
2887         *tfsoff += 2;
2888         *tfsoff += write_conf_or_var_desc(file, current_structure, 0, st, switch_is );
2889         print_file(file, 2, "NdrFcShort(0x2),\t/* Offset= 2 (%u) */\n", *tfsoff + 2);
2890         *tfsoff += 2;
2891         print_file(file, 0, "/* %u */\n", *tfsoff);
2892     }
2893
2894     print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)size, size);
2895     print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)nbranch, nbranch);
2896     *tfsoff += 4;
2897
2898     if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
2899     {
2900         type_t *ft = f->type;
2901         expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
2902         int deflt = is_attr(f->attrs, ATTR_DEFAULT);
2903         expr_t *c;
2904
2905         if (cases == NULL && !deflt)
2906             error("union field %s with neither case nor default attribute\n", f->name);
2907
2908         if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
2909         {
2910             /* MIDL doesn't check for duplicate cases, even though that seems
2911                like a reasonable thing to do, it just dumps them to the TFS
2912                like we're going to do here.  */
2913             print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
2914             *tfsoff += 4;
2915             write_branch_type(file, ft, tfsoff);
2916         }
2917
2918         /* MIDL allows multiple default branches, even though that seems
2919            illogical, it just chooses the last one, which is what we will
2920            do.  */
2921         if (deflt)
2922         {
2923             deftype = ft;
2924             nodeftype = 0;
2925         }
2926     }
2927
2928     if (deftype)
2929     {
2930         write_branch_type(file, deftype, tfsoff);
2931     }
2932     else
2933     {
2934         print_file(file, 2, "NdrFcShort(0x%hx),\n", nodeftype);
2935         *tfsoff += 2;
2936     }
2937
2938     return start_offset;
2939 }
2940
2941 static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
2942                                  unsigned int *typeformat_offset)
2943 {
2944     unsigned int i;
2945     unsigned int start_offset = *typeformat_offset;
2946     expr_t *iid = get_attrp(attrs, ATTR_IIDIS);
2947
2948     if (!iid && processed(type)) return type->typestring_offset;
2949
2950     print_start_tfs_comment(file, type, start_offset);
2951     update_tfsoff(type, start_offset, file);
2952
2953     if (iid)
2954     {
2955         print_file(file, 2, "0x2f,  /* FC_IP */\n");
2956         print_file(file, 2, "0x5c,  /* FC_PAD */\n");
2957         *typeformat_offset
2958             += write_conf_or_var_desc(file, current_structure, 0, type, iid) + 2;
2959     }
2960     else
2961     {
2962         const type_t *base = is_ptr(type) ? type_pointer_get_ref(type) : type;
2963         const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
2964
2965         if (! uuid)
2966             error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
2967
2968         print_file(file, 2, "0x2f,\t/* FC_IP */\n");
2969         print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
2970         print_file(file, 2, "NdrFcLong(0x%08x),\n", uuid->Data1);
2971         print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
2972         print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
2973         for (i = 0; i < 8; ++i)
2974             print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
2975
2976         if (file)
2977             fprintf(file, "\n");
2978
2979         *typeformat_offset += 18;
2980     }
2981     return start_offset;
2982 }
2983
2984 static unsigned int write_contexthandle_tfs(FILE *file,
2985                                             const attr_list_t *attrs,
2986                                             type_t *type,
2987                                             int toplevel_param,
2988                                             unsigned int *typeformat_offset)
2989 {
2990     unsigned int start_offset = *typeformat_offset;
2991     unsigned char flags = get_contexthandle_flags( current_iface, attrs, type );
2992
2993     print_start_tfs_comment(file, type, start_offset);
2994
2995     if (flags & 0x80)  /* via ptr */
2996     {
2997         int pointer_type = get_pointer_fc( type, attrs, toplevel_param );
2998         if (!pointer_type) pointer_type = RPC_FC_RP;
2999         *typeformat_offset += 4;
3000         print_file(file, 2,"0x%x, 0x0,\t/* %s */\n", pointer_type, string_of_type(pointer_type) );
3001         print_file(file, 2, "NdrFcShort(0x2),\t /* Offset= 2 (%u) */\n", *typeformat_offset);
3002         print_file(file, 0, "/* %2u */\n", *typeformat_offset);
3003     }
3004
3005     print_file(file, 2, "0x%02x,\t/* FC_BIND_CONTEXT */\n", RPC_FC_BIND_CONTEXT);
3006     print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
3007     /* return and can't be null values overlap */
3008     if (((flags & 0x21) != 0x21) && (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL))
3009         print_file(file, 0, "can't be null, ");
3010     if (flags & NDR_CONTEXT_HANDLE_SERIALIZE)
3011         print_file(file, 0, "serialize, ");
3012     if (flags & NDR_CONTEXT_HANDLE_NO_SERIALIZE)
3013         print_file(file, 0, "no serialize, ");
3014     if (flags & NDR_STRICT_CONTEXT_HANDLE)
3015         print_file(file, 0, "strict, ");
3016     if ((flags & 0x21) == 0x20)
3017         print_file(file, 0, "out, ");
3018     if ((flags & 0x21) == 0x21)
3019         print_file(file, 0, "return, ");
3020     if (flags & 0x40)
3021         print_file(file, 0, "in, ");
3022     if (flags & 0x80)
3023         print_file(file, 0, "via ptr, ");
3024     print_file(file, 0, "*/\n");
3025     print_file(file, 2, "0x%x,\t/* rundown routine */\n", get_context_handle_offset( type ));
3026     print_file(file, 2, "0, /* FIXME: param num */\n");
3027     *typeformat_offset += 4;
3028
3029     update_tfsoff( type, start_offset, file );
3030     return start_offset;
3031 }
3032
3033 static unsigned int write_range_tfs(FILE *file, const attr_list_t *attrs,
3034                                     type_t *type, expr_list_t *range_list,
3035                                     unsigned int *typeformat_offset)
3036 {
3037     unsigned char fc;
3038     unsigned int start_offset = *typeformat_offset;
3039     const expr_t *range_min = LIST_ENTRY(list_head(range_list), const expr_t, entry);
3040     const expr_t *range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry);
3041
3042     if (type_get_type(type) == TYPE_BASIC)
3043         fc = get_basic_fc(type);
3044     else
3045         fc = get_enum_fc(type);
3046
3047     /* fc must fit in lower 4-bits of 8-bit field below */
3048     assert(fc <= 0xf);
3049
3050     print_file(file, 0, "/* %u */\n", *typeformat_offset);
3051     print_file(file, 2, "0x%x,\t/* FC_RANGE */\n", RPC_FC_RANGE);
3052     print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
3053     print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_min->cval, range_min->cval);
3054     print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_max->cval, range_max->cval);
3055     update_tfsoff( type, start_offset, file );
3056     *typeformat_offset += 10;
3057
3058     return start_offset;
3059 }
3060
3061 static unsigned int write_type_tfs(FILE *file, int indent,
3062                                    const attr_list_t *attrs, type_t *type,
3063                                    const char *name,
3064                                    enum type_context context,
3065                                    unsigned int *typeformat_offset)
3066 {
3067     unsigned int offset;
3068
3069     switch (typegen_detect_type(type, attrs, TDT_ALL_TYPES))
3070     {
3071     case TGT_CTXT_HANDLE:
3072     case TGT_CTXT_HANDLE_POINTER:
3073         return write_contexthandle_tfs(file, attrs, type,
3074                                        context == TYPE_CONTEXT_TOPLEVELPARAM, typeformat_offset);
3075     case TGT_USER_TYPE:
3076         return write_user_tfs(file, type, typeformat_offset);
3077     case TGT_STRING:
3078         return write_string_tfs(file, attrs, type,
3079                                 context == TYPE_CONTEXT_TOPLEVELPARAM,
3080                                 name, typeformat_offset);
3081     case TGT_ARRAY:
3082     {
3083         unsigned int off;
3084         /* conformant and pointer arrays are handled specially */
3085         if ((context != TYPE_CONTEXT_CONTAINER &&
3086              context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) ||
3087             !is_conformant_array(type) || type_array_is_decl_as_ptr(type))
3088             off = write_array_tfs(file, attrs, type, name, typeformat_offset);
3089         else
3090             off = 0;
3091         if (context != TYPE_CONTEXT_CONTAINER &&
3092             context != TYPE_CONTEXT_CONTAINER_NO_POINTERS)
3093         {
3094             int ptr_type;
3095             ptr_type = get_pointer_fc(type, attrs,
3096                                       context == TYPE_CONTEXT_TOPLEVELPARAM);
3097             if (ptr_type != RPC_FC_RP)
3098             {
3099                 unsigned int absoff = type->typestring_offset;
3100                 short reloff = absoff - (*typeformat_offset + 2);
3101                 off = *typeformat_offset;
3102                 print_file(file, 0, "/* %d */\n", off);
3103                 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
3104                            string_of_type(ptr_type));
3105                 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
3106                            reloff, reloff, absoff);
3107                 update_tfsoff( type, off, file );
3108                 *typeformat_offset += 4;
3109             }
3110         }
3111         return off;
3112     }
3113     case TGT_STRUCT:
3114         return write_struct_tfs(file, type, name, typeformat_offset);
3115     case TGT_UNION:
3116         return write_union_tfs(file, attrs, type, typeformat_offset);
3117     case TGT_ENUM:
3118     case TGT_BASIC:
3119         /* nothing to do */
3120         return 0;
3121     case TGT_RANGE:
3122     {
3123         expr_list_t *range_list = get_attrp(attrs, ATTR_RANGE);
3124         if (!range_list)
3125             range_list = get_aliaschain_attrp(type, ATTR_RANGE);
3126         return write_range_tfs(file, attrs, type, range_list, typeformat_offset);
3127     }
3128     case TGT_IFACE_POINTER:
3129         return write_ip_tfs(file, attrs, type, typeformat_offset);
3130     case TGT_POINTER:
3131     {
3132         enum type_context ref_context;
3133         if (context == TYPE_CONTEXT_TOPLEVELPARAM)
3134             ref_context = TYPE_CONTEXT_PARAM;
3135         else if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS)
3136             ref_context = TYPE_CONTEXT_CONTAINER;
3137         else
3138             ref_context = context;
3139         offset = write_type_tfs( file, indent, attrs, type_pointer_get_ref(type), name,
3140                                  ref_context, typeformat_offset);
3141         if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS)
3142             return 0;
3143         return write_pointer_tfs(file, attrs, type, offset,
3144                                  context == TYPE_CONTEXT_TOPLEVELPARAM,
3145                                  typeformat_offset);
3146     }
3147     case TGT_INVALID:
3148         break;
3149     }
3150     error("invalid type %s for var %s\n", type->name, name);
3151     return 0;
3152 }
3153
3154 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
3155                                 const char *name, int write_ptr, unsigned int *tfsoff)
3156 {
3157     return write_type_tfs(file, 2, attrs, type, name, write_ptr ? TYPE_CONTEXT_CONTAINER : TYPE_CONTEXT_CONTAINER_NO_POINTERS, tfsoff);
3158 }
3159
3160 static unsigned int process_tfs_stmts(FILE *file, const statement_list_t *stmts,
3161                                       type_pred_t pred, unsigned int *typeformat_offset)
3162 {
3163     const var_t *var;
3164     const statement_t *stmt;
3165
3166     if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
3167     {
3168         const type_t *iface;
3169         const statement_t *stmt_func;
3170
3171         if (stmt->type == STMT_LIBRARY)
3172         {
3173             process_tfs_stmts(file, stmt->u.lib->stmts, pred, typeformat_offset);
3174             continue;
3175         }
3176         else if (stmt->type != STMT_TYPE || type_get_type(stmt->u.type) != TYPE_INTERFACE)
3177             continue;
3178
3179         iface = stmt->u.type;
3180         if (!pred(iface))
3181             continue;
3182
3183         current_iface = iface;
3184         STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(iface) )
3185         {
3186             const var_t *func = stmt_func->u.var;
3187             current_func = func;
3188             if (is_local(func->attrs)) continue;
3189
3190             if (!is_void(type_function_get_rettype(func->type)))
3191             {
3192                 write_type_tfs( file, 2, func->attrs, type_function_get_rettype(func->type),
3193                                 func->name, TYPE_CONTEXT_PARAM, typeformat_offset);
3194             }
3195
3196             if (type_get_function_args(func->type))
3197                 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
3198                     write_type_tfs( file, 2, var->attrs, var->type, var->name,
3199                                     TYPE_CONTEXT_TOPLEVELPARAM, typeformat_offset );
3200         }
3201     }
3202
3203     return *typeformat_offset + 1;
3204 }
3205
3206 static unsigned int process_tfs(FILE *file, const statement_list_t *stmts, type_pred_t pred)
3207 {
3208     unsigned int typeformat_offset = 2;
3209
3210     return process_tfs_stmts(file, stmts, pred, &typeformat_offset);
3211 }
3212
3213
3214 void write_typeformatstring(FILE *file, const statement_list_t *stmts, type_pred_t pred)
3215 {
3216     int indent = 0;
3217
3218     print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
3219     print_file(file, indent, "{\n");
3220     indent++;
3221     print_file(file, indent, "0,\n");
3222     print_file(file, indent, "{\n");
3223     indent++;
3224     print_file(file, indent, "NdrFcShort(0x0),\n");
3225
3226     set_all_tfswrite(TRUE);
3227     process_tfs(file, stmts, pred);
3228
3229     print_file(file, indent, "0x0\n");
3230     indent--;
3231     print_file(file, indent, "}\n");
3232     indent--;
3233     print_file(file, indent, "};\n");
3234     print_file(file, indent, "\n");
3235 }
3236
3237 static unsigned int get_required_buffer_size_type(
3238     const type_t *type, const char *name, const attr_list_t *attrs, int toplevel_param, unsigned int *alignment)
3239 {
3240     *alignment = 0;
3241     switch (typegen_detect_type(type, NULL, TDT_IGNORE_RANGES))
3242     {
3243     case TGT_USER_TYPE:
3244     {
3245         const char *uname;
3246         const type_t *utype = get_user_type(type, &uname);
3247         return get_required_buffer_size_type(utype, uname, NULL, FALSE, alignment);
3248     }
3249     case TGT_BASIC:
3250         switch (get_basic_fc(type))
3251         {
3252         case RPC_FC_BYTE:
3253         case RPC_FC_CHAR:
3254         case RPC_FC_USMALL:
3255         case RPC_FC_SMALL:
3256             *alignment = 4;
3257             return 1;
3258
3259         case RPC_FC_WCHAR:
3260         case RPC_FC_USHORT:
3261         case RPC_FC_SHORT:
3262             *alignment = 4;
3263             return 2;
3264
3265         case RPC_FC_ULONG:
3266         case RPC_FC_LONG:
3267         case RPC_FC_FLOAT:
3268         case RPC_FC_ERROR_STATUS_T:
3269             *alignment = 4;
3270             return 4;
3271
3272         case RPC_FC_HYPER:
3273         case RPC_FC_DOUBLE:
3274             *alignment = 8;
3275             return 8;
3276
3277         case RPC_FC_INT3264:
3278         case RPC_FC_UINT3264:
3279             assert( pointer_size );
3280             *alignment = pointer_size;
3281             return pointer_size;
3282
3283         case RPC_FC_IGNORE:
3284         case RPC_FC_BIND_PRIMITIVE:
3285             return 0;
3286
3287         default:
3288             error("get_required_buffer_size: unknown basic type 0x%02x\n",
3289                   get_basic_fc(type));
3290             return 0;
3291         }
3292         break;
3293
3294     case TGT_ENUM:
3295         switch (get_enum_fc(type))
3296         {
3297         case RPC_FC_ENUM32:
3298             *alignment = 4;
3299             return 4;
3300         case RPC_FC_ENUM16:
3301             *alignment = 4;
3302             return 2;
3303         }
3304         break;
3305
3306     case TGT_STRUCT:
3307         if (get_struct_fc(type) == RPC_FC_STRUCT)
3308         {
3309             if (!type_struct_get_fields(type)) return 0;
3310             return fields_memsize(type_struct_get_fields(type), alignment);
3311         }
3312         break;
3313
3314     case TGT_POINTER:
3315         {
3316             unsigned int size, align;
3317             const type_t *ref = type_pointer_get_ref(type);
3318             if (is_string_type( attrs, ref )) break;
3319             if (!(size = get_required_buffer_size_type( ref, name, NULL, FALSE, &align ))) break;
3320             if (get_pointer_fc(type, attrs, toplevel_param) != RPC_FC_RP)
3321             {
3322                 size += 4 + align;
3323                 align = 4;
3324             }
3325             *alignment = align;
3326             return size;
3327         }
3328
3329     case TGT_ARRAY:
3330         if (get_pointer_fc(type, attrs, toplevel_param) == RPC_FC_RP)
3331         {
3332             switch (get_array_fc(type))
3333             {
3334             case RPC_FC_SMFARRAY:
3335             case RPC_FC_LGFARRAY:
3336                 return type_array_get_dim(type) *
3337                     get_required_buffer_size_type(type_array_get_element(type), name,
3338                                                   NULL, FALSE, alignment);
3339             }
3340         }
3341         break;
3342
3343     default:
3344         break;
3345     }
3346     return 0;
3347 }
3348
3349 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
3350 {
3351     int in_attr = is_attr(var->attrs, ATTR_IN);
3352     int out_attr = is_attr(var->attrs, ATTR_OUT);
3353
3354     if (!in_attr && !out_attr)
3355         in_attr = 1;
3356
3357     *alignment = 0;
3358
3359     if ((pass == PASS_IN && in_attr) || (pass == PASS_OUT && out_attr) ||
3360         pass == PASS_RETURN)
3361     {
3362         if (is_ptrchain_attr(var, ATTR_CONTEXTHANDLE))
3363         {
3364             *alignment = 4;
3365             return 20;
3366         }
3367
3368         if (!is_string_type(var->attrs, var->type))
3369             return get_required_buffer_size_type(var->type, var->name,
3370                                                  var->attrs, TRUE, alignment);
3371     }
3372     return 0;
3373 }
3374
3375 static unsigned int get_function_buffer_size( const var_t *func, enum pass pass )
3376 {
3377     const var_t *var;
3378     unsigned int total_size = 0, alignment;
3379
3380     if (type_get_function_args(func->type))
3381     {
3382         LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
3383         {
3384             total_size += get_required_buffer_size(var, &alignment, pass);
3385             total_size += alignment;
3386         }
3387     }
3388
3389     if (pass == PASS_OUT && !is_void(type_function_get_rettype(func->type)))
3390     {
3391         var_t v = *func;
3392         v.type = type_function_get_rettype(func->type);
3393         total_size += get_required_buffer_size(&v, &alignment, PASS_RETURN);
3394         total_size += alignment;
3395     }
3396     return total_size;
3397 }
3398
3399 static void print_phase_function(FILE *file, int indent, const char *type,
3400                                  const char *local_var_prefix, enum remoting_phase phase,
3401                                  const var_t *var, unsigned int type_offset)
3402 {
3403     const char *function;
3404     switch (phase)
3405     {
3406     case PHASE_BUFFERSIZE:
3407         function = "BufferSize";
3408         break;
3409     case PHASE_MARSHAL:
3410         function = "Marshall";
3411         break;
3412     case PHASE_UNMARSHAL:
3413         function = "Unmarshall";
3414         break;
3415     case PHASE_FREE:
3416         function = "Free";
3417         break;
3418     default:
3419         assert(0);
3420         return;
3421     }
3422
3423     print_file(file, indent, "Ndr%s%s(\n", type, function);
3424     indent++;
3425     print_file(file, indent, "&__frame->_StubMsg,\n");
3426     print_file(file, indent, "%s%s%s%s%s,\n",
3427                (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
3428                (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
3429                local_var_prefix,
3430                (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
3431                var->name);
3432     print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
3433                type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
3434     if (phase == PHASE_UNMARSHAL)
3435         print_file(file, indent, "0);\n");
3436     indent--;
3437 }
3438
3439 void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix,
3440                           enum remoting_phase phase, enum pass pass, const var_t *var,
3441                           const char *varname)
3442 {
3443     type_t *type = var->type;
3444     unsigned int alignment = 0;
3445
3446     /* no work to do for other phases, buffer sizing is done elsewhere */
3447     if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
3448         return;
3449
3450     if (type_get_type(type) == TYPE_ENUM ||
3451         (type_get_type(type) == TYPE_BASIC &&
3452          type_basic_get_type(type) == TYPE_BASIC_INT3264 &&
3453          pointer_size != 4))
3454     {
3455         unsigned char fc;
3456
3457         if (type_get_type(type) == TYPE_ENUM)
3458             fc = get_enum_fc(type);
3459         else
3460             fc = get_basic_fc(type);
3461
3462         if (phase == PHASE_MARSHAL)
3463             print_file(file, indent, "NdrSimpleTypeMarshall(\n");
3464         else
3465             print_file(file, indent, "NdrSimpleTypeUnmarshall(\n");
3466         print_file(file, indent+1, "&__frame->_StubMsg,\n");
3467         print_file(file, indent+1, "(unsigned char *)&%s%s,\n",
3468                    local_var_prefix,
3469                    var->name);
3470         print_file(file, indent+1, "0x%02x /* %s */);\n", fc, string_of_type(fc));
3471     }
3472     else
3473     {
3474         const type_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : type;
3475         switch (get_basic_fc(ref))
3476         {
3477         case RPC_FC_BYTE:
3478         case RPC_FC_CHAR:
3479         case RPC_FC_SMALL:
3480         case RPC_FC_USMALL:
3481             alignment = 1;
3482             break;
3483
3484         case RPC_FC_WCHAR:
3485         case RPC_FC_USHORT:
3486         case RPC_FC_SHORT:
3487             alignment = 2;
3488             break;
3489
3490         case RPC_FC_ULONG:
3491         case RPC_FC_LONG:
3492         case RPC_FC_FLOAT:
3493         case RPC_FC_ERROR_STATUS_T:
3494         /* pointer_size must be 4 if we got here in these two cases */
3495         case RPC_FC_INT3264:
3496         case RPC_FC_UINT3264:
3497             alignment = 4;
3498             break;
3499
3500         case RPC_FC_HYPER:
3501         case RPC_FC_DOUBLE:
3502             alignment = 8;
3503             break;
3504
3505         case RPC_FC_IGNORE:
3506         case RPC_FC_BIND_PRIMITIVE:
3507             /* no marshalling needed */
3508             return;
3509
3510         default:
3511             error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n",
3512                   var->name, get_basic_fc(ref));
3513         }
3514
3515         if (phase == PHASE_MARSHAL && alignment > 1)
3516             print_file(file, indent, "MIDL_memset(__frame->_StubMsg.Buffer, 0, (0x%x - (ULONG_PTR)__frame->_StubMsg.Buffer) & 0x%x);\n", alignment, alignment - 1);
3517         print_file(file, indent, "__frame->_StubMsg.Buffer = (unsigned char *)(((ULONG_PTR)__frame->_StubMsg.Buffer + %u) & ~0x%x);\n",
3518                     alignment - 1, alignment - 1);
3519
3520         if (phase == PHASE_MARSHAL)
3521         {
3522             print_file(file, indent, "*(");
3523             write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL);
3524             if (is_ptr(type))
3525                 fprintf(file, " *)__frame->_StubMsg.Buffer = *");
3526             else
3527                 fprintf(file, " *)__frame->_StubMsg.Buffer = ");
3528             fprintf(file, "%s%s", local_var_prefix, varname);
3529             fprintf(file, ";\n");
3530         }
3531         else if (phase == PHASE_UNMARSHAL)
3532         {
3533             print_file(file, indent, "if (__frame->_StubMsg.Buffer + sizeof(");
3534             write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL);
3535             fprintf(file, ") > __frame->_StubMsg.BufferEnd)\n");
3536             print_file(file, indent, "{\n");
3537             print_file(file, indent + 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
3538             print_file(file, indent, "}\n");
3539             print_file(file, indent, "%s%s%s",
3540                        (pass == PASS_IN || pass == PASS_RETURN) ? "" : "*",
3541                        local_var_prefix, varname);
3542             if (pass == PASS_IN && is_ptr(type))
3543                 fprintf(file, " = (");
3544             else
3545                 fprintf(file, " = *(");
3546             write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL);
3547             fprintf(file, " *)__frame->_StubMsg.Buffer;\n");
3548         }
3549
3550         print_file(file, indent, "__frame->_StubMsg.Buffer += sizeof(");
3551         write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL);
3552         fprintf(file, ");\n");
3553     }
3554 }
3555
3556 /* returns whether the MaxCount, Offset or ActualCount members need to be
3557  * filled in for the specified phase */
3558 static inline int is_conformance_needed_for_phase(enum remoting_phase phase)
3559 {
3560     return (phase != PHASE_UNMARSHAL);
3561 }
3562
3563 expr_t *get_size_is_expr(const type_t *t, const char *name)
3564 {
3565     expr_t *x = NULL;
3566
3567     for ( ; is_array(t); t = type_array_get_element(t))
3568         if (type_array_has_conformance(t) &&
3569             type_array_get_conformance(t)->type != EXPR_VOID)
3570         {
3571             if (!x)
3572                 x = type_array_get_conformance(t);
3573             else
3574                 error("%s: multidimensional conformant"
3575                       " arrays not supported at the top level\n",
3576                       name);
3577         }
3578
3579     return x;
3580 }
3581
3582 static void write_parameter_conf_or_var_exprs(FILE *file, int indent, const char *local_var_prefix,
3583                                               enum remoting_phase phase, const var_t *var)
3584 {
3585     const type_t *type = var->type;
3586     /* get fundamental type for the argument */
3587     for (;;)
3588     {
3589         switch (typegen_detect_type(type, var->attrs, TDT_IGNORE_STRINGS|TDT_IGNORE_RANGES))
3590         {
3591         case TGT_ARRAY:
3592             if (is_conformance_needed_for_phase(phase))
3593             {
3594                 if (type_array_has_conformance(type) &&
3595                     type_array_get_conformance(type)->type != EXPR_VOID)
3596                 {
3597                     print_file(file, indent, "__frame->_StubMsg.MaxCount = (ULONG_PTR)");
3598                     write_expr(file, type_array_get_conformance(type), 1, 1, NULL, NULL, local_var_prefix);
3599                     fprintf(file, ";\n\n");
3600                 }
3601                 if (type_array_has_variance(type))
3602                 {
3603                     print_file(file, indent, "__frame->_StubMsg.Offset = 0;\n"); /* FIXME */
3604                     print_file(file, indent, "__frame->_StubMsg.ActualCount = (ULONG_PTR)");
3605                     write_expr(file, type_array_get_variance(type), 1, 1, NULL, NULL, local_var_prefix);
3606                     fprintf(file, ";\n\n");
3607                 }
3608             }
3609             break;
3610         case TGT_UNION:
3611             if (type_get_type(type) == TYPE_UNION &&
3612                 is_conformance_needed_for_phase(phase))
3613             {
3614                 print_file(file, indent, "__frame->_StubMsg.MaxCount = (ULONG_PTR)");
3615                 write_expr(file, get_attrp(var->attrs, ATTR_SWITCHIS), 1, 1, NULL, NULL, local_var_prefix);
3616                 fprintf(file, ";\n\n");
3617             }
3618             break;
3619         case TGT_IFACE_POINTER:
3620         {
3621             expr_t *iid;
3622
3623             if (is_conformance_needed_for_phase(phase) && (iid = get_attrp( var->attrs, ATTR_IIDIS )))
3624             {
3625                 print_file( file, indent, "__frame->_StubMsg.MaxCount = (ULONG_PTR) " );
3626                 write_expr( file, iid, 1, 1, NULL, NULL, local_var_prefix );
3627                 fprintf( file, ";\n\n" );
3628             }
3629             break;
3630         }
3631         case TGT_POINTER:
3632             type = type_pointer_get_ref(type);
3633             continue;
3634         case TGT_INVALID:
3635         case TGT_USER_TYPE:
3636         case TGT_CTXT_HANDLE:
3637         case TGT_CTXT_HANDLE_POINTER:
3638         case TGT_STRING:
3639         case TGT_BASIC:
3640         case TGT_ENUM:
3641         case TGT_STRUCT:
3642         case TGT_RANGE:
3643             break;
3644         }
3645         break;
3646     }
3647 }
3648
3649 static void write_remoting_arg(FILE *file, int indent, const var_t *func, const char *local_var_prefix,
3650                                enum pass pass, enum remoting_phase phase, const var_t *var)
3651 {
3652     int in_attr, out_attr, pointer_type;
3653     const char *type_str = NULL;
3654     const type_t *type = var->type;
3655     unsigned int alignment, start_offset = type->typestring_offset;
3656
3657     if (is_ptr(type) || is_array(type))
3658         pointer_type = get_pointer_fc(type, var->attrs, pass != PASS_RETURN);
3659     else
3660         pointer_type = 0;
3661
3662     in_attr = is_attr(var->attrs, ATTR_IN);
3663     out_attr = is_attr(var->attrs, ATTR_OUT);
3664     if (!in_attr && !out_attr)
3665         in_attr = 1;
3666
3667     if (phase != PHASE_FREE)
3668         switch (pass)
3669         {
3670         case PASS_IN:
3671             if (!in_attr) return;
3672             break;
3673         case PASS_OUT:
3674             if (!out_attr) return;
3675             break;
3676         case PASS_RETURN:
3677             break;
3678         }
3679
3680     if (phase == PHASE_BUFFERSIZE && get_required_buffer_size( var, &alignment, pass )) return;
3681
3682     write_parameter_conf_or_var_exprs(file, indent, local_var_prefix, phase, var);
3683
3684     switch (typegen_detect_type(type, var->attrs, TDT_ALL_TYPES))
3685     {
3686     case TGT_CTXT_HANDLE:
3687     case TGT_CTXT_HANDLE_POINTER:
3688         if (phase == PHASE_MARSHAL)
3689         {
3690             if (pass == PASS_IN)
3691             {
3692                 /* if the context_handle attribute appears in the chain of types
3693                  * without pointers being followed, then the context handle must
3694                  * be direct, otherwise it is a pointer */
3695                 int is_ch_ptr = is_aliaschain_attr(type, ATTR_CONTEXTHANDLE) ? FALSE : TRUE;
3696                 print_file(file, indent, "NdrClientContextMarshall(\n");
3697                 print_file(file, indent + 1, "&__frame->_StubMsg,\n");
3698                 print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s%s,\n", is_ch_ptr ? "*" : "", local_var_prefix, var->name);
3699                 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0");
3700             }
3701             else
3702             {
3703                 print_file(file, indent, "NdrServerContextNewMarshall(\n");
3704                 print_file(file, indent + 1, "&__frame->_StubMsg,\n");
3705                 print_file(file, indent + 1, "(NDR_SCONTEXT)%s%s,\n", local_var_prefix, var->name);
3706                 print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var->type));
3707                 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset);
3708             }
3709         }
3710         else if (phase == PHASE_UNMARSHAL)
3711         {
3712             if (pass == PASS_OUT)
3713             {
3714                 if (!in_attr)
3715                     print_file(file, indent, "*%s%s = 0;\n", local_var_prefix, var->name);
3716                 print_file(file, indent, "NdrClientContextUnmarshall(\n");
3717                 print_file(file, indent + 1, "&__frame->_StubMsg,\n");
3718                 print_file(file, indent + 1, "(NDR_CCONTEXT *)%s%s,\n", local_var_prefix, var->name);
3719                 print_file(file, indent + 1, "__frame->_Handle);\n");
3720             }
3721             else
3722             {
3723                 print_file(file, indent, "%s%s = NdrServerContextNewUnmarshall(\n", local_var_prefix, var->name);
3724                 print_file(file, indent + 1, "&__frame->_StubMsg,\n");
3725                 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset);
3726             }
3727         }
3728         break;
3729     case TGT_USER_TYPE:
3730         print_phase_function(file, indent, "UserMarshal", local_var_prefix, phase, var, start_offset);
3731         break;
3732     case TGT_STRING:
3733         if (phase == PHASE_FREE || pass == PASS_RETURN ||
3734             pointer_type != RPC_FC_RP)
3735         {
3736             if (pointer_type == RPC_FC_RP && phase == PHASE_FREE &&
3737                 !in_attr && is_conformant_array(type))
3738             {
3739                 print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name);
3740                 indent++;
3741                 print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name);
3742             }
3743             /* strings returned are assumed to be global and hence don't
3744              * need freeing */
3745             else if (is_declptr(type) &&
3746                      !(phase == PHASE_FREE && pass == PASS_RETURN))
3747                 print_phase_function(file, indent, "Pointer", local_var_prefix,
3748                                      phase, var, start_offset);
3749         }
3750         else
3751         {
3752             unsigned int real_start_offset = start_offset;
3753             /* skip over pointer description straight to string description */
3754             if (is_declptr(type))
3755             {
3756                 if (is_conformant_array(type))
3757                     real_start_offset += 4;
3758                 else
3759                     real_start_offset += 2;
3760             }
3761             if (is_array(type) && !is_conformant_array(type))
3762                 print_phase_function(file, indent, "NonConformantString",
3763                                      local_var_prefix, phase, var,
3764                                      real_start_offset);
3765             else
3766                 print_phase_function(file, indent, "ConformantString", local_var_prefix,
3767                                      phase, var, real_start_offset);
3768         }
3769         break;
3770     case TGT_ARRAY:
3771     {
3772         unsigned char tc = get_array_fc(type);
3773         const char *array_type = NULL;
3774
3775         /* We already have the size_is expression since it's at the
3776            top level, but do checks for multidimensional conformant
3777            arrays.  When we handle them, we'll need to extend this
3778            function to return a list, and then we'll actually use
3779            the return value.  */
3780         get_size_is_expr(type, var->name);
3781
3782         switch (tc)
3783         {
3784         case RPC_FC_SMFARRAY:
3785         case RPC_FC_LGFARRAY:
3786             array_type = "FixedArray";
3787             break;
3788         case RPC_FC_SMVARRAY:
3789         case RPC_FC_LGVARRAY:
3790             array_type = "VaryingArray";
3791             break;
3792         case RPC_FC_CARRAY:
3793             array_type = "ConformantArray";
3794             break;
3795         case RPC_FC_CVARRAY:
3796             array_type = "ConformantVaryingArray";
3797             break;
3798         case RPC_FC_BOGUS_ARRAY:
3799             array_type = "ComplexArray";
3800             break;
3801         }
3802
3803         if (pointer_type != RPC_FC_RP) array_type = "Pointer";
3804         print_phase_function(file, indent, array_type, local_var_prefix, phase, var, start_offset);
3805         if (phase == PHASE_FREE && pointer_type == RPC_FC_RP)
3806         {
3807             /* these are all unmarshalled by allocating memory */
3808             if (tc == RPC_FC_BOGUS_ARRAY ||
3809                 tc == RPC_FC_CVARRAY ||
3810                 ((tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY) && in_attr) ||
3811                 (tc == RPC_FC_CARRAY && !in_attr))
3812             {
3813                 print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name);
3814                 indent++;
3815                 print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name);
3816             }
3817         }
3818         break;
3819     }
3820     case TGT_BASIC:
3821         print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name);
3822         break;
3823     case TGT_ENUM:
3824         print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name);
3825         break;
3826     case TGT_RANGE:
3827         print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name);
3828         /* Note: this goes beyond what MIDL does - it only supports arguments
3829          * with the [range] attribute in Oicf mode */
3830         if (phase == PHASE_UNMARSHAL)
3831         {
3832             const expr_t *range_min;
3833             const expr_t *range_max;
3834             expr_list_t *range_list = get_attrp(var->attrs, ATTR_RANGE);
3835             if (!range_list)
3836                 range_list = get_aliaschain_attrp(type, ATTR_RANGE);
3837             range_min = LIST_ENTRY(list_head(range_list), const expr_t, entry);
3838             range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry);
3839
3840             print_file(file, indent, "if ((%s%s < (", local_var_prefix, var->name);
3841             write_type_decl(file, var->type, NULL);
3842             fprintf(file, ")0x%x) || (%s%s > (", range_min->cval, local_var_prefix, var->name);
3843             write_type_decl(file, var->type, NULL);
3844             fprintf(file, ")0x%x))\n", range_max->cval);
3845             print_file(file, indent, "{\n");
3846             print_file(file, indent+1, "RpcRaiseException(RPC_S_INVALID_BOUND);\n");
3847             print_file(file, indent, "}\n");
3848         }
3849         break;
3850     case TGT_STRUCT:
3851         switch (get_struct_fc(type))
3852         {
3853         case RPC_FC_STRUCT:
3854             if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL)
3855                 print_phase_function(file, indent, "SimpleStruct", local_var_prefix, phase, var, start_offset);
3856             break;
3857         case RPC_FC_PSTRUCT:
3858             print_phase_function(file, indent, "SimpleStruct", local_var_prefix, phase, var, start_offset);
3859             break;
3860         case RPC_FC_CSTRUCT:
3861         case RPC_FC_CPSTRUCT:
3862             print_phase_function(file, indent, "ConformantStruct", local_var_prefix, phase, var, start_offset);
3863             break;
3864         case RPC_FC_CVSTRUCT:
3865             print_phase_function(file, indent, "ConformantVaryingStruct", local_var_prefix, phase, var, start_offset);
3866             break;
3867         case RPC_FC_BOGUS_STRUCT:
3868             print_phase_function(file, indent, "ComplexStruct", local_var_prefix, phase, var, start_offset);
3869             break;
3870         default:
3871             error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, get_struct_fc(type));
3872         }
3873         break;
3874     case TGT_UNION:
3875     {
3876         const char *union_type = NULL;
3877
3878         if (type_get_type(type) == TYPE_UNION)
3879             union_type = "NonEncapsulatedUnion";
3880         else if (type_get_type(type) == TYPE_ENCAPSULATED_UNION)
3881             union_type = "EncapsulatedUnion";
3882
3883         print_phase_function(file, indent, union_type, local_var_prefix,
3884                              phase, var, start_offset);
3885         break;
3886     }
3887     case TGT_POINTER:
3888     {
3889         const type_t *ref = type_pointer_get_ref(type);
3890         if (pointer_type == RPC_FC_RP) switch (typegen_detect_type(ref, NULL, TDT_ALL_TYPES))
3891         {
3892         case TGT_BASIC:
3893             print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name);
3894             break;
3895         case TGT_ENUM:
3896             /* base types have known sizes, so don't need a sizing pass
3897              * and don't have any memory to free and so don't need a
3898              * freeing pass */
3899             if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL)
3900                 print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset);
3901             break;
3902         case TGT_STRUCT:
3903             switch (get_struct_fc(ref))
3904             {
3905             case RPC_FC_STRUCT:
3906                 /* simple structs have known sizes, so don't need a sizing
3907                  * pass and don't have any memory to free and so don't
3908                  * need a freeing pass */
3909                 if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL)
3910                     type_str = "SimpleStruct";
3911                 else if (phase == PHASE_FREE && pass == PASS_RETURN)
3912                 {
3913                     print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name);
3914                     indent++;
3915                     print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name);
3916                     indent--;
3917                 }
3918                 break;
3919             case RPC_FC_PSTRUCT:
3920                 type_str = "SimpleStruct";
3921                 break;
3922             case RPC_FC_CSTRUCT:
3923             case RPC_FC_CPSTRUCT:
3924                 type_str = "ConformantStruct";
3925                 break;
3926             case RPC_FC_CVSTRUCT:
3927                 type_str = "ConformantVaryingStruct";
3928                 break;
3929             case RPC_FC_BOGUS_STRUCT:
3930                 type_str = "ComplexStruct";
3931                 break;
3932             default:
3933                 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, get_struct_fc(ref));
3934             }
3935
3936             if (type_str)
3937             {
3938                 if (phase == PHASE_FREE)
3939                     type_str = "Pointer";
3940                 else
3941                     start_offset = ref->typestring_offset;
3942                 print_phase_function(file, indent, type_str, local_var_prefix, phase, var, start_offset);
3943             }
3944             break;
3945         case TGT_UNION:
3946             if (phase == PHASE_FREE)
3947                 type_str = "Pointer";
3948             else
3949             {
3950                 if (type_get_type(ref) == TYPE_UNION)
3951                     type_str = "NonEncapsulatedUnion";
3952                 else if (type_get_type(ref) == TYPE_ENCAPSULATED_UNION)
3953                     type_str = "EncapsulatedUnion";
3954
3955                 start_offset = ref->typestring_offset;
3956             }
3957
3958             print_phase_function(file, indent, type_str, local_var_prefix,
3959                                  phase, var, start_offset);
3960             break;
3961         case TGT_USER_TYPE:
3962             if (phase != PHASE_FREE)
3963             {
3964                 type_str = "UserMarshal";
3965                 start_offset = ref->typestring_offset;
3966             }
3967             else type_str = "Pointer";
3968
3969             print_phase_function(file, indent, type_str, local_var_prefix, phase, var, start_offset);
3970             break;
3971         case TGT_STRING:
3972         case TGT_POINTER:
3973         case TGT_ARRAY:
3974         case TGT_RANGE:
3975         case TGT_IFACE_POINTER:
3976         case TGT_CTXT_HANDLE:
3977         case TGT_CTXT_HANDLE_POINTER:
3978             print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset);
3979             break;
3980         case TGT_INVALID:
3981             assert(0);
3982             break;
3983         }
3984         else
3985             print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset);
3986         break;
3987     }
3988     case TGT_IFACE_POINTER:
3989         print_phase_function(file, indent, "InterfacePointer", local_var_prefix, phase, var, start_offset);
3990         break;
3991     case TGT_INVALID:
3992         assert(0);
3993         break;
3994     }
3995     fprintf(file, "\n");
3996 }
3997
3998 void write_remoting_arguments(FILE *file, int indent, const var_t *func, const char *local_var_prefix,
3999                               enum pass pass, enum remoting_phase phase)
4000 {
4001     if (phase == PHASE_BUFFERSIZE && pass != PASS_RETURN)
4002     {
4003         unsigned int size = get_function_buffer_size( func, pass );
4004         print_file(file, indent, "__frame->_StubMsg.BufferLength = %u;\n", size);
4005     }
4006
4007     if (pass == PASS_RETURN)
4008     {
4009         var_t var;
4010         var = *func;
4011         var.type = type_function_get_rettype(func->type);
4012         var.name = xstrdup( "_RetVal" );
4013         write_remoting_arg( file, indent, func, local_var_prefix, pass, phase, &var );
4014         free( var.name );
4015     }
4016     else
4017     {
4018         const var_t *var;
4019         if (!type_get_function_args(func->type))
4020             return;
4021         LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
4022             write_remoting_arg( file, indent, func, local_var_prefix, pass, phase, var );
4023     }
4024 }
4025
4026
4027 unsigned int get_size_procformatstring_func(const var_t *func)
4028 {
4029     unsigned int offset = 0;
4030     write_procformatstring_func( NULL, 0, func, &offset );
4031     return offset;
4032 }
4033
4034 unsigned int get_size_procformatstring(const statement_list_t *stmts, type_pred_t pred)
4035 {
4036     const statement_t *stmt;
4037     unsigned int size = 1;
4038
4039     if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
4040     {
4041         const type_t *iface;
4042         const statement_t *stmt_func;
4043
4044         if (stmt->type == STMT_LIBRARY)
4045         {
4046             size += get_size_procformatstring(stmt->u.lib->stmts, pred) - 1;
4047             continue;
4048         }
4049         else if (stmt->type != STMT_TYPE || type_get_type(stmt->u.type) != TYPE_INTERFACE)
4050             continue;
4051
4052         iface = stmt->u.type;
4053         if (!pred(iface))
4054             continue;
4055
4056         STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(iface) )
4057         {
4058             const var_t *func = stmt_func->u.var;
4059             if (!is_local(func->attrs))
4060                 size += get_size_procformatstring_func( func );
4061         }
4062     }
4063     return size;
4064 }
4065
4066 unsigned int get_size_typeformatstring(const statement_list_t *stmts, type_pred_t pred)
4067 {
4068     set_all_tfswrite(FALSE);
4069     return process_tfs(NULL, stmts, pred);
4070 }
4071
4072 void declare_stub_args( FILE *file, int indent, const var_t *func )
4073 {
4074     int in_attr, out_attr;
4075     int i = 0;
4076     const var_t *var;
4077
4078     /* declare return value '_RetVal' */
4079     if (!is_void(type_function_get_rettype(func->type)))
4080     {
4081         print_file(file, indent, "%s", "");
4082         write_type_decl_left(file, type_function_get_rettype(func->type));
4083         fprintf(file, " _RetVal;\n");
4084     }
4085
4086     if (!type_get_function_args(func->type))
4087         return;
4088
4089     LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
4090     {
4091         in_attr = is_attr(var->attrs, ATTR_IN);
4092         out_attr = is_attr(var->attrs, ATTR_OUT);
4093         if (!out_attr && !in_attr)
4094             in_attr = 1;
4095
4096         if (is_context_handle(var->type))
4097             print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name);
4098         else
4099         {
4100             if (!in_attr && !is_conformant_array(var->type))
4101             {
4102                 type_t *type_to_print;
4103                 char name[16];
4104                 print_file(file, indent, "%s", "");
4105                 if (type_get_type(var->type) == TYPE_ARRAY &&
4106                     !type_array_is_decl_as_ptr(var->type))
4107                     type_to_print = var->type;
4108                 else
4109                     type_to_print = type_pointer_get_ref(var->type);
4110                 sprintf(name, "_W%u", i++);
4111                 write_type_decl(file, type_to_print, name);
4112                 fprintf(file, ";\n");
4113             }
4114
4115             print_file(file, indent, "%s", "");
4116             write_type_decl_left(file, var->type);
4117             fprintf(file, " ");
4118             if (type_get_type(var->type) == TYPE_ARRAY &&
4119                 !type_array_is_decl_as_ptr(var->type)) {
4120                 fprintf(file, "(*%s)", var->name);
4121             } else
4122                 fprintf(file, "%s", var->name);
4123             write_type_right(file, var->type, FALSE);
4124             fprintf(file, ";\n");
4125
4126             if (decl_indirect(var->type))
4127                 print_file(file, indent, "void *_p_%s;\n", var->name);
4128         }
4129     }
4130 }
4131
4132
4133 void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char *local_var_prefix )
4134 {
4135     int in_attr, out_attr;
4136     int i = 0, sep = 0;
4137     const var_t *var;
4138
4139     if (!type_get_function_args(func->type))
4140         return;
4141
4142     LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
4143     {
4144         in_attr = is_attr(var->attrs, ATTR_IN);
4145         out_attr = is_attr(var->attrs, ATTR_OUT);
4146         if (!out_attr && !in_attr)
4147             in_attr = 1;
4148
4149         if (!in_attr)
4150         {
4151             print_file(file, indent, "%s%s", local_var_prefix, var->name);
4152
4153             switch (typegen_detect_type(var->type, var->attrs, TDT_IGNORE_STRINGS))
4154             {
4155             case TGT_CTXT_HANDLE_POINTER:
4156                 fprintf(file, " = NdrContextHandleInitialize(\n");
4157                 print_file(file, indent + 1, "&__frame->_StubMsg,\n");
4158                 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n",
4159                            var->type->typestring_offset);
4160                 break;
4161             case TGT_ARRAY:
4162                 if (type_array_has_conformance(var->type))
4163                 {
4164                     unsigned int size;
4165                     type_t *type;
4166
4167                     fprintf(file, " = NdrAllocate(&__frame->_StubMsg, ");
4168                     for (type = var->type;
4169                          is_array(type) && type_array_has_conformance(type);
4170                          type = type_array_get_element(type))
4171                     {
4172                         write_expr(file, type_array_get_conformance(type), TRUE,
4173                                    TRUE, NULL, NULL, local_var_prefix);
4174                         fprintf(file, " * ");
4175                     }
4176                     size = type_memsize(type);
4177                     fprintf(file, "%u);\n", size);
4178
4179                     print_file(file, indent, "memset(%s%s, 0, ", local_var_prefix, var->name);
4180                     for (type = var->type;
4181                          is_array(type) && type_array_has_conformance(type);
4182                          type = type_array_get_element(type))
4183                     {
4184                         write_expr(file, type_array_get_conformance(type), TRUE,
4185                                    TRUE, NULL, NULL, local_var_prefix);
4186                         fprintf(file, " * ");
4187                     }
4188                     size = type_memsize(type);
4189                     fprintf(file, "%u);\n", size);
4190                 }
4191                 else
4192                     fprintf(file, " = &%s_W%u;\n", local_var_prefix, i++);
4193                 break;
4194             case TGT_POINTER:
4195                 fprintf(file, " = &%s_W%u;\n", local_var_prefix, i);
4196                 switch (typegen_detect_type(type_pointer_get_ref(var->type), var->attrs, TDT_IGNORE_STRINGS))
4197                 {
4198                 case TGT_BASIC:
4199                 case TGT_ENUM:
4200                 case TGT_POINTER:
4201                 case TGT_RANGE:
4202                 case TGT_IFACE_POINTER:
4203                     print_file(file, indent, "%s_W%u = 0;\n", local_var_prefix, i);
4204                     break;
4205                 case TGT_USER_TYPE:
4206                     print_file(file, indent, "memset(&%s_W%u, 0, sizeof(%s_W%u));\n",
4207                                local_var_prefix, i, local_var_prefix, i);
4208                     break;
4209                 case TGT_STRUCT:
4210                 case TGT_UNION:
4211                 case TGT_ARRAY:
4212                 case TGT_CTXT_HANDLE:
4213                 case TGT_CTXT_HANDLE_POINTER:
4214                 case TGT_INVALID:
4215                 case TGT_STRING:
4216                     /* not initialised */
4217                     break;
4218                 }
4219                 i++;
4220                 break;
4221             default:
4222                 break;
4223             }
4224
4225             sep = 1;
4226         }
4227     }
4228     if (sep)
4229         fprintf(file, "\n");
4230 }
4231
4232
4233 int write_expr_eval_routines(FILE *file, const char *iface)
4234 {
4235     static const char *var_name = "pS";
4236     static const char *var_name_expr = "pS->";
4237     int result = 0;
4238     struct expr_eval_routine *eval;
4239     unsigned short callback_offset = 0;
4240
4241     LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry)
4242     {
4243         const char *name = eval->name;
4244         result = 1;
4245
4246         print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n",
4247                    iface, name, callback_offset);
4248         print_file(file, 0, "{\n");
4249         if (type_get_type( eval->cont_type ) == TYPE_FUNCTION)
4250         {
4251             const var_list_t *args = type_get_function_args( eval->cont_type );
4252             const var_t *arg;
4253
4254             print_file(file, 1, "struct _PARAM_STRUCT\n" );
4255             print_file(file, 1, "{\n" );
4256             if (is_object( eval->iface )) print_file(file, 2, "%s *This;\n", eval->iface->name );
4257
4258             if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
4259             {
4260                 print_file(file, 2, "%s", "");
4261                 write_type_left( file, (type_t *)arg->type, TRUE );
4262                 if (needs_space_after( arg->type )) fputc( ' ', file );
4263                 if (is_array( arg->type ) && !type_array_is_decl_as_ptr( arg->type )) fputc( '*', file );
4264                 /* FIXME: should check for large args being passed by pointer */
4265                 if (is_array( arg->type ) || is_ptr( arg->type ) || type_memsize( arg->type ) == pointer_size)
4266                     fprintf( file, "%s;\n", arg->name );
4267                 else
4268                     fprintf( file, "%s DECLSPEC_ALIGN(%u);\n", arg->name, pointer_size );
4269             }
4270             print_file(file, 1, "} *pS = (struct _PARAM_STRUCT *)pStubMsg->StackTop;\n" );
4271         }
4272         else
4273         {
4274             print_file(file, 1, "%s", "");
4275             write_type_left(file, (type_t *)eval->cont_type, TRUE);
4276             fprintf(file, " *%s = (", var_name);
4277             write_type_left(file, (type_t *)eval->cont_type, TRUE);
4278             fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff);
4279         }
4280         print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */
4281         print_file(file, 1, "pStubMsg->MaxCount = (ULONG_PTR)");
4282         write_expr(file, eval->expr, 1, 1, var_name_expr, eval->cont_type, "");
4283         fprintf(file, ";\n");
4284         print_file(file, 0, "}\n\n");
4285         callback_offset++;
4286     }
4287     return result;
4288 }
4289
4290 void write_expr_eval_routine_list(FILE *file, const char *iface)
4291 {
4292     struct expr_eval_routine *eval;
4293     struct expr_eval_routine *cursor;
4294     unsigned short callback_offset = 0;
4295
4296     fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n");
4297     fprintf(file, "{\n");
4298
4299     LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry)
4300     {
4301         print_file(file, 1, "%s_%sExprEval_%04u,\n", iface, eval->name, callback_offset);
4302         callback_offset++;
4303         list_remove(&eval->entry);
4304         free(eval->name);
4305         free(eval);
4306     }
4307
4308     fprintf(file, "};\n\n");
4309 }
4310
4311 void write_user_quad_list(FILE *file)
4312 {
4313     user_type_t *ut;
4314
4315     if (list_empty(&user_type_list))
4316         return;
4317
4318     fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n");
4319     fprintf(file, "{\n");
4320     LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
4321     {
4322         const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ",";
4323         print_file(file, 1, "{\n");
4324         print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name);
4325         print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name);
4326         print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name);
4327         print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name);
4328         print_file(file, 1, "}%s\n", sep);
4329     }
4330     fprintf(file, "};\n\n");
4331 }
4332
4333 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list )
4334 {
4335     const struct str_list_entry_t *endpoint;
4336     const char *p;
4337
4338     /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */
4339     print_file( f, 0, "static const unsigned char * const %s__RpcProtseqEndpoint[][2] =\n{\n", prefix );
4340     LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry )
4341     {
4342         print_file( f, 1, "{ (const unsigned char *)\"" );
4343         for (p = endpoint->str; *p && *p != ':'; p++)
4344         {
4345             if (*p == '"' || *p == '\\') fputc( '\\', f );
4346             fputc( *p, f );
4347         }
4348         if (!*p) goto error;
4349         if (p[1] != '[') goto error;
4350
4351         fprintf( f, "\", (const unsigned char *)\"" );
4352         for (p += 2; *p && *p != ']'; p++)
4353         {
4354             if (*p == '"' || *p == '\\') fputc( '\\', f );
4355             fputc( *p, f );
4356         }
4357         if (*p != ']') goto error;
4358         fprintf( f, "\" },\n" );
4359     }
4360     print_file( f, 0, "};\n\n" );
4361     return;
4362
4363 error:
4364     error("Invalid endpoint syntax '%s'\n", endpoint->str);
4365 }
4366
4367 void write_exceptions( FILE *file )
4368 {
4369     fprintf( file, "#ifndef USE_COMPILER_EXCEPTIONS\n");
4370     fprintf( file, "\n");
4371     fprintf( file, "#include \"wine/exception.h\"\n");
4372     fprintf( file, "#undef RpcTryExcept\n");
4373     fprintf( file, "#undef RpcExcept\n");
4374     fprintf( file, "#undef RpcEndExcept\n");
4375     fprintf( file, "#undef RpcTryFinally\n");
4376     fprintf( file, "#undef RpcFinally\n");
4377     fprintf( file, "#undef RpcEndFinally\n");
4378     fprintf( file, "#undef RpcExceptionCode\n");
4379     fprintf( file, "#undef RpcAbnormalTermination\n");
4380     fprintf( file, "\n");
4381     fprintf( file, "struct __exception_frame;\n");
4382     fprintf( file, "typedef int (*__filter_func)(struct __exception_frame *);\n");
4383     fprintf( file, "typedef void (*__finally_func)(struct __exception_frame *);\n");
4384     fprintf( file, "\n");
4385     fprintf( file, "#define __DECL_EXCEPTION_FRAME \\\n");
4386     fprintf( file, "    EXCEPTION_REGISTRATION_RECORD frame; \\\n");
4387     fprintf( file, "    __filter_func                 filter; \\\n");
4388     fprintf( file, "    __finally_func                finally; \\\n");
4389     fprintf( file, "    sigjmp_buf                    jmp; \\\n");
4390     fprintf( file, "    DWORD                         code; \\\n");
4391     fprintf( file, "    unsigned char                 abnormal_termination; \\\n");
4392     fprintf( file, "    unsigned char                 filter_level; \\\n");
4393     fprintf( file, "    unsigned char                 finally_level;\n");
4394     fprintf( file, "\n");
4395     fprintf( file, "struct __exception_frame\n{\n");
4396     fprintf( file, "    __DECL_EXCEPTION_FRAME\n");
4397     fprintf( file, "};\n");
4398     fprintf( file, "\n");
4399     fprintf( file, "static inline void __widl_unwind_target(void)\n" );
4400     fprintf( file, "{\n");
4401     fprintf( file, "    struct __exception_frame *exc_frame = (struct __exception_frame *)__wine_get_frame();\n" );
4402     fprintf( file, "    if (exc_frame->finally_level > exc_frame->filter_level)\n" );
4403     fprintf( file, "    {\n");
4404     fprintf( file, "        exc_frame->abnormal_termination = 1;\n");
4405     fprintf( file, "        exc_frame->finally( exc_frame );\n");
4406     fprintf( file, "        __wine_pop_frame( &exc_frame->frame );\n");
4407     fprintf( file, "    }\n");
4408     fprintf( file, "    exc_frame->filter_level = 0;\n");
4409     fprintf( file, "    siglongjmp( exc_frame->jmp, 1 );\n");
4410     fprintf( file, "}\n");
4411     fprintf( file, "\n");
4412     fprintf( file, "static DWORD __widl_exception_handler( EXCEPTION_RECORD *record,\n");
4413     fprintf( file, "                                       EXCEPTION_REGISTRATION_RECORD *frame,\n");
4414     fprintf( file, "                                       CONTEXT *context,\n");
4415     fprintf( file, "                                       EXCEPTION_REGISTRATION_RECORD **pdispatcher )\n");
4416     fprintf( file, "{\n");
4417     fprintf( file, "    struct __exception_frame *exc_frame = (struct __exception_frame *)frame;\n");
4418     fprintf( file, "\n");
4419     fprintf( file, "    if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))\n");
4420     fprintf( file, "    {\n" );
4421     fprintf( file, "        if (exc_frame->finally_level && (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))\n");
4422     fprintf( file, "        {\n" );
4423     fprintf( file, "            exc_frame->abnormal_termination = 1;\n");
4424     fprintf( file, "            exc_frame->finally( exc_frame );\n");
4425     fprintf( file, "        }\n" );
4426     fprintf( file, "        return ExceptionContinueSearch;\n");
4427     fprintf( file, "    }\n" );
4428     fprintf( file, "    exc_frame->code = record->ExceptionCode;\n");
4429     fprintf( file, "    if (exc_frame->filter_level && exc_frame->filter( exc_frame ) == EXCEPTION_EXECUTE_HANDLER)\n" );
4430     fprintf( file, "        __wine_rtl_unwind( frame, record, __widl_unwind_target );\n");
4431     fprintf( file, "    return ExceptionContinueSearch;\n");
4432     fprintf( file, "}\n");
4433     fprintf( file, "\n");
4434     fprintf( file, "#define RpcTryExcept \\\n");
4435     fprintf( file, "    if (!sigsetjmp( __frame->jmp, 0 )) \\\n");
4436     fprintf( file, "    { \\\n");
4437     fprintf( file, "        if (!__frame->finally_level) \\\n" );
4438     fprintf( file, "            __wine_push_frame( &__frame->frame ); \\\n");
4439     fprintf( file, "        __frame->filter_level = __frame->finally_level + 1;\n" );
4440     fprintf( file, "\n");
4441     fprintf( file, "#define RpcExcept(expr) \\\n");
4442     fprintf( file, "        if (!__frame->finally_level) \\\n" );
4443     fprintf( file, "            __wine_pop_frame( &__frame->frame ); \\\n");
4444     fprintf( file, "        __frame->filter_level = 0; \\\n" );
4445     fprintf( file, "    } \\\n");
4446     fprintf( file, "    else \\\n");
4447     fprintf( file, "\n");
4448     fprintf( file, "#define RpcEndExcept\n");
4449     fprintf( file, "\n");
4450     fprintf( file, "#define RpcExceptionCode() (__frame->code)\n");
4451     fprintf( file, "\n");
4452     fprintf( file, "#define RpcTryFinally \\\n");
4453     fprintf( file, "    if (!__frame->filter_level) \\\n");
4454     fprintf( file, "        __wine_push_frame( &__frame->frame ); \\\n");
4455     fprintf( file, "    __frame->finally_level = __frame->filter_level + 1;\n");
4456     fprintf( file, "\n");
4457     fprintf( file, "#define RpcFinally \\\n");
4458     fprintf( file, "    if (!__frame->filter_level) \\\n");
4459     fprintf( file, "        __wine_pop_frame( &__frame->frame ); \\\n");
4460     fprintf( file, "    __frame->finally_level = 0;\n");
4461     fprintf( file, "\n");
4462     fprintf( file, "#define RpcEndFinally\n");
4463     fprintf( file, "\n");
4464     fprintf( file, "#define RpcAbnormalTermination() (__frame->abnormal_termination)\n");
4465     fprintf( file, "\n");
4466     fprintf( file, "#define RpcExceptionInit(filter_func,finally_func) \\\n");
4467     fprintf( file, "    do { \\\n");
4468     fprintf( file, "        __frame->frame.Handler = __widl_exception_handler; \\\n");
4469     fprintf( file, "        __frame->filter = (__filter_func)(filter_func); \\\n" );
4470     fprintf( file, "        __frame->finally = (__finally_func)(finally_func); \\\n");
4471     fprintf( file, "        __frame->abnormal_termination = 0; \\\n");
4472     fprintf( file, "        __frame->filter_level = 0; \\\n");
4473     fprintf( file, "        __frame->finally_level = 0; \\\n");
4474     fprintf( file, "    } while (0)\n");
4475     fprintf( file, "\n");
4476     fprintf( file, "#else /* USE_COMPILER_EXCEPTIONS */\n");
4477     fprintf( file, "\n");
4478     fprintf( file, "#define RpcExceptionInit(filter_func,finally_func) \\\n");
4479     fprintf( file, "    do { (void)(filter_func); } while(0)\n");
4480     fprintf( file, "\n");
4481     fprintf( file, "#define __DECL_EXCEPTION_FRAME \\\n");
4482     fprintf( file, "    DWORD code;\n");
4483     fprintf( file, "\n");
4484     fprintf( file, "#endif /* USE_COMPILER_EXCEPTIONS */\n");
4485 }