ReactOS  0.4.15-dev-1636-gf634010
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  nb_args++;
1325  }
1326  if (!is_void( type_function_get_rettype( func->type )))
1327  {
1328  stack_size += pointer_size;
1329  nb_args++;
1330  }
1331 
1332  print_file( file, 0, "/* %u (procedure %s::%s) */\n", *offset, iface->name, func->name );
1333  print_file( file, indent, "0x%02x,\t/* %s */\n", implicit_fc,
1334  implicit_fc ? string_of_type(implicit_fc) : "explicit handle" );
1335  print_file( file, indent, "0x%02x,\n", oi_flags );
1336  print_file( file, indent, "NdrFcLong(0x%x),\n", rpc_flags );
1337  print_file( file, indent, "NdrFcShort(0x%hx),\t/* method %hu */\n", num_proc, num_proc );
1338  print_file( file, indent, "NdrFcShort(0x%x),\t/* stack size = %u */\n", stack_size, stack_size );
1339  *offset += 10;
1340 
1341  if (!implicit_fc)
1342  {
1343  switch (explicit_fc)
1344  {
1345  case FC_BIND_PRIMITIVE:
1346  handle_flags = 0;
1347  print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) );
1348  print_file( file, indent, "0x%02x,\n", handle_flags );
1349  print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n",
1350  handle_stack_offset, handle_stack_offset );
1351  *offset += 4;
1352  break;
1353  case FC_BIND_GENERIC:
1354  handle_flags = type_memsize( handle_var->type );
1355  print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) );
1356  print_file( file, indent, "0x%02x,\n", handle_flags );
1357  print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n",
1358  handle_stack_offset, handle_stack_offset );
1359  print_file( file, indent, "0x%02x,\n", get_generic_handle_offset( handle_var->type ) );
1360  print_file( file, indent, "0x%x,\t/* FC_PAD */\n", FC_PAD);
1361  *offset += 6;
1362  break;
1363  case FC_BIND_CONTEXT:
1364  handle_flags = get_contexthandle_flags( iface, handle_var->attrs, handle_var->type );
1365  print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) );
1366  print_file( file, indent, "0x%02x,\n", handle_flags );
1367  print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n",
1368  handle_stack_offset, handle_stack_offset );
1369  print_file( file, indent, "0x%02x,\n", get_context_handle_offset( handle_var->type ) );
1370  print_file( file, indent, "0x%02x,\t/* param %hu */\n", handle_param_num, handle_param_num );
1371  *offset += 6;
1372  break;
1373  }
1374  }
1375 
1376  if (get_stub_mode() == MODE_Oif)
1377  {
1378  unsigned char oi2_flags = get_func_oi2_flags( func );
1379  unsigned char ext_flags = 0;
1380  unsigned int size;
1381 
1382  if (is_attr( func->attrs, ATTR_NOTIFY )) ext_flags |= 0x08; /* HasNotify */
1383  if (is_attr( func->attrs, ATTR_NOTIFYFLAG )) ext_flags |= 0x10; /* HasNotify2 */
1384  if (iface == iface->details.iface->async_iface) oi2_flags |= 0x20;
1385 
1387  print_file( file, indent, "NdrFcShort(0x%x),\t/* client buffer = %u */\n", size, size );
1389  print_file( file, indent, "NdrFcShort(0x%x),\t/* server buffer = %u */\n", size, size );
1390  print_file( file, indent, "0x%02x,\n", oi2_flags );
1391  print_file( file, indent, "0x%02x,\t/* %u params */\n", nb_args, nb_args );
1392  print_file( file, indent, "0x%02x,\n", pointer_size == 8 ? 10 : 8 );
1393  print_file( file, indent, "0x%02x,\n", ext_flags );
1394  print_file( file, indent, "NdrFcShort(0x0),\n" ); /* server corr hint */
1395  print_file( file, indent, "NdrFcShort(0x0),\n" ); /* client corr hint */
1396  print_file( file, indent, "NdrFcShort(0x0),\n" ); /* FIXME: notify index */
1397  *offset += 14;
1398  if (pointer_size == 8)
1399  {
1400  unsigned short pos = 0, fpu_mask = 0;
1401 
1402  if (is_object( iface )) pos += 2;
1404  {
1405  if (type_get_type( var->type ) == TYPE_BASIC)
1406  {
1407  switch (type_basic_get_type( var->type ))
1408  {
1409  case TYPE_BASIC_FLOAT: fpu_mask |= 1 << pos; break;
1410  case TYPE_BASIC_DOUBLE: fpu_mask |= 2 << pos; break;
1411  default: break;
1412  }
1413  }
1414  pos += 2;
1415  if (pos >= 16) break;
1416  }
1417  print_file( file, indent, "NdrFcShort(0x%x),\n", fpu_mask ); /* floating point mask */
1418  *offset += 2;
1419  }
1420  }
1421 }
1422 
1423 static void write_procformatstring_func( FILE *file, int indent, const type_t *iface,
1424  const var_t *func, unsigned int *offset,
1425  unsigned short num_proc )
1426 {
1427  unsigned int stack_offset = is_object( iface ) ? pointer_size : 0;
1428  int is_interpreted = is_interpreted_func( iface, func );
1429  int is_new_style = is_interpreted && (get_stub_mode() == MODE_Oif);
1430  var_t *retval = type_function_get_retval( func->type );
1431 
1432  if (is_interpreted) write_proc_func_header( file, indent, iface, func, offset, num_proc );
1433 
1434  /* emit argument data */
1435  if (type_get_function_args(func->type))
1436  {
1437  const var_t *var;
1439  {
1440  print_file( file, 0, "/* %u (parameter %s) */\n", *offset, var->name );
1441  if (is_new_style)
1443  else
1444  *offset += write_old_procformatstring_type(file, indent, var, FALSE, is_interpreted);
1445  }
1446  }
1447 
1448  /* emit return value data */
1449  if (is_void(retval->type))
1450  {
1451  if (!is_new_style)
1452  {
1453  print_file(file, 0, "/* %u (void) */\n", *offset);
1454  print_file(file, indent, "0x5b,\t/* FC_END */\n");
1455  print_file(file, indent, "0x5c,\t/* FC_PAD */\n");
1456  *offset += 2;
1457  }
1458  }
1459  else
1460  {
1461  print_file( file, 0, "/* %u (return value) */\n", *offset );
1462  if (is_new_style)
1464  else
1465  *offset += write_old_procformatstring_type(file, indent, retval, TRUE, is_interpreted);
1466  }
1467 }
1468 
1469 static void for_each_iface(const statement_list_t *stmts,
1470  void (*proc)(type_t *iface, FILE *file, int indent, unsigned int *offset),
1471  type_pred_t pred, FILE *file, int indent, unsigned int *offset)
1472 {
1473  const statement_t *stmt;
1474  type_t *iface;
1475 
1476  if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
1477  {
1478  if (stmt->type != STMT_TYPE || type_get_type(stmt->u.type) != TYPE_INTERFACE)
1479  continue;
1480  iface = stmt->u.type;
1481  if (!pred(iface)) continue;
1482  proc(iface, file, indent, offset);
1483  if (iface->details.iface->async_iface)
1484  proc(iface->details.iface->async_iface, file, indent, offset);
1485  }
1486 }
1487 
1488 static void write_iface_procformatstring(type_t *iface, FILE *file, int indent, unsigned int *offset)
1489 {
1490  const statement_t *stmt;
1491  const type_t *parent = type_iface_get_inherit( iface );
1492  int count = parent ? count_methods( parent ) : 0;
1493 
1495  {
1496  var_t *func = stmt->u.var;
1497  if (is_local(func->attrs)) continue;
1499  }
1500 }
1501 
1503 {
1504  int indent = 0;
1505  unsigned int offset = 0;
1506 
1507  print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
1508  print_file(file, indent, "{\n");
1509  indent++;
1510  print_file(file, indent, "0,\n");
1511  print_file(file, indent, "{\n");
1512  indent++;
1513 
1515 
1516  print_file(file, indent, "0x0\n");
1517  indent--;
1518  print_file(file, indent, "}\n");
1519  indent--;
1520  print_file(file, indent, "};\n");
1521  print_file(file, indent, "\n");
1522 }
1523 
1525 {
1526  const statement_t *stmt;
1527  int indent = 0;
1528 
1529  print_file( file, indent, "static const unsigned short %s_FormatStringOffsetTable[] =\n",
1530  iface->name );
1531  print_file( file, indent, "{\n" );
1532  indent++;
1534  {
1535  var_t *func = stmt->u.var;
1536  if (is_local( func->attrs )) continue;
1537  print_file( file, indent, "%u, /* %s */\n", func->procstring_offset, func->name );
1538  }
1539  indent--;
1540  print_file( file, indent, "};\n\n" );
1541 }
1542 
1543 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset)
1544 {
1545  unsigned char fc;
1546 
1547  if (type_get_type(type) == TYPE_BASIC)
1549  else if (type_get_type(type) == TYPE_ENUM)
1550  fc = get_enum_fc(type);
1551  else
1552  return 0;
1553 
1554  print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
1555  *typestring_offset += 1;
1556  return 1;
1557 }
1558 
1559 /* write conformance / variance descriptor */
1560 static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type,
1561  unsigned int baseoff, const type_t *type,
1562  const expr_t *expr)
1563 {
1564  unsigned char operator_type = 0;
1565  unsigned char conftype = FC_NORMAL_CONFORMANCE;
1566  const char *conftype_string = "field";
1567  const expr_t *subexpr;
1568  const type_t *iface = NULL;
1569  const char *name;
1570 
1571  if (!expr)
1572  {
1573  print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n");
1574  return 4;
1575  }
1576 
1577  if (expr->is_const)
1578  {
1579  if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX)
1580  error("write_conf_or_var_desc: constant value %d is greater than "
1581  "the maximum constant size of %d\n", expr->cval,
1582  UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX);
1583 
1584  print_file(file, 2, "0x%x, /* Corr desc: constant, val = %d */\n",
1585  FC_CONSTANT_CONFORMANCE, expr->cval);
1586  print_file(file, 2, "0x%x,\n", expr->cval >> 16);
1587  print_file(file, 2, "NdrFcShort(0x%hx),\n", (unsigned short)expr->cval);
1588 
1589  return 4;
1590  }
1591 
1592  if (!cont_type) /* top-level conformance */
1593  {
1594  conftype = FC_TOP_LEVEL_CONFORMANCE;
1595  conftype_string = "parameter";
1596  cont_type = current_func->type;
1597  name = current_func->name;
1598  iface = current_iface;
1599  }
1600  else
1601  {
1602  name = cont_type->name;
1604  {
1605  conftype = FC_POINTER_CONFORMANCE;
1606  conftype_string = "field pointer";
1607  }
1608  }
1609 
1610  subexpr = expr;
1611  switch (subexpr->type)
1612  {
1613  case EXPR_PPTR:
1614  subexpr = subexpr->ref;
1615  operator_type = FC_DEREFERENCE;
1616  break;
1617  case EXPR_DIV:
1618  if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
1619  {
1620  subexpr = subexpr->ref;
1621  operator_type = FC_DIV_2;
1622  }
1623  break;
1624  case EXPR_MUL:
1625  if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2))
1626  {
1627  subexpr = subexpr->ref;
1628  operator_type = FC_MULT_2;
1629  }
1630  break;
1631  case EXPR_SUB:
1632  if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
1633  {
1634  subexpr = subexpr->ref;
1635  operator_type = FC_SUB_1;
1636  }
1637  break;
1638  case EXPR_ADD:
1639  if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1))
1640  {
1641  subexpr = subexpr->ref;
1642  operator_type = FC_ADD_1;
1643  }
1644  break;
1645  default:
1646  break;
1647  }
1648 
1649  if (subexpr->type == EXPR_IDENTIFIER)
1650  {
1651  const type_t *correlation_variable = NULL;
1652  unsigned char param_type = 0;
1653  unsigned int offset = 0;
1654  const var_t *var;
1655  struct expr_loc expr_loc;
1656 
1657  if (type_get_type(cont_type) == TYPE_FUNCTION)
1658  {
1659  var_list_t *args = type_get_function_args( cont_type );
1660 
1661  if (is_object( iface )) offset += pointer_size;
1662  if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry )
1663  {
1664  if (var->name && !strcmp(var->name, subexpr->u.sval))
1665  {
1666  expr_loc.v = var;
1667  correlation_variable = var->type;
1668  break;
1669  }
1670  offset += get_stack_size( var, NULL );
1671  }
1672  }
1673  else
1674  {
1675  var_list_t *fields = type_struct_get_fields( cont_type );
1676 
1677  if (fields) LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
1678  {
1679  unsigned int size = field_memsize( var->type, &offset );
1680  if (var->name && !strcmp(var->name, subexpr->u.sval))
1681  {
1682  expr_loc.v = var;
1683  correlation_variable = var->type;
1684  break;
1685  }
1686  offset += size;
1687  }
1688  }
1689 
1690  if (!correlation_variable)
1691  error("write_conf_or_var_desc: couldn't find variable %s in %s\n", subexpr->u.sval, name);
1692  expr_loc.attr = NULL;
1693  correlation_variable = expr_resolve_type(&expr_loc, cont_type, expr);
1694 
1695  offset -= baseoff;
1696 
1697  if (type_get_type(correlation_variable) == TYPE_BASIC)
1698  {
1699  switch (get_basic_fc(correlation_variable))
1700  {
1701  case FC_CHAR:
1702  case FC_SMALL:
1703  param_type = FC_SMALL;
1704  break;
1705  case FC_BYTE:
1706  case FC_USMALL:
1707  param_type = FC_USMALL;
1708  break;
1709  case FC_WCHAR:
1710  case FC_SHORT:
1711  param_type = FC_SHORT;
1712  break;
1713  case FC_USHORT:
1714  param_type = FC_USHORT;
1715  break;
1716  case FC_LONG:
1717  param_type = FC_LONG;
1718  break;
1719  case FC_ULONG:
1720  param_type = FC_ULONG;
1721  break;
1722  default:
1723  error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n",
1724  get_basic_fc(correlation_variable));
1725  }
1726  }
1727  else if (type_get_type(correlation_variable) == TYPE_ENUM)
1728  {
1729  if (get_enum_fc(correlation_variable) == FC_ENUM32)
1730  param_type = FC_LONG;
1731  else
1732  param_type = FC_SHORT;
1733  }
1734  else if (type_get_type(correlation_variable) == TYPE_POINTER)
1735  {
1736  if (pointer_size == 8)
1737  param_type = FC_HYPER;
1738  else
1739  param_type = FC_LONG;
1740  }
1741  else
1742  {
1743  error("write_conf_or_var_desc: non-arithmetic type used as correlation variable %s\n",
1744  subexpr->u.sval);
1745  return 0;
1746  }
1747 
1748  print_file(file, 2, "0x%x,\t/* Corr desc: %s %s, %s */\n",
1749  conftype | param_type, conftype_string, subexpr->u.sval, string_of_type(param_type));
1750  print_file(file, 2, "0x%x,\t/* %s */\n", operator_type,
1751  operator_type ? string_of_type(operator_type) : "no operators");
1752  print_file(file, 2, "NdrFcShort(0x%hx),\t/* offset = %d */\n",
1753  (unsigned short)offset, offset);
1754  }
1755  else if (!iface || is_interpreted_func( iface, current_func ))
1756  {
1757  unsigned int callback_offset = 0;
1758  struct expr_eval_routine *eval;
1759  int found = 0;
1760 
1762  {
1763  if (eval->cont_type == cont_type ||
1764  (type_get_type( eval->cont_type ) == type_get_type( cont_type ) &&
1765  eval->iface == iface &&
1766  eval->name && name && !strcmp(eval->name, name) &&
1767  !compare_expr(eval->expr, expr)))
1768  {
1769  found = 1;
1770  break;
1771  }
1772  callback_offset++;
1773  }
1774 
1775  if (!found)
1776  {
1777  eval = xmalloc (sizeof(*eval));
1778  eval->iface = iface;
1779  eval->cont_type = cont_type;
1780  eval->name = xstrdup( name );
1781  eval->baseoff = baseoff;
1782  eval->expr = expr;
1784  }
1785 
1786  if (callback_offset > USHRT_MAX)
1787  error("Maximum number of callback routines reached\n");
1788 
1789  print_file(file, 2, "0x%x,\t/* Corr desc: %s in %s */\n", conftype, conftype_string, name);
1790  print_file(file, 2, "0x%x,\t/* %s */\n", FC_CALLBACK, "FC_CALLBACK");
1791  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)callback_offset, callback_offset);
1792  }
1793  else /* output a dummy corr desc that isn't used */
1794  {
1795  print_file(file, 2, "0x%x,\t/* Corr desc: unused for %s */\n", conftype, name);
1796  print_file(file, 2, "0x0,\n" );
1797  print_file(file, 2, "NdrFcShort(0x0),\n" );
1798  }
1799  return 4;
1800 }
1801 
1802 /* return size and start offset of a data field based on current offset */
1803 static unsigned int field_memsize(const type_t *type, unsigned int *offset)
1804 {
1805  unsigned int align = 0;
1806  unsigned int size = type_memsize_and_alignment( type, &align );
1807 
1808  *offset = ROUND_SIZE( *offset, align );
1809  return size;
1810 }
1811 
1812 static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align)
1813 {
1814  unsigned int size = 0;
1815  unsigned int max_align;
1816  const var_t *v;
1817 
1818  if (!fields) return 0;
1819  LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
1820  {
1821  unsigned int falign = 0;
1822  unsigned int fsize = type_memsize_and_alignment(v->type, &falign);
1823  if (*align < falign) *align = falign;
1824  falign = clamp_align(falign);
1825  size = ROUND_SIZE(size, falign);
1826  size += fsize;
1827  }
1828 
1829  max_align = clamp_align(*align);
1830  size = ROUND_SIZE(size, max_align);
1831 
1832  return size;
1833 }
1834 
1835 static unsigned int union_memsize(const var_list_t *fields, unsigned int *pmaxa)
1836 {
1837  unsigned int size, maxs = 0;
1838  unsigned int align = *pmaxa;
1839  const var_t *v;
1840 
1841  if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
1842  {
1843  /* we could have an empty default field with NULL type */
1844  if (v->type)
1845  {
1847  if (maxs < size) maxs = size;
1848  if (*pmaxa < align) *pmaxa = align;
1849  }
1850  }
1851 
1852  return maxs;
1853 }
1854 
1855 unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align)
1856 {
1857  unsigned int size = 0;
1858 
1859  switch (type_get_type(t))
1860  {
1861  case TYPE_BASIC:
1862  switch (get_basic_fc(t))
1863  {
1864  case FC_BYTE:
1865  case FC_CHAR:
1866  case FC_USMALL:
1867  case FC_SMALL:
1868  size = 1;
1869  if (size > *align) *align = size;
1870  break;
1871  case FC_WCHAR:
1872  case FC_USHORT:
1873  case FC_SHORT:
1874  size = 2;
1875  if (size > *align) *align = size;
1876  break;
1877  case FC_ULONG:
1878  case FC_LONG:
1879  case FC_ERROR_STATUS_T:
1880  case FC_FLOAT:
1881  size = 4;
1882  if (size > *align) *align = size;
1883  break;
1884  case FC_HYPER:
1885  case FC_DOUBLE:
1886  size = 8;
1887  if (size > *align) *align = size;
1888  break;
1889  case FC_INT3264:
1890  case FC_UINT3264:
1891  case FC_BIND_PRIMITIVE:
1892  assert( pointer_size );
1893  size = pointer_size;
1894  if (size > *align) *align = size;
1895  break;
1896  default:
1897  error("type_memsize: Unknown type 0x%x\n", get_basic_fc(t));
1898  size = 0;
1899  }
1900  break;
1901  case TYPE_ENUM:
1902  switch (get_enum_fc(t))
1903  {
1904  case FC_ENUM16:
1905  case FC_ENUM32:
1906  size = 4;
1907  if (size > *align) *align = size;
1908  break;
1909  default:
1910  error("type_memsize: Unknown enum type\n");
1911  size = 0;
1912  }
1913  break;
1914  case TYPE_STRUCT:
1916  break;
1919  break;
1920  case TYPE_UNION:
1922  break;
1923  case TYPE_POINTER:
1924  case TYPE_INTERFACE:
1925  assert( pointer_size );
1926  size = pointer_size;
1927  if (size > *align) *align = size;
1928  break;
1929  case TYPE_ARRAY:
1931  {
1932  if (is_conformant_array(t))
1933  {
1935  size = 0;
1936  }
1937  else
1940  }
1941  else /* declared as a pointer */
1942  {
1943  assert( pointer_size );
1944  size = pointer_size;
1945  if (size > *align) *align = size;
1946  }
1947  break;
1948  case TYPE_ALIAS:
1949  case TYPE_VOID:
1950  case TYPE_COCLASS:
1951  case TYPE_MODULE:
1952  case TYPE_FUNCTION:
1953  case TYPE_BITFIELD:
1954  /* these types should not be encountered here due to language
1955  * restrictions (interface, void, coclass, module), logical
1956  * restrictions (alias - due to type_get_type call above) or
1957  * checking restrictions (function, bitfield). */
1958  assert(0);
1959  }
1960 
1961  return size;
1962 }
1963 
1964 unsigned int type_memsize(const type_t *t)
1965 {
1966  unsigned int align = 0;
1967  return type_memsize_and_alignment( t, &align );
1968 }
1969 
1970 static unsigned int type_buffer_alignment(const type_t *t)
1971 {
1972  const var_list_t *fields;
1973  const var_t *var;
1974  unsigned int max = 0, align;
1975 
1976  switch (type_get_type(t))
1977  {
1978  case TYPE_BASIC:
1979  switch (get_basic_fc(t))
1980  {
1981  case FC_BYTE:
1982  case FC_CHAR:
1983  case FC_USMALL:
1984  case FC_SMALL:
1985  return 1;
1986  case FC_WCHAR:
1987  case FC_USHORT:
1988  case FC_SHORT:
1989  return 2;
1990  case FC_ULONG:
1991  case FC_LONG:
1992  case FC_ERROR_STATUS_T:
1993  case FC_FLOAT:
1994  case FC_INT3264:
1995  case FC_UINT3264:
1996  return 4;
1997  case FC_HYPER:
1998  case FC_DOUBLE:
1999  return 8;
2000  default:
2001  error("type_buffer_alignment: Unknown type 0x%x\n", get_basic_fc(t));
2002  }
2003  break;
2004  case TYPE_ENUM:
2005  switch (get_enum_fc(t))
2006  {
2007  case FC_ENUM16:
2008  return 2;
2009  case FC_ENUM32:
2010  return 4;
2011  default:
2012  error("type_buffer_alignment: Unknown enum type\n");
2013  }
2014  break;
2015  case TYPE_STRUCT:
2016  if (!(fields = type_struct_get_fields(t))) break;
2017  LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
2018  {
2019  if (!var->type) continue;
2020  align = type_buffer_alignment( var->type );
2021  if (max < align) max = align;
2022  }
2023  break;
2025  if (!(fields = type_encapsulated_union_get_fields(t))) break;
2026  LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
2027  {
2028  if (!var->type) continue;
2029  align = type_buffer_alignment( var->type );
2030  if (max < align) max = align;
2031  }
2032  break;
2033  case TYPE_UNION:
2034  if (!(fields = type_union_get_cases(t))) break;
2035  LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry )
2036  {
2037  if (!var->type) continue;
2038  align = type_buffer_alignment( var->type );
2039  if (max < align) max = align;
2040  }
2041  break;
2042  case TYPE_ARRAY:
2045  /* else fall through */
2046  case TYPE_POINTER:
2047  return 4;
2048  case TYPE_INTERFACE:
2049  case TYPE_ALIAS:
2050  case TYPE_VOID:
2051  case TYPE_COCLASS:
2052  case TYPE_MODULE:
2053  case TYPE_FUNCTION:
2054  case TYPE_BITFIELD:
2055  /* these types should not be encountered here due to language
2056  * restrictions (interface, void, coclass, module), logical
2057  * restrictions (alias - due to type_get_type call above) or
2058  * checking restrictions (function, bitfield). */
2059  assert(0);
2060  }
2061  return max;
2062 }
2063 
2065 {
2066  const var_t *var;
2068  return TRUE;
2069  if (!type_get_function_args(func->type))
2070  return FALSE;
2072  if (type_has_full_pointer( var->type, var->attrs, TRUE ))
2073  return TRUE;
2074  return FALSE;
2075 }
2076 
2077 void write_full_pointer_init(FILE *file, int indent, const var_t *func, int is_server)
2078 {
2079  print_file(file, indent, "__frame->_StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,%s);\n",
2080  is_server ? "XLAT_SERVER" : "XLAT_CLIENT");
2081  fprintf(file, "\n");
2082 }
2083 
2085 {
2086  print_file(file, indent, "NdrFullPointerXlatFree(__frame->_StubMsg.FullPtrXlatTables);\n");
2087  fprintf(file, "\n");
2088 }
2089 
2090 static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs,
2091  const type_t *type,
2092  enum type_context context,
2093  unsigned int offset,
2094  unsigned int *typeformat_offset)
2095 {
2096  unsigned int start_offset = *typeformat_offset;
2097  short reloff = offset - (*typeformat_offset + 2);
2098  int in_attr, out_attr;
2099  int pointer_type;
2100  unsigned char flags = 0;
2101 
2102  pointer_type = get_pointer_fc_context(type, attrs, context);
2103 
2104  in_attr = is_attr(attrs, ATTR_IN);
2105  out_attr = is_attr(attrs, ATTR_OUT);
2106  if (!in_attr && !out_attr) in_attr = 1;
2107 
2109  {
2110  if (out_attr && !in_attr && pointer_type == FC_RP)
2112  }
2113  else if (get_stub_mode() == MODE_Oif)
2114  {
2115  if (context == TYPE_CONTEXT_TOPLEVELPARAM && is_ptr(type) && pointer_type == FC_RP)
2116  {
2118  {
2119  case TGT_STRING:
2120  case TGT_POINTER:
2121  case TGT_CTXT_HANDLE:
2124  break;
2125  case TGT_IFACE_POINTER:
2126  if (in_attr && out_attr)
2128  break;
2129  default:
2130  break;
2131  }
2132  }
2133  }
2134 
2135  if (is_ptr(type))
2136  {
2138  if(is_declptr(ref) && !is_user_type(ref))
2140  if (pointer_type != FC_RP) {
2141  flags |= get_attrv(type->attrs, ATTR_ALLOCATE);
2142  }
2143  }
2144 
2145  print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
2146  pointer_type,
2147  flags,
2148  string_of_type(pointer_type));
2149  if (file)
2150  {
2151  if (flags & FC_ALLOCED_ON_STACK)
2152  fprintf(file, " [allocated_on_stack]");
2153  if (flags & FC_POINTER_DEREF)
2154  fprintf(file, " [pointer_deref]");
2155  if (flags & FC_DONT_FREE)
2156  fprintf(file, " [dont_free]");
2158  fprintf(file, " [all_nodes]");
2159  fprintf(file, " */\n");
2160  }
2161 
2162  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, offset);
2163  *typeformat_offset += 4;
2164 
2165  return start_offset;
2166 }
2167 
2168 static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs,
2169  const type_t *type, enum type_context context)
2170 {
2171  unsigned char fc;
2172  unsigned char pointer_fc;
2173  const type_t *ref;
2174  int in_attr = is_attr(attrs, ATTR_IN);
2175  int out_attr = is_attr(attrs, ATTR_OUT);
2176  unsigned char flags = FC_SIMPLE_POINTER;
2177 
2178  /* for historical reasons, write_simple_pointer also handled string types,
2179  * but no longer does. catch bad uses of the function with this check */
2180  if (is_string_type(attrs, type))
2181  error("write_simple_pointer: can't handle type %s which is a string type\n", type->name);
2182 
2183  pointer_fc = get_pointer_fc_context(type, attrs, context);
2184 
2186  if (type_get_type(ref) == TYPE_ENUM)
2187  fc = get_enum_fc(ref);
2188  else
2189  fc = get_basic_fc(ref);
2190 
2192  {
2193  if (out_attr && !in_attr && pointer_fc == FC_RP)
2195  }
2196  else if (get_stub_mode() == MODE_Oif)
2197  {
2198  if (context == TYPE_CONTEXT_TOPLEVELPARAM && fc == FC_ENUM16 && pointer_fc == FC_RP)
2200  }
2201 
2202  print_file(file, 2, "0x%02x, 0x%x,\t/* %s %s[simple_pointer] */\n",
2203  pointer_fc, flags, string_of_type(pointer_fc),
2204  flags & FC_ALLOCED_ON_STACK ? "[allocated_on_stack] " : "");
2205  print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
2206  print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
2207  return 4;
2208 }
2209 
2210 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
2211 {
2212  print_file(file, 0, "/* %u (", tfsoff);
2214  print_file(file, 0, ") */\n");
2215 }
2216 
2217 static unsigned int write_pointer_tfs(FILE *file, const attr_list_t *attrs,
2218  type_t *type, unsigned int ref_offset,
2219  enum type_context context,
2220  unsigned int *typestring_offset)
2221 {
2222  unsigned int offset = *typestring_offset;
2224 
2227 
2228  switch (typegen_detect_type(ref, attrs, TDT_ALL_TYPES))
2229  {
2230  case TGT_BASIC:
2231  case TGT_ENUM:
2232  *typestring_offset += write_simple_pointer(file, attrs, type, context);
2233  break;
2234  default:
2235  if (ref_offset)
2236  write_nonsimple_pointer(file, attrs, type, context, ref_offset, typestring_offset);
2237  break;
2238  }
2239 
2240  return offset;
2241 }
2242 
2243 static int processed(const type_t *type)
2244 {
2245  return type->typestring_offset && !type->tfswrite;
2246 }
2247 
2249 {
2250  if (is_ptr(t))
2251  return TRUE;
2252  else if (type_get_type(t) == TYPE_STRUCT)
2253  {
2254  switch (get_struct_fc(t))
2255  {
2256  case FC_PSTRUCT:
2257  case FC_CSTRUCT:
2258  case FC_CPSTRUCT:
2259  case FC_CVSTRUCT:
2260  return TRUE;
2261  }
2262  }
2263  /* Note: Since this only applies to user types, we can't have a conformant
2264  array here, and strings should get filed under pointer in this case. */
2265  return FALSE;
2266 }
2267 
2268 static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
2269 {
2270  unsigned int start, absoff, flags;
2271  const char *name = NULL;
2272  type_t *utype = get_user_type(type, &name);
2273  unsigned int usize = type_memsize(utype);
2274  unsigned int ualign = type_buffer_alignment(utype);
2275  unsigned int size = type_memsize(type);
2276  unsigned short funoff = user_type_offset(name);
2277  short reloff;
2278 
2279  if (processed(type)) return type->typestring_offset;
2280 
2281  guard_rec(type);
2282 
2283  if(user_type_has_variable_size(utype)) usize = 0;
2284 
2285  if (type_get_type(utype) == TYPE_BASIC ||
2286  type_get_type(utype) == TYPE_ENUM)
2287  {
2288  unsigned char fc;
2289 
2290  if (type_get_type(utype) == TYPE_ENUM)
2291  fc = get_enum_fc(utype);
2292  else
2293  fc = get_basic_fc(utype);
2294 
2295  absoff = *tfsoff;
2296  print_start_tfs_comment(file, utype, absoff);
2297  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
2298  print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
2299  *tfsoff += 2;
2300  }
2301  else
2302  {
2303  if (!processed(utype))
2304  write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
2305  absoff = utype->typestring_offset;
2306  }
2307 
2308  if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == FC_RP)
2309  flags = 0x40;
2310  else if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == FC_UP)
2311  flags = 0x80;
2312  else
2313  flags = 0;
2314 
2315  start = *tfsoff;
2318  print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", FC_USER_MARSHAL);
2319  print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
2320  flags | (ualign - 1), ualign - 1, flags);
2321  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
2322  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)size, size);
2323  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)usize, usize);
2324  *tfsoff += 8;
2325  reloff = absoff - *tfsoff;
2326  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, absoff);
2327  *tfsoff += 2;
2328  return start;
2329 }
2330 
2331 static void write_member_type(FILE *file, const type_t *cont,
2332  int cont_is_complex, const attr_list_t *attrs,
2333  const type_t *type, unsigned int *corroff,
2334  unsigned int *tfsoff)
2335 {
2337  {
2338  unsigned int absoff;
2339  short reloff;
2340 
2341  if (type_get_type(type) == TYPE_UNION && is_attr(attrs, ATTR_SWITCHIS))
2342  {
2343  absoff = *corroff;
2344  *corroff += 8;
2345  }
2346  else
2347  {
2348  absoff = type->typestring_offset;
2349  }
2350  reloff = absoff - (*tfsoff + 2);
2351 
2352  print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
2353  /* padding is represented using FC_STRUCTPAD* types, so presumably
2354  * this is left over in the format for historical purposes in MIDL
2355  * or rpcrt4. */
2356  print_file(file, 2, "0x0,\n");
2357  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2358  reloff, reloff, absoff);
2359  *tfsoff += 4;
2360  }
2361  else if (is_ptr(type) || is_conformant_array(type))
2362  {
2363  unsigned char fc = cont_is_complex ? FC_POINTER : FC_LONG;
2364  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
2365  *tfsoff += 1;
2366  }
2367  else if (!write_base_type(file, type, tfsoff))
2368  error("Unsupported member type %d\n", type_get_type(type));
2369 }
2370 
2371 static void write_array_element_type(FILE *file, const attr_list_t *attrs, const type_t *type,
2372  int cont_is_complex, unsigned int *tfsoff)
2373 {
2375 
2376  if (!is_embedded_complex(elem) && is_ptr(elem))
2377  {
2379 
2380  if (processed(ref))
2381  {
2383  ref->typestring_offset, tfsoff);
2384  return;
2385  }
2386  if (cont_is_complex && is_string_type(attrs, elem))
2387  {
2389  return;
2390  }
2391  if (!is_string_type(NULL, elem) &&
2393  {
2395  return;
2396  }
2397  }
2398  write_member_type(file, type, cont_is_complex, NULL, elem, NULL, tfsoff);
2399 }
2400 
2401 static void write_end(FILE *file, unsigned int *tfsoff)
2402 {
2403  if (*tfsoff % 2 == 0)
2404  {
2405  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
2406  *tfsoff += 1;
2407  }
2408  print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END);
2409  *tfsoff += 1;
2410 }
2411 
2412 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
2413 {
2414  unsigned int offset = 0;
2416  var_t *f;
2417 
2419  {
2420  type_t *ft = f->type;
2421  unsigned int size = field_memsize( ft, &offset );
2422  if (type_get_type(ft) == TYPE_UNION && is_attr(f->attrs, ATTR_SWITCHIS))
2423  {
2424  short reloff;
2425  unsigned int absoff = ft->typestring_offset;
2426  if (is_attr(ft->attrs, ATTR_SWITCHTYPE))
2427  absoff += 8; /* we already have a corr descr, skip it */
2428  reloff = absoff - (*tfsoff + 6);
2429  print_file(file, 0, "/* %d */\n", *tfsoff);
2430  print_file(file, 2, "0x%x,\t/* FC_NON_ENCAPSULATED_UNION */\n", FC_NON_ENCAPSULATED_UNION);
2431  print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", FC_LONG);
2433  get_attrp(f->attrs, ATTR_SWITCHIS));
2434  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2435  (unsigned short)reloff, reloff, absoff);
2436  *tfsoff += 8;
2437  }
2438  offset += size;
2439  }
2440 }
2441 
2443  FILE *file, const attr_list_t *attrs, type_t *type,
2444  unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2445  unsigned int *typestring_offset)
2446 {
2447  int written = 0;
2448 
2451  {
2452  if (offset_in_memory && offset_in_buffer)
2453  {
2454  unsigned int memsize;
2455 
2456  /* pointer instance
2457  *
2458  * note that MSDN states that for pointer layouts in structures,
2459  * this is a negative offset from the end of the structure, but
2460  * this statement is incorrect. all offsets are positive */
2461  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Memory offset = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory);
2462  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Buffer offset = %d */\n", (unsigned short)*offset_in_buffer, *offset_in_buffer);
2463 
2464  memsize = type_memsize(type);
2465  *offset_in_memory += memsize;
2466  /* increment these separately as in the case of conformant (varying)
2467  * structures these start at different values */
2468  *offset_in_buffer += memsize;
2469  }
2470  *typestring_offset += 4;
2471 
2472  if (is_ptr(type))
2473  {
2475 
2476  if (is_string_type(attrs, type))
2477  write_string_tfs(file, attrs, type, TYPE_CONTEXT_CONTAINER, NULL, typestring_offset);
2478  else if (processed(ref))
2480  ref->typestring_offset, typestring_offset);
2481  else if (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM)
2482  *typestring_offset += write_simple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER);
2483  else
2484  error("write_pointer_description_offsets: type format string unknown\n");
2485  }
2486  else
2487  {
2488  unsigned int offset = type->typestring_offset;
2489  /* skip over the pointer that is written for strings, since a
2490  * pointer has to be written in-place here */
2491  if (is_string_type(attrs, type))
2492  offset += 4;
2493  write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER, offset, typestring_offset);
2494  }
2495 
2496  return 1;
2497  }
2498 
2499  if (is_array(type))
2500  {
2502  file, attrs, type_array_get_element(type), offset_in_memory,
2503  offset_in_buffer, typestring_offset);
2504  }
2505  else if (is_non_complex_struct(type))
2506  {
2507  /* otherwise search for interesting fields to parse */
2508  const var_t *v;
2510  {
2511  if (offset_in_memory && offset_in_buffer)
2512  {
2513  unsigned int padding;
2514  unsigned int align = 0;
2516  padding = ROUNDING(*offset_in_memory, align);
2517  *offset_in_memory += padding;
2518  *offset_in_buffer += padding;
2519  }
2521  file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
2522  typestring_offset);
2523  }
2524  }
2525  else
2526  {
2527  if (offset_in_memory && offset_in_buffer)
2528  {
2529  unsigned int memsize = type_memsize(type);
2530  *offset_in_memory += memsize;
2531  /* increment these separately as in the case of conformant (varying)
2532  * structures these start at different values */
2533  *offset_in_buffer += memsize;
2534  }
2535  }
2536 
2537  return written;
2538 }
2539 
2541  FILE *file, const attr_list_t *attrs, type_t *type,
2542  unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2543  unsigned int *typestring_offset)
2544 {
2545  int written = 0;
2546 
2547  if (is_ptr(type) ||
2549  {
2550  print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", FC_NO_REPEAT);
2551  print_file(file, 2, "0x%02x, /* FC_PAD */\n", FC_PAD);
2552  *typestring_offset += 2;
2553 
2555  offset_in_memory, offset_in_buffer, typestring_offset);
2556  }
2557 
2559  {
2560  const var_t *v;
2562  {
2563  if (offset_in_memory && offset_in_buffer)
2564  {
2565  unsigned int padding;
2566  unsigned int align = 0;
2568  padding = ROUNDING(*offset_in_memory, align);
2569  *offset_in_memory += padding;
2570  *offset_in_buffer += padding;
2571  }
2573  file, v->attrs, v->type,
2574  offset_in_memory, offset_in_buffer, typestring_offset);
2575  }
2576  }
2577  else
2578  {
2579  unsigned int memsize = type_memsize(type);
2580  *offset_in_memory += memsize;
2581  /* increment these separately as in the case of conformant (varying)
2582  * structures these start at different values */
2583  *offset_in_buffer += memsize;
2584  }
2585 
2586  return written;
2587 }
2588 
2589 /* Note: if file is NULL return value is number of pointers to write, else
2590  * it is the number of type format characters written */
2592  FILE *file, const attr_list_t *attrs, type_t *type,
2593  unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2594  unsigned int *typestring_offset)
2595 {
2596  int pointer_count = 0;
2597 
2598  if (type_get_type(type) == TYPE_ARRAY &&
2600  {
2601  unsigned int temp = 0;
2602  /* unfortunately, this needs to be done in two passes to avoid
2603  * writing out redundant FC_FIXED_REPEAT descriptions */
2604  pointer_count = write_pointer_description_offsets(
2605  NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
2606  if (pointer_count > 0)
2607  {
2608  unsigned int increment_size;
2609  unsigned int offset_of_array_pointer_mem = 0;
2610  unsigned int offset_of_array_pointer_buf = 0;
2611 
2612  increment_size = type_memsize(type_array_get_element(type));
2613 
2614  print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", FC_FIXED_REPEAT);
2615  print_file(file, 2, "0x%02x, /* FC_PAD */\n", FC_PAD);
2616  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Iterations = %d */\n", (unsigned short)type_array_get_dim(type), type_array_get_dim(type));
2617  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
2618  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory);
2619  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count);
2620  *typestring_offset += 10;
2621 
2622  pointer_count = write_pointer_description_offsets(
2623  file, attrs, type, &offset_of_array_pointer_mem,
2624  &offset_of_array_pointer_buf, typestring_offset);
2625  }
2626  }
2627  else if (type_get_type(type) == TYPE_STRUCT)
2628  {
2629  const var_t *v;
2631  {
2632  if (offset_in_memory && offset_in_buffer)
2633  {
2634  unsigned int padding;
2635  unsigned int align = 0;
2637  padding = ROUNDING(*offset_in_memory, align);
2638  *offset_in_memory += padding;
2639  *offset_in_buffer += padding;
2640  }
2641  pointer_count += write_fixed_array_pointer_descriptions(
2642  file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
2643  typestring_offset);
2644  }
2645  }
2646  else
2647  {
2648  if (offset_in_memory && offset_in_buffer)
2649  {
2650  unsigned int memsize;
2651  memsize = type_memsize(type);
2652  *offset_in_memory += memsize;
2653  /* increment these separately as in the case of conformant (varying)
2654  * structures these start at different values */
2655  *offset_in_buffer += memsize;
2656  }
2657  }
2658 
2659  return pointer_count;
2660 }
2661 
2662 /* Note: if file is NULL return value is number of pointers to write, else
2663  * it is the number of type format characters written */
2665  FILE *file, const attr_list_t *attrs, type_t *type,
2666  unsigned int offset_in_memory, unsigned int *typestring_offset)
2667 {
2668  int pointer_count = 0;
2669 
2671  {
2672  unsigned int temp = 0;
2673  /* unfortunately, this needs to be done in two passes to avoid
2674  * writing out redundant FC_VARIABLE_REPEAT descriptions */
2675  pointer_count = write_pointer_description_offsets(
2676  NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
2677  if (pointer_count > 0)
2678  {
2679  unsigned int increment_size;
2680  unsigned int offset_of_array_pointer_mem = offset_in_memory;
2681  unsigned int offset_of_array_pointer_buf = offset_in_memory;
2682 
2683  increment_size = type_memsize(type_array_get_element(type));
2684 
2685  if (increment_size > USHRT_MAX)
2686  error("array size of %u bytes is too large\n", increment_size);
2687 
2688  print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", FC_VARIABLE_REPEAT);
2689  print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", FC_FIXED_OFFSET);
2690  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
2691  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)offset_in_memory, offset_in_memory);
2692  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count);
2693  *typestring_offset += 8;
2694 
2695  pointer_count = write_pointer_description_offsets(
2696  file, attrs, type_array_get_element(type),
2697  &offset_of_array_pointer_mem, &offset_of_array_pointer_buf,
2698  typestring_offset);
2699  }
2700  }
2701 
2702  return pointer_count;
2703 }
2704 
2705 /* Note: if file is NULL return value is number of pointers to write, else
2706  * it is the number of type format characters written */
2708  FILE *file, const attr_list_t *attrs, type_t *type,
2709  unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2710  unsigned int *typestring_offset)
2711 {
2712  int pointer_count = 0;
2713 
2715  {
2716  unsigned int temp = 0;
2717  /* unfortunately, this needs to be done in two passes to avoid
2718  * writing out redundant FC_VARIABLE_REPEAT descriptions */
2719  pointer_count = write_pointer_description_offsets(
2720  NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
2721  if (pointer_count > 0)
2722  {
2723  unsigned int increment_size;
2724 
2725  increment_size = type_memsize(type_array_get_element(type));
2726 
2727  if (increment_size > USHRT_MAX)
2728  error("array size of %u bytes is too large\n", increment_size);
2729 
2730  print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", FC_VARIABLE_REPEAT);
2731  print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", FC_VARIABLE_OFFSET);
2732  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
2733  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory);
2734  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count);
2735  *typestring_offset += 8;
2736 
2737  pointer_count = write_pointer_description_offsets(
2738  file, attrs, type_array_get_element(type), offset_in_memory,
2739  offset_in_buffer, typestring_offset);
2740  }
2741  }
2742  else if (type_get_type(type) == TYPE_STRUCT)
2743  {
2744  const var_t *v;
2746  {
2747  if (offset_in_memory && offset_in_buffer)
2748  {
2749  unsigned int align = 0, padding;
2750 
2751  if (is_array(v->type) && type_array_has_variance(v->type))
2752  {
2753  *offset_in_buffer = ROUND_SIZE(*offset_in_buffer, 4);
2754  /* skip over variance and offset in buffer */
2755  *offset_in_buffer += 8;
2756  }
2757 
2759  padding = ROUNDING(*offset_in_memory, align);
2760  *offset_in_memory += padding;
2761  *offset_in_buffer += padding;
2762  }
2764  file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
2765  typestring_offset);
2766  }
2767  }
2768  else
2769  {
2770  if (offset_in_memory && offset_in_buffer)
2771  {
2772  unsigned int memsize = type_memsize(type);
2773  *offset_in_memory += memsize;
2774  /* increment these separately as in the case of conformant (varying)
2775  * structures these start at different values */
2776  *offset_in_buffer += memsize;
2777  }
2778  }
2779 
2780  return pointer_count;
2781 }
2782 
2784  unsigned int *typestring_offset)
2785 {
2786  unsigned int offset_in_buffer;
2787  unsigned int offset_in_memory;
2788 
2789  /* pass 1: search for single instance of a pointer (i.e. don't descend
2790  * into arrays) */
2791  if (!is_array(type))
2792  {
2793  offset_in_memory = 0;
2794  offset_in_buffer = 0;
2796  file, NULL, type,
2797  &offset_in_memory, &offset_in_buffer, typestring_offset);
2798  }
2799 
2800  /* pass 2: search for pointers in fixed arrays */
2801  offset_in_memory = 0;
2802  offset_in_buffer = 0;
2804  file, NULL, type,
2805  &offset_in_memory, &offset_in_buffer, typestring_offset);
2806 
2807  /* pass 3: search for pointers in conformant only arrays (but don't descend
2808  * into conformant varying or varying arrays) */
2809  if (is_conformant_array(type) &&
2812  file, attrs, type, 0, typestring_offset);
2813  else if (type_get_type(type) == TYPE_STRUCT &&
2815  {
2818  type_memsize(type), typestring_offset);
2819  }
2820 
2821  /* pass 4: search for pointers in varying arrays */
2822  offset_in_memory = 0;
2823  offset_in_buffer = 0;
2825  file, NULL, type,
2826  &offset_in_memory, &offset_in_buffer, typestring_offset);
2827 }
2828 
2829 static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
2831  const char *name, unsigned int *typestring_offset)
2832 {
2833  unsigned int start_offset;
2834  unsigned char rtype;
2835  type_t *elem_type;
2836  int is_processed = processed(type);
2837 
2838  start_offset = *typestring_offset;
2839 
2840  if (is_declptr(type))
2841  {
2842  unsigned char flag = is_conformant_array(type) ? 0 : FC_SIMPLE_POINTER;
2843  int pointer_type = get_pointer_fc_context(type, attrs, context);
2844  if (!pointer_type)
2845  pointer_type = FC_RP;
2846  print_start_tfs_comment(file, type, *typestring_offset);
2847  print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
2848  pointer_type, flag, string_of_type(pointer_type),
2849  flag ? " [simple_pointer]" : "");
2850  *typestring_offset += 2;
2851  if (!flag)
2852  {
2853  print_file(file, 2, "NdrFcShort(0x2),\n");
2854  *typestring_offset += 2;
2855  }
2856  is_processed = FALSE;
2857  }
2858 
2859  if (is_array(type))
2860  elem_type = type_array_get_element(type);
2861  else
2862  elem_type = type_pointer_get_ref(type);
2863 
2864  if (type_get_type(elem_type) == TYPE_POINTER && is_array(type))
2865  return write_array_tfs(file, attrs, type, name, typestring_offset);
2866 
2867  if (type_get_type(elem_type) != TYPE_BASIC)
2868  {
2869  error("write_string_tfs: Unimplemented for non-basic type %s\n", name);
2870  return start_offset;
2871  }
2872 
2873  rtype = get_basic_fc(elem_type);
2874  if ((rtype != FC_BYTE) && (rtype != FC_CHAR) && (rtype != FC_WCHAR))
2875  {
2876  error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
2877  return start_offset;
2878  }
2879 
2881  {
2882  unsigned int dim = type_array_get_dim(type);
2883 
2884  if (is_processed) return start_offset;
2885 
2886  /* FIXME: multi-dimensional array */
2887  if (0xffffu < dim)
2888  error("array size for parameter %s exceeds %u bytes by %u bytes\n",
2889  name, 0xffffu, dim - 0xffffu);
2890 
2891  if (rtype == FC_WCHAR)
2892  WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
2893  else
2894  WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
2895  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
2896  *typestring_offset += 2;
2897 
2898  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)dim, dim);
2899  *typestring_offset += 2;
2900 
2901  update_tfsoff(type, start_offset, file);
2902  return start_offset;
2903  }
2904  else if (is_conformant_array(type))
2905  {
2906  if (rtype == FC_WCHAR)
2907  WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
2908  else
2909  WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
2910  print_file(file, 2, "0x%x,\t/* FC_STRING_SIZED */\n", FC_STRING_SIZED);
2911  *typestring_offset += 2;
2912 
2913  *typestring_offset += write_conf_or_var_desc(
2917  : 0),
2919 
2920  update_tfsoff(type, start_offset, file);
2921  return start_offset;
2922  }
2923  else
2924  {
2925  if (is_processed) return start_offset;
2926 
2927  if (rtype == FC_WCHAR)
2928  WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
2929  else
2930  WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
2931  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
2932  *typestring_offset += 2;
2933 
2934  update_tfsoff(type, start_offset, file);
2935  return start_offset;
2936  }
2937 }
2938 
2939 static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
2940  const char *name, unsigned int *typestring_offset)
2941 {
2942  const expr_t *length_is = type_array_get_variance(type);
2943  const expr_t *size_is = type_array_get_conformance(type);
2944  unsigned int align;
2945  unsigned int size;
2946  unsigned int start_offset;
2947  unsigned char fc;
2948  int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
2949  unsigned int baseoff
2952  : 0;
2953 
2954  if (!pointer_type)
2955  pointer_type = FC_RP;
2956 
2958  write_embedded_types(file, attrs, type_array_get_element(type), name, FALSE, typestring_offset);
2959 
2962  fc = get_array_fc(type);
2963 
2964  start_offset = *typestring_offset;
2965  update_tfsoff(type, start_offset, file);
2966  print_start_tfs_comment(file, type, start_offset);
2967  print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
2968  print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
2969  *typestring_offset += 2;
2970 
2971  align = 0;
2972  if (fc != FC_BOGUS_ARRAY)
2973  {
2974  if (fc == FC_LGFARRAY || fc == FC_LGVARRAY)
2975  {
2976  print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", size, size);
2977  *typestring_offset += 4;
2978  }
2979  else
2980  {
2981  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)size, size);
2982  *typestring_offset += 2;
2983  }
2984 
2986  *typestring_offset
2988  type, size_is);
2989 
2990  if (fc == FC_SMVARRAY || fc == FC_LGVARRAY)
2991  {
2992  unsigned int elsize = type_memsize(type_array_get_element(type));
2993  unsigned int dim = type_array_get_dim(type);
2994 
2995  if (fc == FC_LGVARRAY)
2996  {
2997  print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", dim, dim);
2998  *typestring_offset += 4;
2999  }
3000  else
3001  {
3002  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)dim, dim);
3003  *typestring_offset += 2;
3004  }
3005 
3006  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)elsize, elsize);
3007  *typestring_offset += 2;
3008  }
3009 
3010  if (length_is)
3011  *typestring_offset
3013  type, length_is);
3014 
3017  {
3018  print_file(file, 2, "0x%x,\t/* FC_PP */\n", FC_PP);
3019  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
3020  *typestring_offset += 2;
3021  write_pointer_description(file, is_string_type(attrs, type) ? attrs : NULL, type, typestring_offset);
3022  print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END);
3023  *typestring_offset += 1;
3024  }
3025 
3026  write_array_element_type(file, is_string_type(attrs, type) ? attrs : NULL, type, FALSE, typestring_offset);
3027  write_end(file, typestring_offset);
3028  }
3029  else
3030  {
3031  unsigned int dim = size_is ? 0 : type_array_get_dim(type);
3032  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)dim, dim);
3033  *typestring_offset += 2;
3034  *typestring_offset
3036  type, size_is);
3037  *typestring_offset
3039  type, length_is);
3040 
3041  write_array_element_type(file, is_string_type(attrs, type) ? attrs : NULL, type, TRUE, typestring_offset);
3042  write_end(file, typestring_offset);
3043  }
3044 
3045  return start_offset;
3046 }
3047 
3049 {
3050  const var_list_t *fields = type_struct_get_fields(type);
3051  const var_t *last_field;
3052  const type_t *ft;
3053 
3054  if (!fields || list_empty(fields))
3055  return NULL;
3056 
3057  last_field = LIST_ENTRY( list_tail(fields), const var_t, entry );
3058  ft = last_field->type;
3059 
3061  return last_field;
3062 
3063  if (type_get_type(ft) == TYPE_STRUCT)
3064  return find_array_or_string_in_struct(ft);
3065  else
3066  return NULL;
3067 }
3068 
3070  int is_complex, unsigned int *corroff,
3071  unsigned int *typestring_offset)
3072 {
3073  const var_t *field;
3074  unsigned short offset = 0;
3075  unsigned int salign = 1;
3076  int padding;
3078 
3079  if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
3080  {
3081  type_t *ft = field->type;
3082  unsigned int align = 0;
3083  unsigned int size = type_memsize_and_alignment(ft, &align);
3084  align = clamp_align(align);
3085  if (salign < align) salign = align;
3086 
3088  {
3089  if ((align - 1) & offset)
3090  {
3091  unsigned char fc = 0;
3092  switch (align)
3093  {
3094  case 2:
3095  fc = FC_ALIGNM2;
3096  break;
3097  case 4:
3098  fc = FC_ALIGNM4;
3099  break;
3100  case 8:
3101  fc = FC_ALIGNM8;
3102  break;
3103  default:
3104  error("write_struct_members: cannot align type %d\n", type_get_type(ft));
3105  }
3106  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
3108  *typestring_offset += 1;
3109  }
3110  write_member_type(file, type, is_complex, field->attrs, field->type, corroff,
3111  typestring_offset);
3112  offset += size;
3113  }
3114  }
3115 
3116  padding = ROUNDING(offset, salign);
3117  if (padding)
3118  {
3119  print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
3120  FC_STRUCTPAD1 + padding - 1,
3121  padding);
3122  *typestring_offset += 1;
3123  }
3124 
3125  write_end(file, typestring_offset);
3126 }
3127 
3128 static unsigned int write_struct_tfs(FILE *file, type_t *type,
3129  const char *name, unsigned int *tfsoff)
3130 {
3131  const type_t *save_current_structure = current_structure;
3132  unsigned int total_size;
3133  const var_t *array;
3134  unsigned int start_offset;
3135  unsigned int align;
3136  unsigned int corroff;
3137  var_t *f;
3138  unsigned char fc = get_struct_fc(type);
3140 
3141  if (processed(type)) return type->typestring_offset;
3142 
3143  guard_rec(type);
3145 
3146  total_size = type_memsize(type);
3148  if (total_size > USHRT_MAX)
3149  error("structure size for %s exceeds %d bytes by %d bytes\n",
3150  name, USHRT_MAX, total_size - USHRT_MAX);
3151 
3152  if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
3153  write_embedded_types(file, f->attrs, f->type, f->name, FALSE, tfsoff);
3154 
3156  if (array && !processed(array->type))
3157  {
3158  if(is_string_type(array->attrs, array->type))
3159  write_string_tfs(file, array->attrs, array->type, TYPE_CONTEXT_CONTAINER, array->name, tfsoff);
3160  else
3161  write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
3162  }
3163 
3164  corroff = *tfsoff;
3165  write_descriptors(file, type, tfsoff);
3166 
3167  start_offset = *tfsoff;
3168  update_tfsoff(type, start_offset, file);
3169  print_start_tfs_comment(file, type, start_offset);
3170  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
3171  print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
3172  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)total_size, total_size);
3173  *tfsoff += 4;
3174 
3175  if (array)
3176  {
3177  unsigned int absoff = array->type->typestring_offset;
3178  short reloff = absoff - *tfsoff;
3179  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
3180  reloff, reloff, absoff);
3181  *tfsoff += 2;
3182  }
3183  else if (fc == FC_BOGUS_STRUCT)
3184  {
3185  print_file(file, 2, "NdrFcShort(0x0),\n");
3186  *tfsoff += 2;
3187  }
3188 
3189  if (fc == FC_BOGUS_STRUCT)
3190  {
3191  /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
3192  nothing is written to file yet. On the actual writing pass,
3193  this will have been updated. */
3194  unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff;
3195  int reloff = absoff - *tfsoff;
3196  assert( reloff >= 0 );
3197  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %d (%u) */\n",
3198  (unsigned short)reloff, reloff, absoff);
3199  *tfsoff += 2;
3200  }
3201  else if ((fc == FC_PSTRUCT) ||
3202  (fc == FC_CPSTRUCT) ||
3204  {
3205  print_file(file, 2, "0x%x,\t/* FC_PP */\n", FC_PP);
3206  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
3207  *tfsoff += 2;
3209  print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END);
3210  *tfsoff += 1;
3211  }
3212 
3214  tfsoff);
3215 
3216  if (fc == FC_BOGUS_STRUCT)
3217  {
3218  const var_t *f;
3219 
3220  type->ptrdesc = *tfsoff;
3221  if (fields) LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
3222  {
3223  type_t *ft = f->type;
3225  {
3226  case TGT_POINTER:
3227  if (is_string_type(f->attrs, ft))
3228  write_string_tfs(file, f->attrs, ft, TYPE_CONTEXT_CONTAINER, f->name, tfsoff);
3229  else
3230  write_pointer_tfs(file, f->attrs, ft,
3231  type_pointer_get_ref(ft)->typestring_offset,
3232  TYPE_CONTEXT_CONTAINER, tfsoff);
3233  break;
3234  case TGT_ARRAY:
3235  if (type_array_is_decl_as_ptr(ft))
3236  {
3237  unsigned int offset;
3238 
3239  print_file(file, 0, "/* %d */\n", *tfsoff);
3240 
3241  offset = ft->typestring_offset;
3242  /* skip over the pointer that is written for strings, since a
3243  * pointer has to be written in-place here */
3244  if (is_string_type(f->attrs, ft))
3245  offset += 4;
3247  }
3248  break;
3249  default:
3250  break;
3251  }
3252  }
3253  if (type->ptrdesc == *tfsoff)
3254  type->ptrdesc = 0;
3255  }
3256 
3257  current_structure = save_current_structure;
3258  return start_offset;
3259 }
3260 
3261 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
3262 {
3263  if (t == NULL)
3264  {
3265  print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
3266  }
3267  else
3268  {
3270  {
3271  unsigned char fc;
3272  if (type_get_type(t) == TYPE_BASIC)
3273  fc = get_basic_fc(t);
3274  else
3275  fc = get_enum_fc(t);
3276  print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
3277  fc, string_of_type(fc));
3278  }
3279  else if (t->typestring_offset)
3280  {
3281  short reloff = t->typestring_offset - *tfsoff;
3282  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %d (%d) */\n",
3283  reloff, reloff, t->typestring_offset);
3284  }
3285  else
3286  error("write_branch_type: type unimplemented %d\n", type_get_type(t));
3287  }
3288 
3289  *tfsoff += 2;
3290 }
3291 
3292 static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
3293  type_t *type, unsigned int *tfsoff)
3294 {
3295  unsigned int start_offset;
3296  unsigned int size;
3297  var_list_t *fields;
3298  unsigned int nbranch = 0;
3299  type_t *deftype = NULL;
3300  short nodeftype = 0xffff;
3301  unsigned int dummy;
3302  var_t *f;
3303 
3304  if (processed(type) &&
3306  return type->typestring_offset;
3307 
3308  guard_rec(type);
3309 
3310  fields = type_union_get_cases(type);
3311 
3312  size = union_memsize(fields, &dummy);
3313 
3314  if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
3315  {
3316  expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
3317  if (cases)
3318  nbranch += list_count(cases);
3319  if (f->type)
3320  write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
3321  }
3322 
3323  start_offset = *tfsoff;
3324  update_tfsoff(type, start_offset, file);
3325  print_start_tfs_comment(file, type, start_offset);
3327  {
3328  const var_t *sv = type_union_get_switch_value(type);
3329  const type_t *st = sv->type;
3330  unsigned int align = 0;
3331  unsigned char fc;
3332 
3333  if (type_get_type(st) == TYPE_BASIC)
3334  {
3335  fc = get_basic_fc(st);
3336  switch (fc)
3337  {
3338  case FC_CHAR:
3339  case FC_SMALL:
3340  case FC_BYTE:
3341  case FC_USMALL:
3342  case FC_WCHAR:
3343  case FC_SHORT:
3344  case FC_USHORT:
3345  case FC_LONG:
3346  case FC_ULONG:
3347  break;
3348  default:
3349  fc = 0;
3350  error("union switch type must be an integer, char, or enum\n");
3351  }
3352  }
3353  else if (type_get_type(st) == TYPE_ENUM)
3354  fc = get_enum_fc(st);
3355  else
3356  error("union switch type must be an integer, char, or enum\n");
3357 
3359  if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
3360  {
3361  if (f->type)
3363  }
3364 
3365  print_file(file, 2, "0x%x,\t/* FC_ENCAPSULATED_UNION */\n", FC_ENCAPSULATED_UNION);
3366  print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
3367  (align << 4) | fc, string_of_type(fc));
3368  *tfsoff += 2;
3369  }
3370  else if (is_attr(type->attrs, ATTR_SWITCHTYPE))
3371  {
3372  const expr_t *switch_is = get_attrp(attrs, ATTR_SWITCHIS);
3373  const type_t *st = get_attrp(type->attrs, ATTR_SWITCHTYPE);
3374  unsigned char fc;
3375 
3376  if (type_get_type(st) == TYPE_BASIC)
3377  {
3378  fc = get_basic_fc(st);
3379  switch (fc)
3380  {
3381  case FC_CHAR:
3382  case FC_SMALL:
3383  case FC_USMALL:
3384  case FC_SHORT:
3385  case FC_USHORT:
3386  case FC_LONG:
3387  case FC_ULONG:
3388  case FC_ENUM16:
3389  case FC_ENUM32:
3390  break;
3391  default:
3392  fc = 0;
3393  error("union switch type must be an integer, char, or enum\n");
3394  }
3395  }
3396  else if (type_get_type(st) == TYPE_ENUM)
3397  fc = get_enum_fc(st);
3398  else
3399  error("union switch type must be an integer, char, or enum\n");
3400 
3401  print_file(file, 2, "0x%x,\t/* FC_NON_ENCAPSULATED_UNION */\n", FC_NON_ENCAPSULATED_UNION);
3402  print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
3403  fc, string_of_type(fc));
3404  *tfsoff += 2;
3405  *tfsoff += write_conf_or_var_desc(file, current_structure, 0, st, switch_is );
3406  print_file(file, 2, "NdrFcShort(0x2),\t/* Offset= 2 (%u) */\n", *tfsoff + 2);
3407  *tfsoff += 2;
3408  print_file(file, 0, "/* %u */\n", *tfsoff);
3409  }
3410 
3411  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)size, size);
3412  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)nbranch, nbranch);
3413  *tfsoff += 4;
3414 
3415  if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
3416  {
3417  type_t *ft = f->type;
3418  expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
3419  int deflt = is_attr(f->attrs, ATTR_DEFAULT);
3420  expr_t *c;
3421 
3422  if (cases == NULL && !deflt)
3423  error("union field %s with neither case nor default attribute\n", f->name);
3424 
3425  if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
3426  {
3427  /* MIDL doesn't check for duplicate cases, even though that seems
3428  like a reasonable thing to do, it just dumps them to the TFS
3429  like we're going to do here. */
3430  print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
3431  *tfsoff += 4;
3432  write_branch_type(file, ft, tfsoff);
3433  }
3434 
3435  /* MIDL allows multiple default branches, even though that seems
3436  illogical, it just chooses the last one, which is what we will
3437  do. */
3438  if (deflt)
3439  {
3440  deftype = ft;
3441  nodeftype = 0;
3442  }
3443  }
3444 
3445  if (deftype)
3446  {
3447  write_branch_type(file, deftype, tfsoff);
3448  }
3449  else
3450  {
3451  print_file(file, 2, "NdrFcShort(0x%hx),\n", nodeftype);
3452  *tfsoff += 2;
3453  }
3454 
3455  return start_offset;
3456 }
3457 
3458 static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
3459  unsigned int *typeformat_offset)
3460 {
3461  unsigned int i;
3462  unsigned int start_offset = *typeformat_offset;
3463  expr_t *iid = get_attrp(attrs, ATTR_IIDIS);
3464 
3465  if (!iid && processed(type)) return type->typestring_offset;
3466 
3467  print_start_tfs_comment(file, type, start_offset);
3468  update_tfsoff(type, start_offset, file);
3469 
3470  if (iid)
3471  {
3472  print_file(file, 2, "0x2f, /* FC_IP */\n");
3473  print_file(file, 2, "0x5c, /* FC_PAD */\n");
3474  *typeformat_offset
3476  }
3477  else
3478  {
3480  const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
3481 
3482  if (! uuid)
3483  error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
3484 
3485  print_file(file, 2, "0x2f,\t/* FC_IP */\n");
3486  print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
3487  print_file(file, 2, "NdrFcLong(0x%08x),\n", uuid->Data1);
3488  print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
3489  print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
3490  for (i = 0; i < 8; ++i)
3491  print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
3492 
3493  if (file)
3494  fprintf(file, "\n");
3495 
3496  *typeformat_offset += 18;
3497  }
3498  return start_offset;
3499 }
3500 
3501 static unsigned int write_contexthandle_tfs(FILE *file,
3502  const attr_list_t *attrs,
3503  type_t *type,
3504  int toplevel_param,
3505  unsigned int *typeformat_offset)
3506 {
3507  unsigned int start_offset = *typeformat_offset;
3508  unsigned char flags = get_contexthandle_flags( current_iface, attrs, type );
3509 
3510  print_start_tfs_comment(file, type, start_offset);
3511 
3512  if (flags & 0x80) /* via ptr */
3513  {
3514  int pointer_type = get_pointer_fc( type, attrs, toplevel_param );
3515  if (!pointer_type) pointer_type = FC_RP;
3516  *typeformat_offset += 4;
3517  print_file(file, 2,"0x%x, 0x0,\t/* %s */\n", pointer_type, string_of_type(pointer_type) );
3518  print_file(file, 2, "NdrFcShort(0x2),\t /* Offset= 2 (%u) */\n", *typeformat_offset);
3519  print_file(file, 0, "/* %2u */\n", *typeformat_offset);
3520  }
3521 
3522  print_file(file, 2, "0x%02x,\t/* FC_BIND_CONTEXT */\n", FC_BIND_CONTEXT);
3523  print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
3524  /* return and can't be null values overlap */
3525  if (((flags & 0x21) != 0x21) && (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL))
3526  print_file(file, 0, "can't be null, ");
3528  print_file(file, 0, "serialize, ");
3530  print_file(file, 0, "no serialize, ");
3532  print_file(file, 0, "strict, ");
3533  if ((flags & 0x21) == 0x20)
3534  print_file(file, 0, "out, ");
3535  if ((flags & 0x21) == 0x21)
3536  print_file(file, 0, "return, ");
3537  if (flags & 0x40)
3538  print_file(file, 0, "in, ");
3539  if (flags & 0x80)
3540  print_file(file, 0, "via ptr, ");
3541  print_file(file, 0, "*/\n");
3542  print_file(file, 2, "0x%x,\t/* rundown routine */\n", get_context_handle_offset( type ));
3543  print_file(file, 2, "0, /* FIXME: param num */\n");
3544  *typeformat_offset += 4;
3545 
3546  update_tfsoff( type, start_offset, file );
3547  return start_offset;
3548 }
3549 
3550 static unsigned int write_range_tfs(FILE *file, const attr_list_t *attrs,
3551  type_t *type, expr_list_t *range_list,
3552  unsigned int *typeformat_offset)
3553 {
3554  unsigned char fc;
3555  unsigned int start_offset = *typeformat_offset;
3556  const expr_t *range_min = LIST_ENTRY(list_head(range_list), const expr_t, entry);
3557  const expr_t *range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry);
3558 
3559  if (type_get_type(type) == TYPE_BASIC)
3560  fc = get_basic_fc(type);
3561  else
3562  fc = get_enum_fc(type);
3563 
3564  /* fc must fit in lower 4-bits of 8-bit field below */
3565  assert(fc <= 0xf);
3566 
3567  print_file(file, 0, "/* %u */\n", *typeformat_offset);
3568  print_file(file, 2, "0x%x,\t/* FC_RANGE */\n", FC_RANGE);
3569  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
3570  print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_min->cval, range_min->cval);
3571  print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_max->cval, range_max->cval);
3572  update_tfsoff( type, start_offset, file );
3573  *typeformat_offset += 10;
3574 
3575  return start_offset;
3576 }
3577 
3578 static unsigned int write_type_tfs(FILE *file, int indent,
3579  const attr_list_t *attrs, type_t *type,
3580  const char *name,
3581  enum type_context context,
3582  unsigned int *typeformat_offset)
3583 {
3584  unsigned int offset;
3585 
3586  switch (typegen_detect_type(type, attrs, TDT_ALL_TYPES))
3587  {
3588  case TGT_CTXT_HANDLE:
3590  return write_contexthandle_tfs(file, attrs, type,
3591  context == TYPE_CONTEXT_TOPLEVELPARAM, typeformat_offset);
3592  case TGT_USER_TYPE:
3593  return write_user_tfs(file, type, typeformat_offset);
3594  case TGT_STRING:
3595  return write_string_tfs(file, attrs, type, context, name, typeformat_offset);
3596  case TGT_ARRAY:
3597  {
3598  unsigned int off;
3599  /* conformant and pointer arrays are handled specially */
3600  if ((context != TYPE_CONTEXT_CONTAINER &&
3603  off = write_array_tfs(file, attrs, type, name, typeformat_offset);
3604  else
3605  off = 0;
3608  {
3609  int ptr_type;
3610  ptr_type = get_pointer_fc(type, attrs,
3612  if (ptr_type != FC_RP || type_array_is_decl_as_ptr(type))
3613  {
3614  unsigned int absoff = type->typestring_offset;
3615  short reloff = absoff - (*typeformat_offset + 2);
3616  off = *typeformat_offset;
3617  print_file(file, 0, "/* %d */\n", off);
3618  print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
3619  string_of_type(ptr_type));
3620  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
3621  reloff, reloff, absoff);
3622  if (ptr_type != FC_RP) update_tfsoff( type, off, file );
3623  *typeformat_offset += 4;
3624  }
3625  type->details.array.ptr_tfsoff = off;
3626  }
3627  return off;
3628  }
3629  case TGT_STRUCT:
3630  return write_struct_tfs(file, type, name, typeformat_offset);
3631  case TGT_UNION:
3632  return write_union_tfs(file, attrs, type, typeformat_offset);
3633  case TGT_ENUM:
3634  case TGT_BASIC:
3635  /* nothing to do */
3636  return 0;
3637  case TGT_RANGE:
3638  {
3639  expr_list_t *range_list = get_attrp(attrs, ATTR_RANGE);
3640  if (!range_list)
3641  range_list = get_aliaschain_attrp(type, ATTR_RANGE);
3642  return write_range_tfs(file, attrs, type, range_list, typeformat_offset);
3643  }
3644  case TGT_IFACE_POINTER:
3645  return write_ip_tfs(file, attrs, type, typeformat_offset);
3646  case TGT_POINTER:
3647  {
3648  enum type_context ref_context;
3649  unsigned int toplevel_offset = *typeformat_offset;
3651 
3653  ref_context = TYPE_CONTEXT_PARAM;
3655  ref_context = TYPE_CONTEXT_CONTAINER;
3656  else
3657  ref_context = context;
3658 
3659  if (is_string_type(attrs, ref))
3660  {
3662  write_pointer_tfs(file, attrs, type, *typeformat_offset + 4, context, typeformat_offset);
3663 
3664  offset = write_type_tfs(file, indent, attrs, ref, name, ref_context, typeformat_offset);
3666  return 0;
3667  return (context == TYPE_CONTEXT_TOPLEVELPARAM) ? toplevel_offset : offset;
3668  }
3669 
3671  ref_context, typeformat_offset);
3673  return 0;
3674  return write_pointer_tfs(file, attrs, type, offset, context, typeformat_offset);
3675  }
3676  case TGT_INVALID:
3677  break;
3678  }
3679  error("invalid type %s for var %s\n", type->name, name);
3680  return 0;
3681 }
3682 
3683 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
3684  const char *name, int write_ptr, unsigned int *tfsoff)
3685 {
3686  return write_type_tfs(file, 2, attrs, type, name, write_ptr ? TYPE_CONTEXT_CONTAINER : TYPE_CONTEXT_CONTAINER_NO_POINTERS, tfsoff);
3687 }
3688 
3689 static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned int *offset)
3690 {
3692  const statement_t *stmt;
3693  var_t *var;
3694 
3695  current_iface = iface;
3696  if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry )
3697  {
3698  switch(stmt->type)
3699  {
3700  case STMT_DECLARATION:
3701  {
3702  const var_t *func = stmt->u.var;
3703 
3704  if(stmt->u.var->stgclass != STG_NONE
3706  continue;
3707 
3708  current_func = func;
3709  if (is_local(func->attrs)) continue;
3710 
3712  if (!is_void(var->type))
3713  var->typestring_offset = write_type_tfs( file, 2, func->attrs, var->type, func->name,
3715 
3716  if (type_get_function_args(func->type))
3718  var->typestring_offset = write_type_tfs( file, 2, var->attrs, var->type, var->name,
3720  break;
3721 
3722  }
3723  case STMT_TYPEDEF:
3724  {
3725  const type_list_t *type_entry;
3726  for (type_entry = stmt->u.type_list; type_entry; type_entry = type_entry->next)
3727  {
3728  if (is_attr(type_entry->type->attrs, ATTR_ENCODE)
3729  || is_attr(type_entry->type->attrs, ATTR_DECODE))
3730  type_entry->type->typestring_offset = write_type_tfs( file, 2,
3731  type_entry->type->attrs, type_entry->type, type_entry->type->name,
3733  }
3734  break;
3735  }
3736  default:
3737  break;
3738  }
3739  }
3740 }
3741 
3742 static unsigned int process_tfs(FILE *file, const statement_list_t *stmts, type_pred_t pred)
3743 {
3744  unsigned int typeformat_offset = 2;
3745  for_each_iface(stmts, process_tfs_iface, pred, file, 0, &typeformat_offset);
3746  return typeformat_offset + 1;
3747 }
3748 
3749 
3751 {
3752  int indent = 0;
3753 
3754  print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
3755  print_file(file, indent, "{\n");
3756  indent++;
3757  print_file(file, indent, "0,\n");
3758  print_file(file, indent, "{\n");
3759  indent++;
3760  print_file(file, indent, "NdrFcShort(0x0),\n");
3761 
3763  process_tfs(file, stmts, pred);
3764 
3765  print_file(file, indent, "0x0\n");
3766  indent--;
3767  print_file(file, indent, "}\n");
3768  indent--;
3769  print_file(file, indent, "};\n");
3770  print_file(file, indent, "\n");
3771 }
3772 
3773 static unsigned int get_required_buffer_size_type(
3774  const type_t *type, const char *name, const attr_list_t *attrs, int toplevel_param, unsigned int *alignment)
3775 {
3776  *alignment = 0;
3778  {
3779  case TGT_USER_TYPE:
3780  {
3781  const char *uname = NULL;
3782  const type_t *utype = get_user_type(type, &uname);
3783  return get_required_buffer_size_type(utype, uname, NULL, FALSE, alignment);
3784  }
3785  case TGT_BASIC:
3786  switch (get_basic_fc(type))
3787  {
3788  case FC_BYTE:
3789  case FC_CHAR:
3790  case FC_USMALL:
3791  case FC_SMALL:
3792  *alignment = 4;
3793  return 1;
3794 
3795  case FC_WCHAR:
3796  case FC_USHORT:
3797  case FC_SHORT:
3798  *alignment = 4;
3799  return 2;
3800 
3801  case FC_ULONG:
3802  case FC_LONG:
3803  case FC_FLOAT:
3804  case FC_ERROR_STATUS_T:
3805  *alignment = 4;
3806  return 4;
3807 
3808  case FC_HYPER:
3809  case FC_DOUBLE:
3810  *alignment = 8;
3811  return 8;
3812 
3813  case FC_INT3264:
3814  case FC_UINT3264:
3815  assert( pointer_size );
3816  *alignment = pointer_size;
3817  return pointer_size;
3818 
3819  case FC_IGNORE:
3820  case FC_BIND_PRIMITIVE:
3821  return 0;
3822 
3823  default:
3824  error("get_required_buffer_size: unknown basic type 0x%02x\n",
3825  get_basic_fc(type));
3826  return 0;
3827  }
3828  break;
3829 
3830  case TGT_ENUM:
3831  switch (get_enum_fc(type))
3832  {
3833  case FC_ENUM32:
3834  *alignment = 4;
3835  return 4;
3836  case FC_ENUM16:
3837  *alignment = 4;
3838  return 2;
3839  }
3840  break;
3841 
3842  case TGT_STRUCT:
3843  if (get_struct_fc(type) == FC_STRUCT)
3844  {
3845  if (!type_struct_get_fields(type)) return 0;
3846  return fields_memsize(type_struct_get_fields(type), alignment);
3847  }
3848  break;
3849 
3850  case TGT_POINTER:
3851  {
3852  unsigned int size, align;
3853  const type_t *ref = type_pointer_get_ref(type);
3854  if (is_string_type( attrs, ref )) break;
3855  if (!(size = get_required_buffer_size_type( ref, name, NULL, FALSE, &align ))) break;
3856  if (get_pointer_fc(type, attrs, toplevel_param) != FC_RP)
3857  {
3858  size += 4 + align;
3859  align = 4;
3860  }
3861  *alignment = align;
3862  return size;
3863  }
3864 
3865  case TGT_ARRAY:
3866  if (get_pointer_fc(type, attrs, toplevel_param) == FC_RP)
3867  {
3868  switch (get_array_fc(type))
3869  {
3870  case FC_SMFARRAY:
3871  case FC_LGFARRAY:
3872  return type_array_get_dim(type) *
3874  NULL, FALSE, alignment);
3875  }
3876  }
3877  break;
3878 
3879  default:
3880  break;
3881  }
3882  return 0;
3883 }
3884 
3885 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
3886 {
3887  int in_attr = is_attr(var->attrs, ATTR_IN);
3888  int out_attr = is_attr(var->attrs, ATTR_OUT);
3889 
3890  if (!in_attr && !out_attr)
3891  in_attr = 1;
3892 
3893  *alignment = 0;
3894 
3895  if ((pass == PASS_IN && in_attr) || (pass == PASS_OUT && out_attr) ||
3896  pass == PASS_RETURN)
3897  {
3899  {
3900  *alignment = 4;
3901  return 20;
3902  }
3903 
3904  if (!is_string_type(var->attrs, var->type))
3905  return get_required_buffer_size_type(var->type, var->name,
3906  var->attrs, TRUE, alignment);
3907  }
3908  return 0;
3909 }
3910 
3911 static unsigned int get_function_buffer_size( const var_t *func, enum pass pass )
3912 {
3913  const var_t *var;
3914  unsigned int total_size = 0, alignment;
3915 
3916  if (type_get_function_args(func->type))
3917  {
3919  {
3920  total_size += get_required_buffer_size(var, &alignment, pass);
3921  total_size += alignment;
3922  }
3923  }
3924 
3925  if (pass == PASS_OUT && !is_void(type_function_get_rettype(func->type)))
3926  {
3927  var_t v = *func;
3928  v.type = type_function_get_rettype(func->type);
3929  total_size += get_required_buffer_size(&v, &alignment, PASS_RETURN);
3930  total_size += alignment;
3931  }
3932  return total_size;
3933 }
3934 
3935 static void print_phase_function(FILE *file, int indent, const char *type,
3936  const char *local_var_prefix, enum remoting_phase phase,
3937  const var_t *var, unsigned int type_offset)
3938 {
3939  const char *function;
3940  switch (phase)
3941  {
3942  case PHASE_BUFFERSIZE:
3943  function = "BufferSize";
3944  break;
3945  case PHASE_MARSHAL:
3946  function = "Marshall";
3947  break;
3948  case PHASE_UNMARSHAL:
3949  function = "Unmarshall";
3950  break;
3951  case PHASE_FREE:
3952  function = "Free";
3953  break;
3954  default:
3955  assert(0);
3956  return;
3957  }
3958 
3959  print_file(file, indent, "Ndr%s%s(\n", type, function);
3960  indent++;
3961  print_file(file, indent, "&__frame->_StubMsg,\n");
3962  print_file(file, indent, "%s%s%s%s%s,\n",
3963  (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
3964  (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
3965  local_var_prefix,
3966  (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
3967  var->name);
3968  print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
3969  type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
3970  if (phase == PHASE_UNMARSHAL)
3971  print_file(file, indent, "0);\n");
3972  indent--;
3973 }
3974 
3975 void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix,
3976  enum remoting_phase phase, enum pass pass, const var_t *var,
3977  const char *varname)
3978 {
3979  type_t *type = var->type;
3980  unsigned int alignment = 0;
3981 
3982  /* no work to do for other phases, buffer sizing is done elsewhere */
3983  if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
3984  return;
3985 
3986  if (type_get_type(type) == TYPE_ENUM ||
3987  (type_get_type(type) == TYPE_BASIC &&
3989  pointer_size != 4))
3990  {
3991  unsigned char fc;
3992 
3993  if (