user32: Don't exit when double-clicking with right button held.
[wine] / tools / widl / header.c
1 /*
2  * IDL Compiler
3  *
4  * Copyright 2002 Ove Kaaven
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
23 #include <stdarg.h>
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 "windef.h"
35 #include "widl.h"
36 #include "utils.h"
37 #include "parser.h"
38 #include "header.h"
39
40 static int indentation = 0;
41
42 static void indent(FILE *h, int delta)
43 {
44   int c;
45   if (delta < 0) indentation += delta;
46   for (c=0; c<indentation; c++) fprintf(h, "    ");
47   if (delta > 0) indentation += delta;
48 }
49
50 int is_ptrchain_attr(const var_t *var, enum attr_type t)
51 {
52     if (is_attr(var->attrs, t))
53         return 1;
54     else
55     {
56         type_t *type = var->type;
57         for (;;)
58         {
59             if (is_attr(type->attrs, t))
60                 return 1;
61             else if (type->kind == TKIND_ALIAS)
62                 type = type->orig;
63             else if (is_ptr(type))
64                 type = type->ref;
65             else return 0;
66         }
67     }
68 }
69
70 int is_attr(const attr_list_t *list, enum attr_type t)
71 {
72     const attr_t *attr;
73     if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
74         if (attr->type == t) return 1;
75     return 0;
76 }
77
78 void *get_attrp(const attr_list_t *list, enum attr_type t)
79 {
80     const attr_t *attr;
81     if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
82         if (attr->type == t) return attr->u.pval;
83     return NULL;
84 }
85
86 unsigned long get_attrv(const attr_list_t *list, enum attr_type t)
87 {
88     const attr_t *attr;
89     if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
90         if (attr->type == t) return attr->u.ival;
91     return 0;
92 }
93
94 int is_void(const type_t *t)
95 {
96   if (!t->type && !t->ref) return 1;
97   return 0;
98 }
99
100 int is_conformant_array(const type_t *t)
101 {
102     return t->type == RPC_FC_CARRAY || t->type == RPC_FC_CVARRAY;
103 }
104
105 void write_guid(FILE *f, const char *guid_prefix, const char *name, const UUID *uuid)
106 {
107   if (!uuid) return;
108   fprintf(f, "DEFINE_GUID(%s_%s, 0x%08x, 0x%04x, 0x%04x, 0x%02x,0x%02x, 0x%02x,"
109         "0x%02x,0x%02x,0x%02x,0x%02x,0x%02x);\n",
110         guid_prefix, name, uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0],
111         uuid->Data4[1], uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5],
112         uuid->Data4[6], uuid->Data4[7]);
113 }
114
115 void write_name(FILE *h, const var_t *v)
116 {
117   if (is_attr( v->attrs, ATTR_PROPGET ))
118     fprintf(h, "get_" );
119   else if (is_attr( v->attrs, ATTR_PROPPUT ))
120     fprintf(h, "put_" );
121   else if (is_attr( v->attrs, ATTR_PROPPUTREF ))
122     fprintf(h, "putref_" );
123   fprintf(h, "%s", v->name);
124 }
125
126 void write_prefix_name(FILE *h, const char *prefix, const var_t *v)
127 {
128   fprintf(h, "%s", prefix);
129   write_name(h, v);
130 }
131
132 static void write_field(FILE *h, var_t *v)
133 {
134   if (!v) return;
135   if (v->type) {
136     const char *name = v->name;
137     if (name == NULL) {
138       switch (v->type->type) {
139       case RPC_FC_STRUCT:
140       case RPC_FC_CVSTRUCT:
141       case RPC_FC_CPSTRUCT:
142       case RPC_FC_CSTRUCT:
143       case RPC_FC_PSTRUCT:
144       case RPC_FC_BOGUS_STRUCT:
145       case RPC_FC_ENCAPSULATED_UNION:
146         name = "DUMMYSTRUCTNAME";
147         break;
148       case RPC_FC_NON_ENCAPSULATED_UNION:
149         name = "DUMMYUNIONNAME";
150         break;
151       default:
152         /* ? */
153         break;
154       }
155     }
156     indent(h, 0);
157     write_type(h, v->type, TRUE, "%s", name);
158     fprintf(h, ";\n");
159   }
160 }
161
162 static void write_fields(FILE *h, var_list_t *fields)
163 {
164     var_t *v;
165     if (!fields) return;
166     LIST_FOR_EACH_ENTRY( v, fields, var_t, entry ) write_field(h, v);
167 }
168
169 static void write_enums(FILE *h, var_list_t *enums)
170 {
171   var_t *v;
172   if (!enums) return;
173   LIST_FOR_EACH_ENTRY( v, enums, var_t, entry )
174   {
175     if (v->name) {
176       indent(h, 0);
177       write_name(h, v);
178       if (v->eval) {
179         fprintf(h, " = ");
180         write_expr(h, v->eval, 0);
181       }
182     }
183     if (list_next( enums, &v->entry )) fprintf(h, ",\n");
184   }
185   fprintf(h, "\n");
186 }
187
188 int needs_space_after(type_t *t)
189 {
190   return (t->kind == TKIND_ALIAS
191           || (!is_ptr(t) && (!is_conformant_array(t) || t->declarray)));
192 }
193
194 void write_type_left(FILE *h, type_t *t)
195 {
196   if (t->is_const) fprintf(h, "const ");
197
198   if (t->kind == TKIND_ALIAS) fprintf(h, "%s", t->name);
199   else if (t->declarray) write_type_left(h, t->ref);
200   else {
201     if (t->sign > 0) fprintf(h, "signed ");
202     else if (t->sign < 0) fprintf(h, "unsigned ");
203     switch (t->type) {
204       case RPC_FC_ENUM16:
205       case RPC_FC_ENUM32:
206         if (t->defined && !t->written && !t->ignore) {
207           if (t->name) fprintf(h, "enum %s {\n", t->name);
208           else fprintf(h, "enum {\n");
209           t->written = TRUE;
210           indentation++;
211           write_enums(h, t->fields);
212           indent(h, -1);
213           fprintf(h, "}");
214         }
215         else fprintf(h, "enum %s", t->name);
216         break;
217       case RPC_FC_STRUCT:
218       case RPC_FC_CVSTRUCT:
219       case RPC_FC_CPSTRUCT:
220       case RPC_FC_CSTRUCT:
221       case RPC_FC_PSTRUCT:
222       case RPC_FC_BOGUS_STRUCT:
223       case RPC_FC_ENCAPSULATED_UNION:
224         if (t->defined && !t->written && !t->ignore) {
225           if (t->name) fprintf(h, "struct %s {\n", t->name);
226           else fprintf(h, "struct {\n");
227           t->written = TRUE;
228           indentation++;
229           write_fields(h, t->fields);
230           indent(h, -1);
231           fprintf(h, "}");
232         }
233         else fprintf(h, "struct %s", t->name);
234         break;
235       case RPC_FC_NON_ENCAPSULATED_UNION:
236         if (t->defined && !t->written && !t->ignore) {
237           if (t->name) fprintf(h, "union %s {\n", t->name);
238           else fprintf(h, "union {\n");
239           t->written = TRUE;
240           indentation++;
241           write_fields(h, t->fields);
242           indent(h, -1);
243           fprintf(h, "}");
244         }
245         else fprintf(h, "union %s", t->name);
246         break;
247       case RPC_FC_RP:
248       case RPC_FC_UP:
249       case RPC_FC_FP:
250       case RPC_FC_OP:
251       case RPC_FC_CARRAY:
252       case RPC_FC_CVARRAY:
253         write_type_left(h, t->ref);
254         fprintf(h, "%s*", needs_space_after(t->ref) ? " " : "");
255         break;
256       default:
257         fprintf(h, "%s", t->name);
258     }
259   }
260 }
261
262 void write_type_right(FILE *h, type_t *t, int is_field)
263 {
264   if (t->declarray) {
265     if (is_conformant_array(t)) {
266       fprintf(h, "[%s]", is_field ? "1" : "");
267       t = t->ref;
268     }
269     for ( ; t->declarray; t = t->ref)
270       fprintf(h, "[%lu]", t->dim);
271   }
272 }
273
274 void write_type(FILE *h, type_t *t, int is_field, const char *fmt, ...)
275 {
276   write_type_left(h, t);
277   if (fmt) {
278     va_list args;
279     va_start(args, fmt);
280     if (needs_space_after(t))
281       fprintf(h, " ");
282     vfprintf(h, fmt, args);
283     va_end(args);
284   }
285   write_type_right(h, t, is_field);
286 }
287
288 user_type_list_t user_type_list = LIST_INIT(user_type_list);
289
290 static int user_type_registered(const char *name)
291 {
292   user_type_t *ut;
293   LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
294     if (!strcmp(name, ut->name))
295       return 1;
296   return 0;
297 }
298
299 void check_for_user_types(const var_list_t *list)
300 {
301   const var_t *v;
302
303   if (!list) return;
304   LIST_FOR_EACH_ENTRY( v, list, const var_t, entry )
305   {
306     type_t *type;
307     for (type = v->type; type; type = type->kind == TKIND_ALIAS ? type->orig : type->ref) {
308       const char *name = type->name;
309       if (type->user_types_registered) continue;
310       type->user_types_registered = 1;
311       if (is_attr(type->attrs, ATTR_WIREMARSHAL)) {
312         if (!user_type_registered(name))
313         {
314           user_type_t *ut = xmalloc(sizeof *ut);
315           ut->name = xstrdup(name);
316           list_add_tail(&user_type_list, &ut->entry);
317         }
318         /* don't carry on parsing fields within this type as we are already
319          * using a wire marshaled type */
320         break;
321       }
322       else
323       {
324         check_for_user_types(type->fields);
325       }
326     }
327   }
328 }
329
330 void write_user_types(void)
331 {
332   user_type_t *ut;
333   LIST_FOR_EACH_ENTRY(ut, &user_type_list, user_type_t, entry)
334   {
335     const char *name = ut->name;
336     fprintf(header, "ULONG           __RPC_USER %s_UserSize     (ULONG *, ULONG, %s *);\n", name, name);
337     fprintf(header, "unsigned char * __RPC_USER %s_UserMarshal  (ULONG *, unsigned char *, %s *);\n", name, name);
338     fprintf(header, "unsigned char * __RPC_USER %s_UserUnmarshal(ULONG *, unsigned char *, %s *);\n", name, name);
339     fprintf(header, "void            __RPC_USER %s_UserFree     (ULONG *, %s *);\n", name, name);
340   }
341 }
342
343 void write_typedef(type_t *type)
344 {
345   fprintf(header, "typedef ");
346   write_type(header, type->orig, FALSE, "%s", type->name);
347   fprintf(header, ";\n");
348 }
349
350 void write_expr(FILE *h, const expr_t *e, int brackets)
351 {
352   switch (e->type) {
353   case EXPR_VOID:
354     break;
355   case EXPR_NUM:
356     fprintf(h, "%lu", e->u.lval);
357     break;
358   case EXPR_HEXNUM:
359     fprintf(h, "0x%lx", e->u.lval);
360     break;
361   case EXPR_DOUBLE:
362     fprintf(h, "%#.15g", e->u.dval);
363     break;
364   case EXPR_TRUEFALSE:
365     if (e->u.lval == 0)
366       fprintf(h, "FALSE");
367     else
368       fprintf(h, "TRUE");
369     break;
370   case EXPR_IDENTIFIER:
371     fprintf(h, "%s", e->u.sval);
372     break;
373   case EXPR_NEG:
374     fprintf(h, "-");
375     write_expr(h, e->ref, 1);
376     break;
377   case EXPR_NOT:
378     fprintf(h, "~");
379     write_expr(h, e->ref, 1);
380     break;
381   case EXPR_PPTR:
382     fprintf(h, "*");
383     write_expr(h, e->ref, 1);
384     break;
385   case EXPR_CAST:
386     fprintf(h, "(");
387     write_type(h, e->u.tref, FALSE, NULL);
388     fprintf(h, ")");
389     write_expr(h, e->ref, 1);
390     break;
391   case EXPR_SIZEOF:
392     fprintf(h, "sizeof(");
393     write_type(h, e->u.tref, FALSE, NULL);
394     fprintf(h, ")");
395     break;
396   case EXPR_SHL:
397   case EXPR_SHR:
398   case EXPR_MUL:
399   case EXPR_DIV:
400   case EXPR_ADD:
401   case EXPR_SUB:
402   case EXPR_AND:
403   case EXPR_OR:
404     if (brackets) fprintf(h, "(");
405     write_expr(h, e->ref, 1);
406     switch (e->type) {
407     case EXPR_SHL: fprintf(h, " << "); break;
408     case EXPR_SHR: fprintf(h, " >> "); break;
409     case EXPR_MUL: fprintf(h, " * "); break;
410     case EXPR_DIV: fprintf(h, " / "); break;
411     case EXPR_ADD: fprintf(h, " + "); break;
412     case EXPR_SUB: fprintf(h, " - "); break;
413     case EXPR_AND: fprintf(h, " & "); break;
414     case EXPR_OR:  fprintf(h, " | "); break;
415     default: break;
416     }
417     write_expr(h, e->u.ext, 1);
418     if (brackets) fprintf(h, ")");
419     break;
420   case EXPR_COND:
421     if (brackets) fprintf(h, "(");
422     write_expr(h, e->ref, 1);
423     fprintf(h, " ? ");
424     write_expr(h, e->u.ext, 1);
425     fprintf(h, " : ");
426     write_expr(h, e->ext2, 1);
427     if (brackets) fprintf(h, ")");
428     break;
429   }
430 }
431
432 void write_constdef(const var_t *v)
433 {
434   fprintf(header, "#define %s (", v->name);
435   write_expr(header, v->eval, 0);
436   fprintf(header, ")\n\n");
437 }
438
439 void write_externdef(const var_t *v)
440 {
441   fprintf(header, "extern const ");
442   write_type(header, v->type, FALSE, "%s", v->name);
443   fprintf(header, ";\n\n");
444 }
445
446 void write_library(const char *name, const attr_list_t *attr)
447 {
448   const UUID *uuid = get_attrp(attr, ATTR_UUID);
449   fprintf(header, "\n");
450   write_guid(header, "LIBID", name, uuid);
451   fprintf(header, "\n");
452 }
453
454
455 const var_t* get_explicit_handle_var(const func_t* func)
456 {
457     const var_t* var;
458
459     if (!func->args)
460         return NULL;
461
462     LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
463         if (var->type->type == RPC_FC_BIND_PRIMITIVE)
464             return var;
465
466     return NULL;
467 }
468
469 int has_out_arg_or_return(const func_t *func)
470 {
471     const var_t *var;
472
473     if (!is_void(func->def->type))
474         return 1;
475
476     if (!func->args)
477         return 0;
478
479     LIST_FOR_EACH_ENTRY( var, func->args, const var_t, entry )
480         if (is_attr(var->attrs, ATTR_OUT))
481             return 1;
482
483     return 0;
484 }
485
486
487 /********** INTERFACES **********/
488
489 int is_object(const attr_list_t *list)
490 {
491     const attr_t *attr;
492     if (list) LIST_FOR_EACH_ENTRY( attr, list, const attr_t, entry )
493         if (attr->type == ATTR_OBJECT || attr->type == ATTR_ODL) return 1;
494     return 0;
495 }
496
497 int is_local(const attr_list_t *a)
498 {
499   return is_attr(a, ATTR_LOCAL);
500 }
501
502 const var_t *is_callas(const attr_list_t *a)
503 {
504   return get_attrp(a, ATTR_CALLAS);
505 }
506
507 static void write_method_macro(const type_t *iface, const char *name)
508 {
509   const func_t *cur;
510
511   if (iface->ref) write_method_macro(iface->ref, name);
512
513   if (!iface->funcs) return;
514
515   fprintf(header, "/*** %s methods ***/\n", iface->name);
516   LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
517   {
518     var_t *def = cur->def;
519     if (!is_callas(def->attrs)) {
520       const var_t *arg;
521       int argc = 0;
522       int c;
523
524       if (cur->args) LIST_FOR_EACH_ENTRY( arg, cur->args, const var_t, entry ) argc++;
525
526       fprintf(header, "#define %s_", name);
527       write_name(header,def);
528       fprintf(header, "(p");
529       for (c=0; c<argc; c++)
530         fprintf(header, ",%c", c+'a');
531       fprintf(header, ") ");
532
533       fprintf(header, "(p)->lpVtbl->");
534       write_name(header, def);
535       fprintf(header, "(p");
536       for (c=0; c<argc; c++)
537         fprintf(header, ",%c", c+'a');
538       fprintf(header, ")\n");
539     }
540   }
541 }
542
543 void write_args(FILE *h, const var_list_t *args, const char *name, int method, int do_indent)
544 {
545   const var_t *arg;
546   int count = 0;
547
548   if (do_indent)
549   {
550       indentation++;
551       indent(h, 0);
552   }
553   if (method == 1) {
554     fprintf(h, "%s* This", name);
555     count++;
556   }
557   if (args) LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry ) {
558     if (count) {
559         if (do_indent)
560         {
561             fprintf(h, ",\n");
562             indent(h, 0);
563         }
564         else fprintf(h, ",");
565     }
566     if (arg->args)
567     {
568       write_type_left(h, arg->type);
569       fprintf(h, " (STDMETHODCALLTYPE *");
570       write_name(h,arg);
571       fprintf(h, ")(");
572       write_args(h, arg->args, NULL, 0, FALSE);
573       fprintf(h, ")");
574     }
575     else
576       write_type(h, arg->type, FALSE, "%s", arg->name);
577     count++;
578   }
579   if (do_indent) indentation--;
580 }
581
582 static void write_cpp_method_def(const type_t *iface)
583 {
584   const func_t *cur;
585
586   if (!iface->funcs) return;
587
588   LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
589   {
590     var_t *def = cur->def;
591     if (!is_callas(def->attrs)) {
592       indent(header, 0);
593       fprintf(header, "virtual ");
594       write_type_left(header, def->type);
595       fprintf(header, " STDMETHODCALLTYPE ");
596       write_name(header, def);
597       fprintf(header, "(\n");
598       write_args(header, cur->args, iface->name, 2, TRUE);
599       fprintf(header, ") = 0;\n");
600       fprintf(header, "\n");
601     }
602   }
603 }
604
605 static void do_write_c_method_def(const type_t *iface, const char *name)
606 {
607   const func_t *cur;
608
609   if (iface->ref) do_write_c_method_def(iface->ref, name);
610
611   if (!iface->funcs) return;
612   indent(header, 0);
613   fprintf(header, "/*** %s methods ***/\n", iface->name);
614   LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
615   {
616     const var_t *def = cur->def;
617     if (!is_callas(def->attrs)) {
618       indent(header, 0);
619       write_type_left(header, def->type);
620       fprintf(header, " (STDMETHODCALLTYPE *");
621       write_name(header, def);
622       fprintf(header, ")(\n");
623       write_args(header, cur->args, name, 1, TRUE);
624       fprintf(header, ");\n");
625       fprintf(header, "\n");
626     }
627   }
628 }
629
630 static void write_c_method_def(const type_t *iface)
631 {
632   do_write_c_method_def(iface, iface->name);
633 }
634
635 static void write_c_disp_method_def(const type_t *iface)
636 {
637   do_write_c_method_def(iface->ref, iface->name);
638 }
639
640 static void write_method_proto(const type_t *iface)
641 {
642   const func_t *cur;
643
644   if (!iface->funcs) return;
645   LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
646   {
647     const var_t *def = cur->def;
648     const var_t *cas = is_callas(def->attrs);
649
650     if (!is_local(def->attrs)) {
651       /* proxy prototype */
652       write_type_left(header, def->type);
653       fprintf(header, " CALLBACK %s_", iface->name);
654       write_name(header, def);
655       fprintf(header, "_Proxy(\n");
656       write_args(header, cur->args, iface->name, 1, TRUE);
657       fprintf(header, ");\n");
658       /* stub prototype */
659       fprintf(header, "void __RPC_STUB %s_", iface->name);
660       write_name(header,def);
661       fprintf(header, "_Stub(\n");
662       fprintf(header, "    IRpcStubBuffer* This,\n");
663       fprintf(header, "    IRpcChannelBuffer* pRpcChannelBuffer,\n");
664       fprintf(header, "    PRPC_MESSAGE pRpcMessage,\n");
665       fprintf(header, "    DWORD* pdwStubPhase);\n");
666     }
667     if (cas) {
668       const func_t *m;
669       LIST_FOR_EACH_ENTRY( m, iface->funcs, const func_t, entry )
670           if (!strcmp(m->def->name, cas->name)) break;
671       if (&m->entry != iface->funcs) {
672         const var_t *mdef = m->def;
673         /* proxy prototype - use local prototype */
674         write_type_left(header, mdef->type);
675         fprintf(header, " CALLBACK %s_", iface->name);
676         write_name(header, mdef);
677         fprintf(header, "_Proxy(\n");
678         write_args(header, m->args, iface->name, 1, TRUE);
679         fprintf(header, ");\n");
680         /* stub prototype - use remotable prototype */
681         write_type_left(header, def->type);
682         fprintf(header, " __RPC_STUB %s_", iface->name);
683         write_name(header, mdef);
684         fprintf(header, "_Stub(\n");
685         write_args(header, cur->args, iface->name, 1, TRUE);
686         fprintf(header, ");\n");
687       }
688       else {
689         parser_warning("invalid call_as attribute (%s -> %s)\n", def->name, cas->name);
690       }
691     }
692   }
693 }
694
695 static void write_function_proto(const type_t *iface, const func_t *fun, const char *prefix)
696 {
697   var_t *def = fun->def;
698
699   /* FIXME: do we need to handle call_as? */
700   write_type_left(header, def->type);
701   fprintf(header, " ");
702   write_prefix_name(header, prefix, def);
703   fprintf(header, "(\n");
704   if (fun->args)
705     write_args(header, fun->args, iface->name, 0, TRUE);
706   else
707     fprintf(header, "    void");
708   fprintf(header, ");\n");
709 }
710
711 static void write_function_protos(const type_t *iface)
712 {
713   const char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
714   int explicit_handle = is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE);
715   const var_t* explicit_handle_var;
716   const func_t *cur;
717   int prefixes_differ = strcmp(prefix_client, prefix_server);
718
719   if (!iface->funcs) return;
720   LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
721   {
722     var_t *def = cur->def;
723
724     /* check for a defined binding handle */
725     explicit_handle_var = get_explicit_handle_var(cur);
726     if (explicit_handle) {
727       if (!explicit_handle_var) {
728         error("%s() does not define an explicit binding handle!\n", def->name);
729         return;
730       }
731     } else if (implicit_handle) {
732       if (explicit_handle_var) {
733         error("%s() must not define a binding handle!\n", def->name);
734         return;
735       }
736     }
737
738     if (prefixes_differ) {
739       fprintf(header, "/* client prototype */\n");
740       write_function_proto(iface, cur, prefix_client);
741       fprintf(header, "/* server prototype */\n");
742     }
743     write_function_proto(iface, cur, prefix_server);
744   }
745 }
746
747 void write_forward(type_t *iface)
748 {
749   /* C/C++ forwards should only be written for object interfaces, so if we
750    * have a full definition we only write one if we find [object] among the
751    * attributes - however, if we don't have a full definition at this point
752    * (i.e. this is an IDL forward), then we also assume that it is an object
753    * interface, since non-object interfaces shouldn't need forwards */
754   if ((!iface->defined || is_object(iface->attrs) || is_attr(iface->attrs, ATTR_DISPINTERFACE))
755         && !iface->written) {
756     fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", iface->name);
757     fprintf(header, "#define __%s_FWD_DEFINED__\n", iface->name);
758     fprintf(header, "typedef interface %s %s;\n", iface->name, iface->name);
759     fprintf(header, "#endif\n\n" );
760     iface->written = TRUE;
761   }
762 }
763
764 static void write_iface_guid(const type_t *iface)
765 {
766   const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
767   write_guid(header, "IID", iface->name, uuid);
768
769
770 static void write_dispiface_guid(const type_t *iface)
771 {
772   const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
773   write_guid(header, "DIID", iface->name, uuid);
774 }
775
776 static void write_coclass_guid(type_t *cocl)
777 {
778   const UUID *uuid = get_attrp(cocl->attrs, ATTR_UUID);
779   write_guid(header, "CLSID", cocl->name, uuid);
780 }
781
782 static void write_com_interface(type_t *iface)
783 {
784   if (!iface->funcs && !iface->ref) {
785     parser_warning("%s has no methods", iface->name);
786     return;
787   }
788
789   fprintf(header, "/*****************************************************************************\n");
790   fprintf(header, " * %s interface\n", iface->name);
791   fprintf(header, " */\n");
792   fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name);
793   fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name);
794   write_iface_guid(iface);
795   write_forward(iface);
796   /* C++ interface */
797   fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
798   if (iface->ref)
799   {
800       fprintf(header, "interface %s : public %s\n", iface->name, iface->ref->name);
801       fprintf(header, "{\n");
802       indentation++;
803       write_cpp_method_def(iface);
804       indentation--;
805       fprintf(header, "};\n");
806   }
807   else
808   {
809       fprintf(header, "interface %s\n", iface->name);
810       fprintf(header, "{\n");
811       fprintf(header, "    BEGIN_INTERFACE\n");
812       fprintf(header, "\n");
813       indentation++;
814       write_cpp_method_def(iface);
815       indentation--;
816       fprintf(header, "    END_INTERFACE\n");
817       fprintf(header, "};\n");
818   }
819   fprintf(header, "#else\n");
820   /* C interface */
821   fprintf(header, "typedef struct %sVtbl {\n", iface->name);
822   indentation++;
823   fprintf(header, "    BEGIN_INTERFACE\n");
824   fprintf(header, "\n");
825   write_c_method_def(iface);
826   indentation--;
827   fprintf(header, "    END_INTERFACE\n");
828   fprintf(header, "} %sVtbl;\n", iface->name);
829   fprintf(header, "interface %s {\n", iface->name);
830   fprintf(header, "    CONST_VTBL %sVtbl* lpVtbl;\n", iface->name);
831   fprintf(header, "};\n");
832   fprintf(header, "\n");
833   fprintf(header, "#ifdef COBJMACROS\n");
834   write_method_macro(iface, iface->name);
835   fprintf(header, "#endif\n");
836   fprintf(header, "\n");
837   fprintf(header, "#endif\n");
838   fprintf(header, "\n");
839   write_method_proto(iface);
840   fprintf(header,"\n#endif  /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
841 }
842
843 static void write_rpc_interface(const type_t *iface)
844 {
845   unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);
846   const char *var = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
847   static int allocate_written = 0;
848
849   if (!allocate_written)
850   {
851     allocate_written = 1;
852     fprintf(header, "void * __RPC_USER MIDL_user_allocate(size_t);\n");
853     fprintf(header, "void __RPC_USER MIDL_user_free(void *);\n\n");
854   }
855
856   fprintf(header, "/*****************************************************************************\n");
857   fprintf(header, " * %s interface (v%d.%d)\n", iface->name, LOWORD(ver), HIWORD(ver));
858   fprintf(header, " */\n");
859   fprintf(header,"#ifndef __%s_INTERFACE_DEFINED__\n", iface->name);
860   fprintf(header,"#define __%s_INTERFACE_DEFINED__\n\n", iface->name);
861   if (iface->funcs)
862   {
863     write_iface_guid(iface);
864     if (var) fprintf(header, "extern handle_t %s;\n", var);
865     if (old_names)
866     {
867         fprintf(header, "extern RPC_IF_HANDLE %s%s_ClientIfHandle;\n", prefix_client, iface->name);
868         fprintf(header, "extern RPC_IF_HANDLE %s%s_ServerIfHandle;\n", prefix_server, iface->name);
869     }
870     else
871     {
872         fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_c_ifspec;\n",
873                 prefix_client, iface->name, LOWORD(ver), HIWORD(ver));
874         fprintf(header, "extern RPC_IF_HANDLE %s%s_v%d_%d_s_ifspec;\n",
875                 prefix_server, iface->name, LOWORD(ver), HIWORD(ver));
876     }
877     write_function_protos(iface);
878   }
879   fprintf(header,"\n#endif  /* __%s_INTERFACE_DEFINED__ */\n\n", iface->name);
880
881   /* FIXME: server/client code */
882 }
883
884 void write_interface(type_t *iface)
885 {
886   if (is_object(iface->attrs))
887     write_com_interface(iface);
888   else
889     write_rpc_interface(iface);
890 }
891
892 void write_dispinterface(type_t *iface)
893 {
894   fprintf(header, "/*****************************************************************************\n");
895   fprintf(header, " * %s dispinterface\n", iface->name);
896   fprintf(header, " */\n");
897   fprintf(header,"#ifndef __%s_DISPINTERFACE_DEFINED__\n", iface->name);
898   fprintf(header,"#define __%s_DISPINTERFACE_DEFINED__\n\n", iface->name);
899   write_dispiface_guid(iface);
900   write_forward(iface);
901   /* C++ interface */
902   fprintf(header, "#if defined(__cplusplus) && !defined(CINTERFACE)\n");
903   fprintf(header, "interface %s : public %s\n", iface->name, iface->ref->name);
904   fprintf(header, "{\n");
905   fprintf(header, "};\n");
906   fprintf(header, "#else\n");
907   /* C interface */
908   fprintf(header, "typedef struct %sVtbl {\n", iface->name);
909   indentation++;
910   fprintf(header, "    BEGIN_INTERFACE\n");
911   fprintf(header, "\n");
912   write_c_disp_method_def(iface);
913   indentation--;
914   fprintf(header, "    END_INTERFACE\n");
915   fprintf(header, "} %sVtbl;\n", iface->name);
916   fprintf(header, "interface %s {\n", iface->name);
917   fprintf(header, "    CONST_VTBL %sVtbl* lpVtbl;\n", iface->name);
918   fprintf(header, "};\n");
919   fprintf(header, "\n");
920   fprintf(header, "#ifdef COBJMACROS\n");
921   write_method_macro(iface->ref, iface->name);
922   fprintf(header, "#endif\n");
923   fprintf(header, "\n");
924   fprintf(header, "#endif\n");
925   fprintf(header, "\n");
926   fprintf(header,"#endif  /* __%s_DISPINTERFACE_DEFINED__ */\n\n", iface->name);
927 }
928
929 void write_coclass(type_t *cocl)
930 {
931   fprintf(header, "/*****************************************************************************\n");
932   fprintf(header, " * %s coclass\n", cocl->name);
933   fprintf(header, " */\n\n");
934   write_coclass_guid(cocl);
935   fprintf(header, "\n");
936 }
937
938 void write_coclass_forward(type_t *cocl)
939 {
940   fprintf(header, "#ifndef __%s_FWD_DEFINED__\n", cocl->name);
941   fprintf(header, "#define __%s_FWD_DEFINED__\n", cocl->name);
942   fprintf(header, "typedef struct %s %s;\n", cocl->name, cocl->name);
943   fprintf(header, "#endif /* defined __%s_FWD_DEFINED__ */\n\n", cocl->name );
944 }