Exemplo n.º 1
0
static
NTSTATUS
LfsFiltCloseControl (
	IN	HANDLE			ControlFileHandle,
	IN	PFILE_OBJECT	ControlFileObject
	)
{
	NTSTATUS status;

	if(ControlFileObject)
		ObDereferenceObject(ControlFileObject);

	if(!ControlFileHandle)
		return STATUS_SUCCESS;

	status = ZwClose (ControlFileHandle);

	if (!NT_SUCCESS(status)) {
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("FAILURE, NtClose returned status code=%x\n", status));
	} else {
		Bus_KdPrint_Def(BUS_DBG_SS_TRACE, ("SUCCESS.\n"));
	}

	return status;
}
Exemplo n.º 2
0
//
//	Plug in a device on NDAS bus in KernelMode.
//
NTSTATUS
LSBus_PlugInLSBUSDevice(
			PFDO_DEVICE_DATA				FdoData,
			PBUSENUM_PLUGIN_HARDWARE_EX2	PlugIn
	){
	HANDLE						DisconEvent;
	HANDLE						AlarmEvent;
    NTSTATUS					status;

    //
	//	Create events
    //
	status = ZwCreateEvent(
							&DisconEvent,
							GENERIC_READ,
							NULL,
							NotificationEvent,
							FALSE
						);
	if(!NT_SUCCESS(status)) {
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PlugInLSBUSDevice: ZwCreateEvent() failed. Disconnection event.\n"));
		return status;
	}

	status = ZwCreateEvent(
							&AlarmEvent,
							GENERIC_READ,
							NULL,
							NotificationEvent,
							FALSE
						);
    if(!NT_SUCCESS(status)) {
		ZwClose(DisconEvent);
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PlugInLSBUSDevice: ExAllocatePoolWithTag() failed. AlarmEvent\n"));
		return status;
    }

	//
	//	Set up BUSENUM_PLUGIN_HARDWARE_EX2 structure.
	//
	PlugIn->phAlarmEvent = &AlarmEvent;
	PlugIn->phEvent = &DisconEvent;

	status = Bus_PlugInDeviceEx2(PlugIn, PlugIn->Size, FdoData, KernelMode, TRUE);

	//
	//	Close handle to decrease one reference from events.
	//
	ZwClose(AlarmEvent);
	ZwClose(DisconEvent);

	return status;
}
Exemplo n.º 3
0
NTSTATUS
DriverEntry (
    __in  PDRIVER_OBJECT  DriverObject,
    __in  PUNICODE_STRING RegistryPath
    )
/*++
Routine Description:

    Initialize the driver dispatch table.

Arguments:

    DriverObject - pointer to the driver object

    RegistryPath - pointer to a unicode string representing the path,
                   to driver-specific key in the registry.

Return Value:

  NT Status Code

--*/
{

    Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Driver Entry \n"));

    //
    // Save the RegistryPath for WMI.
    //

    Globals.RegistryPath.MaximumLength = RegistryPath->Length +
                                          sizeof(UNICODE_NULL);
    Globals.RegistryPath.Length = RegistryPath->Length;
    Globals.RegistryPath.Buffer = ExAllocatePoolWithTag(
                                       PagedPool,
                                       Globals.RegistryPath.MaximumLength,
                                       BUSENUM_POOL_TAG
                                       );

    if (!Globals.RegistryPath.Buffer) {

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath);

    //
    // Set entry points into the driver
    //
    DriverObject->MajorFunction [IRP_MJ_CREATE] =
    DriverObject->MajorFunction [IRP_MJ_CLOSE] = Bus_CreateClose;
    DriverObject->MajorFunction [IRP_MJ_PNP] = Bus_PnP;
    DriverObject->MajorFunction [IRP_MJ_POWER] = Bus_Power;
    DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = Bus_IoCtl;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = Bus_SystemControl;
    DriverObject->DriverUnload = Bus_DriverUnload;
    DriverObject->DriverExtension->AddDevice = Bus_AddDevice;

    return STATUS_SUCCESS;
}
Exemplo n.º 4
0
NTSTATUS
LSBus_OpenLanscsiAdapter(
				   IN	PPDO_LANSCSI_DEVICE_DATA	LanscsiAdapter,
				   IN	ULONG				MaxBlocks,
				   IN	PKEVENT				DisconEventToService,
				   IN	PKEVENT				AlarmEventToService
				   )
{

	Bus_KdPrint_Def(BUS_DBG_SS_TRACE, ("Entered.\n"));

    ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);

	RtlZeroMemory(
		LanscsiAdapter,
		sizeof(PDO_LANSCSI_DEVICE_DATA)
		);

	KeInitializeSpinLock(&LanscsiAdapter->LSDevDataSpinLock);
	LanscsiAdapter->MaxBlocksPerRequest = MaxBlocks;
	LanscsiAdapter->DisconEventToService = DisconEventToService;
	LanscsiAdapter->AlarmEventToService = AlarmEventToService;

	//
	//	initialize private fields.
	//
	KeInitializeEvent(
			&LanscsiAdapter->AddTargetEvent,
			NotificationEvent,
			FALSE
    );

	return STATUS_SUCCESS;
}
Exemplo n.º 5
0
NTSTATUS
LSBus_CloseLanscsiAdapter(
					IN	PPDO_LANSCSI_DEVICE_DATA	LanscsiAdapter
					)
{
	
    ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
	Bus_KdPrint_Def(BUS_DBG_SS_TRACE, ("Entered.\n"));

	//
	//	Dereference objects.
	//
	ObDereferenceObject(LanscsiAdapter->DisconEventToService);

	if(LanscsiAdapter->AlarmEventToService)
		ObDereferenceObject(LanscsiAdapter->AlarmEventToService);

	//
	//	Free allocated memory.
	//
	if(LanscsiAdapter->AddDevInfo)
		ExFreePool(LanscsiAdapter->AddDevInfo);

	return STATUS_SUCCESS;
}
Exemplo n.º 6
0
NTSTATUS
VerifyAddTargetData(
	IN PNDASBUS_ADD_TARGET_DATA	AddTargetData
){
	switch(AddTargetData->ucTargetType) {
	case NDASSCSI_TYPE_DISK_NORMAL:
	case NDASSCSI_TYPE_DVD:
	case NDASSCSI_TYPE_VDVD:
	case NDASSCSI_TYPE_MO: {
		if(AddTargetData->ulNumberOfUnitDiskList != 1) {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("NORMAL/ODD: Too many Unit devices\n"));
			return STATUS_TOO_MANY_NODES;
		}
		break;
	}
	case NDASSCSI_TYPE_DISK_RAID0:
	case NDASSCSI_TYPE_DISK_RAID1R2:
	case NDASSCSI_TYPE_DISK_RAID4R2:
	case NDASSCSI_TYPE_DISK_RAID1R3:
	case NDASSCSI_TYPE_DISK_RAID4R3:
	case NDASSCSI_TYPE_DISK_RAID5:        
	case NDASSCSI_TYPE_DISK_MIRROR:
	case NDASSCSI_TYPE_DISK_AGGREGATION: {
		if(AddTargetData->ulNumberOfUnitDiskList <= 1) {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("RAID: Too few Unit devices\n"));
			return STATUS_INVALID_PARAMETER;
		}
		break;
	}
	case NDASSCSI_TYPE_AOD: {
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("AOD: Not supported\n"));
		return STATUS_NOT_SUPPORTED;
	}
	default:
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Invalid target type.\n"));
		return STATUS_OBJECT_TYPE_MISMATCH;
	}

	return STATUS_SUCCESS;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
static
NTSTATUS
LfsFiltIoControl(
	IN  HANDLE			ControlFileHandle,
	IN	PFILE_OBJECT	ControlFileObject,
	IN	ULONG    		IoControlCode,
	IN	PVOID    		InputBuffer OPTIONAL,
	IN	ULONG    		InputBufferLength,
	OUT PVOID	    	OutputBuffer OPTIONAL,
	IN	ULONG    		OutputBufferLength
	)
{
	NTSTATUS		ntStatus;
	PDEVICE_OBJECT	deviceObject;
	PIRP			irp;
	KEVENT	    	event;
	IO_STATUS_BLOCK	ioStatus;

	UNREFERENCED_PARAMETER(ControlFileHandle);

	Bus_KdPrint_Def(BUS_DBG_SS_TRACE, ("Entered\n"));

	deviceObject = IoGetRelatedDeviceObject(ControlFileObject);
	
	KeInitializeEvent(&event, NotificationEvent, FALSE);

	irp = IoBuildDeviceIoControlRequest(
			IoControlCode,
			deviceObject,
			InputBuffer,
			InputBufferLength,
			OutputBuffer,
			OutputBufferLength,
			FALSE,
			&event,
			&ioStatus
			);
	
	if (irp == NULL) {
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	ntStatus = IoCallDriver(deviceObject, irp);
	if (ntStatus == STATUS_PENDING)
	{
		KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
		ntStatus = ioStatus.Status;
	}

	return ntStatus;
}
Exemplo n.º 9
0
VOID
Bus_DriverUnload (
    IN PDRIVER_OBJECT DriverObject
    )
/*++
Routine Description:
    Clean up everything we did in driver entry.

Arguments:

   DriverObject - pointer to this driverObject.


Return Value:

--*/
{
    PAGED_CODE ();

    Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Unload\n"));
    
    //
    // All the device objects should be gone.
    //

    ASSERT (NULL == DriverObject->DeviceObject);
	UNREFERENCED_PARAMETER(DriverObject);

    //
    // Here we free all the resources allocated in the DriverEntry
    //

    if(Globals.RegistryPath.Buffer)
        ExFreePool(Globals.RegistryPath.Buffer);   
        
    return;
}
Exemplo n.º 10
0
VOID
Bus_InterfaceDereference (
   IN PVOID Context
   )
/*++

Routine Description:

    This routine decrements the refcount. We check this refcount
    during query_remove decide whether to allow the remove or not.

Arguments:

    Context        pointer to  PDO device extension

Return Value:

--*/
{
	Bus_KdPrint_Def(BUS_DBG_PNP_INFO, 
            ("Entered\n"));

    InterlockedDecrement(&((PPDO_DEVICE_DATA)Context)->ToasterInterfaceRefCount);
}
Exemplo n.º 11
0
NTSTATUS
Bus_AddDevice(
    __in PDRIVER_OBJECT DriverObject,
    __in PDEVICE_OBJECT PhysicalDeviceObject
    )
/*++
Routine Description.

    Our Toaster bus has been found.  Attach our FDO to it.
    Allocate any required resources.  Set things up.
    And be prepared for the ``start device''

Arguments:

    DriverObject - pointer to driver object.

    PhysicalDeviceObject  - Device object representing the bus to which we
                            will attach a new FDO.

--*/
{
    NTSTATUS            status;
    PDEVICE_OBJECT      deviceObject = NULL;
    PFDO_DEVICE_DATA    deviceData = NULL;
    PWCHAR              deviceName = NULL;
    ULONG               nameLength;
    PKTIMER		timer;
    PKDPC		dpc;

    PAGED_CODE ();

    Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Add Device: 0x%p\n",
                                          PhysicalDeviceObject));

    status = IoCreateDevice (
                    DriverObject,               // our driver object
                    sizeof (FDO_DEVICE_DATA),   // device object extension size
                    NULL,                       // FDOs do not have names
                    FILE_DEVICE_BUS_EXTENDER,   // We are a bus
                    FILE_DEVICE_SECURE_OPEN,    //
                    TRUE,                       // our FDO is exclusive
                    &deviceObject);             // The device object created

    if (!NT_SUCCESS (status))
    {
        goto End;
    }

    deviceData = (PFDO_DEVICE_DATA) deviceObject->DeviceExtension;
    RtlZeroMemory (deviceData, sizeof (FDO_DEVICE_DATA));

    //
    // Set the initial state of the FDO
    //

    INITIALIZE_PNP_STATE(deviceData);

    deviceData->DebugLevel = BusEnumDebugLevel;

    deviceData->IsFDO = TRUE;

    deviceData->Self = deviceObject;

    ExInitializeFastMutex (&deviceData->Mutex);

    InitializeListHead (&deviceData->ListOfPDOs);

    // Set the PDO for use with PlugPlay functions

    deviceData->UnderlyingPDO = PhysicalDeviceObject;

    //
    // Set the initial powerstate of the FDO
    //

    deviceData->DevicePowerState = PowerDeviceUnspecified;
    deviceData->SystemPowerState = PowerSystemWorking;


    //
    // Biased to 1. Transition to zero during remove device
    // means IO is finished. Transition to 1 means the device
    // can be stopped.
    //

    deviceData->OutstandingIO = 1;

    //
    // Initialize the remove event to Not-Signaled.  This event
    // will be set when the OutstandingIO will become 0.
    //

    KeInitializeEvent(&deviceData->RemoveEvent,
                  SynchronizationEvent,
                  FALSE);
    //
    // Initialize the stop event to Signaled:
    // there are no Irps that prevent the device from being
    // stopped. This event will be set when the OutstandingIO
    // will become 0.
    //

    KeInitializeEvent(&deviceData->StopEvent,
                      SynchronizationEvent,
                      TRUE);

    deviceObject->Flags |= DO_POWER_PAGABLE|DO_BUFFERED_IO;

    //
    // Tell the Plug & Play system that this device will need a
    // device interface.
    //

    status = IoRegisterDeviceInterface (
                PhysicalDeviceObject,
                (LPGUID) &GUID_DEVINTERFACE_BUSENUM_TOASTER,
                NULL,
                &deviceData->InterfaceName);

    if (!NT_SUCCESS (status)) {
        Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR,
                      ("AddDevice: IoRegisterDeviceInterface failed (%x)", status));
        goto End;
    }

    //
    // Attach our FDO to the device stack.
    // The return value of IoAttachDeviceToDeviceStack is the top of the
    // attachment chain.  This is where all the IRPs should be routed.
    //

    deviceData->NextLowerDriver = IoAttachDeviceToDeviceStack (
                                    deviceObject,
                                    PhysicalDeviceObject);

    if (NULL == deviceData->NextLowerDriver) {

        status = STATUS_NO_SUCH_DEVICE;
        goto End;
    }


