示例#1
0
void
PrintStatus(DWORD PdoStatus) {
    _tprintf(TEXT("ADAPTERINFO_STATUS : %s\n"),
             ADAPTERINFO_ISSTATUS(PdoStatus, NDASSCSI_ADAPTER_STATUS_INIT) ? TEXT("NDASSCSI_ADAPTER_STATUS_INIT") :
             ADAPTERINFO_ISSTATUS(PdoStatus, NDASSCSI_ADAPTER_STATUS_RUNNING) ? TEXT("NDASSCSI_ADAPTER_STATUS_RUNNING") :
             ADAPTERINFO_ISSTATUS(PdoStatus, NDASSCSI_ADAPTER_STATUS_STOPPING) ? TEXT("NDASSCSI_ADAPTER_STATUS_STOPPING") :
             ADAPTERINFO_ISSTATUS(PdoStatus, NDASSCSI_ADAPTER_STATUS_STOPPED) ? TEXT("NDASSCSI_ADAPTER_STATUS_STOPPED") :
             TEXT("Unknown status"));

#define PRINT_FLAG(STATUS, FLAG) \
	_tprintf(TEXT("") TEXT(#FLAG) TEXT(": %s\n"), ADAPTERINFO_ISSTATUSFLAG((STATUS), (FLAG)) ? TEXT("ON") : TEXT("off"));

    PRINT_FLAG(PdoStatus, NDASSCSI_ADAPTER_STATUSFLAG_RECONNECT_PENDING);
    PRINT_FLAG(PdoStatus, NDASSCSI_ADAPTER_STATUSFLAG_RESTARTING);
    PRINT_FLAG(PdoStatus, NDASSCSI_ADAPTER_STATUSFLAG_BUSRESET_PENDING);
    PRINT_FLAG(PdoStatus, NDASSCSI_ADAPTER_STATUSFLAG_MEMBER_FAULT);
    PRINT_FLAG(PdoStatus, NDASSCSI_ADAPTER_STATUSFLAG_RECOVERING);
    PRINT_FLAG(PdoStatus, NDASSCSI_ADAPTER_STATUSFLAG_ABNORMAL_TERMINAT);
    PRINT_FLAG(PdoStatus, NDASSCSI_ADAPTER_STATUSFLAG_POWERRECYCLED);
    PRINT_FLAG(PdoStatus, NDASSCSI_ADAPTER_STATUSFLAG_RAID_FAILURE);
    PRINT_FLAG(PdoStatus, NDASSCSI_ADAPTER_STATUSFLAG_RAID_NORMAL);
    PRINT_FLAG(PdoStatus, NDASSCSI_ADAPTER_STATUSFLAG_RESETSTATUS);
    PRINT_FLAG(PdoStatus, NDASSCSI_ADAPTER_STATUSFLAG_NEXT_EVENT_EXIST);
#undef PRINT_FLAG
}
void
CNdasEventMonitor::OnLogicalDeviceAlarmedByPnP(
	__in INdasLogicalUnit* pNdasLogicalUnit, 
	__in ULONG NewAdapterStatus)
{
	NDAS_LOCATION ndasLocation;
	COMVERIFY(pNdasLogicalUnit->get_Id(&ndasLocation));

	XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_INFORMATION,
		"Alarm Event, ndasLocation=%08X, logicalUnit=%p\n", 
		ndasLocation, pNdasLogicalUnit);

	if (0 == ndasLocation) 
	{
		XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_ERROR,
			"Invalid SCSI Location\n");
		XTLASSERT(FALSE);
		return;
	}

	XTLTRACE2(NDASSVC_EVENTMON, TRACE_LEVEL_INFORMATION,
		"Logical device alarmed by PnP, ndasLocation=%08X, adapterStatus=%08X.\n", 
		ndasLocation, NewAdapterStatus);

	// Determine whether an alarm will be issued.
	// Only viable alarm will be published
	ULONG currentAdapterStatus;
	COMVERIFY(pNdasLogicalUnit->get_AdapterStatus(&currentAdapterStatus));

	if (pIsViableAlarmStatus(currentAdapterStatus, NewAdapterStatus))
	{
		CNdasEventPublisher& epub = pGetNdasEventPublisher();

		if (ADAPTERINFO_ISSTATUS(NewAdapterStatus, NDASSCSI_ADAPTER_STATUS_STOPPED) &&
			ADAPTERINFO_ISSTATUSFLAG(NewAdapterStatus, NDAS_DEVICE_ALARM_STATUSFLAG_ABNORMAL_TERMINAT))
		{
			//
			// Notify abnormal removal of the LU device.
			//
			OnLogicalDeviceDisconnected(pNdasLogicalUnit);
		}
		else
		{
			NDAS_LOGICALDEVICE_ID logicalUnitId;
			COMVERIFY(pNdasLogicalUnit->get_Id(&logicalUnitId));
			(void) epub.LogicalDeviceAlarmed(
				logicalUnitId, 
				pGetSignificantAlarm(currentAdapterStatus, NewAdapterStatus));
		}
	}

	COMVERIFY(pNdasLogicalUnit->put_AdapterStatus(NewAdapterStatus));
}
示例#3
0
NTSTATUS
LSBus_WaitUntilLanscsiMiniportStop(
		IN	PPDO_LANSCSI_DEVICE_DATA	LanscsiAdapter
	) {
	LARGE_INTEGER	Interval;
	LONG			WaitCnt;
	NTSTATUS		ntStatus;
	KIRQL			oldIrql;

    ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
	Bus_KdPrint_Def(BUS_DBG_SS_TRACE, ("Entered.\n"));

	//
	//	Wait for Lanscsiminiport.
	//
	ntStatus = STATUS_SUCCESS;
	Interval.QuadPart = - NANO100_PER_SEC / 2;	// 0.5 seconds.
	WaitCnt = 0;
	while(1) {

		KeAcquireSpinLock(&LanscsiAdapter->LSDevDataSpinLock, &oldIrql);
		if(ADAPTERINFO_ISSTATUS(LanscsiAdapter->AdapterStatus, ADAPTERINFO_STATUS_STOPPED)) {
			KeReleaseSpinLock(&LanscsiAdapter->LSDevDataSpinLock, oldIrql);
			break;
		}
		KeReleaseSpinLock(&LanscsiAdapter->LSDevDataSpinLock, oldIrql);

		Bus_KdPrint_Def(BUS_DBG_SS_INFO, ("Wait for Lanscsiminiport!!\n"));
		WaitCnt ++;
		KeDelayExecutionThread(KernelMode, TRUE,&Interval);
		if(WaitCnt >= LSBUS_LANSCSIMINIPORT_STOP_TIMEOUT) {
			Bus_KdPrint_Def(BUS_DBG_SS_INFO, ("TimeOut!!!\n"));
			ntStatus = STATUS_TIMEOUT;
			break;
		}
	}

	return ntStatus;
}
示例#4
0
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
    }
