📄 umsspnp.c
字号:
/*++
Routine Description:
Dispatch table routine for IRP_MJ_PNP.
Process the Plug and Play IRPs sent to our PDO.
Arguments:
DeviceObject - pointer to our child PDO
Irp - pointer to an I/O Request Packet
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpStack;
PDEVICE_EXTENSION deviceExtension;
NTSTATUS ntStatus = STATUS_SUCCESS;
PDEVICE_OBJECT stackDeviceObject;
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
ENTER(UMSS_PdoProcessPnPIrp);
irpStack = IoGetCurrentIrpStackLocation (Irp);
//
// Get a pointer to the device extension
//
deviceExtension = DeviceObject->DeviceExtension;
stackDeviceObject = deviceExtension->TopOfStackDeviceObject;
UMSS_KdPrint( DBGLVL_MEDIUM, ( "enter UMSS_ProcessPnPIrp() IRP_MJ_PNP, minor %s\n",
UMSS_StringForPnpMnFunc( irpStack->MinorFunction ) ));
// inc the FDO device extension's pending IO count for this Irp
//UMSS_IncrementIoCount(DeviceObject);
UMSS_ASSERT( IRP_MJ_PNP == irpStack->MajorFunction );
switch (irpStack->MinorFunction)
{
case IRP_MN_QUERY_DEVICE_RELATIONS:
ntStatus = UMSS_PdoDeviceQuery(DeviceObject, Irp);
break;
case IRP_MN_QUERY_ID:
ntStatus = UMSS_PdoQueryID(DeviceObject, Irp);
break;
case IRP_MN_REMOVE_DEVICE:
IoDeleteDevice(DeviceObject);
break;
case IRP_MN_QUERY_BUS_INFORMATION:
ntStatus = UMSS_QueryBusInfo(DeviceObject, Irp);
break;
}
RETURN(ntStatus, UMSS_PdoProcessPnPIrp);
}
NTSTATUS
UMSS_QueryBusInfo(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Handler for IRP_MN_QUERY_BUS_INFO. Returns info about our virtual bus.
Arguments:
DeviceObject - pointer to our child PDO
Irp - pointer to an I/O Request Packet
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus;
PIO_STACK_LOCATION irpStack;
PPNP_BUS_INFORMATION BusInfo;
ENTER(UMSS_QueryBusInfo);
irpStack = IoGetCurrentIrpStackLocation(Irp);
BusInfo = ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
// If we can't allocate BusInfo structure, bail
if (!BusInfo)
{
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
BusInfo->BusTypeGuid = GUID_BUS_UMSS;
BusInfo->LegacyBusType = PNPBus;
BusInfo->BusNumber = 0;
Irp->IoStatus.Information = (ULONG)BusInfo;
ntStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
}
RETURN(ntStatus, UMSS_QueryBusInfo);
}
NTSTATUS
UMSS_PdoDeviceQuery(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Handler for IRP_MN_QUERY_DEVICE_RELATIONS for our virtual child device.
Arguments:
DeviceObject - pointer to our child PDO
Irp - pointer to an I/O Request Packet
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus;
PIO_STACK_LOCATION irpStack;
PDEVICE_RELATIONS DeviceRelations;
PDEVICE_EXTENSION DeviceExtension;
ENTER(UMSS_PdoDeviceQuery);
irpStack = IoGetCurrentIrpStackLocation(Irp);
DeviceExtension = DeviceObject->DeviceExtension;
switch (irpStack->Parameters.QueryDeviceRelations.Type)
{
case TargetDeviceRelation:
// Allocate space for 1 child device
DeviceRelations = UMSS_ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
// If we can't allocate DeviceRelations structure, bail
if (!DeviceRelations)
{
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
}
else
{
ObReferenceObject(DeviceObject);
DeviceRelations->Count = 1;
DeviceRelations->Objects[0] = DeviceObject;
Irp->IoStatus.Information = (ULONG)DeviceRelations;
ntStatus = Irp->IoStatus.Status = STATUS_SUCCESS;
}
break;
default:
ntStatus = Irp->IoStatus.Status;
}
RETURN(ntStatus, UMSS_PdoDeviceQuery);
}
NTSTATUS
UMSS_PdoQueryID(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
/*++
Routine Description:
Handler for IRP_MN_QUERY_ID. Returns hardware, device, and instance
IDs for our virtual child PDO.
Arguments:
DeviceObject - pointer to our child PDO
Irp - pointer to an I/O Request Packet
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION ioStack;
PWCHAR buffer;
WCHAR IDString[] = CHILD_DEVICE_ID;
WCHAR InstanceIDString[] = L"0000";
ULONG length;
ENTER(UMSS_PdoQueryID);
ioStack = IoGetCurrentIrpStackLocation(Irp);
switch (ioStack->Parameters.QueryId.IdType)
{
case BusQueryHardwareIDs:
// return a multi WCHAR (null terminated) string (null terminated)
// array for use in matching hardare ids in inf files;
case BusQueryDeviceID:
// return a WCHAR (null terminated) string describing the device
// For symplicity we make it exactly the same as the Hardware ID.
length = sizeof (IDString) * sizeof(WCHAR);
buffer = ExAllocatePool (PagedPool, length);
if (buffer)
{
RtlCopyMemory (buffer, IDString, length);
}
Irp->IoStatus.Information = (ULONG) buffer;
break;
case BusQueryInstanceID:
length = sizeof (InstanceIDString) * sizeof(WCHAR);
buffer = ExAllocatePool (PagedPool, length);
if (buffer)
{
RtlCopyMemory (buffer, InstanceIDString, length);
}
Irp->IoStatus.Information = (ULONG) buffer;
break;
}
RETURN(STATUS_SUCCESS, UMSS_PdoQueryID);
}
NTSTATUS
UMSS_AbortPipes(
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Called as part of sudden device removal handling.
Cancels any pending transfers for all open pipes.
If any pipes are still open, call USBD with URB_FUNCTION_ABORT_PIPE
Also marks the pipe 'closed' in our saved configuration info.
Arguments:
Ptrs to our FDO
Return Value:
NT status code
--*/
{
NTSTATUS ntStatus = STATUS_SUCCESS;
PURB urb;
PDEVICE_EXTENSION deviceExtension;
ULONG i;
PUSBD_INTERFACE_INFORMATION interface;
PUSBD_PIPE_INFORMATION PipeInfo;
ENTER(UMSS_AbortPipes);
deviceExtension = DeviceObject->DeviceExtension;
interface = deviceExtension->UsbInterface;
for (i=0; i<interface->NumberOfPipes; i++)
{
PipeInfo = &interface->Pipes[i]; // PUSBD_PIPE_INFORMATION PipeInfo;
if ( PipeInfo->PipeFlags )
{
UMSS_KdPrint( DBGLVL_HIGH,("UMSS_AbortPipes() Aborting open Pipe %d\n", i));
urb = UMSS_ExAllocatePool(NonPagedPool, sizeof(struct _URB_PIPE_REQUEST));
if (urb)
{
urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST);
urb->UrbHeader.Function = URB_FUNCTION_ABORT_PIPE;
urb->UrbPipeRequest.PipeHandle = PipeInfo->PipeHandle;
ntStatus = UMSS_CallUSBD(DeviceObject, urb);
UMSS_ExFreePool(urb);
}
else
{
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
UMSS_KdPrint( DBGLVL_HIGH,("UMSS_AbortPipes() FAILED urb alloc\n" ));
break;
}
if (!(NT_SUCCESS(ntStatus)))
{
// if we failed, dump out
#if DBG
if ( gpDbg )
gpDbg->PipeErrorCount++;
#endif
break;
}
else
{
PipeInfo->PipeFlags = FALSE; // mark the pipe 'closed'
deviceExtension->OpenPipeCount--;
#if DBG
if ( gpDbg )
gpDbg->AbortPipeCount++;
#endif
}
} // end, if pipe open
} // end, for all pipes
RETURN(ntStatus, UMSS_AbortPipes);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -