IRP_MJ_CREATE (FS 和 FS 筛选器)
发送时
I/O 管理器在以下情况下发送IRP_MJ_CREATE请求:
- 正在创建新文件或目录。
- 正在打开现有文件、设备、目录或卷。
通常,此 IRP 是代表已调用 Microsoft Win32 函数(例如 CreateFile )的用户模式应用程序发送的,或者代表调用 了 IoCreateFile、 IoCreateFileSpecifyDeviceObjectHint、 ZwCreateFile 或 ZwOpenFile 等函数的内核模式组件发送。
如果创建请求成功完成,应用程序或内核模式组件将收到文件对象的句柄。
操作:文件系统驱动程序
如果目标设备对象是文件系统的控制设备对象,则文件系统驱动程序的调度例程必须在将 Irp-IoStatus.Status 和 Irp-IoStatus.Information>> 设置为适当的值后完成 IRP 并返回相应的 NTSTATUS 值。
否则,文件系统驱动程序应处理创建请求。
操作:旧版文件系统筛选器驱动程序
如果目标设备对象是筛选器驱动程序的控制设备对象,则筛选器驱动程序的调度例程必须在将Irp-IoStatus.Status 和 Irp-IoStatus.Information>> 设置为适当的值后完成 IRP 并返回相应的 NTSTATUS 值。
否则,筛选器驱动程序应执行任何所需的处理。 然后,根据筛选器的性质,它应完成 IRP 或将其向下传递给堆栈上下一个较低的驱动程序。
通常,筛选器驱动程序不应返回 STATUS_PENDING 以响应 IRP_MJ_CREATE。 但是,如果较低级别的驱动程序返回 STATUS_PENDING,则筛选器驱动程序应将此状态值传递到驱动程序链上。
文件系统筛选器驱动程序编写者应注意 IoCreateStreamFileObject 会导致 将IRP_MJ_CLEANUP 请求发送到卷的文件系统驱动程序堆栈。 由于文件系统通常会创建流文件对象作为 IRP_MJ_CREATE以外的操作的副作用,因此筛选器驱动程序很难可靠地检测流文件对象的创建。 因此,筛选器驱动程序应接收 IRP_MJ_CLEANUP ,并 IRP_MJ_CLOSE 以前看不见的文件对象请求。 对于 IoCreateStreamFileObjectLite,不会发送 IRP_MJ_CLEANUP 请求。
当旧筛选器驱动程序在创建后回调中重新发出创建请求时,它们必须释放并设置与其重分析点关联的缓冲区, (辅助缓冲区) 为 NULL。 如果旧版筛选器驱动程序未释放此缓冲区并将其设置为 NULL,则该驱动程序将泄漏内存。 微筛选器驱动程序不必执行此操作,因为筛选器管理器会为它们执行此操作。
参数
文件系统或旧筛选器驱动程序使用给定的 IRP 调用 IoGetCurrentIrpStackLocation ,以获取指向 IRP 中自己的堆栈位置的指针。 在以下参数中, Irp 指向 IRP , 而 IrpSp 指向 IO_STACK_LOCATION。 驱动程序可以使用 IRP 和 IRP 堆栈位置的以下成员中设置的信息来处理创建请求。
DeviceObject 是指向目标设备对象的指针。
Irp->如果文件对象表示具有扩展属性的文件,则 AssociatedIrp.SystemBuffer 指向 FILE_FULL_EA_INFORMATION结构化缓冲区。 否则,此成员将设置为 NULL。
Irp->标志 设置为此请求的以下标志:
- IRP_CREATE_OPERATION
- IRP_DEFER_IO_COMPLETION
- IRP_SYNCHRONOUS_API
Irp->RequestorMode 指示请求操作的进程( KernelMode 或 UserMode )的执行 模式。 如果设置了SL_FORCE_ACCESS_CHECK标志,则必须执行访问检查,即使 Irp-RequestorMode> 为 KernelMode 也是如此。
Irp->IoStatus 指向一个 IO_STATUS_BLOCK 结构,该结构接收最终完成状态和有关所请求操作的信息。 文件系统将此结构的 Information 成员设置为以下值之一:
- FILE_CREATED
- FILE_DOES_NOT_EXIST
- FILE_EXISTS
- FILE_OPENED
- FILE_OVERWRITTEN
- FILE_SUPERSEDED
Irp->Overlay.AllocationSize 是文件的初始分配大小(以字节为单位)。 除非正在创建、覆盖或取代文件,否则非零值不起作用。
IrpSp->FileObject 指向 I/O 管理器为表示要创建或打开的文件而创建的文件对象。 当文件系统处理IRP_MJ_CREATE请求时,它将此文件对象中的 FsContext 和可能为 FsContext2 字段设置为特定于文件系统的值。 因此,在文件系统处理创建请求之前, FsContext 和 FsContext2 字段的值不能被视为有效。 有关详细信息,请参阅 文件流、流上下文和 Per-Stream 上下文。
FltCancelFileOpen 和 IoCancelFileOpen 在文件对象的 Flags 字段中设置FO_FILE_OPEN_CANCELLED标志。 设置此标志表示已取消IRP_MJ_CREATE请求,并将为此文件对象发出 IRP_MJ_CLOSE 请求。 取消创建请求后,无法重新发出该请求。
IrpSp-FileObject> 参数包含指向 RelatedFileObject 字段的指针,该字段也是FILE_OBJECT结构。 FILE_OBJECT 结构的 RelatedFileObject 字段用于指示给定文件已相对于已打开的文件对象打开。 这通常表示相对文件是目录,但基于流的文件可能相对于已存在的文件流打开。 FILE_OBJECT 结构的 RelatedFileObject 字段仅在处理IRP_MJ_CREATE期间有效。
IrpSp->标志 可以设置为以下一个或多个值:
标志 含义 SL_FORCE_ACCESS_CHECK 0x01 如果设置了此标志,则即使 IRP-RequestorMode> 的值为 KernelMode,也必须执行访问检查。 SL_OPEN_PAGING_FILE 0x02 如果设置了此标志,则该文件是分页文件。 SL_OPEN_TARGET_DIRECTORY 0x04 如果设置了此标志,则应打开文件的父目录。 SL_STOP_ON_SYMLINK 0x08 如果设置了此标志,I/O 管理器对交汇点和符号链接的自动遍历将被禁止,从而导致打开交汇点和符号链接返回STATUS_REPARSE。 SL_IGNORE_READONLY_ATTRIBUTE 0x40 如果设置了此标志,则允许使用 FILE_DELETE_ON_CLOSE 选项创建只读文件。 此选项会导致在关闭句柄时删除文件。 SL_CASE_SENSITIVE 0x80 如果已设置,文件名比较应区分大小写。 IrpSp->MajorFunction 设置为 IRP_MJ_CREATE。
IrpSp->Parameters.Create.EaLength 是 Irp-AssociatedIrp.SystemBuffer> 中缓冲区的大小(以字节为单位)。 如果 Irp*->AssociatedIrp.SystemBuffer 的值为 NULL,则此成员必须为零。
IrpSp->Parameters.Create.FileAttributes 是创建或打开文件时要应用的属性标志的位掩码。 仅当创建、取代文件或在某些情况下被覆盖时,才会应用显式指定的属性。 默认情况下,此值为FILE_ATTRIBUTE_NORMAL,任何其他标志或兼容标志的 OR 组合都可以替代此值。 此成员对应于 IoCreateFileSpecifyDeviceObjectHint的 FileAttributes 参数。
IrpSp->Parameters.Create.Options 是标志的位掩码,指定创建或打开文件时要应用的选项,以及文件已存在时要执行的操作。
此参数的高 8 位对应于 IoCreateFileSpecifyDeviceObjectHint 的 Disposition 参数。
此成员的低 24 位对应于 IoCreateFileSpecifyDeviceObjectHint 的 CreateOptions 参数。 执行文件扫描 ((如防病毒程序) )的文件系统筛选器和微筛选器驱动程序应特别注意FILE_COMPLETE_IF_OPLOCKED标志。 如果设置了此标志,则筛选器不得阻止或以其他方式延迟IRP_MJ_CREATE操作。
如果在预创建 (创建调度) 路径中设置了FILE_COMPLETE_IF_OPLOCKED标志,则筛选器不得启动以下任何类型的操作,因为它们可能会导致 oplock 中断:
- IRP_MJ_CLEANUP
- IRP_MJ_CREATE
- IRP_MJ_FILE_SYSTEM_CONTROL
- IRP_MJ_FLUSH_BUFFERS
- IRP_MJ_LOCK_CONTROL
- IRP_MJ_READ
- IRP_MJ_SET_INFORMATION
- IRP_MJ_WRITE
如果筛选器或微筛选器无法遵循FILE_COMPLETE_IF_OPLOCKED标志,则必须使用 STATUS_SHARING_VIOLATION 完成IRP_MJ_CREATE请求。
如果在完成 (创建后) 路径中设置了FILE_COMPLETE_IF_OPLOCKED标志,则筛选器应检查文件系统是否已将 Irp-IoStatus.Status> 设置为STATUS_OPLOCK_BREAK_IN_PROGRESS状态值。 如果未设置此状态值,筛选器可以安全地对文件启动上述操作之一。 如果设置了此状态值,则表明操作锁尚未中断,并且筛选器不得启动任何可能导致 oplock 中断的操作。 因此,筛选器必须推迟对文件执行上述所有操作,直到满足以下条件之一:
- oplock 的所有者向文件系统发送FSCTL_OPLOCK_BREAK_ACKNOWLEDGE请求。
- 筛选器或微筛选器以外的系统组件向文件系统发送 I/O 请求,该请求必须等待操作锁中断完成, (例如IRP_MJ_READ或IRP_MJ_WRITE) 。 筛选器或微筛选器可以从此新操作的调度 (或预操作回调) 例程启动上述操作之一,因为调度或预操作回调例程将进入等待状态,直到操作锁中断完成。
*IrpSp->Parameters.Create.SecurityContext-AccessState> 指向包含对象的主题上下文、授予的访问权限类型和剩余所需访问类型的ACCESS_STATE结构。
IrpSp->Parameters.Create.SecurityContext-DesiredAccess> 是一个ACCESS_MASK结构,用于指定为文件请求的访问权限。 有关详细信息,请参阅 IoCreateFileSpecifyDeviceObjectHint的 DesiredAccess 参数的说明。
IrpSp->Parameters.Create.ShareAccess 是为文件请求的共享访问权限的位掩码。 如果此成员为零,则请求独占访问权限。 有关详细信息,请参阅 IoCreateFileSpecifyDeviceObjectHint 的 ShareAccess 参数的说明。