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 if (pointer_type != FC_RP) { 2141 flags |= get_attrv(type->attrs, ATTR_ALLOCATE); 2142 } 2143 } 2144 2145 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s", 2146 pointer_type, 2147 flags, 2148 string_of_type(pointer_type)); 2149 if (file) 2150 { 2151 if (flags & FC_ALLOCED_ON_STACK) 2152 fprintf(file, " [allocated_on_stack]"); 2153 if (flags & FC_POINTER_DEREF) 2154 fprintf(file, " [pointer_deref]"); 2155 if (flags & FC_DONT_FREE) 2156 fprintf(file, " [dont_free]"); 2157 if (flags & FC_ALLOCATE_ALL_NODES) 2158 fprintf(file, " [all_nodes]"); 2159 fprintf(file, " */\n"); 2160 } 2161 2162 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, offset); 2163 *typeformat_offset += 4; 2164 2165 return start_offset; 2166 } 2167 2168 static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs, 2169 const type_t *type, enum type_context context) 2170 { 2171 unsigned char fc; 2172 unsigned char pointer_fc; 2173 const type_t *ref; 2174 int in_attr = is_attr(attrs, ATTR_IN); 2175 int out_attr = is_attr(attrs, ATTR_OUT); 2176 unsigned char flags = FC_SIMPLE_POINTER; 2177 2178 /* for historical reasons, write_simple_pointer also handled string types, 2179 * but no longer does. catch bad uses of the function with this check */ 2180 if (is_string_type(attrs, type)) 2181 error("write_simple_pointer: can't handle type %s which is a string type\n", type->name); 2182 2183 pointer_fc = get_pointer_fc_context(type, attrs, context); 2184 2185 ref = type_pointer_get_ref(type); 2186 if (type_get_type(ref) == TYPE_ENUM) 2187 fc = get_enum_fc(ref); 2188 else 2189 fc = get_basic_fc(ref); 2190 2191 if (!is_interpreted_func(current_iface, current_func)) 2192 { 2193 if (out_attr && !in_attr && pointer_fc == FC_RP) 2194 flags |= FC_ALLOCED_ON_STACK; 2195 } 2196 else if (get_stub_mode() == MODE_Oif) 2197 { 2198 if (context == TYPE_CONTEXT_TOPLEVELPARAM && fc == FC_ENUM16 && pointer_fc == FC_RP) 2199 flags |= FC_ALLOCED_ON_STACK; 2200 } 2201 2202 print_file(file, 2, "0x%02x, 0x%x,\t/* %s %s[simple_pointer] */\n", 2203 pointer_fc, flags, string_of_type(pointer_fc), 2204 flags & FC_ALLOCED_ON_STACK ? "[allocated_on_stack] " : ""); 2205 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc)); 2206 print_file(file, 2, "0x5c,\t/* FC_PAD */\n"); 2207 return 4; 2208 } 2209 2210 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff) 2211 { 2212 print_file(file, 0, "/* %u (", tfsoff); 2213 write_type_decl(file, t, NULL); 2214 print_file(file, 0, ") */\n"); 2215 } 2216 2217 static unsigned int write_pointer_tfs(FILE *file, const attr_list_t *attrs, 2218 type_t *type, unsigned int ref_offset, 2219 enum type_context context, 2220 unsigned int *typestring_offset) 2221 { 2222 unsigned int offset = *typestring_offset; 2223 type_t *ref = type_pointer_get_ref(type); 2224 2225 print_start_tfs_comment(file, type, offset); 2226 update_tfsoff(type, offset, file); 2227 2228 switch (typegen_detect_type(ref, attrs, TDT_ALL_TYPES)) 2229 { 2230 case TGT_BASIC: 2231 case TGT_ENUM: 2232 *typestring_offset += write_simple_pointer(file, attrs, type, context); 2233 break; 2234 default: 2235 if (ref_offset) 2236 write_nonsimple_pointer(file, attrs, type, context, ref_offset, typestring_offset); 2237 break; 2238 } 2239 2240 return offset; 2241 } 2242 2243 static int processed(const type_t *type) 2244 { 2245 return type->typestring_offset && !type->tfswrite; 2246 } 2247 2248 static int user_type_has_variable_size(const type_t *t) 2249 { 2250 if (is_ptr(t)) 2251 return TRUE; 2252 else if (type_get_type(t) == TYPE_STRUCT) 2253 { 2254 switch (get_struct_fc(t)) 2255 { 2256 case FC_PSTRUCT: 2257 case FC_CSTRUCT: 2258 case FC_CPSTRUCT: 2259 case FC_CVSTRUCT: 2260 return TRUE; 2261 } 2262 } 2263 /* Note: Since this only applies to user types, we can't have a conformant 2264 array here, and strings should get filed under pointer in this case. */ 2265 return FALSE; 2266 } 2267 2268 static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff) 2269 { 2270 unsigned int start, absoff, flags; 2271 const char *name = NULL; 2272 type_t *utype = get_user_type(type, &name); 2273 unsigned int usize = type_memsize(utype); 2274 unsigned int ualign = type_buffer_alignment(utype); 2275 unsigned int size = type_memsize(type); 2276 unsigned short funoff = user_type_offset(name); 2277 short reloff; 2278 2279 if (processed(type)) return type->typestring_offset; 2280 2281 guard_rec(type); 2282 2283 if(user_type_has_variable_size(utype)) usize = 0; 2284 2285 if (type_get_type(utype) == TYPE_BASIC || 2286 type_get_type(utype) == TYPE_ENUM) 2287 { 2288 unsigned char fc; 2289 2290 if (type_get_type(utype) == TYPE_ENUM) 2291 fc = get_enum_fc(utype); 2292 else 2293 fc = get_basic_fc(utype); 2294 2295 absoff = *tfsoff; 2296 print_start_tfs_comment(file, utype, absoff); 2297 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); 2298 print_file(file, 2, "0x5c,\t/* FC_PAD */\n"); 2299 *tfsoff += 2; 2300 } 2301 else 2302 { 2303 if (!processed(utype)) 2304 write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff); 2305 absoff = utype->typestring_offset; 2306 } 2307 2308 if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == FC_RP) 2309 flags = 0x40; 2310 else if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == FC_UP) 2311 flags = 0x80; 2312 else 2313 flags = 0; 2314 2315 start = *tfsoff; 2316 update_tfsoff(type, start, file); 2317 print_start_tfs_comment(file, type, start); 2318 print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", FC_USER_MARSHAL); 2319 print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n", 2320 flags | (ualign - 1), ualign - 1, flags); 2321 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff); 2322 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)size, size); 2323 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)usize, usize); 2324 *tfsoff += 8; 2325 reloff = absoff - *tfsoff; 2326 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, absoff); 2327 *tfsoff += 2; 2328 return start; 2329 } 2330 2331 static void write_member_type(FILE *file, const type_t *cont, 2332 int cont_is_complex, const attr_list_t *attrs, 2333 const type_t *type, unsigned int *corroff, 2334 unsigned int *tfsoff) 2335 { 2336 if (is_embedded_complex(type) && !is_conformant_array(type)) 2337 { 2338 unsigned int absoff; 2339 short reloff; 2340 2341 if (type_get_type(type) == TYPE_UNION && is_attr(attrs, ATTR_SWITCHIS)) 2342 { 2343 absoff = *corroff; 2344 *corroff += 8; 2345 } 2346 else 2347 { 2348 absoff = type->typestring_offset; 2349 } 2350 reloff = absoff - (*tfsoff + 2); 2351 2352 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n"); 2353 /* padding is represented using FC_STRUCTPAD* types, so presumably 2354 * this is left over in the format for historical purposes in MIDL 2355 * or rpcrt4. */ 2356 print_file(file, 2, "0x0,\n"); 2357 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", 2358 reloff, reloff, absoff); 2359 *tfsoff += 4; 2360 } 2361 else if (is_ptr(type) || is_conformant_array(type)) 2362 { 2363 unsigned char fc = cont_is_complex ? FC_POINTER : FC_LONG; 2364 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); 2365 *tfsoff += 1; 2366 } 2367 else if (!write_base_type(file, type, tfsoff)) 2368 error("Unsupported member type %d\n", type_get_type(type)); 2369 } 2370 2371 static void write_array_element_type(FILE *file, const attr_list_t *attrs, const type_t *type, 2372 int cont_is_complex, unsigned int *tfsoff) 2373 { 2374 type_t *elem = type_array_get_element(type); 2375 2376 if (!is_embedded_complex(elem) && is_ptr(elem)) 2377 { 2378 type_t *ref = type_pointer_get_ref(elem); 2379 2380 if (processed(ref)) 2381 { 2382 write_nonsimple_pointer(file, NULL, elem, TYPE_CONTEXT_CONTAINER, 2383 ref->typestring_offset, tfsoff); 2384 return; 2385 } 2386 if (cont_is_complex && is_string_type(attrs, elem)) 2387 { 2388 write_string_tfs(file, NULL, elem, TYPE_CONTEXT_CONTAINER, NULL, tfsoff); 2389 return; 2390 } 2391 if (!is_string_type(NULL, elem) && 2392 (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM)) 2393 { 2394 *tfsoff += write_simple_pointer(file, NULL, elem, TYPE_CONTEXT_CONTAINER); 2395 return; 2396 } 2397 } 2398 write_member_type(file, type, cont_is_complex, NULL, elem, NULL, tfsoff); 2399 } 2400 2401 static void write_end(FILE *file, unsigned int *tfsoff) 2402 { 2403 if (*tfsoff % 2 == 0) 2404 { 2405 print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD); 2406 *tfsoff += 1; 2407 } 2408 print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END); 2409 *tfsoff += 1; 2410 } 2411 2412 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff) 2413 { 2414 unsigned int offset = 0; 2415 var_list_t *fs = type_struct_get_fields(type); 2416 var_t *f; 2417 2418 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry) 2419 { 2420 type_t *ft = f->type; 2421 unsigned int size = field_memsize( ft, &offset ); 2422 if (type_get_type(ft) == TYPE_UNION && is_attr(f->attrs, ATTR_SWITCHIS)) 2423 { 2424 short reloff; 2425 unsigned int absoff = ft->typestring_offset; 2426 if (is_attr(ft->attrs, ATTR_SWITCHTYPE)) 2427 absoff += 8; /* we already have a corr descr, skip it */ 2428 reloff = absoff - (*tfsoff + 6); 2429 print_file(file, 0, "/* %d */\n", *tfsoff); 2430 print_file(file, 2, "0x%x,\t/* FC_NON_ENCAPSULATED_UNION */\n", FC_NON_ENCAPSULATED_UNION); 2431 print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", FC_LONG); 2432 write_conf_or_var_desc(file, current_structure, offset, ft, 2433 get_attrp(f->attrs, ATTR_SWITCHIS)); 2434 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", 2435 (unsigned short)reloff, reloff, absoff); 2436 *tfsoff += 8; 2437 } 2438 offset += size; 2439 } 2440 } 2441 2442 static int write_pointer_description_offsets( 2443 FILE *file, const attr_list_t *attrs, type_t *type, 2444 unsigned int *offset_in_memory, unsigned int *offset_in_buffer, 2445 unsigned int *typestring_offset) 2446 { 2447 int written = 0; 2448 2449 if ((is_ptr(type) && type_get_type(type_pointer_get_ref(type)) != TYPE_INTERFACE) || 2450 (is_array(type) && type_array_is_decl_as_ptr(type))) 2451 { 2452 if (offset_in_memory && offset_in_buffer) 2453 { 2454 unsigned int memsize; 2455 2456 /* pointer instance 2457 * 2458 * note that MSDN states that for pointer layouts in structures, 2459 * this is a negative offset from the end of the structure, but 2460 * this statement is incorrect. all offsets are positive */ 2461 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Memory offset = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory); 2462 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Buffer offset = %d */\n", (unsigned short)*offset_in_buffer, *offset_in_buffer); 2463 2464 memsize = type_memsize(type); 2465 *offset_in_memory += memsize; 2466 /* increment these separately as in the case of conformant (varying) 2467 * structures these start at different values */ 2468 *offset_in_buffer += memsize; 2469 } 2470 *typestring_offset += 4; 2471 2472 if (is_ptr(type)) 2473 { 2474 type_t *ref = type_pointer_get_ref(type); 2475 2476 if (is_string_type(attrs, type)) 2477 write_string_tfs(file, attrs, type, TYPE_CONTEXT_CONTAINER, NULL, typestring_offset); 2478 else if (processed(ref)) 2479 write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER, 2480 ref->typestring_offset, typestring_offset); 2481 else if (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM) 2482 *typestring_offset += write_simple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER); 2483 else 2484 error("write_pointer_description_offsets: type format string unknown\n"); 2485 } 2486 else 2487 { 2488 unsigned int offset = type->typestring_offset; 2489 /* skip over the pointer that is written for strings, since a 2490 * pointer has to be written in-place here */ 2491 if (is_string_type(attrs, type)) 2492 offset += 4; 2493 write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER, offset, typestring_offset); 2494 } 2495 2496 return 1; 2497 } 2498 2499 if (is_array(type)) 2500 { 2501 return write_pointer_description_offsets( 2502 file, attrs, type_array_get_element(type), offset_in_memory, 2503 offset_in_buffer, typestring_offset); 2504 } 2505 else if (is_non_complex_struct(type)) 2506 { 2507 /* otherwise search for interesting fields to parse */ 2508 const var_t *v; 2509 LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) 2510 { 2511 if (offset_in_memory && offset_in_buffer) 2512 { 2513 unsigned int padding; 2514 unsigned int align = 0; 2515 type_memsize_and_alignment(v->type, &align); 2516 padding = ROUNDING(*offset_in_memory, align); 2517 *offset_in_memory += padding; 2518 *offset_in_buffer += padding; 2519 } 2520 written += write_pointer_description_offsets( 2521 file, v->attrs, v->type, offset_in_memory, offset_in_buffer, 2522 typestring_offset); 2523 } 2524 } 2525 else 2526 { 2527 if (offset_in_memory && offset_in_buffer) 2528 { 2529 unsigned int memsize = type_memsize(type); 2530 *offset_in_memory += memsize; 2531 /* increment these separately as in the case of conformant (varying) 2532 * structures these start at different values */ 2533 *offset_in_buffer += memsize; 2534 } 2535 } 2536 2537 return written; 2538 } 2539 2540 static int write_no_repeat_pointer_descriptions( 2541 FILE *file, const attr_list_t *attrs, type_t *type, 2542 unsigned int *offset_in_memory, unsigned int *offset_in_buffer, 2543 unsigned int *typestring_offset) 2544 { 2545 int written = 0; 2546 2547 if (is_ptr(type) || 2548 (is_conformant_array(type) && type_array_is_decl_as_ptr(type))) 2549 { 2550 print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", FC_NO_REPEAT); 2551 print_file(file, 2, "0x%02x, /* FC_PAD */\n", FC_PAD); 2552 *typestring_offset += 2; 2553 2554 return write_pointer_description_offsets(file, attrs, type, 2555 offset_in_memory, offset_in_buffer, typestring_offset); 2556 } 2557 2558 if (is_non_complex_struct(type)) 2559 { 2560 const var_t *v; 2561 LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) 2562 { 2563 if (offset_in_memory && offset_in_buffer) 2564 { 2565 unsigned int padding; 2566 unsigned int align = 0; 2567 type_memsize_and_alignment(v->type, &align); 2568 padding = ROUNDING(*offset_in_memory, align); 2569 *offset_in_memory += padding; 2570 *offset_in_buffer += padding; 2571 } 2572 written += write_no_repeat_pointer_descriptions( 2573 file, v->attrs, v->type, 2574 offset_in_memory, offset_in_buffer, typestring_offset); 2575 } 2576 } 2577 else 2578 { 2579 unsigned int memsize = type_memsize(type); 2580 *offset_in_memory += memsize; 2581 /* increment these separately as in the case of conformant (varying) 2582 * structures these start at different values */ 2583 *offset_in_buffer += memsize; 2584 } 2585 2586 return written; 2587 } 2588 2589 /* Note: if file is NULL return value is number of pointers to write, else 2590 * it is the number of type format characters written */ 2591 static int write_fixed_array_pointer_descriptions( 2592 FILE *file, const attr_list_t *attrs, type_t *type, 2593 unsigned int *offset_in_memory, unsigned int *offset_in_buffer, 2594 unsigned int *typestring_offset) 2595 { 2596 int pointer_count = 0; 2597 2598 if (type_get_type(type) == TYPE_ARRAY && 2599 !type_array_has_conformance(type) && !type_array_has_variance(type)) 2600 { 2601 unsigned int temp = 0; 2602 /* unfortunately, this needs to be done in two passes to avoid 2603 * writing out redundant FC_FIXED_REPEAT descriptions */ 2604 pointer_count = write_pointer_description_offsets( 2605 NULL, attrs, type_array_get_element(type), NULL, NULL, &temp); 2606 if (pointer_count > 0) 2607 { 2608 unsigned int increment_size; 2609 unsigned int offset_of_array_pointer_mem = 0; 2610 unsigned int offset_of_array_pointer_buf = 0; 2611 2612 increment_size = type_memsize(type_array_get_element(type)); 2613 2614 print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", FC_FIXED_REPEAT); 2615 print_file(file, 2, "0x%02x, /* FC_PAD */\n", FC_PAD); 2616 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Iterations = %d */\n", (unsigned short)type_array_get_dim(type), type_array_get_dim(type)); 2617 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size); 2618 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory); 2619 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count); 2620 *typestring_offset += 10; 2621 2622 pointer_count = write_pointer_description_offsets( 2623 file, attrs, type, &offset_of_array_pointer_mem, 2624 &offset_of_array_pointer_buf, typestring_offset); 2625 } 2626 } 2627 else if (type_get_type(type) == TYPE_STRUCT) 2628 { 2629 const var_t *v; 2630 LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) 2631 { 2632 if (offset_in_memory && offset_in_buffer) 2633 { 2634 unsigned int padding; 2635 unsigned int align = 0; 2636 type_memsize_and_alignment(v->type, &align); 2637 padding = ROUNDING(*offset_in_memory, align); 2638 *offset_in_memory += padding; 2639 *offset_in_buffer += padding; 2640 } 2641 pointer_count += write_fixed_array_pointer_descriptions( 2642 file, v->attrs, v->type, offset_in_memory, offset_in_buffer, 2643 typestring_offset); 2644 } 2645 } 2646 else 2647 { 2648 if (offset_in_memory && offset_in_buffer) 2649 { 2650 unsigned int memsize; 2651 memsize = type_memsize(type); 2652 *offset_in_memory += memsize; 2653 /* increment these separately as in the case of conformant (varying) 2654 * structures these start at different values */ 2655 *offset_in_buffer += memsize; 2656 } 2657 } 2658 2659 return pointer_count; 2660 } 2661 2662 /* Note: if file is NULL return value is number of pointers to write, else 2663 * it is the number of type format characters written */ 2664 static int write_conformant_array_pointer_descriptions( 2665 FILE *file, const attr_list_t *attrs, type_t *type, 2666 unsigned int offset_in_memory, unsigned int *typestring_offset) 2667 { 2668 int pointer_count = 0; 2669 2670 if (is_conformant_array(type) && !type_array_has_variance(type)) 2671 { 2672 unsigned int temp = 0; 2673 /* unfortunately, this needs to be done in two passes to avoid 2674 * writing out redundant FC_VARIABLE_REPEAT descriptions */ 2675 pointer_count = write_pointer_description_offsets( 2676 NULL, attrs, type_array_get_element(type), NULL, NULL, &temp); 2677 if (pointer_count > 0) 2678 { 2679 unsigned int increment_size; 2680 unsigned int offset_of_array_pointer_mem = offset_in_memory; 2681 unsigned int offset_of_array_pointer_buf = offset_in_memory; 2682 2683 increment_size = type_memsize(type_array_get_element(type)); 2684 2685 if (increment_size > USHRT_MAX) 2686 error("array size of %u bytes is too large\n", increment_size); 2687 2688 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", FC_VARIABLE_REPEAT); 2689 print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", FC_FIXED_OFFSET); 2690 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size); 2691 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)offset_in_memory, offset_in_memory); 2692 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count); 2693 *typestring_offset += 8; 2694 2695 pointer_count = write_pointer_description_offsets( 2696 file, attrs, type_array_get_element(type), 2697 &offset_of_array_pointer_mem, &offset_of_array_pointer_buf, 2698 typestring_offset); 2699 } 2700 } 2701 2702 return pointer_count; 2703 } 2704 2705 /* Note: if file is NULL return value is number of pointers to write, else 2706 * it is the number of type format characters written */ 2707 static int write_varying_array_pointer_descriptions( 2708 FILE *file, const attr_list_t *attrs, type_t *type, 2709 unsigned int *offset_in_memory, unsigned int *offset_in_buffer, 2710 unsigned int *typestring_offset) 2711 { 2712 int pointer_count = 0; 2713 2714 if (is_array(type) && type_array_has_variance(type)) 2715 { 2716 unsigned int temp = 0; 2717 /* unfortunately, this needs to be done in two passes to avoid 2718 * writing out redundant FC_VARIABLE_REPEAT descriptions */ 2719 pointer_count = write_pointer_description_offsets( 2720 NULL, attrs, type_array_get_element(type), NULL, NULL, &temp); 2721 if (pointer_count > 0) 2722 { 2723 unsigned int increment_size; 2724 2725 increment_size = type_memsize(type_array_get_element(type)); 2726 2727 if (increment_size > USHRT_MAX) 2728 error("array size of %u bytes is too large\n", increment_size); 2729 2730 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", FC_VARIABLE_REPEAT); 2731 print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", FC_VARIABLE_OFFSET); 2732 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size); 2733 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory); 2734 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count); 2735 *typestring_offset += 8; 2736 2737 pointer_count = write_pointer_description_offsets( 2738 file, attrs, type_array_get_element(type), offset_in_memory, 2739 offset_in_buffer, typestring_offset); 2740 } 2741 } 2742 else if (type_get_type(type) == TYPE_STRUCT) 2743 { 2744 const var_t *v; 2745 LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) 2746 { 2747 if (offset_in_memory && offset_in_buffer) 2748 { 2749 unsigned int align = 0, padding; 2750 2751 if (is_array(v->type) && type_array_has_variance(v->type)) 2752 { 2753 *offset_in_buffer = ROUND_SIZE(*offset_in_buffer, 4); 2754 /* skip over variance and offset in buffer */ 2755 *offset_in_buffer += 8; 2756 } 2757 2758 type_memsize_and_alignment(v->type, &align); 2759 padding = ROUNDING(*offset_in_memory, align); 2760 *offset_in_memory += padding; 2761 *offset_in_buffer += padding; 2762 } 2763 pointer_count += write_varying_array_pointer_descriptions( 2764 file, v->attrs, v->type, offset_in_memory, offset_in_buffer, 2765 typestring_offset); 2766 } 2767 } 2768 else 2769 { 2770 if (offset_in_memory && offset_in_buffer) 2771 { 2772 unsigned int memsize = type_memsize(type); 2773 *offset_in_memory += memsize; 2774 /* increment these separately as in the case of conformant (varying) 2775 * structures these start at different values */ 2776 *offset_in_buffer += memsize; 2777 } 2778 } 2779 2780 return pointer_count; 2781 } 2782 2783 static void write_pointer_description(FILE *file, const attr_list_t *attrs, type_t *type, 2784 unsigned int *typestring_offset) 2785 { 2786 unsigned int offset_in_buffer; 2787 unsigned int offset_in_memory; 2788 2789 /* pass 1: search for single instance of a pointer (i.e. don't descend 2790 * into arrays) */ 2791 if (!is_array(type)) 2792 { 2793 offset_in_memory = 0; 2794 offset_in_buffer = 0; 2795 write_no_repeat_pointer_descriptions( 2796 file, NULL, type, 2797 &offset_in_memory, &offset_in_buffer, typestring_offset); 2798 } 2799 2800 /* pass 2: search for pointers in fixed arrays */ 2801 offset_in_memory = 0; 2802 offset_in_buffer = 0; 2803 write_fixed_array_pointer_descriptions( 2804 file, NULL, type, 2805 &offset_in_memory, &offset_in_buffer, typestring_offset); 2806 2807 /* pass 3: search for pointers in conformant only arrays (but don't descend 2808 * into conformant varying or varying arrays) */ 2809 if (is_conformant_array(type) && 2810 (type_array_is_decl_as_ptr(type) || !current_structure)) 2811 write_conformant_array_pointer_descriptions( 2812 file, attrs, type, 0, typestring_offset); 2813 else if (type_get_type(type) == TYPE_STRUCT && 2814 get_struct_fc(type) == FC_CPSTRUCT) 2815 { 2816 type_t *carray = find_array_or_string_in_struct(type)->type; 2817 write_conformant_array_pointer_descriptions( file, NULL, carray, 2818 type_memsize(type), typestring_offset); 2819 } 2820 2821 /* pass 4: search for pointers in varying arrays */ 2822 offset_in_memory = 0; 2823 offset_in_buffer = 0; 2824 write_varying_array_pointer_descriptions( 2825 file, NULL, type, 2826 &offset_in_memory, &offset_in_buffer, typestring_offset); 2827 } 2828 2829 static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, 2830 type_t *type, enum type_context context, 2831 const char *name, unsigned int *typestring_offset) 2832 { 2833 unsigned int start_offset; 2834 unsigned char rtype; 2835 type_t *elem_type; 2836 int is_processed = processed(type); 2837 2838 start_offset = *typestring_offset; 2839 2840 if (is_declptr(type)) 2841 { 2842 unsigned char flag = is_conformant_array(type) ? 0 : FC_SIMPLE_POINTER; 2843 int pointer_type = get_pointer_fc_context(type, attrs, context); 2844 if (!pointer_type) 2845 pointer_type = FC_RP; 2846 print_start_tfs_comment(file, type, *typestring_offset); 2847 print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n", 2848 pointer_type, flag, string_of_type(pointer_type), 2849 flag ? " [simple_pointer]" : ""); 2850 *typestring_offset += 2; 2851 if (!flag) 2852 { 2853 print_file(file, 2, "NdrFcShort(0x2),\n"); 2854 *typestring_offset += 2; 2855 } 2856 is_processed = FALSE; 2857 } 2858 2859 if (is_array(type)) 2860 elem_type = type_array_get_element(type); 2861 else 2862 elem_type = type_pointer_get_ref(type); 2863 2864 if (type_get_type(elem_type) == TYPE_POINTER && is_array(type)) 2865 return write_array_tfs(file, attrs, type, name, typestring_offset); 2866 2867 if (type_get_type(elem_type) != TYPE_BASIC) 2868 { 2869 error("write_string_tfs: Unimplemented for non-basic type %s\n", name); 2870 return start_offset; 2871 } 2872 2873 rtype = get_basic_fc(elem_type); 2874 if ((rtype != FC_BYTE) && (rtype != FC_CHAR) && (rtype != FC_WCHAR)) 2875 { 2876 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name); 2877 return start_offset; 2878 } 2879 2880 if (type_get_type(type) == TYPE_ARRAY && !type_array_has_conformance(type)) 2881 { 2882 unsigned int dim = type_array_get_dim(type); 2883 2884 if (is_processed) return start_offset; 2885 2886 /* FIXME: multi-dimensional array */ 2887 if (0xffffu < dim) 2888 error("array size for parameter %s exceeds %u bytes by %u bytes\n", 2889 name, 0xffffu, dim - 0xffffu); 2890 2891 if (rtype == FC_WCHAR) 2892 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset); 2893 else 2894 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset); 2895 print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD); 2896 *typestring_offset += 2; 2897 2898 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)dim, dim); 2899 *typestring_offset += 2; 2900 2901 update_tfsoff(type, start_offset, file); 2902 return start_offset; 2903 } 2904 else if (is_conformant_array(type)) 2905 { 2906 if (rtype == FC_WCHAR) 2907 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset); 2908 else 2909 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset); 2910 print_file(file, 2, "0x%x,\t/* FC_STRING_SIZED */\n", FC_STRING_SIZED); 2911 *typestring_offset += 2; 2912 2913 *typestring_offset += write_conf_or_var_desc( 2914 file, current_structure, 2915 (!type_array_is_decl_as_ptr(type) && current_structure 2916 ? type_memsize(current_structure) 2917 : 0), 2918 type, type_array_get_conformance(type)); 2919 2920 update_tfsoff(type, start_offset, file); 2921 return start_offset; 2922 } 2923 else 2924 { 2925 if (is_processed) return start_offset; 2926 2927 if (rtype == FC_WCHAR) 2928 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset); 2929 else 2930 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset); 2931 print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD); 2932 *typestring_offset += 2; 2933 2934 update_tfsoff(type, start_offset, file); 2935 return start_offset; 2936 } 2937 } 2938 2939 static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type, 2940 const char *name, unsigned int *typestring_offset) 2941 { 2942 const expr_t *length_is = type_array_get_variance(type); 2943 const expr_t *size_is = type_array_get_conformance(type); 2944 unsigned int align; 2945 unsigned int size; 2946 unsigned int start_offset; 2947 unsigned char fc; 2948 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE); 2949 unsigned int baseoff 2950 = !type_array_is_decl_as_ptr(type) && current_structure 2951 ? type_memsize(current_structure) 2952 : 0; 2953 2954 if (!pointer_type) 2955 pointer_type = FC_RP; 2956 2957 if (!is_string_type(attrs, type_array_get_element(type))) 2958 write_embedded_types(file, attrs, type_array_get_element(type), name, FALSE, typestring_offset); 2959 2960 size = type_memsize(is_conformant_array(type) ? type_array_get_element(type) : type); 2961 align = type_buffer_alignment(is_conformant_array(type) ? type_array_get_element(type) : type); 2962 fc = get_array_fc(type); 2963 2964 start_offset = *typestring_offset; 2965 update_tfsoff(type, start_offset, file); 2966 print_start_tfs_comment(file, type, start_offset); 2967 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc)); 2968 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1); 2969 *typestring_offset += 2; 2970 2971 align = 0; 2972 if (fc != FC_BOGUS_ARRAY) 2973 { 2974 if (fc == FC_LGFARRAY || fc == FC_LGVARRAY) 2975 { 2976 print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", size, size); 2977 *typestring_offset += 4; 2978 } 2979 else 2980 { 2981 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)size, size); 2982 *typestring_offset += 2; 2983 } 2984 2985 if (is_conformant_array(type)) 2986 *typestring_offset 2987 += write_conf_or_var_desc(file, current_structure, baseoff, 2988 type, size_is); 2989 2990 if (fc == FC_SMVARRAY || fc == FC_LGVARRAY) 2991 { 2992 unsigned int elsize = type_memsize(type_array_get_element(type)); 2993 unsigned int dim = type_array_get_dim(type); 2994 2995 if (fc == FC_LGVARRAY) 2996 { 2997 print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", dim, dim); 2998 *typestring_offset += 4; 2999 } 3000 else 3001 { 3002 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)dim, dim); 3003 *typestring_offset += 2; 3004 } 3005 3006 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)elsize, elsize); 3007 *typestring_offset += 2; 3008 } 3009 3010 if (length_is) 3011 *typestring_offset 3012 += write_conf_or_var_desc(file, current_structure, baseoff, 3013 type, length_is); 3014 3015 if (type_has_pointers(type_array_get_element(type)) && 3016 (type_array_is_decl_as_ptr(type) || !current_structure)) 3017 { 3018 print_file(file, 2, "0x%x,\t/* FC_PP */\n", FC_PP); 3019 print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD); 3020 *typestring_offset += 2; 3021 write_pointer_description(file, is_string_type(attrs, type) ? attrs : NULL, type, typestring_offset); 3022 print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END); 3023 *typestring_offset += 1; 3024 } 3025 3026 write_array_element_type(file, is_string_type(attrs, type) ? attrs : NULL, type, FALSE, typestring_offset); 3027 write_end(file, typestring_offset); 3028 } 3029 else 3030 { 3031 unsigned int dim = size_is ? 0 : type_array_get_dim(type); 3032 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)dim, dim); 3033 *typestring_offset += 2; 3034 *typestring_offset 3035 += write_conf_or_var_desc(file, current_structure, baseoff, 3036 type, size_is); 3037 *typestring_offset 3038 += write_conf_or_var_desc(file, current_structure, baseoff, 3039 type, length_is); 3040 3041 write_array_element_type(file, is_string_type(attrs, type) ? attrs : NULL, type, TRUE, typestring_offset); 3042 write_end(file, typestring_offset); 3043 } 3044 3045 return start_offset; 3046 } 3047 3048 static const var_t *find_array_or_string_in_struct(const type_t *type) 3049 { 3050 const var_list_t *fields = type_struct_get_fields(type); 3051 const var_t *last_field; 3052 const type_t *ft; 3053 3054 if (!fields || list_empty(fields)) 3055 return NULL; 3056 3057 last_field = LIST_ENTRY( list_tail(fields), const var_t, entry ); 3058 ft = last_field->type; 3059 3060 if (is_conformant_array(ft) && !type_array_is_decl_as_ptr(ft)) 3061 return last_field; 3062 3063 if (type_get_type(ft) == TYPE_STRUCT) 3064 return find_array_or_string_in_struct(ft); 3065 else 3066 return NULL; 3067 } 3068 3069 static void write_struct_members(FILE *file, const type_t *type, 3070 int is_complex, unsigned int *corroff, 3071 unsigned int *typestring_offset) 3072 { 3073 const var_t *field; 3074 unsigned short offset = 0; 3075 unsigned int salign = 1; 3076 int padding; 3077 var_list_t *fields = type_struct_get_fields(type); 3078 3079 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) 3080 { 3081 type_t *ft = field->type; 3082 unsigned int align = 0; 3083 unsigned int size = type_memsize_and_alignment(ft, &align); 3084 align = clamp_align(align); 3085 if (salign < align) salign = align; 3086 3087 if (!is_conformant_array(ft) || type_array_is_decl_as_ptr(ft)) 3088 { 3089 if ((align - 1) & offset) 3090 { 3091 unsigned char fc = 0; 3092 switch (align) 3093 { 3094 case 2: 3095 fc = FC_ALIGNM2; 3096 break; 3097 case 4: 3098 fc = FC_ALIGNM4; 3099 break; 3100 case 8: 3101 fc = FC_ALIGNM8; 3102 break; 3103 default: 3104 error("write_struct_members: cannot align type %d\n", type_get_type(ft)); 3105 } 3106 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); 3107 offset = ROUND_SIZE(offset, align); 3108 *typestring_offset += 1; 3109 } 3110 write_member_type(file, type, is_complex, field->attrs, field->type, corroff, 3111 typestring_offset); 3112 offset += size; 3113 } 3114 } 3115 3116 padding = ROUNDING(offset, salign); 3117 if (padding) 3118 { 3119 print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n", 3120 FC_STRUCTPAD1 + padding - 1, 3121 padding); 3122 *typestring_offset += 1; 3123 } 3124 3125 write_end(file, typestring_offset); 3126 } 3127 3128 static unsigned int write_struct_tfs(FILE *file, type_t *type, 3129 const char *name, unsigned int *tfsoff) 3130 { 3131 const type_t *save_current_structure = current_structure; 3132 unsigned int total_size; 3133 const var_t *array; 3134 unsigned int start_offset; 3135 unsigned int align; 3136 unsigned int corroff; 3137 var_t *f; 3138 unsigned char fc = get_struct_fc(type); 3139 var_list_t *fields = type_struct_get_fields(type); 3140 3141 if (processed(type)) return type->typestring_offset; 3142 3143 guard_rec(type); 3144 current_structure = type; 3145 3146 total_size = type_memsize(type); 3147 align = type_buffer_alignment(type); 3148 if (total_size > USHRT_MAX) 3149 error("structure size for %s exceeds %d bytes by %d bytes\n", 3150 name, USHRT_MAX, total_size - USHRT_MAX); 3151 3152 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) 3153 write_embedded_types(file, f->attrs, f->type, f->name, FALSE, tfsoff); 3154 3155 array = find_array_or_string_in_struct(type); 3156 if (array && !processed(array->type)) 3157 { 3158 if(is_string_type(array->attrs, array->type)) 3159 write_string_tfs(file, array->attrs, array->type, TYPE_CONTEXT_CONTAINER, array->name, tfsoff); 3160 else 3161 write_array_tfs(file, array->attrs, array->type, array->name, tfsoff); 3162 } 3163 3164 corroff = *tfsoff; 3165 write_descriptors(file, type, tfsoff); 3166 3167 start_offset = *tfsoff; 3168 update_tfsoff(type, start_offset, file); 3169 print_start_tfs_comment(file, type, start_offset); 3170 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); 3171 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1); 3172 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)total_size, total_size); 3173 *tfsoff += 4; 3174 3175 if (array) 3176 { 3177 unsigned int absoff = array->type->typestring_offset; 3178 short reloff = absoff - *tfsoff; 3179 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", 3180 reloff, reloff, absoff); 3181 *tfsoff += 2; 3182 } 3183 else if (fc == FC_BOGUS_STRUCT) 3184 { 3185 print_file(file, 2, "NdrFcShort(0x0),\n"); 3186 *tfsoff += 2; 3187 } 3188 3189 if (fc == FC_BOGUS_STRUCT) 3190 { 3191 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as 3192 nothing is written to file yet. On the actual writing pass, 3193 this will have been updated. */ 3194 unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff; 3195 int reloff = absoff - *tfsoff; 3196 assert( reloff >= 0 ); 3197 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %d (%u) */\n", 3198 (unsigned short)reloff, reloff, absoff); 3199 *tfsoff += 2; 3200 } 3201 else if ((fc == FC_PSTRUCT) || 3202 (fc == FC_CPSTRUCT) || 3203 (fc == FC_CVSTRUCT && type_has_pointers(type))) 3204 { 3205 print_file(file, 2, "0x%x,\t/* FC_PP */\n", FC_PP); 3206 print_file(file, 2, "0x%x,\t/* FC_PAD */\n", FC_PAD); 3207 *tfsoff += 2; 3208 write_pointer_description(file, NULL, type, tfsoff); 3209 print_file(file, 2, "0x%x,\t/* FC_END */\n", FC_END); 3210 *tfsoff += 1; 3211 } 3212 3213 write_struct_members(file, type, fc == FC_BOGUS_STRUCT, &corroff, 3214 tfsoff); 3215 3216 if (fc == FC_BOGUS_STRUCT) 3217 { 3218 const var_t *f; 3219 3220 type->ptrdesc = *tfsoff; 3221 if (fields) LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry) 3222 { 3223 type_t *ft = f->type; 3224 switch (typegen_detect_type(ft, f->attrs, TDT_IGNORE_STRINGS)) 3225 { 3226 case TGT_POINTER: 3227 if (is_string_type(f->attrs, ft)) 3228 write_string_tfs(file, f->attrs, ft, TYPE_CONTEXT_CONTAINER, f->name, tfsoff); 3229 else 3230 write_pointer_tfs(file, f->attrs, ft, 3231 type_pointer_get_ref(ft)->typestring_offset, 3232 TYPE_CONTEXT_CONTAINER, tfsoff); 3233 break; 3234 case TGT_ARRAY: 3235 if (type_array_is_decl_as_ptr(ft)) 3236 { 3237 unsigned int offset; 3238 3239 print_file(file, 0, "/* %d */\n", *tfsoff); 3240 3241 offset = ft->typestring_offset; 3242 /* skip over the pointer that is written for strings, since a 3243 * pointer has to be written in-place here */ 3244 if (is_string_type(f->attrs, ft)) 3245 offset += 4; 3246 write_nonsimple_pointer(file, f->attrs, ft, TYPE_CONTEXT_CONTAINER, offset, tfsoff); 3247 } 3248 break; 3249 default: 3250 break; 3251 } 3252 } 3253 if (type->ptrdesc == *tfsoff) 3254 type->ptrdesc = 0; 3255 } 3256 3257 current_structure = save_current_structure; 3258 return start_offset; 3259 } 3260 3261 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff) 3262 { 3263 if (t == NULL) 3264 { 3265 print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n"); 3266 } 3267 else 3268 { 3269 if (type_get_type(t) == TYPE_BASIC || type_get_type(t) == TYPE_ENUM) 3270 { 3271 unsigned char fc; 3272 if (type_get_type(t) == TYPE_BASIC) 3273 fc = get_basic_fc(t); 3274 else 3275 fc = get_enum_fc(t); 3276 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n", 3277 fc, string_of_type(fc)); 3278 } 3279 else if (t->typestring_offset) 3280 { 3281 short reloff = t->typestring_offset - *tfsoff; 3282 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %d (%d) */\n", 3283 reloff, reloff, t->typestring_offset); 3284 } 3285 else 3286 error("write_branch_type: type unimplemented %d\n", type_get_type(t)); 3287 } 3288 3289 *tfsoff += 2; 3290 } 3291 3292 static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs, 3293 type_t *type, unsigned int *tfsoff) 3294 { 3295 unsigned int start_offset; 3296 unsigned int size; 3297 var_list_t *fields; 3298 unsigned int nbranch = 0; 3299 type_t *deftype = NULL; 3300 short nodeftype = 0xffff; 3301 unsigned int dummy; 3302 var_t *f; 3303 3304 if (processed(type) && 3305 (type_get_type(type) == TYPE_ENCAPSULATED_UNION || !is_attr(type->attrs, ATTR_SWITCHTYPE))) 3306 return type->typestring_offset; 3307 3308 guard_rec(type); 3309 3310 fields = type_union_get_cases(type); 3311 3312 size = union_memsize(fields, &dummy); 3313 3314 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) 3315 { 3316 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE); 3317 if (cases) 3318 nbranch += list_count(cases); 3319 if (f->type) 3320 write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff); 3321 } 3322 3323 start_offset = *tfsoff; 3324 update_tfsoff(type, start_offset, file); 3325 print_start_tfs_comment(file, type, start_offset); 3326 if (type_get_type(type) == TYPE_ENCAPSULATED_UNION) 3327 { 3328 const var_t *sv = type_union_get_switch_value(type); 3329 const type_t *st = sv->type; 3330 unsigned int align = 0; 3331 unsigned char fc; 3332 3333 if (type_get_type(st) == TYPE_BASIC) 3334 { 3335 fc = get_basic_fc(st); 3336 switch (fc) 3337 { 3338 case FC_CHAR: 3339 case FC_SMALL: 3340 case FC_BYTE: 3341 case FC_USMALL: 3342 case FC_WCHAR: 3343 case FC_SHORT: 3344 case FC_USHORT: 3345 case FC_LONG: 3346 case FC_ULONG: 3347 break; 3348 default: 3349 fc = 0; 3350 error("union switch type must be an integer, char, or enum\n"); 3351 } 3352 } 3353 else if (type_get_type(st) == TYPE_ENUM) 3354 fc = get_enum_fc(st); 3355 else 3356 error("union switch type must be an integer, char, or enum\n"); 3357 3358 type_memsize_and_alignment(st, &align); 3359 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) 3360 { 3361 if (f->type) 3362 type_memsize_and_alignment(f->type, &align); 3363 } 3364 3365 print_file(file, 2, "0x%x,\t/* FC_ENCAPSULATED_UNION */\n", FC_ENCAPSULATED_UNION); 3366 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n", 3367 (align << 4) | fc, string_of_type(fc)); 3368 *tfsoff += 2; 3369 } 3370 else if (is_attr(type->attrs, ATTR_SWITCHTYPE)) 3371 { 3372 const expr_t *switch_is = get_attrp(attrs, ATTR_SWITCHIS); 3373 const type_t *st = get_attrp(type->attrs, ATTR_SWITCHTYPE); 3374 unsigned char fc; 3375 3376 if (type_get_type(st) == TYPE_BASIC) 3377 { 3378 fc = get_basic_fc(st); 3379 switch (fc) 3380 { 3381 case FC_CHAR: 3382 case FC_SMALL: 3383 case FC_USMALL: 3384 case FC_SHORT: 3385 case FC_USHORT: 3386 case FC_LONG: 3387 case FC_ULONG: 3388 case FC_ENUM16: 3389 case FC_ENUM32: 3390 break; 3391 default: 3392 fc = 0; 3393 error("union switch type must be an integer, char, or enum\n"); 3394 } 3395 } 3396 else if (type_get_type(st) == TYPE_ENUM) 3397 fc = get_enum_fc(st); 3398 else 3399 error("union switch type must be an integer, char, or enum\n"); 3400 3401 print_file(file, 2, "0x%x,\t/* FC_NON_ENCAPSULATED_UNION */\n", FC_NON_ENCAPSULATED_UNION); 3402 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n", 3403 fc, string_of_type(fc)); 3404 *tfsoff += 2; 3405 *tfsoff += write_conf_or_var_desc(file, current_structure, 0, st, switch_is ); 3406 print_file(file, 2, "NdrFcShort(0x2),\t/* Offset= 2 (%u) */\n", *tfsoff + 2); 3407 *tfsoff += 2; 3408 print_file(file, 0, "/* %u */\n", *tfsoff); 3409 } 3410 3411 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)size, size); 3412 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)nbranch, nbranch); 3413 *tfsoff += 4; 3414 3415 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) 3416 { 3417 type_t *ft = f->type; 3418 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE); 3419 int deflt = is_attr(f->attrs, ATTR_DEFAULT); 3420 expr_t *c; 3421 3422 if (cases == NULL && !deflt) 3423 error("union field %s with neither case nor default attribute\n", f->name); 3424 3425 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry) 3426 { 3427 /* MIDL doesn't check for duplicate cases, even though that seems 3428 like a reasonable thing to do, it just dumps them to the TFS 3429 like we're going to do here. */ 3430 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval); 3431 *tfsoff += 4; 3432 write_branch_type(file, ft, tfsoff); 3433 } 3434 3435 /* MIDL allows multiple default branches, even though that seems 3436 illogical, it just chooses the last one, which is what we will 3437 do. */ 3438 if (deflt) 3439 { 3440 deftype = ft; 3441 nodeftype = 0; 3442 } 3443 } 3444 3445 if (deftype) 3446 { 3447 write_branch_type(file, deftype, tfsoff); 3448 } 3449 else 3450 { 3451 print_file(file, 2, "NdrFcShort(0x%hx),\n", nodeftype); 3452 *tfsoff += 2; 3453 } 3454 3455 return start_offset; 3456 } 3457 3458 static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type, 3459 unsigned int *typeformat_offset) 3460 { 3461 unsigned int i; 3462 unsigned int start_offset = *typeformat_offset; 3463 expr_t *iid = get_attrp(attrs, ATTR_IIDIS); 3464 3465 if (!iid && processed(type)) return type->typestring_offset; 3466 3467 print_start_tfs_comment(file, type, start_offset); 3468 update_tfsoff(type, start_offset, file); 3469 3470 if (iid) 3471 { 3472 print_file(file, 2, "0x2f, /* FC_IP */\n"); 3473 print_file(file, 2, "0x5c, /* FC_PAD */\n"); 3474 *typeformat_offset 3475 += write_conf_or_var_desc(file, current_structure, 0, type, iid) + 2; 3476 } 3477 else 3478 { 3479 const type_t *base = is_ptr(type) ? type_pointer_get_ref(type) : type; 3480 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID); 3481 3482 if (! uuid) 3483 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name); 3484 3485 print_file(file, 2, "0x2f,\t/* FC_IP */\n"); 3486 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n"); 3487 print_file(file, 2, "NdrFcLong(0x%08x),\n", uuid->Data1); 3488 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2); 3489 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3); 3490 for (i = 0; i < 8; ++i) 3491 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]); 3492 3493 if (file) 3494 fprintf(file, "\n"); 3495 3496 *typeformat_offset += 18; 3497 } 3498 return start_offset; 3499 } 3500 3501 static unsigned int write_contexthandle_tfs(FILE *file, 3502 const attr_list_t *attrs, 3503 type_t *type, 3504 int toplevel_param, 3505 unsigned int *typeformat_offset) 3506 { 3507 unsigned int start_offset = *typeformat_offset; 3508 unsigned char flags = get_contexthandle_flags( current_iface, attrs, type ); 3509 3510 print_start_tfs_comment(file, type, start_offset); 3511 3512 if (flags & 0x80) /* via ptr */ 3513 { 3514 int pointer_type = get_pointer_fc( type, attrs, toplevel_param ); 3515 if (!pointer_type) pointer_type = FC_RP; 3516 *typeformat_offset += 4; 3517 print_file(file, 2,"0x%x, 0x0,\t/* %s */\n", pointer_type, string_of_type(pointer_type) ); 3518 print_file(file, 2, "NdrFcShort(0x2),\t /* Offset= 2 (%u) */\n", *typeformat_offset); 3519 print_file(file, 0, "/* %2u */\n", *typeformat_offset); 3520 } 3521 3522 print_file(file, 2, "0x%02x,\t/* FC_BIND_CONTEXT */\n", FC_BIND_CONTEXT); 3523 print_file(file, 2, "0x%x,\t/* Context flags: ", flags); 3524 /* return and can't be null values overlap */ 3525 if (((flags & 0x21) != 0x21) && (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL)) 3526 print_file(file, 0, "can't be null, "); 3527 if (flags & NDR_CONTEXT_HANDLE_SERIALIZE) 3528 print_file(file, 0, "serialize, "); 3529 if (flags & NDR_CONTEXT_HANDLE_NOSERIALIZE) 3530 print_file(file, 0, "no serialize, "); 3531 if (flags & NDR_STRICT_CONTEXT_HANDLE) 3532 print_file(file, 0, "strict, "); 3533 if ((flags & 0x21) == 0x20) 3534 print_file(file, 0, "out, "); 3535 if ((flags & 0x21) == 0x21) 3536 print_file(file, 0, "return, "); 3537 if (flags & 0x40) 3538 print_file(file, 0, "in, "); 3539 if (flags & 0x80) 3540 print_file(file, 0, "via ptr, "); 3541 print_file(file, 0, "*/\n"); 3542 print_file(file, 2, "0x%x,\t/* rundown routine */\n", get_context_handle_offset( type )); 3543 print_file(file, 2, "0, /* FIXME: param num */\n"); 3544 *typeformat_offset += 4; 3545 3546 update_tfsoff( type, start_offset, file ); 3547 return start_offset; 3548 } 3549 3550 static unsigned int write_range_tfs(FILE *file, const attr_list_t *attrs, 3551 type_t *type, expr_list_t *range_list, 3552 unsigned int *typeformat_offset) 3553 { 3554 unsigned char fc; 3555 unsigned int start_offset = *typeformat_offset; 3556 const expr_t *range_min = LIST_ENTRY(list_head(range_list), const expr_t, entry); 3557 const expr_t *range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry); 3558 3559 if (type_get_type(type) == TYPE_BASIC) 3560 fc = get_basic_fc(type); 3561 else 3562 fc = get_enum_fc(type); 3563 3564 /* fc must fit in lower 4-bits of 8-bit field below */ 3565 assert(fc <= 0xf); 3566 3567 print_file(file, 0, "/* %u */\n", *typeformat_offset); 3568 print_file(file, 2, "0x%x,\t/* FC_RANGE */\n", FC_RANGE); 3569 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); 3570 print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_min->cval, range_min->cval); 3571 print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_max->cval, range_max->cval); 3572 update_tfsoff( type, start_offset, file ); 3573 *typeformat_offset += 10; 3574 3575 return start_offset; 3576 } 3577 3578 static unsigned int write_type_tfs(FILE *file, int indent, 3579 const attr_list_t *attrs, type_t *type, 3580 const char *name, 3581 enum type_context context, 3582 unsigned int *typeformat_offset) 3583 { 3584 unsigned int offset; 3585 3586 switch (typegen_detect_type(type, attrs, TDT_ALL_TYPES)) 3587 { 3588 case TGT_CTXT_HANDLE: 3589 case TGT_CTXT_HANDLE_POINTER: 3590 return write_contexthandle_tfs(file, attrs, type, 3591 context == TYPE_CONTEXT_TOPLEVELPARAM, typeformat_offset); 3592 case TGT_USER_TYPE: 3593 return write_user_tfs(file, type, typeformat_offset); 3594 case TGT_STRING: 3595 return write_string_tfs(file, attrs, type, context, name, typeformat_offset); 3596 case TGT_ARRAY: 3597 { 3598 unsigned int off; 3599 /* conformant and pointer arrays are handled specially */ 3600 if ((context != TYPE_CONTEXT_CONTAINER && 3601 context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) || 3602 !is_conformant_array(type) || type_array_is_decl_as_ptr(type)) 3603 off = write_array_tfs(file, attrs, type, name, typeformat_offset); 3604 else 3605 off = 0; 3606 if (context != TYPE_CONTEXT_CONTAINER && 3607 context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) 3608 { 3609 int ptr_type; 3610 ptr_type = get_pointer_fc(type, attrs, 3611 context == TYPE_CONTEXT_TOPLEVELPARAM); 3612 if (ptr_type != FC_RP || type_array_is_decl_as_ptr(type)) 3613 { 3614 unsigned int absoff = type->typestring_offset; 3615 short reloff = absoff - (*typeformat_offset + 2); 3616 off = *typeformat_offset; 3617 print_file(file, 0, "/* %d */\n", off); 3618 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type, 3619 string_of_type(ptr_type)); 3620 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", 3621 reloff, reloff, absoff); 3622 if (ptr_type != FC_RP) update_tfsoff( type, off, file ); 3623 *typeformat_offset += 4; 3624 } 3625 type->details.array.ptr_tfsoff = off; 3626 } 3627 return off; 3628 } 3629 case TGT_STRUCT: 3630 return write_struct_tfs(file, type, name, typeformat_offset); 3631 case TGT_UNION: 3632 return write_union_tfs(file, attrs, type, typeformat_offset); 3633 case TGT_ENUM: 3634 case TGT_BASIC: 3635 /* nothing to do */ 3636 return 0; 3637 case TGT_RANGE: 3638 { 3639 expr_list_t *range_list = get_attrp(attrs, ATTR_RANGE); 3640 if (!range_list) 3641 range_list = get_aliaschain_attrp(type, ATTR_RANGE); 3642 return write_range_tfs(file, attrs, type, range_list, typeformat_offset); 3643 } 3644 case TGT_IFACE_POINTER: 3645 return write_ip_tfs(file, attrs, type, typeformat_offset); 3646 case TGT_POINTER: 3647 { 3648 enum type_context ref_context; 3649 unsigned int toplevel_offset = *typeformat_offset; 3650 type_t *ref = type_pointer_get_ref(type); 3651 3652 if (context == TYPE_CONTEXT_TOPLEVELPARAM) 3653 ref_context = TYPE_CONTEXT_PARAM; 3654 else if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS) 3655 ref_context = TYPE_CONTEXT_CONTAINER; 3656 else 3657 ref_context = context; 3658 3659 if (is_string_type(attrs, ref)) 3660 { 3661 if (context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) 3662 write_pointer_tfs(file, attrs, type, *typeformat_offset + 4, context, typeformat_offset); 3663 3664 offset = write_type_tfs(file, indent, attrs, ref, name, ref_context, typeformat_offset); 3665 if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS) 3666 return 0; 3667 return (context == TYPE_CONTEXT_TOPLEVELPARAM) ? toplevel_offset : offset; 3668 } 3669 3670 offset = write_type_tfs( file, indent, attrs, type_pointer_get_ref(type), name, 3671 ref_context, typeformat_offset); 3672 if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS) 3673 return 0; 3674 return write_pointer_tfs(file, attrs, type, offset, context, typeformat_offset); 3675 } 3676 case TGT_INVALID: 3677 break; 3678 } 3679 error("invalid type %s for var %s\n", type->name, name); 3680 return 0; 3681 } 3682 3683 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type, 3684 const char *name, int write_ptr, unsigned int *tfsoff) 3685 { 3686 return write_type_tfs(file, 2, attrs, type, name, write_ptr ? TYPE_CONTEXT_CONTAINER : TYPE_CONTEXT_CONTAINER_NO_POINTERS, tfsoff); 3687 } 3688 3689 static void process_tfs_iface(type_t *iface, FILE *file, int indent, unsigned int *offset) 3690 { 3691 const statement_list_t *stmts = type_iface_get_stmts(iface); 3692 const statement_t *stmt; 3693 var_t *var; 3694 3695 current_iface = iface; 3696 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, statement_t, entry ) 3697 { 3698 switch(stmt->type) 3699 { 3700 case STMT_DECLARATION: 3701 { 3702 const var_t *func = stmt->u.var; 3703 3704 if(stmt->u.var->stgclass != STG_NONE 3705 || type_get_type_detect_alias(stmt->u.var->type) != TYPE_FUNCTION) 3706 continue; 3707 3708 current_func = func; 3709 if (is_local(func->attrs)) continue; 3710 3711 var = type_function_get_retval(func->type); 3712 if (!is_void(var->type)) 3713 var->typestring_offset = write_type_tfs( file, 2, func->attrs, var->type, func->name, 3714 TYPE_CONTEXT_PARAM, offset); 3715 3716 if (type_get_function_args(func->type)) 3717 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), var_t, entry ) 3718 var->typestring_offset = write_type_tfs( file, 2, var->attrs, var->type, var->name, 3719 TYPE_CONTEXT_TOPLEVELPARAM, offset ); 3720 break; 3721 3722 } 3723 case STMT_TYPEDEF: 3724 { 3725 const type_list_t *type_entry; 3726 for (type_entry = stmt->u.type_list; type_entry; type_entry = type_entry->next) 3727 { 3728 if (is_attr(type_entry->type->attrs, ATTR_ENCODE) 3729 || is_attr(type_entry->type->attrs, ATTR_DECODE)) 3730 type_entry->type->typestring_offset = write_type_tfs( file, 2, 3731 type_entry->type->attrs, type_entry->type, type_entry->type->name, 3732 TYPE_CONTEXT_CONTAINER, offset); 3733 } 3734 break; 3735 } 3736 default: 3737 break; 3738 } 3739 } 3740 } 3741 3742 static unsigned int process_tfs(FILE *file, const statement_list_t *stmts, type_pred_t pred) 3743 { 3744 unsigned int typeformat_offset = 2; 3745 for_each_iface(stmts, process_tfs_iface, pred, file, 0, &typeformat_offset); 3746 return typeformat_offset + 1; 3747 } 3748 3749 3750 void write_typeformatstring(FILE *file, const statement_list_t *stmts, type_pred_t pred) 3751 { 3752 int indent = 0; 3753 3754 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n"); 3755 print_file(file, indent, "{\n"); 3756 indent++; 3757 print_file(file, indent, "0,\n"); 3758 print_file(file, indent, "{\n"); 3759 indent++; 3760 print_file(file, indent, "NdrFcShort(0x0),\n"); 3761 3762 set_all_tfswrite(TRUE); 3763 process_tfs(file, stmts, pred); 3764 3765 print_file(file, indent, "0x0\n"); 3766 indent--; 3767 print_file(file, indent, "}\n"); 3768 indent--; 3769 print_file(file, indent, "};\n"); 3770 print_file(file, indent, "\n"); 3771 } 3772 3773 static unsigned int get_required_buffer_size_type( 3774 const type_t *type, const char *name, const attr_list_t *attrs, int toplevel_param, unsigned int *alignment) 3775 { 3776 *alignment = 0; 3777 switch (typegen_detect_type(type, NULL, TDT_IGNORE_RANGES)) 3778 { 3779 case TGT_USER_TYPE: 3780 { 3781 const char *uname = NULL; 3782 const type_t *utype = get_user_type(type, &uname); 3783 return get_required_buffer_size_type(utype, uname, NULL, FALSE, alignment); 3784 } 3785 case TGT_BASIC: 3786 switch (get_basic_fc(type)) 3787 { 3788 case FC_BYTE: 3789 case FC_CHAR: 3790 case FC_USMALL: 3791 case FC_SMALL: 3792 *alignment = 4; 3793 return 1; 3794 3795 case FC_WCHAR: 3796 case FC_USHORT: 3797 case FC_SHORT: 3798 *alignment = 4; 3799 return 2; 3800 3801 case FC_ULONG: 3802 case FC_LONG: 3803 case FC_FLOAT: 3804 case FC_ERROR_STATUS_T: 3805 *alignment = 4; 3806 return 4; 3807 3808 case FC_HYPER: 3809 case FC_DOUBLE: 3810 *alignment = 8; 3811 return 8; 3812 3813 case FC_INT3264: 3814 case FC_UINT3264: 3815 assert( pointer_size ); 3816 *alignment = pointer_size; 3817 return pointer_size; 3818 3819 case FC_IGNORE: 3820 case FC_BIND_PRIMITIVE: 3821 return 0; 3822 3823 default: 3824 error("get_required_buffer_size: unknown basic type 0x%02x\n", 3825 get_basic_fc(type)); 3826 return 0; 3827 } 3828 break; 3829 3830 case TGT_ENUM: 3831 switch (get_enum_fc(type)) 3832 { 3833 case FC_ENUM32: 3834 *alignment = 4; 3835 return 4; 3836 case FC_ENUM16: 3837 *alignment = 4; 3838 return 2; 3839 } 3840 break; 3841 3842 case TGT_STRUCT: 3843 if (get_struct_fc(type) == FC_STRUCT) 3844 { 3845 if (!type_struct_get_fields(type)) return 0; 3846 return fields_memsize(type_struct_get_fields(type), alignment); 3847 } 3848 break; 3849 3850 case TGT_POINTER: 3851 { 3852 unsigned int size, align; 3853 const type_t *ref = type_pointer_get_ref(type); 3854 if (is_string_type( attrs, ref )) break; 3855 if (!(size = get_required_buffer_size_type( ref, name, NULL, FALSE, &align ))) break; 3856 if (get_pointer_fc(type, attrs, toplevel_param) != FC_RP) 3857 { 3858 size += 4 + align; 3859 align = 4; 3860 } 3861 *alignment = align; 3862 return size; 3863 } 3864 3865 case TGT_ARRAY: 3866 if (get_pointer_fc(type, attrs, toplevel_param) == FC_RP) 3867 { 3868 switch (get_array_fc(type)) 3869 { 3870 case FC_SMFARRAY: 3871 case FC_LGFARRAY: 3872 return type_array_get_dim(type) * 3873 get_required_buffer_size_type(type_array_get_element(type), name, 3874 NULL, FALSE, alignment); 3875 } 3876 } 3877 break; 3878 3879 default: 3880 break; 3881 } 3882 return 0; 3883 } 3884 3885 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass) 3886 { 3887 int in_attr = is_attr(var->attrs, ATTR_IN); 3888 int out_attr = is_attr(var->attrs, ATTR_OUT); 3889 3890 if (!in_attr && !out_attr) 3891 in_attr = 1; 3892 3893 *alignment = 0; 3894 3895 if ((pass == PASS_IN && in_attr) || (pass == PASS_OUT && out_attr) || 3896 pass == PASS_RETURN) 3897 { 3898 if (is_ptrchain_attr(var, ATTR_CONTEXTHANDLE)) 3899 { 3900 *alignment = 4; 3901 return 20; 3902 } 3903 3904 if (!is_string_type(var->attrs, var->type)) 3905 return get_required_buffer_size_type(var->type, var->name, 3906 var->attrs, TRUE, alignment); 3907 } 3908 return 0; 3909 } 3910 3911 static unsigned int get_function_buffer_size( const var_t *func, enum pass pass ) 3912 { 3913 const var_t *var; 3914 unsigned int total_size = 0, alignment; 3915 3916 if (type_get_function_args(func->type)) 3917 { 3918 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 3919 { 3920 total_size += get_required_buffer_size(var, &alignment, pass); 3921 total_size += alignment; 3922 } 3923 } 3924 3925 if (pass == PASS_OUT && !is_void(type_function_get_rettype(func->type))) 3926 { 3927 var_t v = *func; 3928 v.type = type_function_get_rettype(func->type); 3929 total_size += get_required_buffer_size(&v, &alignment, PASS_RETURN); 3930 total_size += alignment; 3931 } 3932 return total_size; 3933 } 3934 3935 static void print_phase_function(FILE *file, int indent, const char *type, 3936 const char *local_var_prefix, enum remoting_phase phase, 3937 const var_t *var, unsigned int type_offset) 3938 { 3939 const char *function; 3940 switch (phase) 3941 { 3942 case PHASE_BUFFERSIZE: 3943 function = "BufferSize"; 3944 break; 3945 case PHASE_MARSHAL: 3946 function = "Marshall"; 3947 break; 3948 case PHASE_UNMARSHAL: 3949 function = "Unmarshall"; 3950 break; 3951 case PHASE_FREE: 3952 function = "Free"; 3953 break; 3954 default: 3955 assert(0); 3956 return; 3957 } 3958 3959 print_file(file, indent, "Ndr%s%s(\n", type, function); 3960 indent++; 3961 print_file(file, indent, "&__frame->_StubMsg,\n"); 3962 print_file(file, indent, "%s%s%s%s%s,\n", 3963 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)", 3964 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "", 3965 local_var_prefix, 3966 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "", 3967 var->name); 3968 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n", 3969 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");"); 3970 if (phase == PHASE_UNMARSHAL) 3971 print_file(file, indent, "0);\n"); 3972 indent--; 3973 } 3974 3975 void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, 3976 enum remoting_phase phase, enum pass pass, const var_t *var, 3977 const char *varname) 3978 { 3979 type_t *type = var->type; 3980 unsigned int alignment = 0; 3981 3982 /* no work to do for other phases, buffer sizing is done elsewhere */ 3983 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL) 3984 return; 3985 3986 if (type_get_type(type) == TYPE_ENUM || 3987 (type_get_type(type) == TYPE_BASIC && 3988 type_basic_get_type(type) == TYPE_BASIC_INT3264 && 3989 pointer_size != 4)) 3990 { 3991 unsigned char fc; 3992 3993 if (type_get_type(type) == TYPE_ENUM) 3994 fc = get_enum_fc(type); 3995 else 3996 fc = get_basic_fc(type); 3997 3998 if (phase == PHASE_MARSHAL) 3999 print_file(file, indent, "NdrSimpleTypeMarshall(\n"); 4000 else 4001 print_file(file, indent, "NdrSimpleTypeUnmarshall(\n"); 4002 print_file(file, indent+1, "&__frame->_StubMsg,\n"); 4003 print_file(file, indent+1, "(unsigned char *)&%s%s,\n", 4004 local_var_prefix, 4005 var->name); 4006 print_file(file, indent+1, "0x%02x /* %s */);\n", fc, string_of_type(fc)); 4007 } 4008 else 4009 { 4010 const type_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : type; 4011 switch (get_basic_fc(ref)) 4012 { 4013 case FC_BYTE: 4014 case FC_CHAR: 4015 case FC_SMALL: 4016 case FC_USMALL: 4017 alignment = 1; 4018 break; 4019 4020 case FC_WCHAR: 4021 case FC_USHORT: 4022 case FC_SHORT: 4023 alignment = 2; 4024 break; 4025 4026 case FC_ULONG: 4027 case FC_LONG: 4028 case FC_FLOAT: 4029 case FC_ERROR_STATUS_T: 4030 /* pointer_size must be 4 if we got here in these two cases */ 4031 case FC_INT3264: 4032 case FC_UINT3264: 4033 alignment = 4; 4034 break; 4035 4036 case FC_HYPER: 4037 case FC_DOUBLE: 4038 alignment = 8; 4039 break; 4040 4041 case FC_IGNORE: 4042 case FC_BIND_PRIMITIVE: 4043 /* no marshalling needed */ 4044 return; 4045 4046 default: 4047 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", 4048 var->name, get_basic_fc(ref)); 4049 } 4050 4051 if (phase == PHASE_MARSHAL && alignment > 1) 4052 print_file(file, indent, "MIDL_memset(__frame->_StubMsg.Buffer, 0, (0x%x - (ULONG_PTR)__frame->_StubMsg.Buffer) & 0x%x);\n", alignment, alignment - 1); 4053 print_file(file, indent, "__frame->_StubMsg.Buffer = (unsigned char *)(((ULONG_PTR)__frame->_StubMsg.Buffer + %u) & ~0x%x);\n", 4054 alignment - 1, alignment - 1); 4055 4056 if (phase == PHASE_MARSHAL) 4057 { 4058 print_file(file, indent, "*("); 4059 write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); 4060 if (is_ptr(type)) 4061 fprintf(file, " *)__frame->_StubMsg.Buffer = *"); 4062 else 4063 fprintf(file, " *)__frame->_StubMsg.Buffer = "); 4064 fprintf(file, "%s%s", local_var_prefix, varname); 4065 fprintf(file, ";\n"); 4066 } 4067 else if (phase == PHASE_UNMARSHAL) 4068 { 4069 print_file(file, indent, "if (__frame->_StubMsg.Buffer + sizeof("); 4070 write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); 4071 fprintf(file, ") > __frame->_StubMsg.BufferEnd)\n"); 4072 print_file(file, indent, "{\n"); 4073 print_file(file, indent + 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n"); 4074 print_file(file, indent, "}\n"); 4075 print_file(file, indent, "%s%s%s", 4076 (pass == PASS_IN || pass == PASS_RETURN) ? "" : "*", 4077 local_var_prefix, varname); 4078 if (pass == PASS_IN && is_ptr(type)) 4079 fprintf(file, " = ("); 4080 else 4081 fprintf(file, " = *("); 4082 write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); 4083 fprintf(file, " *)__frame->_StubMsg.Buffer;\n"); 4084 } 4085 4086 print_file(file, indent, "__frame->_StubMsg.Buffer += sizeof("); 4087 write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); 4088 fprintf(file, ");\n"); 4089 } 4090 } 4091 4092 /* returns whether the MaxCount, Offset or ActualCount members need to be 4093 * filled in for the specified phase */ 4094 static inline int is_conformance_needed_for_phase(enum remoting_phase phase) 4095 { 4096 return (phase != PHASE_UNMARSHAL); 4097 } 4098 4099 expr_t *get_size_is_expr(const type_t *t, const char *name) 4100 { 4101 expr_t *x = NULL; 4102 4103 for ( ; is_array(t); t = type_array_get_element(t)) 4104 if (type_array_has_conformance(t) && 4105 type_array_get_conformance(t)->type != EXPR_VOID) 4106 { 4107 if (!x) 4108 x = type_array_get_conformance(t); 4109 else 4110 error("%s: multidimensional conformant" 4111 " arrays not supported at the top level\n", 4112 name); 4113 } 4114 4115 return x; 4116 } 4117 4118 void write_parameter_conf_or_var_exprs(FILE *file, int indent, const char *local_var_prefix, 4119 enum remoting_phase phase, const var_t *var, int valid_variance) 4120 { 4121 const type_t *type = var->type; 4122 /* get fundamental type for the argument */ 4123 for (;;) 4124 { 4125 switch (typegen_detect_type(type, var->attrs, TDT_IGNORE_STRINGS|TDT_IGNORE_RANGES)) 4126 { 4127 case TGT_ARRAY: 4128 if (is_conformance_needed_for_phase(phase)) 4129 { 4130 if (type_array_has_conformance(type) && 4131 type_array_get_conformance(type)->type != EXPR_VOID) 4132 { 4133 print_file(file, indent, "__frame->_StubMsg.MaxCount = (ULONG_PTR)"); 4134 write_expr(file, type_array_get_conformance(type), 1, 1, NULL, NULL, local_var_prefix); 4135 fprintf(file, ";\n\n"); 4136 } 4137 if (type_array_has_variance(type)) 4138 { 4139 print_file(file, indent, "__frame->_StubMsg.Offset = 0;\n"); /* FIXME */ 4140 if (valid_variance) 4141 { 4142 print_file(file, indent, "__frame->_StubMsg.ActualCount = (ULONG_PTR)"); 4143 write_expr(file, type_array_get_variance(type), 1, 1, NULL, NULL, local_var_prefix); 4144 fprintf(file, ";\n\n"); 4145 } 4146 else 4147 print_file(file, indent, "__frame->_StubMsg.ActualCount = __frame->_StubMsg.MaxCount;\n\n"); 4148 } 4149 } 4150 break; 4151 case TGT_UNION: 4152 if (type_get_type(type) == TYPE_UNION && 4153 is_conformance_needed_for_phase(phase)) 4154 { 4155 print_file(file, indent, "__frame->_StubMsg.MaxCount = (ULONG_PTR)"); 4156 write_expr(file, get_attrp(var->attrs, ATTR_SWITCHIS), 1, 1, NULL, NULL, local_var_prefix); 4157 fprintf(file, ";\n\n"); 4158 } 4159 break; 4160 case TGT_IFACE_POINTER: 4161 { 4162 expr_t *iid; 4163 4164 if (is_conformance_needed_for_phase(phase) && (iid = get_attrp( var->attrs, ATTR_IIDIS ))) 4165 { 4166 print_file( file, indent, "__frame->_StubMsg.MaxCount = (ULONG_PTR) " ); 4167 write_expr( file, iid, 1, 1, NULL, NULL, local_var_prefix ); 4168 fprintf( file, ";\n\n" ); 4169 } 4170 break; 4171 } 4172 case TGT_POINTER: 4173 type = type_pointer_get_ref(type); 4174 continue; 4175 case TGT_INVALID: 4176 case TGT_USER_TYPE: 4177 case TGT_CTXT_HANDLE: 4178 case TGT_CTXT_HANDLE_POINTER: 4179 case TGT_STRING: 4180 case TGT_BASIC: 4181 case TGT_ENUM: 4182 case TGT_STRUCT: 4183 case TGT_RANGE: 4184 break; 4185 } 4186 break; 4187 } 4188 } 4189 4190 static void write_remoting_arg(FILE *file, int indent, const var_t *func, const char *local_var_prefix, 4191 enum pass pass, enum remoting_phase phase, const var_t *var) 4192 { 4193 int in_attr, out_attr, pointer_type; 4194 const char *type_str = NULL; 4195 const type_t *type = var->type; 4196 unsigned int alignment, start_offset = type->typestring_offset; 4197 4198 if (is_ptr(type) || is_array(type)) 4199 pointer_type = get_pointer_fc(type, var->attrs, pass != PASS_RETURN); 4200 else 4201 pointer_type = 0; 4202 4203 in_attr = is_attr(var->attrs, ATTR_IN); 4204 out_attr = is_attr(var->attrs, ATTR_OUT); 4205 if (!in_attr && !out_attr) 4206 in_attr = 1; 4207 4208 if (phase != PHASE_FREE) 4209 switch (pass) 4210 { 4211 case PASS_IN: 4212 if (!in_attr) return; 4213 break; 4214 case PASS_OUT: 4215 if (!out_attr) return; 4216 break; 4217 case PASS_RETURN: 4218 break; 4219 } 4220 4221 if (phase == PHASE_BUFFERSIZE && get_required_buffer_size( var, &alignment, pass )) return; 4222 4223 write_parameter_conf_or_var_exprs(file, indent, local_var_prefix, phase, var, TRUE); 4224 4225 switch (typegen_detect_type(type, var->attrs, TDT_ALL_TYPES)) 4226 { 4227 case TGT_CTXT_HANDLE: 4228 case TGT_CTXT_HANDLE_POINTER: 4229 if (phase == PHASE_MARSHAL) 4230 { 4231 if (pass == PASS_IN) 4232 { 4233 /* if the context_handle attribute appears in the chain of types 4234 * without pointers being followed, then the context handle must 4235 * be direct, otherwise it is a pointer */ 4236 const char *ch_ptr = is_aliaschain_attr(type, ATTR_CONTEXTHANDLE) ? "" : "*"; 4237 print_file(file, indent, "NdrClientContextMarshall(\n"); 4238 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 4239 print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s%s,\n", ch_ptr, local_var_prefix, 4240 var->name); 4241 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0"); 4242 } 4243 else 4244 { 4245 print_file(file, indent, "NdrServerContextNewMarshall(\n"); 4246 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 4247 print_file(file, indent + 1, "(NDR_SCONTEXT)%s%s,\n", local_var_prefix, var->name); 4248 print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var->type)); 4249 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset); 4250 } 4251 } 4252 else if (phase == PHASE_UNMARSHAL) 4253 { 4254 if (pass == PASS_OUT) 4255 { 4256 if (!in_attr) 4257 print_file(file, indent, "*%s%s = 0;\n", local_var_prefix, var->name); 4258 print_file(file, indent, "NdrClientContextUnmarshall(\n"); 4259 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 4260 print_file(file, indent + 1, "(NDR_CCONTEXT *)%s%s,\n", local_var_prefix, var->name); 4261 print_file(file, indent + 1, "__frame->_Handle);\n"); 4262 } 4263 else 4264 { 4265 print_file(file, indent, "%s%s = NdrServerContextNewUnmarshall(\n", local_var_prefix, var->name); 4266 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 4267 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset); 4268 } 4269 } 4270 break; 4271 case TGT_USER_TYPE: 4272 print_phase_function(file, indent, "UserMarshal", local_var_prefix, phase, var, start_offset); 4273 break; 4274 case TGT_STRING: 4275 if (phase == PHASE_FREE || pass == PASS_RETURN || 4276 pointer_type != FC_RP) 4277 { 4278 /* strings returned are assumed to be global and hence don't 4279 * need freeing */ 4280 if (is_declptr(type) && !(phase == PHASE_FREE && pass == PASS_RETURN)) 4281 print_phase_function(file, indent, "Pointer", local_var_prefix, 4282 phase, var, start_offset); 4283 else if (pointer_type == FC_RP && phase == PHASE_FREE && 4284 !in_attr && is_conformant_array(type)) 4285 { 4286 print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name); 4287 indent++; 4288 print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name); 4289 } 4290 } 4291 else 4292 { 4293 unsigned int real_start_offset = start_offset; 4294 /* skip over pointer description straight to string description */ 4295 if (is_declptr(type)) 4296 { 4297 if (is_conformant_array(type)) 4298 real_start_offset += 4; 4299 else 4300 real_start_offset += 2; 4301 } 4302 if (is_array(type) && !is_conformant_array(type)) 4303 print_phase_function(file, indent, "NonConformantString", 4304 local_var_prefix, phase, var, 4305 real_start_offset); 4306 else 4307 print_phase_function(file, indent, "ConformantString", local_var_prefix, 4308 phase, var, real_start_offset); 4309 } 4310 break; 4311 case TGT_ARRAY: 4312 { 4313 unsigned char tc = get_array_fc(type); 4314 const char *array_type = NULL; 4315 4316 /* We already have the size_is expression since it's at the 4317 top level, but do checks for multidimensional conformant 4318 arrays. When we handle them, we'll need to extend this 4319 function to return a list, and then we'll actually use 4320 the return value. */ 4321 get_size_is_expr(type, var->name); 4322 4323 switch (tc) 4324 { 4325 case FC_SMFARRAY: 4326 case FC_LGFARRAY: 4327 array_type = "FixedArray"; 4328 break; 4329 case FC_SMVARRAY: 4330 case FC_LGVARRAY: 4331 array_type = "VaryingArray"; 4332 break; 4333 case FC_CARRAY: 4334 array_type = "ConformantArray"; 4335 break; 4336 case FC_CVARRAY: 4337 array_type = "ConformantVaryingArray"; 4338 break; 4339 case FC_BOGUS_ARRAY: 4340 array_type = "ComplexArray"; 4341 break; 4342 } 4343 4344 if (pointer_type != FC_RP) array_type = "Pointer"; 4345 4346 if (phase == PHASE_FREE && pointer_type == FC_RP) 4347 { 4348 /* these are all unmarshalled by allocating memory */ 4349 if (tc == FC_BOGUS_ARRAY || 4350 tc == FC_CVARRAY || 4351 ((tc == FC_SMVARRAY || tc == FC_LGVARRAY) && in_attr) || 4352 (tc == FC_CARRAY && !in_attr)) 4353 { 4354 if (type_array_is_decl_as_ptr(type) && type->details.array.ptr_tfsoff) 4355 { 4356 print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, 4357 type->details.array.ptr_tfsoff); 4358 break; 4359 } 4360 print_phase_function(file, indent, array_type, local_var_prefix, phase, var, start_offset); 4361 print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name); 4362 indent++; 4363 print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name); 4364 break; 4365 } 4366 } 4367 print_phase_function(file, indent, array_type, local_var_prefix, phase, var, start_offset); 4368 break; 4369 } 4370 case TGT_BASIC: 4371 print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name); 4372 break; 4373 case TGT_ENUM: 4374 print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name); 4375 break; 4376 case TGT_RANGE: 4377 print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name); 4378 /* Note: this goes beyond what MIDL does - it only supports arguments 4379 * with the [range] attribute in Oicf mode */ 4380 if (phase == PHASE_UNMARSHAL) 4381 { 4382 const expr_t *range_min; 4383 const expr_t *range_max; 4384 expr_list_t *range_list = get_attrp(var->attrs, ATTR_RANGE); 4385 if (!range_list) 4386 range_list = get_aliaschain_attrp(type, ATTR_RANGE); 4387 range_min = LIST_ENTRY(list_head(range_list), const expr_t, entry); 4388 range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry); 4389 4390 print_file(file, indent, "if ((%s%s < (", local_var_prefix, var->name); 4391 write_type_decl(file, var->type, NULL); 4392 fprintf(file, ")0x%x) || (%s%s > (", range_min->cval, local_var_prefix, var->name); 4393 write_type_decl(file, var->type, NULL); 4394 fprintf(file, ")0x%x))\n", range_max->cval); 4395 print_file(file, indent, "{\n"); 4396 print_file(file, indent+1, "RpcRaiseException(RPC_S_INVALID_BOUND);\n"); 4397 print_file(file, indent, "}\n"); 4398 } 4399 break; 4400 case TGT_STRUCT: 4401 switch (get_struct_fc(type)) 4402 { 4403 case FC_STRUCT: 4404 if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL) 4405 print_phase_function(file, indent, "SimpleStruct", local_var_prefix, phase, var, start_offset); 4406 break; 4407 case FC_PSTRUCT: 4408 print_phase_function(file, indent, "SimpleStruct", local_var_prefix, phase, var, start_offset); 4409 break; 4410 case FC_CSTRUCT: 4411 case FC_CPSTRUCT: 4412 print_phase_function(file, indent, "ConformantStruct", local_var_prefix, phase, var, start_offset); 4413 break; 4414 case FC_CVSTRUCT: 4415 print_phase_function(file, indent, "ConformantVaryingStruct", local_var_prefix, phase, var, start_offset); 4416 break; 4417 case FC_BOGUS_STRUCT: 4418 print_phase_function(file, indent, "ComplexStruct", local_var_prefix, phase, var, start_offset); 4419 break; 4420 default: 4421 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, get_struct_fc(type)); 4422 } 4423 break; 4424 case TGT_UNION: 4425 { 4426 const char *union_type = NULL; 4427 4428 if (type_get_type(type) == TYPE_UNION) 4429 union_type = "NonEncapsulatedUnion"; 4430 else if (type_get_type(type) == TYPE_ENCAPSULATED_UNION) 4431 union_type = "EncapsulatedUnion"; 4432 4433 print_phase_function(file, indent, union_type, local_var_prefix, 4434 phase, var, start_offset); 4435 break; 4436 } 4437 case TGT_POINTER: 4438 { 4439 const type_t *ref = type_pointer_get_ref(type); 4440 if (pointer_type == FC_RP) switch (typegen_detect_type(ref, NULL, TDT_ALL_TYPES)) 4441 { 4442 case TGT_BASIC: 4443 print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name); 4444 break; 4445 case TGT_ENUM: 4446 /* base types have known sizes, so don't need a sizing pass 4447 * and don't have any memory to free and so don't need a 4448 * freeing pass */ 4449 if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL) 4450 print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset); 4451 break; 4452 case TGT_STRUCT: 4453 switch (get_struct_fc(ref)) 4454 { 4455 case FC_STRUCT: 4456 /* simple structs have known sizes, so don't need a sizing 4457 * pass and don't have any memory to free and so don't 4458 * need a freeing pass */ 4459 if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL) 4460 type_str = "SimpleStruct"; 4461 else if (phase == PHASE_FREE && pass == PASS_RETURN) 4462 { 4463 print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name); 4464 indent++; 4465 print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name); 4466 indent--; 4467 } 4468 break; 4469 case FC_PSTRUCT: 4470 type_str = "SimpleStruct"; 4471 break; 4472 case FC_CSTRUCT: 4473 case FC_CPSTRUCT: 4474 type_str = "ConformantStruct"; 4475 break; 4476 case FC_CVSTRUCT: 4477 type_str = "ConformantVaryingStruct"; 4478 break; 4479 case FC_BOGUS_STRUCT: 4480 type_str = "ComplexStruct"; 4481 break; 4482 default: 4483 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, get_struct_fc(ref)); 4484 } 4485 4486 if (type_str) 4487 { 4488 if (phase == PHASE_FREE) 4489 type_str = "Pointer"; 4490 else 4491 start_offset = ref->typestring_offset; 4492 print_phase_function(file, indent, type_str, local_var_prefix, phase, var, start_offset); 4493 } 4494 break; 4495 case TGT_UNION: 4496 if (phase == PHASE_FREE) 4497 type_str = "Pointer"; 4498 else 4499 { 4500 if (type_get_type(ref) == TYPE_UNION) 4501 type_str = "NonEncapsulatedUnion"; 4502 else if (type_get_type(ref) == TYPE_ENCAPSULATED_UNION) 4503 type_str = "EncapsulatedUnion"; 4504 4505 start_offset = ref->typestring_offset; 4506 } 4507 4508 print_phase_function(file, indent, type_str, local_var_prefix, 4509 phase, var, start_offset); 4510 break; 4511 case TGT_USER_TYPE: 4512 if (phase != PHASE_FREE) 4513 { 4514 type_str = "UserMarshal"; 4515 start_offset = ref->typestring_offset; 4516 } 4517 else type_str = "Pointer"; 4518 4519 print_phase_function(file, indent, type_str, local_var_prefix, phase, var, start_offset); 4520 break; 4521 case TGT_STRING: 4522 case TGT_POINTER: 4523 case TGT_ARRAY: 4524 case TGT_RANGE: 4525 case TGT_IFACE_POINTER: 4526 case TGT_CTXT_HANDLE: 4527 case TGT_CTXT_HANDLE_POINTER: 4528 print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset); 4529 break; 4530 case TGT_INVALID: 4531 assert(0); 4532 break; 4533 } 4534 else 4535 print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset); 4536 break; 4537 } 4538 case TGT_IFACE_POINTER: 4539 print_phase_function(file, indent, "InterfacePointer", local_var_prefix, phase, var, start_offset); 4540 break; 4541 case TGT_INVALID: 4542 assert(0); 4543 break; 4544 } 4545 fprintf(file, "\n"); 4546 } 4547 4548 void write_remoting_arguments(FILE *file, int indent, const var_t *func, const char *local_var_prefix, 4549 enum pass pass, enum remoting_phase phase) 4550 { 4551 if (phase == PHASE_BUFFERSIZE && pass != PASS_RETURN) 4552 { 4553 unsigned int size = get_function_buffer_size( func, pass ); 4554 print_file(file, indent, "__frame->_StubMsg.BufferLength = %u;\n", size); 4555 } 4556 4557 if (pass == PASS_RETURN) 4558 { 4559 write_remoting_arg( file, indent, func, local_var_prefix, pass, phase, 4560 type_function_get_retval(func->type) ); 4561 } 4562 else 4563 { 4564 const var_t *var; 4565 if (!type_get_function_args(func->type)) 4566 return; 4567 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 4568 write_remoting_arg( file, indent, func, local_var_prefix, pass, phase, var ); 4569 } 4570 } 4571 4572 4573 unsigned int get_size_procformatstring_func(const type_t *iface, const var_t *func) 4574 { 4575 unsigned int offset = 0; 4576 write_procformatstring_func( NULL, 0, iface, func, &offset, 0 ); 4577 return offset; 4578 } 4579 4580 static void get_size_procformatstring_iface(type_t *iface, FILE *file, int indent, unsigned int *size) 4581 { 4582 const statement_t *stmt; 4583 STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) 4584 { 4585 const var_t *func = stmt->u.var; 4586 if (!is_local(func->attrs)) 4587 *size += get_size_procformatstring_func( iface, func ); 4588 } 4589 } 4590 4591 unsigned int get_size_procformatstring(const statement_list_t *stmts, type_pred_t pred) 4592 { 4593 unsigned int size = 1; 4594 for_each_iface(stmts, get_size_procformatstring_iface, pred, NULL, 0, &size); 4595 return size; 4596 } 4597 4598 unsigned int get_size_typeformatstring(const statement_list_t *stmts, type_pred_t pred) 4599 { 4600 set_all_tfswrite(FALSE); 4601 return process_tfs(NULL, stmts, pred); 4602 } 4603 4604 void declare_stub_args( FILE *file, int indent, const var_t *func ) 4605 { 4606 int in_attr, out_attr; 4607 int i = 0; 4608 const var_t *var = type_function_get_retval(func->type); 4609 4610 /* declare return value */ 4611 if (!is_void(var->type)) 4612 { 4613 print_file(file, indent, "%s", ""); 4614 write_type_decl(file, var->type, var->name); 4615 fprintf(file, ";\n"); 4616 } 4617 4618 if (!type_get_function_args(func->type)) 4619 return; 4620 4621 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 4622 { 4623 in_attr = is_attr(var->attrs, ATTR_IN); 4624 out_attr = is_attr(var->attrs, ATTR_OUT); 4625 if (!out_attr && !in_attr) 4626 in_attr = 1; 4627 4628 if (is_context_handle(var->type)) 4629 print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name); 4630 else 4631 { 4632 if (!in_attr && !is_conformant_array(var->type)) 4633 { 4634 type_t *type_to_print; 4635 char name[16]; 4636 print_file(file, indent, "%s", ""); 4637 if (type_get_type(var->type) == TYPE_ARRAY && 4638 !type_array_is_decl_as_ptr(var->type)) 4639 type_to_print = var->type; 4640 else 4641 type_to_print = type_pointer_get_ref(var->type); 4642 sprintf(name, "_W%u", i++); 4643 write_type_decl(file, type_to_print, name); 4644 fprintf(file, ";\n"); 4645 } 4646 4647 print_file(file, indent, "%s", ""); 4648 write_type_decl_left(file, var->type); 4649 fprintf(file, " "); 4650 if (type_get_type(var->type) == TYPE_ARRAY && 4651 !type_array_is_decl_as_ptr(var->type)) { 4652 fprintf(file, "(*%s)", var->name); 4653 } else 4654 fprintf(file, "%s", var->name); 4655 write_type_right(file, var->type, FALSE); 4656 fprintf(file, ";\n"); 4657 4658 if (decl_indirect(var->type)) 4659 print_file(file, indent, "void *_p_%s;\n", var->name); 4660 } 4661 } 4662 } 4663 4664 4665 void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char *local_var_prefix ) 4666 { 4667 int in_attr, out_attr; 4668 int i = 0, sep = 0; 4669 const var_t *var; 4670 type_t *ref; 4671 4672 if (!type_get_function_args(func->type)) 4673 return; 4674 4675 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 4676 { 4677 in_attr = is_attr(var->attrs, ATTR_IN); 4678 out_attr = is_attr(var->attrs, ATTR_OUT); 4679 if (!out_attr && !in_attr) 4680 in_attr = 1; 4681 4682 if (!in_attr) 4683 { 4684 print_file(file, indent, "%s%s", local_var_prefix, var->name); 4685 4686 switch (typegen_detect_type(var->type, var->attrs, TDT_IGNORE_STRINGS)) 4687 { 4688 case TGT_CTXT_HANDLE_POINTER: 4689 fprintf(file, " = NdrContextHandleInitialize(\n"); 4690 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 4691 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", 4692 var->typestring_offset); 4693 break; 4694 case TGT_ARRAY: 4695 if (type_array_has_conformance(var->type)) 4696 { 4697 unsigned int size; 4698 type_t *type; 4699 4700 fprintf(file, " = NdrAllocate(&__frame->_StubMsg, "); 4701 for (type = var->type; 4702 is_array(type) && type_array_has_conformance(type); 4703 type = type_array_get_element(type)) 4704 { 4705 write_expr(file, type_array_get_conformance(type), TRUE, 4706 TRUE, NULL, NULL, local_var_prefix); 4707 fprintf(file, " * "); 4708 } 4709 size = type_memsize(type); 4710 fprintf(file, "%u);\n", size); 4711 4712 print_file(file, indent, "memset(%s%s, 0, ", local_var_prefix, var->name); 4713 for (type = var->type; 4714 is_array(type) && type_array_has_conformance(type); 4715 type = type_array_get_element(type)) 4716 { 4717 write_expr(file, type_array_get_conformance(type), TRUE, 4718 TRUE, NULL, NULL, local_var_prefix); 4719 fprintf(file, " * "); 4720 } 4721 size = type_memsize(type); 4722 fprintf(file, "%u);\n", size); 4723 } 4724 else 4725 fprintf(file, " = &%s_W%u;\n", local_var_prefix, i++); 4726 break; 4727 case TGT_POINTER: 4728 fprintf(file, " = &%s_W%u;\n", local_var_prefix, i); 4729 ref = type_pointer_get_ref(var->type); 4730 switch (typegen_detect_type(ref, var->attrs, TDT_IGNORE_STRINGS)) 4731 { 4732 case TGT_BASIC: 4733 case TGT_ENUM: 4734 case TGT_POINTER: 4735 case TGT_RANGE: 4736 case TGT_IFACE_POINTER: 4737 print_file(file, indent, "%s_W%u = 0;\n", local_var_prefix, i); 4738 break; 4739 case TGT_USER_TYPE: 4740 print_file(file, indent, "memset(&%s_W%u, 0, sizeof(%s_W%u));\n", 4741 local_var_prefix, i, local_var_prefix, i); 4742 break; 4743 case TGT_ARRAY: 4744 if (type_array_is_decl_as_ptr(ref)) 4745 { 4746 print_file(file, indent, "%s_W%u = 0;\n", local_var_prefix, i); 4747 break; 4748 } 4749 ref = type_array_get_element(ref); 4750 /* fall through */ 4751 case TGT_STRUCT: 4752 case TGT_UNION: 4753 if (type_has_pointers(ref)) 4754 print_file(file, indent, "memset(&%s_W%u, 0, sizeof(%s_W%u));\n", 4755 local_var_prefix, i, local_var_prefix, i); 4756 break; 4757 case TGT_CTXT_HANDLE: 4758 case TGT_CTXT_HANDLE_POINTER: 4759 case TGT_INVALID: 4760 case TGT_STRING: 4761 /* not initialised */ 4762 break; 4763 } 4764 i++; 4765 break; 4766 default: 4767 break; 4768 } 4769 4770 sep = 1; 4771 } 4772 } 4773 if (sep) 4774 fprintf(file, "\n"); 4775 } 4776 4777 4778 void write_func_param_struct( FILE *file, const type_t *iface, const type_t *func, 4779 const char *var_decl, int add_retval ) 4780 { 4781 var_t *retval = type_function_get_retval( func ); 4782 const var_list_t *args = type_get_function_args( func ); 4783 const var_t *arg; 4784 int needs_packing; 4785 unsigned int align = 0; 4786 4787 if (args) 4788 LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) 4789 if (!is_array( arg->type )) type_memsize_and_alignment( arg->type, &align ); 4790 4791 needs_packing = (align > pointer_size); 4792 4793 if (needs_packing) print_file( file, 0, "#include <pshpack%u.h>\n", pointer_size ); 4794 print_file(file, 1, "struct _PARAM_STRUCT\n" ); 4795 print_file(file, 1, "{\n" ); 4796 if (is_object( iface )) print_file(file, 2, "%s *This;\n", iface->name ); 4797 4798 if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) 4799 { 4800 print_file(file, 2, "%s", ""); 4801 write_type_left( file, (type_t *)arg->type, NAME_DEFAULT, TRUE ); 4802 if (needs_space_after( arg->type )) fputc( ' ', file ); 4803 if (is_array( arg->type ) && !type_array_is_decl_as_ptr( arg->type )) fputc( '*', file ); 4804 4805 /* FIXME: should check for large args being passed by pointer */ 4806 align = 0; 4807 if (is_array( arg->type ) || is_ptr( arg->type )) align = pointer_size; 4808 else type_memsize_and_alignment( arg->type, &align ); 4809 4810 if (align >= pointer_size) 4811 fprintf( file, "%s;\n", arg->name ); 4812 else 4813 #ifdef __REACTOS__ 4814 fprintf( file, "DECLSPEC_ALIGN(%u) %s;\n", pointer_size, arg->name ); 4815 #else 4816 fprintf( file, "%s DECLSPEC_ALIGN(%u);\n", arg->name, pointer_size ); 4817 #endif 4818 } 4819 if (add_retval && !is_void( retval->type )) 4820 { 4821 print_file(file, 2, "%s", ""); 4822 write_type_decl( file, retval->type, retval->name ); 4823 if (is_array( retval->type ) || is_ptr( retval->type ) || 4824 type_memsize( retval->type ) == pointer_size) 4825 fprintf( file, ";\n" ); 4826 else 4827 fprintf( file, " DECLSPEC_ALIGN(%u);\n", pointer_size ); 4828 } 4829 print_file(file, 1, "} %s;\n", var_decl ); 4830 if (needs_packing) print_file( file, 0, "#include <poppack.h>\n" ); 4831 print_file( file, 0, "\n" ); 4832 } 4833 4834 void write_pointer_checks( FILE *file, int indent, const var_t *func ) 4835 { 4836 const var_list_t *args = type_get_function_args( func->type ); 4837 const var_t *var; 4838 4839 if (!args) return; 4840 4841 LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) 4842 if (cant_be_null( var )) 4843 print_file( file, indent, "if (!%s) RpcRaiseException(RPC_X_NULL_REF_POINTER);\n", var->name ); 4844 } 4845 4846 int write_expr_eval_routines(FILE *file, const char *iface) 4847 { 4848 static const char *var_name = "pS"; 4849 static const char *var_name_expr = "pS->"; 4850 int result = 0; 4851 struct expr_eval_routine *eval; 4852 unsigned short callback_offset = 0; 4853 4854 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry) 4855 { 4856 const char *name = eval->name; 4857 result = 1; 4858 4859 print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n", 4860 eval->iface ? eval->iface->name : iface, name, callback_offset); 4861 print_file(file, 0, "{\n"); 4862 if (type_get_type( eval->cont_type ) == TYPE_FUNCTION) 4863 { 4864 write_func_param_struct( file, eval->iface, eval->cont_type, 4865 "*pS = (struct _PARAM_STRUCT *)pStubMsg->StackTop", FALSE ); 4866 } 4867 else 4868 { 4869 print_file(file, 1, "%s", ""); 4870 write_type_left(file, (type_t *)eval->cont_type, NAME_DEFAULT, TRUE); 4871 fprintf(file, " *%s = (", var_name); 4872 write_type_left(file, (type_t *)eval->cont_type, NAME_DEFAULT, TRUE); 4873 fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff); 4874 } 4875 print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */ 4876 print_file(file, 1, "pStubMsg->MaxCount = (ULONG_PTR)"); 4877 write_expr(file, eval->expr, 1, 1, var_name_expr, eval->cont_type, ""); 4878 fprintf(file, ";\n"); 4879 print_file(file, 0, "}\n\n"); 4880 callback_offset++; 4881 } 4882 return result; 4883 } 4884 4885 void write_expr_eval_routine_list(FILE *file, const char *iface) 4886 { 4887 struct expr_eval_routine *eval; 4888 struct expr_eval_routine *cursor; 4889 unsigned short callback_offset = 0; 4890 4891 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n"); 4892 fprintf(file, "{\n"); 4893 4894 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry) 4895 { 4896 print_file(file, 1, "%s_%sExprEval_%04u,\n", 4897 eval->iface ? eval->iface->name : iface, eval->name, callback_offset); 4898 callback_offset++; 4899 list_remove(&eval->entry); 4900 free(eval->name); 4901 free(eval); 4902 } 4903 4904 fprintf(file, "};\n\n"); 4905 } 4906 4907 void write_user_quad_list(FILE *file) 4908 { 4909 user_type_t *ut; 4910 4911 if (list_empty(&user_type_list)) 4912 return; 4913 4914 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n"); 4915 fprintf(file, "{\n"); 4916 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) 4917 { 4918 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ","; 4919 print_file(file, 1, "{\n"); 4920 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name); 4921 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name); 4922 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name); 4923 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name); 4924 print_file(file, 1, "}%s\n", sep); 4925 } 4926 fprintf(file, "};\n\n"); 4927 } 4928 4929 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list ) 4930 { 4931 const struct str_list_entry_t *endpoint; 4932 const char *p; 4933 4934 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */ 4935 print_file( f, 0, "static const unsigned char * const %s__RpcProtseqEndpoint[][2] =\n{\n", prefix ); 4936 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry ) 4937 { 4938 print_file( f, 1, "{ (const unsigned char *)\"" ); 4939 for (p = endpoint->str; *p && *p != ':'; p++) 4940 { 4941 if (*p == '"' || *p == '\\') fputc( '\\', f ); 4942 fputc( *p, f ); 4943 } 4944 if (!*p) goto error; 4945 if (p[1] != '[') goto error; 4946 4947 fprintf( f, "\", (const unsigned char *)\"" ); 4948 for (p += 2; *p && *p != ']'; p++) 4949 { 4950 if (*p == '"' || *p == '\\') fputc( '\\', f ); 4951 fputc( *p, f ); 4952 } 4953 if (*p != ']') goto error; 4954 fprintf( f, "\" },\n" ); 4955 } 4956 print_file( f, 0, "};\n\n" ); 4957 return; 4958 4959 error: 4960 error("Invalid endpoint syntax '%s'\n", endpoint->str); 4961 } 4962 4963 void write_client_call_routine( FILE *file, const type_t *iface, const var_t *func, 4964 const char *prefix, unsigned int proc_offset ) 4965 { 4966 type_t *rettype = type_function_get_rettype( func->type ); 4967 int has_ret = !is_void( rettype ); 4968 const var_list_t *args = type_get_function_args( func->type ); 4969 const var_t *arg; 4970 int len, needs_params = 0; 4971 4972 /* we need a param structure if we have more than one arg */ 4973 if (pointer_size == 4 && args) needs_params = is_object( iface ) || list_count( args ) > 1; 4974 4975 print_file( file, 0, "{\n"); 4976 if (needs_params) 4977 { 4978 if (has_ret) print_file( file, 1, "%s", "CLIENT_CALL_RETURN _RetVal;\n" ); 4979 write_func_param_struct( file, iface, func->type, "__params", FALSE ); 4980 if (is_object( iface )) print_file( file, 1, "__params.This = This;\n" ); 4981 if (args) 4982 LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) 4983 print_file( file, 1, "__params.%s = %s;\n", arg->name, arg->name ); 4984 } 4985 else if (has_ret) print_file( file, 1, "%s", "CLIENT_CALL_RETURN _RetVal;\n\n" ); 4986 4987 len = fprintf( file, " %s%s( ", 4988 has_ret ? "_RetVal = " : "", 4989 get_stub_mode() == MODE_Oif ? "NdrClientCall2" : "NdrClientCall" ); 4990 fprintf( file, "&%s_StubDesc,", prefix ); 4991 fprintf( file, "\n%*s&__MIDL_ProcFormatString.Format[%u]", len, "", proc_offset ); 4992 if (needs_params) 4993 { 4994 fprintf( file, ",\n%*s&__params", len, "" ); 4995 } 4996 else if (pointer_size == 8) 4997 { 4998 if (is_object( iface )) fprintf( file, ",\n%*sThis", len, "" ); 4999 if (args) 5000 LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) 5001 fprintf( file, ",\n%*s%s", len, "", arg->name ); 5002 } 5003 else 5004 { 5005 if (is_object( iface )) fprintf( file, ",\n%*s&This", len, "" ); 5006 else if (args) 5007 { 5008 arg = LIST_ENTRY( list_head(args), const var_t, entry ); 5009 fprintf( file, ",\n%*s&%s", len, "", arg->name ); 5010 } 5011 } 5012 fprintf( file, " );\n" ); 5013 if (has_ret) 5014 { 5015 print_file( file, 1, "return (" ); 5016 write_type_decl_left(file, rettype); 5017 fprintf( file, ")%s;\n", pointer_size == 8 ? "_RetVal.Simple" : "*(LONG_PTR *)&_RetVal" ); 5018 } 5019 print_file( file, 0, "}\n\n"); 5020 } 5021 5022 void write_exceptions( FILE *file ) 5023 { 5024 fprintf( file, "#ifndef USE_COMPILER_EXCEPTIONS\n"); 5025 fprintf( file, "\n"); 5026 fprintf( file, "#include \"wine/exception.h\"\n"); 5027 fprintf( file, "#undef RpcTryExcept\n"); 5028 fprintf( file, "#undef RpcExcept\n"); 5029 fprintf( file, "#undef RpcEndExcept\n"); 5030 fprintf( file, "#undef RpcTryFinally\n"); 5031 fprintf( file, "#undef RpcFinally\n"); 5032 fprintf( file, "#undef RpcEndFinally\n"); 5033 fprintf( file, "#undef RpcExceptionCode\n"); 5034 fprintf( file, "#undef RpcAbnormalTermination\n"); 5035 fprintf( file, "\n"); 5036 fprintf( file, "struct __exception_frame;\n"); 5037 fprintf( file, "typedef int (*__filter_func)(struct __exception_frame *);\n"); 5038 fprintf( file, "typedef void (*__finally_func)(struct __exception_frame *);\n"); 5039 fprintf( file, "\n"); 5040 fprintf( file, "#define __DECL_EXCEPTION_FRAME \\\n"); 5041 fprintf( file, " EXCEPTION_REGISTRATION_RECORD frame; \\\n"); 5042 fprintf( file, " __filter_func filter; \\\n"); 5043 fprintf( file, " __finally_func finally; \\\n"); 5044 fprintf( file, " sigjmp_buf jmp; \\\n"); 5045 fprintf( file, " DWORD code; \\\n"); 5046 fprintf( file, " unsigned char abnormal_termination; \\\n"); 5047 fprintf( file, " unsigned char filter_level; \\\n"); 5048 fprintf( file, " unsigned char finally_level;\n"); 5049 fprintf( file, "\n"); 5050 fprintf( file, "struct __exception_frame\n{\n"); 5051 fprintf( file, " __DECL_EXCEPTION_FRAME\n"); 5052 fprintf( file, "};\n"); 5053 fprintf( file, "\n"); 5054 fprintf( file, "static inline void __widl_unwind_target(void)\n" ); 5055 fprintf( file, "{\n"); 5056 fprintf( file, " struct __exception_frame *exc_frame = (struct __exception_frame *)__wine_get_frame();\n" ); 5057 fprintf( file, " if (exc_frame->finally_level > exc_frame->filter_level)\n" ); 5058 fprintf( file, " {\n"); 5059 fprintf( file, " exc_frame->abnormal_termination = 1;\n"); 5060 fprintf( file, " exc_frame->finally( exc_frame );\n"); 5061 fprintf( file, " __wine_pop_frame( &exc_frame->frame );\n"); 5062 fprintf( file, " }\n"); 5063 fprintf( file, " exc_frame->filter_level = 0;\n"); 5064 fprintf( file, " siglongjmp( exc_frame->jmp, 1 );\n"); 5065 fprintf( file, "}\n"); 5066 fprintf( file, "\n"); 5067 fprintf( file, "static DWORD __widl_exception_handler( EXCEPTION_RECORD *record,\n"); 5068 fprintf( file, " EXCEPTION_REGISTRATION_RECORD *frame,\n"); 5069 fprintf( file, " CONTEXT *context,\n"); 5070 fprintf( file, " EXCEPTION_REGISTRATION_RECORD **pdispatcher )\n"); 5071 fprintf( file, "{\n"); 5072 fprintf( file, " struct __exception_frame *exc_frame = (struct __exception_frame *)frame;\n"); 5073 fprintf( file, "\n"); 5074 fprintf( file, " if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))\n"); 5075 fprintf( file, " {\n" ); 5076 fprintf( file, " if (exc_frame->finally_level && (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))\n"); 5077 fprintf( file, " {\n" ); 5078 fprintf( file, " exc_frame->abnormal_termination = 1;\n"); 5079 fprintf( file, " exc_frame->finally( exc_frame );\n"); 5080 fprintf( file, " }\n" ); 5081 fprintf( file, " return ExceptionContinueSearch;\n"); 5082 fprintf( file, " }\n" ); 5083 fprintf( file, " exc_frame->code = record->ExceptionCode;\n"); 5084 fprintf( file, " if (exc_frame->filter_level && exc_frame->filter( exc_frame ) == EXCEPTION_EXECUTE_HANDLER)\n" ); 5085 fprintf( file, " __wine_rtl_unwind( frame, record, __widl_unwind_target );\n"); 5086 fprintf( file, " return ExceptionContinueSearch;\n"); 5087 fprintf( file, "}\n"); 5088 fprintf( file, "\n"); 5089 fprintf( file, "#define RpcTryExcept \\\n"); 5090 fprintf( file, " if (!sigsetjmp( __frame->jmp, 0 )) \\\n"); 5091 fprintf( file, " { \\\n"); 5092 fprintf( file, " if (!__frame->finally_level) \\\n" ); 5093 fprintf( file, " __wine_push_frame( &__frame->frame ); \\\n"); 5094 fprintf( file, " __frame->filter_level = __frame->finally_level + 1;\n" ); 5095 fprintf( file, "\n"); 5096 fprintf( file, "#define RpcExcept(expr) \\\n"); 5097 fprintf( file, " if (!__frame->finally_level) \\\n" ); 5098 fprintf( file, " __wine_pop_frame( &__frame->frame ); \\\n"); 5099 fprintf( file, " __frame->filter_level = 0; \\\n" ); 5100 fprintf( file, " } \\\n"); 5101 fprintf( file, " else \\\n"); 5102 fprintf( file, "\n"); 5103 fprintf( file, "#define RpcEndExcept\n"); 5104 fprintf( file, "\n"); 5105 fprintf( file, "#define RpcExceptionCode() (__frame->code)\n"); 5106 fprintf( file, "\n"); 5107 fprintf( file, "#define RpcTryFinally \\\n"); 5108 fprintf( file, " if (!__frame->filter_level) \\\n"); 5109 fprintf( file, " __wine_push_frame( &__frame->frame ); \\\n"); 5110 fprintf( file, " __frame->finally_level = __frame->filter_level + 1;\n"); 5111 fprintf( file, "\n"); 5112 fprintf( file, "#define RpcFinally \\\n"); 5113 fprintf( file, " if (!__frame->filter_level) \\\n"); 5114 fprintf( file, " __wine_pop_frame( &__frame->frame ); \\\n"); 5115 fprintf( file, " __frame->finally_level = 0;\n"); 5116 fprintf( file, "\n"); 5117 fprintf( file, "#define RpcEndFinally\n"); 5118 fprintf( file, "\n"); 5119 fprintf( file, "#define RpcAbnormalTermination() (__frame->abnormal_termination)\n"); 5120 fprintf( file, "\n"); 5121 fprintf( file, "#define RpcExceptionInit(filter_func,finally_func) \\\n"); 5122 fprintf( file, " do { \\\n"); 5123 fprintf( file, " __frame->frame.Handler = __widl_exception_handler; \\\n"); 5124 fprintf( file, " __frame->filter = (__filter_func)(filter_func); \\\n" ); 5125 fprintf( file, " __frame->finally = (__finally_func)(finally_func); \\\n"); 5126 fprintf( file, " __frame->abnormal_termination = 0; \\\n"); 5127 fprintf( file, " __frame->filter_level = 0; \\\n"); 5128 fprintf( file, " __frame->finally_level = 0; \\\n"); 5129 fprintf( file, " } while (0)\n"); 5130 fprintf( file, "\n"); 5131 fprintf( file, "#else /* USE_COMPILER_EXCEPTIONS */\n"); 5132 fprintf( file, "\n"); 5133 fprintf( file, "#define RpcExceptionInit(filter_func,finally_func) \\\n"); 5134 fprintf( file, " do { (void)(filter_func); } while(0)\n"); 5135 fprintf( file, "\n"); 5136 fprintf( file, "#define __DECL_EXCEPTION_FRAME \\\n"); 5137 fprintf( file, " DWORD code;\n"); 5138 fprintf( file, "\n"); 5139 fprintf( file, "#endif /* USE_COMPILER_EXCEPTIONS */\n"); 5140 } 5141