server.c 18.6 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
        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 */
178
                const char *ch_ptr = is_aliaschain_attr(var->type, ATTR_CONTEXTHANDLE) ? "*" : "";
179 180
                print_server("(");
                write_type_decl_left(server, var->type);
181
                fprintf(server, ")%sNDRSContextValue(__frame->%s)", ch_ptr, var->name);
182 183 184 185 186
            }
            else
            {
                print_server("%s__frame->%s", is_array(var->type) && !type_array_is_decl_as_ptr(var->type) ? "*" : "", var->name);
            }
187
        }
188 189 190 191 192 193 194
        fprintf(server, ");\n");
        indent--;
    }
    else
    {
        fprintf(server, "();\n");
    }
195

196 197 198
    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
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 204 205 206
        print_server("_pRpcMessage->BufferLength = __frame->_StubMsg.BufferLength;\n");
        fprintf(server, "\n");
        print_server("_Status = I_RpcGetBuffer(_pRpcMessage);\n");
        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 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
    }

    /* 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 );
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 259
    }
}


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

    print_server("static RPC_DISPATCH_FUNCTION %s_table[] =\n", iface->name);
    print_server("{\n");
    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 274
        else
            print_server("%s_%s,\n", iface->name, get_name(func));
275 276 277 278 279
        method_count++;
    }
    print_server("0\n");
    indent--;
    print_server("};\n");
280
    print_server("static RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable =\n", iface->name, MAJORVERSION(ver), MINORVERSION(ver));
281 282 283 284 285 286 287 288 289 290
    print_server("{\n");
    indent++;
    print_server("%u,\n", method_count);
    print_server("%s_table\n", iface->name);
    indent--;
    print_server("};\n");
    fprintf(server, "\n");
}


291 292 293 294 295 296 297 298 299 300 301
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;
302
        print_server( "(SERVER_ROUTINE)%s%s,\n", prefix_server, get_name(func));
303 304 305 306 307 308
    }
    indent--;
    print_server( "};\n\n" );
}


309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
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" );
}


329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
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" );
}


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


354
static void write_stubdescriptor(type_t *iface, int expr_eval_routines)
355 356 357 358
{
    print_server("static const MIDL_STUB_DESC %s_StubDesc =\n", iface->name);
    print_server("{\n");
    indent++;
359
    print_server("(void *)& %s___RpcServerInterface,\n", iface->name);
360 361
    print_server("MIDL_user_allocate,\n");
    print_server("MIDL_user_free,\n");
362 363
    print_server("{\n");
    indent++;
364
    print_server("0,\n");
365 366
    indent--;
    print_server("},\n");
367 368 369 370
    if (!list_empty( &context_handle_list ))
        print_server("RundownRoutines,\n");
    else
        print_server("0,\n");
371
    print_server("0,\n");
372 373 374 375
    if (expr_eval_routines)
        print_server("ExprEvalRoutines,\n");
    else
        print_server("0,\n");
376 377 378
    print_server("0,\n");
    print_server("__MIDL_TypeFormatString.Format,\n");
    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 381 382
    print_server("0,\n");
    print_server("0x50100a4, /* MIDL Version 5.1.164 */\n");
    print_server("0,\n");
383
    print_server("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines");
384 385 386 387 388 389 390 391 392 393 394 395 396
    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)
{
397
    unsigned int ver = get_attrv(iface->attrs, ATTR_VERSION);
398
    UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
399 400 401
    const str_list_t *endpoints = get_attrp(iface->attrs, ATTR_ENDPOINT);

    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 406 407 408 409
    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");
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 412
                 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],
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 417 418 419 420 421 422 423 424 425
    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");
    }
426
    print_server("0,\n");
427
    print_server("&%s_ServerInfo,\n", iface->name);
428 429 430
    print_server("0,\n");
    indent--;
    print_server("};\n");
431
    if (old_names)
432
        print_server("RPC_IF_HANDLE %s_ServerIfHandle DECLSPEC_HIDDEN = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n",
433 434
                     iface->name, iface->name);
    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 438 439 440 441 442 443 444 445 446 447
    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);

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 454 455 456
    print_server( "#ifndef DECLSPEC_HIDDEN\n");
    print_server( "#define DECLSPEC_HIDDEN\n");
    print_server( "#endif\n");
    print_server( "\n");
457 458 459
}


460 461 462 463 464
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 )
    {
465
        if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_INTERFACE)
466 467 468 469 470 471 472 473 474 475
        {
            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");

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

                write_function_stubs(iface, proc_offset);

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

                fprintf(server, "\n");
488
                write_procformatstring_offsets( server, iface );
489 490
                write_stubdescriptor(iface, expr_eval_routines);
                write_dispatchtable(iface);
491 492
                write_routinetable(iface);
                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 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
    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");
    }
522

523
    write_formatstringsdecl(server, indent, stmts, need_stub);
524 525 526 527
    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);
528
    write_rundown_routines();
529

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

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

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)
    {
549
        fprintf(server, "#ifndef _WIN64\n\n");
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566
        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 );
    }
567

568 569
    fclose(server);
}