/*++ 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 #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