📄 util.c
字号:
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1998 - 1999
//
// File: util.c
//
//--------------------------------------------------------------------------
#include "pch.h"
// PptSucceedRequestNullInfo(Irp) - IoStatus.Status=STATUS_SUCCESS, IoStatus.Information=NULL
// PptSucceedRequest(Irp) - IoStatus.Status=STATUS_SUCCESS, IoStatus.Information unmodified
// PptSucceedRequestBoostPriority(Irp, Increment) - IoStatus.Status=STATUS_SUCCESS, IoStatus.Information=NULL
// PptFailRequest(Irp, status) - IoStatus.Status=STATUS_SUCCESS, IoStatus.Information=NULL
NTSTATUS
PptFailRequest(PIRP Irp, NTSTATUS Status) {
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
PptCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
NTSTATUS
PptAcquireRemoveLockOrFailIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PDEVICE_EXTENSION extension = DeviceObject->DeviceExtension;
PIO_REMOVE_LOCK removeLock = &extension->RemoveLock;
NTSTATUS status = IoAcquireRemoveLock(removeLock, Irp);
if( !NT_SUCCESS(status) ) {
PptFailRequest(Irp, status);
}
return status;
}
NTSTATUS
PptDispatchPreProcessIrp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
- Acquire removelock
- If(!Special Handling IRP) {
check if we are running, stalled
--*/
{
PDEVICE_EXTENSION Extension = DeviceObject->DeviceExtension;
NTSTATUS status = PptAcquireRemoveLock(&Extension->RemoveLock, Irp);
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
if ( !NT_SUCCESS( status ) ) {
//
// Someone gave us a pnp irp after a remove. Unthinkable!
//
ASSERT(FALSE);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = status;
PptCompleteRequest(Irp, IO_NO_INCREMENT);
}
return status;
}
NTSTATUS
PptDispatchPostProcessIrp() { return STATUS_SUCCESS; }
NTSTATUS
PptSynchCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PKEVENT Event
)
/*++
Routine Description:
This routine is for use with synchronous IRP processing.
All it does is signal an event, so the driver knows it
can continue.
Arguments:
DriverObject - Pointer to driver object created by system.
Irp - Irp that just completed
Event - Event we'll signal to say Irp is done
Return Value:
None.
--*/
{
UNREFERENCED_PARAMETER( Irp );
UNREFERENCED_PARAMETER( DeviceObject );
KeSetEvent((PKEVENT) Event, 0, FALSE);
return (STATUS_MORE_PROCESSING_REQUIRED);
}
PWSTR
PptGetPortNameFromPhysicalDeviceObject(
PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
Retrieve the PortName for the ParPort from the registry. This PortName
will be used as the symbolic link name for the end of chain device
object created by ParClass for this ParPort.
*** This function allocates pool. ExFreePool must be called when
result is no longer needed.
Arguments:
PortDeviceObject - The ParPort Device Object
Return Value:
PortName - if successful
NULL - otherwise
--*/
{
NTSTATUS status;
HANDLE hKey;
PKEY_VALUE_FULL_INFORMATION buffer;
ULONG bufferLength;
ULONG resultLength;
PWSTR valueNameWstr;
UNICODE_STRING valueName;
PWSTR portName;
PAGED_CODE ();
//
// try to open the registry key
//
PptDumpV( ("PptGetPortNameFromPhysicalDeviceObject()\n") );
status = IoOpenDeviceRegistryKey(PhysicalDeviceObject,
PLUGPLAY_REGKEY_DEVICE,
STANDARD_RIGHTS_ALL,
&hKey);
if( !NT_SUCCESS(status) ) {
// unable to open key, bail out
PptDumpV( ("PptGetPortNameFromPhysicalDeviceObject(): "
"registry key open failed, status = %x\n", status) );
return NULL;
}
//
// we have a handle to the registry key
//
// loop trying to read registry value until either we succeed or
// we get a hard failure, grow the result buffer as needed
//
bufferLength = 0; // we will ask how large a buffer we need
buffer = NULL;
valueNameWstr = (PWSTR)L"PortName";
RtlInitUnicodeString(&valueName, valueNameWstr);
status = STATUS_BUFFER_TOO_SMALL;
while(status == STATUS_BUFFER_TOO_SMALL) {
status = ZwQueryValueKey(hKey,
&valueName,
KeyValueFullInformation,
buffer,
bufferLength,
&resultLength);
if(status == STATUS_BUFFER_TOO_SMALL) {
//
// buffer too small, free it and allocate a larger buffer
//
if(buffer) ExFreePool(buffer);
buffer = ExAllocatePool(PagedPool, resultLength);
bufferLength = resultLength;
if(!buffer) {
// unable to allocate pool, clean up and exit
PptDumpV( (" - unable to allocate pool to for PortName query\n") );
ZwClose(hKey);
return NULL;
}
}
} // end while BUFFER_TOO_SMALL
//
// query is complete
//
// no longer need the handle so close it
ZwClose(hKey);
// check the status of our query
if( !NT_SUCCESS(status) ) {
if(buffer) ExFreePool(buffer);
PptDumpV( (" - query for PortName FAILED - status = %x\n",
status) );
return NULL;
}
// sanity check our result
if( (buffer->Type != REG_SZ) || (!buffer->DataLength) ) {
PptDumpV( (" - either bogus PortName data type or zero length\n",
status) );
ExFreePool(buffer); // query succeeded, so we know we have a buffer
return NULL;
}
//
// result looks ok, copy PortName to its own allocation of the proper size
// and return a pointer to it
//
portName = ExAllocatePool(PagedPool, buffer->DataLength);
if(!portName) {
// unable to allocate pool, clean up and exit
PptDumpV( (" - unable to allocate pool to hold PortName(SymbolicLinkName)\n") );
ExFreePool(buffer);
return NULL;
}
RtlCopyMemory(portName,
(PUCHAR)buffer + buffer->DataOffset,
buffer->DataLength);
ExFreePool(buffer);
return portName;
}
NTSTATUS
PptConnectInterrupt(
IN PDEVICE_EXTENSION Extension
)
/*++
Routine Description:
This routine connects the port interrupt service routine
to the interrupt.
Arguments:
Extension - Supplies the device extension.
Return Value:
NTSTATUS code.
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
if (!Extension->FoundInterrupt) {
return STATUS_NOT_SUPPORTED;
}
//
// Connect the interrupt.
//
Status = IoConnectInterrupt(&Extension->InterruptObject,
PptInterruptService,
Extension,
NULL,
Extension->InterruptVector,
Extension->InterruptLevel,
Extension->InterruptLevel,
Extension->InterruptMode,
TRUE,
Extension->InterruptAffinity,
FALSE);
if (!NT_SUCCESS(Status)) {
PptLogError(Extension->DeviceObject->DriverObject,
Extension->DeviceObject,
Extension->PortInfo.OriginalController,
PhysicalZero, 0, 0, 0, 14,
Status, PAR_INTERRUPT_CONFLICT);
PptDump2(PARERRORS, ("Could not connect to interrupt for %x\n",
Extension->PortInfo.OriginalController.LowPart) );
}
return Status;
}
VOID
PptDisconnectInterrupt(
IN PDEVICE_EXTENSION Extension
)
/*++
Routine Description:
This routine disconnects the port interrupt service routine
from the interrupt.
Arguments:
Extension - Supplies the device extension.
Return Value:
None.
--*/
{
IoDisconnectInterrupt(Extension->InterruptObject);
}
BOOLEAN
PptSynchronizedIncrement(
IN OUT PVOID SyncContext
)
/*++
Routine Description:
This routine increments the 'Count' variable in the context and returns
its new value in the 'NewCount' variable.
Arguments:
SyncContext - Supplies the synchronize count context.
Return Value:
TRUE
--*/
{
((PSYNCHRONIZED_COUNT_CONTEXT) SyncContext)->NewCount =
++(*(((PSYNCHRONIZED_COUNT_CONTEXT) SyncContext)->Count));
return(TRUE);
}
BOOLEAN
PptSynchronizedDecrement(
IN OUT PVOID SyncContext
)
/*++
Routine Description:
This routine decrements the 'Count' variable in the context and returns
its new value in the 'NewCount' variable.
Arguments:
SyncContext - Supplies the synchronize count context.
Return Value:
TRUE
--*/
{
((PSYNCHRONIZED_COUNT_CONTEXT) SyncContext)->NewCount =
--(*(((PSYNCHRONIZED_COUNT_CONTEXT) SyncContext)->Count));
return(TRUE);
}
BOOLEAN
PptSynchronizedRead(
IN OUT PVOID SyncContext
)
/*++
Routine Description:
This routine reads the 'Count' variable in the context and returns
its value in the 'NewCount' variable.
Arguments:
SyncContext - Supplies the synchronize count context.
Return Value:
None.
--*/
{
((PSYNCHRONIZED_COUNT_CONTEXT) SyncContext)->NewCount =
*(((PSYNCHRONIZED_COUNT_CONTEXT) SyncContext)->Count);
return(TRUE);
}
BOOLEAN
PptSynchronizedQueue(
IN PVOID Context
)
/*++
Routine Description:
This routine adds the given list entry to the given list.
Arguments:
Context - Supplies the synchronized list context.
Return Value:
TRUE
--*/
{
PSYNCHRONIZED_LIST_CONTEXT ListContext;
ListContext = Context;
InsertTailList(ListContext->List, ListContext->NewEntry);
return(TRUE);
}
BOOLEAN
PptSynchronizedDisconnect(
IN PVOID Context
)
/*++
Routine Description:
This routine removes the given list entry from the ISR
list.
Arguments:
Context - Supplies the synchronized disconnect context.
Return Value:
FALSE - The given list entry was not removed from the list.
TRUE - The given list entry was removed from the list.
--*/
{
PSYNCHRONIZED_DISCONNECT_CONTEXT DisconnectContext;
PKSERVICE_ROUTINE ServiceRoutine;
PVOID ServiceContext;
PLIST_ENTRY Current;
PISR_LIST_ENTRY ListEntry;
DisconnectContext = Context;
ServiceRoutine = DisconnectContext->IsrInfo->InterruptServiceRoutine;
ServiceContext = DisconnectContext->IsrInfo->InterruptServiceContext;
for (Current = DisconnectContext->Extension->IsrList.Flink;
Current != &(DisconnectContext->Extension->IsrList);
Current = Current->Flink) {
ListEntry = CONTAINING_RECORD(Current, ISR_LIST_ENTRY, ListEntry);
if (ListEntry->ServiceRoutine == ServiceRoutine &&
ListEntry->ServiceContext == ServiceContext) {
RemoveEntryList(Current);
return TRUE;
}
}
return FALSE;
}
VOID
PptCancelRoutine(
IN OUT PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -