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
4.5 KiB

  1. /*++
  2. Copyright (c) 2000-2002 Microsoft Corporation
  3. Module Name:
  4. CheckJoyCaps.cpp
  5. Abstract:
  6. Check for error return value in joyGetDevCaps and joyGetPos and if found
  7. make the structure (2nd parameter to routines) look just like it does under
  8. Win9x. It also looks for handles applications that are passing in a size
  9. parameter (3rd parameter) to joyGetDevCaps smaller than the current
  10. structure size. Not checking for this condition results in having the
  11. applications stack stomped on.
  12. Notes:
  13. This is general shim that could be used for any application with WINMM
  14. joystick problems.
  15. History:
  16. 10/02/2000 a-brienw Created
  17. 02/21/2002 mnikkel Corrected possible buffer overrun when copying in data
  18. --*/
  19. #include "precomp.h"
  20. #include <mmsystem.h>
  21. IMPLEMENT_SHIM_BEGIN(EmulateJoystick)
  22. #include "ShimHookMacro.h"
  23. APIHOOK_ENUM_BEGIN
  24. APIHOOK_ENUM_ENTRY(joyGetDevCapsA)
  25. APIHOOK_ENUM_ENTRY(joyGetPos)
  26. APIHOOK_ENUM_END
  27. /*++
  28. Hooked joyGetDevCapsA to make sure the JOYCAPS structure matched Win9x when
  29. an error was the result of a call to the OS. Also make sure that the call to
  30. joyGetDevCaps doesn't stomp on the applications stack by not paying attention
  31. to the size passed in by the application. Check the routine joyGetDevCapsA in
  32. joy.c in the WINMM code to see what it does.
  33. --*/
  34. MMRESULT
  35. APIHOOK(joyGetDevCapsA)(
  36. UINT uJoyID,
  37. LPJOYCAPS pjc,
  38. UINT cbjc
  39. )
  40. {
  41. MMRESULT ret = JOYERR_PARMS;
  42. JOYCAPSA JoyCaps;
  43. static const BYTE val[] = {0x00,0x70,0x6A,0x00,0x18,0xFD,0x6A,0x00,0xF8,0x58,
  44. 0xF9,0xBF,0x08,0x00,0x00,0x00,0xD0,0x5A,0x00,0x80,
  45. 0x00,0x00,0x00,0x00,0xC4,0x2F,0x73,0x81,0x00,0x00,
  46. 0x5A,0x00,0x18,0xFD,0x6A,0x00,0xF8,0x58,0xF9,0xBF,
  47. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x02,
  48. 0x00,0x00,0x52,0xD7,0x40,0x00,0x00,0x00,0x00,0x00,
  49. 0xC4,0x2F,0x73,0x81,0x00,0x00,0x5A,0x00,0x03};
  50. if (!IsBadWritePtr(pjc, cbjc) && cbjc > 0)
  51. {
  52. ret = ORIGINAL_API(joyGetDevCapsA)(
  53. uJoyID, (JOYCAPS *)&JoyCaps, sizeof(JOYCAPSA));
  54. if (ret == JOYERR_NOERROR)
  55. {
  56. // make sure the joycaps will fit in the supplied buffer
  57. DWORD dwSize = sizeof(JOYCAPSA);
  58. if (cbjc < dwSize)
  59. {
  60. dwSize = cbjc;
  61. LOGN( eDbgLevelWarning, "[APIHook_joyGetDevCapsA] Buffer too small, fixing");
  62. }
  63. memcpy(pjc, &JoyCaps, dwSize);
  64. }
  65. else
  66. {
  67. // make sure the joycaps will fit in the supplied buffer
  68. DWORD dwSize = ARRAYSIZE(val);
  69. if (cbjc < dwSize)
  70. {
  71. dwSize = cbjc;
  72. LOGN( eDbgLevelWarning, "[APIHook_joyGetDevCapsA] Buffer too small, fixing");
  73. }
  74. //
  75. // Make the return structure look just like Win9x under error
  76. // conditions without this CandyLand Adventure from Hasbro Interactive
  77. // will do a divide by 0 during start up. Note these values were copied
  78. // verbatim from Win9x.
  79. //
  80. memcpy(pjc, &val, dwSize);
  81. DPFN( eDbgLevelSpew, "[APIHook_joyGetDevCapsA] Joystick error, returning Win9x buffer");
  82. }
  83. }
  84. else
  85. {
  86. DPFN( eDbgLevelError, "[APIHook_joyGetDevCapsA] Invalid buffer");
  87. }
  88. return ret;
  89. }
  90. /*++
  91. Hooked joyGetPos to make sure the JOYINFO structure matched Win9x when an error
  92. was the result of a call to the OS.
  93. --*/
  94. MMRESULT
  95. APIHOOK(joyGetPos)(
  96. UINT uJoyID,
  97. LPJOYINFO pji
  98. )
  99. {
  100. BYTE *bp;
  101. MMRESULT ret;
  102. ret = ORIGINAL_API(joyGetPos)(uJoyID, pji);
  103. if (ret != JOYERR_NOERROR)
  104. {
  105. if (!IsBadWritePtr(pji, sizeof(JOYINFO)))
  106. {
  107. //
  108. // Make the return structure look just like Win9x under error
  109. // conditions.
  110. //
  111. bp = (BYTE *)pji;
  112. memset(bp, 0, sizeof(JOYINFO));
  113. bp[0] = 0x01;
  114. bp[5] = 0x30;
  115. DPFN( eDbgLevelSpew, "[APIHook_joyGetPos] Joystick error, returning Win9x buffer");
  116. }
  117. else
  118. {
  119. DPFN( eDbgLevelError, "[APIHook_joyGetPos] Invalid buffer");
  120. }
  121. }
  122. return ret;
  123. }
  124. /*++
  125. Register hooked functions
  126. --*/
  127. HOOK_BEGIN
  128. APIHOOK_ENTRY(WINMM.DLL, joyGetDevCapsA)
  129. APIHOOK_ENTRY(WINMM.DLL, joyGetPos)
  130. HOOK_END
  131. IMPLEMENT_SHIM_END