/****************************************************************************\ * * 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 #include #include #include #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); } }