NT4/private/ntos/cntfs/seinfo.c
2020-09-30 17:12:29 +02:00

579 lines
13 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)
#pragma alloc_text(PAGE, NtfsFsdQuerySecurityInfo)
#pragma alloc_text(PAGE, NtfsFsdSetSecurityInfo)
#endif
NTSTATUS
NtfsFsdQuerySecurityInfo (
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine implements the FSD part of the Query Security Information API
calls.
Arguments:
VolumeDeviceObject - Supplies the device object to use.
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The Fsd status for the Irp
--*/
{
TOP_LEVEL_CONTEXT TopLevelContext;
PTOP_LEVEL_CONTEXT ThreadTopLevelContext;
NTSTATUS Status = STATUS_SUCCESS;
PIRP_CONTEXT IrpContext = NULL;
ASSERT_IRP( Irp );
UNREFERENCED_PARAMETER( VolumeDeviceObject );
PAGED_CODE();
DebugTrace( +1, Dbg, ("NtfsFsdQuerySecurityInfo\n") );
//
// Call the common query Information routine
//
FsRtlEnterFileSystem();
ThreadTopLevelContext = NtfsSetTopLevelIrp( &TopLevelContext, FALSE, FALSE );
do {
try {
//
// We are either initiating this request or retrying it.
//
if (IrpContext == NULL) {
IrpContext = NtfsCreateIrpContext( Irp, CanFsdWait( Irp ) );
NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext );
} else if (Status == STATUS_LOG_FILE_FULL) {
NtfsCheckpointForLogFileFull( IrpContext );
}
Status = NtfsCommonQuerySecurityInfo( IrpContext, Irp );
break;
} except(NtfsExceptionFilter( IrpContext, GetExceptionInformation() )) {
//
// We had some trouble trying to perform the requested
// operation, so we'll abort the I/O request with
// the error status that we get back from the
// execption code
//
Status = NtfsProcessException( IrpContext, Irp, GetExceptionCode() );
}
} while (Status == STATUS_CANT_WAIT ||
Status == STATUS_LOG_FILE_FULL);
if (ThreadTopLevelContext == &TopLevelContext) {
NtfsRestoreTopLevelIrp( ThreadTopLevelContext );
}
FsRtlExitFileSystem();
//
// And return to our caller
//
DebugTrace( -1, Dbg, ("NtfsFsdQuerySecurityInfo -> %08lx\n", Status) );
return Status;
}
NTSTATUS
NtfsFsdSetSecurityInfo (
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine implements the FSD part of the Set Security Information API
calls.
Arguments:
VolumeDeviceObject - Supplies the device object to use.
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The Fsd status for the Irp
--*/
{
TOP_LEVEL_CONTEXT TopLevelContext;
PTOP_LEVEL_CONTEXT ThreadTopLevelContext;
NTSTATUS Status = STATUS_SUCCESS;
PIRP_CONTEXT IrpContext = NULL;
ASSERT_IRP( Irp );
UNREFERENCED_PARAMETER( VolumeDeviceObject );
PAGED_CODE();
DebugTrace( +1, Dbg, ("NtfsFsdSetSecurityInfo\n") );
//
// Call the common query Information routine
//
FsRtlEnterFileSystem();
ThreadTopLevelContext = NtfsSetTopLevelIrp( &TopLevelContext, FALSE, FALSE );
do {
try {
//
// We are either initiating this request or retrying it.
//
if (IrpContext == NULL) {
IrpContext = NtfsCreateIrpContext( Irp, CanFsdWait( Irp ) );
NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext );
} else if (Status == STATUS_LOG_FILE_FULL) {
NtfsCheckpointForLogFileFull( IrpContext );
}
Status = NtfsCommonSetSecurityInfo( IrpContext, Irp );
break;
} except(NtfsExceptionFilter( IrpContext, GetExceptionInformation() )) {
//
// We had some trouble trying to perform the requested
// operation, so we'll abort the I/O request with
// the error status that we get back from the
// execption code
//
Status = NtfsProcessException( IrpContext, Irp, GetExceptionCode() );
}
} while (Status == STATUS_CANT_WAIT ||
Status == STATUS_LOG_FILE_FULL);
if (ThreadTopLevelContext == &TopLevelContext) {
NtfsRestoreTopLevelIrp( ThreadTopLevelContext );
}
FsRtlExitFileSystem();
//
// And return to our caller
//
DebugTrace( -1, Dbg, ("NtfsFsdSetSecurityInfo -> %08lx\n", Status) );
return Status;
}
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 );
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)) {
Status = STATUS_INVALID_PARAMETER;
//
// If the this handle does not open the entire file then refuse access.
//
} else if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_AS_FILE )) {
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, FALSE );
try {
if (Fcb->SharedSecurity == NULL) {
NtfsReleaseFcb( IrpContext, Fcb );
AcquiredFcb = FALSE;
NtfsAcquireExclusiveFcb( IrpContext, Fcb, NULL, FALSE, FALSE );
AcquiredFcb = TRUE;
}
Status = NtfsQuerySecurity( IrpContext,
Fcb,
&IrpSp->Parameters.QuerySecurity.SecurityInformation,
(PSECURITY_DESCRIPTOR)Irp->UserBuffer,
&IrpSp->Parameters.QuerySecurity.Length );
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;
#ifdef _CAIRO_
PQUOTA_CONTROL_BLOCK OldQuotaControl;
ULONG OldOwnerId;
ULONG LargeStdInfo;
#endif // _CAIRO_
TYPE_OF_OPEN TypeOfOpen;
PVCB Vcb;
PFCB Fcb;
PSCB Scb;
PCCB Ccb;
ASSERT_IRP_CONTEXT( IrpContext );
ASSERT_IRP( Irp );
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)) {
Status = STATUS_INVALID_PARAMETER;
//
// If the this handle does not open the entire file then refuse access.
//
} else if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_AS_FILE )) {
Status = STATUS_INVALID_PARAMETER;
} else {
//
// Our operation is to acquire the fcb, do the operation and then
// release the fcb
//
NtfsAcquireExclusiveFcb( IrpContext, Fcb, NULL, FALSE, FALSE );
try {
#ifdef _CAIRO_
//
// 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;
#endif // _CAIRO_
Status = NtfsModifySecurity( IrpContext,
Fcb,
&IrpSp->Parameters.SetSecurity.SecurityInformation,
IrpSp->Parameters.SetSecurity.SecurityDescriptor );
if (NT_SUCCESS( Status )) {
#ifdef _CAIRO_
//
// Make sure the new security descriptor Id is written out.
//
NtfsUpdateStandardInformation( IrpContext, Fcb );
#endif
}
//
// Abort transaction on error by raising.
//
NtfsCleanupTransaction( IrpContext, Status, FALSE );
//
// Set the flag in the Ccb to indicate this change occurred.
//
SetFlag( Ccb->Flags,
CCB_FLAG_UPDATE_LAST_CHANGE | CCB_FLAG_SET_ARCHIVE );
} finally {
DebugUnwind( NtfsCommonSetSecurityInfo );
#ifdef _CAIRO_
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);
}
}
#endif // _CAIRO_
NtfsReleaseFcb( IrpContext, Fcb );
}
}
//
// Now complete the request and return to our caller
//
NtfsCompleteRequest( &IrpContext, &Irp, Status );
DebugTrace( -1, Dbg, ("NtfsCommonSetSecurityInfo -> %08lx", Status) );
return Status;
}