Sync to wine-1.1.4:
[reactos.git] / reactos / tools / widl / proxy.c
1 /*
2 * IDL Compiler
3 *
4 * Copyright 2002 Ove Kaaven
5 * Copyright 2004 Mike McCormack
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #include <string.h>
31 #include <ctype.h>
32
33 #include "widl.h"
34 #include "utils.h"
35 #include "parser.h"
36 #include "header.h"
37 #include "typegen.h"
38 #include "expr.h"
39
40 #define END_OF_LIST(list) \
41 do { \
42 if (list) { \
43 while (NEXT_LINK(list)) \
44 list = NEXT_LINK(list); \
45 } \
46 } while(0)
47
48 static FILE* proxy;
49 static int indent = 0;
50
51 /* FIXME: support generation of stubless proxies */
52
53 static void print_proxy( const char *format, ... )
54 {
55 va_list va;
56 va_start( va, format );
57 print( proxy, indent, format, va );
58 va_end( va );
59 }
60
61 static void write_stubdescproto(void)
62 {
63 print_proxy( "static const MIDL_STUB_DESC Object_StubDesc;\n");
64 print_proxy( "\n");
65 }
66
67 static void write_stubdesc(int expr_eval_routines)
68 {
69 print_proxy( "static const MIDL_STUB_DESC Object_StubDesc =\n{\n");
70 indent++;
71 print_proxy( "0,\n");
72 print_proxy( "NdrOleAllocate,\n");
73 print_proxy( "NdrOleFree,\n");
74 print_proxy( "{0}, 0, 0, %s, 0,\n", expr_eval_routines ? "ExprEvalRoutines" : "0");
75 print_proxy( "__MIDL_TypeFormatString.Format,\n");
76 print_proxy( "1, /* -error bounds_check flag */\n");
77 print_proxy( "0x10001, /* Ndr library version */\n");
78 print_proxy( "0,\n");
79 print_proxy( "0x50100a4, /* MIDL Version 5.1.164 */\n");
80 print_proxy( "0,\n");
81 print_proxy("%s,\n", list_empty(&user_type_list) ? "0" : "UserMarshalRoutines");
82 print_proxy( "0, /* notify & notify_flag routine table */\n");
83 print_proxy( "1, /* Flags */\n");
84 print_proxy( "0, /* Reserved3 */\n");
85 print_proxy( "0, /* Reserved4 */\n");
86 print_proxy( "0 /* Reserved5 */\n");
87 indent--;
88 print_proxy( "};\n");
89 print_proxy( "\n");
90 }
91
92 static void init_proxy(const statement_list_t *stmts)
93 {
94 if (proxy) return;
95 if(!(proxy = fopen(proxy_name, "w")))
96 error("Could not open %s for output\n", proxy_name);
97 print_proxy( "/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", PACKAGE_VERSION, input_name);
98 print_proxy( "\n");
99 print_proxy( "#ifndef __REDQ_RPCPROXY_H_VERSION__\n");
100 print_proxy( "#define __REQUIRED_RPCPROXY_H_VERSION__ 440\n");
101 print_proxy( "#endif /* __REDQ_RPCPROXY_H_VERSION__ */\n");
102 print_proxy( "\n");
103 print_proxy( "#define __midl_proxy\n");
104 print_proxy( "#include \"objbase.h\"\n");
105 print_proxy( "#include \"rpcproxy.h\"\n");
106 print_proxy( "#ifndef __RPCPROXY_H_VERSION__\n");
107 print_proxy( "#error This code needs a newer version of rpcproxy.h\n");
108 print_proxy( "#endif /* __RPCPROXY_H_VERSION__ */\n");
109 print_proxy( "\n");
110 print_proxy( "#include \"%s\"\n", header_name);
111 print_proxy( "\n");
112 write_formatstringsdecl(proxy, indent, stmts, need_proxy);
113 write_stubdescproto();
114 }
115
116 static void clear_output_vars( const var_list_t *args )
117 {
118 const var_t *arg;
119
120 if (!args) return;
121 LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
122 {
123 if (is_attr(arg->attrs, ATTR_OUT) && !is_attr(arg->attrs, ATTR_IN)) {
124 print_proxy( "if(%s)\n", arg->name );
125 indent++;
126 print_proxy( "MIDL_memset( %s, 0, sizeof( *%s ));\n", arg->name, arg->name );
127 indent--;
128 }
129 }
130 }
131
132 int is_var_ptr(const var_t *v)
133 {
134 return is_ptr(v->type);
135 }
136
137 int cant_be_null(const var_t *v)
138 {
139 /* Search backwards for the most recent pointer attribute. */
140 const attr_list_t *attrs = v->attrs;
141 const type_t *type = v->type;
142
143 /* context handles have their own checking so they can be null for the
144 * purposes of null ref pointer checking */
145 if (is_aliaschain_attr(type, ATTR_CONTEXTHANDLE))
146 return 0;
147
148 if (! attrs && type)
149 {
150 attrs = type->attrs;
151 type = type->ref;
152 }
153
154 while (attrs)
155 {
156 int t = get_attrv(attrs, ATTR_POINTERTYPE);
157
158 if (t == RPC_FC_FP || t == RPC_FC_OP || t == RPC_FC_UP)
159 return 0;
160
161 if (t == RPC_FC_RP)
162 return 1;
163
164 if (type)
165 {
166 attrs = type->attrs;
167 type = type->ref;
168 }
169 else
170 attrs = NULL;
171 }
172
173 return 1; /* Default is RPC_FC_RP. */
174 }
175
176 static void proxy_check_pointers( const var_list_t *args )
177 {
178 const var_t *arg;
179
180 if (!args) return;
181 LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
182 {
183 if (is_var_ptr(arg) && cant_be_null(arg)) {
184 print_proxy( "if(!%s)\n", arg->name );
185 indent++;
186 print_proxy( "RpcRaiseException(RPC_X_NULL_REF_POINTER);\n");
187 indent--;
188 }
189 }
190 }
191
192 static void free_variable( const var_t *arg )
193 {
194 unsigned int type_offset = arg->type->typestring_offset;
195 expr_t *iid;
196 type_t *type = arg->type;
197 expr_t *size = get_size_is_expr(type, arg->name);
198
199 if (size)
200 {
201 print_proxy( "_StubMsg.MaxCount = " );
202 write_expr(proxy, size, 0, 1, NULL, NULL);
203 fprintf(proxy, ";\n\n");
204 print_proxy( "NdrClearOutParameters( &_StubMsg, ");
205 fprintf(proxy, "&__MIDL_TypeFormatString.Format[%u], ", type_offset );
206 fprintf(proxy, "(void*)%s );\n", arg->name );
207 return;
208 }
209
210 switch( type->type )
211 {
212 case RPC_FC_BYTE:
213 case RPC_FC_CHAR:
214 case RPC_FC_WCHAR:
215 case RPC_FC_SHORT:
216 case RPC_FC_USHORT:
217 case RPC_FC_ENUM16:
218 case RPC_FC_LONG:
219 case RPC_FC_ULONG:
220 case RPC_FC_ENUM32:
221 case RPC_FC_STRUCT:
222 break;
223
224 case RPC_FC_FP:
225 case RPC_FC_IP:
226 iid = get_attrp( arg->attrs, ATTR_IIDIS );
227 if( iid )
228 {
229 print_proxy( "_StubMsg.MaxCount = (unsigned long) " );
230 write_expr(proxy, iid, 1, 1, NULL, NULL);
231 print_proxy( ";\n\n" );
232 }
233 print_proxy( "NdrClearOutParameters( &_StubMsg, ");
234 fprintf(proxy, "&__MIDL_TypeFormatString.Format[%u], ", type_offset );
235 fprintf(proxy, "(void*)%s );\n", arg->name );
236 break;
237
238 default:
239 print_proxy("/* FIXME: %s code for %s type %d missing */\n", __FUNCTION__, arg->name, type->type );
240 }
241 }
242
243 static void proxy_free_variables( var_list_t *args )
244 {
245 const var_t *arg;
246
247 if (!args) return;
248 LIST_FOR_EACH_ENTRY( arg, args, const var_t, entry )
249 if (is_attr(arg->attrs, ATTR_OUT))
250 {
251 free_variable( arg );
252 fprintf(proxy, "\n");
253 }
254 }
255
256 static void gen_proxy(type_t *iface, const func_t *cur, int idx,
257 unsigned int proc_offset)
258 {
259 var_t *def = cur->def;
260 int has_ret = !is_void(get_func_return_type(cur));
261 int has_full_pointer = is_full_pointer_function(cur);
262 const char *callconv = get_attrp(def->type->attrs, ATTR_CALLCONV);
263 if (!callconv) callconv = "";
264
265 indent = 0;
266 write_type_decl_left(proxy, get_func_return_type(cur));
267 print_proxy( " %s %s_%s_Proxy(\n", callconv, iface->name, get_name(def));
268 write_args(proxy, cur->args, iface->name, 1, TRUE);
269 print_proxy( ")\n");
270 print_proxy( "{\n");
271 indent ++;
272 /* local variables */
273 if (has_ret) {
274 print_proxy( "" );
275 write_type_decl_left(proxy, get_func_return_type(cur));
276
277 /* Initialize _RetVal properly in order to avoid compiler warnings */
278 if (is_ptr(get_func_return_type(cur)) || is_array(get_func_return_type(cur)))
279 print_proxy(" _RetVal = NULL;\n");
280 else
281 print_proxy(" _RetVal = 0;\n");
282 }
283 print_proxy( "RPC_MESSAGE _RpcMessage;\n" );
284 print_proxy( "MIDL_STUB_MESSAGE _StubMsg;\n" );
285 if (has_ret) {
286 if (decl_indirect(get_func_return_type(cur)))
287 print_proxy("void *_p_%s = &%s;\n",
288 "_RetVal", "_RetVal");
289 }
290 print_proxy( "\n");
291
292 if (has_full_pointer)
293 write_full_pointer_init(proxy, indent, cur, FALSE);
294
295 /* FIXME: trace */
296 clear_output_vars( cur->args );
297
298 print_proxy( "RpcTryExcept\n" );
299 print_proxy( "{\n" );
300 indent++;
301 print_proxy( "NdrProxyInitialize(This, &_RpcMessage, &_StubMsg, &Object_StubDesc, %d);\n", idx);
302 proxy_check_pointers( cur->args );
303
304 print_proxy( "RpcTryFinally\n" );
305 print_proxy( "{\n" );
306 indent++;
307
308 write_remoting_arguments(proxy, indent, cur, PASS_IN, PHASE_BUFFERSIZE);
309
310 print_proxy( "NdrProxyGetBuffer(This, &_StubMsg);\n" );
311
312 write_remoting_arguments(proxy, indent, cur, PASS_IN, PHASE_MARSHAL);
313
314 print_proxy( "NdrProxySendReceive(This, &_StubMsg);\n" );
315 fprintf(proxy, "\n");
316 print_proxy( "_StubMsg.BufferStart = _RpcMessage.Buffer;\n" );
317 print_proxy( "_StubMsg.BufferEnd = _StubMsg.BufferStart + _RpcMessage.BufferLength;\n\n" );
318
319 print_proxy("if ((_RpcMessage.DataRepresentation & 0xffff) != NDR_LOCAL_DATA_REPRESENTATION)\n");
320 indent++;
321 print_proxy("NdrConvert( &_StubMsg, &__MIDL_ProcFormatString.Format[%u]);\n", proc_offset );
322 indent--;
323 fprintf(proxy, "\n");
324
325 write_remoting_arguments(proxy, indent, cur, PASS_OUT, PHASE_UNMARSHAL);
326
327 if (has_ret)
328 {
329 if (decl_indirect(get_func_return_type(cur)))
330 print_proxy("MIDL_memset(&%s, 0, sizeof(%s));\n", "_RetVal", "_RetVal");
331 else if (is_ptr(get_func_return_type(cur)) || is_array(get_func_return_type(cur)))
332 print_proxy("%s = 0;\n", "_RetVal");
333 write_remoting_arguments(proxy, indent, cur, PASS_RETURN, PHASE_UNMARSHAL);
334 }
335
336 indent--;
337 print_proxy( "}\n");
338 print_proxy( "RpcFinally\n" );
339 print_proxy( "{\n" );
340 indent++;
341 if (has_full_pointer)
342 write_full_pointer_free(proxy, indent, cur);
343 print_proxy( "NdrProxyFreeBuffer(This, &_StubMsg);\n" );
344 indent--;
345 print_proxy( "}\n");
346 print_proxy( "RpcEndFinally\n" );
347 indent--;
348 print_proxy( "}\n" );
349 print_proxy( "RpcExcept(_StubMsg.dwStubPhase != PROXY_SENDRECEIVE)\n" );
350 print_proxy( "{\n" );
351 if (has_ret) {
352 indent++;
353 proxy_free_variables( cur->args );
354 print_proxy( "_RetVal = NdrProxyErrorHandler(RpcExceptionCode());\n" );
355 indent--;
356 }
357 print_proxy( "}\n" );
358 print_proxy( "RpcEndExcept\n" );
359
360 if (has_ret) {
361 print_proxy( "return _RetVal;\n" );
362 }
363 indent--;
364 print_proxy( "}\n");
365 print_proxy( "\n");
366 }
367
368 static void gen_stub(type_t *iface, const func_t *cur, const char *cas,
369 unsigned int proc_offset)
370 {
371 var_t *def = cur->def;
372 const var_t *arg;
373 int has_ret = !is_void(get_func_return_type(cur));
374 int has_full_pointer = is_full_pointer_function(cur);
375
376 indent = 0;
377 print_proxy( "void __RPC_STUB %s_%s_Stub(\n", iface->name, get_name(def));
378 indent++;
379 print_proxy( "IRpcStubBuffer* This,\n");
380 print_proxy( "IRpcChannelBuffer *_pRpcChannelBuffer,\n");
381 print_proxy( "PRPC_MESSAGE _pRpcMessage,\n");
382 print_proxy( "DWORD* _pdwStubPhase)\n");
383 indent--;
384 print_proxy( "{\n");
385 indent++;
386 print_proxy("%s * _This = (%s*)((CStdStubBuffer*)This)->pvServerObject;\n", iface->name, iface->name);
387 print_proxy("MIDL_STUB_MESSAGE _StubMsg;\n");
388 declare_stub_args( proxy, indent, cur );
389 fprintf(proxy, "\n");
390
391 /* FIXME: trace */
392
393 print_proxy("NdrStubInitialize(_pRpcMessage, &_StubMsg, &Object_StubDesc, _pRpcChannelBuffer);\n");
394 fprintf(proxy, "\n");
395
396 write_parameters_init(proxy, indent, cur);
397
398 print_proxy("RpcTryFinally\n");
399 print_proxy("{\n");
400 indent++;
401 if (has_full_pointer)
402 write_full_pointer_init(proxy, indent, cur, TRUE);
403 print_proxy("if ((_pRpcMessage->DataRepresentation & 0xffff) != NDR_LOCAL_DATA_REPRESENTATION)\n");
404 indent++;
405 print_proxy("NdrConvert( &_StubMsg, &__MIDL_ProcFormatString.Format[%u]);\n", proc_offset );
406 indent--;
407 fprintf(proxy, "\n");
408
409 write_remoting_arguments(proxy, indent, cur, PASS_IN, PHASE_UNMARSHAL);
410 fprintf(proxy, "\n");
411
412 assign_stub_out_args( proxy, indent, cur );
413
414 print_proxy("*_pdwStubPhase = STUB_CALL_SERVER;\n");
415 fprintf(proxy, "\n");
416 print_proxy("");
417 if (has_ret) fprintf(proxy, "_RetVal = ");
418 if (cas) fprintf(proxy, "%s_%s_Stub", iface->name, cas);
419 else fprintf(proxy, "_This->lpVtbl->%s", get_name(def));
420 fprintf(proxy, "(_This");
421
422 if (cur->args)
423 {
424 LIST_FOR_EACH_ENTRY( arg, cur->args, const var_t, entry )
425 fprintf(proxy, ", %s%s", arg->type->declarray ? "*" : "", get_name(arg));
426 }
427 fprintf(proxy, ");\n");
428 fprintf(proxy, "\n");
429 print_proxy("*_pdwStubPhase = STUB_MARSHAL;\n");
430 fprintf(proxy, "\n");
431
432 write_remoting_arguments(proxy, indent, cur, PASS_OUT, PHASE_BUFFERSIZE);
433
434 if (!is_void(get_func_return_type(cur)))
435 write_remoting_arguments(proxy, indent, cur, PASS_RETURN, PHASE_BUFFERSIZE);
436
437 print_proxy("NdrStubGetBuffer(This, _pRpcChannelBuffer, &_StubMsg);\n");
438
439 write_remoting_arguments(proxy, indent, cur, PASS_OUT, PHASE_MARSHAL);
440 fprintf(proxy, "\n");
441
442 /* marshall the return value */
443 if (!is_void(get_func_return_type(cur)))
444 write_remoting_arguments(proxy, indent, cur, PASS_RETURN, PHASE_MARSHAL);
445
446 indent--;
447 print_proxy("}\n");
448 print_proxy("RpcFinally\n");
449 print_proxy("{\n");
450
451 write_remoting_arguments(proxy, indent+1, cur, PASS_OUT, PHASE_FREE);
452
453 if (has_full_pointer)
454 write_full_pointer_free(proxy, indent, cur);
455
456 print_proxy("}\n");
457 print_proxy("RpcEndFinally\n");
458
459 print_proxy("_pRpcMessage->BufferLength = _StubMsg.Buffer - (unsigned char *)_pRpcMessage->Buffer;\n");
460 indent--;
461
462 print_proxy("}\n");
463 print_proxy("\n");
464 }
465
466 static int write_proxy_methods(type_t *iface, int skip)
467 {
468 const func_t *cur;
469 int i = 0;
470
471 if (iface->ref) i = write_proxy_methods(iface->ref, iface->ref->ref != NULL);
472 if (iface->funcs) LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry ) {
473 var_t *def = cur->def;
474 if (!is_callas(def->attrs)) {
475 if (i) fprintf(proxy, ",\n");
476 if (skip) print_proxy( "0 /* %s_%s_Proxy */", iface->name, get_name(def));
477 else print_proxy( "%s_%s_Proxy", iface->name, get_name(def));
478 i++;
479 }
480 }
481 return i;
482 }
483
484 static int write_stub_methods(type_t *iface, int skip)
485 {
486 const func_t *cur;
487 int i = 0;
488
489 if (iface->ref) i = write_stub_methods(iface->ref, TRUE);
490 else return i; /* skip IUnknown */
491
492 if (iface->funcs) LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry ) {
493 var_t *def = cur->def;
494 if (!is_local(def->attrs)) {
495 if (i) fprintf(proxy,",\n");
496 if (skip) print_proxy("STUB_FORWARDING_FUNCTION");
497 else print_proxy( "%s_%s_Stub", iface->name, get_name(def));
498 i++;
499 }
500 }
501 return i;
502 }
503
504 static void write_proxy(type_t *iface, unsigned int *proc_offset)
505 {
506 int midx = -1, stubs;
507 const func_t *cur;
508
509 if (!iface->funcs) return;
510
511 /* FIXME: check for [oleautomation], shouldn't generate proxies/stubs if specified */
512
513 fprintf(proxy, "/*****************************************************************************\n");
514 fprintf(proxy, " * %s interface\n", iface->name);
515 fprintf(proxy, " */\n");
516 LIST_FOR_EACH_ENTRY( cur, iface->funcs, const func_t, entry )
517 {
518 const var_t *def = cur->def;
519 if (!is_local(def->attrs)) {
520 const var_t *cas = is_callas(def->attrs);
521 const char *cname = cas ? cas->name : NULL;
522 int idx = cur->idx;
523 if (cname) {
524 const func_t *m;
525 LIST_FOR_EACH_ENTRY( m, iface->funcs, const func_t, entry )
526 if (!strcmp(m->def->name, cname))
527 {
528 idx = m->idx;
529 break;
530 }
531 }
532 gen_proxy(iface, cur, idx, *proc_offset);
533 gen_stub(iface, cur, cname, *proc_offset);
534 *proc_offset += get_size_procformatstring_func( cur );
535 if (midx == -1) midx = idx;
536 else if (midx != idx) error("method index mismatch in write_proxy\n");
537 midx++;
538 }
539 }
540
541 /* proxy vtable */
542 print_proxy( "static const CINTERFACE_PROXY_VTABLE(%d) _%sProxyVtbl =\n", midx, iface->name);
543 print_proxy( "{\n");
544 indent++;
545 print_proxy( "{\n", iface->name);
546 indent++;
547 print_proxy( "&IID_%s,\n", iface->name);
548 indent--;
549 print_proxy( "},\n");
550 print_proxy( "{\n");
551 indent++;
552 write_proxy_methods(iface, FALSE);
553 fprintf(proxy, "\n");
554 indent--;
555 print_proxy( "}\n");
556 indent--;
557 print_proxy( "};\n");
558 fprintf(proxy, "\n\n");
559
560 /* stub vtable */
561 print_proxy( "static const PRPC_STUB_FUNCTION %s_table[] =\n", iface->name);
562 print_proxy( "{\n");
563 indent++;
564 stubs = write_stub_methods(iface, FALSE);
565 fprintf(proxy, "\n");
566 indent--;
567 fprintf(proxy, "};\n");
568 print_proxy( "\n");
569 print_proxy( "static const CInterfaceStubVtbl _%sStubVtbl =\n", iface->name);
570 print_proxy( "{\n");
571 indent++;
572 print_proxy( "{\n");
573 indent++;
574 print_proxy( "&IID_%s,\n", iface->name);
575 print_proxy( "0,\n");
576 print_proxy( "%d,\n", stubs+3);
577 print_proxy( "&%s_table[-3],\n", iface->name);
578 indent--;
579 print_proxy( "},\n", iface->name);
580 print_proxy( "{\n");
581 indent++;
582 print_proxy( "CStdStubBuffer_METHODS\n");
583 indent--;
584 print_proxy( "}\n");
585 indent--;
586 print_proxy( "};\n");
587 print_proxy( "\n");
588 }
589
590 static int does_any_iface(const statement_list_t *stmts, type_pred_t pred)
591 {
592 const statement_t *stmt;
593
594 if (stmts)
595 LIST_FOR_EACH_ENTRY(stmt, stmts, const statement_t, entry)
596 {
597 if (stmt->type == STMT_LIBRARY)
598 {
599 if (does_any_iface(stmt->u.lib->stmts, pred))
600 return TRUE;
601 }
602 else if (stmt->type == STMT_TYPE && stmt->u.type->type == RPC_FC_IP)
603 {
604 if (pred(stmt->u.type))
605 return TRUE;
606 }
607 }
608
609 return FALSE;
610 }
611
612 int need_proxy(const type_t *iface)
613 {
614 return is_object(iface->attrs) && !is_local(iface->attrs);
615 }
616
617 int need_stub(const type_t *iface)
618 {
619 return !is_object(iface->attrs) && !is_local(iface->attrs);
620 }
621
622 int need_proxy_file(const statement_list_t *stmts)
623 {
624 return does_any_iface(stmts, need_proxy);
625 }
626
627 int need_stub_files(const statement_list_t *stmts)
628 {
629 return does_any_iface(stmts, need_stub);
630 }
631
632 static void write_proxy_stmts(const statement_list_t *stmts, unsigned int *proc_offset)
633 {
634 const statement_t *stmt;
635 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
636 {
637 if (stmt->type == STMT_LIBRARY)
638 write_proxy_stmts(stmt->u.lib->stmts, proc_offset);
639 else if (stmt->type == STMT_TYPE && stmt->u.type->type == RPC_FC_IP)
640 {
641 if (need_proxy(stmt->u.type))
642 write_proxy(stmt->u.type, proc_offset);
643 }
644 }
645 }
646
647 static void write_proxy_iface_name_format(const statement_list_t *stmts, const char *format)
648 {
649 const statement_t *stmt;
650 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
651 {
652 if (stmt->type == STMT_LIBRARY)
653 write_proxy_iface_name_format(stmt->u.lib->stmts, format);
654 else if (stmt->type == STMT_TYPE && stmt->u.type->type == RPC_FC_IP)
655 {
656 type_t *iface = stmt->u.type;
657 if (iface->ref && iface->funcs && need_proxy(iface))
658 fprintf(proxy, format, iface->name);
659 }
660 }
661 }
662
663 static void write_iid_lookup(const statement_list_t *stmts, const char *file_id, int *c)
664 {
665 const statement_t *stmt;
666 if (stmts) LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
667 {
668 if (stmt->type == STMT_LIBRARY)
669 write_iid_lookup(stmt->u.lib->stmts, file_id, c);
670 else if (stmt->type == STMT_TYPE && stmt->u.type->type == RPC_FC_IP)
671 {
672 type_t *iface = stmt->u.type;
673 if(iface->ref && iface->funcs && need_proxy(iface))
674 {
675 fprintf(proxy, " if (!_%s_CHECK_IID(%d))\n", file_id, *c);
676 fprintf(proxy, " {\n");
677 fprintf(proxy, " *pIndex = %d;\n", *c);
678 fprintf(proxy, " return 1;\n");
679 fprintf(proxy, " }\n");
680 (*c)++;
681 }
682 }
683 }
684 }
685
686 void write_proxies(const statement_list_t *stmts)
687 {
688 int expr_eval_routines;
689 char *file_id = proxy_token;
690 int c;
691 unsigned int proc_offset = 0;
692
693 if (!do_proxies) return;
694 if (do_everything && !need_proxy_file(stmts)) return;
695
696 init_proxy(stmts);
697 if(!proxy) return;
698
699 write_proxy_stmts(stmts, &proc_offset);
700
701 expr_eval_routines = write_expr_eval_routines(proxy, proxy_token);
702 if (expr_eval_routines)
703 write_expr_eval_routine_list(proxy, proxy_token);
704 write_user_quad_list(proxy);
705 write_stubdesc(expr_eval_routines);
706
707 print_proxy( "#if !defined(__RPC_WIN32__)\n");
708 print_proxy( "#error Currently only Wine and WIN32 are supported.\n");
709 print_proxy( "#endif\n");
710 print_proxy( "\n");
711 write_procformatstring(proxy, stmts, need_proxy);
712 write_typeformatstring(proxy, stmts, need_proxy);
713
714 fprintf(proxy, "static const CInterfaceProxyVtbl* const _%s_ProxyVtblList[] =\n", file_id);
715 fprintf(proxy, "{\n");
716 write_proxy_iface_name_format(stmts, " (const CInterfaceProxyVtbl*)&_%sProxyVtbl,\n");
717 fprintf(proxy, " 0\n");
718 fprintf(proxy, "};\n");
719 fprintf(proxy, "\n");
720
721 fprintf(proxy, "static const CInterfaceStubVtbl* const _%s_StubVtblList[] =\n", file_id);
722 fprintf(proxy, "{\n");
723 write_proxy_iface_name_format(stmts, " (const CInterfaceStubVtbl*)&_%sStubVtbl,\n");
724 fprintf(proxy, " 0\n");
725 fprintf(proxy, "};\n");
726 fprintf(proxy, "\n");
727
728 fprintf(proxy, "static PCInterfaceName const _%s_InterfaceNamesList[] =\n", file_id);
729 fprintf(proxy, "{\n");
730 write_proxy_iface_name_format(stmts, " \"%s\",\n");
731 fprintf(proxy, " 0\n");
732 fprintf(proxy, "};\n");
733 fprintf(proxy, "\n");
734
735 fprintf(proxy, "#define _%s_CHECK_IID(n) IID_GENERIC_CHECK_IID(_%s, pIID, n)\n", file_id, file_id);
736 fprintf(proxy, "\n");
737 fprintf(proxy, "int __stdcall _%s_IID_Lookup(const IID* pIID, int* pIndex)\n", file_id);
738 fprintf(proxy, "{\n");
739 c = 0;
740 write_iid_lookup(stmts, file_id, &c);
741 fprintf(proxy, " return 0;\n");
742 fprintf(proxy, "}\n");
743 fprintf(proxy, "\n");
744
745 fprintf(proxy, "const ExtendedProxyFileInfo %s_ProxyFileInfo =\n", file_id);
746 fprintf(proxy, "{\n");
747 fprintf(proxy, " (const PCInterfaceProxyVtblList*)&_%s_ProxyVtblList,\n", file_id);
748 fprintf(proxy, " (const PCInterfaceStubVtblList*)&_%s_StubVtblList,\n", file_id);
749 fprintf(proxy, " _%s_InterfaceNamesList,\n", file_id);
750 fprintf(proxy, " 0,\n");
751 fprintf(proxy, " &_%s_IID_Lookup,\n", file_id);
752 fprintf(proxy, " %d,\n", c);
753 fprintf(proxy, " 1,\n");
754 fprintf(proxy, " 0,\n");
755 fprintf(proxy, " 0,\n");
756 fprintf(proxy, " 0,\n");
757 fprintf(proxy, " 0\n");
758 fprintf(proxy, "};\n");
759
760 fclose(proxy);
761 }