📄 ioctl.c
字号:
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: ioctl.c
//
//--------------------------------------------------------------------------
#include "pch.h"
VOID
PptCleanRemovalRelationsList(PDEVICE_EXTENSION Extension)
//
// Clean up any remaining list pool allocations.
//
// Called from IRP_MN_REMOVE handler
//
{
PLIST_ENTRY listHead = &Extension->RemovalRelationsList;
PLIST_ENTRY thisListEntry = NULL;
PREMOVAL_RELATIONS_LIST_ENTRY node = NULL;
ExAcquireFastMutex( &Extension->ExtensionFastMutex );
while( !IsListEmpty( listHead ) ) {
thisListEntry = RemoveHeadList( listHead );
node = CONTAINING_RECORD( thisListEntry, REMOVAL_RELATIONS_LIST_ENTRY, ListEntry );
PptDump2(PARPNP1, ("ioctl::PptCleanRemovalRelationsList - deleting entry for node=%x devobj=%x %wZ\n",
node, node->DeviceObject, &node->DeviceName));
RtlFreeUnicodeString( &node->DeviceName );
ExFreePool( node );
}
ExReleaseFastMutex( &Extension->ExtensionFastMutex );
return;
}
NTSTATUS
PptAddPptRemovalRelation(PDEVICE_EXTENSION Extension, PPARPORT_REMOVAL_RELATIONS PptRemovalRelations)
{
PREMOVAL_RELATIONS_LIST_ENTRY node = ExAllocatePool(PagedPool, sizeof(REMOVAL_RELATIONS_LIST_ENTRY));
PptDump2(PARPNP1, ("ioctl::PptAddPptRemovalRelation - DeviceObject= %x %wZ\n",
PptRemovalRelations->DeviceObject, PptRemovalRelations->DeviceName));
if( !node ) {
PptDump2(PARPNP1, ("ioctl::PptAddPptRemovalRelation - can't get storage for node\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
// initialize node
node->DeviceObject = PptRemovalRelations->DeviceObject;
node->Flags = PptRemovalRelations->Flags;
RtlZeroMemory( &node->DeviceName, sizeof(UNICODE_STRING) );
node->DeviceName.Buffer = ExAllocatePool(PagedPool, PptRemovalRelations->DeviceName->MaximumLength);
if( !(node->DeviceName.Buffer) ) {
PptDump2(PARPNP1, ("ioctl::PptAddPptRemovalRelation - can't get storage for UNICODE_STRING\n"));
ExFreePool( node );
return STATUS_INSUFFICIENT_RESOURCES;
}
node->DeviceName.MaximumLength = PptRemovalRelations->DeviceName->MaximumLength;
RtlCopyUnicodeString( &node->DeviceName, PptRemovalRelations->DeviceName);
// add to list
ExAcquireFastMutex( &Extension->ExtensionFastMutex );
InsertTailList( &Extension->RemovalRelationsList, &node->ListEntry );
ExReleaseFastMutex( &Extension->ExtensionFastMutex );
return STATUS_SUCCESS;
}
NTSTATUS
PptRemovePptRemovalRelation(
IN PDEVICE_EXTENSION Extension,
IN PPARPORT_REMOVAL_RELATIONS PptRemovalRelations
)
/*++
Search the list for the element specified. If found, remove it
from the list and free pool associated with the entry.
--*/
{
PDEVICE_OBJECT callerDevObj = PptRemovalRelations->DeviceObject;
PLIST_ENTRY listHead = &Extension->RemovalRelationsList;
PDEVICE_OBJECT listDevObj = NULL;
PLIST_ENTRY thisListEntry = NULL;
PLIST_ENTRY firstListEntry = NULL;
BOOLEAN found = FALSE;
BOOLEAN done = FALSE;
PREMOVAL_RELATIONS_LIST_ENTRY node = NULL;
PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Entry - DeviceObject= %x %wZ\n",
PptRemovalRelations->DeviceObject, PptRemovalRelations->DeviceName) );
ExAcquireFastMutex( &Extension->ExtensionFastMutex );
if( IsListEmpty( listHead ) ) {
PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Empty List\n"));
ExReleaseFastMutex( &Extension->ExtensionFastMutex );
return STATUS_SUCCESS;
} else {
PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Nonempty List - begin search\n"));
ExReleaseFastMutex( &Extension->ExtensionFastMutex );
}
ExAcquireFastMutex( &Extension->ExtensionFastMutex );
while( !done ) {
thisListEntry = RemoveHeadList( listHead );
node = CONTAINING_RECORD( thisListEntry, REMOVAL_RELATIONS_LIST_ENTRY, ListEntry );
if( node->DeviceObject == callerDevObj ) {
// found it
PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Found device= %x %wZ\n",
node->DeviceObject, &node->DeviceName));
found = TRUE;
done = TRUE;
} else if( firstListEntry == thisListEntry ) {
// searched entire list and didn't find it
PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Not Found\n"));
done = TRUE;
} else if( !firstListEntry ) {
// this is first element in list - save as marker for loop termination
PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Not Found - First Entry\n"));
firstListEntry = thisListEntry;
}
if( !found ) {
// return current element to end of list
// PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - InsertTailList\n"));
InsertTailList( listHead, &node->ListEntry );
}
}
ExReleaseFastMutex( &Extension->ExtensionFastMutex );
if( found ) {
// found the matching entry - clean up allocations
// PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Found - freeing pool\n"));
RtlFreeUnicodeString( &node->DeviceName );
ExFreePool( node );
}
PptDump2(PARPNP1, ("ioctl::PptRemovePptRemovalRelation - Returning\n"));
return STATUS_SUCCESS; // always
}
VOID
PptDumpRemovalRelationsList(PDEVICE_EXTENSION Extension)
{
PLIST_ENTRY listHead = &Extension->RemovalRelationsList;
PLIST_ENTRY thisListEntry = NULL;
PLIST_ENTRY firstListEntry = NULL;
BOOLEAN done = FALSE;
PREMOVAL_RELATIONS_LIST_ENTRY node = NULL;
PptDump2(PARPNP1, ("ioctl::PptDumpRemovalRelationsList\n"));
ExAcquireFastMutex( &Extension->ExtensionFastMutex );
if( IsListEmpty( listHead ) ) {
PptDump2(PARPNP1, ("ioctl::PptDumpRemovalRelationsList - Empty List\n"));
ExReleaseFastMutex( &Extension->ExtensionFastMutex );
return;
} else {
PptDump2(PARPNP1, ("ioctl::PptDumpRemovalRelationsList - Nonempty List - begin scan/dump\n"));
}
while( !done ) {
thisListEntry = RemoveHeadList( listHead );
node = CONTAINING_RECORD( thisListEntry, REMOVAL_RELATIONS_LIST_ENTRY, ListEntry );
if( firstListEntry == thisListEntry ) {
// done - push back onto front of list
InsertHeadList( listHead, &node->ListEntry );
done = TRUE;
PptDump2(PARPNP1, ("ioctl::PptDumpRemovalRelationsList - Done\n"));
} else {
// dump node info
PptDump2(PARPNP1, ("ioctl::PptDumpRemovalRelationsList - entry= %x %wZ\n", node->DeviceObject, &node->DeviceName));
InsertTailList( listHead, &node->ListEntry );
}
if( !firstListEntry ) {
// save first element - use for loop termination
firstListEntry = thisListEntry;
}
}
ExReleaseFastMutex( &Extension->ExtensionFastMutex );
return;
}
VOID
PptDumpPptRemovalRelationsStruct(PPARPORT_REMOVAL_RELATIONS PptRemovalRelations)
{
#if DBG
ASSERT( PptRemovalRelations );
ASSERT( PptRemovalRelations->DeviceName );
PptDump2(PARPNP1, ("ioctl::PptDumpPptRemovalRelationsStruct - DevObj = %x\n", PptRemovalRelations->DeviceObject));
PptDump2(PARPNP1, ("ioctl::PptDumpPptRemovalRelationsStruct - DevName = %wZ\n", PptRemovalRelations->DeviceName));
#else
UNREFERENCED_PARAMETER( PptRemovalRelations );
#endif
return;
}
NTSTATUS
PptDispatchInternalDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine is the dispatch routine for IRP_MJ_INTERNAL_DEVICE_CONTROL.
Arguments:
DeviceObject - Supplies the device object.
Irp - Supplies the I/O request packet.
Return Value:
STATUS_SUCCESS - Success.
STATUS_UNSUCCESSFUL - The request was unsuccessful.
STATUS_PENDING - The request is pending.
STATUS_INVALID_PARAMETER - Invalid parameter.
STATUS_CANCELLED - The request was cancelled.
STATUS_BUFFER_TOO_SMALL - The supplied buffer is too small.
STATUS_INVALID_DEVICE_STATE - The current chip mode is invalid to change to asked mode
--*/
{
PIO_STACK_LOCATION IrpSp;
PDEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
NTSTATUS Status;
PPARALLEL_PORT_INFORMATION PortInfo;
PPARALLEL_PNP_INFORMATION PnpInfo;
PMORE_PARALLEL_PORT_INFORMATION MorePortInfo;
KIRQL CancelIrql;
SYNCHRONIZED_COUNT_CONTEXT SyncContext;
PPARALLEL_INTERRUPT_SERVICE_ROUTINE IsrInfo;
PPARALLEL_INTERRUPT_INFORMATION InterruptInfo;
PISR_LIST_ENTRY IsrListEntry;
SYNCHRONIZED_LIST_CONTEXT ListContext;
SYNCHRONIZED_DISCONNECT_CONTEXT DisconnectContext;
BOOLEAN DisconnectInterrupt;
PptDump2(PARENTRY, ("ioctl::PptDispatchInternalDeviceControl - Irp= %x , UserEvent= %x\n", Irp, Irp->UserEvent));
if(Irp->UserEvent) {
ASSERT_EVENT(Irp->UserEvent);
}
//
// Verify that our device has not been SUPRISE_REMOVED. Generally
// only parallel ports on hot-plug busses (e.g., PCMCIA) and
// parallel ports in docking stations will be surprise removed.
//
// dvdf - RMT - It would probably be a good idea to also check
// here if we are in a "paused" state (stop-pending, stopped, or
// remove-pending) and queue the request until we either return to
// a fully functional state or are removed.
//
if( Extension->DeviceStateFlags & PPT_DEVICE_SURPRISE_REMOVED ) {
PptDumpV( ("IRP_MJ_CREATE - FAIL - %S, DEVICE_SURPRISE_REMOVED\n", Extension->PnpInfo.PortName) );
return PptFailRequest( Irp, STATUS_DELETE_PENDING );
}
//
// Try to acquire RemoveLock to prevent the device object from going
// away while we're using it.
//
Status = PptAcquireRemoveLockOrFailIrp( DeviceObject, Irp );
if ( !NT_SUCCESS(Status) ) {
PptDumpV( ("IRP_MJ_CREATE - FAIL - unable to acquire RemoveLock\n") );
return Status;
}
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Irp->IoStatus.Information = 0;
switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_INTERNAL_REGISTER_FOR_REMOVAL_RELATIONS:
PptDump2(PARPNP1, ("ioctl:: - RegisterForRemovalRelations - Enter\n") );
if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(PARPORT_REMOVAL_RELATIONS) ) {
PptDump2(PARPNP1, ("ioctl:: - RegisterForRemovalRelations - BUFFER_TOO_SMALL\n") );
Status = STATUS_BUFFER_TOO_SMALL;
} else {
PPARPORT_REMOVAL_RELATIONS removalRelations = Irp->AssociatedIrp.SystemBuffer;
PptDumpPptRemovalRelationsStruct( removalRelations );
PptDumpRemovalRelationsList(Extension);
PptAddPptRemovalRelation(Extension, removalRelations);
PptDumpRemovalRelationsList(Extension);
PptDump2(PARPNP1, ("ioctl:: - RegisterForRemovalRelations - SUCCESS\n") );
Status = STATUS_SUCCESS;
}
Irp->IoStatus.Status = Status;
PptReleaseRemoveLock(&Extension->RemoveLock, Irp);
PptCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
case IOCTL_INTERNAL_UNREGISTER_FOR_REMOVAL_RELATIONS:
PptDump2(PARPNP1, ("ioctl:: - UnregisterForRemovalRelations - Enter\n") );
if( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(PARPORT_REMOVAL_RELATIONS) ) {
PptDump2(PARPNP1, ("ioctl:: - RegisterForRemovalRelations - BUFFER_TOO_SMALL\n") );
Status = STATUS_BUFFER_TOO_SMALL;
} else {
PPARPORT_REMOVAL_RELATIONS removalRelations = Irp->AssociatedIrp.SystemBuffer;
PptDumpPptRemovalRelationsStruct(Irp->AssociatedIrp.SystemBuffer);
PptDumpRemovalRelationsList(Extension);
PptRemovePptRemovalRelation(Extension, removalRelations);
PptDumpRemovalRelationsList(Extension);
PptDump2(PARPNP1, ("ioctl:: - RegisterForRemovalRelations - SUCCESS\n") );
Status = STATUS_SUCCESS;
}
Irp->IoStatus.Status = Status;
PptReleaseRemoveLock(&Extension->RemoveLock, Irp);
PptCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
case IOCTL_INTERNAL_PARALLEL_PORT_FREE:
PptFreePort(Extension);
Irp->IoStatus.Status = STATUS_SUCCESS;
PptReleaseRemoveLock(&Extension->RemoveLock, Irp);
PptCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
case IOCTL_INTERNAL_PARALLEL_PORT_ALLOCATE:
IoAcquireCancelSpinLock(&CancelIrql);
if (Irp->Cancel) {
Status = STATUS_CANCELLED;
} else {
SyncContext.Count = &Extension->WorkQueueCount;
if (Extension->InterruptRefCount) {
KeSynchronizeExecution(Extension->InterruptObject,
PptSynchronizedIncrement,
&SyncContext);
} else {
PptSynchronizedIncrement(&SyncContext);
}
if (SyncContext.NewCount) {
// someone else currently has the port, queue request
PptSetCancelRoutine(Irp, PptCancelRoutine);
IoMarkIrpPending(Irp);
InsertTailList(&Extension->WorkQueue,
&Irp->Tail.Overlay.ListEntry);
Status = STATUS_PENDING;
} else {
// port aquired
Extension->WmiPortAllocFreeCounts.PortAllocates++;
Status = STATUS_SUCCESS;
}
}
IoReleaseCancelSpinLock(CancelIrql);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -