This is a resubmit of my previous patch. This time, I've fixed the conflict with the ICOM_THIS_MULTI macro from obj_base.h by using ICOM_THIS_OBJECT instead. To make the patch smaller, I've only focused on the ddraw COM infrastructure and changed some references to the ICOM_OBJECT macro that was needed. I've also a small doc that explains how to implement objects with multiple interfaces using the macros define in ddcomimpl.h. I will submit it later when it's finished. Modified files : dlls/ddraw/ddcomimpl.h dlls/ddraw/dclipper/main.c dlls/ddraw/ddraw/main.c dlls/ddraw/dpalette/main.c dlls/ddraw/durface/dib.c dlls/ddraw/durface/main.c Changelog : Enhance ddraw COM macros by adding a pointer to the object itself after each VTable.
Index: ddcomimpl.h =================================================================== RCS file: /home/wine/wine/dlls/ddraw/ddcomimpl.h,v retrieving revision 1.2 diff -u -r1.2 ddcomimpl.h --- ddcomimpl.h 9 Mar 2002 23:29:35 -0000 1.2 +++ ddcomimpl.h 10 Nov 2002 14:25:38 -0000 @@ -17,37 +17,53 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifndef _DDCOMIMPL_H_ +#define _DDCOMIMPL_H_ + #include <stddef.h> +#define INTERFACE(iface) \ + struct { \ + iface interface; \ + LPVOID object; \ + } + +typedef INTERFACE(LPVOID) Interface; + /* Generates the name for a vtable pointer for a given interface. */ /* The canonical name for a single interface is "lpVtbl". */ #define ICOM_VFIELD_MULTI_NAME2(iface) ITF_##iface #define ICOM_VFIELD_MULTI_NAME(iface) ICOM_VFIELD_MULTI_NAME2(iface) -/* Declares a vtable pointer field in an implementation. */ +/* Declares an interface in an implementation. */ #define ICOM_VFIELD_MULTI(iface) \ - iface ICOM_VFIELD_MULTI_NAME(iface) - -/* Returns the offset of a vtable pointer within an implementation object. */ -#define ICOM_VFIELD_OFFSET(impltype, iface) \ - offsetof(impltype, ICOM_VFIELD_MULTI_NAME(iface)) + INTERFACE(iface) ICOM_VFIELD_MULTI_NAME(iface) /* Given an interface pointer, returns the implementation pointer. */ -#define ICOM_OBJECT(impltype, ifacename, ifaceptr) \ - (impltype*)((ifaceptr) == NULL ? NULL \ - : (char*)(ifaceptr) - ICOM_VFIELD_OFFSET(impltype,ifacename)) +#define ICOM_OBJECT(impltype, ifaceptr) \ + (impltype*)(((LPVOID)ifaceptr) == NULL ? NULL \ + : ((Interface*)(ifaceptr))->object) + +#define ICOM_THIS_OBJECT(impltype, ifaceptr) \ + impltype* This = ICOM_OBJECT(impltype, ifaceptr) +/* Same as ICOM_THIS_OBJECT but compatible with current DDRAW code */ #define ICOM_THIS_FROM(impltype, ifacename, ifaceptr) \ - impltype* This = ICOM_OBJECT(impltype, ifacename, ifaceptr) + impltype* This = ICOM_OBJECT(impltype, ifaceptr) /* Given an object and interface name, returns a pointer to that interface. */ #define ICOM_INTERFACE(implobj, iface) \ - (&((implobj)->ICOM_VFIELD_MULTI_NAME(iface))) + (&((implobj)->ICOM_VFIELD_MULTI_NAME(iface)).interface) +/* Initialize an object's interface */ #define ICOM_INIT_INTERFACE(implobj, ifacename, vtblname) \ do { \ - (implobj)->ICOM_VFIELD_MULTI_NAME(ifacename).lpVtbl = &(vtblname); \ + (implobj)->ICOM_VFIELD_MULTI_NAME(ifacename).interface.lpVtbl = &(vtblname); \ + (implobj)->ICOM_VFIELD_MULTI_NAME(ifacename).object = implobj; \ } while (0) -#define COM_INTERFACE_CAST(impltype, ifnamefrom, ifnameto, ifaceptr) \ - ICOM_INTERFACE(ICOM_OBJECT(impltype, ifnamefrom, ifaceptr), ifnameto) +#define COM_INTERFACE_CAST(impltype, ifnamefrom, ifnameto, ifaceptr) \ + ICOM_INTERFACE(ICOM_OBJECT(impltype, ifaceptr), ifnameto) + +#endif /* _DDCOMIMPL_H_ */ + Index: dclipper/main.c =================================================================== RCS file: /home/wine/wine/dlls/ddraw/dclipper/main.c,v retrieving revision 1.8 diff -u -r1.8 main.c --- dclipper/main.c 31 May 2002 23:25:45 -0000 1.8 +++ dclipper/main.c 10 Nov 2002 14:25:39 -0000 @@ -184,7 +184,7 @@ if (This->ddraw_owner != NULL) return DDERR_ALREADYINITIALIZED; - pOwner = ICOM_OBJECT(IDirectDrawImpl, IDirectDraw, lpDD); + pOwner = ICOM_OBJECT(IDirectDrawImpl, lpDD); This->ddraw_owner = pOwner; Main_DirectDraw_AddClipper(pOwner, This); Index: ddraw/main.c =================================================================== RCS file: /home/wine/wine/dlls/ddraw/ddraw/main.c,v retrieving revision 1.25 diff -u -r1.25 main.c --- ddraw/main.c 18 Oct 2002 23:48:59 -0000 1.25 +++ ddraw/main.c 10 Nov 2002 14:25:41 -0000 @@ -414,8 +414,7 @@ ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_BACKBUFFER); - primary = ICOM_OBJECT(IDirectDrawSurfaceImpl,IDirectDrawSurface7, - *ppSurf); + primary = ICOM_OBJECT(IDirectDrawSurfaceImpl,*ppSurf); pPrev = *ppSurf; IDirectDrawSurface7_AddRef(pPrev); @@ -560,8 +559,7 @@ { ICOM_THIS(IDirectDrawImpl,iface); - IDirectDrawSurfaceImpl *pSrc = ICOM_OBJECT(IDirectDrawSurfaceImpl, - IDirectDrawSurface7, src); + IDirectDrawSurfaceImpl *pSrc = ICOM_OBJECT(IDirectDrawSurfaceImpl, src); TRACE("(%p)->(%p,%p)\n",This,src,dst); Index: dpalette/main.c =================================================================== RCS file: /home/wine/wine/dlls/ddraw/dpalette/main.c,v retrieving revision 1.7 diff -u -r1.7 main.c --- dpalette/main.c 10 Jul 2002 03:05:43 -0000 1.7 +++ dpalette/main.c 10 Nov 2002 14:25:42 -0000 @@ -162,8 +162,7 @@ LPDIRECTDRAWSURFACE7 psurf = NULL; IDirectDraw7_GetGDISurface(ICOM_INTERFACE(This->ddraw_owner,IDirectDraw7), &psurf); if (psurf) { - IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, - IDirectDrawSurface7, psurf); + IDirectDrawSurfaceImpl *surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, psurf); surf->update_palette(surf, This, dwStart, dwCount, palent); IDirectDrawSurface7_Release(psurf); } Index: dsurface/dib.c =================================================================== RCS file: /home/wine/wine/dlls/ddraw/dsurface/dib.c,v retrieving revision 1.18 diff -u -r1.18 dib.c --- dsurface/dib.c 6 Nov 2002 19:53:45 -0000 1.18 +++ dsurface/dib.c 10 Nov 2002 14:25:46 -0000 @@ -1038,8 +1038,7 @@ &back_caps, &tgt); if (!FAILED(hr)) { - IDirectDrawSurfaceImpl* target = ICOM_OBJECT(IDirectDrawSurfaceImpl, - IDirectDrawSurface7,tgt); + IDirectDrawSurfaceImpl* target = ICOM_OBJECT(IDirectDrawSurfaceImpl, tgt); IDirectDrawSurface7_Release(tgt); target->get_dc(target, &dc); SetDIBColorTable(dc, dwStart, dwCount, col); Index: dsurface/main.c =================================================================== RCS file: /home/wine/wine/dlls/ddraw/dsurface/main.c,v retrieving revision 1.32 diff -u -r1.32 main.c --- dsurface/main.c 4 Nov 2002 22:34:11 -0000 1.32 +++ dsurface/main.c 10 Nov 2002 14:25:46 -0000 @@ -288,8 +288,7 @@ LPDIRECTDRAWSURFACE7 pAttach) { ICOM_THIS(IDirectDrawSurfaceImpl, iface); - IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, - IDirectDrawSurface7, pAttach); + IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, pAttach); TRACE("(%p)->(%p)\n",This,pAttach); @@ -385,8 +384,7 @@ LPDIRECTDRAWSURFACE7 pAttach) { ICOM_THIS(IDirectDrawSurfaceImpl, iface); - IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, - IDirectDrawSurface7, pAttach); + IDirectDrawSurfaceImpl* surf = ICOM_OBJECT(IDirectDrawSurfaceImpl, pAttach); TRACE("(%p)->(%08lx,%p)\n",This,dwFlags,pAttach); @@ -508,8 +506,7 @@ hr = IDirectDrawSurface7_GetAttachedSurface(iface, &back_caps, &tgt); if (FAILED(hr)) return DDERR_NOTFLIPPABLE; /* unchecked */ - target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, - tgt); + target = ICOM_OBJECT(IDirectDrawSurfaceImpl, tgt); IDirectDrawSurface7_Release(tgt); } else @@ -523,8 +520,7 @@ /* Verify that override is on this flip chain. We assume that * surf is the head of the flipping chain, because it's the front * buffer. */ - target = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, - override); + target = ICOM_OBJECT(IDirectDrawSurfaceImpl, override); /* Either target is (indirectly) attached to This or This is * (indirectly) attached to target. */ @@ -1052,8 +1048,7 @@ IDirectDrawClipper_Release(ICOM_INTERFACE(This->clipper, IDirectDrawClipper)); - This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, IDirectDrawClipper, - pDDClipper); + This->clipper = ICOM_OBJECT(IDirectDrawClipperImpl, pDDClipper); if (pDDClipper != NULL) IDirectDrawClipper_AddRef(pDDClipper); @@ -1135,8 +1130,7 @@ IDirectDrawPalette)); } - This->palette = ICOM_OBJECT(IDirectDrawPaletteImpl, IDirectDrawPalette, - pPalette); + This->palette = ICOM_OBJECT(IDirectDrawPaletteImpl, pPalette); if (pPalette != NULL) { IDirectDrawPalette_AddRef(pPalette); if (This->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)