ReactOS  0.4.15-dev-2945-g7100a24
typegen.c
Go to the documentation of this file.
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 
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 
65 {
70 };
71 
72 /* parameter flags in Oif mode */
73 static const unsigned short MustSize = 0x0001;
74 static const unsigned short MustFree = 0x0002;
75 static const unsigned short IsPipe = 0x0004;
76 static const unsigned short IsIn = 0x0008;
77 static const unsigned short IsOut = 0x0010;
78 static const unsigned short IsReturn = 0x0020;
79 static const unsigned short IsBasetype = 0x0040;
80 static const unsigned short IsByValue = 0x0080;
81 static const unsigned short IsSimpleRef = 0x0100;
82 /* static const unsigned short IsDontCallFreeInst = 0x0200; */
83 /* static const unsigned short SaveForAsyncFinish = 0x0400; */
84 
85 static unsigned int field_memsize(const type_t *type, unsigned int *offset);
86 static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align);
87 static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
88  const char *name, unsigned int *typestring_offset);
89 static unsigned int write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff);
90 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
91  const char *name, int write_ptr, unsigned int *tfsoff);
92 static const var_t *find_array_or_string_in_struct(const type_t *type);
93 static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
95  const char *name, unsigned int *typestring_offset);
96 static unsigned int get_required_buffer_size_type( const type_t *type, const char *name,
97  const attr_list_t *attrs, int toplevel_param,
98  unsigned int *alignment );
99 static unsigned int get_function_buffer_size( const var_t *func, enum pass pass );
100 
101 static const char *string_of_type(unsigned char type)
102 {
103  switch (type)
104  {
105  case FC_BYTE: return "FC_BYTE";
106  case FC_CHAR: return "FC_CHAR";
107  case FC_SMALL: return "FC_SMALL";
108  case FC_USMALL: return "FC_USMALL";
109  case FC_WCHAR: return "FC_WCHAR";
110  case FC_SHORT: return "FC_SHORT";
111  case FC_USHORT: return "FC_USHORT";
112  case FC_LONG: return "FC_LONG";
113  case FC_ULONG: return "FC_ULONG";
114  case FC_FLOAT: return "FC_FLOAT";
115  case FC_HYPER: return "FC_HYPER";
116  case FC_DOUBLE: return "FC_DOUBLE";
117  case FC_ENUM16: return "FC_ENUM16";
118  case FC_ENUM32: return "FC_ENUM32";
119  case FC_IGNORE: return "FC_IGNORE";
120  case FC_ERROR_STATUS_T: return "FC_ERROR_STATUS_T";
121  case FC_RP: return "FC_RP";
122  case FC_UP: return "FC_UP";
123  case FC_OP: return "FC_OP";
124  case FC_FP: return "FC_FP";
125  case FC_ENCAPSULATED_UNION: return "FC_ENCAPSULATED_UNION";
126  case FC_NON_ENCAPSULATED_UNION: return "FC_NON_ENCAPSULATED_UNION";
127  case FC_STRUCT: return "FC_STRUCT";
128  case FC_PSTRUCT: return "FC_PSTRUCT";
129  case FC_CSTRUCT: return "FC_CSTRUCT";
130  case FC_CPSTRUCT: return "FC_CPSTRUCT";
131  case FC_CVSTRUCT: return "FC_CVSTRUCT";
132  case FC_BOGUS_STRUCT: return "FC_BOGUS_STRUCT";
133  case FC_SMFARRAY: return "FC_SMFARRAY";
134  case FC_LGFARRAY: return "FC_LGFARRAY";
135  case FC_SMVARRAY: return "FC_SMVARRAY";
136  case FC_LGVARRAY: return "FC_LGVARRAY";
137  case FC_CARRAY: return "FC_CARRAY";
138  case FC_CVARRAY: return "FC_CVARRAY";
139  case FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY";
140  case FC_ALIGNM2: return "FC_ALIGNM2";
141  case FC_ALIGNM4: return "FC_ALIGNM4";
142  case FC_ALIGNM8: return "FC_ALIGNM8";
143  case FC_POINTER: return "FC_POINTER";
144  case FC_C_CSTRING: return "FC_C_CSTRING";
145  case FC_C_WSTRING: return "FC_C_WSTRING";
146  case FC_CSTRING: return "FC_CSTRING";
147  case FC_WSTRING: return "FC_WSTRING";
148  case FC_BYTE_COUNT_POINTER: return "FC_BYTE_COUNT_POINTER";
149  case FC_TRANSMIT_AS: return "FC_TRANSMIT_AS";
150  case FC_REPRESENT_AS: return "FC_REPRESENT_AS";
151  case FC_IP: return "FC_IP";
152  case FC_BIND_CONTEXT: return "FC_BIND_CONTEXT";
153  case FC_BIND_GENERIC: return "FC_BIND_GENERIC";
154  case FC_BIND_PRIMITIVE: return "FC_BIND_PRIMITIVE";
155  case FC_AUTO_HANDLE: return "FC_AUTO_HANDLE";
156  case FC_CALLBACK_HANDLE: return "FC_CALLBACK_HANDLE";
157  case FC_STRUCTPAD1: return "FC_STRUCTPAD1";
158  case FC_STRUCTPAD2: return "FC_STRUCTPAD2";
159  case FC_STRUCTPAD3: return "FC_STRUCTPAD3";
160  case FC_STRUCTPAD4: return "FC_STRUCTPAD4";
161  case FC_STRUCTPAD5: return "FC_STRUCTPAD5";
162  case FC_STRUCTPAD6: return "FC_STRUCTPAD6";
163  case FC_STRUCTPAD7: return "FC_STRUCTPAD7";
164  case FC_STRING_SIZED: return "FC_STRING_SIZED";
165  case FC_NO_REPEAT: return "FC_NO_REPEAT";
166  case FC_FIXED_REPEAT: return "FC_FIXED_REPEAT";
167  case FC_VARIABLE_REPEAT: return "FC_VARIABLE_REPEAT";
168  case FC_FIXED_OFFSET: return "FC_FIXED_OFFSET";
169  case FC_VARIABLE_OFFSET: return "FC_VARIABLE_OFFSET";
170  case FC_PP: return "FC_PP";
171  case FC_EMBEDDED_COMPLEX: return "FC_EMBEDDED_COMPLEX";
172  case FC_DEREFERENCE: return "FC_DEREFERENCE";
173  case FC_DIV_2: return "FC_DIV_2";
174  case FC_MULT_2: return "FC_MULT_2";
175  case FC_ADD_1: return "FC_ADD_1";
176  case FC_SUB_1: return "FC_SUB_1";
177  case FC_CALLBACK: return "FC_CALLBACK";
178  case FC_CONSTANT_IID: return "FC_CONSTANT_IID";
179  case FC_END: return "FC_END";
180  case FC_PAD: return "FC_PAD";
181  case FC_USER_MARSHAL: return "FC_USER_MARSHAL";
182  case FC_RANGE: return "FC_RANGE";
183  case FC_INT3264: return "FC_INT3264";
184  case FC_UINT3264: return "FC_UINT3264";
185  default:
186  error("string_of_type: unknown type 0x%02x\n", type);
187  return NULL;
188  }
189 }
190 
191 static void *get_aliaschain_attrp(const type_t *type, enum attr_type attr)
192 {
193  const type_t *t = type;
194  for (;;)
195  {
196  if (is_attr(t->attrs, attr))
197  return get_attrp(t->attrs, attr);
198  else if (type_is_alias(t))
200  else return NULL;
201  }
202 }
203 
204 unsigned char get_basic_fc(const type_t *type)
205 {
207  switch (type_basic_get_type(type))
208  {
209  case TYPE_BASIC_INT8: return (sign <= 0 ? FC_SMALL : FC_USMALL);
210  case TYPE_BASIC_INT16: return (sign <= 0 ? FC_SHORT : FC_USHORT);
211  case TYPE_BASIC_INT32:
212  case TYPE_BASIC_LONG: return (sign <= 0 ? FC_LONG : FC_ULONG);
213  case TYPE_BASIC_INT64: return FC_HYPER;
214  case TYPE_BASIC_INT: return (sign <= 0 ? FC_LONG : FC_ULONG);
215  case TYPE_BASIC_INT3264: return (sign <= 0 ? FC_INT3264 : FC_UINT3264);
216  case TYPE_BASIC_BYTE: return FC_BYTE;
217  case TYPE_BASIC_CHAR: return FC_CHAR;
218  case TYPE_BASIC_WCHAR: return FC_WCHAR;
219  case TYPE_BASIC_HYPER: return FC_HYPER;
220  case TYPE_BASIC_FLOAT: return FC_FLOAT;
221  case TYPE_BASIC_DOUBLE: return FC_DOUBLE;
224  }
225  return 0;
226 }
227 
228 static unsigned char get_basic_fc_signed(const type_t *type)
229 {
230  switch (type_basic_get_type(type))
231  {
232  case TYPE_BASIC_INT8: return FC_SMALL;
233  case TYPE_BASIC_INT16: return FC_SHORT;
234  case TYPE_BASIC_INT32: return FC_LONG;
235  case TYPE_BASIC_INT64: return FC_HYPER;
236  case TYPE_BASIC_INT: return FC_LONG;
237  case TYPE_BASIC_INT3264: return FC_INT3264;
238  case TYPE_BASIC_LONG: return FC_LONG;
239  case TYPE_BASIC_BYTE: return FC_BYTE;
240  case TYPE_BASIC_CHAR: return FC_CHAR;
241  case TYPE_BASIC_WCHAR: return FC_WCHAR;
242  case TYPE_BASIC_HYPER: return FC_HYPER;
243  case TYPE_BASIC_FLOAT: return FC_FLOAT;
244  case TYPE_BASIC_DOUBLE: return FC_DOUBLE;
247  }
248  return 0;
249 }
250 
251 static inline unsigned int clamp_align(unsigned int align)
252 {
253  unsigned int packing = (pointer_size == 4) ? win32_packing : win64_packing;
254  if(align > packing) align = packing;
255  return align;
256 }
257 
258 unsigned char get_pointer_fc(const type_t *type, const attr_list_t *attrs, int toplevel_param)
259 {
260  const type_t *t;
261  int pointer_type;
262 
264 
265  pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
266  if (pointer_type)
267  return pointer_type;
268 
270  {
271  pointer_type = get_attrv(t->attrs, ATTR_POINTERTYPE);
272  if (pointer_type)
273  return pointer_type;
274  }
275 
276  if (toplevel_param)
277  return FC_RP;
278  else if (is_ptr(type))
280  else
282 }
283 
284 static unsigned char get_pointer_fc_context( const type_t *type, const attr_list_t *attrs,
285  enum type_context context )
286 {
287  int pointer_fc = get_pointer_fc(type, attrs, context == TYPE_CONTEXT_TOPLEVELPARAM);
288 
289  if (pointer_fc == FC_UP && is_attr( attrs, ATTR_OUT ) &&
291  pointer_fc = FC_OP;
292 
293  return pointer_fc;
294 }
295 
296 static unsigned char get_enum_fc(const type_t *type)
297 {
300  return FC_ENUM32;
301  else
302  return FC_ENUM16;
303 }
304 
305 static type_t *get_user_type(const type_t *t, const char **pname)
306 {
307  for (;;)
308  {
309  type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL);
310  if (ut)
311  {
312  if (pname)
313  *pname = t->name;
314  return ut;
315  }
316 
317  if (type_is_alias(t))
319  else
320  return NULL;
321  }
322 }
323 
324 static int is_user_type(const type_t *t)
325 {
326  return get_user_type(t, NULL) != NULL;
327 }
328 
329 enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *attrs, unsigned int flags)
330 {
331  if (is_user_type(type))
332  return TGT_USER_TYPE;
333 
335  return TGT_CTXT_HANDLE;
336 
337  if (!(flags & TDT_IGNORE_STRINGS) && is_string_type(attrs, type))
338  return TGT_STRING;
339 
340  switch (type_get_type(type))
341  {
342  case TYPE_BASIC:
343  if (!(flags & TDT_IGNORE_RANGES) &&
345  return TGT_RANGE;
346  return TGT_BASIC;
347  case TYPE_ENUM:
348  if (!(flags & TDT_IGNORE_RANGES) &&
350  return TGT_RANGE;
351  return TGT_ENUM;
352  case TYPE_POINTER:
355  return TGT_IFACE_POINTER;
358  else
359  return TGT_POINTER;
360  case TYPE_STRUCT:
361  return TGT_STRUCT;
363  case TYPE_UNION:
364  return TGT_UNION;
365  case TYPE_ARRAY:
366  return TGT_ARRAY;
367  case TYPE_FUNCTION:
368  case TYPE_COCLASS:
369  case TYPE_INTERFACE:
370  case TYPE_MODULE:
371  case TYPE_VOID:
372  case TYPE_ALIAS:
373  case TYPE_BITFIELD:
374  break;
375  }
376  return TGT_INVALID;
377 }
378 
379 static int cant_be_null(const var_t *v)
380 {
381  switch (typegen_detect_type(v->type, v->attrs, TDT_IGNORE_STRINGS))
382  {
383  case TGT_ARRAY:
384  if (!type_array_is_decl_as_ptr( v->type )) return 0;
385  /* fall through */
386  case TGT_POINTER:
387  return (get_pointer_fc(v->type, v->attrs, TRUE) == FC_RP);
389  return TRUE;
390  default:
391  return 0;
392  }
393 
394 }
395 
396 static int get_padding(const var_list_t *fields)
397 {
398  unsigned short offset = 0;
399  unsigned int salign = 1;
400  const var_t *f;
401 
402  if (!fields)
403  return 0;
404 
405  LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
406  {
407  type_t *ft = f->type;
408  unsigned int align = 0;
409  unsigned int size = type_memsize_and_alignment(ft, &align);
411  if (align > salign) salign = align;
413  offset += size;
414  }
415 
416  return ROUNDING(offset, salign);
417 }
418 
419 static unsigned int get_stack_size( const var_t *var, int *by_value )
420 {
421  unsigned int stack_size;
422  int by_val;
423 
424  switch (typegen_detect_type( var->type, var->attrs, TDT_ALL_TYPES ))
425  {
426  case TGT_BASIC:
427  case TGT_ENUM:
428  case TGT_RANGE:
429  case TGT_STRUCT:
430  case TGT_UNION:
431  case TGT_USER_TYPE:
432  stack_size = type_memsize( var->type );
433  by_val = (pointer_size < 8 || stack_size <= pointer_size); /* FIXME: should be platform-specific */
434  break;
435  default:
436  by_val = 0;
437  break;
438  }
439  if (!by_val) stack_size = pointer_size;
440  if (by_value) *by_value = by_val;
441  return ROUND_SIZE( stack_size, pointer_size );
442 }
443 
444 static unsigned char get_contexthandle_flags( const type_t *iface, const attr_list_t *attrs,
445  const type_t *type )
446 {
447  unsigned char flags = 0;
448 
450 
451  if (is_ptr(type) &&
452  !is_attr( type->attrs, ATTR_CONTEXTHANDLE ) &&
453  !is_attr( attrs, ATTR_CONTEXTHANDLE ))
454  flags |= 0x80;
455 
456  if (is_attr(attrs, ATTR_IN))
457  {
458  flags |= 0x40;
460  }
461  if (is_attr(attrs, ATTR_OUT)) flags |= 0x20;
462 
463  return flags;
464 }
465 
466 static unsigned int get_rpc_flags( const attr_list_t *attrs )
467 {
468  unsigned int flags = 0;
469 
470  if (is_attr( attrs, ATTR_IDEMPOTENT )) flags |= 0x0001;
471  if (is_attr( attrs, ATTR_BROADCAST )) flags |= 0x0002;
472  if (is_attr( attrs, ATTR_MAYBE )) flags |= 0x0004;
473  if (is_attr( attrs, ATTR_MESSAGE )) flags |= 0x0100;
474  if (is_attr( attrs, ATTR_ASYNC )) flags |= 0x4000;
475  return flags;
476 }
477 
478 unsigned char get_struct_fc(const type_t *type)
479 {
480  int has_pointer = 0;
481  int has_conformance = 0;
482  int has_variance = 0;
483  var_t *field;
484  var_list_t *fields;
485 
486  fields = type_struct_get_fields(type);
487 
488  if (get_padding(fields))
489  return FC_BOGUS_STRUCT;
490 
491  if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry )
492  {
493  type_t *t = field->type;
495 
497 
499  {
500  if (is_string_type(field->attrs, field->type))
501  {
502  if (is_conformant_array(t))
503  has_conformance = 1;
504  has_variance = 1;
505  continue;
506  }
507 
509  return FC_BOGUS_STRUCT;
510 
512  {
513  has_conformance = 1;
514  if (list_next(fields, &field->entry))
515  error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n",
516  field->name);
517  }
519  has_variance = 1;
520 
523  }
524 
525  switch (typegen_type)
526  {
527  case TGT_USER_TYPE:
528  case TGT_IFACE_POINTER:
529  return FC_BOGUS_STRUCT;
530  case TGT_BASIC:
532  return FC_BOGUS_STRUCT;
533  break;
534  case TGT_ENUM:
535  if (get_enum_fc(t) == FC_ENUM16)
536  return FC_BOGUS_STRUCT;
537  break;
538  case TGT_POINTER:
539  case TGT_ARRAY:
540  if (get_pointer_fc(t, field->attrs, FALSE) == FC_RP || pointer_size != 4)
541  return FC_BOGUS_STRUCT;
542  has_pointer = 1;
543  break;
544  case TGT_UNION:
545  return FC_BOGUS_STRUCT;
546  case TGT_STRUCT:
547  {
548  unsigned char fc = get_struct_fc(t);
549  switch (fc)
550  {
551  case FC_STRUCT:
552  break;
553  case FC_CVSTRUCT:
554  has_conformance = 1;
555  has_variance = 1;
556  has_pointer = 1;
557  break;
558 
559  case FC_CPSTRUCT:
560  has_conformance = 1;
561  if (list_next( fields, &field->entry ))
562  error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n",
563  field->name);
564  has_pointer = 1;
565  break;
566 
567  case FC_CSTRUCT:
568  has_conformance = 1;
569  if (list_next( fields, &field->entry ))
570  error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n",
571  field->name);
572  break;
573 
574  case FC_PSTRUCT:
575  has_pointer = 1;
576  break;
577 
578  default:
579  error_loc("Unknown struct member %s with type (0x%02x)\n", field->name, fc);
580  /* fallthru - treat it as complex */
581 
582  /* as soon as we see one of these these members, it's bogus... */
583  case FC_BOGUS_STRUCT:
584  return FC_BOGUS_STRUCT;
585  }
586  break;
587  }
588  case TGT_RANGE:
589  return FC_BOGUS_STRUCT;
590  case TGT_STRING:
591  /* shouldn't get here because of TDT_IGNORE_STRINGS above. fall through */
592  case TGT_INVALID:
593  case TGT_CTXT_HANDLE:
595  /* checking after parsing should mean that we don't get here. if we do,
596  * it's a checker bug */
597  assert(0);
598  }
599  }
600 
601  if( has_variance )
602  {
603  if ( has_conformance )
604  return FC_CVSTRUCT;
605  else
606  return FC_BOGUS_STRUCT;
607  }
608  if( has_conformance && has_pointer )
609  return FC_CPSTRUCT;
610  if( has_conformance )
611  return FC_CSTRUCT;
612  if( has_pointer )
613  return FC_PSTRUCT;
614  return FC_STRUCT;
615 }
616 
617 static unsigned char get_array_fc(const type_t *type)
618 {
619  unsigned char fc;
620  const expr_t *size_is;
621  const type_t *elem_type;
622 
623  elem_type = type_array_get_element(type);
624  size_is = type_array_get_conformance(type);
625 
626  if (!size_is)
627  {
628  unsigned int size = type_memsize(elem_type);
629  if (size * type_array_get_dim(type) > 0xffffuL)
630  fc = FC_LGFARRAY;
631  else
632  fc = FC_SMFARRAY;
633  }
634  else
635  fc = FC_CARRAY;
636 
638  {
639  if (fc == FC_SMFARRAY)
640  fc = FC_SMVARRAY;
641  else if (fc == FC_LGFARRAY)
642  fc = FC_LGVARRAY;
643  else if (fc == FC_CARRAY)
644  fc = FC_CVARRAY;
645  }
646 
647  switch (typegen_detect_type(elem_type, NULL, TDT_IGNORE_STRINGS))
648  {
649  case TGT_USER_TYPE:
650  fc = FC_BOGUS_ARRAY;
651  break;
652  case TGT_BASIC:
653  if (type_basic_get_type(elem_type) == TYPE_BASIC_INT3264 &&
654  pointer_size != 4)
655  fc = FC_BOGUS_ARRAY;
656  break;
657  case TGT_STRUCT:
658  switch (get_struct_fc(elem_type))
659  {
660  case FC_BOGUS_STRUCT:
661  fc = FC_BOGUS_ARRAY;
662  break;
663  }
664  break;
665  case TGT_ENUM:
666  /* is 16-bit enum - if so, wire size differs from mem size and so
667  * the array cannot be block copied, which means the array is complex */
668  if (get_enum_fc(elem_type) == FC_ENUM16)
669  fc = FC_BOGUS_ARRAY;
670  break;
671  case TGT_UNION:
672  case TGT_IFACE_POINTER:
673  fc = FC_BOGUS_ARRAY;
674  break;
675  case TGT_POINTER:
676  /* ref pointers cannot just be block copied. unique pointers to
677  * interfaces need special treatment. either case means the array is
678  * complex */
679  if (get_pointer_fc(elem_type, NULL, FALSE) == FC_RP || pointer_size != 4)
680  fc = FC_BOGUS_ARRAY;
681  break;
682  case TGT_RANGE:
683  fc = FC_BOGUS_ARRAY;
684  break;
685  case TGT_CTXT_HANDLE:
687  case TGT_STRING:
688  case TGT_INVALID:
689  case TGT_ARRAY:
690  /* nothing to do for everything else */
691  break;
692  }
693 
694  return fc;
695 }
696 
698 {
699  return (type_get_type(type) == TYPE_STRUCT &&
701 }
702 
703 static int type_has_pointers(const type_t *type)
704 {
706  {
707  case TGT_USER_TYPE:
708  return FALSE;
709  case TGT_POINTER:
710  return TRUE;
711  case TGT_ARRAY:
713  case TGT_STRUCT:
714  {
716  const var_t *field;
717  if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
718  {
720  return TRUE;
721  }
722  break;
723  }
724  case TGT_UNION:
725  {
726  var_list_t *fields;
727  const var_t *field;
728  fields = type_union_get_cases(type);
729  if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
730  {
732  return TRUE;
733  }
734  break;
735  }
736  case TGT_CTXT_HANDLE:
738  case TGT_STRING:
739  case TGT_IFACE_POINTER:
740  case TGT_BASIC:
741  case TGT_ENUM:
742  case TGT_RANGE:
743  case TGT_INVALID:
744  break;
745  }
746 
747  return FALSE;
748 }
749 
750 static int type_has_full_pointer(const type_t *type, const attr_list_t *attrs,
751  int toplevel_param)
752 {
754  {
755  case TGT_USER_TYPE:
756  return FALSE;
757  case TGT_POINTER:
758  if (get_pointer_fc(type, attrs, toplevel_param) == FC_FP)
759  return TRUE;
760  else
761  return FALSE;
762  case TGT_ARRAY:
763  if (get_pointer_fc(type, attrs, toplevel_param) == FC_FP)
764  return TRUE;
765  else
767  case TGT_STRUCT:
768  {
770  const var_t *field;
771  if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
772  {
773  if (type_has_full_pointer(field->type, field->attrs, FALSE))
774  return TRUE;
775  }
776  break;
777  }
778  case TGT_UNION:
779  {
780  var_list_t *fields;
781  const var_t *field;
782  fields = type_union_get_cases(type);
783  if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
784  {
785  if (field->type && type_has_full_pointer(field->type, field->attrs, FALSE))
786  return TRUE;
787  }
788  break;
789  }
790  case TGT_CTXT_HANDLE:
792  case TGT_STRING:
793  case TGT_IFACE_POINTER:
794  case TGT_BASIC:
795  case TGT_ENUM:
796  case TGT_RANGE:
797  case TGT_INVALID:
798  break;
799  }
800 
801  return FALSE;
802 }
803 
804 static unsigned short user_type_offset(const char *name)
805 {
806  user_type_t *ut;
807  unsigned short off = 0;
809  {
810  if (strcmp(name, ut->name) == 0)
811  return off;
812  ++off;
813  }
814  error("user_type_offset: couldn't find type (%s)\n", name);
815  return 0;
816 }
817 
818 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file)
819 {
820  type->typestring_offset = offset;
821  if (file) type->tfswrite = FALSE;
822 }
823 
824 static void guard_rec(type_t *type)
825 {
826  /* types that contain references to themselves (like a linked list),
827  need to be shielded from infinite recursion when writing embedded
828  types */
829  if (type->typestring_offset)
830  type->tfswrite = FALSE;
831  else
832  type->typestring_offset = 1;
833 }
834 
835 static int is_embedded_complex(const type_t *type)
836 {
838  {
839  case TGT_USER_TYPE:
840  case TGT_STRUCT:
841  case TGT_UNION:
842  case TGT_ARRAY:
843  case TGT_IFACE_POINTER:
844  return TRUE;
845  default:
846  return FALSE;
847  }
848 }
849 
850 static const char *get_context_handle_type_name(const type_t *type)
851 {
852  const type_t *t;
853  for (t = type;
854  is_ptr(t) || type_is_alias(t);
856  if (is_attr(t->attrs, ATTR_CONTEXTHANDLE))
857  return t->name;
858  assert(0);
859  return NULL;
860 }
861 
862 #define WRITE_FCTYPE(file, fctype, typestring_offset) \
863  do { \
864  if (file) \
865  fprintf(file, "/* %2u */\n", typestring_offset); \
866  print_file((file), 2, "0x%02x,\t/* " #fctype " */\n", fctype); \
867  } \
868  while (0)
869 
870 static void print_file(FILE *file, int indent, const char *format, ...) __attribute__((format (printf, 3, 4)));
871 static void print_file(FILE *file, int indent, const char *format, ...)
872 {
873  va_list va;
874  va_start(va, format);
875  print(file, indent, format, va);
876  va_end(va);
877 }
878 
879 void print(FILE *file, int indent, const char *format, va_list va)
880 {
881  if (file)
882  {
883  if (format[0] != '\n')
884  while (0 < indent--)
885  fprintf(file, " ");
886  vfprintf(file, format, va);
887  }
888 }
889 
890 
891 static void write_var_init(FILE *file, int indent, const type_t *t, const char *n, const char *local_var_prefix)
892 {
893  if (decl_indirect(t))
894  {
895  print_file(file, indent, "MIDL_memset(&%s%s, 0, sizeof(%s%s));\n",
896  local_var_prefix, n, local_var_prefix, n);
897  print_file(file, indent, "%s_p_%s = &%s%s;\n", local_var_prefix, n, local_var_prefix, n);
898  }
899  else if (is_ptr(t) || is_array(t))
900  print_file(file, indent, "%s%s = 0;\n", local_var_prefix, n);
901 }
902 
903 void write_parameters_init(FILE *file, int indent, const var_t *func, const char *local_var_prefix)
904 {
905  const var_t *var = type_function_get_retval(func->type);
906 
907  if (!is_void(var->type))
908  write_var_init(file, indent, var->type, var->name, local_var_prefix);
909 
910  if (!type_get_function_args(func->type))
911  return;
912 
914  write_var_init(file, indent, var->type, var->name, local_var_prefix);
915 
916  fprintf(file, "\n");
917 }
918 
919 static void write_formatdesc(FILE *f, int indent, const char *str)
920 {
921  print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str);
922  print_file(f, indent, "{\n");
923  print_file(f, indent + 1, "short Pad;\n");
924  print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
925  print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str);
926  print_file(f, indent, "\n");
927 }
928 
930 {
932 
933  print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n",
934  get_size_typeformatstring(stmts, pred));
935 
936  print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n",
937  get_size_procformatstring(stmts, pred));
938 
939  fprintf(f, "\n");
940  write_formatdesc(f, indent, "TYPE");
941  write_formatdesc(f, indent, "PROC");
942  fprintf(f, "\n");
943  print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
944  print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
945  print_file(f, indent, "\n");
946 }
947 
948 int decl_indirect(const type_t *t)
949 {
950  if (is_user_type(t))
951  return TRUE;
952  return (type_get_type(t) != TYPE_BASIC &&
953  type_get_type(t) != TYPE_ENUM &&
956 }
957 
958 static unsigned char get_parameter_fc( const var_t *var, int is_return, unsigned short *flags,
959  unsigned int *stack_size, unsigned int *typestring_offset )
960 {
961  unsigned int alignment, server_size = 0, buffer_size = 0;
962  unsigned char fc = 0;
963  int is_byval;
964  int is_in = is_attr(var->attrs, ATTR_IN);
965  int is_out = is_attr(var->attrs, ATTR_OUT);
966 
967  if (is_return) is_out = TRUE;
968  else if (!is_in && !is_out) is_in = TRUE;
969 
970  *flags = 0;
971  *stack_size = get_stack_size( var, &is_byval );
972  *typestring_offset = var->typestring_offset;
973 
974  if (is_in) *flags |= IsIn;
975  if (is_out) *flags |= IsOut;
976  if (is_return) *flags |= IsReturn;
977 
978  if (!is_string_type( var->attrs, var->type ))
979  buffer_size = get_required_buffer_size_type( var->type, NULL, var->attrs, TRUE, &alignment );
980 
981  switch (typegen_detect_type( var->type, var->attrs, TDT_ALL_TYPES ))
982  {
983  case TGT_BASIC:
984  *flags |= IsBasetype;
985  fc = get_basic_fc_signed( var->type );
986  if (fc == FC_BIND_PRIMITIVE)
987  {
988  buffer_size = 4; /* actually 0 but avoids setting MustSize */
989  fc = FC_LONG;
990  }
991  break;
992  case TGT_ENUM:
993  *flags |= IsBasetype;
994  fc = get_enum_fc( var->type );
995  break;
996  case TGT_RANGE:
997  *flags |= IsByValue;
998  break;
999  case TGT_STRUCT:
1000  case TGT_UNION:
1001  case TGT_USER_TYPE:
1002  *flags |= MustFree | (is_byval ? IsByValue : IsSimpleRef);
1003  break;
1004  case TGT_IFACE_POINTER:
1005  *flags |= MustFree;
1006  break;
1007  case TGT_ARRAY:
1008  *flags |= MustFree;
1009  if (type_array_is_decl_as_ptr(var->type) && var->type->details.array.ptr_tfsoff &&
1010  get_pointer_fc( var->type, var->attrs, !is_return ) == FC_RP)
1011  {
1012  *typestring_offset = var->type->typestring_offset;
1013  *flags |= IsSimpleRef;
1014  }
1015  break;
1016  case TGT_STRING:
1017  *flags |= MustFree;
1018  if (is_declptr( var->type ) && get_pointer_fc( var->type, var->attrs, !is_return ) == FC_RP)
1019  {
1020  /* skip over pointer description straight to string description */
1021  if (is_conformant_array( var->type )) *typestring_offset += 4;
1022  else *typestring_offset += 2;
1023  *flags |= IsSimpleRef;
1024  }
1025  break;
1027  *flags |= IsSimpleRef;
1028  *typestring_offset += 4;
1029  /* fall through */
1030  case TGT_CTXT_HANDLE:
1031  buffer_size = 20;
1032  break;
1033  case TGT_POINTER:
1034  if (get_pointer_fc( var->type, var->attrs, !is_return ) == FC_RP)
1035  {
1036  const type_t *ref = type_pointer_get_ref( var->type );
1037 
1038  if (!is_string_type( var->attrs, ref ))
1040 
1042  {
1043  case TGT_BASIC:
1045  fc = get_basic_fc( ref );
1046  if (!is_in && is_out) server_size = pointer_size;
1047  break;
1048  case TGT_ENUM:
1049  if ((fc = get_enum_fc( ref )) == FC_ENUM32)
1050  {
1052  if (!is_in && is_out) server_size = pointer_size;
1053  }
1054  else
1055  {
1056  server_size = pointer_size;
1057  }
1058  break;
1059  case TGT_UNION:
1060  case TGT_USER_TYPE:
1061  case TGT_RANGE:
1062  case TGT_ARRAY:
1063  *flags |= IsSimpleRef | MustFree;
1064  *typestring_offset = ref->typestring_offset;
1065  if (!is_in && is_out) server_size = type_memsize( ref );
1066  break;
1067  case TGT_STRING:
1068  case TGT_POINTER:
1069  case TGT_CTXT_HANDLE:
1071  *flags |= MustFree;
1072  server_size = pointer_size;
1073  break;
1074  case TGT_IFACE_POINTER:
1075  *flags |= MustFree;
1076  if (is_in && is_out) server_size = pointer_size;
1077  break;
1078  case TGT_STRUCT:
1079  *flags |= IsSimpleRef | MustFree;
1080  *typestring_offset = ref->typestring_offset;
1081  switch (get_struct_fc(ref))
1082  {
1083  case FC_STRUCT:
1084  case FC_PSTRUCT:
1085  case FC_BOGUS_STRUCT:
1086  if (!is_in && is_out) server_size = type_memsize( ref );
1087  break;
1088  default:
1089  break;
1090  }
1091  break;
1092  case TGT_INVALID:
1093  assert(0);
1094  }
1095  }
1096  else /* not ref pointer */
1097  {
1098  *flags |= MustFree;
1099  }
1100  break;
1101  case TGT_INVALID:
1102  assert(0);
1103  }
1104 
1105  if (!buffer_size) *flags |= MustSize;
1106 
1107  if (server_size)
1108  {
1109  server_size = (server_size + 7) / 8;
1110  if (server_size < 8) *flags |= server_size << 13;
1111  }
1112  return fc;
1113 }
1114 
1115 static unsigned char get_func_oi2_flags( const var_t *func )
1116 {
1117  const var_t *var;
1119  var_t *retval = type_function_get_retval( func->type );
1120  unsigned char oi2_flags = 0x40; /* HasExtensions */
1121  unsigned short flags;
1122  unsigned int stack_size, typestring_offset;
1123 
1124  if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
1125  {
1126  get_parameter_fc( var, 0, &flags, &stack_size, &typestring_offset );
1127  if (flags & MustSize)
1128  {
1129  if (flags & IsIn) oi2_flags |= 0x02; /* ClientMustSize */
1130  if (flags & IsOut) oi2_flags |= 0x01; /* ServerMustSize */
1131  }
1132  }
1133 
1134  if (!is_void( retval->type ))
1135  {
1136  oi2_flags |= 0x04; /* HasRet */
1137  get_parameter_fc( retval, 1, &flags, &stack_size, &typestring_offset );
1138  if (flags & MustSize) oi2_flags |= 0x01; /* ServerMustSize */
1139  }
1140  return oi2_flags;
1141 }
1142 
1143 static unsigned int write_new_procformatstring_type(FILE *file, int indent, const var_t *var,
1144  int is_return, unsigned int *stack_offset)
1145 {
1146  char buffer[128];
1147  unsigned int stack_size, typestring_offset;
1148  unsigned short flags;
1149  unsigned char fc = get_parameter_fc( var, is_return, &flags, &stack_size, &typestring_offset );
1150 
1151  strcpy( buffer, "/* flags:" );
1152  if (flags & MustSize) strcat( buffer, " must size," );
1153  if (flags & MustFree) strcat( buffer, " must free," );
1154  if (flags & IsPipe) strcat( buffer, " pipe," );
1155  if (flags & IsIn) strcat( buffer, " in," );
1156  if (flags & IsOut) strcat( buffer, " out," );
1157  if (flags & IsReturn) strcat( buffer, " return," );
1158  if (flags & IsBasetype) strcat( buffer, " base type," );
1159  if (flags & IsByValue) strcat( buffer, " by value," );
1160  if (flags & IsSimpleRef) strcat( buffer, " simple ref," );
1161  if (flags >> 13) sprintf( buffer + strlen(buffer), " srv size=%u,", (flags >> 13) * 8 );
1162  strcpy( buffer + strlen( buffer ) - 1, " */" );
1163  print_file( file, indent, "NdrFcShort(0x%hx),\t%s\n", flags, buffer );
1164  print_file( file, indent, "NdrFcShort(0x%x), /* stack offset = %u */\n",
1166  if (flags & IsBasetype)
1167  {
1168  print_file( file, indent, "0x%02x, /* %s */\n", fc, string_of_type(fc) );
1169  print_file( file, indent, "0x0,\n" );
1170  }
1171  else
1172  print_file( file, indent, "NdrFcShort(0x%x), /* type offset = %u */\n",
1173  typestring_offset, typestring_offset );
1174  *stack_offset += max( stack_size, pointer_size );
1175  return 6;
1176 }
1177 
1178 static unsigned int write_old_procformatstring_type(FILE *file, int indent, const var_t *var,
1179  int is_return, int is_interpreted)
1180 {
1181  unsigned int size;
1182 
1183  int is_in = is_attr(var->attrs, ATTR_IN);
1184  int is_out = is_attr(var->attrs, ATTR_OUT);
1185 
1186  if (!is_in && !is_out) is_in = TRUE;
1187 
1188  if (type_get_type(var->type) == TYPE_BASIC ||
1189  type_get_type(var->type) == TYPE_ENUM)
1190  {
1191  unsigned char fc;
1192 
1193  if (is_return)
1194  print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
1195  else
1196  print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n");
1197 
1198  if (type_get_type(var->type) == TYPE_ENUM)
1199  {
1200  fc = get_enum_fc(var->type);
1201  }
1202  else
1203  {
1204  fc = get_basic_fc_signed(var->type);
1205 
1206  if (fc == FC_BIND_PRIMITIVE)
1207  fc = FC_IGNORE;
1208  }
1209 
1210  print_file(file, indent, "0x%02x, /* %s */\n",
1211  fc, string_of_type(fc));
1212  size = 2; /* includes param type prefix */
1213  }
1214  else
1215  {
1216  unsigned short offset = var->typestring_offset;
1217 
1218  if (!is_interpreted && is_array(var->type) &&
1219  type_array_is_decl_as_ptr(var->type) &&
1220  var->type->details.array.ptr_tfsoff)
1221  offset = var->type->typestring_offset;
1222 
1223  if (is_return)
1224  print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n");
1225  else if (is_in && is_out)
1226  print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n");
1227  else if (is_out)
1228  print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n");
1229  else
1230  print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n");
1231 
1232  size = get_stack_size( var, NULL );
1233  print_file(file, indent, "0x%02x,\n", size / pointer_size );
1234  print_file(file, indent, "NdrFcShort(0x%x), /* type offset = %u */\n", offset, offset);
1235  size = 4; /* includes param type prefix */
1236  }
1237  return size;
1238 }
1239 
1240 int is_interpreted_func( const type_t *iface, const var_t *func )
1241 {
1242  const char *str;
1243  const var_t *var;
1244  const var_list_t *args = type_get_function_args( func->type );
1245  const type_t *ret_type = type_function_get_rettype( func->type );
1246 
1247  if (type_get_type( ret_type ) == TYPE_BASIC)
1248  {
1249  switch (type_basic_get_type( ret_type ))
1250  {
1251  case TYPE_BASIC_INT64:
1252  case TYPE_BASIC_HYPER:
1253  /* return value must fit in a long_ptr */
1254  if (pointer_size < 8) return 0;
1255  break;
1256  case TYPE_BASIC_FLOAT:
1257  case TYPE_BASIC_DOUBLE:
1258  /* floating point values can't be returned */
1259  return 0;
1260  default:
1261  break;
1262  }
1263  }
1264  if (get_stub_mode() != MODE_Oif && args)
1265  {
1266  LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
1267  switch (type_get_type( var->type ))
1268  {
1269  case TYPE_BASIC:
1270  switch (type_basic_get_type( var->type ))
1271  {
1272  /* floating point arguments are not supported in Oi mode */
1273  case TYPE_BASIC_FLOAT: return 0;
1274  case TYPE_BASIC_DOUBLE: return 0;
1275  default: break;
1276  }
1277  break;
1278  /* unions passed by value are not supported in Oi mode */
1279  case TYPE_UNION: return 0;
1280  case TYPE_ENCAPSULATED_UNION: return 0;
1281  default: break;
1282  }
1283  }
1284 
1285  if ((str = get_attrp( func->attrs, ATTR_OPTIMIZE ))) return !strcmp( str, "i" );
1286  if ((str = get_attrp( iface->attrs, ATTR_OPTIMIZE ))) return !strcmp( str, "i" );
1287  return (get_stub_mode() != MODE_Os);
1288 }
1289 
1290 static void write_proc_func_header( FILE *file, int indent, const type_t *iface,
1291  const var_t *func, unsigned int *offset,
1292  unsigned short num_proc )
1293 {
1294  var_t *var;
1296  unsigned char explicit_fc, implicit_fc;
1297  unsigned char handle_flags;
1298  const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc );
1299  unsigned char oi_flags = Oi_HAS_RPCFLAGS | Oi_USE_NEW_INIT_ROUTINES;
1300  unsigned int rpc_flags = get_rpc_flags( func->attrs );
1301  unsigned int nb_args = 0;
1302  unsigned int stack_size = 0;
1303  unsigned short param_num = 0;
1304  unsigned short handle_stack_offset = 0;
1305  unsigned short handle_param_num = 0;
1306 
1307  if (is_full_pointer_function( func )) oi_flags |= Oi_FULL_PTR_USED;
1308  if (is_object( iface ))
1309  {
1310  oi_flags |= Oi_OBJECT_PROC;
1311  if (get_stub_mode() == MODE_Oif) oi_flags |= Oi_OBJ_USE_V2_INTERPRETER;
1312  stack_size += pointer_size;
1313  }
1314 
1316  {
1317  if (var == handle_var)
1318  {
1319  handle_stack_offset = stack_size;
1320  handle_param_num = param_num;
1321  }
1322  stack_size += get_stack_size( var, NULL );
1323  param_num++;
1324 
1325  if (var != handle_var || implicit_fc || explicit_fc != FC_BIND_PRIMITIVE)
1326  nb_args++;
1327  }
1328  if (!is_void( type_function_get_rettype( func->type )))
1329  {
1330  stack_size += pointer_size;
1331  nb_args++;
1332  }
1333 
1334  print_file( file, 0, "/* %u (procedure %s::%s) */\n", *offset, iface->name, func->name );
1335  print_file( file, indent, "0x%02x,\t/* %s */\n", implicit_fc,
1336  implicit_fc ? string_of_type(implicit_fc) : "explicit handle" );
1337  print_file( file, indent, "0x%02x,\n", oi_flags );
1338  print_file( file, indent, "NdrFcLong(0x%x),\n", rpc_flags );
1339  print_file( file, indent, "NdrFcShort(0x%hx),\t/* method %hu */\n", num_proc, num_proc );
1340  print_file( file, indent, "NdrFcShort(0x%x),\t/* stack size = %u */\n", stack_size, stack_size );
1341  *offset += 10;
1342 
1343  if (!implicit_fc)
1344  {
1345  switch (explicit_fc)
1346  {
1347  case FC_BIND_PRIMITIVE:
1348  handle_flags = 0;
1349  print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) );
1350  print_file( file, indent, "0x%02x,\n", handle_flags );
1351  print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n",
1352  handle_stack_offset, handle_stack_offset );
1353  *offset += 4;
1354  break;
1355  case FC_BIND_GENERIC:
1356  handle_flags = type_memsize( handle_var->type );
1357  print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) );
1358  print_file( file, indent, "0x%02x,\n", handle_flags );
1359  print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n",
1360  handle_stack_offset, handle_stack_offset );
1361  print_file( file, indent, "0x%02x,\n", get_generic_handle_offset( handle_var->type ) );
1362  print_file( file, indent, "0x%x,\t/* FC_PAD */\n", FC_PAD);
1363  *offset += 6;
1364  break;
1365  case FC_BIND_CONTEXT:
1366  handle_flags = get_contexthandle_flags( iface, handle_var->attrs, handle_var->type );
1367  print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) );
1368  print_file( file, indent, "0x%02x,\n", handle_flags );
1369  print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n",
1370  handle_stack_offset, handle_stack_offset );
1371  print_file( file, indent, "0x%02x,\n", get_context_handle_offset( handle_var->type ) );
1372  print_file( file, indent, "0x%02x,\t/* param %hu */\n", handle_param_num, handle_param_num );
1373  *offset += 6;
1374  break;
1375  }
1376  }
1377 
1378  if (get_stub_mode() == MODE_Oif)
1379  {
1380  unsigned char oi2_flags = get_func_oi2_flags( func );
1381  unsigned char ext_flags = 0;
1382  unsigned int size;
1383 
1384  if (is_attr( func->attrs, ATTR_NOTIFY )) ext_flags |= 0x08; /* HasNotify */
1385  if (is_attr( func->attrs, ATTR_NOTIFYFLAG )) ext_flags |= 0x10; /* HasNotify2 */
1386  if (iface == iface->details.iface->async_iface) oi2_flags |= 0x20;
1387 
1389  print_file( file, indent, "NdrFcShort(0x%x),\t/* client buffer = %u */\n", size, size );
1391  print_file( file, indent, "NdrFcShort(0x%x),\t/* server buffer = %u */\n", size, size );
1392  print_file( file, indent, "0x%02x,\n", oi2_flags );
1393  print_file( file, indent, "0x%02x,\t/* %u params */\n", nb_args, nb_args );
1394  print_file( file, indent, "0x%02x,\n", pointer_size == 8 ? 10 : 8 );
1395  print_file( file, indent, "0x%02x,\n", ext_flags );
1396  print_file( file, indent, "NdrFcShort(0x0),\n" ); /* server corr hint */
1397  print_file( file, indent, "NdrFcShort(0x0),\n" ); /* client corr hint */
1398  print_file( file, indent, "NdrFcShort(0x0),\n" ); /* FIXME: notify index */
1399  *offset += 14;
1400  if (pointer_size == 8)
1401  {
1402  unsigned short pos = 0, fpu_mask = 0;
1403 
1404  if (is_object( iface )) pos += 2;
1406  {
1407  if (type_get_type( var->type ) == TYPE_BASIC)
1408  {
1409  switch (type_basic_get_type( var->type ))
1410  {
1411  case TYPE_BASIC_FLOAT: fpu_mask |= 1 << pos; break;
1412  case TYPE_BASIC_DOUBLE: fpu_mask |= 2 << pos; break;
1413  default: break;
1414  }
1415  }
1416  pos += 2;
1417  if (pos >= 16) break;
1418  }
1419  print_file( file, indent, "NdrFcShort(0x%x),\n", fpu_mask ); /* floating point mask */
1420  *offset += 2;
1421  }
1422  }
1423 }
1424 
1425 static void write_procformatstring_func( FILE *file, int indent, const type_t *iface,
1426  const var_t *func, unsigned int *offset,
1427  unsigned short num_proc )
1428 {
1429  unsigned int stack_offset = is_object( iface ) ? pointer_size : 0;
1430  int is_interpreted = is_interpreted_func( iface, func );
1431  int is_new_style = is_interpreted && (get_stub_mode() == MODE_Oif);
1432  var_t *retval = type_function_get_retval( func->type );
1433  unsigned char explicit_fc, implicit_fc;
1434  const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc );
1435 
1436  if (is_interpreted) write_proc_func_header( file, indent, iface, func, offset, num_proc );
1437 
1438  /* emit argument data */
1439  if (type_get_function_args(func->type))
1440  {
1441  const var_t *var;
1443  {
1444  if (var != handle_var || implicit_fc || explicit_fc != FC_BIND_PRIMITIVE)
1445  {
1446  print_file( file, 0, "/* %u (parameter %s) */\n", *offset, var->name );
1447  if (is_new_style)
1449  else
1450  *offset += write_old_procformatstring_type(file, indent, var, FALSE, is_interpreted);
1451  }
1452  else
1453  {
1455  }
1456  }
1457  }
1458 
1459  /* emit return value data */
1460  if (is_void(retval->type))
1461  {
1462  if (!is_new_style)
1463  {
1464  print_file(file, 0, "/* %u (void) */\n", *offset);
1465  print_file(file, indent, "0x5b,\t/* FC_END */\n");
1466  print_file(file, indent, "0x5c,\t/* FC_PAD */\n");
1467  *offset += 2;
1468  }
1469  }
1470  else
1471  {
1472  print_file( file, 0, "/* %u (return value) */\n", *offset );
1473  if (is_new_style)
1475  else
1476  *offset += write_old_procformatstring_type(file, indent, retval, TRUE, is_interpreted);
1477  }
1478 }
1479 
1480 static void for_each_iface(const statement_list_t *stmts,
1481  void (*proc)(type_t *iface, FILE *file, int indent, unsigned int *offset),
1482  type_pred_t pred, FILE *file, int indent, unsigned int *offset)
1483 {
1484  const statement_t *stmt;
1485  type_t *iface;
1486 
1487  if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
1488  {
1489  if (stmt->type != STMT_TYPE || type_get_type(stmt->u.type) != TYPE_INTERFACE)
1490  continue;
1491  iface = stmt->u.type;
1492  if (!pred(iface)) continue;
1493  proc(iface, file, indent, offset);
1494  if (iface->details.iface->async_iface)
1495  proc(iface->details.iface->async_iface, file, indent, offset);
1496  }
1497 }
1498 
1499 static void write_iface_procformatstring(type_t *iface, FILE *file, int indent, unsigned int *offset)
1500 {
1501  const statement_t *stmt;
1502  const type_t *parent = type_iface_get_inherit( iface );
1503  int count = parent ? count_methods( parent ) : 0;
1504 
1506  {
1507  var_t *func = stmt->u.var;
1508  if (is_local(func->attrs)) continue;
1510  }
1511 }
1512 
1514 {
1515  int indent = 0;
1516  unsigned int offset = 0;
1517 
1518  print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
1519  print_file(file, indent, "{\n");
1520  indent++;
1521  print_file(file, indent, "0,\n");
1522  print_file(file, indent, "{\n");
1523  indent++;
1524 
1526 
1527  print_file(file, indent, "0x0\n");
1528  indent--;
1529  print_file(file, indent, "}\n");
1530  indent--;
1531  print_file(file, indent, "};\n");
1532  print_file(file, indent, "\n");
1533 }
1534 
1536 {
1537  const statement_t *stmt;
1538  int indent = 0;
1539 
1540  print_file( file, indent, "static const unsigned short %s_FormatStringOffsetTable[] =\n",
1541  iface->name );
1542  print_file( file, indent, "{\n" );
1543  indent++;
1545  {
1546  var_t *func = stmt->u.var;
1547  if (is_local( func->attrs )) continue;
1548  print_file( file, indent, "%u, /* %s */\n", func->procstring_offset, func->name );
1549  }
1550  indent--;
1551  print_file( file, indent, "};\n\n" );
1552 }
1553 
1554 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
1555 {
1556  unsigned char fc;
1557 
1558  if (type_get_type(type) == TYPE_BASIC)
1560  else if (type_get_type(type) == TYPE_ENUM)
1561  fc = get_enum_fc(type);
1562  else
1563  return 0;
1564 
1565  print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
1566  *typestring_offset += 1;
1567  return 1;
1568 }
1569 
1570 /* write conformance / variance descriptor */
1571 static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type,
1572  unsigned int baseoff, const type_t *type,
1573  const expr_t *expr)
1574 {
1575  unsigned char operator_type = 0;
1576  unsigned char conftype = FC_NORMAL_CONFORMANCE;
1577  const char *conftype_string = "field";
1578  const expr_t *subexpr;
1579  const type_t *iface = NULL;
1580  const char *name;
1581 
1582  if (!expr)
1583  {
1584  print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
1585  return 4;
1586  }
1587 
1588  if (expr->is_const)
1589  {
1590  if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
1591  error("write_conf_or_var_desc: constant value %d is greater than "
1592  "the maximum constant size of %d\n", expr->cval,
1593  UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
1594 
1595  print_file(file, 2, "0x%x, /* Corr desc: constant, val = %d */\n",
1596  FC_CONSTANT_CONFORMANCE, expr->cval);
1597  print_file(file, 2, "0x%x,\n", expr->cval >> 16);
1598  print_file(file, 2, "NdrFcShort(0x%hx),\n", (unsigned short)expr->cval);
1599 
1600  return 4;
1601  }
1602 
1603  if (!cont_type) /* top-level conformance */
1604  {
1605  conftype = FC_TOP_LEVEL_CONFORMANCE;
1606  conftype_string = "parameter";
1607  cont_type = current_func->type;
1608  name = current_func->name;
1609  iface = current_iface;
1610  }
1611  else
1612  {
1613  name = cont_type->name;
1615  {
1616  conftype = FC_POINTER_CONFORMANCE;
1617  conftype_string = "field pointer";
1618  }
1619  }
1620 
1621  subexpr = expr;
1622  switch (subexpr->type)
1623  {
1624  case EXPR_PPTR:
1625  subexpr = subexpr->ref;
1626  operator_type = FC_DEREFERENCE;
1627  break;
1628  case EXPR_DIV:
1629  if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
1630  {
1631  subexpr = subexpr->ref;
1632  operator_type = FC_DIV_2;
1633  }
1634  break;
1635  case EXPR_MUL:
1636  if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
1637  {
1638  subexpr = subexpr->ref;
1639  operator_type = FC_MULT_2;
1640  }
1641  break;
1642  case EXPR_SUB:
1643  if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
1644  {
1645  subexpr = subexpr->ref;
1646  operator_type = FC_SUB_1;
1647  }
1648  break;
1649  case EXPR_ADD:
1650  if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
1651  {
1652  subexpr = subexpr->ref;
1653  operator_type = FC_ADD_1;
1654  }
1655  break;
1656  default:
1657  break;
1658  }
1659 
1660  if (subexpr->type == EXPR_IDENTIFIER)
1661  {
1662  const type_t *correlation_variable = NULL;
1663  unsigned char param_type = 0;
1664  unsigned int offset = 0;
1665  const var_t *var;
1666  struct expr_loc expr_loc;
1667 
1668  if (type_get_type(cont_type) == TYPE_FUNCTION)
1669  {
1670  var_list_t *args = type_get_function_args( cont_type );
1671 
1672  if (is_object( iface )) offset += pointer_size;
1673  if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
1674  {
1675  if (var->name && !strcmp(var->name, subexpr->u.sval))
1676  {
1677  expr_loc.v = var;
1678  correlation_variable = var->type;
1679  break;
1680  }
1681  offset += get_stack_size( var, NULL );
1682  }
1683  }
1684  else
1685  {
1686  var_list_t *fields = type_struct_get_fields( cont_type );
1687 
1688  if (fields) LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
1689  {
1690  unsigned int size = field_memsize( var->type, &offset );
1691  if (var->name && !strcmp(var->name, subexpr->u.sval))
1692  {
1693  expr_loc.v = var;
1694  correlation_variable = var->type;
1695  break;
1696  }
1697  offset += size;
1698  }
1699  }
1700 
1701  if (!correlation_variable)
1702  error("write_conf_or_var_desc: couldn't find variable %s in %s\n", subexpr->u.sval, name);
1703  expr_loc.attr = NULL;
1704  correlation_variable = expr_resolve_type(&expr_loc, cont_type, expr);
1705 
1706  offset -= baseoff;
1707 
1708  if (type_get_type(correlation_variable) == TYPE_BASIC)
1709  {
1710  switch (get_basic_fc(correlation_variable))
1711  {
1712  case FC_CHAR:
1713  case FC_SMALL:
1714  param_type = FC_SMALL;
1715  break;
1716  case FC_BYTE:
1717  case FC_USMALL:
1718  param_type = FC_USMALL;
1719  break;
1720  case FC_WCHAR:
1721  case FC_SHORT:
1722  param_type = FC_SHORT;
1723  break;
1724  case FC_USHORT:
1725  param_type = FC_USHORT;
1726  break;
1727  case FC_LONG:
1728  param_type = FC_LONG;
1729  break;
1730  case FC_ULONG:
1731  param_type = FC_ULONG;
1732  break;
1733  default:
1734  error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
1735  get_basic_fc(correlation_variable));
1736  }
1737  }
1738  else if (type_get_type(correlation_variable) == TYPE_ENUM)
1739  {
1740  if (get_enum_fc(correlation_variable) == FC_ENUM32)
1741  param_type = FC_LONG;
1742  else
1743  param_type = FC_SHORT;
1744  }
1745  else if (type_get_type(correlation_variable) == TYPE_POINTER)
1746  {
1747  if (pointer_size == 8)
1748  param_type = FC_HYPER;
1749  else
1750  param_type = FC_LONG;
1751  }
1752  else
1753  {
1754  error("write_conf_or_var_desc: non-arithmetic type used as correlation variable %s\n",
1755  subexpr->u.sval);
1756  return 0;
1757  }
1758 
1759  print_file(file, 2, "0x%x,\t/* Corr desc: %s %s, %s */\n",
1760  conftype | param_type, conftype_string, subexpr->u.sval, string_of_type(param_type));
1761  print_file(file, 2, "0x%x,\t/* %s */\n", operator_type,
1762  operator_type ? string_of_type(operator_type) : "no operators");
1763  print_file(file, 2, "NdrFcShort(0x%hx),\t/* offset = %d */\n",
1764  (unsigned short)offset, offset);
1765  }
1766  else if (!iface || is_interpreted_func( iface, current_func ))
1767  {
1768  unsigned int callback_offset = 0;
1769  struct expr_eval_routine *eval;
1770  int found = 0;
1771 
1773  {
1774  if (eval->cont_type == cont_type ||
1775  (type_get_type( eval->cont_type ) == type_get_type( cont_type ) &&
1776  eval->iface == iface &&
1777  eval->name && name && !strcmp(eval->name, name) &&
1778  !compare_expr(eval->expr, expr)))
1779  {
1780  found = 1;
1781  break;
1782  }
1783  callback_offset++;
1784  }
1785 
1786  if (!found)
1787  {
1788  eval = xmalloc (sizeof(*eval));
1789  eval->iface = iface;
1790  eval->cont_type = cont_type;
1791  eval->name = xstrdup( name );
1792  eval->baseoff = baseoff;
1793  eval->expr = expr;
1795  }
1796 
1797  if (callback_offset > USHRT_MAX)
1798  error("Maximum number of callback routines reached\n");
1799 
1800  print_file(file, 2, "0x%x,\t/* Corr desc: %s in %s */\n", conftype, conftype_string, name);
1801  print_file(file, 2, "0x%x,\t/* %s */\n", FC_CALLBACK, "FC_CALLBACK");
1802  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)callback_offset, callback_offset);
1803  }
1804  else /* output a dummy corr desc that isn't used */
1805  {
1806  print_file(file, 2, "0x%x,\t/* Corr desc: unused for %s */\n", conftype, name);
1807  print_file(file, 2, "0x0,\n" );
1808  print_file(file, 2, "NdrFcShort(0x0),\n" );
1809  }
1810  return 4;
1811 }
1812 
1813 /* return size and start offset of a data field based on current offset */
1814 static unsigned int field_memsize(const type_t *type, unsigned int *offset)
1815 {
1816  unsigned int align = 0;
1817  unsigned int size = type_memsize_and_alignment( type, &align );
1818 
1819  *offset = ROUND_SIZE( *offset, align );
1820  return size;
1821 }
1822 
1823 static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align)
1824 {
1825  unsigned int size = 0;
1826  unsigned int max_align;
1827  const var_t *v;
1828 
1829  if (!fields) return 0;
1830  LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
1831  {
1832  unsigned int falign = 0;
1833  unsigned int fsize = type_memsize_and_alignment(v->type, &falign);
1834  if (*align < falign) *align = falign;
1835  falign = clamp_align(falign);
1836  size = ROUND_SIZE(size, falign);
1837  size += fsize;
1838  }
1839 
1840  max_align = clamp_align(*align);
1841  size = ROUND_SIZE(size, max_align);
1842 
1843  return size;
1844 }
1845 
1846 static unsigned int union_memsize(const var_list_t *fields, unsigned int *pmaxa)
1847 {
1848  unsigned int size, maxs = 0;
1849  unsigned int align = *pmaxa;
1850  const var_t *v;
1851 
1852  if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
1853  {
1854  /* we could have an empty default field with NULL type */
1855  if (v->type)
1856  {
1858  if (maxs < size) maxs = size;
1859  if (*pmaxa < align) *pmaxa = align;
1860  }
1861  }
1862 
1863  return maxs;
1864 }
1865 
1866 unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align)
1867 {
1868  unsigned int size = 0;
1869 
1870  switch (type_get_type(t))
1871  {
1872  case TYPE_BASIC:
1873  switch (get_basic_fc(t))
1874  {
1875  case FC_BYTE:
1876  case FC_CHAR:
1877  case FC_USMALL:
1878  case FC_SMALL:
1879  size = 1;
1880  if (size > *align) *align = size;
1881  break;
1882  case FC_WCHAR:
1883  case FC_USHORT:
1884  case FC_SHORT:
1885  size = 2;
1886  if (size > *align) *align = size;
1887  break;
1888  case FC_ULONG:
1889  case FC_LONG:
1890  case FC_ERROR_STATUS_T:
1891  case FC_FLOAT:
1892  size = 4;
1893  if (size > *align) *align = size;
1894  break;
1895  case FC_HYPER:
1896  case FC_DOUBLE:
1897  size = 8;
1898  if (size > *align) *align = size;
1899  break;
1900  case FC_INT3264:
1901  case FC_UINT3264:
1902  case FC_BIND_PRIMITIVE:
1903  assert( pointer_size );
1904  size = pointer_size;
1905  if (size > *align) *align = size;
1906  break;
1907  default:
1908  error("type_memsize: Unknown type 0x%x\n", get_basic_fc(t));
1909  size = 0;
1910  }
1911  break;
1912  case TYPE_ENUM:
1913  switch (get_enum_fc(t))
1914  {
1915  case FC_ENUM16:
1916  case FC_ENUM32:
1917  size = 4;
1918  if (size > *align) *align = size;
1919  break;
1920  default:
1921  error("type_memsize: Unknown enum type\n");
1922  size = 0;
1923  }
1924  break;
1925  case TYPE_STRUCT:
1927  break;
1930  break;
1931  case TYPE_UNION:
1933  break;
1934  case TYPE_POINTER:
1935  case TYPE_INTERFACE:
1936  assert( pointer_size );
1937  size = pointer_size;
1938  if (size > *align) *align = size;
1939  break;
1940  case TYPE_ARRAY:
1942  {
1943  if (is_conformant_array(t))
1944  {
1946  size = 0;
1947  }
1948  else
1951  }
1952  else /* declared as a pointer */
1953  {
1954  assert( pointer_size );
1955  size = pointer_size;
1956  if (size > *align) *align = size;
1957  }
1958  break;
1959  case TYPE_ALIAS:
1960  case TYPE_VOID:
1961  case TYPE_COCLASS:
1962  case TYPE_MODULE:
1963  case TYPE_FUNCTION:
1964  case TYPE_BITFIELD:
1965  /* these types should not be encountered here due to language
1966  * restrictions (interface, void, coclass, module), logical
1967  * restrictions (alias - due to type_get_type call above) or
1968  * checking restrictions (function, bitfield). */
1969  assert(0);
1970  }
1971 
1972  return size;
1973 }
1974 
1975 unsigned int type_memsize(const type_t *t)
1976 {
1977  unsigned int align = 0;
1978  return type_memsize_and_alignment( t, &align );
1979 }
1980 
1981 static unsigned int type_buffer_alignment(const type_t *t)
1982 {
1983  const var_list_t *fields;
1984  const var_t *var;
1985  unsigned int max = 0, align;
1986 
1987  switch (type_get_type(t))
1988  {
1989  case TYPE_BASIC:
1990  switch (get_basic_fc(t))
1991  {
1992  case FC_BYTE:
1993  case FC_CHAR:
1994  case FC_USMALL:
1995  case FC_SMALL:
1996  return 1;
1997  case FC_WCHAR:
1998  case FC_USHORT:
1999  case FC_SHORT:
2000  return 2;
2001  case FC_ULONG:
2002  case FC_LONG:
2003  case FC_ERROR_STATUS_T:
2004  case FC_FLOAT:
2005  case FC_INT3264:
2006  case FC_UINT3264:
2007  return 4;
2008  case FC_HYPER:
2009  case FC_DOUBLE:
2010  return 8;
2011  default:
2012  error("type_buffer_alignment: Unknown type 0x%x\n", get_basic_fc(t));
2013  }
2014  break;
2015  case TYPE_ENUM:
2016  switch (get_enum_fc(t))
2017  {
2018  case FC_ENUM16:
2019  return 2;
2020  case FC_ENUM32:
2021  return 4;
2022  default:
2023  error("type_buffer_alignment: Unknown enum type\n");
2024  }
2025  break;
2026  case TYPE_STRUCT:
2027  if (!(fields = type_struct_get_fields(t))) break;
2028  LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
2029  {
2030  if (!var->type) continue;
2031  align = type_buffer_alignment( var->type );
2032  if (max < align) max = align;
2033  }
2034  break;
2036  if (!(fields = type_encapsulated_union_get_fields(t))) break;
2037  LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
2038  {
2039  if (!var->type) continue;
2040  align = type_buffer_alignment( var->type );
2041  if (max < align) max = align;
2042  }
2043  break;
2044  case TYPE_UNION:
2045  if (!(fields = type_union_get_cases(t))) break;
2046  LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
2047  {
2048  if (!var->type) continue;
2049  align = type_buffer_alignment( var->type );
2050  if (max < align) max = align;
2051  }
2052  break;
2053  case TYPE_ARRAY:
2056  /* else fall through */
2057  case TYPE_POINTER:
2058  return 4;
2059  case TYPE_INTERFACE:
2060  case TYPE_ALIAS:
2061  case TYPE_VOID:
2062  case TYPE_COCLASS:
2063  case TYPE_MODULE:
2064  case TYPE_FUNCTION:
2065  case TYPE_BITFIELD:
2066  /* these types should not be encountered here due to language
2067  * restrictions (interface, void, coclass, module), logical
2068  * restrictions (alias - due to type_get_type call above) or
2069  * checking restrictions (function, bitfield). */
2070  assert(0);
2071  }
2072  return max;
2073 }
2074 
2076 {
2077  const var_t *var;
2079  return TRUE;
2080  if (!type_get_function_args(func->type))
2081  return FALSE;
2083  if (type_has_full_pointer( var->type, var->attrs, TRUE ))
2084  return TRUE;
2085  return FALSE;
2086 }
2087 
2088 void write_full_pointer_init(FILE *file, int indent, const var_t *func, int is_server)
2089 {
2090  print_file(file, indent, "__frame->_StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,%s);\n",
2091  is_server ? "XLAT_SERVER" : "XLAT_CLIENT");
2092  fprintf(file, "\n");
2093 }
2094 
2096 {
2097  print_file(file, indent, "NdrFullPointerXlatFree(__frame->_StubMsg.FullPtrXlatTables);\n");
2098  fprintf(file, "\n");
2099 }
2100 
2101 static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs,
2102  const type_t *type,
2103  enum type_context context,
2104  unsigned int offset,
2105  unsigned int *typeformat_offset)
2106 {
2107  unsigned int start_offset = *typeformat_offset;
2108  short reloff = offset - (*typeformat_offset + 2);
2109  int in_attr, out_attr;
2110  int pointer_type;
2111  unsigned char flags = 0;
2112 
2113  pointer_type = get_pointer_fc_context(type, attrs, context);
2114 
2115  in_attr = is_attr(attrs, ATTR_IN);
2116  out_attr = is_attr(attrs, ATTR_OUT);
2117  if (!in_attr && !out_attr) in_attr = 1;
2118 
2120  {
2121  if (out_attr && !in_attr && pointer_type == FC_RP)
2123  }
2124  else if (get_stub_mode() == MODE_Oif)
2125  {
2126  if (context == TYPE_CONTEXT_TOPLEVELPARAM && is_ptr(type) && pointer_type == FC_RP)
2127  {
2129  {
2130  case TGT_STRING:
2131  case TGT_POINTER:
2132  case TGT_CTXT_HANDLE:
2135  break;
2136  case TGT_IFACE_POINTER:
2137  if (in_attr && out_attr)
2139  break;
2140  default:
2141  break;
2142  }
2143  }
2144  }
2145 
2146  if (is_ptr(type))
2147  {
2149  if(is_declptr(ref) && !is_user_type(ref))
2151  if (pointer_type != FC_RP) {
2152  flags |= get_attrv(type->attrs, ATTR_ALLOCATE);
2153  }
2154  }
2155 
2156  print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
2157  pointer_type,
2158  flags,
2159  string_of_type(pointer_type));
2160  if (file)
2161  {
2162  if (flags & FC_ALLOCED_ON_STACK)
2163  fprintf(file, " [allocated_on_stack]");
2164  if (flags & FC_POINTER_DEREF)
2165  fprintf(file, " [pointer_deref]");
2166  if (flags & FC_DONT_FREE)
2167  fprintf(file, " [dont_free]");
2169  fprintf(file, " [all_nodes]");
2170  fprintf(file, " */\n");
2171  }
2172 
2173  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, offset);
2174  *typeformat_offset += 4;
2175 
2176  return start_offset;
2177 }
2178 
2179 static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs,
2180  const type_t *type, enum type_context context)
2181 {
2182  unsigned char fc;
2183  unsigned char pointer_fc;
2184  const type_t *ref;
2185  int in_attr = is_attr(attrs, ATTR_IN);
2186  int out_attr = is_attr(attrs, ATTR_OUT);
2187  unsigned char flags = FC_SIMPLE_POINTER;
2188 
2189  /* for historical reasons, write_simple_pointer also handled string types,
2190  * but no longer does. catch bad uses of the function with this check */
2191  if (is_string_type(attrs, type))
2192  error("write_simple_pointer: can't handle type %s which is a string type\n", type->name);
2193 
2194  pointer_fc = get_pointer_fc_context(type, attrs, context);
2195 
2197  if (type_get_type(ref) == TYPE_ENUM)
2198  fc = get_enum_fc(ref);
2199  else
2200  fc = get_basic_fc(ref);
2201 
2203  {
2204  if (out_attr && !in_attr && pointer_fc == FC_RP)
2206  }
2207  else if (get_stub_mode() == MODE_Oif)
2208  {
2209  if (context == TYPE_CONTEXT_TOPLEVELPARAM && fc == FC_ENUM16 && pointer_fc == FC_RP)
2211  }
2212 
2213  print_file(file, 2, "0x%02x, 0x%x,\t/* %s %s[simple_pointer] */\n",
2214  pointer_fc, flags, string_of_type(pointer_fc),
2215  flags & FC_ALLOCED_ON_STACK ? "[allocated_on_stack] " : "");
2216  print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
2217  print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
2218  return 4;
2219 }
2220 
2221 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
2222 {
2223  print_file(file, 0, "/* %u (", tfsoff);
2225  print_file(file, 0, ") */\n");
2226 }
2227 
2228 static unsigned int write_pointer_tfs(FILE *file, const attr_list_t *attrs,
2229  type_t *type, unsigned int ref_offset,
2230  enum type_context context,
2231  unsigned int *typestring_offset)
2232 {
2233  unsigned int offset = *typestring_offset;
2235 
2238 
2239  switch (typegen_detect_type(ref, attrs, TDT_ALL_TYPES))
2240  {
2241  case TGT_BASIC:
2242  case TGT_ENUM:
2243  *typestring_offset += write_simple_pointer(file, attrs, type, context);
2244  break;
2245  default:
2246  if (ref_offset)
2247  write_nonsimple_pointer(file, attrs, type, context, ref_offset, typestring_offset);
2248  break;
2249  }
2250 
2251  return offset;
2252 }
2253 
2254 static int processed(const type_t *type)
2255 {
2256  return type->typestring_offset && !type->tfswrite;
2257 }
2258 
2260 {
2261  if (is_ptr(t))
2262  return TRUE;
2263  else if (type_get_type(t) == TYPE_STRUCT)
2264  {
2265  switch (get_struct_fc(t))
2266  {
2267  case FC_PSTRUCT:
2268  case FC_CSTRUCT:
2269  case FC_CPSTRUCT:
2270  case FC_CVSTRUCT:
2271  return TRUE;
2272  }
2273  }
2274  /* Note: Since this only applies to user types, we can't have a conformant
2275  array here, and strings should get filed under pointer in this case. */
2276  return FALSE;
2277 }
2278 
2279 static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
2280 {
2281  unsigned int start, absoff, flags;
2282  const char *name = NULL;
2283  type_t *utype = get_user_type(type, &name);
2284  unsigned int usize = type_memsize(utype);
2285  unsigned int ualign = type_buffer_alignment(utype);
2286  unsigned int size = type_memsize(type);
2287  unsigned short funoff = user_type_offset(name);
2288  short reloff;
2289 
2290  if (processed(type)) return type->typestring_offset;
2291 
2292  guard_rec(type);
2293 
2294  if(user_type_has_variable_size(utype)) usize = 0;
2295 
2296  if (type_get_type(utype) == TYPE_BASIC ||
2297  type_get_type(utype) == TYPE_ENUM)
2298  {
2299  unsigned char fc;
2300 
2301  if (type_get_type(utype) == TYPE_ENUM)
2302  fc = get_enum_fc(utype);
2303  else
2304  fc = get_basic_fc(utype);
2305 
2306  absoff = *tfsoff;
2307  print_start_tfs_comment(file, utype, absoff);
2308  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
2309  print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
2310  *tfsoff += 2;
2311  }
2312  else
2313  {
2314  if (!processed(utype))
2315  write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
2316  absoff = utype->typestring_offset;
2317  }
2318 
2319  if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == FC_RP)
2320  flags = 0x40;
2321  else if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == FC_UP)
2322  flags = 0x80;
2323  else
2324  flags = 0;
2325 
2326  start = *tfsoff;
2329  print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", FC_USER_MARSHAL);
2330  print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
2331  flags | (ualign - 1), ualign - 1, flags);
2332  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
2333  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)size, size);
2334  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)usize, usize);
2335  *tfsoff += 8;
2336  reloff = absoff - *tfsoff;
2337  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, absoff);
2338  *tfsoff += 2;
2339  return start;
2340 }
2341 
2342 static void write_member_type(FILE *file, const type_t *cont,
2343  int cont_is_complex, const attr_list_t *attrs,
2344  const type_t *type, unsigned int *corroff,
2345  unsigned int *tfsoff)
2346 {
2348  {
2349  unsigned int absoff;
2350  short reloff;
2351 
2352  if (type_get_type(type) == TYPE_UNION && is_attr(attrs, ATTR_SWITCHIS))
2353  {
2354  absoff = *corroff;
2355  *corroff += 8;
2356  }
2357  else
2358  {
2359  absoff = type->typestring_offset;
2360  }
2361  reloff = absoff - (*tfsoff + 2);
2362 
2363  print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
2364  /* padding is represented using FC_STRUCTPAD* types, so presumably
2365  * this is left over in the format for historical purposes in MIDL
2366  * or rpcrt4. */
2367  print_file(file, 2, "0x0,\n");
2368  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2369  reloff, reloff, absoff);
2370  *tfsoff += 4;
2371  }
2372  else if (is_ptr(type) || is_conformant_array(type))
2373  {
2374  unsigned char fc = cont_is_complex ? FC_POINTER : FC_LONG;
2375  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
2376  *tfsoff += 1;
2377  }
2378  else if (!write_base_type(file, type, tfsoff))
2379  error("Unsupported member type %d\n", type_get_type(type));
2380 }
2381 
2382 static void write_array_element_type(FILE *file, const attr_list_t *attrs, const type_t *type,
2383  int cont_is_complex, unsigned int *tfsoff)
2384 {
2386 
2387  if (!is_embedded_complex(elem) && is_ptr(elem))
2388  {
2390 
2391  if (processed(ref))
2392  {
2394  ref->typestring_offset, tfsoff);
2395  return;
2396  }
2397  if (cont_is_complex && is_string_type(attrs, elem))
2398  {
2400  return;
2401  }
2402  if (!is_string_type(NULL, elem) &&
2404  {
2406  return;
2407  }
2408  }
2409  write_member_type(file, type, cont_is_complex, NULL, elem, NULL, tfsoff);
2410 }
2411 
2412 static void write_end(FILE *file, unsigned int *tfsoff)
2413 {
2414  if (*tfsoff % 2 == 0)
2415  {
2416  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
2417  *tfsoff += 1;
2418  }
2419  print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END);
2420  *tfsoff += 1;
2421 }
2422 
2423 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
2424 {
2425  unsigned int offset = 0;
2427  var_t *f;
2428 
2430  {
2431  type_t *ft = f->type;
2432  unsigned int size = field_memsize( ft, &offset );
2433  if (type_get_type(ft) == TYPE_UNION && is_attr(f->attrs, ATTR_SWITCHIS))
2434  {
2435  short reloff;
2436  unsigned int absoff = ft->typestring_offset;
2437  if (is_attr(ft->attrs, ATTR_SWITCHTYPE))
2438  absoff += 8; /* we already have a corr descr, skip it */
2439  reloff = absoff - (*tfsoff + 6);
2440  print_file(file, 0, "/* %d */\n", *tfsoff);
2441  print_file(file, 2, "0x%x,\t/* FC_NON_ENCAPSULATED_UNION */\n", FC_NON_ENCAPSULATED_UNION);
2442  print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", FC_LONG);
2444  get_attrp(f->attrs, ATTR_SWITCHIS));
2445  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2446  (unsigned short)reloff, reloff, absoff);
2447  *tfsoff += 8;
2448  }
2449  offset += size;
2450  }
2451 }
2452 
2454  FILE *file, const attr_list_t *attrs, type_t *type,
2455  unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2456  unsigned int *typestring_offset)
2457 {
2458  int written = 0;
2459 
2462  {
2463  if (offset_in_memory && offset_in_buffer)
2464  {
2465  unsigned int memsize;
2466 
2467  /* pointer instance
2468  *
2469  * note that MSDN states that for pointer layouts in structures,
2470  * this is a negative offset from the end of the structure, but
2471  * this statement is incorrect. all offsets are positive */
2472  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Memory offset = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory);
2473  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Buffer offset = %d */\n", (unsigned short)*offset_in_buffer, *offset_in_buffer);
2474 
2475  memsize = type_memsize(type);
2476  *offset_in_memory += memsize;
2477  /* increment these separately as in the case of conformant (varying)
2478  * structures these start at different values */
2479  *offset_in_buffer += memsize;
2480  }
2481  *typestring_offset += 4;
2482 
2483  if (is_ptr(type))
2484  {
2486 
2487  if (is_string_type(attrs, type))
2488  write_string_tfs(file, attrs, type, TYPE_CONTEXT_CONTAINER, NULL, typestring_offset);
2489  else if (processed(ref))
2491  ref->typestring_offset, typestring_offset);
2492  else if (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM)
2493  *typestring_offset += write_simple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER);
2494  else
2495  error("write_pointer_description_offsets: type format string unknown\n");
2496  }
2497  else
2498  {
2499  unsigned int offset = type->typestring_offset;
2500  /* skip over the pointer that is written for strings, since a
2501  * pointer has to be written in-place here */
2502  if (is_string_type(attrs, type))
2503  offset += 4;
2504  write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER, offset, typestring_offset);
2505  }
2506 
2507  return 1;
2508  }
2509 
2510  if (is_array(type))
2511  {
2513  file, attrs, type_array_get_element(type), offset_in_memory,
2514  offset_in_buffer, typestring_offset);
2515  }
2516  else if (is_non_complex_struct(type))
2517  {
2518  /* otherwise search for interesting fields to parse */
2519  const var_t *v;
2521  {
2522  if (offset_in_memory && offset_in_buffer)
2523  {
2524  unsigned int padding;
2525  unsigned int align = 0;
2527  padding = ROUNDING(*offset_in_memory, align);
2528  *offset_in_memory += padding;
2529  *offset_in_buffer += padding;
2530  }
2532  file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
2533  typestring_offset);
2534  }
2535  }
2536  else
2537  {
2538  if (offset_in_memory && offset_in_buffer)
2539  {
2540  unsigned int memsize = type_memsize(type);
2541  *offset_in_memory += memsize;
2542  /* increment these separately as in the case of conformant (varying)
2543  * structures these start at different values */
2544  *offset_in_buffer += memsize;
2545  }
2546  }
2547 
2548  return written;
2549 }
2550 
2552  FILE *file, const attr_list_t *attrs, type_t *type,
2553  unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2554  unsigned int *typestring_offset)
2555 {
2556  int written = 0;
2557 
2558  if (is_ptr(type) ||
2560  {
2561  print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", FC_NO_REPEAT);
2562  print_file(file, 2, "0x%02x, /* FC_PAD */\n", FC_PAD);
2563  *typestring_offset += 2;
2564 
2566  offset_in_memory, offset_in_buffer, typestring_offset);
2567  }
2568 
2570  {
2571  const var_t *v;
2573  {
2574  if (offset_in_memory && offset_in_buffer)
2575  {
2576  unsigned int padding;
2577  unsigned int align = 0;
2579  padding = ROUNDING(*offset_in_memory, align);
2580  *offset_in_memory += padding;
2581  *offset_in_buffer += padding;
2582  }
2584  file, v->attrs, v->type,
2585  offset_in_memory, offset_in_buffer, typestring_offset);
2586  }
2587  }
2588  else
2589  {
2590  unsigned int memsize = type_memsize(type);
2591  *offset_in_memory += memsize;
2592  /* increment these separately as in the case of conformant (varying)
2593  * structures these start at different values */
2594  *offset_in_buffer += memsize;
2595  }
2596 
2597  return written;
2598 }
2599 
2600 /* Note: if file is NULL return value is number of pointers to write, else
2601  * it is the number of type format characters written */
2603  FILE *file, const attr_list_t *attrs, type_t *type,
2604  unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2605  unsigned int *typestring_offset)
2606 {
2607  int pointer_count = 0;
2608 
2609  if (type_get_type(type) == TYPE_ARRAY &&
2611  {
2612  unsigned int temp = 0;
2613  /* unfortunately, this needs to be done in two passes to avoid
2614  * writing out redundant FC_FIXED_REPEAT descriptions */
2615  pointer_count = write_pointer_description_offsets(
2616  NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
2617  if (pointer_count > 0)
2618  {
2619  unsigned int increment_size;
2620  unsigned int offset_of_array_pointer_mem = 0;
2621  unsigned int offset_of_array_pointer_buf = 0;
2622 
2623  increment_size = type_memsize(type_array_get_element(type));
2624 
2625  print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", FC_FIXED_REPEAT);
2626  print_file(file, 2, "0x%02x, /* FC_PAD */\n", FC_PAD);
2627  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Iterations = %d */\n", (unsigned short)type_array_get_dim(type), type_array_get_dim(type));
2628  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
2629  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory);
2630  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count);
2631  *typestring_offset += 10;
2632 
2633  pointer_count = write_pointer_description_offsets(
2634  file, attrs, type, &offset_of_array_pointer_mem,
2635  &offset_of_array_pointer_buf, typestring_offset);
2636  }
2637  }
2638  else if (type_get_type(type) == TYPE_STRUCT)
2639  {
2640  const var_t *v;
2642  {
2643  if (offset_in_memory && offset_in_buffer)
2644  {
2645  unsigned int padding;
2646  unsigned int align = 0;
2648  padding = ROUNDING(*offset_in_memory, align);
2649  *offset_in_memory += padding;
2650  *offset_in_buffer += padding;
2651  }
2652  pointer_count += write_fixed_array_pointer_descriptions(
2653  file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
2654  typestring_offset);
2655  }
2656  }
2657  else
2658  {
2659  if (offset_in_memory && offset_in_buffer)
2660  {
2661  unsigned int memsize;
2662  memsize = type_memsize(type);
2663  *offset_in_memory += memsize;
2664  /* increment these separately as in the case of conformant (varying)
2665  * structures these start at different values */
2666  *offset_in_buffer += memsize;
2667  }
2668  }
2669 
2670  return pointer_count;
2671 }
2672 
2673 /* Note: if file is NULL return value is number of pointers to write, else
2674  * it is the number of type format characters written */
2676  FILE *file, const attr_list_t *attrs, type_t *type,
2677  unsigned int offset_in_memory, unsigned int *typestring_offset)
2678 {
2679  int pointer_count = 0;
2680 
2682  {
2683  unsigned int temp = 0;
2684  /* unfortunately, this needs to be done in two passes to avoid
2685  * writing out redundant FC_VARIABLE_REPEAT descriptions */
2686  pointer_count = write_pointer_description_offsets(
2687  NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
2688  if (pointer_count > 0)
2689  {
2690  unsigned int increment_size;
2691  unsigned int offset_of_array_pointer_mem = offset_in_memory;
2692  unsigned int offset_of_array_pointer_buf = offset_in_memory;
2693 
2694  increment_size = type_memsize(type_array_get_element(type));
2695 
2696  if (increment_size > USHRT_MAX)
2697  error("array size of %u bytes is too large\n", increment_size);
2698 
2699  print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", FC_VARIABLE_REPEAT);
2700  print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", FC_FIXED_OFFSET);
2701  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
2702  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)offset_in_memory, offset_in_memory);
2703  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count);
2704  *typestring_offset += 8;
2705 
2706  pointer_count = write_pointer_description_offsets(
2707  file, attrs, type_array_get_element(type),
2708  &offset_of_array_pointer_mem, &offset_of_array_pointer_buf,
2709  typestring_offset);
2710  }
2711  }
2712 
2713  return pointer_count;
2714 }
2715 
2716 /* Note: if file is NULL return value is number of pointers to write, else
2717  * it is the number of type format characters written */
2719  FILE *file, const attr_list_t *attrs, type_t *type,
2720  unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2721  unsigned int *typestring_offset)
2722 {
2723  int pointer_count = 0;
2724 
2726  {
2727  unsigned int temp = 0;
2728  /* unfortunately, this needs to be done in two passes to avoid
2729  * writing out redundant FC_VARIABLE_REPEAT descriptions */
2730  pointer_count = write_pointer_description_offsets(
2731  NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
2732  if (pointer_count > 0)
2733  {
2734  unsigned int increment_size;
2735 
2736  increment_size = type_memsize(type_array_get_element(type));
2737 
2738  if (increment_size > USHRT_MAX)
2739  error("array size of %u bytes is too large\n", increment_size);
2740 
2741  print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", FC_VARIABLE_REPEAT);
2742  print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", FC_VARIABLE_OFFSET);
2743  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
2744  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory);
2745  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count);
2746  *typestring_offset += 8;
2747 
2748  pointer_count = write_pointer_description_offsets(
2749  file, attrs, type_array_get_element(type), offset_in_memory,
2750  offset_in_buffer, typestring_offset);
2751  }
2752  }
2753  else if (type_get_type(type) == TYPE_STRUCT)
2754  {
2755  const var_t *v;
2757  {
2758  if (offset_in_memory && offset_in_buffer)
2759  {
2760  unsigned int align = 0, padding;
2761 
2762  if (is_array(v->type) && type_array_has_variance(v->type))
2763  {
2764  *offset_in_buffer = ROUND_SIZE(*offset_in_buffer, 4);
2765  /* skip over variance and offset in buffer */
2766  *offset_in_buffer += 8;
2767  }
2768 
2770  padding = ROUNDING(*offset_in_memory, align);
2771  *offset_in_memory += padding;
2772  *offset_in_buffer += padding;
2773  }
2775  file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
2776  typestring_offset);
2777  }
2778  }
2779  else
2780  {
2781  if (offset_in_memory && offset_in_buffer)
2782  {
2783  unsigned int memsize = type_memsize(type);
2784  *offset_in_memory += memsize;
2785  /* increment these separately as in the case of conformant (varying)
2786  * structures these start at different values */
2787  *offset_in_buffer += memsize;
2788  }
2789  }
2790 
2791  return pointer_count;
2792 }
2793 
2795  unsigned int *typestring_offset)
2796 {
2797  unsigned int offset_in_buffer;
2798  unsigned int offset_in_memory;
2799 
2800  /* pass 1: search for single instance of a pointer (i.e. don't descend
2801  * into arrays) */
2802  if (!is_array(type))
2803  {
2804  offset_in_memory = 0;
2805  offset_in_buffer = 0;
2807  file, NULL, type,
2808  &offset_in_memory, &offset_in_buffer, typestring_offset);
2809  }
2810 
2811  /* pass 2: search for pointers in fixed arrays */
2812  offset_in_memory = 0;
2813  offset_in_buffer = 0;
2815  file, NULL, type,
2816  &offset_in_memory, &offset_in_buffer, typestring_offset);
2817 
2818  /* pass 3: search for pointers in conformant only arrays (but don't descend
2819  * into conformant varying or varying arrays) */
2820  if (is_conformant_array(type) &&
2823  file, attrs, type, 0, typestring_offset);
2824  else if (type_get_type(type) == TYPE_STRUCT &&
2826  {
2829  type_memsize(type), typestring_offset);
2830  }
2831 
2832  /* pass 4: search for pointers in varying arrays */
2833  offset_in_memory = 0;
2834  offset_in_buffer = 0;
2836  file, NULL, type,
2837  &offset_in_memory, &offset_in_buffer, typestring_offset);
2838 }
2839 
2840 static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
2842  const char *name, unsigned int *typestring_offset)
2843 {
2844  unsigned int start_offset;
2845  unsigned char rtype;
2846  type_t *elem_type;
2847  int is_processed = processed(type);
2848 
2849  start_offset = *typestring_offset;
2850 
2851  if (is_declptr(type))
2852  {
2853  unsigned char flag = is_conformant_array(type) ? 0 : FC_SIMPLE_POINTER;
2854  int pointer_type = get_pointer_fc_context(type, attrs, context);
2855  if (!pointer_type)
2856  pointer_type = FC_RP;
2857  print_start_tfs_comment(file, type, *typestring_offset);
2858  print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
2859  pointer_type, flag, string_of_type(pointer_type),
2860  flag ? " [simple_pointer]" : "");
2861  *typestring_offset += 2;
2862  if (!flag)
2863  {
2864  print_file(file, 2, "NdrFcShort(0x2),\n");
2865  *typestring_offset += 2;
2866  }
2867  is_processed = FALSE;
2868  }
2869 
2870  if (is_array(type))
2871  elem_type = type_array_get_element(type);
2872  else
2873  elem_type = type_pointer_get_ref(type);
2874 
2875  if (type_get_type(elem_type) == TYPE_POINTER && is_array(type))
2876  return write_array_tfs(file, attrs, type, name, typestring_offset);
2877 
2878  if (type_get_type(elem_type) != TYPE_BASIC)
2879  {
2880  error("write_string_tfs: Unimplemented for non-basic type %s\n", name);
2881  return start_offset;
2882  }
2883 
2884  rtype = get_basic_fc(elem_type);
2885  if ((rtype != FC_BYTE) && (rtype != FC_CHAR) && (rtype != FC_WCHAR))
2886  {
2887  error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
2888  return start_offset;
2889  }
2890 
2892  {
2893  unsigned int dim = type_array_get_dim(type);
2894 
2895  if (is_processed) return start_offset;
2896 
2897  /* FIXME: multi-dimensional array */
2898  if (0xffffu < dim)
2899  error("array size for parameter %s exceeds %u bytes by %u bytes\n",
2900  name, 0xffffu, dim - 0xffffu);
2901 
2902  if (rtype == FC_WCHAR)
2903  WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
2904  else
2905  WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
2906  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
2907  *typestring_offset += 2;
2908 
2909  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)dim, dim);
2910  *typestring_offset += 2;
2911 
2912  update_tfsoff(type, start_offset, file);
2913  return start_offset;
2914  }
2915  else if (is_conformant_array(type))
2916  {
2917  if (rtype == FC_WCHAR)
2918  WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
2919  else
2920  WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
2921  print_file(file, 2, "0x%x,\t/* FC_STRING_SIZED */\n", FC_STRING_SIZED);
2922  *typestring_offset += 2;
2923 
2924  *typestring_offset += write_conf_or_var_desc(
2928  : 0),
2930 
2931  update_tfsoff(type, start_offset, file);
2932  return start_offset;
2933  }
2934  else
2935  {
2936  if (is_processed) return start_offset;
2937 
2938  if (rtype == FC_WCHAR)
2939  WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
2940  else
2941  WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
2942  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
2943  *typestring_offset += 2;
2944 
2945  update_tfsoff(type, start_offset, file);
2946  return start_offset;
2947  }
2948 }
2949 
2950 static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
2951  const char *name, unsigned int *typestring_offset)
2952 {
2953  const expr_t *length_is = type_array_get_variance(type);
2954  const expr_t *size_is = type_array_get_conformance(type);
2955  unsigned int align;
2956  unsigned int size;
2957  unsigned int start_offset;
2958  unsigned char fc;
2959  int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
2960  unsigned int baseoff
2963  : 0;
2964 
2965  if (!pointer_type)
2966  pointer_type = FC_RP;
2967 
2969  write_embedded_types(file, attrs, type_array_get_element(type), name, FALSE, typestring_offset);
2970 
2973  fc = get_array_fc(type);
2974 
2975  start_offset = *typestring_offset;
2976  update_tfsoff(type, start_offset, file);
2977  print_start_tfs_comment(file, type, start_offset);
2978  print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
2979  print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
2980  *typestring_offset += 2;
2981 
2982  align = 0;
2983  if (fc != FC_BOGUS_ARRAY)
2984  {
2985  if (fc == FC_LGFARRAY || fc == FC_LGVARRAY)
2986  {
2987  print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", size, size);
2988  *typestring_offset += 4;
2989  }
2990  else
2991  {
2992  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)size, size);
2993  *typestring_offset += 2;
2994  }
2995 
2997  *typestring_offset
2999  type, size_is);
3000 
3001  if (fc == FC_SMVARRAY || fc == FC_LGVARRAY)
3002  {
3003  unsigned int elsize = type_memsize(type_array_get_element(type));
3004  unsigned int dim = type_array_get_dim(type);
3005 
3006  if (fc == FC_LGVARRAY)
3007  {
3008  print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", dim, dim);
3009  *typestring_offset += 4;
3010  }
3011  else
3012  {
3013  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)dim, dim);
3014  *typestring_offset += 2;
3015  }
3016 
3017  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)elsize, elsize);
3018  *typestring_offset += 2;
3019  }
3020 
3021  if (length_is)
3022  *typestring_offset
3024  type, length_is);
3025 
3028  {
3029  print_file(file, 2, "0x%x,\t/* FC_PP */\n", FC_PP);
3030  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
3031  *typestring_offset += 2;
3032  write_pointer_description(file, is_string_type(attrs, type) ? attrs : NULL, type, typestring_offset);
3033  print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END);
3034  *typestring_offset += 1;
3035  }
3036 
3037  write_array_element_type(file, is_string_type(attrs, type) ? attrs : NULL, type, FALSE, typestring_offset);
3038  write_end(file, typestring_offset);
3039  }
3040  else
3041  {
3042  unsigned int dim = size_is ? 0 : type_array_get_dim(type);
3043  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)dim, dim);
3044  *typestring_offset += 2;
3045  *typestring_offset
3047  type, size_is);
3048  *typestring_offset
3050  type, length_is);
3051 
3052  write_array_element_type(file, is_string_type(attrs, type) ? attrs : NULL, type, TRUE, typestring_offset);
3053  write_end(file, typestring_offset);
3054  }
3055 
3056  return start_offset;
3057 }
3058 
3060 {
3061  const var_list_t *fields = type_struct_get_fields(type);
3062  const var_t *last_field;
3063  const type_t *ft;
3064 
3065  if (!fields || list_empty(fields))
3066  return NULL;
3067 
3068  last_field = LIST_ENTRY( list_tail(fields), const var_t, entry );
3069  ft = last_field->type;
3070 
3072  return last_field;
3073 
3074  if (type_get_type(ft) == TYPE_STRUCT)
3075  return find_array_or_string_in_struct(ft);
3076  else
3077  return NULL;
3078 }
3079 
3081  int is_complex, unsigned int *corroff,
3082  unsigned int *typestring_offset)
3083 {
3084  const var_t *field;
3085  unsigned short offset = 0;
3086  unsigned int salign = 1;
3087  int padding;
3089 
3090  if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
3091  {
3092  type_t *ft = field->type;
3093  unsigned int align = 0;
3094  unsigned int size = type_memsize_and_alignment(ft, &align);
3095  align = clamp_align(align);
3096  if (salign < align) salign = align;
3097 
3099  {
3100  if ((align - 1) & offset)
3101  {
3102  unsigned char fc = 0;
3103  switch (align)
3104  {
3105  case 2:
3106  fc = FC_ALIGNM2;
3107  break;
3108  case 4:
3109  fc = FC_ALIGNM4;
3110  break;
3111  case 8:
3112  fc = FC_ALIGNM8;
3113  break;
3114  default:
3115  error("write_struct_members: cannot align type %d\n", type_get_type(ft));
3116  }
3117  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
3119  *typestring_offset += 1;
3120  }
3121  write_member_type(file, type, is_complex, field->attrs, field->type, corroff,
3122  typestring_offset);
3123  offset += size;
3124  }
3125  }
3126 
3127  padding = ROUNDING(offset, salign);
3128  if (padding)
3129  {
3130  print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
3131  FC_STRUCTPAD1 + padding - 1,
3132  padding);
3133  *typestring_offset += 1;
3134  }
3135 
3136  write_end(file, typestring_offset);
3137 }
3138 
3139 static unsigned int write_struct_tfs(FILE *file, type_t *type,
3140  const char *name, unsigned int *tfsoff)
3141 {
3142  const type_t *save_current_structure = current_structure;
3143  unsigned int total_size;
3144  const var_t *array;
3145  unsigned int start_offset;
3146  unsigned int align;
3147  unsigned int corroff;
3148  var_t *f;
3149  unsigned char fc = get_struct_fc(type);
3151 
3152  if (processed(type)) return type->typestring_offset;
3153 
3154  guard_rec(type);
3156 
3157  total_size = type_memsize(type);
3159  if (total_size > USHRT_MAX)
3160  error("structure size for %s exceeds %d bytes by %d bytes\n",
3161  name, USHRT_MAX, total_size - USHRT_MAX);
3162 
3163  if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
3164  write_embedded_types(file, f->attrs, f->type, f->name, FALSE, tfsoff);
3165 
3167  if (array && !processed(array->type))
3168  {
3169  if(is_string_type(array->attrs, array->type))
3170  write_string_tfs(file, array->attrs, array->type, TYPE_CONTEXT_CONTAINER, array->name, tfsoff);
3171  else
3172  write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
3173  }
3174 
3175  corroff = *tfsoff;
3176  write_descriptors(file, type, tfsoff);
3177 
3178  start_offset = *tfsoff;
3179  update_tfsoff(type, start_offset, file);
3180  print_start_tfs_comment(file, type, start_offset);
3181  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
3182  print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
3183  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)total_size, total_size);
3184  *tfsoff += 4;
3185 
3186  if (array)
3187  {
3188  unsigned int absoff = array->type->typestring_offset;
3189  short reloff = absoff - *tfsoff;
3190  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
3191  reloff, reloff, absoff);
3192  *tfsoff += 2;
3193  }
3194  else if (fc == FC_BOGUS_STRUCT)
3195  {
3196  print_file(file, 2, "NdrFcShort(0x0),\n");
3197  *tfsoff += 2;
3198  }
3199 
3200  if (fc == FC_BOGUS_STRUCT)
3201  {
3202  /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
3203  nothing is written to file yet. On the actual writing pass,
3204  this will have been updated. */
3205  unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff;
3206  int reloff = absoff - *tfsoff;
3207  assert( reloff >= 0 );
3208  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %d (%u) */\n",
3209  (unsigned short)reloff, reloff, absoff);
3210  *tfsoff += 2;
3211  }
3212  else if ((fc == FC_PSTRUCT) ||
3213  (fc == FC_CPSTRUCT) ||
3215  {
3216  print_file(file, 2, "0x%x,\t/* FC_PP */\n", FC_PP);
3217  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
3218  *tfsoff += 2;
3220  print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END);
3221  *tfsoff += 1;
3222  }
3223 
3225  tfsoff);
3226 
3227  if (fc == FC_BOGUS_STRUCT)
3228  {
3229  const var_t *f;
3230 
3231  type->ptrdesc = *tfsoff;
3232  if (fields) LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
3233  {
3234  type_t *ft = f->type;
3236  {
3237  case TGT_POINTER:
3238  if (is_string_type(f->attrs, ft))
3239  write_string_tfs(file, f->attrs, ft, TYPE_CONTEXT_CONTAINER, f->name, tfsoff);
3240  else
3241  write_pointer_tfs(file, f->attrs, ft,
3242  type_pointer_get_ref(ft)->typestring_offset,
3243  TYPE_CONTEXT_CONTAINER, tfsoff);
3244  break;
3245  case TGT_ARRAY:
3246  if (type_array_is_decl_as_ptr(ft))
3247  {
3248  unsigned int offset;
3249 
3250  print_file(file, 0, "/* %d */\n", *tfsoff);
3251 
3252  offset = ft->typestring_offset;
3253  /* skip over the pointer that is written for strings, since a
3254  * pointer has to be written in-place here */
3255  if (is_string_type(f->attrs, ft))
3256  offset += 4;
3258  }
3259  break;
3260  default:
3261  break;
3262  }
3263  }
3264  if (type->ptrdesc == *tfsoff)
3265  type->ptrdesc = 0;
3266  }
3267 
3268  current_structure = save_current_structure;
3269  return start_offset;
3270 }
3271 
3272 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
3273 {
3274  if (t == NULL)
3275  {
3276  print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
3277  }
3278  else
3279  {
3281  {
3282  unsigned char fc;
3283  if (type_get_type(t) == TYPE_BASIC)
3284  fc = get_basic_fc(t);
3285  else
3286  fc = get_enum_fc(t);
3287  print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
3288  fc, string_of_type(fc));
3289  }
3290  else if (t->typestring_offset)
3291  {
3292  short reloff = t->typestring_offset - *tfsoff;
3293  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %d (%d) */\n",
3294  reloff, reloff, t->typestring_offset);
3295  }
3296  else
3297  error("write_branch_type: type unimplemented %d\n", type_get_type(t));
3298  }
3299 
3300  *tfsoff += 2;
3301 }
3302 
3303 static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
3304  type_t *type, unsigned int *tfsoff)
3305 {
3306  unsigned int start_offset;
3307  unsigned int size;
3308  var_list_t *fields;
3309  unsigned int nbranch = 0;
3310  type_t *deftype = NULL;
3311  short nodeftype = 0xffff;
3312  unsigned int dummy;
3313  var_t *f;
3314 
3315  if (processed(type) &&
3317  return type->typestring_offset;
3318 
3319  guard_rec(type);
3320 
3321  fields = type_union_get_cases(type);
3322 
3323  size = union_memsize(fields, &dummy);
3324 
3325  if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
3326  {
3327  expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
3328  if (cases)
3329  nbranch += list_count(cases);
3330  if (f->type)
3331  write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
3332  }
3333 
3334  start_offset = *tfsoff;
3335  update_tfsoff(type, start_offset, file);
3336  print_start_tfs_comment(file, type, start_offset);
3338  {
3339  const var_t *sv = type_union_get_switch_value(type);
3340  const type_t *st = sv->type;
3341  unsigned int align = 0;
3342  unsigned char fc;
3343 
3344  if (type_get_type(st) == TYPE_BASIC)
3345  {
3346  fc = get_basic_fc(st);
3347  switch (fc)
3348  {
3349  case FC_CHAR:
3350  case FC_SMALL:
3351  case FC_BYTE:
3352  case FC_USMALL:
3353  case FC_WCHAR:
3354  case FC_SHORT:
3355  case FC_USHORT:
3356  case FC_LONG:
3357  case FC_ULONG:
3358  break;
3359  default:
3360  fc = 0;
3361  error("union switch type must be an integer, char, or enum\n");
3362  }
3363  }
3364  else if (type_get_type(st) == TYPE_ENUM)
3365  fc = get_enum_fc(st);
3366  else
3367  error("union switch type must be an integer, char, or enum\n");
3368 
3370  if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
3371  {
3372  if (f->type)
3374  }
3375 
3376  print_file(file, 2, "0x%x,\t/* FC_ENCAPSULATED_UNION */\n", FC_ENCAPSULATED_UNION);
3377  print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
3378  (align << 4) | fc, string_of_type(fc));
3379  *tfsoff += 2;
3380  }
3381  else if (is_attr(type->attrs, ATTR_SWITCHTYPE))
3382  {
3383  const expr_t *switch_is = get_attrp(attrs, ATTR_SWITCHIS);
3384  const type_t *st = get_attrp(type->attrs, ATTR_SWITCHTYPE);
3385  unsigned char fc;
3386 
3387  if (type_get_type(st) == TYPE_BASIC)
3388  {
3389  fc = get_basic_fc(st);
3390  switch (fc)
3391  {
3392  case FC_CHAR:
3393  case FC_SMALL:
3394  case FC_USMALL:
3395  case FC_SHORT:
3396  case FC_USHORT:
3397  case FC_LONG:
3398  case FC_ULONG:
3399  case FC_ENUM16:
3400  case FC_ENUM32:
3401  break;
3402  default:
3403  fc = 0;
3404  error("union switch type must be an integer, char, or enum\n");
3405  }
3406  }
3407  else if (type_get_type(st) == TYPE_ENUM)
3408  fc = get_enum_fc(st);
3409  else
3410  error("union switch type must be an integer, char, or enum\n");
3411 
3412  print_file(file, 2, "0x%x,\t/* FC_NON_ENCAPSULATED_UNION */\n", FC_NON_ENCAPSULATED_UNION);
3413  print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
3414  fc, string_of_type(fc));
3415  *tfsoff += 2;
3416  *tfsoff += write_conf_or_var_desc(file, current_structure, 0, st, switch_is );
3417  print_file(file, 2, "NdrFcShort(0x2),\t/* Offset= 2 (%u) */\n", *tfsoff + 2);
3418  *tfsoff += 2;
3419  print_file(file, 0, "/* %u */\n", *tfsoff);
3420  }
3421 
3422  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)size, size);
3423  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)nbranch, nbranch);
3424  *tfsoff += 4;
3425 
3426  if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
3427  {
3428  type_t *ft = f->type;
3429  expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
3430  int deflt = is_attr(f->attrs, ATTR_DEFAULT);
3431  expr_t *c;
3432 
3433  if (cases == NULL && !deflt)
3434  error("union field %s with neither case nor default attribute\n", f->name);
3435 
3436  if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
3437  {
3438  /* MIDL doesn't check for duplicate cases, even though that seems
3439  like a reasonable thing to do, it just dumps them to the TFS
3440  like we're going to do here. */
3441  print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
3442  *tfsoff += 4;
3443  write_branch_type(file, ft, tfsoff);
3444  }
3445 
3446  /* MIDL allows multiple default branches, even though that seems
3447  illogical, it just chooses the last one, which is what we will
3448  do. */
3449  if (deflt)
3450  {
3451  deftype = ft;
3452  nodeftype = 0;
3453  }
3454  }
3455 
3456  if (deftype)
3457  {
3458  write_branch_type(file, deftype, tfsoff);
3459  }
3460  else
3461  {
3462  print_file(file, 2, "NdrFcShort(0x%hx),\n", nodeftype);
3463  *tfsoff += 2;
3464  }
3465 
3466  return start_offset;
3467 }
3468 
3469 static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
3470  unsigned int *typeformat_offset)
3471 {
3472  unsigned int i;
3473  unsigned int start_offset = *typeformat_offset;
3474  expr_t *iid = get_attrp(attrs, ATTR_IIDIS);
3475 
3476  if (!iid && processed(type)) return type->typestring_offset;
3477 
3478  print_start_tfs_comment(file, type, start_offset);
3479  update_tfsoff(type, start_offset, file);
3480 
3481  if (iid)
3482  {
3483  print_file(file, 2, "0x2f, /* FC_IP */\n");
3484  print_file(file, 2, "0x5c, /* FC_PAD */\n");
3485  *typeformat_offset
3487  }
3488  else
3489  {
3491  const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
3492 
3493  if (! uuid)
3494  error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
3495 
3496  print_file(file, 2, "0x2f,\t/* FC_IP */\n");
3497  print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
3498  print_file(file, 2, "NdrFcLong(0x%08x),\n", uuid->Data1);
3499  print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
3500  print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
3501  for (i = 0; i < 8; ++i)
3502  print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
3503 
3504  if (file)
3505  fprintf(file, "\n");
3506 
3507  *typeformat_offset += 18;
3508  }
3509  return start_offset;
3510 }
3511 
3512 static unsigned int write_contexthandle_tfs(FILE *file,
3513  const attr_list_t *attrs,
3514  type_t *type,
3515  int toplevel_param,
3516  unsigned int *typeformat_offset)
3517 {
3518  unsigned int start_offset = *typeformat_offset;
3519  unsigned char flags = get_contexthandle_flags( current_iface, attrs, type );
3520 
3521  print_start_tfs_comment(file, type, start_offset);
3522 
3523  if (flags & 0x80) /* via ptr */
3524  {
3525  int pointer_type = get_pointer_fc( type, attrs, toplevel_param );
3526  if (!pointer_type) pointer_type = FC_RP;
3527  *typeformat_offset += 4;
3528  print_file(file, 2,"0x%x, 0x0,\t/* %s */\n", pointer_type, string_of_type(pointer_type) );
3529  print_file(file, 2, "NdrFcShort(0x2),\t /* Offset= 2 (%u) */\n", *typeformat_offset);
3530  print_file(file, 0, "/* %2u */\n", *typeformat_offset);
3531  }
3532 
3533  print_file(file, 2, "0x%02x,\t/* FC_BIND_CONTEXT */\n", FC_BIND_CONTEXT);
3534  print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
3535  /* return and can't be null values overlap */
3536  if (((flags & 0x21) != 0x21) && (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL))
3537  print_file(file, 0, "can't be null, ");
3539  print_file(file, 0, "serialize, ");
3541  print_file(file, 0, "no serialize, ");
3543  print_file(file, 0, "strict, ");
3544  if ((flags & 0x21) == 0x20)
3545  print_file(file, 0, "out, ");
3546  if ((flags & 0x21) == 0x21)
3547  print_file(file, 0, "return, ");
3548  if (flags & 0x40)
3549  print_file(file, 0, "in, ");
3550  if (flags & 0x80)
3551  print_file(file, 0, "via ptr, ");
3552  print_file(file, 0, "*/\n");
3553  print_file(file, 2, "0x%x,\t/* rundown routine */\n", get_context_handle_offset( type ));
3554  print_file(file, 2, "0, /* FIXME: param num */\n");
3555  *typeformat_offset += 4;
3556 
3557  update_tfsoff( type, start_offset, file );
3558  return start_offset;
3559 }
3560 
3561 static unsigned int write_range_tfs(FILE *file, const attr_list_t *attrs,
3562  type_t *type, expr_list_t *range_list,
3563  unsigned int *typeformat_offset)
3564 {
3565  unsigned char fc;
3566  unsigned int start_offset = *typeformat_offset;
3567  const expr_t *range_min = LIST_ENTRY(list_head(range_list), const expr_t, entry);
3568  const expr_t *range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry);
3569 
3570  if (type_get_type(type) == TYPE_BASIC)
3571  fc = get_basic_fc(type);
3572  else
3573  fc = get_enum_fc(type);
3574 
3575  /* fc must fit in lower 4-bits of 8-bit field below */
3576  assert(fc <= 0xf);
3577 
3578  print_file(file, 0, "/* %u */\n", *typeformat_offset);
3579  print_file(file, 2, "0x%x,\t/* FC_RANGE */\n", FC_RANGE);
3580  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
3581  print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_min->cval, range_min->cval);
3582  print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_max->cval, range_max->cval);
3583  update_tfsoff( type, start_offset, file );
3584  *typeformat_offset += 10;
3585 
3586  return start_offset;
3587 }
3588 
3589 static unsigned int write_type_tfs(FILE *file, int indent,
3590  const attr_list_t *attrs, type_t *type,
3591  const char *name,
3592  enum type_context context,
3593  unsigned int *typeformat_offset)
3594 {
3595  unsigned int offset;
3596 
3597  switch (typegen_detect_type(type, attrs, TDT_ALL_TYPES))
3598  {
3599  case TGT_CTXT_HANDLE:
3601  return write_contexthandle_tfs(file, attrs, type,
3602  context == TYPE_CONTEXT_TOPLEVELPARAM, typeformat_offset);
3603  case TGT_USER_TYPE:
3604  return write_user_tfs(file, type, typeformat_offset);
3605  case TGT_STRING:
3606  return write_string_tfs(file, attrs, type, context, name, typeformat_offset);
3607  case TGT_ARRAY:
3608  {
3609  unsigned int off;
3610  /* conformant and pointer arrays are handled specially */
3611  if ((context != TYPE_CONTEXT_CONTAINER &&
3614  off = write_array_tfs(file, attrs, type, name, typeformat_offset);
3615  else
3616  off = 0;
3619  {
3620  int ptr_type;
3621  ptr_type = get_pointer_fc(type, attrs,
3623  if (ptr_type != FC_RP || type_array_is_decl_as_ptr(type))
3624  {
3625  unsigned int absoff = type->typestring_offset;
3626  short reloff = absoff - (*typeformat_offset + 2);
3627  off = *typeformat_offset;
3628  print_file(file, 0, "/* %d */\n", off);
3629  print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
3630  string_of_type(ptr_type));
3631  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
3632  reloff, reloff, absoff);
3633  if (ptr_type != FC_RP) update_tfsoff( type, off, file );
3634  *typeformat_offset += 4;
3635  }
3636  type->details.array.ptr_tfsoff = off;
3637  }
3638  return off;
3639  }
3640  case TGT_STRUCT:
3641  return write_struct_tfs(file, type, name, typeformat_offset);
3642  case TGT_UNION:
3643  return write_union_tfs(file, attrs, type, typeformat_offset);
3644  case TGT_ENUM:
3645  case TGT_BASIC:
3646  /* nothing to do */
3647  return 0;
3648  case TGT_RANGE:
3649  {
3650  expr_list_t *range_list = get_attrp(attrs, ATTR_RANGE);
3651  if (!range_list)
3652  range_list = get_aliaschain_attrp(type, ATTR_RANGE);
3653  return write_range_tfs(file, attrs, type, range_list, typeformat_offset);
3654  }
3655  case TGT_IFACE_POINTER:
3656  return write_ip_tfs(file, attrs, type, typeformat_offset);
3657  case TGT_POINTER:
3658  {
3659  enum type_context ref_context;
3660  unsigned int toplevel_offset = *typeformat_offset;
3662 
3664  ref_context = TYPE_CONTEXT_PARAM;
3666  ref_context = TYPE_CONTEXT_CONTAINER;
3667  else
3668  ref_context = context;
3669 
3670  if (is_string_type(attrs, ref))
3671  {
3673  write_pointer_tfs(file, attrs, type, *typeformat_offset + 4, context, typeformat_offset);
3674 
3675  offset = write_type_tfs(file, indent, attrs, ref, name, ref_context, typeformat_offset);
3677  return 0;
3678  return (context == TYPE_CONTEXT_TOPLEVELPARAM) ? toplevel_offset : offset;
3679  }
3680 
3682  ref_context, typeformat_offset);
3684  return 0;
3685  return write_pointer_tfs(file, attrs, type, offset, context, typeformat_offset);
3686  }
3687  case TGT_INVALID:
3688  break;
3689  }
3690  error("invalid type %s for var %s\n", type->name, name);
3691  return 0;
3692 }
3693 
3694 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
3695  const char *name, int write_ptr, unsigned int *tfsoff)
3696 {
3697  return write_type_tfs(file, 2, attrs, type, name, write_ptr ? TYPE_CONTEXT_CONTAINER : TYPE_CONTEXT_CONTAINER_NO_POINTERS, tfsoff);
3698 }
3699 
3700 static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned int *offset)
3701 {
3703  const statement_t *stmt;
3704  var_t *var;
3705 
3706  current_iface = iface;
3707  if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry )
3708  {
3709  switch(stmt->type)
3710  {
3711  case STMT_DECLARATION:
3712  {
3713  const var_t *func = stmt->u.var;
3714 
3715  if(stmt->u.var->stgclass != STG_NONE
3717  continue;
3718 
3719  current_func = func;
3720  if (is_local(func->attrs)) continue;
3721 
3723  if (!is_void(var->type))
3724  var->typestring_offset = write_type_tfs( file, 2, func->attrs, var->type, func->name,
3726 
3727  if (type_get_function_args(func->type))
3729  var->typestring_offset = write_type_tfs( file, 2, var->attrs, var->type, var->name,
3731  break;
3732 
3733  }
3734  case STMT_TYPEDEF:
3735  {
3736  const type_list_t *type_entry;
3737  for (type_entry = stmt->u.type_list; type_entry; type_entry = type_entry->next)
3738  {
3739  if (is_attr(type_entry->type->attrs, ATTR_ENCODE)
3740  || is_attr(type_entry->type->attrs, ATTR_DECODE))
3741  type_entry->type->typestring_offset = write_type_tfs( file, 2,
3742  type_entry->type->attrs, type_entry->type, type_entry->type->name,
3744  }
3745  break;
3746  }
3747  default:
3748  break;
3749  }
3750  }
3751 }
3752 
3753 static unsigned int process_tfs(FILE *file, const statement_list_t *stmts, type_pred_t pred)
3754 {
3755  unsigned int typeformat_offset = 2;
3756  for_each_iface(stmts, process_tfs_iface, pred, file, 0, &typeformat_offset);
3757  return typeformat_offset + 1;
3758 }
3759 
3760 
3762 {
3763  int indent = 0;
3764 
3765  print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
3766  print_file(file, indent, "{\n");
3767  indent++;
3768  print_file(file, indent, "0,\n");
3769  print_file(file, indent, "{\n");
3770  indent++;
3771  print_file(file, indent, "NdrFcShort(0x0),\n");
3772 
3774  process_tfs(file, stmts, pred);
3775 
3776  print_file(file, indent, "0x0\n");
3777  indent--;
3778  print_file(file, indent, "}\n");
3779  indent--;
3780  print_file(file, indent, "};\n");
3781  print_file(file, indent, "\n");
3782 }
3783 
3784 static unsigned int get_required_buffer_size_type(
3785  const type_t *type, const char *name, const attr_list_t *attrs, int toplevel_param, unsigned int *alignment)
3786 {
3787  *alignment = 0;
3789  {
3790  case TGT_USER_TYPE:
3791  {
3792  const char *uname = NULL;
3793  const type_t *utype = get_user_type(type, &uname);
3794  return get_required_buffer_size_type(utype, uname, NULL, FALSE, alignment);
3795  }
3796  case TGT_BASIC:
3797  switch (get_basic_fc(type))
3798  {
3799  case FC_BYTE:
3800  case FC_CHAR:
3801  case FC_USMALL:
3802  case FC_SMALL:
3803  *alignment = 4;
3804  return 1;
3805 
3806  case FC_WCHAR:
3807  case FC_USHORT:
3808  case FC_SHORT:
3809  *alignment = 4;
3810  return 2;
3811 
3812  case FC_ULONG:
3813  case FC_LONG:
3814  case FC_FLOAT:
3815  case FC_ERROR_STATUS_T:
3816  *alignment = 4;
3817  return 4;
3818 
3819  case FC_HYPER:
3820  case FC_DOUBLE:
3821  *alignment = 8;
3822  return 8;
3823 
3824  case FC_INT3264:
3825  case FC_UINT3264:
3826  assert( pointer_size );
3827  *alignment = pointer_size;
3828  return pointer_size;
3829 
3830  case FC_IGNORE:
3831  case FC_BIND_PRIMITIVE:
3832  return 0;
3833 
3834  default:
3835  error("get_required_buffer_size: unknown basic type 0x%02x\n",
3836  get_basic_fc(type));
3837  return 0;
3838  }
3839  break;
3840 
3841  case TGT_ENUM:
3842  switch (get_enum_fc(type))
3843  {
3844  case FC_ENUM32:
3845  *alignment = 4;
3846  return 4;
3847  case FC_ENUM16:
3848  *alignment = 4;
3849  return 2;
3850  }
3851  break;
3852 
3853  case TGT_STRUCT:
3854  if (get_struct_fc(type) == FC_STRUCT)
3855  {
3856  if (!type_struct_get_fields(type)) return 0;
3857  return fields_memsize(type_struct_get_fields(type), alignment);
3858  }
3859  break;
3860 
3861  case TGT_POINTER:
3862  {
3863  unsigned int size, align;
3864  const type_t *ref = type_pointer_get_ref(type);
3865  if (is_string_type( attrs, ref )) break;
3866  if (!(size = get_required_buffer_size_type( ref, name, NULL, FALSE, &align ))) break;
3867  if (get_pointer_fc(type, attrs, toplevel_param) != FC_RP)
3868  {
3869  size += 4 + align;
3870  align = 4;
3871  }
3872  *alignment = align;
3873  return size;
3874  }
3875 
3876  case TGT_ARRAY:
3877  if (get_pointer_fc(type, attrs, toplevel_param) == FC_RP)
3878  {
3879  switch (get_array_fc(type))
3880  {
3881  case FC_SMFARRAY:
3882  case FC_LGFARRAY:
3883  return type_array_get_dim(type) *
3885  NULL, FALSE, alignment);
3886  }
3887  }
3888  break;
3889 
3890  default:
3891  break;
3892  }
3893  return 0;
3894 }
3895 
3896 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
3897 {
3898  int in_attr = is_attr(var->attrs, ATTR_IN);
3899  int out_attr = is_attr(var->attrs, ATTR_OUT);
3900 
3901  if (!in_attr && !out_attr)
3902  in_attr = 1;
3903 
3904  *alignment = 0;
3905 
3906  if ((pass == PASS_IN && in_attr) || (pass == PASS_OUT && out_attr) ||
3907  pass == PASS_RETURN)
3908  {
3910  {
3911  *alignment = 4;
3912  return 20;
3913  }
3914 
3915  if (!is_string_type(var->attrs, var->type))
3916  return get_required_buffer_size_type(var->type, var->name,
3917  var->attrs, TRUE, alignment);
3918  }
3919  return 0;
3920 }
3921 
3922 static unsigned int get_function_buffer_size( const var_t *func, enum pass pass )
3923 {
3924  const var_t *var;
3925  unsigned int total_size = 0, alignment;
3926 
3927  if (type_get_function_args(func->type))
3928  {
3930  {
3931  total_size += get_required_buffer_size(var, &alignment, pass);
3932  total_size += alignment;
3933  }
3934  }
3935 
3936  if (pass == PASS_OUT && !is_void(type_function_get_rettype(func->type)))
3937  {
3938  var_t v = *func;
3939  v.type = type_function_get_rettype(func->type);
3940  total_size += get_required_buffer_size(&v, &alignment, PASS_RETURN);
3941  total_size += alignment;
3942  }
3943  return total_size;
3944 }
3945 
3946 static void print_phase_function(FILE *file, int indent, const char *type,
3947  const char *local_var_prefix, enum remoting_phase phase,
3948  const var_t *var, unsigned int type_offset)
3949 {
3950  const char *function;
3951  switch (phase)
3952  {
3953  case PHASE_BUFFERSIZE:
3954  function = "BufferSize";
3955  break;
3956  case PHASE_MARSHAL:
3957  function = "Marshall";
3958  break;
3959  case PHASE_UNMARSHAL:
3960  function = "Unmarshall";
3961  break;
3962  case PHASE_FREE:
3963  function = "Free";
3964  break;
3965  default:
3966  assert(0);
3967  return;
3968  }
3969 
3970  print_file(file, indent, "Ndr%s%s(\n", type, function);
3971  indent++;
3972  print_file(file, indent, "&__frame->_StubMsg,\n");
3973  print_file(file, indent, "%s%s%s%s%s,\n",
3974  (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
3975  (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
3976  local_var_prefix,
3977  (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
3978  var->name);
3979  print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
3980  type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
3981  if (phase == PHASE_UNMARSHAL)
3982  print_file(file, indent, "0);\n");
3983  indent--;
3984 }
3985 
3986 void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix,
3987  enum remoting_phase phase, enum pass pass, const var_t *var,
3988  const char *varname)
3989 {
3990  type_t *type = var->type;
3991  unsigned int alignment = 0;
3992 
3993  /* no work to do for other phases, buffer sizing is done elsewhere */
3994  if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
3995  return;
3996 
3997  if (type_get_type(