commit d541cb606421272065c0a2ef95343b79336d3b17
Author: Jacek Caban <jacek@codeweavers.com>
Date:   Wed Jul 25 11:18:45 2012 +0200

    widl: Added support for type safe C interfaces

diff --git a/include/objbase.h b/include/objbase.h
index c366a28..d54377a 100644
--- a/include/objbase.h
+++ b/include/objbase.h
@@ -204,7 +204,7 @@
 #define THIS_ INTERFACE *This,
 #define THIS  INTERFACE *This
 
-#define interface struct
+#define interface __widl_interface
 
 #ifdef __WINESRC__
 #define CONST_VTABLE
diff --git a/include/rpcndr.h b/include/rpcndr.h
index 514f1ce..195c634 100644
--- a/include/rpcndr.h
+++ b/include/rpcndr.h
@@ -137,8 +137,14 @@ typedef void (__RPC_USER *NDR_RUNDOWN)(void *context);
 typedef void (__RPC_USER *NDR_NOTIFY_ROUTINE)(void);
 typedef void (__RPC_USER *NDR_NOTIFY2_ROUTINE)(boolean flag);
 
+#if !defined(__cplusplus) && defined(WIDL_TYPE_SAFE_C_INTERFACE)
+#define __widl_interface union
+#else
+#define __widl_interface struct
+#endif
+
 #define DECLSPEC_UUID(x)
-#define MIDL_INTERFACE(x)   struct
+#define MIDL_INTERFACE(x)   __widl_interface
 
 struct _MIDL_STUB_MESSAGE;
 struct _MIDL_STUB_DESC;
@@ -226,7 +232,7 @@ typedef struct _MIDL_STUB_MESSAGE
   void *pvDestContext;
   NDR_SCONTEXT *SavedContextHandles;
   LONG ParamNumber;
-  struct IRpcChannelBuffer *pRpcChannelBuffer;
+  __widl_interface IRpcChannelBuffer *pRpcChannelBuffer;
   PARRAY_INFO pArrayInfo;
   ULONG *SizePtrCountArray;
   ULONG *SizePtrOffsetArray;
@@ -471,7 +477,7 @@ typedef struct _FULL_PTR_XLAT_TABLES {
   XLAT_SIDE               XlatSide;
 } FULL_PTR_XLAT_TABLES,  *PFULL_PTR_XLAT_TABLES;
 
-struct IRpcStubBuffer;
+__widl_interface IRpcStubBuffer;
 
 typedef ULONG error_status_t;
 typedef void  * NDR_CCONTEXT;
@@ -487,7 +493,7 @@ typedef struct _NDR_USER_MARSHAL_INFO_LEVEL1
     ULONG BufferSize;
     void * (__WINE_ALLOC_SIZE(1) __RPC_API *pfnAllocate)(SIZE_T);
     void (__RPC_API *pfnFree)(void *);
-    struct IRpcChannelBuffer *pRpcChannelBuffer;
+    __widl_interface IRpcChannelBuffer *pRpcChannelBuffer;
     ULONG_PTR Reserved[5];
 } NDR_USER_MARSHAL_INFO_LEVEL1;
 
@@ -668,13 +674,13 @@ RPCRTAPI void RPC_ENTRY
   NdrAsyncServerCall( PRPC_MESSAGE pRpcMsg );
 
 RPCRTAPI LONG RPC_ENTRY
-  NdrStubCall2( struct IRpcStubBuffer* pThis, struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, DWORD * pdwStubPhase );
+  NdrStubCall2( __widl_interface IRpcStubBuffer* pThis, __widl_interface IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, DWORD * pdwStubPhase );
 RPCRTAPI LONG RPC_ENTRY
-  NdrStubCall( struct IRpcStubBuffer* pThis, struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, DWORD * pdwStubPhase );
+  NdrStubCall( __widl_interface IRpcStubBuffer* pThis, __widl_interface IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, DWORD * pdwStubPhase );
 RPCRTAPI LONG RPC_ENTRY
-  NdrAsyncStubCall( struct IRpcStubBuffer* pThis, struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, DWORD * pdwStubPhase );
+  NdrAsyncStubCall( __widl_interface IRpcStubBuffer* pThis, __widl_interface IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, DWORD * pdwStubPhase );
 RPCRTAPI LONG RPC_ENTRY