#if DBG
    //
    // We will demonstrate here the step to retrieve the name of the PDO
    //

    status = IoGetDeviceProperty (PhysicalDeviceObject,
                                  DevicePropertyPhysicalDeviceObjectName,
                                  0,
                                  NULL,
                                  &nameLength);

    if (status != STATUS_BUFFER_TOO_SMALL)
    {
        Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR,
                      ("AddDevice:IoGDP failed (0x%x)\n", status));
        goto End;
    }

    deviceName = ExAllocatePoolWithTag (NonPagedPool,
                            nameLength, BUSENUM_POOL_TAG);

    if (NULL == deviceName) {
        Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR,
        ("AddDevice: no memory to alloc for deviceName(0x%x)\n", nameLength));
        status =  STATUS_INSUFFICIENT_RESOURCES;
        goto End;
    }

    status = IoGetDeviceProperty (PhysicalDeviceObject,
                         DevicePropertyPhysicalDeviceObjectName,
                         nameLength,
                         deviceName,
                         &nameLength);

    if (!NT_SUCCESS (status)) {

        Bus_KdPrint (deviceData, BUS_DBG_SS_ERROR,
                      ("AddDevice:IoGDP(2) failed (0x%x)", status));
        goto End;
    }

    Bus_KdPrint (deviceData, BUS_DBG_SS_TRACE,
                  ("AddDevice: %p to %p->%p (%ws) \n",
                   deviceObject,
                   deviceData->NextLowerDriver,
                   PhysicalDeviceObject,
                   deviceName));

#endif

    //
    // We are done with initializing, so let's indicate that and return.
    // This should be the final step in the AddDevice process.
    //
    deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

