- Support multiple interfaces per idl file.
[reactos.git] / reactos / tools / widl / client.c
1 /*
2 * IDL Compiler
3 *
4 * Copyright 2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <assert.h>
26 #include <ctype.h>
27 #include <signal.h>
28
29 #include "widl.h"
30 #include "utils.h"
31 #include "parser.h"
32 #include "header.h"
33
34 #define END_OF_LIST(list) \
35 do { \
36 if (list) { \
37 while (NEXT_LINK(list)) \
38 list = NEXT_LINK(list); \
39 } \
40 } while(0)
41
42 static FILE* client;
43 static int indent = 0;
44
45 static int print_client( const char *format, ... )
46 {
47 va_list va;
48 int i, r;
49
50 va_start(va, format);
51 for (i = 0; i < indent; i++)
52 fprintf(client, " ");
53 r = vfprintf(client, format, va);
54 va_end(va);
55 return r;
56 }
57
58
59 static void write_procformatstring(type_t *iface)
60 {
61 func_t *func = iface->funcs;
62 var_t *var;
63
64 print_client("static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
65 print_client("{\n");
66 indent++;
67 print_client("0,\n");
68 print_client("{\n");
69 indent++;
70
71 while (NEXT_LINK(func)) func = NEXT_LINK(func);
72 while (func)
73 {
74 /* emit argument data */
75 if (func->args)
76 {
77 var = func->args;
78 while (NEXT_LINK(var)) var = NEXT_LINK(var);
79 while (var)
80 {
81 switch(var->type->type)
82 {
83 case RPC_FC_BYTE:
84 print_client("0x4e, /* FC_IN_PARAM_BASETYPE */\n");
85 print_client("0x%02x, /* FC_BYTE */\n", RPC_FC_BYTE);
86 break;
87 case RPC_FC_CHAR:
88 print_client("0x4e, /* FC_IN_PARAM_BASETYPE */\n");
89 print_client("0x%02x, /* FC_CHAR */\n", RPC_FC_CHAR);
90 break;
91 case RPC_FC_WCHAR:
92 print_client("0x4e, /* FC_IN_PARAM_BASETYPE */\n");
93 print_client("0x%02x, /* FC_WCHAR */\n", RPC_FC_WCHAR);
94 break;
95 case RPC_FC_USHORT:
96 case RPC_FC_SHORT:
97 print_client("0x4e, /* FC_IN_PARAM_BASETYPE */\n");
98 print_client("0x%02x, /* FC_USHORT */\n", RPC_FC_SHORT);
99 break;
100 case RPC_FC_ULONG:
101 case RPC_FC_LONG:
102 print_client("0x4e, /* FC_IN_PARAM_BASETYPE */\n");
103 print_client("0x%02x, /* FC_LONG */\n", RPC_FC_LONG);
104 break;
105 case RPC_FC_HYPER:
106 print_client("0x4e, /* FC_IN_PARAM_BASETYPE */\n");
107 print_client("0x%02x, /* FC_HYPER */\n", RPC_FC_HYPER);
108 break;
109 case RPC_FC_IGNORE:
110 print_client("0x4e, /* FC_IN_PARAM_BASETYPE */\n");
111 print_client("0x%02x, /* FC_IGNORE */\n", RPC_FC_IGNORE);
112 break;
113 case RPC_FC_SMALL:
114 print_client("0x4e, /* FC_IN_PARAM_BASETYPE */\n");
115 print_client("0x%02x, /* FC_SMALL */\n", RPC_FC_SMALL);
116 break;
117 case RPC_FC_FLOAT:
118 print_client("0x4e, /* FC_IN_PARAM_BASETYPE */\n");
119 print_client("0x%02x, /* FC_FLOAT */\n", RPC_FC_FLOAT);
120 break;
121 case RPC_FC_DOUBLE:
122 print_client("0x4e, /* FC_IN_PARAM_BASETYPE */\n");
123 print_client("0x%02x, /* FC_DOUBLE */\n", RPC_FC_DOUBLE);
124 break;
125 default:
126 error("Unknown/unsupported type\n");
127 return;
128 }
129
130 var = PREV_LINK(var);
131 }
132 }
133
134 /* emit return value data */
135 var = func->def;
136 if (is_void(var->type, NULL))
137 {
138 print_client("0x5b, /* FC_END */\n");
139 print_client("0x5c, /* FC_PAD */\n");
140 }
141 else
142 {
143 switch(var->type->type)
144 {
145 case RPC_FC_BYTE:
146 print_client("0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
147 print_client("0x%02x, /* FC_BYTE */\n", var->type->type);
148 break;
149 case RPC_FC_CHAR:
150 print_client("0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
151 print_client("0x%02x, /* FC_CHAR */\n", var->type->type);
152 break;
153 case RPC_FC_WCHAR:
154 print_client("0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
155 print_client("0x%02x, /* FC_WCHAR */\n", var->type->type);
156 break;
157 case RPC_FC_USHORT:
158 print_client("0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
159 print_client("0x%02x, /* FC_USHORT */\n", var->type->type);
160 break;
161 case RPC_FC_SHORT:
162 print_client("0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
163 print_client("0x%02x, /* FC_SHORT */\n", var->type->type);
164 break;
165 case RPC_FC_ULONG:
166 print_client("0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
167 print_client("0x%02x, /* FC_ULONG */\n", var->type->type);
168 break;
169 case RPC_FC_LONG:
170 print_client("0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
171 print_client("0x%02x, /* FC_LONG */\n", var->type->type);
172 break;
173 case RPC_FC_HYPER:
174 print_client("0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
175 print_client("0x%02x, /* FC_HYPER */\n", var->type->type);
176 break;
177 case RPC_FC_SMALL:
178 print_client("0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
179 print_client("0x%02x, /* FC_SMALL */\n", RPC_FC_SMALL);
180 break;
181 case RPC_FC_FLOAT:
182 print_client("0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
183 print_client("0x%02x, /* FC_FLOAT */\n", RPC_FC_FLOAT);
184 break;
185 case RPC_FC_DOUBLE:
186 print_client("0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
187 print_client("0x%02x, /* FC_DOUBLE */\n", RPC_FC_DOUBLE);
188 break;
189 default:
190 error("Unknown/unsupported type\n");
191 return;
192 }
193 }
194
195 func = PREV_LINK(func);
196 }
197
198 print_client("0x0\n");
199 indent--;
200 print_client("}\n");
201 indent--;
202 print_client("};\n");
203 print_client("\n");
204 }
205
206
207 static void write_typeformatstring(void)
208 {
209 print_client("static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
210 print_client("{\n");
211 indent++;
212 print_client("0,\n");
213 print_client("{\n");
214 indent++;
215 print_client("NdrFcShort(0x0),\n");
216 print_client("0x0\n");
217 indent--;
218 print_client("}\n");
219 indent--;
220 print_client("};\n");
221 print_client("\n");
222 }
223
224
225 static void print_message_buffer_size(func_t *func)
226 {
227 unsigned int alignment;
228 int size;
229 int last_size = -1;
230 var_t *var;
231
232 if (!func->args)
233 {
234 fprintf(client, " 0U");
235 return;
236 }
237
238 var = func->args;
239 while (NEXT_LINK(var)) var = NEXT_LINK(var);
240 while (var)
241 {
242 alignment = 0;
243 switch (var->type->type)
244 {
245 case RPC_FC_BYTE:
246 case RPC_FC_CHAR:
247 case RPC_FC_SMALL:
248 size = 1;
249 alignment = 0;
250 break;
251
252 case RPC_FC_WCHAR:
253 case RPC_FC_USHORT:
254 case RPC_FC_SHORT:
255 size = 2;
256 if (last_size != -1 && last_size < 2)
257 alignment += (2 - last_size);
258 break;
259
260 case RPC_FC_ULONG:
261 case RPC_FC_LONG:
262 case RPC_FC_FLOAT:
263 size = 4;
264 if (last_size != -1 && last_size < 4)
265 alignment += (4 - last_size);
266 break;
267
268 case RPC_FC_HYPER:
269 case RPC_FC_DOUBLE:
270 size = 8;
271 if (last_size != -1 && last_size < 4)
272 alignment += (4 - last_size);
273 break;
274
275 case RPC_FC_IGNORE:
276 size = 0;
277 break;
278
279 default:
280 error("Unknown/unsupported type!");
281 }
282
283 if (last_size != -1)
284 fprintf(client, " +");
285 fprintf(client, " %dU", (size == 0) ? 0 : size + alignment);
286
287 last_size = size;
288
289 var = PREV_LINK(var);
290 }
291 }
292
293
294 static void marshall_arguments(func_t *func)
295 {
296 unsigned int alignment;
297 unsigned int size;
298 unsigned int last_size = 0;
299 var_t *var;
300
301 if (!func->args)
302 return;
303
304 var = func->args;
305 while (NEXT_LINK(var)) var = NEXT_LINK(var);
306 while (var)
307 {
308 alignment = 0;
309 switch (var->type->type)
310 {
311 case RPC_FC_BYTE:
312 case RPC_FC_CHAR:
313 case RPC_FC_SMALL:
314 size = 1;
315 alignment = 0;
316 break;
317
318 case RPC_FC_WCHAR:
319 case RPC_FC_USHORT:
320 case RPC_FC_SHORT:
321 size = 2;
322 if (last_size != 0 && last_size < 2)
323 alignment = (2 - last_size);
324 break;
325
326 case RPC_FC_ULONG:
327 case RPC_FC_LONG:
328 case RPC_FC_FLOAT:
329 size = 4;
330 if (last_size != 0 && last_size < 4)
331 alignment = (4 - last_size);
332 break;
333
334 case RPC_FC_HYPER:
335 case RPC_FC_DOUBLE:
336 size = 8;
337 if (last_size != 0 && last_size < 4)
338 alignment = (4 - last_size);
339 break;
340
341 case RPC_FC_IGNORE:
342 size = 0;
343 break;
344
345 default:
346 error("Unknown/unsupported type!");
347 }
348
349 if (size != 0)
350 {
351 if (alignment != 0)
352 print_client("_StubMsg.Buffer += %u;\n", alignment);
353
354 print_client("*((");
355 write_type(client, var->type, var, var->tname);
356 fprintf(client, " __RPC_FAR*)_StubMsg.Buffer)++ = ");
357 write_name(client, var);
358 fprintf(client, ";\n");
359 fprintf(client, "\n");
360
361 last_size = size;
362 }
363
364 var = PREV_LINK(var);
365 }
366 }
367
368
369 static void write_function_stubs(type_t *iface)
370 {
371 char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
372 int explicit_handle = is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE);
373 func_t *func = iface->funcs;
374 var_t* var;
375 var_t* explicit_handle_var;
376 int method_count = 0;
377 unsigned int proc_offset = 0;
378
379 while (NEXT_LINK(func)) func = NEXT_LINK(func);
380 while (func)
381 {
382 var_t *def = func->def;
383
384 /* check for a defined binding handle */
385 explicit_handle_var = get_explicit_handle_var(func);
386 if (explicit_handle)
387 {
388 if (!explicit_handle_var)
389 {
390 error("%s() does not define an explicit binding handle!\n", def->name);
391 return;
392 }
393 }
394 else
395 {
396 if (explicit_handle_var)
397 {
398 error("%s() must not define a binding handle!\n", def->name);
399 return;
400 }
401 }
402
403 write_type(client, def->type, def, def->tname);
404 fprintf(client, " ");
405 write_name(client, def);
406 fprintf(client, "(\n");
407 indent++;
408 write_args(client, func->args, iface->name, 0, TRUE);
409 fprintf(client, ")\n");
410 indent--;
411
412 /* write the functions body */
413 fprintf(client, "{\n");
414 indent++;
415
416 /* declare return value '_RetVal' */
417 if (!is_void(def->type, NULL))
418 {
419 print_client("");
420 write_type(client, def->type, def, def->tname);
421 fprintf(client, " _RetVal;\n");
422 }
423
424 if (implicit_handle || explicit_handle)
425 print_client("RPC_BINDING_HANDLE _Handle = 0;\n");
426 print_client("RPC_MESSAGE _RpcMessage;\n");
427 print_client("MIDL_STUB_MESSAGE _StubMsg;\n");
428 fprintf(client, "\n");
429 print_client("RpcTryFinally\n");
430 print_client("{\n");
431 indent++;
432
433 print_client("NdrClientInitializeNew(\n");
434 indent++;
435 print_client("(PRPC_MESSAGE)&_RpcMessage,\n");
436 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
437 print_client("(PMIDL_STUB_DESC)&%s_StubDesc,\n", iface->name);
438 print_client("%d);\n", method_count);
439 indent--;
440 fprintf(client, "\n");
441
442 if (implicit_handle)
443 {
444 print_client("_Handle = %s;\n", implicit_handle);
445 fprintf(client, "\n");
446 }
447 else if (explicit_handle)
448 {
449 print_client("_Handle = %s;\n", explicit_handle_var->name);
450 fprintf(client, "\n");
451 }
452
453 /* emit the message buffer size */
454 print_client("_StubMsg.BufferLength =");
455 print_message_buffer_size(func);
456 fprintf(client, ";\n");
457
458
459 print_client("NdrGetBuffer(\n");
460 indent++;
461 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
462 print_client("_StubMsg.BufferLength,\n");
463 if (implicit_handle || explicit_handle)
464 print_client("%_Handle);\n");
465 else
466 print_client("%s__MIDL_AutoBindHandle);\n", iface->name);
467 indent--;
468 fprintf(client, "\n");
469
470 /* marshal arguments */
471 marshall_arguments(func);
472
473 /* send/recieve message */
474 print_client("NdrSendReceive(\n");
475 indent++;
476 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
477 print_client("(unsigned char __RPC_FAR *)_StubMsg.Buffer);\n");
478 indent--;
479
480 /* unmarshal return value */
481 if (!is_void(def->type, NULL))
482 {
483 fprintf(client, "\n");
484
485 print_client("if ((_RpcMessage.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n");
486 indent++;
487 print_client("NdrConvert(\n");
488 indent++;
489 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
490 print_client("(PFORMAT_STRING)&__MIDL_ProcFormatString.Format[%u]);\n", proc_offset);
491 indent -= 2;
492 fprintf(client, "\n");
493
494 print_client("_RetVal = *((");
495 write_type(client, def->type, def, def->tname);
496 fprintf(client, " __RPC_FAR *)_StubMsg.Buffer)++;\n");
497 }
498
499 /* update proc_offset */
500 if (func->args)
501 {
502 var = func->args;
503 while (NEXT_LINK(var)) var = NEXT_LINK(var);
504 while (var)
505 {
506 proc_offset += 2; /* FIXME */
507 var = PREV_LINK(var);
508 }
509 }
510 proc_offset += 2; /* FIXME */
511
512 indent--;
513 print_client("}\n");
514 print_client("RpcFinally\n");
515 print_client("{\n");
516 indent++;
517
518
519 /* FIXME: emit client finally code */
520
521 print_client("NdrFreeBuffer((PMIDL_STUB_MESSAGE)&_StubMsg);\n");
522
523 indent--;
524 print_client("}\n");
525 print_client("RpcEndFinally\n");
526
527
528 /* emit return code */
529 if (!is_void(def->type, NULL))
530 {
531 fprintf(client, "\n");
532 print_client("return _RetVal;\n");
533 }
534
535 indent--;
536 fprintf(client, "}\n");
537 fprintf(client, "\n");
538
539 method_count++;
540 func = PREV_LINK(func);
541 }
542 }
543
544
545 static void write_bindinghandledecl(type_t *iface)
546 {
547 print_client("static RPC_BINDING_HANDLE %s__MIDL_AutoBindHandle;\n", iface->name);
548 fprintf(client, "\n");
549 }
550
551
552 static void write_stubdescdecl(type_t *iface)
553 {
554 print_client("extern const MIDL_STUB_DESC %s_StubDesc;\n", iface->name);
555 fprintf(client, "\n");
556 }
557
558
559 static void write_stubdescriptor(type_t *iface)
560 {
561 char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
562
563 print_client("static const MIDL_STUB_DESC %s_StubDesc =\n", iface->name);
564 print_client("{\n");
565 indent++;
566 print_client("(void __RPC_FAR *)& %s___RpcClientInterface,\n", iface->name);
567 print_client("MIDL_user_allocate,\n");
568 print_client("MIDL_user_free,\n");
569 if (implicit_handle)
570 print_client("&%s,\n", implicit_handle);
571 else
572 print_client("&%s__MIDL_AutoBindHandle,\n", iface->name);
573 print_client("0,\n");
574 print_client("0,\n");
575 print_client("0,\n");
576 print_client("0,\n");
577 print_client("__MIDL_TypeFormatString.Format,\n");
578 print_client("1, /* -error bounds_check flag */\n");
579 print_client("0x10001, /* Ndr library version */\n");
580 print_client("0,\n");
581 print_client("0x50100a4, /* MIDL Version 5.1.164 */\n");
582 print_client("0,\n");
583 print_client("0,\n");
584 print_client("0, /* notify & notify_flag routine table */\n");
585 print_client("1, /* Flags */\n");
586 print_client("0, /* Reserved3 */\n");
587 print_client("0, /* Reserved4 */\n");
588 print_client("0 /* Reserved5 */\n");
589 indent--;
590 print_client("};\n");
591 fprintf(client, "\n");
592 }
593
594
595 static void write_clientinterfacedecl(type_t *iface)
596 {
597 unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);
598 UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
599
600 print_client("static const RPC_CLIENT_INTERFACE %s___RpcClientInterface =\n", iface->name );
601 print_client("{\n");
602 indent++;
603 print_client("sizeof(RPC_CLIENT_INTERFACE),\n");
604 print_client("{{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",
605 uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1],
606 uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6],
607 uuid->Data4[7], LOWORD(ver), HIWORD(ver));
608 print_client("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */
609 print_client("0,\n");
610 print_client("0,\n");
611 print_client("0,\n");
612 print_client("0,\n");
613 print_client("0,\n");
614 print_client("0,\n");
615 indent--;
616 print_client("};\n");
617 print_client("RPC_IF_HANDLE %s_v%d_%d_c_ifspec = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n",
618 iface->name, LOWORD(ver), HIWORD(ver), iface->name);
619 fprintf(client, "\n");
620 }
621
622
623 static void write_formatdesc( const char *str )
624 {
625 print_client("typedef struct _MIDL_%s_FORMAT_STRING\n", str );
626 print_client("{\n");
627 indent++;
628 print_client("short Pad;\n");
629 print_client("unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
630 indent--;
631 print_client("} MIDL_%s_FORMAT_STRING;\n", str);
632 print_client("\n");
633 }
634
635
636 static void write_formatstringsdecl(type_t *iface)
637 {
638 int byte_count = 1;
639 func_t *func;
640 var_t *var;
641
642 print_client("#define TYPE_FORMAT_STRING_SIZE %d\n", 3); /* FIXME */
643
644 /* determine the proc format string size */
645 func = iface->funcs;
646 while (NEXT_LINK(func)) func = NEXT_LINK(func);
647 while (func)
648 {
649 /* argument list size */
650 if (func->args)
651 {
652 var = func->args;
653 while (NEXT_LINK(var)) var = NEXT_LINK(var);
654 while (var)
655 {
656 byte_count += 2; /* FIXME: determine real size */
657 var = PREV_LINK(var);
658 }
659 }
660
661 /* return value size */
662 byte_count += 2; /* FIXME: determine real size */
663 func = PREV_LINK(func);
664 }
665
666 print_client("#define PROC_FORMAT_STRING_SIZE %d\n", byte_count);
667
668 fprintf(client, "\n");
669 write_formatdesc("TYPE");
670 write_formatdesc("PROC");
671 fprintf(client, "\n");
672 print_client("extern const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
673 print_client("extern const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
674 print_client("\n");
675 }
676
677
678 static void write_implicithandledecl(type_t *iface)
679 {
680 char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
681
682 if (implicit_handle)
683 {
684 fprintf(client, "handle_t %s;\n", implicit_handle);
685 fprintf(client, "\n");
686 }
687 }
688
689
690 static void init_client(void)
691 {
692 if (client) return;
693 if (!(client = fopen(client_name, "w")))
694 error("Could not open %s for output\n", client_name);
695
696 print_client("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", WIDL_FULLVERSION, input_name);
697 print_client("#include<string.h>\n");
698 print_client("#ifdef _ALPHA_\n");
699 print_client("#include<stdarg.h>\n");
700 print_client("#endif\n");
701 fprintf(client, "\n");
702 print_client("#include\"%s\"\n", header_name);
703 fprintf(client, "\n");
704 }
705
706
707 void write_client(ifref_t *ifaces)
708 {
709 ifref_t *iface = ifaces;
710
711 if (!do_client)
712 return;
713 if (!iface)
714 return;
715 END_OF_LIST(iface);
716
717 init_client();
718 if (!client)
719 return;
720
721 while (iface)
722 {
723 fprintf(client, "/*****************************************************************************\n");
724 fprintf(client, " * %s interface\n", iface->iface->name);
725 fprintf(client, " */\n");
726 fprintf(client, "\n");
727
728 write_formatstringsdecl(iface->iface);
729 write_implicithandledecl(iface->iface);
730
731 write_clientinterfacedecl(iface->iface);
732 write_stubdescdecl(iface->iface);
733 write_bindinghandledecl(iface->iface);
734
735 write_function_stubs(iface->iface);
736 write_stubdescriptor(iface->iface);
737
738 print_client("#if !defined(__RPC_WIN32__)\n");
739 print_client("#error Invalid build platform for this stub.\n");
740 print_client("#endif\n");
741 fprintf(client, "\n");
742
743 write_procformatstring(iface->iface);
744 write_typeformatstring();
745
746 fprintf(client, "\n");
747
748 iface = PREV_LINK(iface);
749 }
750
751 fclose(client);
752 }