You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
281 lines
7.6 KiB
281 lines
7.6 KiB
//---------------------------------------------------------------------------
|
|
//
|
|
// 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->pObjectHeader = NULL;
|
|
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),
|
|
POOLTAG_SYSA);
|
|
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);
|
|
|
|
GrabInstanceMutex();
|
|
|
|
DPF1(50, "CInstance::Invalidate %08x", this);
|
|
|
|
// "RemoveRef" from file object
|
|
if(pNextFileObject != NULL) {
|
|
ObDereferenceObject(pNextFileObject);
|
|
}
|
|
pNextFileObject = NULL;
|
|
|
|
ReleaseInstanceMutex();
|
|
}
|
|
|
|
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;
|
|
|
|
//
|
|
// ISSUE: 02/26/02 ALPERS
|
|
// Why do we need the global mutex here. Can't we do it with
|
|
// instance mutex?
|
|
//
|
|
|
|
::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", DBG_IOCTL_LOG);
|
|
#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();
|
|
|
|
//
|
|
// ISSUE: 02/21/02 ALPERS
|
|
// This is totally wrong. How would sysaudio know that the pNextDeviceObject
|
|
// and sysaudio has the same DeviceStack.
|
|
// Sysaudio should allocate a new IRP and send the new IRP down to
|
|
// pNextDeviceObject.
|
|
//
|
|
// This code path is executed for IOCTL_KS_READ_STREAM,
|
|
// IOCTL_KS_WRITE_STREAM and IOCTL_KS_RESET_STATE requests.
|
|
//
|
|
// In order to solve the problem mentioned above sysaudio has to
|
|
// create new irps, pend/queue original irp and complete irps
|
|
// asynchronously.
|
|
// There is no infrastructure to do it in sysaudio. And this is
|
|
// not directly related to security.
|
|
//
|
|
if (NT_SUCCESS(Status)) {
|
|
pIrpStack->FileObject = pNextFileObject;
|
|
IoSkipCurrentIrpStackLocation(pIrp);
|
|
AssertFileObject(pIrpStack->FileObject);
|
|
Status = IoCallDriver(pInstance->pNextDeviceObject, pIrp);
|
|
}
|
|
|
|
return(Status);
|
|
}
|
|
|