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; }
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; }
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; }
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; }
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; }
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; }