1*c2c66affSColin Finck /* 2*c2c66affSColin Finck * PROJECT: ReactOS Kernel 3*c2c66affSColin Finck * COPYRIGHT: GPL - See COPYING in the top level directory 4*c2c66affSColin Finck * FILE: ntoskrnl/io/pnpmgr/pnpreport.c 5*c2c66affSColin Finck * PURPOSE: Device Changes Reporting Functions 6*c2c66affSColin Finck * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org) 7*c2c66affSColin Finck * Pierre Schweitzer 8*c2c66affSColin Finck */ 9*c2c66affSColin Finck 10*c2c66affSColin Finck /* INCLUDES ******************************************************************/ 11*c2c66affSColin Finck 12*c2c66affSColin Finck #include <ntoskrnl.h> 13*c2c66affSColin Finck #define NDEBUG 14*c2c66affSColin Finck #include <debug.h> 15*c2c66affSColin Finck 16*c2c66affSColin Finck /* TYPES *******************************************************************/ 17*c2c66affSColin Finck 18*c2c66affSColin Finck typedef struct _INTERNAL_WORK_QUEUE_ITEM 19*c2c66affSColin Finck { 20*c2c66affSColin Finck WORK_QUEUE_ITEM WorkItem; 21*c2c66affSColin Finck PDEVICE_OBJECT PhysicalDeviceObject; 22*c2c66affSColin Finck PDEVICE_CHANGE_COMPLETE_CALLBACK Callback; 23*c2c66affSColin Finck PVOID Context; 24*c2c66affSColin Finck PTARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure; 25*c2c66affSColin Finck } INTERNAL_WORK_QUEUE_ITEM, *PINTERNAL_WORK_QUEUE_ITEM; 26*c2c66affSColin Finck 27*c2c66affSColin Finck NTSTATUS 28*c2c66affSColin Finck NTAPI 29*c2c66affSColin Finck IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath, 30*c2c66affSColin Finck IN ULONG CreateOptions, 31*c2c66affSColin Finck OUT PHANDLE Handle); 32*c2c66affSColin Finck 33*c2c66affSColin Finck NTSTATUS 34*c2c66affSColin Finck IopSetDeviceInstanceData(HANDLE InstanceKey, 35*c2c66affSColin Finck PDEVICE_NODE DeviceNode); 36*c2c66affSColin Finck 37*c2c66affSColin Finck NTSTATUS 38*c2c66affSColin Finck IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode, 39*c2c66affSColin Finck PVOID Context); 40*c2c66affSColin Finck 41*c2c66affSColin Finck NTSTATUS 42*c2c66affSColin Finck PpSetCustomTargetEvent(IN PDEVICE_OBJECT DeviceObject, 43*c2c66affSColin Finck IN OUT PKEVENT SyncEvent OPTIONAL, 44*c2c66affSColin Finck IN OUT PNTSTATUS SyncStatus OPTIONAL, 45*c2c66affSColin Finck IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL, 46*c2c66affSColin Finck IN PVOID Context OPTIONAL, 47*c2c66affSColin Finck IN PTARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure); 48*c2c66affSColin Finck 49*c2c66affSColin Finck /* PRIVATE FUNCTIONS *********************************************************/ 50*c2c66affSColin Finck 51*c2c66affSColin Finck PWCHAR 52*c2c66affSColin Finck IopGetInterfaceTypeString(INTERFACE_TYPE IfType) 53*c2c66affSColin Finck { 54*c2c66affSColin Finck switch (IfType) 55*c2c66affSColin Finck { 56*c2c66affSColin Finck case Internal: 57*c2c66affSColin Finck return L"Internal"; 58*c2c66affSColin Finck 59*c2c66affSColin Finck case Isa: 60*c2c66affSColin Finck return L"Isa"; 61*c2c66affSColin Finck 62*c2c66affSColin Finck case Eisa: 63*c2c66affSColin Finck return L"Eisa"; 64*c2c66affSColin Finck 65*c2c66affSColin Finck case MicroChannel: 66*c2c66affSColin Finck return L"MicroChannel"; 67*c2c66affSColin Finck 68*c2c66affSColin Finck case TurboChannel: 69*c2c66affSColin Finck return L"TurboChannel"; 70*c2c66affSColin Finck 71*c2c66affSColin Finck case PCIBus: 72*c2c66affSColin Finck return L"PCIBus"; 73*c2c66affSColin Finck 74*c2c66affSColin Finck case VMEBus: 75*c2c66affSColin Finck return L"VMEBus"; 76*c2c66affSColin Finck 77*c2c66affSColin Finck case NuBus: 78*c2c66affSColin Finck return L"NuBus"; 79*c2c66affSColin Finck 80*c2c66affSColin Finck case PCMCIABus: 81*c2c66affSColin Finck return L"PCMCIABus"; 82*c2c66affSColin Finck 83*c2c66affSColin Finck case CBus: 84*c2c66affSColin Finck return L"CBus"; 85*c2c66affSColin Finck 86*c2c66affSColin Finck case MPIBus: 87*c2c66affSColin Finck return L"MPIBus"; 88*c2c66affSColin Finck 89*c2c66affSColin Finck case MPSABus: 90*c2c66affSColin Finck return L"MPSABus"; 91*c2c66affSColin Finck 92*c2c66affSColin Finck case ProcessorInternal: 93*c2c66affSColin Finck return L"ProcessorInternal"; 94*c2c66affSColin Finck 95*c2c66affSColin Finck case PNPISABus: 96*c2c66affSColin Finck return L"PNPISABus"; 97*c2c66affSColin Finck 98*c2c66affSColin Finck case PNPBus: 99*c2c66affSColin Finck return L"PNPBus"; 100*c2c66affSColin Finck 101*c2c66affSColin Finck case Vmcs: 102*c2c66affSColin Finck return L"Vmcs"; 103*c2c66affSColin Finck 104*c2c66affSColin Finck default: 105*c2c66affSColin Finck DPRINT1("Invalid bus type: %d\n", IfType); 106*c2c66affSColin Finck return NULL; 107*c2c66affSColin Finck } 108*c2c66affSColin Finck } 109*c2c66affSColin Finck 110*c2c66affSColin Finck VOID 111*c2c66affSColin Finck NTAPI 112*c2c66affSColin Finck IopReportTargetDeviceChangeAsyncWorker(PVOID Context) 113*c2c66affSColin Finck { 114*c2c66affSColin Finck PINTERNAL_WORK_QUEUE_ITEM Item; 115*c2c66affSColin Finck 116*c2c66affSColin Finck Item = (PINTERNAL_WORK_QUEUE_ITEM)Context; 117*c2c66affSColin Finck PpSetCustomTargetEvent(Item->PhysicalDeviceObject, NULL, NULL, Item->Callback, Item->Context, Item->NotificationStructure); 118*c2c66affSColin Finck ObDereferenceObject(Item->PhysicalDeviceObject); 119*c2c66affSColin Finck ExFreePoolWithTag(Context, ' pP'); 120*c2c66affSColin Finck } 121*c2c66affSColin Finck 122*c2c66affSColin Finck NTSTATUS 123*c2c66affSColin Finck PpSetCustomTargetEvent(IN PDEVICE_OBJECT DeviceObject, 124*c2c66affSColin Finck IN OUT PKEVENT SyncEvent OPTIONAL, 125*c2c66affSColin Finck IN OUT PNTSTATUS SyncStatus OPTIONAL, 126*c2c66affSColin Finck IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL, 127*c2c66affSColin Finck IN PVOID Context OPTIONAL, 128*c2c66affSColin Finck IN PTARGET_DEVICE_CUSTOM_NOTIFICATION NotificationStructure) 129*c2c66affSColin Finck { 130*c2c66affSColin Finck ASSERT(NotificationStructure != NULL); 131*c2c66affSColin Finck ASSERT(DeviceObject != NULL); 132*c2c66affSColin Finck 133*c2c66affSColin Finck if (SyncEvent) 134*c2c66affSColin Finck { 135*c2c66affSColin Finck ASSERT(SyncStatus); 136*c2c66affSColin Finck *SyncStatus = STATUS_PENDING; 137*c2c66affSColin Finck } 138*c2c66affSColin Finck 139*c2c66affSColin Finck /* That call is totally wrong but notifications handler must be fixed first */ 140*c2c66affSColin Finck IopNotifyPlugPlayNotification(DeviceObject, 141*c2c66affSColin Finck EventCategoryTargetDeviceChange, 142*c2c66affSColin Finck &GUID_PNP_CUSTOM_NOTIFICATION, 143*c2c66affSColin Finck NotificationStructure, 144*c2c66affSColin Finck NULL); 145*c2c66affSColin Finck 146*c2c66affSColin Finck if (SyncEvent) 147*c2c66affSColin Finck { 148*c2c66affSColin Finck KeSetEvent(SyncEvent, IO_NO_INCREMENT, FALSE); 149*c2c66affSColin Finck *SyncStatus = STATUS_SUCCESS; 150*c2c66affSColin Finck } 151*c2c66affSColin Finck 152*c2c66affSColin Finck return STATUS_SUCCESS; 153*c2c66affSColin Finck } 154*c2c66affSColin Finck 155*c2c66affSColin Finck /* PUBLIC FUNCTIONS **********************************************************/ 156*c2c66affSColin Finck 157*c2c66affSColin Finck /* 158*c2c66affSColin Finck * @implemented 159*c2c66affSColin Finck */ 160*c2c66affSColin Finck NTSTATUS 161*c2c66affSColin Finck NTAPI 162*c2c66affSColin Finck IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject, 163*c2c66affSColin Finck IN INTERFACE_TYPE LegacyBusType, 164*c2c66affSColin Finck IN ULONG BusNumber, 165*c2c66affSColin Finck IN ULONG SlotNumber, 166*c2c66affSColin Finck IN PCM_RESOURCE_LIST ResourceList, 167*c2c66affSColin Finck IN PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements OPTIONAL, 168*c2c66affSColin Finck IN BOOLEAN ResourceAssigned, 169*c2c66affSColin Finck IN OUT PDEVICE_OBJECT *DeviceObject OPTIONAL) 170*c2c66affSColin Finck { 171*c2c66affSColin Finck PDEVICE_NODE DeviceNode; 172*c2c66affSColin Finck PDEVICE_OBJECT Pdo; 173*c2c66affSColin Finck NTSTATUS Status; 174*c2c66affSColin Finck HANDLE InstanceKey; 175*c2c66affSColin Finck ULONG RequiredLength; 176*c2c66affSColin Finck UNICODE_STRING ValueName, ServiceName; 177*c2c66affSColin Finck WCHAR HardwareId[256]; 178*c2c66affSColin Finck PWCHAR IfString; 179*c2c66affSColin Finck ULONG IdLength; 180*c2c66affSColin Finck 181*c2c66affSColin Finck DPRINT("IoReportDetectedDevice (DeviceObject %p, *DeviceObject %p)\n", 182*c2c66affSColin Finck DeviceObject, DeviceObject ? *DeviceObject : NULL); 183*c2c66affSColin Finck 184*c2c66affSColin Finck ServiceName = DriverObject->DriverExtension->ServiceKeyName; 185*c2c66affSColin Finck 186*c2c66affSColin Finck /* If the interface type is unknown, treat it as internal */ 187*c2c66affSColin Finck if (LegacyBusType == InterfaceTypeUndefined) 188*c2c66affSColin Finck LegacyBusType = Internal; 189*c2c66affSColin Finck 190*c2c66affSColin Finck /* Get the string equivalent of the interface type */ 191*c2c66affSColin Finck IfString = IopGetInterfaceTypeString(LegacyBusType); 192*c2c66affSColin Finck 193*c2c66affSColin Finck /* If NULL is returned then it's a bad type */ 194*c2c66affSColin Finck if (!IfString) 195*c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 196*c2c66affSColin Finck 197*c2c66affSColin Finck /* We use the caller's PDO if they supplied one */ 198*c2c66affSColin Finck if (DeviceObject && *DeviceObject) 199*c2c66affSColin Finck { 200*c2c66affSColin Finck Pdo = *DeviceObject; 201*c2c66affSColin Finck } 202*c2c66affSColin Finck else 203*c2c66affSColin Finck { 204*c2c66affSColin Finck /* Create the PDO */ 205*c2c66affSColin Finck Status = PnpRootCreateDevice(&ServiceName, 206*c2c66affSColin Finck NULL, 207*c2c66affSColin Finck &Pdo, 208*c2c66affSColin Finck NULL); 209*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 210*c2c66affSColin Finck { 211*c2c66affSColin Finck DPRINT("PnpRootCreateDevice() failed (Status 0x%08lx)\n", Status); 212*c2c66affSColin Finck return Status; 213*c2c66affSColin Finck } 214*c2c66affSColin Finck } 215*c2c66affSColin Finck 216*c2c66affSColin Finck /* Create the device node for the new PDO */ 217*c2c66affSColin Finck Status = IopCreateDeviceNode(IopRootDeviceNode, 218*c2c66affSColin Finck Pdo, 219*c2c66affSColin Finck NULL, 220*c2c66affSColin Finck &DeviceNode); 221*c2c66affSColin Finck 222*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 223*c2c66affSColin Finck { 224*c2c66affSColin Finck DPRINT("IopCreateDeviceNode() failed (Status 0x%08lx)\n", Status); 225*c2c66affSColin Finck return Status; 226*c2c66affSColin Finck } 227*c2c66affSColin Finck 228*c2c66affSColin Finck /* We're enumerated already */ 229*c2c66affSColin Finck IopDeviceNodeSetFlag(DeviceNode, DNF_ENUMERATED); 230*c2c66affSColin Finck 231*c2c66affSColin Finck /* We don't call AddDevice for devices reported this way */ 232*c2c66affSColin Finck IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED); 233*c2c66affSColin Finck 234*c2c66affSColin Finck /* We don't send IRP_MN_START_DEVICE */ 235*c2c66affSColin Finck IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED); 236*c2c66affSColin Finck 237*c2c66affSColin Finck /* We need to get device IDs */ 238*c2c66affSColin Finck #if 0 239*c2c66affSColin Finck IopDeviceNodeSetFlag(DeviceNode, DNF_NEED_QUERY_IDS); 240*c2c66affSColin Finck #endif 241*c2c66affSColin Finck 242*c2c66affSColin Finck /* This is a legacy driver for this device */ 243*c2c66affSColin Finck IopDeviceNodeSetFlag(DeviceNode, DNF_LEGACY_DRIVER); 244*c2c66affSColin Finck 245*c2c66affSColin Finck /* Perform a manual configuration of our device */ 246*c2c66affSColin Finck IopActionInterrogateDeviceStack(DeviceNode, DeviceNode->Parent); 247*c2c66affSColin Finck IopActionConfigureChildServices(DeviceNode, DeviceNode->Parent); 248*c2c66affSColin Finck 249*c2c66affSColin Finck /* Open a handle to the instance path key */ 250*c2c66affSColin Finck /* REG_OPTION_VOLATILE is a HACK!!! */ 251*c2c66affSColin Finck Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_VOLATILE, &InstanceKey); 252*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 253*c2c66affSColin Finck return Status; 254*c2c66affSColin Finck 255*c2c66affSColin Finck /* Add DETECTEDInterfaceType\DriverName */ 256*c2c66affSColin Finck IdLength = 0; 257*c2c66affSColin Finck IdLength += swprintf(&HardwareId[IdLength], 258*c2c66affSColin Finck L"DETECTED%ls\\%wZ", 259*c2c66affSColin Finck IfString, 260*c2c66affSColin Finck &ServiceName); 261*c2c66affSColin Finck IdLength++; 262*c2c66affSColin Finck 263*c2c66affSColin Finck /* Add DETECTED\DriverName */ 264*c2c66affSColin Finck IdLength += swprintf(&HardwareId[IdLength], 265*c2c66affSColin Finck L"DETECTED\\%wZ", 266*c2c66affSColin Finck &ServiceName); 267*c2c66affSColin Finck IdLength++; 268*c2c66affSColin Finck 269*c2c66affSColin Finck /* Terminate the string with another null */ 270*c2c66affSColin Finck HardwareId[IdLength++] = UNICODE_NULL; 271*c2c66affSColin Finck 272*c2c66affSColin Finck /* Store the value for CompatibleIDs */ 273*c2c66affSColin Finck RtlInitUnicodeString(&ValueName, L"CompatibleIDs"); 274*c2c66affSColin Finck Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_MULTI_SZ, HardwareId, IdLength * sizeof(WCHAR)); 275*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 276*c2c66affSColin Finck { 277*c2c66affSColin Finck DPRINT("Failed to write the compatible IDs: 0x%x\n", Status); 278*c2c66affSColin Finck ZwClose(InstanceKey); 279*c2c66affSColin Finck return Status; 280*c2c66affSColin Finck } 281*c2c66affSColin Finck 282*c2c66affSColin Finck /* Add a hardware ID if the driver didn't report one */ 283*c2c66affSColin Finck RtlInitUnicodeString(&ValueName, L"HardwareID"); 284*c2c66affSColin Finck if (ZwQueryValueKey(InstanceKey, &ValueName, KeyValueBasicInformation, NULL, 0, &RequiredLength) == STATUS_OBJECT_NAME_NOT_FOUND) 285*c2c66affSColin Finck { 286*c2c66affSColin Finck /* Just use our most specific compatible ID */ 287*c2c66affSColin Finck IdLength = 0; 288*c2c66affSColin Finck IdLength += swprintf(&HardwareId[IdLength], 289*c2c66affSColin Finck L"DETECTED%ls\\%wZ", 290*c2c66affSColin Finck IfString, 291*c2c66affSColin Finck &ServiceName); 292*c2c66affSColin Finck IdLength++; 293*c2c66affSColin Finck 294*c2c66affSColin Finck HardwareId[IdLength++] = UNICODE_NULL; 295*c2c66affSColin Finck 296*c2c66affSColin Finck /* Write the value to the registry */ 297*c2c66affSColin Finck Status = ZwSetValueKey(InstanceKey, &ValueName, 0, REG_MULTI_SZ, HardwareId, IdLength * sizeof(WCHAR)); 298*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 299*c2c66affSColin Finck { 300*c2c66affSColin Finck DPRINT("Failed to write the hardware ID: 0x%x\n", Status); 301*c2c66affSColin Finck ZwClose(InstanceKey); 302*c2c66affSColin Finck return Status; 303*c2c66affSColin Finck } 304*c2c66affSColin Finck } 305*c2c66affSColin Finck 306*c2c66affSColin Finck /* Assign the resources to the device node */ 307*c2c66affSColin Finck DeviceNode->BootResources = ResourceList; 308*c2c66affSColin Finck DeviceNode->ResourceRequirements = ResourceRequirements; 309*c2c66affSColin Finck 310*c2c66affSColin Finck /* Set appropriate flags */ 311*c2c66affSColin Finck if (DeviceNode->BootResources) 312*c2c66affSColin Finck IopDeviceNodeSetFlag(DeviceNode, DNF_HAS_BOOT_CONFIG); 313*c2c66affSColin Finck 314*c2c66affSColin Finck if (!DeviceNode->ResourceRequirements && !DeviceNode->BootResources) 315*c2c66affSColin Finck IopDeviceNodeSetFlag(DeviceNode, DNF_NO_RESOURCE_REQUIRED); 316*c2c66affSColin Finck 317*c2c66affSColin Finck /* Write the resource information to the registry */ 318*c2c66affSColin Finck IopSetDeviceInstanceData(InstanceKey, DeviceNode); 319*c2c66affSColin Finck 320*c2c66affSColin Finck /* If the caller didn't get the resources assigned for us, do it now */ 321*c2c66affSColin Finck if (!ResourceAssigned) 322*c2c66affSColin Finck { 323*c2c66affSColin Finck Status = IopAssignDeviceResources(DeviceNode); 324*c2c66affSColin Finck 325*c2c66affSColin Finck /* See if we failed */ 326*c2c66affSColin Finck if (!NT_SUCCESS(Status)) 327*c2c66affSColin Finck { 328*c2c66affSColin Finck DPRINT("Assigning resources failed: 0x%x\n", Status); 329*c2c66affSColin Finck ZwClose(InstanceKey); 330*c2c66affSColin Finck return Status; 331*c2c66affSColin Finck } 332*c2c66affSColin Finck } 333*c2c66affSColin Finck 334*c2c66affSColin Finck /* Close the instance key handle */ 335*c2c66affSColin Finck ZwClose(InstanceKey); 336*c2c66affSColin Finck 337*c2c66affSColin Finck /* Register the given DO with PnP root if required */ 338*c2c66affSColin Finck if (DeviceObject && *DeviceObject) 339*c2c66affSColin Finck PnpRootRegisterDevice(*DeviceObject); 340*c2c66affSColin Finck 341*c2c66affSColin Finck /* Report the device's enumeration to umpnpmgr */ 342*c2c66affSColin Finck IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED, 343*c2c66affSColin Finck &DeviceNode->InstancePath); 344*c2c66affSColin Finck 345*c2c66affSColin Finck /* Report the device's arrival to umpnpmgr */ 346*c2c66affSColin Finck IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, 347*c2c66affSColin Finck &DeviceNode->InstancePath); 348*c2c66affSColin Finck 349*c2c66affSColin Finck DPRINT("Reported device: %S (%wZ)\n", HardwareId, &DeviceNode->InstancePath); 350*c2c66affSColin Finck 351*c2c66affSColin Finck /* Return the PDO */ 352*c2c66affSColin Finck if (DeviceObject) *DeviceObject = Pdo; 353*c2c66affSColin Finck 354*c2c66affSColin Finck return STATUS_SUCCESS; 355*c2c66affSColin Finck } 356*c2c66affSColin Finck 357*c2c66affSColin Finck /* 358*c2c66affSColin Finck * @halfplemented 359*c2c66affSColin Finck */ 360*c2c66affSColin Finck NTSTATUS 361*c2c66affSColin Finck NTAPI 362*c2c66affSColin Finck IoReportResourceForDetection(IN PDRIVER_OBJECT DriverObject, 363*c2c66affSColin Finck IN PCM_RESOURCE_LIST DriverList OPTIONAL, 364*c2c66affSColin Finck IN ULONG DriverListSize OPTIONAL, 365*c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject OPTIONAL, 366*c2c66affSColin Finck IN PCM_RESOURCE_LIST DeviceList OPTIONAL, 367*c2c66affSColin Finck IN ULONG DeviceListSize OPTIONAL, 368*c2c66affSColin Finck OUT PBOOLEAN ConflictDetected) 369*c2c66affSColin Finck { 370*c2c66affSColin Finck PCM_RESOURCE_LIST ResourceList; 371*c2c66affSColin Finck NTSTATUS Status; 372*c2c66affSColin Finck 373*c2c66affSColin Finck *ConflictDetected = FALSE; 374*c2c66affSColin Finck 375*c2c66affSColin Finck if (!DriverList && !DeviceList) 376*c2c66affSColin Finck return STATUS_INVALID_PARAMETER; 377*c2c66affSColin Finck 378*c2c66affSColin Finck /* Find the real list */ 379*c2c66affSColin Finck if (!DriverList) 380*c2c66affSColin Finck ResourceList = DeviceList; 381*c2c66affSColin Finck else 382*c2c66affSColin Finck ResourceList = DriverList; 383*c2c66affSColin Finck 384*c2c66affSColin Finck /* Look for a resource conflict */ 385*c2c66affSColin Finck Status = IopDetectResourceConflict(ResourceList, FALSE, NULL); 386*c2c66affSColin Finck if (Status == STATUS_CONFLICTING_ADDRESSES) 387*c2c66affSColin Finck { 388*c2c66affSColin Finck /* Oh noes */ 389*c2c66affSColin Finck *ConflictDetected = TRUE; 390*c2c66affSColin Finck } 391*c2c66affSColin Finck else if (NT_SUCCESS(Status)) 392*c2c66affSColin Finck { 393*c2c66affSColin Finck /* Looks like we're good to go */ 394*c2c66affSColin Finck 395*c2c66affSColin Finck /* TODO: Claim the resources in the ResourceMap */ 396*c2c66affSColin Finck } 397*c2c66affSColin Finck 398*c2c66affSColin Finck return Status; 399*c2c66affSColin Finck } 400*c2c66affSColin Finck 401*c2c66affSColin Finck VOID 402*c2c66affSColin Finck NTAPI 403*c2c66affSColin Finck IopSetEvent(IN PVOID Context) 404*c2c66affSColin Finck { 405*c2c66affSColin Finck PKEVENT Event = Context; 406*c2c66affSColin Finck 407*c2c66affSColin Finck /* Set the event */ 408*c2c66affSColin Finck KeSetEvent(Event, IO_NO_INCREMENT, FALSE); 409*c2c66affSColin Finck } 410*c2c66affSColin Finck 411*c2c66affSColin Finck /* 412*c2c66affSColin Finck * @implemented 413*c2c66affSColin Finck */ 414*c2c66affSColin Finck NTSTATUS 415*c2c66affSColin Finck NTAPI 416*c2c66affSColin Finck IoReportTargetDeviceChange(IN PDEVICE_OBJECT PhysicalDeviceObject, 417*c2c66affSColin Finck IN PVOID NotificationStructure) 418*c2c66affSColin Finck { 419*c2c66affSColin Finck KEVENT NotifyEvent; 420*c2c66affSColin Finck NTSTATUS Status, NotifyStatus; 421*c2c66affSColin Finck PTARGET_DEVICE_CUSTOM_NOTIFICATION notifyStruct = (PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure; 422*c2c66affSColin Finck 423*c2c66affSColin Finck ASSERT(notifyStruct); 424*c2c66affSColin Finck 425*c2c66affSColin Finck /* Check for valid PDO */ 426*c2c66affSColin Finck if (!IopIsValidPhysicalDeviceObject(PhysicalDeviceObject)) 427*c2c66affSColin Finck { 428*c2c66affSColin Finck KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG)PhysicalDeviceObject, 0, 0); 429*c2c66affSColin Finck } 430*c2c66affSColin Finck 431*c2c66affSColin Finck /* FileObject must be null. PnP will fill in it */ 432*c2c66affSColin Finck ASSERT(notifyStruct->FileObject == NULL); 433*c2c66affSColin Finck 434*c2c66affSColin Finck /* Do not handle system PnP events */ 435*c2c66affSColin Finck if ((RtlCompareMemory(&(notifyStruct->Event), &(GUID_TARGET_DEVICE_QUERY_REMOVE), sizeof(GUID)) != sizeof(GUID)) || 436*c2c66affSColin Finck (RtlCompareMemory(&(notifyStruct->Event), &(GUID_TARGET_DEVICE_REMOVE_CANCELLED), sizeof(GUID)) != sizeof(GUID)) || 437*c2c66affSColin Finck (RtlCompareMemory(&(notifyStruct->Event), &(GUID_TARGET_DEVICE_REMOVE_COMPLETE), sizeof(GUID)) != sizeof(GUID))) 438*c2c66affSColin Finck { 439*c2c66affSColin Finck return STATUS_INVALID_DEVICE_REQUEST; 440*c2c66affSColin Finck } 441*c2c66affSColin Finck 442*c2c66affSColin Finck if (notifyStruct->Version != 1) 443*c2c66affSColin Finck { 444*c2c66affSColin Finck return STATUS_INVALID_DEVICE_REQUEST; 445*c2c66affSColin Finck } 446*c2c66affSColin Finck 447*c2c66affSColin Finck /* Initialize even that will let us know when PnP will have finished notify */ 448*c2c66affSColin Finck KeInitializeEvent(&NotifyEvent, NotificationEvent, FALSE); 449*c2c66affSColin Finck 450*c2c66affSColin Finck Status = PpSetCustomTargetEvent(PhysicalDeviceObject, &NotifyEvent, &NotifyStatus, NULL, NULL, notifyStruct); 451*c2c66affSColin Finck /* If no error, wait for the notify to end and return the status of the notify and not of the event */ 452*c2c66affSColin Finck if (NT_SUCCESS(Status)) 453*c2c66affSColin Finck { 454*c2c66affSColin Finck KeWaitForSingleObject(&NotifyEvent, Executive, KernelMode, FALSE, NULL); 455*c2c66affSColin Finck Status = NotifyStatus; 456*c2c66affSColin Finck } 457*c2c66affSColin Finck 458*c2c66affSColin Finck return Status; 459*c2c66affSColin Finck } 460*c2c66affSColin Finck 461*c2c66affSColin Finck /* 462*c2c66affSColin Finck * @implemented 463*c2c66affSColin Finck */ 464*c2c66affSColin Finck NTSTATUS 465*c2c66affSColin Finck NTAPI 466*c2c66affSColin Finck IoReportTargetDeviceChangeAsynchronous(IN PDEVICE_OBJECT PhysicalDeviceObject, 467*c2c66affSColin Finck IN PVOID NotificationStructure, 468*c2c66affSColin Finck IN PDEVICE_CHANGE_COMPLETE_CALLBACK Callback OPTIONAL, 469*c2c66affSColin Finck IN PVOID Context OPTIONAL) 470*c2c66affSColin Finck { 471*c2c66affSColin Finck PINTERNAL_WORK_QUEUE_ITEM Item = NULL; 472*c2c66affSColin Finck PTARGET_DEVICE_CUSTOM_NOTIFICATION notifyStruct = (PTARGET_DEVICE_CUSTOM_NOTIFICATION)NotificationStructure; 473*c2c66affSColin Finck 474*c2c66affSColin Finck ASSERT(notifyStruct); 475*c2c66affSColin Finck 476*c2c66affSColin Finck /* Check for valid PDO */ 477*c2c66affSColin Finck if (!IopIsValidPhysicalDeviceObject(PhysicalDeviceObject)) 478*c2c66affSColin Finck { 479*c2c66affSColin Finck KeBugCheckEx(PNP_DETECTED_FATAL_ERROR, 0x2, (ULONG)PhysicalDeviceObject, 0, 0); 480*c2c66affSColin Finck } 481*c2c66affSColin Finck 482*c2c66affSColin Finck /* FileObject must be null. PnP will fill in it */ 483*c2c66affSColin Finck ASSERT(notifyStruct->FileObject == NULL); 484*c2c66affSColin Finck 485*c2c66affSColin Finck /* Do not handle system PnP events */ 486*c2c66affSColin Finck if ((RtlCompareMemory(&(notifyStruct->Event), &(GUID_TARGET_DEVICE_QUERY_REMOVE), sizeof(GUID)) != sizeof(GUID)) || 487*c2c66affSColin Finck (RtlCompareMemory(&(notifyStruct->Event), &(GUID_TARGET_DEVICE_REMOVE_CANCELLED), sizeof(GUID)) != sizeof(GUID)) || 488*c2c66affSColin Finck (RtlCompareMemory(&(notifyStruct->Event), &(GUID_TARGET_DEVICE_REMOVE_COMPLETE), sizeof(GUID)) != sizeof(GUID))) 489*c2c66affSColin Finck { 490*c2c66affSColin Finck return STATUS_INVALID_DEVICE_REQUEST; 491*c2c66affSColin Finck } 492*c2c66affSColin Finck 493*c2c66affSColin Finck if (notifyStruct->Version != 1) 494*c2c66affSColin Finck { 495*c2c66affSColin Finck return STATUS_INVALID_DEVICE_REQUEST; 496*c2c66affSColin Finck } 497*c2c66affSColin Finck 498*c2c66affSColin Finck /* We need to store all the data given by the caller with the WorkItem, so use our own struct */ 499*c2c66affSColin Finck Item = ExAllocatePoolWithTag(NonPagedPool, sizeof(INTERNAL_WORK_QUEUE_ITEM), ' pP'); 500*c2c66affSColin Finck if (!Item) return STATUS_INSUFFICIENT_RESOURCES; 501*c2c66affSColin Finck 502*c2c66affSColin Finck /* Initialize all stuff */ 503*c2c66affSColin Finck ObReferenceObject(PhysicalDeviceObject); 504*c2c66affSColin Finck Item->NotificationStructure = notifyStruct; 505*c2c66affSColin Finck Item->PhysicalDeviceObject = PhysicalDeviceObject; 506*c2c66affSColin Finck Item->Callback = Callback; 507*c2c66affSColin Finck Item->Context = Context; 508*c2c66affSColin Finck ExInitializeWorkItem(&(Item->WorkItem), IopReportTargetDeviceChangeAsyncWorker, Item); 509*c2c66affSColin Finck 510*c2c66affSColin Finck /* Finally, queue the item, our work here is done */ 511*c2c66affSColin Finck ExQueueWorkItem(&(Item->WorkItem), DelayedWorkQueue); 512*c2c66affSColin Finck 513*c2c66affSColin Finck return STATUS_PENDING; 514*c2c66affSColin Finck } 515