专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »编程综合 » reactos:reactos操作系统实现(87) »正文

reactos:reactos操作系统实现(87)

来源: 发布时间:星期一, 2009年9月28日 浏览:0次 评论:0


  应用对设备I/O进行Win32这个由I/O系统服务接收然后I/O管理器从这个请求构造个合适I/O请求包(IRP)那么I/O管理器是如何样创建这个I/O请求包(IRP)呢?又是如何样传送给驱动呢?我们带着这两个问题来分析下面实现文件读取代码如下:

#001  NTSTATUS
#002  NTAPI
#003  NtReadFile(IN HANDLE FileHandle,
#004             IN HANDLE Event OPTIONAL,
#005             IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
#006             IN PVOID ApcContext OPTIONAL,
#007             OUT PIO_STATUS_BLOCK IoStatusBlock,
#008             OUT PVOID Buffer,
#009             IN ULONG Length,
#010             IN PLARGE_INTEGER ByteOff OPTIONAL,
#011             IN PULONG Key OPTIONAL)
#012  {
#013      NTSTATUS Status = STATUS_SUCCESS;
#014      PFILE_OBJECT FileObject;
#015      PIRP Irp;
#016      PDEVICE_OBJECT DeviceObject;
#017      PIO_STACK_LOCATION StackPtr;
#018      KPROCESSOR_MODE PreviousMode = KeGetPreviousMode;
#019      PKEVENT EventObject = NULL;
#020      LARGE_INTEGER CapturedByteOff;
#021      ULONG CapturedKey = 0;
#022      BOOLEAN Synchronous = FALSE;
#023      PMDL Mdl;
#024      PAGED_CODE;
#025      CapturedByteOff.QuadPart = 0;
#026      IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
#027


  检查是否在用户模式

#028      /* Validate User-Mode Buffers */
#029      (PreviousMode != KernelMode)
#030      {


  使用SEH机制以便截取异常

#031          _SEH2_TRY
#032          {


  检测状态块

#033              /* Probe the status block */
#034              ProbeForWriteIoStatusBlock(IoStatusBlock);
#035 


  检查读取缓冲区

#036              /* Probe the read buffer */
#037              ProbeForWrite(Buffer, Length, 1);
#038 
#039              /* Check  we got a  off */
#040               (ByteOff)
#041              {
#042                  /* Capture and probe it */
#043                  CapturedByteOff = ProbeForReadLargeInteger(ByteOff);
#044              }
#045 
#046              /* Capture and probe the key */
#047               (Key) CapturedKey = ProbeForReadUlong(Key);
#048          }
#049          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
#050          {
#051              /* Get the exception code */
#052              Status = _SEH2_GetExceptionCode;
#053          }
#054          _SEH2_END;
#055 
#056          /* Check for probe failure */
#057           (!NT_SUCCESS(Status))  Status;
#058      }
#059      
#060      {
#061          /* Kernel mode: capture directly */
#062           (ByteOff) CapturedByteOff = *ByteOff;
#063           (Key) CapturedKey = *Key;
#064      }
#065 


  获取文件对象

#066      /* Get File Object */
#067      Status = ObReferenceObjectByHandle(FileHandle,
#068                                         FILE_READ_DATA,
#069                                         IoFileObjectType,
#070                                         PreviousMode,
#071                                         (PVOID*)&FileObject,
#072                                         NULL);
#073       (!NT_SUCCESS(Status))  Status;
#074 


  检查事件是否响应

#075      /* Check for event */
#076       (Event)
#077      {
#078          /* Reference it */
#079          Status = ObReferenceObjectByHandle(Event,
#080                                             EVENT_MODIFY_STATE,
#081                                             ExEventObjectType,
#082                                             PreviousMode,
#083                                             (PVOID*)&EventObject,
#084                                             NULL);
#085           (!NT_SUCCESS(Status))
#086          {
#087              /* Fail */
#088              ObDereferenceObject(FileObject);
#089               Status;
#090          }
#091 
#092          /* Otherwise re the event */
#093          KeClearEvent(EventObject);
#094      }
#095 


  检查是否使用同步I/O方式

#096      /* Check  we should use Sync IO or not */
#097       (FileObject->Flags & FO_SYNCHRONOUS_IO)
#098      {


  这里是使用同步模式

#099          /* Lock the file object */
#100          IopLockFileObject(FileObject);
#101 
#102          /* Check  we don't have a  off avilable */
#103           (!(ByteOff) ||
#104              ((CapturedByteOff.u.LowPart  FILE_USE_FILE_POINTER_POSITION) &&
#105               (CapturedByteOff.u.HighPart  -1)))
#106          {
#107              /* Use the Current Byte Off instead */
#108              CapturedByteOff = FileObject->CurrentByteOff;
#109          }
#110 
#111          /* Remember we are sync */
#112          Synchronous = TRUE;
#113      }
#114        (!(ByteOff) &&
#115               !(FileObject->Flags & (FO_NAMED_PIPE | FO_MAILSLOT)))
#116      {


  非法文件对象

