1 /* 2 * Format String Generator for IDL Compiler 3 * 4 * Copyright 2005-2006 Eric Kohl 5 * Copyright 2005-2006 Robert Shearman 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include "config.h" 23 #include "wine/port.h" 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #ifdef HAVE_UNISTD_H 28 # include <unistd.h> 29 #endif 30 #include <string.h> 31 #include <assert.h> 32 #include <ctype.h> 33 #include <limits.h> 34 35 #include "widl.h" 36 #include "utils.h" 37 #include "parser.h" 38 #include "header.h" 39 #include "typetree.h" 40 41 #include "typegen.h" 42 #include "expr.h" 43 44 /* round size up to multiple of alignment */ 45 #define ROUND_SIZE(size, alignment) (((size) + ((alignment) - 1)) & ~((alignment) - 1)) 46 /* value to add on to round size up to a multiple of alignment */ 47 #define ROUNDING(size, alignment) (((alignment) - 1) - (((size) + ((alignment) - 1)) & ((alignment) - 1))) 48 49 static const type_t *current_structure; 50 static const var_t *current_func; 51 static const type_t *current_iface; 52 53 static struct list expr_eval_routines = LIST_INIT(expr_eval_routines); 54 struct expr_eval_routine 55 { 56 struct list entry; 57 const type_t *iface; 58 const type_t *cont_type; 59 char *name; 60 unsigned int baseoff; 61 const expr_t *expr; 62 }; 63 64 enum type_context 65 { 66 TYPE_CONTEXT_TOPLEVELPARAM, 67 TYPE_CONTEXT_PARAM, 68 TYPE_CONTEXT_CONTAINER, 69 TYPE_CONTEXT_CONTAINER_NO_POINTERS, 70 }; 71 72 /* 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, 94 type_t *type, enum type_context context, 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)) 199 t = type_alias_get_aliasee(t); 200 else return NULL; 201 } 202 } 203 204 unsigned char get_basic_fc(const type_t *type) 205 { 206 int sign = type_basic_get_sign(type); 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; 222 case TYPE_BASIC_ERROR_STATUS_T: return FC_ERROR_STATUS_T; 223 case TYPE_BASIC_HANDLE: return FC_BIND_PRIMITIVE; 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; 245 case TYPE_BASIC_ERROR_STATUS_T: return FC_ERROR_STATUS_T; 246 case TYPE_BASIC_HANDLE: return FC_BIND_PRIMITIVE; 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 263 assert(is_ptr(type) || is_array(type)); 264 265 pointer_type = get_attrv(attrs, ATTR_POINTERTYPE); 266 if (pointer_type) 267 return pointer_type; 268 269 for (t = type; type_is_alias(t); t = type_alias_get_aliasee(t)) 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)) 279 return type_pointer_get_default_fc(type); 280 else 281 return type_array_get_ptr_default_fc(type); 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 ) && 290 context == TYPE_CONTEXT_PARAM && is_object( current_iface )) 291 pointer_fc = FC_OP; 292 293 return pointer_fc; 294 } 295 296 static unsigned char get_enum_fc(const type_t *type) 297 { 298 assert(type_get_type(type) == TYPE_ENUM); 299 if (is_aliaschain_attr(type, ATTR_V1ENUM)) 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)) 318 t = type_alias_get_aliasee(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 334 if (is_aliaschain_attr(type, ATTR_CONTEXTHANDLE)) 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) && 344 (is_attr(attrs, ATTR_RANGE) || is_aliaschain_attr(type, ATTR_RANGE))) 345 return TGT_RANGE; 346 return TGT_BASIC; 347 case TYPE_ENUM: 348 if (!(flags & TDT_IGNORE_RANGES) && 349 (is_attr(attrs, ATTR_RANGE) || is_aliaschain_attr(type, ATTR_RANGE))) 350 return TGT_RANGE; 351 return TGT_ENUM; 352 case TYPE_POINTER: 353 if (type_get_type(type_pointer_get_ref(type)) == TYPE_INTERFACE || 354 (type_get_type(type_pointer_get_ref(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS))) 355 return TGT_IFACE_POINTER; 356 else if (is_aliaschain_attr(type_pointer_get_ref(type), ATTR_CONTEXTHANDLE)) 357 return TGT_CTXT_HANDLE_POINTER; 358 else 359 return TGT_POINTER; 360 case TYPE_STRUCT: 361 return TGT_STRUCT; 362 case TYPE_ENCAPSULATED_UNION: 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); 388 case TGT_CTXT_HANDLE_POINTER: 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); 410 align = clamp_align(align); 411 if (align > salign) salign = align; 412 offset = ROUND_SIZE(offset, 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 449 if (is_attr(iface->attrs, ATTR_STRICTCONTEXTHANDLE)) flags |= NDR_STRICT_CONTEXT_HANDLE; 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; 459 if (!is_attr(attrs, ATTR_OUT)) flags |= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL; 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; 494 enum typegen_type typegen_type; 495 496 typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS); 497 498 if (typegen_type == TGT_ARRAY && !type_array_is_decl_as_ptr(t)) 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 508 if (is_array(type_array_get_element(field->type))) 509 return FC_BOGUS_STRUCT; 510 511 if (type_array_has_conformance(field->type)) 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 } 518 if (type_array_has_variance(t)) 519 has_variance = 1; 520 521 t = type_array_get_element(t); 522 typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS); 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: 531 if (type_basic_get_type(t) == TYPE_BASIC_INT3264 && pointer_size != 4) 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: 594 case TGT_CTXT_HANDLE_POINTER: 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 637 if (type_array_has_variance(type)) 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: 686 case TGT_CTXT_HANDLE_POINTER: 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 697 static int is_non_complex_struct(const type_t *type) 698 { 699 return (type_get_type(type) == TYPE_STRUCT && 700 get_struct_fc(type) != FC_BOGUS_STRUCT); 701 } 702 703 static int type_has_pointers(const type_t *type) 704 { 705 switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS)) 706 { 707 case TGT_USER_TYPE: 708 return FALSE; 709 case TGT_POINTER: 710 return TRUE; 711 case TGT_ARRAY: 712 return type_array_is_decl_as_ptr(type) || type_has_pointers(type_array_get_element(type)); 713 case TGT_STRUCT: 714 { 715 var_list_t *fields = type_struct_get_fields(type); 716 const var_t *field; 717 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) 718 { 719 if (type_has_pointers(field->type)) 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 { 731 if (field->type && type_has_pointers(field->type)) 732 return TRUE; 733 } 734 break; 735 } 736 case TGT_CTXT_HANDLE: 737 case TGT_CTXT_HANDLE_POINTER: 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 { 753 switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS)) 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 766 return type_has_full_pointer(type_array_get_element(type), NULL, FALSE); 767 case TGT_STRUCT: 768 { 769 var_list_t *fields = type_struct_get_fields(type); 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: 791 case TGT_CTXT_HANDLE_POINTER: 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; 808 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) 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 { 837 switch (typegen_detect_type(type, NULL, TDT_ALL_TYPES)) 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); 855 t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(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 913 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 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 929 void write_formatstringsdecl(FILE *f, int indent, const statement_list_t *stmts, type_pred_t pred) 930 { 931 clear_all_offsets(); 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 && 954 type_get_type(t) != TYPE_POINTER && 955 type_get_type(t) != TYPE_ARRAY); 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; 1026 case TGT_CTXT_HANDLE_POINTER: 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 )) 1039 buffer_size = get_required_buffer_size_type( ref, NULL, NULL, TRUE, &alignment ); 1040 1041 switch (typegen_detect_type( ref, NULL, TDT_ALL_TYPES )) 1042 { 1043 case TGT_BASIC: 1044 *flags |= IsSimpleRef | IsBasetype; 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 { 1051 *flags |= IsSimpleRef | IsBasetype; 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: 1070 case TGT_CTXT_HANDLE_POINTER: 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; 1118 var_list_t *args = type_get_function_args( func->type ); 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", 1165 *stack_offset, *stack_offset ); 1166 if (flags & IsBasetype) 1167 { 1168 print_file( file, indent, "0x%02x, /* %s */\n", fc, string_of_type(fc) ); 1169 print_file( file, indent, "0x0,\n" ); 1170 } 1171 else 1172 print_file( file, indent, "NdrFcShort(0x%x), /* type offset = %u */\n", 1173 typestring_offset, typestring_offset ); 1174 *stack_offset += max( stack_size, pointer_size ); 1175 return 6; 1176 } 1177 1178 static unsigned int write_old_procformatstring_type(FILE *file, int indent, const var_t *var, 1179 int is_return, int is_interpreted) 1180 { 1181 unsigned int size; 1182 1183 int is_in = is_attr(var->attrs, ATTR_IN); 1184 int is_out = is_attr(var->attrs, ATTR_OUT); 1185 1186 if (!is_in && !is_out) is_in = TRUE; 1187 1188 if (type_get_type(var->type) == TYPE_BASIC || 1189 type_get_type(var->type) == TYPE_ENUM) 1190 { 1191 unsigned char fc; 1192 1193 if (is_return) 1194 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n"); 1195 else 1196 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n"); 1197 1198 if (type_get_type(var->type) == TYPE_ENUM) 1199 { 1200 fc = get_enum_fc(var->type); 1201 } 1202 else 1203 { 1204 fc = get_basic_fc_signed(var->type); 1205 1206 if (fc == FC_BIND_PRIMITIVE) 1207 fc = FC_IGNORE; 1208 } 1209 1210 print_file(file, indent, "0x%02x, /* %s */\n", 1211 fc, string_of_type(fc)); 1212 size = 2; /* includes param type prefix */ 1213 } 1214 else 1215 { 1216 unsigned short offset = var->typestring_offset; 1217 1218 if (!is_interpreted && is_array(var->type) && 1219 type_array_is_decl_as_ptr(var->type) && 1220 var->type->details.array.ptr_tfsoff) 1221 offset = var->type->typestring_offset; 1222 1223 if (is_return) 1224 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n"); 1225 else if (is_in && is_out) 1226 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n"); 1227 else if (is_out) 1228 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n"); 1229 else 1230 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n"); 1231 1232 size = get_stack_size( var, NULL ); 1233 print_file(file, indent, "0x%02x,\n", size / pointer_size ); 1234 print_file(file, indent, "NdrFcShort(0x%x), /* type offset = %u */\n", offset, offset); 1235 size = 4; /* includes param type prefix */ 1236 } 1237 return size; 1238 } 1239 1240 int is_interpreted_func( const type_t *iface, const var_t *func ) 1241 { 1242 const char *str; 1243 const var_t *var; 1244 const var_list_t *args = type_get_function_args( func->type ); 1245 const type_t *ret_type = type_function_get_rettype( func->type ); 1246 1247 if (type_get_type( ret_type ) == TYPE_BASIC) 1248 { 1249 switch (type_basic_get_type( ret_type )) 1250 { 1251 case TYPE_BASIC_INT64: 1252 case TYPE_BASIC_HYPER: 1253 /* return value must fit in a long_ptr */ 1254 if (pointer_size < 8) return 0; 1255 break; 1256 case TYPE_BASIC_FLOAT: 1257 case TYPE_BASIC_DOUBLE: 1258 /* floating point values can't be returned */ 1259 return 0; 1260 default: 1261 break; 1262 } 1263 } 1264 if (get_stub_mode() != MODE_Oif && args) 1265 { 1266 LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) 1267 switch (type_get_type( var->type )) 1268 { 1269 case TYPE_BASIC: 1270 switch (type_basic_get_type( var->type )) 1271 { 1272 /* floating point arguments are not supported in Oi mode */ 1273 case TYPE_BASIC_FLOAT: return 0; 1274 case TYPE_BASIC_DOUBLE: return 0; 1275 default: break; 1276 } 1277 break; 1278 /* unions passed by value are not supported in Oi mode */ 1279 case TYPE_UNION: return 0; 1280 case TYPE_ENCAPSULATED_UNION: return 0; 1281 default: break; 1282 } 1283 } 1284 1285 if ((str = get_attrp( func->attrs, ATTR_OPTIMIZE ))) return !strcmp( str, "i" ); 1286 if ((str = get_attrp( iface->attrs, ATTR_OPTIMIZE ))) return !strcmp( str, "i" ); 1287 return (get_stub_mode() != MODE_Os); 1288 } 1289 1290 static void write_proc_func_header( FILE *file, int indent, const type_t *iface, 1291 const var_t *func, unsigned int *offset, 1292 unsigned short num_proc ) 1293 { 1294 var_t *var; 1295 var_list_t *args = type_get_function_args( func->type ); 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 1386 size = get_function_buffer_size( func, PASS_IN ); 1387 print_file( file, indent, "NdrFcShort(0x%x),\t/* client buffer = %u */\n", size, size ); 1388 size = get_function_buffer_size( func, PASS_OUT ); 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; 1438 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 1439 { 1440 print_file( file, 0, "/* %u (parameter %s) */\n", *offset, var->name ); 1441 if (is_new_style) 1442 *offset += write_new_procformatstring_type(file, indent, var, FALSE, &stack_offset); 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) 1463 *offset += write_new_procformatstring_type(file, indent, retval, TRUE, &stack_offset); 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 1494 STATEMENTS_FOR_EACH_FUNC(stmt, type_iface_get_stmts(iface)) 1495 { 1496 var_t *func = stmt->u.var; 1497 if (is_local(func->attrs)) continue; 1498 write_procformatstring_func( file, indent, iface, func, offset, count++ ); 1499 } 1500 } 1501 1502 void write_procformatstring(FILE *file, const statement_list_t *stmts, type_pred_t pred) 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 1514 for_each_iface(stmts, write_iface_procformatstring, pred, file, indent, &offset); 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 1524 void write_procformatstring_offsets( FILE *file, const type_t *iface ) 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++; 1533 STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) 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) 1548 fc = get_basic_fc_signed(type); 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; 1603 if (is_ptr(type) || (is_array(type) && type_array_is_decl_as_ptr(type))) 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 1761 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry) 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; 1783 list_add_tail (&expr_eval_routines, &eval->entry); 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 { 1846 size = type_memsize_and_alignment(v->type, &align); 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: 1915 size = fields_memsize(type_struct_get_fields(t), align); 1916 break; 1917 case TYPE_ENCAPSULATED_UNION: 1918 size = fields_memsize(type_encapsulated_union_get_fields(t), align); 1919 break; 1920 case TYPE_UNION: 1921 size = union_memsize(type_union_get_cases(t), align); 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: 1930 if (!type_array_is_decl_as_ptr(t)) 1931 { 1932 if (is_conformant_array(t)) 1933 { 1934 type_memsize_and_alignment(type_array_get_element(t), align); 1935 size = 0; 1936 } 1937 else 1938 size = type_array_get_dim(t) * 1939 type_memsize_and_alignment(type_array_get_element(t), align); 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; 2024 case TYPE_ENCAPSULATED_UNION: 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: 2043 if (!type_array_is_decl_as_ptr(t)) 2044 return type_buffer_alignment( type_array_get_element(t) ); 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 2064 int is_full_pointer_function(const var_t *func) 2065 { 2066 const var_t *var; 2067 if (type_has_full_pointer(type_function_get_rettype(func->type), func->attrs, TRUE)) 2068 return TRUE; 2069 if (!type_get_function_args(func->type)) 2070 return FALSE; 2071 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 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 2084 void write_full_pointer_free(FILE *file, int indent, const var_t *func) 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 2108 if (!is_interpreted_func(current_iface, current_func)) 2109 { 2110 if (out_attr && !in_attr && pointer_type == FC_RP) 2111 flags |= FC_ALLOCED_ON_STACK; 2112 } 2113 else if (get_stub_mode() == MODE_Oif) 2114 { 2115 if (context == TYPE_CONTEXT_TOPLEVELPARAM && is_ptr(type) && pointer_type == FC_RP) 2116 { 2117 switch (typegen_detect_type(type_pointer_get_ref(type), NULL, TDT_ALL_TYPES)) 2118 { 2119 case TGT_STRING: 2120 case TGT_POINTER: 2121 case TGT_CTXT_HANDLE: 2122 case TGT_CTXT_HANDLE_POINTER: 2123 flags |= FC_ALLOCED_ON_STACK; 2124 break; 2125 case TGT_IFACE_POINTER: 2126 if (in_attr && out_attr) 2127 flags |= FC_ALLOCED_ON_STACK; 2128 break; 2129 default: 2130 break; 2131 } 2132 } 2133 } 2134 2135 if (is_ptr(type)) 2136 { 2137 type_t *ref = type_pointer_get_ref(type); 2138 if(is_declptr(ref) && !is_user_type(ref)) 2139 flags |= FC_POINTER_DEREF; 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 2178 ref = type_pointer_get_ref(type); 2179 if (type_get_type(ref) == TYPE_ENUM) 2180 fc = get_enum_fc(ref); 2181 else 2182 fc = get_basic_fc(ref); 2183 2184 if (!is_interpreted_func(current_iface, current_func)) 2185 { 2186 if (out_attr && !in_attr && pointer_fc == FC_RP) 2187 flags |= FC_ALLOCED_ON_STACK; 2188 } 2189 else if (get_stub_mode() == MODE_Oif) 2190 { 2191 if (context == TYPE_CONTEXT_TOPLEVELPARAM && fc == FC_ENUM16 && pointer_fc == FC_RP) 2192 flags |= FC_ALLOCED_ON_STACK; 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); 2206 write_type_decl(file, t, NULL); 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; 2216 type_t *ref = type_pointer_get_ref(type); 2217 2218 print_start_tfs_comment(file, type, offset); 2219 update_tfsoff(type, offset, file); 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 2241 static int user_type_has_variable_size(const type_t *t) 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; 2309 update_tfsoff(type, start, file); 2310 print_start_tfs_comment(file, type, start); 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 { 2329 if (is_embedded_complex(type) && !is_conformant_array(type)) 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 { 2367 type_t *elem = type_array_get_element(type); 2368 2369 if (!is_embedded_complex(elem) && is_ptr(elem)) 2370 { 2371 type_t *ref = type_pointer_get_ref(elem); 2372 2373 if (processed(ref)) 2374 { 2375 write_nonsimple_pointer(file, NULL, elem, TYPE_CONTEXT_CONTAINER, 2376 ref->typestring_offset, tfsoff); 2377 return; 2378 } 2379 if (cont_is_complex && is_string_type(attrs, elem)) 2380 { 2381 write_string_tfs(file, NULL, elem, TYPE_CONTEXT_CONTAINER, NULL, tfsoff); 2382 return; 2383 } 2384 if (!is_string_type(NULL, elem) && 2385 (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM)) 2386 { 2387 *tfsoff += write_simple_pointer(file, NULL, elem, TYPE_CONTEXT_CONTAINER); 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; 2408 var_list_t *fs = type_struct_get_fields(type); 2409 var_t *f; 2410 2411 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry) 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); 2425 write_conf_or_var_desc(file, current_structure, offset, ft, 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 2435 static int write_pointer_description_offsets( 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 2442 if ((is_ptr(type) && type_get_type(type_pointer_get_ref(type)) != TYPE_INTERFACE) || 2443 (is_array(type) && type_array_is_decl_as_ptr(type))) 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 { 2467 type_t *ref = type_pointer_get_ref(type); 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)) 2472 write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER, 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 { 2494 return write_pointer_description_offsets( 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; 2502 LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) 2503 { 2504 if (offset_in_memory && offset_in_buffer) 2505 { 2506 unsigned int padding; 2507 unsigned int align = 0; 2508 type_memsize_and_alignment(v->type, &align); 2509 padding = ROUNDING(*offset_in_memory, align); 2510 *offset_in_memory += padding; 2511 *offset_in_buffer += padding; 2512 } 2513 written += write_pointer_description_offsets( 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 2533 static int write_no_repeat_pointer_descriptions( 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) || 2541 (is_conformant_array(type) && type_array_is_decl_as_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 2547 return write_pointer_description_offsets(file, attrs, type, 2548 offset_in_memory, offset_in_buffer, typestring_offset); 2549 } 2550 2551 if (is_non_complex_struct(type)) 2552 { 2553 const var_t *v; 2554 LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) 2555 { 2556 if (offset_in_memory && offset_in_buffer) 2557 { 2558 unsigned int padding; 2559 unsigned int align = 0; 2560 type_memsize_and_alignment(v->type, &align); 2561 padding = ROUNDING(*offset_in_memory, align); 2562 *offset_in_memory += padding; 2563 *offset_in_buffer += padding; 2564 } 2565 written += write_no_repeat_pointer_descriptions( 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 */ 2584 static int write_fixed_array_pointer_descriptions( 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 && 2592 !type_array_has_conformance(type) && !type_array_has_variance(type)) 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; 2623 LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) 2624 { 2625 if (offset_in_memory && offset_in_buffer) 2626 { 2627 unsigned int padding; 2628 unsigned int align = 0; 2629 type_memsize_and_alignment(v->type, &align); 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 */ 2657 static int write_conformant_array_pointer_descriptions( 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 2663 if (is_conformant_array(type) && !type_array_has_variance(type)) 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 */ 2700 static int write_varying_array_pointer_descriptions( 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 2707 if (is_array(type) && type_array_has_variance(type)) 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; 2738 LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) 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 2751 type_memsize_and_alignment(v->type, &align); 2752 padding = ROUNDING(*offset_in_memory, align); 2753 *offset_in_memory += padding; 2754 *offset_in_buffer += padding; 2755 } 2756 pointer_count += write_varying_array_pointer_descriptions( 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 2776 static void write_pointer_description(FILE *file, const attr_list_t *attrs, type_t *type, 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; 2788 write_no_repeat_pointer_descriptions( 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; 2796 write_fixed_array_pointer_descriptions( 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) && 2803 (type_array_is_decl_as_ptr(type) || !current_structure)) 2804 write_conformant_array_pointer_descriptions( 2805 file, attrs, type, 0, typestring_offset); 2806 else if (type_get_type(type) == TYPE_STRUCT && 2807 get_struct_fc(type) == FC_CPSTRUCT) 2808 { 2809 type_t *carray = find_array_or_string_in_struct(type)->type; 2810 write_conformant_array_pointer_descriptions( file, NULL, carray, 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; 2817 write_varying_array_pointer_descriptions( 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, 2823 type_t *type, enum type_context context, 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 2873 if (type_get_type(type) == TYPE_ARRAY && !type_array_has_conformance(type)) 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( 2907 file, current_structure, 2908 (!type_array_is_decl_as_ptr(type) && current_structure 2909 ? type_memsize(current_structure) 2910 : 0), 2911 type, type_array_get_conformance(type)); 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 2943 = !type_array_is_decl_as_ptr(type) && current_structure 2944 ? type_memsize(current_structure) 2945 : 0; 2946 2947 if (!pointer_type) 2948 pointer_type = FC_RP; 2949 2950 if (!is_string_type(attrs, type_array_get_element(type))) 2951 write_embedded_types(file, attrs, type_array_get_element(type), name, FALSE, typestring_offset); 2952 2953 size = type_memsize(is_conformant_array(type) ? type_array_get_element(type) : type); 2954 align = type_buffer_alignment(is_conformant_array(type) ? type_array_get_element(type) : type); 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 2978 if (is_conformant_array(type)) 2979 *typestring_offset 2980 += write_conf_or_var_desc(file, current_structure, baseoff, 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 3005 += write_conf_or_var_desc(file, current_structure, baseoff, 3006 type, length_is); 3007 3008 if (type_has_pointers(type_array_get_element(type)) && 3009 (type_array_is_decl_as_ptr(type) || !current_structure)) 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 3028 += write_conf_or_var_desc(file, current_structure, baseoff, 3029 type, size_is); 3030 *typestring_offset 3031 += write_conf_or_var_desc(file, current_structure, baseoff, 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 3041 static const var_t *find_array_or_string_in_struct(const type_t *type) 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 3053 if (is_conformant_array(ft) && !type_array_is_decl_as_ptr(ft)) 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 3062 static void write_struct_members(FILE *file, const type_t *type, 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; 3070 var_list_t *fields = type_struct_get_fields(type); 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 3080 if (!is_conformant_array(ft) || type_array_is_decl_as_ptr(ft)) 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)); 3100 offset = ROUND_SIZE(offset, align); 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); 3132 var_list_t *fields = type_struct_get_fields(type); 3133 3134 if (processed(type)) return type->typestring_offset; 3135 3136 guard_rec(type); 3137 current_structure = type; 3138 3139 total_size = type_memsize(type); 3140 align = type_buffer_alignment(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 3148 array = find_array_or_string_in_struct(type); 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) || 3196 (fc == FC_CVSTRUCT && type_has_pointers(type))) 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; 3201 write_pointer_description(file, NULL, type, tfsoff); 3202 print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END); 3203 *tfsoff += 1; 3204 } 3205 3206 write_struct_members(file, type, fc == FC_BOGUS_STRUCT, &corroff, 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; 3217 switch (typegen_detect_type(ft, f->attrs, TDT_IGNORE_STRINGS)) 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; 3239 write_nonsimple_pointer(file, f->attrs, ft, TYPE_CONTEXT_CONTAINER, offset, tfsoff); 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 { 3262 if (type_get_type(t) == TYPE_BASIC || type_get_type(t) == TYPE_ENUM) 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) && 3298 (type_get_type(type) == TYPE_ENCAPSULATED_UNION || !is_attr(type->attrs, ATTR_SWITCHTYPE))) 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); 3319 if (type_get_type(type) == TYPE_ENCAPSULATED_UNION) 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 3351 type_memsize_and_alignment(st, &align); 3352 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) 3353 { 3354 if (f->type) 3355 type_memsize_and_alignment(f->type, &align); 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 3468 += write_conf_or_var_desc(file, current_structure, 0, type, iid) + 2; 3469 } 3470 else 3471 { 3472 const type_t *base = is_ptr(type) ? type_pointer_get_ref(type) : type; 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, "); 3520 if (flags & NDR_CONTEXT_HANDLE_SERIALIZE) 3521 print_file(file, 0, "serialize, "); 3522 if (flags & NDR_CONTEXT_HANDLE_NOSERIALIZE) 3523 print_file(file, 0, "no serialize, "); 3524 if (flags & NDR_STRICT_CONTEXT_HANDLE) 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: 3582 case TGT_CTXT_HANDLE_POINTER: 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 && 3594 context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) || 3595 !is_conformant_array(type) || type_array_is_decl_as_ptr(type)) 3596 off = write_array_tfs(file, attrs, type, name, typeformat_offset); 3597 else 3598 off = 0; 3599 if (context != TYPE_CONTEXT_CONTAINER && 3600 context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) 3601 { 3602 int ptr_type; 3603 ptr_type = get_pointer_fc(type, attrs, 3604 context == TYPE_CONTEXT_TOPLEVELPARAM); 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; 3642 unsigned int toplevel_offset = *typeformat_offset; 3643 type_t *ref = type_pointer_get_ref(type); 3644 3645 if (context == TYPE_CONTEXT_TOPLEVELPARAM) 3646 ref_context = TYPE_CONTEXT_PARAM; 3647 else if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS) 3648 ref_context = TYPE_CONTEXT_CONTAINER; 3649 else 3650 ref_context = context; 3651 3652 if (is_string_type(attrs, ref)) 3653 { 3654 if (context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) 3655 write_pointer_tfs(file, attrs, type, *typeformat_offset + 4, context, typeformat_offset); 3656 3657 offset = write_type_tfs(file, indent, attrs, ref, name, ref_context, typeformat_offset); 3658 if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS) 3659 return 0; 3660 return (context == TYPE_CONTEXT_TOPLEVELPARAM) ? toplevel_offset : offset; 3661 } 3662 3663 offset = write_type_tfs( file, indent, attrs, type_pointer_get_ref(type), name, 3664 ref_context, typeformat_offset); 3665 if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS) 3666 return 0; 3667 return write_pointer_tfs(file, attrs, type, offset, context, typeformat_offset); 3668 } 3669 case TGT_INVALID: 3670 break; 3671 } 3672 error("invalid type %s for var %s\n", type->name, name); 3673 return 0; 3674 } 3675 3676 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type, 3677 const char *name, int write_ptr, unsigned int *tfsoff) 3678 { 3679 return write_type_tfs(file, 2, attrs, type, name, write_ptr ? TYPE_CONTEXT_CONTAINER : TYPE_CONTEXT_CONTAINER_NO_POINTERS, tfsoff); 3680 } 3681 3682 static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned int *offset) 3683 { 3684 const statement_list_t *stmts = type_iface_get_stmts(iface); 3685 const statement_t *stmt; 3686 var_t *var; 3687 3688 current_iface = iface; 3689 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry ) 3690 { 3691 switch(stmt->type) 3692 { 3693 case STMT_DECLARATION: 3694 { 3695 const var_t *func = stmt->u.var; 3696 3697 if(stmt->u.var->stgclass != STG_NONE 3698 || type_get_type_detect_alias(stmt->u.var->type) != TYPE_FUNCTION) 3699 continue; 3700 3701 current_func = func; 3702 if (is_local(func->attrs)) continue; 3703 3704 var = type_function_get_retval(func->type); 3705 if (!is_void(var->type)) 3706 var->typestring_offset = write_type_tfs( file, 2, func->attrs, var->type, func->name, 3707 TYPE_CONTEXT_PARAM, offset); 3708 3709 if (type_get_function_args(func->type)) 3710 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), var_t, entry ) 3711 var->typestring_offset = write_type_tfs( file, 2, var->attrs, var->type, var->name, 3712 TYPE_CONTEXT_TOPLEVELPARAM, offset ); 3713 break; 3714 3715 } 3716 case STMT_TYPEDEF: 3717 { 3718 const type_list_t *type_entry; 3719 for (type_entry = stmt->u.type_list; type_entry; type_entry = type_entry->next) 3720 { 3721 if (is_attr(type_entry->type->attrs, ATTR_ENCODE) 3722 || is_attr(type_entry->type->attrs, ATTR_DECODE)) 3723 type_entry->type->typestring_offset = write_type_tfs( file, 2, 3724 type_entry->type->attrs, type_entry->type, type_entry->type->name, 3725 TYPE_CONTEXT_CONTAINER, offset); 3726 } 3727 break; 3728 } 3729 default: 3730 break; 3731 } 3732 } 3733 } 3734 3735 static unsigned int process_tfs(FILE *file, const statement_list_t *stmts, type_pred_t pred) 3736 { 3737 unsigned int typeformat_offset = 2; 3738 for_each_iface(stmts, process_tfs_iface, pred, file, 0, &typeformat_offset); 3739 return typeformat_offset + 1; 3740 } 3741 3742 3743 void write_typeformatstring(FILE *file, const statement_list_t *stmts, type_pred_t pred) 3744 { 3745 int indent = 0; 3746 3747 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n"); 3748 print_file(file, indent, "{\n"); 3749 indent++; 3750 print_file(file, indent, "0,\n"); 3751 print_file(file, indent, "{\n"); 3752 indent++; 3753 print_file(file, indent, "NdrFcShort(0x0),\n"); 3754 3755 set_all_tfswrite(TRUE); 3756 process_tfs(file, stmts, pred); 3757 3758 print_file(file, indent, "0x0\n"); 3759 indent--; 3760 print_file(file, indent, "}\n"); 3761 indent--; 3762 print_file(file, indent, "};\n"); 3763 print_file(file, indent, "\n"); 3764 } 3765 3766 static unsigned int get_required_buffer_size_type( 3767 const type_t *type, const char *name, const attr_list_t *attrs, int toplevel_param, unsigned int *alignment) 3768 { 3769 *alignment = 0; 3770 switch (typegen_detect_type(type, NULL, TDT_IGNORE_RANGES)) 3771 { 3772 case TGT_USER_TYPE: 3773 { 3774 const char *uname = NULL; 3775 const type_t *utype = get_user_type(type, &uname); 3776 return get_required_buffer_size_type(utype, uname, NULL, FALSE, alignment); 3777 } 3778 case TGT_BASIC: 3779 switch (get_basic_fc(type)) 3780 { 3781 case FC_BYTE: 3782 case FC_CHAR: 3783 case FC_USMALL: 3784 case FC_SMALL: 3785 *alignment = 4; 3786 return 1; 3787 3788 case FC_WCHAR: 3789 case FC_USHORT: 3790 case FC_SHORT: 3791 *alignment = 4; 3792 return 2; 3793 3794 case FC_ULONG: 3795 case FC_LONG: 3796 case FC_FLOAT: 3797 case FC_ERROR_STATUS_T: 3798 *alignment = 4; 3799 return 4; 3800 3801 case FC_HYPER: 3802 case FC_DOUBLE: 3803 *alignment = 8; 3804 return 8; 3805 3806 case FC_INT3264: 3807 case FC_UINT3264: 3808 assert( pointer_size ); 3809 *alignment = pointer_size; 3810 return pointer_size; 3811 3812 case FC_IGNORE: 3813 case FC_BIND_PRIMITIVE: 3814 return 0; 3815 3816 default: 3817 error("get_required_buffer_size: unknown basic type 0x%02x\n", 3818 get_basic_fc(type)); 3819 return 0; 3820 } 3821 break; 3822 3823 case TGT_ENUM: 3824 switch (get_enum_fc(type)) 3825 { 3826 case FC_ENUM32: 3827 *alignment = 4; 3828 return 4; 3829 case FC_ENUM16: 3830 *alignment = 4; 3831 return 2; 3832 } 3833 break; 3834 3835 case TGT_STRUCT: 3836 if (get_struct_fc(type) == FC_STRUCT) 3837 { 3838 if (!type_struct_get_fields(type)) return 0; 3839 return fields_memsize(type_struct_get_fields(type), alignment); 3840 } 3841 break; 3842 3843 case TGT_POINTER: 3844 { 3845 unsigned int size, align; 3846 const type_t *ref = type_pointer_get_ref(type); 3847 if (is_string_type( attrs, ref )) break; 3848 if (!(size = get_required_buffer_size_type( ref, name, NULL, FALSE, &align ))) break; 3849 if (get_pointer_fc(type, attrs, toplevel_param) != FC_RP) 3850 { 3851 size += 4 + align; 3852 align = 4; 3853 } 3854 *alignment = align; 3855 return size; 3856 } 3857 3858 case TGT_ARRAY: 3859 if (get_pointer_fc(type, attrs, toplevel_param) == FC_RP) 3860 { 3861 switch (get_array_fc(type)) 3862 { 3863 case FC_SMFARRAY: 3864 case FC_LGFARRAY: 3865 return type_array_get_dim(type) * 3866 get_required_buffer_size_type(type_array_get_element(type), name, 3867 NULL, FALSE, alignment); 3868 } 3869 } 3870 break; 3871 3872 default: 3873 break; 3874 } 3875 return 0; 3876 } 3877 3878 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass) 3879 { 3880 int in_attr = is_attr(var->attrs, ATTR_IN); 3881 int out_attr = is_attr(var->attrs, ATTR_OUT); 3882 3883 if (!in_attr && !out_attr) 3884 in_attr = 1; 3885 3886 *alignment = 0; 3887 3888 if ((pass == PASS_IN && in_attr) || (pass == PASS_OUT && out_attr) || 3889 pass == PASS_RETURN) 3890 { 3891 if (is_ptrchain_attr(var, ATTR_CONTEXTHANDLE)) 3892 { 3893 *alignment = 4; 3894 return 20; 3895 } 3896 3897 if (!is_string_type(var->attrs, var->type)) 3898 return get_required_buffer_size_type(var->type, var->name, 3899 var->attrs, TRUE, alignment); 3900 } 3901 return 0; 3902 } 3903 3904 static unsigned int get_function_buffer_size( const var_t *func, enum pass pass ) 3905 { 3906 const var_t *var; 3907 unsigned int total_size = 0, alignment; 3908 3909 if (type_get_function_args(func->type)) 3910 { 3911 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 3912 { 3913 total_size += get_required_buffer_size(var, &alignment, pass); 3914 total_size += alignment; 3915 } 3916 } 3917 3918 if (pass == PASS_OUT && !is_void(type_function_get_rettype(func->type))) 3919 { 3920 var_t v = *func; 3921 v.type = type_function_get_rettype(func->type); 3922 total_size += get_required_buffer_size(&v, &alignment, PASS_RETURN); 3923 total_size += alignment; 3924 } 3925 return total_size; 3926 } 3927 3928 static void print_phase_function(FILE *file, int indent, const char *type, 3929 const char *local_var_prefix, enum remoting_phase phase, 3930 const var_t *var, unsigned int type_offset) 3931 { 3932 const char *function; 3933 switch (phase) 3934 { 3935 case PHASE_BUFFERSIZE: 3936 function = "BufferSize"; 3937 break; 3938 case PHASE_MARSHAL: 3939 function = "Marshall"; 3940 break; 3941 case PHASE_UNMARSHAL: 3942 function = "Unmarshall"; 3943 break; 3944 case PHASE_FREE: 3945 function = "Free"; 3946 break; 3947 default: 3948 assert(0); 3949 return; 3950 } 3951 3952 print_file(file, indent, "Ndr%s%s(\n", type, function); 3953 indent++; 3954 print_file(file, indent, "&__frame->_StubMsg,\n"); 3955 print_file(file, indent, "%s%s%s%s%s,\n", 3956 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)", 3957 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "", 3958 local_var_prefix, 3959 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "", 3960 var->name); 3961 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n", 3962 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");"); 3963 if (phase == PHASE_UNMARSHAL) 3964 print_file(file, indent, "0);\n"); 3965 indent--; 3966 } 3967 3968 void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, 3969 enum remoting_phase phase, enum pass pass, const var_t *var, 3970 const char *varname) 3971 { 3972 type_t *type = var->type; 3973 unsigned int alignment = 0; 3974 3975 /* no work to do for other phases, buffer sizing is done elsewhere */ 3976 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL) 3977 return; 3978 3979 if (type_get_type(type) == TYPE_ENUM || 3980 (type_get_type(type) == TYPE_BASIC && 3981 type_basic_get_type(type) == TYPE_BASIC_INT3264 && 3982 pointer_size != 4)) 3983 { 3984 unsigned char fc; 3985 3986 if (type_get_type(type) == TYPE_ENUM) 3987 fc = get_enum_fc(type); 3988 else 3989 fc = get_basic_fc(type); 3990 3991 if (phase == PHASE_MARSHAL) 3992 print_file(file, indent, "NdrSimpleTypeMarshall(\n"); 3993 else 3994 print_file(file, indent, "NdrSimpleTypeUnmarshall(\n"); 3995 print_file(file, indent+1, "&__frame->_StubMsg,\n"); 3996 print_file(file, indent+1, "(unsigned char *)&%s%s,\n", 3997 local_var_prefix, 3998 var->name); 3999 print_file(file, indent+1, "0x%02x /* %s */);\n", fc, string_of_type(fc)); 4000 } 4001 else 4002 { 4003 const type_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : type; 4004 switch (get_basic_fc(ref)) 4005 { 4006 case FC_BYTE: 4007 case FC_CHAR: 4008 case FC_SMALL: 4009 case FC_USMALL: 4010 alignment = 1; 4011 break; 4012 4013 case FC_WCHAR: 4014 case FC_USHORT: 4015 case FC_SHORT: 4016 alignment = 2; 4017 break; 4018 4019 case FC_ULONG: 4020 case FC_LONG: 4021 case FC_FLOAT: 4022 case FC_ERROR_STATUS_T: 4023 /* pointer_size must be 4 if we got here in these two cases */ 4024 case FC_INT3264: 4025 case FC_UINT3264: 4026 alignment = 4; 4027 break; 4028 4029 case FC_HYPER: 4030 case FC_DOUBLE: 4031 alignment = 8; 4032 break; 4033 4034 case FC_IGNORE: 4035 case FC_BIND_PRIMITIVE: 4036 /* no marshalling needed */ 4037 return; 4038 4039 default: 4040 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", 4041 var->name, get_basic_fc(ref)); 4042 } 4043 4044 if (phase == PHASE_MARSHAL && alignment > 1) 4045 print_file(file, indent, "MIDL_memset(__frame->_StubMsg.Buffer, 0, (0x%x - (ULONG_PTR)__frame->_StubMsg.Buffer) & 0x%x);\n", alignment, alignment - 1); 4046 print_file(file, indent, "__frame->_StubMsg.Buffer = (unsigned char *)(((ULONG_PTR)__frame->_StubMsg.Buffer + %u) & ~0x%x);\n", 4047 alignment - 1, alignment - 1); 4048 4049 if (phase == PHASE_MARSHAL) 4050 { 4051 print_file(file, indent, "*("); 4052 write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); 4053 if (is_ptr(type)) 4054 fprintf(file, " *)__frame->_StubMsg.Buffer = *"); 4055 else 4056 fprintf(file, " *)__frame->_StubMsg.Buffer = "); 4057 fprintf(file, "%s%s", local_var_prefix, varname); 4058 fprintf(file, ";\n"); 4059 } 4060 else if (phase == PHASE_UNMARSHAL) 4061 { 4062 print_file(file, indent, "if (__frame->_StubMsg.Buffer + sizeof("); 4063 write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); 4064 fprintf(file, ") > __frame->_StubMsg.BufferEnd)\n"); 4065 print_file(file, indent, "{\n"); 4066 print_file(file, indent + 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n"); 4067 print_file(file, indent, "}\n"); 4068 print_file(file, indent, "%s%s%s", 4069 (pass == PASS_IN || pass == PASS_RETURN) ? "" : "*", 4070 local_var_prefix, varname); 4071 if (pass == PASS_IN && is_ptr(type)) 4072 fprintf(file, " = ("); 4073 else 4074 fprintf(file, " = *("); 4075 write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); 4076 fprintf(file, " *)__frame->_StubMsg.Buffer;\n"); 4077 } 4078 4079 print_file(file, indent, "__frame->_StubMsg.Buffer += sizeof("); 4080 write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); 4081 fprintf(file, ");\n"); 4082 } 4083 } 4084 4085 /* returns whether the MaxCount, Offset or ActualCount members need to be 4086 * filled in for the specified phase */ 4087 static inline int is_conformance_needed_for_phase(enum remoting_phase phase) 4088 { 4089 return (phase != PHASE_UNMARSHAL); 4090 } 4091 4092 expr_t *get_size_is_expr(const type_t *t, const char *name) 4093 { 4094 expr_t *x = NULL; 4095 4096 for ( ; is_array(t); t = type_array_get_element(t)) 4097 if (type_array_has_conformance(t) && 4098 type_array_get_conformance(t)->type != EXPR_VOID) 4099 { 4100 if (!x) 4101 x = type_array_get_conformance(t); 4102 else 4103 error("%s: multidimensional conformant" 4104 " arrays not supported at the top level\n", 4105 name); 4106 } 4107 4108 return x; 4109 } 4110 4111 void write_parameter_conf_or_var_exprs(FILE *file, int indent, const char *local_var_prefix, 4112 enum remoting_phase phase, const var_t *var, int valid_variance) 4113 { 4114 const type_t *type = var->type; 4115 /* get fundamental type for the argument */ 4116 for (;;) 4117 { 4118 switch (typegen_detect_type(type, var->attrs, TDT_IGNORE_STRINGS|TDT_IGNORE_RANGES)) 4119 { 4120 case TGT_ARRAY: 4121 if (is_conformance_needed_for_phase(phase)) 4122 { 4123 if (type_array_has_conformance(type) && 4124 type_array_get_conformance(type)->type != EXPR_VOID) 4125 { 4126 print_file(file, indent, "__frame->_StubMsg.MaxCount = (ULONG_PTR)"); 4127 write_expr(file, type_array_get_conformance(type), 1, 1, NULL, NULL, local_var_prefix); 4128 fprintf(file, ";\n\n"); 4129 } 4130 if (type_array_has_variance(type)) 4131 { 4132 print_file(file, indent, "__frame->_StubMsg.Offset = 0;\n"); /* FIXME */ 4133 if (valid_variance) 4134 { 4135 print_file(file, indent, "__frame->_StubMsg.ActualCount = (ULONG_PTR)"); 4136 write_expr(file, type_array_get_variance(type), 1, 1, NULL, NULL, local_var_prefix); 4137 fprintf(file, ";\n\n"); 4138 } 4139 else 4140 print_file(file, indent, "__frame->_StubMsg.ActualCount = __frame->_StubMsg.MaxCount;\n\n"); 4141 } 4142 } 4143 break; 4144 case TGT_UNION: 4145 if (type_get_type(type) == TYPE_UNION && 4146 is_conformance_needed_for_phase(phase)) 4147 { 4148 print_file(file, indent, "__frame->_StubMsg.MaxCount = (ULONG_PTR)"); 4149 write_expr(file, get_attrp(var->attrs, ATTR_SWITCHIS), 1, 1, NULL, NULL, local_var_prefix); 4150 fprintf(file, ";\n\n"); 4151 } 4152 break; 4153 case TGT_IFACE_POINTER: 4154 { 4155 expr_t *iid; 4156 4157 if (is_conformance_needed_for_phase(phase) && (iid = get_attrp( var->attrs, ATTR_IIDIS ))) 4158 { 4159 print_file( file, indent, "__frame->_StubMsg.MaxCount = (ULONG_PTR) " ); 4160 write_expr( file, iid, 1, 1, NULL, NULL, local_var_prefix ); 4161 fprintf( file, ";\n\n" ); 4162 } 4163 break; 4164 } 4165 case TGT_POINTER: 4166 type = type_pointer_get_ref(type); 4167 continue; 4168 case TGT_INVALID: 4169 case TGT_USER_TYPE: 4170 case TGT_CTXT_HANDLE: 4171 case TGT_CTXT_HANDLE_POINTER: 4172 case TGT_STRING: 4173 case TGT_BASIC: 4174 case TGT_ENUM: 4175 case TGT_STRUCT: 4176 case TGT_RANGE: 4177 break; 4178 } 4179 break; 4180 } 4181 } 4182 4183 static void write_remoting_arg(FILE *file, int indent, const var_t *func, const char *local_var_prefix, 4184 enum pass pass, enum remoting_phase phase, const var_t *var) 4185 { 4186 int in_attr, out_attr, pointer_type; 4187 const char *type_str = NULL; 4188 const type_t *type = var->type; 4189 unsigned int alignment, start_offset = type->typestring_offset; 4190 4191 if (is_ptr(type) || is_array(type)) 4192 pointer_type = get_pointer_fc(type, var->attrs, pass != PASS_RETURN); 4193 else 4194 pointer_type = 0; 4195 4196 in_attr = is_attr(var->attrs, ATTR_IN); 4197 out_attr = is_attr(var->attrs, ATTR_OUT); 4198 if (!in_attr && !out_attr) 4199 in_attr = 1; 4200 4201 if (phase != PHASE_FREE) 4202 switch (pass) 4203 { 4204 case PASS_IN: 4205 if (!in_attr) return; 4206 break; 4207 case PASS_OUT: 4208 if (!out_attr) return; 4209 break; 4210 case PASS_RETURN: 4211 break; 4212 } 4213 4214 if (phase == PHASE_BUFFERSIZE && get_required_buffer_size( var, &alignment, pass )) return; 4215 4216 write_parameter_conf_or_var_exprs(file, indent, local_var_prefix, phase, var, TRUE); 4217 4218 switch (typegen_detect_type(type, var->attrs, TDT_ALL_TYPES)) 4219 { 4220 case TGT_CTXT_HANDLE: 4221 case TGT_CTXT_HANDLE_POINTER: 4222 if (phase == PHASE_MARSHAL) 4223 { 4224 if (pass == PASS_IN) 4225 { 4226 /* if the context_handle attribute appears in the chain of types 4227 * without pointers being followed, then the context handle must 4228 * be direct, otherwise it is a pointer */ 4229 const char *ch_ptr = is_aliaschain_attr(type, ATTR_CONTEXTHANDLE) ? "" : "*"; 4230 print_file(file, indent, "NdrClientContextMarshall(\n"); 4231 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 4232 print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s%s,\n", ch_ptr, local_var_prefix, 4233 var->name); 4234 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0"); 4235 } 4236 else 4237 { 4238 print_file(file, indent, "NdrServerContextNewMarshall(\n"); 4239 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 4240 print_file(file, indent + 1, "(NDR_SCONTEXT)%s%s,\n", local_var_prefix, var->name); 4241 print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var->type)); 4242 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset); 4243 } 4244 } 4245 else if (phase == PHASE_UNMARSHAL) 4246 { 4247 if (pass == PASS_OUT) 4248 { 4249 if (!in_attr) 4250 print_file(file, indent, "*%s%s = 0;\n", local_var_prefix, var->name); 4251 print_file(file, indent, "NdrClientContextUnmarshall(\n"); 4252 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 4253 print_file(file, indent + 1, "(NDR_CCONTEXT *)%s%s,\n", local_var_prefix, var->name); 4254 print_file(file, indent + 1, "__frame->_Handle);\n"); 4255 } 4256 else 4257 { 4258 print_file(file, indent, "%s%s = NdrServerContextNewUnmarshall(\n", local_var_prefix, var->name); 4259 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 4260 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset); 4261 } 4262 } 4263 break; 4264 case TGT_USER_TYPE: 4265 print_phase_function(file, indent, "UserMarshal", local_var_prefix, phase, var, start_offset); 4266 break; 4267 case TGT_STRING: 4268 if (phase == PHASE_FREE || pass == PASS_RETURN || 4269 pointer_type != FC_RP) 4270 { 4271 /* strings returned are assumed to be global and hence don't 4272 * need freeing */ 4273 if (is_declptr(type) && !(phase == PHASE_FREE && pass == PASS_RETURN)) 4274 print_phase_function(file, indent, "Pointer", local_var_prefix, 4275 phase, var, start_offset); 4276 else if (pointer_type == FC_RP && phase == PHASE_FREE && 4277 !in_attr && is_conformant_array(type)) 4278 { 4279 print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name); 4280 indent++; 4281 print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name); 4282 } 4283 } 4284 else 4285 { 4286 unsigned int real_start_offset = start_offset; 4287 /* skip over pointer description straight to string description */ 4288 if (is_declptr(type)) 4289 { 4290 if (is_conformant_array(type)) 4291 real_start_offset += 4; 4292 else 4293 real_start_offset += 2; 4294 } 4295 if (is_array(type) && !is_conformant_array(type)) 4296 print_phase_function(file, indent, "NonConformantString", 4297 local_var_prefix, phase, var, 4298 real_start_offset); 4299 else 4300 print_phase_function(file, indent, "ConformantString", local_var_prefix, 4301 phase, var, real_start_offset); 4302 } 4303 break; 4304 case TGT_ARRAY: 4305 { 4306 unsigned char tc = get_array_fc(type); 4307 const char *array_type = NULL; 4308 4309 /* We already have the size_is expression since it's at the 4310 top level, but do checks for multidimensional conformant 4311 arrays. When we handle them, we'll need to extend this 4312 function to return a list, and then we'll actually use 4313 the return value. */ 4314 get_size_is_expr(type, var->name); 4315 4316 switch (tc) 4317 { 4318 case FC_SMFARRAY: 4319 case FC_LGFARRAY: 4320 array_type = "FixedArray"; 4321 break; 4322 case FC_SMVARRAY: 4323 case FC_LGVARRAY: 4324 array_type = "VaryingArray"; 4325 break; 4326 case FC_CARRAY: 4327 array_type = "ConformantArray"; 4328 break; 4329 case FC_CVARRAY: 4330 array_type = "ConformantVaryingArray"; 4331 break; 4332 case FC_BOGUS_ARRAY: 4333 array_type = "ComplexArray"; 4334 break; 4335 } 4336 4337 if (pointer_type != FC_RP) array_type = "Pointer"; 4338 4339 if (phase == PHASE_FREE && pointer_type == FC_RP) 4340 { 4341 /* these are all unmarshalled by allocating memory */ 4342 if (tc == FC_BOGUS_ARRAY || 4343 tc == FC_CVARRAY || 4344 ((tc == FC_SMVARRAY || tc == FC_LGVARRAY) && in_attr) || 4345 (tc == FC_CARRAY && !in_attr)) 4346 { 4347 if (type_array_is_decl_as_ptr(type) && type->details.array.ptr_tfsoff) 4348 { 4349 print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, 4350 type->details.array.ptr_tfsoff); 4351 break; 4352 } 4353 print_phase_function(file, indent, array_type, local_var_prefix, phase, var, start_offset); 4354 print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name); 4355 indent++; 4356 print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name); 4357 break; 4358 } 4359 } 4360 print_phase_function(file, indent, array_type, local_var_prefix, phase, var, start_offset); 4361 break; 4362 } 4363 case TGT_BASIC: 4364 print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name); 4365 break; 4366 case TGT_ENUM: 4367 print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name); 4368 break; 4369 case TGT_RANGE: 4370 print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name); 4371 /* Note: this goes beyond what MIDL does - it only supports arguments 4372 * with the [range] attribute in Oicf mode */ 4373 if (phase == PHASE_UNMARSHAL) 4374 { 4375 const expr_t *range_min; 4376 const expr_t *range_max; 4377 expr_list_t *range_list = get_attrp(var->attrs, ATTR_RANGE); 4378 if (!range_list) 4379 range_list = get_aliaschain_attrp(type, ATTR_RANGE); 4380 range_min = LIST_ENTRY(list_head(range_list), const expr_t, entry); 4381 range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry); 4382 4383 print_file(file, indent, "if ((%s%s < (", local_var_prefix, var->name); 4384 write_type_decl(file, var->type, NULL); 4385 fprintf(file, ")0x%x) || (%s%s > (", range_min->cval, local_var_prefix, var->name); 4386 write_type_decl(file, var->type, NULL); 4387 fprintf(file, ")0x%x))\n", range_max->cval); 4388 print_file(file, indent, "{\n"); 4389 print_file(file, indent+1, "RpcRaiseException(RPC_S_INVALID_BOUND);\n"); 4390 print_file(file, indent, "}\n"); 4391 } 4392 break; 4393 case TGT_STRUCT: 4394 switch (get_struct_fc(type)) 4395 { 4396 case FC_STRUCT: 4397 if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL) 4398 print_phase_function(file, indent, "SimpleStruct", local_var_prefix, phase, var, start_offset); 4399 break; 4400 case FC_PSTRUCT: 4401 print_phase_function(file, indent, "SimpleStruct", local_var_prefix, phase, var, start_offset); 4402 break; 4403 case FC_CSTRUCT: 4404 case FC_CPSTRUCT: 4405 print_phase_function(file, indent, "ConformantStruct", local_var_prefix, phase, var, start_offset); 4406 break; 4407 case FC_CVSTRUCT: 4408 print_phase_function(file, indent, "ConformantVaryingStruct", local_var_prefix, phase, var, start_offset); 4409 break; 4410 case FC_BOGUS_STRUCT: 4411 print_phase_function(file, indent, "ComplexStruct", local_var_prefix, phase, var, start_offset); 4412 break; 4413 default: 4414 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, get_struct_fc(type)); 4415 } 4416 break; 4417 case TGT_UNION: 4418 { 4419 const char *union_type = NULL; 4420 4421 if (type_get_type(type) == TYPE_UNION) 4422 union_type = "NonEncapsulatedUnion"; 4423 else if (type_get_type(type) == TYPE_ENCAPSULATED_UNION) 4424 union_type = "EncapsulatedUnion"; 4425 4426 print_phase_function(file, indent, union_type, local_var_prefix, 4427 phase, var, start_offset); 4428 break; 4429 } 4430 case TGT_POINTER: 4431 { 4432 const type_t *ref = type_pointer_get_ref(type); 4433 if (pointer_type == FC_RP) switch (typegen_detect_type(ref, NULL, TDT_ALL_TYPES)) 4434 { 4435 case TGT_BASIC: 4436 print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name); 4437 break; 4438 case TGT_ENUM: 4439 /* base types have known sizes, so don't need a sizing pass 4440 * and don't have any memory to free and so don't need a 4441 * freeing pass */ 4442 if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL) 4443 print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset); 4444 break; 4445 case TGT_STRUCT: 4446 switch (get_struct_fc(ref)) 4447 { 4448 case FC_STRUCT: 4449 /* simple structs have known sizes, so don't need a sizing 4450 * pass and don't have any memory to free and so don't 4451 * need a freeing pass */ 4452 if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL) 4453 type_str = "SimpleStruct"; 4454 else if (phase == PHASE_FREE && pass == PASS_RETURN) 4455 { 4456 print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name); 4457 indent++; 4458 print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name); 4459 indent--; 4460 } 4461 break; 4462 case FC_PSTRUCT: 4463 type_str = "SimpleStruct"; 4464 break; 4465 case FC_CSTRUCT: 4466 case FC_CPSTRUCT: 4467 type_str = "ConformantStruct"; 4468 break; 4469 case FC_CVSTRUCT: 4470 type_str = "ConformantVaryingStruct"; 4471 break; 4472 case FC_BOGUS_STRUCT: 4473 type_str = "ComplexStruct"; 4474 break; 4475 default: 4476 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, get_struct_fc(ref)); 4477 } 4478 4479 if (type_str) 4480 { 4481 if (phase == PHASE_FREE) 4482 type_str = "Pointer"; 4483 else 4484 start_offset = ref->typestring_offset; 4485 print_phase_function(file, indent, type_str, local_var_prefix, phase, var, start_offset); 4486 } 4487 break; 4488 case TGT_UNION: 4489 if (phase == PHASE_FREE) 4490 type_str = "Pointer"; 4491 else 4492 { 4493 if (type_get_type(ref) == TYPE_UNION) 4494 type_str = "NonEncapsulatedUnion"; 4495 else if (type_get_type(ref) == TYPE_ENCAPSULATED_UNION) 4496 type_str = "EncapsulatedUnion"; 4497 4498 start_offset = ref->typestring_offset; 4499 } 4500 4501 print_phase_function(file, indent, type_str, local_var_prefix, 4502 phase, var, start_offset); 4503 break; 4504 case TGT_USER_TYPE: 4505 if (phase != PHASE_FREE) 4506 { 4507 type_str = "UserMarshal"; 4508 start_offset = ref->typestring_offset; 4509 } 4510 else type_str = "Pointer"; 4511 4512 print_phase_function(file, indent, type_str, local_var_prefix, phase, var, start_offset); 4513 break; 4514 case TGT_STRING: 4515 case TGT_POINTER: 4516 case TGT_ARRAY: 4517 case TGT_RANGE: 4518 case TGT_IFACE_POINTER: 4519 case TGT_CTXT_HANDLE: 4520 case TGT_CTXT_HANDLE_POINTER: 4521 print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset); 4522 break; 4523 case TGT_INVALID: 4524 assert(0); 4525 break; 4526 } 4527 else 4528 print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset); 4529 break; 4530 } 4531 case TGT_IFACE_POINTER: 4532 print_phase_function(file, indent, "InterfacePointer", local_var_prefix, phase, var, start_offset); 4533 break; 4534 case TGT_INVALID: 4535 assert(0); 4536 break; 4537 } 4538 fprintf(file, "\n"); 4539 } 4540 4541 void write_remoting_arguments(FILE *file, int indent, const var_t *func, const char *local_var_prefix, 4542 enum pass pass, enum remoting_phase phase) 4543 { 4544 if (phase == PHASE_BUFFERSIZE && pass != PASS_RETURN) 4545 { 4546 unsigned int size = get_function_buffer_size( func, pass ); 4547 print_file(file, indent, "__frame->_StubMsg.BufferLength = %u;\n", size); 4548 } 4549 4550 if (pass == PASS_RETURN) 4551 { 4552 write_remoting_arg( file, indent, func, local_var_prefix, pass, phase, 4553 type_function_get_retval(func->type) ); 4554 } 4555 else 4556 { 4557 const var_t *var; 4558 if (!type_get_function_args(func->type)) 4559 return; 4560 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 4561 write_remoting_arg( file, indent, func, local_var_prefix, pass, phase, var ); 4562 } 4563 } 4564 4565 4566 unsigned int get_size_procformatstring_func(const type_t *iface, const var_t *func) 4567 { 4568 unsigned int offset = 0; 4569 write_procformatstring_func( NULL, 0, iface, func, &offset, 0 ); 4570 return offset; 4571 } 4572 4573 static void get_size_procformatstring_iface(type_t *iface, FILE *file, int indent, unsigned int *size) 4574 { 4575 const statement_t *stmt; 4576 STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) 4577 { 4578 const var_t *func = stmt->u.var; 4579 if (!is_local(func->attrs)) 4580 *size += get_size_procformatstring_func( iface, func ); 4581 } 4582 } 4583 4584 unsigned int get_size_procformatstring(const statement_list_t *stmts, type_pred_t pred) 4585 { 4586 unsigned int size = 1; 4587 for_each_iface(stmts, get_size_procformatstring_iface, pred, NULL, 0, &size); 4588 return size; 4589 } 4590 4591 unsigned int get_size_typeformatstring(const statement_list_t *stmts, type_pred_t pred) 4592 { 4593 set_all_tfswrite(FALSE); 4594 return process_tfs(NULL, stmts, pred); 4595 } 4596 4597 void declare_stub_args( FILE *file, int indent, const var_t *func ) 4598 { 4599 int in_attr, out_attr; 4600 int i = 0; 4601 const var_t *var = type_function_get_retval(func->type); 4602 4603 /* declare return value */ 4604 if (!is_void(var->type)) 4605 { 4606 print_file(file, indent, "%s", ""); 4607 write_type_decl(file, var->type, var->name); 4608 fprintf(file, ";\n"); 4609 } 4610 4611 if (!type_get_function_args(func->type)) 4612 return; 4613 4614 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 4615 { 4616 in_attr = is_attr(var->attrs, ATTR_IN); 4617 out_attr = is_attr(var->attrs, ATTR_OUT); 4618 if (!out_attr && !in_attr) 4619 in_attr = 1; 4620 4621 if (is_context_handle(var->type)) 4622 print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name); 4623 else 4624 { 4625 if (!in_attr && !is_conformant_array(var->type)) 4626 { 4627 type_t *type_to_print; 4628 char name[16]; 4629 print_file(file, indent, "%s", ""); 4630 if (type_get_type(var->type) == TYPE_ARRAY && 4631 !type_array_is_decl_as_ptr(var->type)) 4632 type_to_print = var->type; 4633 else 4634 type_to_print = type_pointer_get_ref(var->type); 4635 sprintf(name, "_W%u", i++); 4636 write_type_decl(file, type_to_print, name); 4637 fprintf(file, ";\n"); 4638 } 4639 4640 print_file(file, indent, "%s", ""); 4641 write_type_decl_left(file, var->type); 4642 fprintf(file, " "); 4643 if (type_get_type(var->type) == TYPE_ARRAY && 4644 !type_array_is_decl_as_ptr(var->type)) { 4645 fprintf(file, "(*%s)", var->name); 4646 } else 4647 fprintf(file, "%s", var->name); 4648 write_type_right(file, var->type, FALSE); 4649 fprintf(file, ";\n"); 4650 4651 if (decl_indirect(var->type)) 4652 print_file(file, indent, "void *_p_%s;\n", var->name); 4653 } 4654 } 4655 } 4656 4657 4658 void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char *local_var_prefix ) 4659 { 4660 int in_attr, out_attr; 4661 int i = 0, sep = 0; 4662 const var_t *var; 4663 type_t *ref; 4664 4665 if (!type_get_function_args(func->type)) 4666 return; 4667 4668 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 4669 { 4670 in_attr = is_attr(var->attrs, ATTR_IN); 4671 out_attr = is_attr(var->attrs, ATTR_OUT); 4672 if (!out_attr && !in_attr) 4673 in_attr = 1; 4674 4675 if (!in_attr) 4676 { 4677 print_file(file, indent, "%s%s", local_var_prefix, var->name); 4678 4679 switch (typegen_detect_type(var->type, var->attrs, TDT_IGNORE_STRINGS)) 4680 { 4681 case TGT_CTXT_HANDLE_POINTER: 4682 fprintf(file, " = NdrContextHandleInitialize(\n"); 4683 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 4684 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", 4685 var->typestring_offset); 4686 break; 4687 case TGT_ARRAY: 4688 if (type_array_has_conformance(var->type)) 4689 { 4690 unsigned int size; 4691 type_t *type; 4692 4693 fprintf(file, " = NdrAllocate(&__frame->_StubMsg, "); 4694 for (type = var->type; 4695 is_array(type) && type_array_has_conformance(type); 4696 type = type_array_get_element(type)) 4697 { 4698 write_expr(file, type_array_get_conformance(type), TRUE, 4699 TRUE, NULL, NULL, local_var_prefix); 4700 fprintf(file, " * "); 4701 } 4702 size = type_memsize(type); 4703 fprintf(file, "%u);\n", size); 4704 4705 print_file(file, indent, "memset(%s%s, 0, ", local_var_prefix, var->name); 4706 for (type = var->type; 4707 is_array(type) && type_array_has_conformance(type); 4708 type = type_array_get_element(type)) 4709 { 4710 write_expr(file, type_array_get_conformance(type), TRUE, 4711 TRUE, NULL, NULL, local_var_prefix); 4712 fprintf(file, " * "); 4713 } 4714 size = type_memsize(type); 4715 fprintf(file, "%u);\n", size); 4716 } 4717 else 4718 fprintf(file, " = &%s_W%u;\n", local_var_prefix, i++); 4719 break; 4720 case TGT_POINTER: 4721 fprintf(file, " = &%s_W%u;\n", local_var_prefix, i); 4722 ref = type_pointer_get_ref(var->type); 4723 switch (typegen_detect_type(ref, var->attrs, TDT_IGNORE_STRINGS)) 4724 { 4725 case TGT_BASIC: 4726 case TGT_ENUM: 4727 case TGT_POINTER: 4728 case TGT_RANGE: 4729 case TGT_IFACE_POINTER: 4730 print_file(file, indent, "%s_W%u = 0;\n", local_var_prefix, i); 4731 break; 4732 case TGT_USER_TYPE: 4733 print_file(file, indent, "memset(&%s_W%u, 0, sizeof(%s_W%u));\n", 4734 local_var_prefix, i, local_var_prefix, i); 4735 break; 4736 case TGT_ARRAY: 4737 if (type_array_is_decl_as_ptr(ref)) 4738 { 4739 print_file(file, indent, "%s_W%u = 0;\n", local_var_prefix, i); 4740 break; 4741 } 4742 ref = type_array_get_element(ref); 4743 /* fall through */ 4744 case TGT_STRUCT: 4745 case TGT_UNION: 4746 if (type_has_pointers(ref)) 4747 print_file(file, indent, "memset(&%s_W%u, 0, sizeof(%s_W%u));\n", 4748 local_var_prefix, i, local_var_prefix, i); 4749 break; 4750 case TGT_CTXT_HANDLE: 4751 case TGT_CTXT_HANDLE_POINTER: 4752 case TGT_INVALID: 4753 case TGT_STRING: 4754 /* not initialised */ 4755 break; 4756 } 4757 i++; 4758 break; 4759 default: 4760 break; 4761 } 4762 4763 sep = 1; 4764 } 4765 } 4766 if (sep) 4767 fprintf(file, "\n"); 4768 } 4769 4770 4771 void write_func_param_struct( FILE *file, const type_t *iface, const type_t *func, 4772 const char *var_decl, int add_retval ) 4773 { 4774 var_t *retval = type_function_get_retval( func ); 4775 const var_list_t *args = type_get_function_args( func ); 4776 const var_t *arg; 4777 int needs_packing; 4778 unsigned int align = 0; 4779 4780 if (args) 4781 LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) 4782 if (!is_array( arg->type )) type_memsize_and_alignment( arg->type, &align ); 4783 4784 needs_packing = (align > pointer_size); 4785 4786 if (needs_packing) print_file( file, 0, "#include <pshpack%u.h>\n", pointer_size ); 4787 print_file(file, 1, "struct _PARAM_STRUCT\n" ); 4788 print_file(file, 1, "{\n" ); 4789 if (is_object( iface )) print_file(file, 2, "%s *This;\n", iface->name ); 4790 4791 if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) 4792 { 4793 print_file(file, 2, "%s", ""); 4794 write_type_left( file, (type_t *)arg->type, NAME_DEFAULT, TRUE ); 4795 if (needs_space_after( arg->type )) fputc( ' ', file ); 4796 if (is_array( arg->type ) && !type_array_is_decl_as_ptr( arg->type )) fputc( '*', file ); 4797 4798 /* FIXME: should check for large args being passed by pointer */ 4799 align = 0; 4800 if (is_array( arg->type ) || is_ptr( arg->type )) align = pointer_size; 4801 else type_memsize_and_alignment( arg->type, &align ); 4802 4803 if (align >= pointer_size) 4804 fprintf( file, "%s;\n", arg->name ); 4805 else 4806 #ifdef __REACTOS__ 4807 fprintf( file, "DECLSPEC_ALIGN(%u) %s;\n", pointer_size, arg->name ); 4808 #else 4809 fprintf( file, "%s DECLSPEC_ALIGN(%u);\n", arg->name, pointer_size ); 4810 #endif 4811 } 4812 if (add_retval && !is_void( retval->type )) 4813 { 4814 print_file(file, 2, "%s", ""); 4815 write_type_decl( file, retval->type, retval->name ); 4816 if (is_array( retval->type ) || is_ptr( retval->type ) || 4817 type_memsize( retval->type ) == pointer_size) 4818 fprintf( file, ";\n" ); 4819 else 4820 fprintf( file, " DECLSPEC_ALIGN(%u);\n", pointer_size ); 4821 } 4822 print_file(file, 1, "} %s;\n", var_decl ); 4823 if (needs_packing) print_file( file, 0, "#include <poppack.h>\n" ); 4824 print_file( file, 0, "\n" ); 4825 } 4826 4827 void write_pointer_checks( FILE *file, int indent, const var_t *func ) 4828 { 4829 const var_list_t *args = type_get_function_args( func->type ); 4830 const var_t *var; 4831 4832 if (!args) return; 4833 4834 LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) 4835 if (cant_be_null( var )) 4836 print_file( file, indent, "if (!%s) RpcRaiseException(RPC_X_NULL_REF_POINTER);\n", var->name ); 4837 } 4838 4839 int write_expr_eval_routines(FILE *file, const char *iface) 4840 { 4841 static const char *var_name = "pS"; 4842 static const char *var_name_expr = "pS->"; 4843 int result = 0; 4844 struct expr_eval_routine *eval; 4845 unsigned short callback_offset = 0; 4846 4847 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry) 4848 { 4849 const char *name = eval->name; 4850 result = 1; 4851 4852 print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n", 4853 eval->iface ? eval->iface->name : iface, name, callback_offset); 4854 print_file(file, 0, "{\n"); 4855 if (type_get_type( eval->cont_type ) == TYPE_FUNCTION) 4856 { 4857 write_func_param_struct( file, eval->iface, eval->cont_type, 4858 "*pS = (struct _PARAM_STRUCT *)pStubMsg->StackTop", FALSE ); 4859 } 4860 else 4861 { 4862 print_file(file, 1, "%s", ""); 4863 write_type_left(file, (type_t *)eval->cont_type, NAME_DEFAULT, TRUE); 4864 fprintf(file, " *%s = (", var_name); 4865 write_type_left(file, (type_t *)eval->cont_type, NAME_DEFAULT, TRUE); 4866 fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff); 4867 } 4868 print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */ 4869 print_file(file, 1, "pStubMsg->MaxCount = (ULONG_PTR)"); 4870 write_expr(file, eval->expr, 1, 1, var_name_expr, eval->cont_type, ""); 4871 fprintf(file, ";\n"); 4872 print_file(file, 0, "}\n\n"); 4873 callback_offset++; 4874 } 4875 return result; 4876 } 4877 4878 void write_expr_eval_routine_list(FILE *file, const char *iface) 4879 { 4880 struct expr_eval_routine *eval; 4881 struct expr_eval_routine *cursor; 4882 unsigned short callback_offset = 0; 4883 4884 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n"); 4885 fprintf(file, "{\n"); 4886 4887 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry) 4888 { 4889 print_file(file, 1, "%s_%sExprEval_%04u,\n", 4890 eval->iface ? eval->iface->name : iface, eval->name, callback_offset); 4891 callback_offset++; 4892 list_remove(&eval->entry); 4893 free(eval->name); 4894 free(eval); 4895 } 4896 4897 fprintf(file, "};\n\n"); 4898 } 4899 4900 void write_user_quad_list(FILE *file) 4901 { 4902 user_type_t *ut; 4903 4904 if (list_empty(&user_type_list)) 4905 return; 4906 4907 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n"); 4908 fprintf(file, "{\n"); 4909 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) 4910 { 4911 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ","; 4912 print_file(file, 1, "{\n"); 4913 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name); 4914 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name); 4915 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name); 4916 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name); 4917 print_file(file, 1, "}%s\n", sep); 4918 } 4919 fprintf(file, "};\n\n"); 4920 } 4921 4922 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list ) 4923 { 4924 const struct str_list_entry_t *endpoint; 4925 const char *p; 4926 4927 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */ 4928 print_file( f, 0, "static const unsigned char * const %s__RpcProtseqEndpoint[][2] =\n{\n", prefix ); 4929 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry ) 4930 { 4931 print_file( f, 1, "{ (const unsigned char *)\"" ); 4932 for (p = endpoint->str; *p && *p != ':'; p++) 4933 { 4934 if (*p == '"' || *p == '\\') fputc( '\\', f ); 4935 fputc( *p, f ); 4936 } 4937 if (!*p) goto error; 4938 if (p[1] != '[') goto error; 4939 4940 fprintf( f, "\", (const unsigned char *)\"" ); 4941 for (p += 2; *p && *p != ']'; p++) 4942 { 4943 if (*p == '"' || *p == '\\') fputc( '\\', f ); 4944 fputc( *p, f ); 4945 } 4946 if (*p != ']') goto error; 4947 fprintf( f, "\" },\n" ); 4948 } 4949 print_file( f, 0, "};\n\n" ); 4950 return; 4951 4952 error: 4953 error("Invalid endpoint syntax '%s'\n", endpoint->str); 4954 } 4955 4956 void write_client_call_routine( FILE *file, const type_t *iface, const var_t *func, 4957 const char *prefix, unsigned int proc_offset ) 4958 { 4959 type_t *rettype = type_function_get_rettype( func->type ); 4960 int has_ret = !is_void( rettype ); 4961 const var_list_t *args = type_get_function_args( func->type ); 4962 const var_t *arg; 4963 int len, needs_params = 0; 4964 4965 /* we need a param structure if we have more than one arg */ 4966 if (pointer_size == 4 && args) needs_params = is_object( iface ) || list_count( args ) > 1; 4967 4968 print_file( file, 0, "{\n"); 4969 if (needs_params) 4970 { 4971 if (has_ret) print_file( file, 1, "%s", "CLIENT_CALL_RETURN _RetVal;\n" ); 4972 write_func_param_struct( file, iface, func->type, "__params", FALSE ); 4973 if (is_object( iface )) print_file( file, 1, "__params.This = This;\n" ); 4974 if (args) 4975 LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) 4976 print_file( file, 1, "__params.%s = %s;\n", arg->name, arg->name ); 4977 } 4978 else if (has_ret) print_file( file, 1, "%s", "CLIENT_CALL_RETURN _RetVal;\n\n" ); 4979 4980 len = fprintf( file, " %s%s( ", 4981 has_ret ? "_RetVal = " : "", 4982 get_stub_mode() == MODE_Oif ? "NdrClientCall2" : "NdrClientCall" ); 4983 fprintf( file, "&%s_StubDesc,", prefix ); 4984 fprintf( file, "\n%*s&__MIDL_ProcFormatString.Format[%u]", len, "", proc_offset ); 4985 if (needs_params) 4986 { 4987 fprintf( file, ",\n%*s&__params", len, "" ); 4988 } 4989 else if (pointer_size == 8) 4990 { 4991 if (is_object( iface )) fprintf( file, ",\n%*sThis", len, "" ); 4992 if (args) 4993 LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) 4994 fprintf( file, ",\n%*s%s", len, "", arg->name ); 4995 } 4996 else 4997 { 4998 if (is_object( iface )) fprintf( file, ",\n%*s&This", len, "" ); 4999 else if (args) 5000 { 5001 arg = LIST_ENTRY( list_head(args), const var_t, entry ); 5002 fprintf( file, ",\n%*s&%s", len, "", arg->name ); 5003 } 5004 } 5005 fprintf( file, " );\n" ); 5006 if (has_ret) 5007 { 5008 print_file( file, 1, "return (" ); 5009 write_type_decl_left(file, rettype); 5010 fprintf( file, ")%s;\n", pointer_size == 8 ? "_RetVal.Simple" : "*(LONG_PTR *)&_RetVal" ); 5011 } 5012 print_file( file, 0, "}\n\n"); 5013 } 5014 5015 void write_exceptions( FILE *file ) 5016 { 5017 fprintf( file, "#ifndef USE_COMPILER_EXCEPTIONS\n"); 5018 fprintf( file, "\n"); 5019 fprintf( file, "#include \"wine/exception.h\"\n"); 5020 fprintf( file, "#undef RpcTryExcept\n"); 5021 fprintf( file, "#undef RpcExcept\n"); 5022 fprintf( file, "#undef RpcEndExcept\n"); 5023 fprintf( file, "#undef RpcTryFinally\n"); 5024 fprintf( file, "#undef RpcFinally\n"); 5025 fprintf( file, "#undef RpcEndFinally\n"); 5026 fprintf( file, "#undef RpcExceptionCode\n"); 5027 fprintf( file, "#undef RpcAbnormalTermination\n"); 5028 fprintf( file, "\n"); 5029 fprintf( file, "struct __exception_frame;\n"); 5030 fprintf( file, "typedef int (*__filter_func)(struct __exception_frame *);\n"); 5031 fprintf( file, "typedef void (*__finally_func)(struct __exception_frame *);\n"); 5032 fprintf( file, "\n"); 5033 fprintf( file, "#define __DECL_EXCEPTION_FRAME \\\n"); 5034 fprintf( file, " EXCEPTION_REGISTRATION_RECORD frame; \\\n"); 5035 fprintf( file, " __filter_func filter; \\\n"); 5036 fprintf( file, " __finally_func finally; \\\n"); 5037 fprintf( file, " sigjmp_buf jmp; \\\n"); 5038 fprintf( file, " DWORD code; \\\n"); 5039 fprintf( file, " unsigned char abnormal_termination; \\\n"); 5040 fprintf( file, " unsigned char filter_level; \\\n"); 5041 fprintf( file, " unsigned char finally_level;\n"); 5042 fprintf( file, "\n"); 5043 fprintf( file, "struct __exception_frame\n{\n"); 5044 fprintf( file, " __DECL_EXCEPTION_FRAME\n"); 5045 fprintf( file, "};\n"); 5046 fprintf( file, "\n"); 5047 fprintf( file, "static inline void __widl_unwind_target(void)\n" ); 5048 fprintf( file, "{\n"); 5049 fprintf( file, " struct __exception_frame *exc_frame = (struct __exception_frame *)__wine_get_frame();\n" ); 5050 fprintf( file, " if (exc_frame->finally_level > exc_frame->filter_level)\n" ); 5051 fprintf( file, " {\n"); 5052 fprintf( file, " exc_frame->abnormal_termination = 1;\n"); 5053 fprintf( file, " exc_frame->finally( exc_frame );\n"); 5054 fprintf( file, " __wine_pop_frame( &exc_frame->frame );\n"); 5055 fprintf( file, " }\n"); 5056 fprintf( file, " exc_frame->filter_level = 0;\n"); 5057 fprintf( file, " siglongjmp( exc_frame->jmp, 1 );\n"); 5058 fprintf( file, "}\n"); 5059 fprintf( file, "\n"); 5060 fprintf( file, "static DWORD __widl_exception_handler( EXCEPTION_RECORD *record,\n"); 5061 fprintf( file, " EXCEPTION_REGISTRATION_RECORD *frame,\n"); 5062 fprintf( file, " CONTEXT *context,\n"); 5063 fprintf( file, " EXCEPTION_REGISTRATION_RECORD **pdispatcher )\n"); 5064 fprintf( file, "{\n"); 5065 fprintf( file, " struct __exception_frame *exc_frame = (struct __exception_frame *)frame;\n"); 5066 fprintf( file, "\n"); 5067 fprintf( file, " if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))\n"); 5068 fprintf( file, " {\n" ); 5069 fprintf( file, " if (exc_frame->finally_level && (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))\n"); 5070 fprintf( file, " {\n" ); 5071 fprintf( file, " exc_frame->abnormal_termination = 1;\n"); 5072 fprintf( file, " exc_frame->finally( exc_frame );\n"); 5073 fprintf( file, " }\n" ); 5074 fprintf( file, " return ExceptionContinueSearch;\n"); 5075 fprintf( file, " }\n" ); 5076 fprintf( file, " exc_frame->code = record->ExceptionCode;\n"); 5077 fprintf( file, " if (exc_frame->filter_level && exc_frame->filter( exc_frame ) == EXCEPTION_EXECUTE_HANDLER)\n" ); 5078 fprintf( file, " __wine_rtl_unwind( frame, record, __widl_unwind_target );\n"); 5079 fprintf( file, " return ExceptionContinueSearch;\n"); 5080 fprintf( file, "}\n"); 5081 fprintf( file, "\n"); 5082 fprintf( file, "#define RpcTryExcept \\\n"); 5083 fprintf( file, " if (!sigsetjmp( __frame->jmp, 0 )) \\\n"); 5084 fprintf( file, " { \\\n"); 5085 fprintf( file, " if (!__frame->finally_level) \\\n" ); 5086 fprintf( file, " __wine_push_frame( &__frame->frame ); \\\n"); 5087 fprintf( file, " __frame->filter_level = __frame->finally_level + 1;\n" ); 5088 fprintf( file, "\n"); 5089 fprintf( file, "#define RpcExcept(expr) \\\n"); 5090 fprintf( file, " if (!__frame->finally_level) \\\n" ); 5091 fprintf( file, " __wine_pop_frame( &__frame->frame ); \\\n"); 5092 fprintf( file, " __frame->filter_level = 0; \\\n" ); 5093 fprintf( file, " } \\\n"); 5094 fprintf( file, " else \\\n"); 5095 fprintf( file, "\n"); 5096 fprintf( file, "#define RpcEndExcept\n"); 5097 fprintf( file, "\n"); 5098 fprintf( file, "#define RpcExceptionCode() (__frame->code)\n"); 5099 fprintf( file, "\n"); 5100 fprintf( file, "#define RpcTryFinally \\\n"); 5101 fprintf( file, " if (!__frame->filter_level) \\\n"); 5102 fprintf( file, " __wine_push_frame( &__frame->frame ); \\\n"); 5103 fprintf( file, " __frame->finally_level = __frame->filter_level + 1;\n"); 5104 fprintf( file, "\n"); 5105 fprintf( file, "#define RpcFinally \\\n"); 5106 fprintf( file, " if (!__frame->filter_level) \\\n"); 5107 fprintf( file, " __wine_pop_frame( &__frame->frame ); \\\n"); 5108 fprintf( file, " __frame->finally_level = 0;\n"); 5109 fprintf( file, "\n"); 5110 fprintf( file, "#define RpcEndFinally\n"); 5111 fprintf( file, "\n"); 5112 fprintf( file, "#define RpcAbnormalTermination() (__frame->abnormal_termination)\n"); 5113 fprintf( file, "\n"); 5114 fprintf( file, "#define RpcExceptionInit(filter_func,finally_func) \\\n"); 5115 fprintf( file, " do { \\\n"); 5116 fprintf( file, " __frame->frame.Handler = __widl_exception_handler; \\\n"); 5117 fprintf( file, " __frame->filter = (__filter_func)(filter_func); \\\n" ); 5118 fprintf( file, " __frame->finally = (__finally_func)(finally_func); \\\n"); 5119 fprintf( file, " __frame->abnormal_termination = 0; \\\n"); 5120 fprintf( file, " __frame->filter_level = 0; \\\n"); 5121 fprintf( file, " __frame->finally_level = 0; \\\n"); 5122 fprintf( file, " } while (0)\n"); 5123 fprintf( file, "\n"); 5124 fprintf( file, "#else /* USE_COMPILER_EXCEPTIONS */\n"); 5125 fprintf( file, "\n"); 5126 fprintf( file, "#define RpcExceptionInit(filter_func,finally_func) \\\n"); 5127 fprintf( file, " do { (void)(filter_func); } while(0)\n"); 5128 fprintf( file, "\n"); 5129 fprintf( file, "#define __DECL_EXCEPTION_FRAME \\\n"); 5130 fprintf( file, " DWORD code;\n"); 5131 fprintf( file, "\n"); 5132 fprintf( file, "#endif /* USE_COMPILER_EXCEPTIONS */\n"); 5133 } 5134