1 /* 2 * IDL Compiler 3 * 4 * Copyright 2005-2006 Eric Kohl 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "config.h" 22 #include "wine/port.h" 23 24 #include <stdio.h> 25 #include <stdlib.h> 26 #ifdef HAVE_UNISTD_H 27 # include <unistd.h> 28 #endif 29 #include <string.h> 30 #include <ctype.h> 31 32 #include "widl.h" 33 #include "utils.h" 34 #include "parser.h" 35 #include "header.h" 36 37 #include "typegen.h" 38 39 static FILE* server; 40 static int indent = 0; 41 42 43 static void print_server(const char *format, ...) __attribute__((format (printf, 1, 2))); 44 static void print_server(const char *format, ...) 45 { 46 va_list va; 47 va_start(va, format); 48 print(server, indent, format, va); 49 va_end(va); 50 } 51 52 static void write_function_stub(const type_t *iface, const var_t *func, unsigned int proc_offset) 53 { 54 const var_t *var; 55 unsigned char explicit_fc, implicit_fc; 56 int has_full_pointer = is_full_pointer_function(func); 57 const var_t *handle_var = get_func_handle_var( iface, func, &explicit_fc, &implicit_fc ); 58 59 if (is_interpreted_func( iface, func )) return; 60 61 print_server("struct __frame_%s_%s\n{\n", iface->name, get_name(func)); 62 indent++; 63 print_server("__DECL_EXCEPTION_FRAME\n"); 64 print_server("MIDL_STUB_MESSAGE _StubMsg;\n"); 65 66 /* Declare arguments */ 67 declare_stub_args(server, indent, func); 68 69 indent--; 70 print_server("};\n\n"); 71 72 print_server("static void __finally_%s_%s(", iface->name, get_name(func)); 73 fprintf(server," struct __frame_%s_%s *__frame )\n{\n", iface->name, get_name(func)); 74 75 indent++; 76 write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_FREE); 77 78 if (!is_void(type_function_get_rettype(func->type))) 79 write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_FREE); 80 81 if (has_full_pointer) 82 write_full_pointer_free(server, indent, func); 83 84 indent--; 85 print_server("}\n\n"); 86 87 print_server("void __RPC_STUB %s_%s( PRPC_MESSAGE _pRpcMessage )\n", iface->name, get_name(func)); 88 89 /* write the functions body */ 90 fprintf(server, "{\n"); 91 indent++; 92 print_server("struct __frame_%s_%s __f, * const __frame = &__f;\n", iface->name, get_name(func)); 93 if (has_out_arg_or_return(func)) print_server("RPC_STATUS _Status;\n"); 94 fprintf(server, "\n"); 95 96 print_server("NdrServerInitializeNew(\n"); 97 indent++; 98 print_server("_pRpcMessage,\n"); 99 print_server("&__frame->_StubMsg,\n"); 100 print_server("&%s_StubDesc);\n", iface->name); 101 indent--; 102 fprintf(server, "\n"); 103 print_server( "RpcExceptionInit( __server_filter, __finally_%s_%s );\n", iface->name, get_name(func)); 104 105 write_parameters_init(server, indent, func, "__frame->"); 106 107 if (explicit_fc == RPC_FC_BIND_PRIMITIVE) 108 { 109 print_server("__frame->%s = _pRpcMessage->Handle;\n", handle_var->name); 110 fprintf(server, "\n"); 111 } 112 113 print_server("RpcTryFinally\n"); 114 print_server("{\n"); 115 indent++; 116 print_server("RpcTryExcept\n"); 117 print_server("{\n"); 118 indent++; 119 120 if (has_full_pointer) 121 write_full_pointer_init(server, indent, func, TRUE); 122 123 if (type_get_function_args(func->type)) 124 { 125 print_server("if ((_pRpcMessage->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n"); 126 indent++; 127 print_server("NdrConvert(&__frame->_StubMsg, (PFORMAT_STRING)&__MIDL_ProcFormatString.Format[%u]);\n", 128 proc_offset); 129 indent--; 130 fprintf(server, "\n"); 131 132 /* unmarshall arguments */ 133 write_remoting_arguments(server, indent, func, "__frame->", PASS_IN, PHASE_UNMARSHAL); 134 } 135 136 print_server("if (__frame->_StubMsg.Buffer > __frame->_StubMsg.BufferEnd)\n"); 137 print_server("{\n"); 138 indent++; 139 print_server("RpcRaiseException(RPC_X_BAD_STUB_DATA);\n"); 140 indent--; 141 print_server("}\n"); 142 indent--; 143 print_server("}\n"); 144 print_server("RpcExcept(RPC_BAD_STUB_DATA_EXCEPTION_FILTER)\n"); 145 print_server("{\n"); 146 indent++; 147 print_server("RpcRaiseException(RPC_X_BAD_STUB_DATA);\n"); 148 indent--; 149 print_server("}\n"); 150 print_server("RpcEndExcept\n"); 151 fprintf(server, "\n"); 152 153 /* Assign 'out' arguments */ 154 assign_stub_out_args(server, indent, func, "__frame->"); 155 156 /* Call the real server function */ 157 print_server("%s%s%s", 158 is_void(type_function_get_rettype(func->type)) ? "" : "__frame->_RetVal = ", 159 prefix_server, get_name(func)); 160 161 if (type_get_function_args(func->type)) 162 { 163 int first_arg = 1; 164 165 fprintf(server, "(\n"); 166 indent++; 167 LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry ) 168 { 169 if (first_arg) 170 first_arg = 0; 171 else 172 fprintf(server, ",\n"); 173 if (is_context_handle(var->type)) 174 { 175 /* if the context_handle attribute appears in the chain of types 176 * without pointers being followed, then the context handle must 177 * be direct, otherwise it is a pointer */ 178 const char *ch_ptr = is_aliaschain_attr(var->type, ATTR_CONTEXTHANDLE) ? "*" : ""; 179 print_server("("); 180 write_type_decl_left(server, var->type); 181 fprintf(server, ")%sNDRSContextValue(__frame->%s)", ch_ptr, var->name); 182 } 183 else 184 { 185 print_server("%s__frame->%s", is_array(var->type) && !type_array_is_decl_as_ptr(var->type) ? "*" : "", var->name); 186 } 187 } 188 fprintf(server, ");\n"); 189 indent--; 190 } 191 else 192 { 193 fprintf(server, "();\n"); 194 } 195 196 if (has_out_arg_or_return(func)) 197 { 198 write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_BUFFERSIZE); 199 200 if (!is_void(type_function_get_rettype(func->type))) 201 write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_BUFFERSIZE); 202 203 print_server("_pRpcMessage->BufferLength = __frame->_StubMsg.BufferLength;\n"); 204 fprintf(server, "\n"); 205 print_server("_Status = I_RpcGetBuffer(_pRpcMessage);\n"); 206 print_server("if (_Status)\n"); 207 indent++; 208 print_server("RpcRaiseException(_Status);\n"); 209 indent--; 210 fprintf(server, "\n"); 211 print_server("__frame->_StubMsg.Buffer = _pRpcMessage->Buffer;\n"); 212 fprintf(server, "\n"); 213 } 214 215 /* marshall arguments */ 216 write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_MARSHAL); 217 218 /* marshall the return value */ 219 if (!is_void(type_function_get_rettype(func->type))) 220 write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_MARSHAL); 221 222 indent--; 223 print_server("}\n"); 224 print_server("RpcFinally\n"); 225 print_server("{\n"); 226 indent++; 227 print_server("__finally_%s_%s( __frame );\n", iface->name, get_name(func)); 228 indent--; 229 print_server("}\n"); 230 print_server("RpcEndFinally\n"); 231 232 /* calculate buffer length */ 233 fprintf(server, "\n"); 234 print_server("_pRpcMessage->BufferLength = __frame->_StubMsg.Buffer - (unsigned char *)_pRpcMessage->Buffer;\n"); 235 indent--; 236 fprintf(server, "}\n"); 237 fprintf(server, "\n"); 238 } 239 240 241 static void write_function_stubs(type_t *iface, unsigned int *proc_offset) 242 { 243 const statement_t *stmt; 244 245 STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) 246 { 247 var_t *func = stmt->u.var; 248 249 write_function_stub( iface, func, *proc_offset ); 250 251 /* update proc_offset */ 252 func->procstring_offset = *proc_offset; 253 *proc_offset += get_size_procformatstring_func( iface, func ); 254 } 255 } 256 257 258 static void write_dispatchtable(type_t *iface) 259 { 260 unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION); 261 unsigned int method_count = 0; 262 const statement_t *stmt; 263 264 print_server("static RPC_DISPATCH_FUNCTION %s_table[] =\n", iface->name); 265 print_server("{\n"); 266 indent++; 267 268 STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) 269 { 270 var_t *func = stmt->u.var; 271 if (is_interpreted_func( iface, func )) 272 print_server("%s,\n", get_stub_mode() == MODE_Oif ? "NdrServerCall2" : "NdrServerCall"); 273 else 274 print_server("%s_%s,\n", iface->name, get_name(func)); 275 method_count++; 276 } 277 print_server("0\n"); 278 indent--; 279 print_server("};\n"); 280 print_server("static RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable =\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver)); 281 print_server("{\n"); 282 indent++; 283 print_server("%u,\n", method_count); 284 print_server("%s_table\n", iface->name); 285 indent--; 286 print_server("};\n"); 287 fprintf(server, "\n"); 288 } 289 290 291 static void write_routinetable(type_t *iface) 292 { 293 const statement_t *stmt; 294 295 print_server( "static const SERVER_ROUTINE %s_ServerRoutineTable[] =\n", iface->name ); 296 print_server( "{\n" ); 297 indent++; 298 STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) ) 299 { 300 var_t *func = stmt->u.var; 301 if (is_local( func->attrs )) continue; 302 print_server( "(SERVER_ROUTINE)%s%s,\n", prefix_server, get_name(func)); 303 } 304 indent--; 305 print_server( "};\n\n" ); 306 } 307 308 309 static void write_rundown_routines(void) 310 { 311 context_handle_t *ch; 312 int count = list_count( &context_handle_list ); 313 314 if (!count) return; 315 print_server( "static const NDR_RUNDOWN RundownRoutines[] =\n" ); 316 print_server( "{\n" ); 317 indent++; 318 LIST_FOR_EACH_ENTRY( ch, &context_handle_list, context_handle_t, entry ) 319 { 320 print_server( "%s_rundown", ch->name ); 321 if (--count) fputc( ',', server ); 322 fputc( '\n', server ); 323 } 324 indent--; 325 print_server( "};\n\n" ); 326 } 327 328 329 static void write_serverinfo(type_t *iface) 330 { 331 print_server( "static const MIDL_SERVER_INFO %s_ServerInfo =\n", iface->name ); 332 print_server( "{\n" ); 333 indent++; 334 print_server( "&%s_StubDesc,\n", iface->name ); 335 print_server( "%s_ServerRoutineTable,\n", iface->name ); 336 print_server( "__MIDL_ProcFormatString.Format,\n" ); 337 print_server( "%s_FormatStringOffsetTable,\n", iface->name ); 338 print_server( "0,\n" ); 339 print_server( "0,\n" ); 340 print_server( "0,\n" ); 341 print_server( "0\n" ); 342 indent--; 343 print_server( "};\n\n" ); 344 } 345 346 347 static void write_stubdescdecl(type_t *iface) 348 { 349 print_server("static const MIDL_STUB_DESC %s_StubDesc;\n", iface->name); 350 fprintf(server, "\n"); 351 } 352 353 354 static void write_stubdescriptor(type_t *iface, int expr_eval_routines) 355 { 356 print_server("static const MIDL_STUB_DESC %s_StubDesc =\n", iface->name); 357 print_server("{\n"); 358 indent++; 359 print_server("(void *)& %s___RpcServerInterface,\n", iface->name); 360 print_server("MIDL_user_allocate,\n"); 361 print_server("MIDL_user_free,\n"); 362 print_server("{\n"); 363 indent++; 364 print_server("0,\n"); 365 indent--; 366 print_server("},\n"); 367 if (!list_empty( &context_handle_list )) 368 print_server("RundownRoutines,\n"); 369 else 370 print_server("0,\n"); 371 print_server("0,\n"); 372 if (expr_eval_routines) 373 print_server("ExprEvalRoutines,\n"); 374 else 375 print_server("0,\n"); 376 print_server("0,\n"); 377 print_server("__MIDL_TypeFormatString.Format,\n"); 378 print_server("1, /* -error bounds_check flag */\n"); 379 print_server("0x%x, /* Ndr library version */\n", get_stub_mode() == MODE_Oif ? 0x50002 : 0x10001); 380 print_server("0,\n"); 381 print_server("0x50100a4, /* MIDL Version 5.1.164 */\n"); 382 print_server("0,\n"); 383 print_server("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines"); 384 print_server("0, /* notify & notify_flag routine table */\n"); 385 print_server("1, /* Flags */\n"); 386 print_server("0, /* Reserved3 */\n"); 387 print_server("0, /* Reserved4 */\n"); 388 print_server("0 /* Reserved5 */\n"); 389 indent--; 390 print_server("};\n"); 391 fprintf(server, "\n"); 392 } 393 394 395 static void write_serverinterfacedecl(type_t *iface) 396 { 397 unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION); 398 UUID *uuid = get_attrp(iface->attrs, ATTR_UUID); 399 const str_list_t *endpoints = get_attrp(iface->attrs, ATTR_ENDPOINT); 400 401 if (endpoints) write_endpoints( server, iface->name, endpoints ); 402 403 print_server("static RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable;\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver)); 404 print_server( "static const MIDL_SERVER_INFO %s_ServerInfo;\n", iface->name ); 405 fprintf(server, "\n"); 406 print_server("static const RPC_SERVER_INTERFACE %s___RpcServerInterface =\n", iface->name ); 407 print_server("{\n"); 408 indent++; 409 print_server("sizeof(RPC_SERVER_INTERFACE),\n"); 410 print_server("{{0x%08x,0x%04x,0x%04x,{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x}},{%d,%d}},\n", 411 uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1], 412 uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6], 413 uuid->Data4[7], MAJORVERSION(ver), MINORVERSION(ver)); 414 print_server("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */ 415 print_server("&%s_v%d_%d_DispatchTable,\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver)); 416 if (endpoints) 417 { 418 print_server("%u,\n", list_count(endpoints)); 419 print_server("(PRPC_PROTSEQ_ENDPOINT)%s__RpcProtseqEndpoint,\n", iface->name); 420 } 421 else 422 { 423 print_server("0,\n"); 424 print_server("0,\n"); 425 } 426 print_server("0,\n"); 427 print_server("&%s_ServerInfo,\n", iface->name); 428 print_server("0,\n"); 429 indent--; 430 print_server("};\n"); 431 if (old_names) 432 print_server("RPC_IF_HANDLE %s_ServerIfHandle DECLSPEC_HIDDEN = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n", 433 iface->name, iface->name); 434 else 435 print_server("RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec DECLSPEC_HIDDEN = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n", 436 prefix_server, iface->name, MAJORVERSION(ver), MINORVERSION(ver), iface->name); 437 fprintf(server, "\n"); 438 } 439 440 441 static void init_server(void) 442 { 443 if (server) 444 return; 445 if (!(server = fopen(server_name, "w"))) 446 error("Could not open %s for output\n", server_name); 447 448 print_server("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", PACKAGE_VERSION, input_name); 449 print_server("#include <string.h>\n"); 450 fprintf(server, "\n"); 451 print_server("#include \"%s\"\n", header_name); 452 print_server("\n"); 453 print_server( "#ifndef DECLSPEC_HIDDEN\n"); 454 print_server( "#define DECLSPEC_HIDDEN\n"); 455 print_server( "#endif\n"); 456 print_server( "\n"); 457 } 458 459 460 static void write_server_stmts(const statement_list_t *stmts, int expr_eval_routines, unsigned int *proc_offset) 461 { 462 const statement_t *stmt; 463 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry ) 464 { 465 if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE) 466 { 467 type_t *iface = stmt->u.type; 468 if (!need_stub(iface)) 469 continue; 470 471 fprintf(server, "/*****************************************************************************\n"); 472 fprintf(server, " * %s interface\n", iface->name); 473 fprintf(server, " */\n"); 474 fprintf(server, "\n"); 475 476 if (statements_has_func(type_iface_get_stmts(iface))) 477 { 478 write_serverinterfacedecl(iface); 479 write_stubdescdecl(iface); 480 481 write_function_stubs(iface, proc_offset); 482 483 print_server("#if !defined(__RPC_WIN%u__)\n", pointer_size == 8 ? 64 : 32); 484 print_server("#error Invalid build platform for this stub.\n"); 485 print_server("#endif\n"); 486 487 fprintf(server, "\n"); 488 write_procformatstring_offsets( server, iface ); 489 write_stubdescriptor(iface, expr_eval_routines); 490 write_dispatchtable(iface); 491 write_routinetable(iface); 492 write_serverinfo(iface); 493 } 494 } 495 } 496 } 497 498 static void write_server_routines(const statement_list_t *stmts) 499 { 500 unsigned int proc_offset = 0; 501 int expr_eval_routines; 502 503 if (need_inline_stubs_file( stmts )) 504 { 505 write_exceptions( server ); 506 print_server("\n"); 507 print_server("struct __server_frame\n"); 508 print_server("{\n"); 509 print_server(" __DECL_EXCEPTION_FRAME\n"); 510 print_server(" MIDL_STUB_MESSAGE _StubMsg;\n"); 511 print_server("};\n"); 512 print_server("\n"); 513 print_server("static int __server_filter( struct __server_frame *__frame )\n"); 514 print_server( "{\n"); 515 print_server( " return (__frame->code == STATUS_ACCESS_VIOLATION) ||\n"); 516 print_server( " (__frame->code == STATUS_DATATYPE_MISALIGNMENT) ||\n"); 517 print_server( " (__frame->code == RPC_X_BAD_STUB_DATA) ||\n"); 518 print_server( " (__frame->code == RPC_S_INVALID_BOUND);\n"); 519 print_server( "}\n"); 520 print_server( "\n"); 521 } 522 523 write_formatstringsdecl(server, indent, stmts, need_stub); 524 expr_eval_routines = write_expr_eval_routines(server, server_token); 525 if (expr_eval_routines) 526 write_expr_eval_routine_list(server, server_token); 527 write_user_quad_list(server); 528 write_rundown_routines(); 529 530 write_server_stmts(stmts, expr_eval_routines, &proc_offset); 531 532 write_procformatstring(server, stmts, need_stub); 533 write_typeformatstring(server, stmts, need_stub); 534 } 535 536 void write_server(const statement_list_t *stmts) 537 { 538 if (!do_server) 539 return; 540 if (do_everything && !need_stub_files(stmts)) 541 return; 542 543 init_server(); 544 if (!server) 545 return; 546 547 if (do_win32 && do_win64) 548 { 549 fprintf(server, "#ifndef _WIN64\n\n"); 550 pointer_size = 4; 551 write_server_routines( stmts ); 552 fprintf(server, "\n#else /* _WIN64 */\n\n"); 553 pointer_size = 8; 554 write_server_routines( stmts ); 555 fprintf(server, "\n#endif /* _WIN64 */\n"); 556 } 557 else if (do_win32) 558 { 559 pointer_size = 4; 560 write_server_routines( stmts ); 561 } 562 else if (do_win64) 563 { 564 pointer_size = 8; 565 write_server_routines( stmts ); 566 } 567 568 fclose(server); 569 } 570