VOID Bus_CancelIrp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PPDO_DEVICE_DATA pdoData = (PPDO_DEVICE_DATA) DeviceObject->DeviceExtension; PLIST_ENTRY le = NULL; PIRP cancelIrp = NULL; KIRQL irql; Bus_KdPrint(("Bus_CancelIrp : %p", Irp)); IoReleaseCancelSpinLock(Irp->CancelIrql); KeAcquireSpinLock(&pdoData->PendingQueueLock, &irql); for (le = pdoData->PendingQueue.Flink; le != &pdoData->PendingQueue; le = le->Flink) { PPENDING_IRP lr = CONTAINING_RECORD(le, PENDING_IRP, Link); cancelIrp = lr->Irp; if (cancelIrp->Cancel && cancelIrp == Irp) { Bus_KdPrint(("PendingQueue : %p", cancelIrp)); RemoveEntryList(le); break; } cancelIrp = NULL; } if (cancelIrp == NULL) { for (le = pdoData->HoldingQueue.Flink; le != &pdoData->HoldingQueue; le = le->Flink) { PPENDING_IRP lr = CONTAINING_RECORD(le, PENDING_IRP, Link); cancelIrp = lr->Irp; if (cancelIrp->Cancel && cancelIrp == Irp) { Bus_KdPrint(("HoldingQueue : %p", cancelIrp)); RemoveEntryList(le); break; } cancelIrp = NULL; } } KeReleaseSpinLock(&pdoData->PendingQueueLock, irql); if (cancelIrp) { cancelIrp->IoStatus.Status = STATUS_CANCELLED; cancelIrp->IoStatus.Information = 0; IoCompleteRequest(cancelIrp, IO_NO_INCREMENT); } }
NTSTATUS Bus_CreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION irpStack; NTSTATUS status; PFDO_DEVICE_DATA fdoData; PCOMMON_DEVICE_DATA commonData; PAGED_CODE(); 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); switch (irpStack->MajorFunction) { case IRP_MJ_CREATE: Bus_KdPrint(("Create \n")); status = STATUS_SUCCESS; break; case IRP_MJ_CLOSE: Bus_KdPrint(("Close \n")); status = STATUS_SUCCESS; break; default: status = STATUS_INVALID_DEVICE_REQUEST; break; } Irp->IoStatus.Information = 0; Irp->IoStatus.Status = status; IoCompleteRequest(Irp, IO_NO_INCREMENT); Bus_DecIoCount(fdoData); return status; }
BOOLEAN Bus_GetCrispinessLevel( __in PVOID Context, __out PUCHAR Level ) /*++ Routine Description: This routine gets the current crispiness level of the toaster. Arguments: Context pointer to PDO device extension Level crispiness level of the device Return Value: TRUE or FALSE --*/ { // // Validate the context to see if it's really a pointer // to PDO's device extension. You can store some kind // of signature in the PDO for this purpose // Bus_KdPrint ((PPDO_DEVICE_DATA)Context, BUS_DBG_PNP_TRACE, ("GetCrispinessLevel\n")); *Level = 10; return TRUE; }
BOOLEAN Bus_IsSafetyLockEnabled( IN PVOID Context ) /*++ Routine Description: Routine to check whether safety lock is enabled Arguments: Context pointer to PDO device extension Return Value: TRUE or FALSE --*/ { #if !DBG UNREFERENCED_PARAMETER(Context); #endif Bus_KdPrint ((PPDO_DEVICE_DATA)Context, BUS_DBG_PNP_TRACE, ("\n")); return TRUE; }
BOOLEAN Bus_SetCrispinessLevel( IN PVOID Context, IN UCHAR Level ) /*++ Routine Description: This routine sets the current crispiness level of the toaster. Arguments: Context pointer to PDO device extension Level crispiness level of the device Return Value: TRUE or FALSE --*/ { UNREFERENCED_PARAMETER(Level); #if !DBG UNREFERENCED_PARAMETER(Context); #endif Bus_KdPrint ((PPDO_DEVICE_DATA)Context, BUS_DBG_PNP_TRACE, ("\n")); return TRUE; }
NTSTATUS Bus_DestroyPdo(PDEVICE_OBJECT Device, PPDO_DEVICE_DATA PdoData) { PFDO_DEVICE_DATA fdoData; PAGED_CODE(); fdoData = FDO_FROM_PDO(PdoData); fdoData->NumPDOs--; if (PdoData->InterfaceName.Buffer != NULL) { ExFreePool(PdoData->InterfaceName.Buffer); RtlZeroMemory(&PdoData->InterfaceName, sizeof(UNICODE_STRING)); } if (PdoData->HardwareIDs) { ExFreePool(PdoData->HardwareIDs); PdoData->HardwareIDs = NULL; } Bus_KdPrint(("\tDeleting PDO: 0x%p\n", Device)); IoDeleteDevice(Device); return STATUS_SUCCESS; }
NTSTATUS Bus_StartFdo(__in PFDO_DEVICE_DATA FdoData, __in PIRP Irp) { NTSTATUS status; POWER_STATE powerState; UNREFERENCED_PARAMETER(Irp); PAGED_CODE(); status = IoSetDeviceInterfaceState(&FdoData->InterfaceName, TRUE); if (!NT_SUCCESS (status)) { Bus_KdPrint(("IoSetDeviceInterfaceState failed: 0x%x\n", status)); return status; } FdoData->DevicePowerState = PowerDeviceD0; powerState.DeviceState = PowerDeviceD0; PoSetPowerState(FdoData->Self, DevicePowerState, powerState); SET_NEW_PNP_STATE(FdoData, Started); return status; }
NTSTATUS bus_get_ports_status(ioctl_usbvbus_get_ports_status * st, PFDO_DEVICE_DATA fdodata, ULONG *info) { PDEVICE_OBJECT pdo; PPDO_DEVICE_DATA pdodata; NTSTATUS status; PLIST_ENTRY entry; PAGED_CODE (); Bus_KdPrint (fdodata, BUS_DBG_PNP_INFO, ("get ports status\n")); RtlZeroMemory(st, sizeof(*st)); ExAcquireFastMutex (&fdodata->Mutex); for (entry = fdodata->ListOfPDOs.Flink; entry != &fdodata->ListOfPDOs; entry = entry->Flink) { pdodata = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); if (pdodata->SerialNo > 127 || pdodata->SerialNo == 0){ KdPrint(("strange error")); } if(st->max_used_port < (int)pdodata->SerialNo) st->max_used_port = (int)pdodata->SerialNo; st->port_status[pdodata->SerialNo]=1; } ExReleaseFastMutex (&fdodata->Mutex); *info=sizeof(*st); return STATUS_SUCCESS; }
BOOLEAN Bus_SetCrispinessLevel( __in PVOID Context, __in UCHAR Level ) /*++ Routine Description: This routine sets the current crispiness level of the toaster. Arguments: Context pointer to PDO device extension Level crispiness level of the device Return Value: TRUE or FALSE --*/ { Bus_KdPrint ((PPDO_DEVICE_DATA)Context, BUS_DBG_PNP_TRACE, ("SetCrispinessLevel\n")); return TRUE; }
NTSTATUS DriverEntry(__in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath) { Bus_KdPrint(("Driver Entry\n")); ExInitializeNPagedLookasideList(&g_LookAside, NULL, NULL, 0, sizeof(PENDING_IRP), BUSENUM_POOL_TAG, 0); Globals.RegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL); Globals.RegistryPath.Length = RegistryPath->Length; Globals.RegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, Globals.RegistryPath.MaximumLength, BUSENUM_POOL_TAG); if (!Globals.RegistryPath.Buffer) { return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath); DriverObject->MajorFunction [IRP_MJ_CREATE ] = DriverObject->MajorFunction [IRP_MJ_CLOSE ] = Bus_CreateClose; DriverObject->MajorFunction [IRP_MJ_PNP ] = Bus_PnP; DriverObject->MajorFunction [IRP_MJ_POWER ] = Bus_Power; DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL ] = Bus_IoCtl; DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL] = Bus_Internal_IoCtl; DriverObject->DriverUnload = Bus_DriverUnload; DriverObject->DriverExtension->AddDevice = Bus_AddDevice; return STATUS_SUCCESS; }
// // Plug in a NDAS device with a LUR descriptor. // NTSTATUS LSBus_AddTarget( PFDO_DEVICE_DATA FdoData, PNDASBUS_ADD_TARGET_DATA AddTargetData ) { PPDO_DEVICE_DATA pdoData; NTSTATUS status; status = STATUS_SUCCESS; // // Verify LurDesc // TODO: // // Find Pdo Data... pdoData = LookupPdoData(FdoData, AddTargetData->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (FdoData, BUS_DBG_IOCTL_ERROR, ("no pdo for Slot %u\n", AddTargetData->ulSlotNo)); return STATUS_NOT_FOUND; } // // Copy AddDevInfo into the PDO. // if(pdoData->LanscsiAdapterPDO.AddDevInfo) { Bus_KdPrint_Cont (FdoData, BUS_DBG_IOCTL_ERROR, ("AddDevInfo already set.\n")); status = STATUS_DEVICE_ALREADY_ATTACHED; goto cleanup; } pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePoolWithTag(NonPagedPool, AddTargetData->ulSize, BUSENUM_POOL_TAG); if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, AddTargetData, AddTargetData->ulSize); pdoData->LanscsiAdapterPDO.AddDevInfoLength = AddTargetData->ulSize; // // Init PDO status // pdoData->LanscsiAdapterPDO.LastAdapterStatus = NDASSCSI_ADAPTERINFO_STATUS_INIT; pdoData->LanscsiAdapterPDO.DeviceMode = AddTargetData->DeviceMode; InitializeListHead(&pdoData->LanscsiAdapterPDO.NdasPdoEventQueue); // // Notify to NDASCSI // Bus_KdPrint(FdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET SetEvent AddTargetEvent!\n")); KeSetEvent(&pdoData->LanscsiAdapterPDO.AddTargetEvent, IO_NO_INCREMENT, FALSE); cleanup: ObDereferenceObject(pdoData->Self); return status; }
// // Plug in a NDAS device with a LUR descriptor. // NTSTATUS LSBus_AddTargetWithLurDesc( PFDO_DEVICE_DATA FdoData, PLURELATION_DESC LurDesc, ULONG SlotNo ) { PPDO_DEVICE_DATA pdoData; NTSTATUS status; status = STATUS_SUCCESS; // // Verify LurDesc // TODO: // // Find Pdo Data... pdoData = LookupPdoData(FdoData, SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (FdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); return STATUS_NOT_FOUND; } // // Copy AddDevInfo into the PDO. // if(pdoData->LanscsiAdapterPDO.AddDevInfo) { Bus_KdPrint_Cont (FdoData, BUS_DBG_IOCTL_ERROR, ("AddDevInfo already set.\n")); status = STATUS_DEVICE_ALREADY_ATTACHED; goto cleanup; } pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePool(NonPagedPool, LurDesc->Length); if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } else { RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, LurDesc, LurDesc->Length); status = STATUS_SUCCESS; } pdoData->LanscsiAdapterPDO.AddDevInfoLength = LurDesc->Length; pdoData->LanscsiAdapterPDO.Flags |= LSDEVDATA_FLAG_LURDESC; // // Notify to LanscsiMiniport // Bus_KdPrint(FdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET SetEvent AddTargetEvent!\n")); KeSetEvent(&pdoData->LanscsiAdapterPDO.AddTargetEvent, IO_NO_INCREMENT, FALSE); cleanup: ObDereferenceObject(pdoData->Self); return status; }
// // Plug in a NDAS device with a LUR descriptor. // NTSTATUS LSBus_AddTarget( PFDO_DEVICE_DATA FdoData, PLANSCSI_ADD_TARGET_DATA AddTargetData ) { PPDO_DEVICE_DATA pdoData; NTSTATUS status; status = STATUS_SUCCESS; // // Verify LurDesc // TODO: // // Find Pdo Data... pdoData = LookupPdoData(FdoData, AddTargetData->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (FdoData, BUS_DBG_IOCTL_ERROR, ("no pdo for Slot %u\n", AddTargetData->ulSlotNo)); return STATUS_NOT_FOUND; } // // Copy AddDevInfo into the PDO. // if(pdoData->LanscsiAdapterPDO.AddDevInfo) { Bus_KdPrint_Cont (FdoData, BUS_DBG_IOCTL_ERROR, ("AddDevInfo already set.\n")); status = STATUS_DEVICE_ALREADY_ATTACHED; goto cleanup; } pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePool(NonPagedPool, AddTargetData->ulSize); if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto cleanup; } RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, AddTargetData, AddTargetData->ulSize); pdoData->LanscsiAdapterPDO.AddDevInfoLength = AddTargetData->ulSize; // // Notify to LanscsiMiniport // Bus_KdPrint(FdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET SetEvent AddTargetEvent!\n")); KeSetEvent(&pdoData->LanscsiAdapterPDO.AddTargetEvent, IO_NO_INCREMENT, FALSE); cleanup: ObDereferenceObject(pdoData->Self); return status; }
void bus_init_pdo ( PDEVICE_OBJECT pdo, PFDO_DEVICE_DATA fdodata ) { PPDO_DEVICE_DATA pdodata; unsigned int pdo_num; PAGED_CODE (); pdodata = (PPDO_DEVICE_DATA) pdo->DeviceExtension; Bus_KdPrint(pdodata, BUS_DBG_SS_NOISE, ("pdo 0x%p, extension 0x%p\n", pdo, pdodata)); // // Initialize the rest // pdodata->IsFDO = FALSE; pdodata->Self = pdo; pdodata->DebugLevel = BusEnumDebugLevel; pdodata->ParentFdo = fdodata->Self; pdodata->Present = TRUE; // attached to the bus pdodata->ReportedMissing = FALSE; // not yet reported missing INITIALIZE_PNP_STATE(pdodata); // // PDO's usually start their life at D3 // pdodata->DevicePowerState = PowerDeviceD3; pdodata->SystemPowerState = PowerSystemWorking; InitializeListHead(&pdodata->ioctl_q); KeInitializeSpinLock(&pdodata->q_lock); pdo->Flags |= DO_POWER_PAGABLE|DO_DIRECT_IO; ExAcquireFastMutex (&fdodata->Mutex); InsertTailList(&fdodata->ListOfPDOs, &pdodata->Link); fdodata->NumPDOs++; ExReleaseFastMutex (&fdodata->Mutex); // This should be the last step in initialization. pdo->Flags &= ~DO_DEVICE_INITIALIZING; }
NTSTATUS Bus_PnP(PDEVICE_OBJECT DeviceObject, PIRP Irp) { PIO_STACK_LOCATION irpStack; NTSTATUS status; PCOMMON_DEVICE_DATA commonData; PAGED_CODE(); irpStack = IoGetCurrentIrpStackLocation(Irp); ASSERT(IRP_MJ_PNP == irpStack->MajorFunction); commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; if (commonData->DevicePnPState == Deleted) { Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE ; IoCompleteRequest(Irp, IO_NO_INCREMENT); return status; } if (commonData->IsFDO) { Bus_KdPrint(("FDO %s IRP:0x%p\n", PnPMinorFunctionString(irpStack->MinorFunction), Irp)); status = Bus_FDO_PnP(DeviceObject, Irp, irpStack, (PFDO_DEVICE_DATA) commonData); } else { Bus_KdPrint(("PDO %s IRP: 0x%p\n", PnPMinorFunctionString(irpStack->MinorFunction), Irp)); status = Bus_PDO_PnP(DeviceObject, Irp, irpStack, (PPDO_DEVICE_DATA) commonData); } return status; }
VOID Bus_DriverUnload(__in PDRIVER_OBJECT DriverObject) { UNREFERENCED_PARAMETER(DriverObject); PAGED_CODE(); Bus_KdPrint(("Driver Unload\n")); ASSERT(NULL == DriverObject->DeviceObject); ExDeleteNPagedLookasideList(&g_LookAside); if (Globals.RegistryPath.Buffer) ExFreePool(Globals.RegistryPath.Buffer); return; }
BOOLEAN Bus_IsSafetyLockEnabled( __in PVOID Context ) /*++ Routine Description: Routine to check whether safety lock is enabled Arguments: Context pointer to PDO device extension Return Value: TRUE or FALSE --*/ { Bus_KdPrint ((PPDO_DEVICE_DATA)Context, BUS_DBG_PNP_TRACE, ("IsSafetyLockEnabled\n")); return TRUE; }
NTSTATUS Bus_SystemControl ( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) /*++ Routine Description We have just received a System Control IRP. Assume that this is a WMI IRP and call into the WMI system library and let it handle this IRP for us. --*/ { PFDO_DEVICE_DATA fdoData; SYSCTL_IRP_DISPOSITION disposition; NTSTATUS status; PIO_STACK_LOCATION stack; PCOMMON_DEVICE_DATA commonData; PAGED_CODE(); KdPrint(("Bus SystemControl\r\n")); stack = IoGetCurrentIrpStackLocation (Irp); commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; if (!commonData->IsFDO) { // // The PDO, just complete the request with the current status // Bus_KdPrint (commonData, BUS_DBG_WMI_TRACE, ("PDO %s\n", WMIMinorFunctionString(stack->MinorFunction))); status = Irp->IoStatus.Status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; Bus_KdPrint (fdoData, BUS_DBG_WMI_TRACE, ("FDO: %s\n", WMIMinorFunctionString(stack->MinorFunction))); Bus_IncIoCount (fdoData); if (fdoData->DevicePnPState == Deleted) { Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE ; IoCompleteRequest (Irp, IO_NO_INCREMENT); Bus_DecIoCount (fdoData); return status; } status = WmiSystemControl(&fdoData->WmiLibInfo, DeviceObject, Irp, &disposition); switch(disposition) { case IrpProcessed: { // // This irp has been processed and may be completed or pending. break; } case IrpNotCompleted: { // // This irp has not been completed, but has been fully processed. // we will complete it now IoCompleteRequest(Irp, IO_NO_INCREMENT); break; } case IrpForward: case IrpNotWmi: { // // This irp is either not a WMI irp or is a WMI irp targetted // at a device lower in the stack. IoSkipCurrentIrpStackLocation (Irp); status = IoCallDriver (fdoData->NextLowerDriver, Irp); break; } default: { // // We really should never get here, but if we do just forward.... ASSERT(FALSE); IoSkipCurrentIrpStackLocation (Irp); status = IoCallDriver (fdoData->NextLowerDriver, Irp); break; } } Bus_DecIoCount (fdoData); return(status); }
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, outlen; PFDO_DEVICE_DATA fdoData; PVOID buffer; PAGED_CODE (); // // It is not safe to call IOCTL in raised IRQL. // ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; // // We only take Device Control requests for the FDO. // That is the bus itself. // if (!fdoData->IsFDO) { // // These commands are only allowed to go to the FDO. // status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } // // Check to see whether the bus is removed // 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; outlen = irpStack->Parameters.DeviceIoControl.OutputBufferLength; status = STATUS_INVALID_PARAMETER; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("%d called\n", irpStack->Parameters.DeviceIoControl.IoControlCode)); switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_NDASBUS_ADD_TARGET: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA))); if ((inlen == outlen) && (sizeof(NDASBUS_ADD_TARGET_DATA) <= inlen)) { ULONG ulSize; PNDASBUS_ADD_TARGET_DATA addTargetData = buffer; BOOLEAN accepted; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_ADD_TARGET called\n")); Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET Target Type %d\n", addTargetData->ucTargetType)); status = STATUS_SUCCESS; // // Check structure size // if(VerifySizeOfAddTargetData(addTargetData, &ulSize) == 0) { status = STATUS_INVALID_PARAMETER; break; } if(ulSize != inlen) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Size mismatch. Req %d, in %d\n", ulSize, inlen)); status = STATUS_UNSUCCESSFUL; break; } // // Check to see if acceptable structure. // accepted = TRUE; switch(addTargetData->ucTargetType) { case NDASSCSI_TYPE_DISK_NORMAL: case NDASSCSI_TYPE_DVD: case NDASSCSI_TYPE_VDVD: case NDASSCSI_TYPE_MO: if(addTargetData->ulNumberOfUnitDiskList != 1) accepted = FALSE; break; case NDASSCSI_TYPE_DISK_MIRROR: if(2 != addTargetData->ulNumberOfUnitDiskList) accepted = FALSE; break; case NDASSCSI_TYPE_DISK_AGGREGATION: if (addTargetData->ulNumberOfUnitDiskList < 2 || addTargetData->ulNumberOfUnitDiskList > MAX_NR_UNITDISK_FOR_AGGR) accepted = FALSE; break; case NDASSCSI_TYPE_DISK_RAID0: switch(addTargetData->ulNumberOfUnitDiskList) { case 2: case 4: case 8: break; default: // do not accept accepted = FALSE; break; } break; case NDASSCSI_TYPE_DISK_RAID1R3: { ULONG ulDiskCount; ulDiskCount = addTargetData->ulNumberOfUnitDiskList - addTargetData->RAID_Info.nSpareDisk; if (2 != ulDiskCount) accepted = FALSE; } break; case NDASSCSI_TYPE_DISK_RAID4R3: { ULONG ulDiskCount; ulDiskCount = addTargetData->ulNumberOfUnitDiskList - addTargetData->RAID_Info.nSpareDisk; switch(ulDiskCount) { case 3: // 2 + 1 case 5: // 4 + 1 case 9: // 8 + 1 break; default: // do not accept accepted = FALSE; break; } break; } default: Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Bad Disk Type.\n")); accepted = FALSE; break; } if(accepted == FALSE) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: Invaild type.\n")); status = STATUS_UNSUCCESSFUL; break; } #if DBG NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_TRY_TO_ADDTARGET, IOCTL_NDASBUS_ADD_TARGET, addTargetData->ulSlotNo); #endif // Find Pdo Data... pdoData = LookupPdoData(fdoData, addTargetData->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_ADD_TARGET, addTargetData->ulSlotNo); break; } // // Save the add target information to the PDO extension // pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePoolWithTag(NonPagedPool, inlen, BUSENUM_POOL_TAG); if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) { Irp->IoStatus.Information = 0; status = STATUS_INSUFFICIENT_RESOURCES; break; } else { RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, addTargetData, inlen); status = STATUS_SUCCESS; } pdoData->LanscsiAdapterPDO.AddDevInfoLength = inlen; // // Init PDO status // pdoData->LanscsiAdapterPDO.LastAdapterStatus = NDASSCSI_ADAPTERINFO_STATUS_INIT; pdoData->LanscsiAdapterPDO.DeviceMode = addTargetData->DeviceMode; // // Notify to NDASSCSI // Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET SetEvent AddTargetEvent!\n")); KeSetEvent(&pdoData->LanscsiAdapterPDO.AddTargetEvent, IO_NO_INCREMENT, FALSE); // // Register Target // if(pdoData->Persistent) { status = LSBus_RegisterTarget(fdoData, addTargetData); if(!NT_SUCCESS(status)) { ExFreePoolWithTag(pdoData->LanscsiAdapterPDO.AddDevInfo, BUSENUM_POOL_TAG); pdoData->LanscsiAdapterPDO.AddDevInfo = NULL; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("ADD_TARGET: LSBus_RegisterTarget() failed. STATUS=%08lx\n", status)); status = STATUS_INTERNAL_DB_ERROR; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_REGISTER_TARGET_FAIL, IOCTL_NDASBUS_ADD_TARGET, addTargetData->ulSlotNo); } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("ADD_TARGET: Successfully registered.\n")); } } ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_ADD_TARGET length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA))); } } break; case IOCTL_NDASBUS_REMOVE_TARGET: { PPDO_DEVICE_DATA pdoData; PNDASBUS_REMOVE_TARGET_DATA removeTarget; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_REMOVE_TARGET called\n")); if (sizeof (NDASBUS_REMOVE_TARGET_DATA) != inlen) break; removeTarget = (PNDASBUS_REMOVE_TARGET_DATA)buffer; pdoData = LookupPdoData(fdoData, removeTarget->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_REMOVE_TARGET, removeTarget->ulSlotNo); break; } // // redirect to the NDAS SCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_REMOVE_TARGET, buffer, sizeof(NDASBUS_REMOVE_TARGET_DATA), NULL, 0 ); if(NT_SUCCESS(status) && pdoData->Persistent) { status = LSBus_UnregisterTarget(fdoData, removeTarget->ulSlotNo, removeTarget->ulTargetId); if(!NT_SUCCESS(status)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ( "REMOVE_TARGET: Removed Target instance," " but LSBus_UnregisterTarget() failed.\n")); status = STATUS_INTERNAL_DB_ERROR; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_UNREGISTER_TARGET_FAIL, IOCTL_NDASBUS_REMOVE_TARGET, removeTarget->ulSlotNo); } #if DBG else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_INFO, ("REMOVE_TARGET: LSBus_UnregisterTarget() succeeded.\n")); } #endif } ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = 0; break; } case IOCTL_NDASBUS_STARTSTOP_REGISTRARENUM:{ PULONG onOff = (PULONG)buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "STARTSTOP_REGISTRARENUM: inlen %d, outlen %d OnOff %u\n", inlen, outlen, *onOff)); KeEnterCriticalRegion(); ExAcquireFastMutexUnsafe(&fdoData->RegMutex); if(*onOff != 0) { // // Save old state. // Activate the registrar's enumeration // *onOff = fdoData->StartStopRegistrarEnum; fdoData->StartStopRegistrarEnum = TRUE; } else { // // Save old state. // Deactivate the registrar's enumeration // *onOff = fdoData->StartStopRegistrarEnum; fdoData->StartStopRegistrarEnum = FALSE; } // // Clean up non-enumerated entries. // LSBus_CleanupNDASDeviceRegistryUnsafe(fdoData); ExReleaseFastMutexUnsafe(&fdoData->RegMutex); KeLeaveCriticalRegion(); Irp->IoStatus.Information = sizeof(ULONG); status = STATUS_SUCCESS; break; } case IOCTL_NDASBUS_REGISTER_DEVICE: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_DEVICE: inlen %d, outlen %d," " sizeof(NDASBUS_PLUGIN_HARDWARE_EX2) %d\n", inlen, outlen, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2))); if ((inlen == outlen)) { PNDASBUS_PLUGIN_HARDWARE_EX2 PlugIn = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_DEVICE: entered\n")); status = LSBus_RegisterDevice(fdoData, PlugIn); Irp->IoStatus.Information = 0; } else Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("REGISTER_DEVICE: length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2) %d\n", inlen, outlen, sizeof(NDASBUS_PLUGIN_HARDWARE_EX2))); } break; case IOCTL_NDASBUS_REGISTER_TARGET: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_TARGET: inlen %d, outlen %d," " sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA))); if ((inlen == outlen)) { PNDASBUS_ADD_TARGET_DATA AddTargetData = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("REGISTER_TARGET: entered\n")); status = LSBus_RegisterTarget(fdoData, AddTargetData); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "REGISTER_TARGET: length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_ADD_TARGET_DATA))); } } break; case IOCTL_NDASBUS_UNREGISTER_DEVICE: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_DEVICE: inlen %d, outlen %d," " sizeof(NDASBUS_UNREGISTER_NDASDEV) %d\n", inlen, outlen, sizeof(NDASBUS_UNREGISTER_NDASDEV))); if ((inlen == outlen)) { PNDASBUS_UNREGISTER_NDASDEV UnregDev = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_DEVICE: entered\n")); status = LSBus_UnregisterDevice(fdoData, UnregDev->SlotNo); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_DEVICE: length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(NDASBUS_UNREGISTER_NDASDEV))); } } break; case IOCTL_NDASBUS_UNREGISTER_TARGET: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_TARGET: inlen %d, outlen %d," " sizeof(NDASBUS_UNREGISTER_TARGET) %d\n", inlen, outlen, sizeof(NDASBUS_UNREGISTER_TARGET))); if ((inlen == outlen)) { PNDASBUS_UNREGISTER_TARGET UnregTarget = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UNREGISTER_TARGET: entered\n")); status = LSBus_UnregisterTarget(fdoData, UnregTarget->SlotNo, UnregTarget->TargetId); Irp->IoStatus.Information = 0; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ( "UNREGISTER_TARGET: length mismatch!!!" " inlen %d, outlen %d, sizeof(NDASBUS_UNREGISTER_TARGET) %d\n", inlen, outlen, sizeof(NDASBUS_UNREGISTER_TARGET))); } } break; case IOCTL_NDASBUS_SETPDOINFO: { PPDO_DEVICE_DATA pdoData; PNDASBUS_SETPDOINFO SetPdoInfo; KIRQL oldIrql; PVOID sectionHandle; BOOLEAN acceptStatus; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_SETPDOINFO called\n")); if (sizeof (NDASBUS_SETPDOINFO) != inlen) break; acceptStatus = TRUE; SetPdoInfo = (PNDASBUS_SETPDOINFO)buffer; pdoData = LookupPdoData(fdoData, SetPdoInfo->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_SETPDOINFO, SetPdoInfo->SlotNo); break; } // // lock the code section of this function to acquire spinlock in raised IRQL. // sectionHandle = MmLockPagableCodeSection(Bus_IoCtl); KeAcquireSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql); Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!! SETPDOINFO: PDO %p: %08lx %08lx %08lx\n", pdoData->Self, SetPdoInfo->AdapterStatus, SetPdoInfo->SupportedFeatures, SetPdoInfo->EnabledFeatures)); // // Deny the status change if the current status is STATUS_STOPPED except for RESETSTATUS flag. // if(ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.LastAdapterStatus, NDASSCSI_ADAPTERINFO_STATUS_STOPPED)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: 'An event occured after 'Stopped' event\n")); if(ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTERINFO_STATUSFLAG_RESETSTATUS)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Reset-status event accepted.\n")); } else { acceptStatus = FALSE; } } else { if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) { acceptStatus = FALSE; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!! SETPDOINFO: AddTarget is not occured. Too early to set status.\n")); } } // // Mask off RESETSTATUS. // NDAS service does not need to know it. // SetPdoInfo->AdapterStatus &= ~NDASSCSI_ADAPTERINFO_STATUSFLAG_RESETSTATUS; // // Set status values to the corresponding physical device object. // Save to the extension // if(acceptStatus) { PNDASBUS_PDOEVENT_ENTRY pdoEventEntry; pdoEventEntry = NdasBusCreatePdoStatusItem(SetPdoInfo->AdapterStatus); if(pdoEventEntry) { NdasBusQueuePdoStatusItem(&pdoData->LanscsiAdapterPDO, pdoEventEntry); } #if DBG else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Could not allocate PDO status entry.\n")); } #endif pdoData->LanscsiAdapterPDO.LastAdapterStatus = SetPdoInfo->AdapterStatus; pdoData->LanscsiAdapterPDO.SupportedFeatures = SetPdoInfo->SupportedFeatures; pdoData->LanscsiAdapterPDO.EnabledFeatures = SetPdoInfo->EnabledFeatures; // // Queue plugout worker if the NDAS SCSI stop abnormally. // Notify the NDAS service of abnormal termination // if(ADAPTERINFO_ISSTATUS(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTERINFO_STATUS_STOPPED) && ADAPTERINFO_ISSTATUSFLAG(SetPdoInfo->AdapterStatus, NDASSCSI_ADAPTERINFO_STATUSFLAG_ABNORMAL_TERMINAT)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: Queueing Unplug worker!!!!!!!!\n")); status = QueueUnplugWorker(fdoData, SetPdoInfo->SlotNo); // // Set disconnection event // KeSetEvent(pdoData->LanscsiAdapterPDO.DisconEventToService, IO_DISK_INCREMENT, FALSE); } else { // // Notify the adapter status change // KeSetEvent(pdoData->LanscsiAdapterPDO.AlarmEventToService, IO_DISK_INCREMENT, FALSE); } } KeReleaseSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql); // // Release the code section. // MmUnlockPagableImageSection(sectionHandle); status = STATUS_SUCCESS; ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; } break; case IOCTL_NDASBUS_QUERY_NODE_ALIVE: { PPDO_DEVICE_DATA pdoData; BOOLEAN bAlive; PNDASBUS_NODE_ALIVE_IN pNodeAliveIn; NDASBUS_NODE_ALIVE_OUT nodeAliveOut; // Check Parameter. if(inlen != sizeof(NDASBUS_NODE_ALIVE_IN) || outlen != sizeof(NDASBUS_NODE_ALIVE_OUT)) { status = STATUS_UNKNOWN_REVISION; break; } pNodeAliveIn = (PNDASBUS_NODE_ALIVE_IN)Irp->AssociatedIrp.SystemBuffer; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_NOISE, ("FDO: IOCTL_NDASBUS_QUERY_NODE_ALIVE SlotNumber = %d\n", pNodeAliveIn->SlotNo)); pdoData = LookupPdoData(fdoData, pNodeAliveIn->SlotNo); if(pdoData == NULL) { // Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE, // ("[LanScsiBus]Bus_IoCtl: IOCTL_NDASBUS_QUERY_NODE_ALIVE No pdo\n")); bAlive = FALSE; } else { bAlive = TRUE; } // For Result... nodeAliveOut.SlotNo = pNodeAliveIn->SlotNo; nodeAliveOut.bAlive = bAlive; // Get Adapter Status. if(bAlive == TRUE) { if( ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.LastAdapterStatus, NDASSCSI_ADAPTERINFO_STATUS_STOPPING)) { nodeAliveOut.bHasError = TRUE; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_QUERY_NODE_ALIVE Adapter has Error 0x%x\n", nodeAliveOut.bHasError)); } else { nodeAliveOut.bHasError = FALSE; } } if(pdoData) ObDereferenceObject(pdoData->Self); RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, &nodeAliveOut, sizeof(NDASBUS_NODE_ALIVE_OUT) ); Irp->IoStatus.Information = sizeof(NDASBUS_NODE_ALIVE_OUT); status = STATUS_SUCCESS; } break; // // added by hootch 01172004 // case IOCTL_NDASBUS_UPGRADETOWRITE: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_UPGRADETOWRITE called\n")); // Check Parameter. if(inlen != sizeof(NDASBUS_UPGRADE_TO_WRITE)) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_UPGRADETOWRITE: Invalid input buffer length\n")); status = STATUS_UNKNOWN_REVISION; break; } pdoData = LookupPdoData(fdoData, ((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_UPGRADETOWRITE: No pdo for Slotno:%d\n", ((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo)); status = STATUS_NO_SUCH_DEVICE; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_UPGRADETOWRITE, ((PNDASBUS_UPGRADE_TO_WRITE)buffer)->SlotNo); } else { // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_UPGRADETOWRITE, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = 0; } break; case IOCTL_NDASBUS_REDIRECT_NDASSCSI: { PPDO_DEVICE_DATA pdoData; PNDASBUS_REDIRECT_NDASSCSI redirectIoctl; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_REDIRECT_NDASSCSI called\n")); // Check Parameter. if(inlen < sizeof(NDASBUS_REDIRECT_NDASSCSI)) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_REDIRECT_NDASSCSI: Invalid input buffer length\n")); status = STATUS_UNKNOWN_REVISION; break; } redirectIoctl = (PNDASBUS_REDIRECT_NDASSCSI)buffer; pdoData = LookupPdoData(fdoData, redirectIoctl->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_REDIRECT_NDASSCSI: No pdo for Slotno:%d\n", redirectIoctl->SlotNo)); status = STATUS_NO_SUCH_DEVICE; } else { // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, redirectIoctl->IoctlCode, redirectIoctl->IoctlData, redirectIoctl->IoctlDataSize, redirectIoctl->IoctlData, redirectIoctl->IoctlDataSize ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = 0; } break; case IOCTL_NDASBUS_QUERY_NDASSCSIINFO: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_QUERY_NDASSCSIINFO called\n")); // Check Parameter. if(inlen < FIELD_OFFSET(NDASSCSI_QUERY_INFO_DATA, QueryData) ) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_QUERY_NDASSCSIINFO: Invalid input buffer length too small.\n")); status = STATUS_UNKNOWN_REVISION; break; } pdoData = LookupPdoData(fdoData, ((PNDASSCSI_QUERY_INFO_DATA)buffer)->NdasScsiAddress.SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_QUERY_NDASSCSIINFO No pdo\n")); status = STATUS_NO_SUCH_DEVICE; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_QUERY_NDASSCSIINFO, ((PNDASSCSI_QUERY_INFO_DATA)buffer)->NdasScsiAddress.SlotNo); } else { // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_QUERYINFO_EX, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = outlen; } break; case IOCTL_NDASBUS_QUERY_INFORMATION: { // PPDO_DEVICE_DATA pdoData; NDASBUS_QUERY_INFORMATION Query; PNDASBUS_INFORMATION Information; LONG BufferLenNeeded; // Check Parameter. if( inlen < sizeof(NDASBUS_QUERY_INFORMATION) /*|| outlen < sizeof(NDASBUS_INFORMATION) */) { status = STATUS_UNKNOWN_REVISION; break; } RtlCopyMemory(&Query, buffer, sizeof(NDASBUS_QUERY_INFORMATION)); Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE, ("FDO: IOCTL_NDASBUS_QUERY_INFORMATION QueryType : %d SlotNumber = %d\n", Query.InfoClass, Query.SlotNo)); Information = (PNDASBUS_INFORMATION)buffer; ASSERT(Information); Information->InfoClass = Query.InfoClass; status = LSBus_QueryInformation(fdoData, IoIs32bitProcess(Irp), &Query, Information, outlen, &BufferLenNeeded); if(NT_SUCCESS(status)) { Information->Size = BufferLenNeeded; Irp->IoStatus.Information = BufferLenNeeded; } else { Irp->IoStatus.Information = BufferLenNeeded; } } break; case IOCTL_NDASBUS_PLUGIN_HARDWARE_EX2: { ULONG structLen; // Without variable length field ULONG wholeStructLen; // With variable length field ULONG inputWholeStructLen; // // Check 32 bit thunking request // if(IoIs32bitProcess(Irp)) { structLen = FIELD_OFFSET(NDASBUS_PLUGIN_HARDWARE_EX2_32, HardwareIDs); wholeStructLen = sizeof(NDASBUS_PLUGIN_HARDWARE_EX2_32); inputWholeStructLen = ((PNDASBUS_PLUGIN_HARDWARE_EX2_32) buffer)->Size; } else { structLen = FIELD_OFFSET(NDASBUS_PLUGIN_HARDWARE_EX2, HardwareIDs); wholeStructLen = sizeof(NDASBUS_PLUGIN_HARDWARE_EX2); inputWholeStructLen = ((PNDASBUS_PLUGIN_HARDWARE_EX2) buffer)->Size; } if ((inlen == outlen) && // // Make sure it has at least two nulls and the size // field is set to the declared size of the struct // ((structLen + 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 // (wholeStructLen == inputWholeStructLen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n")); status= Bus_PlugInDeviceEx2((PNDASBUS_PLUGIN_HARDWARE_EX2)buffer, inlen, fdoData, IoIs32bitProcess(Irp), Irp->RequestorMode, FALSE); Irp->IoStatus.Information = outlen; } } break; case IOCTL_NDASBUS_GETVERSION: { if (outlen >= sizeof(NDASBUS_GET_VERSION)) { PNDASBUS_GET_VERSION version = (PNDASBUS_GET_VERSION)buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_NDASBUS_GETVERSION: called\n")); try { version->VersionMajor = VER_FILEMAJORVERSION; version->VersionMinor = VER_FILEMINORVERSION; version->VersionBuild = VER_FILEBUILD; version->VersionPrivate = VER_FILEBUILD_QFE; Irp->IoStatus.Information = sizeof(NDASBUS_GET_VERSION); status = STATUS_SUCCESS; } except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); Irp->IoStatus.Information = 0; } } } break; case IOCTL_NDASBUS_UNPLUG_HARDWARE: { if ((sizeof (NDASBUS_UNPLUG_HARDWARE) == inlen) && (inlen == outlen) && (((PNDASBUS_UNPLUG_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n")); status= Bus_UnPlugDevice( (PNDASBUS_UNPLUG_HARDWARE)buffer, fdoData); Irp->IoStatus.Information = outlen; } } break; case IOCTL_NDASBUS_EJECT_HARDWARE: { if ((sizeof (NDASBUS_EJECT_HARDWARE) == inlen) && (inlen == outlen) && (((PNDASBUS_EJECT_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n")); status= Bus_EjectDevice((PNDASBUS_EJECT_HARDWARE)buffer, fdoData); Irp->IoStatus.Information = outlen; } } break; case IOCTL_NDASBUS_DVD_GET_STATUS: { PPDO_DEVICE_DATA pdoData; PNDASBUS_DVD_STATUS pDvdStatusData; // Check Parameter. if((inlen != outlen) || (sizeof(NDASBUS_DVD_STATUS) > inlen)) { status = STATUS_UNSUCCESSFUL ; break; } pDvdStatusData = (PNDASBUS_DVD_STATUS)Irp->AssociatedIrp.SystemBuffer; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("FDO: IOCTL_NDASBUS_DVD_GET_STATUS SlotNumber = %d\n", pDvdStatusData->SlotNo)); pdoData = LookupPdoData(fdoData, pDvdStatusData->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_DVD_GET_STATUS No pdo\n")); status = STATUS_UNSUCCESSFUL; NDBusIoctlLogError( fdoData->Self, NDASBUS_IO_PDO_NOT_FOUND, IOCTL_NDASBUS_DVD_GET_STATUS, pDvdStatusData->SlotNo); break; } else { if(pdoData->LanscsiAdapterPDO.Flags & LSDEVDATA_FLAG_LURDESC) { // // A LUR descriptor is set. // if(((PLURELATION_DESC)pdoData->LanscsiAdapterPDO.AddDevInfo)->DevType != NDASSCSI_TYPE_DVD) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_DVD_GET_STATUS No DVD Device\n")); status = STATUS_UNSUCCESSFUL; break; } } else { // // ADD_TARGET_DATA is set. // if(((PNDASBUS_ADD_TARGET_DATA)pdoData->LanscsiAdapterPDO.AddDevInfo)->ucTargetType != NDASSCSI_TYPE_DVD) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_NDASBUS_DVD_GET_STATUS No DVD Device\n")); status = STATUS_UNSUCCESSFUL; break; } } // // redirect to the NDASSCSI Device // status = LSBus_IoctlToNdasScsiDevice( pdoData, NDASSCSI_IOCTL_GET_DVD_STATUS, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); status = STATUS_SUCCESS; Irp->IoStatus.Information = outlen; } } break; default: break; // default status is STATUS_INVALID_PARAMETER }
NTSTATUS Bus_StartFdo ( __in PFDO_DEVICE_DATA FdoData, __in PIRP Irp ) /*++ Routine Description: Initialize and start the bus controller. Get the resources by parsing the list and map them if required. Arguments: DeviceData - Pointer to the FDO's device extension. Irp - Pointer to the irp. Return Value: NT Status is returned. --*/ { NTSTATUS status; POWER_STATE powerState; PAGED_CODE (); // // Check the function driver source to learn // about parsing resource list. // // // Enable device interface. If the return status is // STATUS_OBJECT_NAME_EXISTS means we are enabling the interface // that was already enabled, which could happen if the device // is stopped and restarted for resource rebalancing. // status = IoSetDeviceInterfaceState(&FdoData->InterfaceName, TRUE); if (!NT_SUCCESS (status)) { Bus_KdPrint (FdoData, BUS_DBG_PNP_TRACE, ("IoSetDeviceInterfaceState failed: 0x%x\n", status)); return status; } // // Set the device power state to fully on. Also if this Start // is due to resource rebalance, you should restore the device // to the state it was before you stopped the device and relinquished // resources. // FdoData->DevicePowerState = PowerDeviceD0; powerState.DeviceState = PowerDeviceD0; PoSetPowerState ( FdoData->Self, DevicePowerState, powerState ); SET_NEW_PNP_STATE(FdoData, Started); // // Register with WMI // status = Bus_WmiRegistration(FdoData); if (!NT_SUCCESS (status)) { Bus_KdPrint (FdoData, BUS_DBG_SS_ERROR, ("StartFdo: Bus_WmiRegistration failed (%x)\n", status)); } return status; }
NTSTATUS Bus_AddDevice( __in PDRIVER_OBJECT DriverObject, __in PDEVICE_OBJECT PhysicalDeviceObject ) /*++ Routine Description. Our Toaster bus has been found. Attach our FDO to it. Allocate any required resources. Set things up. And be prepared for the ``start device'' Arguments: DriverObject - pointer to driver object. PhysicalDeviceObject - Device object representing the bus to which we will attach a new FDO. --*/ { NTSTATUS status; PDEVICE_OBJECT deviceObject = NULL; PFDO_DEVICE_DATA deviceData = NULL; PWCHAR deviceName = NULL; ULONG nameLength; PKTIMER timer; PKDPC dpc; PAGED_CODE (); Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Add Device: 0x%p\n", PhysicalDeviceObject)); status = IoCreateDevice ( DriverObject, // our driver object sizeof (FDO_DEVICE_DATA), // device object extension size NULL, // FDOs do not have names FILE_DEVICE_BUS_EXTENDER, // We are a bus FILE_DEVICE_SECURE_OPEN, // TRUE, // our FDO is exclusive &deviceObject); // The device object created if (!NT_SUCCESS (status)) { goto End; } deviceData = (PFDO_DEVICE_DATA) deviceObject->DeviceExtension; RtlZeroMemory (deviceData, sizeof (FDO_DEVICE_DATA)); // // Set the initial state of the FDO // INITIALIZE_PNP_STATE(deviceData); deviceData->DebugLevel = BusEnumDebugLevel; deviceData->IsFDO = TRUE; deviceData->Self = deviceObject; ExInitializeFastMutex (&deviceData->Mutex); InitializeListHead (&deviceData->ListOfPDOs); // Set the PDO for use with PlugPlay functions deviceData->UnderlyingPDO = PhysicalDeviceObject; // // Set the initial powerstate of the FDO // deviceData->DevicePowerState = PowerDeviceUnspecified; deviceData->SystemPowerState = PowerSystemWorking; // // Biased to 1. Transition to zero during remove device // means IO is finished. Transition to 1 means the device // can be stopped. // deviceData->OutstandingIO = 1; // // Initialize the remove event to Not-Signaled. This event // will be set when the OutstandingIO will become 0. // KeInitializeEvent(&deviceData->RemoveEvent, SynchronizationEvent, FALSE); // // Initialize the stop event to Signaled: // there are no Irps that prevent the device from being // stopped. This event will be set when the OutstandingIO // will become 0. // KeInitializeEvent(&deviceData->StopEvent, SynchronizationEvent, TRUE); deviceObject->Flags |= DO_POWER_PAGABLE|DO_BUFFERED_IO; // // Tell the Plug & Play system that this device will need a // device interface. // status = IoRegisterDeviceInterface ( PhysicalDeviceObject, (LPGUID) &GUID_DEVINTERFACE_BUSENUM_TOASTER, NULL, &deviceData->InterfaceName); if (!NT_SUCCESS (status)) { Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR, ("AddDevice: IoRegisterDeviceInterface failed (%x)", status)); goto End; } // // Attach our FDO to the device stack. // The return value of IoAttachDeviceToDeviceStack is the top of the // attachment chain. This is where all the IRPs should be routed. // deviceData->NextLowerDriver = IoAttachDeviceToDeviceStack ( deviceObject, PhysicalDeviceObject); if (NULL == deviceData->NextLowerDriver) { status = STATUS_NO_SUCH_DEVICE; goto End; } #if DBG // // We will demonstrate here the step to retrieve the name of the PDO // status = IoGetDeviceProperty (PhysicalDeviceObject, DevicePropertyPhysicalDeviceObjectName, 0, NULL, &nameLength); if (status != STATUS_BUFFER_TOO_SMALL) { Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR, ("AddDevice:IoGDP failed (0x%x)\n", status)); goto End; } deviceName = ExAllocatePoolWithTag (NonPagedPool, nameLength, BUSENUM_POOL_TAG); if (NULL == deviceName) { Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR, ("AddDevice: no memory to alloc for deviceName(0x%x)\n", nameLength)); status = STATUS_INSUFFICIENT_RESOURCES; goto End; } status = IoGetDeviceProperty (PhysicalDeviceObject, DevicePropertyPhysicalDeviceObjectName, nameLength, deviceName, &nameLength); if (!NT_SUCCESS (status)) { Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR, ("AddDevice:IoGDP(2) failed (0x%x)", status)); goto End; } Bus_KdPrint (deviceData, BUS_DBG_SS_TRACE, ("AddDevice: %p to %p->%p (%ws) \n", deviceObject, deviceData->NextLowerDriver, PhysicalDeviceObject, deviceName)); #endif // // We are done with initializing, so let's indicate that and return. // This should be the final step in the AddDevice process. // deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; End: if (deviceName){ ExFreePool(deviceName); } if (!NT_SUCCESS(status) && deviceObject){ if (deviceData && deviceData->NextLowerDriver){ IoDetachDevice (deviceData->NextLowerDriver); } IoDeleteDevice (deviceObject); } return status; }
NTSTATUS Bus_PnP ( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) /*++ Routine Description: Handles PnP Irps sent to both FDO and child PDOs. Arguments: DeviceObject - Pointer to deviceobject Irp - Pointer to a PnP Irp. Return Value: NT Status is returned. --*/ { PIO_STACK_LOCATION irpStack; NTSTATUS status; PCOMMON_DEVICE_DATA commonData; PAGED_CODE (); KdPrint(("Bus_PnP\r\n")); irpStack = IoGetCurrentIrpStackLocation (Irp); ASSERT (IRP_MJ_PNP == irpStack->MajorFunction); commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; // // If the device has been removed, the driver should // not pass the IRP down to the next lower driver. // if (commonData->DevicePnPState == Deleted) { Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE ; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } if (commonData->IsFDO) { Bus_KdPrint (commonData, BUS_DBG_PNP_TRACE, ("FDO %s IRP:0x%p\n", PnPMinorFunctionString(irpStack->MinorFunction), Irp)); // // Request is for the bus FDO // status = Bus_FDO_PnP ( DeviceObject, Irp, irpStack, (PFDO_DEVICE_DATA) commonData); } else { Bus_KdPrint (commonData, BUS_DBG_PNP_TRACE, ("PDO %s IRP: 0x%p\n", PnPMinorFunctionString(irpStack->MinorFunction), Irp)); // // Request is for the child PDO. // status = Bus_PDO_PnP ( DeviceObject, Irp, irpStack, (PPDO_DEVICE_DATA) commonData); } return status; }
NTSTATUS Bus_EjectDevice ( PBUSENUM_EJECT_HARDWARE Eject, PFDO_DEVICE_DATA FdoData ) /*++ Routine Description: The user application has told us to eject the device from the bus. In a real situation the driver gets notified by an interrupt when the user presses the Eject button on the device. Arguments: Eject - pointer to Eject hardware structure. FdoData - contains the list to iterate over Returns: STATUS_SUCCESS upon successful removal from the list STATUS_INVALID_PARAMETER if the removal was unsuccessful --*/ { PLIST_ENTRY entry; PPDO_DEVICE_DATA pdoData; BOOLEAN found = FALSE, ejectAll; PAGED_CODE (); ejectAll = (0 == Eject->SerialNo); ExAcquireFastMutex (&FdoData->Mutex); if (ejectAll) { Bus_KdPrint (FdoData, BUS_DBG_IOCTL_NOISE, ("Ejecting all the pdos!\n")); } else { Bus_KdPrint (FdoData, BUS_DBG_IOCTL_NOISE, ("Ejecting %d\n", Eject->SerialNo)); } if (FdoData->NumPDOs == 0) { // // Somebody in user space isn't playing nice!!! // Bus_KdPrint (FdoData, BUS_DBG_IOCTL_ERROR, ("No devices to eject!\n")); ExReleaseFastMutex (&FdoData->Mutex); return STATUS_NO_SUCH_DEVICE; } // // Scan the list to find matching PDOs // for (entry = FdoData->ListOfPDOs.Flink; entry != &FdoData->ListOfPDOs; entry = entry->Flink) { pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); Bus_KdPrint (FdoData, BUS_DBG_IOCTL_NOISE, ("found device %d\n", pdoData->SerialNo)); if (ejectAll || Eject->SerialNo == pdoData->SerialNo) { Bus_KdPrint (FdoData, BUS_DBG_IOCTL_INFO, ("Ejected %d\n", pdoData->SerialNo)); found = TRUE; IoRequestDeviceEject(pdoData->Self); if (!ejectAll) { break; } } } ExReleaseFastMutex (&FdoData->Mutex); if (found) { return STATUS_SUCCESS; } Bus_KdPrint (FdoData, BUS_DBG_IOCTL_ERROR, ("Device %d is not present\n", Eject->SerialNo)); return STATUS_INVALID_PARAMETER; }
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, outlen; PFDO_DEVICE_DATA fdoData; PVOID buffer; PAGED_CODE (); fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; // // We only take Device Control requests for the FDO. // That is the bus itself. // if (!fdoData->IsFDO) { // // These commands are only allowed to go to the FDO. // status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } // // Check to see whether the bus is removed // 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; outlen = irpStack->Parameters.DeviceIoControl.OutputBufferLength; status = STATUS_INVALID_PARAMETER; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("%d called\n", irpStack->Parameters.DeviceIoControl.IoControlCode)); switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_LANSCSI_ADD_TARGET: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); if ((inlen == outlen) && (sizeof(LANSCSI_ADD_TARGET_DATA) <= inlen)) { ULONG ulSize; PLANSCSI_ADD_TARGET_DATA pBuffer = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_ADD_TARGET called\n")); Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET Target Type %d\n", pBuffer->ucTargetType)); // Check Parameter. switch(pBuffer->ucTargetType) { case DISK_TYPE_NORMAL: case DISK_TYPE_DVD: case DISK_TYPE_VDVD: case DISK_TYPE_MO: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA); if(pBuffer->ulNumberOfUnitDiskList != 1) { ulSize = 0; // Exit when Check if(ulSize != inlen)... } break; case DISK_TYPE_MIRROR: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK); if(2 != pBuffer->ulNumberOfUnitDiskList) { ulSize = 0; // Exit when Check if(ulSize != inlen)... } break; case DISK_TYPE_AGGREGATION: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK) * (pBuffer->ulNumberOfUnitDiskList - 1); if (pBuffer->ulNumberOfUnitDiskList < 2 || pBuffer->ulNumberOfUnitDiskList > MAX_NR_TC_PER_TARGET) { ulSize = 0; // Exit when Check if(ulSize != inlen)... } break; case DISK_TYPE_BIND_RAID0: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK) * (pBuffer->ulNumberOfUnitDiskList - 1); switch(pBuffer->ulNumberOfUnitDiskList) { case 2: case 4: case 8: break; default: // do not accept ulSize = 0; break; } break; case DISK_TYPE_BIND_RAID1: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK) * (pBuffer->ulNumberOfUnitDiskList - 1); if (pBuffer->ulNumberOfUnitDiskList < 2 || pBuffer->ulNumberOfUnitDiskList > MAX_NR_TC_PER_TARGET) { ulSize = 0; // Exit when Check if(ulSize != inlen)... } if (pBuffer->ulNumberOfUnitDiskList % 2) { // should be the multiples of 2 ulSize = 0; // Exit when Check if(ulSize != inlen)... } break; case DISK_TYPE_BIND_RAID4: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK) * (pBuffer->ulNumberOfUnitDiskList - 1); switch(pBuffer->ulNumberOfUnitDiskList) { case 3: // 2 + 1 case 5: // 4 + 1 case 9: // 8 + 1 break; default: // do not accept ulSize = 0; break; } break; default: Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET: Bad Disk Type.\n")); status = STATUS_UNSUCCESSFUL; break; } // Check Size. if(ulSize != inlen) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET: Size mismatch. Req %d, in %d\n", ulSize, inlen)); status = STATUS_UNSUCCESSFUL; break; } // Find Pdo Data... pdoData = LookupPdoData(fdoData, pBuffer->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; break; } /* // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_ADD_TARGET, buffer, sizeof(LANSCSI_ADD_TARGET_DATA), NULL, 0 ); */ pdoData->LanscsiAdapterPDO.AddDevInfo = ExAllocatePool(NonPagedPool, inlen); if(pdoData->LanscsiAdapterPDO.AddDevInfo == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; } else { RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddDevInfo, pBuffer, inlen); status = STATUS_SUCCESS; } pdoData->LanscsiAdapterPDO.AddDevInfoLength = inlen; // // Notify to LanscsiMiniport // Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET SetEvent AddTargetEvent!\n")); KeSetEvent(&pdoData->LanscsiAdapterPDO.AddTargetEvent, IO_NO_INCREMENT, FALSE); ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; } else { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET length mismatch!!! inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); } } break; case IOCTL_LANSCSI_REMOVE_TARGET: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_REMOVE_TARGET called\n")); if (sizeof (LANSCSI_REMOVE_TARGET_DATA) != inlen) break; pdoData = LookupPdoData(fdoData, ((PLANSCSI_REMOVE_TARGET_DATA)buffer)->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; break; } // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_REMOVE_TARGET, buffer, sizeof(LANSCSI_REMOVE_TARGET_DATA), NULL, 0 ); ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; break; } case IOCTL_LANSCSI_REGISTER_DEVICE: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_REGISTER_NDASDEVICE inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); if ((inlen == outlen)) { PLANSCSI_REGISTER_NDASDEV RegNdasDev = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_REGISTER_NDASDEVICE called\n")); status = LSBus_RegisterDevice(fdoData, RegNdasDev); Irp->IoStatus.Information = 0; } else Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET length mismatch!!! inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); } break; case IOCTL_LANSCSI_UNREGISTER_DEVICE: { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_REGISTER_NDASDEVICE inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); if ((inlen == outlen)) { PLANSCSI_UNREGISTER_NDASDEV UnregNdasDev = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_REGISTER_NDASDEVICE called\n")); status = LSBus_UnregisterDevice(fdoData, UnregNdasDev); Irp->IoStatus.Information = 0; } else Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET length mismatch!!! inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); } case IOCTL_LANSCSI_SETPDOINFO: { PPDO_DEVICE_DATA pdoData; PBUSENUM_SETPDOINFO SetPdoInfo; KIRQL oldIrql; PVOID sectionHandle; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_SETPDOINFO called\n")); if (sizeof (BUSENUM_SETPDOINFO) != inlen) break; SetPdoInfo = (PBUSENUM_SETPDOINFO)buffer; pdoData = LookupPdoData(fdoData, (SetPdoInfo)->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; break; } // // set information // lock the code section of the function to raise IRQL // because the function is PAGED_CODE. // sectionHandle = MmLockPagableCodeSection(Bus_IoCtl); KeAcquireSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql); Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!! IOCTL_LANSCSI_SETPDOINFO: %08lx %08lx %08lx\n", SetPdoInfo->AdapterStatus, SetPdoInfo->DesiredAccess, SetPdoInfo->GrantedAccess)); if(ADAPTERINFO_ISSTATUS(SetPdoInfo->AdapterStatus, ADAPTERINFO_STATUS_STOPPING) && ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUS_STOPPED)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("SETPDOINFO: 'Stopping' event occured after 'Stopped' event\n", SetPdoInfo->AdapterStatus, SetPdoInfo->DesiredAccess, SetPdoInfo->GrantedAccess)); } else { pdoData->LanscsiAdapterPDO.AdapterStatus = SetPdoInfo->AdapterStatus; pdoData->LanscsiAdapterPDO.DesiredAccess = SetPdoInfo->DesiredAccess; pdoData->LanscsiAdapterPDO.GrantedAccess = SetPdoInfo->GrantedAccess; } KeReleaseSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql); MmUnlockPagableImageSection(sectionHandle); status = STATUS_SUCCESS; ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; } break; case IOCTL_BUSENUM_QUERY_NODE_ALIVE: { PPDO_DEVICE_DATA pdoData; BOOLEAN bAlive; PBUSENUM_NODE_ALIVE_IN pNodeAliveIn; BUSENUM_NODE_ALIVE_OUT nodeAliveOut; // Check Parameter. if(inlen != sizeof(BUSENUM_NODE_ALIVE_IN) || outlen != sizeof(BUSENUM_NODE_ALIVE_OUT)) { status = STATUS_UNKNOWN_REVISION; break; } pNodeAliveIn = (PBUSENUM_NODE_ALIVE_IN)Irp->AssociatedIrp.SystemBuffer; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_NOISE, ("FDO: IOCTL_BUSENUM_QUERY_NODE_ALIVE SlotNumber = %d\n", pNodeAliveIn->SlotNo)); pdoData = LookupPdoData(fdoData, pNodeAliveIn->SlotNo); if(pdoData == NULL) { // Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE, // ("[LanScsiBus]Bus_IoCtl: IOCTL_BUSENUM_QUERY_NODE_ALIVE No pdo\n")); bAlive = FALSE; } else { // // Check this PDO would be removed... // if(pdoData->Present == TRUE) bAlive = TRUE; else bAlive = FALSE; } // For Result... nodeAliveOut.SlotNo = pNodeAliveIn->SlotNo; nodeAliveOut.bAlive = bAlive; // Get Adapter Status. if(bAlive == TRUE) { if( ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUS_IN_ERROR) || ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUS_STOPPING) /*|| ADAPTERINFO_ISSTATUSFLAG(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUSFLAG_MEMBER_FAULT) */ ) { nodeAliveOut.bHasError = TRUE; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_BUSENUM_QUERY_NODE_ALIVE Adapter has Error 0x%x\n", nodeAliveOut.bHasError)); } else { nodeAliveOut.bHasError = FALSE; } } if(pdoData) ObDereferenceObject(pdoData->Self); RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, &nodeAliveOut, sizeof(BUSENUM_NODE_ALIVE_OUT) ); Irp->IoStatus.Information = sizeof(BUSENUM_NODE_ALIVE_OUT); status = STATUS_SUCCESS; } break; // // added by hootch 01172004 // case IOCTL_LANSCSI_UPGRADETOWRITE: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_UPGRADETOWRITE called\n")); // Check Parameter. if(inlen != sizeof(BUSENUM_UPGRADE_TO_WRITE)) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_UPGRADETOWRITE: Invalid input buffer length\n")); status = STATUS_UNKNOWN_REVISION; break; } pdoData = LookupPdoData(fdoData, ((PBUSENUM_UPGRADE_TO_WRITE)buffer)->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_UPGRADETOWRITE No pdo for Slotno:%d\n", ((PBUSENUM_UPGRADE_TO_WRITE)buffer)->SlotNo)); status = STATUS_NO_SUCH_DEVICE; } else { // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = 0; } break; case IOCTL_LANSCSI_QUERY_LSMPINFORMATION: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_QUERY_LSMPINFORMATION called\n")); // Check Parameter. if(inlen < FIELD_OFFSET(LSMPIOCTL_QUERYINFO, QueryData) ) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_QUERY_LSMPINFORMATION: Invalid input buffer length too small.\n")); status = STATUS_UNKNOWN_REVISION; break; } pdoData = LookupPdoData(fdoData, ((PLSMPIOCTL_QUERYINFO)buffer)->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_QUERY_LSMPINFORMATION No pdo\n")); status = STATUS_NO_SUCH_DEVICE; } else { // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_QUERYINFO_EX, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = outlen; } break; case IOCTL_BUSENUM_QUERY_INFORMATION: { // PPDO_DEVICE_DATA pdoData; BUSENUM_QUERY_INFORMATION Query; PBUSENUM_INFORMATION Information; LONG BufferLenNeeded; // Check Parameter. if( inlen < sizeof(BUSENUM_QUERY_INFORMATION) /*|| outlen < sizeof(BUSENUM_INFORMATION) */) { status = STATUS_UNKNOWN_REVISION; break; } RtlCopyMemory(&Query, buffer, sizeof(BUSENUM_QUERY_INFORMATION)); Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE, ("FDO: IOCTL_BUSENUM_QUERY_INFORMATION QueryType : %d SlotNumber = %d\n", Query.InfoClass, Query.SlotNo)); Information = (PBUSENUM_INFORMATION)buffer; ASSERT(Information); Information->InfoClass = Query.InfoClass; status = LSBus_QueryInformation(fdoData, &Query, Information, outlen, &BufferLenNeeded); if(NT_SUCCESS(status)) { Information->Size = BufferLenNeeded; Irp->IoStatus.Information = BufferLenNeeded; } else { Irp->IoStatus.Information = BufferLenNeeded; } } break; case IOCTL_BUSENUM_PLUGIN_HARDWARE_EX: { if ((inlen == outlen) && // // 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_EX) + 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_EX) == ((PBUSENUM_PLUGIN_HARDWARE_EX) buffer)->Size)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n")); status= Bus_PlugInDeviceEx((PBUSENUM_PLUGIN_HARDWARE_EX)buffer, inlen, fdoData, Irp->RequestorMode); Irp->IoStatus.Information = outlen; } } break; case IOCTL_LANSCSI_GETVERSION: { if (outlen >= sizeof(BUSENUM_GET_VERSION)) { PBUSENUM_GET_VERSION version = (PBUSENUM_GET_VERSION)buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_GETVERSION: called\n")); try { version->VersionMajor = VER_FILEMAJORVERSION; version->VersionMinor = VER_FILEMINORVERSION; version->VersionBuild = VER_FILEBUILD; version->VersionPrivate = VER_FILEBUILD_QFE; Irp->IoStatus.Information = sizeof(BUSENUM_GET_VERSION); status = STATUS_SUCCESS; } except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); Irp->IoStatus.Information = 0; } } } break; case IOCTL_BUSENUM_UNPLUG_HARDWARE: { if ((sizeof (BUSENUM_UNPLUG_HARDWARE) == inlen) && (inlen == outlen) && (((PBUSENUM_UNPLUG_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n")); status= Bus_UnPlugDevice( (PBUSENUM_UNPLUG_HARDWARE)buffer, fdoData); Irp->IoStatus.Information = outlen; } } break; case IOCTL_BUSENUM_EJECT_HARDWARE: { if ((sizeof (BUSENUM_EJECT_HARDWARE) == inlen) && (inlen == outlen) && (((PBUSENUM_EJECT_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n")); status= Bus_EjectDevice((PBUSENUM_EJECT_HARDWARE)buffer, fdoData); Irp->IoStatus.Information = outlen; } } break; case IOCTL_DVD_GET_STATUS: { PPDO_DEVICE_DATA pdoData; PBUSENUM_DVD_STATUS pDvdStatusData; // Check Parameter. if((inlen != outlen) || (sizeof(BUSENUM_DVD_STATUS) > inlen)) { status = STATUS_UNSUCCESSFUL ; break; } pDvdStatusData = (PBUSENUM_DVD_STATUS)Irp->AssociatedIrp.SystemBuffer; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("FDO: IOCTL_DVD_GET_STATUS SlotNumber = %d\n", pDvdStatusData->SlotNo)); pdoData = LookupPdoData(fdoData, pDvdStatusData->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_DVD_GET_STATUS No pdo\n")); status = STATUS_UNSUCCESSFUL; break; } else { if(pdoData->LanscsiAdapterPDO.Flags & LSDEVDATA_FLAG_LURDESC) { // // A LUR descriptor is set. // if(((PLURELATION_DESC)pdoData->LanscsiAdapterPDO.AddDevInfo)->DevType != DISK_TYPE_DVD) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_DVD_GET_STATUS No DVD Device\n")); status = STATUS_UNSUCCESSFUL; break; } } else { // // ADD_TARGET_DATA is set. // if(((PLANSCSI_ADD_TARGET_DATA)pdoData->LanscsiAdapterPDO.AddDevInfo)->ucTargetType != DISK_TYPE_DVD) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_DVD_GET_STATUS No DVD Device\n")); status = STATUS_UNSUCCESSFUL; break; } } // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_GET_DVD_STATUS, buffer, inlen, buffer, outlen ) ; ObDereferenceObject(pdoData->Self); status = STATUS_SUCCESS; Irp->IoStatus.Information = outlen; } } break; default: break; // default status is STATUS_INVALID_PARAMETER }
NTSTATUS Bus_AddDevice(__in PDRIVER_OBJECT DriverObject, __in PDEVICE_OBJECT PhysicalDeviceObject) { NTSTATUS status; PDEVICE_OBJECT deviceObject = NULL; PFDO_DEVICE_DATA deviceData = NULL; PWCHAR deviceName = NULL; ULONG nameLength; UNREFERENCED_PARAMETER(nameLength); PAGED_CODE(); Bus_KdPrint(("Add Device: 0x%p\n", PhysicalDeviceObject)); status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_DATA), NULL, FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_SECURE_OPEN, TRUE, &deviceObject); if (!NT_SUCCESS (status)) { goto End; } deviceData = (PFDO_DEVICE_DATA) deviceObject->DeviceExtension; RtlZeroMemory(deviceData, sizeof (FDO_DEVICE_DATA)); INITIALIZE_PNP_STATE(deviceData); deviceData->IsFDO = TRUE; deviceData->Self = deviceObject; ExInitializeFastMutex(&deviceData->Mutex); InitializeListHead(&deviceData->ListOfPDOs); deviceData->UnderlyingPDO = PhysicalDeviceObject; deviceData->DevicePowerState = PowerDeviceUnspecified; deviceData->SystemPowerState = PowerSystemWorking; deviceData->OutstandingIO = 1; KeInitializeEvent(&deviceData->RemoveEvent, SynchronizationEvent, FALSE); KeInitializeEvent(&deviceData->StopEvent, SynchronizationEvent, TRUE); deviceObject->Flags |= DO_POWER_PAGABLE; status = IoRegisterDeviceInterface(PhysicalDeviceObject, (LPGUID) &GUID_DEVINTERFACE_SCPVBUS, NULL, &deviceData->InterfaceName); if (!NT_SUCCESS(status)) { Bus_KdPrint(("AddDevice: IoRegisterDeviceInterface failed (%x)", status)); goto End; } deviceData->NextLowerDriver = IoAttachDeviceToDeviceStack(deviceObject, PhysicalDeviceObject); if (deviceData->NextLowerDriver == NULL) { status = STATUS_NO_SUCH_DEVICE; goto End; } deviceObject->Flags &= ~DO_DEVICE_INITIALIZING; End: if (deviceName) { ExFreePool(deviceName); } if (!NT_SUCCESS(status) && deviceObject) { if (deviceData && deviceData->NextLowerDriver) { IoDetachDevice(deviceData->NextLowerDriver); } IoDeleteDevice(deviceObject); } return status; }
NTSTATUS bus_plugin_dev(ioctl_usbvbus_plugin * plugin, PFDO_DEVICE_DATA fdodata, PFILE_OBJECT fo) { PDEVICE_OBJECT pdo; PPDO_DEVICE_DATA pdodata, old_pdodata; NTSTATUS status; ULONG len; PLIST_ENTRY entry; unsigned long i; PAGED_CODE (); Bus_KdPrint (fdodata, BUS_DBG_PNP_INFO, ("Exposing PDO\n" "======addr: %d\n" "======vendor:product: %04x:%04x\n", plugin->addr, plugin->vendor, plugin->product)); if(plugin->addr <= 0) return STATUS_INVALID_PARAMETER; ExAcquireFastMutex (&fdodata->Mutex); for (entry = fdodata->ListOfPDOs.Flink; entry != &fdodata->ListOfPDOs; entry = entry->Flink) { pdodata = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); if (plugin->addr == pdodata->SerialNo && pdodata->DevicePnPState != SurpriseRemovePending) { ExReleaseFastMutex (&fdodata->Mutex); return STATUS_INVALID_PARAMETER; } } ExReleaseFastMutex (&fdodata->Mutex); // Create the PDO // Bus_KdPrint(fdodata, BUS_DBG_PNP_NOISE, ("fdodata->NextLowerDriver = 0x%p\n", fdodata->NextLowerDriver)); // // PDO must have a name. You should let the system auto generate a // name by specifying FILE_AUTOGENERATED_DEVICE_NAME in the // DeviceCharacteristics parameter. Let us create a secure deviceobject, // in case the child gets installed as a raw device (RawDeviceOK), to prevent // an unpriviledged user accessing our device. This function is avaliable // in a static WDMSEC.LIB and can be used in Win2k, XP, and Server 2003 // Just make sure that the GUID specified here is not a setup class GUID. // If you specify a setup class guid, you must make sure that class is // installed before enumerating the PDO. // status = IoCreateDeviceSecure(fdodata->Self->DriverObject, sizeof (PDO_DEVICE_DATA), NULL, FILE_DEVICE_BUS_EXTENDER, FILE_AUTOGENERATED_DEVICE_NAME |FILE_DEVICE_SECURE_OPEN, FALSE, &SDDL_DEVOBJ_SYS_ALL_ADM_ALL, // read wdmsec.h for more info (LPCGUID)&GUID_SD_BUSENUM_PDO, &pdo); if (!NT_SUCCESS (status)) { return status; } pdodata = (PPDO_DEVICE_DATA) pdo->DeviceExtension; #define HARDWARE_IDS_TPL L"USB\\Vid_%04x&Pid_%04x&Rev_%04xZUSB\\Vid_%04x&Pid_%04xZ" len = sizeof(HARDWARE_IDS_TPL); pdodata->HardwareIDs = ExAllocatePoolWithTag (NonPagedPool, len, BUSENUM_POOL_TAG); if (NULL == pdodata->HardwareIDs) { IoDeleteDevice(pdo); return STATUS_INSUFFICIENT_RESOURCES; } RtlStringCchPrintfW(pdodata->HardwareIDs, len/sizeof(wchar_t), HARDWARE_IDS_TPL, plugin->vendor, plugin->product, plugin->version, plugin->vendor, plugin->product); for(i=0;i<sizeof(HARDWARE_IDS_TPL);i++){ if('Z'==pdodata->HardwareIDs[i]) pdodata->HardwareIDs[i]=0; } #define COMPATIBLE_IDS_TPL L"USB\\Class_%02x&SubClass_%02x&Prot_%02xZUSB\\Class_%02x&SubClass_%02xZUSB\\Class_%02xZ" #define COMPATIBLE_COMPOSITE_IDS_TPL L"USB\\Class_%02x&SubClass_%02x&Prot_%02xZUSB\\Class_%02x&SubClass_%02xZUSB\\Class_%02xZUSB\\COMPOSITEZ" if(plugin->inum>1) len = sizeof(COMPATIBLE_COMPOSITE_IDS_TPL); else len = sizeof(COMPATIBLE_IDS_TPL); pdodata->compatible_ids = ExAllocatePoolWithTag (NonPagedPool, len, BUSENUM_POOL_TAG); RtlZeroMemory(pdodata->compatible_ids, len); if (NULL == pdodata->compatible_ids) { ExFreePool(pdodata->HardwareIDs); IoDeleteDevice(pdo); return STATUS_INSUFFICIENT_RESOURCES; } pdodata->compatible_ids_len = len; RtlStringCchPrintfW(pdodata->compatible_ids, len/sizeof(wchar_t), (plugin->inum>1)?COMPATIBLE_COMPOSITE_IDS_TPL:COMPATIBLE_IDS_TPL, plugin->int0_class, plugin->int0_subclass, plugin->int0_protocol, plugin->int0_class, plugin->int0_subclass, plugin->int0_class); for(i=0;i<len;i++){ if('Z'==pdodata->compatible_ids[i]) pdodata->compatible_ids[i]=0; } old_pdodata = (PPDO_DEVICE_DATA) InterlockedCompareExchange(&((LONG)fo->FsContext), (LONG) pdodata, 0); if(old_pdodata){ KdPrint(("you can't plugin again")); ExFreePool(pdodata->HardwareIDs); ExFreePool(pdodata->compatible_ids); IoDeleteDevice(pdo); return STATUS_INVALID_PARAMETER; } pdodata->SerialNo = plugin->addr; pdodata->fo = fo; pdodata->devid = plugin->devid; pdodata->speed = plugin->speed; bus_init_pdo (pdo, fdodata); // // Device Relation changes if a new pdo is created. So let // the PNP system now about that. This forces it to send bunch of pnp // queries and cause the function driver to be loaded. // IoInvalidateDeviceRelations (fdodata->UnderlyingPDO, BusRelations); return status; }
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 ( 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, outlen; PFDO_DEVICE_DATA fdoData; PVOID buffer; PAGED_CODE (); fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension; // // We only take Device Control requests for the FDO. // That is the bus itself. // if (!fdoData->IsFDO) { // // These commands are only allowed to go to the FDO. // status = STATUS_INVALID_DEVICE_REQUEST; Irp->IoStatus.Status = status; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } // // Check to see whether the bus is removed // 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; outlen = irpStack->Parameters.DeviceIoControl.OutputBufferLength; status = STATUS_INVALID_PARAMETER; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("%d called\n", irpStack->Parameters.DeviceIoControl.IoControlCode)); switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_LANSCSI_ADD_TARGET: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); if ((inlen == outlen) && (sizeof(LANSCSI_ADD_TARGET_DATA) <= inlen)) { ULONG ulSize; PLANSCSI_ADD_TARGET_DATA pBuffer = buffer; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_ADD_TARGET called\n")); Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET Target Type %d\n", pBuffer->ucTargetType)); // Check Parameter. switch(pBuffer->ucTargetType) { case DISK_TYPE_NORMAL: case DISK_TYPE_DVD: case DISK_TYPE_VDVD: case DISK_TYPE_MO: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA); if(pBuffer->ulNumberOfUnitDiskList != 1) ulSize = 0; // Exit when Check if(ulSize != inlen)... break; case DISK_TYPE_MIRROR: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK); if(2 != pBuffer->ulNumberOfUnitDiskList) ulSize = 0; // Exit when Check if(ulSize != inlen)... break; case DISK_TYPE_AGGREGATION: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK) * (pBuffer->ulNumberOfUnitDiskList - 1); if(pBuffer->ulNumberOfUnitDiskList < 1 || pBuffer->ulNumberOfUnitDiskList > 0xFFFF) ulSize = 0; // Exit when Check if(ulSize != inlen)... break; case DISK_TYPE_BIND_RAID1: ulSize = sizeof(LANSCSI_ADD_TARGET_DATA) + sizeof(LSBUS_UNITDISK) * (pBuffer->ulNumberOfUnitDiskList - 1); // if(pBuffer->ulNumberOfUnitDiskList < 1 || pBuffer->ulNumberOfUnitDiskList > MAX_NR_TC_PER_TARGET) if(pBuffer->ulNumberOfUnitDiskList < 2 || pBuffer->ulNumberOfUnitDiskList > 0xFFFF) ulSize = 0; // Exit when Check if(ulSize != inlen)... if(pBuffer->ulNumberOfUnitDiskList % 2) // should be the multiples of 2 ulSize = 0; // Exit when Check if(ulSize != inlen)... break; default: Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET: Bad Disk Type.\n")); status = STATUS_UNSUCCESSFUL; break; } // Check Size. if(ulSize != inlen) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET: Size mismatch. Req %d, in %d\n", ulSize, inlen)); status = STATUS_UNSUCCESSFUL; break; } // Find Pdo Data... pdoData = LookupPdoData(fdoData, pBuffer->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; break; } /* // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_ADD_TARGET, buffer, sizeof(LANSCSI_ADD_TARGET_DATA), NULL, 0 ); */ pdoData->LanscsiAdapterPDO.AddTargetData = ExAllocatePool(NonPagedPool, inlen); if(pdoData->LanscsiAdapterPDO.AddTargetData == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; } else { RtlCopyMemory(pdoData->LanscsiAdapterPDO.AddTargetData, pBuffer, inlen); status = STATUS_SUCCESS; } // // Notify to LanscsiMiniport // Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET SetEvent AddTargetEvent!\n")); KeSetEvent(&pdoData->LanscsiAdapterPDO.AddTargetEvent, IO_NO_INCREMENT, FALSE); ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; } else Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_ADD_TARGET length mismatch!!! inlen %d, outlen %d, sizeof(LANSCSI_ADD_TARGET_DATA) %d\n", inlen, outlen, sizeof(LANSCSI_ADD_TARGET_DATA))); } break; case IOCTL_LANSCSI_REMOVE_TARGET: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_REMOVE_TARGET called\n")); if (sizeof (LANSCSI_REMOVE_TARGET_DATA) != inlen) break; pdoData = LookupPdoData(fdoData, ((PLANSCSI_REMOVE_TARGET_DATA)buffer)->ulSlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; break; } // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_REMOVE_TARGET, buffer, sizeof(LANSCSI_REMOVE_TARGET_DATA), NULL, 0 ); ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; break; } case IOCTL_LANSCSI_SETPDOINFO: { PPDO_DEVICE_DATA pdoData; PBUSENUM_SETPDOINFO SetPdoInfo; KIRQL oldIrql; PVOID sectionHandle; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_SETPDOINFO called\n")); if (sizeof (BUSENUM_SETPDOINFO) != inlen) break; SetPdoInfo = (PBUSENUM_SETPDOINFO)buffer; pdoData = LookupPdoData(fdoData, (SetPdoInfo)->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("no pdo\n")); status = STATUS_UNSUCCESSFUL; break; } // // set information // lock the code section of the function to raise IRQL // because the function is PAGED_CODE. // sectionHandle = MmLockPagableCodeSection(Bus_IoCtl); KeAcquireSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql); Bus_KdPrint(fdoData, BUS_DBG_IOCTL_ERROR, ("!!!!!!!!!!!!!!!!!! IOCTL_LANSCSI_SETPDOINFO: %08lx %08lx %08lx\n", SetPdoInfo->AdapterStatus, SetPdoInfo->DesiredAccess, SetPdoInfo->GrantedAccess)); pdoData->LanscsiAdapterPDO.AdapterStatus = SetPdoInfo->AdapterStatus; pdoData->LanscsiAdapterPDO.DesiredAccess = SetPdoInfo->DesiredAccess; pdoData->LanscsiAdapterPDO.GrantedAccess = SetPdoInfo->GrantedAccess; KeReleaseSpinLock(&pdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql); MmUnlockPagableImageSection(sectionHandle); status = STATUS_SUCCESS; ObDereferenceObject(pdoData->Self); Irp->IoStatus.Information = outlen; } break; case IOCTL_BUSENUM_QUERY_NODE_ALIVE: { PPDO_DEVICE_DATA pdoData; BOOLEAN bAlive; PBUSENUM_NODE_ALIVE_IN pNodeAliveIn; BUSENUM_NODE_ALIVE_OUT nodeAliveOut; // Check Parameter. if(inlen != sizeof(BUSENUM_NODE_ALIVE_IN) || outlen != sizeof(BUSENUM_NODE_ALIVE_OUT)) { status = STATUS_UNKNOWN_REVISION; break; } pNodeAliveIn = (PBUSENUM_NODE_ALIVE_IN)Irp->AssociatedIrp.SystemBuffer; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_NOISE, ("FDO: IOCTL_BUSENUM_QUERY_NODE_ALIVE SlotNumber = %d\n", pNodeAliveIn->SlotNo)); pdoData = LookupPdoData(fdoData, pNodeAliveIn->SlotNo); if(pdoData == NULL) { // Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE, // ("[LanScsiBus]Bus_IoCtl: IOCTL_BUSENUM_QUERY_NODE_ALIVE No pdo\n")); bAlive = FALSE; } else { // // Check this PDO would be removed... // if(pdoData->Present == TRUE) bAlive = TRUE; else bAlive = FALSE; } // For Result... nodeAliveOut.SlotNo = pNodeAliveIn->SlotNo; nodeAliveOut.bAlive = bAlive; // Get Adapter Status. if(bAlive == TRUE) { if( ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUS_IN_ERROR) || ADAPTERINFO_ISSTATUS(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUS_STOPPING) /*|| ADAPTERINFO_ISSTATUSFLAG(pdoData->LanscsiAdapterPDO.AdapterStatus, ADAPTERINFO_STATUSFLAG_MEMBER_FAULT) */ ) { nodeAliveOut.bHasError = TRUE; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_BUSENUM_QUERY_NODE_ALIVE Adapter has Error 0x%x\n", nodeAliveOut.bHasError)); } else { nodeAliveOut.bHasError = FALSE; } } if(pdoData) ObDereferenceObject(pdoData->Self); RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, &nodeAliveOut, sizeof(BUSENUM_NODE_ALIVE_OUT) ); Irp->IoStatus.Information = sizeof(BUSENUM_NODE_ALIVE_OUT); status = STATUS_SUCCESS; } break; // // added by hootch 01172004 // case IOCTL_LANSCSI_UPGRADETOWRITE: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_UPGRADETOWRITE called\n")); // Check Parameter. if(inlen != sizeof(BUSENUM_UPGRADE_TO_WRITE)) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_UPGRADETOWRITE: Invalid input buffer length\n")); status = STATUS_UNKNOWN_REVISION; break; } pdoData = LookupPdoData(fdoData, ((PBUSENUM_UPGRADE_TO_WRITE)buffer)->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_UPGRADETOWRITE No pdo\n")); status = STATUS_NO_SUCH_DEVICE; } else { // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_UPGRADETOWRITE, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = 0; } break; case IOCTL_LANSCSI_QUERY_LSMPINFORMATION: { PPDO_DEVICE_DATA pdoData; Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("IOCTL_LANSCSI_QUERY_LSMPINFORMATION called\n")); // Check Parameter. if(inlen < sizeof(LSMPIOCTL_QUERYINFO)) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_QUERY_LSMPINFORMATION: Invalid input buffer length too small.\n")); status = STATUS_UNKNOWN_REVISION; break; } pdoData = LookupPdoData(fdoData, ((PLSMPIOCTL_QUERYINFO)buffer)->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_LANSCSI_QUERY_LSMPINFORMATION No pdo\n")); status = STATUS_NO_SUCH_DEVICE; } else { // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_QUERYINFO_EX, buffer, inlen, buffer, outlen ); ObDereferenceObject(pdoData->Self); } Irp->IoStatus.Information = outlen; } break; case IOCTL_BUSENUM_QUERY_INFORMATION: { // PPDO_DEVICE_DATA pdoData; BUSENUM_QUERY_INFORMATION Query; PBUSENUM_INFORMATION Information; LONG BufferLenNeeded; // Check Parameter. if( inlen < sizeof(BUSENUM_QUERY_INFORMATION) /*|| outlen < sizeof(BUSENUM_INFORMATION) */) { status = STATUS_UNKNOWN_REVISION; break; } RtlCopyMemory(&Query, buffer, sizeof(BUSENUM_QUERY_INFORMATION)); Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_TRACE, ("FDO: IOCTL_BUSENUM_QUERY_INFORMATION QueryType : %d SlotNumber = %d\n", Query.InfoClass, Query.SlotNo)); Information = (PBUSENUM_INFORMATION)buffer; ASSERT(Information); Information->InfoClass = Query.InfoClass; status = LSBus_QueryInformation(fdoData, &Query, Information, outlen, &BufferLenNeeded); if(NT_SUCCESS(status)) { Information->Size = BufferLenNeeded; Irp->IoStatus.Information = BufferLenNeeded; } else { Irp->IoStatus.Information = BufferLenNeeded; } } break; /* case IOCTL_BUSENUM_PLUGIN_HARDWARE: status = STATUS_INVALID_PARAMETER; break; */ // inserted by ILGU case IOCTL_BUSENUM_PLUGIN_HARDWARE_EX: if ((inlen == outlen) && // // 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_EX) + 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_EX) == ((PBUSENUM_PLUGIN_HARDWARE_EX) buffer)->Size)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n")); status= Bus_PlugInDeviceEx((PBUSENUM_PLUGIN_HARDWARE_EX)buffer, inlen, fdoData, Irp); Irp->IoStatus.Information = outlen; } break; case IOCTL_BUSENUM_UNPLUG_HARDWARE: if ((sizeof (BUSENUM_UNPLUG_HARDWARE) == inlen) && (inlen == outlen) && (((PBUSENUM_UNPLUG_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n")); status= Bus_UnPlugDevice( (PBUSENUM_UNPLUG_HARDWARE)buffer, fdoData); Irp->IoStatus.Information = outlen; } break; case IOCTL_BUSENUM_EJECT_HARDWARE: if ((sizeof (BUSENUM_EJECT_HARDWARE) == inlen) && (inlen == outlen) && (((PBUSENUM_EJECT_HARDWARE)buffer)->Size == inlen)) { Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n")); status= Bus_EjectDevice((PBUSENUM_EJECT_HARDWARE)buffer, fdoData); Irp->IoStatus.Information = outlen; } break; // Added by ILGU HONG 2004_07_05 case IOCTL_DVD_GET_STATUS: { PPDO_DEVICE_DATA pdoData; PBUSENUM_DVD_STATUS pDvdStatusData; // Check Parameter. if((inlen != outlen) || (sizeof(BUSENUM_DVD_STATUS) > inlen)) { status = STATUS_UNSUCCESSFUL ; break; } pDvdStatusData = (PBUSENUM_DVD_STATUS)Irp->AssociatedIrp.SystemBuffer; Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("FDO: IOCTL_DVD_GET_STATUS SlotNumber = %d\n", pDvdStatusData->SlotNo)); pdoData = LookupPdoData(fdoData, pDvdStatusData->SlotNo); if(pdoData == NULL) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_DVD_GET_STATUS No pdo\n")); status = STATUS_UNSUCCESSFUL; break; } else { if(pdoData->LanscsiAdapterPDO.AddTargetData->ucTargetType != DISK_TYPE_DVD) { Bus_KdPrint_Cont (fdoData, BUS_DBG_IOCTL_ERROR, ("IOCTL_DVD_GET_STATUS No DVD Device\n")); status = STATUS_UNSUCCESSFUL; break; } // // redirect to the LanscsiMiniport Device // status = LSBus_IoctlToLSMPDevice( pdoData, LANSCSIMINIPORT_IOCTL_GET_DVD_STATUS, buffer, inlen, buffer, outlen ) ; ObDereferenceObject(pdoData->Self); status = STATUS_SUCCESS; Irp->IoStatus.Information = outlen; } } break; // Added by ILGU HONG 2004_07_05 end #if 0 case IOCTL_VDVD_GET_VDVD_HD_INFO : { PGET_VDVD_HD_INFO pHeader = NULL; if((inlen == outlen) && (sizeof(GET_VDVD_HD_INFO) <= inlen)) { XXprint(4,("Called IOCTL_VDVD_GET_VDVD_HD_INFO\n")); pHeader = (PGET_VDVD_HD_INFO)buffer; switch(pHeader->COM){ case COM_GET_VDVD_COUNT : { if(inlen != sizeof(GET_VDVD_HD_INFO)){ Irp->IoStatus.Information = outlen; status = STATUS_UNSUCCESSFUL; break; } pHeader->COUNT = FindVDVDPdoCount(fdoData); XXprint(4,("COM_GET_VDVD_COUNT %d\n",pHeader->COUNT)); Irp->IoStatus.Information = outlen; status = STATUS_SUCCESS; } break; case COM_GET_VDVD_HD_INFO : { PPDO_DEVICE_DATA pdoData; PDISC_HEADER pDiscHeader = NULL; if(inlen != sizeof(GET_VDVD_HD_INFO)){ Irp->IoStatus.Information = outlen; status = STATUS_UNSUCCESSFUL; break; } pdoData = FindPdoData(fdoData, pHeader->SlotNo); if(pdoData == NULL) { XXprint(4,("COM_GET_VDVD_HD_INFO : Can't find pdo\n")); status = STATUS_UNSUCCESSFUL; break; } pDiscHeader = pdoData->LanscsiAdapter.LogicalTarget[0].Llu[0].Targets[0].TargetConnectionList.pHeader; pHeader->DISC[0].DISCS = pDiscHeader->DISCS; pHeader->DISC[0].ENABLE_DISCS = pDiscHeader->ENABLE_DISCS; pHeader->DISC[0].SlotNo = pHeader->SlotNo; XXprint(4,("COM_GET_VDVD_HD_INFO : #of DISC(%d), #of ENABLED(%d), SlotNo(%d)\n", pHeader->DISC[0].DISCS,pHeader->DISC[0].ENABLE_DISCS, pHeader->DISC[0].SlotNo)); Irp->IoStatus.Information = outlen; status = STATUS_SUCCESS; } break; case COM_GET_VDVD_HD_INFO_ALL: { int size = sizeof(GET_VDVD_HD_INFO) + (sizeof(VDVD_DISC_HD)*(pHeader->COUNT-1)); if(inlen != size){ Irp->IoStatus.Information = outlen; status = STATUS_UNSUCCESSFUL; break; } FindVDVDPdoInfo(fdoData,pHeader); Irp->IoStatus.Information = outlen; status = STATUS_SUCCESS; } break; default: Irp->IoStatus.Information = outlen; status = STATUS_UNSUCCESSFUL; break; } } else{ Irp->IoStatus.Information = outlen; status = STATUS_UNSUCCESSFUL; } } break; case IOCTL_VDVD_GET_VDVD_DISC_INFO: { XXprint(4,("Called IOCTL_VDVD_GET_VDVD_DISC_INFO START\n")); if((inlen == outlen) && (sizeof(GET_VDVD_DISC_INFO) <= inlen)) { PGET_VDVD_DISC_INFO pDiscInfo = (PGET_VDVD_DISC_INFO)buffer; PTARGET_CONNECTION TargetConnection; XXprint(4,("Called IOCTL_VDVD_GET_VDVD_DISC_INFO\n")); switch(pDiscInfo->COM) { case COM_GET_VDVD_DISC_INFO : { PPDO_DEVICE_DATA pdoData; PJUKE_DISC pInfo = NULL; if(inlen != sizeof(GET_VDVD_DISC_INFO)) { Irp->IoStatus.Information = outlen; status = STATUS_UNSUCCESSFUL; break; } pdoData = FindPdoData(fdoData, pDiscInfo->SlotNo); if(pdoData == NULL) { XXprint(4,("COM_GET_VDVD_DISC_INFO : Can't find pdo\n")); status = STATUS_UNSUCCESSFUL; break; } TargetConnection = &(pdoData->LanscsiAdapter.LogicalTarget[0].Llu[0].Targets[0].TargetConnectionList); if(pDiscInfo->DiscNo >= TargetConnection->pHeader->DISCS ) { XXprint(4,("COM_GET_VDVD_DISC_INFO : DISC nub is too big!!\n")); status = STATUS_UNSUCCESSFUL; break; } pInfo = &(TargetConnection->pInfos[pDiscInfo->DiscNo]); pDiscInfo->DISC[0].LOCATION = pInfo->LOCATION; pDiscInfo->DISC[0].START_SEC = pInfo->START_SEC; pDiscInfo->DISC[0].NR_SEC = pInfo->NR_SEC; pDiscInfo->DISC[0].ENABLED = pInfo->ENABLED; Irp->IoStatus.Information = outlen; XXprint(4,("COM_GET_VDVD_DISC_INFO : LOCATION(0x%I64x), START_SEC(0x%I64x), ENABLED(%d)\n", pDiscInfo->DISC[0].LOCATION, pDiscInfo->DISC[0].START_SEC, pDiscInfo->DISC[0].ENABLED)); status = STATUS_SUCCESS; } break; case COM_VDVD_DISC_INFO_ALL: { PPDO_DEVICE_DATA pdoData; PJUKE_DISC pInfo = NULL; ULONG size = sizeof(GET_VDVD_DISC_INFO) + (sizeof(DISC_INFO) * (pDiscInfo->COUNT - 1)); int i = 0; int max = 0; if(inlen != size) { Irp->IoStatus.Information = outlen; status = STATUS_UNSUCCESSFUL; break; } pdoData = FindPdoData(fdoData, pDiscInfo->SlotNo); if(pdoData == NULL) { XXprint(4,("COM_VDVD_DISC_INFO_ALL : Can't find pdo\n")); status = STATUS_UNSUCCESSFUL; break; } TargetConnection = &(pdoData->LanscsiAdapter.LogicalTarget[0].Llu[0].Targets[0].TargetConnectionList); if(pDiscInfo->COUNT > TargetConnection->pHeader->DISCS) { pDiscInfo->COUNT = TargetConnection->pHeader->DISCS; } max = pDiscInfo->COUNT; for(i = 0; i< max; i++){ pInfo = &(TargetConnection->pInfos[i]); pDiscInfo->DISC[i].LOCATION = pInfo->LOCATION; pDiscInfo->DISC[i].START_SEC = pInfo->START_SEC; pDiscInfo->DISC[i].NR_SEC = pInfo->NR_SEC; pDiscInfo->DISC[i].ENABLED = pInfo->ENABLED; XXprint(4,("COM_VDVD_DISC_INFO_ALL(%d) : LOCATION(0x%I64x), START_SEC(0x%I64x), ENABLED(%d)\n", i,pDiscInfo->DISC[i].LOCATION, pDiscInfo->DISC[i].START_SEC, pDiscInfo->DISC[i].ENABLED)); } Irp->IoStatus.Information = outlen; status = STATUS_SUCCESS; } break; default: Irp->IoStatus.Information = outlen; status = STATUS_UNSUCCESSFUL; break; } }else{ Irp->IoStatus.Information = outlen; status = STATUS_UNSUCCESSFUL; } } break; case IOCTL_VDVD_SET_VDVD_BURN: { if((inlen == outlen) && (sizeof(SET_DVD_DISC_BURN) == inlen)) { XXprint(4,("IOCTL_VDVD_SET_VDVD_BURN\n")); Irp->IoStatus.Information = outlen; status = STATUS_SUCCESS; }else{ Irp->IoStatus.Information = outlen; status = STATUS_UNSUCCESSFUL; } } break; case IOCTL_VDVD_CHANGE_VDVD_DISC: { PCHANGE_VDVD_DISC pChange = (PCHANGE_VDVD_DISC)buffer; if((inlen == outlen) && (sizeof(CHANGE_VDVD_DISC) == inlen)) { XXprint(4,("IOCTL_VDVD_CHANGE_VDVD_DISC\n")); switch(pChange->COM) { case COM_GET_CUR_DISC : { PPDO_DEVICE_DATA pdoData; pdoData = FindPdoData(fdoData, pChange->SlotNo); if(pdoData == NULL) { XXprint(4,("COM_GET_CUR_DISC : Can't find pdo\n")); status = STATUS_UNSUCCESSFUL; break; } KeEnterCriticalRegion(); pChange->DiscNo = pdoData->LanscsiAdapter.LogicalTarget[0].Llu[0].Targets[0].TargetConnectionList.cur_disc; Irp->IoStatus.Information = outlen; KeLeaveCriticalRegion(); status = STATUS_SUCCESS; } break; case COM_SET_CUR_DISC : { PPDO_DEVICE_DATA pdoData; PTARGET_CONNECTION TargetConnection; pdoData = FindPdoData(fdoData, pChange->SlotNo); if(pdoData == NULL) { XXprint(4,("COM_GET_CUR_DISC : Can't find pdo\n")); status = STATUS_UNSUCCESSFUL; break; } KeEnterCriticalRegion(); TargetConnection =&(pdoData->LanscsiAdapter.LogicalTarget[0].Llu[0].Targets[0].TargetConnectionList); if(pChange->DiscNo >= TargetConnection->pHeader->DISCS) { Irp->IoStatus.Information = outlen; status = STATUS_UNSUCCESSFUL; KeLeaveCriticalRegion(); break; } TargetConnection->cur_disc = pChange->DiscNo; TargetConnection->IsChanging = TRUE; TargetConnection->CHCount = 0; Irp->IoStatus.Information = outlen; status = STATUS_SUCCESS; KeLeaveCriticalRegion(); } break; default: Irp->IoStatus.Information = outlen; status = STATUS_UNSUCCESSFUL; } }else{ Irp->IoStatus.Information = outlen; status = STATUS_UNSUCCESSFUL; } } break; #endif // 0 - VDVD default: break; // default status is STATUS_INVALID_PARAMETER } Irp->IoStatus.Status = status; if(Irp->UserIosb) *Irp->UserIosb = Irp->IoStatus; IoCompleteRequest (Irp, IO_NO_INCREMENT); Bus_DecIoCount (fdoData); return status; }
NTSTATUS Bus_Power ( __in PDEVICE_OBJECT DeviceObject, __in PIRP Irp ) /*++ Handles power Irps sent to both FDO and child PDOs. Note: Currently we do not implement full power handling for the FDO. Arguments: DeviceObject - Pointer to the device object. Irp - Pointer to the irp. Return Value: NT status is returned. --*/ { PIO_STACK_LOCATION irpStack; NTSTATUS status; PCOMMON_DEVICE_DATA commonData; status = STATUS_SUCCESS; irpStack = IoGetCurrentIrpStackLocation (Irp); ASSERT (IRP_MJ_POWER == irpStack->MajorFunction); commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension; // // If the device has been removed, the driver should // not pass the IRP down to the next lower driver. // if (commonData->DevicePnPState == Deleted) { PoStartNextPowerIrp (Irp); Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE ; IoCompleteRequest (Irp, IO_NO_INCREMENT); return status; } if (commonData->IsFDO) { Bus_KdPrint (commonData, BUS_DBG_POWER_TRACE, ("FDO %s IRP:0x%p %s %s\n", PowerMinorFunctionString(irpStack->MinorFunction), Irp, DbgSystemPowerString(commonData->SystemPowerState), DbgDevicePowerString(commonData->DevicePowerState))); status = Bus_FDO_Power ((PFDO_DEVICE_DATA)DeviceObject->DeviceExtension, Irp); } else { Bus_KdPrint (commonData, BUS_DBG_POWER_TRACE, ("PDO %s IRP:0x%p %s %s\n", PowerMinorFunctionString(irpStack->MinorFunction), Irp, DbgSystemPowerString(commonData->SystemPowerState), DbgDevicePowerString(commonData->DevicePowerState))); status = Bus_PDO_Power ((PPDO_DEVICE_DATA)DeviceObject->DeviceExtension, Irp); } return status; }
NTSTATUS bus_unplug_dev ( int addr, PFDO_DEVICE_DATA fdodata ) { PLIST_ENTRY entry; PPDO_DEVICE_DATA pdodata; int found=0, all; PAGED_CODE (); if(addr<0||addr>127) return STATUS_INVALID_PARAMETER; all = (0 == addr); ExAcquireFastMutex (&fdodata->Mutex); if (all) { Bus_KdPrint (fdodata, BUS_DBG_IOCTL_NOISE, ("Plugging out all the devices!\n")); } else { Bus_KdPrint (fdodata, BUS_DBG_IOCTL_NOISE, ("Plugging out %d\n", addr)); } if (fdodata->NumPDOs == 0) { // // We got a 2nd plugout...somebody in user space isn't playing nice!!! // Bus_KdPrint (fdodata, BUS_DBG_IOCTL_ERROR, ("BAD BAD BAD...2 removes!!! Send only one!\n")); ExReleaseFastMutex (&fdodata->Mutex); return STATUS_NO_SUCH_DEVICE; } for (entry = fdodata->ListOfPDOs.Flink; entry != &fdodata->ListOfPDOs; entry = entry->Flink) { pdodata = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); Bus_KdPrint (fdodata, BUS_DBG_IOCTL_NOISE, ("found device %d\n", pdodata->SerialNo)); if (all || addr == pdodata->SerialNo) { Bus_KdPrint (fdodata, BUS_DBG_IOCTL_INFO, ("Plugged out %d\n", pdodata->SerialNo)); pdodata->Present = FALSE; complete_pending_read_irp(pdodata); found = 1; if (!all) { break; } } } ExReleaseFastMutex (&fdodata->Mutex); if (found) { IoInvalidateDeviceRelations (fdodata->UnderlyingPDO, BusRelations); ExAcquireFastMutex (&fdodata->Mutex); for (entry = fdodata->ListOfPDOs.Flink; entry != &fdodata->ListOfPDOs; entry = entry->Flink) { pdodata = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); if( pdodata->Present ==FALSE){ complete_pending_irp(pdodata); } } ExReleaseFastMutex (&fdodata->Mutex); Bus_KdPrint (fdodata, BUS_DBG_IOCTL_ERROR, ("Device %d is not present\n", addr)); return STATUS_SUCCESS; } return STATUS_INVALID_PARAMETER; }