End:
    if (deviceName){
        ExFreePool(deviceName);
    }

    if (!NT_SUCCESS(status) && deviceObject){
        if (deviceData && deviceData->NextLowerDriver){
            IoDetachDevice (deviceData->NextLowerDriver);
        }
        IoDeleteDevice (deviceObject);
    }

    return status;

}
Exemplo n.º 12
0
//
//	Query information on LanscsiBus
//
NTSTATUS
LSBus_QueryInformation(
		PFDO_DEVICE_DATA				FdoData,
		PBUSENUM_QUERY_INFORMATION		Query,
		PBUSENUM_INFORMATION			Information,
		LONG							OutBufferLength,
		PLONG							OutBufferLenNeeded
	) {

	NTSTATUS			ntStatus;
	PLIST_ENTRY         entry;
	PPDO_DEVICE_DATA	PdoData;
	

	ntStatus = STATUS_SUCCESS;
	*OutBufferLenNeeded = OutBufferLength;
	PdoData = NULL;

	//
	//	Acquire the mutex to prevent PdoData ( Device Extension ) to disappear.
	//
    KeEnterCriticalRegion();
	ExAcquireFastMutex (&FdoData->Mutex);

	switch(Query->InfoClass) {
	case INFORMATION_NUMOFPDOS: {
		ULONG				NumOfPDOs;

		NumOfPDOs = 0;

		for (entry = FdoData->ListOfPDOs.Flink;
			entry != &FdoData->ListOfPDOs;
			entry = entry->Flink) {
			NumOfPDOs ++;
		}

		Information->NumberOfPDOs = NumOfPDOs;
		break;
	}
	case INFORMATION_PDO: {
		KIRQL	oldIrql;

		for (entry = FdoData->ListOfPDOs.Flink;
			entry != &FdoData->ListOfPDOs;
			entry = entry->Flink) {

				PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link);
				if(Query->SlotNo == PdoData->SlotNo) {
					ObReferenceObject(PdoData->Self);
					break;
				}
				PdoData = NULL;

		}

		if(PdoData) {
			KeAcquireSpinLock(&PdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql);
			Bus_KdPrint_Def(BUS_DBG_SS_TRACE, ("Status:%08lx DAcc:%08lx GAcc:%08lx\n",
											PdoData->LanscsiAdapterPDO.AdapterStatus,
											PdoData->LanscsiAdapterPDO.DesiredAccess,
											PdoData->LanscsiAdapterPDO.GrantedAccess
									));
			Information->PdoInfo.AdapterStatus = PdoData->LanscsiAdapterPDO.AdapterStatus;
			Information->PdoInfo.DesiredAccess = PdoData->LanscsiAdapterPDO.DesiredAccess;
			Information->PdoInfo.GrantedAccess = PdoData->LanscsiAdapterPDO.GrantedAccess;
			KeReleaseSpinLock(&PdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql);

			ObDereferenceObject(PdoData->Self);
		} else {
			Bus_KdPrint_Def(BUS_DBG_SS_NOISE, ("No PDO for SlotNo %d!\n", Query->SlotNo));
			ntStatus = STATUS_NO_SUCH_DEVICE;
		}
		break;
	}
	case INFORMATION_PDOENUM: {
		LARGE_INTEGER			TimeOut;
		ULONG					resultLength;
		DEVICE_INSTALL_STATE	deviceInstallState;

		for (entry = FdoData->ListOfPDOs.Flink;
			entry != &FdoData->ListOfPDOs;
			entry = entry->Flink) {

				PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link);
				if(Query->SlotNo == PdoData->SlotNo) {
					ObReferenceObject(PdoData->Self);
					break;
				}
				PdoData = NULL;

		}

		ExReleaseFastMutex (&FdoData->Mutex);
	    KeLeaveCriticalRegion();

		if(!PdoData) {
		    KeEnterCriticalRegion();
			ExAcquireFastMutex (&FdoData->Mutex);
			ntStatus = STATUS_NO_SUCH_DEVICE;
			break;
		}
		//
		//	Wait until LDServ sends AddTargetData.
		//
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("waiting for AddTargetEvent.\n"));
		TimeOut.QuadPart = -10 * 1000 * 1000 * 120;			// 120 seconds
		ntStatus = KeWaitForSingleObject(
						&PdoData->LanscsiAdapterPDO.AddTargetEvent,
						Executive,
						KernelMode,
						FALSE,
						&TimeOut
					);
		if(ntStatus != STATUS_SUCCESS) {
		    KeEnterCriticalRegion();
			ExAcquireFastMutex (&FdoData->Mutex);

			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("failed to wait for AddTargetEvent.\n"));
			ntStatus = STATUS_NO_SUCH_DEVICE;
			ObDereferenceObject(PdoData->Self);
			break;
		}
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Completed to wait for AddTargetEvent.\n"));


		if(PdoData) {

			if(PdoData->LanscsiAdapterPDO.Flags & LSDEVDATA_FLAG_LURDESC) {
				//
				//	A LUR descriptor is set.
				//

				if(PdoData->LanscsiAdapterPDO.AddDevInfo == NULL) {
					KeEnterCriticalRegion();
					ExAcquireFastMutex (&FdoData->Mutex);

					ntStatus = STATUS_NO_SUCH_DEVICE;
					ObDereferenceObject(PdoData->Self);
					break;
				}

				*OutBufferLenNeeded =	FIELD_OFFSET(BUSENUM_INFORMATION, PdoEnumInfo) +
										FIELD_OFFSET(BUSENUM_INFORMATION_PDOENUM, AddDevInfo) +
										PdoData->LanscsiAdapterPDO.AddDevInfoLength;
				if(OutBufferLength < *OutBufferLenNeeded) {
					ntStatus = STATUS_BUFFER_TOO_SMALL;
				} else {
					RtlCopyMemory(
								&Information->PdoEnumInfo.AddDevInfo,
								PdoData->LanscsiAdapterPDO.AddDevInfo,
								PdoData->LanscsiAdapterPDO.AddDevInfoLength
							);
					Information->PdoEnumInfo.Flags = PDOENUM_FLAG_LURDESC;
					Information->PdoEnumInfo.DisconEventToService = PdoData->LanscsiAdapterPDO.DisconEventToService;
					Information->PdoEnumInfo.AlarmEventToService = PdoData->LanscsiAdapterPDO.AlarmEventToService;
					Information->PdoEnumInfo.MaxBlocksPerRequest = PdoData->LanscsiAdapterPDO.MaxBlocksPerRequest;

					//
					//	Check to see if this is the first enumeration.
					//
					ntStatus = DrGetDeviceProperty(
						PdoData->Self,
						DevicePropertyInstallState,
						sizeof(deviceInstallState),
						&deviceInstallState,
						&resultLength,
						(Globals.MajorVersion == 5) && (Globals.MinorVersion == 0)
						);
					if(NT_SUCCESS(ntStatus)) {
						if(deviceInstallState != InstallStateInstalled) {
							Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("First time installation. Do not enumerate a device.\n"));
							Information->PdoEnumInfo.Flags |= PDOENUM_FLAG_DRV_NOT_INSTALLED;
						}
					}
				}
			} else {
				//
				//	ADD_TARGET_DATA is set.
				//
				PLANSCSI_ADD_TARGET_DATA	AddTargetData;
				LONG						AddTargetLenNeeded;
				LONG						InfoBuffLenNeeded;

				AddTargetData = PdoData->LanscsiAdapterPDO.AddDevInfo;
				if(AddTargetData == NULL) {
					KeEnterCriticalRegion();
					ExAcquireFastMutex (&FdoData->Mutex);

					ntStatus = STATUS_NO_SUCH_DEVICE;
					ObDereferenceObject(PdoData->Self);
					break;
				}

				//
				//	calculate the length needed.
				//
				AddTargetLenNeeded = sizeof(LANSCSI_ADD_TARGET_DATA) + (AddTargetData->ulNumberOfUnitDiskList-1)*sizeof(LSBUS_UNITDISK);
				InfoBuffLenNeeded = sizeof(BUSENUM_INFORMATION) - sizeof(BYTE) + (AddTargetLenNeeded);
				*OutBufferLenNeeded = InfoBuffLenNeeded;
				if(OutBufferLength < InfoBuffLenNeeded) {
					ntStatus = STATUS_BUFFER_TOO_SMALL;
				} else {
					RtlCopyMemory(&Information->PdoEnumInfo.AddDevInfo, AddTargetData, AddTargetLenNeeded);
					Information->PdoEnumInfo.Flags = 0;
					Information->PdoEnumInfo.DisconEventToService = PdoData->LanscsiAdapterPDO.DisconEventToService;
					Information->PdoEnumInfo.AlarmEventToService = PdoData->LanscsiAdapterPDO.AlarmEventToService;
					Information->PdoEnumInfo.MaxBlocksPerRequest = PdoData->LanscsiAdapterPDO.MaxBlocksPerRequest;

					//
					//	Check to see if this is the first enumeration.
					//
					ntStatus = DrGetDeviceProperty(
						PdoData->Self,
						DevicePropertyInstallState,
						sizeof(deviceInstallState),
						&deviceInstallState,
						&resultLength,
						(Globals.MajorVersion == 5) && (Globals.MinorVersion == 0)
						);
					if(NT_SUCCESS(ntStatus)) {
						if(deviceInstallState != InstallStateInstalled) {
							Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("First time installation. Do not enumerate a device.\n"));
							Information->PdoEnumInfo.Flags |= PDOENUM_FLAG_DRV_NOT_INSTALLED;
						}
					} else {
						ntStatus = STATUS_SUCCESS;
						Information->PdoEnumInfo.Flags &= ~PDOENUM_FLAG_DRV_NOT_INSTALLED;
					}
				}
			}
		} else {

			ntStatus = STATUS_NO_SUCH_DEVICE;
		}

		KeEnterCriticalRegion();
		ExAcquireFastMutex (&FdoData->Mutex);

		ObDereferenceObject(PdoData->Self);
		break;
	}
	case INFORMATION_PDOEVENT: {

		for (entry = FdoData->ListOfPDOs.Flink;
			entry != &FdoData->ListOfPDOs;
			entry = entry->Flink) {

				PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link);
				if(Query->SlotNo == PdoData->SlotNo) {
					ObReferenceObject(PdoData->Self);
					break;
				}
				PdoData = NULL;

		}

		if(PdoData == NULL) {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not find the PDO:%u.\n", Query->SlotNo));
			ntStatus = STATUS_NO_SUCH_DEVICE;
			break;
		}

		if( Query->Flags & LSBUS_QUERYFLAG_USERHANDLE) {
			Information->PdoEvents.SlotNo = PdoData->SlotNo;
			Information->PdoEvents.Flags = LSBUS_QUERYFLAG_USERHANDLE;

			//
			//	Get user-mode event handles.
			//
			ntStatus = ObOpenObjectByPointer(
					PdoData->LanscsiAdapterPDO.DisconEventToService,
					0,
					NULL,
					EVENT_ALL_ACCESS,
					*ExEventObjectType,
					UserMode,
					&Information->PdoEvents.DisconEvent
				);
			if(!NT_SUCCESS(ntStatus)) {
				ObDereferenceObject(PdoData->Self);
				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open Disconnect event object!!\n"));
				break;
			}
			ntStatus = ObOpenObjectByPointer(
					PdoData->LanscsiAdapterPDO.AlarmEventToService,
					0,
					NULL,
					EVENT_ALL_ACCESS,
					*ExEventObjectType,
					UserMode,
					&Information->PdoEvents.AlarmEvent
				);
			if(!NT_SUCCESS(ntStatus)) {
				ObDereferenceObject(PdoData->Self);
				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open Disconnect event object!!\n"));
				break;
			}

		} else {
			Information->PdoEvents.SlotNo = PdoData->SlotNo;
			Information->PdoEvents.Flags = 0;
			Information->PdoEvents.DisconEvent = PdoData->LanscsiAdapterPDO.DisconEventToService;
			Information->PdoEvents.AlarmEvent = PdoData->LanscsiAdapterPDO.AlarmEventToService;
		}

		ObDereferenceObject(PdoData->Self);
		break;
   }
	case INFORMATION_ISREGISTERED: {

		ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

		ntStatus = LSBus_IsRegistered(FdoData, Query->SlotNo);
		break;
	}

	case INFORMATION_PDOSLOTLIST: {
		LONG	outputLength;
		LONG	entryCnt;

		if(OutBufferLength < FIELD_OFFSET(BUSENUM_INFORMATION, PdoSlotList)) {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Buffer size is less than required\n"));
			ntStatus = STATUS_INVALID_PARAMETER;
			break;
		}

		Information->Size = 0;
		Information->InfoClass = INFORMATION_PDOSLOTLIST;

		//
		//	Add the size of information header.
		//
		outputLength = FIELD_OFFSET(BUSENUM_INFORMATION, PdoSlotList);
		outputLength += sizeof(UINT32);					// SlotNoCnt
		entryCnt = 0;

		for (entry = FdoData->ListOfPDOs.Flink;
			entry != &FdoData->ListOfPDOs;
			entry = entry->Flink) {

			PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link);

			//
			//	Add the size of each slot entry.
			//
			outputLength += sizeof(UINT32);
			if(outputLength > OutBufferLength) {
				continue;
			}

			Information->PdoSlotList.SlotNo[entryCnt] = PdoData->SlotNo;
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Entry #%u: %u\n", entryCnt, PdoData->SlotNo));

			entryCnt ++;
		}

		if(outputLength > OutBufferLength) {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Could not find a Device(%d).\n", Query->SlotNo));
			*OutBufferLenNeeded = outputLength;
			ntStatus = STATUS_BUFFER_TOO_SMALL;
		} else {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Entry count:%d.\n", entryCnt));
			Information->Size = outputLength;
			Information->PdoSlotList.SlotNoCnt = entryCnt;
			*OutBufferLenNeeded = outputLength;
		}

		break;
	}
	case INFORMATION_PDOFILEHANDLE: {
		PWCHAR	devName;
		USHORT	devNameLen;
		OBJECT_ATTRIBUTES  objectAttr;
		UNICODE_STRING		objName;
		HANDLE				devFileHandle;
		IO_STATUS_BLOCK		ioStatus;

		devName = NULL;


		for (entry = FdoData->ListOfPDOs.Flink;
			entry != &FdoData->ListOfPDOs;
			entry = entry->Flink) {

				PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link);
				if(Query->SlotNo == PdoData->SlotNo) {
					ObReferenceObject(PdoData->Self);
					break;
				}
				PdoData = NULL;

		}

		if(PdoData == NULL) {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not find the PDO:%u.\n", Query->SlotNo));
			ntStatus = STATUS_NO_SUCH_DEVICE;
			break;
		}


		//
		//	Get the name of the physical device object.
		//

		ntStatus = GetPhyDeviceName(PdoData->Self, &devName, &devNameLen);
		if(!NT_SUCCESS(ntStatus)) {
			ObDereferenceObject(PdoData->Self);
			break;
		}


		//
		//	Build unicode name of the device.
		//	Get rid of NULL termination from the length
		//

		objName.Buffer = devName;
		if(devNameLen > 0 && devName[devNameLen/sizeof(WCHAR) - 1] == L'\0') {
			objName.MaximumLength = devNameLen;
			objName.Length = devNameLen - sizeof(WCHAR);
		} else {
			objName.MaximumLength = objName.Length = devNameLen;
		}

		//
		//	Open a device file.
		//

		if(Query->Flags & LSBUS_QUERYFLAG_USERHANDLE) {
			Information->PdoFile.Flags = LSBUS_QUERYFLAG_USERHANDLE;
			InitializeObjectAttributes(&objectAttr, &objName, OBJ_CASE_INSENSITIVE , NULL, NULL);
		} else {
			Information->PdoFile.Flags = 0;
			InitializeObjectAttributes(&objectAttr, &objName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
		}


		ntStatus = ZwCreateFile(
						&devFileHandle,
						SYNCHRONIZE|FILE_READ_DATA,
						&objectAttr,
						&ioStatus,
						NULL,
						0,
						FILE_SHARE_READ|FILE_SHARE_WRITE,
						FILE_OPEN,
						FILE_SYNCHRONOUS_IO_NONALERT,
						NULL,
						0);
		if(!NT_SUCCESS(ntStatus)) {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open the PDO:%u. STATUS=%08lx\n", Query->SlotNo, ntStatus));
			ExFreePool(devName);
			ObDereferenceObject(PdoData->Self);
			break;
		}


		//
		//	Set the return values
		//

		Information->PdoFile.SlotNo = PdoData->SlotNo;
		Information->PdoFile.PdoFileHandle = devFileHandle;

		if(devName)
			ExFreePool(devName);

		ObDereferenceObject(PdoData->Self);
		break;
   }

	default:
		ntStatus = STATUS_INVALID_PARAMETER;
	}

	ExReleaseFastMutex (&FdoData->Mutex);
    KeLeaveCriticalRegion();

	return ntStatus;
}
Exemplo n.º 13
0
//
//	I/O Control to the LanscsiMiniport.
//	Buffers must be allocated from NonPagedPool
//
//	NOTE:	Do not use  LANSCSIMINIPORT_IOCTL_QUERYINFO.
//			It uses separate input/output buffer.
//			It will be obsolete.
//
NTSTATUS
LSBus_IoctlToLSMPDevice(
		PPDO_DEVICE_DATA	PdoData,
		ULONG				IoctlCode,
		PVOID				InputBuffer,
		LONG				InputBufferLength,
		PVOID				OutputBuffer,
		LONG				OutputBufferLength
	) {

	PDEVICE_OBJECT		AttachedDevice;
    PIRP				irp;
    KEVENT				event;
	PSRB_IO_CONTROL		psrbIoctl;
	LONG				srbIoctlLength;
	PVOID				srbIoctlBuffer;
	LONG				srbIoctlBufferLength;
    NTSTATUS			status;
    PIO_STACK_LOCATION	irpStack;
    SCSI_REQUEST_BLOCK	srb;
    LARGE_INTEGER		startingOffset;
    IO_STATUS_BLOCK		ioStatusBlock;

	AttachedDevice = NULL;
	psrbIoctl	= NULL;
	irp = NULL;

	//
	//	get a ScsiPort device or attached one.
	//
	AttachedDevice = IoGetAttachedDeviceReference(PdoData->Self);

	if(AttachedDevice == NULL) {
		Bus_KdPrint_Def( BUS_DBG_SS_ERROR, ("STATUS_INVALID_DEVICE\n"));
		return STATUS_NO_SUCH_DEVICE;
	}

	//
	//	build an SRB for the miniport
	//
	srbIoctlBufferLength = (InputBufferLength>OutputBufferLength)?InputBufferLength:OutputBufferLength;
	srbIoctlLength = sizeof(SRB_IO_CONTROL) +  srbIoctlBufferLength;

	psrbIoctl = (PSRB_IO_CONTROL)ExAllocatePoolWithTag(NonPagedPool , srbIoctlLength, BUSENUM_POOL_TAG);
	if(psrbIoctl == NULL) {
		Bus_KdPrint_Def( BUS_DBG_SS_ERROR, ("STATUS_INSUFFICIENT_RESOURCES\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto cleanup;
	}

	RtlZeroMemory(psrbIoctl, srbIoctlLength);
	psrbIoctl->HeaderLength = sizeof(SRB_IO_CONTROL);
	RtlCopyMemory(psrbIoctl->Signature, LANSCSIMINIPORT_IOCTL_SIGNATURE, 8);
	psrbIoctl->Timeout = 60 * 60;
	psrbIoctl->ControlCode = IoctlCode;
	psrbIoctl->Length = srbIoctlBufferLength;

	srbIoctlBuffer = (PUCHAR)psrbIoctl + sizeof(SRB_IO_CONTROL);
	RtlCopyMemory(srbIoctlBuffer, InputBuffer, InputBufferLength);

    //
    // Initialize the notification event.
    //

    KeInitializeEvent(&event,
                        NotificationEvent,
                        FALSE);
	startingOffset.QuadPart = 1;

    //
    // Build IRP for this request.
    // Note we do this synchronously for two reasons.  If it was done
    // asynchonously then the completion code would have to make a special
    // check to deallocate the buffer.  Second if a completion routine were
    // used then an additional IRP stack location would be needed.
    //

    irp = IoBuildSynchronousFsdRequest(
                IRP_MJ_SCSI,
                AttachedDevice,
                psrbIoctl,
                srbIoctlLength,
                &startingOffset,
                &event,
                &ioStatusBlock);

    irpStack = IoGetNextIrpStackLocation(irp);

    if (irp == NULL) {
        Bus_KdPrint_Def( BUS_DBG_SS_ERROR, ("STATUS_INSUFFICIENT_RESOURCES\n"));

		status = STATUS_INSUFFICIENT_RESOURCES;
		goto cleanup;
    }

    //
    // Set major and minor codes.
    //

    irpStack->MajorFunction = IRP_MJ_SCSI;
    irpStack->MinorFunction = 1;

    //
    // Fill in SRB fields.
    //

    irpStack->Parameters.Others.Argument1 = &srb;

    //
    // Zero out the srb.
    //

    RtlZeroMemory(&srb, sizeof(SCSI_REQUEST_BLOCK));

    srb.PathId = 0;
    srb.TargetId = 0;
    srb.Lun = 0;

    srb.Function = SRB_FUNCTION_IO_CONTROL;
    srb.Length = sizeof(SCSI_REQUEST_BLOCK);

    srb.SrbFlags = /*SRB_FLAGS_DATA_IN |*/ SRB_FLAGS_NO_QUEUE_FREEZE /*| SRB_FLAGS_BYPASS_FROZEN_QUEUE */;

    srb.OriginalRequest = irp;

    //
    // Set timeout to requested value.
    //

    srb.TimeOutValue = psrbIoctl->Timeout;

    //
    // Set the data buffer.
    //

    srb.DataBuffer = psrbIoctl;
    srb.DataTransferLength = srbIoctlLength;

    //
    // Flush the data buffer for output. This will insure that the data is
    // written back to memory.  Since the data-in flag is the the port driver
    // will flush the data again for input which will ensure the data is not
    // in the cache.
    //
/*
    KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);
*/
    status = IoCallDriver( AttachedDevice, irp );

    //
    // Wait for request to complete.
    //
    if (status == STATUS_PENDING) {

        (VOID)KeWaitForSingleObject( 
									&event,
                                     Executive,
                                     KernelMode,
                                     FALSE,
                                     (PLARGE_INTEGER)NULL 
									 );

        status = ioStatusBlock.Status;
    }

	//
	//	get the result
	//
//	if(status == STATUS_SUCCESS) {
		if(OutputBuffer && OutputBufferLength)
			RtlCopyMemory(OutputBuffer, srbIoctlBuffer, OutputBufferLength);
			Bus_KdPrint_Def( BUS_DBG_SS_NOISE, ("%d succeeded!\n", IoctlCode));
//	}
	if(psrbIoctl->ControlCode == STATUS_BUFFER_TOO_SMALL) {
		status = STATUS_BUFFER_TOO_SMALL;
	}

cleanup:
	if(psrbIoctl)
		ExFreePool(psrbIoctl);
	if(AttachedDevice)
		ObDereferenceObject(AttachedDevice);

    return status;
}
Exemplo n.º 14
0
NTSTATUS
NCommVerifyNdasDevWithDIB(
		IN OUT PNDASBUS_ADD_TARGET_DATA	AddTargetData,
		IN PTA_LSTRANS_ADDRESS		SecondaryAddress
	) {
	NTSTATUS			status;
	LSSLOGIN_INFO		loginInfo;
	PNDASBUS_UNITDISK		unit;
	TA_LSTRANS_ADDRESS	targetAddr;
	TA_LSTRANS_ADDRESS	bindingAddr;
	TA_LSTRANS_ADDRESS	bindingAddr2;
	TA_LSTRANS_ADDRESS	boundAddr;
	ULONG				idx_unit;
	ULONG				fault_cnt;
	BOOLEAN				oriDibValid;
	UINT32				crcunit = 0;
	BOOLEAN				exitImm;


	//
	//	check AddTargetData sanity
	//
	status = VerifyAddTargetData(AddTargetData);
	if(!NT_SUCCESS(status)) {
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("VerifyAddTargetData() failed. STATUS=%08lx\n", status));
		return status;
	}


	//
	//	Start verifying
	//

	fault_cnt = 0;
	oriDibValid = FALSE;
	exitImm = FALSE;
	for(idx_unit = 0; idx_unit < AddTargetData->ulNumberOfUnitDiskList; idx_unit++) {
		Bus_KdPrint_Def(BUS_DBG_SS_INFO, ("== UNIT #%u ==\n", idx_unit));

		unit = AddTargetData->UnitDiskList + idx_unit;
		LSTRANS_COPY_LPXADDRESS(&targetAddr, &unit->Address);
		LSTRANS_COPY_LPXADDRESS(&bindingAddr, &unit->NICAddr);
		if(SecondaryAddress)
			LSTRANS_COPY_LPXADDRESS(&bindingAddr2, &SecondaryAddress->Address[0].Address);

		BUILD_LOGININFO(&loginInfo, unit);

		if(unit->ucHWVersion <= LANSCSIIDE_VERSION_2_0)
			loginInfo.UserID = CONVERT_TO_ROUSERID(loginInfo.UserID);


		//
		//	Query binding address
		//

		if(SecondaryAddress)
			status = LsuQueryBindingAddress(&boundAddr, &targetAddr, &bindingAddr, &bindingAddr2, TRUE);
		else
			status = LsuQueryBindingAddress(&boundAddr, &targetAddr, &bindingAddr, NULL, TRUE);

		if(!NT_SUCCESS(status)) {
			unit->LurnOptions |= LURNOPTION_MISSING;
			fault_cnt ++;
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("LsuQueryBindingAddress() failed. STATUS=%08lx\n", status));
			continue;
		}


		//
		//	Set the actual binding address.
		//

		LSTRANS_COPY_TO_LPXADDRESS(&unit->NICAddr, &boundAddr);
		RtlCopyMemory(&bindingAddr, &boundAddr, sizeof(TA_LSTRANS_ADDRESS));


		//
		//	Read and verify DIB
		//

		switch(AddTargetData->ucTargetType) {
		case NDASSCSI_TYPE_DISK_NORMAL: {
			PBLOCK_ACCESS_CONTROL_LIST	bacl = NULL;
			union {
				NDAS_DIB	V1;
				NDAS_DIB_V2	V2;
			}	DIB;


			status = NCommGetDIBV2(	&DIB.V2,
									&bacl,
									&loginInfo,
									unit->ulPhysicalBlocks + NDAS_BLOCK_LOCATION_DIB_V2,
									unit->ulPhysicalBlocks + NDAS_BLOCK_LOCATION_ENCRYPT,
									unit->ulPhysicalBlocks + NDAS_BLOCK_LOCATION_BACL,
									&targetAddr,
									&bindingAddr,
									unit->UDMARestrict);
			if(NT_SUCCESS(status)) {
				//
				//	Disk information block Version 2
				//
				if(DIB.V2.iMediaType != NMT_SINGLE) {
					Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("NORMAL: DIB's disktype mismatch. MediaType:%x\n", DIB.V2.iMediaType));
					status = STATUS_OBJECT_TYPE_MISMATCH;
					break;
				}

				//
				//	Verify block access control list
				//
				status = NCommVerifyNdasBlockACLWithTargetData(AddTargetData, DIB.V2.BACLSize, bacl);
				if(!NT_SUCCESS(status))
					break;

				status = STATUS_SUCCESS;
			} else if(status == STATUS_REVISION_MISMATCH) {
				//
				//	Disk information block Version 1
				//
				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("NORMAL: DIBV2 doesn't exist. try DIBV1. NTSTATUS:%08lx\n", status));
				status = NCommGetDIBV1(	&DIB.V1,
									&loginInfo,
									unit->ulPhysicalBlocks + NDAS_BLOCK_LOCATION_DIB_V1,
									&targetAddr,
									&bindingAddr,
									unit->UDMARestrict);

				if(status == STATUS_REVISION_MISMATCH) {
					Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("NORMAL: DIBV1 doesn't exist. Take it Single. NTSTATUS:%08lx\n", status));
					status = STATUS_SUCCESS;
					break;
				} else if(!NT_SUCCESS(status)) {
					Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("NORMAL: NCommGetDIBV1() failed. NTSTATUS:%08lx\n", status));
					break;
				}
				if(DIB.V1.DiskType != NDAS_DIB_DISK_TYPE_SINGLE) {
					Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("NORMAL: DIB's disktype mismatch. DiskType:%x\n", DIB.V1.DiskType));
					status = STATUS_OBJECT_TYPE_MISMATCH;
					break;
				}
				status = STATUS_SUCCESS;

			} else {
				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("NORMAL: NCommGetDIBV2() failed. NTSTATUS:%08lx\n", status));
			}
			break;
		}

		case NDASSCSI_TYPE_DISK_RAID1R2:	
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("RAID1R2: Not supported.\n"));
			status = STATUS_NOT_SUPPORTED;
			break;
			
		case NDASSCSI_TYPE_DISK_RAID1R3:	{			
			PBLOCK_ACCESS_CONTROL_LIST	bacl = NULL;
			NDAS_DIB_V2	DIBV2;

			//
			//	Disk information block Version 2
			//

			//
			// ulPhysicalBlocks can be 0 if mounted in degraded mode.
			// Temporary fix: 	Just don't mount.
			//			to do later: read RMD and compare RAID set ID and config set ID.
			if (unit->ulPhysicalBlocks ==0) {
				exitImm = TRUE;
				status = STATUS_OBJECT_TYPE_MISMATCH;
				break;
			}
			status = NCommGetDIBV2(	&DIBV2,
									&bacl,
									&loginInfo,
									unit->ulPhysicalBlocks + NDAS_BLOCK_LOCATION_DIB_V2,
									unit->ulPhysicalBlocks + NDAS_BLOCK_LOCATION_ENCRYPT,
									unit->ulPhysicalBlocks + NDAS_BLOCK_LOCATION_BACL,
									&targetAddr,
									&bindingAddr,
									unit->UDMARestrict);
			if(!NT_SUCCESS(status)) {
				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("RAID1R3: NCommGetDIBV2() failed. NTSTATUS:%08lx\n", status));
				exitImm = TRUE;
			}

			if(DIBV2.iMediaType != NdasDevType2DIBType(AddTargetData->ucTargetType)) {
				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("RAID1R3: DIBv2's disktype mismatch. MediaType:%x\n", DIBV2.iMediaType));
				status = STATUS_OBJECT_TYPE_MISMATCH;
				exitImm = TRUE;
				break;
			}

			if(DIBV2.nDiskCount != AddTargetData->ulNumberOfUnitDiskList) {
				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("RAID1R3: DIBv2's Diskcount mismatch."
					" numberofunitdisklist=%u ndiskcount=%u\n", AddTargetData->ulNumberOfUnitDiskList, DIBV2.nDiskCount));
				status = STATUS_OBJECT_TYPE_MISMATCH;
				exitImm = TRUE;
				break;
			}

			if(DIBV2.iSequence != idx_unit) {
				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("RAID1R3: DIBv2's sequence number mismatch."
											" idx_unit=%u Seq=%u\n", idx_unit, DIBV2.iSequence));
				status = STATUS_OBJECT_TYPE_MISMATCH;
				exitImm = TRUE;
				break;
			}

			//
			//	Compare Unit crc with the other units.
			//

			if(oriDibValid == TRUE){
				if(DIBV2.crc32_unitdisks != crcunit) {
					Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("RAID1R3: DIBv2's unit crc mismatch."
						" original=%08lx crc unit=%08lx\n", crcunit, DIBV2.crc32_unitdisks));

					status = STATUS_OBJECT_TYPE_MISMATCH;
					exitImm = TRUE;
					break;
				}
			} else {
				//
				//	Set original DIB information to compare with the rest of units.
				//

				crcunit = DIBV2.crc32_unitdisks;
				oriDibValid = TRUE;

				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("RAID1R3: Set original CRC."
								" original=%08lx\n", crcunit));
			}

			//
			//	Verify block access control list
			//
			status = NCommVerifyNdasBlockACLWithTargetData(AddTargetData, DIBV2.BACLSize, bacl);
			if(!NT_SUCCESS(status)) {
				exitImm = TRUE;
				break;
			}

			status = STATUS_SUCCESS;
			break;
		}
		case NDASSCSI_TYPE_DISK_RAID4R2:
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("MIRROR: Not supported.\n"));
			status = STATUS_NOT_SUPPORTED;
			break;

		case NDASSCSI_TYPE_DISK_RAID0:			
		case NDASSCSI_TYPE_DISK_RAID4R3: 
		case NDASSCSI_TYPE_DISK_RAID5:{
			PBLOCK_ACCESS_CONTROL_LIST	bacl = NULL;
			NDAS_DIB_V2	DIBV2;


			status = NCommGetDIBV2(	&DIBV2,
									&bacl,
									&loginInfo,
									unit->ulPhysicalBlocks + NDAS_BLOCK_LOCATION_DIB_V2,
									unit->ulPhysicalBlocks + NDAS_BLOCK_LOCATION_ENCRYPT,
									unit->ulPhysicalBlocks + NDAS_BLOCK_LOCATION_BACL,
									&targetAddr,
									&bindingAddr,
									unit->UDMARestrict);
			if(status == STATUS_REVISION_MISMATCH) {
				exitImm = TRUE;
				break;
			}
			if(!NT_SUCCESS(status)) {
				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("RAID0/4: could not read DIBV2. NTSTATUS:%x\n", status));
				unit->LurnOptions |= LURNOPTION_MISSING;
				fault_cnt ++;
				break;
			}


			//
			//	Disk information block Version 2
			//

			if(DIBV2.iMediaType != NdasDevType2DIBType(AddTargetData->ucTargetType) ||
				DIBV2.iSequence != idx_unit
				) {
				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("RAID0/4: DIBv2's disktype mismatch. MediaType:%x Sequence:%d\n",
														DIBV2.iMediaType,
														DIBV2.iSequence));
				status = STATUS_OBJECT_TYPE_MISMATCH;
				exitImm = TRUE;
				break;
			}

			//
			//	Compare Unit crc with the other units.
			//

			if(oriDibValid == TRUE){
				if(DIBV2.crc32_unitdisks != crcunit) {
					Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("RAID0/4: DIBv2's unit crc mismatch."
						" original=%08lx crc unit=%08lx\n", crcunit, DIBV2.crc32_unitdisks));

					status = STATUS_OBJECT_TYPE_MISMATCH;
					exitImm = TRUE;
					break;
				}
			} else {
				//
				//	Set original DIB information to compare with the rest of units.
				//

				crcunit = DIBV2.crc32_unitdisks;
				oriDibValid = TRUE;

				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("RAID0/4: Set original CRC."
								" original=%08lx\n", crcunit));
			}

			//
			//	Verify block access control list
			//
			status = NCommVerifyNdasBlockACLWithTargetData(AddTargetData, DIBV2.BACLSize, bacl);
			if(!NT_SUCCESS(status)) {
				exitImm = TRUE;
				break;
			}

			status = STATUS_SUCCESS;
			break;
		}

		case NDASSCSI_TYPE_DISK_MIRROR:
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("MIRROR: Not supported.\n"));
			status = STATUS_NOT_SUPPORTED;
			break;
			
		case NDASSCSI_TYPE_DISK_AGGREGATION: {
			PBLOCK_ACCESS_CONTROL_LIST	bacl = NULL;
			union {
				NDAS_DIB	V1;
				NDAS_DIB_V2	V2;
			}	DIB;

			//
			//	Disk information block Version 2
			//

			status = NCommGetDIBV2(	&DIB.V2,
									&bacl,
									&loginInfo,
									unit->ulPhysicalBlocks + NDAS_BLOCK_LOCATION_DIB_V2,
									unit->ulPhysicalBlocks + NDAS_BLOCK_LOCATION_ENCRYPT,
									unit->ulPhysicalBlocks + NDAS_BLOCK_LOCATION_BACL,
									&targetAddr,
									&bindingAddr,
									unit->UDMARestrict);
			if(NT_SUCCESS(status)) {
				if(DIB.V2.iMediaType != NdasDevType2DIBType(AddTargetData->ucTargetType)) {
					Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("MIRAGR: DIBv2's disktype mismatch. MediaType:%x\n", DIB.V2.iMediaType));
					status = STATUS_OBJECT_TYPE_MISMATCH;
					exitImm = TRUE;
					break;
				}

				if(DIB.V2.nDiskCount != AddTargetData->ulNumberOfUnitDiskList) {
					Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("MIRAGR: DIBv2's Diskcount mismatch."
						" numberofunitdisklist=%u ndiskcount=%u\n", AddTargetData->ulNumberOfUnitDiskList, DIB.V2.nDiskCount));
					status = STATUS_OBJECT_TYPE_MISMATCH;
					exitImm = TRUE;
					break;
				}

				if(DIB.V2.iSequence != idx_unit) {
					Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("MIRAGR: DIBv2's sequence number mismatch."
											" idx_unit=%u Seq=%u\n", idx_unit, DIB.V2.iSequence));
					status = STATUS_OBJECT_TYPE_MISMATCH;
					exitImm = TRUE;
					break;
				}

				//
				//	Verify block access control list
				//
				status = NCommVerifyNdasBlockACLWithTargetData(AddTargetData, DIB.V2.BACLSize, bacl);
				if(!NT_SUCCESS(status)) {
					exitImm = TRUE;
					break;
				}

				status = STATUS_SUCCESS;

			} else if(status == STATUS_REVISION_MISMATCH) {

				//
				//	Disk information block Version 1
				//

				status = NCommGetDIBV1(	&DIB.V1,
									&loginInfo,
									unit->ulPhysicalBlocks + NDAS_BLOCK_LOCATION_DIB_V1,
									&targetAddr,
									&bindingAddr,
									unit->UDMARestrict);
				if(!NT_SUCCESS(status)) {
					Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("MIRAGR: NCommGetDIBV1() failed. NTSTATUS:%08lx\n", status));

					//
					//	Set fault_cnt to exit immediately from this loop.
					//

					fault_cnt = AddTargetData->ulNumberOfUnitDiskList;
					break;
				}
				if(LagacyMirrAggrType2TargetType(DIB.V1.DiskType) != AddTargetData->ucTargetType) {
					Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("MIRAGR: DIBv1's disktype mismatch. Disktype:%x\n", DIB.V1.DiskType));
					status = STATUS_OBJECT_TYPE_MISMATCH;
					exitImm = TRUE;
				}

				if(LagacyMirrAggrType2SeqNo(DIB.V1.DiskType) != idx_unit) {
					Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("MIRAGR: DIBv1's sequnece mismatch."
								" DiskType:%x expected seq:%u\n", DIB.V1.DiskType, idx_unit));
					status = STATUS_OBJECT_TYPE_MISMATCH;
					exitImm = TRUE;
					break;
				}
			} else {
				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("MIRAGR: NCommGetDIBV2() failed. NTSTATUS:%08lx\n", status));
				exitImm = TRUE;
			}

			status = STATUS_SUCCESS;
		break;
		}

		case NDASSCSI_TYPE_DVD:
		case NDASSCSI_TYPE_VDVD:
		case NDASSCSI_TYPE_MO:
			status = STATUS_SUCCESS;
			break;
		case NDASSCSI_TYPE_AOD:
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("AOD: Not supported.\n"));
			status = STATUS_NOT_SUPPORTED;
			break;
		default:
			status = STATUS_OBJECT_TYPE_MISMATCH;
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Invalid target type.\n"));
			break;
		}

		if(exitImm) {
			Bus_KdPrint_Def(BUS_DBG_SS_INFO, ("Exit from this verification loop immediately.\n"));
			break;
		}
	}


	//	Online-recoverable RAIDs.
	//	Even if only one is successfully detected,
	//	go ahead to the plug-in process.
	//

	Bus_KdPrint_Def(BUS_DBG_SS_INFO, ("Fault count = %u\n", fault_cnt));
	if(AddTargetData->ucTargetType == NDASSCSI_TYPE_DISK_RAID1R3 ||
		AddTargetData->ucTargetType == NDASSCSI_TYPE_DISK_RAID4R3 ||
		AddTargetData->ucTargetType == NDASSCSI_TYPE_DISK_RAID5
		) {
#if 0
		//
		// Boot-up mount policy: Do not mount if any of the member is missing
		//
		if (fault_cnt !=0) {
			status = STATUS_UNSUCCESSFUL;
			Bus_KdPrint_Def(BUS_DBG_SS_INFO, ("Member is missing. Denying auto mount.\n"));
		}
#else
		//
		// Boot-up mount policy: Do not mount if any of the member is missing
		//
		if (fault_cnt !=0) {
			status = STATUS_UNSUCCESSFUL;
			Bus_KdPrint_Def(BUS_DBG_SS_INFO, ("Member is missing. Denying auto mount.\n"));
		}
#endif
	} else {

		//
		//	Check the fault counter because RAID0 may set status to SUCCESS
		//		even if a member is in fault.
		//

		if(NT_SUCCESS(status)) {
			if(fault_cnt) {
				status = STATUS_UNSUCCESSFUL;
				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Fault count=%u.\n", fault_cnt));
			}
		}
	}

	return status;
}
Exemplo n.º 15
0
NTSTATUS
GetPhyDeviceName(
	PDEVICE_OBJECT	PhysicalDeviceObject,
	PWCHAR			*DeviceName,
	PUSHORT			DeviceNameLen

){
	PWCHAR              deviceName = NULL;
	ULONG               nameLength;
	NTSTATUS			status;


	status = IoGetDeviceProperty (	PhysicalDeviceObject,
									DevicePropertyPhysicalDeviceObjectName,
									0,
									NULL,
									&nameLength);

	if (status != STATUS_BUFFER_TOO_SMALL)
	{
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR,("IoGetDeviceProperty failed (0x%x)\n", status));
		goto Error;
	}

	deviceName = ExAllocatePoolWithTag (NonPagedPool, nameLength, BUSENUM_POOL_TAG);

	if (NULL == deviceName) {
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR,
			("no memory to alloc for deviceName(0x%x)\n", nameLength));
		status =  STATUS_INSUFFICIENT_RESOURCES;
		goto Error;
	}

	status = IoGetDeviceProperty (	PhysicalDeviceObject,
									DevicePropertyPhysicalDeviceObjectName,
									nameLength,
									deviceName,
									&nameLength);

	if (!NT_SUCCESS (status)) {

		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("IoGetDeviceProperty(2) failed (0x%x)", status));
		goto Error;
	}

	Bus_KdPrint_Def(BUS_DBG_SS_INFO, ("%x (%ws) \n",
					PhysicalDeviceObject,
					deviceName));

	//
	//	Set return values
	//
	*DeviceName = deviceName;
	*DeviceNameLen = (USHORT)nameLength;


