ReactOS  0.4.14-dev-337-gf981a68
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) &&
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 
1315  if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry )
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;
1403  if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry )
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  }
2141 
2142  print_file(file, 2, "0x%x, 0x%x,\t\t/* %s",
2143  pointer_type,
2144  flags,
2145  string_of_type(pointer_type));
2146  if (file)
2147  {
2148  if (flags & FC_ALLOCED_ON_STACK)
2149  fprintf(file, " [allocated_on_stack]");
2150  if (flags & FC_POINTER_DEREF)
2151  fprintf(file, " [pointer_deref]");
2152  fprintf(file, " */\n");
2153  }
2154 
2155  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, offset);
2156  *typeformat_offset += 4;
2157 
2158  return start_offset;
2159 }
2160 
2161 static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs,
2162  const type_t *type, enum type_context context)
2163 {
2164  unsigned char fc;
2165  unsigned char pointer_fc;
2166  const type_t *ref;
2167  int in_attr = is_attr(attrs, ATTR_IN);
2168  int out_attr = is_attr(attrs, ATTR_OUT);
2169  unsigned char flags = FC_SIMPLE_POINTER;
2170 
2171  /* for historical reasons, write_simple_pointer also handled string types,
2172  * but no longer does. catch bad uses of the function with this check */
2173  if (is_string_type(attrs, type))
2174  error("write_simple_pointer: can't handle type %s which is a string type\n", type->name);
2175 
2176  pointer_fc = get_pointer_fc_context(type, attrs, context);
2177 
2179  if (type_get_type(ref) == TYPE_ENUM)
2180  fc = get_enum_fc(ref);
2181  else
2182  fc = get_basic_fc(ref);
2183 
2185  {
2186  if (out_attr && !in_attr && pointer_fc == FC_RP)
2188  }
2189  else if (get_stub_mode() == MODE_Oif)
2190  {
2191  if (context == TYPE_CONTEXT_TOPLEVELPARAM && fc == FC_ENUM16 && pointer_fc == FC_RP)
2193  }
2194 
2195  print_file(file, 2, "0x%02x, 0x%x,\t/* %s %s[simple_pointer] */\n",
2196  pointer_fc, flags, string_of_type(pointer_fc),
2197  flags & FC_ALLOCED_ON_STACK ? "[allocated_on_stack] " : "");
2198  print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
2199  print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
2200  return 4;
2201 }
2202 
2203 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff)
2204 {
2205  print_file(file, 0, "/* %u (", tfsoff);
2207  print_file(file, 0, ") */\n");
2208 }
2209 
2210 static unsigned int write_pointer_tfs(FILE *file, const attr_list_t *attrs,
2211  type_t *type, unsigned int ref_offset,
2212  enum type_context context,
2213  unsigned int *typestring_offset)
2214 {
2215  unsigned int offset = *typestring_offset;
2217 
2220 
2221  switch (typegen_detect_type(ref, attrs, TDT_ALL_TYPES))
2222  {
2223  case TGT_BASIC:
2224  case TGT_ENUM:
2225  *typestring_offset += write_simple_pointer(file, attrs, type, context);
2226  break;
2227  default:
2228  if (ref_offset)
2229  write_nonsimple_pointer(file, attrs, type, context, ref_offset, typestring_offset);
2230  break;
2231  }
2232 
2233  return offset;
2234 }
2235 
2236 static int processed(const type_t *type)
2237 {
2238  return type->typestring_offset && !type->tfswrite;
2239 }
2240 
2242 {
2243  if (is_ptr(t))
2244  return TRUE;
2245  else if (type_get_type(t) == TYPE_STRUCT)
2246  {
2247  switch (get_struct_fc(t))
2248  {
2249  case FC_PSTRUCT:
2250  case FC_CSTRUCT:
2251  case FC_CPSTRUCT:
2252  case FC_CVSTRUCT:
2253  return TRUE;
2254  }
2255  }
2256  /* Note: Since this only applies to user types, we can't have a conformant
2257  array here, and strings should get filed under pointer in this case. */
2258  return FALSE;
2259 }
2260 
2261 static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff)
2262 {
2263  unsigned int start, absoff, flags;
2264  const char *name = NULL;
2265  type_t *utype = get_user_type(type, &name);
2266  unsigned int usize = type_memsize(utype);
2267  unsigned int ualign = type_buffer_alignment(utype);
2268  unsigned int size = type_memsize(type);
2269  unsigned short funoff = user_type_offset(name);
2270  short reloff;
2271 
2272  if (processed(type)) return type->typestring_offset;
2273 
2274  guard_rec(type);
2275 
2276  if(user_type_has_variable_size(utype)) usize = 0;
2277 
2278  if (type_get_type(utype) == TYPE_BASIC ||
2279  type_get_type(utype) == TYPE_ENUM)
2280  {
2281  unsigned char fc;
2282 
2283  if (type_get_type(utype) == TYPE_ENUM)
2284  fc = get_enum_fc(utype);
2285  else
2286  fc = get_basic_fc(utype);
2287 
2288  absoff = *tfsoff;
2289  print_start_tfs_comment(file, utype, absoff);
2290  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
2291  print_file(file, 2, "0x5c,\t/* FC_PAD */\n");
2292  *tfsoff += 2;
2293  }
2294  else
2295  {
2296  if (!processed(utype))
2297  write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff);
2298  absoff = utype->typestring_offset;
2299  }
2300 
2301  if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == FC_RP)
2302  flags = 0x40;
2303  else if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == FC_UP)
2304  flags = 0x80;
2305  else
2306  flags = 0;
2307 
2308  start = *tfsoff;
2311  print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", FC_USER_MARSHAL);
2312  print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n",
2313  flags | (ualign - 1), ualign - 1, flags);
2314  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff);
2315  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)size, size);
2316  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)usize, usize);
2317  *tfsoff += 8;
2318  reloff = absoff - *tfsoff;
2319  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, absoff);
2320  *tfsoff += 2;
2321  return start;
2322 }
2323 
2324 static void write_member_type(FILE *file, const type_t *cont,
2325  int cont_is_complex, const attr_list_t *attrs,
2326  const type_t *type, unsigned int *corroff,
2327  unsigned int *tfsoff)
2328 {
2330  {
2331  unsigned int absoff;
2332  short reloff;
2333 
2334  if (type_get_type(type) == TYPE_UNION && is_attr(attrs, ATTR_SWITCHIS))
2335  {
2336  absoff = *corroff;
2337  *corroff += 8;
2338  }
2339  else
2340  {
2341  absoff = type->typestring_offset;
2342  }
2343  reloff = absoff - (*tfsoff + 2);
2344 
2345  print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n");
2346  /* padding is represented using FC_STRUCTPAD* types, so presumably
2347  * this is left over in the format for historical purposes in MIDL
2348  * or rpcrt4. */
2349  print_file(file, 2, "0x0,\n");
2350  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2351  reloff, reloff, absoff);
2352  *tfsoff += 4;
2353  }
2354  else if (is_ptr(type) || is_conformant_array(type))
2355  {
2356  unsigned char fc = cont_is_complex ? FC_POINTER : FC_LONG;
2357  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
2358  *tfsoff += 1;
2359  }
2360  else if (!write_base_type(file, type, tfsoff))
2361  error("Unsupported member type %d\n", type_get_type(type));
2362 }
2363 
2364 static void write_array_element_type(FILE *file, const attr_list_t *attrs, const type_t *type,
2365  int cont_is_complex, unsigned int *tfsoff)
2366 {
2368 
2369  if (!is_embedded_complex(elem) && is_ptr(elem))
2370  {
2372 
2373  if (processed(ref))
2374  {
2376  ref->typestring_offset, tfsoff);
2377  return;
2378  }
2379  if (cont_is_complex && is_string_type(attrs, elem))
2380  {
2382  return;
2383  }
2384  if (!is_string_type(NULL, elem) &&
2386  {
2388  return;
2389  }
2390  }
2391  write_member_type(file, type, cont_is_complex, NULL, elem, NULL, tfsoff);
2392 }
2393 
2394 static void write_end(FILE *file, unsigned int *tfsoff)
2395 {
2396  if (*tfsoff % 2 == 0)
2397  {
2398  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
2399  *tfsoff += 1;
2400  }
2401  print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END);
2402  *tfsoff += 1;
2403 }
2404 
2405 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff)
2406 {
2407  unsigned int offset = 0;
2409  var_t *f;
2410 
2412  {
2413  type_t *ft = f->type;
2414  unsigned int size = field_memsize( ft, &offset );
2415  if (type_get_type(ft) == TYPE_UNION && is_attr(f->attrs, ATTR_SWITCHIS))
2416  {
2417  short reloff;
2418  unsigned int absoff = ft->typestring_offset;
2419  if (is_attr(ft->attrs, ATTR_SWITCHTYPE))
2420  absoff += 8; /* we already have a corr descr, skip it */
2421  reloff = absoff - (*tfsoff + 6);
2422  print_file(file, 0, "/* %d */\n", *tfsoff);
2423  print_file(file, 2, "0x%x,\t/* FC_NON_ENCAPSULATED_UNION */\n", FC_NON_ENCAPSULATED_UNION);
2424  print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", FC_LONG);
2426  get_attrp(f->attrs, ATTR_SWITCHIS));
2427  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
2428  (unsigned short)reloff, reloff, absoff);
2429  *tfsoff += 8;
2430  }
2431  offset += size;
2432  }
2433 }
2434 
2436  FILE *file, const attr_list_t *attrs, type_t *type,
2437  unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2438  unsigned int *typestring_offset)
2439 {
2440  int written = 0;
2441 
2444  {
2445  if (offset_in_memory && offset_in_buffer)
2446  {
2447  unsigned int memsize;
2448 
2449  /* pointer instance
2450  *
2451  * note that MSDN states that for pointer layouts in structures,
2452  * this is a negative offset from the end of the structure, but
2453  * this statement is incorrect. all offsets are positive */
2454  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Memory offset = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory);
2455  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Buffer offset = %d */\n", (unsigned short)*offset_in_buffer, *offset_in_buffer);
2456 
2457  memsize = type_memsize(type);
2458  *offset_in_memory += memsize;
2459  /* increment these separately as in the case of conformant (varying)
2460  * structures these start at different values */
2461  *offset_in_buffer += memsize;
2462  }
2463  *typestring_offset += 4;
2464 
2465  if (is_ptr(type))
2466  {
2468 
2469  if (is_string_type(attrs, type))
2470  write_string_tfs(file, attrs, type, TYPE_CONTEXT_CONTAINER, NULL, typestring_offset);
2471  else if (processed(ref))
2473  ref->typestring_offset, typestring_offset);
2474  else if (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM)
2475  *typestring_offset += write_simple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER);
2476  else
2477  error("write_pointer_description_offsets: type format string unknown\n");
2478  }
2479  else
2480  {
2481  unsigned int offset = type->typestring_offset;
2482  /* skip over the pointer that is written for strings, since a
2483  * pointer has to be written in-place here */
2484  if (is_string_type(attrs, type))
2485  offset += 4;
2486  write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER, offset, typestring_offset);
2487  }
2488 
2489  return 1;
2490  }
2491 
2492  if (is_array(type))
2493  {
2495  file, attrs, type_array_get_element(type), offset_in_memory,
2496  offset_in_buffer, typestring_offset);
2497  }
2498  else if (is_non_complex_struct(type))
2499  {
2500  /* otherwise search for interesting fields to parse */
2501  const var_t *v;
2503  {
2504  if (offset_in_memory && offset_in_buffer)
2505  {
2506  unsigned int padding;
2507  unsigned int align = 0;
2509  padding = ROUNDING(*offset_in_memory, align);
2510  *offset_in_memory += padding;
2511  *offset_in_buffer += padding;
2512  }
2514  file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
2515  typestring_offset);
2516  }
2517  }
2518  else
2519  {
2520  if (offset_in_memory && offset_in_buffer)
2521  {
2522  unsigned int memsize = type_memsize(type);
2523  *offset_in_memory += memsize;
2524  /* increment these separately as in the case of conformant (varying)
2525  * structures these start at different values */
2526  *offset_in_buffer += memsize;
2527  }
2528  }
2529 
2530  return written;
2531 }
2532 
2534  FILE *file, const attr_list_t *attrs, type_t *type,
2535  unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2536  unsigned int *typestring_offset)
2537 {
2538  int written = 0;
2539 
2540  if (is_ptr(type) ||
2542  {
2543  print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", FC_NO_REPEAT);
2544  print_file(file, 2, "0x%02x, /* FC_PAD */\n", FC_PAD);
2545  *typestring_offset += 2;
2546 
2548  offset_in_memory, offset_in_buffer, typestring_offset);
2549  }
2550 
2552  {
2553  const var_t *v;
2555  {
2556  if (offset_in_memory && offset_in_buffer)
2557  {
2558  unsigned int padding;
2559  unsigned int align = 0;
2561  padding = ROUNDING(*offset_in_memory, align);
2562  *offset_in_memory += padding;
2563  *offset_in_buffer += padding;
2564  }
2566  file, v->attrs, v->type,
2567  offset_in_memory, offset_in_buffer, typestring_offset);
2568  }
2569  }
2570  else
2571  {
2572  unsigned int memsize = type_memsize(type);
2573  *offset_in_memory += memsize;
2574  /* increment these separately as in the case of conformant (varying)
2575  * structures these start at different values */
2576  *offset_in_buffer += memsize;
2577  }
2578 
2579  return written;
2580 }
2581 
2582 /* Note: if file is NULL return value is number of pointers to write, else
2583  * it is the number of type format characters written */
2585  FILE *file, const attr_list_t *attrs, type_t *type,
2586  unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2587  unsigned int *typestring_offset)
2588 {
2589  int pointer_count = 0;
2590 
2591  if (type_get_type(type) == TYPE_ARRAY &&
2593  {
2594  unsigned int temp = 0;
2595  /* unfortunately, this needs to be done in two passes to avoid
2596  * writing out redundant FC_FIXED_REPEAT descriptions */
2597  pointer_count = write_pointer_description_offsets(
2598  NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
2599  if (pointer_count > 0)
2600  {
2601  unsigned int increment_size;
2602  unsigned int offset_of_array_pointer_mem = 0;
2603  unsigned int offset_of_array_pointer_buf = 0;
2604 
2605  increment_size = type_memsize(type_array_get_element(type));
2606 
2607  print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", FC_FIXED_REPEAT);
2608  print_file(file, 2, "0x%02x, /* FC_PAD */\n", FC_PAD);
2609  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Iterations = %d */\n", (unsigned short)type_array_get_dim(type), type_array_get_dim(type));
2610  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
2611  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory);
2612  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count);
2613  *typestring_offset += 10;
2614 
2615  pointer_count = write_pointer_description_offsets(
2616  file, attrs, type, &offset_of_array_pointer_mem,
2617  &offset_of_array_pointer_buf, typestring_offset);
2618  }
2619  }
2620  else if (type_get_type(type) == TYPE_STRUCT)
2621  {
2622  const var_t *v;
2624  {
2625  if (offset_in_memory && offset_in_buffer)
2626  {
2627  unsigned int padding;
2628  unsigned int align = 0;
2630  padding = ROUNDING(*offset_in_memory, align);
2631  *offset_in_memory += padding;
2632  *offset_in_buffer += padding;
2633  }
2634  pointer_count += write_fixed_array_pointer_descriptions(
2635  file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
2636  typestring_offset);
2637  }
2638  }
2639  else
2640  {
2641  if (offset_in_memory && offset_in_buffer)
2642  {
2643  unsigned int memsize;
2644  memsize = type_memsize(type);
2645  *offset_in_memory += memsize;
2646  /* increment these separately as in the case of conformant (varying)
2647  * structures these start at different values */
2648  *offset_in_buffer += memsize;
2649  }
2650  }
2651 
2652  return pointer_count;
2653 }
2654 
2655 /* Note: if file is NULL return value is number of pointers to write, else
2656  * it is the number of type format characters written */
2658  FILE *file, const attr_list_t *attrs, type_t *type,
2659  unsigned int offset_in_memory, unsigned int *typestring_offset)
2660 {
2661  int pointer_count = 0;
2662 
2664  {
2665  unsigned int temp = 0;
2666  /* unfortunately, this needs to be done in two passes to avoid
2667  * writing out redundant FC_VARIABLE_REPEAT descriptions */
2668  pointer_count = write_pointer_description_offsets(
2669  NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
2670  if (pointer_count > 0)
2671  {
2672  unsigned int increment_size;
2673  unsigned int offset_of_array_pointer_mem = offset_in_memory;
2674  unsigned int offset_of_array_pointer_buf = offset_in_memory;
2675 
2676  increment_size = type_memsize(type_array_get_element(type));
2677 
2678  if (increment_size > USHRT_MAX)
2679  error("array size of %u bytes is too large\n", increment_size);
2680 
2681  print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", FC_VARIABLE_REPEAT);
2682  print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", FC_FIXED_OFFSET);
2683  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
2684  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)offset_in_memory, offset_in_memory);
2685  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count);
2686  *typestring_offset += 8;
2687 
2688  pointer_count = write_pointer_description_offsets(
2689  file, attrs, type_array_get_element(type),
2690  &offset_of_array_pointer_mem, &offset_of_array_pointer_buf,
2691  typestring_offset);
2692  }
2693  }
2694 
2695  return pointer_count;
2696 }
2697 
2698 /* Note: if file is NULL return value is number of pointers to write, else
2699  * it is the number of type format characters written */
2701  FILE *file, const attr_list_t *attrs, type_t *type,
2702  unsigned int *offset_in_memory, unsigned int *offset_in_buffer,
2703  unsigned int *typestring_offset)
2704 {
2705  int pointer_count = 0;
2706 
2708  {
2709  unsigned int temp = 0;
2710  /* unfortunately, this needs to be done in two passes to avoid
2711  * writing out redundant FC_VARIABLE_REPEAT descriptions */
2712  pointer_count = write_pointer_description_offsets(
2713  NULL, attrs, type_array_get_element(type), NULL, NULL, &temp);
2714  if (pointer_count > 0)
2715  {
2716  unsigned int increment_size;
2717 
2718  increment_size = type_memsize(type_array_get_element(type));
2719 
2720  if (increment_size > USHRT_MAX)
2721  error("array size of %u bytes is too large\n", increment_size);
2722 
2723  print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", FC_VARIABLE_REPEAT);
2724  print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", FC_VARIABLE_OFFSET);
2725  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size);
2726  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory);
2727  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count);
2728  *typestring_offset += 8;
2729 
2730  pointer_count = write_pointer_description_offsets(
2731  file, attrs, type_array_get_element(type), offset_in_memory,
2732  offset_in_buffer, typestring_offset);
2733  }
2734  }
2735  else if (type_get_type(type) == TYPE_STRUCT)
2736  {
2737  const var_t *v;
2739  {
2740  if (offset_in_memory && offset_in_buffer)
2741  {
2742  unsigned int align = 0, padding;
2743 
2744  if (is_array(v->type) && type_array_has_variance(v->type))
2745  {
2746  *offset_in_buffer = ROUND_SIZE(*offset_in_buffer, 4);
2747  /* skip over variance and offset in buffer */
2748  *offset_in_buffer += 8;
2749  }
2750 
2752  padding = ROUNDING(*offset_in_memory, align);
2753  *offset_in_memory += padding;
2754  *offset_in_buffer += padding;
2755  }
2757  file, v->attrs, v->type, offset_in_memory, offset_in_buffer,
2758  typestring_offset);
2759  }
2760  }
2761  else
2762  {
2763  if (offset_in_memory && offset_in_buffer)
2764  {
2765  unsigned int memsize = type_memsize(type);
2766  *offset_in_memory += memsize;
2767  /* increment these separately as in the case of conformant (varying)
2768  * structures these start at different values */
2769  *offset_in_buffer += memsize;
2770  }
2771  }
2772 
2773  return pointer_count;
2774 }
2775 
2777  unsigned int *typestring_offset)
2778 {
2779  unsigned int offset_in_buffer;
2780  unsigned int offset_in_memory;
2781 
2782  /* pass 1: search for single instance of a pointer (i.e. don't descend
2783  * into arrays) */
2784  if (!is_array(type))
2785  {
2786  offset_in_memory = 0;
2787  offset_in_buffer = 0;
2789  file, NULL, type,
2790  &offset_in_memory, &offset_in_buffer, typestring_offset);
2791  }
2792 
2793  /* pass 2: search for pointers in fixed arrays */
2794  offset_in_memory = 0;
2795  offset_in_buffer = 0;
2797  file, NULL, type,
2798  &offset_in_memory, &offset_in_buffer, typestring_offset);
2799 
2800  /* pass 3: search for pointers in conformant only arrays (but don't descend
2801  * into conformant varying or varying arrays) */
2802  if (is_conformant_array(type) &&
2805  file, attrs, type, 0, typestring_offset);
2806  else if (type_get_type(type) == TYPE_STRUCT &&
2808  {
2811  type_memsize(type), typestring_offset);
2812  }
2813 
2814  /* pass 4: search for pointers in varying arrays */
2815  offset_in_memory = 0;
2816  offset_in_buffer = 0;
2818  file, NULL, type,
2819  &offset_in_memory, &offset_in_buffer, typestring_offset);
2820 }
2821 
2822 static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs,
2824  const char *name, unsigned int *typestring_offset)
2825 {
2826  unsigned int start_offset;
2827  unsigned char rtype;
2828  type_t *elem_type;
2829  int is_processed = processed(type);
2830 
2831  start_offset = *typestring_offset;
2832 
2833  if (is_declptr(type))
2834  {
2835  unsigned char flag = is_conformant_array(type) ? 0 : FC_SIMPLE_POINTER;
2836  int pointer_type = get_pointer_fc_context(type, attrs, context);
2837  if (!pointer_type)
2838  pointer_type = FC_RP;
2839  print_start_tfs_comment(file, type, *typestring_offset);
2840  print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n",
2841  pointer_type, flag, string_of_type(pointer_type),
2842  flag ? " [simple_pointer]" : "");
2843  *typestring_offset += 2;
2844  if (!flag)
2845  {
2846  print_file(file, 2, "NdrFcShort(0x2),\n");
2847  *typestring_offset += 2;
2848  }
2849  is_processed = FALSE;
2850  }
2851 
2852  if (is_array(type))
2853  elem_type = type_array_get_element(type);
2854  else
2855  elem_type = type_pointer_get_ref(type);
2856 
2857  if (type_get_type(elem_type) == TYPE_POINTER && is_array(type))
2858  return write_array_tfs(file, attrs, type, name, typestring_offset);
2859 
2860  if (type_get_type(elem_type) != TYPE_BASIC)
2861  {
2862  error("write_string_tfs: Unimplemented for non-basic type %s\n", name);
2863  return start_offset;
2864  }
2865 
2866  rtype = get_basic_fc(elem_type);
2867  if ((rtype != FC_BYTE) && (rtype != FC_CHAR) && (rtype != FC_WCHAR))
2868  {
2869  error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name);
2870  return start_offset;
2871  }
2872 
2874  {
2875  unsigned int dim = type_array_get_dim(type);
2876 
2877  if (is_processed) return start_offset;
2878 
2879  /* FIXME: multi-dimensional array */
2880  if (0xffffu < dim)
2881  error("array size for parameter %s exceeds %u bytes by %u bytes\n",
2882  name, 0xffffu, dim - 0xffffu);
2883 
2884  if (rtype == FC_WCHAR)
2885  WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset);
2886  else
2887  WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset);
2888  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
2889  *typestring_offset += 2;
2890 
2891  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)dim, dim);
2892  *typestring_offset += 2;
2893 
2894  update_tfsoff(type, start_offset, file);
2895  return start_offset;
2896  }
2897  else if (is_conformant_array(type))
2898  {
2899  if (rtype == FC_WCHAR)
2900  WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
2901  else
2902  WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
2903  print_file(file, 2, "0x%x,\t/* FC_STRING_SIZED */\n", FC_STRING_SIZED);
2904  *typestring_offset += 2;
2905 
2906  *typestring_offset += write_conf_or_var_desc(
2910  : 0),
2912 
2913  update_tfsoff(type, start_offset, file);
2914  return start_offset;
2915  }
2916  else
2917  {
2918  if (is_processed) return start_offset;
2919 
2920  if (rtype == FC_WCHAR)
2921  WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset);
2922  else
2923  WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset);
2924  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
2925  *typestring_offset += 2;
2926 
2927  update_tfsoff(type, start_offset, file);
2928  return start_offset;
2929  }
2930 }
2931 
2932 static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
2933  const char *name, unsigned int *typestring_offset)
2934 {
2935  const expr_t *length_is = type_array_get_variance(type);
2936  const expr_t *size_is = type_array_get_conformance(type);
2937  unsigned int align;
2938  unsigned int size;
2939  unsigned int start_offset;
2940  unsigned char fc;
2941  int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE);
2942  unsigned int baseoff
2945  : 0;
2946 
2947  if (!pointer_type)
2948  pointer_type = FC_RP;
2949 
2951  write_embedded_types(file, attrs, type_array_get_element(type), name, FALSE, typestring_offset);
2952 
2955  fc = get_array_fc(type);
2956 
2957  start_offset = *typestring_offset;
2958  update_tfsoff(type, start_offset, file);
2959  print_start_tfs_comment(file, type, start_offset);
2960  print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc));
2961  print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
2962  *typestring_offset += 2;
2963 
2964  align = 0;
2965  if (fc != FC_BOGUS_ARRAY)
2966  {
2967  if (fc == FC_LGFARRAY || fc == FC_LGVARRAY)
2968  {
2969  print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", size, size);
2970  *typestring_offset += 4;
2971  }
2972  else
2973  {
2974  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)size, size);
2975  *typestring_offset += 2;
2976  }
2977 
2979  *typestring_offset
2981  type, size_is);
2982 
2983  if (fc == FC_SMVARRAY || fc == FC_LGVARRAY)
2984  {
2985  unsigned int elsize = type_memsize(type_array_get_element(type));
2986  unsigned int dim = type_array_get_dim(type);
2987 
2988  if (fc == FC_LGVARRAY)
2989  {
2990  print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", dim, dim);
2991  *typestring_offset += 4;
2992  }
2993  else
2994  {
2995  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)dim, dim);
2996  *typestring_offset += 2;
2997  }
2998 
2999  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)elsize, elsize);
3000  *typestring_offset += 2;
3001  }
3002 
3003  if (length_is)
3004  *typestring_offset
3006  type, length_is);
3007 
3010  {
3011  print_file(file, 2, "0x%x,\t/* FC_PP */\n", FC_PP);
3012  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
3013  *typestring_offset += 2;
3014  write_pointer_description(file, is_string_type(attrs, type) ? attrs : NULL, type, typestring_offset);
3015  print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END);
3016  *typestring_offset += 1;
3017  }
3018 
3019  write_array_element_type(file, is_string_type(attrs, type) ? attrs : NULL, type, FALSE, typestring_offset);
3020  write_end(file, typestring_offset);
3021  }
3022  else
3023  {
3024  unsigned int dim = size_is ? 0 : type_array_get_dim(type);
3025  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)dim, dim);
3026  *typestring_offset += 2;
3027  *typestring_offset
3029  type, size_is);
3030  *typestring_offset
3032  type, length_is);
3033 
3034  write_array_element_type(file, is_string_type(attrs, type) ? attrs : NULL, type, TRUE, typestring_offset);
3035  write_end(file, typestring_offset);
3036  }
3037 
3038  return start_offset;
3039 }
3040 
3042 {
3043  const var_list_t *fields = type_struct_get_fields(type);
3044  const var_t *last_field;
3045  const type_t *ft;
3046 
3047  if (!fields || list_empty(fields))
3048  return NULL;
3049 
3050  last_field = LIST_ENTRY( list_tail(fields), const var_t, entry );
3051  ft = last_field->type;
3052 
3054  return last_field;
3055 
3056  if (type_get_type(ft) == TYPE_STRUCT)
3057  return find_array_or_string_in_struct(ft);
3058  else
3059  return NULL;
3060 }
3061 
3063  int is_complex, unsigned int *corroff,
3064  unsigned int *typestring_offset)
3065 {
3066  const var_t *field;
3067  unsigned short offset = 0;
3068  unsigned int salign = 1;
3069  int padding;
3071 
3072  if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry )
3073  {
3074  type_t *ft = field->type;
3075  unsigned int align = 0;
3076  unsigned int size = type_memsize_and_alignment(ft, &align);
3077  align = clamp_align(align);
3078  if (salign < align) salign = align;
3079 
3081  {
3082  if ((align - 1) & offset)
3083  {
3084  unsigned char fc = 0;
3085  switch (align)
3086  {
3087  case 2:
3088  fc = FC_ALIGNM2;
3089  break;
3090  case 4:
3091  fc = FC_ALIGNM4;
3092  break;
3093  case 8:
3094  fc = FC_ALIGNM8;
3095  break;
3096  default:
3097  error("write_struct_members: cannot align type %d\n", type_get_type(ft));
3098  }
3099  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
3101  *typestring_offset += 1;
3102  }
3103  write_member_type(file, type, is_complex, field->attrs, field->type, corroff,
3104  typestring_offset);
3105  offset += size;
3106  }
3107  }
3108 
3109  padding = ROUNDING(offset, salign);
3110  if (padding)
3111  {
3112  print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n",
3113  FC_STRUCTPAD1 + padding - 1,
3114  padding);
3115  *typestring_offset += 1;
3116  }
3117 
3118  write_end(file, typestring_offset);
3119 }
3120 
3121 static unsigned int write_struct_tfs(FILE *file, type_t *type,
3122  const char *name, unsigned int *tfsoff)
3123 {
3124  const type_t *save_current_structure = current_structure;
3125  unsigned int total_size;
3126  const var_t *array;
3127  unsigned int start_offset;
3128  unsigned int align;
3129  unsigned int corroff;
3130  var_t *f;
3131  unsigned char fc = get_struct_fc(type);
3133 
3134  if (processed(type)) return type->typestring_offset;
3135 
3136  guard_rec(type);
3138 
3139  total_size = type_memsize(type);
3141  if (total_size > USHRT_MAX)
3142  error("structure size for %s exceeds %d bytes by %d bytes\n",
3143  name, USHRT_MAX, total_size - USHRT_MAX);
3144 
3145  if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
3146  write_embedded_types(file, f->attrs, f->type, f->name, FALSE, tfsoff);
3147 
3149  if (array && !processed(array->type))
3150  {
3151  if(is_string_type(array->attrs, array->type))
3152  write_string_tfs(file, array->attrs, array->type, TYPE_CONTEXT_CONTAINER, array->name, tfsoff);
3153  else
3154  write_array_tfs(file, array->attrs, array->type, array->name, tfsoff);
3155  }
3156 
3157  corroff = *tfsoff;
3158  write_descriptors(file, type, tfsoff);
3159 
3160  start_offset = *tfsoff;
3161  update_tfsoff(type, start_offset, file);
3162  print_start_tfs_comment(file, type, start_offset);
3163  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
3164  print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1);
3165  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)total_size, total_size);
3166  *tfsoff += 4;
3167 
3168  if (array)
3169  {
3170  unsigned int absoff = array->type->typestring_offset;
3171  short reloff = absoff - *tfsoff;
3172  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
3173  reloff, reloff, absoff);
3174  *tfsoff += 2;
3175  }
3176  else if (fc == FC_BOGUS_STRUCT)
3177  {
3178  print_file(file, 2, "NdrFcShort(0x0),\n");
3179  *tfsoff += 2;
3180  }
3181 
3182  if (fc == FC_BOGUS_STRUCT)
3183  {
3184  /* On the sizing pass, type->ptrdesc may be zero, but it's ok as
3185  nothing is written to file yet. On the actual writing pass,
3186  this will have been updated. */
3187  unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff;
3188  int reloff = absoff - *tfsoff;
3189  assert( reloff >= 0 );
3190  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %d (%u) */\n",
3191  (unsigned short)reloff, reloff, absoff);
3192  *tfsoff += 2;
3193  }
3194  else if ((fc == FC_PSTRUCT) ||
3195  (fc == FC_CPSTRUCT) ||
3197  {
3198  print_file(file, 2, "0x%x,\t/* FC_PP */\n", FC_PP);
3199  print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD);
3200  *tfsoff += 2;
3202  print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END);
3203  *tfsoff += 1;
3204  }
3205 
3207  tfsoff);
3208 
3209  if (fc == FC_BOGUS_STRUCT)
3210  {
3211  const var_t *f;
3212 
3213  type->ptrdesc = *tfsoff;
3214  if (fields) LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry)
3215  {
3216  type_t *ft = f->type;
3218  {
3219  case TGT_POINTER:
3220  if (is_string_type(f->attrs, ft))
3221  write_string_tfs(file, f->attrs, ft, TYPE_CONTEXT_CONTAINER, f->name, tfsoff);
3222  else
3223  write_pointer_tfs(file, f->attrs, ft,
3224  type_pointer_get_ref(ft)->typestring_offset,
3225  TYPE_CONTEXT_CONTAINER, tfsoff);
3226  break;
3227  case TGT_ARRAY:
3228  if (type_array_is_decl_as_ptr(ft))
3229  {
3230  unsigned int offset;
3231 
3232  print_file(file, 0, "/* %d */\n", *tfsoff);
3233 
3234  offset = ft->typestring_offset;
3235  /* skip over the pointer that is written for strings, since a
3236  * pointer has to be written in-place here */
3237  if (is_string_type(f->attrs, ft))
3238  offset += 4;
3240  }
3241  break;
3242  default:
3243  break;
3244  }
3245  }
3246  if (type->ptrdesc == *tfsoff)
3247  type->ptrdesc = 0;
3248  }
3249 
3250  current_structure = save_current_structure;
3251  return start_offset;
3252 }
3253 
3254 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff)
3255 {
3256  if (t == NULL)
3257  {
3258  print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n");
3259  }
3260  else
3261  {
3263  {
3264  unsigned char fc;
3265  if (type_get_type(t) == TYPE_BASIC)
3266  fc = get_basic_fc(t);
3267  else
3268  fc = get_enum_fc(t);
3269  print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n",
3270  fc, string_of_type(fc));
3271  }
3272  else if (t->typestring_offset)
3273  {
3274  short reloff = t->typestring_offset - *tfsoff;
3275  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %d (%d) */\n",
3276  reloff, reloff, t->typestring_offset);
3277  }
3278  else
3279  error("write_branch_type: type unimplemented %d\n", type_get_type(t));
3280  }
3281 
3282  *tfsoff += 2;
3283 }
3284 
3285 static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs,
3286  type_t *type, unsigned int *tfsoff)
3287 {
3288  unsigned int start_offset;
3289  unsigned int size;
3290  var_list_t *fields;
3291  unsigned int nbranch = 0;
3292  type_t *deftype = NULL;
3293  short nodeftype = 0xffff;
3294  unsigned int dummy;
3295  var_t *f;
3296 
3297  if (processed(type) &&
3299  return type->typestring_offset;
3300 
3301  guard_rec(type);
3302 
3303  fields = type_union_get_cases(type);
3304 
3305  size = union_memsize(fields, &dummy);
3306 
3307  if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
3308  {
3309  expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
3310  if (cases)
3311  nbranch += list_count(cases);
3312  if (f->type)
3313  write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff);
3314  }
3315 
3316  start_offset = *tfsoff;
3317  update_tfsoff(type, start_offset, file);
3318  print_start_tfs_comment(file, type, start_offset);
3320  {
3321  const var_t *sv = type_union_get_switch_value(type);
3322  const type_t *st = sv->type;
3323  unsigned int align = 0;
3324  unsigned char fc;
3325 
3326  if (type_get_type(st) == TYPE_BASIC)
3327  {
3328  fc = get_basic_fc(st);
3329  switch (fc)
3330  {
3331  case FC_CHAR:
3332  case FC_SMALL:
3333  case FC_BYTE:
3334  case FC_USMALL:
3335  case FC_WCHAR:
3336  case FC_SHORT:
3337  case FC_USHORT:
3338  case FC_LONG:
3339  case FC_ULONG:
3340  break;
3341  default:
3342  fc = 0;
3343  error("union switch type must be an integer, char, or enum\n");
3344  }
3345  }
3346  else if (type_get_type(st) == TYPE_ENUM)
3347  fc = get_enum_fc(st);
3348  else
3349  error("union switch type must be an integer, char, or enum\n");
3350 
3352  if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
3353  {
3354  if (f->type)
3356  }
3357 
3358  print_file(file, 2, "0x%x,\t/* FC_ENCAPSULATED_UNION */\n", FC_ENCAPSULATED_UNION);
3359  print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
3360  (align << 4) | fc, string_of_type(fc));
3361  *tfsoff += 2;
3362  }
3363  else if (is_attr(type->attrs, ATTR_SWITCHTYPE))
3364  {
3365  const expr_t *switch_is = get_attrp(attrs, ATTR_SWITCHIS);
3366  const type_t *st = get_attrp(type->attrs, ATTR_SWITCHTYPE);
3367  unsigned char fc;
3368 
3369  if (type_get_type(st) == TYPE_BASIC)
3370  {
3371  fc = get_basic_fc(st);
3372  switch (fc)
3373  {
3374  case FC_CHAR:
3375  case FC_SMALL:
3376  case FC_USMALL:
3377  case FC_SHORT:
3378  case FC_USHORT:
3379  case FC_LONG:
3380  case FC_ULONG:
3381  case FC_ENUM16:
3382  case FC_ENUM32:
3383  break;
3384  default:
3385  fc = 0;
3386  error("union switch type must be an integer, char, or enum\n");
3387  }
3388  }
3389  else if (type_get_type(st) == TYPE_ENUM)
3390  fc = get_enum_fc(st);
3391  else
3392  error("union switch type must be an integer, char, or enum\n");
3393 
3394  print_file(file, 2, "0x%x,\t/* FC_NON_ENCAPSULATED_UNION */\n", FC_NON_ENCAPSULATED_UNION);
3395  print_file(file, 2, "0x%x,\t/* Switch type= %s */\n",
3396  fc, string_of_type(fc));
3397  *tfsoff += 2;
3398  *tfsoff += write_conf_or_var_desc(file, current_structure, 0, st, switch_is );
3399  print_file(file, 2, "NdrFcShort(0x2),\t/* Offset= 2 (%u) */\n", *tfsoff + 2);
3400  *tfsoff += 2;
3401  print_file(file, 0, "/* %u */\n", *tfsoff);
3402  }
3403 
3404  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)size, size);
3405  print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)nbranch, nbranch);
3406  *tfsoff += 4;
3407 
3408  if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry)
3409  {
3410  type_t *ft = f->type;
3411  expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE);
3412  int deflt = is_attr(f->attrs, ATTR_DEFAULT);
3413  expr_t *c;
3414 
3415  if (cases == NULL && !deflt)
3416  error("union field %s with neither case nor default attribute\n", f->name);
3417 
3418  if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry)
3419  {
3420  /* MIDL doesn't check for duplicate cases, even though that seems
3421  like a reasonable thing to do, it just dumps them to the TFS
3422  like we're going to do here. */
3423  print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval);
3424  *tfsoff += 4;
3425  write_branch_type(file, ft, tfsoff);
3426  }
3427 
3428  /* MIDL allows multiple default branches, even though that seems
3429  illogical, it just chooses the last one, which is what we will
3430  do. */
3431  if (deflt)
3432  {
3433  deftype = ft;
3434  nodeftype = 0;
3435  }
3436  }
3437 
3438  if (deftype)
3439  {
3440  write_branch_type(file, deftype, tfsoff);
3441  }
3442  else
3443  {
3444  print_file(file, 2, "NdrFcShort(0x%hx),\n", nodeftype);
3445  *tfsoff += 2;
3446  }
3447 
3448  return start_offset;
3449 }
3450 
3451 static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type,
3452  unsigned int *typeformat_offset)
3453 {
3454  unsigned int i;
3455  unsigned int start_offset = *typeformat_offset;
3456  expr_t *iid = get_attrp(attrs, ATTR_IIDIS);
3457 
3458  if (!iid && processed(type)) return type->typestring_offset;
3459 
3460  print_start_tfs_comment(file, type, start_offset);
3461  update_tfsoff(type, start_offset, file);
3462 
3463  if (iid)
3464  {
3465  print_file(file, 2, "0x2f, /* FC_IP */\n");
3466  print_file(file, 2, "0x5c, /* FC_PAD */\n");
3467  *typeformat_offset
3469  }
3470  else
3471  {
3473  const UUID *uuid = get_attrp(base->attrs, ATTR_UUID);
3474 
3475  if (! uuid)
3476  error("%s: interface %s missing UUID\n", __FUNCTION__, base->name);
3477 
3478  print_file(file, 2, "0x2f,\t/* FC_IP */\n");
3479  print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n");
3480  print_file(file, 2, "NdrFcLong(0x%08x),\n", uuid->Data1);
3481  print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2);
3482  print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3);
3483  for (i = 0; i < 8; ++i)
3484  print_file(file, 2, "0x%02x,\n", uuid->Data4[i]);
3485 
3486  if (file)
3487  fprintf(file, "\n");
3488 
3489  *typeformat_offset += 18;
3490  }
3491  return start_offset;
3492 }
3493 
3494 static unsigned int write_contexthandle_tfs(FILE *file,
3495  const attr_list_t *attrs,
3496  type_t *type,
3497  int toplevel_param,
3498  unsigned int *typeformat_offset)
3499 {
3500  unsigned int start_offset = *typeformat_offset;
3501  unsigned char flags = get_contexthandle_flags( current_iface, attrs, type );
3502 
3503  print_start_tfs_comment(file, type, start_offset);
3504 
3505  if (flags & 0x80) /* via ptr */
3506  {
3507  int pointer_type = get_pointer_fc( type, attrs, toplevel_param );
3508  if (!pointer_type) pointer_type = FC_RP;
3509  *typeformat_offset += 4;
3510  print_file(file, 2,"0x%x, 0x0,\t/* %s */\n", pointer_type, string_of_type(pointer_type) );
3511  print_file(file, 2, "NdrFcShort(0x2),\t /* Offset= 2 (%u) */\n", *typeformat_offset);
3512  print_file(file, 0, "/* %2u */\n", *typeformat_offset);
3513  }
3514 
3515  print_file(file, 2, "0x%02x,\t/* FC_BIND_CONTEXT */\n", FC_BIND_CONTEXT);
3516  print_file(file, 2, "0x%x,\t/* Context flags: ", flags);
3517  /* return and can't be null values overlap */
3518  if (((flags & 0x21) != 0x21) && (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL))
3519  print_file(file, 0, "can't be null, ");
3521  print_file(file, 0, "serialize, ");
3523  print_file(file, 0, "no serialize, ");
3525  print_file(file, 0, "strict, ");
3526  if ((flags & 0x21) == 0x20)
3527  print_file(file, 0, "out, ");
3528  if ((flags & 0x21) == 0x21)
3529  print_file(file, 0, "return, ");
3530  if (flags & 0x40)
3531  print_file(file, 0, "in, ");
3532  if (flags & 0x80)
3533  print_file(file, 0, "via ptr, ");
3534  print_file(file, 0, "*/\n");
3535  print_file(file, 2, "0x%x,\t/* rundown routine */\n", get_context_handle_offset( type ));
3536  print_file(file, 2, "0, /* FIXME: param num */\n");
3537  *typeformat_offset += 4;
3538 
3539  update_tfsoff( type, start_offset, file );
3540  return start_offset;
3541 }
3542 
3543 static unsigned int write_range_tfs(FILE *file, const attr_list_t *attrs,
3544  type_t *type, expr_list_t *range_list,
3545  unsigned int *typeformat_offset)
3546 {
3547  unsigned char fc;
3548  unsigned int start_offset = *typeformat_offset;
3549  const expr_t *range_min = LIST_ENTRY(list_head(range_list), const expr_t, entry);
3550  const expr_t *range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry);
3551 
3552  if (type_get_type(type) == TYPE_BASIC)
3553  fc = get_basic_fc(type);
3554  else
3555  fc = get_enum_fc(type);
3556 
3557  /* fc must fit in lower 4-bits of 8-bit field below */
3558  assert(fc <= 0xf);
3559 
3560  print_file(file, 0, "/* %u */\n", *typeformat_offset);
3561  print_file(file, 2, "0x%x,\t/* FC_RANGE */\n", FC_RANGE);
3562  print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
3563  print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_min->cval, range_min->cval);
3564  print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_max->cval, range_max->cval);
3565  update_tfsoff( type, start_offset, file );
3566  *typeformat_offset += 10;
3567 
3568  return start_offset;
3569 }
3570 
3571 static unsigned int write_type_tfs(FILE *file, int indent,
3572  const attr_list_t *attrs, type_t *type,
3573  const char *name,
3574  enum type_context context,
3575  unsigned int *typeformat_offset)
3576 {
3577  unsigned int offset;
3578 
3579  switch (typegen_detect_type(type, attrs, TDT_ALL_TYPES))
3580  {
3581  case TGT_CTXT_HANDLE:
3583  return write_contexthandle_tfs(file, attrs, type,
3584  context == TYPE_CONTEXT_TOPLEVELPARAM, typeformat_offset);
3585  case TGT_USER_TYPE:
3586  return write_user_tfs(file, type, typeformat_offset);
3587  case TGT_STRING:
3588  return write_string_tfs(file, attrs, type, context, name, typeformat_offset);
3589  case TGT_ARRAY:
3590  {
3591  unsigned int off;
3592  /* conformant and pointer arrays are handled specially */
3593  if ((context != TYPE_CONTEXT_CONTAINER &&
3596  off = write_array_tfs(file, attrs, type, name, typeformat_offset);
3597  else
3598  off = 0;
3601  {
3602  int ptr_type;
3603  ptr_type = get_pointer_fc(type, attrs,
3605  if (ptr_type != FC_RP || type_array_is_decl_as_ptr(type))
3606  {
3607  unsigned int absoff = type->typestring_offset;
3608  short reloff = absoff - (*typeformat_offset + 2);
3609  off = *typeformat_offset;
3610  print_file(file, 0, "/* %d */\n", off);
3611  print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type,
3612  string_of_type(ptr_type));
3613  print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n",
3614  reloff, reloff, absoff);
3615  if (ptr_type != FC_RP) update_tfsoff( type, off, file );
3616  *typeformat_offset += 4;
3617  }
3618  type->details.array.ptr_tfsoff = off;
3619  }
3620  return off;
3621  }
3622  case TGT_STRUCT:
3623  return write_struct_tfs(file, type, name, typeformat_offset);
3624  case TGT_UNION:
3625  return write_union_tfs(file, attrs, type, typeformat_offset);
3626  case TGT_ENUM:
3627  case TGT_BASIC:
3628  /* nothing to do */
3629  return 0;
3630  case TGT_RANGE:
3631  {
3632  expr_list_t *range_list = get_attrp(attrs, ATTR_RANGE);
3633  if (!range_list)
3634  range_list = get_aliaschain_attrp(type, ATTR_RANGE);
3635  return write_range_tfs(file, attrs, type, range_list, typeformat_offset);
3636  }
3637  case TGT_IFACE_POINTER:
3638  return write_ip_tfs(file, attrs, type, typeformat_offset);
3639  case TGT_POINTER:
3640  {
3641  enum type_context ref_context;
3643 
3645  ref_context = TYPE_CONTEXT_PARAM;
3647  ref_context = TYPE_CONTEXT_CONTAINER;
3648  else
3649  ref_context = context;
3650 
3651  if (is_string_type(attrs, ref))
3652  {
3654  write_pointer_tfs(file, attrs, type, *typeformat_offset + 4, context, typeformat_offset);
3655 
3656  offset = write_type_tfs(file, indent, attrs, ref, name, ref_context, typeformat_offset);
3658  return 0;
3659  return offset;
3660  }
3661 
3663  ref_context, typeformat_offset);
3665  return 0;
3666  return write_pointer_tfs(file, attrs, type, offset, context, typeformat_offset);
3667  }
3668  case TGT_INVALID:
3669  break;
3670  }
3671  error("invalid type %s for var %s\n", type->name, name);
3672  return 0;
3673 }
3674 
3675 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type,
3676  const char *name, int write_ptr, unsigned int *tfsoff)
3677 {
3678  return write_type_tfs(file, 2, attrs, type, name, write_ptr ? TYPE_CONTEXT_CONTAINER : TYPE_CONTEXT_CONTAINER_NO_POINTERS, tfsoff);
3679 }
3680 
3681 static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned int *offset)
3682 {
3684  const statement_t *stmt;
3685  var_t *var;
3686 
3687  current_iface = iface;
3688  if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry )
3689  {
3690  switch(stmt->type)
3691  {
3692  case STMT_DECLARATION:
3693  {
3694  const var_t *func = stmt->u.var;
3695 
3696  if(stmt->u.var->stgclass != STG_NONE
3698  continue;
3699 
3700  current_func = func;
3701  if (is_local(func->attrs)) continue;
3702 
3703  var = type_function_get_retval(func->type);
3704  if (!is_void(var->type))
3705  var->typestring_offset = write_type_tfs( file, 2, func->attrs, var->type, func->name,
3707 
3708  if (type_get_function_args(func->type))
3710  var->typestring_offset = write_type_tfs( file, 2, var->attrs, var->type, var->name,
3712  break;
3713 
3714  }
3715  case STMT_TYPEDEF:
3716  {
3717  const type_list_t *type_entry;
3718  for (type_entry = stmt->u.type_list; type_entry; type_entry = type_entry->next)
3719  {
3720  if (is_attr(type_entry->type->attrs, ATTR_ENCODE)
3721  || is_attr(type_entry->type->attrs, ATTR_DECODE))
3722  type_entry->type->typestring_offset = write_type_tfs( file, 2,
3723  type_entry->type->attrs, type_entry->type, type_entry->type->name,
3725  }
3726  break;
3727  }
3728  default:
3729  break;
3730  }
3731  }
3732 }
3733 
3734 static unsigned int process_tfs(FILE *file, const statement_list_t *stmts, type_pred_t pred)
3735 {
3736  unsigned int typeformat_offset = 2;
3737  for_each_iface(stmts, process_tfs_iface, pred, file, 0, &typeformat_offset);
3738  return typeformat_offset + 1;
3739 }
3740 
3741 
3743 {
3744  int indent = 0;
3745 
3746  print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
3747  print_file(file, indent, "{\n");
3748  indent++;
3749  print_file(file, indent, "0,\n");
3750  print_file(file, indent, "{\n");
3751  indent++;
3752  print_file(file, indent, "NdrFcShort(0x0),\n");
3753 
3755  process_tfs(file, stmts, pred);
3756 
3757  print_file(file, indent, "0x0\n");
3758  indent--;
3759  print_file(file, indent, "}\n");
3760  indent--;
3761  print_file(file, indent, "};\n");
3762  print_file(file, indent, "\n");
3763 }
3764 
3765 static unsigned int get_required_buffer_size_type(
3766  const type_t *type, const char *name, const attr_list_t *attrs, int toplevel_param, unsigned int *alignment)
3767 {
3768  *alignment = 0;
3770  {
3771  case TGT_USER_TYPE:
3772  {
3773  const char *uname = NULL;
3774  const type_t *utype = get_user_type(type, &uname);
3775  return get_required_buffer_size_type(utype, uname, NULL, FALSE, alignment);
3776  }
3777  case TGT_BASIC:
3778  switch (get_basic_fc(type))
3779  {
3780  case FC_BYTE:
3781  case FC_CHAR:
3782  case FC_USMALL:
3783  case FC_SMALL:
3784  *alignment = 4;
3785  return 1;
3786 
3787  case FC_WCHAR:
3788  case FC_USHORT:
3789  case FC_SHORT:
3790  *alignment = 4;
3791  return 2;
3792 
3793  case FC_ULONG:
3794  case FC_LONG:
3795  case FC_FLOAT:
3796  case FC_ERROR_STATUS_T:
3797  *alignment = 4;
3798  return 4;
3799 
3800  case FC_HYPER:
3801  case FC_DOUBLE:
3802  *alignment = 8;
3803  return 8;
3804 
3805  case FC_INT3264:
3806  case FC_UINT3264:
3807  assert( pointer_size );
3808  *alignment = pointer_size;
3809  return pointer_size;
3810 
3811  case FC_IGNORE:
3812  case FC_BIND_PRIMITIVE:
3813  return 0;
3814 
3815  default:
3816  error("get_required_buffer_size: unknown basic type 0x%02x\n",
3817  get_basic_fc(type));
3818  return 0;
3819  }
3820  break;
3821 
3822  case TGT_ENUM:
3823  switch (get_enum_fc(type))
3824  {
3825  case FC_ENUM32:
3826  *alignment = 4;
3827  return 4;
3828  case FC_ENUM16:
3829  *alignment = 4;
3830  return 2;
3831  }
3832  break;
3833 
3834  case TGT_STRUCT:
3835  if (get_struct_fc(type) == FC_STRUCT)
3836  {
3837  if (!type_struct_get_fields(type)) return 0;
3838  return fields_memsize(type_struct_get_fields(type), alignment);
3839  }
3840  break;
3841 
3842  case TGT_POINTER:
3843  {
3844  unsigned int size, align;
3845  const type_t *ref = type_pointer_get_ref(type);
3846  if (is_string_type( attrs, ref )) break;
3847  if (!(size = get_required_buffer_size_type( ref, name, NULL, FALSE, &align ))) break;
3848  if (get_pointer_fc(type, attrs, toplevel_param) != FC_RP)
3849  {
3850  size += 4 + align;
3851  align = 4;
3852  }
3853  *alignment = align;
3854  return size;
3855  }
3856 
3857  case TGT_ARRAY:
3858  if (get_pointer_fc(type, attrs, toplevel_param) == FC_RP)
3859  {
3860  switch (get_array_fc(type))
3861  {
3862  case FC_SMFARRAY:
3863  case FC_LGFARRAY:
3864  return type_array_get_dim(type) *
3866  NULL, FALSE, alignment);
3867  }
3868  }
3869  break;
3870 
3871  default:
3872  break;
3873  }
3874  return 0;
3875 }
3876 
3877 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass)
3878 {
3879  int in_attr = is_attr(var->attrs, ATTR_IN);
3880  int out_attr = is_attr(var->attrs, ATTR_OUT);
3881 
3882  if (!in_attr && !out_attr)
3883  in_attr = 1;
3884 
3885  *alignment = 0;
3886 
3887  if ((pass == PASS_IN && in_attr) || (pass == PASS_OUT && out_attr) ||
3888  pass == PASS_RETURN)
3889  {
3891  {
3892  *alignment = 4;
3893  return 20;
3894  }
3895 
3896  if (!is_string_type(var->attrs, var->type))
3897  return get_required_buffer_size_type(var->type, var->name,
3898  var->attrs, TRUE, alignment);
3899  }
3900  return 0;
3901 }
3902 
3903 static unsigned int get_function_buffer_size( const var_t *func, enum pass pass )
3904 {
3905  const var_t *var;
3906  unsigned int total_size = 0, alignment;
3907 
3908  if (type_get_function_args(func->type))
3909  {
3911  {
3912  total_size += get_required_buffer_size(var, &alignment, pass);
3913  total_size += alignment;
3914  }
3915  }
3916 
3917  if (pass == PASS_OUT && !is_void(type_function_get_rettype(func->type)))
3918  {
3919  var_t v = *func;
3920  v.type = type_function_get_rettype(func->type);
3921  total_size += get_required_buffer_size(&v, &alignment, PASS_RETURN);
3922  total_size += alignment;
3923  }
3924  return total_size;
3925 }
3926 
3927 static void print_phase_function(FILE *file, int indent, const char *type,
3928  const char *local_var_prefix, enum remoting_phase phase,
3929  const var_t *var, unsigned int type_offset)
3930 {
3931  const char *function;
3932  switch (phase)
3933  {
3934  case PHASE_BUFFERSIZE:
3935  function = "BufferSize";
3936  break;
3937  case PHASE_MARSHAL:
3938  function = "Marshall";
3939  break;
3940  case PHASE_UNMARSHAL:
3941  function = "Unmarshall";
3942  break;
3943  case PHASE_FREE:
3944  function = "Free";
3945  break;
3946  default:
3947  assert(0);
3948  return;
3949  }
3950 
3951  print_file(file, indent, "Ndr%s%s(\n", type, function);
3952  indent++;
3953  print_file(file, indent, "&__frame->_StubMsg,\n");
3954  print_file(file, indent, "%s%s%s%s%s,\n",
3955  (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)",
3956  (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "",
3957  local_var_prefix,
3958  (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "",
3959  var->name);
3960  print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n",
3961  type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");");
3962  if (phase == PHASE_UNMARSHAL)
3963  print_file(file, indent, "0);\n");
3964  indent--;
3965 }
3966 
3967 void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix,
3968  enum remoting_phase phase, enum pass pass, const var_t *var,
3969  const char *varname)
3970 {
3971  type_t *type = var->type;
3972  unsigned int alignment = 0;
3973 
3974  /* no work to do for other phases, buffer sizing is done elsewhere */
3975  if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL)
3976  return;
3977 
3978  if (type_get_type(type) == TYPE_ENUM ||
3979  (type_get_type(type) == TYPE_BASIC &&
3981  pointer_size != 4))
3982  {
3983  unsigned char fc;
3984 
3985  if (type_get_type(type) == TYPE_ENUM)
3986  fc = get_enum_fc(type);
3987  else
3988  fc = get_basic_fc(type);
3989 
3990  if (phase == PHASE_MARSHAL)
3991  print_file(file, indent, "NdrSimpleTypeMarshall(\n");
3992  else
3993  print_file(file, indent, "NdrSimpleTypeUnmarshall(\n");
3994  print_file(file, indent+1, "&__frame->_StubMsg,\n");
3995  print_file(file, indent+1, "(unsigned char *)&%s%s,\n",
3996  local_var_prefix,
3997  var->name);
3998  print_file(file, indent+1, "0x%02x /* %s */);\n", fc, string_of_type(fc));
3999  }
4000  else
4001  {
4003  switch (get_basic_fc(ref))
4004  {
4005  case FC_BYTE:
4006  case FC_CHAR:
4007  case FC_SMALL:
4008  case FC_USMALL:
4009  alignment = 1;
4010  break;
4011 
4012  case FC_WCHAR:
4013  case FC_USHORT:
4014  case FC_SHORT:
4015  alignment = 2;
4016  break;
4017 
4018  case FC_ULONG:
4019  case FC_LONG:
4020  case FC_FLOAT:
4021  case FC_ERROR_STATUS_T:
4022  /* pointer_size must be 4 if we got here in these two cases */
4023  case FC_INT3264:
4024  case FC_UINT3264:
4025  alignment = 4;
4026  break;
4027 
4028  case FC_HYPER:
4029  case FC_DOUBLE:
4030  alignment = 8;
4031  break;
4032 
4033  case FC_IGNORE:
4034  case