mirror of https://github.com/tongzx/nt5src
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.
935 lines
25 KiB
935 lines
25 KiB
/****************************************************************************\
|
|
*
|
|
* 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);
|
|
}
|
|
}
|