windows-nt/Source/XPSP1/NT/base/fs/ntfs/seinfo.c
2020-09-26 16:20:57 +08:00

393 lines
9.4 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
SeInfo.c
Abstract:
This module implements the Security Info routines for NTFS called by the
dispatch driver.
Author:
Gary Kimura [GaryKi] 26-Dec-1991
Revision History:
--*/
#include "NtfsProc.h"
//
// The debug trace level
//
#define Dbg (DEBUG_TRACE_SEINFO)
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, NtfsCommonQuerySecurityInfo)
#pragma alloc_text(PAGE, NtfsCommonSetSecurityInfo)
#endif
NTSTATUS
NtfsCommonQuerySecurityInfo (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common routine for querying security information called by
both the fsd and fsp threads.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - the return status for the operation
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
PFILE_OBJECT FileObject;
TYPE_OF_OPEN TypeOfOpen;
PVCB Vcb;
PFCB Fcb;
PSCB Scb;
PCCB Ccb;
BOOLEAN AcquiredFcb = TRUE;
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_IRP( Irp );
ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));
PAGED_CODE();
//
// Get the current Irp stack location
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace( +1, Dbg, ("NtfsCommonQuerySecurityInfo") );
DebugTrace( 0, Dbg, ("IrpContext = %08lx\n", IrpContext) );
DebugTrace( 0, Dbg, ("Irp = %08lx\n", Irp) );
//
// Extract and decode the file object
//
FileObject = IrpSp->FileObject;
TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );
//
// The only type of opens we accept are user file and directory opens
//
if ((TypeOfOpen != UserFileOpen)
&& (TypeOfOpen != UserDirectoryOpen)
&& (TypeOfOpen != UserViewIndexOpen)) {
Status = STATUS_INVALID_PARAMETER;
} else {
//
// Our operation is to acquire the fcb, do the operation and then
// release the fcb. If the security descriptor for this file is
// not already loaded we will release the Fcb and then acquire both
// the Vcb and Fcb. We must have the Vcb to examine our parent's
// security descriptor.
//
NtfsAcquireSharedFcb( IrpContext, Fcb, NULL, 0 );
try {
if (Fcb->SharedSecurity == NULL) {
NtfsReleaseFcb( IrpContext, Fcb );
AcquiredFcb = FALSE;
NtfsAcquireExclusiveFcb( IrpContext, Fcb, NULL, 0 );
AcquiredFcb = TRUE;
}
//
// Make sure the volume is still mounted.
//
if (FlagOn( Scb->ScbState, SCB_STATE_VOLUME_DISMOUNTED )) {
Status = STATUS_VOLUME_DISMOUNTED;
leave;
}
Status = NtfsQuerySecurity( IrpContext,
Fcb,
&IrpSp->Parameters.QuerySecurity.SecurityInformation,
(PSECURITY_DESCRIPTOR)Irp->UserBuffer,
&IrpSp->Parameters.QuerySecurity.Length );
if (NT_SUCCESS( Status )) {
Irp->IoStatus.Information = IrpSp->Parameters.QuerySecurity.Length;
} else if (Status == STATUS_BUFFER_TOO_SMALL) {
Irp->IoStatus.Information = IrpSp->Parameters.QuerySecurity.Length;
Status = STATUS_BUFFER_OVERFLOW;
}
//
// Abort transaction on error by raising.
//
NtfsCleanupTransaction( IrpContext, Status, FALSE );
} finally {
DebugUnwind( NtfsCommonQuerySecurityInfo );
if (AcquiredFcb) {
NtfsReleaseFcb( IrpContext, Fcb );
}
}
}
//
// Now complete the request and return to our caller
//
NtfsCompleteRequest( IrpContext, Irp, Status );
DebugTrace( -1, Dbg, ("NtfsCommonQuerySecurityInfo -> %08lx", Status) );
return Status;
}
NTSTATUS
NtfsCommonSetSecurityInfo (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common routine for Setting security information called by
both the fsd and fsp threads.
Arguments:
Irp - Supplies the Irp to process
Return Value:
NTSTATUS - the return status for the operation
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
PFILE_OBJECT FileObject;
PQUOTA_CONTROL_BLOCK OldQuotaControl = NULL;
ULONG OldOwnerId;
ULONG LargeStdInfo;
TYPE_OF_OPEN TypeOfOpen;
PVCB Vcb;
PFCB Fcb;
PSCB Scb;
PCCB Ccb;
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_IRP( Irp );
ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));
PAGED_CODE();
//
// Get the current Irp stack location
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace( +1, Dbg, ("NtfsCommonSetSecurityInfo") );
DebugTrace( 0, Dbg, ("IrpContext = %08lx\n", IrpContext) );
DebugTrace( 0, Dbg, ("Irp = %08lx\n", Irp) );
//
// Extract and decode the file object
//
FileObject = IrpSp->FileObject;
TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );
//
// The only type of opens we accept are user file and directory opens
//
if ((TypeOfOpen != UserFileOpen)
&& (TypeOfOpen != UserDirectoryOpen)
&& (TypeOfOpen != UserViewIndexOpen)) {
Status = STATUS_INVALID_PARAMETER;
} else if (NtfsIsVolumeReadOnly( Vcb )) {
Status = STATUS_MEDIA_WRITE_PROTECTED;
} else {
//
// Capture the source information.
//
IrpContext->SourceInfo = Ccb->UsnSourceInfo;
//
// Our operation is to acquire the fcb, do the operation and then
// release the fcb
//
NtfsAcquireExclusiveFcb( IrpContext, Fcb, NULL, 0 );
try {
//
// Make sure the volume is still mounted.
//
if (FlagOn( Scb->ScbState, SCB_STATE_VOLUME_DISMOUNTED )) {
Status = STATUS_VOLUME_DISMOUNTED;
leave;
}
//
// Post the change to the Usn Journal.
//
NtfsPostUsnChange( IrpContext, Scb, USN_REASON_SECURITY_CHANGE );
//
// Capture the current OwnerId, Qutoa Control Block and
// size of standard information.
//
OldQuotaControl = Fcb->QuotaControl;
OldOwnerId = Fcb->OwnerId;
LargeStdInfo = Fcb->FcbState & FCB_STATE_LARGE_STD_INFO;
Status = NtfsModifySecurity( IrpContext,
Fcb,
&IrpSp->Parameters.SetSecurity.SecurityInformation,
IrpSp->Parameters.SetSecurity.SecurityDescriptor );
if (NT_SUCCESS( Status )) {
//
// Make sure the new security descriptor Id is written out.
//
NtfsUpdateStandardInformation( IrpContext, Fcb );
}
//
// Abort transaction on error by raising.
//
NtfsCleanupTransaction( IrpContext, Status, FALSE );
//
// Set the flag in the Ccb to indicate this change occurred.
//
if (!IsDirectory( &Fcb->Info )) {
SetFlag( Ccb->Flags, CCB_FLAG_UPDATE_LAST_CHANGE | CCB_FLAG_SET_ARCHIVE );
}
} finally {
DebugUnwind( NtfsCommonSetSecurityInfo );
if (AbnormalTermination()) {
//
// The request failed. Restore the owner and
// QuotaControl are restored.
//
if ((Fcb->QuotaControl != OldQuotaControl) &&
(Fcb->QuotaControl != NULL)) {
//
// A new quota control block was assigned.
// Dereference it.
//
NtfsDereferenceQuotaControlBlock( Fcb->Vcb,
&Fcb->QuotaControl );
}
Fcb->QuotaControl = OldQuotaControl;
Fcb->OwnerId = OldOwnerId;
if (LargeStdInfo == 0) {
//
// The standard information has be returned to
// its orginal size.
//
ClearFlag( Fcb->FcbState, FCB_STATE_LARGE_STD_INFO );
}
} else {
//
// The request succeed. If the quota control block was
// changed then derefence the old block.
//
if ((Fcb->QuotaControl != OldQuotaControl) &&
(OldQuotaControl != NULL)) {
NtfsDereferenceQuotaControlBlock( Fcb->Vcb,
&OldQuotaControl);
}
}
}
}
//
// Now complete the request and return to our caller
//
NtfsCompleteRequest( IrpContext, Irp, Status );
DebugTrace( -1, Dbg, ("NtfsCommonSetSecurityInfo -> %08lx", Status) );
return Status;
}