Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1809 lines
45 KiB

/*==========================================================================
*
* Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
*
* File: ddclip.c
* Content: DirectDraw clipper functions
*
* NOTE:
* For functions that manipulate the winwatch list,
* we need to take the win16 lock after we take the directdraw
* lock. The reason for this is that we can get an async
* call from the 16-bit side when a window is closed
* to release winwatch object. Since the win16 lock is held
* when the callup occurs, this makes it safe to manipulate
* the structures.
*
* History:
* Date By Reason
* ==== == ======
* 21-jun-95 craige initial implementation
* 23-jun-95 craige connect with winwatch stuff
* 25-jun-95 craige minor bug fix; one ddraw mutex
* 26-jun-95 craige reorganized surface structure
* 28-jun-95 craige ENTER_DDRAW at very start of fns
* 02-jul-95 craige commented out clipper notification stuff
* 03-jul-95 craige YEEHAW: new driver struct; SEH
* 05-jul-95 craige added Initialize
* 11-jul-95 craige fail aggregation calls
* 13-jul-95 craige ENTER_DDRAW is now the win16 lock
* 31-jul-95 craige validate flags
* 05-aug-95 craige bug 260 - clip user defined rgn to screen
* 09-dec-95 colinmc added execute buffer support
* 15-dec-95 colinmc made clippers sharable across surfaces
* 19-dec-95 kylej added NT cliplist support
* 02-jan-96 kylej handle new interface structs.
* 17-jan-96 kylej fixed NT vis region bug
* 22-feb-96 colinmc clippers no longer need to be associated with a
* DirectDraw object - they can be created independently.
* 03-mar-96 colinmc fixed problem with QueryInterface returning local
* object rather than interface
* 13-mar-96 colinmc added IID validation to QueryInterface.
* 14-mar-96 colinmc added class factory support
* 18-mar-96 colinmc Bug 13545: Independent clipper cleanup
* 21-mar-96 colinmc Bug 13316: Unitialized interfaces
* 09-apr-96 colinmc Bug 13991: Parameter validation on IsClipListChanged
* 26-mar-96 jeffno Watched HWNDs under NT
* 20-sep-96 ketand GetClipList optimization
* 21-jan-96 ketand Deleted unused WinWatch code. Fixed clipping for multi-mon.
* 07-feb-96 ketand bug5673: fix clipping when VisRgn is larger than ClientRect
* 24-mar-97 jeffno Optimized Surfaces
* 05-nov-97 jvanaken Support for master sprite list in SetSpriteDisplayList
*
***************************************************************************/
#include "ddrawpr.h"
#ifdef WINNT
#include "ddrawgdi.h"
#endif
// function in ddsprite.c to remove invalid clipper from master sprite list
extern void RemoveSpriteClipper(LPDDRAWI_DIRECTDRAW_GBL, LPDDRAWI_DDRAWCLIPPER_INT);
/*
* GLOBAL NOTE: You will notice that these functions usually fetch the
* DirectDraw global object pointer from the global clipper object during
* parameter validation. You may wonder why this is given that clippers
* are pretty much completely independent of drivers. Well, this is purely
* for parameter validation purposes. We just want to ensure that we can
* dereference the clipper global object - we could use any parameter.
* So don't remove this code when you notice its not used. It serves
* a purpose.
* Probably should wrap this stuff up in a nice macro.
*/
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDraw::DD_UnInitedClipperQueryInterface"
/*
* DD_UnInitedClipperQueryInterface
*/
HRESULT DDAPI DD_UnInitedClipperQueryInterface(
LPDIRECTDRAWCLIPPER lpDDClipper,
REFIID riid,
LPVOID FAR * ppvObj )
{
LPDDRAWI_DDRAWCLIPPER_GBL this;
LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
LPDDRAWI_DDRAWCLIPPER_INT this_int;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_UnInitedClipperQueryInterface");
/*
* validate parms
*/
TRY
{
this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( !VALID_PTR_PTR( ppvObj ) )
{
DPF( 1, "Invalid clipper pointer" );
LEAVE_DDRAW();
return (DWORD) DDERR_INVALIDPARAMS;
}
if( !VALIDEX_IID_PTR( riid ) )
{
DPF_ERR( "Invalid IID pointer" );
LEAVE_DDRAW();
return (DWORD) DDERR_INVALIDPARAMS;
}
*ppvObj = NULL;
this = this_lcl->lpGbl;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* check guids
*/
if( IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IDirectDrawClipper) )
{
DD_Clipper_AddRef( lpDDClipper );
*ppvObj = (LPVOID) this_int;
LEAVE_DDRAW();
return DD_OK;
}
LEAVE_DDRAW();
return E_NOINTERFACE;
} /* DD_UnInitedClipperQueryInterface */
#undef DPF_MODNAME
#define DPF_MODNAME "Clipper::QueryInterface"
/*
* DD_Clipper_QueryInterface
*/
HRESULT DDAPI DD_Clipper_QueryInterface(
LPDIRECTDRAWCLIPPER lpDDClipper,
REFIID riid,
LPVOID FAR * ppvObj )
{
LPDDRAWI_DDRAWCLIPPER_GBL this;
LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
LPDDRAWI_DDRAWCLIPPER_INT this_int;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Clipper_QueryInterface");
/*
* validate parms
*/
TRY
{
this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( !VALID_PTR_PTR( ppvObj ) )
{
DPF( 1, "Invalid clipper pointer" );
LEAVE_DDRAW();
return (DWORD) DDERR_INVALIDPARAMS;
}
if( !VALIDEX_IID_PTR( riid ) )
{
DPF_ERR( "Invalid IID pointer" );
LEAVE_DDRAW();
return (DWORD) DDERR_INVALIDPARAMS;
}
*ppvObj = NULL;
this = this_lcl->lpGbl;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* check guids
*/
if( IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IDirectDrawClipper) )
{
DD_Clipper_AddRef( lpDDClipper );
*ppvObj = (LPVOID) this_int;
LEAVE_DDRAW();
return DD_OK;
}
LEAVE_DDRAW();
return E_NOINTERFACE;
} /* DD_Clipper_QueryInterface */
#undef DPF_MODNAME
#define DPF_MODNAME "Clipper::AddRef"
/*
* DD_Clipper_AddRef
*/
DWORD DDAPI DD_Clipper_AddRef( LPDIRECTDRAWCLIPPER lpDDClipper )
{
LPDDRAWI_DIRECTDRAW_GBL pdrv;
LPDDRAWI_DDRAWCLIPPER_GBL this;
LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
LPDDRAWI_DDRAWCLIPPER_INT this_int;
DWORD rcnt;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Clipper_AddRef");
/*
* validate parms
*/
TRY
{
this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
{
LEAVE_DDRAW();
return 0;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
pdrv = this->lpDD;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return 0;
}
/*
* update clipper reference count
*/
this->dwRefCnt++;
this_lcl->dwLocalRefCnt++;
this_int->dwIntRefCnt++;
rcnt = this_lcl->dwLocalRefCnt & ~OBJECT_ISROOT;
DPF( 5, "Clipper %08lx addrefed, refcnt = %ld", this, rcnt );
LEAVE_DDRAW();
return this_int->dwIntRefCnt;
} /* DD_Clipper_AddRef */
#undef DPF_MODNAME
#define DPF_MODNAME "Clipper::Release"
/*
* RemoveClipperFromList
*
* Remove a clipper from its owning clipper list.
*
* The clipper can either be a member of a global clipper list
* (if no DirectDraw object owns it) or the clipper list of its
* owning DirectDraw driver object. If pdrv == NULL then the
* clipper will be removed from the global clipper list. If
* pdrv != NULL the clipper will be removed from the clipper
* list of that driver object. It is an error if the clipper
* is not on the appropriate clipper list.
*
* Returns TRUE if the clipper was succesfully removed
* Returns FALSE if the clipper could not be found on the
* appropriate clipper list
*/
static BOOL RemoveClipperFromList( LPDDRAWI_DIRECTDRAW_GBL pdrv,
LPDDRAWI_DDRAWCLIPPER_INT this_int )
{
LPDDRAWI_DDRAWCLIPPER_INT curr_int;
LPDDRAWI_DDRAWCLIPPER_INT last_int;
curr_int = ( ( pdrv != NULL ) ? pdrv->clipperList : lpGlobalClipperList );
last_int = NULL;
while( curr_int != this_int )
{
last_int = curr_int;
curr_int = curr_int->lpLink;
if( curr_int == NULL )
{
return FALSE;
}
}
if( last_int == NULL )
{
if( pdrv != NULL )
pdrv->clipperList = pdrv->clipperList->lpLink;
else
lpGlobalClipperList = lpGlobalClipperList->lpLink;
}
else
{
last_int->lpLink = curr_int->lpLink;
}
return TRUE;
}
/*
* InternalClipperRelease
*
* Done with a clipper. if no one else is using it, then we can free it.
* Also called by ProcessClipperCleanup
*
* Assumes DirectDrawLock is taken
*/
ULONG DDAPI InternalClipperRelease( LPDDRAWI_DDRAWCLIPPER_INT this_int )
{
DWORD intrefcnt;
DWORD lclrefcnt;
DWORD gblrefcnt;
LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
LPDDRAWI_DDRAWCLIPPER_GBL this;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
BOOL root_object_deleted;
BOOL do_free;
IUnknown * pOwner = NULL;
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
pdrv = this->lpDD;
/*
* decrement reference count to this clipper. If it hits zero,
* cleanup
*/
this->dwRefCnt--;
this_lcl->dwLocalRefCnt--;
this_int->dwIntRefCnt--;
gblrefcnt = this->dwRefCnt;
lclrefcnt = this_lcl->dwLocalRefCnt & ~OBJECT_ISROOT;
intrefcnt = this_int->dwIntRefCnt;
root_object_deleted = FALSE;
DPF( 5, "Clipper %08lx released, refcnt = %ld", this, lclrefcnt );
/*
* interface object deleted?
*/
if( intrefcnt == 0 )
{
RemoveClipperFromList( pdrv, this_int );
#ifdef POSTPONED2
/*
* If clipper interface object is referenced in master sprite
* list, delete those references from the list.
*/
if (this->dwFlags & DDRAWICLIP_INMASTERSPRITELIST)
{
RemoveSpriteClipper(pdrv, this_int);
}
#endif //POSTPONED2
/*
* Invalidate the interface and free it
*/
this_int->lpVtbl = NULL;
this_int->lpLcl = NULL;
MemFree( this_int );
}
/*
* local object deleted?
*/
if( lclrefcnt == 0 )
{
/*
* If the ddraw interface which created this clipper caused the surface to addref the ddraw
* object, then we need to release that addref now.
*/
pOwner = this_lcl->pAddrefedThisOwner;
/*
* see if we are deleting the root object
*/
if( this_lcl->dwLocalRefCnt & OBJECT_ISROOT )
{
root_object_deleted = TRUE;
}
}
/*
* did the object get globally deleted?
*/
do_free = FALSE;
if( gblrefcnt == 0 )
{
do_free = TRUE;
// Need to free the static clip list
MemFree( this->lpStaticClipList );
this->lpStaticClipList = NULL;
/*
* if this was the final delete, but this wasn't the root object,
* then we need to delete the dangling root object
*/
if( !root_object_deleted )
{
LPDDRAWI_DDRAWCLIPPER_LCL rootx;
rootx = (LPVOID) (((LPSTR) this) - sizeof( DDRAWI_DDRAWCLIPPER_LCL ) );
MemFree( rootx );
}
}
else if( lclrefcnt == 0 )
{
/*
* only remove the object if it wasn't the root. if it
* was the root, we must leave it dangling until the last
* object referencing it goes away.
*/
if( !root_object_deleted )
{
do_free = TRUE;
}
}
/*
* free the object if needed
*/
if( do_free )
{
/*
* just in case someone comes back in with this pointer, set
* an invalid vtbl & data ptr.
*/
this_lcl->lpGbl = NULL;
MemFree( this_lcl );
}
/*
* If the clipper took a ref count on the ddraw object that created it,
* release that ref now as the very last thing
* We don't want to do this on ddhelp's thread cuz it really mucks up the
* process cleanup stuff.
*/
if (pOwner && (dwHelperPid != GetCurrentProcessId()) )
{
pOwner->lpVtbl->Release(pOwner);
}
return intrefcnt;
} /* InternalClipperRelease */
/*
* DD_Clipper_Release
*/
ULONG DDAPI DD_Clipper_Release( LPDIRECTDRAWCLIPPER lpDDClipper )
{
LPDDRAWI_DIRECTDRAW_GBL pdrv;
LPDDRAWI_DDRAWCLIPPER_GBL this;
LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
LPDDRAWI_DDRAWCLIPPER_INT this_int;
ULONG rc;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Clipper_Release");
/*
* validate parms
*/
TRY
{
this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
if( !VALIDEX_DIRECTDRAWCLIPPER_PTR( this_int ) )
{
LEAVE_DDRAW();
return 0;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
pdrv = this->lpDD;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return 0;
}
rc = InternalClipperRelease( this_int );
LEAVE_DDRAW();
return rc;
} /* DD_Clipper_Release */
#undef DPF_MODNAME
#define DPF_MODNAME "Clipper::SetHwnd"
/*
* DD_Clipper_SetHWnd
*/
HRESULT DDAPI DD_Clipper_SetHWnd(
LPDIRECTDRAWCLIPPER lpDDClipper,
DWORD dwFlags,
HWND hWnd )
{
LPDDRAWI_DDRAWCLIPPER_INT this_int;
LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
LPDDRAWI_DDRAWCLIPPER_GBL this;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Clipper_SetHWnd");
TRY
{
this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( hWnd != NULL )
{
if( !IsWindow( hWnd ) )
{
DPF_ERR( "Invalid window handle" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
if( dwFlags )
{
DPF_ERR( "Invalid flags" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
this = this_lcl->lpGbl;
pdrv = this->lpDD;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
(HWND) this->hWnd = hWnd;
LEAVE_DDRAW();
return DD_OK;
} /* DD_Clipper_SetHWnd */
#undef DPF_MODNAME
#define DPF_MODNAME "Clipper::GetHwnd"
/*
* DD_Clipper_GetHWnd
*/
HRESULT DDAPI DD_Clipper_GetHWnd(
LPDIRECTDRAWCLIPPER lpDDClipper,
HWND FAR *lphWnd )
{
LPDDRAWI_DDRAWCLIPPER_INT this_int;
LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
LPDDRAWI_DDRAWCLIPPER_GBL this;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
/*
* validate parms
*/
TRY
{
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Clipper_GetHWnd");
this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( !VALID_HWND_PTR( lphWnd ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
this = this_lcl->lpGbl;
pdrv = this->lpDD;
*lphWnd = (HWND) this->hWnd;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
LEAVE_DDRAW();
return DD_OK;
} /* DD_Clipper_GetHWnd */
#define SIZE_OF_A_CLIPLIST(lpRgn) \
(sizeof(RGNDATAHEADER)+sizeof(RECTL)*lpRgn->rdh.nCount)
HRESULT InternalGetClipList(
LPDIRECTDRAWCLIPPER lpDDClipper,
LPRECT lpRect,
LPRGNDATA lpClipList,
LPDWORD lpdwSize,
LPDDRAWI_DIRECTDRAW_GBL pdrv )
{
LPDDRAWI_DDRAWCLIPPER_GBL this;
HRESULT ddrval = DD_OK;
DWORD cbRealSize;
HDC hdc;
HRGN hrgn;
RECT rectT;
#ifndef WIN95
DWORD cbSaveSize;
#endif
this = ((LPDDRAWI_DDRAWCLIPPER_INT)(lpDDClipper))->lpLcl->lpGbl;
// if no hwnd specified, then it is just a static cliplist
if( this->hWnd == 0 )
{
if( this->lpStaticClipList == NULL )
{
return DDERR_NOCLIPLIST;
}
cbRealSize = SIZE_OF_A_CLIPLIST( this->lpStaticClipList );
if( lpClipList == NULL )
{
*lpdwSize = cbRealSize;
return DD_OK;
}
if( *lpdwSize < cbRealSize )
{
DPF_ERR( "Region size too small" );
*lpdwSize = cbRealSize;
return DDERR_REGIONTOOSMALL;
}
memcpy( lpClipList, this->lpStaticClipList, cbRealSize );
ClipRgnToRect( lpRect, lpClipList );
return DD_OK;
}
// Use an hwnd for the clipping
#ifdef WIN95
{
hdc = GetDCEx( (HWND)this->hWnd, NULL, DCX_USESTYLE | DCX_CACHE );
if( hdc == NULL )
{
DPF_ERR( "GetDCEx failed" );
return DDERR_GENERIC;
}
hrgn = DD16_InquireVisRgn( hdc );
if( hrgn == NULL )
{
DPF_ERR( "InquireVisRgn failed" );
ReleaseDC( (HWND)this->hWnd, hdc );
return DDERR_GENERIC;
}
}
#else
{
int APIENTRY GetRandomRgn( HDC hdc, HRGN hrgn, int iNum );
int rc;
hdc = GetDC( (HWND) this->hWnd );
if( hdc == NULL )
{
DPF_ERR( "GetDC failed" );
return DDERR_GENERIC;
}
// Create the appropriate Region object
hrgn = CreateRectRgn( 0, 0, 0, 0 );
if( hrgn == NULL )
{
DPF_ERR( "CreateRectRgn failed" );
ReleaseDC( (HWND) this->hWnd, hdc );
return DDERR_GENERIC;
}
// Set the Region to the DC
rc = GetRandomRgn( hdc, hrgn, 4 );
if( rc == -1 )
{
DPF_ERR( "GetRandomRgn failed" );
ReleaseDC( (HWND) this->hWnd, hdc );
DeleteObject( hrgn );
return DDERR_GENERIC;
}
}
#endif
// Client only asking for a size?
if( lpClipList == NULL )
{
// Get the size
*lpdwSize = GetRegionData( hrgn, 0, NULL );
// Release allocations
ReleaseDC( (HWND) this->hWnd, hdc );
DeleteObject( hrgn );
// Check if GetRegionData failed
if( *lpdwSize == 0 )
return DDERR_GENERIC;
return DD_OK;
}
#ifndef WIN95
// Store the size passed in, because GetRegionData may trash it.
cbSaveSize = *lpdwSize;
#endif
// Get the window's region's REGIONDATA
cbRealSize = GetRegionData( hrgn, *lpdwSize, lpClipList );
#ifndef WIN95
if (cbRealSize == 0)
{
cbRealSize = GetRegionData(hrgn, 0, NULL);
if (cbSaveSize < cbRealSize)
{
ReleaseDC( (HWND)this->hWnd, hdc );
DeleteObject( hrgn );
*lpdwSize = cbRealSize;
DPF(4, "size of clip region too small");
return DDERR_REGIONTOOSMALL;
}
}
#endif
ReleaseDC( (HWND)this->hWnd, hdc );
DeleteObject( hrgn );
if( cbRealSize == 0 )
{
DPF_ERR( "GetRegionData failed" );
return DDERR_GENERIC;
}
#ifdef WIN95
// GetRegionData may have failed because the buffer
// was too small
if( *lpdwSize < cbRealSize )
{
DPF( 4, "size of clip region too small" );
*lpdwSize = cbRealSize;
return DDERR_REGIONTOOSMALL;
}
#endif
// Before we do anything more, we need to make sure
// to clip the Rgn to ClientRect of the Window. Normally
// this is not necessary; but InquireVisRgn might
// tell us the vis region of the parent window if the window
// was a dialog or other wnd that used CS_PARENTDC
GetClientRect( (HWND) this->hWnd, &rectT );
ClientToScreen( (HWND) this->hWnd, (LPPOINT)&rectT );
ClientToScreen( (HWND) this->hWnd, ((LPPOINT)&rectT)+1 );
ClipRgnToRect( &rectT, lpClipList );
// lpDD may be NULL if the clipper was created independently
if( pdrv &&
(pdrv->cMonitors > 1) &&
(pdrv->dwFlags & DDRAWI_DISPLAYDRV) )
{
// On multi-mon systems, the Desktop coordinates may be different
// from the device coordinates. On the primary, they are the same however.
// The lpRect passed in is in device coordinates; so we need to convert it
// into desktop coordinates.
UINT i;
LPRECT prectClip;
if( pdrv->rectDevice.top != 0 ||
pdrv->rectDevice.left != 0 )
{
RECT rectT;
if( lpRect != NULL )
{
rectT.left = lpRect->left + pdrv->rectDevice.left;
rectT.right = lpRect->right + pdrv->rectDevice.left;
rectT.top = lpRect->top + pdrv->rectDevice.top;
rectT.bottom = lpRect->bottom + pdrv->rectDevice.top;
}
else
{
rectT = pdrv->rectDevice;
}
// Clip the cliplist to the target rect
ClipRgnToRect( &rectT, lpClipList );
// Clip the cliplist to the device's rect
ClipRgnToRect( &pdrv->rectDevice, lpClipList );
// Iterate over each rect in the region
for ( i = 0, prectClip = (LPRECT)lpClipList->Buffer;
i < lpClipList->rdh.nCount;
i++, prectClip++ )
{
// Convert each Rect into Device coordinates
prectClip->left -= pdrv->rectDevice.left;
prectClip->right -= pdrv->rectDevice.left;
prectClip->top -= pdrv->rectDevice.top;
prectClip->bottom -= pdrv->rectDevice.top;
}
}
else
{
// Clip the cliplist to the target rect
ClipRgnToRect( lpRect, lpClipList );
// Clip the cliplist to the device's rect
ClipRgnToRect( &pdrv->rectDesktop, lpClipList );
}
}
else
{
ClipRgnToRect( lpRect, lpClipList );
}
return DD_OK;
}
/*
* DD_Clipper_GetClipList
*/
HRESULT DDAPI DD_Clipper_GetClipList(
LPDIRECTDRAWCLIPPER lpDDClipper,
LPRECT lpRect,
LPRGNDATA lpClipList,
LPDWORD lpdwSize )
{
LPDDRAWI_DDRAWCLIPPER_INT this_int;
LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
LPDDRAWI_DDRAWCLIPPER_GBL this;
DWORD size;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Clipper_GetClipList");
/*
* validate parms
*/
TRY
{
this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( !VALID_DWORD_PTR( lpdwSize ) )
{
DPF_ERR( "Invalid size ptr" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( lpRect != NULL )
{
if( !VALID_RECT_PTR( lpRect ) )
{
DPF_ERR( "Invalid rectangle ptr" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
size = lpRect->left;
}
if( lpClipList != NULL )
{
if( !VALID_RGNDATA_PTR( lpClipList, *lpdwSize ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDCLIPLIST;
}
// Touch the last address in the promised block to verify
// the memory is actually there. Note that we are
// standing on our head here to prevent the optimizing
// compiler from helping us by removing this code. This
// is done by the macro above, but we want it in the
// retail build, too.
{
volatile BYTE *foo = ((BYTE*)lpClipList) + *lpdwSize - 1;
BYTE bar = *foo;
}
lpClipList->rdh.nCount = 0;
}
this = this_lcl->lpGbl;
pdrv = this->lpDD;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* go fetch the clip list
*/
{
HRESULT ddrval;
#ifdef WIN16_SEPARATE
ENTER_WIN16LOCK();
#endif
ddrval = InternalGetClipList( lpDDClipper, lpRect, lpClipList, lpdwSize, pdrv );
#ifdef WIN16_SEPARATE
LEAVE_WIN16LOCK();
#endif
LEAVE_DDRAW();
return ddrval;
}
} /* DD_Clipper_GetClipList */
/*
* DD_Clipper_SetClipList
*/
HRESULT DDAPI DD_Clipper_SetClipList(
LPDIRECTDRAWCLIPPER lpDDClipper,
LPRGNDATA lpClipList,
DWORD dwFlags )
{
LPDDRAWI_DDRAWCLIPPER_INT this_int;
LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
LPDDRAWI_DDRAWCLIPPER_GBL this;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
LPRGNDATA prd;
DWORD size;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Clipper_SetClipList");
TRY
{
this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
if( dwFlags )
{
DPF_ERR( "Invalid flags" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
if( lpClipList != NULL )
{
if( !VALID_RGNDATA_PTR( lpClipList, sizeof(RGNDATA) ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDCLIPLIST;
}
if( lpClipList->rdh.nCount <= 0 )
{
LEAVE_DDRAW();
return DDERR_INVALIDCLIPLIST;
}
if( this_lcl->lpDD_int == NULL || this_lcl->lpDD_int->lpVtbl != &ddCallbacks )
{
if( (lpClipList->rdh.dwSize < sizeof(RGNDATAHEADER)) ||
(lpClipList->rdh.iType != RDH_RECTANGLES ) ||
IsBadReadPtr(lpClipList, SIZE_OF_A_CLIPLIST(lpClipList)) )
{
LEAVE_DDRAW();
return DDERR_INVALIDCLIPLIST;
}
}
}
this = this_lcl->lpGbl;
pdrv = this->lpDD;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* can't set a clip list if there is an hwnd
*/
if( this->hWnd != 0 )
{
DPF_ERR( "Can't set a clip list: hwnd set" );
LEAVE_DDRAW();
return DDERR_CLIPPERISUSINGHWND;
}
/*
* if NULL, just delete old cliplist
*/
if( lpClipList == NULL )
{
MemFree( this->lpStaticClipList );
this->lpStaticClipList = NULL;
LEAVE_DDRAW();
return DD_OK;
}
/*
* duplicate the user's region data
*/
size = SIZE_OF_A_CLIPLIST(lpClipList);
prd = MemAlloc( size );
if( prd == NULL )
{
LEAVE_DDRAW();
return DDERR_OUTOFMEMORY;
}
memcpy( prd, lpClipList, size );
/*
* save cliplist info
*/
MemFree( this->lpStaticClipList );
this->lpStaticClipList = prd;
LEAVE_DDRAW();
return DD_OK;
} /* DD_Clipper_SetClipList */
#undef DPF_MODNAME
#define DPF_MODNAME "Clipper:IsClipListChanged"
/*
* DD_Clipper_IsClipListChanged
*/
HRESULT DDAPI DD_Clipper_IsClipListChanged(
LPDIRECTDRAWCLIPPER lpDDClipper,
BOOL FAR *lpbChanged )
{
LPDDRAWI_DDRAWCLIPPER_INT this_int;
LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
LPDDRAWI_DDRAWCLIPPER_GBL this;
volatile LPDDRAWI_DIRECTDRAW_GBL pdrv;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Clipper_IsClipListChanged");
/*
* validate parms
*/
TRY
{
this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
pdrv = this->lpDD;
*lpbChanged = 0;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
#pragma message( REMIND( "Do we want to just fail non-watched IsClipListChanged?" ))
*lpbChanged = TRUE;
LEAVE_DDRAW();
return DD_OK;
} /* DD_Clipper_IsClipListChanged */
#undef DPF_MODNAME
#define DPF_MODNAME "GetClipper"
/*
* DD_Surface_GetClipper
*
* Surface function: get the clipper associated with surface
*/
HRESULT DDAPI DD_Surface_GetClipper(
LPDIRECTDRAWSURFACE lpDDSurface,
LPDIRECTDRAWCLIPPER FAR * lplpDDClipper)
{
LPDDRAWI_DDRAWSURFACE_INT this_int;
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
LPDDRAWI_DDRAWSURFACE_GBL this;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Surface_GetClipper");
/*
* validate parms
*/
TRY
{
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
if( !VALID_PTR_PTR( lplpDDClipper ) )
{
DPF_ERR( "Invalid clipper pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
*lplpDDClipper = NULL;
pdrv = this->lpDD;
if( this_lcl->lpSurfMore->lpDDIClipper == NULL )
{
DPF_ERR( "No clipper associated with surface" );
LEAVE_DDRAW();
return DDERR_NOCLIPPERATTACHED;
}
//
// For now, if the current surface is optimized, quit
//
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
{
DPF_ERR( "It is an optimized surface" );
LEAVE_DDRAW();
return DDERR_ISOPTIMIZEDSURFACE;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
DD_Clipper_AddRef( (LPDIRECTDRAWCLIPPER) this_lcl->lpSurfMore->lpDDIClipper );
*lplpDDClipper = (LPDIRECTDRAWCLIPPER) this_lcl->lpSurfMore->lpDDIClipper;
LEAVE_DDRAW();
return DD_OK;
} /* DD_Surface_GetClipper */
#undef DPF_MODNAME
#define DPF_MODNAME "SetClipper"
/*
* DD_Surface_SetClipper
*
* Surface function: set the clipper associated with surface
*/
HRESULT DDAPI DD_Surface_SetClipper(
LPDIRECTDRAWSURFACE lpDDSurface,
LPDIRECTDRAWCLIPPER lpDDClipper )
{
LPDDRAWI_DDRAWSURFACE_INT this_int;
LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
LPDDRAWI_DDRAWSURFACE_GBL this;
LPDDRAWI_DDRAWCLIPPER_INT this_clipper_int;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
BOOL detach;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Surface_SetClipper");
/*
* validate parms
*/
TRY
{
this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER ||
this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
{
/*
* Can't attach a clipper to an execute buffer or an optimized
* surface.
*/
DPF_ERR( "Invalid surface type: can't attach clipper" );
LEAVE_DDRAW();
return DDERR_INVALIDSURFACETYPE;
}
this_clipper_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
if( this_clipper_int != NULL )
{
if( !VALID_DIRECTDRAWCLIPPER_PTR( this_clipper_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
}
pdrv = this->lpDD;
//
// For now, if the current surface is optimized, quit
//
if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
{
DPF_ERR( "Cannot set clipper to an optimized surface" );
LEAVE_DDRAW();
return DDERR_ISOPTIMIZEDSURFACE;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* NULL clipper, remove clipper from this surface
*/
detach = FALSE;
if( this_clipper_int == NULL )
{
detach = TRUE;
this_clipper_int = this_lcl->lpSurfMore->lpDDIClipper;
if( this_clipper_int == NULL )
{
DPF_ERR( "No attached clipper" );
LEAVE_DDRAW();
return DDERR_NOCLIPPERATTACHED;
}
}
/*
* removing the clipper from the surface?
*/
if( detach )
{
this_lcl->lpDDClipper = NULL;
this_lcl->lpSurfMore->lpDDIClipper = NULL;
DD_Clipper_Release( (LPDIRECTDRAWCLIPPER) this_clipper_int );
LEAVE_DDRAW();
return DD_OK;
}
/*
* Setting the clipper.
* You can set the same clipper multiple times without bumping
* the reference count. This is done for orthogonality with
* palettes.
*/
if( this_clipper_int != this_lcl->lpSurfMore->lpDDIClipper )
{
/*
* If there was an existing clipper release it now.
*/
if( this_lcl->lpSurfMore->lpDDIClipper != NULL)
DD_Clipper_Release( (LPDIRECTDRAWCLIPPER) this_lcl->lpSurfMore->lpDDIClipper );
this_lcl->lpSurfMore->lpDDIClipper = this_clipper_int;
this_lcl->lpDDClipper = this_clipper_int->lpLcl;
DD_Clipper_AddRef( (LPDIRECTDRAWCLIPPER) this_clipper_int );
}
LEAVE_DDRAW();
return DD_OK;
} /* DD_Surface_SetClipper */
#undef DPF_MODNAME
#define DPF_MODNAME "InternalCreateClipper"
/*
* InternalCreateClipper
*
* Core clipper creation.
*
* NOTE: Assumes the caller has already entered the DirectDraw critical
* section.
*/
HRESULT InternalCreateClipper(
LPDDRAWI_DIRECTDRAW_GBL lpDD,
DWORD dwFlags,
LPDIRECTDRAWCLIPPER FAR *lplpDDClipper,
IUnknown FAR *pUnkOuter,
BOOL fInitialized,
LPDDRAWI_DIRECTDRAW_LCL lpDD_lcl,
LPDDRAWI_DIRECTDRAW_INT lpDD_int )
{
LPDDRAWI_DDRAWCLIPPER_INT pclipper_int;
LPDDRAWI_DDRAWCLIPPER_LCL pclipper_lcl;
LPDDRAWI_DDRAWCLIPPER_GBL pclipper;
DWORD clipper_size;
if( pUnkOuter != NULL )
{
return CLASS_E_NOAGGREGATION;
}
TRY
{
/*
* NOTE: We do not attempt to validate the DirectDraw
* object passed in. This will be NULL if we are creating
* a clipper not owned by any DirectDraw object.
* IDirectDraw_CreateClipper will validate this for us.
*/
if( !VALID_PTR_PTR( lplpDDClipper ) )
{
DPF_ERR( "Invalid pointer to pointer to clipper" );
return DDERR_INVALIDPARAMS;
}
*lplpDDClipper = NULL;
/*
* verify flags
*/
if( dwFlags )
{
DPF_ERR( "Invalid flags" );
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
return DDERR_INVALIDPARAMS;
}
/*
* allocate the clipper object
*/
clipper_size = sizeof( DDRAWI_DDRAWCLIPPER_GBL ) +
sizeof( DDRAWI_DDRAWCLIPPER_LCL );
pclipper_lcl = (LPDDRAWI_DDRAWCLIPPER_LCL) MemAlloc( clipper_size );
if( pclipper_lcl == NULL )
{
DPF_ERR( "Insufficient memory to allocate the clipper" );
return DDERR_OUTOFMEMORY;
}
pclipper_lcl->lpGbl = (LPDDRAWI_DDRAWCLIPPER_GBL) (((LPSTR)pclipper_lcl) +
sizeof( DDRAWI_DDRAWCLIPPER_LCL ) );
pclipper = pclipper_lcl->lpGbl;
pclipper_lcl->lpDD_lcl = lpDD_lcl;
pclipper_lcl->lpDD_int = lpDD_int;
pclipper_int = MemAlloc( sizeof( DDRAWI_DDRAWCLIPPER_INT ));
if( NULL == pclipper_int)
{
DPF_ERR( "Insufficient memory to allocate the clipper" );
MemFree( pclipper_lcl );
return DDERR_OUTOFMEMORY;
}
/*
* set up data
*/
pclipper_int->lpLcl = pclipper_lcl;
pclipper_int->dwIntRefCnt = 0; // will be addrefed later
/*
* Link the clipper into the appropriate list (either the
* given DirectDraw object's list or the global clipper
* list dependening on whether it is being created off
* a DirectDraw object or nor.
*/
if( lpDD != NULL)
{
/*
* The DirectDraw object's list.
*/
pclipper_int->lpLink = lpDD->clipperList;
lpDD->clipperList = pclipper_int;
}
else
{
/*
* The global clipper list.
*/
pclipper_int->lpLink = lpGlobalClipperList;
lpGlobalClipperList = pclipper_int;
}
/*
* fill in misc stuff
*
* NOTE: The DirectDraw object pointer will be initialized by
* IDirectDraw_CreateClipper. DirectDrawClipperCreate will
* leave it NULL'd out.
*/
pclipper->lpDD = lpDD;
pclipper->dwFlags = 0UL;
/*
* bump reference count, return object
*/
pclipper->dwProcessId = GetCurrentProcessId();
pclipper_lcl->dwLocalRefCnt = OBJECT_ISROOT;
if( fInitialized )
{
/*
* Initialized by default. Use the real vtable.
*/
pclipper->dwFlags |= DDRAWICLIP_ISINITIALIZED;
pclipper_int->lpVtbl = (LPVOID) &ddClipperCallbacks;
}
else
{
/*
* Object is not initialized. Use the dummy vtable
* which only lets the caller call AddRef(), Release()
* and Initialize().
*/
pclipper_int->lpVtbl = (LPVOID) &ddUninitClipperCallbacks;
}
DD_Clipper_AddRef( (LPDIRECTDRAWCLIPPER) pclipper_int );
*lplpDDClipper = (LPDIRECTDRAWCLIPPER) pclipper_int;
/*
* If this ddraw object generates independent child objects, then this clipper takes
* a ref count on that ddraw object. First check lpDD_int, as this object may not
* be owned by a DDraw object.
*/
if (lpDD_int && CHILD_SHOULD_TAKE_REFCNT(lpDD_int))
{
IDirectDraw *pdd = (IDirectDraw*) lpDD_int;
pdd->lpVtbl->AddRef(pdd);
pclipper_lcl->pAddrefedThisOwner = (IUnknown *) pdd;
}
return DD_OK;
} /* InternalCreateClipper */
#undef DPF_MODNAME
#define DPF_MODNAME "CreateClipper"
/*
* DD_CreateClipper
*
* Driver function: create a clipper
*/
HRESULT DDAPI DD_CreateClipper(
LPDIRECTDRAW lpDD,
DWORD dwFlags,
LPDIRECTDRAWCLIPPER FAR *lplpDDClipper,
IUnknown FAR *pUnkOuter )
{
HRESULT hRes;
LPDDRAWI_DIRECTDRAW_INT this_int;
LPDDRAWI_DIRECTDRAW_LCL this_lcl;
LPDDRAWI_DIRECTDRAW_GBL this;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_CreateClipper");
TRY
{
this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( !VALID_DIRECTDRAW_PTR( this_int ) )
{
LEAVE_DDRAW();
return DDERR_INVALIDOBJECT;
}
this_lcl = this_int->lpLcl;
this = this_lcl->lpGbl;
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* Actually create the clipper.
*/
hRes = InternalCreateClipper( this, dwFlags, lplpDDClipper, pUnkOuter, TRUE, this_lcl, this_int );
LEAVE_DDRAW();
return hRes;
} /* DD_CreateClipper */
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawCreateClipper"
/*
* DirectDrawCreateClipper
*
* One of the three end-user API exported from DDRAW.DLL.
* Creates a DIRECTDRAWCLIPPER object not owned by a
* particular DirectDraw object.
*/
HRESULT WINAPI DirectDrawCreateClipper( DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter )
{
HRESULT hRes;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DirectDrawCreateClipper");
hRes = InternalCreateClipper( NULL, dwFlags, lplpDDClipper, pUnkOuter, TRUE, NULL, NULL );
LEAVE_DDRAW();
return hRes;
} /* DirectDrawCreateClipper */
#undef DPF_MODNAME
#define DPF_MODNAME "Clipper: Initialize"
/*
* DD_Clipper_Initialize
*/
HRESULT DDAPI DD_Clipper_Initialize(
LPDIRECTDRAWCLIPPER lpDDClipper,
LPDIRECTDRAW lpDD,
DWORD dwFlags )
{
LPDDRAWI_DDRAWCLIPPER_INT this_int;
LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
LPDDRAWI_DDRAWCLIPPER_GBL this_gbl;
LPDDRAWI_DIRECTDRAW_INT pdrv_int;
LPDDRAWI_DIRECTDRAW_GBL pdrv_gbl;
ENTER_DDRAW();
DPF(2,A,"ENTERAPI: DD_Clipper_Initialize");
TRY
{
this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
{
DPF_ERR( "Invalid clipper interface pointer" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
this_lcl = this_int->lpLcl;
this_gbl = this_lcl->lpGbl;
pdrv_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
if( NULL != pdrv_int )
{
if( !VALID_DIRECTDRAW_PTR( pdrv_int ) )
{
DPF_ERR( "Invalid DirectDraw object" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
pdrv_gbl = pdrv_int->lpLcl->lpGbl;
}
else
{
pdrv_gbl = NULL;
}
if( this_gbl->dwFlags & DDRAWICLIP_ISINITIALIZED )
{
DPF_ERR( "Clipper already initialized" );
LEAVE_DDRAW();
return DDERR_ALREADYINITIALIZED;
}
/*
* Validate flags - no flags currently supported
*/
if( 0UL != dwFlags )
{
DPF_ERR( "Invalid flags" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception encountered validating parameters" );
LEAVE_DDRAW();
return DDERR_INVALIDPARAMS;
}
/*
* As we don't support any flags the only function of Initialize() is
* to move the clipper from the global list to the list of the supplied
* driver object. If no driver is supplied Initialized is a no-op.
* CoCreateInstance() does all the initialization necessary.
*/
if( NULL != pdrv_gbl )
{
RemoveClipperFromList( NULL, this_int );
this_int->lpLink = pdrv_gbl->clipperList;
pdrv_gbl->clipperList = this_int;
this_gbl->lpDD = pdrv_gbl;
this_lcl->lpDD_lcl = pdrv_int->lpLcl;
this_lcl->lpDD_int = pdrv_int;
}
this_gbl->dwFlags |= DDRAWICLIP_ISINITIALIZED;
/*
* The real vtable can be used now.
*/
this_int->lpVtbl = &ddClipperCallbacks;
LEAVE_DDRAW();
return DD_OK;
} /* DD_Clipper_Initialize */
/*
* ProcessClipperCleanup
*
* A process is done, clean up any clippers it may have created
*
* NOTE: we enter with a lock taken on the DIRECTDRAW object.
*/
void ProcessClipperCleanup( LPDDRAWI_DIRECTDRAW_GBL pdrv, DWORD pid, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
{
LPDDRAWI_DDRAWCLIPPER_INT pclipper_int;
LPDDRAWI_DDRAWCLIPPER_INT ppnext_int;
DWORD rcnt;
ULONG rc;
/*
* Cleaning up the clippers is now a two stage process. We need to
* clean up all the clippers create via CreateClipper(), i.e., those
* attached to a DirectDraw driver object. We also need to clean up
* those clippers created by thise process with DirectDrawClipperCreate,
* i.e., those not attached to a driver object.
*/
/*
* run through all clippers owned by the driver object, and find ones
* that have been accessed by this process. If the pdrv_lcl parameter is
* non-null, only clean them up if they were created by that local object.
*/
DPF( 4, "ProcessClipperCleanup" );
if( NULL != pdrv )
{
DPF( 5, "Cleaning up clippers owned by driver object 0x%08x", pdrv );
pclipper_int = pdrv->clipperList;
}
else
{
pclipper_int = NULL;
}
while( pclipper_int != NULL )
{
ppnext_int = pclipper_int->lpLink;
/*
* All clippers in this list should have a valid back pointer to
* this driver object.
*/
DDASSERT( pclipper_int->lpLcl->lpGbl->lpDD == pdrv );
rc = 1;
if( (pclipper_int->lpLcl->lpGbl->dwProcessId == pid) &&
( (pdrv_lcl == NULL) || (pdrv_lcl == pclipper_int->lpLcl->lpDD_lcl) ))
{
/*
* release the references by this process
*/
rcnt = pclipper_int->dwIntRefCnt;
DPF( 5, "Process %08lx had %ld accesses to clipper %08lx", pid, rcnt, pclipper_int );
while( rcnt > 0 )
{
rc = InternalClipperRelease( pclipper_int );
/* GEE: 0 is now an error code,
* errors weren't handled before anyway,
* does this matter.
*/
if( rc == 0 )
{
break;
}
rcnt--;
}
}
else
{
DPF( 5, "Process %08lx does not have access to clipper" );
}
pclipper_int = ppnext_int;
}
/*
* Now clean up the global clipper list.
* If the pdrv_lcl parameter is not NULL then we are only cleaning up clipper
* objects created by a particular local driver object. In this case we
* do not want to free the global clippers.
*
* NOTE: The DirectDraw lock is taken so we can safely access this global object.
*/
if( NULL != pdrv_lcl )
{
DPF( 4, "Not cleaning up clippers not owned by a driver object");
return;
}
DPF( 4, "Cleaning up clippers not owned by a driver object" );
pclipper_int = lpGlobalClipperList;
while( pclipper_int != NULL )
{
ppnext_int = pclipper_int->lpLink;
/*
* The clippers in this list should never have a back pointer to a driver
* object.
*/
DDASSERT( pclipper_int->lpLcl->lpGbl->lpDD == NULL );
rc = 1;
if( pclipper_int->lpLcl->lpGbl->dwProcessId == pid )
{
/*
* release the references by this process
*/
rcnt = pclipper_int->dwIntRefCnt;
while( rcnt > 0 )
{
rc = InternalClipperRelease( pclipper_int );
/* GEE: 0 is now an error code,
* errors weren't handled before anyway,
* does this matter.
*/
if( rc == 0 )
{
break;
}
rcnt--;
}
}
pclipper_int = ppnext_int;
}
DPF( 4, "Done ProcessClipperCleanup" );
} /* ProcessClipperCleanup */