示例#5
0
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;
}
示例#6
0
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
    }
示例#7
0
int __cdecl _tmain(int argc, LPTSTR* argv)
{
	BOOL	fSuccess(FALSE);
	ULONG	SlotNo;
	BOOL	bret;

	if(argc < 2) {
		usage();
		return 1;
	}

	if (lstrcmpi(argv[1],TEXT("version")) == 0) {
		WORD VersionMajor;
		WORD VersionMinor;
		WORD VersionBuild;
		WORD VersionPrivate;

		bret = LsBusCtlGetVersion(
					&VersionMajor,
					&VersionMinor,
					&VersionBuild,
					&VersionPrivate
				);
		if(bret == FALSE) {
			_tprintf(TEXT("LanscsiBus control failed. LastError:%lu\n"), GetLastError());
		} else {
			_tprintf(TEXT("- LanscsiBus version\n"));
			_tprintf(	TEXT("Major   : %u\n")
						TEXT("Minor   : %u\n")
						TEXT("Build   : %u\n")
						TEXT("Private : %u\n"),
						VersionMajor, VersionMinor, VersionBuild, VersionPrivate);
		}

	} else if(lstrcmpi(argv[1],TEXT("mpversion")) == 0) {
		WORD VersionMajor;
		WORD VersionMinor;
		WORD VersionBuild;
		WORD VersionPrivate;

		if(argc < 3) {
			usage();
			return 1;
		}

		SlotNo = _tstoi(argv[2]);
		bret = LsBusCtlGetMiniportVersion(
					SlotNo,
					&VersionMajor,
					&VersionMinor,
					&VersionBuild,
					&VersionPrivate
			);
		if(bret == FALSE) {
			_tprintf(TEXT("NDASSCSI control failed. LastError:%lu\n"), GetLastError());
		} else {
			_tprintf(TEXT("- NDASSCSI version\n"));
			_tprintf(	TEXT("Major   : %u\n")
				TEXT("Minor   : %u\n")
				TEXT("Build   : %u\n")
				TEXT("Private : %u\n"),
				VersionMajor, VersionMinor, VersionBuild, VersionPrivate);
		}

	} else if(lstrcmpi(argv[1],TEXT("slotlist")) == 0) {
		PBUSENUM_INFORMATION	busInfo;

		bret = LsBusCtlQueryPdoSlotList(&busInfo);
		if(bret == FALSE) {
			_tprintf(TEXT("Querying slot list failed. LastError:%lu\n"), GetLastError());
		} else {
			ULONG idx_slot;
			_tprintf(TEXT("Slot list:"));
			for(idx_slot = 0; idx_slot < busInfo->PdoSlotList.SlotNoCnt; idx_slot++ ) {
				_tprintf(TEXT(" %lu"), busInfo->PdoSlotList.SlotNo[idx_slot]);
			}
			_tprintf(TEXT("\n"));
			HeapFree(GetProcessHeap(), 0, busInfo);
		}

	} else if(lstrcmpi(argv[1],TEXT("pdoevent")) == 0) {
		HANDLE	alarm;
		HANDLE	discon;

		if(argc < 3) {
			usage();
			return 1;
		}

		SlotNo = _tstoi(argv[2]);
		bret = LsBusCtlQueryPdoEvent(SlotNo, &alarm, &discon);
		if(bret == FALSE) {
			_tprintf(TEXT("Querying pdo events failed. LastError:%lu\n"), GetLastError());
		} else {
			_tprintf(	TEXT("Alarm event        : %p\n")
						TEXT("Disconnection event: %p\n"),
						alarm, discon
				);
			bret = CloseHandle(alarm);
			if(bret == FALSE) {
				_tprintf(TEXT("Closing alarm event failed. LastError:%lu\n"), GetLastError());
			}
			bret = CloseHandle(discon);
			if(bret == FALSE) {
				_tprintf(TEXT("Closing disconnection event failed. LastError:%lu\n"), GetLastError());
			}
		}

	} else if(lstrcmpi(argv[1],TEXT("status")) == 0) {
	  ULONG ulStatus;
		if(argc < 3) {
			usage();
			return 1;
		}

		SlotNo = _tstoi(argv[2]);
		bret = LsBusCtlQueryStatus(SlotNo, &ulStatus);

		if(bret == FALSE) {
			_tprintf(TEXT("Querying LUR full information  failed. LastError:%lu\n"), GetLastError());
		} else {
		  _tprintf(TEXT("ADAPTERINFO_STATUS : %s\n"),
  		  ADAPTERINFO_ISSTATUS(ulStatus, NDASSCSI_ADAPTERINFO_STATUS_INIT) ? TEXT("NDASSCSI_ADAPTERINFO_STATUS_INIT") :
  		  ADAPTERINFO_ISSTATUS(ulStatus, NDASSCSI_ADAPTERINFO_STATUS_RUNNING) ? TEXT("NDASSCSI_ADAPTERINFO_STATUS_RUNNING") :
  		  ADAPTERINFO_ISSTATUS(ulStatus, NDASSCSI_ADAPTERINFO_STATUS_STOPPING) ? TEXT("NDASSCSI_ADAPTERINFO_STATUS_STOPPING") :
  		  ADAPTERINFO_ISSTATUS(ulStatus, NDASSCSI_ADAPTERINFO_STATUS_IN_ERROR) ? TEXT("NDASSCSI_ADAPTERINFO_STATUS_IN_ERROR") :
  		  ADAPTERINFO_ISSTATUS(ulStatus, NDASSCSI_ADAPTERINFO_STATUS_STOPPED) ? TEXT("NDASSCSI_ADAPTERINFO_STATUS_STOPPED") :
  		  TEXT("Unknown status"));

#define PRINT_FLAG(STATUS, FLAG) \
  		_tprintf(TEXT("") TEXT(#FLAG) TEXT(": %s\n"), ADAPTERINFO_ISSTATUSFLAG((STATUS), (FLAG)) ? TEXT("ON") : TEXT("off"));
  		PRINT_FLAG(ulStatus, NDASSCSI_ADAPTERINFO_STATUSFLAG_RECONNECT_PENDING);
  		PRINT_FLAG(ulStatus, ADAPTERINFO_STATUSFLAG_POWERSAVING_PENDING);
  		PRINT_FLAG(ulStatus, ADAPTERINFO_STATUSFLAG_BUSRESET_PENDING);
  		PRINT_FLAG(ulStatus, NDASSCSI_ADAPTERINFO_STATUSFLAG_MEMBER_FAULT);
#undef PRINT_FLAG
		}


	} else if(lstrcmpi(argv[1],TEXT("fdoinfo")) == 0) {
		PNDSCIOCTL_ADAPTERLURINFO	lurFullInfo;

		if(argc < 3) {
			usage();
			return 1;
		}

		SlotNo = _tstoi(argv[2]);
		bret = LsBusCtlQueryMiniportFullInformation(SlotNo, &lurFullInfo);
		if(bret == FALSE) {
			_tprintf(TEXT("Querying LUR full information  failed. LastError:%lu\n"), GetLastError());
		} else {
			ULONG				idx_ud;
			PNDSC_LURN_FULL		unitDisk;

			_tprintf(TEXT("Structure length                     :%u\n"), lurFullInfo->Length);
			_tprintf(TEXT("Adapter.SlotNo                       :%u\n"), lurFullInfo->Adapter.SlotNo);
			_tprintf(TEXT("Adapter.Length                       :%u\n"), lurFullInfo->Adapter.Length);
			_tprintf(TEXT("Adapter.InitiatorId                  :%u\n"), (int)lurFullInfo->Adapter.InitiatorId);
			_tprintf(TEXT("Adapter.NumberOfBuses                :%u\n"), (int)lurFullInfo->Adapter.NumberOfBuses);
			_tprintf(TEXT("Adapter.MaximumNumberOfTargets       :%u\n"), (int)lurFullInfo->Adapter.MaximumNumberOfTargets);
			_tprintf(TEXT("Adapter.MaximumNumberOfLogicalUnits  :%u\n"), (int)lurFullInfo->Adapter.MaximumNumberOfLogicalUnits);
			_tprintf(TEXT("Adapter.MaxBlocksPerRequest          :%u\n"), lurFullInfo->Adapter.MaxBlocksPerRequest);
			_tprintf(TEXT("Adapter.Status                       :%08lx\n"), lurFullInfo->Adapter.Status);
			_tprintf(TEXT("Lur.Length                           :%u\n"), lurFullInfo->Lur.Length);
			_tprintf(TEXT("Lur.DevType                          :%08lx\n"), lurFullInfo->Lur.DevType);
			_tprintf(TEXT("Lur.TargetId                         :%u\n"), lurFullInfo->Lur.TargetId);
			_tprintf(TEXT("Lur.Lun                              :%u\n"), lurFullInfo->Lur.Lun);
			_tprintf(TEXT("Lur.DesiredAccess                    :%08lx\n"), lurFullInfo->Lur.DesiredAccess);
			_tprintf(TEXT("Lur.GrantedAccess                    :%08lx\n"), lurFullInfo->Lur.GrantedAccess);
			_tprintf(TEXT("Lur.LurnCnt                          :%u\n"), lurFullInfo->Lur.LurnCnt);
			_tprintf(TEXT("EnableTime                           :%I64u\n"), lurFullInfo->EnabledTime.QuadPart);
			_tprintf(TEXT("UnitDiskCnt                          :%u\n"), lurFullInfo->UnitDiskCnt);
			for(idx_ud = 0; idx_ud < lurFullInfo->UnitDiskCnt; idx_ud++) {
				unitDisk = lurFullInfo->UnitDisks + idx_ud;
				_tprintf(TEXT("- LURN #%u   :\n"), idx_ud);
				_tprintf(TEXT("Length       :%u\n"), unitDisk->Length);
				_tprintf(TEXT("LurnId       :%u\n"), unitDisk->LurnId);
				_tprintf(TEXT("LurnType     :%u\n"), unitDisk->LurnType);

				_tprintf(TEXT("NetDiskAddress.TAAddressCount            :%u\n"), unitDisk->NetDiskAddress.TAAddressCount);
				_tprintf(TEXT("NetDiskAddress.Address[0].AddressType    :%x\n"), unitDisk->NetDiskAddress.Address[0].AddressType);
				_tprintf(TEXT("NetDiskAddress.Address[0].AddressLength  :%x\n"), unitDisk->NetDiskAddress.Address[0].AddressLength);
				_tprintf(TEXT("NetDiskAddress.Address[0].Address        :%02X %02X | %02X %02X %02X %02X %02X %02X\n"),
													(int)unitDisk->NetDiskAddress.Address[0].Address.Address[0],
													(int)unitDisk->NetDiskAddress.Address[0].Address.Address[1],
													(int)unitDisk->NetDiskAddress.Address[0].Address.Address[2],
													(int)unitDisk->NetDiskAddress.Address[0].Address.Address[3],
													(int)unitDisk->NetDiskAddress.Address[0].Address.Address[4],
													(int)unitDisk->NetDiskAddress.Address[0].Address.Address[5],
													(int)unitDisk->NetDiskAddress.Address[0].Address.Address[6],
													(int)unitDisk->NetDiskAddress.Address[0].Address.Address[7]
													);

				_tprintf(TEXT("BindingAddress.TAAddressCount            :%u\n"), unitDisk->BindingAddress.TAAddressCount);
				_tprintf(TEXT("BindingAddress.Address[0].AddressType    :%x\n"), unitDisk->BindingAddress.Address[0].AddressType);
				_tprintf(TEXT("BindingAddress.Address[0].AddressLength  :%x\n"), unitDisk->BindingAddress.Address[0].AddressLength);
				_tprintf(TEXT("BindingAddress.Address[0].Address        :%02X %02X | %02X %02X %02X %02X %02X %02X\n"),
													(int)unitDisk->BindingAddress.Address[0].Address.Address[0],
													(int)unitDisk->BindingAddress.Address[0].Address.Address[1],
													(int)unitDisk->BindingAddress.Address[0].Address.Address[2],
													(int)unitDisk->BindingAddress.Address[0].Address.Address[3],
													(int)unitDisk->BindingAddress.Address[0].Address.Address[4],
													(int)unitDisk->BindingAddress.Address[0].Address.Address[5],
													(int)unitDisk->BindingAddress.Address[0].Address.Address[6],
													(int)unitDisk->BindingAddress.Address[0].Address.Address[7]
													);
				_tprintf(TEXT("UnitDiskId   :%u\n"), (int)unitDisk->UnitDiskId);
				_tprintf(TEXT("UserID       :%02x %02x %02x %02x\n"),
															(int)unitDisk->UserID[0],
															(int)unitDisk->UserID[1],
															(int)unitDisk->UserID[2],
															(int)unitDisk->UserID[3]
															);
				_tprintf(TEXT("Password     :%02x %02x %02x %02x %02x %02x\n"),
															(int)unitDisk->Password[0],
															(int)unitDisk->Password[1],
															(int)unitDisk->Password[2],
															(int)unitDisk->Password[3],
															(int)unitDisk->Password[4],
															(int)unitDisk->Password[5]
															);
				_tprintf(TEXT("AccessRight  :%08lx\n"), unitDisk->AccessRight);
				_tprintf(TEXT("UnitBlocks   :%u\n"), unitDisk->UnitBlocks);
				_tprintf(TEXT("StatusFlags  :%u\n"), unitDisk->StatusFlags);
			}
			_tprintf(TEXT("\n"));
			HeapFree(GetProcessHeap(), 0, lurFullInfo);
		}

	}  else if(lstrcmpi(argv[1],TEXT("pdofile")) == 0) {
		HANDLE	pdoFileHandle;

		SlotNo = _tstoi(argv[2]);
		bret = LsBusCtlQueryPdoFileHandle(SlotNo, &pdoFileHandle);
		if(bret == FALSE) {
			_tprintf(TEXT("Querying PDO file handle  failed. LastError:%lu\n"), GetLastError());
		} else {
			_tprintf(TEXT("PDO file handle  :%p\n"), pdoFileHandle);
			ZwClose(pdoFileHandle);
		}
	} else {
		usage();
	}


	return fSuccess ? 0 : 1;
}