Error:
	if(!NT_SUCCESS(status)) {
		if(deviceName)
			ExFreePool(deviceName);
	}

	return status;
}
Exemplo n.º 16
0
NTSTATUS
NCommGetDIBV2(
	OUT	PNDAS_DIB_V2				DiskInformationBlock,
	OUT PBLOCK_ACCESS_CONTROL_LIST	*BlockACL,
	IN	PLSSLOGIN_INFO				LoginInfo,
	IN	UINT64						DIBAddress,
	IN	UINT64						EncryptInfoBlockAddr,
	IN	UINT64						BaclBlockAddr,
	IN	PTA_LSTRANS_ADDRESS			NodeAddress,
	IN	PTA_LSTRANS_ADDRESS			BindingAddress,
	IN	UCHAR						UdmaRestrict
) {
	PLANSCSI_SESSION	LSS;
	NTSTATUS			status;
	LSTRANS_TYPE		LstransType;
	ULONG				pduFlags;
	BOOLEAN				dma;
	ULONG				bytesOfBlock;

	UNREFERENCED_PARAMETER(EncryptInfoBlockAddr);

	LSS = (PLANSCSI_SESSION)ExAllocatePoolWithTag(NonPagedPool, sizeof(LANSCSI_SESSION), NCOMM_POOLTAG_LSS);
	if(!LSS) {
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("ExAllocatePoolWithTag() failed.\n"));
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	//
	//	Connect and log in.
	//

	status = LsuConnectLogin(	LSS,
								NodeAddress,
								BindingAddress,
								LoginInfo,
								&LstransType);
	if(!NT_SUCCESS(status)) {
		ExFreePool(LSS);
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("LsuConnectLogin() failed. NTSTATUS: %08lx.\n", status));
		return status;
	}

	do {


		status = LsuConfigureIdeDisk(LSS, UdmaRestrict, &pduFlags, &dma, &bytesOfBlock);
		if(!NT_SUCCESS(status)) {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("IdeConfigure() failed. NTSTATUS: %08lx.\n", status));
			break;
		}
		if(dma == FALSE) {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Disk does not support DMA. DMA required.\n"));
			status = STATUS_INSUFFICIENT_RESOURCES;
			break;
		}


		//
		//	Read information block
		//

		Bus_KdPrint_Def(BUS_DBG_SS_INFO, ("DIB addr=%I64u\n", DIBAddress));
		status = LsuGetDiskInfoBlockV2(
						LSS,
						DiskInformationBlock,
						DIBAddress,
						bytesOfBlock,
						pduFlags
					);

		//
		//	Read Block ACL
		//

		if(NT_SUCCESS(status) && DiskInformationBlock->BACLSize) {
			PBLOCK_ACCESS_CONTROL_LIST	bacl;

			//
			//	Allocate memory for BACL. Caller take charge in freeing it.
			//

			bacl = ExAllocatePoolWithTag(
							NonPagedPool,
							DiskInformationBlock->BACLSize,
							NCOMM_POOLTAG_BACL);
			if(bacl == NULL) {
				status = STATUS_INSUFFICIENT_RESOURCES;
				break;
			}
			status = LsuGetBlockACL(
					LSS,
					bacl,
					DiskInformationBlock->BACLSize,
					BaclBlockAddr,
					bytesOfBlock,
					pduFlags);
			if(NT_SUCCESS(status)) {
				*BlockACL = bacl;
			} else {
				*BlockACL = NULL;
				ExFreePoolWithTag(bacl, NCOMM_POOLTAG_BACL);
			}
		}

	} while(0);

	LspLogout(LSS, NULL);
	LspDisconnect(LSS);
	ExFreePool(LSS);

	return status;
}
Exemplo n.º 17
0
NTSTATUS
NCommGetDIBV1(
	OUT	PNDAS_DIB				DiskInformationBlock,
	IN	PLSSLOGIN_INFO			LoginInfo,
	IN	UINT64					DIBAddress,
	IN	PTA_LSTRANS_ADDRESS		NodeAddress,
	IN	PTA_LSTRANS_ADDRESS		BindingAddress,
	IN	UCHAR					UdmaRestrict
) {
	PLANSCSI_SESSION	LSS;
	NTSTATUS			status;
	LSTRANS_TYPE		LstransType;
	ULONG				pduFlags;
	BOOLEAN				dma;
	ULONG				bytesOfBlock;

	LSS = (PLANSCSI_SESSION)ExAllocatePoolWithTag(NonPagedPool, sizeof(LANSCSI_SESSION), NCOMM_POOLTAG_LSS);
	if(!LSS) {
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("ExAllocatePoolWithTag() failed.\n"));
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	RtlZeroMemory( LSS, sizeof(LANSCSI_SESSION) );

	//
	//	Connect and log in.
	//

	status = LsuConnectLogin(	LSS,
								NodeAddress,
								BindingAddress,
								LoginInfo,
								&LstransType);
	if(!NT_SUCCESS(status)) {
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("LsuConnectLogin() failed. NTSTATUS: %08lx.\n", status));
		ExFreePoolWithTag(LSS, NCOMM_POOLTAG_LSS);
		return status;
	}

	status = LsuConfigureIdeDisk(LSS, UdmaRestrict, &pduFlags, &dma, &bytesOfBlock);
	if(!NT_SUCCESS(status)) {
		ExFreePoolWithTag(LSS, NCOMM_POOLTAG_LSS);
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("IdeConfigure() failed. NTSTATUS: %08lx.\n", status));
		return status;
	}
	if(dma == FALSE) {
		ExFreePoolWithTag(LSS, NCOMM_POOLTAG_LSS);
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Disk does not support DMA. DMA required.\n"));
		return STATUS_INSUFFICIENT_RESOURCES;
	}


	//
	//	Read informaition block
	//

	Bus_KdPrint_Def(BUS_DBG_SS_INFO, ("DIB addr=%I64u\n", DIBAddress));
	status = LsuGetDiskInfoBlockV1(
					LSS,
					DiskInformationBlock,
					DIBAddress,
					bytesOfBlock,
					pduFlags
				);

	LspLogout(LSS, NULL);
	LspDisconnect(LSS);
	ExFreePoolWithTag(LSS, NCOMM_POOLTAG_LSS);

	return status;
}
Exemplo n.º 18
0
NTSTATUS
Bus_CreateClose (
    IN  PDEVICE_OBJECT  DeviceObject,
    IN  PIRP            Irp
    )
