|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
create.c
Abstract:
This module implements the file create routine for MSFS called by the dispatch driver.
Author:
Manny Weiser (mannyw) 16-Jan-1991
Revision History:
--*/
#include "mailslot.h"
//
// The debug trace level
//
#define Dbg (DEBUG_TRACE_CREATE)
//
// Local procedure prototypes
//
NTSTATUS MsCommonCreate ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp );
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 );
IO_STATUS_BLOCK MsOpenMailslotFileSystem ( IN PVCB Vcb, IN PFILE_OBJECT FileObject, IN ACCESS_MASK DesiredAccess, IN USHORT ShareAccess );
IO_STATUS_BLOCK MsOpenMailslotRootDirectory ( IN PROOT_DCB RootDcb, IN PFILE_OBJECT FileObject, IN ACCESS_MASK DesiredAccess, IN USHORT ShareAccess );
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, MsCommonCreate )
#pragma alloc_text( PAGE, MsCreateClientEnd )
#pragma alloc_text( PAGE, MsFsdCreate )
#pragma alloc_text( PAGE, MsOpenMailslotFileSystem )
#pragma alloc_text( PAGE, MsOpenMailslotRootDirectory )
#endif
NTSTATUS MsFsdCreate ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp )
/*++
Routine Description:
This routine implements the FSD part of the NtCreateFile and NtOpenFile API calls.
Arguments:
MsfsDeviceObject - Supplies the device object to use.
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The Fsd status for the IRP.
--*/
{ NTSTATUS status;
PAGED_CODE(); DebugTrace(+1, Dbg, "MsFsdCreate\n", 0);
//
// Call the common create routine.
//
FsRtlEnterFileSystem();
status = MsCommonCreate( MsfsDeviceObject, Irp );
FsRtlExitFileSystem();
//
// Return to the caller.
//
DebugTrace(-1, Dbg, "MsFsdCreate -> %08lx\n", status ); return status; }
NTSTATUS MsCommonCreate ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp )
/*++
Routine Description:
This is the common routine for creating/opening a file.
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; PFILE_OBJECT relatedFileObject; UNICODE_STRING fileName; ACCESS_MASK desiredAccess; USHORT shareAccess; BOOLEAN caseInsensitive = TRUE; //**** Make all searches case insensitive
PVCB vcb; PFCB fcb; UNICODE_STRING remainingPart;
PAGED_CODE();
//
// Make local copies of our input parameters to make things easier.
//
irpSp = IoGetCurrentIrpStackLocation( Irp ); fileObject = irpSp->FileObject; relatedFileObject = irpSp->FileObject->RelatedFileObject; fileName = *(PUNICODE_STRING)&irpSp->FileObject->FileName; desiredAccess = irpSp->Parameters.Create.SecurityContext->DesiredAccess; shareAccess = irpSp->Parameters.Create.ShareAccess;
//
// Get the VCB we are trying to access.
//
vcb = &MsfsDeviceObject->Vcb;
//
// Acquire exclusive access to the VCB.
//
MsAcquireExclusiveVcb( vcb );
try {
//
// Check if we are trying to open the mailslot file system
// (i.e., the Vcb).
//
if ((fileName.Length == 0) && ((relatedFileObject == NULL) || ( NodeType(relatedFileObject->FsContext) == MSFS_NTC_VCB))) {
DebugTrace(0, Dbg, "Open mailslot file system\n", 0);
Irp->IoStatus = MsOpenMailslotFileSystem( vcb, fileObject, desiredAccess, shareAccess );
status = Irp->IoStatus.Status; try_return( NOTHING ); }
//
// Check if we are trying to open the root directory.
//
if (((fileName.Length == sizeof(WCHAR)) && (fileName.Buffer[0] == L'\\') && (relatedFileObject == NULL))
||
((fileName.Length == 0) && (NodeType( relatedFileObject->FsContext) == MSFS_NTC_ROOT_DCB))) {
DebugTrace(0, Dbg, "Open root directory system\n", 0);
Irp->IoStatus = MsOpenMailslotRootDirectory( vcb->RootDcb, fileObject, desiredAccess, shareAccess );
status = Irp->IoStatus.Status; try_return( NOTHING ); }
//
// If there is a related file object then this is a relative open
// and it better be the root DCB. Both the then and the else clause
// return an FCB.
//
if (relatedFileObject != NULL) {
PDCB dcb;
dcb = relatedFileObject->FsContext;
if (NodeType(dcb) == MSFS_NTC_ROOT_DCB) { status = MsFindRelativePrefix( dcb, &fileName, caseInsensitive, &remainingPart, &fcb ); if (!NT_SUCCESS (status)) { try_return( NOTHING ); } } else if (NodeType(dcb) == MSFS_NTC_CCB && fileName.Length == 0) {
fcb = ((PCCB) dcb)->Fcb; remainingPart.Length = 0;
} else if (NodeType(dcb) == MSFS_NTC_FCB && fileName.Length == 0) {
fcb = (PFCB) dcb; remainingPart.Length = 0;
} else {
DebugTrace(0, Dbg, "Bad file name\n", 0);
try_return( status = STATUS_OBJECT_NAME_INVALID ); }
} else {
//
// The only nonrelative name we allow are of the form
// "\mailslot-name".
//
if ((fileName.Length <= sizeof( WCHAR )) || (fileName.Buffer[0] != L'\\')) {
DebugTrace(0, Dbg, "Bad file name\n", 0);
try_return( status = STATUS_OBJECT_NAME_INVALID ); }
fcb = MsFindPrefix( vcb, &fileName, caseInsensitive, &remainingPart ); }
//
// If the remaining name is not empty then we have an error, either
// we have an illegal name or a non-existent name.
//
if (remainingPart.Length != 0) {
if (fcb->Header.NodeTypeCode == MSFS_NTC_FCB) {
//
// We were given a name such as "\mailslot-name\another-name"
//
DebugTrace(0, Dbg, "Illegal object name\n", 0); status = STATUS_OBJECT_NAME_INVALID;
} else {
//
// We were given a non-existent name
//
DebugTrace(0, Dbg, "non-existent name\n", 0); status = STATUS_OBJECT_NAME_NOT_FOUND; }
} else {
//
// The remaining name is empty so we better have an FCB otherwise
// we have an invalid object name.
//
if (fcb->Header.NodeTypeCode == MSFS_NTC_FCB) {
DebugTrace(0, Dbg, "Create client end mailslot, Fcb = %08lx\n", (ULONG)fcb );
Irp->IoStatus = MsCreateClientEnd( fcb, fileObject, desiredAccess, shareAccess, irpSp->Parameters.Create.SecurityContext->AccessState, Irp->RequestorMode, Irp->Tail.Overlay.Thread ); status = Irp->IoStatus.Status;
} else {
DebugTrace(0, Dbg, "Illegal object name\n", 0); status = STATUS_OBJECT_NAME_INVALID;
} }
try_exit: NOTHING; } finally {
MsReleaseVcb( vcb );
//
// Complete the IRP and return to the caller.
//
MsCompleteRequest( Irp, status ); DebugTrace(-1, Dbg, "MsCommonCreate -> %08lx\n", status);
}
return status; }
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;
PAGED_CODE(); DebugTrace(+1, Dbg, "MsCreateClientEnd\n", 0 );
try {
//
// Lock out mods to the FCB's security descriptor.
//
MsAcquireSharedFcb( Fcb );
SeLockSubjectContext( &AccessState->SubjectSecurityContext );
//
// First do an access check for the user against the Fcb
//
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 | MAXIMUM_ALLOWED); }
RtlInitUnicodeString( &name, L"Mailslot" );
SeOpenObjectAuditAlarm( &name, NULL, &FileObject->FileName, Fcb->SecurityDescriptor, AccessState, FALSE, accessGranted, RequestorMode, &AccessState->GenerateOnClose );
SeUnlockSubjectContext( &AccessState->SubjectSecurityContext );
MsReleaseFcb( Fcb );
if (!accessGranted) {
DebugTrace(0, Dbg, "Access Denied\n", 0 );
try_return( iosb.Status ); }
//
// Now make sure our share access is okay.
//
ASSERT (MsIsAcquiredExclusiveVcb(Fcb->Vcb)); if (!NT_SUCCESS(iosb.Status = IoCheckShareAccess( grantedAccess, ShareAccess, FileObject, &Fcb->ShareAccess, TRUE ))) {
DebugTrace(0, Dbg, "Sharing violation\n", 0);
try_return( NOTHING );
}
//
// Create a CCB for this client.
//
iosb.Status = MsCreateCcb( Fcb, &ccb ); if (!NT_SUCCESS (iosb.Status)) {
IoRemoveShareAccess( FileObject, &Fcb->ShareAccess );
try_return( iosb.Status); }
//
// 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);
}
return iosb; }
IO_STATUS_BLOCK MsOpenMailslotFileSystem ( IN PVCB Vcb, IN PFILE_OBJECT FileObject, IN ACCESS_MASK DesiredAccess, IN USHORT ShareAccess )
{ IO_STATUS_BLOCK iosb = {0};
PAGED_CODE(); DebugTrace(+1, Dbg, "MsOpenMailslotFileSystem, Vcb = %p\n", Vcb);
//
// Set the new share access
//
ASSERT (MsIsAcquiredExclusiveVcb(Vcb)); if (NT_SUCCESS(iosb.Status = IoCheckShareAccess( DesiredAccess, ShareAccess, FileObject, &Vcb->ShareAccess, TRUE ))) { //
// Supply the file object with a referenced pointer to the VCB.
//
MsReferenceVcb (Vcb);
MsSetFileObject( FileObject, Vcb, NULL );
//
// Set the return status.
//
iosb.Status = STATUS_SUCCESS; iosb.Information = FILE_OPENED; }
DebugTrace(-1, Dbg, "MsOpenMailslotFileSystem -> Iosb.Status = %08lx\n", iosb.Status);
//
// Return to the caller.
//
return iosb; }
IO_STATUS_BLOCK MsOpenMailslotRootDirectory( IN PROOT_DCB RootDcb, IN PFILE_OBJECT FileObject, IN ACCESS_MASK DesiredAccess, IN USHORT ShareAccess )
{ IO_STATUS_BLOCK iosb = {0}; PROOT_DCB_CCB ccb;
PAGED_CODE(); DebugTrace( +1, Dbg, "MsOpenMailslotRootDirectory, RootDcb = %08lx\n", (ULONG)RootDcb);
try {
//
// Create a root DCB CCB
//
ccb = MsCreateRootDcbCcb (RootDcb, RootDcb->Vcb);
if (ccb == NULL) {
iosb.Status = STATUS_INSUFFICIENT_RESOURCES; try_return( NOTHING );
} //
// Set the new share access.
//
ASSERT (MsIsAcquiredExclusiveVcb(RootDcb->Vcb)); if (!NT_SUCCESS(iosb.Status = IoCheckShareAccess( DesiredAccess, ShareAccess, FileObject, &RootDcb->ShareAccess, TRUE ))) {
DebugTrace(0, Dbg, "bad share access\n", 0);
//
// Drop ccb
//
MsDereferenceCcb ((PCCB) ccb);
try_return( NOTHING ); }
MsSetFileObject( FileObject, RootDcb, ccb );
//
// 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; }
|