コード例 #1
0
ファイル: busenum.c プロジェクト: JanD1943/ndas4windows
VOID
UnplugWorker(
	IN PDEVICE_OBJECT	DeviceObject,
	IN PVOID			Context
){
	NTSTATUS				status;
	PNDBUS_UNPLUGWORKER		ctx = (PNDBUS_UNPLUGWORKER)Context;
	NDASBUS_UNPLUG_HARDWARE	unplug;


	UNREFERENCED_PARAMETER(DeviceObject);


	//
	//	IO_WORKITEM is rare resource, give it back to the system now.
	//

	IoFreeWorkItem(ctx->IoWorkItem);


	//
	//	Start unplug
	//

	unplug.Size = sizeof(unplug);
	unplug.SlotNo = ctx->SlotNo;
	status = Bus_UnPlugDevice(&unplug, ctx->FdoData);
	ASSERT(NT_SUCCESS(status));

	ExFreePool(Context);

}
コード例 #2
0
ファイル: businit.c プロジェクト: fsouza/3dsp
NTSTATUS Bus_UnPlugDevice( PBUSENUM_UNPLUG_HARDWARE UnPlug, PFDO_DEVICE_DATA FdoData )
{
	BOOLEAN plugOutAll;
	PTDSPBUS_DEVICE_DATA pdoData = NULL;
	int ret;

	plugOutAll = (0 == UnPlug->SerialNo);

	if (plugOutAll)
	{
		Bus_DebugPrint( "%s():%d trace! Plugging out all the devices, SerialNo = %lx\n", __FUNCTION__, __LINE__ , UnPlug->SerialNo);
	}
	else
	{
		Bus_DebugPrint( "%s():%d trace! Plugging out %lu\n", __FUNCTION__, __LINE__ , UnPlug->SerialNo);
	}

	if (plugOutAll)
	{	
		UINT32 i;
		for (i = 0; i < BUS_DEVICE_TOTAL_COUNT; i++)
		{
			if (FdoData->DeviceData[i].pDeviceInterface != NULL)
			{
				UnPlug->SerialNo = FdoData->DeviceData[i].SerialNo;
				Bus_UnPlugDevice(UnPlug, FdoData);
			}
		}
	}
	else
	{
		pdoData = Bus_FindPdoBySerialNo(FdoData, UnPlug->SerialNo & HOTKEY_FLAG_AND);
		
		if (pdoData == NULL)
		{
			Bus_DebugPrint("%s():%d fail! SerialNo = %ld not found\n", __FUNCTION__, __LINE__ , UnPlug->SerialNo);
			return STATUS_NO_SUCH_DEVICE;
		}

		if (pdoData->pDeviceInterface->devstate == NotStarted)
		{
			Bus_DebugPrint("%s():%d fail! SerialNo = %ld devstate is NotStarted\n", __FUNCTION__, __LINE__ , UnPlug->SerialNo);
			return STATUS_NO_SUCH_DEVICE;
		}
		
		pdoData->state_old_from_wb = pdoData->pDeviceInterface->devstate;		
		ret = pdoData->pDeviceInterface->close(pdoData->pDeviceInterface);	//whk		
		if (ret == 0)
		{
			pdoData->pDeviceInterface->devstate = Stopped;
			pdoData->state_old_from_wb = pdoData->pDeviceInterface->devstate;
		}
	}

	return 0;
}
コード例 #3
0
NTSTATUS
LSBus_PlugOutLSBUSDevice(
			PFDO_DEVICE_DATA	FdoData,
			ULONG				SlotNo
	) {
	BUSENUM_UNPLUG_HARDWARE		UnPlug;
	NTSTATUS	status;

	UnPlug.Size = sizeof(BUSENUM_UNPLUG_HARDWARE);
	UnPlug.SlotNo = SlotNo;

	status = Bus_UnPlugDevice (
							&UnPlug,
							FdoData
					) ;

		return status;
	}