-  NdrDcomAsyncStubCall( struct IRpcStubBuffer* pThis, struct IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, DWORD * pdwStubPhase );
+  NdrDcomAsyncStubCall( __widl_interface IRpcStubBuffer* pThis, __widl_interface IRpcChannelBuffer* pChannel, PRPC_MESSAGE pRpcMsg, DWORD * pdwStubPhase );
 
 RPCRTAPI void* RPC_ENTRY
   NdrAllocate( PMIDL_STUB_MESSAGE pStubMsg, SIZE_T Len ) __WINE_ALLOC_SIZE(2);
@@ -706,9 +712,9 @@ RPCRTAPI unsigned char* RPC_ENTRY
 RPCRTAPI void RPC_ENTRY
   NdrServerInitializeMarshall( PRPC_MESSAGE pRpcMsg, PMIDL_STUB_MESSAGE pStubMsg  );
 RPCRTAPI void RPC_ENTRY
-  NdrServerMarshall( struct IRpcStubBuffer *pThis, struct IRpcChannelBuffer *pChannel, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat );
+  NdrServerMarshall( __widl_interface IRpcStubBuffer *pThis, __widl_interface IRpcChannelBuffer *pChannel, PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat );
 RPCRTAPI void RPC_ENTRY
-  NdrServerUnmarshall( struct IRpcChannelBuffer *pChannel, PRPC_MESSAGE pRpcMsg,
+  NdrServerUnmarshall( __widl_interface IRpcChannelBuffer *pChannel, PRPC_MESSAGE pRpcMsg,
                        PMIDL_STUB_MESSAGE pStubMsg, PMIDL_STUB_DESC pStubDesc,
                        PFORMAT_STRING pFormat, void *pParamList );
 RPCRTAPI unsigned char* RPC_ENTRY
diff --git a/tools/widl/header.c b/tools/widl/header.c
index 0b2b9d5..5817fac 100644
--- a/tools/widl/header.c
+++ b/tools/widl/header.c
@@ -1094,6 +1094,7 @@ static void write_com_interface_end(FILE *header, type_t *iface)
 {
   int dispinterface = is_attr(iface->attrs, ATTR_DISPINTERFACE);
   const UUID *uuid = get_attrp(iface->attrs, ATTR_UUID);
+  type_t *parent_iface = type_iface_get_inherit(iface);
 
   if (uuid)
       write_guid(header, dispinterface ? "DIID" : "IID", iface->name, uuid);
@@ -1104,10 +1105,9 @@ static void write_com_interface_end(FILE *header, type_t *iface)
       fprintf(header, "MIDL_INTERFACE(\"%s\")\n", uuid_string(uuid));
   else
       fprintf(header, "interface ");
-  if (type_iface_get_inherit(iface))
+  if (parent_iface)
   {
-    fprintf(header, "%s : public %s\n", iface->name,
-            type_iface_get_inherit(iface)->name);
+    fprintf(header, "%s : public %s\n", iface->name, parent_iface->name);
     fprintf(header, "{\n");
   }
   else
@@ -1125,7 +1125,7 @@ static void write_com_interface_end(FILE *header, type_t *iface)
     write_cpp_method_def(header, iface);
     indentation--;
   }
-  if (!type_iface_get_inherit(iface))
+  if (!parent_iface)
     fprintf(header, "    END_INTERFACE\n");
   fprintf(header, "};\n");
   if (uuid)
@@ -1143,14 +1143,22 @@ static void write_com_interface_end(FILE *header, type_t *iface)
   indentation--;
   fprintf(header, "    END_INTERFACE\n");
   fprintf(header, "} %sVtbl;\n", iface->name);
+  fprintf(header, "#ifndef WIDL_TYPE_SAFE_C_INTERFACE\n");
   fprintf(header, "interface %s {\n", iface->name);
   fprintf(header, "    CONST_VTBL %sVtbl* lpVtbl;\n", iface->name);
   fprintf(header, "};\n");
+  fprintf(header, "#else\n");
+  fprintf(header, "union %s {\n", iface->name);
+  fprintf(header, "    CONST_VTBL %sVtbl* lpVtbl;\n", iface->name);
+  if(parent_iface)
+      fprintf(header, "    %s base;\n", parent_iface->name);
+  fprintf(header, "};\n");
+  fprintf(header, "#endif\n");
   fprintf(header, "\n");
   fprintf(header, "#ifdef COBJMACROS\n");
   /* dispinterfaces don't have real functions, so don't write macros for them,
    * only for the interface this interface inherits from, i.e. IDispatch */
-  write_method_macro(header, dispinterface ? type_iface_get_inherit(iface) : iface, iface->name);
+  write_method_macro(header, dispinterface ? parent_iface : iface, iface->name);
   fprintf(header, "#endif\n");
   fprintf(header, "\n");
   fprintf(header, "#endif\n");
