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.
252 lines
6.9 KiB
252 lines
6.9 KiB
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: w95hack.c
|
|
* Content: Win95 hack-o-rama code
|
|
* This is a HACK to handle the fact that Win95 doesn't notify
|
|
* a DLL when a process is destroyed.
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 28-mar-95 craige initial implementation
|
|
* 01-apr-95 craige happy fun joy updated header file
|
|
* 06-apr-95 craige reworked for new ddhelp
|
|
* 11-apr-95 craige bug where dwFakeCurrPid was getting set and
|
|
* other processes were ending up using it!
|
|
* 24-jun-95 craige call RemoveProcessFromDLL; use that to fiddle
|
|
* with DLL refcnt
|
|
* 25-jun-95 craige one ddraw mutex
|
|
* 19-jul-95 craige notify DDHELP to clean up DC list on last object detach
|
|
* 20-jul-95 craige internal reorg to prevent thunking during modeset
|
|
* 12-oct-96 colinmc Improvements to Win16 locking code to reduce virtual
|
|
* memory usage
|
|
* 18-jan-97 colinmc ddhelp vxd handling is no longer win16 lock specific
|
|
* we now need it for agp support
|
|
*
|
|
***************************************************************************/
|
|
#include "ddrawpr.h"
|
|
#include "dx8priv.h"
|
|
|
|
/*
|
|
* HackGetCurrentProcessId
|
|
*
|
|
* This call is used in place of GetCurrentProcessId on Win95.
|
|
* This allows us to substitute the pid of the terminated task passed to
|
|
* us from DDHELP as the "current" process.
|
|
*/
|
|
DWORD HackGetCurrentProcessId( void )
|
|
{
|
|
DWORD pid;
|
|
|
|
pid = GetCurrentProcessId();
|
|
if( pid == dwGrimReaperPid )
|
|
{
|
|
return dwFakeCurrPid;
|
|
}
|
|
else
|
|
{
|
|
return pid;
|
|
}
|
|
|
|
} /* HackGetCurrentProcessId */
|
|
|
|
/*
|
|
* DDNotify
|
|
*
|
|
* called by DDHELP to notify us when a pid is dead
|
|
*/
|
|
BOOL DDAPI DDNotify( LPDDHELPDATA phd )
|
|
{
|
|
BOOL rc;
|
|
//extern DWORD dwRefCnt;
|
|
|
|
#ifdef USE_CHEAP_MUTEX
|
|
DestroyPIDsLock (&CheapMutexCrossProcess,phd->pid,DDRAW_FAST_CS_NAME);
|
|
#endif
|
|
|
|
ENTER_DDRAW();
|
|
|
|
dwGrimReaperPid = GetCurrentProcessId();
|
|
dwFakeCurrPid = phd->pid;
|
|
DPF( 4, "************* DDNotify: dwPid=%08lx has died, calling CurrentProcessCleanup", phd->pid );
|
|
rc = FALSE;
|
|
|
|
CurrentProcessCleanup( TRUE );
|
|
|
|
if( RemoveProcessFromDLL( phd->pid ) )
|
|
{
|
|
/*
|
|
* update refcnt if RemoveProcessFromDLL is successful.
|
|
* It is only successful if we had a process get blown away...
|
|
*/
|
|
DPF( 5, "DDNotify: DLL RefCnt = %lu", dwRefCnt );
|
|
if( dwRefCnt == 2 )
|
|
{
|
|
DPF( 5, "DDNotify: On last refcnt, safe to kill DDHELP.EXE" );
|
|
dwRefCnt = 1;
|
|
rc = TRUE; // free the DC list
|
|
FreeAppHackData();
|
|
#if defined( DEBUG ) && defined (WIN95)
|
|
DPF( 6, "Memory state after automatic cleanup: (one allocation expected)" );
|
|
MemState();
|
|
#endif
|
|
}
|
|
else if( dwRefCnt == 1 )
|
|
{
|
|
DPF( 0, "ERROR! DLL REFCNT DOWN TO 1" );
|
|
#if 0
|
|
MemFini();
|
|
dwRefCnt = 0;
|
|
strcpy( phd->fname, DDHAL_APP_DLLNAME );
|
|
#endif
|
|
}
|
|
else if( dwRefCnt > 0 )
|
|
{
|
|
dwRefCnt--;
|
|
}
|
|
}
|
|
/* order is important, clear dwGrimReaperPid first */
|
|
dwGrimReaperPid = 0;
|
|
dwFakeCurrPid = 0;
|
|
DPF( 4, "************* DDNotify: *** DONE ***" );
|
|
|
|
LEAVE_DDRAW();
|
|
return rc;
|
|
|
|
} /* DDNotify */
|
|
|
|
/*
|
|
* DDNotifyModeSet
|
|
*
|
|
* called by ddhelp when an extern modeset is done...
|
|
*
|
|
* NOTE: We can explicitly use the cached DDHELP
|
|
* VXD handle as we know this code can only ever get
|
|
* executed on a DDHELP thread.
|
|
*/
|
|
void DDAPI DDNotifyModeSet( LPDDRAWI_DIRECTDRAW_GBL pdrv )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
BOOL bRestoreGamma;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
/* DPF( 2, "DDNotifyModeSet, object %08lx", pdrv ); */
|
|
|
|
/*
|
|
* make sure the driver isn't trying to lie to us about the old object
|
|
* This check should always be made at the top of this routine, since it's
|
|
* possible in stress scenarios for ddhelp's modeset thread to wake up
|
|
* just before it's killed at the end of DD_Release (since the code to kill
|
|
* the mode set thread is executed AFTER the last LEAVE_DDRAW in DD_Release).
|
|
*/
|
|
if( pdrv != NULL )
|
|
{
|
|
pdrv_lcl = lpDriverLocalList;
|
|
while( pdrv_lcl != NULL )
|
|
{
|
|
if( pdrv_lcl->lpGbl == pdrv )
|
|
{
|
|
break;
|
|
}
|
|
pdrv_lcl = pdrv_lcl->lpLink;
|
|
}
|
|
if( pdrv_lcl == NULL )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return;
|
|
}
|
|
}
|
|
|
|
bRestoreGamma = ( pdrv_lcl->lpPrimary != NULL ) &&
|
|
( pdrv_lcl->lpPrimary->lpLcl->lpSurfMore->lpGammaRamp != NULL ) &&
|
|
( pdrv_lcl->lpPrimary->lpLcl->dwFlags & DDRAWISURF_SETGAMMA );
|
|
|
|
#ifdef WIN95
|
|
DDASSERT( INVALID_HANDLE_VALUE != hHelperDDVxd );
|
|
FetchDirectDrawData( pdrv, TRUE, 0, hHelperDDVxd, NULL, 0 , NULL );
|
|
#else /* WIN95 */
|
|
FetchDirectDrawData( pdrv, TRUE, 0, NULL, NULL, 0 , NULL );
|
|
#endif /* WIN95 */
|
|
|
|
/*
|
|
* Some drivers reset the gamma after a mode change, so we need to
|
|
* force it back.
|
|
*/
|
|
if( bRestoreGamma )
|
|
{
|
|
SetGamma( pdrv_lcl->lpPrimary->lpLcl, pdrv_lcl );
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
DPF( 4, "DDNotifyModeSet DONE" );
|
|
|
|
} /* DDNotifyModeSet */
|
|
|
|
/*
|
|
* DDNotifyDOSBox
|
|
*
|
|
* called by ddhelp when exiting from a DOS box...
|
|
*
|
|
* NOTE: We can explicitly use the cached DDHELP
|
|
* VXD handle as we know this code can only ever get
|
|
* executed on a DDHELP thread.
|
|
*/
|
|
void DDAPI DDNotifyDOSBox( LPDDRAWI_DIRECTDRAW_GBL pdrv )
|
|
{
|
|
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
|
|
BOOL bRestoreGamma;
|
|
|
|
ENTER_DDRAW();
|
|
|
|
/* DPF( 2, "DDNotifyDOSBox, object %08lx", pdrv ); */
|
|
|
|
/*
|
|
* make sure the driver isn't trying to lie to us about the old object
|
|
* This check should always be made at the top of this routine, since it's
|
|
* possible in stress scenarios for ddhelp's modeset thread to wake up
|
|
* just before it's killed at the end of DD_Release (since the code to kill
|
|
* the mode set thread is executed AFTER the last LEAVE_DDRAW in DD_Release).
|
|
*/
|
|
if( pdrv != NULL )
|
|
{
|
|
pdrv_lcl = lpDriverLocalList;
|
|
while( pdrv_lcl != NULL )
|
|
{
|
|
if( pdrv_lcl->lpGbl == pdrv )
|
|
{
|
|
break;
|
|
}
|
|
pdrv_lcl = pdrv_lcl->lpLink;
|
|
}
|
|
if( pdrv_lcl == NULL )
|
|
{
|
|
LEAVE_DDRAW();
|
|
return;
|
|
}
|
|
}
|
|
|
|
bRestoreGamma = ( pdrv_lcl->lpPrimary != NULL ) &&
|
|
( pdrv_lcl->lpPrimary->lpLcl->lpSurfMore->lpGammaRamp != NULL ) &&
|
|
( pdrv_lcl->lpPrimary->lpLcl->dwFlags & DDRAWISURF_SETGAMMA );
|
|
|
|
#ifdef WIN95
|
|
InvalidateAllSurfaces( pdrv, hHelperDDVxd, TRUE );
|
|
#else
|
|
InvalidateAllSurfaces( pdrv, NULL, TRUE );
|
|
#endif
|
|
|
|
/*
|
|
* Invalidating the surfaces will mess up the gamma so we need to
|
|
* restore it.
|
|
*/
|
|
if( bRestoreGamma )
|
|
{
|
|
SetGamma( pdrv_lcl->lpPrimary->lpLcl, pdrv_lcl );
|
|
}
|
|
|
|
LEAVE_DDRAW();
|
|
DPF( 4, "DDNotifyDOSBox DONE" );
|
|
|
|
} /* DDNotifyDOSBox */
|