2.1.5.1.1 Creation of a New File

Pseudocode for the operation is as follows:

  • If StreamTypeToOpen is DirectoryStream and DesiredFileAttributes.FILE_ATTRIBUTE_TEMPORARY is set, the operation MUST be failed with STATUS_INVALID_PARAMETER.

  • If DesiredFileAttributes.FILE_ATTRIBUTE_READONLY and CreateOptions.FILE_DELETE_ON_CLOSE are both set, the operation MUST be failed with STATUS_CANNOT_DELETE.

  • If Open.RemainingDesiredAccess.ACCESS_SYSTEM_SECURITY is set and Open.GrantedAccess.ACCESS_SYSTEM_SECURITY is not set and SecurityContext.PrivilegeSet does not contain "SeSecurityPrivilege", the operation MUST be failed with STATUS_ACCESS_DENIED.

  • If StreamTypeToOpen is DataStream and Open.GrantedAccess.FILE_ADD_FILE is not set and AccessCheck(SecurityContext, Open.Link.ParentFile.SecurityDescriptor, FILE_ADD_FILE) returns FALSE and Open.HasRestoreAccess is FALSE, the operation MUST be failed with STATUS_ACCESS_DENIED.

  • If StreamTypeToOpen is DirectoryStream and Open.GrantedAccess.FILE_ADD_SUBDIRECTORY is not set and AccessCheck(SecurityContext, Open.Link.ParentFile.SecurityDescriptor, FILE_ADD_SUBDIRECTORY) returns FALSE and Open.HasRestoreAccess is FALSE, the operation MUST be failed with STATUS_ACCESS_DENIED.

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

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

  • EndIf

  • Initialize UsnReason to zero.

  • Set UsnReason.USN_REASON_FILE_CREATE to TRUE.

  •  The object store MUST build a new File object with fields initialized as follows:

    • File.FileType set to DirectoryFile if StreamTypeToOpen is DirectoryStream, else it is set to DataFile.

    • File.FileId128 assigned a new value. The value chosen is implementation-specific but MUST be unique among all files present on RootOpen.File.Volume.<48>

    • File.FileId64 assigned a new value. The value chosen is implementation-specific<49> but MUST be either -1 or unique among all files present on RootOpen.File.Volume.

    • File.FileNumber assigned a new value. The value chosen is implementation-specific but MUST be unique among all files present on RootOpen.File.Volume.<50>

    • File.FileAttributes set to DesiredFileAttributes.

    • File.CreationTime, File.LastModificationTime, File.LastChangeTime, and File.LastAccessTime all initialized to the current system time.

    • File.Volume set to RootOpen.File.Volume.

    • All other fields set to zero.

  • The object store MUST build a new Link object with fields initialized as follows:

    • Link.File set to File.

    • Link.ParentFile set to ParentFile.

    • All other fields set to zero.

  • If File.FileType is DataFile and Open.IsCaseInsensitive is TRUE, and tunnel caching is implemented, the object store MUST search File.Volume.TunnelCacheList for a TunnelCacheEntry where TunnelCacheEntry.ParentFile equals Link.ParentFile and either (TunnelCacheEntry.KeyByShortName is FALSE and TunnelCacheEntry.FileName matches FileNameToOpen) or (TunnelCacheEntry.KeyByShortName is TRUE and TunnelCacheEntry.FileShortName matches FileNameToOpen). If such an entry is found, then:

    • Set File.CreationTime to TunnelCacheEntry.FileCreationTime.

      • If TunnelCacheEntry.ObjectIdInfo.ObjectId is not empty:

        • If TunnelCacheEntry.ObjectIdInfo.ObjectId is not unique on File.Volume:

          • The object store MUST construct a FILE_OBJECTID_INFORMATION structure (as specified in [MS-FSCC] section 2.4.31.1) ObjectIdInfo as follows:

            • ObjectIdInfo.FileReference set to File.FileId64.

            • ObjectIdInfo.ObjectId set to TunnelCacheEntry.ObjectIdInfo.ObjectId.

            • ObjectIdInfo.BirthVolumeId set to TunnelCacheEntry.ObjectIdInfo.BirthVolumeId.

            • ObjectIdInfo.BirthObjectId set to TunnelCacheEntry.ObjectIdInfo.BirthObjectId.

            • ObjectIdInfo.DomainId set to TunnelCacheEntry.ObjectIdInfo.DomainId.

          • Send directory change notification as specified in section 2.1.4.1, with Volume equal to File.Volume, Action equal to FILE_ACTION_ID_NOT_TUNNELLED, FilterMatch equal to FILE_NOTIFY_CHANGE_FILE_NAME, FileName equal to "\$Extend\$ObjId", NotifyData equal to ObjectIdInfo, and NotifyDataLength equal to sizeof(FILE_OBJECTID_INFORMATION).

        • Else:

          • Set File.ObjectId to TunnelCacheEntry.ObjectIdInfo.ObjectId.

          • Set File.BirthVolumeId to TunnelCacheEntry.ObjectIdInfo.BirthVolumeId.

          • Set File.BirthObjectId to TunnelCacheEntry.ObjectIdInfo.BirthObjectId.

          • Set File.DomainId to TunnelCacheEntry.ObjectIdInfo.DomainId.

          • Set UsnReason.USN_REASON_OBJECT_ID_CHANGE to TRUE.

        • EndIf

      • EndIf

    • Set Link.Name to TunnelCacheEntry.FileName.

    • Set Link.ShortName to TunnelCacheEntry.FileShortName if that name is not already in use among all names and short names in Link.ParentFile.DirectoryList.

    • Remove TunnelCacheEntry from File.Volume.TunnelCacheList.

  • Else:

    • Set Link.Name to FileNameToOpen.

  • EndIf

  • If short names are enabled and Link.ShortName is empty, then the object store MUST create a short name as follows:

    • If Link.Name is 8.3-compliant as described in [MS-FSCC] section 2.1.5.2.1:

      • Set Link.ShortName to Link.Name.

    • Else:

      • Generate a new Link.ShortName that is 8.3-compliant as described in [MS-FSCC] section 2.1.5.2.1. The string chosen is implementation-specific, but MUST be unique among all names and short names present in Link.ParentFile.DirectoryList.

    • EndIf

  • EndIf

  • The object store MUST now grant the full requested access, as shown by the following pseudocode:

    • If Open.RemainingDesiredAccess.MAXIMUM_ALLOWED is set:

      • Open.GrantedAccess |= FILE_ALL_ACCESS

    • Else:

      • Open.GrantedAccess |= Open.RemainingDesiredAccess

    • EndIf

    • Open.RemainingDesiredAccess = 0

  • The object store MUST initialize File.SecurityDescriptor.Dacl to SecurityContext.DefaultDACL. The object store SHOULD append any inheritable security information from Link.ParentFile.SecurityDescriptor to File.SecurityDescriptor.

  • The object store MUST set File.FileAttributes.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED to the value of Link.ParentFile.FileAttributes.FILE_ATTRIBUTE_NOT_CONTENT_INDEXED.

  • The object store MUST clear any attribute flags from File.FileAttributes that cannot be directly set by applications, as follows:

    • ValidSetAttributes = (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_TEMPORARY | FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)

    • File.FileAttributes &= ValidSetAttributes

  • If File.FileType is DataFile, then the object store MUST set File.FileAttributes.FILE_ATTRIBUTE_ARCHIVE.

  • If File.FileType is DirectoryFile, then the object store MUST set File.FileAttributes.FILE_ATTRIBUTE_DIRECTORY.

  • If Link.ParentFile.FileAttributes.FILE_ATTRIBUTE_ENCRYPTED or DesiredFileAttributes.FILE_ATTRIBUTE_ENCRYPTED is set, then the object store MUST set File.FileAttributes.FILE_ATTRIBUTE_ENCRYPTED.

  • If Link.ParentFile.FileAttributes.FILE_ATTRIBUTE_COMPRESSED is set and CreateOptions.FILE_NO_COMPRESSION is not set, then the object store MUST set File.FileAttributes.FILE_ATTRIBUTE_COMPRESSED.

  • If Link.ParentFile.FileAttributes.FILE_ATTRIBUTE_INTEGRITY_STREAM is set or DesiredFileAttributes.FILE_ATTRIBUTE_INTEGRITY_STREAM is set, then the object store MUST set File.FileAttributes.FILE_ATTRIBUTE_INTEGRITY_STREAM.<51>

  • If Link.ParentFile.FileAttributes.FILE_ATTRIBUTE_NO_SCRUB_DATA is set or DesiredFileAttributes.FILE_ATTRIBUTE_NO_SCRUB_DATA is set, then the object store MUST set File.FileAttributes.FILE_ATTRIBUTE_NO_SCRUB_DATA.<52>

  • If the object store implements encryption and File.FileAttributes.FILE_ATTRIBUTE_ENCRYPTED is TRUE, insert UserCertificate into File.UserCertificateList.

  • If File.FileType is DataFile and StreamNameToOpen is not empty, then the object store MUST create a default unnamed stream for the file as follows:<53>

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

    • Set DefaultStream.File to File.

    • If the object store implements encryption and File.FileAttributes.FILE_ATTRIBUTE_ENCRYPTED is TRUE, set DefaultStream.IsEncrypted to TRUE.

    • Add DefaultStream to File.StreamList.

  • EndIf

  • If StreamTypeToOpen is DataStream, then the object store MUST create a new data stream for the file as follows:<54>

    • 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.

    • If Stream.Name is not empty, set UsnReason.USN_REASON_STREAM_CHANGE to TRUE.

  • Else the object store MUST create a new directory stream as follows:

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

    • Set Stream.StreamType to DirectoryStream.

    • Set Stream.File to File.

    • Add Stream to File.StreamList.

    • Set Open.Stream to Stream.

  • EndIf

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

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

  • EndIf

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

  • The object store MUST set Open.File to File.

  • The object store MUST set Open.Link to Link.

  • The object store MUST insert Link into File.LinkList.

  • The object store MUST insert Link into Link.ParentFile.DirectoryList.

  • The object store MUST post a USN change as specified in section 2.1.4.11 with File equal to File, Reason equal to UsnReason, and FileName equal to Link.Name.

  • The object store MUST update Link.ParentFile.LastModificationTime, Link.ParentFile.LastChangeTime, and Link.ParentFile.LastAccessTime to the current system time.

  • If the Oplock member of the DirectoryStream in Link.ParentFile.StreamList (hereinafter referred to as ParentOplock) is not empty, the object store MUST check for an oplock break on the parent 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 ParentOplock

    • Operation equal to "OPEN"

    • Flags equal to "PARENT_OBJECT"

  • The object store MUST insert File into File.Volume.OpenFileList.

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

  • If File.FileType is DirectoryFile:

    • FilterMatch = FILE_NOTIFY_CHANGE_DIR_NAME

  • Else:

    • FilterMatch = FILE_NOTIFY_CHANGE_FILE_NAME

  • EndIf

  • The object store MUST send directory change notification as specified in section 2.1.4.1 with Volume equal to File.Volume, Action equal to FILE_ACTION_ADDED, FilterMatch equal to FilterMatch, and FileName equal to Open.FileName.

  • If Stream.Name is not empty:

    • 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.

  • EndIf

  • The object store MUST return:

    • Status set to STATUS_SUCCESS.

    • CreateAction set to FILE_CREATED.

    • The Open object created previously.