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.