[PATCH 10/14] rpcrt4: Write type format strings for Automation types.

Zebediah Figura z.figura12 at gmail.com
Sat Nov 3 18:07:22 CDT 2018


Signed-off-by: Zebediah Figura <z.figura12 at 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, at bindir\@,$(bindir),g' -e 's, at dlldir\@,$(dlldir),g' -e 's, at srcdir\@,$(srcdir),g' -e 's, at PACKAGE_STRING\@, at PACKAGE_STRING@,g' -e 's, at PACKAGE_VERSION\@, at 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 */
 }
 
-- 
2.19.1




More information about the wine-devel mailing list