2 * Type library proxy/stub implementation
4 * Copyright 2018 Zebediah Figura
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.
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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define USE_STUBLESS_PROXY
28 #include "wine/debug.h"
32 #include "ndr_types.h"
33 #include "ndr_stubless.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
37 static size_t write_type_tfs(ITypeInfo
*typeinfo
, unsigned char *str
,
38 size_t *len
, TYPEDESC
*desc
, BOOL toplevel
, BOOL onstack
);
40 #define WRITE_CHAR(str, len, val) \
41 do { if ((str)) (str)[(len)] = (val); (len)++; } while (0)
42 #define WRITE_SHORT(str, len, val) \
43 do { if ((str)) *((short *)((str) + (len))) = (val); (len) += 2; } while (0)
44 #define WRITE_INT(str, len, val) \
45 do { if ((str)) *((int *)((str) + (len))) = (val); (len) += 4; } while (0)
47 extern const ExtendedProxyFileInfo ndr_types_ProxyFileInfo
;
49 static const MIDL_STUBLESS_PROXY_INFO
*get_ndr_types_proxy_info(void)
51 return ndr_types_ProxyFileInfo
.pProxyVtblList
[0]->header
.pStublessProxyInfo
;
54 static const NDR_PARAM_OIF
*get_ndr_types_params( unsigned int *nb_params
)
56 const MIDL_STUBLESS_PROXY_INFO
*proxy
= get_ndr_types_proxy_info();
57 const unsigned char *format
= proxy
->ProcFormatString
+ proxy
->FormatStringOffset
[3];
58 const NDR_PROC_HEADER
*proc
= (const NDR_PROC_HEADER
*)format
;
59 const NDR_PROC_PARTIAL_OIF_HEADER
*header
;
61 if (proc
->Oi_flags
& Oi_HAS_RPCFLAGS
)
62 format
+= sizeof(NDR_PROC_HEADER_RPC
);
64 format
+= sizeof(NDR_PROC_HEADER
);
66 header
= (const NDR_PROC_PARTIAL_OIF_HEADER
*)format
;
67 format
+= sizeof(*header
);
68 if (header
->Oi2Flags
.HasExtensions
)
70 const NDR_PROC_HEADER_EXTS
*ext
= (const NDR_PROC_HEADER_EXTS
*)format
;
73 *nb_params
= header
->number_of_params
;
74 return (const NDR_PARAM_OIF
*)format
;
77 static unsigned short get_tfs_offset( int param
)
79 unsigned int nb_params
;
80 const NDR_PARAM_OIF
*params
= get_ndr_types_params( &nb_params
);
82 assert( param
< nb_params
);
83 return params
[param
].u
.type_offset
;
86 static const unsigned char *get_type_format_string( size_t *size
)
88 unsigned int nb_params
;
89 const NDR_PARAM_OIF
*params
= get_ndr_types_params( &nb_params
);
91 *size
= params
[nb_params
- 1].u
.type_offset
;
92 return get_ndr_types_proxy_info()->pStubDesc
->pFormatTypes
;
95 static unsigned short write_oleaut_tfs(VARTYPE vt
)
99 case VT_BSTR
: return get_tfs_offset( 0 );
100 case VT_UNKNOWN
: return get_tfs_offset( 1 );
101 case VT_DISPATCH
: return get_tfs_offset( 2 );
102 case VT_VARIANT
: return get_tfs_offset( 3 );
103 case VT_SAFEARRAY
: return get_tfs_offset( 4 );
108 static unsigned char get_basetype(ITypeInfo
*typeinfo
, TYPEDESC
*desc
)
116 case VT_I1
: return FC_SMALL
;
118 case VT_I2
: return FC_SHORT
;
122 case VT_I4
: return FC_LONG
;
124 case VT_UI8
: return FC_HYPER
;
125 case VT_UI1
: return FC_USMALL
;
126 case VT_UI2
: return FC_USHORT
;
128 case VT_UI4
: return FC_ULONG
;
129 case VT_R4
: return FC_FLOAT
;
131 case VT_R8
: return FC_DOUBLE
;
133 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
134 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
135 if (attr
->typekind
== TKIND_ENUM
)
137 else if (attr
->typekind
== TKIND_ALIAS
)
138 ret
= get_basetype(refinfo
, &attr
->tdescAlias
);
141 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
142 ITypeInfo_Release(refinfo
);
148 static unsigned int type_memsize(ITypeInfo
*typeinfo
, TYPEDESC
*desc
)
177 return sizeof(void *);
179 return sizeof(VARIANT
);
182 unsigned int size
= type_memsize(typeinfo
, &desc
->lpadesc
->tdescElem
);
184 for (i
= 0; i
< desc
->lpadesc
->cDims
; i
++)
185 size
*= desc
->lpadesc
->rgbounds
[i
].cElements
;
190 unsigned int size
= 0;
194 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
195 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
196 size
= attr
->cbSizeInstance
;
197 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
198 ITypeInfo_Release(refinfo
);
202 FIXME("unhandled type %u\n", desc
->vt
);
207 static BOOL
type_pointer_is_iface(ITypeInfo
*typeinfo
, TYPEDESC
*tdesc
)
213 if (tdesc
->vt
== VT_USERDEFINED
)
215 ITypeInfo_GetRefTypeInfo(typeinfo
, tdesc
->hreftype
, &refinfo
);
216 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
218 if (attr
->typekind
== TKIND_INTERFACE
219 || attr
->typekind
== TKIND_DISPATCH
220 || attr
->typekind
== TKIND_COCLASS
)
222 else if (attr
->typekind
== TKIND_ALIAS
)
223 ret
= type_pointer_is_iface(refinfo
, &attr
->tdescAlias
);
225 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
226 ITypeInfo_Release(refinfo
);
232 static unsigned char get_array_fc(ITypeInfo
*typeinfo
, TYPEDESC
*desc
);
233 static unsigned char get_struct_fc(ITypeInfo
*typeinfo
, TYPEATTR
*attr
);
235 static unsigned char get_struct_member_fc(ITypeInfo
*typeinfo
, TYPEDESC
*tdesc
)
245 return (sizeof(void *) == 4) ? FC_PSTRUCT
: FC_BOGUS_STRUCT
;
251 return FC_BOGUS_STRUCT
;
253 if (get_array_fc(typeinfo
, &tdesc
->lpadesc
->tdescElem
) == FC_BOGUS_ARRAY
)
254 return FC_BOGUS_STRUCT
;
257 if (type_pointer_is_iface(typeinfo
, tdesc
))
258 fc
= FC_BOGUS_STRUCT
;
260 fc
= (sizeof(void *) == 4) ? FC_PSTRUCT
: FC_BOGUS_STRUCT
;
263 ITypeInfo_GetRefTypeInfo(typeinfo
, tdesc
->hreftype
, &refinfo
);
264 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
266 switch (attr
->typekind
)
272 fc
= get_struct_fc(refinfo
, attr
);
274 case TKIND_INTERFACE
:
277 fc
= FC_BOGUS_STRUCT
;
280 fc
= get_struct_member_fc(refinfo
, &attr
->tdescAlias
);
283 FIXME("Unhandled kind %#x.\n", attr
->typekind
);
284 fc
= FC_BOGUS_STRUCT
;
288 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
289 ITypeInfo_Release(refinfo
);
292 if (get_basetype(typeinfo
, tdesc
))
296 FIXME("Unhandled type %u.\n", tdesc
->vt
);
297 return FC_BOGUS_STRUCT
;
304 static unsigned char get_struct_fc(ITypeInfo
*typeinfo
, TYPEATTR
*attr
)
306 unsigned char fc
= FC_STRUCT
, member_fc
;
310 for (i
= 0; i
< attr
->cVars
; i
++)
312 ITypeInfo_GetVarDesc(typeinfo
, i
, &desc
);
314 member_fc
= get_struct_member_fc(typeinfo
, &desc
->elemdescVar
.tdesc
);
315 if (member_fc
== FC_BOGUS_STRUCT
)
316 fc
= FC_BOGUS_STRUCT
;
317 else if (member_fc
== FC_PSTRUCT
&& fc
!= FC_BOGUS_STRUCT
)
320 ITypeInfo_ReleaseVarDesc(typeinfo
, desc
);
326 static unsigned char get_array_fc(ITypeInfo
*typeinfo
, TYPEDESC
*desc
)
333 return get_array_fc(typeinfo
, &desc
->lpadesc
->tdescElem
);
340 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
341 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
343 if (attr
->typekind
== TKIND_ENUM
)
345 else if (attr
->typekind
== TKIND_RECORD
&& get_struct_fc(refinfo
, attr
) == FC_STRUCT
)
347 else if (attr
->typekind
== TKIND_ALIAS
)
348 fc
= get_array_fc(refinfo
, &attr
->tdescAlias
);
352 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
353 ITypeInfo_Release(refinfo
);
358 return get_basetype(typeinfo
, desc
) ? FC_LGFARRAY
: FC_BOGUS_ARRAY
;
362 static BOOL
type_is_non_iface_pointer(ITypeInfo
*typeinfo
, TYPEDESC
*desc
)
364 if (desc
->vt
== VT_PTR
)
365 return !type_pointer_is_iface(typeinfo
, desc
->lptdesc
);
366 else if (desc
->vt
== VT_USERDEFINED
)
372 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
373 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
375 if (attr
->typekind
== TKIND_ALIAS
)
376 ret
= type_is_non_iface_pointer(refinfo
, &attr
->tdescAlias
);
380 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
381 ITypeInfo_Release(refinfo
);
389 static void write_struct_members(ITypeInfo
*typeinfo
, unsigned char *str
,
390 size_t *len
, TYPEATTR
*attr
)
392 unsigned int struct_offset
= 0;
393 unsigned char basetype
;
398 for (i
= 0; i
< attr
->cVars
; i
++)
400 ITypeInfo_GetVarDesc(typeinfo
, i
, &desc
);
401 tdesc
= &desc
->elemdescVar
.tdesc
;
403 /* This may not match the intended alignment, but we don't have enough
404 * information to determine that. This should always give the correct
406 if ((struct_offset
& 7) && !(desc
->oInst
& 7))
407 WRITE_CHAR(str
, *len
, FC_ALIGNM8
);
408 else if ((struct_offset
& 3) && !(desc
->oInst
& 3))
409 WRITE_CHAR(str
, *len
, FC_ALIGNM4
);
410 else if ((struct_offset
& 1) && !(desc
->oInst
& 1))
411 WRITE_CHAR(str
, *len
, FC_ALIGNM2
);
412 struct_offset
= desc
->oInst
+ type_memsize(typeinfo
, tdesc
);
414 if ((basetype
= get_basetype(typeinfo
, tdesc
)))
415 WRITE_CHAR(str
, *len
, basetype
);
416 else if (type_is_non_iface_pointer(typeinfo
, tdesc
))
417 WRITE_CHAR(str
, *len
, FC_POINTER
);
420 WRITE_CHAR(str
, *len
, FC_EMBEDDED_COMPLEX
);
421 WRITE_CHAR(str
, *len
, 0);
422 WRITE_SHORT(str
, *len
, 0);
425 ITypeInfo_ReleaseVarDesc(typeinfo
, desc
);
428 WRITE_CHAR (str
, *len
, FC_PAD
);
429 WRITE_CHAR (str
, *len
, FC_END
);
432 static void write_simple_struct_tfs(ITypeInfo
*typeinfo
, unsigned char *str
,
433 size_t *len
, TYPEATTR
*attr
)
435 write_struct_members(typeinfo
, str
, len
, attr
);
438 static BOOL
type_needs_pointer_deref(ITypeInfo
*typeinfo
, TYPEDESC
*desc
)
440 if (desc
->vt
== VT_PTR
|| desc
->vt
== VT_UNKNOWN
|| desc
->vt
== VT_DISPATCH
)
442 else if (desc
->vt
== VT_USERDEFINED
)
448 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
449 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
451 if (attr
->typekind
== TKIND_ALIAS
)
452 ret
= type_needs_pointer_deref(refinfo
, &attr
->tdescAlias
);
454 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
455 ITypeInfo_Release(refinfo
);
463 static void write_complex_struct_pointer_layout(ITypeInfo
*typeinfo
,
464 TYPEDESC
*desc
, unsigned char *str
, size_t *len
)
466 unsigned char basetype
;
468 if (desc
->vt
== VT_PTR
&& !type_pointer_is_iface(typeinfo
, desc
->lptdesc
))
470 WRITE_CHAR(str
, *len
, FC_UP
);
471 if ((basetype
= get_basetype(typeinfo
, desc
->lptdesc
)))
473 WRITE_CHAR(str
, *len
, FC_SIMPLE_POINTER
);
474 WRITE_CHAR(str
, *len
, basetype
);
475 WRITE_CHAR(str
, *len
, FC_PAD
);
479 if (type_needs_pointer_deref(typeinfo
, desc
->lptdesc
))
480 WRITE_CHAR(str
, *len
, FC_POINTER_DEREF
);
482 WRITE_CHAR(str
, *len
, 0);
483 WRITE_SHORT(str
, *len
, 0);
486 else if (desc
->vt
== VT_USERDEFINED
)
491 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
492 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
494 if (attr
->typekind
== TKIND_ALIAS
)
495 write_complex_struct_pointer_layout(refinfo
, &attr
->tdescAlias
, str
, len
);
497 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
498 ITypeInfo_Release(refinfo
);
502 static size_t write_complex_struct_pointer_ref(ITypeInfo
*typeinfo
,
503 TYPEDESC
*desc
, unsigned char *str
, size_t *len
)
505 if (desc
->vt
== VT_PTR
&& !type_pointer_is_iface(typeinfo
, desc
->lptdesc
)
506 && !get_basetype(typeinfo
, desc
->lptdesc
))
508 return write_type_tfs(typeinfo
, str
, len
, desc
->lptdesc
, FALSE
, FALSE
);
510 else if (desc
->vt
== VT_USERDEFINED
)
516 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
517 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
519 if (attr
->typekind
== TKIND_ALIAS
)
520 ret
= write_complex_struct_pointer_ref(refinfo
, &attr
->tdescAlias
, str
, len
);
522 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
523 ITypeInfo_Release(refinfo
);
531 static void write_complex_struct_tfs(ITypeInfo
*typeinfo
, unsigned char *str
,
532 size_t *len
, TYPEATTR
*attr
)
534 size_t pointer_layout_offset
, pointer_layout
, member_layout
, ref
;
535 unsigned int struct_offset
= 0;
540 WRITE_SHORT(str
, *len
, 0); /* conformant array description */
541 pointer_layout_offset
= *len
;
542 WRITE_SHORT(str
, *len
, 0); /* pointer layout; will be filled in later */
543 member_layout
= *len
;
545 /* First pass: write the struct members and pointer layout, but do not yet
546 * write the offsets for embedded complexes and pointer refs. These must be
547 * handled after we write the whole struct description, since it must be
550 write_struct_members(typeinfo
, str
, len
, attr
);
552 pointer_layout
= *len
;
553 if (str
) *((short *)(str
+ pointer_layout_offset
)) = pointer_layout
- pointer_layout_offset
;
555 for (i
= 0; i
< attr
->cVars
; i
++)
557 ITypeInfo_GetVarDesc(typeinfo
, i
, &desc
);
558 write_complex_struct_pointer_layout(typeinfo
, &desc
->elemdescVar
.tdesc
, str
, len
);
559 ITypeInfo_ReleaseVarDesc(typeinfo
, desc
);
562 /* Second pass: write types for embedded complexes and non-simple pointers. */
566 for (i
= 0; i
< attr
->cVars
; i
++)
568 ITypeInfo_GetVarDesc(typeinfo
, i
, &desc
);
569 tdesc
= &desc
->elemdescVar
.tdesc
;
571 if (struct_offset
!= desc
->oInst
)
572 member_layout
++; /* alignment directive */
573 struct_offset
= desc
->oInst
+ type_memsize(typeinfo
, tdesc
);
575 if (get_basetype(typeinfo
, tdesc
))
577 else if (type_is_non_iface_pointer(typeinfo
, tdesc
))
580 if ((ref
= write_complex_struct_pointer_ref(typeinfo
, tdesc
, str
, len
)))
582 if (str
) *((short *)(str
+ pointer_layout
+ 2)) = ref
- (pointer_layout
+ 2);
588 ref
= write_type_tfs(typeinfo
, str
, len
, tdesc
, FALSE
, FALSE
);
589 if (str
) *((short *)(str
+ member_layout
+ 2)) = ref
- (member_layout
+ 2);
593 ITypeInfo_ReleaseVarDesc(typeinfo
, desc
);
597 static size_t write_struct_tfs(ITypeInfo
*typeinfo
, unsigned char *str
,
598 size_t *len
, TYPEATTR
*attr
)
600 unsigned char fc
= get_struct_fc(typeinfo
, attr
);
603 /* For the sake of simplicity, write pointer structs as complex structs. */
604 if (fc
== FC_PSTRUCT
)
605 fc
= FC_BOGUS_STRUCT
;
607 WRITE_CHAR (str
, *len
, fc
);
608 WRITE_CHAR (str
, *len
, attr
->cbAlignment
- 1);
609 WRITE_SHORT(str
, *len
, attr
->cbSizeInstance
);
612 write_simple_struct_tfs(typeinfo
, str
, len
, attr
);
613 else if (fc
== FC_BOGUS_STRUCT
)
614 write_complex_struct_tfs(typeinfo
, str
, len
, attr
);
619 static size_t write_array_tfs(ITypeInfo
*typeinfo
, unsigned char *str
,
620 size_t *len
, ARRAYDESC
*desc
)
622 unsigned char fc
= get_array_fc(typeinfo
, &desc
->tdescElem
);
623 unsigned char basetype
;
628 if (!(basetype
= get_basetype(typeinfo
, &desc
->tdescElem
)))
629 ref
= write_type_tfs(typeinfo
, str
, len
, &desc
->tdescElem
, FALSE
, FALSE
);
631 /* In theory arrays should be nested, but there's no reason not to marshal
632 * [x][y] as [x*y]. */
633 for (i
= 0; i
< desc
->cDims
; i
++) size
*= desc
->rgbounds
[i
].cElements
;
637 WRITE_CHAR(str
, *len
, fc
);
638 WRITE_CHAR(str
, *len
, 0);
639 if (fc
== FC_BOGUS_ARRAY
)
641 WRITE_SHORT(str
, *len
, size
);
642 WRITE_INT(str
, *len
, 0xffffffff); /* conformance */
643 WRITE_INT(str
, *len
, 0xffffffff); /* variance */
647 size
*= type_memsize(typeinfo
, &desc
->tdescElem
);
648 WRITE_INT(str
, *len
, size
);
652 WRITE_CHAR(str
, *len
, basetype
);
655 WRITE_CHAR (str
, *len
, FC_EMBEDDED_COMPLEX
);
656 WRITE_CHAR (str
, *len
, 0);
657 WRITE_SHORT(str
, *len
, ref
- *len
);
658 WRITE_CHAR (str
, *len
, FC_PAD
);
660 WRITE_CHAR(str
, *len
, FC_END
);
665 static size_t write_ip_tfs(unsigned char *str
, size_t *len
, const GUID
*iid
)
672 str
[*len
+1] = FC_CONSTANT_IID
;
673 memcpy(str
+ *len
+ 2, iid
, sizeof(*iid
));
675 *len
+= 2 + sizeof(*iid
);
680 static void get_default_iface(ITypeInfo
*typeinfo
, WORD count
, GUID
*iid
)
687 for (i
= 0; i
< count
; ++i
)
689 ITypeInfo_GetImplTypeFlags(typeinfo
, i
, &flags
);
690 if (flags
& IMPLTYPEFLAG_FDEFAULT
)
694 /* If no interface was explicitly marked default, choose the first one. */
698 ITypeInfo_GetRefTypeOfImplType(typeinfo
, i
, &reftype
);
699 ITypeInfo_GetRefTypeInfo(typeinfo
, reftype
, &refinfo
);
700 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
702 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
703 ITypeInfo_Release(refinfo
);
706 static size_t write_pointer_tfs(ITypeInfo
*typeinfo
, unsigned char *str
,
707 size_t *len
, TYPEDESC
*desc
, BOOL toplevel
, BOOL onstack
)
709 unsigned char basetype
, flags
= 0;
710 size_t ref
, off
= *len
;
715 if (desc
->vt
== VT_USERDEFINED
)
717 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
718 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
720 switch (attr
->typekind
)
723 assert(!toplevel
); /* toplevel base-type pointers should use IsSimpleRef */
724 WRITE_CHAR(str
, *len
, FC_UP
);
725 WRITE_CHAR(str
, *len
, FC_SIMPLE_POINTER
);
726 WRITE_CHAR(str
, *len
, FC_ENUM32
);
727 WRITE_CHAR(str
, *len
, FC_PAD
);
730 assert(!toplevel
); /* toplevel struct pointers should use IsSimpleRef */
731 ref
= write_struct_tfs(refinfo
, str
, len
, attr
);
733 WRITE_CHAR (str
, *len
, FC_UP
);
734 WRITE_CHAR (str
, *len
, 0);
735 WRITE_SHORT(str
, *len
, ref
- *len
);
737 case TKIND_INTERFACE
:
739 write_ip_tfs(str
, len
, &attr
->guid
);
742 get_default_iface(refinfo
, attr
->cImplTypes
, &guid
);
743 write_ip_tfs(str
, len
, &guid
);
746 off
= write_pointer_tfs(refinfo
, str
, len
, &attr
->tdescAlias
, toplevel
, onstack
);
749 FIXME("unhandled kind %#x\n", attr
->typekind
);
750 WRITE_SHORT(str
, *len
, 0);
754 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
755 ITypeInfo_Release(refinfo
);
757 else if ((basetype
= get_basetype(typeinfo
, desc
)))
759 assert(!toplevel
); /* toplevel base-type pointers should use IsSimpleRef */
760 WRITE_CHAR(str
, *len
, FC_UP
);
761 WRITE_CHAR(str
, *len
, FC_SIMPLE_POINTER
);
762 WRITE_CHAR(str
, *len
, basetype
);
763 WRITE_CHAR(str
, *len
, FC_PAD
);
767 ref
= write_type_tfs(typeinfo
, str
, len
, desc
, FALSE
, FALSE
);
769 if (onstack
) flags
|= FC_ALLOCED_ON_STACK
;
770 if (desc
->vt
== VT_PTR
|| desc
->vt
== VT_UNKNOWN
|| desc
->vt
== VT_DISPATCH
)
771 flags
|= FC_POINTER_DEREF
;
775 WRITE_CHAR (str
, *len
, toplevel
? FC_RP
: FC_UP
);
776 WRITE_CHAR (str
, *len
, flags
);
777 WRITE_SHORT(str
, *len
, ref
- *len
);
783 static size_t write_type_tfs(ITypeInfo
*typeinfo
, unsigned char *str
,
784 size_t *len
, TYPEDESC
*desc
, BOOL toplevel
, BOOL onstack
)
791 TRACE("vt %d%s\n", desc
->vt
, toplevel
? " (toplevel)" : "");
793 if ((off
= write_oleaut_tfs(desc
->vt
)))
799 return write_pointer_tfs(typeinfo
, str
, len
, desc
->lptdesc
, toplevel
, onstack
);
801 return write_array_tfs(typeinfo
, str
, len
, desc
->lpadesc
);
803 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
804 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
806 switch (attr
->typekind
)
809 off
= write_struct_tfs(refinfo
, str
, len
, attr
);
811 case TKIND_INTERFACE
:
813 /* These are treated as if they were interface pointers. */
815 write_ip_tfs(str
, len
, &attr
->guid
);
819 get_default_iface(refinfo
, attr
->cImplTypes
, &guid
);
820 write_ip_tfs(str
, len
, &guid
);
823 off
= write_type_tfs(refinfo
, str
, len
, &attr
->tdescAlias
, toplevel
, onstack
);
826 FIXME("unhandled kind %u\n", attr
->typekind
);
828 WRITE_SHORT(str
, *len
, 0);
832 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
833 ITypeInfo_Release(refinfo
);
836 /* base types are always embedded directly */
837 assert(!get_basetype(typeinfo
, desc
));
838 FIXME("unhandled type %u\n", desc
->vt
);
840 WRITE_SHORT(str
, *len
, 0);
847 static unsigned short get_stack_size(ITypeInfo
*typeinfo
, TYPEDESC
*desc
)
849 #if defined(__i386__) || defined(__arm__)
850 if (desc
->vt
== VT_CARRAY
)
851 return sizeof(void *);
852 return (type_memsize(typeinfo
, desc
) + 3) & ~3;
854 return sizeof(void *);
858 static const unsigned short MustSize
= 0x0001;
859 static const unsigned short MustFree
= 0x0002;
860 static const unsigned short IsIn
= 0x0008;
861 static const unsigned short IsOut
= 0x0010;
862 static const unsigned short IsReturn
= 0x0020;
863 static const unsigned short IsBasetype
= 0x0040;
864 static const unsigned short IsByValue
= 0x0080;
865 static const unsigned short IsSimpleRef
= 0x0100;
867 static HRESULT
get_param_pointer_info(ITypeInfo
*typeinfo
, TYPEDESC
*tdesc
, int is_in
,
868 int is_out
, unsigned short *server_size
, unsigned short *flags
,
869 unsigned char *basetype
, TYPEDESC
**tfs_tdesc
)
881 *server_size
= sizeof(void *);
885 if (type_pointer_is_iface(typeinfo
, tdesc
->lptdesc
))
888 *server_size
= sizeof(void *);
891 *server_size
= sizeof(void *);
894 *flags
|= IsSimpleRef
| MustFree
;
895 *server_size
= type_memsize(typeinfo
, tdesc
);
899 ITypeInfo_GetRefTypeInfo(typeinfo
, tdesc
->hreftype
, &refinfo
);
900 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
902 switch (attr
->typekind
)
905 *flags
|= IsSimpleRef
| IsBasetype
;
906 if (!is_in
&& is_out
)
907 *server_size
= sizeof(void *);
908 *basetype
= FC_ENUM32
;
911 *flags
|= IsSimpleRef
| MustFree
;
912 if (!is_in
&& is_out
)
913 *server_size
= attr
->cbSizeInstance
;
916 case TKIND_INTERFACE
:
922 hr
= get_param_pointer_info(refinfo
, &attr
->tdescAlias
, is_in
,
923 is_out
, server_size
, flags
, basetype
, tfs_tdesc
);
926 FIXME("unhandled kind %#x\n", attr
->typekind
);
931 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
932 ITypeInfo_Release(refinfo
);
935 *flags
|= IsSimpleRef
;
937 if (!is_in
&& is_out
)
938 *server_size
= type_memsize(typeinfo
, tdesc
);
939 if ((*basetype
= get_basetype(typeinfo
, tdesc
)))
940 *flags
|= IsBasetype
;
949 static HRESULT
get_param_info(ITypeInfo
*typeinfo
, TYPEDESC
*tdesc
, int is_in
,
950 int is_out
, unsigned short *server_size
, unsigned short *flags
,
951 unsigned char *basetype
, TYPEDESC
**tfs_tdesc
)
962 TRACE("vt %u\n", tdesc
->vt
);
967 #if !defined(__i386__) && !defined(__arm__)
968 *flags
|= IsSimpleRef
| MustFree
;
971 /* otherwise fall through */
975 *flags
|= IsByValue
| MustFree
;
983 return get_param_pointer_info(typeinfo
, tdesc
->lptdesc
, is_in
, is_out
,
984 server_size
, flags
, basetype
, tfs_tdesc
);
986 ITypeInfo_GetRefTypeInfo(typeinfo
, tdesc
->hreftype
, &refinfo
);
987 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
989 switch (attr
->typekind
)
992 *flags
|= IsBasetype
;
993 *basetype
= FC_ENUM32
;
996 #if defined(__i386__) || defined(__arm__)
997 *flags
|= IsByValue
| MustFree
;
999 if (attr
->cbSizeInstance
<= 8)
1000 *flags
|= IsByValue
| MustFree
;
1002 *flags
|= IsSimpleRef
| MustFree
;
1006 hr
= get_param_info(refinfo
, &attr
->tdescAlias
, is_in
, is_out
,
1007 server_size
, flags
, basetype
, tfs_tdesc
);
1010 case TKIND_INTERFACE
:
1011 case TKIND_DISPATCH
:
1013 /* These are treated as if they were interface pointers. */
1018 FIXME("unhandled kind %#x\n", attr
->typekind
);
1023 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
1024 ITypeInfo_Release(refinfo
);
1027 if ((*basetype
= get_basetype(typeinfo
, tdesc
)))
1028 *flags
|= IsBasetype
;
1031 FIXME("unhandled type %u\n", tdesc
->vt
);
1040 static HRESULT
write_param_fs(ITypeInfo
*typeinfo
, unsigned char *type
,
1041 size_t *typelen
, unsigned char *proc
, size_t *proclen
, ELEMDESC
*desc
,
1042 BOOL is_return
, unsigned short *stack_offset
)
1044 USHORT param_flags
= desc
->paramdesc
.wParamFlags
;
1045 TYPEDESC
*tdesc
= &desc
->tdesc
, *tfs_tdesc
;
1046 unsigned short server_size
;
1047 unsigned short stack_size
= get_stack_size(typeinfo
, tdesc
);
1048 unsigned char basetype
;
1049 unsigned short flags
;
1054 is_out
= param_flags
& PARAMFLAG_FOUT
;
1055 is_in
= (param_flags
& PARAMFLAG_FIN
) || (!is_out
&& !is_return
);
1057 hr
= get_param_info(typeinfo
, tdesc
, is_in
, is_out
, &server_size
, &flags
,
1058 &basetype
, &tfs_tdesc
);
1060 if (is_in
) flags
|= IsIn
;
1061 if (is_out
) flags
|= IsOut
;
1062 if (is_return
) flags
|= IsOut
| IsReturn
;
1064 server_size
= (server_size
+ 7) / 8;
1065 if (server_size
>= 8) server_size
= 0;
1066 flags
|= server_size
<< 13;
1069 off
= write_type_tfs(typeinfo
, type
, typelen
, tfs_tdesc
, TRUE
, server_size
!= 0);
1073 WRITE_SHORT(proc
, *proclen
, flags
);
1074 WRITE_SHORT(proc
, *proclen
, *stack_offset
);
1075 WRITE_SHORT(proc
, *proclen
, basetype
? basetype
: off
);
1077 *stack_offset
+= stack_size
;
1083 static void write_proc_func_header(ITypeInfo
*typeinfo
, FUNCDESC
*desc
,
1084 WORD proc_idx
, unsigned char *proc
, size_t *proclen
)
1086 unsigned short stack_size
= 2 * sizeof(void *); /* This + return */
1088 unsigned short float_mask
= 0;
1089 unsigned char basetype
;
1093 WRITE_CHAR (proc
, *proclen
, FC_AUTO_HANDLE
);
1094 WRITE_CHAR (proc
, *proclen
, Oi_OBJECT_PROC
| Oi_OBJ_USE_V2_INTERPRETER
);
1095 WRITE_SHORT(proc
, *proclen
, proc_idx
);
1096 for (param_idx
= 0; param_idx
< desc
->cParams
; param_idx
++)
1097 stack_size
+= get_stack_size(typeinfo
, &desc
->lprgelemdescParam
[param_idx
].tdesc
);
1098 WRITE_SHORT(proc
, *proclen
, stack_size
);
1100 WRITE_SHORT(proc
, *proclen
, 0); /* constant_client_buffer_size */
1101 WRITE_SHORT(proc
, *proclen
, 0); /* constant_server_buffer_size */
1103 WRITE_CHAR (proc
, *proclen
, 0x47); /* HasExtensions | HasReturn | ClientMustSize | ServerMustSize */
1105 WRITE_CHAR (proc
, *proclen
, 0x07); /* HasReturn | ClientMustSize | ServerMustSize */
1107 WRITE_CHAR (proc
, *proclen
, desc
->cParams
+ 1); /* incl. return value */
1109 WRITE_CHAR (proc
, *proclen
, 10); /* extension size */
1110 WRITE_CHAR (proc
, *proclen
, 0); /* INTERPRETER_OPT_FLAGS2 */
1111 WRITE_SHORT(proc
, *proclen
, 0); /* ClientCorrHint */
1112 WRITE_SHORT(proc
, *proclen
, 0); /* ServerCorrHint */
1113 WRITE_SHORT(proc
, *proclen
, 0); /* NotifyIndex */
1114 for (param_idx
= 0; param_idx
< desc
->cParams
&& param_idx
< 3; param_idx
++)
1116 basetype
= get_basetype(typeinfo
, &desc
->lprgelemdescParam
[param_idx
].tdesc
);
1117 if (basetype
== FC_FLOAT
)
1118 float_mask
|= (1 << ((param_idx
+ 1) * 2));
1119 else if (basetype
== FC_DOUBLE
)
1120 float_mask
|= (2 << ((param_idx
+ 1) * 2));
1122 WRITE_SHORT(proc
, *proclen
, float_mask
);
1126 static HRESULT
write_iface_fs(ITypeInfo
*typeinfo
, WORD funcs
, WORD parentfuncs
,
1127 unsigned char *type
, size_t *typelen
, unsigned char *proc
,
1128 size_t *proclen
, unsigned short *offset
)
1130 unsigned short stack_offset
;
1131 WORD proc_idx
, param_idx
;
1135 for (proc_idx
= 3; proc_idx
< parentfuncs
; proc_idx
++)
1138 offset
[proc_idx
- 3] = -1;
1141 for (proc_idx
= 0; proc_idx
< funcs
; proc_idx
++)
1143 TRACE("Writing procedure %d.\n", proc_idx
);
1145 hr
= ITypeInfo_GetFuncDesc(typeinfo
, proc_idx
, &desc
);
1146 if (FAILED(hr
)) return hr
;
1149 offset
[proc_idx
+ parentfuncs
- 3] = *proclen
;
1151 write_proc_func_header(typeinfo
, desc
, proc_idx
+ parentfuncs
, proc
, proclen
);
1153 stack_offset
= sizeof(void *); /* This */
1154 for (param_idx
= 0; param_idx
< desc
->cParams
; param_idx
++)
1156 TRACE("Writing parameter %d.\n", param_idx
);
1157 hr
= write_param_fs(typeinfo
, type
, typelen
, proc
, proclen
,
1158 &desc
->lprgelemdescParam
[param_idx
], FALSE
, &stack_offset
);
1161 ITypeInfo_ReleaseFuncDesc(typeinfo
, desc
);
1166 hr
= write_param_fs(typeinfo
, type
, typelen
, proc
, proclen
,
1167 &desc
->elemdescFunc
, TRUE
, &stack_offset
);
1168 ITypeInfo_ReleaseFuncDesc(typeinfo
, desc
);
1169 if (FAILED(hr
)) return hr
;
1175 static HRESULT
build_format_strings(ITypeInfo
*typeinfo
, WORD funcs
,
1176 WORD parentfuncs
, const unsigned char **type_ret
,
1177 const unsigned char **proc_ret
, unsigned short **offset_ret
)
1180 const unsigned char *tfs
= get_type_format_string( &tfs_size
);
1181 size_t typelen
= tfs_size
, proclen
= 0;
1182 unsigned char *type
, *proc
;
1183 unsigned short *offset
;
1186 hr
= write_iface_fs(typeinfo
, funcs
, parentfuncs
, NULL
, &typelen
, NULL
, &proclen
, NULL
);
1187 if (FAILED(hr
)) return hr
;
1189 type
= malloc(typelen
);
1190 proc
= malloc(proclen
);
1191 offset
= malloc((parentfuncs
+ funcs
- 3) * sizeof(*offset
));
1192 if (!type
|| !proc
|| !offset
)
1194 ERR("Failed to allocate format strings.\n");
1199 memcpy(type
, tfs
, tfs_size
);
1203 hr
= write_iface_fs(typeinfo
, funcs
, parentfuncs
, type
, &typelen
, proc
, &proclen
, offset
);
1208 *offset_ret
= offset
;
1219 /* Common helper for Create{Proxy,Stub}FromTypeInfo(). */
1220 static HRESULT
get_iface_info(ITypeInfo
*typeinfo
, WORD
*funcs
, WORD
*parentfuncs
,
1221 GUID
*parentiid
, ITypeInfo
**real_typeinfo
)
1223 ITypeInfo
*parentinfo
;
1232 /* Dual interfaces report their size to be sizeof(IDispatchVtbl) and their
1233 * implemented type to be IDispatch. We need to retrieve the underlying
1234 * interface to get that information. */
1235 hr
= ITypeInfo_GetTypeAttr(typeinfo
, &typeattr
);
1238 typekind
= typeattr
->typekind
;
1239 ITypeInfo_ReleaseTypeAttr(typeinfo
, typeattr
);
1240 if (typekind
== TKIND_DISPATCH
)
1242 hr
= ITypeInfo_GetRefTypeOfImplType(typeinfo
, -1, &reftype
);
1246 hr
= ITypeInfo_GetRefTypeInfo(typeinfo
, reftype
, real_typeinfo
);
1251 ITypeInfo_AddRef(*real_typeinfo
= typeinfo
);
1253 hr
= ITypeInfo_GetContainingTypeLib(*real_typeinfo
, &typelib
, NULL
);
1257 hr
= ITypeLib_GetLibAttr(typelib
, &libattr
);
1260 ITypeLib_Release(typelib
);
1263 syskind
= libattr
->syskind
;
1264 ITypeLib_ReleaseTLibAttr(typelib
, libattr
);
1265 ITypeLib_Release(typelib
);
1267 hr
= ITypeInfo_GetTypeAttr(*real_typeinfo
, &typeattr
);
1270 *funcs
= typeattr
->cFuncs
;
1271 *parentfuncs
= typeattr
->cbSizeVft
/ (syskind
== SYS_WIN64
? 8 : 4) - *funcs
;
1272 ITypeInfo_ReleaseTypeAttr(*real_typeinfo
, typeattr
);
1274 hr
= ITypeInfo_GetRefTypeOfImplType(*real_typeinfo
, 0, &reftype
);
1277 hr
= ITypeInfo_GetRefTypeInfo(*real_typeinfo
, reftype
, &parentinfo
);
1281 hr
= ITypeInfo_GetTypeAttr(parentinfo
, &typeattr
);
1284 *parentiid
= typeattr
->guid
;
1285 ITypeInfo_ReleaseTypeAttr(parentinfo
, typeattr
);
1287 ITypeInfo_Release(parentinfo
);
1292 ITypeInfo_Release(*real_typeinfo
);
1296 static void init_stub_desc(MIDL_STUB_DESC
*desc
)
1298 desc
->pfnAllocate
= NdrOleAllocate
;
1299 desc
->pfnFree
= NdrOleFree
;
1300 desc
->Version
= 0x50002;
1301 desc
->aUserMarshalQuadruple
= get_ndr_types_proxy_info()->pStubDesc
->aUserMarshalQuadruple
;
1302 /* type format string is initialized with proc format string and offset table */
1305 struct typelib_proxy
1309 MIDL_STUB_DESC stub_desc
;
1310 MIDL_STUBLESS_PROXY_INFO proxy_info
;
1311 CInterfaceProxyVtbl
*proxy_vtbl
;
1312 unsigned short *offset_table
;
1315 static ULONG WINAPI
typelib_proxy_Release(IRpcProxyBuffer
*iface
)
1317 struct typelib_proxy
*proxy
= CONTAINING_RECORD(iface
, struct typelib_proxy
, proxy
.IRpcProxyBuffer_iface
);
1318 ULONG refcount
= InterlockedDecrement(&proxy
->proxy
.RefCount
);
1320 TRACE("(%p) decreasing refs to %ld\n", proxy
, refcount
);
1324 if (proxy
->proxy
.pChannel
)
1325 IRpcProxyBuffer_Disconnect(&proxy
->proxy
.IRpcProxyBuffer_iface
);
1326 if (proxy
->proxy
.base_object
)
1327 IUnknown_Release(proxy
->proxy
.base_object
);
1328 if (proxy
->proxy
.base_proxy
)
1329 IRpcProxyBuffer_Release(proxy
->proxy
.base_proxy
);
1330 free((void *)proxy
->stub_desc
.pFormatTypes
);
1331 free((void *)proxy
->proxy_info
.ProcFormatString
);
1332 free(proxy
->offset_table
);
1333 free(proxy
->proxy_vtbl
);
1339 static const IRpcProxyBufferVtbl typelib_proxy_vtbl
=
1341 StdProxy_QueryInterface
,
1343 typelib_proxy_Release
,
1345 StdProxy_Disconnect
,
1348 static HRESULT
typelib_proxy_init(struct typelib_proxy
*proxy
, IUnknown
*outer
,
1349 ULONG count
, const GUID
*parentiid
, IRpcProxyBuffer
**proxy_buffer
, void **out
)
1351 if (!fill_stubless_table((IUnknownVtbl
*)proxy
->proxy_vtbl
->Vtbl
, count
))
1352 return E_OUTOFMEMORY
;
1354 if (!outer
) outer
= (IUnknown
*)&proxy
->proxy
;
1356 proxy
->proxy
.IRpcProxyBuffer_iface
.lpVtbl
= &typelib_proxy_vtbl
;
1357 proxy
->proxy
.PVtbl
= proxy
->proxy_vtbl
->Vtbl
;
1358 proxy
->proxy
.RefCount
= 1;
1359 proxy
->proxy
.piid
= proxy
->proxy_vtbl
->header
.piid
;
1360 proxy
->proxy
.pUnkOuter
= outer
;
1362 if (!IsEqualGUID(parentiid
, &IID_IUnknown
))
1364 HRESULT hr
= create_proxy(parentiid
, NULL
, &proxy
->proxy
.base_proxy
,
1365 (void **)&proxy
->proxy
.base_object
);
1366 if (FAILED(hr
)) return hr
;
1369 *proxy_buffer
= &proxy
->proxy
.IRpcProxyBuffer_iface
;
1370 *out
= &proxy
->proxy
.PVtbl
;
1371 IUnknown_AddRef((IUnknown
*)*out
);
1376 HRESULT WINAPI
CreateProxyFromTypeInfo(ITypeInfo
*typeinfo
, IUnknown
*outer
,
1377 REFIID iid
, IRpcProxyBuffer
**proxy_buffer
, void **out
)
1379 struct typelib_proxy
*proxy
;
1380 WORD funcs
, parentfuncs
, i
;
1381 ITypeInfo
*real_typeinfo
;
1385 TRACE("typeinfo %p, outer %p, iid %s, proxy_buffer %p, out %p.\n",
1386 typeinfo
, outer
, debugstr_guid(iid
), proxy_buffer
, out
);
1388 hr
= get_iface_info(typeinfo
, &funcs
, &parentfuncs
, &parentiid
, &real_typeinfo
);
1392 if (!(proxy
= calloc(1, sizeof(*proxy
))))
1394 ERR("Failed to allocate proxy object.\n");
1395 ITypeInfo_Release(real_typeinfo
);
1396 return E_OUTOFMEMORY
;
1399 init_stub_desc(&proxy
->stub_desc
);
1400 proxy
->proxy_info
.pStubDesc
= &proxy
->stub_desc
;
1402 proxy
->proxy_vtbl
= calloc(1, sizeof(proxy
->proxy_vtbl
->header
) + (funcs
+ parentfuncs
) * sizeof(void *));
1403 if (!proxy
->proxy_vtbl
)
1405 ERR("Failed to allocate proxy vtbl.\n");
1407 ITypeInfo_Release(real_typeinfo
);
1408 return E_OUTOFMEMORY
;
1410 proxy
->proxy_vtbl
->header
.pStublessProxyInfo
= &proxy
->proxy_info
;
1412 proxy
->proxy_vtbl
->header
.piid
= &proxy
->iid
;
1413 fill_delegated_proxy_table((IUnknownVtbl
*)proxy
->proxy_vtbl
->Vtbl
, parentfuncs
);
1414 for (i
= 0; i
< funcs
; i
++)
1415 proxy
->proxy_vtbl
->Vtbl
[parentfuncs
+ i
] = (void *)-1;
1417 hr
= build_format_strings(real_typeinfo
, funcs
, parentfuncs
, &proxy
->stub_desc
.pFormatTypes
,
1418 &proxy
->proxy_info
.ProcFormatString
, &proxy
->offset_table
);
1419 ITypeInfo_Release(real_typeinfo
);
1422 free(proxy
->proxy_vtbl
);
1426 proxy
->proxy_info
.FormatStringOffset
= &proxy
->offset_table
[-3];
1428 hr
= typelib_proxy_init(proxy
, outer
, funcs
+ parentfuncs
, &parentiid
, proxy_buffer
, out
);
1431 free((void *)proxy
->stub_desc
.pFormatTypes
);
1432 free((void *)proxy
->proxy_info
.ProcFormatString
);
1433 free((void *)proxy
->offset_table
);
1434 free(proxy
->proxy_vtbl
);
1443 cstdstubbuffer_delegating_t stub
;
1445 MIDL_STUB_DESC stub_desc
;
1446 MIDL_SERVER_INFO server_info
;
1447 CInterfaceStubVtbl stub_vtbl
;
1448 unsigned short *offset_table
;
1449 PRPC_STUB_FUNCTION
*dispatch_table
;
1452 static ULONG WINAPI
typelib_stub_Release(IRpcStubBuffer
*iface
)
1454 struct typelib_stub
*stub
= CONTAINING_RECORD(iface
, struct typelib_stub
, stub
.stub_buffer
);
1455 ULONG refcount
= InterlockedDecrement(&stub
->stub
.stub_buffer
.RefCount
);
1457 TRACE("(%p) decreasing refs to %ld\n", stub
, refcount
);
1461 /* test_Release shows that native doesn't call Disconnect here.
1462 We'll leave it in for the time being. */
1463 IRpcStubBuffer_Disconnect(iface
);
1465 if (stub
->stub
.base_stub
)
1467 IRpcStubBuffer_Release(stub
->stub
.base_stub
);
1468 free(stub
->dispatch_table
);
1471 free((void *)stub
->stub_desc
.pFormatTypes
);
1472 free((void *)stub
->server_info
.ProcString
);
1473 free(stub
->offset_table
);
1480 static HRESULT
typelib_stub_init(struct typelib_stub
*stub
, IUnknown
*server
,
1481 const GUID
*parentiid
, IRpcStubBuffer
**stub_buffer
)
1485 hr
= IUnknown_QueryInterface(server
, stub
->stub_vtbl
.header
.piid
,
1486 (void **)&stub
->stub
.stub_buffer
.pvServerObject
);
1489 WARN("Failed to get interface %s, hr %#lx.\n",
1490 debugstr_guid(stub
->stub_vtbl
.header
.piid
), hr
);
1491 stub
->stub
.stub_buffer
.pvServerObject
= server
;
1492 IUnknown_AddRef(server
);
1495 if (!IsEqualGUID(parentiid
, &IID_IUnknown
))
1497 stub
->stub
.base_obj
.lpVtbl
= get_delegating_vtbl(stub
->stub_vtbl
.header
.DispatchTableCount
);
1498 hr
= create_stub(parentiid
, &stub
->stub
.base_obj
, &stub
->stub
.base_stub
);
1501 IUnknown_Release(stub
->stub
.stub_buffer
.pvServerObject
);
1506 stub
->stub
.stub_buffer
.lpVtbl
= &stub
->stub_vtbl
.Vtbl
;
1507 stub
->stub
.stub_buffer
.RefCount
= 1;
1509 *stub_buffer
= (IRpcStubBuffer
*)&stub
->stub
.stub_buffer
;
1513 HRESULT WINAPI
CreateStubFromTypeInfo(ITypeInfo
*typeinfo
, REFIID iid
,
1514 IUnknown
*server
, IRpcStubBuffer
**stub_buffer
)
1516 WORD funcs
, parentfuncs
, i
;
1517 struct typelib_stub
*stub
;
1518 ITypeInfo
*real_typeinfo
;
1522 TRACE("typeinfo %p, iid %s, server %p, stub_buffer %p.\n",
1523 typeinfo
, debugstr_guid(iid
), server
, stub_buffer
);
1525 hr
= get_iface_info(typeinfo
, &funcs
, &parentfuncs
, &parentiid
, &real_typeinfo
);
1529 if (!(stub
= calloc(1, sizeof(*stub
))))
1531 ERR("Failed to allocate stub object.\n");
1532 ITypeInfo_Release(real_typeinfo
);
1533 return E_OUTOFMEMORY
;
1536 init_stub_desc(&stub
->stub_desc
);
1537 stub
->server_info
.pStubDesc
= &stub
->stub_desc
;
1539 hr
= build_format_strings(real_typeinfo
, funcs
, parentfuncs
, &stub
->stub_desc
.pFormatTypes
,
1540 &stub
->server_info
.ProcString
, &stub
->offset_table
);
1541 ITypeInfo_Release(real_typeinfo
);
1547 stub
->server_info
.FmtStringOffset
= &stub
->offset_table
[-3];
1550 stub
->stub_vtbl
.header
.piid
= &stub
->iid
;
1551 stub
->stub_vtbl
.header
.pServerInfo
= &stub
->server_info
;
1552 stub
->stub_vtbl
.header
.DispatchTableCount
= funcs
+ parentfuncs
;
1554 if (!IsEqualGUID(&parentiid
, &IID_IUnknown
))
1556 stub
->dispatch_table
= malloc((funcs
+ parentfuncs
) * sizeof(void *));
1557 for (i
= 3; i
< parentfuncs
; i
++)
1558 stub
->dispatch_table
[i
- 3] = NdrStubForwardingFunction
;
1559 for (; i
< funcs
+ parentfuncs
; i
++)
1560 stub
->dispatch_table
[i
- 3] = (PRPC_STUB_FUNCTION
)NdrStubCall2
;
1561 stub
->stub_vtbl
.header
.pDispatchTable
= &stub
->dispatch_table
[-3];
1562 stub
->stub_vtbl
.Vtbl
= CStdStubBuffer_Delegating_Vtbl
;
1565 stub
->stub_vtbl
.Vtbl
= CStdStubBuffer_Vtbl
;
1566 stub
->stub_vtbl
.Vtbl
.Release
= typelib_stub_Release
;
1568 hr
= typelib_stub_init(stub
, server
, &parentiid
, stub_buffer
);
1571 free((void *)stub
->stub_desc
.pFormatTypes
);
1572 free((void *)stub
->server_info
.ProcString
);
1573 free(stub
->offset_table
);