コード例 #4
0
NTSTATUS
LSBus_PlugOutLSBUSDevice(
			PFDO_DEVICE_DATA	FdoData,
			ULONG				SlotNo,
			BOOLEAN				Persistency
	) {
	BUSENUM_UNPLUG_HARDWARE		UnPlug;
	NTSTATUS	status;
	PPDO_DEVICE_DATA			pdoData;

	//
	//	Set/Reset persistency.
	//

	pdoData = LookupPdoData(FdoData, SlotNo);
	if(pdoData) {
		pdoData->Persistent = Persistency;
		ObDereferenceObject(pdoData->Self);
	} else {
		return STATUS_NOT_FOUND;
	}

	//
	//	Unplug
	//

	UnPlug.Size = sizeof(BUSENUM_UNPLUG_HARDWARE);
	UnPlug.SlotNo = SlotNo;

	status = Bus_UnPlugDevice (
							&UnPlug,
							FdoData
					);

		return status;
	}
コード例 #5
0
ファイル: busenum.c プロジェクト: 340211173/Driver
VOID
Bus_EvtIoDeviceControl(
    IN WDFQUEUE     Queue,
    IN WDFREQUEST   Request,
    IN size_t       OutputBufferLength,
    IN size_t       InputBufferLength,
    IN ULONG        IoControlCode
    )

/*++
Routine Description:

  Handle user mode PlugIn, UnPlug and device Eject requests.

Arguments:

    Queue - Handle to the framework queue object that is associated
            with the I/O request.

    Request - Handle to a framework request object. This one represents
              the IRP_MJ_DEVICE_CONTROL IRP received by the framework.

    OutputBufferLength - Length, in bytes, of the request's output buffer,
                        if an output buffer is available.

    InputBufferLength - Length, in bytes, of the request's input buffer,
                        if an input buffer is available.
    IoControlCode - Driver-defined or system-defined I/O control code (IOCTL)
                    that is associated with the request.

Return Value:

   VOID

--*/
{
    NTSTATUS                 status = STATUS_INVALID_PARAMETER;
    WDFDEVICE                hDevice;
    size_t                   length = 0;
    PBUSENUM_PLUGIN_HARDWARE plugIn = NULL;
    PBUSENUM_UNPLUG_HARDWARE unPlug = NULL;
    PBUSENUM_EJECT_HARDWARE  eject  = NULL;


    UNREFERENCED_PARAMETER(OutputBufferLength);

    PAGED_CODE ();

    hDevice = WdfIoQueueGetDevice(Queue);

    KdPrint(("Bus_EvtIoDeviceControl: 0x%p\n", hDevice));

    switch (IoControlCode) {
    case IOCTL_BUSENUM_PLUGIN_HARDWARE:

        status = WdfRequestRetrieveInputBuffer (Request,
                                    sizeof (BUSENUM_PLUGIN_HARDWARE) +
                                    (sizeof(UNICODE_NULL) * 2), // 2 for double NULL termination (MULTI_SZ)
                                    &plugIn, &length);
        if( !NT_SUCCESS(status) ) {
            KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status));
            break;
        }

        ASSERT(length == InputBufferLength);

        if (sizeof (BUSENUM_PLUGIN_HARDWARE) == plugIn->Size)
        {

            length = (InputBufferLength - sizeof (BUSENUM_PLUGIN_HARDWARE))/sizeof(WCHAR);
            //
            // Make sure the IDs is two NULL terminated.
            //
            if ((UNICODE_NULL != plugIn->HardwareIDs[length - 1]) ||
                (UNICODE_NULL != plugIn->HardwareIDs[length - 2])) {

                status = STATUS_INVALID_PARAMETER;
                break;
            }

            status = Bus_PlugInDevice( hDevice,
                                       plugIn->HardwareIDs,
                                       length,
                                       plugIn->SerialNo );
        }

        break;

    case IOCTL_BUSENUM_UNPLUG_HARDWARE:

        status = WdfRequestRetrieveInputBuffer( Request,
                                                sizeof(BUSENUM_UNPLUG_HARDWARE),
                                                &unPlug,
                                                &length );
        if( !NT_SUCCESS(status) ) {
            KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status));
            break;
        }

        if (unPlug->Size == InputBufferLength)
        {

            status= Bus_UnPlugDevice(hDevice, unPlug->SerialNo );

        }

        break;

    case IOCTL_BUSENUM_EJECT_HARDWARE:

        status = WdfRequestRetrieveInputBuffer (Request,
                                                sizeof (BUSENUM_EJECT_HARDWARE),
                                                &eject, &length);
        if( !NT_SUCCESS(status) ) {
            KdPrint(("WdfRequestRetrieveInputBuffer failed 0x%x\n", status));
            break;
        }

        if (eject->Size == InputBufferLength)
        {
            status= Bus_EjectDevice(hDevice, eject->SerialNo);

        }

        break;

    default:
        break; // default status is STATUS_INVALID_PARAMETER
    }

    WdfRequestCompleteWithInformation(Request, status, length);
}
コード例 #6
0
ファイル: busenum.c プロジェクト: JanD1943/ndas4windows
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
    }
