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; }
// // Plug in a device on LanscsiBus in KernelMode. // NTSTATUS LSBus_PlugInLSBUSDevice( PFDO_DEVICE_DATA FdoData, ULONG SlotNo, PWCHAR HardwareIDs, LONG HardwareIDLen, ULONG MaxBlocksPerRequest ){ PBUSENUM_PLUGIN_HARDWARE_EX BusDevice; ULONG Length; HANDLE DisconEvent; HANDLE AlarmEvent; NTSTATUS status; // // Create events // status = ZwCreateEvent( &DisconEvent, GENERIC_READ, NULL, NotificationEvent, FALSE ); if(!NT_SUCCESS(status)) { Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PlugInLSBUSDevice: ZwCreateEvent() failed. Disconnection event.\n")); return status; } status = ZwCreateEvent( &AlarmEvent, GENERIC_READ, NULL, NotificationEvent, FALSE ); if(!NT_SUCCESS(status)) { ZwClose(DisconEvent); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PlugInLSBUSDevice: ExAllocatePoolWithTag() failed. AlarmEvent\n")); return status; } // // Build BUSENUM_PLUGIN_HARDWARE_EX structure. // Length = sizeof(BUSENUM_PLUGIN_HARDWARE_EX) + HardwareIDLen; BusDevice = ExAllocatePoolWithTag( PagedPool, Length, LSBUS_POOTAG_PLUGIN ); if(!BusDevice) { ZwClose(DisconEvent); ZwClose(AlarmEvent); Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PlugInLSBUSDevice: ExAllocatePoolWithTag() failed.\n")); return STATUS_INSUFFICIENT_RESOURCES; } BusDevice->Size = Length; BusDevice->SlotNo = SlotNo; RtlCopyMemory(BusDevice->HardwareIDs, HardwareIDs, HardwareIDLen); BusDevice->MaxRequestBlocks = MaxBlocksPerRequest; BusDevice->phAlarmEvent = &AlarmEvent; BusDevice->phEvent = &DisconEvent; status = Bus_PlugInDeviceEx(BusDevice, Length, FdoData, KernelMode); // // Close handle to decrease one reference from events. // ZwClose(AlarmEvent); ZwClose(DisconEvent); ExFreePool(BusDevice); 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 < 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 }