256 lines
8.1 KiB
C
256 lines
8.1 KiB
C
|
/* 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;
|
||
|
}
|
||
|
|