/*++ 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; }