server.c 18.7 KB
Newer Older
1 2 3
/*
 * IDL Compiler
 *
4
 * Copyright 2005-2006 Eric Kohl
5 6 7 8 9 10 11 12 13 14 15 16 17
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
 */

#include "config.h"
#include "wine/port.h"

#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <string.h>
#include <ctype.h>

#include "widl.h"
#include "utils.h"
#include "parser.h"
#include "header.h"

37
#include "typegen.h"
38 39 40 41 42

static FILE* server;
static int indent = 0;


43
static void print_server(const char *format, ...) __attribute__((format (printf, 1, 2)));
44
static void print_server(const char *format, ...)
45 46 47
{
    va_list va;
    va_start(va, format);
48
    print(server, indent, format, va);
49 50 51
    va_end(va);
}

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 56 57
    unsigned char explicit_fc, implicit_fc;
    int has_full_pointer = is_full_pointer_function(func);
    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 62 63 64
    print_server("struct __frame_%s_%s\n{\n", iface->name, get_name(func));
    indent++;
    print_server("__DECL_EXCEPTION_FRAME\n");
    print_server("MIDL_STUB_MESSAGE _StubMsg;\n");
65

66 67
    /* Declare arguments */
    declare_stub_args(server, indent, func);
68

69 70
    indent--;
    print_server("};\n\n");
71

72 73
    print_server("static void __finally_%s_%s(", iface->name, get_name(func));
    fprintf(server," struct __frame_%s_%s *__frame )\n{\n", iface->name, get_name(func));
74

75 76
    indent++;
    write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_FREE);
77

78 79
    if (!is_void(type_function_get_rettype(func->type)))
        write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_FREE);
80

81 82
    if (has_full_pointer)
        write_full_pointer_free(server, indent, func);
83

84 85
    indent--;
    print_server("}\n\n");
86

87
    print_server("void __RPC_STUB %s_%s( PRPC_MESSAGE _pRpcMessage )\n", iface->name, get_name(func));
88

89 90 91 92 93 94
    /* write the functions body */
    fprintf(server, "{\n");
    indent++;
    print_server("struct __frame_%s_%s __f, * const __frame = &__f;\n", iface->name, get_name(func));
    if (has_out_arg_or_return(func)) print_server("RPC_STATUS _Status;\n");
    fprintf(server, "\n");
95

96 97 98 99 100 101 102 103
    print_server("NdrServerInitializeNew(\n");
    indent++;
    print_server("_pRpcMessage,\n");
    print_server("&__frame->_StubMsg,\n");
    print_server("&%s_StubDesc);\n", iface->name);
    indent--;
    fprintf(server, "\n");
    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 108 109 110 111
    if (explicit_fc == RPC_FC_BIND_PRIMITIVE)
    {
        print_server("__frame->%s = _pRpcMessage->Handle;\n", handle_var->name);
        fprintf(server, "\n");
    }
112

113 114 115 116 117 118
    print_server("RpcTryFinally\n");
    print_server("{\n");
    indent++;
    print_server("RpcTryExcept\n");
    print_server("{\n");
    indent++;
119

120 121
    if (has_full_pointer)
        write_full_pointer_init(server, indent, func, TRUE);
122

123 124 125
    if (type_get_function_args(func->type))
    {
        print_server("if ((_pRpcMessage->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n");
126
        indent++;
127 128
        print_server("NdrConvert(&__frame->_StubMsg, (PFORMAT_STRING)&__MIDL_ProcFormatString.Format[%u]);\n",
                     proc_offset);
129 130 131
        indent--;
        fprintf(server, "\n");

132 133 134
        /* unmarshall arguments */
        write_remoting_arguments(server, indent, func, "__frame->", PASS_IN, PHASE_UNMARSHAL);
    }
135

