📄 buspdo.c
字号:
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),
BUSENUM_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),
BUSENUM_POOL_TAG);
if (busInfo == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
busInfo->BusTypeGuid = GUID_TOASTER_BUS_TYPE;
//
// Some buses have a specific INTERFACE_TYPE value,
// such as PCMCIABus, PCIBus, or PNPISABus.
// For other buses, especially newer buses like TOASTER, 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;
PTOASTER_INTERFACE_STANDARD toasterInterfaceStandard;
GUID *interfaceType;
NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE();
irpStack = IoGetCurrentIrpStackLocation(Irp);
interfaceType = (GUID *) irpStack->Parameters.QueryInterface.InterfaceType;
if (IsEqualGUID(interfaceType, (PVOID) &GUID_TOASTER_INTERFACE_STANDARD)) {
if (irpStack->Parameters.QueryInterface.Size <
sizeof(TOASTER_INTERFACE_STANDARD)
&& irpStack->Parameters.QueryInterface.Version != 1) {
return STATUS_INVALID_PARAMETER;
}
toasterInterfaceStandard = (PTOASTER_INTERFACE_STANDARD)
irpStack->Parameters.QueryInterface.Interface;
toasterInterfaceStandard->Context = DeviceData;
//
// Fill in the exported functions
//
toasterInterfaceStandard->InterfaceReference =
(PINTERFACE_REFERENCE) Bus_InterfaceReference;
toasterInterfaceStandard->InterfaceDereference =
(PINTERFACE_DEREFERENCE) Bus_InterfaceDereference;
toasterInterfaceStandard->GetCrispinessLevel = Bus_GetCrispinessLevel;
toasterInterfaceStandard->SetCrispinessLevel = Bus_SetCrispinessLevel;
toasterInterfaceStandard->IsSafetyLockEnabled = Bus_IsSafetyLockEnabled;
//
// Must take a reference before returning
//
Bus_InterfaceReference(DeviceData);
} else {
//
// Interface type not supported
//
status = Irp->IoStatus.Status;
}
return status;
}
BOOLEAN
Bus_GetCrispinessLevel(
IN PVOID Context,
OUT PUCHAR Level
)
/*++
Routine Description:
This routine gets the current crispiness level of the toaster.
Arguments:
Context pointer to PDO device extension
Level crispiness level of the device
Return Value:
TRUE or FALSE
--*/
{
//
// Validate the context to see if it's really a pointer
// to PDO's device extension. You can store some kind
// of signature in the PDO for this purpose
//
Bus_KdPrint ((PPDO_DEVICE_DATA)Context, BUS_DBG_PNP_TRACE,
("GetCrispinessLevel\n"));
*Level = 10;
return TRUE;
}
BOOLEAN
Bus_SetCrispinessLevel(
IN PVOID Context,
IN UCHAR Level
)
/*++
Routine Description:
This routine sets the current crispiness level of the toaster.
Arguments:
Context pointer to PDO device extension
Level crispiness level of the device
Return Value:
TRUE or FALSE
--*/
{
Bus_KdPrint ((PPDO_DEVICE_DATA)Context, BUS_DBG_PNP_TRACE,
("SetCrispinessLevel\n"));
return TRUE;
}
BOOLEAN
Bus_IsSafetyLockEnabled(
IN PVOID Context
)
/*++
Routine Description:
Routine to check whether safety lock is enabled
Arguments:
Context pointer to PDO device extension
Return Value:
TRUE or FALSE
--*/
{
Bus_KdPrint ((PPDO_DEVICE_DATA)Context, BUS_DBG_PNP_TRACE,
("IsSafetyLockEnabled\n"));
return TRUE;
}
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)->ToasterInterfaceRefCount);
}
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)->ToasterInterfaceRefCount);
}
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 + -