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.

246 lines
5.3 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. BattleZone.cpp
  5. Abstract:
  6. This app is a really good example of things not to do:
  7. 1. Infinite loop on mciSendString('play...'). In order to fix this we
  8. return a failure case if the same play string is sent twice and the
  9. device is playing already. Note that the behaviour of the
  10. mciSendString API is consistent with win9x. Someone managed to repro
  11. this hang on win9x, but it's more difficult.
  12. 2. They call SetCooperativeLevel(DDSCL_NORMAL) between a Begin/End
  13. Scene. On NT, this causes the Z-Buffer to be lost which means that
  14. when EndScene is called, it returns D3DERR_SURFACESLOST which causes
  15. the app to AV.
  16. Notes:
  17. This is an app specific shim.
  18. History:
  19. 02/10/2000 linstev Created
  20. --*/
  21. #include "precomp.h"
  22. #include <mmsystem.h>
  23. IMPLEMENT_SHIM_BEGIN(BattleZone)
  24. #include "ShimHookMacro.h"
  25. APIHOOK_ENUM_BEGIN
  26. APIHOOK_ENUM_ENTRY_DIRECTX_COMSERVER()
  27. APIHOOK_ENUM_ENTRY(mciSendCommandA)
  28. APIHOOK_ENUM_ENTRY(mciSendStringA)
  29. APIHOOK_ENUM_END
  30. IMPLEMENT_DIRECTX_COMSERVER_HOOKS()
  31. CString * g_csLastCommand = NULL;
  32. MCIDEVICEID g_wDeviceID = 0;
  33. LPDIRECTDRAWSURFACE g_lpZBuffer = NULL;
  34. /*++
  35. Store the DeviceId.
  36. --*/
  37. MCIERROR
  38. APIHOOK(mciSendCommandA)(
  39. MCIDEVICEID IDDevice,
  40. UINT uMsg,
  41. DWORD fdwCommand,
  42. DWORD dwParam
  43. )
  44. {
  45. MCIERROR mErr = ORIGINAL_API(mciSendCommandA)(
  46. IDDevice,
  47. uMsg,
  48. fdwCommand,
  49. dwParam);
  50. if ((mErr == 0) && (uMsg == MCI_OPEN))
  51. {
  52. g_wDeviceID = ((LPMCI_OPEN_PARMS)dwParam)->wDeviceID;
  53. }
  54. return mErr;
  55. }
  56. /*++
  57. Prevent looping.
  58. --*/
  59. MCIERROR
  60. APIHOOK(mciSendStringA)(
  61. LPCSTR lpszCommand,
  62. LPSTR lpszReturnString,
  63. UINT cchReturn,
  64. HANDLE hwndCallback
  65. )
  66. {
  67. DPFN( eDbgLevelInfo, "mciSendStringA: %s", lpszCommand);
  68. CSTRING_TRY
  69. {
  70. CString csCommand(lpszCommand);
  71. if (csCommand.Compare(*g_csLastCommand) == 0)
  72. {
  73. MCI_STATUS_PARMS mciStatus;
  74. ZeroMemory(&mciStatus, sizeof(mciStatus));
  75. mciStatus.dwItem = MCI_STATUS_MODE;
  76. if (0 == ORIGINAL_API(mciSendCommandA)(
  77. g_wDeviceID,
  78. MCI_STATUS,
  79. MCI_STATUS_ITEM,
  80. (DWORD_PTR)&mciStatus))
  81. {
  82. if (mciStatus.dwReturn == MCI_MODE_PLAY)
  83. {
  84. DPFN( eDbgLevelWarning, "Device still playing, returning busy");
  85. return MCIERR_DEVICE_NOT_READY;
  86. }
  87. }
  88. }
  89. else
  90. {
  91. *g_csLastCommand = csCommand;
  92. }
  93. }
  94. CSTRING_CATCH
  95. {
  96. // Do nothing
  97. }
  98. return ORIGINAL_API(mciSendStringA)(
  99. lpszCommand,
  100. lpszReturnString,
  101. cchReturn,
  102. hwndCallback);
  103. }
  104. /*++
  105. Hook create surface to find the zbuffer we'll need to restore later. Note that
  106. we use HookObject to get the surface release notification.
  107. --*/
  108. HRESULT
  109. COMHOOK(IDirectDraw, CreateSurface)(
  110. PVOID pThis,
  111. LPDDSURFACEDESC lpDDSurfaceDesc,
  112. LPDIRECTDRAWSURFACE *lplpDDSurface,
  113. IUnknown* pUnkOuter
  114. )
  115. {
  116. HRESULT hReturn;
  117. _pfn_IDirectDraw_CreateSurface pfnOld =
  118. ORIGINAL_COM(IDirectDraw, CreateSurface, pThis);
  119. if (SUCCEEDED(hReturn = (*pfnOld)(
  120. pThis,
  121. lpDDSurfaceDesc,
  122. lplpDDSurface,
  123. pUnkOuter)))
  124. {
  125. if (lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_ZBUFFER)
  126. {
  127. g_lpZBuffer = *lplpDDSurface;
  128. DPFN( eDbgLevelInfo, "Found ZBuffer", g_lpZBuffer);
  129. }
  130. }
  131. return hReturn;
  132. }
  133. /*++
  134. Use SetCooperativeLevel to keep track of who the exclusive mode owner is.
  135. --*/
  136. HRESULT
  137. COMHOOK(IDirectDraw, SetCooperativeLevel)(
  138. PVOID pThis,
  139. HWND hWnd,
  140. DWORD dwFlags
  141. )
  142. {
  143. HRESULT hReturn;
  144. // Original SetCooperativeLevel
  145. _pfn_IDirectDraw_SetCooperativeLevel pfnOld =
  146. ORIGINAL_COM(IDirectDraw, SetCooperativeLevel, pThis);
  147. hReturn = (*pfnOld)(pThis, hWnd, dwFlags);
  148. __try
  149. {
  150. if (g_lpZBuffer && (g_lpZBuffer->IsLost() == DDERR_SURFACELOST))
  151. {
  152. g_lpZBuffer->Restore();
  153. DPFN( eDbgLevelInfo, "Restoring lost ZBuffer");
  154. }
  155. }
  156. __except(EXCEPTION_EXECUTE_HANDLER)
  157. {
  158. }
  159. return hReturn;
  160. }
  161. /*++
  162. Allocate global variables.
  163. --*/
  164. BOOL
  165. NOTIFY_FUNCTION(
  166. DWORD fdwReason)
  167. {
  168. if (fdwReason == DLL_PROCESS_ATTACH) {
  169. CSTRING_TRY
  170. {
  171. g_csLastCommand = new CString;
  172. return g_csLastCommand != NULL;
  173. }
  174. CSTRING_CATCH
  175. {
  176. return FALSE;
  177. }
  178. }
  179. return TRUE;
  180. }
  181. HOOK_BEGIN
  182. CALL_NOTIFY_FUNCTION
  183. APIHOOK_ENTRY_DIRECTX_COMSERVER()
  184. COMHOOK_ENTRY(DirectDraw, IDirectDraw, CreateSurface, 6)
  185. COMHOOK_ENTRY(DirectDraw, IDirectDraw, SetCooperativeLevel, 20)
  186. APIHOOK_ENTRY(WINMM.DLL, mciSendCommandA)
  187. APIHOOK_ENTRY(WINMM.DLL, mciSendStringA)
  188. HOOK_END
  189. IMPLEMENT_SHIM_END