136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    print_server("if (__frame->_StubMsg.Buffer > __frame->_StubMsg.BufferEnd)\n");
    print_server("{\n");
    indent++;
    print_server("RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
    indent--;
    print_server("}\n");
    indent--;
    print_server("}\n");
    print_server("RpcExcept(RPC_BAD_STUB_DATA_EXCEPTION_FILTER)\n");
    print_server("{\n");
    indent++;
    print_server("RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
    indent--;
    print_server("}\n");
    print_server("RpcEndExcept\n");
    fprintf(server, "\n");
152

153 154
    /* Assign 'out' arguments */
    assign_stub_out_args(server, indent, func, "__frame->");
155

156 157 158 159
    /* Call the real server function */
    print_server("%s%s%s",
                 is_void(type_function_get_rettype(func->type)) ? "" : "__frame->_RetVal = ",
                 prefix_server, get_name(func));
160

161 162 163
    if (type_get_function_args(func->type))
    {
        int first_arg = 1;
164

165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
        fprintf(server, "(\n");
        indent++;
        LIST_FOR_EACH_ENTRY( var, type_get_function_args(func->type), const var_t, entry )
        {
            if (first_arg)
                first_arg = 0;
            else
                fprintf(server, ",\n");
            if (is_context_handle(var->type))
            {
                /* if the context_handle attribute appears in the chain of types
                 * without pointers being followed, then the context handle must
                 * be direct, otherwise it is a pointer */
                int is_ch_ptr = is_aliaschain_attr(var->type, ATTR_CONTEXTHANDLE) ? FALSE : TRUE;
                print_server("(");
                write_type_decl_left(server, var->type);
                fprintf(server, ")%sNDRSContextValue(__frame->%s)",
                        is_ch_ptr ? "" : "*", var->name);
            }
            else
            {
                print_server("%s__frame->%s", is_array(var->type) && !type_array_is_decl_as_ptr(var->type) ? "*" : "", var->name);
            }
188
        }
189 190 191 192 193 194 195
        fprintf(server, ");\n");
        indent--;
    }
    else
    {
        fprintf(server, "();\n");
    }
196

197 198 199
    if (has_out_arg_or_return(func))
    {
        write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_BUFFERSIZE);
Robert Shearman's avatar
Robert Shearman committed
200

201
        if (!is_void(type_function_get_rettype(func->type)))
202
            write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_BUFFERSIZE);
203

204 205 206 207
        print_server("_pRpcMessage->BufferLength = __frame->_StubMsg.BufferLength;\n");
        fprintf(server, "\n");
        print_server("_Status = I_RpcGetBuffer(_pRpcMessage);\n");
        print_server("if (_Status)\n");
208
        indent++;
209
        print_server("RpcRaiseException(_Status);\n");
210
        indent--;
211
        fprintf(server, "\n");
212
        print_server("__frame->_StubMsg.Buffer = _pRpcMessage->Buffer;\n");
213
        fprintf(server, "\n");
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
    }

    /* marshall arguments */
    write_remoting_arguments(server, indent, func, "__frame->", PASS_OUT, PHASE_MARSHAL);

    /* marshall the return value */
    if (!is_void(type_function_get_rettype(func->type)))
        write_remoting_arguments(server, indent, func, "__frame->", PASS_RETURN, PHASE_MARSHAL);

    indent--;
    print_server("}\n");
    print_server("RpcFinally\n");
    print_server("{\n");
    indent++;
    print_server("__finally_%s_%s( __frame );\n", iface->name, get_name(func));
    indent--;
    print_server("}\n");
    print_server("RpcEndFinally\n");

    /* calculate buffer length */
    fprintf(server, "\n");
    print_server("_pRpcMessage->BufferLength = __frame->_StubMsg.Buffer - (unsigned char *)_pRpcMessage->Buffer;\n");
    indent--;
    fprintf(server, "}\n");
    fprintf(server, "\n");
}


