Source code of Windows XP (NT5)
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.

170 lines
3.6 KiB

  1. /*++
  2. Copyright (c) 1999 Microsoft Corporation
  3. Module Name:
  4. UltimateSoccerManager.cpp
  5. Abstract:
  6. A hack for Ultimate Soccer Manager (Sierra Sports). The game caches a
  7. pointer to a ddraw system memory surface. It later uses that pointer even
  8. after the surface has been freed.
  9. This worked on Win9x by blind luck: when they re-create a new surface, it
  10. happened to end up in the same system memory as before.
  11. Notes:
  12. This is an app specific shim.
  13. History:
  14. 01/07/2000 linstev Created
  15. --*/
  16. #include "precomp.h"
  17. IMPLEMENT_SHIM_BEGIN(UltimateSoccerManager)
  18. #include "ShimHookMacro.h"
  19. APIHOOK_ENUM_BEGIN
  20. APIHOOK_ENUM_ENTRY_DIRECTX_COMSERVER()
  21. APIHOOK_ENUM_END
  22. IMPLEMENT_DIRECTX_COMSERVER_HOOKS()
  23. // Keep a list of cached surfaces
  24. struct SLIST
  25. {
  26. struct SLIST *next;
  27. DDSURFACEDESC ddsd;
  28. LPDIRECTDRAWSURFACE lpDDSurface;
  29. };
  30. SLIST *g_SList = NULL;
  31. /*++
  32. Hook create surface so we can return the cached surface if possible.
  33. --*/
  34. HRESULT
  35. COMHOOK(IDirectDraw, CreateSurface)(
  36. PVOID pThis,
  37. LPDDSURFACEDESC lpDDSurfaceDesc,
  38. LPDIRECTDRAWSURFACE* lplpDDSurface,
  39. IUnknown* pUnkOuter
  40. )
  41. {
  42. HRESULT hReturn;
  43. // Retrieve the old function
  44. _pfn_IDirectDraw_CreateSurface pfnOld =
  45. ORIGINAL_COM(IDirectDraw, CreateSurface, pThis);
  46. SLIST *surf = g_SList, *last = NULL;
  47. while (surf)
  48. {
  49. // Check for the same kind of surface.
  50. if ((lpDDSurfaceDesc->ddsCaps.dwCaps == surf->ddsd.ddsCaps.dwCaps) &&
  51. (lpDDSurfaceDesc->dwWidth == surf->ddsd.dwWidth) &&
  52. (lpDDSurfaceDesc->dwHeight == surf->ddsd.dwHeight))
  53. {
  54. *lplpDDSurface = surf->lpDDSurface;
  55. if (last)
  56. {
  57. last->next = surf->next;
  58. }
  59. else
  60. {
  61. g_SList = surf->next;
  62. }
  63. free(surf);
  64. DPFN( eDbgLevelInfo, "Returning cached surface %08lx\n", *lplpDDSurface);
  65. return DD_OK;
  66. }
  67. surf = surf->next;
  68. }
  69. if (SUCCEEDED(hReturn = (*pfnOld)(
  70. pThis,
  71. lpDDSurfaceDesc,
  72. lplpDDSurface,
  73. pUnkOuter)))
  74. {
  75. HookObject(
  76. NULL,
  77. IID_IDirectDrawSurface,
  78. (PVOID*)lplpDDSurface,
  79. NULL,
  80. FALSE);
  81. }
  82. return hReturn;
  83. }
  84. /*++
  85. If it's a system memory surface, go ahead and cache it if we're about to
  86. release it anyway.
  87. --*/
  88. ULONG
  89. COMHOOK(IDirectDrawSurface, Release)(
  90. LPDIRECTDRAWSURFACE lpDDSurface
  91. )
  92. {
  93. lpDDSurface->AddRef();
  94. // Retrieve the old function
  95. _pfn_IDirectDrawSurface_Release pfnOld = ORIGINAL_COM(IDirectDrawSurface, Release, (LPVOID) lpDDSurface);
  96. ULONG uRet = (*pfnOld)(lpDDSurface);
  97. if (uRet == 1)
  98. {
  99. DDSURFACEDESC ddsd = {sizeof(ddsd)};
  100. if (SUCCEEDED(lpDDSurface->GetSurfaceDesc(&ddsd)) &&
  101. (ddsd.ddsCaps.dwCaps ==
  102. (DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY)))
  103. {
  104. SLIST *surf = (SLIST *) malloc(sizeof(SLIST));
  105. surf->next = g_SList;
  106. MoveMemory(&surf->ddsd, &ddsd, sizeof(ddsd));
  107. surf->lpDDSurface = lpDDSurface;
  108. g_SList = surf;
  109. DPFN( eDbgLevelInfo, "Surface %08lx is being cached\n", lpDDSurface);
  110. return 0;
  111. }
  112. }
  113. return (*pfnOld)(lpDDSurface);
  114. }
  115. /*++
  116. Register hooked functions
  117. --*/
  118. HOOK_BEGIN
  119. APIHOOK_ENTRY_DIRECTX_COMSERVER()
  120. COMHOOK_ENTRY(DirectDraw, IDirectDraw, CreateSurface, 6)
  121. COMHOOK_ENTRY(DirectDraw, IDirectDrawSurface, Release, 2)
  122. HOOK_END
  123. IMPLEMENT_SHIM_END