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.

490 lines
11 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. VRegistry_DSound.cpp
  5. Abstract:
  6. Module to add DSound apphacks with VRegistry
  7. History:
  8. 08/10/2001 mikrause Created
  9. --*/
  10. #include "precomp.h"
  11. IMPLEMENT_SHIM_BEGIN(VirtualRegistry)
  12. #include <windows.h>
  13. #include "shimhookmacro.h"
  14. #include "vregistry.h"
  15. #include "vregistry_dsound.h"
  16. #define DSAPPHACK_MAXNAME (MAX_PATH + 16 + 16)
  17. BOOL AddDirectSoundAppHack(DWORD dwHack,DWORD dwParam1,DWORD dwParam2);
  18. BOOL GetDirectSoundAppId(LPTSTR pszAppId);
  19. // Available DirectSound hacks
  20. #define DSAPPHACKID_DEVACCEL 1
  21. #define DSAPPHACKID_PADCURSORS 2
  22. #define DSAPPHACKID_CACHEPOSITIONS 3
  23. #define DSAPPHACKID_RETURNWRITEPOS 4
  24. #define DSAPPHACKID_SMOOTHWRITEPOS 5
  25. #define DSAPPHACKID_DISABLEDEVICE 6
  26. /*++
  27. Function Description:
  28. Sets the acceleration level the app will be allowed to use.
  29. Arguments:
  30. IN dwAcceleration - Acceleration level needed.
  31. IN dwDevicesAffected - Combination of device that this hack applies to.
  32. Notes:
  33. See vregistry_dsound.h for acceleration levels and device types.
  34. Returns:
  35. True if app hack applied, false otherwise.
  36. History:
  37. 08/10/2001 mikrause Created
  38. --*/
  39. BOOL
  40. AddDSHackDeviceAcceleration(
  41. IN DWORD dwAcceleration,
  42. IN DWORD dwDevicesAffected)
  43. {
  44. return AddDirectSoundAppHack(DSAPPHACKID_DEVACCEL, dwAcceleration,
  45. dwDevicesAffected);
  46. }
  47. /*++
  48. Function Description:
  49. Disabled some category of devices altogether, forces
  50. playback through emulated path.
  51. Arguments:
  52. IN dwDevicesAffected - Combination of device that this hack applies to.
  53. Notes:
  54. See vregistry_dsound.h for device types.
  55. Returns:
  56. True if app hack applied, false otherwise.
  57. History:
  58. 08/10/2001 mikrause Created
  59. --*/
  60. BOOL
  61. AddDSHackDisableDevice(
  62. IN DWORD dwDevicesAffected)
  63. {
  64. return AddDirectSoundAppHack(DSAPPHACKID_DISABLEDEVICE, dwDevicesAffected,
  65. 0);
  66. }
  67. /*++
  68. Function Description:
  69. Makes IDirectSoundBuffer::GetCurrentPosition() tell the app
  70. that the play and write cursors are X milliseconds further
  71. along than they really are.
  72. Arguments:
  73. IN lCursorPad - Number of milliseconds to pad cursors.
  74. Returns:
  75. True if app hack applied, false otherwise.
  76. History:
  77. 08/10/2001 mikrause Created
  78. --*/
  79. BOOL
  80. AddDSHackPadCursors(
  81. IN LONG lCursorPad)
  82. {
  83. return AddDirectSoundAppHack(DSAPPHACKID_PADCURSORS, (DWORD)lCursorPad,
  84. 0);
  85. }
  86. /*++
  87. Function Description:
  88. When the app asks for the play cursor, we give it the
  89. write cursor instead. The correct way to stream audio
  90. into a looping dsound buffer is to key off the write cursor,
  91. but some apps (e.g. QuickTime) use the play cursor instead.
  92. This apphacks alleviates them.
  93. Arguments:
  94. IN dwDevicesAffected - Combination of devices to apply hack to.
  95. Notes:
  96. See vregistry_dsound.h for device types.
  97. Returns:
  98. True if app hack applied, false otherwise.
  99. History:
  100. 08/10/2001 mikrause Created
  101. --*/
  102. BOOL
  103. AddDSHackReturnWritePos(
  104. IN DWORD dwDevicesAffected)
  105. {
  106. return AddDirectSoundAppHack(DSAPPHACKID_RETURNWRITEPOS, dwDevicesAffected,
  107. 0);
  108. }
  109. /*++
  110. Function Description:
  111. Makes dsound always return a write position which is X
  112. milliseconds ahead of the play position, rather than
  113. the real write position.
  114. Arguments:
  115. IN lCursorPad - Milliseconds of padding.
  116. Returns:
  117. True if app hack applied, false otherwise.
  118. History:
  119. 08/10/2001 mikrause Created
  120. --*/
  121. BOOL
  122. AddDSHackSmoothWritePos(
  123. IN LONG lCursorPad)
  124. {
  125. return AddDirectSoundAppHack(DSAPPHACKID_SMOOTHWRITEPOS, 1,
  126. (DWORD)lCursorPad);
  127. }
  128. /*++
  129. Function Description:
  130. Caches the play/write positions last returned by
  131. GetCurrentPosition(), and reuses them if the app
  132. calls it again within 5ms (great for apps that
  133. abuse GetCurrentPosition(), which is more expensive
  134. on WDM devices than it was on the Win9X VxD devices
  135. many of these games were tested with). This hack
  136. should spring to mind if you see slow or jerky graphics
  137. or stop-and-go sound the GetCurrentPosition() calls are
  138. probably pegging the CPU (to confirm, use debug spew
  139. level 6 on DSound.dll).
  140. Arguments:
  141. IN dwDevicesAffected - Combination of devices to apply this hack to.
  142. Notes:
  143. See vregistry_dsound.h for device types.
  144. Returns:
  145. True if app hack applied, false otherwise.
  146. History:
  147. 08/10/2001 mikrause Created
  148. --*/
  149. BOOL
  150. AddDSHackCachePositions(
  151. IN DWORD dwDevicesAffected)
  152. {
  153. return AddDirectSoundAppHack(DSAPPHACKID_CACHEPOSITIONS, dwDevicesAffected,
  154. 0);
  155. }
  156. ///////////////////////////////////////////////////////////////////////////////
  157. /*++
  158. Function Description:
  159. Adds a DirectSound app hack to the registry.
  160. Arguments:
  161. IN dwHack - ID of app hack to apply.
  162. IN dwParam1 - First parameter. Depends on app hack.
  163. IN dwParam2 - Second paramter. Depends on app hack.
  164. Notes:
  165. See vregistry_dsound.h for more information on specific hacks.
  166. Returns:
  167. True if app hack applied, false otherwise.
  168. History:
  169. 08/10/2001 mikrause Created
  170. --*/
  171. BOOL
  172. AddDirectSoundAppHack(
  173. IN DWORD dwHack,
  174. IN DWORD dwParam1,
  175. IN DWORD dwParam2)
  176. {
  177. WCHAR wzAppID[MAX_PATH];
  178. LPWSTR wzValName;
  179. DWORD dwData[2];
  180. DWORD dwDataSize;
  181. VIRTUALKEY *dsoundKey;
  182. VIRTUALKEY *appKey;
  183. VIRTUALVAL *val;
  184. if (GetDirectSoundAppId(wzAppID) == FALSE)
  185. {
  186. DPFN(eDbgLevelError, "Unable to create DirectSound app ID");
  187. return FALSE;
  188. }
  189. dwData[0] = dwParam1;
  190. dwData[1] = dwParam2;
  191. switch(dwHack)
  192. {
  193. case DSAPPHACKID_DEVACCEL:
  194. wzValName = L"DSAPPHACKID_DEVACCEL";
  195. dwDataSize = 2 * sizeof(DWORD);
  196. break;
  197. case DSAPPHACKID_PADCURSORS:
  198. wzValName = L"DSAPPHACKID_PADCURSORS";
  199. dwDataSize = 1 * sizeof(DWORD);
  200. break;
  201. case DSAPPHACKID_CACHEPOSITIONS:
  202. wzValName = L"DSAPPHACKID_CACHEPOSITIONS";
  203. dwDataSize = 1 * sizeof(DWORD);
  204. break;
  205. case DSAPPHACKID_RETURNWRITEPOS:
  206. wzValName = L"DSAPPHACKID_RETURNWRITEPOS";
  207. dwDataSize = 1 * sizeof(DWORD);
  208. break;
  209. case DSAPPHACKID_SMOOTHWRITEPOS:
  210. wzValName = L"DSAPPHACKID_SMOOTHWRITEPOS";
  211. dwDataSize = 2 * sizeof(DWORD);
  212. break;
  213. case DSAPPHACKID_DISABLEDEVICE:
  214. wzValName = L"DSAPPHACKID_DISABLEDEVICE";
  215. dwDataSize = 1 * sizeof(DWORD);
  216. break;
  217. default:
  218. DPFN(eDbgLevelError, "Unknown DirectSound AppHack");
  219. return FALSE;
  220. }
  221. dsoundKey = VRegistry.AddKey(L"HKLM\\System\\CurrentControlSet\\Control\\MediaResources\\DirectSound\\Application Compatibility");
  222. if (dsoundKey == NULL)
  223. {
  224. DPFN(eDbgLevelError, "Cannot create virtual registry key");
  225. return FALSE;
  226. }
  227. appKey = dsoundKey->AddKey(wzAppID);
  228. if (appKey == NULL)
  229. {
  230. DPFN(eDbgLevelError, "Cannot create virtual registry key");
  231. return FALSE;
  232. }
  233. val = appKey->AddValue(wzValName,REG_BINARY,(BYTE*)dwData, dwDataSize);
  234. if (val == NULL)
  235. {
  236. DPFN(eDbgLevelError, "Cannot create virtual registry value");
  237. return FALSE;
  238. }
  239. DPFN(eDbgLevelWarning, "DirectSound Apphack \"%S\" enabled, arguments: %X %X", wzValName, dwData[0], dwData[1]);
  240. return TRUE;
  241. }
  242. // Arguments:
  243. // LPTSTR szExecPath: full pathname of the app (e.g. C:\program files\foo\foo.exe)
  244. // LPTSTR szExecName: executable name of the app (e.g. foo.exe)
  245. // LPTSTR pszAppId: returns the dsound app ID. (Pass in an array of DSAPPHACK_MAXNAME TCHARs.)
  246. // Return code:
  247. // BOOL: true if we obtained the application ID successfully.
  248. ///////////////////////////////////////////////////////////////////////////////
  249. /*++
  250. Function Description:
  251. Gets an AppID for the running application.
  252. Arguments:
  253. IN OUT wzAppId: Buffer for the dsound app ID. (Pass in an array of DSAPPHACK_MAXNAME TCHARs.)
  254. Returns:
  255. TRUE if app ID created, FALSE otherwise.
  256. History:
  257. 08/10/2001 mikrause Created
  258. --*/
  259. BOOL
  260. GetDirectSoundAppId(
  261. IN OUT LPWSTR wzAppId)
  262. {
  263. WCHAR wzExecPath[MAX_PATH];
  264. LPWSTR wzExecName;
  265. IMAGE_NT_HEADERS nth;
  266. IMAGE_DOS_HEADER dh;
  267. DWORD cbRead;
  268. DWORD dwFileSize;
  269. HANDLE hFile = INVALID_HANDLE_VALUE;
  270. BOOL fSuccess = FALSE;
  271. __try
  272. {
  273. // Get the name of the running EXE, and its full path.
  274. if (GetModuleFileNameW(NULL, wzExecPath, MAX_PATH) == FALSE)
  275. {
  276. __leave;
  277. }
  278. wzExecName = wcsrchr(wzExecPath, L'\\');
  279. if (wzExecName == NULL)
  280. {
  281. __leave;;
  282. }
  283. wzExecName++;
  284. // Open the executable
  285. hFile = CreateFile(wzExecPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
  286. if (hFile == INVALID_HANDLE_VALUE)
  287. {
  288. __leave;
  289. }
  290. // Read the executable's DOS header
  291. fSuccess = ReadFile(hFile, &dh, sizeof(dh), &cbRead, NULL);
  292. if (!fSuccess || cbRead != sizeof(dh))
  293. {
  294. // Log("Unable to read DOS header");
  295. __leave;
  296. }
  297. if (dh.e_magic != IMAGE_DOS_SIGNATURE)
  298. {
  299. // Log("Invalid DOS signature");
  300. __leave;
  301. }
  302. // Read the executable's PE header
  303. cbRead = SetFilePointer(hFile, dh.e_lfanew, NULL, FILE_BEGIN);
  304. if ((LONG)cbRead != dh.e_lfanew)
  305. {
  306. // Log("Unable to seek to PE header");
  307. __leave;
  308. }
  309. if ((ReadFile(hFile, &nth, sizeof(nth), &cbRead, NULL) == FALSE)
  310. || cbRead != sizeof(nth))
  311. {
  312. // Log("Unable to read PE header");
  313. __leave;
  314. }
  315. if (nth.Signature != IMAGE_NT_SIGNATURE)
  316. {
  317. // Log("Invalid PE signature");
  318. __leave;
  319. }
  320. // Get the executable's size
  321. // Assuming < 4 GB
  322. dwFileSize = GetFileSize(hFile, NULL);
  323. if (dwFileSize == INVALID_FILE_SIZE )
  324. {
  325. // Log("Unable to get file size");
  326. __leave;
  327. }
  328. // Create the application ID
  329. if (FAILED(StringCchPrintfW(
  330. wzAppId,
  331. MAX_PATH,
  332. L"%s%8.8lX%8.8lX",
  333. wzExecName,
  334. nth.FileHeader.TimeDateStamp,
  335. dwFileSize)))
  336. {
  337. __leave;
  338. }
  339. CharUpperW(wzAppId);
  340. fSuccess = TRUE;
  341. }
  342. __finally
  343. {
  344. if (hFile != INVALID_HANDLE_VALUE)
  345. {
  346. CloseHandle(hFile);
  347. }
  348. }
  349. return fSuccess;
  350. }
  351. IMPLEMENT_SHIM_END