/*++
Routine Description:

    Some outside source is trying to create a file against us.

    If this is for the FDO (the bus itself) then the caller 
    is trying to open the proprietary connection to tell us 
    to enumerate or remove a device.

    If this is for the PDO (an object on the bus) then this 
    is a client that wishes to use the toaster device.
    
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;
    PFDO_DEVICE_DATA    fdoData;

    PAGED_CODE ();

	Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Entered. \n"));

    fdoData = (PFDO_DEVICE_DATA) DeviceObject->DeviceExtension;

    status = STATUS_INVALID_DEVICE_REQUEST;
    Irp->IoStatus.Information = 0;
    
    Bus_IncIoCount (fdoData);

    //
    // If it's not for the FDO. We don't allow create/close on PDO
    // 
    if (fdoData->IsFDO) {
          
        //
        // Check to see whether the bus is removed
        //
       
        if (fdoData->DevicePnPState == Deleted){         
            status = STATUS_NO_SUCH_DEVICE;
        } else {

            irpStack = IoGetCurrentIrpStackLocation (Irp);

            switch (irpStack->MajorFunction) {
            case IRP_MJ_CREATE:
                Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Create \n"));
                status = STATUS_SUCCESS;
                break;

            case IRP_MJ_CLOSE:
                Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Close \n"));
                status = STATUS_SUCCESS;
                break;
             default:
                break;
            } 
        }
        
    }

    Irp->IoStatus.Status = status;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);
    Bus_DecIoCount (fdoData);

    return status;
}
Exemplo n.º 19
0
NTSTATUS
QueueUnplugWorker(
		PFDO_DEVICE_DATA	FdoData,
		ULONG				SlotNo
	) {
	NTSTATUS			status;
	PNDBUS_UNPLUGWORKER	workItemCtx;

	Bus_KdPrint_Def(BUS_DBG_SS_TRACE, ("entered.\n"));


	//
	//	Parameter check
	//

	if(!FdoData) {
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("FdoData NULL!\n"));
		return STATUS_INVALID_PARAMETER;
	}


	//
	//	Allocate worker's context
	//

	workItemCtx = (PNDBUS_UNPLUGWORKER)ExAllocatePoolWithTag(
								NonPagedPool,
								sizeof(NDBUS_UNPLUGWORKER),
								NDBUS_POOLTAG_UNPLUGWORKITEM);
	if(!workItemCtx) {
		return STATUS_INSUFFICIENT_RESOURCES;
	}
	workItemCtx->FdoData		= FdoData;
	workItemCtx->SlotNo			= SlotNo;


	//
	//	Allocate IO work item for NDASBUS's Functional device object.
	//

	workItemCtx->IoWorkItem = IoAllocateWorkItem(FdoData->Self);
	if(workItemCtx->IoWorkItem == NULL) {
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto cleanup;
	}


	//
	//	Queue the work item.
	//

	IoQueueWorkItem(
		workItemCtx->IoWorkItem,
		UnplugWorker,
		DelayedWorkQueue,
		workItemCtx
		);

	return STATUS_SUCCESS;

cleanup:
	if(workItemCtx) {
		ExFreePool(workItemCtx);
	}

	return status;
}
Exemplo n.º 20
0
NTSTATUS
DriverEntry (
    IN  PDRIVER_OBJECT  DriverObject,
    IN  PUNICODE_STRING RegistryPath
    )
/*++
Routine Description:

    Initialize the driver dispatch table. 

Arguments:

    DriverObject - pointer to the driver object

    RegistryPath - pointer to a unicode string representing the path,
                   to driver-specific key in the registry.

Return Value:

  NT Status Code

--*/
{
	NTSTATUS	status;
	ULONG		tempUlong;

    Bus_KdPrint_Def (BUS_DBG_SS_INFO, ("%s, %s\n", __DATE__, __TIME__));

    //
    // Save the RegistryPath for WMI.
    //

    Globals.RegistryPath.MaximumLength = RegistryPath->Length +
                                          sizeof(UNICODE_NULL);
    Globals.RegistryPath.Length = RegistryPath->Length;
    Globals.RegistryPath.Buffer = ExAllocatePoolWithTag(
                                       PagedPool,
                                       Globals.RegistryPath.MaximumLength,
                                       BUSENUM_POOL_TAG_DRIVER_REGISTRYPATH
                                       );    

    if (!Globals.RegistryPath.Buffer) {

        return STATUS_INSUFFICIENT_RESOURCES;
    }
    
    RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath);

	//
	// Query OS Versions
	//
	Globals.bCheckVersion = PsGetVersion(
								&Globals.MajorVersion,
								&Globals.MinorVersion,
								&Globals.BuildNumber,
								NULL
								);

	if(Globals.bCheckVersion == TRUE) {
		Bus_KdPrint_Def (BUS_DBG_SS_INFO, 
			("Checkd Build, Major Ver %d, Minor Ver %d, Build %d\n", 
				Globals.MajorVersion, Globals.MinorVersion, Globals.BuildNumber));
	} else {
		Bus_KdPrint_Def (BUS_DBG_SS_INFO, 
			("Free Build, Major Ver %d, Minor Ver %d, Build %d\n", 
				Globals.MajorVersion, Globals.MinorVersion, Globals.BuildNumber));
	}

    //
    // Set entry points into the driver
    //
    DriverObject->MajorFunction [IRP_MJ_CREATE] =
    DriverObject->MajorFunction [IRP_MJ_CLOSE] = Bus_CreateClose;
    DriverObject->MajorFunction [IRP_MJ_PNP] = Bus_PnP;
    DriverObject->MajorFunction [IRP_MJ_POWER] = Bus_Power;
    DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = Bus_IoCtl;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = Bus_SystemControl;
    DriverObject->DriverUnload = Bus_DriverUnload;
    DriverObject->DriverExtension->AddDevice = Bus_AddDevice;

	//
	//	Init mutex
	//
	ExInitializeFastMutex(&Globals.Mutex);

	//
	//	Default setting
	//
	Globals.PersistentPdo = TRUE;
	Globals.LfsFilterInstalled = FALSE;

	//
	//	Read options in the registry
	//

	// Disable persistent PDO option
	status = DrReadKeyValueInstantly(	RegistryPath,
									BUSENUM_DRVREG_DISABLE_PERSISTENTPDO,
									REG_DWORD,
									&tempUlong,
									sizeof(tempUlong),
									NULL);
	if(NT_SUCCESS(status) && tempUlong != 0) {
		Globals.PersistentPdo = FALSE;
		Bus_KdPrint_Def (BUS_DBG_SS_INFO, 
			("Persistent PDO option disabled.\n"));
	}

	//
	//	Check to see if LFS filter is installed.
	//

	status = LfsFiltDriverServiceExist();
	if(NT_SUCCESS(status)) {
		Globals.LfsFilterInstalled = TRUE;
		Bus_KdPrint_Def (BUS_DBG_SS_INFO,
			("LFS Filter is detected.\n"));
	} else {
		Globals.LfsFilterInstalled = FALSE;
		Bus_KdPrint_Def (BUS_DBG_SS_INFO,
			("LFS Filter is not detected. STATUS=%08lx\n", status));
	}

    return STATUS_SUCCESS;
}
Exemplo n.º 21
0
NTSTATUS
DriverEntry (
    IN  PDRIVER_OBJECT  DriverObject,
    IN  PUNICODE_STRING RegistryPath
    )