static void write_function_stubs(type_t *iface, unsigned int *proc_offset)
{
    const statement_t *stmt;

    STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
    {
        var_t *func = stmt->u.var;

        write_function_stub( iface, func, *proc_offset );
251

252
        /* update proc_offset */
253
        func->procstring_offset = *proc_offset;
254
        *proc_offset += get_size_procformatstring_func( iface, func );
255 256 257 258 259 260
    }
}


static void write_dispatchtable(type_t *iface)
{
261 262
    unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION);
    unsigned int method_count = 0;
263
    const statement_t *stmt;
264 265 266 267

    print_server("static RPC_DISPATCH_FUNCTION %s_table[] =\n", iface->name);
    print_server("{\n");
    indent++;
268

269
    STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
270
    {
271
        var_t *func = stmt->u.var;
272
        if (is_interpreted_func( iface, func ))
273
            print_server("%s,\n", get_stub_mode() == MODE_Oif ? "NdrServerCall2" : "NdrServerCall");
274 275
        else
            print_server("%s_%s,\n", iface->name, get_name(func));
276 277 278 279 280
        method_count++;
    }
    print_server("0\n");
    indent--;
    print_server("};\n");
281
    print_server("static RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable =\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver));
282 283 284 285 286 287 288 289 290 291
    print_server("{\n");
    indent++;
    print_server("%u,\n", method_count);
    print_server("%s_table\n", iface->name);
    indent--;
    print_server("};\n");
    fprintf(server, "\n");
}


292 293 294 295 296 297 298 299 300 301 302
static void write_routinetable(type_t *iface)
{
    const statement_t *stmt;

    print_server( "static const SERVER_ROUTINE %s_ServerRoutineTable[] =\n", iface->name );
    print_server( "{\n" );
    indent++;
    STATEMENTS_FOR_EACH_FUNC( stmt, type_iface_get_stmts(iface) )
    {
        var_t *func = stmt->u.var;
        if (is_local( func->attrs )) continue;
303
        print_server( "(SERVER_ROUTINE)%s%s,\n", prefix_server, get_name(func));
304 305 306 307 308 309
    }
    indent--;
    print_server( "};\n\n" );
}


310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
static void write_rundown_routines(void)
{
    context_handle_t *ch;
    int count = list_count( &context_handle_list );

    if (!count) return;
    print_server( "static const NDR_RUNDOWN RundownRoutines[] =\n" );
    print_server( "{\n" );
    indent++;
    LIST_FOR_EACH_ENTRY( ch, &context_handle_list, context_handle_t, entry )
    {
        print_server( "%s_rundown", ch->name );
        if (--count) fputc( ',', server );
        fputc( '\n', server );
    }
    indent--;
    print_server( "};\n\n" );
}


330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
static void write_serverinfo(type_t *iface)
{
    print_server( "static const MIDL_SERVER_INFO %s_ServerInfo =\n", iface->name );
    print_server( "{\n" );
    indent++;
    print_server( "&%s_StubDesc,\n", iface->name );
    print_server( "%s_ServerRoutineTable,\n", iface->name );
    print_server( "__MIDL_ProcFormatString.Format,\n" );
    print_server( "%s_FormatStringOffsetTable,\n", iface->name );
    print_server( "0,\n" );
    print_server( "0,\n" );
    print_server( "0,\n" );
    print_server( "0\n" );
    indent--;
    print_server( "};\n\n" );
}


348 349
static void write_stubdescdecl(type_t *iface)
{
350
    print_server("static const MIDL_STUB_DESC %s_StubDesc;\n", iface->name);
351 352 353 354
    fprintf(server, "\n");
}


