|
|
/*****************************************************************************
* kso.cpp - KS object support (IrpTargets) ***************************************************************************** * Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved. */
#include "private.h"
#include <swenum.h>
/*****************************************************************************
* OBJECT_CONTEXT ***************************************************************************** * Context structure for all file objects. */ typedef struct { PVOID pObjectHeader; PIRPTARGET pIrpTarget; BOOLEAN ReferenceParent; } OBJECT_CONTEXT, *POBJECT_CONTEXT;
DEFINE_KSDISPATCH_TABLE( KsoDispatchTable, DispatchDeviceIoControl, DispatchRead, DispatchWrite, DispatchFlush, DispatchClose, DispatchQuerySecurity, DispatchSetSecurity, DispatchFastDeviceIoControl, DispatchFastRead, DispatchFastWrite );
#define CAST_LVALUE(type,lvalue) (*((type*)&(lvalue)))
#define IRPTARGET_FACTORY_IRP_STORAGE(Irp) \
CAST_LVALUE(PIRPTARGETFACTORY,IoGetCurrentIrpStackLocation(Irp)-> \ Parameters.Others.Argument4)
#pragma code_seg("PAGE")
/*****************************************************************************
* AddIrpTargetFactoryToDevice() ***************************************************************************** * Adds an IrpTargetFactory to a device's create items list. */ NTSTATUS NTAPI AddIrpTargetFactoryToDevice ( IN PDEVICE_OBJECT pDeviceObject, IN PIRPTARGETFACTORY pIrpTargetFactory, IN PWCHAR pwcObjectClass, IN PSECURITY_DESCRIPTOR pSecurityDescriptor OPTIONAL ) { PAGED_CODE();
ASSERT(pDeviceObject); ASSERT(pIrpTargetFactory); ASSERT(pwcObjectClass);
PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
NTSTATUS ntStatus = KsAddObjectCreateItemToDeviceHeader ( pDeviceContext->pDeviceHeader, KsoDispatchCreate, pIrpTargetFactory, pwcObjectClass, pSecurityDescriptor );
if (NT_SUCCESS(ntStatus)) { pIrpTargetFactory->AddRef(); }
return ntStatus; }
/*****************************************************************************
* AddIrpTargetFactoryToObject() ***************************************************************************** * Adds an IrpTargetFactory to a objects's create items list. */ NTSTATUS NTAPI AddIrpTargetFactoryToObject ( IN PFILE_OBJECT pFileObject, IN PIRPTARGETFACTORY pIrpTargetFactory, IN PWCHAR pwcObjectClass, IN PSECURITY_DESCRIPTOR pSecurityDescriptor ) { PAGED_CODE();
ASSERT(pFileObject); ASSERT(pIrpTargetFactory); ASSERT(pwcObjectClass);
POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pFileObject->FsContext);
NTSTATUS ntStatus = KsAddObjectCreateItemToObjectHeader ( pObjectContext->pObjectHeader, KsoDispatchCreate, pIrpTargetFactory, pwcObjectClass, pSecurityDescriptor );
if (NT_SUCCESS(ntStatus)) { pIrpTargetFactory->AddRef(); }
return ntStatus; }
#pragma code_seg()
/*****************************************************************************
* KsoGetIrpTargetFromIrp() ***************************************************************************** * Extracts the IrpTarget pointer from an IRP. */ PIRPTARGET NTAPI KsoGetIrpTargetFromIrp ( IN PIRP Irp ) { ASSERT(Irp);
return ( POBJECT_CONTEXT ( IoGetCurrentIrpStackLocation(Irp) -> FileObject -> FsContext ) -> pIrpTarget ); }
/*****************************************************************************
* KsoGetIrpTargetFromFileObject() ***************************************************************************** * Extracts the IrpTarget pointer from a FileObject pointer. */ PIRPTARGET NTAPI KsoGetIrpTargetFromFileObject( IN PFILE_OBJECT FileObject ) { ASSERT(FileObject);
return POBJECT_CONTEXT( FileObject->FsContext )->pIrpTarget; }
#pragma code_seg("PAGE")
IRPDISP GetIrpDisposition( IN PDEVICE_OBJECT DeviceObject, IN UCHAR MinorFunction ) { PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(DeviceObject->DeviceExtension);
//
// If we're removed, or not accepting any calls, fail this.
//
if ((pDeviceContext->DeviceRemoveState == DeviceRemoved) || (pDeviceContext->DeviceStopState == DeviceStopped)) {
return IRPDISP_NOTREADY; }
//
// Similarly, ignore anything but closes if we were surprise removed.
//
if ((MinorFunction != IRP_MJ_CLOSE) && (pDeviceContext->DeviceRemoveState == DeviceSurpriseRemoved)) {
return IRPDISP_NOTREADY; }
if ((MinorFunction == IRP_MJ_CREATE) && (pDeviceContext->PendCreates)) {
return IRPDISP_QUEUE; }
if ( (pDeviceContext->DeviceStopState == DevicePausedForRebalance) || (pDeviceContext->DeviceStopState == DeviceStartPending) || (!NT_SUCCESS(CheckCurrentPowerState(DeviceObject)))) {
return IRPDISP_QUEUE;
} else {
return IRPDISP_PROCESS; } }
/*****************************************************************************
* DispatchCreate() ***************************************************************************** * Handles a create IRP. */ NTSTATUS DispatchCreate ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PAGED_CODE();
ASSERT(pDeviceObject); ASSERT(pIrp);
PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
ASSERT(pDeviceContext);
NTSTATUS ntStatus = STATUS_SUCCESS; IRPDISP irpDisp;
_DbgPrintF( DEBUGLVL_VERBOSE, ("DispatchCreate"));
IncrementPendingIrpCount(pDeviceContext); AcquireDevice(pDeviceContext);
// check the device state
irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_CREATE);
switch(irpDisp) {
default: ASSERT(0);
//
// Fall through
//
case IRPDISP_NOTREADY:
ntStatus = STATUS_DEVICE_NOT_READY; pIrp->IoStatus.Information = 0; CompleteIrp(pDeviceContext,pIrp,ntStatus); break;
case IRPDISP_QUEUE:
// pend the irp
IoMarkIrpPending( pIrp );
// add the IRP to the pended IRP queue
KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList, &pDeviceContext->PendedIrpLock, pIrp, KsListEntryTail, NULL );
ntStatus = STATUS_PENDING; break;
case IRPDISP_PROCESS:
// dispatch the irp
ntStatus = KsDispatchIrp(pDeviceObject,pIrp); break; }
ReleaseDevice(pDeviceContext);
return ntStatus; }
/*****************************************************************************
* xDispatchCreate() ***************************************************************************** * Handles a create IRP. */ NTSTATUS xDispatchCreate ( IN PIRPTARGETFACTORY pIrpTargetFactory, IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PAGED_CODE();
ASSERT(pIrpTargetFactory); ASSERT(pDeviceObject); ASSERT(pIrp); PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
ASSERT(pDeviceContext);
NTSTATUS ntStatus = STATUS_SUCCESS;
POBJECT_CONTEXT pObjectContext=NULL; BOOL bCreatedIrpTarget=FALSE; BOOL bReferencedBusObject=FALSE; KSOBJECT_CREATE ksObjectCreate;
_DbgPrintF( DEBUGLVL_VERBOSE, ("xDispatchCreate"));
// If there no target, fail the IRP
if (! pIrpTargetFactory ) { ntStatus = STATUS_INVALID_DEVICE_REQUEST; }
if (NT_SUCCESS(ntStatus)) { // Allocate our context structure.
pObjectContext = POBJECT_CONTEXT(ExAllocatePoolWithTag(NonPagedPool,sizeof(OBJECT_CONTEXT),'OosK')); if (!pObjectContext) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; } }
if (NT_SUCCESS(ntStatus)) { ntStatus = KsReferenceSoftwareBusObject(pDeviceContext->pDeviceHeader); if (NT_SUCCESS(ntStatus)) { bReferencedBusObject = TRUE; } else if (STATUS_NOT_IMPLEMENTED == ntStatus) { ntStatus = STATUS_SUCCESS; } }
if (NT_SUCCESS(ntStatus)) { // Tell the factory to create a new object.
ksObjectCreate.CreateItemsCount = 0; ksObjectCreate.CreateItemsList = NULL;
ntStatus = pIrpTargetFactory->NewIrpTarget(&pObjectContext->pIrpTarget, &pObjectContext->ReferenceParent, NULL, NonPagedPool, pDeviceObject, pIrp, &ksObjectCreate);
// NewIrpTarget should not pend
ASSERT(ntStatus != STATUS_PENDING); }
if (NT_SUCCESS(ntStatus)) { bCreatedIrpTarget=TRUE;
// Allocate KS's header for this object.
ntStatus = KsAllocateObjectHeader(&pObjectContext->pObjectHeader, ksObjectCreate.CreateItemsCount, ksObjectCreate.CreateItemsList, pIrp, &KsoDispatchTable); }
PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp); if (NT_SUCCESS(ntStatus)) { // Hook up the context to the file object.
ASSERT(pObjectContext); pIrpSp->FileObject->FsContext = pObjectContext;
// AddRef the parent file object if this is a child.
if (pObjectContext->ReferenceParent && pIrpSp->FileObject->RelatedFileObject) { ObReferenceObject(pIrpSp->FileObject->RelatedFileObject); }
InterlockedIncrement(PLONG(&pDeviceContext->ExistingObjectCount)); _DbgPrintF(DEBUGLVL_VERBOSE,("xDispatchCreate objects: %d",pDeviceContext->ExistingObjectCount));
ASSERT(pIrpSp->FileObject->FsContext); } else { if (bCreatedIrpTarget) { pObjectContext->pIrpTarget->Release(); } if (pObjectContext) { ExFreePool(pObjectContext); } pIrpSp->FileObject->FsContext = NULL; if (bReferencedBusObject) { KsDereferenceSoftwareBusObject(pDeviceContext->pDeviceHeader); } } ASSERT(ntStatus != STATUS_PENDING);
pIrp->IoStatus.Information = 0; CompleteIrp(pDeviceContext,pIrp,ntStatus); return ntStatus; }
/*****************************************************************************
* CompletePendedIrps ***************************************************************************** * This pulls pended irps off the queue and either fails them or passes them * back to KsoDispatchIrp. */ void CompletePendedIrps ( IN PDEVICE_OBJECT pDeviceObject, IN PDEVICE_CONTEXT pDeviceContext, IN COMPLETE_STYLE CompleteStyle ) { ASSERT(pDeviceObject); ASSERT(pDeviceContext);
_DbgPrintF(DEBUGLVL_VERBOSE,("Completing pended create IRPs..."));
PIRP pIrp = KsRemoveIrpFromCancelableQueue( &pDeviceContext->PendedIrpList, &pDeviceContext->PendedIrpLock, KsListEntryHead, KsAcquireAndRemove ); while ( pIrp ) { if ( CompleteStyle == EMPTY_QUEUE_AND_FAIL ) { // fail the IRP with STATUS_DEVICE_NOT_READY
CompleteIrp( pDeviceContext, pIrp, STATUS_DEVICE_NOT_READY ); } else { // pass the IRP back to the dispatchers
KsoDispatchIrp( pDeviceObject, pIrp ); }
// clean up the pending irp count
DecrementPendingIrpCount( pDeviceContext );
// get the next irp
pIrp = KsRemoveIrpFromCancelableQueue( &pDeviceContext->PendedIrpList, &pDeviceContext->PendedIrpLock, KsListEntryHead, KsAcquireAndRemove ); } }
/*****************************************************************************
* KsoDispatchCreate() ***************************************************************************** * Handles object create IRPs using the IIrpTargetFactory interface pointer * in the Context field of the create item. */ NTSTATUS KsoDispatchCreate ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { NTSTATUS ntStatus;
PAGED_CODE();
ASSERT(pDeviceObject); ASSERT(pIrp);
ntStatus = xDispatchCreate ( PIRPTARGETFACTORY(KSCREATE_ITEM_IRP_STORAGE(pIrp)->Context), pDeviceObject, pIrp );
return ntStatus; }
/*****************************************************************************
* KsoDispatchCreateWithGenericFactory() ***************************************************************************** * Handles object create IRPs using the IIrpTarget interface pointer in the * device or object context. */ NTSTATUS KsoDispatchCreateWithGenericFactory ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PAGED_CODE();
ASSERT(pDeviceObject); ASSERT(pIrp);
PIRPTARGETFACTORY pIrpTargetFactory; PFILE_OBJECT pParentFileObject = IoGetCurrentIrpStackLocation(pIrp)->FileObject->RelatedFileObject;
if (pParentFileObject) { // Get IrpTargetFactory from parent object context.
pIrpTargetFactory = ( POBJECT_CONTEXT(pParentFileObject->FsContext) -> pIrpTarget ); } else { // Get IrpTargetFactory from device object context.
pIrpTargetFactory = ( PDEVICE_CONTEXT(pDeviceObject->DeviceExtension) -> pIrpTargetFactory ); }
return xDispatchCreate(pIrpTargetFactory,pDeviceObject,pIrp); }
/*****************************************************************************
* DispatchDeviceIoControl() ***************************************************************************** * Dispatches device I/O control IRPs. */ NTSTATUS DispatchDeviceIoControl ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PAGED_CODE();
ASSERT(pDeviceObject); ASSERT(pIrp);
NTSTATUS ntStatus; IRPDISP irpDisp;
PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
IncrementPendingIrpCount(pDeviceContext);
// check the device state
irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_DEVICE_CONTROL);
switch(irpDisp) {
default: ASSERT(0);
//
// Fall through
//
case IRPDISP_NOTREADY:
_DbgPrintF(DEBUGLVL_TERSE,("FAILING DevIoCtl due to dev state"));
ntStatus = STATUS_DEVICE_NOT_READY;
pIrp->IoStatus.Information = 0; CompleteIrp(pDeviceContext,pIrp,ntStatus); break;
case IRPDISP_QUEUE:
ntStatus = STATUS_PENDING; pIrp->IoStatus.Status = ntStatus; IoMarkIrpPending( pIrp );
// add the IRP to the pended IRP queue
KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList, &pDeviceContext->PendedIrpLock, pIrp, KsListEntryTail, NULL );
ntStatus = STATUS_PENDING; break;
case IRPDISP_PROCESS:
// get the stack location
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
// get the object context
POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pIrpStack->FileObject->FsContext);
// if we have an IrpTarget, go ahead and dispatch. Otherwise, pass off to KS.
if( pObjectContext->pIrpTarget ) { ntStatus = pObjectContext->pIrpTarget->DeviceIoControl( pDeviceObject, pIrp ); } else { ntStatus = KsDispatchIrp( pDeviceObject, pIrp ); }
DecrementPendingIrpCount(pDeviceContext); break; }
return ntStatus; }
/*****************************************************************************
* DispatchFastDeviceIoControl() ***************************************************************************** * Dispatches fast device I/O control calls. */ BOOLEAN DispatchFastDeviceIoControl ( IN PFILE_OBJECT FileObject, IN BOOLEAN Wait, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN ULONG IoControlCode, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) { PAGED_CODE();
ASSERT(FileObject); ASSERT(IoStatus); ASSERT(DeviceObject);
CheckCurrentPowerState( DeviceObject );
return(POBJECT_CONTEXT(FileObject->FsContext)->pIrpTarget->FastDeviceIoControl( FileObject, Wait, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, IoControlCode, IoStatus, DeviceObject)); }
/*****************************************************************************
* DispatchRead() ***************************************************************************** * Dispatches read IRPs. */ NTSTATUS DispatchRead ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PAGED_CODE();
ASSERT(pDeviceObject); ASSERT(pIrp);
NTSTATUS ntStatus; IRPDISP irpDisp;
PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
IncrementPendingIrpCount(pDeviceContext);
// check the device state
irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_READ);
switch(irpDisp) {
default: ASSERT(0);
//
// Fall through
//
case IRPDISP_NOTREADY:
ntStatus = STATUS_DEVICE_NOT_READY; pIrp->IoStatus.Information = 0; CompleteIrp(pDeviceContext,pIrp,ntStatus); break;
case IRPDISP_QUEUE:
// pend the IRP
ntStatus = STATUS_PENDING; pIrp->IoStatus.Status = ntStatus; IoMarkIrpPending( pIrp );
// add the IRP to the pended IRP queue
KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList, &pDeviceContext->PendedIrpLock, pIrp, KsListEntryTail, NULL ); break;
case IRPDISP_PROCESS:
// get the stack location
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
// get the object context
POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pIrpStack->FileObject->FsContext);
// if we have an IrpTarget, go ahead and dispatch. Otherwise, pass off to KS.
if( pObjectContext->pIrpTarget ) { ntStatus = pObjectContext->pIrpTarget->Read( pDeviceObject, pIrp ); } else { ntStatus = KsDispatchIrp( pDeviceObject, pIrp ); }
DecrementPendingIrpCount(pDeviceContext); break; }
return ntStatus; }
/*****************************************************************************
* DispatchFastRead() ***************************************************************************** * Dispatches fast read calls. */ BOOLEAN DispatchFastRead ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, OUT PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) { PAGED_CODE();
ASSERT(FileObject); ASSERT(IoStatus); ASSERT(DeviceObject);
CheckCurrentPowerState( DeviceObject );
return ( POBJECT_CONTEXT(FileObject->FsContext) -> pIrpTarget -> FastRead ( FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject ) ); }
/*****************************************************************************
* DispatchWrite() ***************************************************************************** * Dispatches write IRPs. */ NTSTATUS DispatchWrite ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PAGED_CODE();
ASSERT(pDeviceObject); ASSERT(pIrp);
NTSTATUS ntStatus; IRPDISP irpDisp;
PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
IncrementPendingIrpCount(pDeviceContext);
// check the device state
irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_WRITE);
switch(irpDisp) {
default: ASSERT(0);
//
// Fall through
//
case IRPDISP_NOTREADY:
ntStatus = STATUS_DEVICE_NOT_READY; pIrp->IoStatus.Information = 0; CompleteIrp(pDeviceContext,pIrp,ntStatus); break;
case IRPDISP_QUEUE:
// pend the IRP
ntStatus = STATUS_PENDING; pIrp->IoStatus.Status = ntStatus; IoMarkIrpPending( pIrp );
// add the IRP to the pended IRP queue
KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList, &pDeviceContext->PendedIrpLock, pIrp, KsListEntryTail, NULL ); break;
case IRPDISP_PROCESS:
// get the stack location
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
// get the object context
POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pIrpStack->FileObject->FsContext);
// if we have an IrpTarget, go ahead and dispatch. Otherwise, pass off to KS.
if( pObjectContext->pIrpTarget ) { ntStatus = pObjectContext->pIrpTarget->Write( pDeviceObject, pIrp ); } else { ntStatus = KsDispatchIrp( pDeviceObject, pIrp ); }
DecrementPendingIrpCount(pDeviceContext); break; }
return ntStatus; }
/*****************************************************************************
* DispatchFastWrite() ***************************************************************************** * Dispatches fast write calls. */ BOOLEAN DispatchFastWrite ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN Wait, IN ULONG LockKey, IN PVOID Buffer, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) { PAGED_CODE();
ASSERT(FileObject); ASSERT(IoStatus); ASSERT(DeviceObject);
CheckCurrentPowerState( DeviceObject );
return ( POBJECT_CONTEXT(FileObject->FsContext) -> pIrpTarget -> FastWrite ( FileObject, FileOffset, Length, Wait, LockKey, Buffer, IoStatus, DeviceObject ) ); }
/*****************************************************************************
* DispatchFlush() ***************************************************************************** * Dispatches flush IRPs. */ NTSTATUS DispatchFlush ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PAGED_CODE();
ASSERT(pDeviceObject); ASSERT(pIrp);
NTSTATUS ntStatus; IRPDISP irpDisp;
PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
IncrementPendingIrpCount(pDeviceContext);
// check the device state
irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_FLUSH_BUFFERS);
switch(irpDisp) {
default: ASSERT(0);
//
// Fall through
//
case IRPDISP_NOTREADY:
ntStatus = STATUS_DEVICE_NOT_READY; pIrp->IoStatus.Information = 0; CompleteIrp(pDeviceContext,pIrp,ntStatus); break;
case IRPDISP_QUEUE:
// pend the IRP
ntStatus = STATUS_PENDING; pIrp->IoStatus.Status = ntStatus; IoMarkIrpPending( pIrp );
// add the IRP to the pended IRP queue
KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList, &pDeviceContext->PendedIrpLock, pIrp, KsListEntryTail, NULL ); break;
case IRPDISP_PROCESS:
// get the stack location
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
// get the object context
POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pIrpStack->FileObject->FsContext);
// if we have an IrpTarget, go ahead and dispatch. Otherwise, pass off to KS.
if( pObjectContext->pIrpTarget ) { ntStatus = pObjectContext->pIrpTarget->Flush( pDeviceObject, pIrp ); } else { ntStatus = KsDispatchIrp( pDeviceObject, pIrp ); }
DecrementPendingIrpCount(pDeviceContext); break; }
return ntStatus; }
/*****************************************************************************
* DispatchClose() ***************************************************************************** * Dispatches close IRPs. */ NTSTATUS DispatchClose ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PAGED_CODE();
ASSERT(pDeviceObject); ASSERT(pIrp);
NTSTATUS ntStatus; IRPDISP irpDisp;
PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
IncrementPendingIrpCount(pDeviceContext);
// check the device state
irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_CLOSE);
switch(irpDisp) {
default: ASSERT(0);
//
// Fall through
//
case IRPDISP_NOTREADY:
_DbgPrintF(DEBUGLVL_TERSE,("-- FAILED due to dev state"));
ntStatus = STATUS_DEVICE_NOT_READY; pIrp->IoStatus.Information = 0;
CompleteIrp(pDeviceContext,pIrp,ntStatus); break;
case IRPDISP_QUEUE:
ntStatus = STATUS_PENDING; pIrp->IoStatus.Status = ntStatus; IoMarkIrpPending( pIrp );
// add the IRP to the pended IRP queue
KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList, &pDeviceContext->PendedIrpLock, pIrp, KsListEntryTail, NULL ); break;
case IRPDISP_PROCESS:
// get the stack location
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
// get the object context
POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pIrpStack->FileObject->FsContext);
// if we have an IrpTarget, go ahead and dispatch. Otherwise, pass off to KS.
if( pObjectContext->pIrpTarget ) { // get the parent file object (if there is one)
PFILE_OBJECT pFileObjectParent = pIrpStack->FileObject->RelatedFileObject;
// dispatch the close to the IrpTarget
ntStatus = pObjectContext->pIrpTarget->Close( pDeviceObject, pIrp );
// release the IrpTarget
pObjectContext->pIrpTarget->Release();
// dereference the software bus object
KsDereferenceSoftwareBusObject( pDeviceContext->pDeviceHeader );
// free the object header
KsFreeObjectHeader( pObjectContext->pObjectHeader );
// dereference the parent file object
if (pObjectContext->ReferenceParent && pFileObjectParent) { ObDereferenceObject(pFileObjectParent); }
// free the object context
ExFreePool(pObjectContext);
} else { ntStatus = KsDispatchIrp( pDeviceObject, pIrp ); }
// decrement object count
ULONG newObjectCount = InterlockedDecrement(PLONG(&pDeviceContext->ExistingObjectCount));
_DbgPrintF(DEBUGLVL_VERBOSE,("DispatchClose objects: %d",newObjectCount));
DecrementPendingIrpCount(pDeviceContext); break; }
return ntStatus; }
/*****************************************************************************
* DispatchQuerySecurity() ***************************************************************************** * Dispatches query security IRPs. */ NTSTATUS DispatchQuerySecurity ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PAGED_CODE();
ASSERT(pDeviceObject); ASSERT(pIrp);
NTSTATUS ntStatus; IRPDISP irpDisp;
PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
IncrementPendingIrpCount(pDeviceContext);
// check the device state
irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_QUERY_SECURITY);
switch(irpDisp) {
default: ASSERT(0);
//
// Fall through
//
case IRPDISP_NOTREADY:
ntStatus = STATUS_DEVICE_NOT_READY; pIrp->IoStatus.Information = 0; CompleteIrp(pDeviceContext,pIrp,ntStatus); break;
case IRPDISP_QUEUE:
ntStatus = STATUS_PENDING; pIrp->IoStatus.Status = ntStatus; IoMarkIrpPending( pIrp );
// add the IRP to the pended IRP queue
KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList, &pDeviceContext->PendedIrpLock, pIrp, KsListEntryTail, NULL ); break;
case IRPDISP_PROCESS:
// get the stack location
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
// get the object context
POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pIrpStack->FileObject->FsContext);
// if we have an IrpTarget, go ahead and dispatch. Otherwise, pass off to KS.
if( pObjectContext->pIrpTarget ) { ntStatus = pObjectContext->pIrpTarget->QuerySecurity( pDeviceObject, pIrp ); } else { ntStatus = KsDispatchIrp( pDeviceObject, pIrp ); }
DecrementPendingIrpCount(pDeviceContext); }
return ntStatus; }
/*****************************************************************************
* DispatchSetSecurity() ***************************************************************************** * Dispatches set security IRPs. */ NTSTATUS DispatchSetSecurity ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PAGED_CODE();
ASSERT(pDeviceObject); ASSERT(pIrp);
NTSTATUS ntStatus; IRPDISP irpDisp;
PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
IncrementPendingIrpCount(pDeviceContext);
// check the device state
irpDisp = GetIrpDisposition(pDeviceObject, IRP_MJ_SET_SECURITY);
switch(irpDisp) {
default: ASSERT(0);
//
// Fall through
//
case IRPDISP_NOTREADY:
ntStatus = STATUS_DEVICE_NOT_READY; pIrp->IoStatus.Information = 0; CompleteIrp(pDeviceContext,pIrp,ntStatus); break;
case IRPDISP_QUEUE:
ntStatus = STATUS_PENDING; pIrp->IoStatus.Status = ntStatus; IoMarkIrpPending( pIrp );
// add the IRP to the pended IRP queue
KsAddIrpToCancelableQueue( &pDeviceContext->PendedIrpList, &pDeviceContext->PendedIrpLock, pIrp, KsListEntryTail, NULL );
break;
case IRPDISP_PROCESS:
// get the stack location
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
// get the object context
POBJECT_CONTEXT pObjectContext = POBJECT_CONTEXT(pIrpStack->FileObject->FsContext);
// if we have an IrpTarget, go ahead and dispatch. Otherwise, pass off to KS.
if( pObjectContext->pIrpTarget ) { ntStatus = pObjectContext->pIrpTarget->SetSecurity( pDeviceObject, pIrp ); } else { ntStatus = KsDispatchIrp( pDeviceObject, pIrp ); }
DecrementPendingIrpCount(pDeviceContext); break; }
return ntStatus; }
/*****************************************************************************
* KsoSetMajorFunctionHandler() ***************************************************************************** * Sets up the handler for a major function. */ NTSTATUS KsoSetMajorFunctionHandler ( IN PDRIVER_OBJECT pDriverObject, IN ULONG ulMajorFunction ) { PAGED_CODE();
ASSERT(pDriverObject);
NTSTATUS ntStatus = STATUS_SUCCESS; PDRIVER_DISPATCH pDriverDispatch = NULL;
switch (ulMajorFunction) { case IRP_MJ_CREATE: pDriverDispatch = DispatchCreate; break;
case IRP_MJ_CLOSE: pDriverDispatch = DispatchClose; break;
case IRP_MJ_FLUSH_BUFFERS: pDriverDispatch = DispatchFlush; break;
case IRP_MJ_DEVICE_CONTROL: pDriverDispatch = DispatchDeviceIoControl; break;
case IRP_MJ_READ: pDriverDispatch = DispatchRead; break;
case IRP_MJ_WRITE: pDriverDispatch = DispatchWrite; break;
case IRP_MJ_QUERY_SECURITY: pDriverDispatch = DispatchQuerySecurity; break;
case IRP_MJ_SET_SECURITY: pDriverDispatch = DispatchSetSecurity; break;
case IRP_MJ_DEVICE_CONTROL | KSDISPATCH_FASTIO: pDriverObject->FastIoDispatch->FastIoDeviceControl = DispatchFastDeviceIoControl; break;
case IRP_MJ_READ | KSDISPATCH_FASTIO: pDriverObject->FastIoDispatch->FastIoRead = DispatchFastRead; break;
case IRP_MJ_WRITE | KSDISPATCH_FASTIO: pDriverObject->FastIoDispatch->FastIoWrite = DispatchFastWrite; break;
default: ntStatus = STATUS_INVALID_PARAMETER; break; }
if (pDriverDispatch) { pDriverObject->MajorFunction[ulMajorFunction] = pDriverDispatch; }
return ntStatus; }
/*****************************************************************************
* KsoDispatchIrp() ***************************************************************************** * Dispatch an IRP. */ NTSTATUS KsoDispatchIrp ( IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp ) { PAGED_CODE();
ASSERT(pDeviceObject); ASSERT(pIrp);
NTSTATUS ntStatus;
PDEVICE_CONTEXT pDeviceContext = PDEVICE_CONTEXT(pDeviceObject->DeviceExtension);
ntStatus = PcValidateDeviceContext(pDeviceContext, pIrp); if (!NT_SUCCESS(ntStatus)) { // Don't know what to do, but this is probably a PDO.
// We'll try to make this right by completing the IRP
// untouched (per PnP, WMI, and Power rules). Note
// that if this isn't a PDO, and isn't a portcls FDO, then
// the driver messed up by using Portcls as a filter (huh?)
// In this case the verifier will fail us, WHQL will catch
// them, and the driver will be fixed. We'd be very surprised
// to see such a case.
// Assume FDO, no PoStartNextPowerIrp as this isn't IRP_MJ_POWER
ntStatus = pIrp->IoStatus.Status; IoCompleteRequest( pIrp, IO_NO_INCREMENT ); return ntStatus; }
if (IoGetCurrentIrpStackLocation(pIrp)->MajorFunction == IRP_MJ_CREATE) { //
// Creates must be handled differently because portcls does not do
// a KsSetMajorFunctionHandler on IRP_MJ_CREATE.
//
ntStatus = DispatchCreate(pDeviceObject,pIrp); } else { //
// At this point, the object in question may or may not be a portcls
// object (it may be a Ks allocator, for instance). Calling
// KsDispatchIrp() will dispatch the Irp as it normally would for a
// driver which does KsSetMajorFunctionHandler(). This will call
// through the object header to the appropriate dispatch function.
// For portcls objects, this is KsoDispatchTable above. For Ks
// allocators, this will route the call to the correct function
// instead of going to the wrong dispatch routine here.
//
ntStatus = KsDispatchIrp(pDeviceObject,pIrp); }
return ntStatus;
}
#pragma code_seg()
|