IO_STATUS_BLOCK MsOpenMailslotRootDirectory( IN PROOT_DCB RootDcb, IN PFILE_OBJECT FileObject, IN ACCESS_MASK DesiredAccess, IN USHORT ShareAccess ) { IO_STATUS_BLOCK iosb; PAGED_CODE(); DebugTrace( +1, Dbg, "MsOpenMailslotRootDirectory, RootDcb = %08lx\n", (ULONG)RootDcb); try { // // Set the new share access. // if (!NT_SUCCESS(iosb.Status = IoCheckShareAccess( DesiredAccess, ShareAccess, FileObject, &RootDcb->ShareAccess, TRUE ))) { DebugTrace(0, Dbg, "bad share access\n", 0); try_return( NOTHING ); } // // Supply the file object with a referenced pointer to the root DCB. // MsAcquireGlobalLock(); MsReferenceNode( &RootDcb->Header ); MsReleaseGlobalLock(); MsSetFileObject( FileObject, RootDcb, MsCreateRootDcbCcb() ); // // Set the return status. // iosb.Status = STATUS_SUCCESS; iosb.Information = FILE_OPENED; try_exit: NOTHING; } finally { DebugTrace(-1, Dbg, "MsOpenMailslotRootDirectory -> iosb.Status = %08lx\n", iosb.Status); } // // Return to the caller. // return iosb; }
IO_STATUS_BLOCK MsOpenMailslotFileSystem ( IN PVCB Vcb, IN PFILE_OBJECT FileObject, IN ACCESS_MASK DesiredAccess, IN USHORT ShareAccess ) { IO_STATUS_BLOCK iosb; PAGED_CODE(); DebugTrace(+1, Dbg, "MsOpenMailslotFileSystem, Vcb = %08lx\n", (ULONG)Vcb); try { // // Set the new share access // if (!NT_SUCCESS(iosb.Status = IoCheckShareAccess( DesiredAccess, ShareAccess, FileObject, &Vcb->ShareAccess, TRUE ))) { DebugTrace(0, Dbg, "bad share access\n", 0); try_return( NOTHING ); } // // Supply the file object with a referenced pointer to the VCB. // MsAcquireGlobalLock(); MsReferenceNode( &Vcb->Header ); if (Vcb->Header.ReferenceCount == 2) { // // Set the driver paging back to normal // MmResetDriverPaging(MsOpenMailslotFileSystem); } MsReleaseGlobalLock(); MsSetFileObject( FileObject, Vcb, NULL ); // // Set the return status. // iosb.Status = STATUS_SUCCESS; iosb.Information = FILE_OPENED; try_exit: NOTHING; } finally { DebugTrace(-1, Dbg, "MsOpenMailslotFileSystem -> Iosb.Status = %08lx\n", iosb.Status); } // // Return to the caller. // return iosb; }
IO_STATUS_BLOCK MsCreateClientEnd ( IN PFCB Fcb, IN PFILE_OBJECT FileObject, IN ACCESS_MASK DesiredAccess, IN USHORT ShareAccess, IN PACCESS_STATE AccessState, IN KPROCESSOR_MODE RequestorMode, IN PETHREAD UserThread ) /*++ Routine Description: This routine performs the operation for opening the client end of a mailslot. This routine does not complete the IRP, it performs the function and then returns a status. Arguments: Fcb - Supplies the FCB for the mailslot being accessed. FileObject - Supplies the file object associated with the client end. DesiredAccess - Supplies the caller's desired access. ShareAccess - Supplies the caller's share access. Return Value: IO_STATUS_BLOCK - Returns the appropriate status for the operation --*/ { IO_STATUS_BLOCK iosb; PCCB ccb; BOOLEAN accessGranted; ACCESS_MASK grantedAccess; UNICODE_STRING name; PPRIVILEGE_SET Privileges = NULL; BOOLEAN shareAccessUpdated = FALSE; PAGED_CODE(); DebugTrace(+1, Dbg, "MsCreateClientEnd\n", 0 ); try { // // First do an access check for the user against the Fcb // SeLockSubjectContext( &AccessState->SubjectSecurityContext ); accessGranted = SeAccessCheck( Fcb->SecurityDescriptor, &AccessState->SubjectSecurityContext, TRUE, // Tokens are locked DesiredAccess, 0, &Privileges, IoGetFileObjectGenericMapping(), RequestorMode, &grantedAccess, &iosb.Status ); if (Privileges != NULL) { (VOID) SeAppendPrivileges( AccessState, Privileges ); SeFreePrivileges( Privileges ); } if (accessGranted) { AccessState->PreviouslyGrantedAccess |= grantedAccess; AccessState->RemainingDesiredAccess &= ~grantedAccess; } RtlInitUnicodeString( &name, L"Mailslot" ); SeOpenObjectAuditAlarm( &name, NULL, &FileObject->FileName, Fcb->SecurityDescriptor, AccessState, FALSE, accessGranted, RequestorMode, &AccessState->GenerateOnClose ); SeUnlockSubjectContext( &AccessState->SubjectSecurityContext ); if (!accessGranted) { DebugTrace(0, Dbg, "Access Denied\n", 0 ); try_return( iosb.Status ); } // // Now make sure our share access is okay. // if (!NT_SUCCESS(iosb.Status = IoCheckShareAccess( DesiredAccess, ShareAccess, FileObject, &Fcb->ShareAccess, TRUE ))) { DebugTrace(0, Dbg, "Sharing violation\n", 0); try_return( NOTHING ); } shareAccessUpdated = TRUE; // // Create a CCB for this client. // ccb = MsCreateCcb( Fcb ); // // Set the file object back pointers and our pointer to the // server file object. // MsSetFileObject( FileObject, ccb, NULL ); ccb->FileObject = FileObject; // // And set our return status // iosb.Status = STATUS_SUCCESS; iosb.Information = FILE_OPENED; try_exit: NOTHING; } finally { DebugTrace(-1, Dbg, "MsCreateClientEnd -> %08lx\n", iosb.Status); if (!NT_SUCCESS(iosb.Status) || AbnormalTermination()) { if (shareAccessUpdated) { IoRemoveShareAccess( FileObject, &Fcb->ShareAccess ); } } } return iosb; }
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; }
IO_STATUS_BLOCK NTAPI FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext, IN PFILE_OBJECT FileObject, IN PVCB Vcb, IN PFCB Fcb, IN PACCESS_MASK DesiredAccess, IN USHORT ShareAccess, IN ULONG AllocationSize, IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, IN UCHAR FileAttributes, IN ULONG CreateDisposition, IN BOOLEAN NoEaKnowledge, IN BOOLEAN DeleteOnClose, IN BOOLEAN OpenedAsDos, OUT PBOOLEAN OplockPostIrp) { IO_STATUS_BLOCK Iosb = {{0}}; ACCESS_MASK AddedAccess = 0; BOOLEAN Hidden; BOOLEAN System; PCCB Ccb = NULL; NTSTATUS Status, StatusPrev; /* Acquire exclusive FCB lock */ (VOID)FatAcquireExclusiveFcb(IrpContext, Fcb); *OplockPostIrp = FALSE; /* Check if there is a batch oplock */ if (FsRtlCurrentBatchOplock(&Fcb->Fcb.Oplock)) { /* Return with a special information field */ Iosb.Information = FILE_OPBATCH_BREAK_UNDERWAY; /* Check the oplock */ Iosb.Status = FsRtlCheckOplock(&Fcb->Fcb.Oplock, IrpContext->Irp, IrpContext, FatOplockComplete, FatPrePostIrp); if (Iosb.Status != STATUS_SUCCESS && Iosb.Status != STATUS_OPLOCK_BREAK_IN_PROGRESS) { /* The Irp needs to be queued */ *OplockPostIrp = TRUE; /* Release the FCB and return */ FatReleaseFcb(IrpContext, Fcb); return Iosb; } } /* Validate parameters and modify access */ if (CreateDisposition == FILE_CREATE) { Iosb.Status = STATUS_OBJECT_NAME_COLLISION; /* Release the FCB and return */ FatReleaseFcb(IrpContext, Fcb); return Iosb; } else if (CreateDisposition == FILE_SUPERSEDE) { SetFlag(AddedAccess, DELETE & ~(*DesiredAccess)); *DesiredAccess |= DELETE; } else if ((CreateDisposition == FILE_OVERWRITE) || (CreateDisposition == FILE_OVERWRITE_IF)) { SetFlag(AddedAccess, (FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES) & ~(*DesiredAccess) ); *DesiredAccess |= FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES; } // TODO: Check desired access // TODO: Check if this file is readonly and DeleteOnClose is set /* Validate disposition information */ if ((CreateDisposition == FILE_SUPERSEDE) || (CreateDisposition == FILE_OVERWRITE) || (CreateDisposition == FILE_OVERWRITE_IF)) { // TODO: Get this attributes from the dirent Hidden = FALSE; System = FALSE; if ((Hidden && !FlagOn(FileAttributes, FILE_ATTRIBUTE_HIDDEN)) || (System && !FlagOn(FileAttributes, FILE_ATTRIBUTE_SYSTEM))) { DPRINT1("Hidden/system attributes don't match\n"); Iosb.Status = STATUS_ACCESS_DENIED; /* Release the FCB and return */ FatReleaseFcb(IrpContext, Fcb); return Iosb; } // TODO: Check for write protected volume } /* Check share access */ Iosb.Status = IoCheckShareAccess(*DesiredAccess, ShareAccess, FileObject, &Fcb->ShareAccess, FALSE); if (!NT_SUCCESS(Iosb.Status)) { /* Release the FCB and return */ FatReleaseFcb(IrpContext, Fcb); return Iosb; } /* Check the oplock status after checking for share access */ Iosb.Status = FsRtlCheckOplock(&Fcb->Fcb.Oplock, IrpContext->Irp, IrpContext, FatOplockComplete, FatPrePostIrp ); if (Iosb.Status != STATUS_SUCCESS && Iosb.Status != STATUS_OPLOCK_BREAK_IN_PROGRESS) { /* The Irp needs to be queued */ *OplockPostIrp = TRUE; /* Release the FCB and return */ FatReleaseFcb(IrpContext, Fcb); return Iosb; } /* Set Fast I/O flag */ Fcb->Header.IsFastIoPossible = FALSE; //FatiIsFastIoPossible(Fcb); /* Make sure image is not mapped */ if (DeleteOnClose || FlagOn(*DesiredAccess, FILE_WRITE_DATA)) { /* Try to flush the image section */ if (!MmFlushImageSection(&Fcb->SectionObjectPointers, MmFlushForWrite)) { /* Yes, image section exists, set correct status code */ if (DeleteOnClose) Iosb.Status = STATUS_CANNOT_DELETE; else Iosb.Status = STATUS_SHARING_VIOLATION; /* Release the FCB and return */ FatReleaseFcb(IrpContext, Fcb); return Iosb; } } /* Flush the cache if it's non-cached non-pagefile access */ if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING) && Fcb->SectionObjectPointers.DataSectionObject && !FlagOn(Fcb->State, FCB_STATE_PAGEFILE)) { /* Set the flag that create is in progress */ SetFlag(Fcb->Vcb->State, VCB_STATE_CREATE_IN_PROGRESS); /* Flush the cache */ CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, NULL); /* Acquire and release Paging I/O resource before purging the cache section to let lazy writer finish */ ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource, TRUE); ExReleaseResourceLite( Fcb->Header.PagingIoResource ); /* Delete the cache section */ CcPurgeCacheSection(&Fcb->SectionObjectPointers, NULL, 0, FALSE); /* Clear the flag */ ClearFlag(Fcb->Vcb->State, VCB_STATE_CREATE_IN_PROGRESS); } /* Check create disposition flags and branch accordingly */ if (CreateDisposition == FILE_OPEN || CreateDisposition == FILE_OPEN_IF) { DPRINT("Opening a file\n"); /* Check if we need to bother with EA */ if (NoEaKnowledge && FALSE /* FatIsFat32(Vcb)*/) { UNIMPLEMENTED; } /* Set up file object */ Ccb = FatCreateCcb(); FatSetFileObject(FileObject, UserFileOpen, Fcb, Ccb); FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers; /* The file is opened */ Iosb.Information = FILE_OPENED; goto SuccComplete; } else if ((CreateDisposition == FILE_SUPERSEDE) || (CreateDisposition == FILE_OVERWRITE) || (CreateDisposition == FILE_OVERWRITE_IF)) { /* Remember previous status */ StatusPrev = Iosb.Status; // TODO: Check system security access /* Perform overwrite operation */ Iosb = FatiOverwriteFile(IrpContext, FileObject, Fcb, AllocationSize, EaBuffer, EaLength, FileAttributes, CreateDisposition, NoEaKnowledge); /* Restore previous status in case of success */ if (Iosb.Status == STATUS_SUCCESS) Iosb.Status = StatusPrev; /* Fall down to completion */ } else { /* We can't get here */ KeBugCheckEx(FAT_FILE_SYSTEM, CreateDisposition, 0, 0, 0); } SuccComplete: /* If all is fine */ if (Iosb.Status != STATUS_PENDING && NT_SUCCESS(Iosb.Status)) { /* Update access if needed */ if (AddedAccess) { /* Remove added access flags from desired access */ ClearFlag(*DesiredAccess, AddedAccess); /* Check share access */ Status = IoCheckShareAccess(*DesiredAccess, ShareAccess, FileObject, &Fcb->ShareAccess, TRUE); /* Make sure it's success */ ASSERT(Status == STATUS_SUCCESS); } else { /* Update the share access */ IoUpdateShareAccess(FileObject, &Fcb->ShareAccess); } /* Clear the delay close */ ClearFlag(Fcb->State, FCB_STATE_DELAY_CLOSE); /* Increase counters */ Fcb->UncleanCount++; Fcb->OpenCount++; Vcb->OpenFileCount++; if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++; if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) Fcb->NonCachedUncleanCount++; // TODO: Handle DeleteOnClose and OpenedAsDos by storing those flags in CCB } 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; }