コード例 #7
0
ファイル: busenum.c プロジェクト: tigtigtig/ndas4windows
NTSTATUS
Bus_IoCtl (
    __in  PDEVICE_OBJECT  DeviceObject,
    __in  PIRP            Irp
    )
/*++
Routine Description:

    Handle user mode PlugIn, UnPlug and device Eject requests.

Arguments:

   DeviceObject - pointer to a device object.

   Irp - pointer to an I/O Request Packet.

Return Value:

   NT status code

--*/
{
    PIO_STACK_LOCATION      irpStack;
    NTSTATUS                status;
    ULONG                   inlen;
    PFDO_DEVICE_DATA        fdoData;
    PVOID                   buffer;
    PCOMMON_DEVICE_DATA     commonData;

    PAGED_CODE ();

    commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
    //
    // We only allow create/close requests for the FDO.
    // That is the bus itself.
    //
    if (!commonData->IsFDO) {
        Irp->IoStatus.Status = status = STATUS_INVALID_DEVICE_REQUEST;
        IoCompleteRequest (Irp, IO_NO_INCREMENT);
        return status;
    }

    fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;

    Bus_IncIoCount (fdoData);

    //
    // Check to see whether the bus is removed
    //

    if (fdoData->DevicePnPState == Deleted) {
        status = STATUS_NO_SUCH_DEVICE;
        goto END;
    }

    irpStack = IoGetCurrentIrpStackLocation (Irp);

    buffer = Irp->AssociatedIrp.SystemBuffer;
    inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength;

    status = STATUS_INVALID_PARAMETER;

    switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
    case IOCTL_BUSENUM_PLUGIN_HARDWARE:
        if (
            //
            // Make sure it has at least two nulls and the size
            // field is set to the declared size of the struct
            //
            ((sizeof (BUSENUM_PLUGIN_HARDWARE) + sizeof(UNICODE_NULL) * 2) <=
             inlen) &&

            //
            // The size field should be set to the sizeof the struct as declared
            // and *not* the size of the struct plus the multi_sz
            //
            (sizeof (BUSENUM_PLUGIN_HARDWARE) ==
             ((PBUSENUM_PLUGIN_HARDWARE) buffer)->Size)) {

            Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("PlugIn called\n"));

            status= Bus_PlugInDevice((PBUSENUM_PLUGIN_HARDWARE)buffer,
                                inlen, fdoData);


        }
        break;

    case IOCTL_BUSENUM_UNPLUG_HARDWARE:

        if ((sizeof (BUSENUM_UNPLUG_HARDWARE) == inlen) &&
              (((PBUSENUM_UNPLUG_HARDWARE)buffer)->Size == inlen)) {

            Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("UnPlug called\n"));

            status= Bus_UnPlugDevice(
                    (PBUSENUM_UNPLUG_HARDWARE)buffer, fdoData);

        }
        break;

    case IOCTL_BUSENUM_EJECT_HARDWARE:

        if ((sizeof (BUSENUM_EJECT_HARDWARE) == inlen) &&
            (((PBUSENUM_EJECT_HARDWARE)buffer)->Size == inlen)) {

            Bus_KdPrint(fdoData, BUS_DBG_IOCTL_TRACE, ("Eject called\n"));

            status= Bus_EjectDevice((PBUSENUM_EJECT_HARDWARE)buffer, fdoData);

        }
        break;

    default:
        break; // default status is STATUS_INVALID_PARAMETER
    }

    Irp->IoStatus.Information = 0;