355
static void write_stubdescriptor(type_t *iface, int expr_eval_routines)
356 357 358 359
{
    print_server("static const MIDL_STUB_DESC %s_StubDesc =\n", iface->name);
    print_server("{\n");
    indent++;
360
    print_server("(void *)& %s___RpcServerInterface,\n", iface->name);
361 362
    print_server("MIDL_user_allocate,\n");
    print_server("MIDL_user_free,\n");
363 364
    print_server("{\n");
    indent++;
365
    print_server("0,\n");
366 367
    indent--;
    print_server("},\n");
368 369 370 371
    if (!list_empty( &context_handle_list ))
        print_server("RundownRoutines,\n");
    else
        print_server("0,\n");
372
    print_server("0,\n");
373 374 375 376
    if (expr_eval_routines)
        print_server("ExprEvalRoutines,\n");
    else
        print_server("0,\n");
377 378 379
    print_server("0,\n");
    print_server("__MIDL_TypeFormatString.Format,\n");
    print_server("1, /* -error bounds_check flag */\n");
380
    print_server("0x%x, /* Ndr library version */\n", get_stub_mode() == MODE_Oif ? 0x50002 : 0x10001);
381 382 383
    print_server("0,\n");
    print_server("0x50100a4, /* MIDL Version 5.1.164 */\n");
    print_server("0,\n");
384
    print_server("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines");
385 386 387 388 389 390 391 392 393 394 395 396 397
    print_server("0,  /* notify & notify_flag routine table */\n");
    print_server("1,  /* Flags */\n");
    print_server("0,  /* Reserved3 */\n");
    print_server("0,  /* Reserved4 */\n");
    print_server("0   /* Reserved5 */\n");
    indent--;
    print_server("};\n");
    fprintf(server, "\n");
}


static void write_serverinterfacedecl(type_t *iface)
{
398
    unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION);
399
    UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
400 401 402
    const str_list_t *endpoints = get_attrp(iface->attrs, ATTR_ENDPOINT);

    if (endpoints) write_endpoints( server, iface->name, endpoints );
403

404
    print_server("static RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable;\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver));
405
    print_server( "static const MIDL_SERVER_INFO %s_ServerInfo;\n", iface->name );
406 407 408 409 410
    fprintf(server, "\n");
    print_server("static const RPC_SERVER_INTERFACE %s___RpcServerInterface =\n", iface->name );
    print_server("{\n");
    indent++;
    print_server("sizeof(RPC_SERVER_INTERFACE),\n");
411
    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",
412 413
                 uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1],
                 uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6],
414
                 uuid->Data4[7], MAJORVERSION(ver), MINORVERSION(ver));
415
    print_server("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */
416
    print_server("&%s_v%d_%d_DispatchTable,\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver));
417 418 419 420 421 422 423 424 425 426
    if (endpoints)
    {
        print_server("%u,\n", list_count(endpoints));
        print_server("(PRPC_PROTSEQ_ENDPOINT)%s__RpcProtseqEndpoint,\n", iface->name);
    }
    else
    {
        print_server("0,\n");
        print_server("0,\n");
    }
427
    print_server("0,\n");
428
    print_server("&%s_ServerInfo,\n", iface->name);
429 430 431
    print_server("0,\n");
    indent--;
    print_server("};\n");
432
    if (old_names)
433
        print_server("RPC_IF_HANDLE %s_ServerIfHandle DECLSPEC_HIDDEN = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n",
434 435
                     iface->name, iface->name);
    else
436
        print_server("RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec DECLSPEC_HIDDEN = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n",
437
                     prefix_server, iface->name, MAJORVERSION(ver), MINORVERSION(ver), iface->name);
438 439 440 441 442 443 444 445 446 447 448
    fprintf(server, "\n");
}


static void init_server(void)
{
    if (server)
        return;
    if (!(server = fopen(server_name, "w")))
        error("Could not open %s for output\n", server_name);

449
    print_server("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", PACKAGE_VERSION, input_name);
450
    print_server("#include <string.h>\n");
451
    fprintf(server, "\n");
452
    print_server("#include \"%s\"\n", header_name);
453
    print_server("\n");
454 455 456 457
    print_server( "#ifndef DECLSPEC_HIDDEN\n");
    print_server( "#define DECLSPEC_HIDDEN\n");
    print_server( "#endif\n");
    print_server( "\n");
458 459 460
}


461 462 463 464 465
static void write_server_stmts(const statement_list_t *stmts, int expr_eval_routines, unsigned int *proc_offset)
{
    const statement_t *stmt;
    if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
    {
466
        if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE)
467 468 469 470 471 472 473 474 475 476
        {
            type_t *iface = stmt->u.type;
            if (!need_stub(iface))
                continue;

            fprintf(server, "/*****************************************************************************\n");
            fprintf(server, " * %s interface\n", iface->name);
            fprintf(server, " */\n");
            fprintf(server, "\n");

477
            if (statements_has_func(type_iface_get_stmts(iface)))
478 479 480 481 482 483
            {
                write_serverinterfacedecl(iface);
                write_stubdescdecl(iface);

                write_function_stubs(iface, proc_offset);

484
                print_server("#if !defined(__RPC_WIN%u__)\n", pointer_size == 8 ? 64 : 32);
485 486 487 488
                print_server("#error  Invalid build platform for this stub.\n");
                print_server("#endif\n");

                fprintf(server, "\n");
489
                write_procformatstring_offsets( server, iface );
490 491
                write_stubdescriptor(iface, expr_eval_routines);
                write_dispatchtable(iface);
492 493
                write_routinetable(iface);
                write_serverinfo(iface);
494 495 496 497 498
            }
        }
    }
}

