windows-nt/Source/XPSP1/NT/multimedia/media/winmm/regapi.c
2020-09-26 16:20:57 +08:00

936 lines
25 KiB
C

/****************************************************************************\
*
* Module Name : regapi.c
*
* Multimedia support library
*
* This module contains the code for accessing the registry
*
* Copyright (c) 1993-1998 Microsoft Corporation
*
\****************************************************************************/
#define UNICODE
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <regapi.h>
#include "winmmi.h"
HANDLE Drivers32Handle;
static WCHAR gszMsacmDriver[] = L"msacm.";
/*
** Free everything cached
*/
VOID mmRegFree(VOID)
{
if (Drivers32Handle != NULL) {
NtClose(Drivers32Handle);
Drivers32Handle = NULL;
}
}
/*
** Open a subkey
*/
HANDLE mmRegOpenSubkey(HANDLE BaseKeyHandle, LPCWSTR lpszSubkeyName)
{
UNICODE_STRING unicodeSectionName;
HANDLE KeyHandle;
OBJECT_ATTRIBUTES oa;
RtlInitUnicodeString(&unicodeSectionName, lpszSubkeyName);
InitializeObjectAttributes(&oa,
&unicodeSectionName,
OBJ_CASE_INSENSITIVE,
BaseKeyHandle,
(PSECURITY_DESCRIPTOR)NULL);
/*
** Open the sub section
*/
if (!NT_SUCCESS(NtOpenKey(&KeyHandle, GENERIC_READ, &oa))) {
return NULL;
} else {
return KeyHandle;
}
}
/*
** Open a subkey
*/
HANDLE mmRegOpenSubkeyForWrite(HANDLE BaseKeyHandle, LPCWSTR lpszSubkeyName)
{
UNICODE_STRING unicodeSectionName;
HANDLE KeyHandle;
OBJECT_ATTRIBUTES oa;
RtlInitUnicodeString(&unicodeSectionName, lpszSubkeyName);
InitializeObjectAttributes(&oa,
&unicodeSectionName,
OBJ_CASE_INSENSITIVE,
BaseKeyHandle,
(PSECURITY_DESCRIPTOR)NULL);
/*
** Open the sub section
*/
if (!NT_SUCCESS(NtOpenKey(&KeyHandle, MAXIMUM_ALLOWED, &oa))) {
return NULL;
} else {
return KeyHandle;
}
}
/*
** Read (small) registry data entries
*/
BOOL mmRegQueryValue(HANDLE BaseKeyHandle,
LPCWSTR lpszSubkeyName,
LPCWSTR lpszValueName,
ULONG dwLen,
LPWSTR lpszValue)
{
BOOL ReturnCode;
HANDLE KeyHandle;
UNICODE_STRING unicodeSectionName;
UNICODE_STRING unicodeValueName;
ULONG ResultLength;
struct {
KEY_VALUE_PARTIAL_INFORMATION KeyInfo;
UCHAR Data[MAX_PATH * sizeof(WCHAR)];
} OurKeyValueInformation;
if (lpszSubkeyName) {
KeyHandle = mmRegOpenSubkey(BaseKeyHandle, lpszSubkeyName);
} else {
KeyHandle = NULL;
}
/*
** Read the data
*/
if (lpszValueName == NULL) {
RtlInitUnicodeString(&unicodeValueName, TEXT(""));
} else {
RtlInitUnicodeString(&unicodeValueName, lpszValueName);
}
ReturnCode = NT_SUCCESS(NtQueryValueKey(KeyHandle == NULL ?
BaseKeyHandle : KeyHandle,
&unicodeValueName,
KeyValuePartialInformation,
(PVOID)&OurKeyValueInformation,
sizeof(OurKeyValueInformation),
&ResultLength));
if (ReturnCode) {
/*
** Check we got the right type of data and not too much
*/
if (OurKeyValueInformation.KeyInfo.DataLength > dwLen * sizeof(WCHAR) ||
(OurKeyValueInformation.KeyInfo.Type != REG_SZ &&
OurKeyValueInformation.KeyInfo.Type != REG_EXPAND_SZ)) {
ReturnCode = FALSE;
} else {
/*
** Copy back the data
*/
if (OurKeyValueInformation.KeyInfo.Type == REG_EXPAND_SZ) {
lpszValue[0] = TEXT('\0');
ExpandEnvironmentStringsW
((LPCWSTR)OurKeyValueInformation.KeyInfo.Data,
(LPWSTR)lpszValue,
dwLen);
} else {
CopyMemory((PVOID)lpszValue,
(PVOID)OurKeyValueInformation.KeyInfo.Data,
dwLen * sizeof(WCHAR));
lpszValue[ min(OurKeyValueInformation.KeyInfo.DataLength,
dwLen-1) ] = TEXT('\0');
}
}
}
if (KeyHandle) {
NtClose(KeyHandle);
}
return ReturnCode;
}
/*
** Read a mapped 'user' value in a known section
*/
BOOL mmRegQueryUserValue(LPCWSTR lpszSectionName,
LPCWSTR lpszValueName,
ULONG dwLen,
LPWSTR lpszValue)
{
HANDLE UserHandle;
BOOL ReturnCode;
/*
** Open the user's key. It's important to do this EACH time because
** on the server it's different for different threads.
*/
if (!NT_SUCCESS(RtlOpenCurrentUser(GENERIC_READ, &UserHandle))) {
return FALSE;
}
ReturnCode = mmRegQueryValue(UserHandle,
lpszSectionName,
lpszValueName,
dwLen,
lpszValue);
NtClose(UserHandle);
return ReturnCode;
}
/*
** Set a mapped 'user' value in a known section
*/
BOOL mmRegSetUserValue(LPCWSTR lpszSectionName,
LPCWSTR lpszValueName,
LPCWSTR lpszValue)
{
HANDLE UserHandle;
BOOL ReturnCode = FALSE;
/*
** Open the user's key. It's important to do this EACH time because
** on the server it's different for different threads.
*/
if (NT_SUCCESS(RtlOpenCurrentUser(MAXIMUM_ALLOWED, &UserHandle)))
{
HANDLE KeyHandle;
KeyHandle = mmRegOpenSubkeyForWrite (UserHandle, lpszSectionName);
if (KeyHandle != NULL)
{
UNICODE_STRING ValueName;
if (lpszValueName == NULL) {
RtlInitUnicodeString (&ValueName, TEXT(""));
} else {
RtlInitUnicodeString (&ValueName, lpszValueName);
}
ReturnCode = NT_SUCCESS( NtSetValueKey (KeyHandle,
&ValueName,
0,
REG_SZ,
(PVOID)lpszValue,
(lstrlenW(lpszValue)+1)* sizeof(lpszValue[0])
) );
NtClose(KeyHandle);
}
NtClose(UserHandle);
}
return ReturnCode;
}
BOOL mmRegCreateUserKey (LPCWSTR lpszPath, LPCWSTR lpszNewKey)
{
HANDLE UserHandle;
BOOL ReturnValue = FALSE;
/*
** Open the user's key. It's important to do this EACH time because
** on the server it's different for different threads.
*/
if (NT_SUCCESS(RtlOpenCurrentUser(MAXIMUM_ALLOWED, &UserHandle)))
{
HANDLE PathHandle;
HANDLE KeyHandle;
UNICODE_STRING unicodeSectionName;
OBJECT_ATTRIBUTES oa;
if (lpszPath == NULL)
{
PathHandle = NULL;
}
else
{
PathHandle = mmRegOpenSubkeyForWrite (UserHandle, lpszPath);
if (PathHandle == NULL)
{
NtClose(UserHandle);
return FALSE;
}
}
RtlInitUnicodeString(&unicodeSectionName, lpszNewKey);
InitializeObjectAttributes(&oa,
&unicodeSectionName,
OBJ_CASE_INSENSITIVE,
(PathHandle == NULL)
? UserHandle : PathHandle,
(PSECURITY_DESCRIPTOR)NULL);
/*
** Create the sub section
*/
if (NT_SUCCESS( NtCreateKey(&KeyHandle,
KEY_READ | KEY_WRITE,
&oa,
0,
NULL,
0,
NULL
) ))
{
if (KeyHandle)
{
ReturnValue = TRUE;
NtClose (KeyHandle);
}
}
if (PathHandle != NULL)
{
NtClose(PathHandle);
}
NtClose(UserHandle);
}
return ReturnValue;
}
/*
** Test whether a mapped 'user' key exists
*/
BOOL mmRegQueryUserKey (LPCWSTR lpszKeyName)
{
HANDLE UserHandle;
BOOL ReturnValue = FALSE;
if (lpszKeyName == NULL)
{
return FALSE;
}
if (NT_SUCCESS(RtlOpenCurrentUser(MAXIMUM_ALLOWED, &UserHandle)))
{
HANDLE KeyHandle;
KeyHandle = mmRegOpenSubkeyForWrite (UserHandle, lpszKeyName);
if (KeyHandle != NULL)
{
ReturnValue = TRUE;
NtClose(KeyHandle);
}
NtClose(UserHandle);
}
return ReturnValue;
}
/*
** Delete a mapped 'user' key. Careful--this function deletes recursively!
*/
#define nMaxLevelsToRecurseInDELETEKEY 3 // don't runaway or stack fault
BOOL mmRegDeleteUserKeyRecurse (HANDLE UserHandle, LPCWSTR lpszName, int level)
{
HANDLE KeyHandle;
if (lpszName == NULL)
{
return FALSE;
}
if (level > nMaxLevelsToRecurseInDELETEKEY)
{
return FALSE;
}
if ((KeyHandle = mmRegOpenSubkeyForWrite (UserHandle, lpszName)) != NULL)
{
struct {
KEY_BASIC_INFORMATION kbi;
WCHAR NameBuffer [MAX_PATH];
} kbi;
/*
** Before NtDeleteKey() will work on this key, we have to ensure
** there are no subkeys.
*/
while (TRUE)
{
ULONG cbReturned = 0L;
WCHAR szSubKeyName[ MAX_PATH ];
ZeroMemory (&kbi, sizeof(kbi));
if (!NT_SUCCESS(NtEnumerateKey(KeyHandle,
0,
KeyBasicInformation,
(PVOID)&kbi,
sizeof(kbi),
&cbReturned)))
{
break;
}
wsprintf (szSubKeyName, L"%ls\\%ls", lpszName, kbi.kbi.Name);
if (!mmRegDeleteUserKeyRecurse (UserHandle, szSubKeyName, 1+level))
{
NtClose (KeyHandle);
return FALSE;
}
}
/*
** Once there are no subkeys, we should be able to delete this key.
*/
if (NT_SUCCESS(NtDeleteKey(KeyHandle)))
{
NtClose(KeyHandle);
return TRUE;
}
NtClose(KeyHandle);
}
return FALSE;
}
BOOL mmRegDeleteUserKey (LPCWSTR lpszKeyName)
{
HANDLE UserHandle;
BOOL ReturnValue = FALSE;
if (lpszKeyName == NULL)
{
return FALSE;
}
if (NT_SUCCESS(RtlOpenCurrentUser(MAXIMUM_ALLOWED, &UserHandle)))
{
ReturnValue = mmRegDeleteUserKeyRecurse (UserHandle, lpszKeyName, 1);
NtClose(UserHandle);
}
return ReturnValue;
}
/*
** Read a mapped 'HKLM' value in a known section
*/
BOOL mmRegQueryMachineValue(LPCWSTR lpszSectionName,
LPCWSTR lpszValueName,
ULONG dwLen,
LPWSTR lpszValue)
{
WCHAR FullKeyName[MAX_PATH];
HANDLE HostHandle;
BOOL ReturnCode = FALSE;
lstrcpyW (FullKeyName, L"\\Registry\\Machine\\");
wcsncat (FullKeyName, lpszSectionName, (MAX_PATH - wcslen(FullKeyName) - 1));
if ((HostHandle = mmRegOpenSubkey (NULL, FullKeyName)) != NULL)
{
ReturnCode = mmRegQueryValue (HostHandle,
lpszSectionName,
lpszValueName,
dwLen,
lpszValue);
NtClose (HostHandle);
}
return ReturnCode;
}
/*
** Write a mapped 'HKLM' value in a known section
*/
BOOL mmRegSetMachineValue(LPCWSTR lpszSectionName,
LPCWSTR lpszValueName,
LPCWSTR lpszValue)
{
WCHAR FullKeyName[MAX_PATH];
HANDLE HostHandle;
BOOL ReturnCode = FALSE;
lstrcpyW (FullKeyName, L"\\Registry\\Machine\\");
wcsncat (FullKeyName, lpszSectionName, (MAX_PATH - wcslen(FullKeyName) - 1));
if ((HostHandle = mmRegOpenSubkeyForWrite (NULL, FullKeyName)) != NULL)
{
UNICODE_STRING ValueName;
if (lpszValueName == NULL) {
RtlInitUnicodeString (&ValueName, TEXT(""));
} else {
RtlInitUnicodeString (&ValueName, lpszValueName);
}
ReturnCode = NT_SUCCESS( NtSetValueKey (HostHandle,
&ValueName,
0,
REG_SZ,
(PVOID)lpszValue,
(lstrlenW(lpszValue)+1)* sizeof(lpszValue[0])
) );
NtClose(HostHandle);
}
return ReturnCode;
}
BOOL mmRegCreateMachineKey (LPCWSTR lpszPath, LPCWSTR lpszNewKey)
{
WCHAR FullKeyName[MAX_PATH];
HANDLE HostHandle;
BOOL ReturnValue = FALSE;
lstrcpyW (FullKeyName, L"\\Registry\\Machine\\");
wcsncat (FullKeyName, lpszPath, (MAX_PATH - wcslen(FullKeyName) - 1));
if ((HostHandle = mmRegOpenSubkeyForWrite (NULL, FullKeyName)) != NULL)
{
HANDLE KeyHandle;
UNICODE_STRING unicodeSectionName;
OBJECT_ATTRIBUTES oa;
RtlInitUnicodeString(&unicodeSectionName, lpszNewKey);
InitializeObjectAttributes(&oa,
&unicodeSectionName,
OBJ_CASE_INSENSITIVE,
HostHandle,
(PSECURITY_DESCRIPTOR)NULL);
/*
** Create the sub section
*/
if (NT_SUCCESS( NtCreateKey(&KeyHandle,
KEY_READ | KEY_WRITE,
&oa,
0,
NULL,
0,
NULL
) ))
{
if (KeyHandle)
{
ReturnValue = TRUE;
NtClose (KeyHandle);
}
}
NtClose(HostHandle);
}
return ReturnValue;
}
/*
** Read stuff from system.ini
*/
BOOL mmRegQuerySystemIni(LPCWSTR lpszSectionName,
LPCWSTR lpszValueName,
ULONG dwLen,
LPWSTR lpszValue)
{
WCHAR KeyPathBuffer[MAX_PATH];
WCHAR ExKeyPathBuffer[MAX_PATH];
/*
** Create the full path
*/
lstrcpy(KeyPathBuffer,
(LPCTSTR) L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\");
wcsncat(KeyPathBuffer, lpszSectionName, (MAX_PATH - wcslen(KeyPathBuffer) - 1));
if (lstrcmpiW(lpszSectionName, wszDrivers) == 0) {
//
// for remote session, look ..\terminal Server\RDP (or other protocols) for drivers32
// name
//
//
if (WinmmRunningInSession) {
lstrcat(KeyPathBuffer,L"\\");
lstrcat(KeyPathBuffer, REG_TSERVER);
lstrcat(KeyPathBuffer,L"\\");
lstrcat(KeyPathBuffer, SessionProtocolName);
}
if (Drivers32Handle == NULL) {
Drivers32Handle = mmRegOpenSubkey(NULL, KeyPathBuffer);
}
if (Drivers32Handle != NULL) {
BOOL rc;
rc = mmRegQueryValue(Drivers32Handle,
NULL,
lpszValueName,
dwLen,
lpszValue);
//
// If we can't find the codec in the TermSrv protocol path
// we will look under Driver32 next
//
if (rc == FALSE && WinmmRunningInSession &&
_wcsnicmp(lpszValueName, gszMsacmDriver, lstrlen(gszMsacmDriver)) == 0) {
HANDLE hKey;
/*
** Create the full path
*/
lstrcpy(KeyPathBuffer,
(LPCTSTR) L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\");
lstrcat(KeyPathBuffer, lpszSectionName);
hKey = mmRegOpenSubkey(NULL, KeyPathBuffer);
if (hKey != NULL) {
rc = mmRegQueryValue(hKey,
NULL,
lpszValueName,
dwLen,
lpszValue);
RegCloseKey(hKey);
return rc;
}
else {
return FALSE;
}
}
else {
return rc;
}
} else {
return FALSE;
}
}
if (WinmmRunningInSession) {
if (lstrcmpiW(lpszSectionName, MCI_SECTION) == 0) {
memset(ExKeyPathBuffer, 0 , sizeof(ExKeyPathBuffer));
lstrcpy(ExKeyPathBuffer, KeyPathBuffer);
lstrcat(ExKeyPathBuffer,L"\\");
lstrcat(ExKeyPathBuffer, REG_TSERVER);
lstrcat(ExKeyPathBuffer,L"\\");
lstrcat(ExKeyPathBuffer, SessionProtocolName);
/* look through terminal server section for drivers information first */
if (mmRegQueryValue(NULL, ExKeyPathBuffer, lpszValueName, dwLen, lpszValue))
return TRUE;
else {
/* pick the system default drivers information */
return mmRegQueryValue(NULL, KeyPathBuffer, lpszValueName, dwLen, lpszValue);
}
}
}
return mmRegQueryValue(NULL, KeyPathBuffer, lpszValueName, dwLen, lpszValue);
}
/*
** Translate name through sounds section
*/
BOOL mmRegQuerySound(LPCWSTR lpszSoundName,
ULONG dwLen,
LPWSTR lpszValue)
{
WCHAR KeyPathBuffer[MAX_PATH];
lstrcpy(KeyPathBuffer, (LPCWSTR)L"Control Panel\\");
lstrcat(KeyPathBuffer, szSoundSection);
return mmRegQueryUserValue(KeyPathBuffer,
lpszSoundName,
dwLen,
lpszValue);
}
BOOL IsAliasName(LPCWSTR lpSection, LPCWSTR lpKeyName)
{
if ((!wcsncmp(lpKeyName, L"wave", 4)) ||
(!wcsncmp(lpKeyName, L"midi", 4)) ||
(!wcsncmp(lpKeyName, L"aux", 3 )) ||
(!wcsncmp(lpKeyName, L"mixer",5)) ||
(!wcsncmp(lpKeyName, L"msacm",5)) ||
(!wcsncmp(lpKeyName, L"vidc",4)) ||
(!wcsncmp(lpKeyName, L"midimapper", 10)) ||
(!wcsncmp(lpKeyName, L"wavemapper", 10)) ||
(!wcsncmp(lpKeyName, L"auxmapper", 9 )) ||
(!wcsncmp(lpKeyName, L"mixermapper", 11)))
{
return TRUE;
}
else
{
if (lstrcmpiW( lpSection, (LPCWSTR)MCI_HANDLERS) == 0L)
{
UINT n = lstrlen(lpKeyName);
for (; n > 0; n--)
{
// Found a '.' which implies and extension, which implies a
// file.
if ('.' == lpKeyName[n-1])
{
return FALSE;
}
}
// Searched the string for '.'.
// None so it is an alias (that is -- not filename)
return TRUE;
}
if (lstrcmpiW( lpSection, (LPCWSTR)wszDrivers) == 0L)
{
WCHAR szFileName[MAX_PATH];
// It could be something REALLY off the wall, like "ReelDrv"
return (mmRegQuerySystemIni(lpSection, lpKeyName, MAX_PATH, szFileName));
}
return FALSE;
}
}
/*****************************Private*Routine******************************\
* MyGetPrivateProfileString
*
* Attempt to bypass stevewo's private profile stuff.
*
* History:
* dd-mm-93 - StephenE - Created
*
\**************************************************************************/
DWORD
winmmGetPrivateProfileString(
LPCWSTR lpSection,
LPCWSTR lpKeyName,
LPCWSTR lpDefault,
LPWSTR lpReturnedString,
DWORD nSize,
LPCWSTR lpFileName
)
{
WCHAR szFileName[MAX_PATH];
/*
** for now just look for to the [Drivers32] section of system.ini
*/
if ( (lstrcmpiW( lpFileName, wszSystemIni ) == 0L)
&& ( ( lstrcmpiW( lpSection, wszDrivers ) == 0L ) ||
( lstrcmpiW( lpSection, (LPCWSTR)MCI_HANDLERS) == 0L ) ) ) {
if (IsAliasName(lpSection, lpKeyName))
{
if (mmRegQuerySystemIni(lpSection, lpKeyName, nSize, lpReturnedString))
{
return lstrlen(lpReturnedString);
}
else
{
return 0;
}
}
else
{
UINT ii;
HANDLE hFile;
lstrcpyW(szFileName, lpKeyName);
for (ii = 0; 0 != szFileName[ii]; ii++)
{
if(' ' == szFileName[ii])
{
// Truncate parameters...
szFileName[ii] = 0;
break;
}
}
hFile = CreateFile(
szFileName,
0,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(INVALID_HANDLE_VALUE != hFile)
{
CloseHandle(hFile);
wcsncpy(lpReturnedString, lpKeyName, nSize);
return (lstrlenW(lpKeyName));
}
else
{
// Okay was it a full file path?
for(ii = 0; 0 != szFileName[ii]; ii++)
{
if ('\\' == szFileName[ii])
{
// Probably...
break;
}
}
if ('\\' != szFileName[ii])
{
WCHAR szStub[MAX_PATH];
LPWSTR pszFilePart;
lstrcpyW(szStub, lpKeyName);
for(ii = 0; 0 != szStub[ii]; ii++)
{
if(' ' == szStub[ii])
{
// Truncate parameters...
szStub[ii] = 0;
break;
}
}
if (!SearchPathW(NULL,
szStub,
NULL,
MAX_PATH,
szFileName,
&pszFilePart))
{
return (0);
}
hFile = CreateFile(
szFileName,
0,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(INVALID_HANDLE_VALUE != hFile)
{
CloseHandle(hFile);
wcsncpy(lpReturnedString, lpKeyName, nSize);
return (lstrlenW(lpKeyName));
}
}
}
if (lpDefault != NULL) {
wcsncpy(lpReturnedString, lpDefault, nSize);
}
return 0;
}
}
else {
return GetPrivateProfileStringW( lpSection, lpKeyName, lpDefault,
lpReturnedString, nSize, lpFileName );
}
}
DWORD
winmmGetProfileString(
LPCWSTR lpAppName,
LPCWSTR lpKeyName,
LPCWSTR lpDefault,
LPWSTR lpReturnedString,
DWORD nSize
)
{
/*
** See if it's one we know about
*/
if (lstrcmpiW(lpAppName, szSoundSection) == 0) {
if (mmRegQuerySound(lpKeyName, nSize, lpReturnedString)) {
return lstrlen(lpReturnedString);
} else {
if (lpDefault != NULL) {
wcsncpy(lpReturnedString, lpDefault, nSize);
}
return FALSE;
}
} else {
return GetProfileString(lpAppName,
lpKeyName,
lpDefault,
lpReturnedString,
nSize);
}
}