windows-nt/Source/XPSP1/NT/base/busdrv/isapnp/pdopnp.c
2020-09-26 16:20:57 +08:00

1609 lines
50 KiB
C

/*++
Copyright (c) 1990-2000 Microsoft Corporation
Module Name:
pdopnp.c
Abstract:
This file contains the PNP IRP dispatch code for PDOs
Environment:
Kernel Mode Driver.
Revision History:
--*/
#include "busp.h"
#include "pnpisa.h"
#include <wdmguid.h>
#include "halpnpp.h"
#if ISOLATE_CARDS
//
// Function Prototypes
//
BOOLEAN PipFailStartPdo = FALSE;
BOOLEAN PipFailStartRdp = FALSE;
NTSTATUS
PiStartPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PiQueryRemoveStopPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp );
NTSTATUS
PiCancelRemoveStopPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp );
NTSTATUS
PiStopPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PiQueryDeviceRelationsPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PiQueryCapabilitiesPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PiQueryDeviceTextPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PiFilterResourceRequirementsPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PiQueryIdPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PiQueryResourcesPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PiQueryResourceRequirementsPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PiRemovePdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PiQueryBusInformationPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PiQueryInterfacePdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PiDeviceUsageNotificationPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PiSurpriseRemovePdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PiIrpNotSupported(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
NTSTATUS
PipBuildRDPResources(
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
IN ULONG Flags
);
NTSTATUS
PiQueryDeviceState(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,PiDispatchPnpPdo)
#pragma alloc_text(PAGE,PiStartPdo)
#pragma alloc_text(PAGE,PiQueryRemoveStopPdo)
#pragma alloc_text(PAGE,PiRemovePdo)
#pragma alloc_text(PAGE,PiCancelRemoveStopPdo)
#pragma alloc_text(PAGE,PiStopPdo)
#pragma alloc_text(PAGE,PiQueryDeviceRelationsPdo)
#pragma alloc_text(PAGE,PiQueryInterfacePdo)
#pragma alloc_text(PAGE,PiQueryCapabilitiesPdo)
#pragma alloc_text(PAGE,PiQueryResourcesPdo)
#pragma alloc_text(PAGE,PiQueryResourceRequirementsPdo)
#pragma alloc_text(PAGE,PiQueryDeviceTextPdo)
#pragma alloc_text(PAGE,PiFilterResourceRequirementsPdo)
#pragma alloc_text(PAGE,PiSurpriseRemovePdo)
#pragma alloc_text(PAGE,PiIrpNotSupported)
#pragma alloc_text(PAGE,PiQueryIdPdo)
#pragma alloc_text(PAGE,PiQueryBusInformationPdo)
#pragma alloc_text(PAGE,PiDeviceUsageNotificationPdo)
#pragma alloc_text(PAGE,PipBuildRDPResources)
#pragma alloc_text(PAGE,PiQueryDeviceState)
#endif
//
// PNP IRP Dispatch table for PDOs - This should be updated if new IRPs are added
//
PPI_DISPATCH PiPnpDispatchTablePdo[] = {
PiStartPdo, // IRP_MN_START_DEVICE
PiQueryRemoveStopPdo, // IRP_MN_QUERY_REMOVE_DEVICE
PiRemovePdo, // IRP_MN_REMOVE_DEVICE
PiCancelRemoveStopPdo, // IRP_MN_CANCEL_REMOVE_DEVICE
PiStopPdo, // IRP_MN_STOP_DEVICE
PiQueryRemoveStopPdo, // IRP_MN_QUERY_STOP_DEVICE
PiCancelRemoveStopPdo, // IRP_MN_CANCEL_STOP_DEVICE
PiQueryDeviceRelationsPdo, // IRP_MN_QUERY_DEVICE_RELATIONS
PiQueryInterfacePdo, // IRP_MN_QUERY_INTERFACE
PiQueryCapabilitiesPdo, // IRP_MN_QUERY_CAPABILITIES
PiQueryResourcesPdo, // IRP_MN_QUERY_RESOURCES
PiQueryResourceRequirementsPdo, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
PiQueryDeviceTextPdo, // IRP_MN_QUERY_DEVICE_TEXT
PiFilterResourceRequirementsPdo, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
PiIrpNotSupported, // Unused
PiIrpNotSupported, // IRP_MN_READ_CONFIG
PiIrpNotSupported, // IRP_MN_WRITE_CONFIG
PiIrpNotSupported, // IRP_MN_EJECT
PiIrpNotSupported, // IRP_MN_SET_LOCK
PiQueryIdPdo, // IRP_MN_QUERY_ID
PiQueryDeviceState, // IRP_MN_QUERY_PNP_DEVICE_STATE
PiQueryBusInformationPdo, // IRP_MN_QUERY_BUS_INFORMATION
PiDeviceUsageNotificationPdo, // IRP_MN_DEVICE_USAGE_NOTIFICATION
PiSurpriseRemovePdo, // IRP_MN_SURPRISE_REMOVAL
PiIrpNotSupported // IRP_MN_QUERY_LEGACY_BUS_INFORMATION
};
NTSTATUS
PiDispatchPnpPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
/*++
Routine Description:
This routine handles IRP_MJ_PNP IRPs for PDOs.
Arguments:
DeviceObject - Pointer to the PDO for which this IRP applies.
Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
Return Value:
NT status.
--*/
{
PIO_STACK_LOCATION irpSp;
NTSTATUS status;
PVOID information = NULL;
PAGED_CODE();
//
// Get a pointer to our stack location and take appropriate action based
// on the minor function.
//
irpSp = IoGetCurrentIrpStackLocation(Irp);
if (irpSp->MinorFunction > IRP_MN_PNP_MAXIMUM_FUNCTION) {
status = Irp->IoStatus.Status;
} else {
status = PiPnpDispatchTablePdo[irpSp->MinorFunction](DeviceObject, Irp);
if ( status != STATUS_NOT_SUPPORTED ) {
//
// We understood this IRP and handled it so we need to set status before completing
//
Irp->IoStatus.Status = status;
} else {
status = Irp->IoStatus.Status;
}
}
information = (PVOID)Irp->IoStatus.Information;
ASSERT(status == Irp->IoStatus.Status);
PipCompleteRequest(Irp, status, information);
return status;
} //PipDispatchPnpPdo
NTSTATUS
PiStartPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
PIO_STACK_LOCATION irpSp;
NTSTATUS status;
PCM_RESOURCE_LIST cmResources;
PDEVICE_INFORMATION deviceInfo;
UNICODE_STRING unicodeString;
ULONG length;
POWER_STATE newPowerState;
irpSp = IoGetCurrentIrpStackLocation(Irp);
cmResources = irpSp->Parameters.StartDevice.AllocatedResources;
if (PipDebugMask & DEBUG_PNP) {
PipDumpCmResourceList(cmResources);
} else if (!cmResources) {
DbgPrint("StartDevice irp with empty CmResourceList\n");
}
DebugPrint((DEBUG_PNP,
"*** StartDevice irp received PDO: %x\n",DeviceObject));
if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, TRUE)) {
if (deviceInfo->Flags & DF_READ_DATA_PORT) {
ULONG curSize,newSize;
//
if (PipFailStartRdp) {
PipDereferenceDeviceInformation(deviceInfo, TRUE);
return STATUS_UNSUCCESSFUL;
}
// Read data port is special
//
newSize=PipDetermineResourceListSize(cmResources);
curSize=PipDetermineResourceListSize(deviceInfo->AllocatedResources);
//
// Check if we've been removed, or moved (the +3 is the bit mask for the RDP , we claim 4-7, need xxxi7)
//
if ( (deviceInfo->Flags & DF_REMOVED) ||
!(deviceInfo->Flags & DF_STOPPED) ||
(curSize != newSize) ||
(newSize != RtlCompareMemory (deviceInfo->AllocatedResources,cmResources,newSize))) {
//
// This will release the unused resources
//
status = PipStartReadDataPort (deviceInfo,deviceInfo->ParentDeviceExtension,DeviceObject,cmResources);
if (NT_SUCCESS(status) || status == STATUS_NO_SUCH_DEVICE) {
status = STATUS_SUCCESS;
}
//
// Invalidate the device relations
//
if (NT_SUCCESS (status)) {
IoInvalidateDeviceRelations (
deviceInfo->ParentDeviceExtension->PhysicalBusDevice,BusRelations);
}
deviceInfo->Flags &= ~(DF_STOPPED|DF_REMOVED|DF_SURPRISE_REMOVED);
} else {
deviceInfo->Flags &= ~DF_STOPPED;
IoInvalidateDeviceRelations (
deviceInfo->ParentDeviceExtension->PhysicalBusDevice,BusRelations);
status=STATUS_SUCCESS;
}
deviceInfo->Flags |= DF_ACTIVATED;
PipDereferenceDeviceInformation(deviceInfo, TRUE);
DebugPrint((DEBUG_PNP, "StartDevice(RDP) returning: %x\n",status));
return status;
}
//
if (PipFailStartPdo) {
PipDereferenceDeviceInformation(deviceInfo, TRUE);
return STATUS_UNSUCCESSFUL;
}
// Do this first, so that we allow for no-resource devices in the ref count.
// (when we activate the RDP it won't have resources, yet)
//
// ASSERT (!(PipRDPNode->Flags & (DF_STOPPED|DF_REMOVED)));
if (PipRDPNode->Flags & (DF_STOPPED|DF_REMOVED)) {
//
// If the RDP isn't running, fail the start.
//
PipDereferenceDeviceInformation(deviceInfo, TRUE);
return STATUS_UNSUCCESSFUL;
}
if (cmResources) {
deviceInfo->AllocatedResources = ExAllocatePool(
NonPagedPool,
PipDetermineResourceListSize(cmResources));
if (deviceInfo->AllocatedResources) {
RtlMoveMemory(deviceInfo->AllocatedResources,
cmResources,
length = PipDetermineResourceListSize(cmResources));
deviceInfo->Flags &= ~(DF_REMOVED|DF_STOPPED);
status = PipSetDeviceResources (deviceInfo, cmResources);
if (NT_SUCCESS(status)) {
PipActivateDevice();
DebugPrint((DEBUG_STATE,
"Starting CSN %d/LDN %d\n",
deviceInfo->CardInformation->CardSelectNumber,
deviceInfo->LogicalDeviceNumber));
deviceInfo->Flags |= DF_ACTIVATED;
newPowerState.DeviceState =
deviceInfo->DevicePowerState = PowerDeviceD0;
PoSetPowerState(DeviceObject,
DevicePowerState,
newPowerState);
deviceInfo->DevicePowerState = PowerDeviceD0;
if (deviceInfo->LogConfHandle) {
RtlInitUnicodeString(&unicodeString, L"AllocConfig");
ZwSetValueKey(deviceInfo->LogConfHandle,
&unicodeString,
0,
REG_RESOURCE_LIST,
cmResources,
length
);
}
}
} else {
status = STATUS_NO_MEMORY;
}
} else if (deviceInfo->ResourceRequirements) {
status = STATUS_INSUFFICIENT_RESOURCES;
} else {
status = STATUS_SUCCESS;
}
PipDereferenceDeviceInformation(deviceInfo, TRUE);
} else {
status = STATUS_NO_SUCH_DEVICE;
}
DebugPrint((DEBUG_PNP, "StartDevice returning: %x\n",status));
return status;
} // PiStartPdo
NTSTATUS
PiQueryRemoveStopPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
NTSTATUS status;
PDEVICE_INFORMATION deviceInfo;
PIO_STACK_LOCATION irpSp;
irpSp = IoGetCurrentIrpStackLocation(Irp);
DebugPrint((DEBUG_PNP,
"*** Query%s irp received PDO: %x\n",
(irpSp->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) ? "Stop" : "Remove",
DeviceObject));
if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
if (deviceInfo->Paging || deviceInfo->CrashDump) {
status = STATUS_DEVICE_BUSY;
} else if ( deviceInfo->Flags & DF_READ_DATA_PORT ) {
if (irpSp->MinorFunction != IRP_MN_QUERY_STOP_DEVICE) {
status = STATUS_SUCCESS;
} else if (deviceInfo->Flags & DF_PROCESSING_RDP) {
//
// If we're in the middle of the two part RDP start process,
// flag this as a device that needs to be requeried for
// resource requirements.
//
status = STATUS_RESOURCE_REQUIREMENTS_CHANGED;
} else {
PSINGLE_LIST_ENTRY deviceLink;
PDEVICE_INFORMATION childDeviceInfo;
PPI_BUS_EXTENSION busExtension = deviceInfo->ParentDeviceExtension;
//
// If trying to stop the RDP, then if any children fail it.
//
PipLockDeviceDatabase();
status = STATUS_SUCCESS;
deviceLink = busExtension->DeviceList.Next;
while (deviceLink) {
childDeviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, DeviceList);
if (!(childDeviceInfo->Flags & DF_READ_DATA_PORT) &&
((childDeviceInfo->Flags & DF_ENUMERATED) ||
!(childDeviceInfo->Flags & DF_REMOVED))) {
status = STATUS_UNSUCCESSFUL;
break;
}
deviceLink = childDeviceInfo->DeviceList.Next;
}
PipUnlockDeviceDatabase();
}
} else {
if ((irpSp->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) &&
!(deviceInfo->Flags & DF_ENUMERATED)) {
status = STATUS_UNSUCCESSFUL;
} else {
ASSERT(!(PipRDPNode->Flags & (DF_STOPPED|DF_REMOVED)));
if ((irpSp->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE) &&
(deviceInfo->CardInformation->CardFlags & CF_ISOLATION_BROKEN)) {
DebugPrint((DEBUG_ERROR, "Failed query remove due to broken isolatee\n"));
status = STATUS_UNSUCCESSFUL;
} else {
deviceInfo->Flags |= DF_QUERY_STOPPED;
status = STATUS_SUCCESS;
}
}
}
PipDereferenceDeviceInformation(deviceInfo, FALSE);
} else {
status = STATUS_NO_SUCH_DEVICE;
}
DebugPrint((DEBUG_PNP, "Query%s Device returning: %x\n",
(irpSp->MinorFunction == IRP_MN_QUERY_STOP_DEVICE) ? "Stop" : "Remove",
status));
return status;
} // PiQueryRemoveStopPdo
NTSTATUS
PiCancelRemoveStopPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
NTSTATUS status;
PDEVICE_INFORMATION deviceInfo;
PIO_STACK_LOCATION irpSp;
irpSp = IoGetCurrentIrpStackLocation(Irp);
DebugPrint((DEBUG_PNP,
"*** Cancel%s irp received PDO: %x\n",
(irpSp->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE) ? "Stop" : "Remove",
DeviceObject));
if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
deviceInfo->Flags &= ~DF_QUERY_STOPPED;
PipDereferenceDeviceInformation(deviceInfo, FALSE);
status = STATUS_SUCCESS;
} else {
status = STATUS_NO_SUCH_DEVICE;
}
DebugPrint((DEBUG_PNP, "Cancel%s Device returning: %x\n",
(irpSp->MinorFunction == IRP_MN_CANCEL_STOP_DEVICE) ? "Stop" : "Remove",
status));
return status;
} // PiCancelRemoteStopPdo
NTSTATUS
PiStopPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
NTSTATUS status;
PDEVICE_INFORMATION deviceInfo;
POWER_STATE newPowerState;
DebugPrint((DEBUG_PNP, "PiStopPdo %x\n",DeviceObject));
if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, TRUE)) {
//
// Deselect the cards, but not the RDP node.
//
if (DeviceObject != PipRDPNode->PhysicalDeviceObject) {
PipDeactivateDevice();
DebugPrint((DEBUG_STATE,
"Stopping CSN %d/LDN %d\n",
deviceInfo->CardInformation->CardSelectNumber,
deviceInfo->LogicalDeviceNumber));
PipReleaseDeviceResources (deviceInfo);
}
if ((deviceInfo->Flags & DF_ACTIVATED)) {
deviceInfo->Flags &= ~DF_ACTIVATED;
newPowerState.DeviceState = deviceInfo->DevicePowerState = PowerDeviceD3;
PoSetPowerState(DeviceObject, DevicePowerState, newPowerState);
}
deviceInfo->Flags &= ~DF_QUERY_STOPPED;
deviceInfo->Flags |= DF_STOPPED;
PipDereferenceDeviceInformation(deviceInfo, TRUE);
status = STATUS_SUCCESS;
} else {
status = STATUS_NO_SUCH_DEVICE;
}
DebugPrint((DEBUG_PNP, "StopDevice returning: %x\n",status));
return status;
} // PiStopPdo
NTSTATUS
PiQueryDeviceRelationsPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
NTSTATUS status;
PDEVICE_INFORMATION deviceInfo;
PIO_STACK_LOCATION irpSp;
irpSp = IoGetCurrentIrpStackLocation(Irp);
//
// The QueryDeviceRelation Irp is for devices under enumerated PnpIsa device.
//
switch (irpSp->Parameters.QueryDeviceRelations.Type) {
case TargetDeviceRelation: {
PDEVICE_RELATIONS deviceRelations;
deviceRelations = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
if (deviceRelations == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
} else {
deviceRelations->Count = 1;
deviceRelations->Objects[0] = DeviceObject;
ObReferenceObject(DeviceObject);
Irp->IoStatus.Information = (ULONG_PTR)deviceRelations;
status = STATUS_SUCCESS;
}
}
break;
case RemovalRelations: {
PDEVICE_RELATIONS deviceRelations;
if (PipRDPNode && (DeviceObject == PipRDPNode->PhysicalDeviceObject)) {
deviceRelations = ExAllocatePool(PagedPool, sizeof(DEVICE_RELATIONS));
if (deviceRelations == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
} else {
//
//Don't include ourselves in the list of Removal Relations, hence the -1
//
PipLockDeviceDatabase();
status = PipQueryDeviceRelations(
PipRDPNode->ParentDeviceExtension,
(PDEVICE_RELATIONS *)&Irp->IoStatus.Information,
TRUE
);
PipUnlockDeviceDatabase();
}
} else {
status = STATUS_NOT_SUPPORTED;
}
}
break;
default : {
status = STATUS_NOT_SUPPORTED;
break;
}
}
return status;
} // PiQueryDeviceRelationsPdo
NTSTATUS
PiQueryCapabilitiesPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
NTSTATUS status;
PIO_STACK_LOCATION irpSp;
PDEVICE_CAPABILITIES deviceCapabilities;
ULONG i;
PDEVICE_POWER_STATE state;
irpSp = IoGetCurrentIrpStackLocation(Irp);
deviceCapabilities = irpSp->Parameters.DeviceCapabilities.Capabilities;
deviceCapabilities->SystemWake = PowerSystemUnspecified;
deviceCapabilities->DeviceWake = PowerDeviceUnspecified;
deviceCapabilities->LockSupported = FALSE;
deviceCapabilities->EjectSupported = FALSE;
deviceCapabilities->Removable = FALSE;
deviceCapabilities->DockDevice = FALSE;
deviceCapabilities->UniqueID = TRUE;
state = deviceCapabilities->DeviceState;
//
// Init the entire DeviceState array to D3 then replace the entry
// for system state S0.
//
for (i = 0;
i < sizeof(deviceCapabilities->DeviceState);
i += sizeof(deviceCapabilities->DeviceState[0])) {
//
// Only supported state, currently, is off.
//
*state++ = PowerDeviceD3;
}
deviceCapabilities->DeviceState[PowerSystemWorking] = PowerDeviceD0;
//deviceCapabilities->SilentInstall = TRUE;
//deviceCapabilities->RawDeviceOK = FALSE;
if (PipRDPNode && (PipRDPNode->PhysicalDeviceObject == DeviceObject)) {
deviceCapabilities->SilentInstall = TRUE;
deviceCapabilities->RawDeviceOK = TRUE;
}
return STATUS_SUCCESS;
} // PiQueryCapabilitiesPdo
NTSTATUS
PiQueryDeviceTextPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
NTSTATUS status;
PIO_STACK_LOCATION irpSp;
PDEVICE_INFORMATION deviceInfo;
irpSp = IoGetCurrentIrpStackLocation(Irp);
if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
PWSTR functionId;
ULONG functionIdLength;
if (irpSp->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription) {
//
// Once we know we're going to touch the IRP
//
status = STATUS_SUCCESS;
PipGetFunctionIdentifier((PUCHAR)deviceInfo->DeviceData,
&functionId,
&functionIdLength);
if (!functionId) {
if (deviceInfo->CardInformation) {
PipGetCardIdentifier((PUCHAR)deviceInfo->CardInformation->CardData + NUMBER_CARD_ID_BYTES,
&functionId,
&functionIdLength);
}else {
functionId=NULL;
}
}
Irp->IoStatus.Information = (ULONG_PTR)functionId;
} else {
status = STATUS_NOT_SUPPORTED;
}
PipDereferenceDeviceInformation(deviceInfo, FALSE);
} else {
status = STATUS_NO_SUCH_DEVICE;
}
return status;
} // PiQueryDeviceTextPdo
NTSTATUS
PiFilterResourceRequirementsPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
/*++
Routine Description:
This routine ensures that the RDP doesn't get its requirements filtered.
Design Note:
This code may now be extraneous now that we ensure that the
DF_PROCESSING_RDP and DF_REQ_TRIMMED flags are cleared on RDP
removal.
Arguments:
DeviceObject - Pointer to the PDO for which this IRP applies.
Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
Return Value:
NT status.
--*/
{
NTSTATUS status;
PDEVICE_INFORMATION deviceInfo;
PIO_RESOURCE_REQUIREMENTS_LIST IoResources;
USHORT irqBootFlags;
if ((deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) == NULL) {
return STATUS_NO_SUCH_DEVICE;
}
if (deviceInfo->Flags & DF_READ_DATA_PORT) {
DebugPrint((DEBUG_PNP, "Filtering resource requirements for RDP\n"));
status = PipBuildRDPResources(&IoResources, deviceInfo->Flags);
if (NT_SUCCESS(status)) {
//
// if someone above us filtered the RDP resource requirements,
// free them.
if (Irp->IoStatus.Information) {
ExFreePool((PVOID) Irp->IoStatus.Information);
}
Irp->IoStatus.Information = (ULONG_PTR) IoResources;
}
} else {
//
// If the device's resource requirements are being filtered
// and the new requirements have only one alternative vs the n
// alternatives of the original, then we're going to assume we
// are receiving a force config. Apply our earlier derived
// IRQ level/edge settings to this force config in order to
// deal with broken force configs from NT4
//
// Design Note:
// Probably should've left out the force config test
// and done it on everything, but this is what we private
// tested.
IoResources =
(PIO_RESOURCE_REQUIREMENTS_LIST) Irp->IoStatus.Information;
if (IoResources &&
(IoResources->AlternativeLists == 1) &&
(deviceInfo->ResourceRequirements->AlternativeLists > 1)) {
status = PipGetBootIrqFlags(deviceInfo, &irqBootFlags);
if (NT_SUCCESS(status)) {
status = PipTrimResourceRequirements(
&IoResources,
irqBootFlags,
NULL);
Irp->IoStatus.Information = (ULONG_PTR) IoResources;
} else {
status = STATUS_NOT_SUPPORTED;
}
} else {
status = STATUS_NOT_SUPPORTED;
}
}
PipDereferenceDeviceInformation(deviceInfo, FALSE);
return status;
}
NTSTATUS
PiQueryIdPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
NTSTATUS status;
PIO_STACK_LOCATION irpSp;
PDEVICE_INFORMATION deviceInfo;
ULONG length;
PWCHAR requestId = NULL, ids;
irpSp = IoGetCurrentIrpStackLocation(Irp);
if ((deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) == NULL) {
status = STATUS_NO_SUCH_DEVICE;
return status;
}
switch (irpSp->Parameters.QueryId.IdType) {
case BusQueryCompatibleIDs:
ids = (PWCHAR)ExAllocatePool(PagedPool, 1024);
if (ids) {
PWCHAR p1;
ULONG i;
p1 = ids;
length = 0;
for (i = 1; TRUE; i++) {
//
// Use the -1 as a sentinel so that we get the magic RDP compat. ID and also leave the loop
//
ASSERT (i < 256);
if (deviceInfo->Flags & DF_READ_DATA_PORT) {
i =-1;
}
status = PipGetCompatibleDeviceId(
deviceInfo->DeviceData,
i,
&requestId);
if (NT_SUCCESS(status) && requestId) {
if ((length + wcslen(requestId) * sizeof(WCHAR) + 2 * sizeof(WCHAR))
<= 1024) {
RtlMoveMemory(p1, requestId, wcslen(requestId) * sizeof(WCHAR));
p1 += wcslen(requestId);
*p1 = UNICODE_NULL;
p1++;
length += wcslen(requestId) * sizeof(WCHAR) + sizeof(WCHAR);
ExFreePool(requestId);
} else {
ExFreePool(requestId);
break;
}
if ( i == -1 ) {
break;
}
} else {
break;
}
}
if (length == 0) {
ExFreePool(ids);
ids = NULL;
} else {
*p1 = UNICODE_NULL;
}
}
Irp->IoStatus.Information = (ULONG_PTR)ids;
status = STATUS_SUCCESS;
break;
case BusQueryHardwareIDs:
if (deviceInfo->Flags & DF_READ_DATA_PORT) {
status = PipGetCompatibleDeviceId(deviceInfo->DeviceData, -1, &requestId);
}else {
status = PipGetCompatibleDeviceId(deviceInfo->DeviceData, 0, &requestId);
}
if (NT_SUCCESS(status) && requestId) {
ULONG idLength, deviceIdLength;
PWCHAR deviceId = NULL, p;
//
// create HardwareId value name. Even though it is a MULTI_SZ,
// we know there is only one HardwareId for PnpIsa.
//
// HACK - The modem inf files use the form of isapnp\xyz0001
// instead of *xyz0001 as the hardware id. To solve this
// problem we will generate two hardware Ids: *xyz0001 and
// isapnp\xyz0001 (device instance name).
//
status = PipQueryDeviceId(deviceInfo, &deviceId, 0);
if (NT_SUCCESS (status)) {
idLength = wcslen(requestId) * sizeof(WCHAR);
deviceIdLength = wcslen(deviceId) * sizeof(WCHAR);
length = idLength + // returned ID
sizeof(WCHAR) + // UNICODE_NULL
deviceIdLength + // isapnp\id
2 * sizeof(WCHAR); // two UNICODE_NULLs
ids = p = (PWCHAR)ExAllocatePool(PagedPool, length);
if (ids) {
RtlMoveMemory(ids, deviceId, deviceIdLength);
p += deviceIdLength / sizeof(WCHAR);
*p = UNICODE_NULL;
p++;
RtlMoveMemory(p, requestId, idLength);
p += idLength / sizeof(WCHAR);
*p = UNICODE_NULL;
p++;
*p = UNICODE_NULL;
ExFreePool(requestId);
Irp->IoStatus.Information = (ULONG_PTR)ids;
} else {
Irp->IoStatus.Information = (ULONG_PTR)requestId;
}
if (deviceId) {
ExFreePool(deviceId);
}
}
}
break;
case BusQueryDeviceID:
status = PipQueryDeviceId(deviceInfo, &requestId, 0);
Irp->IoStatus.Information = (ULONG_PTR)requestId;
break;
case BusQueryInstanceID:
status = PipQueryDeviceUniqueId (deviceInfo, &requestId);
Irp->IoStatus.Information = (ULONG_PTR)requestId;
break;
default:
status = STATUS_NOT_SUPPORTED;
}
PipDereferenceDeviceInformation(deviceInfo, FALSE);
return status;
} // PiQueryIdPdo
NTSTATUS
PiQueryResourcesPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
NTSTATUS status=STATUS_SUCCESS;
PDEVICE_INFORMATION deviceInfo;
PCM_RESOURCE_LIST cmResources=NULL;
ULONG length;
if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
if ((deviceInfo->Flags & DF_READ_DATA_PORT) ||
((deviceInfo->Flags & (DF_ENUMERATED|DF_REMOVED)) == DF_ENUMERATED)) {
status = PipQueryDeviceResources (
deviceInfo,
0, // BusNumber
&cmResources,
&length
);
}
PipDereferenceDeviceInformation(deviceInfo, FALSE);
Irp->IoStatus.Information = (ULONG_PTR)cmResources;
} else {
status = STATUS_NO_SUCH_DEVICE;
}
DebugPrint((DEBUG_PNP, "PiQueryResourcesPdo returning: %x\n",status));
return status;
} // PiQueryResourcesPdo
NTSTATUS
PiQueryResourceRequirementsPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
NTSTATUS status;
PDEVICE_INFORMATION deviceInfo;
PIO_RESOURCE_REQUIREMENTS_LIST ioResources;
if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
status = STATUS_SUCCESS;
if (deviceInfo->Flags & DF_READ_DATA_PORT) {
status = PipBuildRDPResources (&ioResources,
deviceInfo->Flags);
} else {
if (deviceInfo->ResourceRequirements &&
!(deviceInfo->Flags & (DF_SURPRISE_REMOVED))) {
ioResources = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool (
PagedPool, deviceInfo->ResourceRequirements->ListSize);
if (ioResources == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
} else {
RtlMoveMemory(ioResources,
deviceInfo->ResourceRequirements,
deviceInfo->ResourceRequirements->ListSize
);
}
} else {
ioResources = NULL;
}
}
Irp->IoStatus.Information = (ULONG_PTR)ioResources;
PipDereferenceDeviceInformation(deviceInfo, FALSE);
} else {
status = STATUS_NO_SUCH_DEVICE;
}
DebugPrint((DEBUG_PNP, "PiQueryResourceRequirementsPdo returning: %x\n",status));
return status;
} // PiQueryResourceRequirementsPdo
NTSTATUS
PiRemovePdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
NTSTATUS status;
PDEVICE_INFORMATION deviceInfo;
POWER_STATE newPowerState;
//
// One of our enumerated device is being removed. Mark it and deactivate the
// device. Note, we do NOT delete its device object.
//
DebugPrint((DEBUG_PNP, "PiRemovePdo %x\n",DeviceObject));
if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
if (!(deviceInfo->Flags & (DF_REMOVED|DF_SURPRISE_REMOVED))) {
deviceInfo->Flags |= DF_REMOVED;
deviceInfo->Flags &= ~DF_QUERY_STOPPED;
if (deviceInfo->Flags & DF_READ_DATA_PORT) {
PSINGLE_LIST_ENTRY deviceLink;
PPI_BUS_EXTENSION busExtension = deviceInfo->ParentDeviceExtension;
//
// If the RDP is removed, mark everyone as missing, and then return only the
// RDP
//
PipLockDeviceDatabase();
deviceLink = busExtension->DeviceList.Next;
while (deviceLink) {
deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, DeviceList);
if (!(deviceInfo->Flags & DF_READ_DATA_PORT)) {
deviceInfo->Flags &= ~DF_ENUMERATED;
}
deviceLink = deviceInfo->DeviceList.Next;
}
PipUnlockDeviceDatabase();
IoInvalidateDeviceRelations (
deviceInfo->ParentDeviceExtension->PhysicalBusDevice,BusRelations);
deviceInfo->Flags &= ~(DF_REQ_TRIMMED|DF_PROCESSING_RDP);
}
//
// Deactivate the device
//
if (deviceInfo->Flags & DF_ACTIVATED) {
deviceInfo->Flags &= ~DF_ACTIVATED;
if (!(deviceInfo->Flags & (DF_READ_DATA_PORT|DF_NOT_FUNCTIONING))) {
PipWakeAndSelectDevice(
(UCHAR) deviceInfo->CardInformation->CardSelectNumber,
(UCHAR)deviceInfo->LogicalDeviceNumber);
PipDeactivateDevice();
PipWaitForKey();
DebugPrint((DEBUG_STATE,
"Removing CSN %d/LDN %d\n",
deviceInfo->CardInformation->CardSelectNumber,
deviceInfo->LogicalDeviceNumber));
}
newPowerState.DeviceState = deviceInfo->DevicePowerState = PowerDeviceD3;
PoSetPowerState(DeviceObject, DevicePowerState, newPowerState);
}
PipReleaseDeviceResources (deviceInfo);
}
if (!(deviceInfo->Flags & DF_ENUMERATED)) {
PipDeleteDevice(DeviceObject);
}
PipDereferenceDeviceInformation(deviceInfo, TRUE);
status = STATUS_SUCCESS;
} else {
status = STATUS_NO_SUCH_DEVICE;
}
DebugPrint((DEBUG_PNP, "RemoveDevice returning: %x\n",status));
return status;
} // PiRemovePdo
NTSTATUS
PiQueryBusInformationPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
PPNP_BUS_INFORMATION pnpBusInfo;
PVOID information = NULL;
PPI_BUS_EXTENSION busExtension;
NTSTATUS status;
busExtension = DeviceObject->DeviceExtension;
pnpBusInfo = (PPNP_BUS_INFORMATION) ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
if (pnpBusInfo) {
pnpBusInfo->BusTypeGuid = GUID_BUS_TYPE_ISAPNP;
pnpBusInfo->LegacyBusType = Isa;
pnpBusInfo->BusNumber = busExtension->BusNumber;
information = pnpBusInfo;
status = STATUS_SUCCESS;
} else {
status = STATUS_INSUFFICIENT_RESOURCES;
information = NULL;
}
Irp->IoStatus.Information = (ULONG_PTR) information;
return status;
} // PiQueryBusInformationPdo
NTSTATUS
PiDeviceUsageNotificationPdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
/*++
Routine Description:
This routine notes whether an ISAPNP device is on the crashdump or
paging file path. It fails attempts to put us on the hibernation path.
Arguments:
DeviceObject - Pointer to the PDO for which this IRP applies.
Irp - Pointer to the IRP_MJ_PNP IRP to dispatch.
Return Value:
NT status.
--*/
{
PDEVICE_INFORMATION deviceInfo;
PIO_STACK_LOCATION irpSp;
PLONG addend;
NTSTATUS status = STATUS_SUCCESS;
irpSp = IoGetCurrentIrpStackLocation(Irp);
if ((deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) == NULL) {
status = STATUS_NO_SUCH_DEVICE;
return status;
}
DebugPrint((DEBUG_PNP, "DeviceUsage CSN %d/LSN %d: InPath %s Type %d\n",
deviceInfo->CardInformation->CardSelectNumber,
deviceInfo->LogicalDeviceNumber,
irpSp->Parameters.UsageNotification.InPath ? "TRUE" : "FALSE",
irpSp->Parameters.UsageNotification.Type));
switch (irpSp->Parameters.UsageNotification.Type) {
case DeviceUsageTypePaging:
addend = &deviceInfo->Paging;
break;
case DeviceUsageTypeHibernation:
status = STATUS_DEVICE_BUSY;
break;
case DeviceUsageTypeDumpFile:
addend = &deviceInfo->CrashDump;
break;
default:
status = STATUS_NOT_SUPPORTED;
}
if (status == STATUS_SUCCESS) {
if (irpSp->Parameters.UsageNotification.InPath) {
//
// Turn on broken isolation flag which causes QDR
// to use the cache instead of beating on the hardware if
// we're on the paging or crashdump paths. Some
// hardware appears unhappy during QDR and causes problems when
// we take a page fault in this routine.
//
deviceInfo->CardInformation->CardFlags |= CF_ISOLATION_BROKEN;
(*addend)++;
IoInvalidateDeviceState(DeviceObject);
}
else {
(*addend)--;
}
}
PipDereferenceDeviceInformation(deviceInfo, FALSE);
return status;
}
NTSTATUS
PiQueryInterfacePdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
UNREFERENCED_PARAMETER(DeviceObject);
UNREFERENCED_PARAMETER(Irp);
return STATUS_NOT_SUPPORTED;
} // PiQueryInterfacePdo
NTSTATUS
PiSurpriseRemovePdo(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
NTSTATUS status;
PDEVICE_INFORMATION deviceInfo;
PSINGLE_LIST_ENTRY deviceLink;
DebugPrint((DEBUG_PNP, "SurpriseRemove PDO %x\n", DeviceObject));
//
// One of our enumerated device is being removed. Mark it and deactivate the
// device. Note, we do NOT delete its device object.
//
if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
if (deviceInfo->Flags & DF_READ_DATA_PORT) {
//
// If the RDP is removed, mark everyone as missing, and then return only the
// RDP
//
PipLockDeviceDatabase();
deviceLink = deviceInfo->ParentDeviceExtension->DeviceList.Next;
while (deviceLink) {
deviceInfo = CONTAINING_RECORD (deviceLink, DEVICE_INFORMATION, DeviceList);
if (!(deviceInfo->Flags & DF_READ_DATA_PORT)) {
deviceInfo->Flags &= ~DF_ENUMERATED;
}
deviceLink = deviceInfo->DeviceList.Next;
}
PipUnlockDeviceDatabase();
IoInvalidateDeviceRelations (
deviceInfo->ParentDeviceExtension->PhysicalBusDevice,BusRelations);
} else {
DebugPrint((DEBUG_STATE,
"Surprise removing CSN %d/LDN %d\n",
deviceInfo->CardInformation->CardSelectNumber,
deviceInfo->LogicalDeviceNumber));
if ((deviceInfo->Flags & (DF_ACTIVATED|DF_NOT_FUNCTIONING)) == DF_ACTIVATED) {
PipWakeAndSelectDevice(
(UCHAR) deviceInfo->CardInformation->CardSelectNumber,
(UCHAR)deviceInfo->LogicalDeviceNumber);
PipDeactivateDevice();
PipWaitForKey();
}
PipReleaseDeviceResources (deviceInfo);
deviceInfo->Flags |= DF_SURPRISE_REMOVED;
deviceInfo->Flags &= ~(DF_QUERY_STOPPED|DF_REMOVED|DF_ACTIVATED);
}
PipDereferenceDeviceInformation(deviceInfo, FALSE);
status = STATUS_SUCCESS;
} else {
status = STATUS_NO_SUCH_DEVICE;
}
return status;
} // PiSurpriseRemovePdo
NTSTATUS
PiIrpNotSupported(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
return STATUS_NOT_SUPPORTED;
} // PiIrpNotSupported
NTSTATUS
PipBuildRDPResources(
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
IN ULONG Flags
)
{
ULONG MaxCards = 0, CardsFound;
int i, j, numcases;
int resSize;
ASSERT(Flags & DF_READ_DATA_PORT);
//
// We need to assemble all possible cases for the RDP
//
numcases = 2*READ_DATA_PORT_RANGE_CHOICES;
if (Flags & DF_REQ_TRIMMED) {
numcases = 0;
for (i = 0; i < READ_DATA_PORT_RANGE_CHOICES; i++) {
CardsFound = PipReadDataPortRanges[i].CardsFound;
if (MaxCards < CardsFound) {
MaxCards = CardsFound;
numcases = 1;
} else if (MaxCards == CardsFound) {
numcases++;
}
}
}
//
// need to allow for the RDP range, the address port, the cmd port and the 0
//
resSize = sizeof (IO_RESOURCE_LIST)+((numcases+3)*sizeof (IO_RESOURCE_REQUIREMENTS_LIST));
*IoResources = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool (PagedPool,resSize);
if (*IoResources == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory (*IoResources,resSize);
(*IoResources)->BusNumber=0;
(*IoResources)->AlternativeLists = 1;
(*IoResources)->List->Count = numcases+4;
(*IoResources)->List->Version = ISAPNP_IO_VERSION;
(*IoResources)->List->Revision =ISAPNP_IO_REVISION;
//
// Requirements specify 16-bit decode even though the spec
// says 12. No ill effects have ever been observed from 16
// and 12-bit decode broke some machines when tried.
//
// cmd port
//
(*IoResources)->List->Descriptors[0].Type=CM_RESOURCE_PORT_IO;
(*IoResources)->List->Descriptors[0].u.Port.MinimumAddress.LowPart = COMMAND_PORT;
(*IoResources)->List->Descriptors[0].u.Port.MaximumAddress.LowPart = COMMAND_PORT;
(*IoResources)->List->Descriptors[0].u.Port.Length = 1;
(*IoResources)->List->Descriptors[0].u.Port.Alignment = 1;
(*IoResources)->List->Descriptors[0].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
(*IoResources)->List->Descriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
//
// alternative of 0 for bioses that include COMMAND_PORT in
// a PNP0C02 node.
//
(*IoResources)->List->Descriptors[1].Type=CM_RESOURCE_PORT_IO;
(*IoResources)->List->Descriptors[1].u.Port.MinimumAddress.QuadPart = 0;
(*IoResources)->List->Descriptors[1].u.Port.MaximumAddress.QuadPart = 0;
(*IoResources)->List->Descriptors[1].u.Port.Length = 0;
(*IoResources)->List->Descriptors[1].u.Port.Alignment = 1;
(*IoResources)->List->Descriptors[1].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
(*IoResources)->List->Descriptors[1].ShareDisposition = CmResourceShareDeviceExclusive;
(*IoResources)->List->Descriptors[1].Option = IO_RESOURCE_ALTERNATIVE;
//
// Address port
//
(*IoResources)->List->Descriptors[2].Type=CM_RESOURCE_PORT_IO;
(*IoResources)->List->Descriptors[2].u.Port.MinimumAddress.LowPart = ADDRESS_PORT;
(*IoResources)->List->Descriptors[2].u.Port.MaximumAddress.LowPart = ADDRESS_PORT;
(*IoResources)->List->Descriptors[2].u.Port.Length = 1;
(*IoResources)->List->Descriptors[2].u.Port.Alignment = 1;
(*IoResources)->List->Descriptors[2].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
(*IoResources)->List->Descriptors[2].ShareDisposition = CmResourceShareDeviceExclusive;
//
// alternative of 0
//
(*IoResources)->List->Descriptors[3].Type=CM_RESOURCE_PORT_IO;
(*IoResources)->List->Descriptors[3].u.Port.MinimumAddress.QuadPart = 0;
(*IoResources)->List->Descriptors[3].u.Port.MaximumAddress.QuadPart = 0;
(*IoResources)->List->Descriptors[3].u.Port.Length = 0;
(*IoResources)->List->Descriptors[3].u.Port.Alignment = 1;
(*IoResources)->List->Descriptors[3].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
(*IoResources)->List->Descriptors[3].ShareDisposition = CmResourceShareDeviceExclusive;
(*IoResources)->List->Descriptors[3].Option = IO_RESOURCE_ALTERNATIVE;
if (Flags & DF_REQ_TRIMMED) {
j = 0;
for (i = 0; i < READ_DATA_PORT_RANGE_CHOICES; i++) {
if (PipReadDataPortRanges[i].CardsFound != MaxCards) {
continue;
}
//
// An RDP alternative
//
(*IoResources)->List->Descriptors[4+j].Type=CM_RESOURCE_PORT_IO;
(*IoResources)->List->Descriptors[4+j].u.Port.MinimumAddress.LowPart =
PipReadDataPortRanges[i].MinimumAddress;
(*IoResources)->List->Descriptors[4+j].u.Port.MaximumAddress.LowPart =
PipReadDataPortRanges[i].MaximumAddress;
(*IoResources)->List->Descriptors[4+j].u.Port.Length =
PipReadDataPortRanges[i].MaximumAddress -
PipReadDataPortRanges[i].MinimumAddress+1;
(*IoResources)->List->Descriptors[4+j].u.Port.Alignment = 1;
(*IoResources)->List->Descriptors[4+j].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
(*IoResources)->List->Descriptors[4+j].ShareDisposition = CmResourceShareDeviceExclusive;
(*IoResources)->List->Descriptors[4+j].Option = IO_RESOURCE_ALTERNATIVE;
j++;
}
(*IoResources)->List->Descriptors[4].Option = 0;
} else {
for (i = 0;i< (numcases >> 1);i++) {
//
// The RDP
//
(*IoResources)->List->Descriptors[4+i*2].Type=CM_RESOURCE_PORT_IO;
(*IoResources)->List->Descriptors[4+i*2].u.Port.MinimumAddress.LowPart =
PipReadDataPortRanges[i].MinimumAddress;
(*IoResources)->List->Descriptors[4+i*2].u.Port.MaximumAddress.LowPart =
PipReadDataPortRanges[i].MaximumAddress;
(*IoResources)->List->Descriptors[4+i*2].u.Port.Length =
PipReadDataPortRanges[i].MaximumAddress -
PipReadDataPortRanges[i].MinimumAddress+1;
(*IoResources)->List->Descriptors[4+i*2].u.Port.Alignment = 1;
(*IoResources)->List->Descriptors[4+i*2].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
(*IoResources)->List->Descriptors[4+i*2].ShareDisposition = CmResourceShareDeviceExclusive;
//
// alternative of 0
//
(*IoResources)->List->Descriptors[4+i*2+1].Type=CM_RESOURCE_PORT_IO;
(*IoResources)->List->Descriptors[4+i*2+1].u.Port.MinimumAddress.QuadPart = 0;
(*IoResources)->List->Descriptors[4+i*2+1].u.Port.MaximumAddress.QuadPart = 0;
(*IoResources)->List->Descriptors[4+i*2+1].u.Port.Length = 0;
(*IoResources)->List->Descriptors[4+i*2+1].u.Port.Alignment = 1;
(*IoResources)->List->Descriptors[4+i*2+1].Flags = CM_RESOURCE_PORT_16_BIT_DECODE;
(*IoResources)->List->Descriptors[4+i*2+1].ShareDisposition = CmResourceShareDeviceExclusive;
(*IoResources)->List->Descriptors[4+i*2+1].Option = IO_RESOURCE_ALTERNATIVE;
}
}
(*IoResources)->ListSize = resSize;
return STATUS_SUCCESS;
}
NTSTATUS
PiQueryDeviceState(
IN PDEVICE_OBJECT DeviceObject,
IN OUT PIRP Irp
)
{
NTSTATUS status=STATUS_NOT_SUPPORTED;
PDEVICE_INFORMATION deviceInfo;
//
// One of our enumerated device is being removed. Mark it and deactivate the
// device. Note, we do NOT delete its device object.
//
if (deviceInfo = PipReferenceDeviceInformation(DeviceObject, FALSE)) {
if ((deviceInfo->Flags & DF_READ_DATA_PORT) && (deviceInfo->Flags & DF_PROCESSING_RDP)) {
Irp->IoStatus.Information |= PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED |
PNP_DEVICE_FAILED |
PNP_DEVICE_NOT_DISABLEABLE ;
status = STATUS_SUCCESS;
}
if (deviceInfo->Paging || deviceInfo->CrashDump) {
Irp->IoStatus.Information |= PNP_DEVICE_NOT_DISABLEABLE;
status = STATUS_SUCCESS;
}
PipDereferenceDeviceInformation(deviceInfo, FALSE);
}
return status;
}
#endif