/* File: audiosrvc.c */ /* Copyright (c) 2000-2001 Microsoft Corporation */ #define UNICODE #define _UNICODE #include "winmmi.h" #include "audiosrv.h" #define RPC_CALL_START RpcTryExcept { #define RPC_CALL_END_(status) } RpcExcept(1) { status = RpcExceptionCode(); } RpcEndExcept #define RPC_CALL_END } RpcExcept(1) { RpcExceptionCode(); } RpcEndExcept void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t cb) { return HeapAlloc(hHeap, HEAP_ZERO_MEMORY, cb); } void __RPC_USER MIDL_user_free( void __RPC_FAR * pv) { HeapFree(hHeap, 0, pv); } LONG AudioSrvBinding(void) { RPC_STATUS status; PTSTR pszUuid = NULL; PTSTR pszProtocolSequence = TEXT("ncalrpc"); PTSTR pszNetworkAddress = NULL; PTSTR pszEndpoint = TEXT("AudioSrv"); PTSTR pszOptions = NULL; PTSTR pszStringBinding = NULL; PTSTR pszString = NULL; // dprintf(("AudioSrvBinding")); WinAssert(NULL == AudioSrv_IfHandle); status = RpcStringBindingCompose(pszUuid, pszProtocolSequence, pszNetworkAddress, pszEndpoint, pszOptions, &pszStringBinding); if (RPC_S_OK == status) { status = RpcBindingFromStringBinding(pszStringBinding, &AudioSrv_IfHandle); RpcStringFree(&pszStringBinding); } if (RPC_S_OK != status) dprintf(("AudioSrvBinding: returning %d", status)); return status; } void AudioSrvBindingFree(void) { RPC_STATUS status; // dprintf(("AudioSrvBindingFree")); status = AudioSrv_IfHandle ? RpcBindingFree(&AudioSrv_IfHandle) : RPC_S_OK; if (RPC_S_OK == status) WinAssert(NULL == AudioSrv_IfHandle); if (RPC_S_OK != status) dprintf(("AudioSrvBindingFree: RpcBindingFree returned %d", status)); } BOOL winmmWaitForService(void) { static BOOL fWaited = FALSE; static BOOL fStarted = FALSE; const LONG Timeout = 120000; SC_HANDLE schScm = NULL; SC_HANDLE schAudioSrv = NULL; if (fWaited) return fStarted; schScm = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT); if (!schScm) { DWORD dw = GetLastError(); dprintf(("winmmWaitForService: could not OpenSCManager, LastError=%d", dw)); return FALSE; } schAudioSrv = OpenService(schScm, TEXT("AudioSrv"), SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS); if (schAudioSrv) { int cWaits = 0; while (!fWaited) { SERVICE_STATUS ServiceStatus; if (QueryServiceStatus(schAudioSrv, &ServiceStatus)) { if ( (ServiceStatus.dwCurrentState == SERVICE_RUNNING) || (ServiceStatus.dwCurrentState == SERVICE_CONTINUE_PENDING) || (ServiceStatus.dwCurrentState == SERVICE_PAUSE_PENDING) || (ServiceStatus.dwCurrentState == SERVICE_PAUSED) ) { fStarted = TRUE; fWaited = TRUE; } else if (ServiceStatus.dwCurrentState == SERVICE_STOPPED && ServiceStatus.dwWin32ExitCode == ERROR_SERVICE_NEVER_STARTED) { if (cWaits == 0) { DWORD cbNeeded; // Check that the service StartType is set such that // it will start if (QueryServiceConfig(schAudioSrv, NULL, 0, &cbNeeded) || ERROR_INSUFFICIENT_BUFFER == GetLastError()) { QUERY_SERVICE_CONFIG *ServiceConfig; ServiceConfig = HeapAlloc(hHeap, 0, cbNeeded); if (ServiceConfig) { if (QueryServiceConfig(schAudioSrv, ServiceConfig, cbNeeded, &cbNeeded)) { if (ServiceConfig->dwStartType != SERVICE_AUTO_START) { fWaited = TRUE; } } else { DWORD dwLastError = GetLastError(); dprintf(("winmmWaitForService: QueryServiceConfig failed LastError=%d", dwLastError)); fWaited = TRUE; } HeapFree(hHeap, 0, ServiceConfig); } else { dprintf(("winmmWaitForService: HeapAlloc failed")); } } else { DWORD dwLastError = GetLastError(); dprintf(("winmmWaitForService: QueryServiceConfig failed LastError=%d", dwLastError)); fWaited = TRUE; } } } else if (ServiceStatus.dwCurrentState != SERVICE_START_PENDING) { // Unfamiliar dwCurrentState, or was started and then stopped fWaited = TRUE; } } else { DWORD dwLastError = GetLastError(); dprintf(("winmmWaitForService: QueryServiceStatus failed LastError=%d", dwLastError)); fWaited = TRUE; } if (!fWaited && ((cWaits * 2000) > Timeout)) { dprintf(("winmmWaitForService timed out. Could be design problem. Open a bug!")); WinAssert(FALSE); fWaited = TRUE; } if (!fWaited) { Sleep(2000); cWaits++; } } CloseServiceHandle(schAudioSrv); } else { DWORD dwLastError = GetLastError(); dprintf(("winmmWaitForService: OpenService failed LastError=%d", dwLastError)); } CloseServiceHandle(schScm); return fStarted; } LONG winmmRegisterSessionNotificationEvent(HANDLE hEvent, PHANDLE phRegNotify) { LONG lresult; winmmWaitForService(); RPC_CALL_START; lresult = s_winmmRegisterSessionNotificationEvent(GetCurrentProcessId(), (RHANDLE)hEvent, (PHANDLE_SESSIONNOTIFICATION)phRegNotify); RPC_CALL_END_(lresult); return lresult; } LONG winmmUnregisterSessionNotification(HANDLE hRegNotify) { LONG lresult; winmmWaitForService(); RPC_CALL_START; // if (!AudioSrv_IfHandle) dprintf(("winmmUnregisterSessionNotification : warning: called with AudioSrv_IfHandle == NULL")); // If we have a binding handle, then let's call the server to close this // context handle otherwise we need to call RpcSsDestroyClientContext to // destroy it without contacting the server if (AudioSrv_IfHandle) { lresult = s_winmmUnregisterSessionNotification((PHANDLE_SESSIONNOTIFICATION)&hRegNotify); } else { RpcSsDestroyClientContext(&hRegNotify); lresult = RPC_S_OK; } RPC_CALL_END_(lresult); return lresult; } LONG winmmSessionConnectState(PINT ConnectState) { LONG lresult; winmmWaitForService(); RPC_CALL_START; lresult = s_winmmSessionConnectState(GetCurrentProcessId(), ConnectState); RPC_CALL_END_(lresult); return lresult; } LONG wdmDriverOpenDrvRegKey(IN PCTSTR DeviceInterface, IN REGSAM samDesired, OUT HKEY *phkey) { LONG lresult; winmmWaitForService(); RPC_CALL_START; lresult = s_wdmDriverOpenDrvRegKey(GetCurrentProcessId(), DeviceInterface, samDesired, (RHANDLE*)phkey); RPC_CALL_END_(lresult); return lresult; } void winmmAdvisePreferredDeviceChange(void) { winmmWaitForService(); RPC_CALL_START; s_winmmAdvisePreferredDeviceChange(); RPC_CALL_END; return; } LONG winmmGetPnpInfo(OUT LONG *pcbPnpInfo, OUT PMMPNPINFO *ppPnpInfo) { LONG cbPnpInfo = 0; BYTE *pPnpInfo = NULL; LONG lresult; winmmWaitForService(); RPC_CALL_START; lresult = s_winmmGetPnpInfo(&cbPnpInfo, &pPnpInfo); RPC_CALL_END_(lresult); if (ERROR_SUCCESS == lresult) { *pcbPnpInfo = cbPnpInfo; *ppPnpInfo = (PMMPNPINFO)pPnpInfo; } return lresult; }