499
static void write_server_routines(const statement_list_t *stmts)
500
{
501
    unsigned int proc_offset = 0;
502
    int expr_eval_routines;
503

504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522
    if (need_inline_stubs_file( stmts ))
    {
        write_exceptions( server );
        print_server("\n");
        print_server("struct __server_frame\n");
        print_server("{\n");
        print_server("    __DECL_EXCEPTION_FRAME\n");
        print_server("    MIDL_STUB_MESSAGE _StubMsg;\n");
        print_server("};\n");
        print_server("\n");
        print_server("static int __server_filter( struct __server_frame *__frame )\n");
        print_server( "{\n");
        print_server( "    return (__frame->code == STATUS_ACCESS_VIOLATION) ||\n");
        print_server( "           (__frame->code == STATUS_DATATYPE_MISALIGNMENT) ||\n");
        print_server( "           (__frame->code == RPC_X_BAD_STUB_DATA) ||\n");
        print_server( "           (__frame->code == RPC_S_INVALID_BOUND);\n");
        print_server( "}\n");
        print_server( "\n");
    }
523

524
    write_formatstringsdecl(server, indent, stmts, need_stub);
525 526 527 528
    expr_eval_routines = write_expr_eval_routines(server, server_token);
    if (expr_eval_routines)
        write_expr_eval_routine_list(server, server_token);
    write_user_quad_list(server);
529
    write_rundown_routines();
530

531
    write_server_stmts(stmts, expr_eval_routines, &proc_offset);
532

533 534
    write_procformatstring(server, stmts, need_stub);
    write_typeformatstring(server, stmts, need_stub);
535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
}

void write_server(const statement_list_t *stmts)
{
    if (!do_server)
        return;
    if (do_everything && !need_stub_files(stmts))
        return;

    init_server();
    if (!server)
        return;

    if (do_win32 && do_win64)
    {
550
        fprintf(server, "#ifndef _WIN64\n\n");
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567
        pointer_size = 4;
        write_server_routines( stmts );
        fprintf(server, "\n#else /* _WIN64 */\n\n");
        pointer_size = 8;
        write_server_routines( stmts );
        fprintf(server, "\n#endif /* _WIN64 */\n");
    }
    else if (do_win32)
    {
        pointer_size = 4;
        write_server_routines( stmts );
    }
    else if (do_win64)
    {
        pointer_size = 8;
        write_server_routines( stmts );
    }
568

569 570
    fclose(server);
}