NTSTATUS HandleQueryDeviceRelations( _In_ PFDO_DEVICE_DATA FdoData, _In_ PIRP Irp ) { NTSTATUS status, status2; PDEVICE_RELATIONS relations, prevRelations, newPrevRelations = NULL; PDEVICE_RELATIONS prevPdoList, newPdoList = NULL; PPDO_DEVICE_DATA pdoData; BOOLEAN found; SIZE_T size; PAGED_CODE(); status = FilterSendIrpSynchronously(FdoData->NextLowerDriver, Irp); if (NT_SUCCESS(status)) { KeEnterCriticalRegion(); KeWaitForSingleObject(&FdoData->LockEvent, Executive, KernelMode, FALSE, NULL); prevRelations = FdoData->PrevRelations; prevPdoList = FdoData->PrevPdoList; relations = (PDEVICE_RELATIONS)Irp->IoStatus.Information; if (prevRelations) { for (ULONG i = 0; i < prevRelations->Count; i++) { if (!prevRelations->Objects[i]) continue; found = FALSE; if (relations) { for (ULONG j = 0; j < prevRelations->Count; j++) { if (prevRelations->Objects[i] == relations->Objects[j]) { found = TRUE; break; } } } if (found) continue; pdoData = (PPDO_DEVICE_DATA)prevPdoList->Objects[i]->DeviceExtension; if (!pdoData) continue; pdoData->Present = FALSE; pdoData->ReportedMissing = TRUE; } } if (relations) { size = sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (relations->Count - 1); newPrevRelations = ExAllocatePoolWithTag(PagedPool, size, POOL_TAG); if (!newPrevRelations) goto LOCKEND; newPdoList = ExAllocatePoolWithTag(PagedPool, size, POOL_TAG); if (!newPdoList) { ExFreePoolWithTag(newPrevRelations, POOL_TAG); goto LOCKEND; } RtlMoveMemory(newPrevRelations, relations, size); newPdoList->Count = relations->Count; for (ULONG i = 0; i < relations->Count; i++) { if (!relations->Objects[i]) { newPdoList->Objects[i] = NULL; continue; } found = FALSE; if (prevRelations) { for (ULONG j = 0; j < prevRelations->Count; j++) { if (relations->Objects[i] == prevRelations->Objects[j]) { found = TRUE; newPdoList->Objects[i] = prevPdoList->Objects[j]; break; } } } if (found) continue; status2 = CreatePdoFilterDevice(FdoData, relations->Objects[i], &newPdoList->Objects[i]); if (!NT_SUCCESS(status2)) newPrevRelations->Objects[i] = NULL; } } if (prevRelations) ExFreePoolWithTag(prevRelations, POOL_TAG); FdoData->PrevRelations = newPrevRelations; if (prevPdoList) ExFreePoolWithTag(prevPdoList, POOL_TAG); FdoData->PrevPdoList = newPdoList; LOCKEND: KeSetEvent(&FdoData->LockEvent, IO_NO_INCREMENT, FALSE); KeLeaveCriticalRegion(); } Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); IoReleaseRemoveLock(&FdoData->RemoveLock, Irp); return status; }