END:
    Irp->IoStatus.Status = status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);
    Bus_DecIoCount (fdoData);
    return status;
}
コード例 #8
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;
}
コード例 #9
0
ファイル: busenum.c プロジェクト: yzx65/ndas4windows
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
    }
コード例 #10
0
ファイル: busenum.c プロジェクト: imahmoodz/ScpToolkit
NTSTATUS Bus_IoCtl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
    PIO_STACK_LOCATION      irpStack;
    NTSTATUS                status;
    ULONG                   inlen;
    PFDO_DEVICE_DATA        fdoData;
    PVOID                   buffer;
    PCOMMON_DEVICE_DATA     commonData;

    commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;

	if (!commonData->IsFDO)
	{
        Irp->IoStatus.Status = status = STATUS_INVALID_DEVICE_REQUEST;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return status;
    }

    fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;

    if (fdoData->DevicePnPState == Deleted)
	{
        Irp->IoStatus.Status = status = STATUS_NO_SUCH_DEVICE;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);

        return status;
    }

    Bus_IncIoCount(fdoData);
    irpStack = IoGetCurrentIrpStackLocation(Irp);

    buffer = Irp->AssociatedIrp.SystemBuffer;
    inlen = irpStack->Parameters.DeviceIoControl.InputBufferLength;

    status = STATUS_INVALID_PARAMETER;
	Irp->IoStatus.Information = 0;

    switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
	{
    case IOCTL_BUSENUM_PLUGIN_HARDWARE:

        if ((sizeof(BUSENUM_PLUGIN_HARDWARE) == inlen) && (((PBUSENUM_PLUGIN_HARDWARE) buffer)->Size == inlen))
		{
            Bus_KdPrint(("PlugIn called\n"));

            status = Bus_PlugInDevice((PBUSENUM_PLUGIN_HARDWARE) buffer, inlen, fdoData);
        }
        break;

    case IOCTL_BUSENUM_UNPLUG_HARDWARE:

        if ((sizeof(BUSENUM_UNPLUG_HARDWARE) == inlen) && (((PBUSENUM_UNPLUG_HARDWARE) buffer)->Size == inlen))
		{
            Bus_KdPrint(("UnPlug called\n"));

            status = Bus_UnPlugDevice((PBUSENUM_UNPLUG_HARDWARE) buffer, fdoData);
        }
        break;

    case IOCTL_BUSENUM_EJECT_HARDWARE:

        if ((sizeof(BUSENUM_EJECT_HARDWARE) == inlen) && (((PBUSENUM_EJECT_HARDWARE) buffer)->Size == inlen))
		{
            Bus_KdPrint(("Eject called\n"));

            status = Bus_EjectDevice((PBUSENUM_EJECT_HARDWARE) buffer, fdoData);
        }
        break;

	case IOCTL_BUSENUM_REPORT_HARDWARE:

        if ((sizeof(BUSENUM_REPORT_HARDWARE) == inlen) && (((PBUSENUM_REPORT_HARDWARE) buffer)->Size == inlen))
		{
            status = Bus_ReportDevice((PBUSENUM_REPORT_HARDWARE) buffer, fdoData, buffer);

			if (NT_SUCCESS(status)) Irp->IoStatus.Information = RUMBLE_SIZE;
        }
		break;

    default:

        break; // default status is STATUS_INVALID_PARAMETER
    }

    Irp->IoStatus.Status = status;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    Bus_DecIoCount(fdoData);

    return status;
}