libwine_uuid has been renamed to libuuid.
[wine] / tools / widl / proxy.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #ifdef HAVE_UNISTD_H
26 # include <unistd.h>
27 #endif
28 #include <string.h>
29 #include <assert.h>
30 #include <ctype.h>
31 #include <signal.h>
32
33 #include "widl.h"
34 #include "utils.h"
35 #include "parser.h"
36 #include "header.h"
37
38 static FILE* proxy;
39
40 /* FIXME: support generation of stubless proxies */
41
42 static void write_stubdesc(void)
43 {
44   fprintf(proxy, "const MIDL_STUB_DESC Object_StubDesc = {\n");
45   fprintf(proxy, "    0,\n");
46   fprintf(proxy, "    NdrOleAllocate,\n");
47   fprintf(proxy, "    NdrOleFree,\n");
48   fprintf(proxy, "    {0}, 0, 0, 0, 0,\n");
49   fprintf(proxy, "    0 /* __MIDL_TypeFormatString.Format */\n");
50   fprintf(proxy, "};\n");
51   fprintf(proxy, "\n");
52 }
53
54 static void init_proxy(void)
55 {
56   if (proxy) return;
57   proxy = fopen(proxy_name, "w");
58   fprintf(proxy, "/*** Autogenerated by WIDL %s - Do not edit ***/\n", WIDL_FULLVERSION);
59   fprintf(proxy, "#include \"rpcproxy.h\"\n");
60   fprintf(proxy, "#include \"%s\"\n", header_name);
61   fprintf(proxy, "\n");
62   write_stubdesc();
63 }
64
65 static void gen_proxy(type_t *iface, func_t *cur, int idx)
66 {
67   var_t *def = cur->def;
68   int has_ret = !is_void(def->type, def);
69
70   write_type(proxy, def->type, def, def->tname);
71   fprintf(proxy, " CALLBACK %s_", iface->name);
72   write_name(proxy, def);
73   fprintf(proxy, "_Proxy(\n");
74   write_args(proxy, cur->args, iface->name, 1, TRUE);
75   fprintf(proxy, ")\n");
76   fprintf(proxy, "{\n");
77   /* local variables */
78   if (has_ret) {
79     fprintf(proxy, "    ");
80     write_type(proxy, def->type, def, def->tname);
81     fprintf(proxy, " _Ret;\n");
82   }
83   fprintf(proxy, "    RPC_MESSAGE _Msg;\n");
84   fprintf(proxy, "    MIDL_STUB_MESSAGE _StubMsg;\n");
85   fprintf(proxy, "\n");
86
87   /* FIXME: trace */
88   /* FIXME: clear output vars? */
89
90   fprintf(proxy, "    NdrProxyInitialize(This, &_Msg, &_StubMsg, &Object_StubDesc, %d);\n", idx);
91
92   /* FIXME: size buffer */
93
94   fprintf(proxy, "    NdrProxyGetBuffer(This, &_StubMsg);\n");
95
96   /* FIXME: marshall */
97
98   fprintf(proxy, "    NdrProxySendReceive(This, &_StubMsg);\n");
99
100   /* FIXME: unmarshall */
101
102   fprintf(proxy, "    NdrProxyFreeBuffer(This, &_StubMsg);\n");
103
104   if (has_ret) {
105     fprintf(proxy, "    return _Ret;\n");
106   }
107   fprintf(proxy, "}\n");
108   fprintf(proxy, "\n");
109 }
110
111 static void gen_stub(type_t *iface, func_t *cur, char *cas)
112 {
113   var_t *def = cur->def;
114   var_t *arg;
115   int has_ret = !is_void(def->type, def);
116
117   fprintf(proxy, "void __RPC_STUB %s_", iface->name);
118   write_name(proxy, def);
119   fprintf(proxy, "_Stub(\n");
120   fprintf(proxy, "    IRpcStubBuffer* This,\n");
121   fprintf(proxy, "    IRpcChannelBuffer* pRpcChannelBuffer,\n");
122   fprintf(proxy, "    PRPC_MESSAGE pRpcMessage,\n");
123   fprintf(proxy, "    DWORD* pdwStubPhase)\n");
124   fprintf(proxy, "{\n");
125   /* local variables */
126   if (has_ret) {
127     fprintf(proxy, "    ");
128     write_type(proxy, def->type, def, def->tname);
129     fprintf(proxy, " _Ret;\n");
130   }
131   fprintf(proxy, "    %s* _This = (%s*)((CStdStubBuffer*)This)->pvServerObject;\n", iface->name, iface->name);
132   fprintf(proxy, "    MIDL_STUB_MESSAGE _StubMsg;\n");
133   arg = cur->args;
134   while (arg) {
135     fprintf(proxy, "    ");
136     write_type(proxy, arg->type, arg, arg->tname);
137     fprintf(proxy, " ");
138     write_name(proxy, arg);
139     fprintf(proxy, ";\n");
140     arg = NEXT_LINK(arg);
141   }
142   fprintf(proxy, "\n");
143
144   /* FIXME: trace */
145   /* FIXME: clear output vars? */
146
147   fprintf(proxy, "    NdrStubInitialize(pRpcMessage, &_StubMsg, &Object_StubDesc, pRpcChannelBuffer);\n");
148
149   /* FIXME: unmarshall */
150
151   fprintf(proxy, "    *pdwStubPhase = STUB_CALL_SERVER;\n");
152   fprintf(proxy, "    ");
153   if (has_ret) fprintf(proxy, "_Ret = ");
154   fprintf(proxy, "%s_", iface->name);
155   if (cas) fprintf(proxy, "%s_Stub", cas);
156   else write_name(proxy, def);
157   fprintf(proxy, "(_This");
158   arg = cur->args;
159   if (arg) {
160     while (NEXT_LINK(arg)) arg = NEXT_LINK(arg);
161     while (arg) {
162       fprintf(proxy, ", ");
163       write_name(proxy, arg);
164       arg = PREV_LINK(arg);
165     }
166   }
167   fprintf(proxy, ");\n");
168   fprintf(proxy, "    *pdwStubPhase = STUB_MARSHAL;\n");
169
170   /* FIXME: size buffer */
171
172   fprintf(proxy, "    NdrStubGetBuffer(This, pRpcChannelBuffer, &_StubMsg);\n");
173
174   /* FIXME: marshall */
175
176   fprintf(proxy, "}\n");
177   fprintf(proxy, "\n");
178 }
179
180 static int write_proxy_methods(type_t *iface)
181 {
182   func_t *cur = iface->funcs;
183   int i = 0;
184   while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
185
186   if (iface->ref) i = write_proxy_methods(iface->ref);
187   while (cur) {
188     var_t *def = cur->def;
189     if (!is_callas(def->attrs)) {
190       if (i) fprintf(proxy, ",\n     ");
191       fprintf(proxy, "%s_", iface->name);
192       write_name(proxy, def);
193       fprintf(proxy, "_Proxy");
194       i++;
195     }
196     cur = PREV_LINK(cur);
197   }
198   return i;
199 }
200
201 static int write_stub_methods(type_t *iface)
202 {
203   func_t *cur = iface->funcs;
204   int i = 0;
205   while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
206
207   if (iface->ref) i = write_stub_methods(iface->ref);
208   else return i; /* skip IUnknown */
209   while (cur) {
210     var_t *def = cur->def;
211     if (!is_local(def->attrs)) {
212       if (i) fprintf(proxy, ",\n");
213       fprintf(proxy, "    %s_", iface->name);
214       write_name(proxy, def);
215       fprintf(proxy, "_Stub");
216       i++;
217     }
218     cur = PREV_LINK(cur);
219   }
220   return i;
221 }
222
223 static void write_proxy(type_t *iface)
224 {
225   int midx = -1, stubs;
226   func_t *cur = iface->funcs;
227
228   if (!cur) return;
229   if (!do_everything) return;
230
231   while (NEXT_LINK(cur)) cur = NEXT_LINK(cur);
232
233   /* FIXME: check for [oleautomation], shouldn't generate proxies/stubs if specified */
234
235   init_proxy();
236
237   fprintf(proxy, "/*****************************************************************************\n");
238   fprintf(proxy, " * %s interface\n", iface->name);
239   fprintf(proxy, " */\n");
240   while (cur) {
241     var_t *def = cur->def;
242     if (!is_local(def->attrs)) {
243       var_t *cas = is_callas(def->attrs);
244       char *cname = cas ? cas->name : NULL;
245       int idx = cur->idx;
246       if (cname) {
247         func_t *m = iface->funcs;
248         while (m && strcmp(get_name(m->def), cname))
249           m = NEXT_LINK(m);
250         idx = m->idx;
251       }
252       gen_proxy(iface, cur, idx);
253       gen_stub(iface, cur, cname);
254       if (midx == -1) midx = idx;
255       else if (midx != idx) yyerror("method index mismatch in write_proxy");
256       midx++;
257     }
258     cur = PREV_LINK(cur);
259   }
260
261   /* proxy vtable */
262   fprintf(proxy, "const CINTERFACE_PROXY_VTABLE(%d) %sProxyVtbl = {\n", midx, iface->name);
263   fprintf(proxy, "    {&IID_%s},\n", iface->name);
264   fprintf(proxy, "    {");
265   write_proxy_methods(iface);
266   fprintf(proxy, "}\n");
267   fprintf(proxy, "};\n");
268   fprintf(proxy, "\n");
269
270   /* stub vtable */
271   fprintf(proxy, "static const PRPC_STUB_FUNCTION %s_table[] = {\n", iface->name);
272   stubs = write_stub_methods(iface);
273   fprintf(proxy, "\n");
274   fprintf(proxy, "};\n");
275   fprintf(proxy, "\n");
276   fprintf(proxy, "const CInterfaceStubVtbl %sStubVtbl = {\n", iface->name);
277   fprintf(proxy, "    {&IID_%s,\n", iface->name);
278   fprintf(proxy, "     0,\n");
279   fprintf(proxy, "     %d,\n", stubs+3);
280   fprintf(proxy, "     &%s_table[-3]},\n", iface->name);
281   fprintf(proxy, "    {CStdStubBuffer_METHODS}\n");
282   fprintf(proxy, "};\n");
283   fprintf(proxy, "\n");
284 }
285
286 void write_proxies(ifref_t *ifaces)
287 {
288   ifref_t *lcur = ifaces;
289   ifref_t *cur;
290   char *file_id = proxy_token;
291   int c;
292
293   if (!lcur) return;
294   while (NEXT_LINK(lcur)) lcur = NEXT_LINK(lcur);
295
296   cur = lcur;
297   while (cur) {
298     if (is_object(cur->iface->attrs) && !is_local(cur->iface->attrs))
299       write_proxy(cur->iface);
300     cur = PREV_LINK(cur);
301   }
302
303   if (!proxy) return;
304
305   fprintf(proxy, "const CInterfaceProxyVtbl* _%s_ProxyVtblList[] = {\n", file_id);
306   cur = lcur;
307   while (cur) {
308     fprintf(proxy, "    (CInterfaceProxyVtbl*)&%sProxyVtbl,\n", cur->iface->name);
309     cur = PREV_LINK(cur);
310   }
311   fprintf(proxy, "    0\n");
312   fprintf(proxy, "};\n");
313   fprintf(proxy, "\n");
314
315   fprintf(proxy, "const CInterfaceStubVtbl* _%s_StubVtblList[] = {\n", file_id);
316   cur = lcur;
317   while (cur) {
318     fprintf(proxy, "    (CInterfaceStubVtbl*)&%sStubVtbl,\n", cur->iface->name);
319     cur = PREV_LINK(cur);
320   }
321   fprintf(proxy, "    0\n");
322   fprintf(proxy, "};\n");
323   fprintf(proxy, "\n");
324
325   fprintf(proxy, "const PCInterfaceName _%s_InterfaceNamesList[] = {\n", file_id);
326   cur = lcur;
327   while (cur) {
328     fprintf(proxy, "    \"%s\",\n", cur->iface->name);
329     cur = PREV_LINK(cur);
330   }
331   fprintf(proxy, "    0\n");
332   fprintf(proxy, "};\n");
333   fprintf(proxy, "\n");
334
335   fprintf(proxy, "#define _%s_CHECK_IID(n) IID_GENERIC_CHECK_IID(_XXX, pIID, n)\n", file_id);
336   fprintf(proxy, "\n");
337   fprintf(proxy, "int __stdcall _%s_IID_Lookup(const IID* pIID, int* pIndex)\n", file_id);
338   fprintf(proxy, "{\n");
339   cur = lcur;
340   c = 0;
341   while (cur) {
342     fprintf(proxy, "    if (!_%s_CHECK_IID(%d)) {\n", file_id, c);
343     fprintf(proxy, "        *pIndex = %d\n", c);
344     fprintf(proxy, "        return 1;\n");
345     fprintf(proxy, "    }\n");
346     cur = PREV_LINK(cur);
347     c++;
348   }
349   fprintf(proxy, "    return 0;\n");
350   fprintf(proxy, "}\n");
351   fprintf(proxy, "\n");
352
353   fprintf(proxy, "const ExtendedProxyFileInfo %s_ProxyFileInfo = {\n", file_id);
354   fprintf(proxy, "    (PCInterfaceProxyVtblList*)&_%s_ProxyVtblList,\n", file_id);
355   fprintf(proxy, "    (PCInterfaceStubVtblList*)&_%s_StubVtblList,\n", file_id);
356   fprintf(proxy, "    (const PCInterfaceName*)&_%s_InterfaceNamesList,\n", file_id);
357   fprintf(proxy, "    0,\n");
358   fprintf(proxy, "    &_%s_IID_Lookup,\n", file_id);
359   fprintf(proxy, "    %d,\n", c);
360   fprintf(proxy, "    1\n");
361   fprintf(proxy, "};\n");
362
363   fclose(proxy);
364 }