Allocate another 4 bytes for unique pointers to simple types.
[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 unsigned int
60 get_var_stack_offset_32(func_t *func, char *name)
61 {
62 unsigned int offset = 0;
63 var_t *var;
64
65 var = func->args;
66 while (NEXT_LINK(var)) var = NEXT_LINK(var);
67 while (var)
68 {
69 if (!strcmp(var->name, name))
70 return offset;
71
72 if (var->type->type == RPC_FC_DOUBLE ||
73 var->type->type == RPC_FC_HYPER)
74 offset += 8;
75 else
76 offset += 4;
77
78 var = PREV_LINK(var);
79 }
80
81 return 0;
82 }
83
84
85 static unsigned int
86 get_var_stack_offset_64(func_t *func, char *name)
87 {
88 unsigned int offset = 0;
89 var_t *var;
90
91 var = func->args;
92 while (NEXT_LINK(var)) var = NEXT_LINK(var);
93 while (var)
94 {
95 if (!strcmp(var->name, name))
96 return offset;
97
98 offset += 8;
99
100 var = PREV_LINK(var);
101 }
102
103 return 0;
104 }
105
106
107 static unsigned int
108 get_var_type_offset(var_t *var)
109 {
110 unsigned int toffset = 0;
111 void *sizeis_attr;
112 int string_attr;
113
114 if (var->ptr_level == 0)
115 {
116 if ((var->type->type == RPC_FC_RP) &&
117 (var->type->ref->ref->type == RPC_FC_STRUCT))
118 {
119 var_t *field = var->type->ref->ref->fields;
120 int tsize = 9;
121
122 while (NEXT_LINK(field)) field = NEXT_LINK(field);
123 while (field)
124 {
125 tsize++;
126 field = PREV_LINK(field);
127 }
128 if (tsize % 2)
129 tsize++;
130
131 toffset += tsize;
132 }
133 }
134 else if (var->ptr_level == 1)
135 {
136 sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS);
137 string_attr = is_attr(var->attrs, ATTR_STRING);
138
139 if (sizeis_attr)
140 {
141 if (string_attr)
142 {
143 if (var->type->type == RPC_FC_BYTE ||
144 var->type->type == RPC_FC_CHAR ||
145 var->type->type == RPC_FC_WCHAR)
146 toffset += 10;
147 }
148 else
149 {
150 if (is_base_type(var->type))
151 toffset += 14;
152 }
153 }
154 else
155 {
156 if (is_base_type(var->type))
157 toffset += 4;
158 }
159 }
160
161 return toffset;
162 }
163
164
165 static type_t *get_type_by_name(func_t *func, char *name)
166 {
167 var_t *var;
168
169 var = func->args;
170 while (NEXT_LINK(var)) var = NEXT_LINK(var);
171 while (var)
172 {
173 if (!strcmp(var->name, name))
174 return var->type;
175
176 var = PREV_LINK(var);
177 }
178
179 return NULL;
180 }
181
182
183 static unsigned char
184 get_base_type(unsigned char type)
185 {
186
187 switch (type)
188 {
189 case RPC_FC_USHORT:
190 type = RPC_FC_SHORT;
191 break;
192
193 case RPC_FC_ULONG:
194 type = RPC_FC_LONG;
195 break;
196 }
197
198 return type;
199 }
200
201
202 static int get_type_size(type_t *type, int alignment)
203 {
204 int size;
205 var_t *field;
206
207 switch(type->type)
208 {
209 case RPC_FC_BYTE:
210 case RPC_FC_CHAR:
211 case RPC_FC_SMALL:
212 size = 1;
213 size = ((size + alignment - 1) & ~(alignment -1));
214 break;
215
216 case RPC_FC_WCHAR:
217 case RPC_FC_USHORT:
218 case RPC_FC_SHORT:
219 size = 2;
220 size = ((size + alignment - 1) & ~(alignment -1));
221 break;
222
223 case RPC_FC_ULONG:
224 case RPC_FC_LONG:
225 case RPC_FC_FLOAT:
226 size = 4;
227 size = ((size + alignment - 1) & ~(alignment -1));
228 break;
229
230 case RPC_FC_HYPER:
231 case RPC_FC_DOUBLE:
232 size = 8;
233 size = ((size + alignment - 1) & ~(alignment -1));
234 break;
235
236 case RPC_FC_IGNORE:
237 size = 0;
238 break;
239
240 case RPC_FC_STRUCT:
241 field = type->fields;
242 size = 0;
243 while (NEXT_LINK(field)) field = NEXT_LINK(field);
244 while (field)
245 {
246 size += get_type_size(field->type, alignment);
247 field = PREV_LINK(field);
248 }
249 break;
250
251 default:
252 error("%s:%d Unknown/unsupported type 0x%x\n",
253 __FUNCTION__,__LINE__, type->type);
254 return 0;
255 }
256
257 return size;
258 }
259
260
261 static int get_type_alignment(type_t *type)
262 {
263 int size;
264
265 switch(type->type)
266 {
267 case RPC_FC_BYTE:
268 case RPC_FC_CHAR:
269 case RPC_FC_SMALL:
270 size = 1;
271 break;
272
273 case RPC_FC_WCHAR:
274 case RPC_FC_USHORT:
275 case RPC_FC_SHORT:
276 size = 2;
277 break;
278
279 case RPC_FC_ULONG:
280 case RPC_FC_LONG:
281 case RPC_FC_FLOAT:
282 size = 4;
283 break;
284
285 case RPC_FC_HYPER:
286 case RPC_FC_DOUBLE:
287 size = 8;
288 break;
289
290 default:
291 error("%s:%d Unknown/unsupported type 0x%x\n",
292 __FUNCTION__,__LINE__, type->type);
293 return 0;
294 }
295
296 return size;
297 }
298
299
300 static void write_procformatstring(type_t *iface)
301 {
302 func_t *func = iface->funcs;
303 var_t *var;
304 unsigned int type_offset = 2;
305 int in_attr, out_attr;
306
307 print_client("const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString =\n");
308 print_client("{\n");
309 indent++;
310 print_client("0,\n");
311 print_client("{\n");
312 indent++;
313
314 while (NEXT_LINK(func)) func = NEXT_LINK(func);
315 while (func)
316 {
317 /* emit argument data */
318 if (func->args)
319 {
320 var = func->args;
321 while (NEXT_LINK(var)) var = NEXT_LINK(var);
322 while (var)
323 {
324 out_attr = is_attr(var->attrs, ATTR_OUT);
325 in_attr = is_attr(var->attrs, ATTR_IN);
326
327 /* set 'in' attribute if neither 'in' nor 'out' is set */
328 if (!out_attr && !in_attr)
329 in_attr = 1;
330
331 if (var->ptr_level == 0)
332 {
333 if (is_base_type(var->type))
334 {
335 print_client("0x4e, /* FC_IN_PARAM_BASETYPE */\n");
336 print_client("0x%02x, /* FC_<type> */\n",
337 get_base_type(var->type->type));
338 }
339 else if (var->type->type == RPC_FC_RP)
340 {
341 if (in_attr & !out_attr)
342 print_client("0x4d, /* FC_IN_PARAM */\n");
343 else if (!in_attr & out_attr)
344 print_client("0x51, /* FC_OUT_PARAM */\n");
345 else if (in_attr & out_attr)
346 print_client("0x50, /* FC_IN_OUT_PARAM */\n");
347 fprintf(client, "#ifndef _ALPHA_\n");
348 print_client("0x01,\n");
349 fprintf(client, "#else\n");
350 print_client("0x02,\n");
351 fprintf(client, "#endif\n");
352 print_client("NdrFcShort(0x%x),\n", type_offset);
353 }
354 else
355 {
356 print_client("0x4d, /* FC_IN_PARAM */\n");
357
358 error("%s:%d Unknown/unsupported type 0x%x\n",
359 __FUNCTION__,__LINE__, var->type->type);
360 return;
361 }
362 }
363 else if (var->ptr_level == 1)
364 {
365 if (in_attr & !out_attr)
366 print_client("0x4d, /* FC_IN_PARAM */\n");
367 else if (!in_attr & out_attr)
368 print_client("0x51, /* FC_OUT_PARAM */\n");
369 else if (in_attr & out_attr)
370 print_client("0x50, /* FC_IN_OUT_PARAM */\n");
371 fprintf(client, "#ifndef _ALPHA_\n");
372 print_client("0x01,\n");
373 fprintf(client, "#else\n");
374 print_client("0x02,\n");
375 fprintf(client, "#endif\n");
376 print_client("NdrFcShort(0x%x),\n", type_offset);
377 }
378 else
379 {
380 error("%s:%d Pointer level %d is not supported!\n",
381 __FUNCTION__,__LINE__, var->ptr_level);
382 return;
383 }
384
385 type_offset += get_var_type_offset(var);
386
387 var = PREV_LINK(var);
388 }
389 }
390
391 /* emit return value data */
392 var = func->def;
393 if (is_void(var->type, NULL))
394 {
395 print_client("0x5b, /* FC_END */\n");
396 print_client("0x5c, /* FC_PAD */\n");
397 }
398 else if (is_base_type(var->type))
399 {
400 print_client("0x53, /* FC_RETURN_PARAM_BASETYPE */\n");
401 print_client("0x%02x, /* FC_<type> */\n", get_base_type(var->type->type));
402 }
403 else
404 {
405 error("%s:%d Unknown/unsupported type 0x%x\n",
406 __FUNCTION__,__LINE__, var->type->type);
407 return;
408 }
409
410 func = PREV_LINK(func);
411 }
412
413 print_client("0x0\n");
414 indent--;
415 print_client("}\n");
416 indent--;
417 print_client("};\n");
418 print_client("\n");
419 }
420
421
422 static void write_typeformatstring(type_t *iface)
423 {
424 func_t *func = iface->funcs;
425 var_t *var;
426 type_t *type;
427 int in_attr, out_attr;
428 int string_attr;
429 int ptr_attr, ref_attr, unique_attr;
430 void *sizeis_attr;
431
432 print_client("const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString =\n");
433 print_client("{\n");
434 indent++;
435 print_client("0,\n");
436 print_client("{\n");
437 indent++;
438 print_client("NdrFcShort(0x00),\n");
439
440 while (NEXT_LINK(func)) func = NEXT_LINK(func);
441 while (func)
442 {
443 if (func->args)
444 {
445 var = func->args;
446 while (NEXT_LINK(var)) var = NEXT_LINK(var);
447 while (var)
448 {
449 in_attr = is_attr(var->attrs, ATTR_IN);
450 out_attr = is_attr(var->attrs, ATTR_OUT);
451 string_attr = is_attr(var->attrs, ATTR_STRING);
452
453 if (var->ptr_level > 1)
454 {
455 error("Function '%s' argument '%s': Pointer level %d not supported!\n",
456 func->def->name, var->name, var->ptr_level);
457 return;
458 }
459
460 if (var->ptr_level == 0)
461 {
462 if (!is_base_type(var->type))
463 {
464 if (var->type->type == RPC_FC_RP)
465 {
466 var_t *field;
467 int tsize = 9;
468 unsigned char flags = 0;
469
470 if (!in_attr && out_attr)
471 flags |= RPC_FC_P_ONSTACK;
472
473 print_client("0x11, 0x%02X, /* FC_RP, [flags] */\n", flags);
474 print_client("NdrFcShort(0x%02X),\n", 0x02);
475 print_client("0x%02X,\n", var->type->ref->ref->type);
476 print_client("0x%02X,\n", 3); /* alignment - 1 */
477 print_client("NdrFcShort(0x%02X),\n", get_type_size(var->type->ref->ref, 4));
478
479 field = var->type->ref->ref->fields;
480 while (NEXT_LINK(field)) field = NEXT_LINK(field);
481 while (field)
482 {
483 print_client("0x%02X,\n", get_base_type(field->type->type));
484 tsize++;
485 field = PREV_LINK(field);
486 }
487 if (tsize % 2)
488 {
489 print_client("0x5c, /* FC_PAD */\n");
490 tsize++;
491 }
492 print_client("0x5b, /* FC_END */\n");
493 }
494 else
495 {
496
497 error("%s:%d Unknown/unsupported type 0x%x\n",
498 __FUNCTION__,__LINE__, var->type->type);
499 return;
500 }
501 }
502 }
503 else if (var->ptr_level == 1)
504 {
505 ptr_attr = is_attr(var->attrs, ATTR_PTR);
506 ref_attr = is_attr(var->attrs, ATTR_REF);
507 unique_attr = is_attr(var->attrs, ATTR_UNIQUE);
508 sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS);
509
510 if (ptr_attr + ref_attr + unique_attr == 0)
511 ref_attr = 1;
512
513 if (sizeis_attr)
514 {
515 unsigned char type_type = 0;
516
517 type = get_type_by_name(func, ((var_t *)sizeis_attr)->name);
518 if (type != NULL)
519 type_type = type->type;
520
521 if (ref_attr)
522 print_client("0x11, 0x00, /* FC_RP */\n");
523 else if (unique_attr)
524 print_client("0x12, 0x00, /* FC_UP */\n");
525 else if (ptr_attr)
526 print_client("0x14, 0x00, /* FC_FP */\n");
527
528 print_client("NdrFcShort(0x02),\n");
529
530 if (string_attr)
531 {
532 if (var->type->type == RPC_FC_WCHAR)
533 print_client("0x25, /* FC_C_WSTRING */\n");
534 else
535 print_client("0x22, /* FC_C_CSTRING */\n");
536 print_client("0x44, /* FC_STRING_SIZED */\n");
537 print_client("0x%02x,\n", 0x20 + type_type);
538 print_client("0x00,\n");
539
540 fprintf(client, "#ifndef _ALPHA_\n");
541 print_client("NdrFcShort(0x%02X),\n",
542 get_var_stack_offset_32(func, ((var_t *)sizeis_attr)->name));
543 fprintf(client, "#else\n");
544 print_client("NdrFcShort(0x%02X),\n",
545 get_var_stack_offset_64(func, ((var_t *)sizeis_attr)->name));
546 fprintf(client, "#endif\n");
547 }
548 else
549 {
550 print_client("0x1b, /* FC_CARRAY */\n");
551 print_client("0x%02x,\n", get_type_alignment(var->type) - 1);
552 print_client("NdrFcShort(0x%02x),\n", get_type_size(var->type, 1));
553 print_client("0x%02x,\n", 0x20 + type_type);
554 if (out_attr)
555 print_client("0x54, /* FC_DEREFERENCE */\n");
556 else
557 print_client("0x00, /* */\n");
558
559 fprintf(client, "#ifndef _ALPHA_\n");
560 print_client("NdrFcShort(0x%02X),\n",
561 get_var_stack_offset_32(func, ((var_t *)sizeis_attr)->name));
562 fprintf(client, "#else\n");
563 print_client("NdrFcShort(0x%02X),\n",
564 get_var_stack_offset_64(func, ((var_t *)sizeis_attr)->name));
565 fprintf(client, "#endif\n");
566 print_client("0x%02x,\n", get_base_type(var->type->type));
567 print_client("0x5b, /* FC_END */\n");
568 }
569 }
570 else if (is_base_type(var->type))
571 {
572 if (out_attr && !in_attr)
573 {
574 if (ref_attr)
575 print_client("0x11, 0x0c, /* FC_RP [allocated_on_stack] [simple_pointer] */\n");
576 else if (unique_attr)
577 print_client("0x12, 0x0c, /* FC_UP [allocated_on_stack] [simple_pointer] */\n");
578 else if (ptr_attr)
579 print_client("0x14, 0x0c, /* FC_FP [allocated_on_stack] [simple_pointer] */\n");
580 }
581 else
582 {
583 if (ref_attr)
584 print_client("0x11, 0x08, /* FC_RP [simple_pointer] */\n");
585 else if (unique_attr)
586 print_client("0x12, 0x08, /* FC_UP [simple_pointer] */\n");
587 else if (ptr_attr)
588 print_client("0x14, 0x08, /* FC_FP [simple_pointer] */\n");
589 }
590
591 if (string_attr)
592 {
593 if (var->type->type == RPC_FC_CHAR)
594 print_client("0x%02x, /* FC_C_CSTRING */\n", RPC_FC_C_CSTRING);
595 else if (var->type->type == RPC_FC_WCHAR)
596 print_client("0x%02x, /* FC_C_WSTRING */\n", RPC_FC_C_WSTRING);
597 else
598 {
599 error("%s: Invalid type!\n", __FUNCTION__);
600 return;
601 }
602 }
603 else
604 print_client("0x%02x, /* FC_<type> */\n", get_base_type(var->type->type));
605 print_client("0x5c, /* FC_PAD */\n");
606 }
607 }
608
609 var = PREV_LINK(var);
610 }
611 }
612
613 func = PREV_LINK(func);
614 }
615
616 print_client("0x0\n");
617 indent--;
618 print_client("}\n");
619 indent--;
620 print_client("};\n");
621 print_client("\n");
622 }
623
624
625 static void print_message_buffer_size(func_t *func, unsigned int *type_offset)
626 {
627 unsigned int local_type_offset = *type_offset;
628 unsigned int alignment = 0;
629 int size = 0;
630 int last_size = -1;
631 int in_attr;
632 int out_attr;
633 int string_attr;
634 int nothing_printed = 1;
635 int ptr_attr, ref_attr, unique_attr;
636 int padding = 0, first_padding = 0;
637 void *sizeis_attr;
638 var_t *var;
639
640 print_client("_StubMsg.BufferLength =");
641 if (func->args)
642 {
643 var = func->args;
644 while (NEXT_LINK(var)) var = NEXT_LINK(var);
645 for (; var; var = PREV_LINK(var))
646 {
647 out_attr = is_attr(var->attrs, ATTR_OUT);
648 in_attr = is_attr(var->attrs, ATTR_IN);
649
650 /* set 'in' attribute if neither 'in' nor 'out' is found */
651 if (!out_attr && !in_attr)
652 in_attr = 1;
653
654 ptr_attr = is_attr(var->attrs, ATTR_PTR);
655 ref_attr = is_attr(var->attrs, ATTR_REF);
656 unique_attr = is_attr(var->attrs, ATTR_UNIQUE);
657
658 /* default to 'ref' attribute */
659 if (ptr_attr + ref_attr + unique_attr == 0)
660 ref_attr = 1;
661
662 if (!in_attr)
663 continue;
664
665 string_attr = is_attr(var->attrs, ATTR_STRING);
666 sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS);
667
668 if (var->ptr_level == 1)
669 {
670 if (string_attr && !sizeis_attr)
671 {
672 /* non-sized conformant string */
673 if (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR)
674 {
675 size = (unique_attr) ? 16 : 12;
676 alignment = 0;
677 }
678 }
679 else if (sizeis_attr && !string_attr)
680 {
681 /* conformant arrays */
682 size = 4;
683 alignment = 0;
684 if (padding != 0)
685 padding = 1;
686 }
687 else if (!sizeis_attr && !string_attr)
688 {
689 /* simple pointers */
690 if (is_base_type(var->type))
691 {
692 alignment = 0;
693 switch (var->type->type)
694 {
695 case RPC_FC_BYTE:
696 case RPC_FC_CHAR:
697 case RPC_FC_SMALL:
698 size = 1;
699 alignment = 0;
700 break;
701
702 case RPC_FC_WCHAR:
703 case RPC_FC_USHORT:
704 case RPC_FC_SHORT:
705 size = 2;
706 if (last_size > 0 && last_size < 2)
707 alignment += (2 - last_size);
708 break;
709
710 case RPC_FC_ULONG:
711 case RPC_FC_LONG:
712 case RPC_FC_FLOAT:
713 size = 4;
714 if (last_size > 0 && last_size < 4)
715 alignment += (4 - last_size);
716 break;
717
718 case RPC_FC_HYPER:
719 case RPC_FC_DOUBLE:
720 size = 8;
721 if (last_size > 0 && last_size < 4)
722 alignment += (4 - last_size);
723 break;
724
725 case RPC_FC_IGNORE:
726 size = 0;
727 break;
728
729 default:
730 error("%s:%d Unknown/unsupported type 0x%x\n",
731 __FUNCTION__,__LINE__, var->type->type);
732 return;
733 }
734
735 if (unique_attr)
736 size += 4;
737 }
738 else
739 {
740 /* simple pointer to a struct */
741 size = 8;
742 alignment = 0;
743 }
744 }
745 }
746 else
747 {
748 alignment = 0;
749 switch (var->type->type)
750 {
751 case RPC_FC_BYTE:
752 case RPC_FC_CHAR:
753 case RPC_FC_SMALL:
754 size = 1;
755 alignment = 0;
756 break;
757
758 case RPC_FC_WCHAR:
759 case RPC_FC_USHORT:
760 case RPC_FC_SHORT:
761 size = 2;
762 if (last_size > 0 && last_size < 2)
763 alignment += (2 - last_size);
764 break;
765
766 case RPC_FC_ULONG:
767 case RPC_FC_LONG:
768 case RPC_FC_FLOAT:
769 size = 4;
770 if (last_size > 0 && last_size < 4)
771 alignment += (4 - last_size);
772 break;
773
774 case RPC_FC_HYPER:
775 case RPC_FC_DOUBLE:
776 size = 8;
777 if (last_size > 0 && last_size < 4)
778 alignment += (4 - last_size);
779 break;
780
781 case RPC_FC_IGNORE:
782 size = 0;
783 break;
784
785 case RPC_FC_RP:
786 case RPC_FC_UP:
787 case RPC_FC_FP:
788 size = 0;
789 break;
790
791 default:
792 error("%s:%d Unknown/unsupported type 0x%x\n",
793 __FUNCTION__,__LINE__, var->type->type);
794 return;
795 }
796 }
797
798 if (last_size != -1)
799 fprintf(client, " +");
800 fprintf(client, " %dU", (size == 0) ? 0 : size + alignment + first_padding + padding);
801 nothing_printed = 0;
802 if (first_padding != 0)
803 first_padding = 0;
804
805 /* set paddings */
806 if (var->ptr_level == 1)
807 {
808 if (string_attr && !sizeis_attr)
809 {
810 /* non-sized conformant string */
811 if (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR)
812 {
813 first_padding = 3;
814 padding = 3;
815 }
816 }
817 else if (sizeis_attr && !string_attr)
818 {
819 /* conformant arrays */
820 first_padding = 4;
821 padding = 3;
822 }
823 }
824
825 last_size = size;
826 }
827 }
828
829 if (nothing_printed)
830 {
831 fprintf(client, " 0U");
832 }
833 fprintf(client, ";\n");
834
835 /* get string size */
836 if (func->args)
837 {
838 nothing_printed = 0;
839 var = func->args;
840 while (NEXT_LINK(var)) var = NEXT_LINK(var);
841 for (; var; var = PREV_LINK(var))
842 {
843 out_attr = is_attr(var->attrs, ATTR_OUT);
844 in_attr = is_attr(var->attrs, ATTR_IN);
845
846 /* default to 'in' attribute */
847 if (!out_attr && !in_attr)
848 in_attr = 1;
849
850 ptr_attr = is_attr(var->attrs, ATTR_PTR);
851 ref_attr = is_attr(var->attrs, ATTR_REF);
852 unique_attr = is_attr(var->attrs, ATTR_UNIQUE);
853
854 /* default to 'ref' attribute */
855 if (ptr_attr + ref_attr + unique_attr == 0)
856 ref_attr = 1;
857
858 string_attr = is_attr(var->attrs, ATTR_STRING);
859 sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS);
860
861 if (in_attr)
862 {
863 if (var->ptr_level == 0)
864 {
865 if (var->type->type == RPC_FC_RP &&
866 var->type->ref->ref->type == RPC_FC_STRUCT)
867 {
868 print_client("NdrSimpleStructBufferSize(\n");
869 indent++;
870 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
871 print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
872 print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
873 local_type_offset + 4);
874 nothing_printed = 1;
875 indent--;
876 }
877 }
878 else if (var->ptr_level == 1)
879 {
880 if (string_attr)
881 {
882 if ((var->type->type == RPC_FC_CHAR ||
883 var->type->type == RPC_FC_WCHAR))
884 {
885 if (ref_attr)
886 {
887 print_client("NdrConformantStringBufferSize(\n");
888 indent++;
889 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
890 print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
891 print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
892 local_type_offset + 2);
893 nothing_printed = 1;
894 indent--;
895 }
896 else if (unique_attr)
897 {
898 print_client("NdrPointerBufferSize(\n");
899 indent++;
900 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
901 print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
902 print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
903 local_type_offset);
904 nothing_printed = 1;
905 indent--;
906 }
907 else if (ptr_attr)
908 {
909 /* FIXME: not supported yet */
910 }
911 }
912 }
913 else
914 {
915 if (sizeis_attr)
916 {
917 fprintf(client, "\n");
918 print_client("_StubMsg.MaxCount = %s;\n",
919 ((var_t *)sizeis_attr)->name);
920 fprintf(client, "\n");
921
922 if (ref_attr)
923 {
924 print_client("NdrConformantArrayBufferSize(\n");
925 indent++;
926 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
927 print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
928 print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
929 local_type_offset + 4);
930 indent--;
931 nothing_printed = 1;
932 }
933 else if (unique_attr)
934 {
935 print_client("NdrPointerBufferSize(\n");
936 indent++;
937 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
938 print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
939 print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
940 local_type_offset);
941 nothing_printed = 1;
942 indent--;
943 }
944 else if (ptr_attr)
945 {
946 /* FIXME: not supported yet */
947 }
948 }
949 }
950 }
951 }
952
953 /* calculate the next type offset */
954 local_type_offset += get_var_type_offset(var);
955 }
956
957 if (nothing_printed)
958 fprintf(client, "\n");
959 }
960 }
961
962
963 static void marshall_in_arguments(func_t *func, unsigned int *type_offset)
964 {
965 unsigned int local_type_offset = *type_offset;
966 unsigned int alignment;
967 unsigned int size;
968 unsigned int last_size = 0;
969 int in_attr;
970 int out_attr;
971 int string_attr;
972 int ptr_attr, ref_attr, unique_attr;
973 void *sizeis_attr;
974 var_t *var;
975 int default_align = 0;
976
977 if (!func->args)
978 return;
979
980 var = func->args;
981 while (NEXT_LINK(var)) var = NEXT_LINK(var);
982 for (; var; var = PREV_LINK(var))
983 {
984 out_attr = is_attr(var->attrs, ATTR_OUT);
985 in_attr = is_attr(var->attrs, ATTR_IN);
986
987 /* set 'in' attribute if neither 'in' nor 'out' is set */
988 if (!out_attr && !in_attr)
989 in_attr = 1;
990
991 if (in_attr)
992 {
993 if (var->ptr_level > 1)
994 {
995 error("Function '%s' argument '%s': Pointer level %d not supported!\n",
996 func->def->name, var->name, var->ptr_level);
997 return;
998 }
999
1000 if (var->ptr_level == 1)
1001 {
1002 ptr_attr = is_attr(var->attrs, ATTR_PTR);
1003 ref_attr = is_attr(var->attrs, ATTR_REF);
1004 unique_attr = is_attr(var->attrs, ATTR_UNIQUE);
1005 if (ptr_attr + ref_attr + unique_attr == 0)
1006 ref_attr = 1;
1007
1008 string_attr = is_attr(var->attrs, ATTR_STRING);
1009 sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS);
1010
1011 if (ref_attr)
1012 {
1013 if (sizeis_attr)
1014 {
1015 print_client("_StubMsg.MaxCount = %s;\n",
1016 ((var_t *)sizeis_attr)->name);
1017 fprintf(client, "\n");
1018
1019 print_client("NdrConformantArrayMarshall(\n");
1020 indent++;
1021 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
1022 print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
1023 print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
1024 local_type_offset + 4);
1025 indent--;
1026 fprintf(client, "\n");
1027 default_align = 1;
1028 }
1029 else
1030 if (string_attr &&
1031 (var->type->type == RPC_FC_CHAR || var->type->type == RPC_FC_WCHAR))
1032 {
1033 print_client("NdrConformantStringMarshall(\n");
1034 indent++;
1035 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
1036 print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
1037 print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
1038 local_type_offset + 2);
1039 indent--;
1040 fprintf(client, "\n");
1041 default_align = 1;
1042 }
1043 else
1044 {
1045 alignment = 0;
1046 switch (var->type->type)
1047 {
1048 case RPC_FC_BYTE:
1049 case RPC_FC_CHAR:
1050 case RPC_FC_SMALL:
1051 size = 1;
1052 alignment = 0;
1053 break;
1054
1055 case RPC_FC_WCHAR:
1056 case RPC_FC_USHORT:
1057 case RPC_FC_SHORT:
1058 size = 2;
1059 if (last_size > 0 && last_size < 2)
1060 alignment = (2 - last_size);
1061 break;
1062
1063 case RPC_FC_ULONG:
1064 case RPC_FC_LONG:
1065 case RPC_FC_FLOAT:
1066 size = 4;
1067 if (last_size > 0 && last_size < 4)
1068 alignment = (4 - last_size);
1069 break;
1070
1071 case RPC_FC_HYPER:
1072 case RPC_FC_DOUBLE:
1073 size = 8;
1074 if (last_size > 0 && last_size < 4)
1075 alignment = (4 - last_size);
1076 break;
1077
1078 case RPC_FC_IGNORE:
1079 size = 0;
1080 break;
1081
1082 default:
1083 error("%s:%d Unknown/unsupported type 0x%x\n",
1084 __FUNCTION__,__LINE__, var->type->type);
1085 return;
1086 }
1087
1088 if (size != 0)
1089 {
1090 if (default_align)
1091 {
1092 print_client("_StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~0x3);\n");
1093 fprintf(client, "\n");
1094 default_align = 0;
1095 }
1096 else
1097 if (alignment != 0)
1098 print_client("_StubMsg.Buffer += %u;\n", alignment);
1099
1100 print_client("*((");
1101 write_type(client, var->type, NULL, var->tname);
1102 fprintf(client, " __RPC_FAR*)_StubMsg.Buffer) = ");
1103 if (var->ptr_level == 1)
1104 fprintf(client, "*");
1105 write_name(client, var);
1106 fprintf(client, ";\n");
1107 print_client("_StubMsg.Buffer += sizeof(");
1108 write_type(client, var->type, NULL, var->tname);
1109 fprintf(client, ");\n");
1110 fprintf(client, "\n");
1111
1112 last_size = size;
1113 }
1114 }
1115 }
1116 else if (unique_attr)
1117 {
1118 if (sizeis_attr)
1119 {
1120 print_client("_StubMsg.MaxCount = %s;\n",
1121 ((var_t *)sizeis_attr)->name);
1122 fprintf(client, "\n");
1123 }
1124
1125 print_client("NdrPointerMarshall(\n");
1126 indent++;
1127 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
1128 print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
1129 print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
1130 local_type_offset);
1131 indent--;
1132 fprintf(client, "\n");
1133 default_align = 1;
1134 }
1135 }
1136 else
1137 {
1138 if (is_base_type(var->type))
1139 {
1140 alignment = 0;
1141 switch (var->type->type)
1142 {
1143 case RPC_FC_BYTE:
1144 case RPC_FC_CHAR:
1145 case RPC_FC_SMALL:
1146 size = 1;
1147 alignment = 0;
1148 break;
1149
1150 case RPC_FC_WCHAR:
1151 case RPC_FC_USHORT:
1152 case RPC_FC_SHORT:
1153 size = 2;
1154 if (last_size > 0 && last_size < 2)
1155 alignment = (2 - last_size);
1156 break;
1157
1158 case RPC_FC_ULONG:
1159 case RPC_FC_LONG:
1160 case RPC_FC_FLOAT:
1161 size = 4;
1162 if (last_size > 0 && last_size < 4)
1163 alignment = (4 - last_size);
1164 break;
1165
1166 case RPC_FC_HYPER:
1167 case RPC_FC_DOUBLE:
1168 size = 8;
1169 if (last_size > 0 && last_size < 4)
1170 alignment = (4 - last_size);
1171 break;
1172
1173 case RPC_FC_IGNORE:
1174 size = 0;
1175 break;
1176
1177 default:
1178 error("%s:%d Unknown/unsupported type 0x%x\n",
1179 __FUNCTION__,__LINE__, var->type->type);
1180 return;
1181 }
1182
1183 if (size != 0)
1184 {
1185 if (default_align)
1186 {
1187 fprintf(client, "\n");
1188 print_client("_StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~0x3);\n");
1189 fprintf(client, "\n");
1190 default_align = 0;
1191 }
1192 else
1193 if (alignment != 0)
1194 print_client("_StubMsg.Buffer += %u;\n", alignment);
1195
1196 print_client("*((");
1197 write_type(client, var->type, NULL, var->tname);
1198 fprintf(client, " __RPC_FAR*)_StubMsg.Buffer) = ");
1199 if (var->ptr_level == 1)
1200 fprintf(client, "*");
1201 write_name(client, var);
1202 fprintf(client, ";\n");
1203 print_client("_StubMsg.Buffer += sizeof(");
1204 write_type(client, var->type, NULL, var->tname);
1205 fprintf(client, ");\n");
1206 fprintf(client, "\n");
1207
1208 last_size = size;
1209 }
1210 }
1211 else if (var->type->type == RPC_FC_RP)
1212 {
1213 if (var->type->ref->ref->type == RPC_FC_STRUCT)
1214 {
1215 print_client("NdrSimpleStructMarshall(\n");
1216 indent++;
1217 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
1218 print_client("(unsigned char __RPC_FAR *)%s,\n", var->name);
1219 print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u]);\n",
1220 local_type_offset + 4);
1221 indent--;
1222 fprintf(client, "\n");
1223 default_align = 1;
1224 }
1225 }
1226 }
1227 }
1228
1229 /* calculate the next type offset */
1230 local_type_offset += get_var_type_offset(var);
1231 }
1232 }
1233
1234
1235 static void unmarshall_out_arguments(func_t *func, unsigned int *type_offset)
1236 {
1237 unsigned int alignment;
1238 unsigned int size;
1239 unsigned int last_size = 0;
1240 int out_attr;
1241 int string_attr;
1242 int ptr_attr, ref_attr, unique_attr;
1243 void *sizeis_attr;
1244 var_t *var;
1245 var_t *def;
1246 unsigned int local_type_offset = *type_offset;
1247 int default_align = 0;
1248
1249 def = func->def;
1250
1251 /* unmarshall the out arguments */
1252 if (func->args)
1253 {
1254 var = func->args;
1255 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1256 for (; var; var = PREV_LINK(var))
1257 {
1258 out_attr = is_attr(var->attrs, ATTR_OUT);
1259 sizeis_attr = get_attrp(var->attrs, ATTR_SIZEIS);
1260 string_attr = is_attr(var->attrs, ATTR_STRING);
1261
1262 ptr_attr = is_attr(var->attrs, ATTR_PTR);
1263 ref_attr = is_attr(var->attrs, ATTR_REF);
1264 unique_attr = is_attr(var->attrs, ATTR_UNIQUE);
1265 if (ptr_attr + ref_attr + unique_attr == 0)
1266 ref_attr = 1;
1267
1268 if (out_attr)
1269 {
1270 if (var->ptr_level > 1)
1271 {
1272 error("Function '%s' argument '%s': Pointer level %d not supported!\n",
1273 func->def->name, var->name, var->ptr_level);
1274 return;
1275 }
1276
1277 if (sizeis_attr != NULL)
1278 {
1279 if (string_attr)
1280 {
1281 fprintf(client, "\n");
1282 print_client("NdrConformantStringUnmarshall(\n");
1283 indent++;
1284 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
1285 print_client("(unsigned char __RPC_FAR * __RPC_FAR *)&%s,\n", var->name);
1286 print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u],\n",
1287 local_type_offset + 4);
1288 print_client("(unsigned char)0);\n");
1289 indent--;
1290 fprintf(client, "\n");
1291 default_align = 1;
1292 }
1293 else
1294 {
1295 fprintf(client, "\n");
1296 print_client("NdrConformantArrayUnmarshall(\n");
1297 indent++;
1298 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
1299 print_client("(unsigned char __RPC_FAR * __RPC_FAR *)&%s,\n", var->name);
1300 print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u],\n",
1301 local_type_offset + 4);
1302 print_client("(unsigned char)0);\n");
1303 indent--;
1304 fprintf(client, "\n");
1305 default_align = 1;
1306 }
1307 }
1308 else if (is_base_type(var->type))
1309 {
1310 alignment = 0;
1311 switch (var->type->type)
1312 {
1313 case RPC_FC_BYTE:
1314 case RPC_FC_CHAR:
1315 case RPC_FC_SMALL:
1316 size = 1;
1317 alignment = 0;
1318 break;
1319
1320 case RPC_FC_WCHAR:
1321 case RPC_FC_USHORT:
1322 case RPC_FC_SHORT:
1323 size = 2;
1324 if (last_size > 0 && last_size < 2)
1325 alignment = (2 - last_size);
1326 break;
1327
1328 case RPC_FC_ULONG:
1329 case RPC_FC_LONG:
1330 case RPC_FC_FLOAT:
1331 size = 4;
1332 if (last_size > 0 && last_size < 4)
1333 alignment = (4 - last_size);
1334 break;
1335
1336 case RPC_FC_HYPER:
1337 case RPC_FC_DOUBLE:
1338 size = 8;
1339 if (last_size > 0 && last_size < 4)
1340 alignment = (4 - last_size);
1341 break;
1342
1343 case RPC_FC_IGNORE:
1344 size = 0;
1345 break;
1346
1347 default:
1348 error("%s:%d Unknown/unsupported type 0x%x\n",
1349 __FUNCTION__,__LINE__, var->type->type);
1350 return;
1351 }
1352
1353 if (size != 0)
1354 {
1355 if (var->ptr_level == 1)
1356 {
1357 if (unique_attr)
1358 {
1359 fprintf(client, "\n");
1360 print_client("NdrPointerUnmarshall(\n");
1361 indent++;
1362 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
1363 print_client("(unsigned char __RPC_FAR * __RPC_FAR *)&%s,\n", var->name);
1364 print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u],\n",
1365 local_type_offset);
1366 print_client("(unsigned char)0);\n");
1367 indent--;
1368 fprintf(client, "\n");
1369 default_align = 1;
1370 }
1371 else
1372 {
1373 fprintf(client, "\n");
1374 if (default_align)
1375 {
1376 print_client("_StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~0x3);\n");
1377 fprintf(client, "\n");
1378 default_align = 0;
1379 }
1380 else
1381 if (alignment != 0)
1382 print_client("_StubMsg.Buffer += %u;\n", alignment);
1383
1384
1385 print_client("*");
1386 write_name(client, var);
1387 fprintf(client, " = *((");
1388 write_type(client, var->type, NULL, var->tname);
1389 fprintf(client, " __RPC_FAR *)_StubMsg.Buffer);\n");
1390
1391 print_client("_StubMsg.Buffer += sizeof(");
1392 write_type(client, var->type, NULL, var->tname);
1393 fprintf(client, ");\n");
1394 }
1395 }
1396
1397 last_size = size;
1398 }
1399 }
1400 else if (var->type->type == RPC_FC_RP)
1401 {
1402 if (var->type->ref->ref->type == RPC_FC_STRUCT)
1403 {
1404 fprintf(client, "\n");
1405 print_client("NdrSimpleStructUnmarshall(\n");
1406 indent++;
1407 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
1408 print_client("(unsigned char __RPC_FAR * __RPC_FAR *)&%s,\n", var->name);
1409 print_client("(PFORMAT_STRING)&__MIDL_TypeFormatString.Format[%u],\n",
1410 local_type_offset + 4);
1411 print_client("(unsigned char)0);\n");
1412 indent--;
1413 fprintf(client, "\n");
1414 default_align = 1;
1415 }
1416 }
1417 else
1418 {
1419 error("%s:%d Unknown/unsupported type 0x%x\n",
1420 __FUNCTION__,__LINE__, var->type->type);
1421 return;
1422 }
1423 }
1424
1425 /* calculate the next type offset */
1426 local_type_offset += get_var_type_offset(var);
1427 }
1428 }
1429
1430 /* unmarshall return value */
1431 if (!is_void(def->type, NULL))
1432 {
1433 alignment = 0;
1434 switch (def->type->type)
1435 {
1436 case RPC_FC_BYTE:
1437 case RPC_FC_CHAR:
1438 case RPC_FC_SMALL:
1439 case RPC_FC_WCHAR:
1440 case RPC_FC_USHORT:
1441 case RPC_FC_SHORT:
1442 case RPC_FC_ULONG:
1443 case RPC_FC_LONG:
1444 case RPC_FC_FLOAT:
1445 size = 4;
1446 if (last_size > 0 && last_size < 4)
1447 alignment = (4 - last_size);
1448 break;
1449
1450 case RPC_FC_HYPER:
1451 case RPC_FC_DOUBLE:
1452 size = 8;
1453 if (last_size > 0 && last_size < 4)
1454 alignment = (4 - last_size);
1455 break;
1456
1457 default:
1458 error("%s:%d Unknown/unsupported type 0x%x\n",
1459 __FUNCTION__,__LINE__, def->type->type);
1460 return;
1461 }
1462
1463 fprintf(client, "\n");
1464 if (default_align)
1465 {
1466 print_client("_StubMsg.Buffer = (unsigned char __RPC_FAR *)(((long)_StubMsg.Buffer + 3) & ~0x3);\n");
1467 fprintf(client, "\n");
1468 default_align = 0;
1469 }
1470 else
1471 if (alignment != 0)
1472 print_client("_StubMsg.Buffer += %u;\n", alignment);
1473 print_client("_RetVal = *((");
1474 write_type(client, def->type, def, def->tname);
1475 fprintf(client, " __RPC_FAR *)_StubMsg.Buffer);\n");
1476
1477 print_client("_StubMsg.Buffer += sizeof(");
1478 write_type(client, def->type, def, def->tname);
1479 fprintf(client, ");\n");
1480 }
1481 }
1482
1483
1484 static void check_pointers(func_t *func)
1485 {
1486 var_t *var;
1487 int ptr_attr;
1488 int ref_attr;
1489 int unique_attr;
1490
1491 if (!func->args)
1492 return;
1493
1494 var = func->args;
1495 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1496 while (var)
1497 {
1498 ptr_attr = is_attr(var->attrs, ATTR_PTR);
1499 ref_attr = is_attr(var->attrs, ATTR_REF);
1500 unique_attr = is_attr(var->attrs, ATTR_UNIQUE);
1501
1502 if (var->ptr_level == 0)
1503 {
1504 if (ptr_attr + ref_attr + unique_attr != 0)
1505 {
1506 error("The attributes [ptr], [ref] and [unique] can only be used for pointers!\n");
1507 return;
1508 }
1509 }
1510 else
1511 {
1512 /* default to 'ref' attribute */
1513 if (ptr_attr + ref_attr + unique_attr == 0)
1514 {
1515 ref_attr = 1;
1516 }
1517
1518 if (ptr_attr + ref_attr + unique_attr > 1)
1519 {
1520 error("The attributes [ptr], [ref] and [unique] are mutually exclusive!\n");
1521 return;
1522 }
1523
1524 if (var->ptr_level == 1)
1525 {
1526 if (ref_attr)
1527 {
1528 print_client("if (!%s)\n", var->name);
1529 print_client("{\n");
1530 indent++;
1531 print_client("RpcRaiseException(RPC_X_NULL_REF_POINTER);\n");
1532 indent--;
1533 print_client("}\n");
1534 fprintf(client, "\n");
1535 }
1536 }
1537 else if (var->ptr_level > 1)
1538 {
1539 error("Pointer level %d not supported!\n", var->ptr_level);
1540 return;
1541 }
1542 }
1543
1544 var = PREV_LINK(var);
1545 }
1546 }
1547
1548
1549 static int use_return_buffer(func_t *func)
1550 {
1551 var_t *var;
1552
1553 if (!is_void(func->def->type, NULL))
1554 return 1;
1555
1556 if (!func->args)
1557 return 0;
1558
1559 var = func->args;
1560 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1561 while (var)
1562 {
1563 if (is_attr(var->attrs, ATTR_OUT))
1564 return 1;
1565
1566 var = PREV_LINK(var);
1567 }
1568
1569 return 0;
1570 }
1571
1572
1573 static void write_function_stubs(type_t *iface)
1574 {
1575 char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
1576 int explicit_handle = is_attr(iface->attrs, ATTR_EXPLICIT_HANDLE);
1577 func_t *func = iface->funcs;
1578 var_t* var;
1579 var_t* explicit_handle_var;
1580 int method_count = 0;
1581 unsigned int proc_offset = 0;
1582 unsigned int type_offset = 2;
1583
1584 while (NEXT_LINK(func)) func = NEXT_LINK(func);
1585 while (func)
1586 {
1587 var_t *def = func->def;
1588
1589 /* check for a defined binding handle */
1590 explicit_handle_var = get_explicit_handle_var(func);
1591 if (explicit_handle)
1592 {
1593 if (!explicit_handle_var)
1594 {
1595 error("%s() does not define an explicit binding handle!\n", def->name);
1596 return;
1597 }
1598 }
1599 else
1600 {
1601 if (explicit_handle_var)
1602 {
1603 error("%s() must not define a binding handle!\n", def->name);
1604 return;
1605 }
1606 }
1607
1608 write_type(client, def->type, def, def->tname);
1609 fprintf(client, " ");
1610 write_name(client, def);
1611 fprintf(client, "(\n");
1612 indent++;
1613 write_args(client, func->args, iface->name, 0, TRUE);
1614 fprintf(client, ")\n");
1615 indent--;
1616
1617 /* write the functions body */
1618 fprintf(client, "{\n");
1619 indent++;
1620
1621 /* declare return value '_RetVal' */
1622 if (!is_void(def->type, NULL))
1623 {
1624 print_client("");
1625 write_type(client, def->type, def, def->tname);
1626 fprintf(client, " _RetVal;\n");
1627 }
1628
1629 if (implicit_handle || explicit_handle)
1630 print_client("RPC_BINDING_HANDLE _Handle = 0;\n");
1631 print_client("RPC_MESSAGE _RpcMessage;\n");
1632 print_client("MIDL_STUB_MESSAGE _StubMsg;\n");
1633 fprintf(client, "\n");
1634
1635 /* check pointers */
1636 check_pointers(func);
1637
1638 print_client("RpcTryFinally\n");
1639 print_client("{\n");
1640 indent++;
1641
1642 print_client("NdrClientInitializeNew(\n");
1643 indent++;
1644 print_client("(PRPC_MESSAGE)&_RpcMessage,\n");
1645 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
1646 print_client("(PMIDL_STUB_DESC)&%s_StubDesc,\n", iface->name);
1647 print_client("%d);\n", method_count);
1648 indent--;
1649 fprintf(client, "\n");
1650
1651 if (implicit_handle)
1652 {
1653 print_client("_Handle = %s;\n", implicit_handle);
1654 fprintf(client, "\n");
1655 }
1656 else if (explicit_handle)
1657 {
1658 print_client("_Handle = %s;\n", explicit_handle_var->name);
1659 fprintf(client, "\n");
1660 }
1661
1662 /* emit the message buffer size */
1663 print_message_buffer_size(func, &type_offset);
1664
1665 print_client("NdrGetBuffer(\n");
1666 indent++;
1667 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
1668 print_client("_StubMsg.BufferLength,\n");
1669 if (implicit_handle || explicit_handle)
1670 print_client("_Handle);\n");
1671 else
1672 print_client("%s__MIDL_AutoBindHandle);\n", iface->name);
1673 indent--;
1674 fprintf(client, "\n");
1675
1676 /* marshal in arguments */
1677 marshall_in_arguments(func, &type_offset);
1678
1679 /* send/recieve message */
1680 print_client("NdrSendReceive(\n");
1681 indent++;
1682 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
1683 print_client("(unsigned char __RPC_FAR *)_StubMsg.Buffer);\n");
1684 indent--;
1685
1686 if (use_return_buffer(func))
1687 {
1688 /* convert data representation */
1689 fprintf(client, "\n");
1690 print_client("if ((_RpcMessage.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)\n");
1691 indent++;
1692 print_client("NdrConvert(\n");
1693 indent++;
1694 print_client("(PMIDL_STUB_MESSAGE)&_StubMsg,\n");
1695 print_client("(PFORMAT_STRING)&__MIDL_ProcFormatString.Format[%u]);\n", proc_offset);
1696 indent -= 2;
1697
1698 /* unmarshal out arguments */
1699 unmarshall_out_arguments(func, &type_offset);
1700 }
1701
1702 /* update type_offset */
1703 if (func->args)
1704 {
1705 var = func->args;
1706 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1707 while (var)
1708 {
1709 type_offset += get_var_type_offset(var);
1710
1711 var = PREV_LINK(var);
1712 }
1713 }
1714
1715 /* update proc_offset */
1716 if (func->args)
1717 {
1718 var = func->args;
1719 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1720 while (var)
1721 {
1722 switch (var->ptr_level)
1723 {
1724 case 0:
1725 if (is_base_type(var->type))
1726 proc_offset += 2;
1727 break;
1728
1729 case 1:
1730 if (is_base_type(var->type))
1731 proc_offset += 4;
1732 break;
1733 }
1734
1735 var = PREV_LINK(var);
1736 }
1737 }
1738 proc_offset += 2; /* FIXME */
1739
1740 indent--;
1741 print_client("}\n");
1742 print_client("RpcFinally\n");
1743 print_client("{\n");
1744 indent++;
1745
1746
1747 /* FIXME: emit client finally code */
1748
1749 print_client("NdrFreeBuffer((PMIDL_STUB_MESSAGE)&_StubMsg);\n");
1750
1751 indent--;
1752 print_client("}\n");
1753 print_client("RpcEndFinally\n");
1754
1755
1756 /* emit return code */
1757 if (!is_void(def->type, NULL))
1758 {
1759 fprintf(client, "\n");
1760 print_client("return _RetVal;\n");
1761 }
1762
1763 indent--;
1764 fprintf(client, "}\n");
1765 fprintf(client, "\n");
1766
1767 method_count++;
1768 func = PREV_LINK(func);
1769 }
1770 }
1771
1772
1773 static void write_bindinghandledecl(type_t *iface)
1774 {
1775 if (!get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE))
1776 {
1777 print_client("static RPC_BINDING_HANDLE %s__MIDL_AutoBindHandle;\n", iface->name);
1778 fprintf(client, "\n");
1779 }
1780 }
1781
1782
1783 static void write_stubdescdecl(type_t *iface)
1784 {
1785 print_client("extern const MIDL_STUB_DESC %s_StubDesc;\n", iface->name);
1786 fprintf(client, "\n");
1787 }
1788
1789
1790 static void write_stubdescriptor(type_t *iface)
1791 {
1792 char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
1793
1794 print_client("const MIDL_STUB_DESC %s_StubDesc =\n", iface->name);
1795 print_client("{\n");
1796 indent++;
1797 print_client("(void __RPC_FAR *)& %s___RpcClientInterface,\n", iface->name);
1798 print_client("MIDL_user_allocate,\n");
1799 print_client("MIDL_user_free,\n");
1800 if (implicit_handle)
1801 print_client("{&%s},\n", implicit_handle);
1802 else
1803 print_client("{&%s__MIDL_AutoBindHandle},\n", iface->name);
1804 print_client("0,\n");
1805 print_client("0,\n");
1806 print_client("0,\n");
1807 print_client("0,\n");
1808 print_client("__MIDL_TypeFormatString.Format,\n");
1809 print_client("1, /* -error bounds_check flag */\n");
1810 print_client("0x10001, /* Ndr library version */\n");
1811 print_client("0,\n");
1812 print_client("0x50100a4, /* MIDL Version 5.1.164 */\n");
1813 print_client("0,\n");
1814 print_client("0,\n");
1815 print_client("0, /* notify & notify_flag routine table */\n");
1816 print_client("1, /* Flags */\n");
1817 print_client("0, /* Reserved3 */\n");
1818 print_client("0, /* Reserved4 */\n");
1819 print_client("0 /* Reserved5 */\n");
1820 indent--;
1821 print_client("};\n");
1822 fprintf(client, "\n");
1823 }
1824
1825
1826 static void write_clientinterfacedecl(type_t *iface)
1827 {
1828 unsigned long ver = get_attrv(iface->attrs, ATTR_VERSION);
1829 UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
1830
1831 print_client("static const RPC_CLIENT_INTERFACE %s___RpcClientInterface =\n", iface->name );
1832 print_client("{\n");
1833 indent++;
1834 print_client("sizeof(RPC_CLIENT_INTERFACE),\n");
1835 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",
1836 uuid->Data1, uuid->Data2, uuid->Data3, uuid->Data4[0], uuid->Data4[1],
1837 uuid->Data4[2], uuid->Data4[3], uuid->Data4[4], uuid->Data4[5], uuid->Data4[6],
1838 uuid->Data4[7], LOWORD(ver), HIWORD(ver));
1839 print_client("{{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}},\n"); /* FIXME */
1840 print_client("0,\n");
1841 print_client("0,\n");
1842 print_client("0,\n");
1843 print_client("0,\n");
1844 print_client("0,\n");
1845 print_client("0,\n");
1846 indent--;
1847 print_client("};\n");
1848 if (old_names)
1849 print_client("RPC_IF_HANDLE %s_ClientIfHandle = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n",
1850 iface->name, iface->name);
1851 else
1852 print_client("RPC_IF_HANDLE %s_v%d_%d_c_ifspec = (RPC_IF_HANDLE)& %s___RpcClientInterface;\n",
1853 iface->name, LOWORD(ver), HIWORD(ver), iface->name);
1854 fprintf(client, "\n");
1855 }
1856
1857
1858 static void write_formatdesc( const char *str )
1859 {
1860 print_client("typedef struct _MIDL_%s_FORMAT_STRING\n", str );
1861 print_client("{\n");
1862 indent++;
1863 print_client("short Pad;\n");
1864 print_client("unsigned char Format[%s_FORMAT_STRING_SIZE];\n", str);
1865 indent--;
1866 print_client("} MIDL_%s_FORMAT_STRING;\n", str);
1867 print_client("\n");
1868 }
1869
1870
1871 static int get_type_format_string_size(type_t *iface)
1872 {
1873 int size = 3;
1874 func_t *func;
1875 var_t *var;
1876
1877 /* determine the type format string size */
1878 func = iface->funcs;
1879 while (NEXT_LINK(func)) func = NEXT_LINK(func);
1880 while (func)
1881 {
1882 /* argument list size */
1883 if (func->args)
1884 {
1885 var = func->args;
1886 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1887 while (var)
1888 {
1889 size += get_var_type_offset(var);
1890 var = PREV_LINK(var);
1891 }
1892 }
1893
1894 func = PREV_LINK(func);
1895 }
1896
1897 return size;
1898 }
1899
1900
1901 static int get_proc_format_string_size(type_t *iface)
1902 {
1903 int size = 1;
1904 func_t *func;
1905 var_t *var;
1906
1907 /* determine the proc format string size */
1908 func = iface->funcs;
1909 while (NEXT_LINK(func)) func = NEXT_LINK(func);
1910 while (func)
1911 {
1912 /* argument list size */
1913 if (func->args)
1914 {
1915 var = func->args;
1916 while (NEXT_LINK(var)) var = NEXT_LINK(var);
1917 while (var)
1918 {
1919 switch (var->ptr_level)
1920 {
1921 case 0:
1922 if (is_base_type(var->type))
1923 size += 2;
1924 else if (var->type->type == RPC_FC_RP)
1925 size += 4;
1926 break;
1927
1928 case 1:
1929 if (is_base_type(var->type))
1930 size += 4;
1931 break;
1932 }
1933
1934 var = PREV_LINK(var);
1935 }
1936 }
1937
1938 /* return value size */
1939 size += 2;
1940 func = PREV_LINK(func);
1941 }
1942
1943 return size;
1944 }
1945
1946
1947 static void write_formatstringsdecl(type_t *iface)
1948 {
1949 print_client("#define TYPE_FORMAT_STRING_SIZE %d\n",
1950 get_type_format_string_size(iface));
1951
1952 print_client("#define PROC_FORMAT_STRING_SIZE %d\n",
1953 get_proc_format_string_size(iface));
1954
1955 fprintf(client, "\n");
1956 write_formatdesc("TYPE");
1957 write_formatdesc("PROC");
1958 fprintf(client, "\n");
1959 print_client("extern const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString;\n");
1960 print_client("extern const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString;\n");
1961 print_client("\n");
1962 }
1963
1964
1965 static void write_implicithandledecl(type_t *iface)
1966 {
1967 char *implicit_handle = get_attrp(iface->attrs, ATTR_IMPLICIT_HANDLE);
1968
1969 if (implicit_handle)
1970 {
1971 fprintf(client, "handle_t %s;\n", implicit_handle);
1972 fprintf(client, "\n");
1973 }
1974 }
1975
1976
1977 static void init_client(void)
1978 {
1979 if (client) return;
1980 if (!(client = fopen(client_name, "w")))
1981 error("Could not open %s for output\n", client_name);
1982
1983 print_client("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", WIDL_FULLVERSION, input_name);
1984 print_client("#include <string.h>\n");
1985 print_client("#ifdef _ALPHA_\n");
1986 print_client("#include <stdarg.h>\n");
1987 print_client("#endif\n");
1988 fprintf(client, "\n");
1989 print_client("#include \"%s\"\n", header_name);
1990 fprintf(client, "\n");
1991 }
1992
1993
1994 void write_client(ifref_t *ifaces)
1995 {
1996 ifref_t *iface = ifaces;
1997
1998 if (!do_client)
1999 return;
2000 if (!iface)
2001 return;
2002 END_OF_LIST(iface);
2003
2004 init_client();
2005 if (!client)
2006 return;
2007
2008 while (iface)
2009 {
2010 fprintf(client, "/*****************************************************************************\n");
2011 fprintf(client, " * %s interface\n", iface->iface->name);
2012 fprintf(client, " */\n");
2013 fprintf(client, "\n");
2014
2015 write_formatstringsdecl(iface->iface);
2016 write_implicithandledecl(iface->iface);
2017
2018 write_clientinterfacedecl(iface->iface);
2019 write_stubdescdecl(iface->iface);
2020 write_bindinghandledecl(iface->iface);
2021
2022 write_function_stubs(iface->iface);
2023 write_stubdescriptor(iface->iface);
2024
2025 print_client("#if !defined(__RPC_WIN32__)\n");
2026 print_client("#error Invalid build platform for this stub.\n");
2027 print_client("#endif\n");
2028 fprintf(client, "\n");
2029
2030 write_procformatstring(iface->iface);
2031 write_typeformatstring(iface->iface);
2032
2033 fprintf(client, "\n");
2034
2035 iface = PREV_LINK(iface);
2036 }
2037
2038 fclose(client);
2039 }