Signed-off-by: Zebediah Figura z.figura12@gmail.com ---
Automation types (BSTR, VARIANT, LPSAFEARRAY) are user-marshalled, which means that they require long format strings to represent the wire form of the data. Ideally this should be generated by widl at build time. However, we can't just create a dummy idl and retrieve the type format string from the generated proxy file, since we have no way of retrieving the length of the type format string (and we do need a way of copying it, since it must be contiguous with ours). Instead the solution I propose is to use a script to parse the type format string (and the other parts that we need) into a generated file, to be done at build time. Since we need widl to do this, and since it can be done very easily in shell script, I have embedded it as a Makefile rule.
Makefile.in | 1 + dlls/rpcrt4/Makefile.in | 21 ++++++++++++++++++++- dlls/rpcrt4/ndr_typelib.c | 28 ++++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 3 deletions(-)
diff --git a/Makefile.in b/Makefile.in index c1242afc01..25f535dc7f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -76,6 +76,7 @@ SUBDIRS = @SUBDIRS@ RUNTESTFLAGS = -q -P wine MAKEDEP = $(TOOLSDIR)/tools/makedep$(TOOLSEXT) WRC = $(TOOLSDIR)/tools/wrc/wrc$(TOOLSEXT) +WIDL = $(TOOLSDIR)/tools/widl/widl$(TOOLSEXT) PACKAGE_VERSION = @PACKAGE_VERSION@ SED_CMD = LC_ALL=C sed -e 's,@bindir@,$(bindir),g' -e 's,@dlldir@,$(dlldir),g' -e 's,@srcdir@,$(srcdir),g' -e 's,@PACKAGE_STRING@,@PACKAGE_STRING@,g' -e 's,@PACKAGE_VERSION@,@PACKAGE_VERSION@,g' LDRPATH_INSTALL = @LDRPATH_INSTALL@ diff --git a/dlls/rpcrt4/Makefile.in b/dlls/rpcrt4/Makefile.in index ad67edf92e..aa80c2e7c7 100644 --- a/dlls/rpcrt4/Makefile.in +++ b/dlls/rpcrt4/Makefile.in @@ -2,7 +2,7 @@ EXTRADEFS = -D_RPCRT4_ -DMSWMSG MODULE = rpcrt4.dll IMPORTLIB = rpcrt4 IMPORTS = uuid advapi32 -DELAYIMPORTS = iphlpapi wininet secur32 user32 ws2_32 +DELAYIMPORTS = iphlpapi wininet secur32 user32 ws2_32 oleaut32
C_SRCS = \ cproxy.c \ @@ -28,3 +28,22 @@ C_SRCS = \ RC_SRCS = version.rc
IDL_SRCS = epm.idl + +EXTRA_OBJS = ndr_typelib_generated.o + +ndr_typelib_generated.c: $(WIDL) + echo > ndr_typelib_generated.c '/* Automatically generated from Makefile.in, do not edit */' && \ + echo >> ndr_typelib_generated.c '#include "oaidl.h"' && \ + echo >> ndr_typelib_generated.c '#include "rpcproxy.h"' && \ + echo > ndr_typelib_generated.idl 'import "oaidl.idl"; [object] interface dummy {void dummy(BSTR a, IUnknown *b, IDispatch *c, VARIANT d, LPSAFEARRAY e); }' && \ + $(WIDL) $(WIDLFLAGS) -I $(top_srcdir)/include -p -o ndr_typelib_generated_p.c ndr_typelib_generated.idl && \ + echo >> ndr_typelib_generated.c 'const unsigned char oleaut_tfs[] = {' && \ + awk '/__MIDL_TypeFormatString =/,/};/' ndr_typelib_generated_p.c | head -n -2 | tail -n +5 >> ndr_typelib_generated.c && \ + echo >> ndr_typelib_generated.c '};' && \ + sed -n -e 's/#define TYPE_FORMAT_STRING_SIZE ([0-9]+)/const size_t oleaut_tfs_size = \1;/p' ndr_typelib_generated_p.c >> ndr_typelib_generated.c && \ + echo >> ndr_typelib_generated.c 'const unsigned short oleaut_offsets[] = {' && \ + sed -n -e 's/.*&__MIDL_TypeFormatString.Format[([0-9]+)].*/ \1,/p' ndr_typelib_generated_p.c | head -n 5 >> ndr_typelib_generated.c && \ + echo >> ndr_typelib_generated.c '};' && \ + echo >> ndr_typelib_generated.c 'const USER_MARSHAL_ROUTINE_QUADRUPLE oleaut_user_marshal[] = ' && \ + awk '/UserMarshalRoutines[] =/,/};/' ndr_typelib_generated_p.c | tail -n +2 >> ndr_typelib_generated.c && \ + rm ndr_typelib_generated_p.c ndr_typelib_generated.idl diff --git a/dlls/rpcrt4/ndr_typelib.c b/dlls/rpcrt4/ndr_typelib.c index f78dd85b8a..687db1a5fa 100644 --- a/dlls/rpcrt4/ndr_typelib.c +++ b/dlls/rpcrt4/ndr_typelib.c @@ -42,6 +42,25 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str, #define WRITE_INT(str, len, val) \ do { if ((str)) *((int *)((str) + (len))) = (val); (len) += 4; } while (0)
+extern const unsigned char oleaut_tfs[]; +extern const size_t oleaut_tfs_size; +extern const unsigned short oleaut_offsets[5]; +extern const USER_MARSHAL_ROUTINE_QUADRUPLE oleaut_user_marshal[]; + +static unsigned short write_oleaut_tfs(VARTYPE vt) +{ + switch (vt) + { + case VT_BSTR: return oleaut_offsets[0]; + case VT_UNKNOWN: return oleaut_offsets[1]; + case VT_DISPATCH: return oleaut_offsets[2]; + case VT_VARIANT: return oleaut_offsets[3]; + case VT_SAFEARRAY: return oleaut_offsets[4]; + } + + return 0; +} + static unsigned char get_base_type(VARTYPE vt) { switch (vt) @@ -341,6 +360,9 @@ static size_t write_type_tfs(ITypeInfo *typeinfo, unsigned char *str,
TRACE("vt %d%s\n", desc->vt, toplevel ? " (toplevel)" : "");
+ if ((off = write_oleaut_tfs(desc->vt))) + return off; + switch (desc->vt) { case VT_PTR: @@ -685,7 +707,7 @@ static HRESULT build_format_strings(ITypeInfo *typeinfo, WORD funcs, const unsigned char **type_ret, const unsigned char **proc_ret, unsigned short **offset_ret) { - size_t typelen = 0, proclen = 0; + size_t typelen = oleaut_tfs_size, proclen = 0; unsigned char *type, *proc; unsigned short *offset; HRESULT hr; @@ -703,7 +725,8 @@ static HRESULT build_format_strings(ITypeInfo *typeinfo, WORD funcs, goto err; }
- typelen = 0; + memcpy(type, oleaut_tfs, oleaut_tfs_size); + typelen = oleaut_tfs_size; proclen = 0;
hr = write_iface_fs(typeinfo, funcs, type, &typelen, proc, &proclen, offset); @@ -760,6 +783,7 @@ static void init_stub_desc(MIDL_STUB_DESC *desc) desc->pfnAllocate = NdrOleAllocate; desc->pfnFree = NdrOleFree; desc->Version = 0x50002; + desc->aUserMarshalQuadruple = oleaut_user_marshal; /* type format string is initialized with proc format string and offset table */ }