#117          /* Otherwise, this was async I/O without a  off, so fail */
#118           (EventObject) ObDereferenceObject(EventObject);
#119          ObDereferenceObject(FileObject);
#120           STATUS_INVALID_PARAMETER;
#121      }
#122 


  从文件里获取设备对象

#123      /* Get the device object */
#124      DeviceObject = IoGetRelatedDeviceObject(FileObject);
#125 
#126      /* Clear the File Object's event */
#127      KeClearEvent(&FileObject->Event);
#128 


  分配个读取文件请求包(IRP)

#129      /* Allocate the IRP */
#130      Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
#131       (!Irp)  IopCleanupFailedIrp(FileObject, NULL, NULL);
#132 


  设置IRP属性

#133      /* Set the IRP */
#134      Irp->Tail.Overlay.OriginalFileObject = FileObject;
#135      Irp->Tail.Overlay.Thread = PsGetCurrentThread;
#136      Irp->RequestorMode = PreviousMode;
#137      Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
#138      Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
#139      Irp->UserIosb = IoStatusBlock;
#140      Irp->UserEvent = EventObject;
#141      Irp->PendingReturned = FALSE;
#142      Irp->Cancel = FALSE;
#143      Irp->CancelRoutine = NULL;
#144      Irp->AssociatedIrp.Buffer = NULL;
#145      Irp->MdlAddress = NULL;
#146 


  设置IRP

#147      /* Set the Stack Data */
#148      StackPtr = IoGetNextIrpStackLocation(Irp);
#149      StackPtr->MajorFunction = IRP_MJ_READ;
#150      StackPtr->FileObject = FileObject;
#151      StackPtr->Parameters.Read.Key = CapturedKey;
#152      StackPtr->Parameters.Read.Length = Length;
#153      StackPtr->Parameters.Read.ByteOff = CapturedByteOff;
#154 


  检查设备对象是否使用缓冲I/O方式还是使用直接I/O方式

#155      /* Check  this is buffered I/O */
#156       (DeviceObject->Flags & DO_BUFFERED_IO)
#157      {


  使用缓冲I/O方式就分配非分页内存

#158          /* Check  we have a buffer length */
#159           (Length)
#160          {
#161              /* Enter SEH */
#162              _SEH2_TRY
#163              {
#164                  /* Allocate a buffer */
#165                  Irp->AssociatedIrp.Buffer =
#166                      ExAllocatePoolWithTag(NonPagedPool,
#167                                            Length,
#168                                            TAG_SYSB);
#169              }
#170              _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
#171              {
#172                  /* Allocating failed, clean up */
#173                  IopCleanupAfterException(FileObject, Irp, EventObject, NULL);
#174                  Status = _SEH2_GetExceptionCode;
#175              }
#176              _SEH2_END;
#177               (!NT_SUCCESS(Status))  Status;
#178 
#179              /* Set the buffer and flags */
#180              Irp->UserBuffer = Buffer;
#181              Irp->Flags = (IRP_BUFFERED_IO |
#182                            IRP_DEALLOCATE_BUFFER |
#183                            IRP_INPUT_OPERATION);
#184          }
#185          
#186          {
#187              /* Not reading anything */
#188              Irp->Flags = IRP_BUFFERED_IO | IRP_INPUT_OPERATION;
#189          }
#190      }
#191        (DeviceObject->Flags & DO_DIRECT_IO)
#192      {


  使用直接I/O方式就创建内存描述符列表

#193          /* Check  we have a buffer length */
#194           (Length)
#195          {
#196              _SEH2_TRY
#197              {
#198                  /* Allocate an MDL */
#199                  Mdl = IoAllocateMdl(Buffer, Length, FALSE, TRUE, Irp);
#200                  MmProbeAndLockPages(Mdl, PreviousMode, IoWriteAccess);
#201              }
#202              _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
#203              {
#204                  /* Allocating failed, clean up */
#205                  IopCleanupAfterException(FileObject, Irp, EventObject, NULL);
#206                  Status = _SEH2_GetExceptionCode;
#207                  _SEH2_YIELD( Status);
#208              }
#209              _SEH2_END;
#210 
#211          }
#212 
#213          /* No allocation flags */
#214          Irp->Flags = 0;
#215      }
#216      
#217      {
#218          /* No allocation flags, and use the buffer directly */
#219          Irp->Flags = 0;
#220          Irp->UserBuffer = Buffer;
#221      }
#222 


  设置读取标志

