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.

252 lines
6.9 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: w95hack.c
  6. * Content: Win95 hack-o-rama code
  7. * This is a HACK to handle the fact that Win95 doesn't notify
  8. * a DLL when a process is destroyed.
  9. * History:
  10. * Date By Reason
  11. * ==== == ======
  12. * 28-mar-95 craige initial implementation
  13. * 01-apr-95 craige happy fun joy updated header file
  14. * 06-apr-95 craige reworked for new ddhelp
  15. * 11-apr-95 craige bug where dwFakeCurrPid was getting set and
  16. * other processes were ending up using it!
  17. * 24-jun-95 craige call RemoveProcessFromDLL; use that to fiddle
  18. * with DLL refcnt
  19. * 25-jun-95 craige one ddraw mutex
  20. * 19-jul-95 craige notify DDHELP to clean up DC list on last object detach
  21. * 20-jul-95 craige internal reorg to prevent thunking during modeset
  22. * 12-oct-96 colinmc Improvements to Win16 locking code to reduce virtual
  23. * memory usage
  24. * 18-jan-97 colinmc ddhelp vxd handling is no longer win16 lock specific
  25. * we now need it for agp support
  26. *
  27. ***************************************************************************/
  28. #include "ddrawpr.h"
  29. #include "dx8priv.h"
  30. /*
  31. * HackGetCurrentProcessId
  32. *
  33. * This call is used in place of GetCurrentProcessId on Win95.
  34. * This allows us to substitute the pid of the terminated task passed to
  35. * us from DDHELP as the "current" process.
  36. */
  37. DWORD HackGetCurrentProcessId( void )
  38. {
  39. DWORD pid;
  40. pid = GetCurrentProcessId();
  41. if( pid == dwGrimReaperPid )
  42. {
  43. return dwFakeCurrPid;
  44. }
  45. else
  46. {
  47. return pid;
  48. }
  49. } /* HackGetCurrentProcessId */
  50. /*
  51. * DDNotify
  52. *
  53. * called by DDHELP to notify us when a pid is dead
  54. */
  55. BOOL DDAPI DDNotify( LPDDHELPDATA phd )
  56. {
  57. BOOL rc;
  58. //extern DWORD dwRefCnt;
  59. #ifdef USE_CHEAP_MUTEX
  60. DestroyPIDsLock (&CheapMutexCrossProcess,phd->pid,DDRAW_FAST_CS_NAME);
  61. #endif
  62. ENTER_DDRAW();
  63. dwGrimReaperPid = GetCurrentProcessId();
  64. dwFakeCurrPid = phd->pid;
  65. DPF( 4, "************* DDNotify: dwPid=%08lx has died, calling CurrentProcessCleanup", phd->pid );
  66. rc = FALSE;
  67. CurrentProcessCleanup( TRUE );
  68. if( RemoveProcessFromDLL( phd->pid ) )
  69. {
  70. /*
  71. * update refcnt if RemoveProcessFromDLL is successful.
  72. * It is only successful if we had a process get blown away...
  73. */
  74. DPF( 5, "DDNotify: DLL RefCnt = %lu", dwRefCnt );
  75. if( dwRefCnt == 2 )
  76. {
  77. DPF( 5, "DDNotify: On last refcnt, safe to kill DDHELP.EXE" );
  78. dwRefCnt = 1;
  79. rc = TRUE; // free the DC list
  80. FreeAppHackData();
  81. #if defined( DEBUG ) && defined (WIN95)
  82. DPF( 6, "Memory state after automatic cleanup: (one allocation expected)" );
  83. MemState();
  84. #endif
  85. }
  86. else if( dwRefCnt == 1 )
  87. {
  88. DPF( 0, "ERROR! DLL REFCNT DOWN TO 1" );
  89. #if 0
  90. MemFini();
  91. dwRefCnt = 0;
  92. strcpy( phd->fname, DDHAL_APP_DLLNAME );
  93. #endif
  94. }
  95. else if( dwRefCnt > 0 )
  96. {
  97. dwRefCnt--;
  98. }
  99. }
  100. /* order is important, clear dwGrimReaperPid first */
  101. dwGrimReaperPid = 0;
  102. dwFakeCurrPid = 0;
  103. DPF( 4, "************* DDNotify: *** DONE ***" );
  104. LEAVE_DDRAW();
  105. return rc;
  106. } /* DDNotify */
  107. /*
  108. * DDNotifyModeSet
  109. *
  110. * called by ddhelp when an extern modeset is done...
  111. *
  112. * NOTE: We can explicitly use the cached DDHELP
  113. * VXD handle as we know this code can only ever get
  114. * executed on a DDHELP thread.
  115. */
  116. void DDAPI DDNotifyModeSet( LPDDRAWI_DIRECTDRAW_GBL pdrv )
  117. {
  118. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  119. BOOL bRestoreGamma;
  120. ENTER_DDRAW();
  121. /* DPF( 2, "DDNotifyModeSet, object %08lx", pdrv ); */
  122. /*
  123. * make sure the driver isn't trying to lie to us about the old object
  124. * This check should always be made at the top of this routine, since it's
  125. * possible in stress scenarios for ddhelp's modeset thread to wake up
  126. * just before it's killed at the end of DD_Release (since the code to kill
  127. * the mode set thread is executed AFTER the last LEAVE_DDRAW in DD_Release).
  128. */
  129. if( pdrv != NULL )
  130. {
  131. pdrv_lcl = lpDriverLocalList;
  132. while( pdrv_lcl != NULL )
  133. {
  134. if( pdrv_lcl->lpGbl == pdrv )
  135. {
  136. break;
  137. }
  138. pdrv_lcl = pdrv_lcl->lpLink;
  139. }
  140. if( pdrv_lcl == NULL )
  141. {
  142. LEAVE_DDRAW();
  143. return;
  144. }
  145. }
  146. bRestoreGamma = ( pdrv_lcl->lpPrimary != NULL ) &&
  147. ( pdrv_lcl->lpPrimary->lpLcl->lpSurfMore->lpGammaRamp != NULL ) &&
  148. ( pdrv_lcl->lpPrimary->lpLcl->dwFlags & DDRAWISURF_SETGAMMA );
  149. #ifdef WIN95
  150. DDASSERT( INVALID_HANDLE_VALUE != hHelperDDVxd );
  151. FetchDirectDrawData( pdrv, TRUE, 0, hHelperDDVxd, NULL, 0 , NULL );
  152. #else /* WIN95 */
  153. FetchDirectDrawData( pdrv, TRUE, 0, NULL, NULL, 0 , NULL );
  154. #endif /* WIN95 */
  155. /*
  156. * Some drivers reset the gamma after a mode change, so we need to
  157. * force it back.
  158. */
  159. if( bRestoreGamma )
  160. {
  161. SetGamma( pdrv_lcl->lpPrimary->lpLcl, pdrv_lcl );
  162. }
  163. LEAVE_DDRAW();
  164. DPF( 4, "DDNotifyModeSet DONE" );
  165. } /* DDNotifyModeSet */
  166. /*
  167. * DDNotifyDOSBox
  168. *
  169. * called by ddhelp when exiting from a DOS box...
  170. *
  171. * NOTE: We can explicitly use the cached DDHELP
  172. * VXD handle as we know this code can only ever get
  173. * executed on a DDHELP thread.
  174. */
  175. void DDAPI DDNotifyDOSBox( LPDDRAWI_DIRECTDRAW_GBL pdrv )
  176. {
  177. LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
  178. BOOL bRestoreGamma;
  179. ENTER_DDRAW();
  180. /* DPF( 2, "DDNotifyDOSBox, object %08lx", pdrv ); */
  181. /*
  182. * make sure the driver isn't trying to lie to us about the old object
  183. * This check should always be made at the top of this routine, since it's
  184. * possible in stress scenarios for ddhelp's modeset thread to wake up
  185. * just before it's killed at the end of DD_Release (since the code to kill
  186. * the mode set thread is executed AFTER the last LEAVE_DDRAW in DD_Release).
  187. */
  188. if( pdrv != NULL )
  189. {
  190. pdrv_lcl = lpDriverLocalList;
  191. while( pdrv_lcl != NULL )
  192. {
  193. if( pdrv_lcl->lpGbl == pdrv )
  194. {
  195. break;
  196. }
  197. pdrv_lcl = pdrv_lcl->lpLink;
  198. }
  199. if( pdrv_lcl == NULL )
  200. {
  201. LEAVE_DDRAW();
  202. return;
  203. }
  204. }
  205. bRestoreGamma = ( pdrv_lcl->lpPrimary != NULL ) &&
  206. ( pdrv_lcl->lpPrimary->lpLcl->lpSurfMore->lpGammaRamp != NULL ) &&
  207. ( pdrv_lcl->lpPrimary->lpLcl->dwFlags & DDRAWISURF_SETGAMMA );
  208. #ifdef WIN95
  209. InvalidateAllSurfaces( pdrv, hHelperDDVxd, TRUE );
  210. #else
  211. InvalidateAllSurfaces( pdrv, NULL, TRUE );
  212. #endif
  213. /*
  214. * Invalidating the surfaces will mess up the gamma so we need to
  215. * restore it.
  216. */
  217. if( bRestoreGamma )
  218. {
  219. SetGamma( pdrv_lcl->lpPrimary->lpLcl, pdrv_lcl );
  220. }
  221. LEAVE_DDRAW();
  222. DPF( 4, "DDNotifyDOSBox DONE" );
  223. } /* DDNotifyDOSBox */