windows-nt/Source/XPSP1/NT/drivers/parallel/parclass/openclos.c
2020-09-26 16:20:57 +08:00

339 lines
8.8 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: openclos.c
//
//--------------------------------------------------------------------------
//
// This file contains functions associated with Create/Open, Cleanup, and Close
//
#include "pch.h"
#include "ecp.h"
NTSTATUS
ParCreateOpen(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is the dispatch for a create requests.
Arguments:
DeviceObject - Supplies the device object.
Irp - Supplies the I/O request packet.
Return Value:
STATUS_SUCCESS - Success.
!STATUS_SUCCESS - Failure.
--*/
{
NTSTATUS Status;
PDEVICE_EXTENSION Extension;
USHORT i;
ParDump2(PAROPENCLOSE, ("openclose::ParCreateOpen - IRP_MJ_CREATE - Enter\n") );
Extension = DeviceObject->DeviceExtension;
Irp->IoStatus.Information = 0;
ExAcquireFastMutex(&Extension->OpenCloseMutex);
//
// bail out if a delete is pending for this device object
//
if(Extension->DeviceStateFlags & PAR_DEVICE_DELETE_PENDING) {
ExReleaseFastMutex(&Extension->OpenCloseMutex);
Irp->IoStatus.Status = STATUS_DELETE_PENDING;
ParCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_DELETE_PENDING;
}
//
// bail out if a remove is pending for our ParPort device object
//
if(Extension->DeviceStateFlags & PAR_DEVICE_PORT_REMOVE_PENDING) {
ExReleaseFastMutex(&Extension->OpenCloseMutex);
Irp->IoStatus.Status = STATUS_DELETE_PENDING;
ParCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_DELETE_PENDING;
}
//
// bail out if device has been removed
//
if(Extension->DeviceStateFlags & (PAR_DEVICE_REMOVED|PAR_DEVICE_SURPRISE_REMOVAL) ) {
ExReleaseFastMutex(&Extension->OpenCloseMutex);
Irp->IoStatus.Status = STATUS_DEVICE_REMOVED;
ParCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_DEVICE_REMOVED;
}
//
// fail IRP if no hardware under this device
//
if (!Extension->PortDeviceObject) {
ParDump2(PAROPENCLOSE, ("NULL PortDeviceObject pointer - FAIL IRP - This is the FDO!!!\n") );
ExReleaseFastMutex(&Extension->OpenCloseMutex);
Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
ParCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INVALID_DEVICE_REQUEST;
}
// this is an exclusive access device - fail IRP if we are already open
if (InterlockedIncrement(&Extension->OpenCloseRefCount) != 1) {
ParDump2(PAROPENCLOSE, ("ParCreateOpen - Device Already Open - Fail request\n") );
ExReleaseFastMutex(&Extension->OpenCloseMutex);
InterlockedDecrement(&Extension->OpenCloseRefCount);
Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
ParCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_ACCESS_DENIED;
}
ExReleaseFastMutex(&Extension->OpenCloseMutex);
//
// Lock in code.
//
ParClaimDriver();
//
// Lock in the port driver.
//
// RMT - what if this fails?
ParGetPortInfoFromPortDevice(Extension);
//
// Set the default ieee1284 modes
//
ParInitializeExtension1284Info( Extension );
ExInitializeFastMutex (&Extension->LockPortMutex);
KeInitializeEvent(&Extension->PauseEvent, NotificationEvent, TRUE);
Extension->TimeToTerminateThread = FALSE;
// assert that we do not already have a thread
ASSERT(!Extension->ThreadObjectPointer);
// - replaced following by above assertion: Extension->ThreadObjectPointer = NULL;
KeInitializeSemaphore(&Extension->RequestSemaphore, 0, MAXLONG);
if (IoGetCurrentIrpStackLocation(Irp)->Parameters.Create.Options & FILE_DIRECTORY_FILE) {
Status = Irp->IoStatus.Status = STATUS_NOT_A_DIRECTORY;
} else {
Status = Irp->IoStatus.Status = ParCreateSystemThread(Extension);
}
ParDump2(PAROPENCLOSE, ("About to complete IRP in create/open - Irp: %x status: %x Information: %x\n",
Irp, Irp->IoStatus.Status, Irp->IoStatus.Information) );
if (!NT_SUCCESS(Status)) {
// open failed
ULONG openCloseCount = InterlockedDecrement(&Extension->OpenCloseRefCount);
ASSERT(0 == openCloseCount);
}
ParCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
ParCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is the dispatch for a cleanup requests.
Arguments:
DeviceObject - Supplies the device object.
Irp - Supplies the I/O request packet.
Return Value:
STATUS_SUCCESS - Success.
--*/
{
PDEVICE_EXTENSION Extension;
KIRQL CancelIrql;
PDRIVER_CANCEL CancelRoutine;
PIRP CurrentLastIrp;
ParDump2(PAROPENCLOSE, ("In ParCleanup\n") );
Extension = DeviceObject->DeviceExtension;
//
// While the list is not empty, go through and cancel each irp.
//
IoAcquireCancelSpinLock(&CancelIrql);
//
// Clean the list from back to front.
//
while (!IsListEmpty(&Extension->WorkQueue)) {
CurrentLastIrp = CONTAINING_RECORD(Extension->WorkQueue.Blink,
IRP, Tail.Overlay.ListEntry);
RemoveEntryList(Extension->WorkQueue.Blink);
CancelRoutine = CurrentLastIrp->CancelRoutine;
CurrentLastIrp->CancelIrql = CancelIrql;
CurrentLastIrp->CancelRoutine = NULL;
CurrentLastIrp->Cancel = TRUE;
CancelRoutine(DeviceObject, CurrentLastIrp);
IoAcquireCancelSpinLock(&CancelIrql);
}
//
// If there is a current irp then mark it as cancelled.
//
if (Extension->CurrentOpIrp) {
Extension->CurrentOpIrp->Cancel = TRUE;
}
IoReleaseCancelSpinLock(CancelIrql);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
// ParDump(PARIRPPATH | PARDUMP_VERBOSE_MAX,
// ("PARALLEL: "
// "About to complete IRP in cleanup - "
// "Irp: %x status: %x Information: %x\n",
// Irp, Irp->IoStatus.Status, Irp->IoStatus.Information) );
ParCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS
ParClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is the dispatch for a close requests.
Arguments:
DeviceObject - Supplies the device object.
Irp - Supplies the I/O request packet.
Return Value:
STATUS_SUCCESS - Success.
--*/
{
PDEVICE_EXTENSION Extension;
// NTSTATUS StatusOfWait;
ParDump2(PAROPENCLOSE, ( "ParClose(...)\n") );
Extension = DeviceObject->DeviceExtension;
// immediately stop signalling event
Extension->P12843DL.bEventActive = FALSE;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
if (Extension->bShadowBuffer)
{
Queue_Delete(&(Extension->ShadowBuffer));
Extension->bShadowBuffer = FALSE;
}
// if we still have a worker thread, kill it
if(Extension->ThreadObjectPointer) {
// set the flag for the worker thread to kill itself
Extension->TimeToTerminateThread = TRUE;
// wake up the thread so it can kill itself
KeReleaseSemaphore(&Extension->RequestSemaphore, 0, 1, FALSE);
// allow thread to get past PauseEvent so it can kill self
KeSetEvent(&Extension->PauseEvent, 0, TRUE);
// wait for the thread to die
KeWaitForSingleObject(Extension->ThreadObjectPointer, UserRequest, KernelMode, FALSE, NULL);
// allow the system to release the thread object
ObDereferenceObject(Extension->ThreadObjectPointer);
// note that we no longer have a worker thread
Extension->ThreadObjectPointer = NULL;
}
// release our hold on ParPort, possibly allowing ParPort to be paged
ParReleasePortInfoToPortDevice(Extension);
ParCompleteRequest(Irp, IO_NO_INCREMENT);
// RMT - is underflow possible?
{
ULONG openCloseRefCount;
ExAcquireFastMutex(&Extension->OpenCloseMutex);
openCloseRefCount = InterlockedDecrement(&Extension->OpenCloseRefCount);
ASSERT(0 == openCloseRefCount);
if(openCloseRefCount != 0) {
// if we underflowed, increment and check again
openCloseRefCount = InterlockedIncrement(&Extension->OpenCloseRefCount);
ASSERT(0 == openCloseRefCount);
}
ExReleaseFastMutex(&Extension->OpenCloseMutex);
}
// Unlock the code that was locked during the open.
ParReleaseDriver();
return STATUS_SUCCESS;
}