|
|
/* mme.cpp
* Handles pnp, etc. for MME APIs * Created by FrankYe on 2/14/2001 * Copyright (c) 2001-2001 Microsoft Corporation */
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <regstr.h>
#include <mmsystem.h>
#include <mmsysp.h>
#include <ks.h>
#include <ksmedia.h>
#include <setupapi.h>
#include "debug.h"
#include "reg.h"
#include "service.h"
#include "audiosrv.h"
//=============================================================================
//=== file scope constants ===
//=============================================================================
#define REGSTR_VAL_SETUPPREFERREDAUDIODEVICES TEXT("SetupPreferredAudioDevices")
#define REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT TEXT("SetupPreferredAudioDevicesCount")
#define PNPINFOSIZE (256 * 1024)
//=============================================================================
//=== file scope globals ===
//=============================================================================
RTL_RESOURCE PnpInfoResource; BOOL gfPnpInfoResource = FALSE; HANDLE hPnpInfo = NULL; PMMPNPINFO pPnpInfo = NULL;
//=============================================================================
//=== security helpers ===
//=============================================================================
PSECURITY_DESCRIPTOR BuildSecurityDescriptor(DWORD AccessMask) { PSECURITY_DESCRIPTOR pSd; PSID pSidSystem; PSID pSidEveryone; PACL pDacl; ULONG cbDacl; BOOL fSuccess; BOOL f;
SID_IDENTIFIER_AUTHORITY AuthorityNt = SECURITY_NT_AUTHORITY; SID_IDENTIFIER_AUTHORITY AuthorityWorld = SECURITY_WORLD_SID_AUTHORITY;
fSuccess = FALSE;
pSd = HeapAlloc(hHeap, 0, SECURITY_DESCRIPTOR_MIN_LENGTH); if (pSd) { if (InitializeSecurityDescriptor(pSd, SECURITY_DESCRIPTOR_REVISION)) { if (AllocateAndInitializeSid(&AuthorityNt, 1, SECURITY_LOCAL_SYSTEM_RID, 0, 0, 0, 0, 0, 0, 0, &pSidSystem)) { ASSERT(IsValidSid(pSidSystem)); if (AllocateAndInitializeSid(&AuthorityWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSidEveryone)) { ASSERT(IsValidSid(pSidEveryone)); cbDacl = sizeof(ACL) + 2 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) + GetLengthSid(pSidSystem) + GetLengthSid(pSidEveryone);
pDacl = (PACL)HeapAlloc(hHeap, 0, cbDacl); if (pDacl) { if (InitializeAcl(pDacl, cbDacl, ACL_REVISION)) { if (AddAccessAllowedAce(pDacl, ACL_REVISION, GENERIC_ALL, pSidSystem)) { if (AddAccessAllowedAce(pDacl, ACL_REVISION, AccessMask, pSidEveryone)) { if (SetSecurityDescriptorDacl(pSd, TRUE, pDacl, FALSE)) { fSuccess = TRUE; } else { dprintf(TEXT("BuildSD: SetSecurityDescriptorDacl failed\n")); } } else { dprintf(TEXT("BuildSD: AddAccessAlloweAce for Everyone failed\n")); } } else { dprintf(TEXT("BuildSD: AddAccessAllowedAce for System failed\n")); } } else { dprintf(TEXT("BuildSD: InitializeAcl failed\n")); }
if (!fSuccess) { f = HeapFree(hHeap, 0, pDacl); ASSERT(f); } } FreeSid(pSidEveryone); } else { dprintf(TEXT("BuildSD: AllocateAndInitizeSid failed for Everyone\n")); } FreeSid(pSidSystem); } else { dprintf(TEXT("BuildSD: AllocateAndInitizeSid failed for System\n")); } } else { dprintf(TEXT("BuildSD: InitializeSecurityDescriptor failed\n")); }
if (!fSuccess) { f = HeapFree(hHeap, 0, pSd); ASSERT(f); } }
return fSuccess ? pSd : NULL; }
void DestroySecurityDescriptor(PSECURITY_DESCRIPTOR pSd) { PACL pDacl; BOOL fDaclPresent; BOOL fDaclDefaulted; BOOL f;
if (GetSecurityDescriptorDacl(pSd, &fDaclPresent, &pDacl, &fDaclDefaulted)) { if (fDaclPresent) { f = HeapFree(hHeap, 0, pDacl); ASSERT(f); } } else { dprintf(TEXT("DestroySD: GetSecurityDescriptorDacl failed\n")); }
f = HeapFree(hHeap, 0, pSd); ASSERT(f);
return; }
//=============================================================================
//=== ===
//=============================================================================
//--------------------------------------------------------------------------;
//
// PTSTR BroadcastWinmmDeviceChange
//
// Arguments:
//
// Return value:
//
// History:
// 11/9/98 FrankYe Created
// 2/15/2001 FrankYe Moved from winmm to audiosrv
//
//--------------------------------------------------------------------------;
void BroadcastWinmmDeviceChange(void) { static UINT uWinmmDeviceChange = 0;
if (!uWinmmDeviceChange) { uWinmmDeviceChange = RegisterWindowMessage(WINMMDEVICECHANGEMSGSTRING); // dprintf(TEXT("BroadcastWinmmDeviceChange: WINMMDEVICECHANGEMSG = %d\n"), uWinmmDeviceChange);
if (!uWinmmDeviceChange) { dprintf(TEXT("BroadcastWinmmDeviceChange: RegisterWindowMessage failed!\n")); } }
if (uWinmmDeviceChange) { DWORD dwRecipients = BSM_APPLICATIONS | BSM_ALLDESKTOPS; long result;
// dprintf(TEXT("BroadcastWinmmDeviceChange: BroadcastSystemMessage\n"));
result = BroadcastSystemMessage(BSF_POSTMESSAGE, &dwRecipients, uWinmmDeviceChange, 0, 0); if (result < 0) { dprintf(TEXT("BroadcastWinmmDeviceChange: BroadcastSystemMessage failed\n")); } } return; }
//--------------------------------------------------------------------------;
//
// PTSTR MakeRendererDeviceInstanceIdFromDeviceInterface
//
// Arguments:
//
// Return value:
//
// History:
// 11/9/98 FrankYe Created
//
//--------------------------------------------------------------------------;
PTSTR MakeRendererDeviceInstanceIdFromDeviceInterface(PWSTR DeviceInterface) { PTSTR DeviceInstanceId; HDEVINFO hdi; DWORD dwLastError;
// dprintf(TEXT("MRDIIFDI: DeviceInterface=%ls\n"), DeviceInterface);
DeviceInstanceId = NULL; hdi = SetupDiCreateDeviceInfoList(NULL, NULL); if (INVALID_HANDLE_VALUE != hdi) { SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
// dprintf(TEXT("MRDIIFDI: Created empty DeviceInfoList\n"));
DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData); if (SetupDiOpenDeviceInterface(hdi, DeviceInterface, 0, &DeviceInterfaceData)) { SP_DEVINFO_DATA DeviceInfoData; DWORD cbDeviceInterfaceDetail;
// dprintf(TEXT("MRDIIFDI: Opened DeviceInterface\n"));
DeviceInfoData.cbSize = sizeof(DeviceInfoData); if (SetupDiGetDeviceInterfaceDetail(hdi, &DeviceInterfaceData, NULL, 0, &cbDeviceInterfaceDetail, &DeviceInfoData) || (ERROR_INSUFFICIENT_BUFFER == GetLastError())) { DWORD cchDeviceInstanceId;
// dprintf(TEXT("MRDIIFDI: Got DeviceInfoData\n"));
if (SetupDiGetDeviceInstanceId(hdi, &DeviceInfoData, NULL, 0, &cchDeviceInstanceId) || ERROR_INSUFFICIENT_BUFFER == GetLastError()) { // dprintf(TEXT("MRDIIFDI: DeviceInstanceId is %d characters\n"), cchDeviceInstanceId);
DeviceInstanceId = (PTSTR)HeapAlloc(hHeap, 0, cchDeviceInstanceId * sizeof(DeviceInstanceId[0])); if (DeviceInstanceId) { // dprintf(TEXT("MRDIIFDI: Allocated storage for DeviceInstanceId\n"));
if (SetupDiGetDeviceInstanceId(hdi, &DeviceInfoData, DeviceInstanceId, cchDeviceInstanceId, NULL)) { // dprintf(TEXT("MRDIIFDI: DeviceInstanceId=%ls\n"), DeviceInstanceId);
} else { BOOL f; dwLastError = GetLastError(); dprintf(TEXT("MRDIIFDI: Couldn't query DeviceInstanceId, LastError=%d\n"), dwLastError); f = HeapFree(hHeap, 0, DeviceInstanceId); DeviceInstanceId = NULL; ASSERT(f); } } else { dprintf(TEXT("MRDIIFDI: Could not allocate storage for DeviceInstanceId\n")); } } else { dwLastError = GetLastError(); dprintf(TEXT("MRDIIFDI: Couldn't query size of DeviceInstanceId, LastError=%d\n"), dwLastError); } } else { dwLastError = GetLastError(); dprintf(TEXT("MRDIIFDI: SetupDiGetDeviceInterfaceDetail failed LastError=%d\n"), dwLastError); } } else { dwLastError = GetLastError(); dprintf(TEXT("MRDIIFDI: SetupDiOpenDeviceInterface failed, LastError=%d\n"), dwLastError); }
if (!SetupDiDestroyDeviceInfoList(hdi)) { dwLastError = GetLastError(); dprintf(TEXT("MRDIIFDI: SetupDiDestroyDeviceInfoList failed, LastError=%d\n"), dwLastError); } } else { dwLastError = GetLastError(); dprintf(TEXT("MRDIIFDI: SetupDiCreateDeviceInfoList failed, LastError=%d\n"), dwLastError); } return DeviceInstanceId; }
//--------------------------------------------------------------------------;
//
// MigrageNewDeviceInterfaceSetup
//
// Arguments:
//
// Return value:
//
// History:
// 1/19/99 FrankYe Created
//
//--------------------------------------------------------------------------;
void MigrateNewDeviceInterfaceSetup(PMMDEVICEINTERFACEINFO pdii, DWORD CurrentSetupCount) { HDEVINFO hdi; DWORD dwLastError; DWORD SetupCount;
SetupCount = 0;
hdi = SetupDiCreateDeviceInfoList(NULL, NULL); if (INVALID_HANDLE_VALUE != hdi) { SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData); if (SetupDiOpenDeviceInterface(hdi, pdii->szName, 0, &DeviceInterfaceData)) { HKEY hkeyDeviceInterface;
hkeyDeviceInterface = SetupDiCreateDeviceInterfaceRegKeyW(hdi, &DeviceInterfaceData, 0, KEY_SET_VALUE | KEY_QUERY_VALUE, NULL, NULL); if (INVALID_HANDLE_VALUE != hkeyDeviceInterface) { LONG result;
result = RegQueryDwordValue(hkeyDeviceInterface, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, &SetupCount); if ((ERROR_SUCCESS != result) || (SetupCount < CurrentSetupCount)) { SetupCount = CurrentSetupCount; if (ERROR_SUCCESS == RegSetDwordValue(hkeyDeviceInterface, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, SetupCount)) { // dprintf(TEXT("MNDIS: Success\n"));
} else { dwLastError = GetLastError(); dprintf(TEXT("MNDIS: RegSetValueEx failed, LastError=%d\n"), dwLastError); } }
result = RegCloseKey(hkeyDeviceInterface); ASSERT(ERROR_SUCCESS == result); } else { dwLastError = GetLastError(); dprintf(TEXT("MNDIS: SetupDiCreateDeviceInterfaceRegKey failed, LastError=%d\n"), dwLastError); } } else { dwLastError = GetLastError(); dprintf(TEXT("MRDIIFDI: SetupDiOpenDeviceInterface failed, LastError=%d\n"), dwLastError); }
if (!SetupDiDestroyDeviceInfoList(hdi)) { dwLastError = GetLastError(); dprintf(TEXT("MRDIIFDI: SetupDiDestroyDeviceInfoList failed, LastError=%d\n"), dwLastError); } } else { dwLastError = GetLastError(); dprintf(TEXT("MRDIIFDI: SetupDiCreateDeviceInfoList failed, LastError=%d\n"), dwLastError); }
pdii->SetupPreferredAudioCount = SetupCount; return; }
//--------------------------------------------------------------------------;
//
// MigrateNewDeviceInstanceSetup
//
// Arguments:
//
// Return value:
//
// History:
// 11/9/98 FrankYe Created
//
//--------------------------------------------------------------------------;
void MigrateNewDeviceInstanceSetup(PTSTR DeviceInstanceId, PDWORD pSetupCountOut) { HDEVINFO hdi; DWORD dwLastError;
*pSetupCountOut = 0; hdi = SetupDiCreateDeviceInfoList(NULL, NULL); if (INVALID_HANDLE_VALUE != hdi) { SP_DEVINFO_DATA DeviceInfoData;
// dprintf(TEXT("MNDS: Created empty DeviceInfoList\n"));
DeviceInfoData.cbSize = sizeof(DeviceInfoData); if (SetupDiOpenDeviceInfoW(hdi, DeviceInstanceId, NULL, 0, &DeviceInfoData)) { HKEY hkeyDriver;
hkeyDriver = SetupDiOpenDevRegKey(hdi, &DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, KEY_QUERY_VALUE | KEY_SET_VALUE); if (INVALID_HANDLE_VALUE != hkeyDriver) { HKEY hkeyMmeDrivers; dwLastError = RegOpenKeyEx(hkeyDriver, TEXT("Drivers"), 0, KEY_QUERY_VALUE, &hkeyMmeDrivers); if (ERROR_SUCCESS == dwLastError) { DWORD fNewInstall; BOOL fSetupPreferredAudioDevices; DWORD cbfSetupPreferredAudioDevices; DWORD SetupCount;
// Read the driver's existing setup count. If it doesn't exist
// then this is a new install.
dwLastError = RegQueryDwordValue(hkeyDriver, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, &SetupCount); if (ERROR_SUCCESS == dwLastError) { fNewInstall = FALSE; } else if (ERROR_FILE_NOT_FOUND == dwLastError) { fNewInstall = TRUE; SetupCount = 0; dwLastError = ERROR_SUCCESS; } else { fNewInstall = FALSE; SetupCount = 0; }
if (ERROR_SUCCESS == dwLastError) { // Read the driver's SetupPreferredAudioDevices flag.
cbfSetupPreferredAudioDevices = sizeof(fSetupPreferredAudioDevices); dwLastError = RegQueryValueEx(hkeyDriver, REGSTR_VAL_SETUPPREFERREDAUDIODEVICES, NULL, NULL, (PBYTE)&fSetupPreferredAudioDevices, &cbfSetupPreferredAudioDevices); if (ERROR_FILE_NOT_FOUND == dwLastError) { fSetupPreferredAudioDevices = FALSE; dwLastError = ERROR_SUCCESS; } // If this is a new install AND the driver .inf set the
// fSetupPreferredAudioDevices flag, then let's try to
// increment the machine setupcount and write the driver
// setupcount.
if ((ERROR_SUCCESS == dwLastError) && fNewInstall && fSetupPreferredAudioDevices) { HKEY hkeySetupPreferredAudioDevices; dwLastError = RegCreateKey(HKEY_LOCAL_MACHINE, REGSTR_PATH_MEDIARESOURCES TEXT("\\") REGSTR_VAL_SETUPPREFERREDAUDIODEVICES, &hkeySetupPreferredAudioDevices); if (ERROR_SUCCESS == dwLastError) { dwLastError = RegQueryDwordValue(hkeySetupPreferredAudioDevices, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, &SetupCount); if (ERROR_FILE_NOT_FOUND == dwLastError) { SetupCount = 0; dwLastError = ERROR_SUCCESS; } if (ERROR_SUCCESS == dwLastError) { SetupCount++; dwLastError = RegSetDwordValue(hkeySetupPreferredAudioDevices, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, SetupCount); if (ERROR_SUCCESS != dwLastError) dprintf(TEXT("MNDIS: Couldn't set count\n")); } RegCloseKey(hkeySetupPreferredAudioDevices); } else { dprintf(TEXT("MNDIS: Couldn't create hklm\\...\\SetupPreferredAudioDevices\n")); } } if (ERROR_SUCCESS == dwLastError) { // We've successfully read, incremented, and written the
// setup version to HKLM, or we've done nothing because we
// didn't have to.
if (fNewInstall) RegSetDwordValue(hkeyDriver, REGSTR_VAL_SETUPPREFERREDAUDIODEVICESCOUNT, SetupCount); if (fSetupPreferredAudioDevices) RegDeleteValue(hkeyDriver, REGSTR_VAL_SETUPPREFERREDAUDIODEVICES); } }
// Return the SetupCount for the driver
*pSetupCountOut = SetupCount; RegCloseKey(hkeyMmeDrivers); } RegCloseKey(hkeyDriver); } else { dwLastError = GetLastError(); dprintf(TEXT("MNDS: SetupDiCreateDevRegKey failed, LastError=%d\n"), dwLastError); } } else { dwLastError = GetLastError(); dprintf(TEXT("MNDS: SetupDiOpenDeviceInfo failed, LastError=%d\n"), dwLastError); }
if (!SetupDiDestroyDeviceInfoList(hdi)) { dwLastError = GetLastError(); dprintf(TEXT("MNDS: SetupDiDestroyDeviceInfoList failed, LastError=%d\n"), dwLastError); } } else { dwLastError = GetLastError(); dprintf(TEXT("MNDS: SetupDiCreateDeviceInfoList failed, LastError=%d\n"), dwLastError); } return; }
//------------------------------------------------------------------------------
//
//
// MigrateAutoSetupPreferredAudio
//
//
//------------------------------------------------------------------------------
void MigrateAutoSetupPreferredAudio(PMMDEVICEINTERFACEINFO pdii) { PTSTR pstrRendererDeviceInstanceId; DWORD SetupCount;
SetupCount = 0; pstrRendererDeviceInstanceId = MakeRendererDeviceInstanceIdFromDeviceInterface(pdii->szName);
if (pstrRendererDeviceInstanceId) { BOOL f; MigrateNewDeviceInstanceSetup(pstrRendererDeviceInstanceId, &SetupCount); f = HeapFree(hHeap, 0, pstrRendererDeviceInstanceId); ASSERT(f); }
MigrateNewDeviceInterfaceSetup(pdii, SetupCount); return; }
PMMDEVICEINTERFACEINFO pnpServerInstallDevice ( PCTSTR pszDeviceInterface, BOOL fRemove ) { PMMDEVICEINTERFACEINFO pdii; PWSTR pszDev; UINT ii;
if (NULL == pPnpInfo) { dprintf(TEXT("pnpServerInstallDevice called at bad time\n")); ASSERT(FALSE);
return NULL; }
pdii = (PMMDEVICEINTERFACEINFO)&(pPnpInfo[1]);
pdii = (PMMDEVICEINTERFACEINFO)PAD_POINTER(pdii);
for (ii = pPnpInfo->cDevInterfaces; ii; ii--) { // Searching for the device interface...
pszDev = (PWSTR)(&(pdii->szName[0]));
if (0 == lstrcmpi(pszDev, pszDeviceInterface)) { break; }
pdii = (PMMDEVICEINTERFACEINFO)(pszDev + lstrlenW(pszDev) + 1); pdii = (PMMDEVICEINTERFACEINFO)PAD_POINTER(pdii); }
// Getting the current settings...
if (0 == ii) { PMMDEVICEINTERFACEINFO pdiiNext; SIZE_T sizePnpInfo;
// Does not exist, create it, first ensuring there is enough room
pdiiNext = (PMMDEVICEINTERFACEINFO)(pdii->szName + ((lstrlenW(pszDeviceInterface) + 1))); pdiiNext = (PMMDEVICEINTERFACEINFO)PAD_POINTER(pdiiNext); sizePnpInfo = ((PBYTE)pdiiNext) - ((PBYTE)pPnpInfo); if (sizePnpInfo < PNPINFOSIZE) { // dprintf(TEXT("pnpServerInstallDevice: note: sizePnpInfo = %p\n", sizePnpInfo);
pdii->cPnpEvents = 0; pdii->fdwInfo = 0L;
pszDev = (PWSTR)(&(pdii->szName[0])); lstrcpy(pszDev, pszDeviceInterface);
pPnpInfo->cDevInterfaces++; pPnpInfo->cbSize = (DWORD)sizePnpInfo; } else { dprintf(TEXT("pnpServerInstallDevice RAN OUT OF PNPINO STORAGE!!!\n")); pdii = NULL; } } else { // Already exists, increment the event count.
pdii->cPnpEvents++; }
// Set or clear the "removed" bit.
if (pdii) { if (fRemove) { pdii->fdwInfo |= MMDEVICEINFO_REMOVED; // dprintf("pnpServerInstallDevice removed [%ls]\n", pszDeviceInterface);
} else { pdii->fdwInfo &= (~MMDEVICEINFO_REMOVED); // dprintf("pnpServerInstallDevice added [%ls]\n", pszDeviceInterface);
}
}
return pdii; }
BOOL PnpInfoEnum ( void ) { UINT cDevs = 0; HDEVINFO hDevInfo; BOOL fEnum; DWORD ii, dw; DWORD cbSize; GUID guidClass = KSCATEGORY_AUDIO; SP_DEVICE_INTERFACE_DATA did; SP_DEVINFO_DATA DevInfoData; PSP_DEVICE_INTERFACE_DETAIL_DATA pdidd;
cbSize = 300 * sizeof(TCHAR) + sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
pdidd = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(hHeap, 0, cbSize);
if (NULL == pdidd) { HeapFree(hHeap, 0, pdidd); return FALSE; }
pdidd->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
hDevInfo = SetupDiGetClassDevs( &guidClass, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (INVALID_HANDLE_VALUE == hDevInfo) { dprintf(TEXT("SetupDiGetClasDevs failed [0x%08lx].\n"), GetLastError()); HeapFree(hHeap, 0, pdidd); return FALSE; }
ZeroMemory(&did, sizeof(did));
did.cbSize = sizeof(did);
ZeroMemory(&DevInfoData, sizeof(SP_DEVINFO_DATA));
DevInfoData.cbSize = sizeof(SP_DEVINFO_DATA); DevInfoData.ClassGuid = KSCATEGORY_AUDIO;
for (ii = 0; ;ii++, cDevs++) { PMMDEVICEINTERFACEINFO pdii; fEnum = SetupDiEnumDeviceInterfaces( hDevInfo, NULL, &guidClass, ii, &did);
if (!fEnum) { break; }
dw = 0;
fEnum = SetupDiGetDeviceInterfaceDetail( hDevInfo, &did, pdidd, cbSize, &dw, &DevInfoData);
if (!fEnum) { dprintf(TEXT("SetupDiGetDeviceInterfaceDetail failed (0x%08lx).\n"), GetLastError()); break; }
// dprintf(TEXT("PnpInfoEnum: Enumerated[%ls]\n"), pdidd->DevicePath);
pdii = pnpServerInstallDevice(pdidd->DevicePath, FALSE); if (pdii) MigrateAutoSetupPreferredAudio(pdii); }
if (!SetupDiDestroyDeviceInfoList(hDevInfo)) { ASSERT(!"wdmEnumerateInstalledDevices: SetupDiDestroyDeviceInfoList failed."); }
HeapFree(hHeap, 0, pdidd); SetLastError(ERROR_SUCCESS);
return TRUE;
} // PnpInfoEnum()
BOOL InitializePnpInfo ( void ) { SECURITY_ATTRIBUTES sa; PSECURITY_DESCRIPTOR pSd; BOOL result;
ASSERT(!gfPnpInfoResource); ASSERT(!hPnpInfo); ASSERT(!pPnpInfo);
result = FALSE; __try { RtlInitializeResource(&PnpInfoResource); gfPnpInfoResource = TRUE; } __except(EXCEPTION_EXECUTE_HANDLER) { gfPnpInfoResource = FALSE;; } if (!gfPnpInfoResource) return FALSE; pSd = BuildSecurityDescriptor(FILE_MAP_READ); if (pSd) { sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = pSd; sa.bInheritHandle = FALSE;
hPnpInfo = CreateFileMapping(GetCurrentProcess(), &sa, PAGE_READWRITE, 0, PNPINFOSIZE, MMGLOBALPNPINFONAME);
DestroySecurityDescriptor(pSd);
if (hPnpInfo) { pPnpInfo = (PMMPNPINFO)MapViewOfFile(hPnpInfo, FILE_MAP_WRITE, 0, 0, 0); if (pPnpInfo) { ZeroMemory(pPnpInfo, PNPINFOSIZE); pPnpInfo->cbSize = sizeof(MMPNPINFO); pPnpInfo->cPnpEvents = 0;
result = TRUE;
} else { dprintf(TEXT("InitializePnpInfo: MapViewOfFile failed!\n")); } } else { dprintf(TEXT("InitializePnpInfo: CreateFileMappingFailed!\n")); } } else { dprintf(TEXT("InitializePnpInfo: BuildSecurityDescriptor failed!\n")); }
if (!result) { if (pPnpInfo) UnmapViewOfFile(pPnpInfo); if (hPnpInfo) CloseHandle(hPnpInfo); if (gfPnpInfoResource) RtlDeleteResource(&PnpInfoResource); pPnpInfo = NULL; hPnpInfo = NULL; gfPnpInfoResource = FALSE; }
return result; } // InitializePnpInfo()
void DeletePnpInfo(void) { ASSERT(gfPnpInfoResource); ASSERT(hPnpInfo); ASSERT(pPnpInfo);
UnmapViewOfFile(pPnpInfo); CloseHandle(hPnpInfo); RtlDeleteResource(&PnpInfoResource); pPnpInfo = NULL; hPnpInfo = NULL; gfPnpInfoResource = FALSE; return; }
//=============================================================================
//=== rpc functions ===
//=============================================================================
long s_wdmDriverOpenDrvRegKey(IN DWORD dwProcessId, IN LPCTSTR DeviceInterface, IN ULONG samDesired, OUT RHANDLE *phkeyClient) { HDEVINFO hdi; HKEY hkey; RPC_STATUS status;
// We impersonate the client while calling setupapi so that we are sure
// the client actually has access to open the driver reg key
status = RpcImpersonateClient(NULL); if (status) return status; hdi = SetupDiCreateDeviceInfoList(NULL, NULL); if (INVALID_HANDLE_VALUE != hdi) { SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
DeviceInterfaceData.cbSize = sizeof(DeviceInterfaceData); if (SetupDiOpenDeviceInterface(hdi, DeviceInterface, 0, &DeviceInterfaceData)) { SP_DEVINFO_DATA DeviceInfoData; DWORD cbDeviceInterfaceDetail;
DeviceInfoData.cbSize = sizeof(DeviceInfoData); if (SetupDiGetDeviceInterfaceDetail(hdi, &DeviceInterfaceData, NULL, 0, &cbDeviceInterfaceDetail, &DeviceInfoData) || (ERROR_INSUFFICIENT_BUFFER == GetLastError())) { hkey = SetupDiOpenDevRegKey(hdi, &DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DRV, samDesired); if (INVALID_HANDLE_VALUE != hkey) { status = ERROR_SUCCESS; } else { status = GetLastError(); dprintf(TEXT("s_wdmDriverOpenDrvRegKey: SetupDiOpenDevRegKey failed, Error=%d\n"), status); } } else { status = GetLastError(); dprintf(TEXT("s_wdmDriverOpenDrvRegKey: SetupDiGetDeviceInterfaceDetail failed, Error=%d\n"), status); } } else { status = GetLastError(); dprintf(TEXT("s_wdmDriverOpenDrvRegKey: SetupDiOpenDeviceInterface failed, Error=%d\n"), status); }
SetupDiDestroyDeviceInfoList(hdi); } else { status = GetLastError(); dprintf(TEXT("s_wdmDriverOpenDrvRegKey: SetupDiCreateDeviceInfoList failed, Error=%d\n"), status); }
// We stop impersonating here because the remaining operations
// should not depend on the client's privileges.
RpcRevertToSelf();
if (ERROR_SUCCESS == status) { HANDLE hClientProcess;
hClientProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId); if (hClientProcess) { HANDLE hkeyClient;
if (DuplicateHandle(GetCurrentProcess(), hkey, hClientProcess, &hkeyClient, 0, FALSE, DUPLICATE_SAME_ACCESS)) { // dprintf(TEXT("s_wdmDriverOpenDrvRegKey hkeyClient=%p\n"), hkeyClient);
*phkeyClient = (RHANDLE)hkeyClient; } else { status = GetLastError(); dprintf(TEXT("s_wdmDriverOpenDrvRegKey: DuplicateHandle failed, Error=%d\n"), status); } CloseHandle(hClientProcess); } else { status = GetLastError(); dprintf(TEXT("s_wdmDriverOpenDrvRegKey: OpenProcess failed, Error=%d\n"), status); }
RegCloseKey(hkey); }
return status; }
void s_winmmAdvisePreferredDeviceChange(void) { // dprintf(TEXT("s_winmmAdvisePreferredDeviceChange\n"));
ASSERT(pPnpInfo); InterlockedIncrement(&pPnpInfo->cPreferredDeviceChanges); BroadcastWinmmDeviceChange(); return; }
long s_winmmGetPnpInfo(OUT LONG *pcbPnpInfo, OUT BYTE **ppPnpInfoOut) { static BOOL fEnumDone = FALSE; PBYTE pPnpInfoOut; LONG result;
// dprintf(TEXT("s_winmmGetPnpInfo\n"));
ASSERT(pPnpInfo);
RtlAcquireResourceShared(&PnpInfoResource, TRUE); pPnpInfoOut = (PBYTE)HeapAlloc(hHeap, 0, pPnpInfo->cbSize); if (pPnpInfoOut) { CopyMemory(pPnpInfoOut, pPnpInfo, pPnpInfo->cbSize); *pcbPnpInfo = pPnpInfo->cbSize; *ppPnpInfoOut = pPnpInfoOut; result = NO_ERROR; } else { // ISSUE-2001/02/15-FrankYe Do we need to zero the out params?
result = ERROR_OUTOFMEMORY; } RtlReleaseResource(&PnpInfoResource); return result; }
//=============================================================================
//=== pnp interface handlers ===
//=============================================================================
void MME_AudioInterfaceArrival(PCTSTR DeviceInterface) { PMMDEVICEINTERFACEINFO pdii; // dprintf(TEXT("MME_AudioInterfaceArrival\n"));
RtlAcquireResourceExclusive(&PnpInfoResource, TRUE); pdii = pnpServerInstallDevice(DeviceInterface, FALSE); if (pdii) MigrateAutoSetupPreferredAudio(pdii); InterlockedIncrement(&pPnpInfo->cPnpEvents); InterlockedIncrement(&pPnpInfo->cPreferredDeviceChanges); RtlReleaseResource(&PnpInfoResource); if (pdii) BroadcastWinmmDeviceChange(); return; }
void MME_AudioInterfaceRemove(PCTSTR DeviceInterface) { PMMDEVICEINTERFACEINFO pdii; // dprintf(TEXT("MME_AudioInterfaceRemove\n"));
RtlAcquireResourceExclusive(&PnpInfoResource, TRUE); pdii = pnpServerInstallDevice(DeviceInterface, TRUE); InterlockedIncrement(&pPnpInfo->cPnpEvents); InterlockedIncrement(&pPnpInfo->cPreferredDeviceChanges); RtlReleaseResource(&PnpInfoResource); if (pdii) BroadcastWinmmDeviceChange(); return; }
LONG MME_ServiceStart(void) { ASSERT(pPnpInfo); // dprintf(TEXT("MME_ServiceStart\n"));
RtlAcquireResourceExclusive(&PnpInfoResource, TRUE); if (!PnpInfoEnum()) dprintf(TEXT("MME_ServiceStart: PnpInfoEnum failed!\n")); InterlockedIncrement(&pPnpInfo->cPnpEvents); RtlReleaseResource(&PnpInfoResource); return NO_ERROR; }
//=============================================================================
//=== DLL attach/detach ===
//=============================================================================
BOOL MME_DllProcessAttach(void) { return InitializePnpInfo(); }
void MME_DllProcessDetach(void) { return DeletePnpInfo(); }
|