|
|
/* audiosrv.cpp
* Copyright (c) 2000-2001 Microsoft Corporation */ #include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#undef ASSERT
#include <stdio.h>
#include <windows.h>
#include <setupapi.h>
#include <dbt.h>
#include <ks.h>
#include <ksmedia.h>
#include <svcs.h>
#include "debug.h"
#include "list.h"
#include "audiosrv.h"
#include "service.h"
#include "agfxs.h"
#include "mme.h"
#include "ts.h"
//
// Note in general don't rely on compiler init of global
// variables since service might be stopped and restarted
// without this DLL being freed and then reloaded.
//
PSVCHOST_GLOBAL_DATA gpSvchostSharedGlobals = NULL; BOOL fRpcStarted; HANDLE hHeap; HDEVNOTIFY hdevNotifyAudio; HDEVNOTIFY hdevNotifyRender; HDEVNOTIFY hdevNotifyCapture; HDEVNOTIFY hdevNotifyDataTransform; HDEVNOTIFY hdevNotifySysaudio;
//
// Upon loading this DLL, svchost will find this exported function
// and pass a pointer to useful shared globals.
void SvchostPushServiceGlobals(IN PSVCHOST_GLOBAL_DATA pSvchostSharedGlobals) { gpSvchostSharedGlobals = pSvchostSharedGlobals; }
//--------------------------------------------------------------------------;
//
// AudioSrvRpcIfCallback
//
// Description:
// RPC security callback function. See MSDN for RpcServerRegisterIfEx
// IfCallback parameter. This security callback function will fail any
// non local RPC calls. It checks this by using the internal RPC
// function I_RpcBindingInqTransportType.
//
// Arguments:
// See MSDN for RPC_IF_CALLBACK_FN.
//
// Return value:
// See MSDN for RPC_IF_CALLBACK_FN.
//
// History:
// 05/02/2002 FrankYe Created
//
//--------------------------------------------------------------------------;
RPC_STATUS RPC_ENTRY AudioSrvRpcIfCallback(IN RPC_IF_HANDLE Interface, IN void *Context) { unsigned int type; RPC_STATUS status;
status = I_RpcBindingInqTransportType(Context, &type); if (RPC_S_OK != status) return ERROR_ACCESS_DENIED; if (TRANSPORT_TYPE_LPC != type) return ERROR_ACCESS_DENIED; return RPC_S_OK; }
// Stub initialization function.
DWORD MyServiceInitialization(SERVICE_STATUS_HANDLE ssh, DWORD argc, LPTSTR *argv, DWORD *specificError) { DEV_BROADCAST_DEVICEINTERFACE dbdi; LONG status;
// dprintf(TEXT("MyServiceInitialization\n"));
status = ERROR_SUCCESS;;
fRpcStarted = FALSE; hdevNotifyAudio = NULL; hdevNotifyRender = NULL; hdevNotifyCapture = NULL; hdevNotifyDataTransform = NULL; hdevNotifySysaudio = NULL;
gplistSessionNotifications = new CListSessionNotifications; if (!gplistSessionNotifications) status = ERROR_OUTOFMEMORY; if (!status) status = gplistSessionNotifications->Initialize();
if (!status) { ZeroMemory(&dbdi, sizeof(dbdi)); dbdi.dbcc_size = sizeof(dbdi); dbdi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; dbdi.dbcc_classguid = KSCATEGORY_AUDIO; hdevNotifyAudio = RegisterDeviceNotification(ssh, &dbdi, DEVICE_NOTIFY_SERVICE_HANDLE); if (!hdevNotifyAudio) status = GetLastError(); } if (!status) { ZeroMemory(&dbdi, sizeof(dbdi)); dbdi.dbcc_size = sizeof(dbdi); dbdi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; dbdi.dbcc_classguid = KSCATEGORY_RENDER; hdevNotifyRender = RegisterDeviceNotification(ssh, &dbdi, DEVICE_NOTIFY_SERVICE_HANDLE); if (!hdevNotifyRender) status = GetLastError(); } if (!status) { ZeroMemory(&dbdi, sizeof(dbdi)); dbdi.dbcc_size = sizeof(dbdi); dbdi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; dbdi.dbcc_classguid = KSCATEGORY_CAPTURE; hdevNotifyCapture = RegisterDeviceNotification(ssh, &dbdi, DEVICE_NOTIFY_SERVICE_HANDLE); if (!hdevNotifyCapture) status = GetLastError(); } if (!status) { ZeroMemory(&dbdi, sizeof(dbdi)); dbdi.dbcc_size = sizeof(dbdi); dbdi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; dbdi.dbcc_classguid = KSCATEGORY_DATATRANSFORM; hdevNotifyDataTransform = RegisterDeviceNotification(ssh, &dbdi, DEVICE_NOTIFY_SERVICE_HANDLE); if (!hdevNotifyDataTransform) status = GetLastError(); } if (!status) { ZeroMemory(&dbdi, sizeof(dbdi)); dbdi.dbcc_size = sizeof(dbdi); dbdi.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; dbdi.dbcc_classguid = KSCATEGORY_SYSAUDIO; hdevNotifySysaudio = RegisterDeviceNotification(ssh, &dbdi, DEVICE_NOTIFY_SERVICE_HANDLE); if (!hdevNotifySysaudio) status = GetLastError(); } if (!status) { NTSTATUS ntstatus; ntstatus = RpcServerUseAllProtseqsIf(RPC_C_PROTSEQ_MAX_REQS_DEFAULT, AudioSrv_v1_0_s_ifspec, NULL); if (!ntstatus) ntstatus = RpcServerRegisterIfEx(AudioSrv_v1_0_s_ifspec, NULL, NULL, RPC_IF_AUTOLISTEN, RPC_C_LISTEN_MAX_CALLS_DEFAULT, AudioSrvRpcIfCallback); if (!ntstatus) { fRpcStarted = TRUE; } else { // ISSUE-2000/10/10-FrankYe Try to convert to proper win32 error.
status = RPC_S_SERVER_UNAVAILABLE; } }
if (!status) { status = MME_ServiceStart(); }
if (status) { // Rely on MyServiceTerminate to clean up anything
// that is partially initialized.
}
return status; } // end MyServiceInitialization
void MyServiceTerminate(void) { //
// Stop the Rpc server
//
if (fRpcStarted) { NTSTATUS status; status = RpcServerUnregisterIf(AudioSrv_v1_0_s_ifspec, NULL, 1); if (status) dprintf(TEXT("ServiceStop: StopRpcServerEx returned NTSTATUS=%08Xh\n"), status); fRpcStarted = FALSE; } //
// Unregister PnP notifications
//
if (hdevNotifySysaudio) UnregisterDeviceNotification(hdevNotifySysaudio); if (hdevNotifyDataTransform) UnregisterDeviceNotification(hdevNotifyDataTransform); if (hdevNotifyCapture) UnregisterDeviceNotification(hdevNotifyCapture); if (hdevNotifyRender) UnregisterDeviceNotification(hdevNotifyRender); if (hdevNotifyAudio) UnregisterDeviceNotification(hdevNotifyAudio); hdevNotifySysaudio = NULL; hdevNotifyDataTransform = NULL; hdevNotifyCapture = NULL; hdevNotifyRender = NULL; hdevNotifyAudio = NULL;
//
// Clean up any remaining session notifications and delete list
//
if (gplistSessionNotifications) { POSITION pos = gplistSessionNotifications->GetHeadPosition(); while (pos) { PSESSIONNOTIFICATION pNotification; pNotification = gplistSessionNotifications->GetNext(pos); CloseHandle(pNotification->Event); delete pNotification; } delete gplistSessionNotifications; } gplistSessionNotifications = NULL;
//
// Clean up GFX support
//
GFX_ServiceStop();
return; }
DWORD ServiceDeviceEvent(DWORD EventType, LPVOID EventData) { PDEV_BROADCAST_DEVICEINTERFACE dbdi = (PDEV_BROADCAST_DEVICEINTERFACE)EventData;
switch (EventType) { case DBT_DEVICEARRIVAL: if (dbdi->dbcc_devicetype != DBT_DEVTYP_DEVICEINTERFACE) break; if (dbdi->dbcc_classguid == KSCATEGORY_AUDIO) MME_AudioInterfaceArrival(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_SYSAUDIO) GFX_SysaudioInterfaceArrival(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_AUDIO) GFX_AudioInterfaceArrival(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_RENDER) GFX_RenderInterfaceArrival(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_CAPTURE) GFX_CaptureInterfaceArrival(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_DATATRANSFORM) GFX_DataTransformInterfaceArrival(dbdi->dbcc_name); return NO_ERROR;
case DBT_DEVICEQUERYREMOVEFAILED: if (dbdi->dbcc_devicetype != DBT_DEVTYP_DEVICEINTERFACE) break; if (dbdi->dbcc_classguid == KSCATEGORY_SYSAUDIO) GFX_SysaudioInterfaceArrival(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_AUDIO) GFX_AudioInterfaceArrival(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_RENDER) GFX_RenderInterfaceArrival(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_CAPTURE) GFX_CaptureInterfaceArrival(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_DATATRANSFORM) GFX_DataTransformInterfaceArrival(dbdi->dbcc_name); return NO_ERROR;
case DBT_DEVICEQUERYREMOVE: if (dbdi->dbcc_devicetype != DBT_DEVTYP_DEVICEINTERFACE) break; if (dbdi->dbcc_classguid == KSCATEGORY_SYSAUDIO) GFX_SysaudioInterfaceRemove(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_AUDIO) GFX_AudioInterfaceRemove(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_RENDER) GFX_RenderInterfaceRemove(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_CAPTURE) GFX_CaptureInterfaceRemove(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_DATATRANSFORM) GFX_DataTransformInterfaceRemove(dbdi->dbcc_name); return NO_ERROR;
case DBT_DEVICEREMOVEPENDING: if (dbdi->dbcc_devicetype != DBT_DEVTYP_DEVICEINTERFACE) break; if (dbdi->dbcc_classguid == KSCATEGORY_AUDIO) MME_AudioInterfaceRemove(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_SYSAUDIO) GFX_SysaudioInterfaceRemove(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_AUDIO) GFX_AudioInterfaceRemove(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_RENDER) GFX_RenderInterfaceRemove(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_CAPTURE) GFX_CaptureInterfaceRemove(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_DATATRANSFORM) GFX_DataTransformInterfaceRemove(dbdi->dbcc_name); return NO_ERROR;
case DBT_DEVICEREMOVECOMPLETE: if (dbdi->dbcc_devicetype != DBT_DEVTYP_DEVICEINTERFACE) break; if (dbdi->dbcc_classguid == KSCATEGORY_AUDIO) MME_AudioInterfaceRemove(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_SYSAUDIO) GFX_SysaudioInterfaceRemove(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_AUDIO) GFX_AudioInterfaceRemove(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_RENDER) GFX_RenderInterfaceRemove(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_CAPTURE) GFX_CaptureInterfaceRemove(dbdi->dbcc_name); if (dbdi->dbcc_classguid == KSCATEGORY_DATATRANSFORM) GFX_DataTransformInterfaceRemove(dbdi->dbcc_name); return NO_ERROR;
default: return ERROR_CALL_NOT_IMPLEMENTED; }
return ERROR_CALL_NOT_IMPLEMENTED; }
void ServiceStop(void) { dprintf(TEXT("ServiceStop\n")); ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0); MyServiceTerminate(); ReportStatusToSCMgr(SERVICE_STOPPED, NO_ERROR, 0);
return; }
VOID ServiceStart(SERVICE_STATUS_HANDLE ssh, DWORD dwArgc, LPTSTR *lpszArgv) { DWORD status; DWORD specificError;
// dprintf(TEXT("ServiceStart\n"));
status = MyServiceInitialization(ssh, dwArgc, lpszArgv, &specificError);
if (!status) { // dprintf(TEXT("MyServiceInitialization succeeded\n"));
ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0); } else { dprintf(TEXT("MyServiceInitialization returned status=%d\n"), status); ReportStatusToSCMgr(SERVICE_STOPPED, status, 0); }
return; }
void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t cb) { return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb); }
void __RPC_USER MIDL_user_free( void __RPC_FAR * pv) { HeapFree(hHeap, 0, pv); }
BOOL DllMain(PVOID hModule, ULONG Reason, PCONTEXT pContext) { BOOL result = TRUE; static BOOL fGfxResult = FALSE; static BOOL fMmeResult = FALSE; if (DLL_PROCESS_ATTACH == Reason) { hHeap = GetProcessHeap(); result = fGfxResult = GFX_DllProcessAttach(); if (result) result = fMmeResult = MME_DllProcessAttach();
if (!result) { if (fMmeResult) MME_DllProcessDetach(); if (fGfxResult) GFX_DllProcessDetach();
fMmeResult = FALSE; fGfxResult = FALSE; } } else if (DLL_PROCESS_DETACH == Reason) { if (fMmeResult) MME_DllProcessDetach(); if (fGfxResult) GFX_DllProcessDetach();
fMmeResult = FALSE; fGfxResult = FALSE; }
return result; }
|