windows-nt/Source/XPSP1/NT/drivers/wdm/audio/sysaudio/cinstanc.cpp
2020-09-26 16:20:57 +08:00

259 lines
6.4 KiB
C++

//---------------------------------------------------------------------------
//
// Module: ins.cpp
//
// Description:
//
// KS Instance base class definitions
//
//@@BEGIN_MSINTERNAL
// Development Team:
// Mike McLaughlin
//
// History: Date Author Comment
//
// To Do: 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.
//
//---------------------------------------------------------------------------
#include "common.h"
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
DEFINE_KSDISPATCH_TABLE(
DispatchTable,
CInstance::DispatchForwardIrp, // Ioctl
DispatchInvalidDeviceRequest, // Read
DispatchInvalidDeviceRequest, // Write
DispatchInvalidDeviceRequest, // Flush
CInstance::DispatchClose, // Close
DispatchInvalidDeviceRequest, // QuerySecurity
DispatchInvalidDeviceRequest, // SetSeturity
DispatchFastIoDeviceControlFailure, // FastDeviceIoControl
DispatchFastReadFailure, // FastRead
DispatchFastWriteFailure // FastWrite
);
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
CInstance::CInstance(
IN PPARENT_INSTANCE pParentInstance
)
{
Assert(pParentInstance);
this->pParentInstance = pParentInstance;
AddList(&pParentInstance->lstChildInstance);
}
CInstance::~CInstance(
)
{
Assert(this);
RemoveList();
// IMPORTANT : Caller must acquire gmutex.
//
// "RemoveRef" from file object
if(pNextFileObject != NULL) {
ObDereferenceObject(pNextFileObject);
pNextFileObject = NULL;
}
if(pObjectHeader != NULL) {
KsFreeObjectHeader(pObjectHeader);
}
// "RemoveRef" from parent file object
if(pParentFileObject != NULL) {
ObDereferenceObject(pParentFileObject);
}
// Clean up pin mutex
if(pMutex != NULL) {
ExFreePool(pMutex);
}
}
NTSTATUS
CInstance::DispatchCreate(
IN PIRP pIrp,
IN UTIL_PFN pfnDispatchCreate,
IN OUT PVOID pReference,
IN ULONG cCreateItems,
IN PKSOBJECT_CREATE_ITEM pCreateItems OPTIONAL,
IN const KSDISPATCH_TABLE *pDispatchTable OPTIONAL
)
{
PIO_STACK_LOCATION pIrpStack;
NTSTATUS Status;
Assert(this);
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
pParentFileObject = pIrpStack->FileObject->RelatedFileObject;
ObReferenceObject(pParentFileObject);
pMutex = (KMUTEX *)ExAllocatePoolWithTag(
NonPagedPool,
sizeof(KMUTEX),
0x41535953);
if(pMutex == NULL) {
Status = STATUS_INSUFFICIENT_RESOURCES;
goto exit;
}
KeInitializeMutex(pMutex, 0);
Status = KsAllocateObjectHeader(
&pObjectHeader,
cCreateItems,
pCreateItems,
pIrp,
pDispatchTable);
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
Status = pfnDispatchCreate(this, pReference);
if(!NT_SUCCESS(Status)) {
goto exit;
}
pNextDeviceObject = IoGetRelatedDeviceObject(pNextFileObject);
//
// ISSUE: 05/10/02 ALPERS
// Windows does not support dynamically adjusting StackSizes on the fly.
// The only place we are supposed to change this is in AddDevice.
// This must be fixed later.
//
//
// Never make the StackSize smaller. It can cause unexpected problems
// if there are devices with deeper stacks.
//
if (pIrpStack->DeviceObject->StackSize < pNextDeviceObject->StackSize) {
pIrpStack->DeviceObject->StackSize = pNextDeviceObject->StackSize;
}
pIrpStack->FileObject->FsContext = this;
exit:
return(Status);
}
VOID
CInstance::Invalidate(
)
{
Assert(this);
GrabMutex();
DPF1(50, "CInstance::Invalidate %08x", this);
// "RemoveRef" from file object
if(pNextFileObject != NULL) {
ObDereferenceObject(pNextFileObject);
}
pNextFileObject = NULL;
ReleaseMutex();
}
VOID
CParentInstance::Invalidate(
)
{
PINSTANCE pInstance;
Assert(this);
FOR_EACH_LIST_ITEM_DELETE(&lstChildInstance, pInstance) {
pInstance->Invalidate();
} END_EACH_LIST_ITEM
}
NTSTATUS
CInstance::DispatchClose(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
{
PIO_STACK_LOCATION pIrpStack;
PINSTANCE pInstance;
::GrabMutex();
pIrpStack = IoGetCurrentIrpStackLocation( pIrp );
pInstance = (PINSTANCE)pIrpStack->FileObject->FsContext;
Assert(pInstance);
pIrpStack->FileObject->FsContext = NULL;
delete pInstance;
::ReleaseMutex();
pIrp->IoStatus.Information = 0;
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return(STATUS_SUCCESS);
}
#pragma LOCKED_CODE
#pragma LOCKED_DATA
NTSTATUS
CInstance::DispatchForwardIrp(
IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIrp
)
{
PIO_STACK_LOCATION pIrpStack;
PFILE_OBJECT pNextFileObject;
PINSTANCE pInstance;
NTSTATUS Status = STATUS_SUCCESS;
#ifdef DEBUG
DumpIoctl(pIrp, "ForwardIrp");
#endif
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
pInstance = (PINSTANCE)pIrpStack->FileObject->FsContext;
// Use gMutex instead of instance mutex. The instance mutex
// is not used in any of the dispatch handlers, therefore will
// not synchronize DispatchForwardIrp with other DispatchHandlers in
// CPinInstance.
// Grab mutex for a very short time to check the validity of CInstance.
// If it is valid, IoCallDriver is called. This does not need
// synchronization
//
::GrabMutex();
Assert(pInstance);
pNextFileObject = pInstance->pNextFileObject;
if(pNextFileObject == NULL) {
DPF(60, "DispatchIoControl: pNextFileObject == NULL");
Status = pIrp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
}
::ReleaseMutex();
if (NT_SUCCESS(Status)) {
pIrpStack->FileObject = pNextFileObject;
IoSkipCurrentIrpStackLocation(pIrp);
AssertFileObject(pIrpStack->FileObject);
Status = IoCallDriver(pInstance->pNextDeviceObject, pIrp);
}
return(Status);
}