|
|
//+-------------------------------------------------------------------------
//
// 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; }
|