mirror of https://github.com/tongzx/nt5src
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.
338 lines
8.8 KiB
338 lines
8.8 KiB
//+-------------------------------------------------------------------------
|
|
//
|
|
// 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;
|
|
}
|