2.1.5.1.2 Open of an Existing File

Files that require knowledge of extended attributes cannot be opened by applications that do not understand extended attributes. If CreateOptions.FILE_NO_EA_KNOWLEDGE is set and (StreamTypeToOpen is DirectoryStream or (StreamTypeToOpen is DataStream and StreamNameToOpen is empty)) and File.ExtendedAttributes contains an ExistingEa where ExistingEa.Flags.FILE_NEED_EA is set, the operation MUST be failed with STATUS_ACCESS_DENIED.

Pseudocode for the operation is as follows:

  • If CreateOptions.FILE_OPEN_REPARSE_POINT is not set and File.ReparsePointTag is not empty, then the operation MUST be failed with Status set to STATUS_REPARSE and ReparsePointData set to File.ReparsePointData.

  • If StreamTypeToOpen is DirectoryStream:

    • If CreateDisposition is FILE_OPEN or FILE_OPEN_IF then:

      • Perform access checks as described in section 2.1.5.1.2.1. If this fails with STATUS_SHARING_VIOLATION:

        • If Open.Stream.Oplock is not empty and Open.Stream.Oplock.State contains HANDLE_CACHING, the object store MUST check for an oplock break according to the algorithm in section 2.1.4.12, with input values as follows:

          • Open equal to this operation's Open

          • Oplock equal to Open.Stream.Oplock

          • Operation equal to "OPEN_BREAK_H"

        • Perform access checks as described in section 2.1.5.1.2.1. If this fails, the request MUST be failed with the same status.

      • ElseIf this fails with any other status code:

        • The request MUST be failed with the same status.

      • EndIf

      • Perform sharing access checks as described in section 2.1.5.1.2.2. If this fails with STATUS_SHARING_VIOLATION:

        • If Open.Stream.Oplock is not empty and Open.Stream.Oplock.State contains HANDLE_CACHING, the object store MUST check for an oplock break according to the algorithm in section 2.1.4.12, with input values as follows:

          • Open equal to this operation's Open

          • Oplock equal to Open.Stream.Oplock

        • Perform sharing access checks as described in section 2.1.5.1.2.2. If this fails, the request MUST be failed with the same status.

      • ElseIf this fails with any other status code:

        • The request MUST be failed with the same status.

      • EndIf

      • If Open.File.OpenList is empty, Open.SharingMode does not contain FILE_SHARE_READ, and AccessCheck(SecurityContext, File.SecurityDescriptor, FILE_GENERIC_WRITE) returns FALSE:

        • If CreateOptions.FILE_DISALLOW_EXCLUSIVE is TRUE:<55>

          • The operation MUST be failed with STATUS_ACCESS_DENIED.

        • Else:

          • The object store MUST set Open.SharingMode.FILE_SHARE_READ to TRUE.

        • EndIf

      • EndIf

      • Set CreateAction to FILE_OPENED.

    • Else:

      • // Existing directories cannot be overwritten/superseded.

      • If File == File.Volume.RootDirectory, then the operation MUST be failed with STATUS_ACCESS_DENIED, else the operation MUST be failed with STATUS_OBJECT_NAME_COLLISION.

    • EndIf

  • Else if StreamTypeToOpen is DataStream:

    • The object store MUST search File.StreamList for a DataStream with Stream.Name matching StreamNameToOpen. If IsCaseInsensitive is TRUE, then the search MUST be case-insensitive; otherwise it MUST be case-sensitive.

    • If Stream was found:

      • Set Open.Stream to Stream.

      • If CreateDisposition is FILE_CREATE, then the operation MUST be failed with STATUS_OBJECT_NAME_COLLISION.

      • If CreateDisposition is FILE_OPEN or FILE_OPEN_IF:

        • If Open.Stream.Oplock is not empty and Open.Stream.Oplock.State contains BATCH_OPLOCK, the object store MUST check for an oplock break according to the algorithm in section 2.1.4.12, with input values as follows:

          • Open equal to this operation's Open

          • Oplock equal to Open.Stream.Oplock

          • Operation equal to "OPEN"

          • OpParams containing two members:

            • DesiredAccess equal to this operation's DesiredAccess

            • CreateDisposition equal to this operation's CreateDisposition

        • Perform access checks as described in section 2.1.5.1.2.1. If this fails with STATUS_SHARING_VIOLATION:

          • If Open.Stream.Oplock is not empty and Open.Stream.Oplock.State contains HANDLE_CACHING, the object store MUST check for an oplock break according to the algorithm in section 2.1.4.12, with input values as follows:

            • Open equal to this operation's Open

            • Oplock equal to Open.Stream.Oplock

            • Operation equal to "OPEN_BREAK_H"

          • Perform access checks as described in section 2.1.5.1.2.1. If this fails, the request MUST be failed with the same status.

        • ElseIf this fails with any other status code:

          • The request MUST be failed with the same status.

        • EndIf

        • Perform sharing access checks as described in section 2.1.5.1.2.2. If this fails with STATUS_SHARING_VIOLATION:

          • If Open.Stream.Oplock is not empty and Open.Stream.Oplock.State contains HANDLE_CACHING, the object store MUST check for an oplock break according to the algorithm in section 2.1.4.12, with input values as follows:

            • Open equal to this operation's Open

            • Oplock equal to Open.Stream.Oplock

            • Operation equal to "OPEN_BREAK_H"

          • Perform sharing access checks as described in section 2.1.5.1.2.2. If this fails, the request MUST be failed with the same status.

        • ElseIf this fails with any other status code:

          • The request MUST be failed with the same status.

        • EndIf

        • Set CreateAction to FILE_OPENED.

      • Else:

        • If File.Volume.IsReadOnly is TRUE, the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED.

        • If Open.Stream.Oplock is not empty and Open.Stream.Oplock.State contains BATCH_OPLOCK, the object store MUST check for an oplock break according to the algorithm in section 2.1.4.12, with input values as follows:

          • Open equal to this operation's Open

          • Oplock equal to Open.Stream.Oplock

          • Operation equal to "OPEN"

          • OpParams containing two members:

            • DesiredAccess equal to this operation's DesiredAccess

            • CreateDisposition equal to this operation's CreateDisposition

        • If Stream.Name is empty:

          • If File.FileAttributes.FILE_ATTRIBUTE_HIDDEN is TRUE and DesiredFileAttributes.FILE_ATTRIBUTE_HIDDEN is FALSE, then the operation MUST be failed with STATUS_ACCESS_DENIED.

          • If File.FileAttributes.FILE_ATTRIBUTE_SYSTEM is TRUE and DesiredFileAttributes.FILE_ATTRIBUTE_SYSTEM is FALSE, then the operation MUST be failed with STATUS_ACCESS_DENIED.

          • Set DesiredFileAttributes.FILE_ATTRIBUTE_ARCHIVE to TRUE.

          • Set DesiredFileAttributes.FILE_ATTRIBUTE_NORMAL to FALSE.

          • Set DesiredFileAttributes.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED to FALSE.

          • If File.FileAttributes.FILE_ATTRIBUTE_ENCRYPTED is TRUE, then set DesiredFileAttributes.FILE_ATTRIBUTE_ENCRYPTED to TRUE.

          • If Open.HasRestoreAccess is TRUE, then the object store MUST set Open.GrantedAccess.FILE_WRITE_EA to TRUE. Otherwise, the object store MUST set Open.RemainingDesiredAccess.FILE_WRITE_EA to TRUE.

          • If Open.HasRestoreAccess is TRUE, then the object store MUST set Open.GrantedAccess.FILE_WRITE_ATTRIBUTES to TRUE. Otherwise, the object store MUST set Open.RemainingDesiredAccess.FILE_WRITE_ATTRIBUTES to TRUE.

        • EndIf

        • If CreateDisposition is FILE_SUPERSEDE:

          • If Open.HasRestoreAccess is TRUE, then the object store MUST set Open.GrantedAccess.DELETE to TRUE. Otherwise, the object store MUST set Open.RemainingDesiredAccess.DELETE to TRUE.

        • Else:

          • If Open.HasRestoreAccess is TRUE, then the object store MUST set Open.GrantedAccess.FILE_WRITE_DATA to TRUE. Otherwise, the object store MUST set Open.RemainingDesiredAccess.FILE_WRITE_DATA to TRUE.

        • EndIf

        • Open.RemainingDesiredAccess &= ~Open.GrantedAccess

        • Perform access checks as described in section 2.1.5.1.2.1. If this fails with STATUS_SHARING_VIOLATION:

          • If Open.Stream.Oplock is not empty and Open.Stream.Oplock.State contains HANDLE_CACHING, the object store MUST check for an oplock break according to the algorithm in section 2.1.4.12, with input values as follows:

          • Open equal to this operation's Open

          • Oplock equal to Open.Stream.Oplock

          • Operation equal to "OPEN_BREAK_H"

          • Perform access checks as described in section 2.1.5.1.2.1. If this fails, the request MUST be failed with the same status.

        • ElseIf this fails with any other status code:

          • The request MUST be failed with the same status.

        • EndIf

        • Perform sharing access checks as described in section 2.1.5.1.2.2. If this fails with STATUS_SHARING_VIOLATION:

          • If Open.Stream.Oplock is not empty and Open.Stream.Oplock.State contains HANDLE_CACHING, the object store MUST check for an oplock break according to the algorithm in section 2.1.4.12, with input values as follows:

            • Open equal to this operation's Open

            • Oplock equal to Open.Stream.Oplock

            • Operation equal to "OPEN_BREAK_H"

          • Perform sharing access checks as described in section 2.1.5.1.2.2. If this fails, the request MUST be failed with the same status.

        • ElseIf this fails with any other status code:

          • The request MUST be failed with the same status.

        • EndIf

        • Note that the file has been modified as specified in section 2.1.4.17 with Open equal to Open.

        • If CreateDisposition is FILE_SUPERSEDE, the object store MUST set CreateAction to FILE_SUPERSEDED; otherwise, it MUST set CreateAction to FILE_OVERWRITTEN.

      • EndIf

    • Else: // Stream not found.

      • If CreateDisposition is FILE_OPEN or FILE_OVERWRITE, the operation MUST be failed with STATUS_OBJECT_NAME_NOT_FOUND.

      • If Open.GrantedAccess.FILE_WRITE_DATA is not set and Open.RemainingDesiredAccess.FILE_WRITE_DATA is not set:

        • If Open.HasRestoreAccess is TRUE, then the object store MUST set Open.GrantedAccess.FILE_WRITE_DATA to TRUE; otherwise, the object store MUST set Open.RemainingDesiredAccess.FILE_WRITE_DATA to TRUE.

      • EndIf

      • Perform access checks as described in section 2.1.5.1.2.1. If this fails, the request MUST be failed with the same status.

      • If File.Volume.IsReadOnly is TRUE, the operation MUST be failed with STATUS_MEDIA_WRITE_PROTECTED.

      • Update File.LastChangeTime to the current time.

      • Set File.FileAttributes.FILE_ATTRIBUTE_ARCHIVE to TRUE.

      • Build a new Stream object with all fields initially set to zero.

      • Set Stream.StreamType to DataStream.

      • Set Stream.Name to StreamNameToOpen.

      • Set Stream.File to File.

      • Add Stream to File.StreamList.

      • Set Open.Stream to Stream.

      • Set CreateAction to FILE_CREATED.

    • EndIf.

  • Else: // StreamTypeToOpen is ViewIndexStream

    • // Note that when StreamTypeToOpen is ViewIndexStream, the stream always exists in the file

    • // Open.Stream.StreamType is ViewIndexStream.

  • EndIf

  • If the object store implements encryption:

    • If (CreateAction is FILE_OVERWRITTEN or FILE_SUPERSEDED) and (Stream.Name is empty) and (DesiredFileAttributes.FILE_ATTRIBUTE_ENCRYPTED is TRUE) and (File.FileAttributes.FILE_ATTRIBUTE_ENCRYPTED is FALSE), then:

      • If File.OpenList is non-empty, then the operation MUST be failed with STATUS_SHARING_VIOLATION.

    • EndIf

  • EndIf

  • If CreateAction is one of FILE_OVERWRITTEN or FILE_SUPERSEDED, then:

    • If Stream.Name is empty:

      • Set File.FileAttributes to DesiredFileAttributes.

    • EndIf

  • EndIf

  • If the object store implements encryption and File.FileAttributes.FILE_ATTRIBUTE_ENCRYPTED is TRUE:

    • If CreateAction is FILE_OPENED:

      • If Stream.IsEncrypted is TRUE:

        • If UserCertificate is empty, the operation MUST be failed with STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE.

        • If UserCertificate is not in File.UserCertificateList, the operation MUST be failed with STATUS_ACCESS_DENIED.

      • EndIf

    • Else:  // we are creating, overwriting, or superseding a stream

      • If UserCertificate is empty, the operation MUST be failed with STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE.

      • If Stream.Name is empty:

        • If File.UserCertificateList is empty, insert UserCertificate into File.UserCertificateList.

      • Else:

        • If UserCertificate is not in File.UserCertificateList, the operation MUST be failed with STATUS_ACCESS_DENIED.

      • EndIf

      • If File.FileType is DataFile, set Stream.IsEncrypted to TRUE.

    • EndIf

  • EndIf

  • If CreateAction is one of FILE_CREATED, FILE_OVERWRITTEN or FILE_SUPERSEDED, then:

    • The object store MUST set FilterMatch to a set of flags capturing modifications to the existing file's persistent attributes performed during the Open operation.

    • Send directory change notification as specified in section 2.1.4.1, with Volume equal to File.Volume, Action equal to FILE_ACTION_MODIFIED, FilterMatch equal to FilterMatch, and FileName equal to Open.FileName.

  • EndIf

  • If CreateAction is FILE_CREATED, then the object store MUST insert Stream into File.StreamList.

  • If File is not in File.Volume.OpenFileList, the object store MUST insert it.

  • The object store MUST insert Open into File.OpenList.

  • If Stream.Name is not empty:

    • If CreateAction is FILE_CREATED:

      • Send directory change notification as specified in section 2.1.4.1, with Volume equal to File.Volume, Action equal to FILE_ACTION_ADDED_STREAM, FilterMatch equal to FILE_NOTIFY_CHANGE_STREAM_NAME, and FileName equal to Open.FileName + ":" + Stream.Name.

    • If CreateAction is one of FILE_OVERWRITTEN or FILE_SUPERSEDED:

      • Send directory change notification as specified in section 2.1.4.1, with Volume equal to File.Volume, Action equal to FILE_ACTION_MODIFIED_STREAM, FilterMatch equal to (FILE_NOTIFY_CHANGE_STREAM_SIZE | FILE_NOTIFY_CHANGE_STREAM_WRITE), and FileName equal to Open.FileName + ":" + Stream.Name.

    • EndIf

  • EndIf

  • The object store SHOULD update the duplicated information as specified in section 2.1.4.18 with Link equal to Open.Link.

  • The object store MUST return:

    • Status set to STATUS_SUCCESS.

    • CreateAction set to FILE_OPENED.

    • The Open object created previously.