#223      /* Now  the deferred read flags */
#224      Irp->Flags |= (IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION);
#225  # 0
#226      /* FIXME: VFAT SUCKS */
#227       (FileObject->Flags & FO_NO_INTERMEDIATE_BUFFERING) Irp->Flags |= IRP_NOCACHE;
#228  #end
#229 


  IopPerformSynchronousRequest把IRP发送给过滤驱动或者目标驱动

#230      /* Perform the call */
#231       IopPerformSynchronousRequest(DeviceObject,
#232                                          Irp,
#233                                          FileObject,
#234                                          TRUE,
#235                                          PreviousMode,
#236                                          Synchronous,
#237                                          IopReadTransfer);
#238  }
#239 


  下面继续分析写文件操作就可以知道写文件时如何样发送I/O请求包实现代码如下:

#001  NTSTATUS
#002  NTAPI
#003  NtWriteFile(IN HANDLE FileHandle,
#004              IN HANDLE Event OPTIONAL,
#005              IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
#006              IN PVOID ApcContext OPTIONAL,
#007              OUT PIO_STATUS_BLOCK IoStatusBlock,
#008              IN PVOID Buffer,
#009              IN ULONG Length,
#010              IN PLARGE_INTEGER ByteOff OPTIONAL,
#011              IN PULONG Key OPTIONAL)
#012  {
#013      NTSTATUS Status = STATUS_SUCCESS;
#014      PFILE_OBJECT FileObject;
#015      PIRP Irp;
#016      PDEVICE_OBJECT DeviceObject;
#017      PIO_STACK_LOCATION StackPtr;


  获取前个内核模式

#018      KPROCESSOR_MODE PreviousMode = KeGetPreviousMode;
#019      PKEVENT EventObject = NULL;
#020      LARGE_INTEGER CapturedByteOff;
#021      ULONG CapturedKey = 0;
#022      BOOLEAN Synchronous = FALSE;
#023      PMDL Mdl;
#024      OBJECT_HANDLE_INFORMATION ObjectHandleInfo;
#025      PAGED_CODE;
#026      CapturedByteOff.QuadPart = 0;
#027      IOTRACE(IO_API_DEBUG, "FileHandle: %p\n", FileHandle);
#028 


  获取文件对象

#029      /* Get File Object */
#030      Status = ObReferenceObjectByHandle(FileHandle,
#031                                         0,
#032                                         IoFileObjectType,
#033                                         PreviousMode,
#034                                         (PVOID*)&FileObject,
#035                                         &ObjectHandleInfo);
#036       (!NT_SUCCESS(Status))  Status;
#037 


  检查是否用户模式如果是就需要使用SEH机制

#038      /* Validate User-Mode Buffers */
#039      (PreviousMode != KernelMode)
#040      {
#041          _SEH2_TRY
#042          {


  检查是否有写文件权限

#043              /*
#044               * Check  the handle has either FILE_WRITE_DATA or
#045               * FILE_APPEND_DATA granted. However,  this is a named pipe,
#046               * make sure we don't ask for FILE_APPEND_DATA as it erferes
#047               * with the FILE_CREATE_PIPE_INSTANCE access right!
#048               */
#049               (!(ObjectHandleInfo.GrantedAccess &
#050                   ((!(FileObject->Flags & FO_NAMED_PIPE) ?
#051                     FILE_APPEND_DATA : 0) | FILE_WRITE_DATA)))
#052              {
#053                  /* We failed */
#054                  ObDereferenceObject(FileObject);
#055                  _SEH2_YIELD( STATUS_ACCESS_DENIED);
#056              }
#057 


  获取状态代码块

#058              /* Probe the status block */
#059              ProbeForWriteIoStatusBlock(IoStatusBlock);
#060 
#061              /* Probe the read buffer */
#062              ProbeForRead(Buffer, Length, 1);
#063 
#064              /* Check  we got a  off */
#065               (ByteOff)
#066              {
#067                  /* Capture and probe it */
#068                  CapturedByteOff = ProbeForReadLargeInteger(ByteOff);
#069              }
#070 
#071              /* Capture and probe the key */
#072               (Key) CapturedKey = ProbeForReadUlong(Key);
#073          }
#074          _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
#075          {
#076              /* Get the exception code */
#077              Status = _SEH2_GetExceptionCode;
#078          }
#079          _SEH2_END;
#080 
#081          /* Check for probe failure */
#082           (!NT_SUCCESS(Status))  Status;
#083      }
#084      
#085      {
#086          /* Kernel mode: capture directly */
#087           (ByteOff) CapturedByteOff = *ByteOff;
#088           (Key) CapturedKey = *Key;
#089      }
#090


标签:reactos
0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: