//--------------------------------------------------------------------------- // // 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 #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); // // ISSUE: 02/13/02 ALPERS // Why would we acquire the mutex in DriverEntry? // 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: // // SECURITY NOTE: // The PnP system will not send anymore message if this routine fails. Even // DriverUnload will not be called. // According to DDK docs DriverEntry should do its own cleanup in case of // failures. // if (!NT_SUCCESS(Status)) { UninitializeUtil(); UninitializeVirtualSourceLine(); UninitializeDeviceNode(); UninitializeFilterNode(); UninitializeMemory(); } ReleaseMutex(); return(Status); } #pragma PAGEABLE_CODE #pragma PAGEABLE_DATA NTSTATUS DispatchPnp( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PIO_STACK_LOCATION pIrpStack; 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(); gpDeviceInstance = NULL; UninitializeMemory(); ReleaseMutex(); break; } return(KsDefaultDispatchPnp(pDeviceObject, pIrp)); } VOID DriverUnload( IN PDRIVER_OBJECT DriverObject ) { } 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. --*/ { PDEVICE_OBJECT FunctionalDeviceObject = NULL; NTSTATUS Status; int i; GrabMutex(); Status = IoCreateDevice( DriverObject, sizeof(DEVICE_INSTANCE), NULL, FILE_DEVICE_KS, 0, FALSE, &FunctionalDeviceObject); if(!NT_SUCCESS(Status)) { Trap(); goto exit; } gpDeviceInstance = (PDEVICE_INSTANCE)FunctionalDeviceObject->DeviceExtension; gpDeviceInstance->pPhysicalDeviceObject = PhysicalDeviceObject; 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 < SYSTEM_LARGE_IRP_LOCATIONS) { FunctionalDeviceObject->StackSize = SYSTEM_LARGE_IRP_LOCATIONS; } 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 //---------------------------------------------------------------------------