/*++
Routine Description:

    Initialize the driver dispatch table. 

Arguments:

    DriverObject - pointer to the driver object

    RegistryPath - pointer to a unicode string representing the path,
                   to driver-specific key in the registry.

Return Value:

  NT Status Code

--*/
{

    Bus_KdPrint_Def (BUS_DBG_SS_INFO, ("%s, %s\n", __DATE__, __TIME__));

    //
    // Save the RegistryPath for WMI.
    //

    Globals.RegistryPath.MaximumLength = RegistryPath->Length +
                                          sizeof(UNICODE_NULL);
    Globals.RegistryPath.Length = RegistryPath->Length;
    Globals.RegistryPath.Buffer = ExAllocatePoolWithTag(
                                       PagedPool,
                                       Globals.RegistryPath.MaximumLength,
                                       BUSENUM_POOL_TAG
                                       );    

    if (!Globals.RegistryPath.Buffer) {

        return STATUS_INSUFFICIENT_RESOURCES;
    }
    
    RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath);

	// Added by jgahn. 
	// Get OS Version.
	Globals.bCheckVersion = PsGetVersion(
		&Globals.MajorVersion,
		&Globals.MinorVersion,
		&Globals.BuildNumber,
		NULL
		);

	if(Globals.bCheckVersion == TRUE) {
		Bus_KdPrint_Def (BUS_DBG_SS_INFO, 
			("Checkd Build, Major Ver %d, Minor Ver %d, Build %d\n", 
				Globals.MajorVersion, Globals.MinorVersion, Globals.BuildNumber));
	} else {
		Bus_KdPrint_Def (BUS_DBG_SS_INFO, 
			("Free Build, Major Ver %d, Minor Ver %d, Build %d\n", 
				Globals.MajorVersion, Globals.MinorVersion, Globals.BuildNumber));
	}

    //
    // Set entry points into the driver
    //
    DriverObject->MajorFunction [IRP_MJ_CREATE] =
    DriverObject->MajorFunction [IRP_MJ_CLOSE] = Bus_CreateClose;
    DriverObject->MajorFunction [IRP_MJ_PNP] = Bus_PnP;
    DriverObject->MajorFunction [IRP_MJ_POWER] = Bus_Power;
    DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = Bus_IoCtl;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = Bus_SystemControl;
    DriverObject->DriverUnload = Bus_DriverUnload;
    DriverObject->DriverExtension->AddDevice = Bus_AddDevice;

    return STATUS_SUCCESS;
}
Exemplo n.º 22
0
static
NTSTATUS
LfsFiltOpenControl (
	OUT PHANDLE					ControlFileHandle, 
	OUT	PFILE_OBJECT			*ControlFileObject
	)
{
	HANDLE						controlFileHandle; 
	PFILE_OBJECT				controlFileObject;

	UNICODE_STRING	    		nameString;
	OBJECT_ATTRIBUTES	    	objectAttributes;
	IO_STATUS_BLOCK				ioStatusBlock;
	NTSTATUS	    			status;
	
	Bus_KdPrint_Def(BUS_DBG_SS_TRACE, ("Entered\n"));

	//
	// Init object attributes
	//

	RtlInitUnicodeString (&nameString, LFSFILT_CTLDEVICE_NAME);
	InitializeObjectAttributes (
		&objectAttributes,
		&nameString,
		0,
		NULL,
		NULL
		);

	status = ZwCreateFile(
				&controlFileHandle,
				GENERIC_READ,
				&objectAttributes,
				&ioStatusBlock,
				NULL,
				FILE_ATTRIBUTE_NORMAL,
				0,
				0,
				0,
				NULL,	// Open as control
				0		// 
				);

	if (!NT_SUCCESS(status)) {
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("FAILURE, ZwCreateFile returned status code=%x\n", status));
		*ControlFileHandle = NULL;
		*ControlFileObject = NULL;
		return status;
	}

	status = ioStatusBlock.Status;

	if (!NT_SUCCESS(status)) {
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("FAILURE, IoStatusBlock.Status contains status code=%x\n", status));
		*ControlFileHandle = NULL;
		*ControlFileObject = NULL;
		return status;
	}

	status = ObReferenceObjectByHandle (
		        controlFileHandle,
		        0L,
		        NULL,
		        KernelMode,
		        (PVOID *) &controlFileObject,
		        NULL
				);

	if (!NT_SUCCESS(status)) {
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("ObReferenceObjectByHandle() failed. STATUS=%08lx\n", status));
		ZwClose(controlFileHandle);
		*ControlFileHandle = NULL;
		*ControlFileObject = NULL;
		return status;
	}
	 
	*ControlFileHandle = controlFileHandle;
	*ControlFileObject = controlFileObject;

	return status;
}
Exemplo n.º 23
0
//
//	Plug in a device on LanscsiBus in KernelMode.
//
NTSTATUS
LSBus_PlugInLSBUSDevice(
			PFDO_DEVICE_DATA	FdoData,
			ULONG				SlotNo,
			PWCHAR				HardwareIDs,
			LONG				HardwareIDLen,
			ULONG				MaxBlocksPerRequest
	){
	PBUSENUM_PLUGIN_HARDWARE_EX	BusDevice;
	ULONG						Length;
	HANDLE						DisconEvent;
	HANDLE						AlarmEvent;
    NTSTATUS			status;

    //
	//	Create events
    //
	status = ZwCreateEvent(
							&DisconEvent,
							GENERIC_READ,
							NULL,
							NotificationEvent,
							FALSE
						);
	if(!NT_SUCCESS(status)) {
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PlugInLSBUSDevice: ZwCreateEvent() failed. Disconnection event.\n"));
		return status;
	}

	status = ZwCreateEvent(
							&AlarmEvent,
							GENERIC_READ,
                               NULL,
							NotificationEvent,
							FALSE
						);
    if(!NT_SUCCESS(status)) {
		ZwClose(DisconEvent);
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PlugInLSBUSDevice: ExAllocatePoolWithTag() failed. AlarmEvent\n"));
		return status;
    }

	//
	//	Build BUSENUM_PLUGIN_HARDWARE_EX structure.
	//
	Length = sizeof(BUSENUM_PLUGIN_HARDWARE_EX) + HardwareIDLen;
	BusDevice = ExAllocatePoolWithTag(
							PagedPool,
							Length,
							LSBUS_POOTAG_PLUGIN
						);
	if(!BusDevice) {
		ZwClose(DisconEvent);
		ZwClose(AlarmEvent);
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PlugInLSBUSDevice: ExAllocatePoolWithTag() failed.\n"));
		return STATUS_INSUFFICIENT_RESOURCES;
	}


	BusDevice->Size = Length;
	BusDevice->SlotNo = SlotNo;
	RtlCopyMemory(BusDevice->HardwareIDs, HardwareIDs, HardwareIDLen);
	BusDevice->MaxRequestBlocks = MaxBlocksPerRequest;
	BusDevice->phAlarmEvent = &AlarmEvent;
	BusDevice->phEvent = &DisconEvent;

	status = Bus_PlugInDeviceEx(BusDevice, Length, FdoData, KernelMode);

	//
	//	Close handle to decrease one reference from events.
	//
	ZwClose(AlarmEvent);
	ZwClose(DisconEvent);

	ExFreePool(BusDevice);
	return status;
}
Exemplo n.º 24
0
//
//	Query information on LanscsiBus
//
NTSTATUS
LSBus_QueryInformation(
		PFDO_DEVICE_DATA				FdoData,
		PBUSENUM_QUERY_INFORMATION		Query,
		PBUSENUM_INFORMATION			Information,
		LONG							OutBufferLength,
		PLONG							OutBufferLenNeeded
	) {

	NTSTATUS			ntStatus;
	PLIST_ENTRY         entry;
	PPDO_DEVICE_DATA	PdoData;
	

	ntStatus = STATUS_SUCCESS;
	*OutBufferLenNeeded = OutBufferLength;
	PdoData = NULL;

	//
	//	Acquire the mutex to prevent PdoData ( Device Extension ) to disappear.
	//
    KeEnterCriticalRegion();
	ExAcquireFastMutex (&FdoData->Mutex);

	switch(Query->InfoClass) {
	case INFORMATION_NUMOFPDOS: {
		ULONG				NumOfPDOs;

		NumOfPDOs = 0;

		for (entry = FdoData->ListOfPDOs.Flink;
			entry != &FdoData->ListOfPDOs;
			entry = entry->Flink) {
			NumOfPDOs ++;
		}

		Information->NumberOfPDOs = NumOfPDOs;
		break;
	}
	case INFORMATION_PDO: {
		KIRQL	oldIrql;

		for (entry = FdoData->ListOfPDOs.Flink;
			entry != &FdoData->ListOfPDOs;
			entry = entry->Flink) {

				PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link);
				if(Query->SlotNo == PdoData->SlotNo) {
					ObReferenceObject(PdoData->Self);
					break;
				}
				PdoData = NULL;

		}

		if(PdoData) {
			KeAcquireSpinLock(&PdoData->LanscsiAdapterPDO.LSDevDataSpinLock, &oldIrql);
			Bus_KdPrint_Def(BUS_DBG_SS_TRACE, ("Status:%08lx DAcc:%08lx GAcc:%08lx\n",
											PdoData->LanscsiAdapterPDO.AdapterStatus,
											PdoData->LanscsiAdapterPDO.DesiredAccess,
											PdoData->LanscsiAdapterPDO.GrantedAccess
									));
			Information->PdoInfo.AdapterStatus = PdoData->LanscsiAdapterPDO.AdapterStatus;
			Information->PdoInfo.DesiredAccess = PdoData->LanscsiAdapterPDO.DesiredAccess;
			Information->PdoInfo.GrantedAccess = PdoData->LanscsiAdapterPDO.GrantedAccess;
			KeReleaseSpinLock(&PdoData->LanscsiAdapterPDO.LSDevDataSpinLock, oldIrql);

			ObDereferenceObject(PdoData->Self);
		} else {
			Bus_KdPrint_Def(BUS_DBG_SS_NOISE, ("No PDO for SlotNo %d!\n", Query->SlotNo));
			ntStatus = STATUS_NO_SUCH_DEVICE;
		}
		break;
	}
	case INFORMATION_PDOENUM: {
		LARGE_INTEGER		TimeOut;

		for (entry = FdoData->ListOfPDOs.Flink;
			entry != &FdoData->ListOfPDOs;
			entry = entry->Flink) {

				PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link);
				if(Query->SlotNo == PdoData->SlotNo) {
					ObReferenceObject(PdoData->Self);
					break;
				}
				PdoData = NULL;

		}

		ExReleaseFastMutex (&FdoData->Mutex);
	    KeLeaveCriticalRegion();

		if(!PdoData) {
		    KeEnterCriticalRegion();
			ExAcquireFastMutex (&FdoData->Mutex);
			ntStatus = STATUS_NO_SUCH_DEVICE;
			break;
		}
		//
		//	Wait until LDServ sends AddTargetData.
		//
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("waiting for AddTargetEvent.\n"));
		TimeOut.QuadPart = -10 * 1000 * 1000 * 120;			// 120 seconds
		ntStatus = KeWaitForSingleObject(
						&PdoData->LanscsiAdapterPDO.AddTargetEvent,
						Executive,
						KernelMode,
						FALSE,
						&TimeOut
					);
		if(ntStatus != STATUS_SUCCESS) {
		    KeEnterCriticalRegion();
			ExAcquireFastMutex (&FdoData->Mutex);

			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("failed to wait for AddTargetEvent.\n"));
			ntStatus = STATUS_NO_SUCH_DEVICE;
			ObDereferenceObject(PdoData->Self);
			break;
		}
		Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Completed to wait for AddTargetEvent.\n"));

	    KeEnterCriticalRegion();
		ExAcquireFastMutex (&FdoData->Mutex);


		if(PdoData) {

			if(PdoData->LanscsiAdapterPDO.Flags & LSDEVDATA_FLAG_LURDESC) {
				//
				//	A LUR descriptor is set.
				//

				if(PdoData->LanscsiAdapterPDO.AddDevInfo == NULL) {
					ntStatus = STATUS_NO_SUCH_DEVICE;
					ObDereferenceObject(PdoData->Self);
					break;
				}

				*OutBufferLenNeeded =	FIELD_OFFSET(BUSENUM_INFORMATION, PdoEnumInfo) +
										FIELD_OFFSET(BUSENUM_INFORMATION_PDOENUM, AddDevInfo) +
										PdoData->LanscsiAdapterPDO.AddDevInfoLength;
				if(OutBufferLength < *OutBufferLenNeeded) {
					ntStatus = STATUS_BUFFER_TOO_SMALL;
				} else {
					RtlCopyMemory(
								&Information->PdoEnumInfo.AddDevInfo,
								PdoData->LanscsiAdapterPDO.AddDevInfo,
								PdoData->LanscsiAdapterPDO.AddDevInfoLength
							);
					Information->PdoEnumInfo.Flags = PDOENUM_FLAG_LURDESC;
					Information->PdoEnumInfo.DisconEventToService = PdoData->LanscsiAdapterPDO.DisconEventToService;
					Information->PdoEnumInfo.AlarmEventToService = PdoData->LanscsiAdapterPDO.AlarmEventToService;
					Information->PdoEnumInfo.MaxBlocksPerRequest = PdoData->LanscsiAdapterPDO.MaxBlocksPerRequest;
				}
			} else {
				//
				//	ADD_TARGET_DATA is set.
				//
				PLANSCSI_ADD_TARGET_DATA	AddTargetData;
			LONG						AddTargetLenNeeded;
			LONG						InfoBuffLenNeeded;

				AddTargetData = PdoData->LanscsiAdapterPDO.AddDevInfo;
				if(AddTargetData == NULL) {
				ntStatus = STATUS_NO_SUCH_DEVICE;
				ObDereferenceObject(PdoData->Self);
				break;
			}
				//
				//	calculate the length needed.
				//
				AddTargetLenNeeded = sizeof(LANSCSI_ADD_TARGET_DATA) + (AddTargetData->ulNumberOfUnitDiskList-1)*sizeof(LSBUS_UNITDISK);
				InfoBuffLenNeeded = sizeof(BUSENUM_INFORMATION) - sizeof(BYTE) + (AddTargetLenNeeded);
			*OutBufferLenNeeded = InfoBuffLenNeeded;
			if(OutBufferLength < InfoBuffLenNeeded) {
				ntStatus = STATUS_BUFFER_TOO_SMALL;
			} else {
					RtlCopyMemory(&Information->PdoEnumInfo.AddDevInfo, AddTargetData, AddTargetLenNeeded);
					Information->PdoEnumInfo.Flags = 0;
				Information->PdoEnumInfo.DisconEventToService = PdoData->LanscsiAdapterPDO.DisconEventToService;
				Information->PdoEnumInfo.AlarmEventToService = PdoData->LanscsiAdapterPDO.AlarmEventToService;
				Information->PdoEnumInfo.MaxBlocksPerRequest = PdoData->LanscsiAdapterPDO.MaxBlocksPerRequest;
			}
			}
		} else {

			ntStatus = STATUS_NO_SUCH_DEVICE;
		}

		ObDereferenceObject(PdoData->Self);
		break;
	}
	case INFORMATION_PDOEVENT: {

		for (entry = FdoData->ListOfPDOs.Flink;
			entry != &FdoData->ListOfPDOs;
			entry = entry->Flink) {

				PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link);
				if(Query->SlotNo == PdoData->SlotNo) {
					ObReferenceObject(PdoData->Self);
					break;
				}
				PdoData = NULL;

		}

		if(PdoData == NULL) {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not find the PDO:%u.\n", Query->SlotNo));
			ntStatus = STATUS_NO_SUCH_DEVICE;
			break;
		}

		if( Query->Flags & LSBUS_QUERYFLAG_USERHANDLE) {
			Information->PdoEvents.SlotNo = PdoData->SlotNo;
			Information->PdoEvents.Flags = LSBUS_QUERYFLAG_USERHANDLE;

			//
			//	Get user-mode event handles.
			//
			ntStatus = ObOpenObjectByPointer(
					PdoData->LanscsiAdapterPDO.DisconEventToService,
					0,
					NULL,
					GENERIC_READ,
					*ExEventObjectType,
					UserMode,
					&Information->PdoEvents.DisconEvent
				);
			if(!NT_SUCCESS(ntStatus)) {
				ObDereferenceObject(PdoData->Self);
				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open Disconnect event object!!\n"));
				break;
			}
			ntStatus = ObOpenObjectByPointer(
					PdoData->LanscsiAdapterPDO.AlarmEventToService,
					0,
					NULL,
					GENERIC_READ,
					*ExEventObjectType,
					UserMode,
					&Information->PdoEvents.AlarmEvent
				);
			if(!NT_SUCCESS(ntStatus)) {
				ObDereferenceObject(PdoData->Self);
				Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("Could not open Disconnect event object!!\n"));
				break;
			}

		} else {
			Information->PdoEvents.SlotNo = PdoData->SlotNo;
			Information->PdoEvents.Flags = 0;
			Information->PdoEvents.DisconEvent = PdoData->LanscsiAdapterPDO.DisconEventToService;
			Information->PdoEvents.AlarmEvent = PdoData->LanscsiAdapterPDO.AlarmEventToService;
		}

		ObDereferenceObject(PdoData->Self);
		break;
   }
	case INFORMATION_ISREGISTERED: {
		HANDLE	DeviceReg;
		HANDLE	NdasDeviceReg;

		ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

		DeviceReg = NULL;
		NdasDeviceReg = NULL;
		ntStatus = Reg_OpenDeviceRegistry(FdoData->UnderlyingPDO, &DeviceReg, KEY_READ|KEY_WRITE);
		if(!NT_SUCCESS(ntStatus)) {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("ISREGISTERED: OpenServiceRegistry() failed.\n"));
			break;
		}
		ntStatus = Reg_OpenNdasDeviceRegistry(&NdasDeviceReg, KEY_READ|KEY_WRITE, DeviceReg);
		if(!NT_SUCCESS(ntStatus)) {
			ZwClose(DeviceReg);
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("ISREGISTERED: OpenNdasDeviceRegistry() failed.\n"));
			break;
		}

		ntStatus = Reg_LookupRegDeviceWithSlotNo(NdasDeviceReg, Query->SlotNo, &DeviceReg);
		if(NT_SUCCESS(ntStatus)) {
			ZwClose(DeviceReg);
			Information->IsRegistered = 1;
			Bus_KdPrint_Def(BUS_DBG_SS_INFO, ("ISREGISTERED: Device(%d) is registered.\n", Query->SlotNo));
		} else {
			Information->IsRegistered = 0;
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("ISREGISTERED: Could not find a Device(%d).\n", Query->SlotNo));
		}
		if(NdasDeviceReg)
			ZwClose(NdasDeviceReg);
		if(DeviceReg)
			ZwClose(DeviceReg);

		break;
	}

	case INFORMATION_PDOSLOTLIST: {
		LONG	outputLength;
		LONG	entryCnt;

		if(OutBufferLength < FIELD_OFFSET(BUSENUM_INFORMATION, PdoSlotList)) {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Buffer size is less than required\n"));
			ntStatus = STATUS_INVALID_PARAMETER;
			break;
		}

		Information->Size = 0;
		Information->InfoClass = INFORMATION_PDOSLOTLIST;

		//
		//	Add the size of information header.
		//
		outputLength = FIELD_OFFSET(BUSENUM_INFORMATION, PdoSlotList);
		outputLength += sizeof(UINT32);					// SlotNoCnt
		entryCnt = 0;

		for (entry = FdoData->ListOfPDOs.Flink;
			entry != &FdoData->ListOfPDOs;
			entry = entry->Flink) {

			PdoData = CONTAINING_RECORD(entry, PDO_DEVICE_DATA, Link);

			//
			//	Add the size of each slot entry.
			//
			outputLength += sizeof(UINT32);
			if(outputLength > OutBufferLength) {
				continue;
			}

			Information->PdoSlotList.SlotNo[entryCnt] = PdoData->SlotNo;
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Entry #%u: %u\n", entryCnt, PdoData->SlotNo));

			entryCnt ++;
		}

		if(outputLength > OutBufferLength) {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Could not find a Device(%d).\n", Query->SlotNo));
			*OutBufferLenNeeded = outputLength;
			ntStatus = STATUS_BUFFER_TOO_SMALL;
		} else {
			Bus_KdPrint_Def(BUS_DBG_SS_ERROR, ("PDOSLOTLIST: Entry count:%d.\n", entryCnt));
			Information->Size = outputLength;
			Information->PdoSlotList.SlotNoCnt = entryCnt;
			*OutBufferLenNeeded = outputLength;
		}

		break;
	}

	default:
		ntStatus = STATUS_INVALID_PARAMETER;
	}

	ExReleaseFastMutex (&FdoData->Mutex);
    KeLeaveCriticalRegion();

	return ntStatus;
}