491 lines
11 KiB
C++
491 lines
11 KiB
C++
/*++
|
||
|
||
Copyright (c) 2001 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
VRegistry_DSound.cpp
|
||
|
||
Abstract:
|
||
|
||
Module to add DSound apphacks with VRegistry
|
||
|
||
History:
|
||
|
||
08/10/2001 mikrause Created
|
||
|
||
--*/
|
||
|
||
#include "precomp.h"
|
||
|
||
IMPLEMENT_SHIM_BEGIN(VirtualRegistry)
|
||
|
||
#include <windows.h>
|
||
#include "shimhookmacro.h"
|
||
#include "vregistry.h"
|
||
#include "vregistry_dsound.h"
|
||
|
||
#define DSAPPHACK_MAXNAME (MAX_PATH + 16 + 16)
|
||
|
||
BOOL AddDirectSoundAppHack(DWORD dwHack,DWORD dwParam1,DWORD dwParam2);
|
||
BOOL GetDirectSoundAppId(LPTSTR pszAppId);
|
||
|
||
// Available DirectSound hacks
|
||
#define DSAPPHACKID_DEVACCEL 1
|
||
#define DSAPPHACKID_PADCURSORS 2
|
||
#define DSAPPHACKID_CACHEPOSITIONS 3
|
||
#define DSAPPHACKID_RETURNWRITEPOS 4
|
||
#define DSAPPHACKID_SMOOTHWRITEPOS 5
|
||
#define DSAPPHACKID_DISABLEDEVICE 6
|
||
|
||
/*++
|
||
|
||
Function Description:
|
||
|
||
Sets the acceleration level the app will be allowed to use.
|
||
|
||
Arguments:
|
||
|
||
IN dwAcceleration - Acceleration level needed.
|
||
IN dwDevicesAffected - Combination of device that this hack applies to.
|
||
|
||
Notes:
|
||
|
||
See vregistry_dsound.h for acceleration levels and device types.
|
||
|
||
Returns:
|
||
|
||
True if app hack applied, false otherwise.
|
||
|
||
History:
|
||
|
||
08/10/2001 mikrause Created
|
||
|
||
--*/
|
||
|
||
BOOL
|
||
AddDSHackDeviceAcceleration(
|
||
IN DWORD dwAcceleration,
|
||
IN DWORD dwDevicesAffected)
|
||
{
|
||
return AddDirectSoundAppHack(DSAPPHACKID_DEVACCEL, dwAcceleration,
|
||
dwDevicesAffected);
|
||
}
|
||
|
||
/*++
|
||
|
||
Function Description:
|
||
|
||
Disabled some category of devices altogether, forces
|
||
playback through emulated path.
|
||
|
||
Arguments:
|
||
|
||
IN dwDevicesAffected - Combination of device that this hack applies to.
|
||
|
||
Notes:
|
||
|
||
See vregistry_dsound.h for device types.
|
||
|
||
Returns:
|
||
|
||
True if app hack applied, false otherwise.
|
||
|
||
History:
|
||
|
||
08/10/2001 mikrause Created
|
||
|
||
--*/
|
||
|
||
BOOL
|
||
AddDSHackDisableDevice(
|
||
IN DWORD dwDevicesAffected)
|
||
{
|
||
return AddDirectSoundAppHack(DSAPPHACKID_DISABLEDEVICE, dwDevicesAffected,
|
||
0);
|
||
}
|
||
|
||
/*++
|
||
|
||
Function Description:
|
||
|
||
Makes IDirectSoundBuffer::GetCurrentPosition() tell the app
|
||
that the play and write cursors are X milliseconds further
|
||
along than they really are.
|
||
|
||
Arguments:
|
||
|
||
IN lCursorPad - Number of milliseconds to pad cursors.
|
||
|
||
Returns:
|
||
|
||
True if app hack applied, false otherwise.
|
||
|
||
History:
|
||
|
||
08/10/2001 mikrause Created
|
||
|
||
--*/
|
||
|
||
BOOL
|
||
AddDSHackPadCursors(
|
||
IN LONG lCursorPad)
|
||
{
|
||
return AddDirectSoundAppHack(DSAPPHACKID_PADCURSORS, (DWORD)lCursorPad,
|
||
0);
|
||
}
|
||
|
||
/*++
|
||
|
||
Function Description:
|
||
|
||
When the app asks for the play cursor, we give it the
|
||
write cursor instead. The correct way to stream audio
|
||
into a looping dsound buffer is to key off the write cursor,
|
||
but some apps (e.g. QuickTime) use the play cursor instead.
|
||
This apphacks alleviates them.
|
||
|
||
Arguments:
|
||
|
||
IN dwDevicesAffected - Combination of devices to apply hack to.
|
||
|
||
Notes:
|
||
|
||
See vregistry_dsound.h for device types.
|
||
|
||
Returns:
|
||
|
||
True if app hack applied, false otherwise.
|
||
|
||
History:
|
||
|
||
08/10/2001 mikrause Created
|
||
|
||
--*/
|
||
|
||
BOOL
|
||
AddDSHackReturnWritePos(
|
||
IN DWORD dwDevicesAffected)
|
||
{
|
||
return AddDirectSoundAppHack(DSAPPHACKID_RETURNWRITEPOS, dwDevicesAffected,
|
||
0);
|
||
}
|
||
|
||
/*++
|
||
|
||
Function Description:
|
||
|
||
Makes dsound always return a write position which is X
|
||
milliseconds ahead of the play position, rather than
|
||
the <20>real<61> write position.
|
||
|
||
Arguments:
|
||
|
||
IN lCursorPad - Milliseconds of padding.
|
||
|
||
Returns:
|
||
|
||
True if app hack applied, false otherwise.
|
||
|
||
History:
|
||
|
||
08/10/2001 mikrause Created
|
||
|
||
--*/
|
||
|
||
BOOL
|
||
AddDSHackSmoothWritePos(
|
||
IN LONG lCursorPad)
|
||
{
|
||
return AddDirectSoundAppHack(DSAPPHACKID_SMOOTHWRITEPOS, 1,
|
||
(DWORD)lCursorPad);
|
||
}
|
||
|
||
/*++
|
||
|
||
Function Description:
|
||
|
||
Caches the play/write positions last returned by
|
||
GetCurrentPosition(), and reuses them if the app
|
||
calls it again within 5ms (great for apps that
|
||
abuse GetCurrentPosition(), which is more expensive
|
||
on WDM devices than it was on the Win9X VxD devices
|
||
many of these games were tested with). This hack
|
||
should spring to mind if you see slow or jerky graphics
|
||
or stop-and-go sound <20> the GetCurrentPosition() calls are
|
||
probably pegging the CPU (to confirm, use debug spew
|
||
level 6 on DSound.dll).
|
||
|
||
Arguments:
|
||
|
||
IN dwDevicesAffected - Combination of devices to apply this hack to.
|
||
|
||
|
||
Notes:
|
||
|
||
See vregistry_dsound.h for device types.
|
||
|
||
Returns:
|
||
|
||
True if app hack applied, false otherwise.
|
||
|
||
History:
|
||
|
||
08/10/2001 mikrause Created
|
||
|
||
--*/
|
||
|
||
BOOL
|
||
AddDSHackCachePositions(
|
||
IN DWORD dwDevicesAffected)
|
||
{
|
||
return AddDirectSoundAppHack(DSAPPHACKID_CACHEPOSITIONS, dwDevicesAffected,
|
||
0);
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
/*++
|
||
|
||
Function Description:
|
||
|
||
Adds a DirectSound app hack to the registry.
|
||
|
||
Arguments:
|
||
|
||
IN dwHack - ID of app hack to apply.
|
||
IN dwParam1 - First parameter. Depends on app hack.
|
||
IN dwParam2 - Second paramter. Depends on app hack.
|
||
|
||
Notes:
|
||
|
||
See vregistry_dsound.h for more information on specific hacks.
|
||
|
||
Returns:
|
||
|
||
True if app hack applied, false otherwise.
|
||
|
||
History:
|
||
|
||
08/10/2001 mikrause Created
|
||
|
||
--*/
|
||
|
||
BOOL
|
||
AddDirectSoundAppHack(
|
||
IN DWORD dwHack,
|
||
IN DWORD dwParam1,
|
||
IN DWORD dwParam2)
|
||
{
|
||
WCHAR wzAppID[MAX_PATH];
|
||
LPWSTR wzValName;
|
||
DWORD dwData[2];
|
||
DWORD dwDataSize;
|
||
VIRTUALKEY *dsoundKey;
|
||
VIRTUALKEY *appKey;
|
||
VIRTUALVAL *val;
|
||
|
||
if (GetDirectSoundAppId(wzAppID) == FALSE)
|
||
{
|
||
DPFN(eDbgLevelError, "Unable to create DirectSound app ID");
|
||
return FALSE;
|
||
}
|
||
|
||
dwData[0] = dwParam1;
|
||
dwData[1] = dwParam2;
|
||
|
||
switch(dwHack)
|
||
{
|
||
case DSAPPHACKID_DEVACCEL:
|
||
wzValName = L"DSAPPHACKID_DEVACCEL";
|
||
dwDataSize = 2 * sizeof(DWORD);
|
||
break;
|
||
|
||
case DSAPPHACKID_PADCURSORS:
|
||
wzValName = L"DSAPPHACKID_PADCURSORS";
|
||
dwDataSize = 1 * sizeof(DWORD);
|
||
break;
|
||
|
||
case DSAPPHACKID_CACHEPOSITIONS:
|
||
wzValName = L"DSAPPHACKID_CACHEPOSITIONS";
|
||
dwDataSize = 1 * sizeof(DWORD);
|
||
break;
|
||
|
||
case DSAPPHACKID_RETURNWRITEPOS:
|
||
wzValName = L"DSAPPHACKID_RETURNWRITEPOS";
|
||
dwDataSize = 1 * sizeof(DWORD);
|
||
break;
|
||
|
||
case DSAPPHACKID_SMOOTHWRITEPOS:
|
||
wzValName = L"DSAPPHACKID_SMOOTHWRITEPOS";
|
||
dwDataSize = 2 * sizeof(DWORD);
|
||
break;
|
||
|
||
case DSAPPHACKID_DISABLEDEVICE:
|
||
wzValName = L"DSAPPHACKID_DISABLEDEVICE";
|
||
dwDataSize = 1 * sizeof(DWORD);
|
||
break;
|
||
|
||
default:
|
||
DPFN(eDbgLevelError, "Unknown DirectSound AppHack");
|
||
return FALSE;
|
||
}
|
||
|
||
dsoundKey = VRegistry.AddKey(L"HKLM\\System\\CurrentControlSet\\Control\\MediaResources\\DirectSound\\Application Compatibility");
|
||
if (dsoundKey == NULL)
|
||
{
|
||
DPFN(eDbgLevelError, "Cannot create virtual registry key");
|
||
return FALSE;
|
||
}
|
||
|
||
appKey = dsoundKey->AddKey(wzAppID);
|
||
if (appKey == NULL)
|
||
{
|
||
DPFN(eDbgLevelError, "Cannot create virtual registry key");
|
||
return FALSE;
|
||
}
|
||
|
||
val = appKey->AddValue(wzValName,REG_BINARY,(BYTE*)dwData, dwDataSize);
|
||
if (val == NULL)
|
||
{
|
||
DPFN(eDbgLevelError, "Cannot create virtual registry value");
|
||
return FALSE;
|
||
}
|
||
|
||
DPFN(eDbgLevelWarning, "DirectSound Apphack \"%S\" enabled, arguments: %X %X", wzValName, dwData[0], dwData[1]);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
// Arguments:
|
||
// LPTSTR szExecPath: full pathname of the app (e.g. C:\program files\foo\foo.exe)
|
||
// LPTSTR szExecName: executable name of the app (e.g. foo.exe)
|
||
// LPTSTR pszAppId: returns the dsound app ID. (Pass in an array of DSAPPHACK_MAXNAME TCHARs.)
|
||
// Return code:
|
||
// BOOL: true if we obtained the application ID successfully.
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
/*++
|
||
|
||
Function Description:
|
||
|
||
Gets an AppID for the running application.
|
||
|
||
Arguments:
|
||
IN OUT wzAppId: Buffer for the dsound app ID. (Pass in an array of DSAPPHACK_MAXNAME TCHARs.)
|
||
|
||
Returns:
|
||
|
||
TRUE if app ID created, FALSE otherwise.
|
||
|
||
History:
|
||
|
||
08/10/2001 mikrause Created
|
||
|
||
--*/
|
||
BOOL
|
||
GetDirectSoundAppId(
|
||
IN OUT LPWSTR wzAppId)
|
||
{
|
||
WCHAR wzExecPath[MAX_PATH];
|
||
LPWSTR wzExecName;
|
||
IMAGE_NT_HEADERS nth;
|
||
IMAGE_DOS_HEADER dh;
|
||
DWORD cbRead;
|
||
DWORD dwFileSize;
|
||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||
BOOL fSuccess = FALSE;
|
||
|
||
__try
|
||
{
|
||
// Get the name of the running EXE, and its full path.
|
||
if (GetModuleFileNameW(NULL, wzExecPath, MAX_PATH) == FALSE)
|
||
{
|
||
__leave;
|
||
}
|
||
|
||
wzExecName = wcsrchr(wzExecPath, L'\\');
|
||
if (wzExecName == NULL)
|
||
{
|
||
__leave;;
|
||
}
|
||
|
||
wzExecName++;
|
||
|
||
// Open the executable
|
||
hFile = CreateFile(wzExecPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||
if (hFile == INVALID_HANDLE_VALUE)
|
||
{
|
||
__leave;
|
||
}
|
||
|
||
// Read the executable's DOS header
|
||
fSuccess = ReadFile(hFile, &dh, sizeof(dh), &cbRead, NULL);
|
||
if (!fSuccess || cbRead != sizeof(dh))
|
||
{
|
||
// Log("Unable to read DOS header");
|
||
__leave;
|
||
}
|
||
|
||
if (dh.e_magic != IMAGE_DOS_SIGNATURE)
|
||
{
|
||
// Log("Invalid DOS signature");
|
||
__leave;
|
||
}
|
||
|
||
// Read the executable's PE header
|
||
cbRead = SetFilePointer(hFile, dh.e_lfanew, NULL, FILE_BEGIN);
|
||
if ((LONG)cbRead != dh.e_lfanew)
|
||
{
|
||
// Log("Unable to seek to PE header");
|
||
__leave;
|
||
}
|
||
|
||
if ((ReadFile(hFile, &nth, sizeof(nth), &cbRead, NULL) == FALSE)
|
||
|| cbRead != sizeof(nth))
|
||
{
|
||
// Log("Unable to read PE header");
|
||
__leave;
|
||
}
|
||
|
||
if (nth.Signature != IMAGE_NT_SIGNATURE)
|
||
{
|
||
// Log("Invalid PE signature");
|
||
__leave;
|
||
}
|
||
|
||
// Get the executable's size
|
||
// Assuming < 4 GB
|
||
dwFileSize = GetFileSize(hFile, NULL);
|
||
if (dwFileSize == INVALID_FILE_SIZE )
|
||
{
|
||
// Log("Unable to get file size");
|
||
__leave;
|
||
}
|
||
|
||
// Create the application ID
|
||
if (FAILED(StringCchPrintfW(
|
||
wzAppId,
|
||
MAX_PATH,
|
||
L"%s%8.8lX%8.8lX",
|
||
wzExecName,
|
||
nth.FileHeader.TimeDateStamp,
|
||
dwFileSize)))
|
||
{
|
||
__leave;
|
||
}
|
||
CharUpperW(wzAppId);
|
||
|
||
fSuccess = TRUE;
|
||
}
|
||
__finally
|
||
{
|
||
if (hFile != INVALID_HANDLE_VALUE)
|
||
{
|
||
CloseHandle(hFile);
|
||
}
|
||
}
|
||
|
||
return fSuccess;
|
||
}
|
||
|
||
IMPLEMENT_SHIM_END |