NTSTATUS
NdasDluSendIoctlSrbAsynch(
		IN PDEVICE_OBJECT	DeviceObject,
		IN ULONG			IoctlCode,
		IN PVOID			InputBuffer,
		IN LONG				InputBufferLength,
		OUT PVOID			OutputBuffer,
		IN LONG				OutputBufferLength
){

    PIRP				irp;
	PMINISENDSRB_CONTEXT	context = NULL;
 	PSRB_IO_CONTROL		psrbIoctl;
	PSCSI_REQUEST_BLOCK	srb;
	LONG				srbIoctlLength;
	PVOID				srbIoctlBuffer;
	LONG				srbIoctlBufferLength;
    NTSTATUS			status;
    PIO_STACK_LOCATION	irpStack;
    LARGE_INTEGER		startingOffset;
    IO_STATUS_BLOCK		ioStatusBlock;

	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	psrbIoctl	= NULL;
	irp = NULL;

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

	context = (PMINISENDSRB_CONTEXT)ExAllocatePoolWithTag(NonPagedPool,
					FIELD_OFFSET(MINISENDSRB_CONTEXT, SrbIoctl) + srbIoctlLength,
					NDAS_DLU_PTAG_SRB_CMPDATA);
	if(context == NULL) {
		KDPrint(1, ("STATUS_INSUFFICIENT_RESOURCES\n"));
		status = STATUS_INSUFFICIENT_RESOURCES;
		goto cleanup;
	}

	context->UserBuffer = OutputBuffer;
	context->UserBufferLen = OutputBufferLength;
	srb = &context->Srb;
	psrbIoctl = &context->SrbIoctl;

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

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

	startingOffset.QuadPart = 1;

    //
    // Build IRP for this request.
    // Note we do this synchronously for two reasons.  If it was done
    // asynchronously 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 = IoBuildAsynchronousFsdRequest(
                 IRP_MJ_SCSI,
                DeviceObject,
                psrbIoctl,
                srbIoctlLength,
                &startingOffset,
                &ioStatusBlock);

	context->Irp = irp;
	IoSetCompletionRoutine(irp, NdasDluSendSrbIoCompletion, context, TRUE, TRUE, TRUE);
    irpStack = IoGetNextIrpStackLocation(irp);

    if (irp == NULL) {
        KDPrint(1,("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_OUT | SRB_FLAGS_NO_QUEUE_FREEZE;

	srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
	srb->QueueTag = SP_UNTAGGED;

    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( DeviceObject, irp );

	return status;

cleanup:
	if(context)
		ExFreePool(context);

    return status;
}
Beispiel #2
0
NTSTATUS
W2KNtfsPerformVerifyDiskRead (
    IN PDEVICE_OBJECT	DeviceObject,
    IN PVOID			Buffer,
    IN LONGLONG			Offset,
    IN ULONG			NumberOfBytesToRead
    )

/*++

Routine Description:

    This routine is used to read in a range of bytes from the disk.  It
    bypasses all of the caching and regular I/O logic, and builds and issues
    the requests itself.  It does this operation overriding the verify
    volume flag in the device object.

Arguments:

    Vcb - Supplies the Vcb denoting the device for this operation

    Buffer - Supplies the buffer that will recieve the results of this operation

    Offset - Supplies the offset of where to start reading

    NumberOfBytesToRead - Supplies the number of bytes to read, this must
        be in multiple of bytes units acceptable to the disk driver.

Return Value:

    None.

--*/

{
    KEVENT Event;
    PIRP Irp;
    NTSTATUS Status;


    PAGED_CODE();

    //
    //  Initialize the event we're going to use
    //

    KeInitializeEvent( &Event, NotificationEvent, FALSE );

    //
    //  Build the irp for the operation and also set the overrride flag
    //
    //  Note that we may be at APC level, so do this asyncrhonously and
    //  use an event for synchronization normal request completion
    //  cannot occur at APC level.
    //
    Irp = IoBuildAsynchronousFsdRequest( IRP_MJ_READ,
                                         DeviceObject,
                                         Buffer,
                                         NumberOfBytesToRead,
                                         (PLARGE_INTEGER)&Offset,
                                         NULL );

    if ( Irp == NULL ) {

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    SetFlag( IoGetNextIrpStackLocation( Irp )->Flags, SL_OVERRIDE_VERIFY_VOLUME );

    //
    //  Set up the completion routine
    //

    IoSetCompletionRoutine( Irp,
                            W2KNtfsVerifyReadCompletionRoutine,
                            &Event,
                            TRUE,
                            TRUE,
                            TRUE );

    //
    //  Call the device to do the write and wait for it to finish.
    //

    try {

        (VOID)IoCallDriver( DeviceObject, Irp );
        (VOID)KeWaitForSingleObject( &Event, Executive, KernelMode, FALSE, (PLARGE_INTEGER)NULL );

        //
        //  Grab the Status.
        //

        Status = Irp->IoStatus.Status;

    } finally {

        //
        //  If there is an MDL (or MDLs) associated with this I/O
        //  request, Free it (them) here.  This is accomplished by
        //  walking the MDL list hanging off of the IRP and deallocating
        //  each MDL encountered.
        //

        while (Irp->MdlAddress != NULL) {

            PMDL NextMdl;

            NextMdl = Irp->MdlAddress->Next;

            MmUnlockPages( Irp->MdlAddress );

            IoFreeMdl( Irp->MdlAddress );

            Irp->MdlAddress = NextMdl;
        }

        IoFreeIrp( Irp );
    }

    //
    //  If it doesn't succeed then raise the error
    //

    return Status;
}
Beispiel #3
0
NTSTATUS
NTAPI
_MiSimpleWrite(PFILE_OBJECT FileObject,
               PLARGE_INTEGER FileOffset,
               PVOID Buffer,
               ULONG Length,
               PIO_STATUS_BLOCK ReadStatus,
               const char *File,
               int Line)
{
    NTSTATUS Status;
    PIRP Irp = NULL;
    KEVENT ReadWait;
    PDEVICE_OBJECT DeviceObject;
    PIO_STACK_LOCATION IrpSp;

    ASSERT(FileObject);
    ASSERT(FileOffset);
    ASSERT(Buffer);
    ASSERT(ReadStatus);

    DeviceObject = MmGetDeviceObjectForFile(FileObject);
    ASSERT(DeviceObject);

    DPRINT("PAGING WRITE: FileObject %p <%wZ> Offset 0x%I64x Length %lu (%s:%d)\n",
           FileObject,
           &FileObject->FileName,
           FileOffset->QuadPart,
           Length,
           File,
           Line);

    KeInitializeEvent(&ReadWait, NotificationEvent, FALSE);

    Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_WRITE,
                                        DeviceObject,
                                        Buffer,
                                        Length,
                                        FileOffset,
                                        ReadStatus);

    if (!Irp)
    {
        return STATUS_NO_MEMORY;
    }

    Irp->Flags = IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE | IRP_SYNCHRONOUS_API;

    Irp->UserEvent = &ReadWait;
    Irp->Tail.Overlay.OriginalFileObject = FileObject;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
    IrpSp = IoGetNextIrpStackLocation(Irp);
    IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
    IrpSp->FileObject = FileObject;
    IrpSp->CompletionRoutine = MiSimpleReadComplete;

    DPRINT("Call Driver\n");
    Status = IoCallDriver(DeviceObject, Irp);
    DPRINT("Status %x\n", Status);

    if (Status == STATUS_PENDING)
    {
        DPRINT("KeWaitForSingleObject(&ReadWait)\n");
        if (!NT_SUCCESS(KeWaitForSingleObject(&ReadWait,
                                              Suspended,
                                              KernelMode,
                                              FALSE,
                                              NULL)))
        {
            DPRINT1("Warning: Failed to wait for synchronous IRP\n");
            ASSERT(FALSE);
            return Status;
        }
    }

    DPRINT("Paging IO Done: %08x\n", ReadStatus->Status);
    return ReadStatus->Status;
}
Beispiel #4
0
NTSTATUS
NTAPI
MiSimpleRead(PFILE_OBJECT FileObject,
             PLARGE_INTEGER FileOffset,
             PVOID Buffer,
             ULONG Length,
             BOOLEAN Paging,
             PIO_STATUS_BLOCK ReadStatus)
{
    NTSTATUS Status;
    PIRP Irp = NULL;
    KEVENT ReadWait;
    PDEVICE_OBJECT DeviceObject;
    PIO_STACK_LOCATION IrpSp;

    ASSERT(FileObject);
    ASSERT(FileOffset);
    ASSERT(Buffer);
    ASSERT(ReadStatus);

    DeviceObject = MmGetDeviceObjectForFile(FileObject);
    ReadStatus->Status = STATUS_INTERNAL_ERROR;
    ReadStatus->Information = 0;

    ASSERT(DeviceObject);

    DPRINT("PAGING READ: FileObject %p <%wZ> Offset %08x%08x Length %ul\n",
           FileObject,
           &FileObject->FileName,
           FileOffset->HighPart,
           FileOffset->LowPart,
           Length);

    KeInitializeEvent(&ReadWait, NotificationEvent, FALSE);

    Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_READ,
                                        DeviceObject,
                                        Buffer,
                                        Length,
                                        FileOffset,
                                        ReadStatus);

    if (!Irp)
    {
        return STATUS_NO_MEMORY;
    }

    Irp->Flags |= (Paging ? IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE : 0) | IRP_SYNCHRONOUS_API;

    Irp->UserEvent = &ReadWait;
    Irp->Tail.Overlay.OriginalFileObject = FileObject;
    Irp->Tail.Overlay.Thread = PsGetCurrentThread();
    IrpSp = IoGetNextIrpStackLocation(Irp);
    IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
    IrpSp->FileObject = FileObject;
    IrpSp->CompletionRoutine = MiSimpleReadComplete;

    /* Non paging case, the FileObject will be dereferenced at completion */
    if (!Paging)
        ObReferenceObject(FileObject);

    Status = IoCallDriver(DeviceObject, Irp);
    if (Status == STATUS_PENDING)
    {
        DPRINT("KeWaitForSingleObject(&ReadWait)\n");
        if (!NT_SUCCESS(KeWaitForSingleObject(&ReadWait,
                                              Suspended,
                                              KernelMode,
                                              FALSE,
                                              NULL)))
        {
            DPRINT1("Warning: Failed to wait for synchronous IRP\n");
            ASSERT(FALSE);
            return Status;
        }
    }

    DPRINT("Paging IO Done: %08x\n", ReadStatus->Status);
    Status = ReadStatus->Status == STATUS_END_OF_FILE ? STATUS_SUCCESS : ReadStatus->Status;
    return Status;
}
Beispiel #5
0
NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj,
								 IN PIRP pIrp) 
{
	KdPrint(("DriverB:Enter B HelloDDKRead\n"));
	NTSTATUS ntStatus = STATUS_SUCCESS;

	UNICODE_STRING DeviceName;
	RtlInitUnicodeString( &DeviceName, L"\\Device\\MyDDKDeviceA" );

	PDEVICE_OBJECT DeviceObject = NULL;
	PFILE_OBJECT FileObject = NULL;
	//得到设备对象指针
	ntStatus = IoGetDeviceObjectPointer(&DeviceName,FILE_ALL_ACCESS,&FileObject,&DeviceObject);

	KdPrint(("DriverB:FileObject:%x\n",FileObject));
	KdPrint(("DriverB:DeviceObject:%x\n",DeviceObject));

	if (!NT_SUCCESS(ntStatus))
	{
		KdPrint(("DriverB:IoGetDeviceObjectPointer() 0x%x\n", ntStatus ));

		ntStatus = STATUS_UNSUCCESSFUL;
		// 完成IRP
		pIrp->IoStatus.Status = ntStatus;
		pIrp->IoStatus.Information = 0;	// bytes xfered
		IoCompleteRequest( pIrp, IO_NO_INCREMENT );
		KdPrint(("DriverB:Leave B HelloDDKRead\n"));

		return ntStatus;
	}

	KEVENT event;
	KeInitializeEvent(&event,NotificationEvent,FALSE);
	IO_STATUS_BLOCK status_block;
	LARGE_INTEGER offsert = RtlConvertLongToLargeInteger(0);

	//创建异步IRP
	PIRP pNewIrp = IoBuildAsynchronousFsdRequest(IRP_MJ_READ,
												DeviceObject,
												NULL,0,
												&offsert,&status_block);
	KdPrint(("pNewIrp->UserEvent :%x\n",pNewIrp->UserEvent));
	//设置pNewIrp->UserEvent,这样在IRP完成后可以通知该事件
	pNewIrp->UserEvent = &event;
	
 	KdPrint(("DriverB:pNewIrp:%x\n",pNewIrp));

	PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(pNewIrp);
	stack->FileObject = FileObject;

	NTSTATUS status = IoCallDriver(DeviceObject,pNewIrp);

    if (status == STATUS_PENDING) {
       status = KeWaitForSingleObject(
                            &event,
                            Executive,
                            KernelMode,
                            FALSE, // Not alertable
                            NULL);
        status = status_block.Status;
    }

	ZwClose(FileObject);
 
	//关闭设备句柄
 	ObDereferenceObject( FileObject );

	ntStatus = STATUS_SUCCESS;
	// 完成IRP
	pIrp->IoStatus.Status = ntStatus;
	pIrp->IoStatus.Information = 0;	// bytes xfered
	IoCompleteRequest( pIrp, IO_NO_INCREMENT );
	KdPrint(("DriverB:Leave B HelloDDKRead\n"));
	return ntStatus;
}
Beispiel #6
0
NTSTATUS DPQueryVolumeInformation(
	PDEVICE_OBJECT			DevObj,
	LARGE_INTEGER *			TotalSize,
	DWORD *					ClusterSize,
	DWORD *					SectorSize
	)
{
#define _FileSystemNameLength	64
//定义FAT16文件系统签名的偏移量
#define FAT16_SIG_OFFSET	54
//定义FAT32文件系统签名的偏移量
#define FAT32_SIG_OFFSET	82
//定义NTFS文件系统签名的偏移量
#define NTFS_SIG_OFFSET		3
	//这是FAT16文件系统的标志
	const UCHAR FAT16FLG[4] = {'F','A','T','1'};
	//这是FAT32文件系统的标志
	const UCHAR FAT32FLG[4] = {'F','A','T','3'};
	//这是NTFS文件系统的标志
	const UCHAR NTFSFLG[4] = {'N','T','F','S'};
	//返回值
	NTSTATUS ntStatus = STATUS_SUCCESS;
	//用来读取卷DBR扇区的数据缓冲区
	BYTE DBR[512] = { 0 };
	//DBR扇区有512个bytes大小
	ULONG DBRLength = 512;
	//以下是三个指针,统一指向读取的DBR数据,但是这三个指针的类型分别代表FAT16,FAT32和NTFS类型文件系统的DBR数据结构
	PDP_NTFS_BOOT_SECTOR pNtfsBootSector = (PDP_NTFS_BOOT_SECTOR)DBR;
	PDP_FAT32_BOOT_SECTOR pFat32BootSector = (PDP_FAT32_BOOT_SECTOR)DBR;
	PDP_FAT16_BOOT_SECTOR pFat16BootSector = (PDP_FAT16_BOOT_SECTOR)DBR;
	//读取的偏移量,对于DBR来说是卷的起始位置,所以偏移量为0
	LARGE_INTEGER readOffset = { 0 };
	//读取时的io操作状态
	IO_STATUS_BLOCK ios;
 	//为了同步读取所设置的同步事件
 	KEVENT Event;
 	//为了同步读取所需要构建的irp指针
 	PIRP   pIrp	= NULL;

	//下面我们首先从指定的卷设备上读取偏移量为0的一个扇区,也就是这个卷的DBR扇区,准备加以分析
 	//因为我们要同步读取,所以先初始化一个为了同步读取设置的事件
 	KeInitializeEvent(&Event, NotificationEvent, FALSE);
 	//构造一个irp用来发给卷设备来读取信息
 	pIrp = IoBuildAsynchronousFsdRequest(
 		IRP_MJ_READ,
 		DevObj,
 		DBR,
 		DBRLength,
 		&readOffset,
 		&ios
 		);
 	if (NULL == pIrp)
 	{
 		goto ERROUT;
 	}
 	//设置完成函数,并且将同步事件作为完成函数的参数传入
 	IoSetCompletionRoutine(
 		pIrp,
 		DPQueryVolumeInformationCompletionRoutine,
 		&Event,
 		TRUE,
 		TRUE,
 		TRUE
 		);
 	//调用目标设备去处理这个irp
 	ntStatus = IoCallDriver(DevObj, pIrp);
 	if(ntStatus = STATUS_PENDING)
 	{
 		//如果下层设备一时不能完成这个irp请求,我们就等
 		ntStatus = KeWaitForSingleObject(
 			&Event,
 			Executive,
 			KernelMode,
 			FALSE,
 			NULL
 			);
 		//将返回值设置为这个io操作的状态
 		ntStatus = pIrp->IoStatus.Status;
 		if (!NT_SUCCESS(ntStatus))
 		{
 			goto ERROUT;
 		}
 	}
	
	if (*(DWORD*)NTFSFLG == *(DWORD*)&DBR[NTFS_SIG_OFFSET])
	{
		//通过比较标志发现这个卷是一个ntfs文件系统的卷,下面根据ntfs卷的DBR定义来对各种需要获取的值进行赋值操作
		*SectorSize = (DWORD)(pNtfsBootSector->BytesPerSector);
		*ClusterSize = (*SectorSize) * (DWORD)(pNtfsBootSector->SectorsPerCluster);    
		TotalSize->QuadPart = (LONGLONG)(*SectorSize) * (LONGLONG)pNtfsBootSector->TotalSectors;
	}
	else if (*(DWORD*)FAT32FLG == *(DWORD*)&DBR[FAT32_SIG_OFFSET])
	{
		//通过比较标志发现这个卷是一个ntfs文件系统的卷,下面根据ntfs卷的DBR定义来对各种需要获取的值进行赋值操作
		*SectorSize = (DWORD)(pFat32BootSector->BytesPerSector);
		*ClusterSize = (*SectorSize) * (DWORD)(pFat32BootSector->SectorsPerCluster);    
		TotalSize->QuadPart = (LONGLONG)(*SectorSize) * 
			(LONGLONG)(pFat32BootSector->LargeSectors + pFat32BootSector->Sectors);
	}
	else if (*(DWORD*)FAT16FLG == *(DWORD*)&DBR[FAT16_SIG_OFFSET])
	{
		//通过比较标志发现这个卷是一个ntfs文件系统的卷,下面根据ntfs卷的DBR定义来对各种需要获取的值进行赋值操作
		*SectorSize = (DWORD)(pFat16BootSector->BytesPerSector);
		*ClusterSize = (*SectorSize) * (DWORD)(pFat16BootSector->SectorsPerCluster);    
		TotalSize->QuadPart = (LONGLONG)(*SectorSize) * 
			(LONGLONG)(pFat16BootSector->LargeSectors + pFat16BootSector->Sectors);
	}
	else
	{
		//走到这里,可能是其它任何文件系统,但是不是windows认识的文件系统,我们统一返回错
		ntStatus = STATUS_UNSUCCESSFUL;
	}
ERROUT:
 	if (NULL != pIrp)
 	{
 		IoFreeIrp(pIrp);
 	}
	return ntStatus;
}