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"
29 #include "wine/heap.h"
33 #include "ndr_types.h"
34 #include "ndr_stubless.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
38 static size_t write_type_tfs(ITypeInfo
*typeinfo
, unsigned char *str
,
39 size_t *len
, TYPEDESC
*desc
, BOOL toplevel
, BOOL onstack
);
41 #define WRITE_CHAR(str, len, val) \
42 do { if ((str)) (str)[(len)] = (val); (len)++; } while (0)
43 #define WRITE_SHORT(str, len, val) \
44 do { if ((str)) *((short *)((str) + (len))) = (val); (len) += 2; } while (0)
45 #define WRITE_INT(str, len, val) \
46 do { if ((str)) *((int *)((str) + (len))) = (val); (len) += 4; } while (0)
48 extern const ExtendedProxyFileInfo ndr_types_ProxyFileInfo
;
50 static const MIDL_STUBLESS_PROXY_INFO
*get_ndr_types_proxy_info(void)
52 return ndr_types_ProxyFileInfo
.pProxyVtblList
[0]->header
.pStublessProxyInfo
;
55 static const NDR_PARAM_OIF
*get_ndr_types_params( unsigned int *nb_params
)
57 const MIDL_STUBLESS_PROXY_INFO
*proxy
= get_ndr_types_proxy_info();
58 const unsigned char *format
= proxy
->ProcFormatString
+ proxy
->FormatStringOffset
[3];
59 const NDR_PROC_HEADER
*proc
= (const NDR_PROC_HEADER
*)format
;
60 const NDR_PROC_PARTIAL_OIF_HEADER
*header
;
62 if (proc
->Oi_flags
& Oi_HAS_RPCFLAGS
)
63 format
+= sizeof(NDR_PROC_HEADER_RPC
);
65 format
+= sizeof(NDR_PROC_HEADER
);
67 header
= (const NDR_PROC_PARTIAL_OIF_HEADER
*)format
;
68 format
+= sizeof(*header
);
69 if (header
->Oi2Flags
.HasExtensions
)
71 const NDR_PROC_HEADER_EXTS
*ext
= (const NDR_PROC_HEADER_EXTS
*)format
;
74 *nb_params
= header
->number_of_params
;
75 return (const NDR_PARAM_OIF
*)format
;
78 static unsigned short get_tfs_offset( int param
)
80 unsigned int nb_params
;
81 const NDR_PARAM_OIF
*params
= get_ndr_types_params( &nb_params
);
83 assert( param
< nb_params
);
84 return params
[param
].u
.type_offset
;
87 static const unsigned char *get_type_format_string( size_t *size
)
89 unsigned int nb_params
;
90 const NDR_PARAM_OIF
*params
= get_ndr_types_params( &nb_params
);
92 *size
= params
[nb_params
- 1].u
.type_offset
;
93 return get_ndr_types_proxy_info()->pStubDesc
->pFormatTypes
;
96 static unsigned short write_oleaut_tfs(VARTYPE vt
)
100 case VT_BSTR
: return get_tfs_offset( 0 );
101 case VT_UNKNOWN
: return get_tfs_offset( 1 );
102 case VT_DISPATCH
: return get_tfs_offset( 2 );
103 case VT_VARIANT
: return get_tfs_offset( 3 );
104 case VT_SAFEARRAY
: return get_tfs_offset( 4 );
109 static unsigned char get_basetype(ITypeInfo
*typeinfo
, TYPEDESC
*desc
)
117 case VT_I1
: return FC_SMALL
;
119 case VT_I2
: return FC_SHORT
;
123 case VT_I4
: return FC_LONG
;
125 case VT_UI8
: return FC_HYPER
;
126 case VT_UI1
: return FC_USMALL
;
127 case VT_UI2
: return FC_USHORT
;
129 case VT_UI4
: return FC_ULONG
;
130 case VT_R4
: return FC_FLOAT
;
132 case VT_R8
: return FC_DOUBLE
;
134 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
135 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
136 if (attr
->typekind
== TKIND_ENUM
)
138 else if (attr
->typekind
== TKIND_ALIAS
)
139 ret
= get_basetype(refinfo
, &attr
->tdescAlias
);
142 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
143 ITypeInfo_Release(refinfo
);
149 static unsigned int type_memsize(ITypeInfo
*typeinfo
, TYPEDESC
*desc
)
178 return sizeof(void *);
180 return sizeof(VARIANT
);
183 unsigned int size
= type_memsize(typeinfo
, &desc
->lpadesc
->tdescElem
);
185 for (i
= 0; i
< desc
->lpadesc
->cDims
; i
++)
186 size
*= desc
->lpadesc
->rgbounds
[i
].cElements
;
191 unsigned int size
= 0;
195 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
196 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
197 size
= attr
->cbSizeInstance
;
198 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
199 ITypeInfo_Release(refinfo
);
203 FIXME("unhandled type %u\n", desc
->vt
);
208 static BOOL
type_pointer_is_iface(ITypeInfo
*typeinfo
, TYPEDESC
*tdesc
)
214 if (tdesc
->vt
== VT_USERDEFINED
)
216 ITypeInfo_GetRefTypeInfo(typeinfo
, tdesc
->hreftype
, &refinfo
);
217 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
219 if (attr
->typekind
== TKIND_INTERFACE
220 || attr
->typekind
== TKIND_DISPATCH
221 || attr
->typekind
== TKIND_COCLASS
)
223 else if (attr
->typekind
== TKIND_ALIAS
)
224 ret
= type_pointer_is_iface(refinfo
, &attr
->tdescAlias
);
226 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
227 ITypeInfo_Release(refinfo
);
233 static unsigned char get_array_fc(ITypeInfo
*typeinfo
, TYPEDESC
*desc
);
234 static unsigned char get_struct_fc(ITypeInfo
*typeinfo
, TYPEATTR
*attr
);
236 static unsigned char get_struct_member_fc(ITypeInfo
*typeinfo
, TYPEDESC
*tdesc
)
246 return (sizeof(void *) == 4) ? FC_PSTRUCT
: FC_BOGUS_STRUCT
;
252 return FC_BOGUS_STRUCT
;
254 if (get_array_fc(typeinfo
, &tdesc
->lpadesc
->tdescElem
) == FC_BOGUS_ARRAY
)
255 return FC_BOGUS_STRUCT
;
258 if (type_pointer_is_iface(typeinfo
, tdesc
))
259 fc
= FC_BOGUS_STRUCT
;
261 fc
= (sizeof(void *) == 4) ? FC_PSTRUCT
: FC_BOGUS_STRUCT
;
264 ITypeInfo_GetRefTypeInfo(typeinfo
, tdesc
->hreftype
, &refinfo
);
265 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
267 switch (attr
->typekind
)
273 fc
= get_struct_fc(refinfo
, attr
);
275 case TKIND_INTERFACE
:
278 fc
= FC_BOGUS_STRUCT
;
281 fc
= get_struct_member_fc(refinfo
, &attr
->tdescAlias
);
284 FIXME("Unhandled kind %#x.\n", attr
->typekind
);
285 fc
= FC_BOGUS_STRUCT
;
289 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
290 ITypeInfo_Release(refinfo
);
293 if (get_basetype(typeinfo
, tdesc
))
297 FIXME("Unhandled type %u.\n", tdesc
->vt
);
298 return FC_BOGUS_STRUCT
;
305 static unsigned char get_struct_fc(ITypeInfo
*typeinfo
, TYPEATTR
*attr
)
307 unsigned char fc
= FC_STRUCT
, member_fc
;
311 for (i
= 0; i
< attr
->cVars
; i
++)
313 ITypeInfo_GetVarDesc(typeinfo
, i
, &desc
);
315 member_fc
= get_struct_member_fc(typeinfo
, &desc
->elemdescVar
.tdesc
);
316 if (member_fc
== FC_BOGUS_STRUCT
)
317 fc
= FC_BOGUS_STRUCT
;
318 else if (member_fc
== FC_PSTRUCT
&& fc
!= FC_BOGUS_STRUCT
)
321 ITypeInfo_ReleaseVarDesc(typeinfo
, desc
);
327 static unsigned char get_array_fc(ITypeInfo
*typeinfo
, TYPEDESC
*desc
)
334 return get_array_fc(typeinfo
, &desc
->lpadesc
->tdescElem
);
341 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
342 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
344 if (attr
->typekind
== TKIND_ENUM
)
346 else if (attr
->typekind
== TKIND_RECORD
&& get_struct_fc(refinfo
, attr
) == FC_STRUCT
)
348 else if (attr
->typekind
== TKIND_ALIAS
)
349 fc
= get_array_fc(refinfo
, &attr
->tdescAlias
);
353 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
354 ITypeInfo_Release(refinfo
);
359 return get_basetype(typeinfo
, desc
) ? FC_LGFARRAY
: FC_BOGUS_ARRAY
;
363 static BOOL
type_is_non_iface_pointer(ITypeInfo
*typeinfo
, TYPEDESC
*desc
)
365 if (desc
->vt
== VT_PTR
)
366 return !type_pointer_is_iface(typeinfo
, desc
->lptdesc
);
367 else if (desc
->vt
== VT_USERDEFINED
)
373 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
374 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
376 if (attr
->typekind
== TKIND_ALIAS
)
377 ret
= type_is_non_iface_pointer(refinfo
, &attr
->tdescAlias
);
381 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
382 ITypeInfo_Release(refinfo
);
390 static void write_struct_members(ITypeInfo
*typeinfo
, unsigned char *str
,
391 size_t *len
, TYPEATTR
*attr
)
393 unsigned int struct_offset
= 0;
394 unsigned char basetype
;
399 for (i
= 0; i
< attr
->cVars
; i
++)
401 ITypeInfo_GetVarDesc(typeinfo
, i
, &desc
);
402 tdesc
= &desc
->elemdescVar
.tdesc
;
404 /* This may not match the intended alignment, but we don't have enough
405 * information to determine that. This should always give the correct
407 if ((struct_offset
& 7) && !(desc
->oInst
& 7))
408 WRITE_CHAR(str
, *len
, FC_ALIGNM8
);
409 else if ((struct_offset
& 3) && !(desc
->oInst
& 3))
410 WRITE_CHAR(str
, *len
, FC_ALIGNM4
);
411 else if ((struct_offset
& 1) && !(desc
->oInst
& 1))
412 WRITE_CHAR(str
, *len
, FC_ALIGNM2
);
413 struct_offset
= desc
->oInst
+ type_memsize(typeinfo
, tdesc
);
415 if ((basetype
= get_basetype(typeinfo
, tdesc
)))
416 WRITE_CHAR(str
, *len
, basetype
);
417 else if (type_is_non_iface_pointer(typeinfo
, tdesc
))
418 WRITE_CHAR(str
, *len
, FC_POINTER
);
421 WRITE_CHAR(str
, *len
, FC_EMBEDDED_COMPLEX
);
422 WRITE_CHAR(str
, *len
, 0);
423 WRITE_SHORT(str
, *len
, 0);
426 ITypeInfo_ReleaseVarDesc(typeinfo
, desc
);
429 WRITE_CHAR (str
, *len
, FC_PAD
);
430 WRITE_CHAR (str
, *len
, FC_END
);
433 static void write_simple_struct_tfs(ITypeInfo
*typeinfo
, unsigned char *str
,
434 size_t *len
, TYPEATTR
*attr
)
436 write_struct_members(typeinfo
, str
, len
, attr
);
439 static BOOL
type_needs_pointer_deref(ITypeInfo
*typeinfo
, TYPEDESC
*desc
)
441 if (desc
->vt
== VT_PTR
|| desc
->vt
== VT_UNKNOWN
|| desc
->vt
== VT_DISPATCH
)
443 else if (desc
->vt
== VT_USERDEFINED
)
449 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
450 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
452 if (attr
->typekind
== TKIND_ALIAS
)
453 ret
= type_needs_pointer_deref(refinfo
, &attr
->tdescAlias
);
455 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
456 ITypeInfo_Release(refinfo
);
464 static void write_complex_struct_pointer_layout(ITypeInfo
*typeinfo
,
465 TYPEDESC
*desc
, unsigned char *str
, size_t *len
)
467 unsigned char basetype
;
469 if (desc
->vt
== VT_PTR
&& !type_pointer_is_iface(typeinfo
, desc
->lptdesc
))
471 WRITE_CHAR(str
, *len
, FC_UP
);
472 if ((basetype
= get_basetype(typeinfo
, desc
->lptdesc
)))
474 WRITE_CHAR(str
, *len
, FC_SIMPLE_POINTER
);
475 WRITE_CHAR(str
, *len
, basetype
);
476 WRITE_CHAR(str
, *len
, FC_PAD
);
480 if (type_needs_pointer_deref(typeinfo
, desc
->lptdesc
))
481 WRITE_CHAR(str
, *len
, FC_POINTER_DEREF
);
483 WRITE_CHAR(str
, *len
, 0);
484 WRITE_SHORT(str
, *len
, 0);
487 else if (desc
->vt
== VT_USERDEFINED
)
492 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
493 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
495 if (attr
->typekind
== TKIND_ALIAS
)
496 write_complex_struct_pointer_layout(refinfo
, &attr
->tdescAlias
, str
, len
);
498 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
499 ITypeInfo_Release(refinfo
);
503 static size_t write_complex_struct_pointer_ref(ITypeInfo
*typeinfo
,
504 TYPEDESC
*desc
, unsigned char *str
, size_t *len
)
506 if (desc
->vt
== VT_PTR
&& !type_pointer_is_iface(typeinfo
, desc
->lptdesc
)
507 && !get_basetype(typeinfo
, desc
->lptdesc
))
509 return write_type_tfs(typeinfo
, str
, len
, desc
->lptdesc
, FALSE
, FALSE
);
511 else if (desc
->vt
== VT_USERDEFINED
)
517 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
518 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
520 if (attr
->typekind
== TKIND_ALIAS
)
521 ret
= write_complex_struct_pointer_ref(refinfo
, &attr
->tdescAlias
, str
, len
);
523 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
524 ITypeInfo_Release(refinfo
);
532 static void write_complex_struct_tfs(ITypeInfo
*typeinfo
, unsigned char *str
,
533 size_t *len
, TYPEATTR
*attr
)
535 size_t pointer_layout_offset
, pointer_layout
, member_layout
, ref
;
536 unsigned int struct_offset
= 0;
541 WRITE_SHORT(str
, *len
, 0); /* conformant array description */
542 pointer_layout_offset
= *len
;
543 WRITE_SHORT(str
, *len
, 0); /* pointer layout; will be filled in later */
544 member_layout
= *len
;
546 /* First pass: write the struct members and pointer layout, but do not yet
547 * write the offsets for embedded complexes and pointer refs. These must be
548 * handled after we write the whole struct description, since it must be
551 write_struct_members(typeinfo
, str
, len
, attr
);
553 pointer_layout
= *len
;
554 if (str
) *((short *)(str
+ pointer_layout_offset
)) = pointer_layout
- pointer_layout_offset
;
556 for (i
= 0; i
< attr
->cVars
; i
++)
558 ITypeInfo_GetVarDesc(typeinfo
, i
, &desc
);
559 write_complex_struct_pointer_layout(typeinfo
, &desc
->elemdescVar
.tdesc
, str
, len
);
560 ITypeInfo_ReleaseVarDesc(typeinfo
, desc
);
563 /* Second pass: write types for embedded complexes and non-simple pointers. */
567 for (i
= 0; i
< attr
->cVars
; i
++)
569 ITypeInfo_GetVarDesc(typeinfo
, i
, &desc
);
570 tdesc
= &desc
->elemdescVar
.tdesc
;
572 if (struct_offset
!= desc
->oInst
)
573 member_layout
++; /* alignment directive */
574 struct_offset
= desc
->oInst
+ type_memsize(typeinfo
, tdesc
);
576 if (get_basetype(typeinfo
, tdesc
))
578 else if (type_is_non_iface_pointer(typeinfo
, tdesc
))
581 if ((ref
= write_complex_struct_pointer_ref(typeinfo
, tdesc
, str
, len
)))
583 if (str
) *((short *)(str
+ pointer_layout
+ 2)) = ref
- (pointer_layout
+ 2);
589 ref
= write_type_tfs(typeinfo
, str
, len
, tdesc
, FALSE
, FALSE
);
590 if (str
) *((short *)(str
+ member_layout
+ 2)) = ref
- (member_layout
+ 2);
594 ITypeInfo_ReleaseVarDesc(typeinfo
, desc
);
598 static size_t write_struct_tfs(ITypeInfo
*typeinfo
, unsigned char *str
,
599 size_t *len
, TYPEATTR
*attr
)
601 unsigned char fc
= get_struct_fc(typeinfo
, attr
);
604 /* For the sake of simplicity, write pointer structs as complex structs. */
605 if (fc
== FC_PSTRUCT
)
606 fc
= FC_BOGUS_STRUCT
;
608 WRITE_CHAR (str
, *len
, fc
);
609 WRITE_CHAR (str
, *len
, attr
->cbAlignment
- 1);
610 WRITE_SHORT(str
, *len
, attr
->cbSizeInstance
);
613 write_simple_struct_tfs(typeinfo
, str
, len
, attr
);
614 else if (fc
== FC_BOGUS_STRUCT
)
615 write_complex_struct_tfs(typeinfo
, str
, len
, attr
);
620 static size_t write_array_tfs(ITypeInfo
*typeinfo
, unsigned char *str
,
621 size_t *len
, ARRAYDESC
*desc
)
623 unsigned char fc
= get_array_fc(typeinfo
, &desc
->tdescElem
);
624 unsigned char basetype
;
629 if (!(basetype
= get_basetype(typeinfo
, &desc
->tdescElem
)))
630 ref
= write_type_tfs(typeinfo
, str
, len
, &desc
->tdescElem
, FALSE
, FALSE
);
632 /* In theory arrays should be nested, but there's no reason not to marshal
633 * [x][y] as [x*y]. */
634 for (i
= 0; i
< desc
->cDims
; i
++) size
*= desc
->rgbounds
[i
].cElements
;
638 WRITE_CHAR(str
, *len
, fc
);
639 WRITE_CHAR(str
, *len
, 0);
640 if (fc
== FC_BOGUS_ARRAY
)
642 WRITE_SHORT(str
, *len
, size
);
643 WRITE_INT(str
, *len
, 0xffffffff); /* conformance */
644 WRITE_INT(str
, *len
, 0xffffffff); /* variance */
648 size
*= type_memsize(typeinfo
, &desc
->tdescElem
);
649 WRITE_INT(str
, *len
, size
);
653 WRITE_CHAR(str
, *len
, basetype
);
656 WRITE_CHAR (str
, *len
, FC_EMBEDDED_COMPLEX
);
657 WRITE_CHAR (str
, *len
, 0);
658 WRITE_SHORT(str
, *len
, ref
- *len
);
659 WRITE_CHAR (str
, *len
, FC_PAD
);
661 WRITE_CHAR(str
, *len
, FC_END
);
666 static size_t write_ip_tfs(unsigned char *str
, size_t *len
, const GUID
*iid
)
673 str
[*len
+1] = FC_CONSTANT_IID
;
674 memcpy(str
+ *len
+ 2, iid
, sizeof(*iid
));
676 *len
+= 2 + sizeof(*iid
);
681 static void get_default_iface(ITypeInfo
*typeinfo
, WORD count
, GUID
*iid
)
688 for (i
= 0; i
< count
; ++i
)
690 ITypeInfo_GetImplTypeFlags(typeinfo
, i
, &flags
);
691 if (flags
& IMPLTYPEFLAG_FDEFAULT
)
695 /* If no interface was explicitly marked default, choose the first one. */
699 ITypeInfo_GetRefTypeOfImplType(typeinfo
, i
, &reftype
);
700 ITypeInfo_GetRefTypeInfo(typeinfo
, reftype
, &refinfo
);
701 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
703 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
704 ITypeInfo_Release(refinfo
);
707 static size_t write_pointer_tfs(ITypeInfo
*typeinfo
, unsigned char *str
,
708 size_t *len
, TYPEDESC
*desc
, BOOL toplevel
, BOOL onstack
)
710 unsigned char basetype
, flags
= 0;
711 size_t ref
, off
= *len
;
716 if (desc
->vt
== VT_USERDEFINED
)
718 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
719 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
721 switch (attr
->typekind
)
724 assert(!toplevel
); /* toplevel base-type pointers should use IsSimpleRef */
725 WRITE_CHAR(str
, *len
, FC_UP
);
726 WRITE_CHAR(str
, *len
, FC_SIMPLE_POINTER
);
727 WRITE_CHAR(str
, *len
, FC_ENUM32
);
728 WRITE_CHAR(str
, *len
, FC_PAD
);
731 assert(!toplevel
); /* toplevel struct pointers should use IsSimpleRef */
732 ref
= write_struct_tfs(refinfo
, str
, len
, attr
);
734 WRITE_CHAR (str
, *len
, FC_UP
);
735 WRITE_CHAR (str
, *len
, 0);
736 WRITE_SHORT(str
, *len
, ref
- *len
);
738 case TKIND_INTERFACE
:
740 write_ip_tfs(str
, len
, &attr
->guid
);
743 get_default_iface(refinfo
, attr
->cImplTypes
, &guid
);
744 write_ip_tfs(str
, len
, &guid
);
747 off
= write_pointer_tfs(refinfo
, str
, len
, &attr
->tdescAlias
, toplevel
, onstack
);
750 FIXME("unhandled kind %#x\n", attr
->typekind
);
751 WRITE_SHORT(str
, *len
, 0);
755 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
756 ITypeInfo_Release(refinfo
);
758 else if ((basetype
= get_basetype(typeinfo
, desc
)))
760 assert(!toplevel
); /* toplevel base-type pointers should use IsSimpleRef */
761 WRITE_CHAR(str
, *len
, FC_UP
);
762 WRITE_CHAR(str
, *len
, FC_SIMPLE_POINTER
);
763 WRITE_CHAR(str
, *len
, basetype
);
764 WRITE_CHAR(str
, *len
, FC_PAD
);
768 ref
= write_type_tfs(typeinfo
, str
, len
, desc
, FALSE
, FALSE
);
770 if (onstack
) flags
|= FC_ALLOCED_ON_STACK
;
771 if (desc
->vt
== VT_PTR
|| desc
->vt
== VT_UNKNOWN
|| desc
->vt
== VT_DISPATCH
)
772 flags
|= FC_POINTER_DEREF
;
776 WRITE_CHAR (str
, *len
, toplevel
? FC_RP
: FC_UP
);
777 WRITE_CHAR (str
, *len
, flags
);
778 WRITE_SHORT(str
, *len
, ref
- *len
);
784 static size_t write_type_tfs(ITypeInfo
*typeinfo
, unsigned char *str
,
785 size_t *len
, TYPEDESC
*desc
, BOOL toplevel
, BOOL onstack
)
792 TRACE("vt %d%s\n", desc
->vt
, toplevel
? " (toplevel)" : "");
794 if ((off
= write_oleaut_tfs(desc
->vt
)))
800 return write_pointer_tfs(typeinfo
, str
, len
, desc
->lptdesc
, toplevel
, onstack
);
802 return write_array_tfs(typeinfo
, str
, len
, desc
->lpadesc
);
804 ITypeInfo_GetRefTypeInfo(typeinfo
, desc
->hreftype
, &refinfo
);
805 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
807 switch (attr
->typekind
)
810 off
= write_struct_tfs(refinfo
, str
, len
, attr
);
812 case TKIND_INTERFACE
:
814 /* These are treated as if they were interface pointers. */
816 write_ip_tfs(str
, len
, &attr
->guid
);
820 get_default_iface(refinfo
, attr
->cImplTypes
, &guid
);
821 write_ip_tfs(str
, len
, &guid
);
824 off
= write_type_tfs(refinfo
, str
, len
, &attr
->tdescAlias
, toplevel
, onstack
);
827 FIXME("unhandled kind %u\n", attr
->typekind
);
829 WRITE_SHORT(str
, *len
, 0);
833 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
834 ITypeInfo_Release(refinfo
);
837 /* base types are always embedded directly */
838 assert(!get_basetype(typeinfo
, desc
));
839 FIXME("unhandled type %u\n", desc
->vt
);
841 WRITE_SHORT(str
, *len
, 0);
848 static unsigned short get_stack_size(ITypeInfo
*typeinfo
, TYPEDESC
*desc
)
850 #if defined(__i386__) || defined(__arm__)
851 if (desc
->vt
== VT_CARRAY
)
852 return sizeof(void *);
853 return (type_memsize(typeinfo
, desc
) + 3) & ~3;
855 return sizeof(void *);
859 static const unsigned short MustSize
= 0x0001;
860 static const unsigned short MustFree
= 0x0002;
861 static const unsigned short IsIn
= 0x0008;
862 static const unsigned short IsOut
= 0x0010;
863 static const unsigned short IsReturn
= 0x0020;
864 static const unsigned short IsBasetype
= 0x0040;
865 static const unsigned short IsByValue
= 0x0080;
866 static const unsigned short IsSimpleRef
= 0x0100;
868 static HRESULT
get_param_pointer_info(ITypeInfo
*typeinfo
, TYPEDESC
*tdesc
, int is_in
,
869 int is_out
, unsigned short *server_size
, unsigned short *flags
,
870 unsigned char *basetype
, TYPEDESC
**tfs_tdesc
)
882 *server_size
= sizeof(void *);
886 if (type_pointer_is_iface(typeinfo
, tdesc
->lptdesc
))
889 *server_size
= sizeof(void *);
892 *server_size
= sizeof(void *);
895 *flags
|= IsSimpleRef
| MustFree
;
896 *server_size
= type_memsize(typeinfo
, tdesc
);
900 ITypeInfo_GetRefTypeInfo(typeinfo
, tdesc
->hreftype
, &refinfo
);
901 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
903 switch (attr
->typekind
)
906 *flags
|= IsSimpleRef
| IsBasetype
;
907 if (!is_in
&& is_out
)
908 *server_size
= sizeof(void *);
909 *basetype
= FC_ENUM32
;
912 *flags
|= IsSimpleRef
| MustFree
;
913 if (!is_in
&& is_out
)
914 *server_size
= attr
->cbSizeInstance
;
917 case TKIND_INTERFACE
:
923 hr
= get_param_pointer_info(refinfo
, &attr
->tdescAlias
, is_in
,
924 is_out
, server_size
, flags
, basetype
, tfs_tdesc
);
927 FIXME("unhandled kind %#x\n", attr
->typekind
);
932 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
933 ITypeInfo_Release(refinfo
);
936 *flags
|= IsSimpleRef
;
938 if (!is_in
&& is_out
)
939 *server_size
= type_memsize(typeinfo
, tdesc
);
940 if ((*basetype
= get_basetype(typeinfo
, tdesc
)))
941 *flags
|= IsBasetype
;
950 static HRESULT
get_param_info(ITypeInfo
*typeinfo
, TYPEDESC
*tdesc
, int is_in
,
951 int is_out
, unsigned short *server_size
, unsigned short *flags
,
952 unsigned char *basetype
, TYPEDESC
**tfs_tdesc
)
963 TRACE("vt %u\n", tdesc
->vt
);
968 #if !defined(__i386__) && !defined(__arm__)
969 *flags
|= IsSimpleRef
| MustFree
;
972 /* otherwise fall through */
976 *flags
|= IsByValue
| MustFree
;
984 return get_param_pointer_info(typeinfo
, tdesc
->lptdesc
, is_in
, is_out
,
985 server_size
, flags
, basetype
, tfs_tdesc
);
987 ITypeInfo_GetRefTypeInfo(typeinfo
, tdesc
->hreftype
, &refinfo
);
988 ITypeInfo_GetTypeAttr(refinfo
, &attr
);
990 switch (attr
->typekind
)
993 *flags
|= IsBasetype
;
994 *basetype
= FC_ENUM32
;
997 #if defined(__i386__) || defined(__arm__)
998 *flags
|= IsByValue
| MustFree
;
1000 if (attr
->cbSizeInstance
<= 8)
1001 *flags
|= IsByValue
| MustFree
;
1003 *flags
|= IsSimpleRef
| MustFree
;
1007 hr
= get_param_info(refinfo
, &attr
->tdescAlias
, is_in
, is_out
,
1008 server_size
, flags
, basetype
, tfs_tdesc
);
1011 case TKIND_INTERFACE
:
1012 case TKIND_DISPATCH
:
1014 /* These are treated as if they were interface pointers. */
1019 FIXME("unhandled kind %#x\n", attr
->typekind
);
1024 ITypeInfo_ReleaseTypeAttr(refinfo
, attr
);
1025 ITypeInfo_Release(refinfo
);
1028 if ((*basetype
= get_basetype(typeinfo
, tdesc
)))
1029 *flags
|= IsBasetype
;
1032 FIXME("unhandled type %u\n", tdesc
->vt
);
1041 static HRESULT
write_param_fs(ITypeInfo
*typeinfo
, unsigned char *type
,
1042 size_t *typelen
, unsigned char *proc
, size_t *proclen
, ELEMDESC
*desc
,
1043 BOOL is_return
, unsigned short *stack_offset
)
1045 USHORT param_flags
= desc
->paramdesc
.wParamFlags
;
1046 TYPEDESC
*tdesc
= &desc
->tdesc
, *tfs_tdesc
;
1047 unsigned short server_size
;
1048 unsigned short stack_size
= get_stack_size(typeinfo
, tdesc
);
1049 unsigned char basetype
;
1050 unsigned short flags
;
1055 is_out
= param_flags
& PARAMFLAG_FOUT
;
1056 is_in
= (param_flags
& PARAMFLAG_FIN
) || (!is_out
&& !is_return
);
1058 hr
= get_param_info(typeinfo
, tdesc
, is_in
, is_out
, &server_size
, &flags
,
1059 &basetype
, &tfs_tdesc
);
1061 if (is_in
) flags
|= IsIn
;
1062 if (is_out
) flags
|= IsOut
;
1063 if (is_return
) flags
|= IsOut
| IsReturn
;
1065 server_size
= (server_size
+ 7) / 8;
1066 if (server_size
>= 8) server_size
= 0;
1067 flags
|= server_size
<< 13;
1070 off
= write_type_tfs(typeinfo
, type
, typelen
, tfs_tdesc
, TRUE
, server_size
!= 0);
1074 WRITE_SHORT(proc
, *proclen
, flags
);
1075 WRITE_SHORT(proc
, *proclen
, *stack_offset
);
1076 WRITE_SHORT(proc
, *proclen
, basetype
? basetype
: off
);
1078 *stack_offset
+= stack_size
;
1084 static void write_proc_func_header(ITypeInfo
*typeinfo
, FUNCDESC
*desc
,
1085 WORD proc_idx
, unsigned char *proc
, size_t *proclen
)
1087 unsigned short stack_size
= 2 * sizeof(void *); /* This + return */
1089 unsigned short float_mask
= 0;
1090 unsigned char basetype
;
1094 WRITE_CHAR (proc
, *proclen
, FC_AUTO_HANDLE
);
1095 WRITE_CHAR (proc
, *proclen
, Oi_OBJECT_PROC
| Oi_OBJ_USE_V2_INTERPRETER
);
1096 WRITE_SHORT(proc
, *proclen
, proc_idx
);
1097 for (param_idx
= 0; param_idx
< desc
->cParams
; param_idx
++)
1098 stack_size
+= get_stack_size(typeinfo
, &desc
->lprgelemdescParam
[param_idx
].tdesc
);
1099 WRITE_SHORT(proc
, *proclen
, stack_size
);
1101 WRITE_SHORT(proc
, *proclen
, 0); /* constant_client_buffer_size */
1102 WRITE_SHORT(proc
, *proclen
, 0); /* constant_server_buffer_size */
1104 WRITE_CHAR (proc
, *proclen
, 0x47); /* HasExtensions | HasReturn | ClientMustSize | ServerMustSize */
1106 WRITE_CHAR (proc
, *proclen
, 0x07); /* HasReturn | ClientMustSize | ServerMustSize */
1108 WRITE_CHAR (proc
, *proclen
, desc
->cParams
+ 1); /* incl. return value */
1110 WRITE_CHAR (proc
, *proclen
, 10); /* extension size */
1111 WRITE_CHAR (proc
, *proclen
, 0); /* INTERPRETER_OPT_FLAGS2 */
1112 WRITE_SHORT(proc
, *proclen
, 0); /* ClientCorrHint */
1113 WRITE_SHORT(proc
, *proclen
, 0); /* ServerCorrHint */
1114 WRITE_SHORT(proc
, *proclen
, 0); /* NotifyIndex */
1115 for (param_idx
= 0; param_idx
< desc
->cParams
&& param_idx
< 3; param_idx
++)
1117 basetype
= get_basetype(typeinfo
, &desc
->lprgelemdescParam
[param_idx
].tdesc
);
1118 if (basetype
== FC_FLOAT
)
1119 float_mask
|= (1 << ((param_idx
+ 1) * 2));
1120 else if (basetype
== FC_DOUBLE
)
1121 float_mask
|= (2 << ((param_idx
+ 1) * 2));
1123 WRITE_SHORT(proc
, *proclen
, float_mask
);
1127 static HRESULT
write_iface_fs(ITypeInfo
*typeinfo
, WORD funcs
, WORD parentfuncs
,
1128 unsigned char *type
, size_t *typelen
, unsigned char *proc
,
1129 size_t *proclen
, unsigned short *offset
)
1131 unsigned short stack_offset
;
1132 WORD proc_idx
, param_idx
;
1136 for (proc_idx
= 3; proc_idx
< parentfuncs
; proc_idx
++)
1139 offset
[proc_idx
- 3] = -1;
1142 for (proc_idx
= 0; proc_idx
< funcs
; proc_idx
++)
1144 TRACE("Writing procedure %d.\n", proc_idx
);
1146 hr
= ITypeInfo_GetFuncDesc(typeinfo
, proc_idx
, &desc
);
1147 if (FAILED(hr
)) return hr
;
1150 offset
[proc_idx
+ parentfuncs
- 3] = *proclen
;
1152 write_proc_func_header(typeinfo
, desc
, proc_idx
+ parentfuncs
, proc
, proclen
);
1154 stack_offset
= sizeof(void *); /* This */
1155 for (param_idx
= 0; param_idx
< desc
->cParams
; param_idx
++)
1157 TRACE("Writing parameter %d.\n", param_idx
);
1158 hr
= write_param_fs(typeinfo
, type
, typelen
, proc
, proclen
,
1159 &desc
->lprgelemdescParam
[param_idx
], FALSE
, &stack_offset
);
1162 ITypeInfo_ReleaseFuncDesc(typeinfo
, desc
);
1167 hr
= write_param_fs(typeinfo
, type
, typelen
, proc
, proclen
,
1168 &desc
->elemdescFunc
, TRUE
, &stack_offset
);
1169 ITypeInfo_ReleaseFuncDesc(typeinfo
, desc
);
1170 if (FAILED(hr
)) return hr
;
1176 static HRESULT
build_format_strings(ITypeInfo
*typeinfo
, WORD funcs
,
1177 WORD parentfuncs
, const unsigned char **type_ret
,
1178 const unsigned char **proc_ret
, unsigned short **offset_ret
)
1181 const unsigned char *tfs
= get_type_format_string( &tfs_size
);
1182 size_t typelen
= tfs_size
, proclen
= 0;
1183 unsigned char *type
, *proc
;
1184 unsigned short *offset
;
1187 hr
= write_iface_fs(typeinfo
, funcs
, parentfuncs
, NULL
, &typelen
, NULL
, &proclen
, NULL
);
1188 if (FAILED(hr
)) return hr
;
1190 type
= heap_alloc(typelen
);
1191 proc
= heap_alloc(proclen
);
1192 offset
= heap_alloc((parentfuncs
+ funcs
- 3) * sizeof(*offset
));
1193 if (!type
|| !proc
|| !offset
)
1195 ERR("Failed to allocate format strings.\n");
1200 memcpy(type
, tfs
, tfs_size
);
1204 hr
= write_iface_fs(typeinfo
, funcs
, parentfuncs
, type
, &typelen
, proc
, &proclen
, offset
);
1209 *offset_ret
= offset
;
1220 /* Common helper for Create{Proxy,Stub}FromTypeInfo(). */
1221 static HRESULT
get_iface_info(ITypeInfo
*typeinfo
, WORD
*funcs
, WORD
*parentfuncs
,
1222 GUID
*parentiid
, ITypeInfo
**real_typeinfo
)
1224 ITypeInfo
*parentinfo
;
1233 /* Dual interfaces report their size to be sizeof(IDispatchVtbl) and their
1234 * implemented type to be IDispatch. We need to retrieve the underlying
1235 * interface to get that information. */
1236 hr
= ITypeInfo_GetTypeAttr(typeinfo
, &typeattr
);
1239 typekind
= typeattr
->typekind
;
1240 ITypeInfo_ReleaseTypeAttr(typeinfo
, typeattr
);
1241 if (typekind
== TKIND_DISPATCH
)
1243 hr
= ITypeInfo_GetRefTypeOfImplType(typeinfo
, -1, &reftype
);
1247 hr
= ITypeInfo_GetRefTypeInfo(typeinfo
, reftype
, real_typeinfo
);
1252 ITypeInfo_AddRef(*real_typeinfo
= typeinfo
);
1254 hr
= ITypeInfo_GetContainingTypeLib(*real_typeinfo
, &typelib
, NULL
);
1258 hr
= ITypeLib_GetLibAttr(typelib
, &libattr
);
1261 ITypeLib_Release(typelib
);
1264 syskind
= libattr
->syskind
;
1265 ITypeLib_ReleaseTLibAttr(typelib
, libattr
);
1266 ITypeLib_Release(typelib
);
1268 hr
= ITypeInfo_GetTypeAttr(*real_typeinfo
, &typeattr
);
1271 *funcs
= typeattr
->cFuncs
;
1272 *parentfuncs
= typeattr
->cbSizeVft
/ (syskind
== SYS_WIN64
? 8 : 4) - *funcs
;
1273 ITypeInfo_ReleaseTypeAttr(*real_typeinfo
, typeattr
);
1275 hr
= ITypeInfo_GetRefTypeOfImplType(*real_typeinfo
, 0, &reftype
);
1278 hr
= ITypeInfo_GetRefTypeInfo(*real_typeinfo
, reftype
, &parentinfo
);
1282 hr
= ITypeInfo_GetTypeAttr(parentinfo
, &typeattr
);
1285 *parentiid
= typeattr
->guid
;
1286 ITypeInfo_ReleaseTypeAttr(parentinfo
, typeattr
);
1288 ITypeInfo_Release(parentinfo
);
1293 ITypeInfo_Release(*real_typeinfo
);
1297 static void init_stub_desc(MIDL_STUB_DESC
*desc
)
1299 desc
->pfnAllocate
= NdrOleAllocate
;
1300 desc
->pfnFree
= NdrOleFree
;
1301 desc
->Version
= 0x50002;
1302 desc
->aUserMarshalQuadruple
= get_ndr_types_proxy_info()->pStubDesc
->aUserMarshalQuadruple
;
1303 /* type format string is initialized with proc format string and offset table */
1306 struct typelib_proxy
1310 MIDL_STUB_DESC stub_desc
;
1311 MIDL_STUBLESS_PROXY_INFO proxy_info
;
1312 CInterfaceProxyVtbl
*proxy_vtbl
;
1313 unsigned short *offset_table
;
1316 static ULONG WINAPI
typelib_proxy_Release(IRpcProxyBuffer
*iface
)
1318 struct typelib_proxy
*proxy
= CONTAINING_RECORD(iface
, struct typelib_proxy
, proxy
.IRpcProxyBuffer_iface
);
1319 ULONG refcount
= InterlockedDecrement(&proxy
->proxy
.RefCount
);
1321 TRACE("(%p) decreasing refs to %d\n", proxy
, refcount
);
1325 if (proxy
->proxy
.pChannel
)
1326 IRpcProxyBuffer_Disconnect(&proxy
->proxy
.IRpcProxyBuffer_iface
);
1327 if (proxy
->proxy
.base_object
)
1328 IUnknown_Release(proxy
->proxy
.base_object
);
1329 if (proxy
->proxy
.base_proxy
)
1330 IRpcProxyBuffer_Release(proxy
->proxy
.base_proxy
);
1331 heap_free((void *)proxy
->stub_desc
.pFormatTypes
);
1332 heap_free((void *)proxy
->proxy_info
.ProcFormatString
);
1333 heap_free(proxy
->offset_table
);
1334 heap_free(proxy
->proxy_vtbl
);
1340 static const IRpcProxyBufferVtbl typelib_proxy_vtbl
=
1342 StdProxy_QueryInterface
,
1344 typelib_proxy_Release
,
1346 StdProxy_Disconnect
,
1349 static HRESULT
typelib_proxy_init(struct typelib_proxy
*proxy
, IUnknown
*outer
,
1350 ULONG count
, const GUID
*parentiid
, IRpcProxyBuffer
**proxy_buffer
, void **out
)
1352 if (!fill_stubless_table((IUnknownVtbl
*)proxy
->proxy_vtbl
->Vtbl
, count
))
1353 return E_OUTOFMEMORY
;
1355 if (!outer
) outer
= (IUnknown
*)&proxy
->proxy
;
1357 proxy
->proxy
.IRpcProxyBuffer_iface
.lpVtbl
= &typelib_proxy_vtbl
;
1358 proxy
->proxy
.PVtbl
= proxy
->proxy_vtbl
->Vtbl
;
1359 proxy
->proxy
.RefCount
= 1;
1360 proxy
->proxy
.piid
= proxy
->proxy_vtbl
->header
.piid
;
1361 proxy
->proxy
.pUnkOuter
= outer
;
1363 if (!IsEqualGUID(parentiid
, &IID_IUnknown
))
1365 HRESULT hr
= create_proxy(parentiid
, NULL
, &proxy
->proxy
.base_proxy
,
1366 (void **)&proxy
->proxy
.base_object
);
1367 if (FAILED(hr
)) return hr
;
1370 *proxy_buffer
= &proxy
->proxy
.IRpcProxyBuffer_iface
;
1371 *out
= &proxy
->proxy
.PVtbl
;
1372 IUnknown_AddRef((IUnknown
*)*out
);
1377 HRESULT WINAPI
CreateProxyFromTypeInfo(ITypeInfo
*typeinfo
, IUnknown
*outer
,
1378 REFIID iid
, IRpcProxyBuffer
**proxy_buffer
, void **out
)
1380 struct typelib_proxy
*proxy
;
1381 WORD funcs
, parentfuncs
, i
;
1382 ITypeInfo
*real_typeinfo
;
1386 TRACE("typeinfo %p, outer %p, iid %s, proxy_buffer %p, out %p.\n",
1387 typeinfo
, outer
, debugstr_guid(iid
), proxy_buffer
, out
);
1389 hr
= get_iface_info(typeinfo
, &funcs
, &parentfuncs
, &parentiid
, &real_typeinfo
);
1393 if (!(proxy
= heap_alloc_zero(sizeof(*proxy
))))
1395 ERR("Failed to allocate proxy object.\n");
1396 ITypeInfo_Release(real_typeinfo
);
1397 return E_OUTOFMEMORY
;
1400 init_stub_desc(&proxy
->stub_desc
);
1401 proxy
->proxy_info
.pStubDesc
= &proxy
->stub_desc
;
1403 proxy
->proxy_vtbl
= heap_alloc_zero(sizeof(proxy
->proxy_vtbl
->header
) + (funcs
+ parentfuncs
) * sizeof(void *));
1404 if (!proxy
->proxy_vtbl
)
1406 ERR("Failed to allocate proxy vtbl.\n");
1408 ITypeInfo_Release(real_typeinfo
);
1409 return E_OUTOFMEMORY
;
1411 proxy
->proxy_vtbl
->header
.pStublessProxyInfo
= &proxy
->proxy_info
;
1413 proxy
->proxy_vtbl
->header
.piid
= &proxy
->iid
;
1414 fill_delegated_proxy_table((IUnknownVtbl
*)proxy
->proxy_vtbl
->Vtbl
, parentfuncs
);
1415 for (i
= 0; i
< funcs
; i
++)
1416 proxy
->proxy_vtbl
->Vtbl
[parentfuncs
+ i
] = (void *)-1;
1418 hr
= build_format_strings(real_typeinfo
, funcs
, parentfuncs
, &proxy
->stub_desc
.pFormatTypes
,
1419 &proxy
->proxy_info
.ProcFormatString
, &proxy
->offset_table
);
1420 ITypeInfo_Release(real_typeinfo
);
1423 heap_free(proxy
->proxy_vtbl
);
1427 proxy
->proxy_info
.FormatStringOffset
= &proxy
->offset_table
[-3];
1429 hr
= typelib_proxy_init(proxy
, outer
, funcs
+ parentfuncs
, &parentiid
, proxy_buffer
, out
);
1432 heap_free((void *)proxy
->stub_desc
.pFormatTypes
);
1433 heap_free((void *)proxy
->proxy_info
.ProcFormatString
);
1434 heap_free((void *)proxy
->offset_table
);
1435 heap_free(proxy
->proxy_vtbl
);
1444 cstdstubbuffer_delegating_t stub
;
1446 MIDL_STUB_DESC stub_desc
;
1447 MIDL_SERVER_INFO server_info
;
1448 CInterfaceStubVtbl stub_vtbl
;
1449 unsigned short *offset_table
;
1450 PRPC_STUB_FUNCTION
*dispatch_table
;
1453 static ULONG WINAPI
typelib_stub_Release(IRpcStubBuffer
*iface
)
1455 struct typelib_stub
*stub
= CONTAINING_RECORD(iface
, struct typelib_stub
, stub
.stub_buffer
);
1456 ULONG refcount
= InterlockedDecrement(&stub
->stub
.stub_buffer
.RefCount
);
1458 TRACE("(%p) decreasing refs to %d\n", stub
, refcount
);
1462 /* test_Release shows that native doesn't call Disconnect here.
1463 We'll leave it in for the time being. */
1464 IRpcStubBuffer_Disconnect(iface
);
1466 if (stub
->stub
.base_stub
)
1468 IRpcStubBuffer_Release(stub
->stub
.base_stub
);
1469 release_delegating_vtbl(stub
->stub
.base_obj
);
1470 heap_free(stub
->dispatch_table
);
1473 heap_free((void *)stub
->stub_desc
.pFormatTypes
);
1474 heap_free((void *)stub
->server_info
.ProcString
);
1475 heap_free(stub
->offset_table
);
1482 static HRESULT
typelib_stub_init(struct typelib_stub
*stub
, IUnknown
*server
,
1483 const GUID
*parentiid
, IRpcStubBuffer
**stub_buffer
)
1487 hr
= IUnknown_QueryInterface(server
, stub
->stub_vtbl
.header
.piid
,
1488 (void **)&stub
->stub
.stub_buffer
.pvServerObject
);
1491 WARN("Failed to get interface %s, hr %#x.\n",
1492 debugstr_guid(stub
->stub_vtbl
.header
.piid
), hr
);
1493 stub
->stub
.stub_buffer
.pvServerObject
= server
;
1494 IUnknown_AddRef(server
);
1497 if (!IsEqualGUID(parentiid
, &IID_IUnknown
))
1499 stub
->stub
.base_obj
= get_delegating_vtbl(stub
->stub_vtbl
.header
.DispatchTableCount
);
1500 hr
= create_stub(parentiid
, (IUnknown
*)&stub
->stub
.base_obj
, &stub
->stub
.base_stub
);
1503 release_delegating_vtbl(stub
->stub
.base_obj
);
1504 IUnknown_Release(stub
->stub
.stub_buffer
.pvServerObject
);
1509 stub
->stub
.stub_buffer
.lpVtbl
= &stub
->stub_vtbl
.Vtbl
;
1510 stub
->stub
.stub_buffer
.RefCount
= 1;
1512 *stub_buffer
= (IRpcStubBuffer
*)&stub
->stub
.stub_buffer
;
1516 HRESULT WINAPI
CreateStubFromTypeInfo(ITypeInfo
*typeinfo
, REFIID iid
,
1517 IUnknown
*server
, IRpcStubBuffer
**stub_buffer
)
1519 WORD funcs
, parentfuncs
, i
;
1520 struct typelib_stub
*stub
;
1521 ITypeInfo
*real_typeinfo
;
1525 TRACE("typeinfo %p, iid %s, server %p, stub_buffer %p.\n",
1526 typeinfo
, debugstr_guid(iid
), server
, stub_buffer
);
1528 hr
= get_iface_info(typeinfo
, &funcs
, &parentfuncs
, &parentiid
, &real_typeinfo
);
1532 if (!(stub
= heap_alloc_zero(sizeof(*stub
))))
1534 ERR("Failed to allocate stub object.\n");
1535 ITypeInfo_Release(real_typeinfo
);
1536 return E_OUTOFMEMORY
;
1539 init_stub_desc(&stub
->stub_desc
);
1540 stub
->server_info
.pStubDesc
= &stub
->stub_desc
;
1542 hr
= build_format_strings(real_typeinfo
, funcs
, parentfuncs
, &stub
->stub_desc
.pFormatTypes
,
1543 &stub
->server_info
.ProcString
, &stub
->offset_table
);
1544 ITypeInfo_Release(real_typeinfo
);
1550 stub
->server_info
.FmtStringOffset
= &stub
->offset_table
[-3];
1553 stub
->stub_vtbl
.header
.piid
= &stub
->iid
;
1554 stub
->stub_vtbl
.header
.pServerInfo
= &stub
->server_info
;
1555 stub
->stub_vtbl
.header
.DispatchTableCount
= funcs
+ parentfuncs
;
1557 if (!IsEqualGUID(&parentiid
, &IID_IUnknown
))
1559 stub
->dispatch_table
= heap_alloc((funcs
+ parentfuncs
) * sizeof(void *));
1560 for (i
= 3; i
< parentfuncs
; i
++)
1561 stub
->dispatch_table
[i
- 3] = NdrStubForwardingFunction
;
1562 for (; i
< funcs
+ parentfuncs
; i
++)
1563 stub
->dispatch_table
[i
- 3] = (PRPC_STUB_FUNCTION
)NdrStubCall2
;
1564 stub
->stub_vtbl
.header
.pDispatchTable
= &stub
->dispatch_table
[-3];
1565 stub
->stub_vtbl
.Vtbl
= CStdStubBuffer_Delegating_Vtbl
;
1568 stub
->stub_vtbl
.Vtbl
= CStdStubBuffer_Vtbl
;
1569 stub
->stub_vtbl
.Vtbl
.Release
= typelib_stub_Release
;
1571 hr
= typelib_stub_init(stub
, server
, &parentiid
, stub_buffer
);
1574 heap_free((void *)stub
->stub_desc
.pFormatTypes
);
1575 heap_free((void *)stub
->server_info
.ProcString
);
1576 heap_free(stub
->offset_table
);