|
|
/*++
Copyright (c) 1998-2000 Microsoft Corporation
Module Name:
control.c
Abstract:
this has code for the sr control object. this is the object that is created that matches the HANDLE usermode uses to perform operations with the sr driver Author:
Paul McDaniel (paulmcd) 23-Jan-2000
Revision History:
--*/
#include "precomp.h"
//
// Private constants.
//
//
// Private types.
//
//
// Private prototypes.
//
//
// linker commands
//
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, SrCreateControlObject )
#pragma alloc_text( PAGE, SrDeleteControlObject )
#pragma alloc_text( PAGE, SrCancelControlIo )
#pragma alloc_text( PAGE, SrReferenceControlObject)
#pragma alloc_text( PAGE, SrDereferenceControlObject )
#endif // ALLOC_PRAGMA
//
// Private globals.
//
//
// Public globals.
//
//
// Public functions.
//
//
// you must have the lock EXCLUSIVE prior to calling this !
//
NTSTATUS SrCreateControlObject( OUT PSR_CONTROL_OBJECT * ppControlObject, IN ULONG Options ) { NTSTATUS Status = STATUS_SUCCESS; PSR_CONTROL_OBJECT pControlObject = NULL;
PAGED_CODE();
SrTrace(FUNC_ENTRY, ("SR!SrCreateControlObject()\n")); //
// allocate the control object
//
pControlObject = SR_ALLOCATE_STRUCT( NonPagedPool, SR_CONTROL_OBJECT, SR_CONTROL_OBJECT_TAG );
if (pControlObject == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; goto end; }
//
// wipe it clean
//
RtlZeroMemory(pControlObject, sizeof(SR_CONTROL_OBJECT));
pControlObject->Signature = SR_CONTROL_OBJECT_TAG;
//
// Start the refcount at 1 (the caller's ref)
//
pControlObject->RefCount = 1;
//
// Copy over the info from create
//
pControlObject->Options = Options; //
// Init our lists
//
InitializeListHead(&pControlObject->IrpListHead); InitializeListHead(&pControlObject->NotifyRecordListHead);
//
// Fill in the EPROCESS
//
pControlObject->pProcess = IoGetCurrentProcess();
//
// return the object
//
*ppControlObject = pControlObject;
//
// all done
//
SrTrace(NOTIFY, ("SR!SrCreateControlObject(%p)\n", pControlObject));
end:
if (NT_SUCCESS(Status) == FALSE) { if (pControlObject != NULL) { SR_FREE_POOL_WITH_SIG(pControlObject, SR_CONTROL_OBJECT_TAG); } }
RETURN(Status); } // SrCreateControlObject
NTSTATUS SrDeleteControlObject( IN PSR_CONTROL_OBJECT pControlObject ) { NTSTATUS Status; PLIST_ENTRY pEntry;
ASSERT(IS_GLOBAL_LOCK_ACQUIRED());
PAGED_CODE();
SrTrace(NOTIFY, ("SR!SrDeleteControlObject(%p)\n", pControlObject));
if (IS_VALID_CONTROL_OBJECT(pControlObject) == FALSE) { RETURN(STATUS_INVALID_DEVICE_REQUEST); }
//
// cancel all pending io (just in case)
//
Status = SrCancelControlIo(pControlObject); CHECK_STATUS(Status);
//
// dump all of our pending notif records...
//
while (IsListEmpty(&pControlObject->NotifyRecordListHead) == FALSE) { PSR_NOTIFICATION_RECORD pRecord; //
// Pop it off the list.
//
pEntry = RemoveHeadList(&pControlObject->NotifyRecordListHead); pEntry->Blink = pEntry->Flink = NULL;
pRecord = CONTAINING_RECORD( pEntry, SR_NOTIFICATION_RECORD, ListEntry ); ASSERT(IS_VALID_NOTIFICATION_RECORD(pRecord));
//
// free the record
//
SR_FREE_POOL_WITH_SIG(pRecord, SR_NOTIFICATION_RECORD_TAG);
//
// move on to the next one
//
} // while (IsListEmpty(&pControlObject->NotifyRecordListHead) == FALSE)
//
// we no longer have a process lying around
//
pControlObject->pProcess = NULL; //
// and release the final reference ... this should delete it
// (pending async cancels)
//
SrDereferenceControlObject(pControlObject); pControlObject = NULL;
//
// all done
//
RETURN(STATUS_SUCCESS); } // SrDeleteControlObject
NTSTATUS SrCancelControlIo( IN PSR_CONTROL_OBJECT pControlObject ) { PLIST_ENTRY pEntry;
ASSERT(IS_GLOBAL_LOCK_ACQUIRED());
PAGED_CODE();
SrTrace(NOTIFY, ("SR!SrCancelControlIo(%p)\n", pControlObject));
if (IS_VALID_CONTROL_OBJECT(pControlObject) == FALSE) { RETURN(STATUS_INVALID_DEVICE_REQUEST); }
//
// loop over the list and cancel any pending io.
//
while (!IsListEmpty(&pControlObject->IrpListHead)) { PIRP pIrp;
//
// Pop it off the list.
//
pEntry = RemoveHeadList(&pControlObject->IrpListHead); pEntry->Blink = pEntry->Flink = NULL;
pIrp = CONTAINING_RECORD(pEntry, IRP, Tail.Overlay.ListEntry); ASSERT(IS_VALID_IRP(pIrp));
//
// pop the cancel routine
//
if (IoSetCancelRoutine(pIrp, NULL) == NULL) { //
// IoCancelIrp pop'd it first
//
// ok to just ignore this irp, it's been pop'd off the queue
// and will be completed in the cancel routine.
//
// keep looping
//
pIrp = NULL;
} else { PSR_CONTROL_OBJECT pIrpControlObject;
//
// cancel it. even if pIrp->Cancel == TRUE we are supposed to
// complete it, our cancel routine will never run.
//
pIrpControlObject = (PSR_CONTROL_OBJECT)( IoGetCurrentIrpStackLocation(pIrp)-> Parameters.DeviceIoControl.Type3InputBuffer );
ASSERT(pIrpControlObject == pControlObject); ASSERT(IS_VALID_CONTROL_OBJECT(pIrpControlObject));
SrDereferenceControlObject(pIrpControlObject);
IoGetCurrentIrpStackLocation(pIrp)-> Parameters.DeviceIoControl.Type3InputBuffer = NULL;
pIrp->IoStatus.Status = STATUS_CANCELLED; pIrp->IoStatus.Information = 0;
IoCompleteRequest(pIrp, IO_NO_INCREMENT); pIrp = NULL; }
//
// move on to the next one
//
}
//
// our irp list should now empty.
//
ASSERT(IsListEmpty(&pControlObject->IrpListHead));
RETURN(STATUS_SUCCESS);
} // SrCancelControlIo
VOID SrReferenceControlObject( IN PSR_CONTROL_OBJECT pControlObject ) { LONG RefCount;
//
// Sanity check.
//
PAGED_CODE();
ASSERT(IS_VALID_CONTROL_OBJECT(pControlObject));
RefCount = InterlockedIncrement( &pControlObject->RefCount );
} // SrReferenceControlObject
VOID SrDereferenceControlObject( IN PSR_CONTROL_OBJECT pControlObject ) { LONG RefCount; //
// Sanity check.
//
PAGED_CODE();
ASSERT(IS_VALID_CONTROL_OBJECT(pControlObject));
RefCount = InterlockedDecrement( &pControlObject->RefCount );
if (RefCount == 0) {
//
// there better not be any items on any lists
//
ASSERT(IsListEmpty(&pControlObject->NotifyRecordListHead)); ASSERT(IsListEmpty(&pControlObject->IrpListHead));
//
// and the memory
//
SR_FREE_POOL_WITH_SIG(pControlObject, SR_CONTROL_OBJECT_TAG);
}
} // SrDereferenceControlObject
|