/* looks alot like acpi_bus_walk doesnt it */ NTSTATUS ACPIEnumerateDevices(PFDO_DEVICE_DATA DeviceExtension) { ULONG Count = 0; struct acpi_device *Device = acpi_root; while(Device) { if (Device->status.present && Device->status.enabled && Device->flags.hardware_id) { Bus_PlugInDevice(Device, DeviceExtension); Count++; } if (HAS_CHILDREN(Device)) { Device = NODE_TO_DEVICE(Device->children.next); continue; } if (HAS_SIBLINGS(Device)) { Device = NODE_TO_DEVICE(Device->node.next); continue; } while ((Device = Device->parent)) { if (HAS_SIBLINGS(Device)) { Device = NODE_TO_DEVICE(Device->node.next); break; } } } DPRINT("acpi device count: %d\n", Count); return STATUS_SUCCESS; }
NTSTATUS Bus_DoStaticEnumeration( IN WDFDEVICE Device ) /*++ Routine Description: The routine enables you to statically enumerate child devices during start instead of running the enum.exe/notify.exe to enumerate toaster devices. In order to statically enumerate, user must specify the number of toasters in the Toaster Bus driver's device registry. The default value is zero. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root\SYSTEM\0002\ Device Parameters NumberOfToasters:REG_DWORD:2 You can also configure this value in the Toaster Bus Inf file. --*/ { WDFKEY hKey = NULL; NTSTATUS status; ULONG value, i; DECLARE_CONST_UNICODE_STRING(valueName, L"NumberOfToasters"); // // If the registry value doesn't exist, we will use the // hardcoded default number. // value = DEF_STATICALLY_ENUMERATED_TOASTERS; // // Open the device registry and read the "NumberOfToasters" value. // status = WdfDeviceOpenRegistryKey(Device, PLUGPLAY_REGKEY_DEVICE, STANDARD_RIGHTS_ALL, NULL, // PWDF_OBJECT_ATTRIBUTES &hKey); if (NT_SUCCESS (status)) { status = WdfRegistryQueryULong(hKey, &valueName, &value); WdfRegistryClose(hKey); hKey = NULL; // Set hKey to NULL to catch any accidental subsequent use. if (NT_SUCCESS (status)) { // // Make sure it doesn't exceed the max. This is required to prevent // denial of service by enumerating large number of child devices. // value = min(value, MAX_STATICALLY_ENUMERATED_TOASTERS); }else { return STATUS_SUCCESS; // This is an optional property. } } KdPrint(("Enumerating %d toaster devices\n", value)); for(i=1; i<= value; i++) { // // Value of i is used as serial number. // status = Bus_PlugInDevice(Device, BUS_HARDWARE_IDS, BUS_HARDWARE_IDS_LENGTH / sizeof(WCHAR), i ); } return status; }
VOID Bus_EvtIoDeviceControl( IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t OutputBufferLength, IN size_t InputBufferLength, IN ULONG IoControlCode ) /*++ Routine Description: Handle user mode PlugIn, UnPlug and device Eject requests. Arguments: Queue - Handle to the framework queue object that is associated with the I/O request. Request - Handle to a framework request object. This one represents the IRP_MJ_DEVICE_CONTROL IRP received by the framework. OutputBufferLength - Length, in bytes, of the request's output buffer, if an output buffer is available. InputBufferLength - Length, in bytes, of the request's input buffer, if an input buffer is available. IoControlCode - Driver-defined or system-defined I/O control code (IOCTL) that is associated with the request. Return Value: VOID --*/ { NTSTATUS status = STATUS_INVALID_PARAMETER; WDFDEVICE hDevice; size_t length = 0; PBUSENUM_PLUGIN_HARDWARE plugIn = NULL; PBUSENUM_UNPLUG_HARDWARE unPlug = NULL; PBUSENUM_EJECT_HARDWARE eject = NULL; UNREFERENCED_PARAMETER(OutputBufferLength); PAGED_CODE (); hDevice = WdfIoQueueGetDevice(Queue); KdPrint(("Bus_EvtIoDeviceControl: 0x%p\n", hDevice)); switch (IoControlCode) { case IOCTL_BUSENUM_PLUGIN_HARDWARE: status = WdfRequestRetrieveInputBuffer (Request, sizeof (BUSENUM_PLUGIN_HARDWARE) + (sizeof(UNICODE_NULL) * 2), // 2 for double NULL termination (MULTI_SZ) &plugIn, &length); if( !NT_SUCCESS(status) ) { KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status)); break; } ASSERT(length == InputBufferLength); if (sizeof (BUSENUM_PLUGIN_HARDWARE) == plugIn->Size) { length = (InputBufferLength - sizeof (BUSENUM_PLUGIN_HARDWARE))/sizeof(WCHAR); // // Make sure the IDs is two NULL terminated. // if ((UNICODE_NULL != plugIn->HardwareIDs[length - 1]) || (UNICODE_NULL != plugIn->HardwareIDs[length - 2])) { status = STATUS_INVALID_PARAMETER; break; } status = Bus_PlugInDevice( hDevice, plugIn->HardwareIDs, length, plugIn->SerialNo ); } break; case IOCTL_BUSENUM_UNPLUG_HARDWARE: status = WdfRequestRetrieveInputBuffer( Request, sizeof(BUSENUM_UNPLUG_HARDWARE), &unPlug, &length ); if( !NT_SUCCESS(status) ) { KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status)); break; } if (unPlug->Size == InputBufferLength) { status= Bus_UnPlugDevice(hDevice, unPlug->SerialNo ); } break; case IOCTL_BUSENUM_EJECT_HARDWARE: status = WdfRequestRetrieveInputBuffer (Request, sizeof (BUSENUM_EJECT_HARDWARE), &eject, &length); if( !NT_SUCCESS(status) ) { KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status)); break; } if (eject->Size == InputBufferLength) { status= Bus_EjectDevice(hDevice, eject->SerialNo); } break; default: break; // default status is STATUS_INVALID_PARAMETER } WdfRequestCompleteWithInformation(Request, status, length); }
NTSTATUS Bus_IoCtl ( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) /*++ Routine Description: Handle user mode PlugIn, UnPlug and device Eject requests. Arguments: DeviceObject - pointer to a device object. Irp - pointer to an I/O Request Packet. Return Value: NT status code --*/ { PIO_STACK_LOCATION irpStack; NTSTATUS status; ULONG inlen; PFDO_DEVICE_DATA fdoData; PVOID buffer; PCOMMON_DEVICE_DATA commonData; PAGED_CODE (); commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; // // We only allow create/close requests for the FDO. // That is the bus itself. // if (!commonData->IsFDO) { Irp->IoStatus.Status = status = STATUS_INVALID_DEVICE_REQUEST; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; Bus_IncIoCount (fdoData); // // Check to see whether the bus is removed // if (fdoData->DevicePnPState == Deleted) { status = STATUS_NO_SUCH_DEVICE; goto END; } irpStack = IoGetCurrentIrpStackLocation (Irp); buffer = Irp->AssociatedIrp.SystemBuffer; inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength; status = STATUS_INVALID_PARAMETER; switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_BUSENUM_PLUGIN_HARDWARE: if ( // // Make sure it has at least two nulls and the size // field is set to the declared size of the struct // ((sizeof (BUSENUM_PLUGIN_HARDWARE) + sizeof(UNICODE_NULL) * 2) <= inlen) && // // The size field should be set to the sizeof the struct as declared // and *not* the size of the struct plus the multi_sz // (sizeof (BUSENUM_PLUGIN_HARDWARE) == ((PBUSENUM_PLUGIN_HARDWARE) buffer)->Size)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n")); status= Bus_PlugInDevice((PBUSENUM_PLUGIN_HARDWARE)buffer, inlen, fdoData); } break; case IOCTL_BUSENUM_UNPLUG_HARDWARE: if ((sizeof (BUSENUM_UNPLUG_HARDWARE) == inlen) && (((PBUSENUM_UNPLUG_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n")); status= Bus_UnPlugDevice( (PBUSENUM_UNPLUG_HARDWARE)buffer, fdoData); } break; case IOCTL_BUSENUM_EJECT_HARDWARE: if ((sizeof (BUSENUM_EJECT_HARDWARE) == inlen) && (((PBUSENUM_EJECT_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n")); status= Bus_EjectDevice((PBUSENUM_EJECT_HARDWARE)buffer, fdoData); } break; default: break; // default status is STATUS_INVALID_PARAMETER } Irp->IoStatus.Information = 0; END: Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); Bus_DecIoCount (fdoData); return status; }
NTSTATUS Bus_IoCtl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION irpStack; NTSTATUS status; ULONG inlen; PFDO_DEVICE_DATA fdoData; PVOID buffer; PCOMMON_DEVICE_DATA commonData; commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; if (!commonData->IsFDO) { Irp->IoStatus.Status = status = STATUS_INVALID_DEVICE_REQUEST; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; if (fdoData->DevicePnPState == Deleted) { Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } Bus_IncIoCount(fdoData); irpStack = IoGetCurrentIrpStackLocation(Irp); buffer = Irp->AssociatedIrp.SystemBuffer; inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength; status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_BUSENUM_PLUGIN_HARDWARE: if ((sizeof(BUSENUM_PLUGIN_HARDWARE) == inlen) && (((PBUSENUM_PLUGIN_HARDWARE) buffer)->Size == inlen)) { Bus_KdPrint(("PlugIn called\n")); status = Bus_PlugInDevice((PBUSENUM_PLUGIN_HARDWARE) buffer, inlen, fdoData); } break; case IOCTL_BUSENUM_UNPLUG_HARDWARE: if ((sizeof(BUSENUM_UNPLUG_HARDWARE) == inlen) && (((PBUSENUM_UNPLUG_HARDWARE) buffer)->Size == inlen)) { Bus_KdPrint(("UnPlug called\n")); status = Bus_UnPlugDevice((PBUSENUM_UNPLUG_HARDWARE) buffer, fdoData); } break; case IOCTL_BUSENUM_EJECT_HARDWARE: if ((sizeof(BUSENUM_EJECT_HARDWARE) == inlen) && (((PBUSENUM_EJECT_HARDWARE) buffer)->Size == inlen)) { Bus_KdPrint(("Eject called\n")); status = Bus_EjectDevice((PBUSENUM_EJECT_HARDWARE) buffer, fdoData); } break; case IOCTL_BUSENUM_REPORT_HARDWARE: if ((sizeof(BUSENUM_REPORT_HARDWARE) == inlen) && (((PBUSENUM_REPORT_HARDWARE) buffer)->Size == inlen)) { status = Bus_ReportDevice((PBUSENUM_REPORT_HARDWARE) buffer, fdoData, buffer); if (NT_SUCCESS(status)) Irp->IoStatus.Information = RUMBLE_SIZE; } break; default: break; // default status is STATUS_INVALID_PARAMETER } Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); Bus_DecIoCount(fdoData); return status; }