Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentypegen.c
Go to the documentation of this file.
00001 /* 00002 * Format String Generator for IDL Compiler 00003 * 00004 * Copyright 2005-2006 Eric Kohl 00005 * Copyright 2005-2006 Robert Shearman 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00020 */ 00021 00022 #include "config.h" 00023 #include "wine/port.h" 00024 00025 #include <stdio.h> 00026 #include <stdlib.h> 00027 #ifdef HAVE_UNISTD_H 00028 # include <unistd.h> 00029 #endif 00030 #include <string.h> 00031 #include <assert.h> 00032 #include <ctype.h> 00033 #include <limits.h> 00034 00035 #include "widl.h" 00036 #include "utils.h" 00037 #include "parser.h" 00038 #include "header.h" 00039 #include "typetree.h" 00040 00041 #include "typegen.h" 00042 #include "expr.h" 00043 00044 /* round size up to multiple of alignment */ 00045 #define ROUND_SIZE(size, alignment) (((size) + ((alignment) - 1)) & ~((alignment) - 1)) 00046 /* value to add on to round size up to a multiple of alignment */ 00047 #define ROUNDING(size, alignment) (((alignment) - 1) - (((size) + ((alignment) - 1)) & ((alignment) - 1))) 00048 00049 static const type_t *current_structure; 00050 static const var_t *current_func; 00051 static const type_t *current_iface; 00052 00053 static struct list expr_eval_routines = LIST_INIT(expr_eval_routines); 00054 struct expr_eval_routine 00055 { 00056 struct list entry; 00057 const type_t *iface; 00058 const type_t *cont_type; 00059 char *name; 00060 unsigned int baseoff; 00061 const expr_t *expr; 00062 }; 00063 00064 enum type_context 00065 { 00066 TYPE_CONTEXT_TOPLEVELPARAM, 00067 TYPE_CONTEXT_PARAM, 00068 TYPE_CONTEXT_CONTAINER, 00069 TYPE_CONTEXT_CONTAINER_NO_POINTERS, 00070 }; 00071 00072 /* parameter flags in Oif mode */ 00073 static const unsigned short MustSize = 0x0001; 00074 static const unsigned short MustFree = 0x0002; 00075 static const unsigned short IsPipe = 0x0004; 00076 static const unsigned short IsIn = 0x0008; 00077 static const unsigned short IsOut = 0x0010; 00078 static const unsigned short IsReturn = 0x0020; 00079 static const unsigned short IsBasetype = 0x0040; 00080 static const unsigned short IsByValue = 0x0080; 00081 static const unsigned short IsSimpleRef = 0x0100; 00082 /* static const unsigned short IsDontCallFreeInst = 0x0200; */ 00083 /* static const unsigned short SaveForAsyncFinish = 0x0400; */ 00084 00085 static unsigned int field_memsize(const type_t *type, unsigned int *offset); 00086 static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align); 00087 static unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align); 00088 static unsigned int write_struct_tfs(FILE *file, type_t *type, const char *name, unsigned int *tfsoff); 00089 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type, 00090 const char *name, int write_ptr, unsigned int *tfsoff); 00091 static const var_t *find_array_or_string_in_struct(const type_t *type); 00092 static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, 00093 type_t *type, enum type_context context, 00094 const char *name, unsigned int *typestring_offset); 00095 static unsigned int get_required_buffer_size_type( const type_t *type, const char *name, 00096 const attr_list_t *attrs, int toplevel_param, 00097 unsigned int *alignment ); 00098 static unsigned int get_function_buffer_size( const var_t *func, enum pass pass ); 00099 00100 static const char *string_of_type(unsigned char type) 00101 { 00102 switch (type) 00103 { 00104 case RPC_FC_BYTE: return "FC_BYTE"; 00105 case RPC_FC_CHAR: return "FC_CHAR"; 00106 case RPC_FC_SMALL: return "FC_SMALL"; 00107 case RPC_FC_USMALL: return "FC_USMALL"; 00108 case RPC_FC_WCHAR: return "FC_WCHAR"; 00109 case RPC_FC_SHORT: return "FC_SHORT"; 00110 case RPC_FC_USHORT: return "FC_USHORT"; 00111 case RPC_FC_LONG: return "FC_LONG"; 00112 case RPC_FC_ULONG: return "FC_ULONG"; 00113 case RPC_FC_FLOAT: return "FC_FLOAT"; 00114 case RPC_FC_HYPER: return "FC_HYPER"; 00115 case RPC_FC_DOUBLE: return "FC_DOUBLE"; 00116 case RPC_FC_ENUM16: return "FC_ENUM16"; 00117 case RPC_FC_ENUM32: return "FC_ENUM32"; 00118 case RPC_FC_IGNORE: return "FC_IGNORE"; 00119 case RPC_FC_ERROR_STATUS_T: return "FC_ERROR_STATUS_T"; 00120 case RPC_FC_RP: return "FC_RP"; 00121 case RPC_FC_UP: return "FC_UP"; 00122 case RPC_FC_OP: return "FC_OP"; 00123 case RPC_FC_FP: return "FC_FP"; 00124 case RPC_FC_ENCAPSULATED_UNION: return "FC_ENCAPSULATED_UNION"; 00125 case RPC_FC_NON_ENCAPSULATED_UNION: return "FC_NON_ENCAPSULATED_UNION"; 00126 case RPC_FC_STRUCT: return "FC_STRUCT"; 00127 case RPC_FC_PSTRUCT: return "FC_PSTRUCT"; 00128 case RPC_FC_CSTRUCT: return "FC_CSTRUCT"; 00129 case RPC_FC_CPSTRUCT: return "FC_CPSTRUCT"; 00130 case RPC_FC_CVSTRUCT: return "FC_CVSTRUCT"; 00131 case RPC_FC_BOGUS_STRUCT: return "FC_BOGUS_STRUCT"; 00132 case RPC_FC_SMFARRAY: return "FC_SMFARRAY"; 00133 case RPC_FC_LGFARRAY: return "FC_LGFARRAY"; 00134 case RPC_FC_SMVARRAY: return "FC_SMVARRAY"; 00135 case RPC_FC_LGVARRAY: return "FC_LGVARRAY"; 00136 case RPC_FC_CARRAY: return "FC_CARRAY"; 00137 case RPC_FC_CVARRAY: return "FC_CVARRAY"; 00138 case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY"; 00139 case RPC_FC_ALIGNM2: return "FC_ALIGNM2"; 00140 case RPC_FC_ALIGNM4: return "FC_ALIGNM4"; 00141 case RPC_FC_ALIGNM8: return "FC_ALIGNM8"; 00142 case RPC_FC_POINTER: return "FC_POINTER"; 00143 case RPC_FC_C_CSTRING: return "FC_C_CSTRING"; 00144 case RPC_FC_C_WSTRING: return "FC_C_WSTRING"; 00145 case RPC_FC_CSTRING: return "FC_CSTRING"; 00146 case RPC_FC_WSTRING: return "FC_WSTRING"; 00147 case RPC_FC_BYTE_COUNT_POINTER: return "FC_BYTE_COUNT_POINTER"; 00148 case RPC_FC_TRANSMIT_AS: return "FC_TRANSMIT_AS"; 00149 case RPC_FC_REPRESENT_AS: return "FC_REPRESENT_AS"; 00150 case RPC_FC_IP: return "FC_IP"; 00151 case RPC_FC_BIND_CONTEXT: return "FC_BIND_CONTEXT"; 00152 case RPC_FC_BIND_GENERIC: return "FC_BIND_GENERIC"; 00153 case RPC_FC_BIND_PRIMITIVE: return "FC_BIND_PRIMITIVE"; 00154 case RPC_FC_AUTO_HANDLE: return "FC_AUTO_HANDLE"; 00155 case RPC_FC_CALLBACK_HANDLE: return "FC_CALLBACK_HANDLE"; 00156 case RPC_FC_STRUCTPAD1: return "FC_STRUCTPAD1"; 00157 case RPC_FC_STRUCTPAD2: return "FC_STRUCTPAD2"; 00158 case RPC_FC_STRUCTPAD3: return "FC_STRUCTPAD3"; 00159 case RPC_FC_STRUCTPAD4: return "FC_STRUCTPAD4"; 00160 case RPC_FC_STRUCTPAD5: return "FC_STRUCTPAD5"; 00161 case RPC_FC_STRUCTPAD6: return "FC_STRUCTPAD6"; 00162 case RPC_FC_STRUCTPAD7: return "FC_STRUCTPAD7"; 00163 case RPC_FC_STRING_SIZED: return "FC_STRING_SIZED"; 00164 case RPC_FC_NO_REPEAT: return "FC_NO_REPEAT"; 00165 case RPC_FC_FIXED_REPEAT: return "FC_FIXED_REPEAT"; 00166 case RPC_FC_VARIABLE_REPEAT: return "FC_VARIABLE_REPEAT"; 00167 case RPC_FC_FIXED_OFFSET: return "FC_FIXED_OFFSET"; 00168 case RPC_FC_VARIABLE_OFFSET: return "FC_VARIABLE_OFFSET"; 00169 case RPC_FC_PP: return "FC_PP"; 00170 case RPC_FC_EMBEDDED_COMPLEX: return "FC_EMBEDDED_COMPLEX"; 00171 case RPC_FC_DEREFERENCE: return "FC_DEREFERENCE"; 00172 case RPC_FC_DIV_2: return "FC_DIV_2"; 00173 case RPC_FC_MULT_2: return "FC_MULT_2"; 00174 case RPC_FC_ADD_1: return "FC_ADD_1"; 00175 case RPC_FC_SUB_1: return "FC_SUB_1"; 00176 case RPC_FC_CALLBACK: return "FC_CALLBACK"; 00177 case RPC_FC_CONSTANT_IID: return "FC_CONSTANT_IID"; 00178 case RPC_FC_END: return "FC_END"; 00179 case RPC_FC_PAD: return "FC_PAD"; 00180 case RPC_FC_USER_MARSHAL: return "FC_USER_MARSHAL"; 00181 case RPC_FC_RANGE: return "FC_RANGE"; 00182 case RPC_FC_INT3264: return "FC_INT3264"; 00183 case RPC_FC_UINT3264: return "FC_UINT3264"; 00184 default: 00185 error("string_of_type: unknown type 0x%02x\n", type); 00186 return NULL; 00187 } 00188 } 00189 00190 static void *get_aliaschain_attrp(const type_t *type, enum attr_type attr) 00191 { 00192 const type_t *t = type; 00193 for (;;) 00194 { 00195 if (is_attr(t->attrs, attr)) 00196 return get_attrp(t->attrs, attr); 00197 else if (type_is_alias(t)) 00198 t = type_alias_get_aliasee(t); 00199 else return NULL; 00200 } 00201 } 00202 00203 unsigned char get_basic_fc(const type_t *type) 00204 { 00205 int sign = type_basic_get_sign(type); 00206 switch (type_basic_get_type(type)) 00207 { 00208 case TYPE_BASIC_INT8: return (sign <= 0 ? RPC_FC_SMALL : RPC_FC_USMALL); 00209 case TYPE_BASIC_INT16: return (sign <= 0 ? RPC_FC_SHORT : RPC_FC_USHORT); 00210 case TYPE_BASIC_INT32: return (sign <= 0 ? RPC_FC_LONG : RPC_FC_ULONG); 00211 case TYPE_BASIC_INT64: return RPC_FC_HYPER; 00212 case TYPE_BASIC_INT: return (sign <= 0 ? RPC_FC_LONG : RPC_FC_ULONG); 00213 case TYPE_BASIC_INT3264: return (sign <= 0 ? RPC_FC_INT3264 : RPC_FC_UINT3264); 00214 case TYPE_BASIC_BYTE: return RPC_FC_BYTE; 00215 case TYPE_BASIC_CHAR: return RPC_FC_CHAR; 00216 case TYPE_BASIC_WCHAR: return RPC_FC_WCHAR; 00217 case TYPE_BASIC_HYPER: return RPC_FC_HYPER; 00218 case TYPE_BASIC_FLOAT: return RPC_FC_FLOAT; 00219 case TYPE_BASIC_DOUBLE: return RPC_FC_DOUBLE; 00220 case TYPE_BASIC_ERROR_STATUS_T: return RPC_FC_ERROR_STATUS_T; 00221 case TYPE_BASIC_HANDLE: return RPC_FC_BIND_PRIMITIVE; 00222 } 00223 return 0; 00224 } 00225 00226 static unsigned char get_basic_fc_signed(const type_t *type) 00227 { 00228 switch (type_basic_get_type(type)) 00229 { 00230 case TYPE_BASIC_INT8: return RPC_FC_SMALL; 00231 case TYPE_BASIC_INT16: return RPC_FC_SHORT; 00232 case TYPE_BASIC_INT32: return RPC_FC_LONG; 00233 case TYPE_BASIC_INT64: return RPC_FC_HYPER; 00234 case TYPE_BASIC_INT: return RPC_FC_LONG; 00235 case TYPE_BASIC_INT3264: return RPC_FC_INT3264; 00236 case TYPE_BASIC_BYTE: return RPC_FC_BYTE; 00237 case TYPE_BASIC_CHAR: return RPC_FC_CHAR; 00238 case TYPE_BASIC_WCHAR: return RPC_FC_WCHAR; 00239 case TYPE_BASIC_HYPER: return RPC_FC_HYPER; 00240 case TYPE_BASIC_FLOAT: return RPC_FC_FLOAT; 00241 case TYPE_BASIC_DOUBLE: return RPC_FC_DOUBLE; 00242 case TYPE_BASIC_ERROR_STATUS_T: return RPC_FC_ERROR_STATUS_T; 00243 case TYPE_BASIC_HANDLE: return RPC_FC_BIND_PRIMITIVE; 00244 } 00245 return 0; 00246 } 00247 00248 static inline unsigned int clamp_align(unsigned int align) 00249 { 00250 unsigned int packing = (pointer_size == 4) ? win32_packing : win64_packing; 00251 if(align > packing) align = packing; 00252 return align; 00253 } 00254 00255 unsigned char get_pointer_fc(const type_t *type, const attr_list_t *attrs, int toplevel_param) 00256 { 00257 const type_t *t; 00258 int pointer_type; 00259 00260 assert(is_ptr(type) || is_array(type)); 00261 00262 pointer_type = get_attrv(attrs, ATTR_POINTERTYPE); 00263 if (pointer_type) 00264 return pointer_type; 00265 00266 for (t = type; type_is_alias(t); t = type_alias_get_aliasee(t)) 00267 { 00268 pointer_type = get_attrv(t->attrs, ATTR_POINTERTYPE); 00269 if (pointer_type) 00270 return pointer_type; 00271 } 00272 00273 if (toplevel_param) 00274 return RPC_FC_RP; 00275 else if (is_ptr(type)) 00276 return type_pointer_get_default_fc(type); 00277 else 00278 return type_array_get_ptr_default_fc(type); 00279 } 00280 00281 static unsigned char get_pointer_fc_context( const type_t *type, const attr_list_t *attrs, 00282 enum type_context context ) 00283 { 00284 int pointer_fc = get_pointer_fc(type, attrs, context == TYPE_CONTEXT_TOPLEVELPARAM); 00285 00286 if (pointer_fc == RPC_FC_UP && is_attr( attrs, ATTR_OUT ) && 00287 context == TYPE_CONTEXT_PARAM && is_object( current_iface )) 00288 pointer_fc = RPC_FC_OP; 00289 00290 return pointer_fc; 00291 } 00292 00293 static unsigned char get_enum_fc(const type_t *type) 00294 { 00295 assert(type_get_type(type) == TYPE_ENUM); 00296 if (is_aliaschain_attr(type, ATTR_V1ENUM)) 00297 return RPC_FC_ENUM32; 00298 else 00299 return RPC_FC_ENUM16; 00300 } 00301 00302 static type_t *get_user_type(const type_t *t, const char **pname) 00303 { 00304 for (;;) 00305 { 00306 type_t *ut = get_attrp(t->attrs, ATTR_WIREMARSHAL); 00307 if (ut) 00308 { 00309 if (pname) 00310 *pname = t->name; 00311 return ut; 00312 } 00313 00314 if (type_is_alias(t)) 00315 t = type_alias_get_aliasee(t); 00316 else 00317 return NULL; 00318 } 00319 } 00320 00321 static int is_user_type(const type_t *t) 00322 { 00323 return get_user_type(t, NULL) != NULL; 00324 } 00325 00326 enum typegen_type typegen_detect_type(const type_t *type, const attr_list_t *attrs, unsigned int flags) 00327 { 00328 if (is_user_type(type)) 00329 return TGT_USER_TYPE; 00330 00331 if (is_aliaschain_attr(type, ATTR_CONTEXTHANDLE)) 00332 return TGT_CTXT_HANDLE; 00333 00334 if (!(flags & TDT_IGNORE_STRINGS) && is_string_type(attrs, type)) 00335 return TGT_STRING; 00336 00337 switch (type_get_type(type)) 00338 { 00339 case TYPE_BASIC: 00340 if (!(flags & TDT_IGNORE_RANGES) && 00341 (is_attr(attrs, ATTR_RANGE) || is_aliaschain_attr(type, ATTR_RANGE))) 00342 return TGT_RANGE; 00343 return TGT_BASIC; 00344 case TYPE_ENUM: 00345 if (!(flags & TDT_IGNORE_RANGES) && 00346 (is_attr(attrs, ATTR_RANGE) || is_aliaschain_attr(type, ATTR_RANGE))) 00347 return TGT_RANGE; 00348 return TGT_ENUM; 00349 case TYPE_POINTER: 00350 if (type_get_type(type_pointer_get_ref(type)) == TYPE_INTERFACE || 00351 (type_get_type(type_pointer_get_ref(type)) == TYPE_VOID && is_attr(attrs, ATTR_IIDIS))) 00352 return TGT_IFACE_POINTER; 00353 else if (is_aliaschain_attr(type_pointer_get_ref(type), ATTR_CONTEXTHANDLE)) 00354 return TGT_CTXT_HANDLE_POINTER; 00355 else 00356 return TGT_POINTER; 00357 case TYPE_STRUCT: 00358 return TGT_STRUCT; 00359 case TYPE_ENCAPSULATED_UNION: 00360 case TYPE_UNION: 00361 return TGT_UNION; 00362 case TYPE_ARRAY: 00363 return TGT_ARRAY; 00364 case TYPE_FUNCTION: 00365 case TYPE_COCLASS: 00366 case TYPE_INTERFACE: 00367 case TYPE_MODULE: 00368 case TYPE_VOID: 00369 case TYPE_ALIAS: 00370 case TYPE_BITFIELD: 00371 break; 00372 } 00373 return TGT_INVALID; 00374 } 00375 00376 static int cant_be_null(const var_t *v) 00377 { 00378 switch (typegen_detect_type(v->type, v->attrs, TDT_IGNORE_STRINGS)) 00379 { 00380 case TGT_ARRAY: 00381 if (!type_array_is_decl_as_ptr( v->type )) return 0; 00382 /* fall through */ 00383 case TGT_POINTER: 00384 return (get_pointer_fc(v->type, v->attrs, TRUE) == RPC_FC_RP); 00385 case TGT_CTXT_HANDLE_POINTER: 00386 return TRUE; 00387 default: 00388 return 0; 00389 } 00390 00391 } 00392 00393 static int get_padding(const var_list_t *fields) 00394 { 00395 unsigned short offset = 0; 00396 unsigned int salign = 1; 00397 const var_t *f; 00398 00399 if (!fields) 00400 return 0; 00401 00402 LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry) 00403 { 00404 type_t *ft = f->type; 00405 unsigned int align = 0; 00406 unsigned int size = type_memsize_and_alignment(ft, &align); 00407 align = clamp_align(align); 00408 if (align > salign) salign = align; 00409 offset = ROUND_SIZE(offset, align); 00410 offset += size; 00411 } 00412 00413 return ROUNDING(offset, salign); 00414 } 00415 00416 static unsigned int get_stack_size( const type_t *type, const attr_list_t *attrs, int *by_value ) 00417 { 00418 unsigned int stack_size; 00419 int by_val; 00420 00421 switch (typegen_detect_type( type, attrs, TDT_ALL_TYPES )) 00422 { 00423 case TGT_BASIC: 00424 case TGT_ENUM: 00425 case TGT_RANGE: 00426 case TGT_STRUCT: 00427 case TGT_UNION: 00428 case TGT_USER_TYPE: 00429 stack_size = type_memsize( type ); 00430 by_val = (pointer_size < 8 || stack_size <= pointer_size); /* FIXME: should be platform-specific */ 00431 break; 00432 default: 00433 by_val = 0; 00434 break; 00435 } 00436 if (!by_val) stack_size = pointer_size; 00437 if (by_value) *by_value = by_val; 00438 return ROUND_SIZE( stack_size, pointer_size ); 00439 } 00440 00441 static unsigned char get_contexthandle_flags( const type_t *iface, const attr_list_t *attrs, 00442 const type_t *type ) 00443 { 00444 unsigned char flags = 0; 00445 00446 if (is_attr(iface->attrs, ATTR_STRICTCONTEXTHANDLE)) flags |= NDR_STRICT_CONTEXT_HANDLE; 00447 00448 if (is_ptr(type) && 00449 !is_attr( type->attrs, ATTR_CONTEXTHANDLE ) && 00450 !is_attr( attrs, ATTR_CONTEXTHANDLE )) 00451 flags |= 0x80; 00452 00453 if (is_attr(attrs, ATTR_IN)) 00454 { 00455 flags |= 0x40; 00456 if (!is_attr(attrs, ATTR_OUT)) flags |= NDR_CONTEXT_HANDLE_CANNOT_BE_NULL; 00457 } 00458 if (is_attr(attrs, ATTR_OUT)) flags |= 0x20; 00459 00460 return flags; 00461 } 00462 00463 static unsigned int get_rpc_flags( const attr_list_t *attrs ) 00464 { 00465 unsigned int flags = 0; 00466 00467 if (is_attr( attrs, ATTR_IDEMPOTENT )) flags |= 0x0001; 00468 if (is_attr( attrs, ATTR_BROADCAST )) flags |= 0x0002; 00469 if (is_attr( attrs, ATTR_MAYBE )) flags |= 0x0004; 00470 if (is_attr( attrs, ATTR_MESSAGE )) flags |= 0x0100; 00471 if (is_attr( attrs, ATTR_ASYNC )) flags |= 0x4000; 00472 return flags; 00473 } 00474 00475 unsigned char get_struct_fc(const type_t *type) 00476 { 00477 int has_pointer = 0; 00478 int has_conformance = 0; 00479 int has_variance = 0; 00480 var_t *field; 00481 var_list_t *fields; 00482 00483 fields = type_struct_get_fields(type); 00484 00485 if (get_padding(fields)) 00486 return RPC_FC_BOGUS_STRUCT; 00487 00488 if (fields) LIST_FOR_EACH_ENTRY( field, fields, var_t, entry ) 00489 { 00490 type_t *t = field->type; 00491 enum typegen_type typegen_type; 00492 00493 typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS); 00494 00495 if (typegen_type == TGT_ARRAY && !type_array_is_decl_as_ptr(t)) 00496 { 00497 if (is_string_type(field->attrs, field->type)) 00498 { 00499 if (is_conformant_array(t)) 00500 has_conformance = 1; 00501 has_variance = 1; 00502 continue; 00503 } 00504 00505 if (is_array(type_array_get_element(field->type))) 00506 return RPC_FC_BOGUS_STRUCT; 00507 00508 if (type_array_has_conformance(field->type)) 00509 { 00510 has_conformance = 1; 00511 if (list_next(fields, &field->entry)) 00512 error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n", 00513 field->name); 00514 } 00515 if (type_array_has_variance(t)) 00516 has_variance = 1; 00517 00518 t = type_array_get_element(t); 00519 typegen_type = typegen_detect_type(t, field->attrs, TDT_IGNORE_STRINGS); 00520 } 00521 00522 switch (typegen_type) 00523 { 00524 case TGT_USER_TYPE: 00525 case TGT_IFACE_POINTER: 00526 return RPC_FC_BOGUS_STRUCT; 00527 case TGT_BASIC: 00528 if (type_basic_get_type(t) == TYPE_BASIC_INT3264 && pointer_size != 4) 00529 return RPC_FC_BOGUS_STRUCT; 00530 break; 00531 case TGT_ENUM: 00532 if (get_enum_fc(t) == RPC_FC_ENUM16) 00533 return RPC_FC_BOGUS_STRUCT; 00534 break; 00535 case TGT_POINTER: 00536 case TGT_ARRAY: 00537 if (get_pointer_fc(t, field->attrs, FALSE) == RPC_FC_RP || pointer_size != 4) 00538 return RPC_FC_BOGUS_STRUCT; 00539 has_pointer = 1; 00540 break; 00541 case TGT_UNION: 00542 return RPC_FC_BOGUS_STRUCT; 00543 case TGT_STRUCT: 00544 { 00545 unsigned char fc = get_struct_fc(t); 00546 switch (fc) 00547 { 00548 case RPC_FC_STRUCT: 00549 break; 00550 case RPC_FC_CVSTRUCT: 00551 has_conformance = 1; 00552 has_variance = 1; 00553 has_pointer = 1; 00554 break; 00555 00556 case RPC_FC_CPSTRUCT: 00557 has_conformance = 1; 00558 if (list_next( fields, &field->entry )) 00559 error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n", 00560 field->name); 00561 has_pointer = 1; 00562 break; 00563 00564 case RPC_FC_CSTRUCT: 00565 has_conformance = 1; 00566 if (list_next( fields, &field->entry )) 00567 error_loc("field '%s' deriving from a conformant array must be the last field in the structure\n", 00568 field->name); 00569 break; 00570 00571 case RPC_FC_PSTRUCT: 00572 has_pointer = 1; 00573 break; 00574 00575 default: 00576 error_loc("Unknown struct member %s with type (0x%02x)\n", field->name, fc); 00577 /* fallthru - treat it as complex */ 00578 00579 /* as soon as we see one of these these members, it's bogus... */ 00580 case RPC_FC_BOGUS_STRUCT: 00581 return RPC_FC_BOGUS_STRUCT; 00582 } 00583 break; 00584 } 00585 case TGT_RANGE: 00586 return RPC_FC_BOGUS_STRUCT; 00587 case TGT_STRING: 00588 /* shouldn't get here because of TDT_IGNORE_STRINGS above. fall through */ 00589 case TGT_INVALID: 00590 case TGT_CTXT_HANDLE: 00591 case TGT_CTXT_HANDLE_POINTER: 00592 /* checking after parsing should mean that we don't get here. if we do, 00593 * it's a checker bug */ 00594 assert(0); 00595 } 00596 } 00597 00598 if( has_variance ) 00599 { 00600 if ( has_conformance ) 00601 return RPC_FC_CVSTRUCT; 00602 else 00603 return RPC_FC_BOGUS_STRUCT; 00604 } 00605 if( has_conformance && has_pointer ) 00606 return RPC_FC_CPSTRUCT; 00607 if( has_conformance ) 00608 return RPC_FC_CSTRUCT; 00609 if( has_pointer ) 00610 return RPC_FC_PSTRUCT; 00611 return RPC_FC_STRUCT; 00612 } 00613 00614 static unsigned char get_array_fc(const type_t *type) 00615 { 00616 unsigned char fc; 00617 const expr_t *size_is; 00618 const type_t *elem_type; 00619 00620 elem_type = type_array_get_element(type); 00621 size_is = type_array_get_conformance(type); 00622 00623 if (!size_is) 00624 { 00625 unsigned int size = type_memsize(elem_type); 00626 if (size * type_array_get_dim(type) > 0xffffuL) 00627 fc = RPC_FC_LGFARRAY; 00628 else 00629 fc = RPC_FC_SMFARRAY; 00630 } 00631 else 00632 fc = RPC_FC_CARRAY; 00633 00634 if (type_array_has_variance(type)) 00635 { 00636 if (fc == RPC_FC_SMFARRAY) 00637 fc = RPC_FC_SMVARRAY; 00638 else if (fc == RPC_FC_LGFARRAY) 00639 fc = RPC_FC_LGVARRAY; 00640 else if (fc == RPC_FC_CARRAY) 00641 fc = RPC_FC_CVARRAY; 00642 } 00643 00644 switch (typegen_detect_type(elem_type, NULL, TDT_IGNORE_STRINGS)) 00645 { 00646 case TGT_USER_TYPE: 00647 fc = RPC_FC_BOGUS_ARRAY; 00648 break; 00649 case TGT_BASIC: 00650 if (type_basic_get_type(elem_type) == TYPE_BASIC_INT3264 && 00651 pointer_size != 4) 00652 fc = RPC_FC_BOGUS_ARRAY; 00653 break; 00654 case TGT_STRUCT: 00655 switch (get_struct_fc(elem_type)) 00656 { 00657 case RPC_FC_BOGUS_STRUCT: 00658 fc = RPC_FC_BOGUS_ARRAY; 00659 break; 00660 } 00661 break; 00662 case TGT_ENUM: 00663 /* is 16-bit enum - if so, wire size differs from mem size and so 00664 * the array cannot be block copied, which means the array is complex */ 00665 if (get_enum_fc(elem_type) == RPC_FC_ENUM16) 00666 fc = RPC_FC_BOGUS_ARRAY; 00667 break; 00668 case TGT_UNION: 00669 case TGT_IFACE_POINTER: 00670 fc = RPC_FC_BOGUS_ARRAY; 00671 break; 00672 case TGT_POINTER: 00673 /* ref pointers cannot just be block copied. unique pointers to 00674 * interfaces need special treatment. either case means the array is 00675 * complex */ 00676 if (get_pointer_fc(elem_type, NULL, FALSE) == RPC_FC_RP || pointer_size != 4) 00677 fc = RPC_FC_BOGUS_ARRAY; 00678 break; 00679 case TGT_RANGE: 00680 fc = RPC_FC_BOGUS_ARRAY; 00681 break; 00682 case TGT_CTXT_HANDLE: 00683 case TGT_CTXT_HANDLE_POINTER: 00684 case TGT_STRING: 00685 case TGT_INVALID: 00686 case TGT_ARRAY: 00687 /* nothing to do for everything else */ 00688 break; 00689 } 00690 00691 return fc; 00692 } 00693 00694 static int is_non_complex_struct(const type_t *type) 00695 { 00696 return (type_get_type(type) == TYPE_STRUCT && 00697 get_struct_fc(type) != RPC_FC_BOGUS_STRUCT); 00698 } 00699 00700 static int type_has_pointers(const type_t *type) 00701 { 00702 switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS)) 00703 { 00704 case TGT_USER_TYPE: 00705 return FALSE; 00706 case TGT_POINTER: 00707 return TRUE; 00708 case TGT_ARRAY: 00709 return type_array_is_decl_as_ptr(type) || type_has_pointers(type_array_get_element(type)); 00710 case TGT_STRUCT: 00711 { 00712 var_list_t *fields = type_struct_get_fields(type); 00713 const var_t *field; 00714 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) 00715 { 00716 if (type_has_pointers(field->type)) 00717 return TRUE; 00718 } 00719 break; 00720 } 00721 case TGT_UNION: 00722 { 00723 var_list_t *fields; 00724 const var_t *field; 00725 fields = type_union_get_cases(type); 00726 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) 00727 { 00728 if (field->type && type_has_pointers(field->type)) 00729 return TRUE; 00730 } 00731 break; 00732 } 00733 case TGT_CTXT_HANDLE: 00734 case TGT_CTXT_HANDLE_POINTER: 00735 case TGT_STRING: 00736 case TGT_IFACE_POINTER: 00737 case TGT_BASIC: 00738 case TGT_ENUM: 00739 case TGT_RANGE: 00740 case TGT_INVALID: 00741 break; 00742 } 00743 00744 return FALSE; 00745 } 00746 00747 static int type_has_full_pointer(const type_t *type, const attr_list_t *attrs, 00748 int toplevel_param) 00749 { 00750 switch (typegen_detect_type(type, NULL, TDT_IGNORE_STRINGS)) 00751 { 00752 case TGT_USER_TYPE: 00753 return FALSE; 00754 case TGT_POINTER: 00755 if (get_pointer_fc(type, attrs, toplevel_param) == RPC_FC_FP) 00756 return TRUE; 00757 else 00758 return FALSE; 00759 case TGT_ARRAY: 00760 if (get_pointer_fc(type, attrs, toplevel_param) == RPC_FC_FP) 00761 return TRUE; 00762 else 00763 return type_has_full_pointer(type_array_get_element(type), NULL, FALSE); 00764 case TGT_STRUCT: 00765 { 00766 var_list_t *fields = type_struct_get_fields(type); 00767 const var_t *field; 00768 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) 00769 { 00770 if (type_has_full_pointer(field->type, field->attrs, FALSE)) 00771 return TRUE; 00772 } 00773 break; 00774 } 00775 case TGT_UNION: 00776 { 00777 var_list_t *fields; 00778 const var_t *field; 00779 fields = type_union_get_cases(type); 00780 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) 00781 { 00782 if (field->type && type_has_full_pointer(field->type, field->attrs, FALSE)) 00783 return TRUE; 00784 } 00785 break; 00786 } 00787 case TGT_CTXT_HANDLE: 00788 case TGT_CTXT_HANDLE_POINTER: 00789 case TGT_STRING: 00790 case TGT_IFACE_POINTER: 00791 case TGT_BASIC: 00792 case TGT_ENUM: 00793 case TGT_RANGE: 00794 case TGT_INVALID: 00795 break; 00796 } 00797 00798 return FALSE; 00799 } 00800 00801 static unsigned short user_type_offset(const char *name) 00802 { 00803 user_type_t *ut; 00804 unsigned short off = 0; 00805 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) 00806 { 00807 if (strcmp(name, ut->name) == 0) 00808 return off; 00809 ++off; 00810 } 00811 error("user_type_offset: couldn't find type (%s)\n", name); 00812 return 0; 00813 } 00814 00815 static void update_tfsoff(type_t *type, unsigned int offset, FILE *file) 00816 { 00817 type->typestring_offset = offset; 00818 if (file) type->tfswrite = FALSE; 00819 } 00820 00821 static void guard_rec(type_t *type) 00822 { 00823 /* types that contain references to themselves (like a linked list), 00824 need to be shielded from infinite recursion when writing embedded 00825 types */ 00826 if (type->typestring_offset) 00827 type->tfswrite = FALSE; 00828 else 00829 type->typestring_offset = 1; 00830 } 00831 00832 static int is_embedded_complex(const type_t *type) 00833 { 00834 switch (typegen_detect_type(type, NULL, TDT_ALL_TYPES)) 00835 { 00836 case TGT_USER_TYPE: 00837 case TGT_STRUCT: 00838 case TGT_UNION: 00839 case TGT_ARRAY: 00840 case TGT_IFACE_POINTER: 00841 return TRUE; 00842 default: 00843 return FALSE; 00844 } 00845 } 00846 00847 static const char *get_context_handle_type_name(const type_t *type) 00848 { 00849 const type_t *t; 00850 for (t = type; 00851 is_ptr(t) || type_is_alias(t); 00852 t = type_is_alias(t) ? type_alias_get_aliasee(t) : type_pointer_get_ref(t)) 00853 if (is_attr(t->attrs, ATTR_CONTEXTHANDLE)) 00854 return t->name; 00855 assert(0); 00856 return NULL; 00857 } 00858 00859 #define WRITE_FCTYPE(file, fctype, typestring_offset) \ 00860 do { \ 00861 if (file) \ 00862 fprintf(file, "/* %2u */\n", typestring_offset); \ 00863 print_file((file), 2, "0x%02x, /* " #fctype " */\n", RPC_##fctype); \ 00864 } \ 00865 while (0) 00866 00867 static void print_file(FILE *file, int indent, const char *format, ...) __attribute__((format (printf, 3, 4))); 00868 static void print_file(FILE *file, int indent, const char *format, ...) 00869 { 00870 va_list va; 00871 va_start(va, format); 00872 print(file, indent, format, va); 00873 va_end(va); 00874 } 00875 00876 void print(FILE *file, int indent, const char *format, va_list va) 00877 { 00878 if (file) 00879 { 00880 if (format[0] != '\n') 00881 while (0 < indent--) 00882 fprintf(file, " "); 00883 vfprintf(file, format, va); 00884 } 00885 } 00886 00887 00888 static void write_var_init(FILE *file, int indent, const type_t *t, const char *n, const char *local_var_prefix) 00889 { 00890 if (decl_indirect(t)) 00891 { 00892 print_file(file, indent, "MIDL_memset(&%s%s, 0, sizeof(%s%s));\n", 00893 local_var_prefix, n, local_var_prefix, n); 00894 print_file(file, indent, "%s_p_%s = &%s%s;\n", local_var_prefix, n, local_var_prefix, n); 00895 } 00896 else if (is_ptr(t) || is_array(t)) 00897 print_file(file, indent, "%s%s = 0;\n", local_var_prefix, n); 00898 } 00899 00900 void write_parameters_init(FILE *file, int indent, const var_t *func, const char *local_var_prefix) 00901 { 00902 const var_t *var; 00903 00904 if (!is_void(type_function_get_rettype(func->type))) 00905 write_var_init(file, indent, type_function_get_rettype(func->type), "_RetVal", local_var_prefix); 00906 00907 if (!type_get_function_args(func->type)) 00908 return; 00909 00910 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 00911 write_var_init(file, indent, var->type, var->name, local_var_prefix); 00912 00913 fprintf(file, "\n"); 00914 } 00915 00916 static void write_formatdesc(FILE *f, int indent, const char *str) 00917 { 00918 print_file(f, indent, "typedef struct _MIDL_%s_FORMAT_STRING\n", str); 00919 print_file(f, indent, "{\n"); 00920 print_file(f, indent + 1, "short Pad;\n"); 00921 print_file(f, indent + 1, "unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str); 00922 print_file(f, indent, "} MIDL_%s_FORMAT_STRING;\n", str); 00923 print_file(f, indent, "\n"); 00924 } 00925 00926 void write_formatstringsdecl(FILE *f, int indent, const statement_list_t *stmts, type_pred_t pred) 00927 { 00928 clear_all_offsets(); 00929 00930 print_file(f, indent, "#define TYPE_FORMAT_STRING_SIZE %d\n", 00931 get_size_typeformatstring(stmts, pred)); 00932 00933 print_file(f, indent, "#define PROC_FORMAT_STRING_SIZE %d\n", 00934 get_size_procformatstring(stmts, pred)); 00935 00936 fprintf(f, "\n"); 00937 write_formatdesc(f, indent, "TYPE"); 00938 write_formatdesc(f, indent, "PROC"); 00939 fprintf(f, "\n"); 00940 print_file(f, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n"); 00941 print_file(f, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n"); 00942 print_file(f, indent, "\n"); 00943 } 00944 00945 int decl_indirect(const type_t *t) 00946 { 00947 if (is_user_type(t)) 00948 return TRUE; 00949 return (type_get_type(t) != TYPE_BASIC && 00950 type_get_type(t) != TYPE_ENUM && 00951 type_get_type(t) != TYPE_POINTER && 00952 type_get_type(t) != TYPE_ARRAY); 00953 } 00954 00955 static unsigned char get_parameter_fc( const type_t *type, const attr_list_t *attrs, int is_return, 00956 unsigned short *flags, unsigned int *stack_size, 00957 unsigned int *typestring_offset ) 00958 { 00959 unsigned int alignment, server_size = 0, buffer_size = 0; 00960 unsigned char fc = 0; 00961 int is_byval; 00962 int is_in = is_attr(attrs, ATTR_IN); 00963 int is_out = is_attr(attrs, ATTR_OUT); 00964 00965 if (is_return) is_out = TRUE; 00966 else if (!is_in && !is_out) is_in = TRUE; 00967 00968 *flags = 0; 00969 *stack_size = get_stack_size( type, attrs, &is_byval ); 00970 *typestring_offset = type->typestring_offset; 00971 00972 if (is_in) *flags |= IsIn; 00973 if (is_out) *flags |= IsOut; 00974 if (is_return) *flags |= IsReturn; 00975 00976 if (!is_string_type( attrs, type )) 00977 buffer_size = get_required_buffer_size_type( type, NULL, attrs, TRUE, &alignment ); 00978 00979 switch (typegen_detect_type( type, attrs, TDT_ALL_TYPES )) 00980 { 00981 case TGT_BASIC: 00982 *flags |= IsBasetype; 00983 fc = get_basic_fc_signed( type ); 00984 if (fc == RPC_FC_BIND_PRIMITIVE) 00985 { 00986 buffer_size = 4; /* actually 0 but avoids setting MustSize */ 00987 fc = RPC_FC_LONG; 00988 } 00989 break; 00990 case TGT_ENUM: 00991 *flags |= IsBasetype; 00992 fc = get_enum_fc( type ); 00993 break; 00994 case TGT_RANGE: 00995 *flags |= IsByValue; 00996 break; 00997 case TGT_STRUCT: 00998 case TGT_UNION: 00999 case TGT_USER_TYPE: 01000 *flags |= MustFree | (is_byval ? IsByValue : IsSimpleRef); 01001 break; 01002 case TGT_IFACE_POINTER: 01003 *flags |= MustFree; 01004 break; 01005 case TGT_ARRAY: 01006 *flags |= MustFree; 01007 if (type_array_is_decl_as_ptr(type) && type->details.array.ptr_tfsoff && 01008 get_pointer_fc( type, attrs, !is_return ) == RPC_FC_RP) 01009 *flags |= IsSimpleRef; 01010 break; 01011 case TGT_STRING: 01012 *flags |= MustFree; 01013 if (is_declptr( type ) && get_pointer_fc( type, attrs, !is_return ) == RPC_FC_RP) 01014 { 01015 /* skip over pointer description straight to string description */ 01016 if (is_conformant_array( type )) *typestring_offset += 4; 01017 else *typestring_offset += 2; 01018 *flags |= IsSimpleRef; 01019 } 01020 break; 01021 case TGT_CTXT_HANDLE_POINTER: 01022 *flags |= IsSimpleRef; 01023 *typestring_offset += 4; 01024 /* fall through */ 01025 case TGT_CTXT_HANDLE: 01026 buffer_size = 20; 01027 break; 01028 case TGT_POINTER: 01029 if (get_pointer_fc( type, attrs, !is_return ) == RPC_FC_RP) 01030 { 01031 const type_t *ref = type_pointer_get_ref( type ); 01032 01033 if (!is_string_type( attrs, ref )) 01034 buffer_size = get_required_buffer_size_type( ref, NULL, NULL, TRUE, &alignment ); 01035 01036 switch (typegen_detect_type( ref, NULL, TDT_ALL_TYPES )) 01037 { 01038 case TGT_BASIC: 01039 *flags |= IsSimpleRef | IsBasetype; 01040 fc = get_basic_fc( ref ); 01041 if (!is_in && is_out) server_size = pointer_size; 01042 break; 01043 case TGT_ENUM: 01044 if ((fc = get_enum_fc( ref )) == RPC_FC_ENUM32) 01045 { 01046 *flags |= IsSimpleRef | IsBasetype; 01047 if (!is_in && is_out) server_size = pointer_size; 01048 } 01049 else 01050 { 01051 server_size = pointer_size; 01052 } 01053 break; 01054 case TGT_UNION: 01055 case TGT_USER_TYPE: 01056 case TGT_RANGE: 01057 *flags |= IsSimpleRef | MustFree; 01058 *typestring_offset = ref->typestring_offset; 01059 if (!is_in && is_out) server_size = type_memsize( ref ); 01060 break; 01061 case TGT_STRING: 01062 case TGT_POINTER: 01063 case TGT_ARRAY: 01064 case TGT_CTXT_HANDLE: 01065 case TGT_CTXT_HANDLE_POINTER: 01066 *flags |= MustFree; 01067 server_size = pointer_size; 01068 break; 01069 case TGT_IFACE_POINTER: 01070 *flags |= MustFree; 01071 if (is_in && is_out) server_size = pointer_size; 01072 break; 01073 case TGT_STRUCT: 01074 *flags |= IsSimpleRef | MustFree; 01075 *typestring_offset = ref->typestring_offset; 01076 switch (get_struct_fc(ref)) 01077 { 01078 case RPC_FC_STRUCT: 01079 case RPC_FC_PSTRUCT: 01080 case RPC_FC_BOGUS_STRUCT: 01081 if (!is_in && is_out) server_size = type_memsize( ref ); 01082 break; 01083 default: 01084 break; 01085 } 01086 break; 01087 case TGT_INVALID: 01088 assert(0); 01089 } 01090 } 01091 else /* not ref pointer */ 01092 { 01093 *flags |= MustFree; 01094 } 01095 break; 01096 case TGT_INVALID: 01097 assert(0); 01098 } 01099 01100 if (!buffer_size) *flags |= MustSize; 01101 01102 if (server_size) 01103 { 01104 server_size = (server_size + 7) / 8; 01105 if (server_size < 8) *flags |= server_size << 13; 01106 } 01107 return fc; 01108 } 01109 01110 static unsigned char get_func_oi2_flags( const var_t *func ) 01111 { 01112 const var_t *var; 01113 var_list_t *args = type_get_function_args( func->type ); 01114 type_t *ret_type = type_function_get_rettype( func->type ); 01115 unsigned char oi2_flags = 0x40; /* HasExtensions */ 01116 unsigned short flags; 01117 unsigned int stack_size, typestring_offset; 01118 01119 if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) 01120 { 01121 get_parameter_fc( var->type, var->attrs, 0, &flags, &stack_size, &typestring_offset ); 01122 if (flags & MustSize) 01123 { 01124 if (flags & IsIn) oi2_flags |= 0x02; /* ClientMustSize */ 01125 if (flags & IsOut) oi2_flags |= 0x01; /* ServerMustSize */ 01126 } 01127 } 01128 01129 if (!is_void( ret_type )) 01130 { 01131 oi2_flags |= 0x04; /* HasRet */ 01132 get_parameter_fc( ret_type, NULL, 1, &flags, &stack_size, &typestring_offset ); 01133 if (flags & MustSize) oi2_flags |= 0x01; /* ServerMustSize */ 01134 } 01135 return oi2_flags; 01136 } 01137 01138 static unsigned int write_new_procformatstring_type(FILE *file, int indent, 01139 const type_t *type, 01140 const attr_list_t *attrs, 01141 int is_return, unsigned int *stack_offset) 01142 { 01143 char buffer[64]; 01144 unsigned int stack_size, typestring_offset; 01145 unsigned short flags; 01146 unsigned char fc = get_parameter_fc( type, attrs, is_return, &flags, &stack_size, &typestring_offset ); 01147 01148 strcpy( buffer, "/* flags:" ); 01149 if (flags & MustSize) strcat( buffer, " must size," ); 01150 if (flags & MustFree) strcat( buffer, " must free," ); 01151 if (flags & IsPipe) strcat( buffer, " pipe," ); 01152 if (flags & IsIn) strcat( buffer, " in," ); 01153 if (flags & IsOut) strcat( buffer, " out," ); 01154 if (flags & IsReturn) strcat( buffer, " return," ); 01155 if (flags & IsBasetype) strcat( buffer, " base type," ); 01156 if (flags & IsByValue) strcat( buffer, " by value," ); 01157 if (flags & IsSimpleRef) strcat( buffer, " simple ref," ); 01158 if (flags >> 13) sprintf( buffer + strlen(buffer), " srv size=%u,", (flags >> 13) * 8 ); 01159 strcpy( buffer + strlen( buffer ) - 1, " */" ); 01160 print_file( file, indent, "NdrFcShort(0x%hx),\t%s\n", flags, buffer ); 01161 print_file( file, indent, "NdrFcShort(0x%hx), /* stack offset = %hu */\n", 01162 *stack_offset, *stack_offset ); 01163 if (flags & IsBasetype) 01164 { 01165 print_file( file, indent, "0x%02x, /* %s */\n", fc, string_of_type(fc) ); 01166 print_file( file, indent, "0x0,\n" ); 01167 } 01168 else 01169 print_file( file, indent, "NdrFcShort(0x%x), /* type offset = %u */\n", 01170 typestring_offset, typestring_offset ); 01171 *stack_offset += max( stack_size, pointer_size ); 01172 return 6; 01173 } 01174 01175 static unsigned int write_old_procformatstring_type(FILE *file, int indent, 01176 const type_t *type, 01177 const attr_list_t *attrs, 01178 int is_return, int is_interpreted) 01179 { 01180 unsigned int size; 01181 01182 int is_in = is_attr(attrs, ATTR_IN); 01183 int is_out = is_attr(attrs, ATTR_OUT); 01184 01185 if (!is_in && !is_out) is_in = TRUE; 01186 01187 if (type_get_type(type) == TYPE_BASIC || 01188 type_get_type(type) == TYPE_ENUM) 01189 { 01190 unsigned char fc; 01191 01192 if (is_return) 01193 print_file(file, indent, "0x53, /* FC_RETURN_PARAM_BASETYPE */\n"); 01194 else 01195 print_file(file, indent, "0x4e, /* FC_IN_PARAM_BASETYPE */\n"); 01196 01197 if (type_get_type(type) == TYPE_ENUM) 01198 { 01199 fc = get_enum_fc(type); 01200 } 01201 else 01202 { 01203 fc = get_basic_fc_signed(type); 01204 01205 if (fc == RPC_FC_BIND_PRIMITIVE) 01206 fc = RPC_FC_IGNORE; 01207 } 01208 01209 print_file(file, indent, "0x%02x, /* %s */\n", 01210 fc, string_of_type(fc)); 01211 size = 2; /* includes param type prefix */ 01212 } 01213 else 01214 { 01215 unsigned short offset = type->typestring_offset; 01216 01217 if (is_interpreted && is_array(type) && 01218 type_array_is_decl_as_ptr(type) && 01219 type->details.array.ptr_tfsoff) 01220 offset = type->details.array.ptr_tfsoff; 01221 01222 if (is_return) 01223 print_file(file, indent, "0x52, /* FC_RETURN_PARAM */\n"); 01224 else if (is_in && is_out) 01225 print_file(file, indent, "0x50, /* FC_IN_OUT_PARAM */\n"); 01226 else if (is_out) 01227 print_file(file, indent, "0x51, /* FC_OUT_PARAM */\n"); 01228 else 01229 print_file(file, indent, "0x4d, /* FC_IN_PARAM */\n"); 01230 01231 size = get_stack_size( type, attrs, NULL ); 01232 print_file(file, indent, "0x%02x,\n", size / pointer_size ); 01233 print_file(file, indent, "NdrFcShort(0x%x), /* type offset = %u */\n", offset, offset); 01234 size = 4; /* includes param type prefix */ 01235 } 01236 return size; 01237 } 01238 01239 int is_interpreted_func( const type_t *iface, const var_t *func ) 01240 { 01241 const char *str; 01242 const var_t *var; 01243 const var_list_t *args = type_get_function_args( func->type ); 01244 const type_t *ret_type = type_function_get_rettype( func->type ); 01245 01246 if (type_get_type( ret_type ) == TYPE_BASIC) 01247 { 01248 switch (type_basic_get_type( ret_type )) 01249 { 01250 case TYPE_BASIC_INT64: 01251 case TYPE_BASIC_HYPER: 01252 /* return value must fit in a long_ptr */ 01253 if (pointer_size < 8) return 0; 01254 break; 01255 case TYPE_BASIC_FLOAT: 01256 case TYPE_BASIC_DOUBLE: 01257 /* floating point values can't be returned */ 01258 return 0; 01259 default: 01260 break; 01261 } 01262 } 01263 if (get_stub_mode() != MODE_Oif && args) 01264 { 01265 LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) 01266 switch (type_get_type( var->type )) 01267 { 01268 case TYPE_BASIC: 01269 switch (type_basic_get_type( var->type )) 01270 { 01271 /* floating point arguments are not supported in Oi mode */ 01272 case TYPE_BASIC_FLOAT: return 0; 01273 case TYPE_BASIC_DOUBLE: return 0; 01274 default: break; 01275 } 01276 break; 01277 /* unions passed by value are not supported in Oi mode */ 01278 case TYPE_UNION: return 0; 01279 case TYPE_ENCAPSULATED_UNION: return 0; 01280 default: break; 01281 } 01282 } 01283 01284 if ((str = get_attrp( func->attrs, ATTR_OPTIMIZE ))) return !strcmp( str, "i" ); 01285 if ((str = get_attrp( iface->attrs, ATTR_OPTIMIZE ))) return !strcmp( str, "i" ); 01286 return (get_stub_mode() != MODE_Os); 01287 } 01288 01289 static void write_proc_func_header( FILE *file, int indent, const type_t *iface, 01290 const var_t *func, unsigned int *offset, 01291 unsigned short num_proc ) 01292 { 01293 var_t *var; 01294 var_list_t *args = type_get_function_args( func->type ); 01295 unsigned char explicit_fc, implicit_fc; 01296 unsigned char handle_flags; 01297 const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc ); 01298 unsigned char oi_flags = RPC_FC_PROC_OIF_RPCFLAGS | RPC_FC_PROC_OIF_NEWINIT; 01299 unsigned int rpc_flags = get_rpc_flags( func->attrs ); 01300 unsigned int nb_args = 0; 01301 unsigned int stack_size = 0; 01302 unsigned short param_num = 0; 01303 unsigned short handle_stack_offset = 0; 01304 unsigned short handle_param_num = 0; 01305 01306 if (is_full_pointer_function( func )) oi_flags |= RPC_FC_PROC_OIF_FULLPTR; 01307 if (is_object( iface )) 01308 { 01309 oi_flags |= RPC_FC_PROC_OIF_OBJECT; 01310 if (get_stub_mode() == MODE_Oif) oi_flags |= RPC_FC_PROC_OIF_OBJ_V2; 01311 stack_size += pointer_size; 01312 } 01313 01314 if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry ) 01315 { 01316 if (var == handle_var) 01317 { 01318 handle_stack_offset = stack_size; 01319 handle_param_num = param_num; 01320 } 01321 stack_size += get_stack_size( var->type, var->attrs, NULL ); 01322 param_num++; 01323 nb_args++; 01324 } 01325 if (!is_void( type_function_get_rettype( func->type ))) 01326 { 01327 stack_size += pointer_size; 01328 nb_args++; 01329 } 01330 01331 print_file( file, 0, "/* %u (procedure %s::%s) */\n", *offset, iface->name, func->name ); 01332 print_file( file, indent, "0x%02x,\t/* %s */\n", implicit_fc, 01333 implicit_fc ? string_of_type(implicit_fc) : "explicit handle" ); 01334 print_file( file, indent, "0x%02x,\n", oi_flags ); 01335 print_file( file, indent, "NdrFcLong(0x%x),\n", rpc_flags ); 01336 print_file( file, indent, "NdrFcShort(0x%hx),\t/* method %hu */\n", num_proc, num_proc ); 01337 print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack size = %hu */\n", stack_size, stack_size ); 01338 *offset += 10; 01339 01340 if (!implicit_fc) 01341 { 01342 switch (explicit_fc) 01343 { 01344 case RPC_FC_BIND_PRIMITIVE: 01345 handle_flags = 0; 01346 print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) ); 01347 print_file( file, indent, "0x%02x,\n", handle_flags ); 01348 print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n", 01349 handle_stack_offset, handle_stack_offset ); 01350 *offset += 4; 01351 break; 01352 case RPC_FC_BIND_GENERIC: 01353 handle_flags = type_memsize( handle_var->type ); 01354 print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) ); 01355 print_file( file, indent, "0x%02x,\n", handle_flags ); 01356 print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n", 01357 handle_stack_offset, handle_stack_offset ); 01358 print_file( file, indent, "0x%02x,\n", get_generic_handle_offset( handle_var->type ) ); 01359 print_file( file, indent, "0x%x,\t/* FC_PAD */\n", RPC_FC_PAD); 01360 *offset += 6; 01361 break; 01362 case RPC_FC_BIND_CONTEXT: 01363 handle_flags = get_contexthandle_flags( iface, handle_var->attrs, handle_var->type ); 01364 print_file( file, indent, "0x%02x,\t/* %s */\n", explicit_fc, string_of_type(explicit_fc) ); 01365 print_file( file, indent, "0x%02x,\n", handle_flags ); 01366 print_file( file, indent, "NdrFcShort(0x%hx),\t/* stack offset = %hu */\n", 01367 handle_stack_offset, handle_stack_offset ); 01368 print_file( file, indent, "0x%02x,\n", get_context_handle_offset( handle_var->type ) ); 01369 print_file( file, indent, "0x%02x,\t/* param %hu */\n", handle_param_num, handle_param_num ); 01370 *offset += 6; 01371 break; 01372 } 01373 } 01374 01375 if (get_stub_mode() == MODE_Oif) 01376 { 01377 unsigned char oi2_flags = get_func_oi2_flags( func ); 01378 unsigned char ext_flags = 0; 01379 unsigned int size; 01380 01381 if (is_attr( func->attrs, ATTR_NOTIFY )) ext_flags |= 0x08; /* HasNotify */ 01382 if (is_attr( func->attrs, ATTR_NOTIFYFLAG )) ext_flags |= 0x10; /* HasNotify2 */ 01383 01384 size = get_function_buffer_size( func, PASS_IN ); 01385 print_file( file, indent, "NdrFcShort(0x%x),\t/* client buffer = %hu */\n", size, size ); 01386 size = get_function_buffer_size( func, PASS_OUT ); 01387 print_file( file, indent, "NdrFcShort(0x%x),\t/* server buffer = %hu */\n", size, size ); 01388 print_file( file, indent, "0x%02x,\n", oi2_flags ); 01389 print_file( file, indent, "0x%02x,\t/* %u params */\n", nb_args, nb_args ); 01390 print_file( file, indent, "0x%02x,\n", pointer_size == 8 ? 10 : 8 ); 01391 print_file( file, indent, "0x%02x,\n", ext_flags ); 01392 print_file( file, indent, "NdrFcShort(0x0),\n" ); /* server corr hint */ 01393 print_file( file, indent, "NdrFcShort(0x0),\n" ); /* client corr hint */ 01394 print_file( file, indent, "NdrFcShort(0x0),\n" ); /* FIXME: notify index */ 01395 *offset += 14; 01396 if (pointer_size == 8) 01397 { 01398 unsigned short pos = 0, fpu_mask = 0; 01399 01400 if (is_object( iface )) pos += 2; 01401 if (args) LIST_FOR_EACH_ENTRY( var, args, var_t, entry ) 01402 { 01403 if (type_get_type( var->type ) == TYPE_BASIC) 01404 { 01405 switch (type_basic_get_type( var->type )) 01406 { 01407 case TYPE_BASIC_FLOAT: fpu_mask |= 1 << pos; break; 01408 case TYPE_BASIC_DOUBLE: fpu_mask |= 2 << pos; break; 01409 default: break; 01410 } 01411 } 01412 pos += 2; 01413 if (pos >= 16) break; 01414 } 01415 print_file( file, indent, "NdrFcShort(0x%x),\n", fpu_mask ); /* floating point mask */ 01416 *offset += 2; 01417 } 01418 } 01419 } 01420 01421 static void write_procformatstring_func( FILE *file, int indent, const type_t *iface, 01422 const var_t *func, unsigned int *offset, 01423 unsigned short num_proc ) 01424 { 01425 unsigned int stack_offset = is_object( iface ) ? pointer_size : 0; 01426 int is_interpreted = is_interpreted_func( iface, func ); 01427 int is_new_style = is_interpreted && (get_stub_mode() == MODE_Oif); 01428 01429 if (is_interpreted) write_proc_func_header( file, indent, iface, func, offset, num_proc ); 01430 01431 /* emit argument data */ 01432 if (type_get_function_args(func->type)) 01433 { 01434 const var_t *var; 01435 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 01436 { 01437 print_file( file, 0, "/* %u (parameter %s) */\n", *offset, var->name ); 01438 if (is_new_style) 01439 *offset += write_new_procformatstring_type(file, indent, var->type, var->attrs, 01440 FALSE, &stack_offset); 01441 else 01442 *offset += write_old_procformatstring_type(file, indent, var->type, var->attrs, 01443 FALSE, is_interpreted); 01444 } 01445 } 01446 01447 /* emit return value data */ 01448 if (is_void(type_function_get_rettype(func->type))) 01449 { 01450 if (!is_new_style) 01451 { 01452 print_file(file, 0, "/* %u (void) */\n", *offset); 01453 print_file(file, indent, "0x5b, /* FC_END */\n"); 01454 print_file(file, indent, "0x5c, /* FC_PAD */\n"); 01455 *offset += 2; 01456 } 01457 } 01458 else 01459 { 01460 print_file( file, 0, "/* %u (return value) */\n", *offset ); 01461 if (is_new_style) 01462 *offset += write_new_procformatstring_type(file, indent, type_function_get_rettype(func->type), 01463 NULL, TRUE, &stack_offset); 01464 else 01465 *offset += write_old_procformatstring_type(file, indent, type_function_get_rettype(func->type), 01466 NULL, TRUE, is_interpreted); 01467 } 01468 } 01469 01470 static void write_procformatstring_stmts(FILE *file, int indent, const statement_list_t *stmts, 01471 type_pred_t pred, unsigned int *offset) 01472 { 01473 const statement_t *stmt; 01474 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 01475 { 01476 if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE) 01477 { 01478 const statement_t *stmt_func; 01479 const type_t *iface = stmt->u.type; 01480 const type_t *parent = type_iface_get_inherit( iface ); 01481 int count = parent ? count_methods( parent ) : 0; 01482 01483 if (!pred(iface)) continue; 01484 STATEMENTS_FOR_EACH_FUNC(stmt_func, type_iface_get_stmts(iface)) 01485 { 01486 var_t *func = stmt_func->u.var; 01487 if (is_local(func->attrs)) continue; 01488 write_procformatstring_func( file, indent, iface, func, offset, count++ ); 01489 } 01490 } 01491 else if (stmt->type == STMT_LIBRARY) 01492 write_procformatstring_stmts(file, indent, stmt->u.lib->stmts, pred, offset); 01493 } 01494 } 01495 01496 void write_procformatstring(FILE *file, const statement_list_t *stmts, type_pred_t pred) 01497 { 01498 int indent = 0; 01499 unsigned int offset = 0; 01500 01501 print_file(file, indent, "static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n"); 01502 print_file(file, indent, "{\n"); 01503 indent++; 01504 print_file(file, indent, "0,\n"); 01505 print_file(file, indent, "{\n"); 01506 indent++; 01507 01508 write_procformatstring_stmts(file, indent, stmts, pred, &offset); 01509 01510 print_file(file, indent, "0x0\n"); 01511 indent--; 01512 print_file(file, indent, "}\n"); 01513 indent--; 01514 print_file(file, indent, "};\n"); 01515 print_file(file, indent, "\n"); 01516 } 01517 01518 void write_procformatstring_offsets( FILE *file, const type_t *iface ) 01519 { 01520 const statement_t *stmt; 01521 int indent = 0; 01522 01523 print_file( file, indent, "static const unsigned short %s_FormatStringOffsetTable[] =\n", 01524 iface->name ); 01525 print_file( file, indent, "{\n" ); 01526 indent++; 01527 STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) 01528 { 01529 var_t *func = stmt->u.var; 01530 if (is_local( func->attrs )) continue; 01531 print_file( file, indent, "%u, /* %s */\n", func->procstring_offset, func->name ); 01532 } 01533 indent--; 01534 print_file( file, indent, "};\n\n" ); 01535 } 01536 01537 static int write_base_type(FILE *file, const type_t *type, unsigned int *typestring_offset) 01538 { 01539 unsigned char fc; 01540 01541 if (type_get_type(type) == TYPE_BASIC) 01542 fc = get_basic_fc_signed(type); 01543 else if (type_get_type(type) == TYPE_ENUM) 01544 fc = get_enum_fc(type); 01545 else 01546 return 0; 01547 01548 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc)); 01549 *typestring_offset += 1; 01550 return 1; 01551 } 01552 01553 /* write conformance / variance descriptor */ 01554 static unsigned int write_conf_or_var_desc(FILE *file, const type_t *cont_type, 01555 unsigned int baseoff, const type_t *type, 01556 const expr_t *expr) 01557 { 01558 unsigned char operator_type = 0; 01559 unsigned char conftype = RPC_FC_NORMAL_CONFORMANCE; 01560 const char *conftype_string = "field"; 01561 const expr_t *subexpr; 01562 const type_t *iface = NULL; 01563 const char *name; 01564 01565 if (!expr) 01566 { 01567 print_file(file, 2, "NdrFcLong(0xffffffff),\t/* -1 */\n"); 01568 return 4; 01569 } 01570 01571 if (expr->is_const) 01572 { 01573 if (expr->cval > UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX) 01574 error("write_conf_or_var_desc: constant value %d is greater than " 01575 "the maximum constant size of %d\n", expr->cval, 01576 UCHAR_MAX * (USHRT_MAX + 1) + USHRT_MAX); 01577 01578 print_file(file, 2, "0x%x, /* Corr desc: constant, val = %d */\n", 01579 RPC_FC_CONSTANT_CONFORMANCE, expr->cval); 01580 print_file(file, 2, "0x%x,\n", expr->cval >> 16); 01581 print_file(file, 2, "NdrFcShort(0x%hx),\n", (unsigned short)expr->cval); 01582 01583 return 4; 01584 } 01585 01586 if (!cont_type) /* top-level conformance */ 01587 { 01588 conftype = RPC_FC_TOP_LEVEL_CONFORMANCE; 01589 conftype_string = "parameter"; 01590 cont_type = current_func->type; 01591 name = current_func->name; 01592 iface = current_iface; 01593 } 01594 else 01595 { 01596 name = cont_type->name; 01597 if (is_ptr(type) || (is_array(type) && type_array_is_decl_as_ptr(type))) 01598 { 01599 conftype = RPC_FC_POINTER_CONFORMANCE; 01600 conftype_string = "field pointer"; 01601 } 01602 } 01603 01604 subexpr = expr; 01605 switch (subexpr->type) 01606 { 01607 case EXPR_PPTR: 01608 subexpr = subexpr->ref; 01609 operator_type = RPC_FC_DEREFERENCE; 01610 break; 01611 case EXPR_DIV: 01612 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2)) 01613 { 01614 subexpr = subexpr->ref; 01615 operator_type = RPC_FC_DIV_2; 01616 } 01617 break; 01618 case EXPR_MUL: 01619 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 2)) 01620 { 01621 subexpr = subexpr->ref; 01622 operator_type = RPC_FC_MULT_2; 01623 } 01624 break; 01625 case EXPR_SUB: 01626 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1)) 01627 { 01628 subexpr = subexpr->ref; 01629 operator_type = RPC_FC_SUB_1; 01630 } 01631 break; 01632 case EXPR_ADD: 01633 if (subexpr->u.ext->is_const && (subexpr->u.ext->cval == 1)) 01634 { 01635 subexpr = subexpr->ref; 01636 operator_type = RPC_FC_ADD_1; 01637 } 01638 break; 01639 default: 01640 break; 01641 } 01642 01643 if (subexpr->type == EXPR_IDENTIFIER) 01644 { 01645 const type_t *correlation_variable = NULL; 01646 unsigned char param_type = 0; 01647 unsigned int offset = 0; 01648 const var_t *var; 01649 struct expr_loc expr_loc; 01650 01651 if (type_get_type(cont_type) == TYPE_FUNCTION) 01652 { 01653 var_list_t *args = type_get_function_args( cont_type ); 01654 01655 if (is_object( iface )) offset += pointer_size; 01656 if (args) LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) 01657 { 01658 if (var->name && !strcmp(var->name, subexpr->u.sval)) 01659 { 01660 expr_loc.v = var; 01661 correlation_variable = var->type; 01662 break; 01663 } 01664 offset += get_stack_size( var->type, var->attrs, NULL ); 01665 } 01666 } 01667 else 01668 { 01669 var_list_t *fields = type_struct_get_fields( cont_type ); 01670 01671 if (fields) LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry ) 01672 { 01673 unsigned int size = field_memsize( var->type, &offset ); 01674 if (var->name && !strcmp(var->name, subexpr->u.sval)) 01675 { 01676 expr_loc.v = var; 01677 correlation_variable = var->type; 01678 break; 01679 } 01680 offset += size; 01681 } 01682 } 01683 01684 if (!correlation_variable) 01685 error("write_conf_or_var_desc: couldn't find variable %s in %s\n", subexpr->u.sval, name); 01686 expr_loc.attr = NULL; 01687 correlation_variable = expr_resolve_type(&expr_loc, cont_type, expr); 01688 01689 offset -= baseoff; 01690 01691 if (type_get_type(correlation_variable) == TYPE_BASIC) 01692 { 01693 switch (get_basic_fc(correlation_variable)) 01694 { 01695 case RPC_FC_CHAR: 01696 case RPC_FC_SMALL: 01697 param_type = RPC_FC_SMALL; 01698 break; 01699 case RPC_FC_BYTE: 01700 case RPC_FC_USMALL: 01701 param_type = RPC_FC_USMALL; 01702 break; 01703 case RPC_FC_WCHAR: 01704 case RPC_FC_SHORT: 01705 param_type = RPC_FC_SHORT; 01706 break; 01707 case RPC_FC_USHORT: 01708 param_type = RPC_FC_USHORT; 01709 break; 01710 case RPC_FC_LONG: 01711 param_type = RPC_FC_LONG; 01712 break; 01713 case RPC_FC_ULONG: 01714 param_type = RPC_FC_ULONG; 01715 break; 01716 default: 01717 error("write_conf_or_var_desc: conformance variable type not supported 0x%x\n", 01718 get_basic_fc(correlation_variable)); 01719 } 01720 } 01721 else if (type_get_type(correlation_variable) == TYPE_ENUM) 01722 { 01723 if (get_enum_fc(correlation_variable) == RPC_FC_ENUM32) 01724 param_type = RPC_FC_LONG; 01725 else 01726 param_type = RPC_FC_SHORT; 01727 } 01728 else if (type_get_type(correlation_variable) == TYPE_POINTER) 01729 { 01730 if (pointer_size == 8) 01731 param_type = RPC_FC_HYPER; 01732 else 01733 param_type = RPC_FC_LONG; 01734 } 01735 else 01736 { 01737 error("write_conf_or_var_desc: non-arithmetic type used as correlation variable %s\n", 01738 subexpr->u.sval); 01739 return 0; 01740 } 01741 01742 print_file(file, 2, "0x%x,\t/* Corr desc: %s %s, %s */\n", 01743 conftype | param_type, conftype_string, subexpr->u.sval, string_of_type(param_type)); 01744 print_file(file, 2, "0x%x,\t/* %s */\n", operator_type, 01745 operator_type ? string_of_type(operator_type) : "no operators"); 01746 print_file(file, 2, "NdrFcShort(0x%hx),\t/* offset = %d */\n", 01747 (unsigned short)offset, offset); 01748 } 01749 else if (!iface || is_interpreted_func( iface, current_func )) 01750 { 01751 unsigned int callback_offset = 0; 01752 struct expr_eval_routine *eval; 01753 int found = 0; 01754 01755 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry) 01756 { 01757 if (eval->cont_type == cont_type || 01758 (type_get_type( eval->cont_type ) == type_get_type( cont_type ) && 01759 eval->iface == iface && 01760 eval->name && name && !strcmp(eval->name, name) && 01761 !compare_expr(eval->expr, expr))) 01762 { 01763 found = 1; 01764 break; 01765 } 01766 callback_offset++; 01767 } 01768 01769 if (!found) 01770 { 01771 eval = xmalloc (sizeof(*eval)); 01772 eval->iface = iface; 01773 eval->cont_type = cont_type; 01774 eval->name = xstrdup( name ); 01775 eval->baseoff = baseoff; 01776 eval->expr = expr; 01777 list_add_tail (&expr_eval_routines, &eval->entry); 01778 } 01779 01780 if (callback_offset > USHRT_MAX) 01781 error("Maximum number of callback routines reached\n"); 01782 01783 print_file(file, 2, "0x%x,\t/* Corr desc: %s in %s */\n", conftype, conftype_string, name); 01784 print_file(file, 2, "0x%x,\t/* %s */\n", RPC_FC_CALLBACK, "FC_CALLBACK"); 01785 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)callback_offset, callback_offset); 01786 } 01787 else /* output a dummy corr desc that isn't used */ 01788 { 01789 print_file(file, 2, "0x%x,\t/* Corr desc: unused for %s */\n", conftype, name); 01790 print_file(file, 2, "0x0,\n" ); 01791 print_file(file, 2, "NdrFcShort(0x0),\n" ); 01792 } 01793 return 4; 01794 } 01795 01796 /* return size and start offset of a data field based on current offset */ 01797 static unsigned int field_memsize(const type_t *type, unsigned int *offset) 01798 { 01799 unsigned int align = 0; 01800 unsigned int size = type_memsize_and_alignment( type, &align ); 01801 01802 *offset = ROUND_SIZE( *offset, align ); 01803 return size; 01804 } 01805 01806 static unsigned int fields_memsize(const var_list_t *fields, unsigned int *align) 01807 { 01808 unsigned int size = 0; 01809 unsigned int max_align; 01810 const var_t *v; 01811 01812 if (!fields) return 0; 01813 LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry ) 01814 { 01815 unsigned int falign = 0; 01816 unsigned int fsize = type_memsize_and_alignment(v->type, &falign); 01817 if (*align < falign) *align = falign; 01818 falign = clamp_align(falign); 01819 size = ROUND_SIZE(size, falign); 01820 size += fsize; 01821 } 01822 01823 max_align = clamp_align(*align); 01824 size = ROUND_SIZE(size, max_align); 01825 01826 return size; 01827 } 01828 01829 static unsigned int union_memsize(const var_list_t *fields, unsigned int *pmaxa) 01830 { 01831 unsigned int size, maxs = 0; 01832 unsigned int align = *pmaxa; 01833 const var_t *v; 01834 01835 if (fields) LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry ) 01836 { 01837 /* we could have an empty default field with NULL type */ 01838 if (v->type) 01839 { 01840 size = type_memsize_and_alignment(v->type, &align); 01841 if (maxs < size) maxs = size; 01842 if (*pmaxa < align) *pmaxa = align; 01843 } 01844 } 01845 01846 return maxs; 01847 } 01848 01849 static unsigned int type_memsize_and_alignment(const type_t *t, unsigned int *align) 01850 { 01851 unsigned int size = 0; 01852 01853 switch (type_get_type(t)) 01854 { 01855 case TYPE_BASIC: 01856 switch (get_basic_fc(t)) 01857 { 01858 case RPC_FC_BYTE: 01859 case RPC_FC_CHAR: 01860 case RPC_FC_USMALL: 01861 case RPC_FC_SMALL: 01862 size = 1; 01863 if (size > *align) *align = size; 01864 break; 01865 case RPC_FC_WCHAR: 01866 case RPC_FC_USHORT: 01867 case RPC_FC_SHORT: 01868 size = 2; 01869 if (size > *align) *align = size; 01870 break; 01871 case RPC_FC_ULONG: 01872 case RPC_FC_LONG: 01873 case RPC_FC_ERROR_STATUS_T: 01874 case RPC_FC_FLOAT: 01875 size = 4; 01876 if (size > *align) *align = size; 01877 break; 01878 case RPC_FC_HYPER: 01879 case RPC_FC_DOUBLE: 01880 size = 8; 01881 if (size > *align) *align = size; 01882 break; 01883 case RPC_FC_INT3264: 01884 case RPC_FC_UINT3264: 01885 case RPC_FC_BIND_PRIMITIVE: 01886 assert( pointer_size ); 01887 size = pointer_size; 01888 if (size > *align) *align = size; 01889 break; 01890 default: 01891 error("type_memsize: Unknown type 0x%x\n", get_basic_fc(t)); 01892 size = 0; 01893 } 01894 break; 01895 case TYPE_ENUM: 01896 switch (get_enum_fc(t)) 01897 { 01898 case RPC_FC_ENUM16: 01899 case RPC_FC_ENUM32: 01900 size = 4; 01901 if (size > *align) *align = size; 01902 break; 01903 default: 01904 error("type_memsize: Unknown enum type\n"); 01905 size = 0; 01906 } 01907 break; 01908 case TYPE_STRUCT: 01909 size = fields_memsize(type_struct_get_fields(t), align); 01910 break; 01911 case TYPE_ENCAPSULATED_UNION: 01912 size = fields_memsize(type_encapsulated_union_get_fields(t), align); 01913 break; 01914 case TYPE_UNION: 01915 size = union_memsize(type_union_get_cases(t), align); 01916 break; 01917 case TYPE_POINTER: 01918 assert( pointer_size ); 01919 size = pointer_size; 01920 if (size > *align) *align = size; 01921 break; 01922 case TYPE_ARRAY: 01923 if (!type_array_is_decl_as_ptr(t)) 01924 { 01925 if (is_conformant_array(t)) 01926 { 01927 type_memsize_and_alignment(type_array_get_element(t), align); 01928 size = 0; 01929 } 01930 else 01931 size = type_array_get_dim(t) * 01932 type_memsize_and_alignment(type_array_get_element(t), align); 01933 } 01934 else /* declared as a pointer */ 01935 { 01936 assert( pointer_size ); 01937 size = pointer_size; 01938 if (size > *align) *align = size; 01939 } 01940 break; 01941 case TYPE_INTERFACE: 01942 case TYPE_ALIAS: 01943 case TYPE_VOID: 01944 case TYPE_COCLASS: 01945 case TYPE_MODULE: 01946 case TYPE_FUNCTION: 01947 case TYPE_BITFIELD: 01948 /* these types should not be encountered here due to language 01949 * restrictions (interface, void, coclass, module), logical 01950 * restrictions (alias - due to type_get_type call above) or 01951 * checking restrictions (function, bitfield). */ 01952 assert(0); 01953 } 01954 01955 return size; 01956 } 01957 01958 unsigned int type_memsize(const type_t *t) 01959 { 01960 unsigned int align = 0; 01961 return type_memsize_and_alignment( t, &align ); 01962 } 01963 01964 static unsigned int type_buffer_alignment(const type_t *t) 01965 { 01966 const var_list_t *fields; 01967 const var_t *var; 01968 unsigned int max = 0, align; 01969 01970 switch (type_get_type(t)) 01971 { 01972 case TYPE_BASIC: 01973 switch (get_basic_fc(t)) 01974 { 01975 case RPC_FC_BYTE: 01976 case RPC_FC_CHAR: 01977 case RPC_FC_USMALL: 01978 case RPC_FC_SMALL: 01979 return 1; 01980 case RPC_FC_WCHAR: 01981 case RPC_FC_USHORT: 01982 case RPC_FC_SHORT: 01983 return 2; 01984 case RPC_FC_ULONG: 01985 case RPC_FC_LONG: 01986 case RPC_FC_ERROR_STATUS_T: 01987 case RPC_FC_FLOAT: 01988 case RPC_FC_INT3264: 01989 case RPC_FC_UINT3264: 01990 return 4; 01991 case RPC_FC_HYPER: 01992 case RPC_FC_DOUBLE: 01993 return 8; 01994 default: 01995 error("type_buffer_alignment: Unknown type 0x%x\n", get_basic_fc(t)); 01996 } 01997 break; 01998 case TYPE_ENUM: 01999 switch (get_enum_fc(t)) 02000 { 02001 case RPC_FC_ENUM16: 02002 return 2; 02003 case RPC_FC_ENUM32: 02004 return 4; 02005 default: 02006 error("type_buffer_alignment: Unknown enum type\n"); 02007 } 02008 break; 02009 case TYPE_STRUCT: 02010 if (!(fields = type_struct_get_fields(t))) break; 02011 LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry ) 02012 { 02013 if (!var->type) continue; 02014 align = type_buffer_alignment( var->type ); 02015 if (max < align) max = align; 02016 } 02017 break; 02018 case TYPE_ENCAPSULATED_UNION: 02019 if (!(fields = type_encapsulated_union_get_fields(t))) break; 02020 LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry ) 02021 { 02022 if (!var->type) continue; 02023 align = type_buffer_alignment( var->type ); 02024 if (max < align) max = align; 02025 } 02026 break; 02027 case TYPE_UNION: 02028 if (!(fields = type_union_get_cases(t))) break; 02029 LIST_FOR_EACH_ENTRY( var, fields, const var_t, entry ) 02030 { 02031 if (!var->type) continue; 02032 align = type_buffer_alignment( var->type ); 02033 if (max < align) max = align; 02034 } 02035 break; 02036 case TYPE_ARRAY: 02037 if (!type_array_is_decl_as_ptr(t)) 02038 return type_buffer_alignment( type_array_get_element(t) ); 02039 /* else fall through */ 02040 case TYPE_POINTER: 02041 return 4; 02042 case TYPE_INTERFACE: 02043 case TYPE_ALIAS: 02044 case TYPE_VOID: 02045 case TYPE_COCLASS: 02046 case TYPE_MODULE: 02047 case TYPE_FUNCTION: 02048 case TYPE_BITFIELD: 02049 /* these types should not be encountered here due to language 02050 * restrictions (interface, void, coclass, module), logical 02051 * restrictions (alias - due to type_get_type call above) or 02052 * checking restrictions (function, bitfield). */ 02053 assert(0); 02054 } 02055 return max; 02056 } 02057 02058 int is_full_pointer_function(const var_t *func) 02059 { 02060 const var_t *var; 02061 if (type_has_full_pointer(type_function_get_rettype(func->type), func->attrs, TRUE)) 02062 return TRUE; 02063 if (!type_get_function_args(func->type)) 02064 return FALSE; 02065 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 02066 if (type_has_full_pointer( var->type, var->attrs, TRUE )) 02067 return TRUE; 02068 return FALSE; 02069 } 02070 02071 void write_full_pointer_init(FILE *file, int indent, const var_t *func, int is_server) 02072 { 02073 print_file(file, indent, "__frame->_StubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,%s);\n", 02074 is_server ? "XLAT_SERVER" : "XLAT_CLIENT"); 02075 fprintf(file, "\n"); 02076 } 02077 02078 void write_full_pointer_free(FILE *file, int indent, const var_t *func) 02079 { 02080 print_file(file, indent, "NdrFullPointerXlatFree(__frame->_StubMsg.FullPtrXlatTables);\n"); 02081 fprintf(file, "\n"); 02082 } 02083 02084 static unsigned int write_nonsimple_pointer(FILE *file, const attr_list_t *attrs, 02085 const type_t *type, 02086 enum type_context context, 02087 unsigned int offset, 02088 unsigned int *typeformat_offset) 02089 { 02090 unsigned int start_offset = *typeformat_offset; 02091 short reloff = offset - (*typeformat_offset + 2); 02092 int in_attr, out_attr; 02093 int pointer_type; 02094 unsigned char flags = 0; 02095 02096 pointer_type = get_pointer_fc_context(type, attrs, context); 02097 02098 in_attr = is_attr(attrs, ATTR_IN); 02099 out_attr = is_attr(attrs, ATTR_OUT); 02100 if (!in_attr && !out_attr) in_attr = 1; 02101 02102 if (out_attr && !in_attr && pointer_type == RPC_FC_RP) 02103 flags |= RPC_FC_P_ONSTACK; 02104 02105 if (is_ptr(type)) 02106 { 02107 type_t *ref = type_pointer_get_ref(type); 02108 if(is_declptr(ref) && !is_user_type(ref)) 02109 flags |= RPC_FC_P_DEREF; 02110 } 02111 02112 print_file(file, 2, "0x%x, 0x%x,\t\t/* %s", 02113 pointer_type, 02114 flags, 02115 string_of_type(pointer_type)); 02116 if (file) 02117 { 02118 if (flags & RPC_FC_P_ONSTACK) 02119 fprintf(file, " [allocated_on_stack]"); 02120 if (flags & RPC_FC_P_DEREF) 02121 fprintf(file, " [pointer_deref]"); 02122 fprintf(file, " */\n"); 02123 } 02124 02125 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, offset); 02126 *typeformat_offset += 4; 02127 02128 return start_offset; 02129 } 02130 02131 static unsigned int write_simple_pointer(FILE *file, const attr_list_t *attrs, 02132 const type_t *type, enum type_context context) 02133 { 02134 unsigned char fc; 02135 unsigned char pointer_fc; 02136 const type_t *ref; 02137 int in_attr = is_attr(attrs, ATTR_IN); 02138 int out_attr = is_attr(attrs, ATTR_OUT); 02139 unsigned char flags = RPC_FC_P_SIMPLEPOINTER; 02140 02141 /* for historical reasons, write_simple_pointer also handled string types, 02142 * but no longer does. catch bad uses of the function with this check */ 02143 if (is_string_type(attrs, type)) 02144 error("write_simple_pointer: can't handle type %s which is a string type\n", type->name); 02145 02146 pointer_fc = get_pointer_fc_context(type, attrs, context); 02147 02148 ref = type_pointer_get_ref(type); 02149 if (type_get_type(ref) == TYPE_ENUM) 02150 fc = get_enum_fc(ref); 02151 else 02152 fc = get_basic_fc(ref); 02153 02154 if (out_attr && !in_attr) 02155 flags |= RPC_FC_P_ONSTACK; 02156 02157 print_file(file, 2, "0x%02x, 0x%x,\t/* %s %s[simple_pointer] */\n", 02158 pointer_fc, flags, string_of_type(pointer_fc), 02159 flags & RPC_FC_P_ONSTACK ? "[allocated_on_stack] " : ""); 02160 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc)); 02161 print_file(file, 2, "0x5c,\t/* FC_PAD */\n"); 02162 return 4; 02163 } 02164 02165 static void print_start_tfs_comment(FILE *file, type_t *t, unsigned int tfsoff) 02166 { 02167 print_file(file, 0, "/* %u (", tfsoff); 02168 write_type_decl(file, t, NULL); 02169 print_file(file, 0, ") */\n"); 02170 } 02171 02172 static unsigned int write_pointer_tfs(FILE *file, const attr_list_t *attrs, 02173 type_t *type, unsigned int ref_offset, 02174 enum type_context context, 02175 unsigned int *typestring_offset) 02176 { 02177 unsigned int offset = *typestring_offset; 02178 type_t *ref = type_pointer_get_ref(type); 02179 02180 print_start_tfs_comment(file, type, offset); 02181 update_tfsoff(type, offset, file); 02182 02183 switch (typegen_detect_type(ref, attrs, TDT_ALL_TYPES)) 02184 { 02185 case TGT_BASIC: 02186 case TGT_ENUM: 02187 *typestring_offset += write_simple_pointer(file, attrs, type, context); 02188 break; 02189 default: 02190 if (ref_offset) 02191 write_nonsimple_pointer(file, attrs, type, context, ref_offset, typestring_offset); 02192 break; 02193 } 02194 02195 return offset; 02196 } 02197 02198 static int processed(const type_t *type) 02199 { 02200 return type->typestring_offset && !type->tfswrite; 02201 } 02202 02203 static int user_type_has_variable_size(const type_t *t) 02204 { 02205 if (is_ptr(t)) 02206 return TRUE; 02207 else if (type_get_type(t) == TYPE_STRUCT) 02208 { 02209 switch (get_struct_fc(t)) 02210 { 02211 case RPC_FC_PSTRUCT: 02212 case RPC_FC_CSTRUCT: 02213 case RPC_FC_CPSTRUCT: 02214 case RPC_FC_CVSTRUCT: 02215 return TRUE; 02216 } 02217 } 02218 /* Note: Since this only applies to user types, we can't have a conformant 02219 array here, and strings should get filed under pointer in this case. */ 02220 return FALSE; 02221 } 02222 02223 static unsigned int write_user_tfs(FILE *file, type_t *type, unsigned int *tfsoff) 02224 { 02225 unsigned int start, absoff, flags; 02226 const char *name = NULL; 02227 type_t *utype = get_user_type(type, &name); 02228 unsigned int usize = type_memsize(utype); 02229 unsigned int ualign = type_buffer_alignment(utype); 02230 unsigned int size = type_memsize(type); 02231 unsigned short funoff = user_type_offset(name); 02232 short reloff; 02233 02234 if (processed(type)) return type->typestring_offset; 02235 02236 guard_rec(type); 02237 02238 if(user_type_has_variable_size(utype)) usize = 0; 02239 02240 if (type_get_type(utype) == TYPE_BASIC || 02241 type_get_type(utype) == TYPE_ENUM) 02242 { 02243 unsigned char fc; 02244 02245 if (type_get_type(utype) == TYPE_ENUM) 02246 fc = get_enum_fc(utype); 02247 else 02248 fc = get_basic_fc(utype); 02249 02250 absoff = *tfsoff; 02251 print_start_tfs_comment(file, utype, absoff); 02252 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); 02253 print_file(file, 2, "0x5c,\t/* FC_PAD */\n"); 02254 *tfsoff += 2; 02255 } 02256 else 02257 { 02258 if (!processed(utype)) 02259 write_embedded_types(file, NULL, utype, utype->name, TRUE, tfsoff); 02260 absoff = utype->typestring_offset; 02261 } 02262 02263 if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == RPC_FC_RP) 02264 flags = 0x40; 02265 else if (type_get_type(utype) == TYPE_POINTER && get_pointer_fc(utype, NULL, FALSE) == RPC_FC_UP) 02266 flags = 0x80; 02267 else 02268 flags = 0; 02269 02270 start = *tfsoff; 02271 update_tfsoff(type, start, file); 02272 print_start_tfs_comment(file, type, start); 02273 print_file(file, 2, "0x%x,\t/* FC_USER_MARSHAL */\n", RPC_FC_USER_MARSHAL); 02274 print_file(file, 2, "0x%x,\t/* Alignment= %d, Flags= %02x */\n", 02275 flags | (ualign - 1), ualign - 1, flags); 02276 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Function offset= %hu */\n", funoff, funoff); 02277 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)size, size); 02278 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)usize, usize); 02279 *tfsoff += 8; 02280 reloff = absoff - *tfsoff; 02281 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", reloff, reloff, absoff); 02282 *tfsoff += 2; 02283 return start; 02284 } 02285 02286 static void write_member_type(FILE *file, const type_t *cont, 02287 int cont_is_complex, const attr_list_t *attrs, 02288 const type_t *type, unsigned int *corroff, 02289 unsigned int *tfsoff) 02290 { 02291 if (is_embedded_complex(type) && !is_conformant_array(type)) 02292 { 02293 unsigned int absoff; 02294 short reloff; 02295 02296 if (type_get_type(type) == TYPE_UNION && is_attr(attrs, ATTR_SWITCHIS)) 02297 { 02298 absoff = *corroff; 02299 *corroff += 8; 02300 } 02301 else 02302 { 02303 absoff = type->typestring_offset; 02304 } 02305 reloff = absoff - (*tfsoff + 2); 02306 02307 print_file(file, 2, "0x4c,\t/* FC_EMBEDDED_COMPLEX */\n"); 02308 /* padding is represented using FC_STRUCTPAD* types, so presumably 02309 * this is left over in the format for historical purposes in MIDL 02310 * or rpcrt4. */ 02311 print_file(file, 2, "0x0,\n"); 02312 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", 02313 reloff, reloff, absoff); 02314 *tfsoff += 4; 02315 } 02316 else if (is_ptr(type) || is_conformant_array(type)) 02317 { 02318 unsigned char fc = cont_is_complex ? RPC_FC_POINTER : RPC_FC_LONG; 02319 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); 02320 *tfsoff += 1; 02321 } 02322 else if (!write_base_type(file, type, tfsoff)) 02323 error("Unsupported member type %d\n", type_get_type(type)); 02324 } 02325 02326 static void write_array_element_type(FILE *file, const type_t *type, 02327 int cont_is_complex, unsigned int *tfsoff) 02328 { 02329 type_t *elem = type_array_get_element(type); 02330 02331 if (!is_embedded_complex(elem) && is_ptr(elem)) 02332 { 02333 type_t *ref = type_pointer_get_ref(elem); 02334 02335 if (processed(ref)) 02336 { 02337 write_nonsimple_pointer(file, NULL, elem, TYPE_CONTEXT_CONTAINER, 02338 ref->typestring_offset, tfsoff); 02339 return; 02340 } 02341 if (!is_string_type(NULL, elem) && 02342 (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM)) 02343 { 02344 *tfsoff += write_simple_pointer(file, NULL, elem, TYPE_CONTEXT_CONTAINER); 02345 return; 02346 } 02347 } 02348 return write_member_type(file, type, cont_is_complex, NULL, elem, NULL, tfsoff); 02349 } 02350 02351 static void write_end(FILE *file, unsigned int *tfsoff) 02352 { 02353 if (*tfsoff % 2 == 0) 02354 { 02355 print_file(file, 2, "0x%x,\t\t/* FC_PAD */\n", RPC_FC_PAD); 02356 *tfsoff += 1; 02357 } 02358 print_file(file, 2, "0x%x,\t\t/* FC_END */\n", RPC_FC_END); 02359 *tfsoff += 1; 02360 } 02361 02362 static void write_descriptors(FILE *file, type_t *type, unsigned int *tfsoff) 02363 { 02364 unsigned int offset = 0; 02365 var_list_t *fs = type_struct_get_fields(type); 02366 var_t *f; 02367 02368 if (fs) LIST_FOR_EACH_ENTRY(f, fs, var_t, entry) 02369 { 02370 type_t *ft = f->type; 02371 unsigned int size = field_memsize( ft, &offset ); 02372 if (type_get_type(ft) == TYPE_UNION && is_attr(f->attrs, ATTR_SWITCHIS)) 02373 { 02374 short reloff; 02375 unsigned int absoff = ft->typestring_offset; 02376 if (is_attr(ft->attrs, ATTR_SWITCHTYPE)) 02377 absoff += 8; /* we already have a corr descr, skip it */ 02378 reloff = absoff - (*tfsoff + 6); 02379 print_file(file, 0, "/* %d */\n", *tfsoff); 02380 print_file(file, 2, "0x%x,\t/* FC_NON_ENCAPSULATED_UNION */\n", RPC_FC_NON_ENCAPSULATED_UNION); 02381 print_file(file, 2, "0x%x,\t/* FIXME: always FC_LONG */\n", RPC_FC_LONG); 02382 write_conf_or_var_desc(file, current_structure, offset, ft, 02383 get_attrp(f->attrs, ATTR_SWITCHIS)); 02384 print_file(file, 2, "NdrFcShort(%hd),\t/* Offset= %hd (%u) */\n", 02385 reloff, reloff, absoff); 02386 *tfsoff += 8; 02387 } 02388 offset += size; 02389 } 02390 } 02391 02392 static int write_pointer_description_offsets( 02393 FILE *file, const attr_list_t *attrs, type_t *type, 02394 unsigned int *offset_in_memory, unsigned int *offset_in_buffer, 02395 unsigned int *typestring_offset) 02396 { 02397 int written = 0; 02398 02399 if ((is_ptr(type) && type_get_type(type_pointer_get_ref(type)) != TYPE_INTERFACE) || 02400 (is_array(type) && type_array_is_decl_as_ptr(type))) 02401 { 02402 if (offset_in_memory && offset_in_buffer) 02403 { 02404 unsigned int memsize; 02405 02406 /* pointer instance 02407 * 02408 * note that MSDN states that for pointer layouts in structures, 02409 * this is a negative offset from the end of the structure, but 02410 * this statement is incorrect. all offsets are positive */ 02411 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Memory offset = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory); 02412 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Buffer offset = %d */\n", (unsigned short)*offset_in_buffer, *offset_in_buffer); 02413 02414 memsize = type_memsize(type); 02415 *offset_in_memory += memsize; 02416 /* increment these separately as in the case of conformant (varying) 02417 * structures these start at different values */ 02418 *offset_in_buffer += memsize; 02419 } 02420 *typestring_offset += 4; 02421 02422 if (is_ptr(type)) 02423 { 02424 type_t *ref = type_pointer_get_ref(type); 02425 02426 if (is_string_type(attrs, type)) 02427 write_string_tfs(file, attrs, type, TYPE_CONTEXT_CONTAINER, NULL, typestring_offset); 02428 else if (processed(ref)) 02429 write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER, 02430 ref->typestring_offset, typestring_offset); 02431 else if (type_get_type(ref) == TYPE_BASIC || type_get_type(ref) == TYPE_ENUM) 02432 *typestring_offset += write_simple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER); 02433 else 02434 error("write_pointer_description_offsets: type format string unknown\n"); 02435 } 02436 else 02437 { 02438 unsigned int offset = type->typestring_offset; 02439 /* skip over the pointer that is written for strings, since a 02440 * pointer has to be written in-place here */ 02441 if (is_string_type(attrs, type)) 02442 offset += 4; 02443 write_nonsimple_pointer(file, attrs, type, TYPE_CONTEXT_CONTAINER, offset, typestring_offset); 02444 } 02445 02446 return 1; 02447 } 02448 02449 if (is_array(type)) 02450 { 02451 return write_pointer_description_offsets( 02452 file, attrs, type_array_get_element(type), offset_in_memory, 02453 offset_in_buffer, typestring_offset); 02454 } 02455 else if (is_non_complex_struct(type)) 02456 { 02457 /* otherwise search for interesting fields to parse */ 02458 const var_t *v; 02459 LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) 02460 { 02461 if (offset_in_memory && offset_in_buffer) 02462 { 02463 unsigned int padding; 02464 unsigned int align = 0; 02465 type_memsize_and_alignment(v->type, &align); 02466 padding = ROUNDING(*offset_in_memory, align); 02467 *offset_in_memory += padding; 02468 *offset_in_buffer += padding; 02469 } 02470 written += write_pointer_description_offsets( 02471 file, v->attrs, v->type, offset_in_memory, offset_in_buffer, 02472 typestring_offset); 02473 } 02474 } 02475 else 02476 { 02477 if (offset_in_memory && offset_in_buffer) 02478 { 02479 unsigned int memsize = type_memsize(type); 02480 *offset_in_memory += memsize; 02481 /* increment these separately as in the case of conformant (varying) 02482 * structures these start at different values */ 02483 *offset_in_buffer += memsize; 02484 } 02485 } 02486 02487 return written; 02488 } 02489 02490 static int write_no_repeat_pointer_descriptions( 02491 FILE *file, const attr_list_t *attrs, type_t *type, 02492 unsigned int *offset_in_memory, unsigned int *offset_in_buffer, 02493 unsigned int *typestring_offset) 02494 { 02495 int written = 0; 02496 02497 if (is_ptr(type) || 02498 (is_conformant_array(type) && type_array_is_decl_as_ptr(type))) 02499 { 02500 print_file(file, 2, "0x%02x, /* FC_NO_REPEAT */\n", RPC_FC_NO_REPEAT); 02501 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD); 02502 *typestring_offset += 2; 02503 02504 return write_pointer_description_offsets(file, attrs, type, 02505 offset_in_memory, offset_in_buffer, typestring_offset); 02506 } 02507 02508 if (is_non_complex_struct(type)) 02509 { 02510 const var_t *v; 02511 LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) 02512 { 02513 if (offset_in_memory && offset_in_buffer) 02514 { 02515 unsigned int padding; 02516 unsigned int align = 0; 02517 type_memsize_and_alignment(v->type, &align); 02518 padding = ROUNDING(*offset_in_memory, align); 02519 *offset_in_memory += padding; 02520 *offset_in_buffer += padding; 02521 } 02522 written += write_no_repeat_pointer_descriptions( 02523 file, v->attrs, v->type, 02524 offset_in_memory, offset_in_buffer, typestring_offset); 02525 } 02526 } 02527 else 02528 { 02529 unsigned int memsize = type_memsize(type); 02530 *offset_in_memory += memsize; 02531 /* increment these separately as in the case of conformant (varying) 02532 * structures these start at different values */ 02533 *offset_in_buffer += memsize; 02534 } 02535 02536 return written; 02537 } 02538 02539 /* Note: if file is NULL return value is number of pointers to write, else 02540 * it is the number of type format characters written */ 02541 static int write_fixed_array_pointer_descriptions( 02542 FILE *file, const attr_list_t *attrs, type_t *type, 02543 unsigned int *offset_in_memory, unsigned int *offset_in_buffer, 02544 unsigned int *typestring_offset) 02545 { 02546 int pointer_count = 0; 02547 02548 if (type_get_type(type) == TYPE_ARRAY && 02549 !type_array_has_conformance(type) && !type_array_has_variance(type)) 02550 { 02551 unsigned int temp = 0; 02552 /* unfortunately, this needs to be done in two passes to avoid 02553 * writing out redundant FC_FIXED_REPEAT descriptions */ 02554 pointer_count = write_pointer_description_offsets( 02555 NULL, attrs, type_array_get_element(type), NULL, NULL, &temp); 02556 if (pointer_count > 0) 02557 { 02558 unsigned int increment_size; 02559 unsigned int offset_of_array_pointer_mem = 0; 02560 unsigned int offset_of_array_pointer_buf = 0; 02561 02562 increment_size = type_memsize(type_array_get_element(type)); 02563 02564 print_file(file, 2, "0x%02x, /* FC_FIXED_REPEAT */\n", RPC_FC_FIXED_REPEAT); 02565 print_file(file, 2, "0x%02x, /* FC_PAD */\n", RPC_FC_PAD); 02566 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Iterations = %d */\n", (unsigned short)type_array_get_dim(type), type_array_get_dim(type)); 02567 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size); 02568 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory); 02569 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count); 02570 *typestring_offset += 10; 02571 02572 pointer_count = write_pointer_description_offsets( 02573 file, attrs, type, &offset_of_array_pointer_mem, 02574 &offset_of_array_pointer_buf, typestring_offset); 02575 } 02576 } 02577 else if (type_get_type(type) == TYPE_STRUCT) 02578 { 02579 const var_t *v; 02580 LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) 02581 { 02582 if (offset_in_memory && offset_in_buffer) 02583 { 02584 unsigned int padding; 02585 unsigned int align = 0; 02586 type_memsize_and_alignment(v->type, &align); 02587 padding = ROUNDING(*offset_in_memory, align); 02588 *offset_in_memory += padding; 02589 *offset_in_buffer += padding; 02590 } 02591 pointer_count += write_fixed_array_pointer_descriptions( 02592 file, v->attrs, v->type, offset_in_memory, offset_in_buffer, 02593 typestring_offset); 02594 } 02595 } 02596 else 02597 { 02598 if (offset_in_memory && offset_in_buffer) 02599 { 02600 unsigned int memsize; 02601 memsize = type_memsize(type); 02602 *offset_in_memory += memsize; 02603 /* increment these separately as in the case of conformant (varying) 02604 * structures these start at different values */ 02605 *offset_in_buffer += memsize; 02606 } 02607 } 02608 02609 return pointer_count; 02610 } 02611 02612 /* Note: if file is NULL return value is number of pointers to write, else 02613 * it is the number of type format characters written */ 02614 static int write_conformant_array_pointer_descriptions( 02615 FILE *file, const attr_list_t *attrs, type_t *type, 02616 unsigned int offset_in_memory, unsigned int *typestring_offset) 02617 { 02618 int pointer_count = 0; 02619 02620 if (is_conformant_array(type) && !type_array_has_variance(type)) 02621 { 02622 unsigned int temp = 0; 02623 /* unfortunately, this needs to be done in two passes to avoid 02624 * writing out redundant FC_VARIABLE_REPEAT descriptions */ 02625 pointer_count = write_pointer_description_offsets( 02626 NULL, attrs, type_array_get_element(type), NULL, NULL, &temp); 02627 if (pointer_count > 0) 02628 { 02629 unsigned int increment_size; 02630 unsigned int offset_of_array_pointer_mem = offset_in_memory; 02631 unsigned int offset_of_array_pointer_buf = offset_in_memory; 02632 02633 increment_size = type_memsize(type_array_get_element(type)); 02634 02635 if (increment_size > USHRT_MAX) 02636 error("array size of %u bytes is too large\n", increment_size); 02637 02638 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT); 02639 print_file(file, 2, "0x%02x, /* FC_FIXED_OFFSET */\n", RPC_FC_FIXED_OFFSET); 02640 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size); 02641 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)offset_in_memory, offset_in_memory); 02642 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count); 02643 *typestring_offset += 8; 02644 02645 pointer_count = write_pointer_description_offsets( 02646 file, attrs, type_array_get_element(type), 02647 &offset_of_array_pointer_mem, &offset_of_array_pointer_buf, 02648 typestring_offset); 02649 } 02650 } 02651 02652 return pointer_count; 02653 } 02654 02655 /* Note: if file is NULL return value is number of pointers to write, else 02656 * it is the number of type format characters written */ 02657 static int write_varying_array_pointer_descriptions( 02658 FILE *file, const attr_list_t *attrs, type_t *type, 02659 unsigned int *offset_in_memory, unsigned int *offset_in_buffer, 02660 unsigned int *typestring_offset) 02661 { 02662 int pointer_count = 0; 02663 02664 if (is_array(type) && type_array_has_variance(type)) 02665 { 02666 unsigned int temp = 0; 02667 /* unfortunately, this needs to be done in two passes to avoid 02668 * writing out redundant FC_VARIABLE_REPEAT descriptions */ 02669 pointer_count = write_pointer_description_offsets( 02670 NULL, attrs, type_array_get_element(type), NULL, NULL, &temp); 02671 if (pointer_count > 0) 02672 { 02673 unsigned int increment_size; 02674 02675 increment_size = type_memsize(type_array_get_element(type)); 02676 02677 if (increment_size > USHRT_MAX) 02678 error("array size of %u bytes is too large\n", increment_size); 02679 02680 print_file(file, 2, "0x%02x, /* FC_VARIABLE_REPEAT */\n", RPC_FC_VARIABLE_REPEAT); 02681 print_file(file, 2, "0x%02x, /* FC_VARIABLE_OFFSET */\n", RPC_FC_VARIABLE_OFFSET); 02682 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Increment = %d */\n", (unsigned short)increment_size, increment_size); 02683 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset to array = %d */\n", (unsigned short)*offset_in_memory, *offset_in_memory); 02684 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Number of pointers = %d */\n", (unsigned short)pointer_count, pointer_count); 02685 *typestring_offset += 8; 02686 02687 pointer_count = write_pointer_description_offsets( 02688 file, attrs, type_array_get_element(type), offset_in_memory, 02689 offset_in_buffer, typestring_offset); 02690 } 02691 } 02692 else if (type_get_type(type) == TYPE_STRUCT) 02693 { 02694 const var_t *v; 02695 LIST_FOR_EACH_ENTRY( v, type_struct_get_fields(type), const var_t, entry ) 02696 { 02697 if (offset_in_memory && offset_in_buffer) 02698 { 02699 unsigned int align = 0, padding; 02700 02701 if (is_array(v->type) && type_array_has_variance(v->type)) 02702 { 02703 *offset_in_buffer = ROUND_SIZE(*offset_in_buffer, 4); 02704 /* skip over variance and offset in buffer */ 02705 *offset_in_buffer += 8; 02706 } 02707 02708 type_memsize_and_alignment(v->type, &align); 02709 padding = ROUNDING(*offset_in_memory, align); 02710 *offset_in_memory += padding; 02711 *offset_in_buffer += padding; 02712 } 02713 pointer_count += write_varying_array_pointer_descriptions( 02714 file, v->attrs, v->type, offset_in_memory, offset_in_buffer, 02715 typestring_offset); 02716 } 02717 } 02718 else 02719 { 02720 if (offset_in_memory && offset_in_buffer) 02721 { 02722 unsigned int memsize = type_memsize(type); 02723 *offset_in_memory += memsize; 02724 /* increment these separately as in the case of conformant (varying) 02725 * structures these start at different values */ 02726 *offset_in_buffer += memsize; 02727 } 02728 } 02729 02730 return pointer_count; 02731 } 02732 02733 static void write_pointer_description(FILE *file, type_t *type, 02734 unsigned int *typestring_offset) 02735 { 02736 unsigned int offset_in_buffer; 02737 unsigned int offset_in_memory; 02738 02739 /* pass 1: search for single instance of a pointer (i.e. don't descend 02740 * into arrays) */ 02741 if (!is_array(type)) 02742 { 02743 offset_in_memory = 0; 02744 offset_in_buffer = 0; 02745 write_no_repeat_pointer_descriptions( 02746 file, NULL, type, 02747 &offset_in_memory, &offset_in_buffer, typestring_offset); 02748 } 02749 02750 /* pass 2: search for pointers in fixed arrays */ 02751 offset_in_memory = 0; 02752 offset_in_buffer = 0; 02753 write_fixed_array_pointer_descriptions( 02754 file, NULL, type, 02755 &offset_in_memory, &offset_in_buffer, typestring_offset); 02756 02757 /* pass 3: search for pointers in conformant only arrays (but don't descend 02758 * into conformant varying or varying arrays) */ 02759 if (is_conformant_array(type) && 02760 (type_array_is_decl_as_ptr(type) || !current_structure)) 02761 write_conformant_array_pointer_descriptions( 02762 file, NULL, type, 0, typestring_offset); 02763 else if (type_get_type(type) == TYPE_STRUCT && 02764 get_struct_fc(type) == RPC_FC_CPSTRUCT) 02765 { 02766 type_t *carray = find_array_or_string_in_struct(type)->type; 02767 write_conformant_array_pointer_descriptions( file, NULL, carray, 02768 type_memsize(type), typestring_offset); 02769 } 02770 02771 /* pass 4: search for pointers in varying arrays */ 02772 offset_in_memory = 0; 02773 offset_in_buffer = 0; 02774 write_varying_array_pointer_descriptions( 02775 file, NULL, type, 02776 &offset_in_memory, &offset_in_buffer, typestring_offset); 02777 } 02778 02779 int is_declptr(const type_t *t) 02780 { 02781 return is_ptr(t) || (type_get_type(t) == TYPE_ARRAY && type_array_is_decl_as_ptr(t)); 02782 } 02783 02784 static unsigned int write_string_tfs(FILE *file, const attr_list_t *attrs, 02785 type_t *type, enum type_context context, 02786 const char *name, unsigned int *typestring_offset) 02787 { 02788 unsigned int start_offset; 02789 unsigned char rtype; 02790 type_t *elem_type; 02791 int is_processed = processed(type); 02792 02793 start_offset = *typestring_offset; 02794 02795 if (is_declptr(type)) 02796 { 02797 unsigned char flag = is_conformant_array(type) ? 0 : RPC_FC_P_SIMPLEPOINTER; 02798 int pointer_type = get_pointer_fc_context(type, attrs, context); 02799 if (!pointer_type) 02800 pointer_type = RPC_FC_RP; 02801 print_start_tfs_comment(file, type, *typestring_offset); 02802 print_file(file, 2,"0x%x, 0x%x,\t/* %s%s */\n", 02803 pointer_type, flag, string_of_type(pointer_type), 02804 flag ? " [simple_pointer]" : ""); 02805 *typestring_offset += 2; 02806 if (!flag) 02807 { 02808 print_file(file, 2, "NdrFcShort(0x2),\n"); 02809 *typestring_offset += 2; 02810 } 02811 is_processed = FALSE; 02812 } 02813 02814 if (is_array(type)) 02815 elem_type = type_array_get_element(type); 02816 else 02817 elem_type = type_pointer_get_ref(type); 02818 02819 if (type_get_type(elem_type) != TYPE_BASIC) 02820 { 02821 error("write_string_tfs: Unimplemented for non-basic type %s\n", name); 02822 return start_offset; 02823 } 02824 02825 rtype = get_basic_fc(elem_type); 02826 if ((rtype != RPC_FC_BYTE) && (rtype != RPC_FC_CHAR) && (rtype != RPC_FC_WCHAR)) 02827 { 02828 error("write_string_tfs: Unimplemented for type 0x%x of name: %s\n", rtype, name); 02829 return start_offset; 02830 } 02831 02832 if (type_get_type(type) == TYPE_ARRAY && !type_array_has_conformance(type)) 02833 { 02834 unsigned int dim = type_array_get_dim(type); 02835 02836 if (is_processed) return start_offset; 02837 02838 /* FIXME: multi-dimensional array */ 02839 if (0xffffu < dim) 02840 error("array size for parameter %s exceeds %u bytes by %u bytes\n", 02841 name, 0xffffu, dim - 0xffffu); 02842 02843 if (rtype == RPC_FC_WCHAR) 02844 WRITE_FCTYPE(file, FC_WSTRING, *typestring_offset); 02845 else 02846 WRITE_FCTYPE(file, FC_CSTRING, *typestring_offset); 02847 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); 02848 *typestring_offset += 2; 02849 02850 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)dim, dim); 02851 *typestring_offset += 2; 02852 02853 update_tfsoff(type, start_offset, file); 02854 return start_offset; 02855 } 02856 else if (is_conformant_array(type)) 02857 { 02858 if (rtype == RPC_FC_WCHAR) 02859 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset); 02860 else 02861 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset); 02862 print_file(file, 2, "0x%x, /* FC_STRING_SIZED */\n", RPC_FC_STRING_SIZED); 02863 *typestring_offset += 2; 02864 02865 *typestring_offset += write_conf_or_var_desc( 02866 file, current_structure, 02867 (!type_array_is_decl_as_ptr(type) && current_structure 02868 ? type_memsize(current_structure) 02869 : 0), 02870 type, type_array_get_conformance(type)); 02871 02872 update_tfsoff(type, start_offset, file); 02873 return start_offset; 02874 } 02875 else 02876 { 02877 if (is_processed) return start_offset; 02878 02879 if (rtype == RPC_FC_WCHAR) 02880 WRITE_FCTYPE(file, FC_C_WSTRING, *typestring_offset); 02881 else 02882 WRITE_FCTYPE(file, FC_C_CSTRING, *typestring_offset); 02883 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); 02884 *typestring_offset += 2; 02885 02886 update_tfsoff(type, start_offset, file); 02887 return start_offset; 02888 } 02889 } 02890 02891 static unsigned int write_array_tfs(FILE *file, const attr_list_t *attrs, type_t *type, 02892 const char *name, unsigned int *typestring_offset) 02893 { 02894 const expr_t *length_is = type_array_get_variance(type); 02895 const expr_t *size_is = type_array_get_conformance(type); 02896 unsigned int align; 02897 unsigned int size; 02898 unsigned int start_offset; 02899 unsigned char fc; 02900 int pointer_type = get_attrv(attrs, ATTR_POINTERTYPE); 02901 unsigned int baseoff 02902 = !type_array_is_decl_as_ptr(type) && current_structure 02903 ? type_memsize(current_structure) 02904 : 0; 02905 02906 if (!pointer_type) 02907 pointer_type = RPC_FC_RP; 02908 02909 write_embedded_types(file, attrs, type_array_get_element(type), name, FALSE, typestring_offset); 02910 02911 size = type_memsize(is_conformant_array(type) ? type_array_get_element(type) : type); 02912 align = type_buffer_alignment(is_conformant_array(type) ? type_array_get_element(type) : type); 02913 fc = get_array_fc(type); 02914 02915 start_offset = *typestring_offset; 02916 update_tfsoff(type, start_offset, file); 02917 print_start_tfs_comment(file, type, start_offset); 02918 print_file(file, 2, "0x%02x,\t/* %s */\n", fc, string_of_type(fc)); 02919 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1); 02920 *typestring_offset += 2; 02921 02922 align = 0; 02923 if (fc != RPC_FC_BOGUS_ARRAY) 02924 { 02925 if (fc == RPC_FC_LGFARRAY || fc == RPC_FC_LGVARRAY) 02926 { 02927 print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", size, size); 02928 *typestring_offset += 4; 02929 } 02930 else 02931 { 02932 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)size, size); 02933 *typestring_offset += 2; 02934 } 02935 02936 if (is_conformant_array(type)) 02937 *typestring_offset 02938 += write_conf_or_var_desc(file, current_structure, baseoff, 02939 type, size_is); 02940 02941 if (fc == RPC_FC_SMVARRAY || fc == RPC_FC_LGVARRAY) 02942 { 02943 unsigned int elsize = type_memsize(type_array_get_element(type)); 02944 unsigned int dim = type_array_get_dim(type); 02945 02946 if (fc == RPC_FC_LGVARRAY) 02947 { 02948 print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", dim, dim); 02949 *typestring_offset += 4; 02950 } 02951 else 02952 { 02953 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)dim, dim); 02954 *typestring_offset += 2; 02955 } 02956 02957 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)elsize, elsize); 02958 *typestring_offset += 2; 02959 } 02960 02961 if (length_is) 02962 *typestring_offset 02963 += write_conf_or_var_desc(file, current_structure, baseoff, 02964 type, length_is); 02965 02966 if (type_has_pointers(type_array_get_element(type)) && 02967 (type_array_is_decl_as_ptr(type) || !current_structure)) 02968 { 02969 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP); 02970 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); 02971 *typestring_offset += 2; 02972 write_pointer_description(file, type, typestring_offset); 02973 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END); 02974 *typestring_offset += 1; 02975 } 02976 02977 write_array_element_type(file, type, FALSE, typestring_offset); 02978 write_end(file, typestring_offset); 02979 } 02980 else 02981 { 02982 unsigned int dim = size_is ? 0 : type_array_get_dim(type); 02983 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %u */\n", (unsigned short)dim, dim); 02984 *typestring_offset += 2; 02985 *typestring_offset 02986 += write_conf_or_var_desc(file, current_structure, baseoff, 02987 type, size_is); 02988 *typestring_offset 02989 += write_conf_or_var_desc(file, current_structure, baseoff, 02990 type, length_is); 02991 02992 write_array_element_type(file, type, TRUE, typestring_offset); 02993 write_end(file, typestring_offset); 02994 } 02995 02996 return start_offset; 02997 } 02998 02999 static const var_t *find_array_or_string_in_struct(const type_t *type) 03000 { 03001 const var_list_t *fields = type_struct_get_fields(type); 03002 const var_t *last_field; 03003 const type_t *ft; 03004 03005 if (!fields || list_empty(fields)) 03006 return NULL; 03007 03008 last_field = LIST_ENTRY( list_tail(fields), const var_t, entry ); 03009 ft = last_field->type; 03010 03011 if (is_conformant_array(ft) && !type_array_is_decl_as_ptr(ft)) 03012 return last_field; 03013 03014 if (type_get_type(ft) == TYPE_STRUCT) 03015 return find_array_or_string_in_struct(ft); 03016 else 03017 return NULL; 03018 } 03019 03020 static void write_struct_members(FILE *file, const type_t *type, 03021 int is_complex, unsigned int *corroff, 03022 unsigned int *typestring_offset) 03023 { 03024 const var_t *field; 03025 unsigned short offset = 0; 03026 unsigned int salign = 1; 03027 int padding; 03028 var_list_t *fields = type_struct_get_fields(type); 03029 03030 if (fields) LIST_FOR_EACH_ENTRY( field, fields, const var_t, entry ) 03031 { 03032 type_t *ft = field->type; 03033 unsigned int align = 0; 03034 unsigned int size = type_memsize_and_alignment(ft, &align); 03035 align = clamp_align(align); 03036 if (salign < align) salign = align; 03037 03038 if (!is_conformant_array(ft) || type_array_is_decl_as_ptr(ft)) 03039 { 03040 if ((align - 1) & offset) 03041 { 03042 unsigned char fc = 0; 03043 switch (align) 03044 { 03045 case 2: 03046 fc = RPC_FC_ALIGNM2; 03047 break; 03048 case 4: 03049 fc = RPC_FC_ALIGNM4; 03050 break; 03051 case 8: 03052 fc = RPC_FC_ALIGNM8; 03053 break; 03054 default: 03055 error("write_struct_members: cannot align type %d\n", type_get_type(ft)); 03056 } 03057 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); 03058 offset = ROUND_SIZE(offset, align); 03059 *typestring_offset += 1; 03060 } 03061 write_member_type(file, type, is_complex, field->attrs, field->type, corroff, 03062 typestring_offset); 03063 offset += size; 03064 } 03065 } 03066 03067 padding = ROUNDING(offset, salign); 03068 if (padding) 03069 { 03070 print_file(file, 2, "0x%x,\t/* FC_STRUCTPAD%d */\n", 03071 RPC_FC_STRUCTPAD1 + padding - 1, 03072 padding); 03073 *typestring_offset += 1; 03074 } 03075 03076 write_end(file, typestring_offset); 03077 } 03078 03079 static unsigned int write_struct_tfs(FILE *file, type_t *type, 03080 const char *name, unsigned int *tfsoff) 03081 { 03082 const type_t *save_current_structure = current_structure; 03083 unsigned int total_size; 03084 const var_t *array; 03085 unsigned int start_offset; 03086 unsigned int align; 03087 unsigned int corroff; 03088 var_t *f; 03089 unsigned char fc = get_struct_fc(type); 03090 var_list_t *fields = type_struct_get_fields(type); 03091 03092 if (processed(type)) return type->typestring_offset; 03093 03094 guard_rec(type); 03095 current_structure = type; 03096 03097 total_size = type_memsize(type); 03098 align = type_buffer_alignment(type); 03099 if (total_size > USHRT_MAX) 03100 error("structure size for %s exceeds %d bytes by %d bytes\n", 03101 name, USHRT_MAX, total_size - USHRT_MAX); 03102 03103 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) 03104 write_embedded_types(file, f->attrs, f->type, f->name, FALSE, tfsoff); 03105 03106 array = find_array_or_string_in_struct(type); 03107 if (array && !processed(array->type)) 03108 { 03109 if(is_string_type(array->attrs, array->type)) 03110 write_string_tfs(file, array->attrs, array->type, TYPE_CONTEXT_CONTAINER, array->name, tfsoff); 03111 else 03112 write_array_tfs(file, array->attrs, array->type, array->name, tfsoff); 03113 } 03114 03115 corroff = *tfsoff; 03116 write_descriptors(file, type, tfsoff); 03117 03118 start_offset = *tfsoff; 03119 update_tfsoff(type, start_offset, file); 03120 print_start_tfs_comment(file, type, start_offset); 03121 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); 03122 print_file(file, 2, "0x%x,\t/* %d */\n", align - 1, align - 1); 03123 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)total_size, total_size); 03124 *tfsoff += 4; 03125 03126 if (array) 03127 { 03128 unsigned int absoff = array->type->typestring_offset; 03129 short reloff = absoff - *tfsoff; 03130 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", 03131 reloff, reloff, absoff); 03132 *tfsoff += 2; 03133 } 03134 else if (fc == RPC_FC_BOGUS_STRUCT) 03135 { 03136 print_file(file, 2, "NdrFcShort(0x0),\n"); 03137 *tfsoff += 2; 03138 } 03139 03140 if (fc == RPC_FC_BOGUS_STRUCT) 03141 { 03142 /* On the sizing pass, type->ptrdesc may be zero, but it's ok as 03143 nothing is written to file yet. On the actual writing pass, 03144 this will have been updated. */ 03145 unsigned int absoff = type->ptrdesc ? type->ptrdesc : *tfsoff; 03146 int reloff = absoff - *tfsoff; 03147 assert( reloff >= 0 ); 03148 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %d (%u) */\n", 03149 (unsigned short)reloff, reloff, absoff); 03150 *tfsoff += 2; 03151 } 03152 else if ((fc == RPC_FC_PSTRUCT) || 03153 (fc == RPC_FC_CPSTRUCT) || 03154 (fc == RPC_FC_CVSTRUCT && type_has_pointers(type))) 03155 { 03156 print_file(file, 2, "0x%x, /* FC_PP */\n", RPC_FC_PP); 03157 print_file(file, 2, "0x%x, /* FC_PAD */\n", RPC_FC_PAD); 03158 *tfsoff += 2; 03159 write_pointer_description(file, type, tfsoff); 03160 print_file(file, 2, "0x%x, /* FC_END */\n", RPC_FC_END); 03161 *tfsoff += 1; 03162 } 03163 03164 write_struct_members(file, type, fc == RPC_FC_BOGUS_STRUCT, &corroff, 03165 tfsoff); 03166 03167 if (fc == RPC_FC_BOGUS_STRUCT) 03168 { 03169 const var_t *f; 03170 03171 type->ptrdesc = *tfsoff; 03172 if (fields) LIST_FOR_EACH_ENTRY(f, fields, const var_t, entry) 03173 { 03174 type_t *ft = f->type; 03175 switch (typegen_detect_type(ft, f->attrs, TDT_IGNORE_STRINGS)) 03176 { 03177 case TGT_POINTER: 03178 if (is_string_type(f->attrs, ft)) 03179 write_string_tfs(file, f->attrs, ft, TYPE_CONTEXT_CONTAINER, f->name, tfsoff); 03180 else 03181 write_pointer_tfs(file, f->attrs, ft, 03182 type_pointer_get_ref(ft)->typestring_offset, 03183 TYPE_CONTEXT_CONTAINER, tfsoff); 03184 break; 03185 case TGT_ARRAY: 03186 if (type_array_is_decl_as_ptr(ft)) 03187 { 03188 unsigned int offset; 03189 03190 print_file(file, 0, "/* %d */\n", *tfsoff); 03191 03192 offset = ft->typestring_offset; 03193 /* skip over the pointer that is written for strings, since a 03194 * pointer has to be written in-place here */ 03195 if (is_string_type(f->attrs, ft)) 03196 offset += 4; 03197 write_nonsimple_pointer(file, f->attrs, ft, TYPE_CONTEXT_CONTAINER, offset, tfsoff); 03198 } 03199 break; 03200 default: 03201 break; 03202 } 03203 } 03204 if (type->ptrdesc == *tfsoff) 03205 type->ptrdesc = 0; 03206 } 03207 03208 current_structure = save_current_structure; 03209 return start_offset; 03210 } 03211 03212 static void write_branch_type(FILE *file, const type_t *t, unsigned int *tfsoff) 03213 { 03214 if (t == NULL) 03215 { 03216 print_file(file, 2, "NdrFcShort(0x0),\t/* No type */\n"); 03217 } 03218 else 03219 { 03220 if (type_get_type(t) == TYPE_BASIC || type_get_type(t) == TYPE_ENUM) 03221 { 03222 unsigned char fc; 03223 if (type_get_type(t) == TYPE_BASIC) 03224 fc = get_basic_fc(t); 03225 else 03226 fc = get_enum_fc(t); 03227 print_file(file, 2, "NdrFcShort(0x80%02x),\t/* Simple arm type: %s */\n", 03228 fc, string_of_type(fc)); 03229 } 03230 else if (t->typestring_offset) 03231 { 03232 short reloff = t->typestring_offset - *tfsoff; 03233 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %d (%d) */\n", 03234 reloff, reloff, t->typestring_offset); 03235 } 03236 else 03237 error("write_branch_type: type unimplemented %d\n", type_get_type(t)); 03238 } 03239 03240 *tfsoff += 2; 03241 } 03242 03243 static unsigned int write_union_tfs(FILE *file, const attr_list_t *attrs, 03244 type_t *type, unsigned int *tfsoff) 03245 { 03246 unsigned int start_offset; 03247 unsigned int size; 03248 var_list_t *fields; 03249 unsigned int nbranch = 0; 03250 type_t *deftype = NULL; 03251 short nodeftype = 0xffff; 03252 var_t *f; 03253 03254 if (processed(type) && 03255 (type_get_type(type) == TYPE_ENCAPSULATED_UNION || !is_attr(type->attrs, ATTR_SWITCHTYPE))) 03256 return type->typestring_offset; 03257 03258 guard_rec(type); 03259 03260 size = type_memsize(type); 03261 03262 fields = type_union_get_cases(type); 03263 03264 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) 03265 { 03266 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE); 03267 if (cases) 03268 nbranch += list_count(cases); 03269 if (f->type) 03270 write_embedded_types(file, f->attrs, f->type, f->name, TRUE, tfsoff); 03271 } 03272 03273 start_offset = *tfsoff; 03274 update_tfsoff(type, start_offset, file); 03275 print_start_tfs_comment(file, type, start_offset); 03276 if (type_get_type(type) == TYPE_ENCAPSULATED_UNION) 03277 { 03278 const var_t *sv = type_union_get_switch_value(type); 03279 const type_t *st = sv->type; 03280 unsigned char fc; 03281 03282 if (type_get_type(st) == TYPE_BASIC) 03283 { 03284 fc = get_basic_fc(st); 03285 switch (fc) 03286 { 03287 case RPC_FC_CHAR: 03288 case RPC_FC_SMALL: 03289 case RPC_FC_BYTE: 03290 case RPC_FC_USMALL: 03291 case RPC_FC_WCHAR: 03292 case RPC_FC_SHORT: 03293 case RPC_FC_USHORT: 03294 case RPC_FC_LONG: 03295 case RPC_FC_ULONG: 03296 break; 03297 default: 03298 fc = 0; 03299 error("union switch type must be an integer, char, or enum\n"); 03300 } 03301 } 03302 else if (type_get_type(st) == TYPE_ENUM) 03303 fc = get_enum_fc(st); 03304 else 03305 error("union switch type must be an integer, char, or enum\n"); 03306 03307 print_file(file, 2, "0x%x,\t/* FC_ENCAPSULATED_UNION */\n", RPC_FC_ENCAPSULATED_UNION); 03308 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n", 03309 0x40 | fc, string_of_type(fc)); 03310 *tfsoff += 2; 03311 } 03312 else if (is_attr(type->attrs, ATTR_SWITCHTYPE)) 03313 { 03314 const expr_t *switch_is = get_attrp(attrs, ATTR_SWITCHIS); 03315 const type_t *st = get_attrp(type->attrs, ATTR_SWITCHTYPE); 03316 unsigned char fc; 03317 03318 if (type_get_type(st) == TYPE_BASIC) 03319 { 03320 fc = get_basic_fc(st); 03321 switch (fc) 03322 { 03323 case RPC_FC_CHAR: 03324 case RPC_FC_SMALL: 03325 case RPC_FC_USMALL: 03326 case RPC_FC_SHORT: 03327 case RPC_FC_USHORT: 03328 case RPC_FC_LONG: 03329 case RPC_FC_ULONG: 03330 case RPC_FC_ENUM16: 03331 case RPC_FC_ENUM32: 03332 break; 03333 default: 03334 fc = 0; 03335 error("union switch type must be an integer, char, or enum\n"); 03336 } 03337 } 03338 else if (type_get_type(st) == TYPE_ENUM) 03339 fc = get_enum_fc(st); 03340 else 03341 error("union switch type must be an integer, char, or enum\n"); 03342 03343 print_file(file, 2, "0x%x,\t/* FC_NON_ENCAPSULATED_UNION */\n", RPC_FC_NON_ENCAPSULATED_UNION); 03344 print_file(file, 2, "0x%x,\t/* Switch type= %s */\n", 03345 fc, string_of_type(fc)); 03346 *tfsoff += 2; 03347 *tfsoff += write_conf_or_var_desc(file, current_structure, 0, st, switch_is ); 03348 print_file(file, 2, "NdrFcShort(0x2),\t/* Offset= 2 (%u) */\n", *tfsoff + 2); 03349 *tfsoff += 2; 03350 print_file(file, 0, "/* %u */\n", *tfsoff); 03351 } 03352 03353 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)size, size); 03354 print_file(file, 2, "NdrFcShort(0x%hx),\t/* %d */\n", (unsigned short)nbranch, nbranch); 03355 *tfsoff += 4; 03356 03357 if (fields) LIST_FOR_EACH_ENTRY(f, fields, var_t, entry) 03358 { 03359 type_t *ft = f->type; 03360 expr_list_t *cases = get_attrp(f->attrs, ATTR_CASE); 03361 int deflt = is_attr(f->attrs, ATTR_DEFAULT); 03362 expr_t *c; 03363 03364 if (cases == NULL && !deflt) 03365 error("union field %s with neither case nor default attribute\n", f->name); 03366 03367 if (cases) LIST_FOR_EACH_ENTRY(c, cases, expr_t, entry) 03368 { 03369 /* MIDL doesn't check for duplicate cases, even though that seems 03370 like a reasonable thing to do, it just dumps them to the TFS 03371 like we're going to do here. */ 03372 print_file(file, 2, "NdrFcLong(0x%x),\t/* %d */\n", c->cval, c->cval); 03373 *tfsoff += 4; 03374 write_branch_type(file, ft, tfsoff); 03375 } 03376 03377 /* MIDL allows multiple default branches, even though that seems 03378 illogical, it just chooses the last one, which is what we will 03379 do. */ 03380 if (deflt) 03381 { 03382 deftype = ft; 03383 nodeftype = 0; 03384 } 03385 } 03386 03387 if (deftype) 03388 { 03389 write_branch_type(file, deftype, tfsoff); 03390 } 03391 else 03392 { 03393 print_file(file, 2, "NdrFcShort(0x%hx),\n", nodeftype); 03394 *tfsoff += 2; 03395 } 03396 03397 return start_offset; 03398 } 03399 03400 static unsigned int write_ip_tfs(FILE *file, const attr_list_t *attrs, type_t *type, 03401 unsigned int *typeformat_offset) 03402 { 03403 unsigned int i; 03404 unsigned int start_offset = *typeformat_offset; 03405 expr_t *iid = get_attrp(attrs, ATTR_IIDIS); 03406 03407 if (!iid && processed(type)) return type->typestring_offset; 03408 03409 print_start_tfs_comment(file, type, start_offset); 03410 update_tfsoff(type, start_offset, file); 03411 03412 if (iid) 03413 { 03414 print_file(file, 2, "0x2f, /* FC_IP */\n"); 03415 print_file(file, 2, "0x5c, /* FC_PAD */\n"); 03416 *typeformat_offset 03417 += write_conf_or_var_desc(file, current_structure, 0, type, iid) + 2; 03418 } 03419 else 03420 { 03421 const type_t *base = is_ptr(type) ? type_pointer_get_ref(type) : type; 03422 const UUID *uuid = get_attrp(base->attrs, ATTR_UUID); 03423 03424 if (! uuid) 03425 error("%s: interface %s missing UUID\n", __FUNCTION__, base->name); 03426 03427 print_file(file, 2, "0x2f,\t/* FC_IP */\n"); 03428 print_file(file, 2, "0x5a,\t/* FC_CONSTANT_IID */\n"); 03429 print_file(file, 2, "NdrFcLong(0x%08x),\n", uuid->Data1); 03430 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data2); 03431 print_file(file, 2, "NdrFcShort(0x%04x),\n", uuid->Data3); 03432 for (i = 0; i < 8; ++i) 03433 print_file(file, 2, "0x%02x,\n", uuid->Data4[i]); 03434 03435 if (file) 03436 fprintf(file, "\n"); 03437 03438 *typeformat_offset += 18; 03439 } 03440 return start_offset; 03441 } 03442 03443 static unsigned int write_contexthandle_tfs(FILE *file, 03444 const attr_list_t *attrs, 03445 type_t *type, 03446 int toplevel_param, 03447 unsigned int *typeformat_offset) 03448 { 03449 unsigned int start_offset = *typeformat_offset; 03450 unsigned char flags = get_contexthandle_flags( current_iface, attrs, type ); 03451 03452 print_start_tfs_comment(file, type, start_offset); 03453 03454 if (flags & 0x80) /* via ptr */ 03455 { 03456 int pointer_type = get_pointer_fc( type, attrs, toplevel_param ); 03457 if (!pointer_type) pointer_type = RPC_FC_RP; 03458 *typeformat_offset += 4; 03459 print_file(file, 2,"0x%x, 0x0,\t/* %s */\n", pointer_type, string_of_type(pointer_type) ); 03460 print_file(file, 2, "NdrFcShort(0x2),\t /* Offset= 2 (%u) */\n", *typeformat_offset); 03461 print_file(file, 0, "/* %2u */\n", *typeformat_offset); 03462 } 03463 03464 print_file(file, 2, "0x%02x,\t/* FC_BIND_CONTEXT */\n", RPC_FC_BIND_CONTEXT); 03465 print_file(file, 2, "0x%x,\t/* Context flags: ", flags); 03466 /* return and can't be null values overlap */ 03467 if (((flags & 0x21) != 0x21) && (flags & NDR_CONTEXT_HANDLE_CANNOT_BE_NULL)) 03468 print_file(file, 0, "can't be null, "); 03469 if (flags & NDR_CONTEXT_HANDLE_SERIALIZE) 03470 print_file(file, 0, "serialize, "); 03471 if (flags & NDR_CONTEXT_HANDLE_NO_SERIALIZE) 03472 print_file(file, 0, "no serialize, "); 03473 if (flags & NDR_STRICT_CONTEXT_HANDLE) 03474 print_file(file, 0, "strict, "); 03475 if ((flags & 0x21) == 0x20) 03476 print_file(file, 0, "out, "); 03477 if ((flags & 0x21) == 0x21) 03478 print_file(file, 0, "return, "); 03479 if (flags & 0x40) 03480 print_file(file, 0, "in, "); 03481 if (flags & 0x80) 03482 print_file(file, 0, "via ptr, "); 03483 print_file(file, 0, "*/\n"); 03484 print_file(file, 2, "0x%x,\t/* rundown routine */\n", get_context_handle_offset( type )); 03485 print_file(file, 2, "0, /* FIXME: param num */\n"); 03486 *typeformat_offset += 4; 03487 03488 update_tfsoff( type, start_offset, file ); 03489 return start_offset; 03490 } 03491 03492 static unsigned int write_range_tfs(FILE *file, const attr_list_t *attrs, 03493 type_t *type, expr_list_t *range_list, 03494 unsigned int *typeformat_offset) 03495 { 03496 unsigned char fc; 03497 unsigned int start_offset = *typeformat_offset; 03498 const expr_t *range_min = LIST_ENTRY(list_head(range_list), const expr_t, entry); 03499 const expr_t *range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry); 03500 03501 if (type_get_type(type) == TYPE_BASIC) 03502 fc = get_basic_fc(type); 03503 else 03504 fc = get_enum_fc(type); 03505 03506 /* fc must fit in lower 4-bits of 8-bit field below */ 03507 assert(fc <= 0xf); 03508 03509 print_file(file, 0, "/* %u */\n", *typeformat_offset); 03510 print_file(file, 2, "0x%x,\t/* FC_RANGE */\n", RPC_FC_RANGE); 03511 print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc)); 03512 print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_min->cval, range_min->cval); 03513 print_file(file, 2, "NdrFcLong(0x%x),\t/* %u */\n", range_max->cval, range_max->cval); 03514 update_tfsoff( type, start_offset, file ); 03515 *typeformat_offset += 10; 03516 03517 return start_offset; 03518 } 03519 03520 static unsigned int write_type_tfs(FILE *file, int indent, 03521 const attr_list_t *attrs, type_t *type, 03522 const char *name, 03523 enum type_context context, 03524 unsigned int *typeformat_offset) 03525 { 03526 unsigned int offset; 03527 03528 switch (typegen_detect_type(type, attrs, TDT_ALL_TYPES)) 03529 { 03530 case TGT_CTXT_HANDLE: 03531 case TGT_CTXT_HANDLE_POINTER: 03532 return write_contexthandle_tfs(file, attrs, type, 03533 context == TYPE_CONTEXT_TOPLEVELPARAM, typeformat_offset); 03534 case TGT_USER_TYPE: 03535 return write_user_tfs(file, type, typeformat_offset); 03536 case TGT_STRING: 03537 return write_string_tfs(file, attrs, type, context, name, typeformat_offset); 03538 case TGT_ARRAY: 03539 { 03540 unsigned int off; 03541 /* conformant and pointer arrays are handled specially */ 03542 if ((context != TYPE_CONTEXT_CONTAINER && 03543 context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) || 03544 !is_conformant_array(type) || type_array_is_decl_as_ptr(type)) 03545 off = write_array_tfs(file, attrs, type, name, typeformat_offset); 03546 else 03547 off = 0; 03548 if (context != TYPE_CONTEXT_CONTAINER && 03549 context != TYPE_CONTEXT_CONTAINER_NO_POINTERS) 03550 { 03551 int ptr_type; 03552 ptr_type = get_pointer_fc(type, attrs, 03553 context == TYPE_CONTEXT_TOPLEVELPARAM); 03554 if (ptr_type != RPC_FC_RP || type_array_is_decl_as_ptr(type)) 03555 { 03556 unsigned int absoff = type->typestring_offset; 03557 short reloff = absoff - (*typeformat_offset + 2); 03558 off = *typeformat_offset; 03559 print_file(file, 0, "/* %d */\n", off); 03560 print_file(file, 2, "0x%x, 0x0,\t/* %s */\n", ptr_type, 03561 string_of_type(ptr_type)); 03562 print_file(file, 2, "NdrFcShort(0x%hx),\t/* Offset= %hd (%u) */\n", 03563 reloff, reloff, absoff); 03564 if (ptr_type != RPC_FC_RP) update_tfsoff( type, off, file ); 03565 *typeformat_offset += 4; 03566 } 03567 type->details.array.ptr_tfsoff = off; 03568 } 03569 return off; 03570 } 03571 case TGT_STRUCT: 03572 return write_struct_tfs(file, type, name, typeformat_offset); 03573 case TGT_UNION: 03574 return write_union_tfs(file, attrs, type, typeformat_offset); 03575 case TGT_ENUM: 03576 case TGT_BASIC: 03577 /* nothing to do */ 03578 return 0; 03579 case TGT_RANGE: 03580 { 03581 expr_list_t *range_list = get_attrp(attrs, ATTR_RANGE); 03582 if (!range_list) 03583 range_list = get_aliaschain_attrp(type, ATTR_RANGE); 03584 return write_range_tfs(file, attrs, type, range_list, typeformat_offset); 03585 } 03586 case TGT_IFACE_POINTER: 03587 return write_ip_tfs(file, attrs, type, typeformat_offset); 03588 case TGT_POINTER: 03589 { 03590 enum type_context ref_context; 03591 if (context == TYPE_CONTEXT_TOPLEVELPARAM) 03592 ref_context = TYPE_CONTEXT_PARAM; 03593 else if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS) 03594 ref_context = TYPE_CONTEXT_CONTAINER; 03595 else 03596 ref_context = context; 03597 offset = write_type_tfs( file, indent, attrs, type_pointer_get_ref(type), name, 03598 ref_context, typeformat_offset); 03599 if (context == TYPE_CONTEXT_CONTAINER_NO_POINTERS) 03600 return 0; 03601 return write_pointer_tfs(file, attrs, type, offset, context, typeformat_offset); 03602 } 03603 case TGT_INVALID: 03604 break; 03605 } 03606 error("invalid type %s for var %s\n", type->name, name); 03607 return 0; 03608 } 03609 03610 static int write_embedded_types(FILE *file, const attr_list_t *attrs, type_t *type, 03611 const char *name, int write_ptr, unsigned int *tfsoff) 03612 { 03613 return write_type_tfs(file, 2, attrs, type, name, write_ptr ? TYPE_CONTEXT_CONTAINER : TYPE_CONTEXT_CONTAINER_NO_POINTERS, tfsoff); 03614 } 03615 03616 static unsigned int process_tfs_stmts(FILE *file, const statement_list_t *stmts, 03617 type_pred_t pred, unsigned int *typeformat_offset) 03618 { 03619 const var_t *var; 03620 const statement_t *stmt; 03621 03622 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 03623 { 03624 const type_t *iface; 03625 const statement_t *stmt_func; 03626 03627 if (stmt->type == STMT_LIBRARY) 03628 { 03629 process_tfs_stmts(file, stmt->u.lib->stmts, pred, typeformat_offset); 03630 continue; 03631 } 03632 else if (stmt->type != STMT_TYPE || type_get_type(stmt->u.type) != TYPE_INTERFACE) 03633 continue; 03634 03635 iface = stmt->u.type; 03636 if (!pred(iface)) 03637 continue; 03638 03639 current_iface = iface; 03640 STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(iface) ) 03641 { 03642 const var_t *func = stmt_func->u.var; 03643 current_func = func; 03644 if (is_local(func->attrs)) continue; 03645 03646 if (!is_void(type_function_get_rettype(func->type))) 03647 { 03648 write_type_tfs( file, 2, func->attrs, type_function_get_rettype(func->type), 03649 func->name, TYPE_CONTEXT_PARAM, typeformat_offset); 03650 } 03651 03652 if (type_get_function_args(func->type)) 03653 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 03654 write_type_tfs( file, 2, var->attrs, var->type, var->name, 03655 TYPE_CONTEXT_TOPLEVELPARAM, typeformat_offset ); 03656 } 03657 } 03658 03659 return *typeformat_offset + 1; 03660 } 03661 03662 static unsigned int process_tfs(FILE *file, const statement_list_t *stmts, type_pred_t pred) 03663 { 03664 unsigned int typeformat_offset = 2; 03665 03666 return process_tfs_stmts(file, stmts, pred, &typeformat_offset); 03667 } 03668 03669 03670 void write_typeformatstring(FILE *file, const statement_list_t *stmts, type_pred_t pred) 03671 { 03672 int indent = 0; 03673 03674 print_file(file, indent, "static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n"); 03675 print_file(file, indent, "{\n"); 03676 indent++; 03677 print_file(file, indent, "0,\n"); 03678 print_file(file, indent, "{\n"); 03679 indent++; 03680 print_file(file, indent, "NdrFcShort(0x0),\n"); 03681 03682 set_all_tfswrite(TRUE); 03683 process_tfs(file, stmts, pred); 03684 03685 print_file(file, indent, "0x0\n"); 03686 indent--; 03687 print_file(file, indent, "}\n"); 03688 indent--; 03689 print_file(file, indent, "};\n"); 03690 print_file(file, indent, "\n"); 03691 } 03692 03693 static unsigned int get_required_buffer_size_type( 03694 const type_t *type, const char *name, const attr_list_t *attrs, int toplevel_param, unsigned int *alignment) 03695 { 03696 *alignment = 0; 03697 switch (typegen_detect_type(type, NULL, TDT_IGNORE_RANGES)) 03698 { 03699 case TGT_USER_TYPE: 03700 { 03701 const char *uname; 03702 const type_t *utype = get_user_type(type, &uname); 03703 return get_required_buffer_size_type(utype, uname, NULL, FALSE, alignment); 03704 } 03705 case TGT_BASIC: 03706 switch (get_basic_fc(type)) 03707 { 03708 case RPC_FC_BYTE: 03709 case RPC_FC_CHAR: 03710 case RPC_FC_USMALL: 03711 case RPC_FC_SMALL: 03712 *alignment = 4; 03713 return 1; 03714 03715 case RPC_FC_WCHAR: 03716 case RPC_FC_USHORT: 03717 case RPC_FC_SHORT: 03718 *alignment = 4; 03719 return 2; 03720 03721 case RPC_FC_ULONG: 03722 case RPC_FC_LONG: 03723 case RPC_FC_FLOAT: 03724 case RPC_FC_ERROR_STATUS_T: 03725 *alignment = 4; 03726 return 4; 03727 03728 case RPC_FC_HYPER: 03729 case RPC_FC_DOUBLE: 03730 *alignment = 8; 03731 return 8; 03732 03733 case RPC_FC_INT3264: 03734 case RPC_FC_UINT3264: 03735 assert( pointer_size ); 03736 *alignment = pointer_size; 03737 return pointer_size; 03738 03739 case RPC_FC_IGNORE: 03740 case RPC_FC_BIND_PRIMITIVE: 03741 return 0; 03742 03743 default: 03744 error("get_required_buffer_size: unknown basic type 0x%02x\n", 03745 get_basic_fc(type)); 03746 return 0; 03747 } 03748 break; 03749 03750 case TGT_ENUM: 03751 switch (get_enum_fc(type)) 03752 { 03753 case RPC_FC_ENUM32: 03754 *alignment = 4; 03755 return 4; 03756 case RPC_FC_ENUM16: 03757 *alignment = 4; 03758 return 2; 03759 } 03760 break; 03761 03762 case TGT_STRUCT: 03763 if (get_struct_fc(type) == RPC_FC_STRUCT) 03764 { 03765 if (!type_struct_get_fields(type)) return 0; 03766 return fields_memsize(type_struct_get_fields(type), alignment); 03767 } 03768 break; 03769 03770 case TGT_POINTER: 03771 { 03772 unsigned int size, align; 03773 const type_t *ref = type_pointer_get_ref(type); 03774 if (is_string_type( attrs, ref )) break; 03775 if (!(size = get_required_buffer_size_type( ref, name, NULL, FALSE, &align ))) break; 03776 if (get_pointer_fc(type, attrs, toplevel_param) != RPC_FC_RP) 03777 { 03778 size += 4 + align; 03779 align = 4; 03780 } 03781 *alignment = align; 03782 return size; 03783 } 03784 03785 case TGT_ARRAY: 03786 if (get_pointer_fc(type, attrs, toplevel_param) == RPC_FC_RP) 03787 { 03788 switch (get_array_fc(type)) 03789 { 03790 case RPC_FC_SMFARRAY: 03791 case RPC_FC_LGFARRAY: 03792 return type_array_get_dim(type) * 03793 get_required_buffer_size_type(type_array_get_element(type), name, 03794 NULL, FALSE, alignment); 03795 } 03796 } 03797 break; 03798 03799 default: 03800 break; 03801 } 03802 return 0; 03803 } 03804 03805 static unsigned int get_required_buffer_size(const var_t *var, unsigned int *alignment, enum pass pass) 03806 { 03807 int in_attr = is_attr(var->attrs, ATTR_IN); 03808 int out_attr = is_attr(var->attrs, ATTR_OUT); 03809 03810 if (!in_attr && !out_attr) 03811 in_attr = 1; 03812 03813 *alignment = 0; 03814 03815 if ((pass == PASS_IN && in_attr) || (pass == PASS_OUT && out_attr) || 03816 pass == PASS_RETURN) 03817 { 03818 if (is_ptrchain_attr(var, ATTR_CONTEXTHANDLE)) 03819 { 03820 *alignment = 4; 03821 return 20; 03822 } 03823 03824 if (!is_string_type(var->attrs, var->type)) 03825 return get_required_buffer_size_type(var->type, var->name, 03826 var->attrs, TRUE, alignment); 03827 } 03828 return 0; 03829 } 03830 03831 static unsigned int get_function_buffer_size( const var_t *func, enum pass pass ) 03832 { 03833 const var_t *var; 03834 unsigned int total_size = 0, alignment; 03835 03836 if (type_get_function_args(func->type)) 03837 { 03838 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 03839 { 03840 total_size += get_required_buffer_size(var, &alignment, pass); 03841 total_size += alignment; 03842 } 03843 } 03844 03845 if (pass == PASS_OUT && !is_void(type_function_get_rettype(func->type))) 03846 { 03847 var_t v = *func; 03848 v.type = type_function_get_rettype(func->type); 03849 total_size += get_required_buffer_size(&v, &alignment, PASS_RETURN); 03850 total_size += alignment; 03851 } 03852 return total_size; 03853 } 03854 03855 static void print_phase_function(FILE *file, int indent, const char *type, 03856 const char *local_var_prefix, enum remoting_phase phase, 03857 const var_t *var, unsigned int type_offset) 03858 { 03859 const char *function; 03860 switch (phase) 03861 { 03862 case PHASE_BUFFERSIZE: 03863 function = "BufferSize"; 03864 break; 03865 case PHASE_MARSHAL: 03866 function = "Marshall"; 03867 break; 03868 case PHASE_UNMARSHAL: 03869 function = "Unmarshall"; 03870 break; 03871 case PHASE_FREE: 03872 function = "Free"; 03873 break; 03874 default: 03875 assert(0); 03876 return; 03877 } 03878 03879 print_file(file, indent, "Ndr%s%s(\n", type, function); 03880 indent++; 03881 print_file(file, indent, "&__frame->_StubMsg,\n"); 03882 print_file(file, indent, "%s%s%s%s%s,\n", 03883 (phase == PHASE_UNMARSHAL) ? "(unsigned char **)" : "(unsigned char *)", 03884 (phase == PHASE_UNMARSHAL || decl_indirect(var->type)) ? "&" : "", 03885 local_var_prefix, 03886 (phase == PHASE_UNMARSHAL && decl_indirect(var->type)) ? "_p_" : "", 03887 var->name); 03888 print_file(file, indent, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]%s\n", 03889 type_offset, (phase == PHASE_UNMARSHAL) ? "," : ");"); 03890 if (phase == PHASE_UNMARSHAL) 03891 print_file(file, indent, "0);\n"); 03892 indent--; 03893 } 03894 03895 void print_phase_basetype(FILE *file, int indent, const char *local_var_prefix, 03896 enum remoting_phase phase, enum pass pass, const var_t *var, 03897 const char *varname) 03898 { 03899 type_t *type = var->type; 03900 unsigned int alignment = 0; 03901 03902 /* no work to do for other phases, buffer sizing is done elsewhere */ 03903 if (phase != PHASE_MARSHAL && phase != PHASE_UNMARSHAL) 03904 return; 03905 03906 if (type_get_type(type) == TYPE_ENUM || 03907 (type_get_type(type) == TYPE_BASIC && 03908 type_basic_get_type(type) == TYPE_BASIC_INT3264 && 03909 pointer_size != 4)) 03910 { 03911 unsigned char fc; 03912 03913 if (type_get_type(type) == TYPE_ENUM) 03914 fc = get_enum_fc(type); 03915 else 03916 fc = get_basic_fc(type); 03917 03918 if (phase == PHASE_MARSHAL) 03919 print_file(file, indent, "NdrSimpleTypeMarshall(\n"); 03920 else 03921 print_file(file, indent, "NdrSimpleTypeUnmarshall(\n"); 03922 print_file(file, indent+1, "&__frame->_StubMsg,\n"); 03923 print_file(file, indent+1, "(unsigned char *)&%s%s,\n", 03924 local_var_prefix, 03925 var->name); 03926 print_file(file, indent+1, "0x%02x /* %s */);\n", fc, string_of_type(fc)); 03927 } 03928 else 03929 { 03930 const type_t *ref = is_ptr(type) ? type_pointer_get_ref(type) : type; 03931 switch (get_basic_fc(ref)) 03932 { 03933 case RPC_FC_BYTE: 03934 case RPC_FC_CHAR: 03935 case RPC_FC_SMALL: 03936 case RPC_FC_USMALL: 03937 alignment = 1; 03938 break; 03939 03940 case RPC_FC_WCHAR: 03941 case RPC_FC_USHORT: 03942 case RPC_FC_SHORT: 03943 alignment = 2; 03944 break; 03945 03946 case RPC_FC_ULONG: 03947 case RPC_FC_LONG: 03948 case RPC_FC_FLOAT: 03949 case RPC_FC_ERROR_STATUS_T: 03950 /* pointer_size must be 4 if we got here in these two cases */ 03951 case RPC_FC_INT3264: 03952 case RPC_FC_UINT3264: 03953 alignment = 4; 03954 break; 03955 03956 case RPC_FC_HYPER: 03957 case RPC_FC_DOUBLE: 03958 alignment = 8; 03959 break; 03960 03961 case RPC_FC_IGNORE: 03962 case RPC_FC_BIND_PRIMITIVE: 03963 /* no marshalling needed */ 03964 return; 03965 03966 default: 03967 error("print_phase_basetype: Unsupported type: %s (0x%02x, ptr_level: 0)\n", 03968 var->name, get_basic_fc(ref)); 03969 } 03970 03971 if (phase == PHASE_MARSHAL && alignment > 1) 03972 print_file(file, indent, "MIDL_memset(__frame->_StubMsg.Buffer, 0, (0x%x - (ULONG_PTR)__frame->_StubMsg.Buffer) & 0x%x);\n", alignment, alignment - 1); 03973 print_file(file, indent, "__frame->_StubMsg.Buffer = (unsigned char *)(((ULONG_PTR)__frame->_StubMsg.Buffer + %u) & ~0x%x);\n", 03974 alignment - 1, alignment - 1); 03975 03976 if (phase == PHASE_MARSHAL) 03977 { 03978 print_file(file, indent, "*("); 03979 write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); 03980 if (is_ptr(type)) 03981 fprintf(file, " *)__frame->_StubMsg.Buffer = *"); 03982 else 03983 fprintf(file, " *)__frame->_StubMsg.Buffer = "); 03984 fprintf(file, "%s%s", local_var_prefix, varname); 03985 fprintf(file, ";\n"); 03986 } 03987 else if (phase == PHASE_UNMARSHAL) 03988 { 03989 print_file(file, indent, "if (__frame->_StubMsg.Buffer + sizeof("); 03990 write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); 03991 fprintf(file, ") > __frame->_StubMsg.BufferEnd)\n"); 03992 print_file(file, indent, "{\n"); 03993 print_file(file, indent + 1, "RpcRaiseException(RPC_X_BAD_STUB_DATA);\n"); 03994 print_file(file, indent, "}\n"); 03995 print_file(file, indent, "%s%s%s", 03996 (pass == PASS_IN || pass == PASS_RETURN) ? "" : "*", 03997 local_var_prefix, varname); 03998 if (pass == PASS_IN && is_ptr(type)) 03999 fprintf(file, " = ("); 04000 else 04001 fprintf(file, " = *("); 04002 write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); 04003 fprintf(file, " *)__frame->_StubMsg.Buffer;\n"); 04004 } 04005 04006 print_file(file, indent, "__frame->_StubMsg.Buffer += sizeof("); 04007 write_type_decl(file, is_ptr(type) ? type_pointer_get_ref(type) : type, NULL); 04008 fprintf(file, ");\n"); 04009 } 04010 } 04011 04012 /* returns whether the MaxCount, Offset or ActualCount members need to be 04013 * filled in for the specified phase */ 04014 static inline int is_conformance_needed_for_phase(enum remoting_phase phase) 04015 { 04016 return (phase != PHASE_UNMARSHAL); 04017 } 04018 04019 expr_t *get_size_is_expr(const type_t *t, const char *name) 04020 { 04021 expr_t *x = NULL; 04022 04023 for ( ; is_array(t); t = type_array_get_element(t)) 04024 if (type_array_has_conformance(t) && 04025 type_array_get_conformance(t)->type != EXPR_VOID) 04026 { 04027 if (!x) 04028 x = type_array_get_conformance(t); 04029 else 04030 error("%s: multidimensional conformant" 04031 " arrays not supported at the top level\n", 04032 name); 04033 } 04034 04035 return x; 04036 } 04037 04038 void write_parameter_conf_or_var_exprs(FILE *file, int indent, const char *local_var_prefix, 04039 enum remoting_phase phase, const var_t *var, int valid_variance) 04040 { 04041 const type_t *type = var->type; 04042 /* get fundamental type for the argument */ 04043 for (;;) 04044 { 04045 switch (typegen_detect_type(type, var->attrs, TDT_IGNORE_STRINGS|TDT_IGNORE_RANGES)) 04046 { 04047 case TGT_ARRAY: 04048 if (is_conformance_needed_for_phase(phase)) 04049 { 04050 if (type_array_has_conformance(type) && 04051 type_array_get_conformance(type)->type != EXPR_VOID) 04052 { 04053 print_file(file, indent, "__frame->_StubMsg.MaxCount = (ULONG_PTR)"); 04054 write_expr(file, type_array_get_conformance(type), 1, 1, NULL, NULL, local_var_prefix); 04055 fprintf(file, ";\n\n"); 04056 } 04057 if (type_array_has_variance(type)) 04058 { 04059 print_file(file, indent, "__frame->_StubMsg.Offset = 0;\n"); /* FIXME */ 04060 if (valid_variance) 04061 { 04062 print_file(file, indent, "__frame->_StubMsg.ActualCount = (ULONG_PTR)"); 04063 write_expr(file, type_array_get_variance(type), 1, 1, NULL, NULL, local_var_prefix); 04064 fprintf(file, ";\n\n"); 04065 } 04066 else 04067 print_file(file, indent, "__frame->_StubMsg.ActualCount = __frame->_StubMsg.MaxCount;\n\n"); 04068 } 04069 } 04070 break; 04071 case TGT_UNION: 04072 if (type_get_type(type) == TYPE_UNION && 04073 is_conformance_needed_for_phase(phase)) 04074 { 04075 print_file(file, indent, "__frame->_StubMsg.MaxCount = (ULONG_PTR)"); 04076 write_expr(file, get_attrp(var->attrs, ATTR_SWITCHIS), 1, 1, NULL, NULL, local_var_prefix); 04077 fprintf(file, ";\n\n"); 04078 } 04079 break; 04080 case TGT_IFACE_POINTER: 04081 { 04082 expr_t *iid; 04083 04084 if (is_conformance_needed_for_phase(phase) && (iid = get_attrp( var->attrs, ATTR_IIDIS ))) 04085 { 04086 print_file( file, indent, "__frame->_StubMsg.MaxCount = (ULONG_PTR) " ); 04087 write_expr( file, iid, 1, 1, NULL, NULL, local_var_prefix ); 04088 fprintf( file, ";\n\n" ); 04089 } 04090 break; 04091 } 04092 case TGT_POINTER: 04093 type = type_pointer_get_ref(type); 04094 continue; 04095 case TGT_INVALID: 04096 case TGT_USER_TYPE: 04097 case TGT_CTXT_HANDLE: 04098 case TGT_CTXT_HANDLE_POINTER: 04099 case TGT_STRING: 04100 case TGT_BASIC: 04101 case TGT_ENUM: 04102 case TGT_STRUCT: 04103 case TGT_RANGE: 04104 break; 04105 } 04106 break; 04107 } 04108 } 04109 04110 static void write_remoting_arg(FILE *file, int indent, const var_t *func, const char *local_var_prefix, 04111 enum pass pass, enum remoting_phase phase, const var_t *var) 04112 { 04113 int in_attr, out_attr, pointer_type; 04114 const char *type_str = NULL; 04115 const type_t *type = var->type; 04116 unsigned int alignment, start_offset = type->typestring_offset; 04117 04118 if (is_ptr(type) || is_array(type)) 04119 pointer_type = get_pointer_fc(type, var->attrs, pass != PASS_RETURN); 04120 else 04121 pointer_type = 0; 04122 04123 in_attr = is_attr(var->attrs, ATTR_IN); 04124 out_attr = is_attr(var->attrs, ATTR_OUT); 04125 if (!in_attr && !out_attr) 04126 in_attr = 1; 04127 04128 if (phase != PHASE_FREE) 04129 switch (pass) 04130 { 04131 case PASS_IN: 04132 if (!in_attr) return; 04133 break; 04134 case PASS_OUT: 04135 if (!out_attr) return; 04136 break; 04137 case PASS_RETURN: 04138 break; 04139 } 04140 04141 if (phase == PHASE_BUFFERSIZE && get_required_buffer_size( var, &alignment, pass )) return; 04142 04143 write_parameter_conf_or_var_exprs(file, indent, local_var_prefix, phase, var, TRUE); 04144 04145 switch (typegen_detect_type(type, var->attrs, TDT_ALL_TYPES)) 04146 { 04147 case TGT_CTXT_HANDLE: 04148 case TGT_CTXT_HANDLE_POINTER: 04149 if (phase == PHASE_MARSHAL) 04150 { 04151 if (pass == PASS_IN) 04152 { 04153 /* if the context_handle attribute appears in the chain of types 04154 * without pointers being followed, then the context handle must 04155 * be direct, otherwise it is a pointer */ 04156 int is_ch_ptr = is_aliaschain_attr(type, ATTR_CONTEXTHANDLE) ? FALSE : TRUE; 04157 print_file(file, indent, "NdrClientContextMarshall(\n"); 04158 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 04159 print_file(file, indent + 1, "(NDR_CCONTEXT)%s%s%s,\n", is_ch_ptr ? "*" : "", local_var_prefix, var->name); 04160 print_file(file, indent + 1, "%s);\n", in_attr && out_attr ? "1" : "0"); 04161 } 04162 else 04163 { 04164 print_file(file, indent, "NdrServerContextNewMarshall(\n"); 04165 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 04166 print_file(file, indent + 1, "(NDR_SCONTEXT)%s%s,\n", local_var_prefix, var->name); 04167 print_file(file, indent + 1, "(NDR_RUNDOWN)%s_rundown,\n", get_context_handle_type_name(var->type)); 04168 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset); 04169 } 04170 } 04171 else if (phase == PHASE_UNMARSHAL) 04172 { 04173 if (pass == PASS_OUT) 04174 { 04175 if (!in_attr) 04176 print_file(file, indent, "*%s%s = 0;\n", local_var_prefix, var->name); 04177 print_file(file, indent, "NdrClientContextUnmarshall(\n"); 04178 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 04179 print_file(file, indent + 1, "(NDR_CCONTEXT *)%s%s,\n", local_var_prefix, var->name); 04180 print_file(file, indent + 1, "__frame->_Handle);\n"); 04181 } 04182 else 04183 { 04184 print_file(file, indent, "%s%s = NdrServerContextNewUnmarshall(\n", local_var_prefix, var->name); 04185 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 04186 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", start_offset); 04187 } 04188 } 04189 break; 04190 case TGT_USER_TYPE: 04191 print_phase_function(file, indent, "UserMarshal", local_var_prefix, phase, var, start_offset); 04192 break; 04193 case TGT_STRING: 04194 if (phase == PHASE_FREE || pass == PASS_RETURN || 04195 pointer_type != RPC_FC_RP) 04196 { 04197 /* strings returned are assumed to be global and hence don't 04198 * need freeing */ 04199 if (is_declptr(type) && !(phase == PHASE_FREE && pass == PASS_RETURN)) 04200 print_phase_function(file, indent, "Pointer", local_var_prefix, 04201 phase, var, start_offset); 04202 else if (pointer_type == RPC_FC_RP && phase == PHASE_FREE && 04203 !in_attr && is_conformant_array(type)) 04204 { 04205 print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name); 04206 indent++; 04207 print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name); 04208 } 04209 } 04210 else 04211 { 04212 unsigned int real_start_offset = start_offset; 04213 /* skip over pointer description straight to string description */ 04214 if (is_declptr(type)) 04215 { 04216 if (is_conformant_array(type)) 04217 real_start_offset += 4; 04218 else 04219 real_start_offset += 2; 04220 } 04221 if (is_array(type) && !is_conformant_array(type)) 04222 print_phase_function(file, indent, "NonConformantString", 04223 local_var_prefix, phase, var, 04224 real_start_offset); 04225 else 04226 print_phase_function(file, indent, "ConformantString", local_var_prefix, 04227 phase, var, real_start_offset); 04228 } 04229 break; 04230 case TGT_ARRAY: 04231 { 04232 unsigned char tc = get_array_fc(type); 04233 const char *array_type = NULL; 04234 04235 /* We already have the size_is expression since it's at the 04236 top level, but do checks for multidimensional conformant 04237 arrays. When we handle them, we'll need to extend this 04238 function to return a list, and then we'll actually use 04239 the return value. */ 04240 get_size_is_expr(type, var->name); 04241 04242 switch (tc) 04243 { 04244 case RPC_FC_SMFARRAY: 04245 case RPC_FC_LGFARRAY: 04246 array_type = "FixedArray"; 04247 break; 04248 case RPC_FC_SMVARRAY: 04249 case RPC_FC_LGVARRAY: 04250 array_type = "VaryingArray"; 04251 break; 04252 case RPC_FC_CARRAY: 04253 array_type = "ConformantArray"; 04254 break; 04255 case RPC_FC_CVARRAY: 04256 array_type = "ConformantVaryingArray"; 04257 break; 04258 case RPC_FC_BOGUS_ARRAY: 04259 array_type = "ComplexArray"; 04260 break; 04261 } 04262 04263 if (pointer_type != RPC_FC_RP) array_type = "Pointer"; 04264 04265 if (phase == PHASE_FREE && pointer_type == RPC_FC_RP) 04266 { 04267 /* these are all unmarshalled by allocating memory */ 04268 if (tc == RPC_FC_BOGUS_ARRAY || 04269 tc == RPC_FC_CVARRAY || 04270 ((tc == RPC_FC_SMVARRAY || tc == RPC_FC_LGVARRAY) && in_attr) || 04271 (tc == RPC_FC_CARRAY && !in_attr)) 04272 { 04273 if (type_array_is_decl_as_ptr(type) && type->details.array.ptr_tfsoff) 04274 { 04275 print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, 04276 type->details.array.ptr_tfsoff); 04277 break; 04278 } 04279 print_phase_function(file, indent, array_type, local_var_prefix, phase, var, start_offset); 04280 print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name); 04281 indent++; 04282 print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name); 04283 break; 04284 } 04285 } 04286 print_phase_function(file, indent, array_type, local_var_prefix, phase, var, start_offset); 04287 break; 04288 } 04289 case TGT_BASIC: 04290 print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name); 04291 break; 04292 case TGT_ENUM: 04293 print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name); 04294 break; 04295 case TGT_RANGE: 04296 print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name); 04297 /* Note: this goes beyond what MIDL does - it only supports arguments 04298 * with the [range] attribute in Oicf mode */ 04299 if (phase == PHASE_UNMARSHAL) 04300 { 04301 const expr_t *range_min; 04302 const expr_t *range_max; 04303 expr_list_t *range_list = get_attrp(var->attrs, ATTR_RANGE); 04304 if (!range_list) 04305 range_list = get_aliaschain_attrp(type, ATTR_RANGE); 04306 range_min = LIST_ENTRY(list_head(range_list), const expr_t, entry); 04307 range_max = LIST_ENTRY(list_next(range_list, list_head(range_list)), const expr_t, entry); 04308 04309 print_file(file, indent, "if ((%s%s < (", local_var_prefix, var->name); 04310 write_type_decl(file, var->type, NULL); 04311 fprintf(file, ")0x%x) || (%s%s > (", range_min->cval, local_var_prefix, var->name); 04312 write_type_decl(file, var->type, NULL); 04313 fprintf(file, ")0x%x))\n", range_max->cval); 04314 print_file(file, indent, "{\n"); 04315 print_file(file, indent+1, "RpcRaiseException(RPC_S_INVALID_BOUND);\n"); 04316 print_file(file, indent, "}\n"); 04317 } 04318 break; 04319 case TGT_STRUCT: 04320 switch (get_struct_fc(type)) 04321 { 04322 case RPC_FC_STRUCT: 04323 if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL) 04324 print_phase_function(file, indent, "SimpleStruct", local_var_prefix, phase, var, start_offset); 04325 break; 04326 case RPC_FC_PSTRUCT: 04327 print_phase_function(file, indent, "SimpleStruct", local_var_prefix, phase, var, start_offset); 04328 break; 04329 case RPC_FC_CSTRUCT: 04330 case RPC_FC_CPSTRUCT: 04331 print_phase_function(file, indent, "ConformantStruct", local_var_prefix, phase, var, start_offset); 04332 break; 04333 case RPC_FC_CVSTRUCT: 04334 print_phase_function(file, indent, "ConformantVaryingStruct", local_var_prefix, phase, var, start_offset); 04335 break; 04336 case RPC_FC_BOGUS_STRUCT: 04337 print_phase_function(file, indent, "ComplexStruct", local_var_prefix, phase, var, start_offset); 04338 break; 04339 default: 04340 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, get_struct_fc(type)); 04341 } 04342 break; 04343 case TGT_UNION: 04344 { 04345 const char *union_type = NULL; 04346 04347 if (type_get_type(type) == TYPE_UNION) 04348 union_type = "NonEncapsulatedUnion"; 04349 else if (type_get_type(type) == TYPE_ENCAPSULATED_UNION) 04350 union_type = "EncapsulatedUnion"; 04351 04352 print_phase_function(file, indent, union_type, local_var_prefix, 04353 phase, var, start_offset); 04354 break; 04355 } 04356 case TGT_POINTER: 04357 { 04358 const type_t *ref = type_pointer_get_ref(type); 04359 if (pointer_type == RPC_FC_RP) switch (typegen_detect_type(ref, NULL, TDT_ALL_TYPES)) 04360 { 04361 case TGT_BASIC: 04362 print_phase_basetype(file, indent, local_var_prefix, phase, pass, var, var->name); 04363 break; 04364 case TGT_ENUM: 04365 /* base types have known sizes, so don't need a sizing pass 04366 * and don't have any memory to free and so don't need a 04367 * freeing pass */ 04368 if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL) 04369 print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset); 04370 break; 04371 case TGT_STRUCT: 04372 switch (get_struct_fc(ref)) 04373 { 04374 case RPC_FC_STRUCT: 04375 /* simple structs have known sizes, so don't need a sizing 04376 * pass and don't have any memory to free and so don't 04377 * need a freeing pass */ 04378 if (phase == PHASE_MARSHAL || phase == PHASE_UNMARSHAL) 04379 type_str = "SimpleStruct"; 04380 else if (phase == PHASE_FREE && pass == PASS_RETURN) 04381 { 04382 print_file(file, indent, "if (%s%s)\n", local_var_prefix, var->name); 04383 indent++; 04384 print_file(file, indent, "__frame->_StubMsg.pfnFree(%s%s);\n", local_var_prefix, var->name); 04385 indent--; 04386 } 04387 break; 04388 case RPC_FC_PSTRUCT: 04389 type_str = "SimpleStruct"; 04390 break; 04391 case RPC_FC_CSTRUCT: 04392 case RPC_FC_CPSTRUCT: 04393 type_str = "ConformantStruct"; 04394 break; 04395 case RPC_FC_CVSTRUCT: 04396 type_str = "ConformantVaryingStruct"; 04397 break; 04398 case RPC_FC_BOGUS_STRUCT: 04399 type_str = "ComplexStruct"; 04400 break; 04401 default: 04402 error("write_remoting_arguments: Unsupported type: %s (0x%02x)\n", var->name, get_struct_fc(ref)); 04403 } 04404 04405 if (type_str) 04406 { 04407 if (phase == PHASE_FREE) 04408 type_str = "Pointer"; 04409 else 04410 start_offset = ref->typestring_offset; 04411 print_phase_function(file, indent, type_str, local_var_prefix, phase, var, start_offset); 04412 } 04413 break; 04414 case TGT_UNION: 04415 if (phase == PHASE_FREE) 04416 type_str = "Pointer"; 04417 else 04418 { 04419 if (type_get_type(ref) == TYPE_UNION) 04420 type_str = "NonEncapsulatedUnion"; 04421 else if (type_get_type(ref) == TYPE_ENCAPSULATED_UNION) 04422 type_str = "EncapsulatedUnion"; 04423 04424 start_offset = ref->typestring_offset; 04425 } 04426 04427 print_phase_function(file, indent, type_str, local_var_prefix, 04428 phase, var, start_offset); 04429 break; 04430 case TGT_USER_TYPE: 04431 if (phase != PHASE_FREE) 04432 { 04433 type_str = "UserMarshal"; 04434 start_offset = ref->typestring_offset; 04435 } 04436 else type_str = "Pointer"; 04437 04438 print_phase_function(file, indent, type_str, local_var_prefix, phase, var, start_offset); 04439 break; 04440 case TGT_STRING: 04441 case TGT_POINTER: 04442 case TGT_ARRAY: 04443 case TGT_RANGE: 04444 case TGT_IFACE_POINTER: 04445 case TGT_CTXT_HANDLE: 04446 case TGT_CTXT_HANDLE_POINTER: 04447 print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset); 04448 break; 04449 case TGT_INVALID: 04450 assert(0); 04451 break; 04452 } 04453 else 04454 print_phase_function(file, indent, "Pointer", local_var_prefix, phase, var, start_offset); 04455 break; 04456 } 04457 case TGT_IFACE_POINTER: 04458 print_phase_function(file, indent, "InterfacePointer", local_var_prefix, phase, var, start_offset); 04459 break; 04460 case TGT_INVALID: 04461 assert(0); 04462 break; 04463 } 04464 fprintf(file, "\n"); 04465 } 04466 04467 void write_remoting_arguments(FILE *file, int indent, const var_t *func, const char *local_var_prefix, 04468 enum pass pass, enum remoting_phase phase) 04469 { 04470 if (phase == PHASE_BUFFERSIZE && pass != PASS_RETURN) 04471 { 04472 unsigned int size = get_function_buffer_size( func, pass ); 04473 print_file(file, indent, "__frame->_StubMsg.BufferLength = %u;\n", size); 04474 } 04475 04476 if (pass == PASS_RETURN) 04477 { 04478 var_t var; 04479 var = *func; 04480 var.type = type_function_get_rettype(func->type); 04481 var.name = xstrdup( "_RetVal" ); 04482 write_remoting_arg( file, indent, func, local_var_prefix, pass, phase, &var ); 04483 free( var.name ); 04484 } 04485 else 04486 { 04487 const var_t *var; 04488 if (!type_get_function_args(func->type)) 04489 return; 04490 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 04491 write_remoting_arg( file, indent, func, local_var_prefix, pass, phase, var ); 04492 } 04493 } 04494 04495 04496 unsigned int get_size_procformatstring_func(const type_t *iface, const var_t *func) 04497 { 04498 unsigned int offset = 0; 04499 write_procformatstring_func( NULL, 0, iface, func, &offset, 0 ); 04500 return offset; 04501 } 04502 04503 unsigned int get_size_procformatstring(const statement_list_t *stmts, type_pred_t pred) 04504 { 04505 const statement_t *stmt; 04506 unsigned int size = 1; 04507 04508 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 04509 { 04510 const type_t *iface; 04511 const statement_t *stmt_func; 04512 04513 if (stmt->type == STMT_LIBRARY) 04514 { 04515 size += get_size_procformatstring(stmt->u.lib->stmts, pred) - 1; 04516 continue; 04517 } 04518 else if (stmt->type != STMT_TYPE || type_get_type(stmt->u.type) != TYPE_INTERFACE) 04519 continue; 04520 04521 iface = stmt->u.type; 04522 if (!pred(iface)) 04523 continue; 04524 04525 STATEMENTS_FOR_EACH_FUNC( stmt_func, type_iface_get_stmts(iface) ) 04526 { 04527 const var_t *func = stmt_func->u.var; 04528 if (!is_local(func->attrs)) 04529 size += get_size_procformatstring_func( iface, func ); 04530 } 04531 } 04532 return size; 04533 } 04534 04535 unsigned int get_size_typeformatstring(const statement_list_t *stmts, type_pred_t pred) 04536 { 04537 set_all_tfswrite(FALSE); 04538 return process_tfs(NULL, stmts, pred); 04539 } 04540 04541 void declare_stub_args( FILE *file, int indent, const var_t *func ) 04542 { 04543 int in_attr, out_attr; 04544 int i = 0; 04545 const var_t *var; 04546 04547 /* declare return value '_RetVal' */ 04548 if (!is_void(type_function_get_rettype(func->type))) 04549 { 04550 print_file(file, indent, "%s", ""); 04551 write_type_decl_left(file, type_function_get_rettype(func->type)); 04552 fprintf(file, " _RetVal;\n"); 04553 } 04554 04555 if (!type_get_function_args(func->type)) 04556 return; 04557 04558 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 04559 { 04560 in_attr = is_attr(var->attrs, ATTR_IN); 04561 out_attr = is_attr(var->attrs, ATTR_OUT); 04562 if (!out_attr && !in_attr) 04563 in_attr = 1; 04564 04565 if (is_context_handle(var->type)) 04566 print_file(file, indent, "NDR_SCONTEXT %s;\n", var->name); 04567 else 04568 { 04569 if (!in_attr && !is_conformant_array(var->type)) 04570 { 04571 type_t *type_to_print; 04572 char name[16]; 04573 print_file(file, indent, "%s", ""); 04574 if (type_get_type(var->type) == TYPE_ARRAY && 04575 !type_array_is_decl_as_ptr(var->type)) 04576 type_to_print = var->type; 04577 else 04578 type_to_print = type_pointer_get_ref(var->type); 04579 sprintf(name, "_W%u", i++); 04580 write_type_decl(file, type_to_print, name); 04581 fprintf(file, ";\n"); 04582 } 04583 04584 print_file(file, indent, "%s", ""); 04585 write_type_decl_left(file, var->type); 04586 fprintf(file, " "); 04587 if (type_get_type(var->type) == TYPE_ARRAY && 04588 !type_array_is_decl_as_ptr(var->type)) { 04589 fprintf(file, "(*%s)", var->name); 04590 } else 04591 fprintf(file, "%s", var->name); 04592 write_type_right(file, var->type, FALSE); 04593 fprintf(file, ";\n"); 04594 04595 if (decl_indirect(var->type)) 04596 print_file(file, indent, "void *_p_%s;\n", var->name); 04597 } 04598 } 04599 } 04600 04601 04602 void assign_stub_out_args( FILE *file, int indent, const var_t *func, const char *local_var_prefix ) 04603 { 04604 int in_attr, out_attr; 04605 int i = 0, sep = 0; 04606 const var_t *var; 04607 04608 if (!type_get_function_args(func->type)) 04609 return; 04610 04611 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 04612 { 04613 in_attr = is_attr(var->attrs, ATTR_IN); 04614 out_attr = is_attr(var->attrs, ATTR_OUT); 04615 if (!out_attr && !in_attr) 04616 in_attr = 1; 04617 04618 if (!in_attr) 04619 { 04620 print_file(file, indent, "%s%s", local_var_prefix, var->name); 04621 04622 switch (typegen_detect_type(var->type, var->attrs, TDT_IGNORE_STRINGS)) 04623 { 04624 case TGT_CTXT_HANDLE_POINTER: 04625 fprintf(file, " = NdrContextHandleInitialize(\n"); 04626 print_file(file, indent + 1, "&__frame->_StubMsg,\n"); 04627 print_file(file, indent + 1, "(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%d]);\n", 04628 var->type->typestring_offset); 04629 break; 04630 case TGT_ARRAY: 04631 if (type_array_has_conformance(var->type)) 04632 { 04633 unsigned int size; 04634 type_t *type; 04635 04636 fprintf(file, " = NdrAllocate(&__frame->_StubMsg, "); 04637 for (type = var->type; 04638 is_array(type) && type_array_has_conformance(type); 04639 type = type_array_get_element(type)) 04640 { 04641 write_expr(file, type_array_get_conformance(type), TRUE, 04642 TRUE, NULL, NULL, local_var_prefix); 04643 fprintf(file, " * "); 04644 } 04645 size = type_memsize(type); 04646 fprintf(file, "%u);\n", size); 04647 04648 print_file(file, indent, "memset(%s%s, 0, ", local_var_prefix, var->name); 04649 for (type = var->type; 04650 is_array(type) && type_array_has_conformance(type); 04651 type = type_array_get_element(type)) 04652 { 04653 write_expr(file, type_array_get_conformance(type), TRUE, 04654 TRUE, NULL, NULL, local_var_prefix); 04655 fprintf(file, " * "); 04656 } 04657 size = type_memsize(type); 04658 fprintf(file, "%u);\n", size); 04659 } 04660 else 04661 fprintf(file, " = &%s_W%u;\n", local_var_prefix, i++); 04662 break; 04663 case TGT_POINTER: 04664 fprintf(file, " = &%s_W%u;\n", local_var_prefix, i); 04665 switch (typegen_detect_type(type_pointer_get_ref(var->type), var->attrs, TDT_IGNORE_STRINGS)) 04666 { 04667 case TGT_BASIC: 04668 case TGT_ENUM: 04669 case TGT_POINTER: 04670 case TGT_RANGE: 04671 case TGT_IFACE_POINTER: 04672 print_file(file, indent, "%s_W%u = 0;\n", local_var_prefix, i); 04673 break; 04674 case TGT_USER_TYPE: 04675 print_file(file, indent, "memset(&%s_W%u, 0, sizeof(%s_W%u));\n", 04676 local_var_prefix, i, local_var_prefix, i); 04677 break; 04678 case TGT_STRUCT: 04679 case TGT_UNION: 04680 case TGT_ARRAY: 04681 case TGT_CTXT_HANDLE: 04682 case TGT_CTXT_HANDLE_POINTER: 04683 case TGT_INVALID: 04684 case TGT_STRING: 04685 /* not initialised */ 04686 break; 04687 } 04688 i++; 04689 break; 04690 default: 04691 break; 04692 } 04693 04694 sep = 1; 04695 } 04696 } 04697 if (sep) 04698 fprintf(file, "\n"); 04699 } 04700 04701 04702 void write_func_param_struct( FILE *file, const type_t *iface, const type_t *func, 04703 const char *var_decl, int add_retval ) 04704 { 04705 type_t *rettype = type_function_get_rettype( func ); 04706 const var_list_t *args = type_get_function_args( func ); 04707 const var_t *arg; 04708 int needs_packing; 04709 unsigned int align = 0; 04710 04711 if (args) 04712 LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) 04713 if (!is_array( arg->type )) type_memsize_and_alignment( arg->type, &align ); 04714 04715 needs_packing = (align > pointer_size); 04716 04717 if (needs_packing) print_file( file, 0, "#include <pshpack%u.h>\n", pointer_size ); 04718 print_file(file, 1, "struct _PARAM_STRUCT\n" ); 04719 print_file(file, 1, "{\n" ); 04720 if (is_object( iface )) print_file(file, 2, "%s *This;\n", iface->name ); 04721 04722 if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) 04723 { 04724 print_file(file, 2, "%s", ""); 04725 write_type_left( file, (type_t *)arg->type, TRUE ); 04726 if (needs_space_after( arg->type )) fputc( ' ', file ); 04727 if (is_array( arg->type ) && !type_array_is_decl_as_ptr( arg->type )) fputc( '*', file ); 04728 04729 /* FIXME: should check for large args being passed by pointer */ 04730 align = 0; 04731 if (is_array( arg->type ) || is_ptr( arg->type )) align = pointer_size; 04732 else type_memsize_and_alignment( arg->type, &align ); 04733 04734 if (align >= pointer_size) 04735 fprintf( file, "%s;\n", arg->name ); 04736 else 04737 fprintf( file, "%s DECLSPEC_ALIGN(%u);\n", arg->name, pointer_size ); 04738 } 04739 if (add_retval && !is_void( rettype )) 04740 { 04741 print_file(file, 2, "%s", ""); 04742 write_type_decl( file, rettype, "_RetVal" ); 04743 if (is_array( rettype ) || is_ptr( rettype ) || type_memsize( rettype ) == pointer_size) 04744 fprintf( file, ";\n" ); 04745 else 04746 fprintf( file, " DECLSPEC_ALIGN(%u);\n", pointer_size ); 04747 } 04748 print_file(file, 1, "} %s;\n", var_decl ); 04749 if (needs_packing) print_file( file, 0, "#include <poppack.h>\n" ); 04750 print_file( file, 0, "\n" ); 04751 } 04752 04753 void write_pointer_checks( FILE *file, int indent, const var_t *func ) 04754 { 04755 const var_list_t *args = type_get_function_args( func->type ); 04756 const var_t *var; 04757 04758 if (!args) return; 04759 04760 LIST_FOR_EACH_ENTRY( var, args, const var_t, entry ) 04761 if (cant_be_null( var )) 04762 print_file( file, indent, "if (!%s) RpcRaiseException(RPC_X_NULL_REF_POINTER);\n", var->name ); 04763 } 04764 04765 int write_expr_eval_routines(FILE *file, const char *iface) 04766 { 04767 static const char *var_name = "pS"; 04768 static const char *var_name_expr = "pS->"; 04769 int result = 0; 04770 struct expr_eval_routine *eval; 04771 unsigned short callback_offset = 0; 04772 04773 LIST_FOR_EACH_ENTRY(eval, &expr_eval_routines, struct expr_eval_routine, entry) 04774 { 04775 const char *name = eval->name; 04776 result = 1; 04777 04778 print_file(file, 0, "static void __RPC_USER %s_%sExprEval_%04u(PMIDL_STUB_MESSAGE pStubMsg)\n", 04779 eval->iface ? eval->iface->name : iface, name, callback_offset); 04780 print_file(file, 0, "{\n"); 04781 if (type_get_type( eval->cont_type ) == TYPE_FUNCTION) 04782 { 04783 write_func_param_struct( file, eval->iface, eval->cont_type, 04784 "*pS = (struct _PARAM_STRUCT *)pStubMsg->StackTop", FALSE ); 04785 } 04786 else 04787 { 04788 print_file(file, 1, "%s", ""); 04789 write_type_left(file, (type_t *)eval->cont_type, TRUE); 04790 fprintf(file, " *%s = (", var_name); 04791 write_type_left(file, (type_t *)eval->cont_type, TRUE); 04792 fprintf(file, " *)(pStubMsg->StackTop - %u);\n", eval->baseoff); 04793 } 04794 print_file(file, 1, "pStubMsg->Offset = 0;\n"); /* FIXME */ 04795 print_file(file, 1, "pStubMsg->MaxCount = (ULONG_PTR)"); 04796 write_expr(file, eval->expr, 1, 1, var_name_expr, eval->cont_type, ""); 04797 fprintf(file, ";\n"); 04798 print_file(file, 0, "}\n\n"); 04799 callback_offset++; 04800 } 04801 return result; 04802 } 04803 04804 void write_expr_eval_routine_list(FILE *file, const char *iface) 04805 { 04806 struct expr_eval_routine *eval; 04807 struct expr_eval_routine *cursor; 04808 unsigned short callback_offset = 0; 04809 04810 fprintf(file, "static const EXPR_EVAL ExprEvalRoutines[] =\n"); 04811 fprintf(file, "{\n"); 04812 04813 LIST_FOR_EACH_ENTRY_SAFE(eval, cursor, &expr_eval_routines, struct expr_eval_routine, entry) 04814 { 04815 print_file(file, 1, "%s_%sExprEval_%04u,\n", 04816 eval->iface ? eval->iface->name : iface, eval->name, callback_offset); 04817 callback_offset++; 04818 list_remove(&eval->entry); 04819 free(eval->name); 04820 free(eval); 04821 } 04822 04823 fprintf(file, "};\n\n"); 04824 } 04825 04826 void write_user_quad_list(FILE *file) 04827 { 04828 user_type_t *ut; 04829 04830 if (list_empty(&user_type_list)) 04831 return; 04832 04833 fprintf(file, "static const USER_MARSHAL_ROUTINE_QUADRUPLE UserMarshalRoutines[] =\n"); 04834 fprintf(file, "{\n"); 04835 LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry) 04836 { 04837 const char *sep = &ut->entry == list_tail(&user_type_list) ? "" : ","; 04838 print_file(file, 1, "{\n"); 04839 print_file(file, 2, "(USER_MARSHAL_SIZING_ROUTINE)%s_UserSize,\n", ut->name); 04840 print_file(file, 2, "(USER_MARSHAL_MARSHALLING_ROUTINE)%s_UserMarshal,\n", ut->name); 04841 print_file(file, 2, "(USER_MARSHAL_UNMARSHALLING_ROUTINE)%s_UserUnmarshal,\n", ut->name); 04842 print_file(file, 2, "(USER_MARSHAL_FREEING_ROUTINE)%s_UserFree\n", ut->name); 04843 print_file(file, 1, "}%s\n", sep); 04844 } 04845 fprintf(file, "};\n\n"); 04846 } 04847 04848 void write_endpoints( FILE *f, const char *prefix, const str_list_t *list ) 04849 { 04850 const struct str_list_entry_t *endpoint; 04851 const char *p; 04852 04853 /* this should be an array of RPC_PROTSEQ_ENDPOINT but we want const strings */ 04854 print_file( f, 0, "static const unsigned char * const %s__RpcProtseqEndpoint[][2] =\n{\n", prefix ); 04855 LIST_FOR_EACH_ENTRY( endpoint, list, const struct str_list_entry_t, entry ) 04856 { 04857 print_file( f, 1, "{ (const unsigned char *)\"" ); 04858 for (p = endpoint->str; *p && *p != ':'; p++) 04859 { 04860 if (*p == '"' || *p == '\\') fputc( '\\', f ); 04861 fputc( *p, f ); 04862 } 04863 if (!*p) goto error; 04864 if (p[1] != '[') goto error; 04865 04866 fprintf( f, "\", (const unsigned char *)\"" ); 04867 for (p += 2; *p && *p != ']'; p++) 04868 { 04869 if (*p == '"' || *p == '\\') fputc( '\\', f ); 04870 fputc( *p, f ); 04871 } 04872 if (*p != ']') goto error; 04873 fprintf( f, "\" },\n" ); 04874 } 04875 print_file( f, 0, "};\n\n" ); 04876 return; 04877 04878 error: 04879 error("Invalid endpoint syntax '%s'\n", endpoint->str); 04880 } 04881 04882 void write_client_call_routine( FILE *file, const type_t *iface, const var_t *func, 04883 const char *prefix, unsigned int proc_offset ) 04884 { 04885 type_t *rettype = type_function_get_rettype( func->type ); 04886 int has_ret = !is_void( rettype ); 04887 const var_list_t *args = type_get_function_args( func->type ); 04888 const var_t *arg; 04889 int len, needs_params = 0; 04890 04891 /* we need a param structure if we have more than one arg */ 04892 if (pointer_size == 4 && args) needs_params = is_object( iface ) || list_count( args ) > 1; 04893 04894 print_file( file, 0, "{\n"); 04895 if (needs_params) 04896 { 04897 if (has_ret) print_file( file, 1, "%s", "CLIENT_CALL_RETURN _RetVal;\n" ); 04898 write_func_param_struct( file, iface, func->type, "__params", FALSE ); 04899 if (is_object( iface )) print_file( file, 1, "__params.This = This;\n" ); 04900 if (args) 04901 LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) 04902 print_file( file, 1, "__params.%s = %s;\n", arg->name, arg->name ); 04903 } 04904 else if (has_ret) print_file( file, 1, "%s", "CLIENT_CALL_RETURN _RetVal;\n\n" ); 04905 04906 len = fprintf( file, " %s%s( ", 04907 has_ret ? "_RetVal = " : "", 04908 get_stub_mode() == MODE_Oif ? "NdrClientCall2" : "NdrClientCall" ); 04909 fprintf( file, "&%s_StubDesc,", prefix ); 04910 fprintf( file, "\n%*s&__MIDL_ProcFormatString.Format[%u]", len, "", proc_offset ); 04911 if (needs_params) 04912 { 04913 fprintf( file, ",\n%*s&__params", len, "" ); 04914 } 04915 else if (pointer_size == 8) 04916 { 04917 if (is_object( iface )) fprintf( file, ",\n%*sThis", len, "" ); 04918 if (args) 04919 LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) 04920 fprintf( file, ",\n%*s%s", len, "", arg->name ); 04921 } 04922 else 04923 { 04924 if (is_object( iface )) fprintf( file, ",\n%*s&This", len, "" ); 04925 else if (args) 04926 { 04927 arg = LIST_ENTRY( list_head(args), const var_t, entry ); 04928 fprintf( file, ",\n%*s&%s", len, "", arg->name ); 04929 } 04930 } 04931 fprintf( file, " );\n" ); 04932 if (has_ret) 04933 { 04934 print_file( file, 1, "return (" ); 04935 write_type_decl_left(file, rettype); 04936 fprintf( file, ")%s;\n", pointer_size == 8 ? "_RetVal.Simple" : "*(LONG_PTR *)&_RetVal" ); 04937 } 04938 print_file( file, 0, "}\n\n"); 04939 } 04940 04941 void write_exceptions( FILE *file ) 04942 { 04943 fprintf( file, "#ifndef USE_COMPILER_EXCEPTIONS\n"); 04944 fprintf( file, "\n"); 04945 fprintf( file, "#include \"wine/exception.h\"\n"); 04946 fprintf( file, "#undef RpcTryExcept\n"); 04947 fprintf( file, "#undef RpcExcept\n"); 04948 fprintf( file, "#undef RpcEndExcept\n"); 04949 fprintf( file, "#undef RpcTryFinally\n"); 04950 fprintf( file, "#undef RpcFinally\n"); 04951 fprintf( file, "#undef RpcEndFinally\n"); 04952 fprintf( file, "#undef RpcExceptionCode\n"); 04953 fprintf( file, "#undef RpcAbnormalTermination\n"); 04954 fprintf( file, "\n"); 04955 fprintf( file, "struct __exception_frame;\n"); 04956 fprintf( file, "typedef int (*__filter_func)(struct __exception_frame *);\n"); 04957 fprintf( file, "typedef void (*__finally_func)(struct __exception_frame *);\n"); 04958 fprintf( file, "\n"); 04959 fprintf( file, "#define __DECL_EXCEPTION_FRAME \\\n"); 04960 fprintf( file, " EXCEPTION_REGISTRATION_RECORD frame; \\\n"); 04961 fprintf( file, " __filter_func filter; \\\n"); 04962 fprintf( file, " __finally_func finally; \\\n"); 04963 fprintf( file, " sigjmp_buf jmp; \\\n"); 04964 fprintf( file, " DWORD code; \\\n"); 04965 fprintf( file, " unsigned char abnormal_termination; \\\n"); 04966 fprintf( file, " unsigned char filter_level; \\\n"); 04967 fprintf( file, " unsigned char finally_level;\n"); 04968 fprintf( file, "\n"); 04969 fprintf( file, "struct __exception_frame\n{\n"); 04970 fprintf( file, " __DECL_EXCEPTION_FRAME\n"); 04971 fprintf( file, "};\n"); 04972 fprintf( file, "\n"); 04973 fprintf( file, "static inline void __widl_unwind_target(void)\n" ); 04974 fprintf( file, "{\n"); 04975 fprintf( file, " struct __exception_frame *exc_frame = (struct __exception_frame *)__wine_get_frame();\n" ); 04976 fprintf( file, " if (exc_frame->finally_level > exc_frame->filter_level)\n" ); 04977 fprintf( file, " {\n"); 04978 fprintf( file, " exc_frame->abnormal_termination = 1;\n"); 04979 fprintf( file, " exc_frame->finally( exc_frame );\n"); 04980 fprintf( file, " __wine_pop_frame( &exc_frame->frame );\n"); 04981 fprintf( file, " }\n"); 04982 fprintf( file, " exc_frame->filter_level = 0;\n"); 04983 fprintf( file, " siglongjmp( exc_frame->jmp, 1 );\n"); 04984 fprintf( file, "}\n"); 04985 fprintf( file, "\n"); 04986 fprintf( file, "static DWORD __widl_exception_handler( EXCEPTION_RECORD *record,\n"); 04987 fprintf( file, " EXCEPTION_REGISTRATION_RECORD *frame,\n"); 04988 fprintf( file, " CONTEXT *context,\n"); 04989 fprintf( file, " EXCEPTION_REGISTRATION_RECORD **pdispatcher )\n"); 04990 fprintf( file, "{\n"); 04991 fprintf( file, " struct __exception_frame *exc_frame = (struct __exception_frame *)frame;\n"); 04992 fprintf( file, "\n"); 04993 fprintf( file, " if (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND | EH_NESTED_CALL))\n"); 04994 fprintf( file, " {\n" ); 04995 fprintf( file, " if (exc_frame->finally_level && (record->ExceptionFlags & (EH_UNWINDING | EH_EXIT_UNWIND)))\n"); 04996 fprintf( file, " {\n" ); 04997 fprintf( file, " exc_frame->abnormal_termination = 1;\n"); 04998 fprintf( file, " exc_frame->finally( exc_frame );\n"); 04999 fprintf( file, " }\n" ); 05000 fprintf( file, " return ExceptionContinueSearch;\n"); 05001 fprintf( file, " }\n" ); 05002 fprintf( file, " exc_frame->code = record->ExceptionCode;\n"); 05003 fprintf( file, " if (exc_frame->filter_level && exc_frame->filter( exc_frame ) == EXCEPTION_EXECUTE_HANDLER)\n" ); 05004 fprintf( file, " __wine_rtl_unwind( frame, record, __widl_unwind_target );\n"); 05005 fprintf( file, " return ExceptionContinueSearch;\n"); 05006 fprintf( file, "}\n"); 05007 fprintf( file, "\n"); 05008 fprintf( file, "#define RpcTryExcept \\\n"); 05009 fprintf( file, " if (!sigsetjmp( __frame->jmp, 0 )) \\\n"); 05010 fprintf( file, " { \\\n"); 05011 fprintf( file, " if (!__frame->finally_level) \\\n" ); 05012 fprintf( file, " __wine_push_frame( &__frame->frame ); \\\n"); 05013 fprintf( file, " __frame->filter_level = __frame->finally_level + 1;\n" ); 05014 fprintf( file, "\n"); 05015 fprintf( file, "#define RpcExcept(expr) \\\n"); 05016 fprintf( file, " if (!__frame->finally_level) \\\n" ); 05017 fprintf( file, " __wine_pop_frame( &__frame->frame ); \\\n"); 05018 fprintf( file, " __frame->filter_level = 0; \\\n" ); 05019 fprintf( file, " } \\\n"); 05020 fprintf( file, " else \\\n"); 05021 fprintf( file, "\n"); 05022 fprintf( file, "#define RpcEndExcept\n"); 05023 fprintf( file, "\n"); 05024 fprintf( file, "#define RpcExceptionCode() (__frame->code)\n"); 05025 fprintf( file, "\n"); 05026 fprintf( file, "#define RpcTryFinally \\\n"); 05027 fprintf( file, " if (!__frame->filter_level) \\\n"); 05028 fprintf( file, " __wine_push_frame( &__frame->frame ); \\\n"); 05029 fprintf( file, " __frame->finally_level = __frame->filter_level + 1;\n"); 05030 fprintf( file, "\n"); 05031 fprintf( file, "#define RpcFinally \\\n"); 05032 fprintf( file, " if (!__frame->filter_level) \\\n"); 05033 fprintf( file, " __wine_pop_frame( &__frame->frame ); \\\n"); 05034 fprintf( file, " __frame->finally_level = 0;\n"); 05035 fprintf( file, "\n"); 05036 fprintf( file, "#define RpcEndFinally\n"); 05037 fprintf( file, "\n"); 05038 fprintf( file, "#define RpcAbnormalTermination() (__frame->abnormal_termination)\n"); 05039 fprintf( file, "\n"); 05040 fprintf( file, "#define RpcExceptionInit(filter_func,finally_func) \\\n"); 05041 fprintf( file, " do { \\\n"); 05042 fprintf( file, " __frame->frame.Handler = __widl_exception_handler; \\\n"); 05043 fprintf( file, " __frame->filter = (__filter_func)(filter_func); \\\n" ); 05044 fprintf( file, " __frame->finally = (__finally_func)(finally_func); \\\n"); 05045 fprintf( file, " __frame->abnormal_termination = 0; \\\n"); 05046 fprintf( file, " __frame->filter_level = 0; \\\n"); 05047 fprintf( file, " __frame->finally_level = 0; \\\n"); 05048 fprintf( file, " } while (0)\n"); 05049 fprintf( file, "\n"); 05050 fprintf( file, "#else /* USE_COMPILER_EXCEPTIONS */\n"); 05051 fprintf( file, "\n"); 05052 fprintf( file, "#define RpcExceptionInit(filter_func,finally_func) \\\n"); 05053 fprintf( file, " do { (void)(filter_func); } while(0)\n"); 05054 fprintf( file, "\n"); 05055 fprintf( file, "#define __DECL_EXCEPTION_FRAME \\\n"); 05056 fprintf( file, " DWORD code;\n"); 05057 fprintf( file, "\n"); 05058 fprintf( file, "#endif /* USE_COMPILER_EXCEPTIONS */\n"); 05059 } Generated on Sun May 27 2012 04:37:52 for ReactOS by
1.7.6.1
|