IO_STATUS_BLOCK NTAPI FatiOpenExistingDcb(IN PFAT_IRP_CONTEXT IrpContext, IN PFILE_OBJECT FileObject, IN PVCB Vcb, IN PFCB Dcb, IN PACCESS_MASK DesiredAccess, IN USHORT ShareAccess, IN ULONG CreateDisposition, IN BOOLEAN NoEaKnowledge, IN BOOLEAN DeleteOnClose) { IO_STATUS_BLOCK Iosb = {{0}}; PCCB Ccb; /* Exclusively lock this FCB */ FatAcquireExclusiveFcb(IrpContext, Dcb); /* Check if it's a delete-on-close of a root DCB */ if (FatNodeType(Dcb) == FAT_NTC_ROOT_DCB && DeleteOnClose) { Iosb.Status = STATUS_CANNOT_DELETE; /* Release the lock and return */ FatReleaseFcb(IrpContext, Dcb); return Iosb; } /*if (NoEaKnowledge && NodeType(Dcb) != FAT_NTC_ROOT_DCB && !FatIsFat32(Vcb)) { UNIMPLEMENTED; }*/ /* Check the create disposition and desired access */ if ((CreateDisposition != FILE_OPEN) && (CreateDisposition != FILE_OPEN_IF)) { Iosb.Status = STATUS_OBJECT_NAME_COLLISION; /* Release the lock and return */ FatReleaseFcb(IrpContext, Dcb); return Iosb; } #if 0 if (!FatCheckFileAccess(IrpContext, Dcb->DirentFatFlags, DesiredAccess)) { Iosb.Status = STATUS_ACCESS_DENIED; try_return( Iosb ); } #endif /* If it's already opened - check share access */ if (Dcb->OpenCount > 0) { Iosb.Status = IoCheckShareAccess(*DesiredAccess, ShareAccess, FileObject, &Dcb->ShareAccess, TRUE); if (!NT_SUCCESS(Iosb.Status)) { /* Release the lock and return */ FatReleaseFcb(IrpContext, Dcb); return Iosb; } } else { IoSetShareAccess(*DesiredAccess, ShareAccess, FileObject, &Dcb->ShareAccess); } /* Set the file object */ Ccb = FatCreateCcb(); FatSetFileObject(FileObject, UserDirectoryOpen, Dcb, Ccb); /* Increase counters */ Dcb->UncleanCount++; Dcb->OpenCount++; Vcb->OpenFileCount++; if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++; /* Set delete on close */ if (DeleteOnClose) SetFlag(Ccb->Flags, CCB_DELETE_ON_CLOSE); /* Clear delay close flag */ ClearFlag(Dcb->State, FCB_STATE_DELAY_CLOSE); /* That's it */ Iosb.Status = STATUS_SUCCESS; Iosb.Information = FILE_OPENED; /* Release the lock */ FatReleaseFcb(IrpContext, Dcb); return Iosb; }
FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, UINT32 GrantedAccess, UINT32 ShareAccess, NTSTATUS *PResult) { /* * Attempt to insert our FileNode into the volume device's generic table. * If an FileNode with the same UserContext already exists, then use that * FileNode instead. * * There is no FileNode that can be acquired when calling this function. */ PAGED_CODE(); PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; FSP_FILE_NODE *OpenedFileNode; BOOLEAN Inserted, DeletePending; NTSTATUS Result; FspFsvolDeviceLockContextTable(FsvolDeviceObject); OpenedFileNode = FspFsvolDeviceInsertContextByName(FsvolDeviceObject, &FileNode->FileName, FileNode, &FileNode->ContextByNameElementStorage, &Inserted); ASSERT(0 != OpenedFileNode); if (Inserted) { /* * The new FileNode was inserted into the Context table. Set its share access * and reference and open it. There should be (at least) two references to this * FileNode, one from our caller and one from the Context table. */ ASSERT(OpenedFileNode == FileNode); IoSetShareAccess(GrantedAccess, ShareAccess, FileObject, &OpenedFileNode->ShareAccess); } else { /* * The new FileNode was NOT inserted into the Context table. Instead we are * opening a prior FileNode that we found in the table. */ ASSERT(OpenedFileNode != FileNode); DeletePending = 0 != OpenedFileNode->DeletePending; MemoryBarrier(); if (DeletePending) { Result = STATUS_DELETE_PENDING; goto exit; } /* * FastFat says to do the following on Vista and above. * * Quote: * Do an extra test for writeable user sections if the user did not allow * write sharing - this is neccessary since a section may exist with no handles * open to the file its based against. */ if (!FlagOn(ShareAccess, FILE_SHARE_WRITE) && FlagOn(GrantedAccess, FILE_EXECUTE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA | DELETE) && MmDoesFileHaveUserWritableReferences(&OpenedFileNode->NonPaged->SectionObjectPointers)) { Result = STATUS_SHARING_VIOLATION; goto exit; } /* share access check */ Result = IoCheckShareAccess(GrantedAccess, ShareAccess, FileObject, &OpenedFileNode->ShareAccess, TRUE); exit: if (!NT_SUCCESS(Result)) { if (0 != PResult) *PResult = Result; OpenedFileNode = 0; } } if (0 != OpenedFileNode) { FspFileNodeReference(OpenedFileNode); OpenedFileNode->OpenCount++; OpenedFileNode->HandleCount++; } FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); return OpenedFileNode; }