widl: Fix updating the proc offset.
[wine] / tools / widl / server.c
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 <assert.h>
31 #include <ctype.h>
32 #include <signal.h>
33
34 #include "widl.h"
35 #include "utils.h"
36 #include "parser.h"
37 #include "header.h"
38 #include "windef.h"
39
40 #include "widl.h"
41 #include "typelib.h"
42 #include "typelib_struct.h"
43 #include "typegen.h"
44
45 static FILE* server;
46 static int indent = 0;
47
48
49 static int print_server(const char *format, ...)
50 {
51     va_list va;
52     int i, r;
53
54     va_start(va, format);
55     for (i = 0; i < indent; i++)
56         fprintf(server, "    ");
57     r = vfprintf(server, format, va);
58     va_end(va);
59     return r;
60 }
61
62
63 static void write_parameters_init(const func_t *func)
64 {
65     const var_t *var;
66
67     if (!func->args)
68         return;
69
70     var = func->args;
71     while (NEXT_LINK(var)) var = NEXT_LINK(var);
72     while (var)
73     {
74         if (var->type->type != RPC_FC_BIND_PRIMITIVE)
75             print_server("%s = 0;\n", var->name);
76
77         var = PREV_LINK(var);
78     }
79     fprintf(server, "\n");
80 }
81
82
83 static void declare_args(const func_t *func)
84 {
85     int in_attr, out_attr;
86     int i = 0;
87     var_t *var;
88
89     if (!func->args)
90         return;
91
92     var = func->args;
93     while (NEXT_LINK(var)) var = NEXT_LINK(var);
94     while (var)
95     {
96         const expr_t *size_is = get_attrp(var->attrs, ATTR_SIZEIS);
97         int has_size = size_is && (size_is->type != EXPR_VOID);
98         int is_string = is_attr(var->attrs, ATTR_STRING);
99
100         in_attr = is_attr(var->attrs, ATTR_IN);
101         out_attr = is_attr(var->attrs, ATTR_OUT);
102         if (!out_attr && !in_attr)
103             in_attr = 1;
104
105         if (!in_attr && !has_size && !is_string)
106         {
107             int indirection;
108             print_server("");
109             write_type(server, var->type, NULL, var->tname);
110             for (indirection = 0; indirection < var->ptr_level - 1; indirection++)
111                 fprintf(server, "*");
112             fprintf(server, " _W%u;\n", i++);
113         }
114
115         print_server("");
116         write_type(server, var->type, var, var->tname);
117         fprintf(server, " ");
118         write_name(server, var);
119         write_array(server, var->array, 0);
120         fprintf(server, ";\n");
121
122         var = PREV_LINK(var);
123     }
124 }
125
126
127 static void assign_out_args(const func_t *func)
128 {
129     int in_attr, out_attr;
130     int i = 0, sep = 0;
131     var_t *var;
132     const expr_t *size_is;
133     int has_size;
134
135     if (!func->args)
136         return;
137
138     var = func->args;
139     while (NEXT_LINK(var)) var = NEXT_LINK(var);
140     while (var)
141     {
142         int is_string = is_attr(var->attrs, ATTR_STRING);
143         size_is = get_attrp(var->attrs, ATTR_SIZEIS);
144         has_size = size_is && (size_is->type != EXPR_VOID);
145         in_attr = is_attr(var->attrs, ATTR_IN);
146         out_attr = is_attr(var->attrs, ATTR_OUT);
147         if (!out_attr && !in_attr)
148             in_attr = 1;
149
150         if (!in_attr)
151         {
152             print_server("");
153             write_name(server, var);
154
155             if (has_size)
156             {
157                 unsigned int size;
158                 type_t *type = var->type;
159                 while (type->type == 0 && type->ref)
160                     type = type->ref;
161
162                 fprintf(server, " = NdrAllocate(&_StubMsg, ");
163                 write_expr(server, size_is, 1);
164                 size = get_type_memsize(type);
165                 fprintf(server, " * %u);\n", size);
166             }
167             else if (!is_string)
168             {
169                 fprintf(server, " = &_W%u;\n", i);
170                 if (var->ptr_level > 1)
171                     print_server("_W%u = 0;\n", i);
172                 i++;
173             }
174
175             sep = 1;
176         }
177
178         var = PREV_LINK(var);
179     }
180
181     if (sep)
182         fprintf(server, "\n");
183 }
184
185
186 static void write_function_stubs(type_t *iface, unsigned int *proc_offset, unsigned int *type_offset)
187 {
188     char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
189     int explicit_handle = is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE);
190     const func_t *func = iface->funcs;
191     const var_t *var;
192     const var_t* explicit_handle_var;
193
194     while (NEXT_LINK(func)) func = NEXT_LINK(func);
195     while (func)
196     {
197         const var_t *def = func->def;
198         unsigned long buffer_size = 0;
199         unsigned int type_offset_func;
200
201         /* check for a defined binding handle */
202         explicit_handle_var = get_explicit_handle_var(func);
203         if (explicit_handle)
204         {
205             if (!explicit_handle_var)
206             {
207                 error("%s() does not define an explicit binding handle!\n", def->name);
208                 return;
209             }
210         }
211         else if (implicit_handle)
212         {
213             if (explicit_handle_var)
214             {
215                 error("%s() must not define a binding handle!\n", def->name);
216                 return;
217             }
218         }
219
220         fprintf(server, "void __RPC_STUB\n");
221         fprintf(server, "%s_", iface->name);
222         write_name(server, def);
223         fprintf(server, "(\n");
224         indent++;
225         print_server("PRPC_MESSAGE _pRpcMessage)\n");
226         indent--;
227
228         /* write the functions body */
229         fprintf(server, "{\n");
230         indent++;
231
232         /* declare return value '_RetVal' */
233         if (!is_void(def->type, NULL))
234         {
235             print_server("");
236             write_type(server, def->type, def, def->tname);
237             fprintf(server, " _RetVal;\n");
238         }
239
240         /* Declare arguments */
241         declare_args(func);
242
243         print_server("MIDL_STUB_MESSAGE _StubMsg;\n");
244         print_server("RPC_STATUS _Status;\n");
245         fprintf(server, "\n");
246
247
248         print_server("((void)(_Status));\n");
249         print_server("NdrServerInitializeNew(\n");
250         indent++;
251         print_server("_pRpcMessage,\n");
252         print_server("&_StubMsg,\n");
253         print_server("&%s_StubDesc);\n", iface->name);
254         indent--;
255         fprintf(server, "\n");
256
257         write_parameters_init(func);
258
259         if (explicit_handle_var)
260         {
261             print_server("%s = _pRpcMessage->Handle;\n", explicit_handle_var->name);
262             fprintf(server, "\n");
263         }
264
265         print_server("RpcTryFinally\n");
266         print_server("{\n");
267         indent++;
268         print_server("RpcTryExcept\n");
269         print_server("{\n");
270         indent++;
271
272         if (func->args)
273         {
274             print_server("if ((_pRpcMessage->DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n");
275             indent++;
276             print_server("NdrConvert(\n");
277             indent++;
278             print_server("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
279             print_server("(PFORMAT_STRING)&__MIDL_ProcFormatString.Format[%u]);\n", *proc_offset);
280             indent -= 2;
281             fprintf(server, "\n");
282
283             /* make a copy so we don't increment the type offset twice */
284             type_offset_func = *type_offset;
285
286             /* unmarshall arguments */
287             write_remoting_arguments(server, indent, func, &type_offset_func, PASS_IN, PHASE_UNMARSHAL);
288         }
289
290         print_server("if (_StubMsg.Buffer > _StubMsg.BufferEnd)\n");
291         print_server("{\n");
292         indent++;
293         print_server("RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
294         indent--;
295         print_server("}\n");
296         indent--;
297         print_server("}\n");
298         print_server("RpcExcept(RPC_BAD_STUB_DATA_EXCEPTION_FILTER)\n");
299         print_server("{\n");
300         indent++;
301         print_server("RpcRaiseException(RPC_X_BAD_STUB_DATA);\n");
302         indent--;
303         print_server("}\n");
304         print_server("RpcEndExcept\n");
305         fprintf(server, "\n");
306
307         /* Assign 'out' arguments */
308         assign_out_args(func);
309
310         /* Call the real server function */
311         if (!is_void(def->type, NULL))
312             print_server("_RetVal = ");
313         else
314             print_server("");
315         write_name(server, def);
316
317         if (func->args)
318         {
319             int first_arg = 1;
320
321             fprintf(server, "(\n");
322             indent++;
323             var = func->args;
324             while (NEXT_LINK(var)) var = NEXT_LINK(var);
325             while (var)
326             {
327                 if (first_arg)
328                     first_arg = 0;
329                 else
330                     fprintf(server, ",\n");
331                 print_server("");
332                 write_name(server, var);
333                 var = PREV_LINK(var);
334             }
335             fprintf(server, ");\n");
336             indent--;
337         }
338         else
339         {
340             fprintf(server, "();\n");
341         }
342
343         if (func->args)
344         {
345             const var_t *var = func->args;
346             while (NEXT_LINK(var)) var = NEXT_LINK(var);
347             while (var)
348             {
349                 if (is_attr(var->attrs, ATTR_OUT))
350                 {
351                     unsigned int alignment;
352                     buffer_size += get_required_buffer_size(var, &alignment, PASS_OUT);
353                     buffer_size += alignment;
354                 }
355
356                 var = PREV_LINK(var);
357             }
358         }
359
360         if (!is_void(def->type, NULL))
361         {
362             unsigned int alignment;
363             buffer_size += get_required_buffer_size(def, &alignment, PASS_RETURN);
364             buffer_size += alignment;
365         }
366
367         if (has_out_arg_or_return(func))
368         {
369             fprintf(server, "\n");
370             print_server("_StubMsg.BufferLength = %u;\n", buffer_size);
371
372             type_offset_func = *type_offset;
373             write_remoting_arguments(server, indent, func, &type_offset_func, PASS_OUT, PHASE_BUFFERSIZE);
374
375             print_server("_pRpcMessage->BufferLength = _StubMsg.BufferLength;\n");
376             fprintf(server, "\n");
377             print_server("_Status = I_RpcGetBuffer(_pRpcMessage);\n");
378             print_server("if (_Status)\n");
379             indent++;
380             print_server("RpcRaiseException(_Status);\n");
381             indent--;
382             fprintf(server, "\n");
383             print_server("_StubMsg.Buffer = (unsigned char *)_pRpcMessage->Buffer;\n");
384             fprintf(server, "\n");
385         }
386
387         type_offset_func = *type_offset;
388
389         /* marshall arguments */
390         write_remoting_arguments(server, indent, func, type_offset, PASS_OUT, PHASE_MARSHAL);
391
392         /* marshall the return value */
393         if (!is_void(def->type, NULL))
394             print_phase_basetype(server, indent, PHASE_MARSHAL, PASS_RETURN, def, "_RetVal");
395
396         indent--;
397         print_server("}\n");
398         print_server("RpcFinally\n");
399         print_server("{\n");
400         indent++;
401
402         write_remoting_arguments(server, indent, func, &type_offset_func, PASS_OUT, PHASE_FREE);
403
404         indent--;
405         print_server("}\n");
406         print_server("RpcEndFinally\n");
407
408         /* calculate buffer length */
409         fprintf(server, "\n");
410         print_server("_pRpcMessage->BufferLength =\n");
411         indent++;
412         print_server("(unsigned int)(_StubMsg.Buffer - (unsigned char *)_pRpcMessage->Buffer);\n");
413         indent--;
414         indent--;
415         fprintf(server, "}\n");
416         fprintf(server, "\n");
417
418         /* update proc_offset */
419         if (func->args)
420         {
421             var = func->args;
422             while (NEXT_LINK(var)) var = NEXT_LINK(var);
423             while (var)
424             {
425                 *proc_offset += get_size_procformatstring_var(var);
426                 var = PREV_LINK(var);
427             }
428         }
429         if (!is_void(def->type, NULL))
430             *proc_offset += get_size_procformatstring_var(def);
431         else
432             *proc_offset += 2; /* FC_END and FC_PAD */
433
434         func = PREV_LINK(func);
435     }
436 }
437
438
439 static void write_dispatchtable(type_t *iface)
440 {
441     unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);
442     unsigned long method_count = 0;
443     func_t *func = iface->funcs;
444
445     print_server("static RPC_DISPATCH_FUNCTION %s_table[] =\n", iface->name);
446     print_server("{\n");
447     indent++;
448     while (NEXT_LINK(func)) func = NEXT_LINK(func);
449     while (func)
450     {
451         var_t *def = func->def;
452
453         print_server("%s_", iface->name);
454         write_name(server, def);
455         fprintf(server, ",\n");
456
457         method_count++;
458         func = PREV_LINK(func);
459     }
460     print_server("0\n");
461     indent--;
462     print_server("};\n");
463     print_server("RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable =\n", iface->name, LOWORD(ver), HIWORD(ver));
464     print_server("{\n");
465     indent++;
466     print_server("%u,\n", method_count);
467     print_server("%s_table\n", iface->name);
468     indent--;
469     print_server("};\n");
470     fprintf(server, "\n");
471 }
472
473
474 static void write_stubdescdecl(type_t *iface)
475 {
476     print_server("static const MIDL_STUB_DESC %s_StubDesc;\n", iface->name);
477     fprintf(server, "\n");
478 }
479
480
481 static void write_stubdescriptor(type_t *iface, int expr_eval_routines)
482 {
483     print_server("static const MIDL_STUB_DESC %s_StubDesc =\n", iface->name);
484     print_server("{\n");
485     indent++;
486     print_server("(void *)& %s___RpcServerInterface,\n", iface->name);
487     print_server("MIDL_user_allocate,\n");
488     print_server("MIDL_user_free,\n");
489     print_server("{\n");
490     indent++;
491     print_server("0,\n");
492     indent--;
493     print_server("},\n");
494     print_server("0,\n");
495     print_server("0,\n");
496     if (expr_eval_routines)
497         print_server("ExprEvalRoutines,\n");
498     else
499         print_server("0,\n");
500     print_server("0,\n");
501     print_server("__MIDL_TypeFormatString.Format,\n");
502     print_server("1, /* -error bounds_check flag */\n");
503     print_server("0x10001, /* Ndr library version */\n");
504     print_server("0,\n");
505     print_server("0x50100a4, /* MIDL Version 5.1.164 */\n");
506     print_server("0,\n");
507     print_server("0,\n");
508     print_server("0,  /* notify & notify_flag routine table */\n");
509     print_server("1,  /* Flags */\n");
510     print_server("0,  /* Reserved3 */\n");
511     print_server("0,  /* Reserved4 */\n");
512     print_server("0   /* Reserved5 */\n");
513     indent--;
514     print_server("};\n");
515     fprintf(server, "\n");
516 }
517
518
519 static void write_serverinterfacedecl(type_t *iface)
520 {
521     unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);
522     UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
523
524     print_server("extern RPC_DISPATCH_TABLE %s_v%d_%d_DispatchTable;\n", iface->name, LOWORD(ver), HIWORD(ver));
525     fprintf(server, "\n");
526     print_server("static const RPC_SERVER_INTERFACE %s___RpcServerInterface =\n", iface->name );
527     print_server("{\n");
528     indent++;
529     print_server("sizeof(RPC_SERVER_INTERFACE),\n");
530     print_server("{{0x%08lx,0x%04x,0x%04x,{0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x}},{%d,%d}},\n",
531                  uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1],
532                  uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6],
533                  uuid->Data4[7], LOWORD(ver), HIWORD(ver));
534     print_server("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */
535     print_server("&%s_v%d_%d_DispatchTable,\n", iface->name, LOWORD(ver), HIWORD(ver));
536     print_server("0,\n");
537     print_server("0,\n");
538     print_server("0,\n");
539     print_server("0,\n");
540     print_server("0,\n");
541     indent--;
542     print_server("};\n");
543     if (old_names)
544         print_server("RPC_IF_HANDLE %s_ServerIfHandle = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n",
545                      iface->name, iface->name);
546     else
547         print_server("RPC_IF_HANDLE %s_v%d_%d_s_ifspec = (RPC_IF_HANDLE)& %s___RpcServerInterface;\n",
548                      iface->name, LOWORD(ver), HIWORD(ver), iface->name);
549     fprintf(server, "\n");
550 }
551
552 static void write_formatdesc( const char *str )
553 {
554     print_server("typedef struct _MIDL_%s_FORMAT_STRING\n", str );
555     print_server("{\n");
556     indent++;
557     print_server("short Pad;\n");
558     print_server("unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
559     indent--;
560     print_server("} MIDL_%s_FORMAT_STRING;\n", str);
561     print_server("\n");
562 }
563
564
565 static void write_formatstringsdecl(ifref_t *ifaces)
566 {
567     print_server("#define TYPE_FORMAT_STRING_SIZE %d\n",
568                  get_size_typeformatstring(ifaces));
569
570     print_server("#define PROC_FORMAT_STRING_SIZE %d\n",
571                  get_size_procformatstring(ifaces));
572
573     fprintf(server, "\n");
574     write_formatdesc("TYPE");
575     write_formatdesc("PROC");
576     fprintf(server, "\n");
577     print_server("static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
578     print_server("static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
579     print_server("\n");
580 }
581
582
583 static void init_server(void)
584 {
585     if (server)
586         return;
587     if (!(server = fopen(server_name, "w")))
588         error("Could not open %s for output\n", server_name);
589
590     print_server("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", WIDL_FULLVERSION, input_name);
591     print_server("#include <string.h>\n");
592     fprintf(server, "\n");
593     print_server("#include \"%s\"\n", header_name);
594     fprintf(server, "\n");
595 }
596
597
598 void write_server(ifref_t *ifaces)
599 {
600     unsigned int proc_offset = 0;
601     unsigned int type_offset = 2;
602     ifref_t *iface = ifaces;
603
604     if (!do_server)
605         return;
606     if (!ifaces)
607         return;
608     END_OF_LIST(iface);
609
610     init_server();
611     if (!server)
612         return;
613
614     write_formatstringsdecl(ifaces);
615
616     for (; iface; iface = PREV_LINK(iface))
617     {
618         if (is_object(iface->iface->attrs) || is_local(iface->iface->attrs))
619             continue;
620
621         fprintf(server, "/*****************************************************************************\n");
622         fprintf(server, " * %s interface\n", iface->iface->name);
623         fprintf(server, " */\n");
624         fprintf(server, "\n");
625
626         if (iface->iface->funcs)
627         {
628             int expr_eval_routines;
629
630             write_serverinterfacedecl(iface->iface);
631             write_stubdescdecl(iface->iface);
632     
633             write_function_stubs(iface->iface, &proc_offset, &type_offset);
634     
635             print_server("#if !defined(__RPC_WIN32__)\n");
636             print_server("#error  Invalid build platform for this stub.\n");
637             print_server("#endif\n");
638
639             fprintf(server, "\n");
640
641             expr_eval_routines = write_expr_eval_routines(server, iface->iface->name);
642             if (expr_eval_routines)
643                 write_expr_eval_routine_list(server, iface->iface->name);
644
645             write_stubdescriptor(iface->iface, expr_eval_routines);
646             write_dispatchtable(iface->iface);
647         }
648     }
649
650     fprintf(server, "\n");
651
652     write_procformatstring(server, ifaces);
653     write_typeformatstring(server, ifaces);
654
655     fclose(server);
656 }