📄 buspdo.c
字号:
Arguments:
DeviceData - Pointer to the PDO's device extension.
Irp - Pointer to the irp.
Return Value:
NT STATUS
--*/
{
PIO_RESOURCE_REQUIREMENTS_LIST resourceList;
PIO_RESOURCE_DESCRIPTOR descriptor;
ULONG resourceListSize;
NTSTATUS status;
PAGED_CODE ();
//
// Note the IO_RESOURCE_REQUIREMENTS_LIST structure includes
// IO_RESOURCE_LIST List[1]; if we specify more than one
// resource, we must include IO_RESOURCE_LIST size
// in the resourceListSize calculation.
//
resourceListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
resourceList = ExAllocatePoolWithTag (
PagedPool,
resourceListSize,
VUSB_POOL_TAG);
if (resourceList == NULL ) {
status = STATUS_INSUFFICIENT_RESOURCES;
return status;
}
RtlZeroMemory( resourceList, resourceListSize );
resourceList->ListSize = resourceListSize;
//
// Initialize the list header.
//
resourceList->AlternativeLists = 1;
resourceList->InterfaceType = InterfaceTypeUndefined;
resourceList->BusNumber = 0;
resourceList->List[0].Version = 1;
resourceList->List[0].Revision = 1;
resourceList->List[0].Count = 1;
descriptor = resourceList->List[0].Descriptors;
//
// Fill in the information about the ports your device
// can use.
//
descriptor->Type = CmResourceTypePort;
descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
descriptor->Flags = CM_RESOURCE_PORT_IO|CM_RESOURCE_PORT_16_BIT_DECODE;
descriptor->u.Port.Length = 1;
descriptor->u.Port.Alignment = 0x01;
descriptor->u.Port.MinimumAddress.QuadPart = 0;
descriptor->u.Port.MaximumAddress.QuadPart = 0xFFFF;
Irp->IoStatus.Information = (ULONG_PTR)resourceList;
status = STATUS_SUCCESS;
return status;
}
NTSTATUS
Bus_PDO_QueryDeviceRelations(
IN PPDO_DEVICE_DATA DeviceData,
IN PIRP Irp )
/*++
Routine Description:
The PnP Manager sends this IRP to gather information about
devices with a relationship to the specified device.
Bus drivers must handle this request for TargetDeviceRelation
for their child devices (child PDOs).
If a driver returns relations in response to this IRP,
it allocates a DEVICE_RELATIONS structure from paged
memory containing a count and the appropriate number of
device object pointers. The PnP Manager frees the structure
when it is no longer needed. If a driver replaces a
DEVICE_RELATIONS structure allocated by another driver,
it must free the previous structure.
A driver must reference the PDO of any device that it
reports in this IRP (ObReferenceObject). The PnP Manager
removes the reference when appropriate.
Arguments:
DeviceData - Pointer to the PDO's device extension.
Irp - Pointer to the irp.
Return Value:
NT STATUS
--*/
{
PIO_STACK_LOCATION stack;
PDEVICE_RELATIONS deviceRelations;
NTSTATUS status;
PAGED_CODE ();
stack = IoGetCurrentIrpStackLocation (Irp);
switch (stack->Parameters.QueryDeviceRelations.Type) {
case TargetDeviceRelation:
deviceRelations = (PDEVICE_RELATIONS) Irp->IoStatus.Information;
if (deviceRelations) {
//
// Only PDO can handle this request. Somebody above
// is not playing by rule.
//
ASSERTMSG("Someone above is handling TagerDeviceRelation", !deviceRelations);
}
deviceRelations = (PDEVICE_RELATIONS)
ExAllocatePoolWithTag (PagedPool,
sizeof(DEVICE_RELATIONS),
VUSB_POOL_TAG);
if (!deviceRelations) {
status = STATUS_INSUFFICIENT_RESOURCES;
break;
}
//
// There is only one PDO pointer in the structure
// for this relation type. The PnP Manager removes
// the reference to the PDO when the driver or application
// un-registers for notification on the device.
//
deviceRelations->Count = 1;
deviceRelations->Objects[0] = DeviceData->Self;
ObReferenceObject(DeviceData->Self);
status = STATUS_SUCCESS;
Irp->IoStatus.Information = (ULONG_PTR) deviceRelations;
break;
case BusRelations: // Not handled by PDO
case EjectionRelations: // optional for PDO
case RemovalRelations: // // optional for PDO
default:
status = Irp->IoStatus.Status;
}
return status;
}
NTSTATUS
Bus_PDO_QueryBusInformation(
IN PPDO_DEVICE_DATA DeviceData,
IN PIRP Irp )
/*++
Routine Description:
The PnP Manager uses this IRP to request the type and
instance number of a device's parent bus. Bus drivers
should handle this request for their child devices (PDOs).
Arguments:
DeviceData - Pointer to the PDO's device extension.
Irp - Pointer to the irp.
Return Value:
NT STATUS
--*/
{
PPNP_BUS_INFORMATION busInfo;
PAGED_CODE ();
busInfo = ExAllocatePoolWithTag (PagedPool, sizeof(PNP_BUS_INFORMATION),
VUSB_POOL_TAG);
if (busInfo == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
busInfo->BusTypeGuid = GUID_VUSB_BUS_TYPE;
//
// Some buses have a specific INTERFACE_TYPE value,
// such as PCMCIABus, PCIBus, or PNPISABus.
// For other buses, especially newer buses like VUSB, the bus
// driver sets this member to PNPBus.
//
busInfo->LegacyBusType = PNPBus;
//
// This is an hypothetical bus
//
busInfo->BusNumber = 0;
Irp->IoStatus.Information = (ULONG_PTR)busInfo;
return STATUS_SUCCESS;
}
NTSTATUS
Bus_PDO_QueryInterface(
IN PPDO_DEVICE_DATA DeviceData,
IN PIRP Irp )
/*++
Routine Description:
This requests enables a driver to export proprietary interface
to other drivers. This function and the following 5 routines
are meant to show how a typical interface is exported.
Note: This and many other routines in this sample are not required if
someone is using this sample for just device enumeration purpose.
Arguments:
DeviceData - Pointer to the PDO's device extension.
Irp - Pointer to the irp.
Return Value:
NT STATUS
--*/
{
PIO_STACK_LOCATION irpStack;
PVUSB_INTERFACE_STANDARD vusbInterfaceStandard;
GUID *interfaceType;
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE();
irpStack = IoGetCurrentIrpStackLocation(Irp);
interfaceType = (GUID *) irpStack->Parameters.QueryInterface.InterfaceType;
if (IsEqualGUID(interfaceType, (PVOID) &GUID_VUSB_INTERFACE_STANDARD)) {
if (irpStack->Parameters.QueryInterface.Size <
sizeof(VUSB_INTERFACE_STANDARD)
&& irpStack->Parameters.QueryInterface.Version != 1) {
return STATUS_INVALID_PARAMETER;
}
vusbInterfaceStandard = (PVUSB_INTERFACE_STANDARD)
irpStack->Parameters.QueryInterface.Interface;
vusbInterfaceStandard->Context = DeviceData;
//
// Fill in the exported functions
//
vusbInterfaceStandard->InterfaceReference =
(PINTERFACE_REFERENCE) Bus_InterfaceReference;
vusbInterfaceStandard->InterfaceDereference =
(PINTERFACE_DEREFERENCE) Bus_InterfaceDereference;
//
// Must take a reference before returning
//
Bus_InterfaceReference(DeviceData);
} else {
//
// Interface type not supported
//
status = Irp->IoStatus.Status;
}
return status;
}
VOID
Bus_InterfaceReference (
IN PVOID Context
)
/*++
Routine Description:
This routine increments the refcount. We check this refcount
during query_remove decide whether to allow the remove or not.
Arguments:
Context pointer to PDO device extension
Return Value:
--*/
{
InterlockedIncrement(&((PPDO_DEVICE_DATA)Context)->VUsbInterfaceRefCount);
}
VOID
Bus_InterfaceDereference (
IN PVOID Context
)
/*++
Routine Description:
This routine decrements the refcount. We check this refcount
during query_remove decide whether to allow the remove or not.
Arguments:
Context pointer to PDO device extension
Return Value:
--*/
{
InterlockedDecrement(&((PPDO_DEVICE_DATA)Context)->VUsbInterfaceRefCount);
}
NTSTATUS
Bus_GetDeviceCapabilities(
IN PDEVICE_OBJECT DeviceObject,
IN PDEVICE_CAPABILITIES DeviceCapabilities
)
/*++
Routine Description:
This routine sends the get capabilities irp to the given stack
Arguments:
DeviceObject A device object in the stack whose capabilities we want
DeviceCapabilites Where to store the answer
Return Value:
NTSTATUS
--*/
{
IO_STATUS_BLOCK ioStatus;
KEVENT pnpEvent;
NTSTATUS status;
PDEVICE_OBJECT targetObject;
PIO_STACK_LOCATION irpStack;
PIRP pnpIrp;
PAGED_CODE();
//
// Initialize the capabilities that we will send down
//
RtlZeroMemory( DeviceCapabilities, sizeof(DEVICE_CAPABILITIES) );
DeviceCapabilities->Size = sizeof(DEVICE_CAPABILITIES);
DeviceCapabilities->Version = 1;
DeviceCapabilities->Address = -1;
DeviceCapabilities->UINumber = -1;
//
// Initialize the event
//
KeInitializeEvent( &pnpEvent, NotificationEvent, FALSE );
targetObject = IoGetAttachedDeviceReference( DeviceObject );
//
// Build an Irp
//
pnpIrp = IoBuildSynchronousFsdRequest(
IRP_MJ_PNP,
targetObject,
NULL,
0,
NULL,
&pnpEvent,
&ioStatus
);
if (pnpIrp == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
goto GetDeviceCapabilitiesExit;
}
//
// Pnp Irps all begin life as STATUS_NOT_SUPPORTED;
//
pnpIrp->IoStatus.Status = STATUS_NOT_SUPPORTED;
//
// Get the top of stack
//
irpStack = IoGetNextIrpStackLocation( pnpIrp );
//
// Set the top of stack
//
RtlZeroMemory( irpStack, sizeof(IO_STACK_LOCATION ) );
irpStack->MajorFunction = IRP_MJ_PNP;
irpStack->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
irpStack->Parameters.DeviceCapabilities.Capabilities = DeviceCapabilities;
//
// Call the driver
//
status = IoCallDriver( targetObject, pnpIrp );
if (status == STATUS_PENDING) {
//
// Block until the irp comes back.
// Important thing to note here is when you allocate
// the memory for an event in the stack you must do a
// KernelMode wait instead of UserMode to prevent
// the stack from getting paged out.
//
KeWaitForSingleObject(
&pnpEvent,
Executive,
KernelMode,
FALSE,
NULL
);
status = ioStatus.Status;
}
GetDeviceCapabilitiesExit:
//
// Done with reference
//
ObDereferenceObject( targetObject );
//
// Done
//
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -