windows-nt/Source/XPSP1/NT/drivers/wdm/audio/sysaudio/device.cpp

314 lines
7.9 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//---------------------------------------------------------------------------
//
// Module: device.c
//
// Description:
//
//
//@@BEGIN_MSINTERNAL
// Development Team:
// S.Mohanraj
//
// History: Date Author Comment
//
//@@END_MSINTERNAL
//---------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
//
//---------------------------------------------------------------------------
#define IRPMJFUNCDESC
//#define TIME_BOMB
#include "common.h"
#ifdef TIME_BOMB
#include <ksdebug.h>
#include "..\timebomb\timebomb.c"
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
PDEVICE_INSTANCE gpDeviceInstance = NULL;
DEFINE_KSCREATE_DISPATCH_TABLE(DeviceCreateItems)
{
DEFINE_KSCREATE_ITEMNULL(
CFilterInstance::FilterDispatchCreate,
NULL),
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#pragma INIT_CODE
#pragma INIT_DATA
NTSTATUS
DriverEntry
(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING usRegistryPathName
)
{
NTSTATUS Status = STATUS_SUCCESS;
#ifdef TIME_BOMB
if (HasEvaluationTimeExpired()) {
return STATUS_EVALUATION_EXPIRATION;
}
#endif
KeInitializeMutex(&gMutex, 0);
GrabMutex();
DriverObject->MajorFunction[IRP_MJ_PNP] = DispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = KsDefaultDispatchPower;
DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = KsDefaultForwardIrp;
DriverObject->DriverUnload = DriverUnload;
DriverObject->DriverExtension->AddDevice = AddDevice;
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CREATE);
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_CLOSE);
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_DEVICE_CONTROL);
KsSetMajorFunctionHandler(DriverObject, IRP_MJ_WRITE);
Status = InitializeUtil();
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
Status = InitializeFilterNode();
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
Status = InitializeDeviceNode();
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
Status = InitializeVirtualSourceLine();
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
InitializeListHead(&gEventQueue);
KeInitializeSpinLock(&gEventLock);
exit:
ReleaseMutex();
return(Status);
}
#pragma PAGEABLE_CODE
#pragma PAGEABLE_DATA
NTSTATUS
DispatchPnp(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
{
PIO_STACK_LOCATION pIrpStack;
UNICODE_STRING usLinkName;
pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
switch(pIrpStack->MinorFunction) {
case IRP_MN_QUERY_PNP_DEVICE_STATE:
//
// Mark the device as not disableable.
//
pIrp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
break;
case IRP_MN_REMOVE_DEVICE:
//
// We need to unregister the notifications first before killing the
// worker threads
//
UnregisterForPlugPlayNotifications();
//
// Needs to be outside the mutex because KsUnregisterWorker blocks
// until all worker threads are done
//
UninitializeUtil();
GrabMutex();
CShingleInstance::UninitializeShingle();
UninitializeFilterNode();
UninitializeDeviceNode();
UninitializeVirtualSourceLine();
RtlInitUnicodeString(&usLinkName, STR_LINKNAME);
IoDeleteSymbolicLink(&usLinkName);
gpDeviceInstance = NULL;
UninitializeMemory();
ReleaseMutex();
break;
}
return(KsDefaultDispatchPnp(pDeviceObject, pIrp));
}
VOID
DriverUnload(
IN PDRIVER_OBJECT DriverObject
)
{
#ifdef DEBUG
#ifndef UNDER_NT
#ifdef _X86_
UninitializeDebug();
#endif
#endif
#endif
}
NTSTATUS
AddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
When a new device is detected, PnP calls this entry point with the
new PhysicalDeviceObject (PDO). The driver creates an associated
FunctionalDeviceObject (FDO).
Arguments:
DriverObject -
Pointer to the driver object.
PhysicalDeviceObject -
Pointer to the new physical device object.
Return Values:
STATUS_SUCCESS or an appropriate error condition.
--*/
{
UNICODE_STRING usDeviceName;
UNICODE_STRING usLinkName;
PDEVICE_OBJECT FunctionalDeviceObject = NULL;
NTSTATUS Status;
int i;
GrabMutex();
RtlInitUnicodeString(&usDeviceName, STR_DEVICENAME);
Status = IoCreateDevice(
DriverObject,
sizeof(DEVICE_INSTANCE),
&usDeviceName,
FILE_DEVICE_KS,
0,
FALSE,
&FunctionalDeviceObject);
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
gpDeviceInstance =
(PDEVICE_INSTANCE)FunctionalDeviceObject->DeviceExtension;
gpDeviceInstance->pPhysicalDeviceObject = PhysicalDeviceObject;
gpDeviceInstance->pFunctionalDeviceObject = FunctionalDeviceObject;
RtlInitUnicodeString(&usLinkName, STR_LINKNAME);
Status = IoCreateSymbolicLink(&usLinkName, &usDeviceName);
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
Status = KsAllocateDeviceHeader(
&gpDeviceInstance->pDeviceHeader,
SIZEOF_ARRAY(DeviceCreateItems),
(PKSOBJECT_CREATE_ITEM)DeviceCreateItems);
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
KsSetDevicePnpAndBaseObject(
gpDeviceInstance->pDeviceHeader,
IoAttachDeviceToDeviceStack(FunctionalDeviceObject, PhysicalDeviceObject),
FunctionalDeviceObject);
//
// ISSUE: 05/13/2002 ALPERS
// StackSize Problem
// Note that we may still have StackSize problems with deeper objects.
// The problem will be caught by IO verifier.
// However in real world, we do not expect any problems because usbaudio
// driver will never passes-down requests from Sysaudio. In other words,
// even if DeviceStackSize is deeper than Sysaudio, the IRP will never go
// down-level from Usbaudio.
//
//
// Set the StackSize for deeper device stacks.
// Sysaudio StackSize is normally 2.
// SYSAUDIO - FDO
// SWENUM - PDO
//
// Sysaudio forwards the IRPs to other device stacks which might
// be deeper than 2. In that case IoVerifier will bugcheck.
// An example of this is an upper UsbAudio filter driver forwarding
// IRPs to UsbAudio.
//
// Setting FDO StackSize to DEFAULT_LARGE_IRP_LOCATIONS 8 (iomgr.h)
// guarantees that the IRP comes from large IRP lookaside list in kernel.
// Thus no memory is wasted. The system has a list of IRPs that it recycles.
//
// StackSize 7 will almost guarantee that sysaudio will be deep enough
// for any DeviceStack, even with IoVerifier turned on.
//
if (FunctionalDeviceObject->StackSize < 7) {
FunctionalDeviceObject->StackSize = 7;
}
Status = RegisterForPlugPlayNotifications();
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
Status = CShingleInstance::InitializeShingle();
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
DeviceCreateItems[0].Context =
apShingleInstance[KSPROPERTY_SYSAUDIO_NORMAL_DEFAULT];
FunctionalDeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE;
FunctionalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
exit:
ReleaseMutex();
return(Status);
}
//---------------------------------------------------------------------------
// End of File: device.c
//---------------------------------------------------------------------------