|
|
/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
createms.c
Abstract:
This module implements the file create mailslot routine for MSFS called by the dispatch driver.
Author:
Manny Weiser (mannyw) 17-Jan-1991
Revision History:
--*/
#include "mailslot.h"
//
// The debug trace level
//
#define Dbg (DEBUG_TRACE_CREATE_MAILSLOT)
//
// local procedure prototypes
//
NTSTATUS MsCommonCreateMailslot ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp );
IO_STATUS_BLOCK MsCreateMailslot ( IN PROOT_DCB RootDcb, IN PFILE_OBJECT FileObject, IN UNICODE_STRING FileName, IN ACCESS_MASK DesiredAccess, IN ULONG CreateDisposition, IN USHORT ShareAccess, IN ULONG MailslotQuota, IN ULONG MaximumMessageSize, IN LARGE_INTEGER ReadTimeout, IN PEPROCESS CreatorProcess, IN PACCESS_STATE AccessState );
BOOLEAN MsIsNameValid ( PUNICODE_STRING Name );
#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, MsCommonCreateMailslot )
#pragma alloc_text( PAGE, MsCreateMailslot )
#pragma alloc_text( PAGE, MsFsdCreateMailslot )
#pragma alloc_text( PAGE, MsIsNameValid )
#endif
NTSTATUS MsFsdCreateMailslot ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp )
/*++
Routine Description:
This routine implements the FSD part of the NtCreateMailslotFile API call.
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, "MsFsdCreateMailslot\n", 0);
//
// Call the common create routine.
//
FsRtlEnterFileSystem();
status = MsCommonCreateMailslot( MsfsDeviceObject, Irp );
FsRtlExitFileSystem();
//
// Return to the caller.
//
DebugTrace(-1, Dbg, "MsFsdCreateMailslot -> %08lx\n", status ); return status; }
NTSTATUS MsCommonCreateMailslot ( IN PMSFS_DEVICE_OBJECT MsfsDeviceObject, IN PIRP Irp )
/*++
Routine Description:
This is the common routine for creating a mailslot.
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; ULONG options; USHORT shareAccess; PMAILSLOT_CREATE_PARAMETERS parameters; ULONG mailslotQuota; ULONG maximumMessageSize; PEPROCESS creatorProcess; LARGE_INTEGER readTimeout;
BOOLEAN caseInsensitive = TRUE; //**** Make all searches case insensitive
PVCB vcb; PFCB fcb;
ULONG createDisposition; UNICODE_STRING remainingPart;
PAGED_CODE();
//
// Make local copies of the 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.CreateMailslot.SecurityContext->DesiredAccess; options = irpSp->Parameters.CreateMailslot.Options; shareAccess = irpSp->Parameters.CreateMailslot.ShareAccess; parameters = irpSp->Parameters.CreateMailslot.Parameters; mailslotQuota = parameters->MailslotQuota; maximumMessageSize = parameters->MaximumMessageSize;
if (parameters->TimeoutSpecified) { readTimeout = parameters->ReadTimeout; } else { readTimeout.QuadPart = -1; }
creatorProcess = IoGetRequestorProcess( Irp );
DebugTrace(+1, Dbg, "MsCommonCreateMailslot\n", 0 ); DebugTrace( 0, Dbg, "MsfsDeviceObject = %08lx\n", (ULONG)MsfsDeviceObject ); DebugTrace( 0, Dbg, "Irp = %08lx\n", (ULONG)Irp ); DebugTrace( 0, Dbg, "FileObject = %08lx\n", (ULONG)fileObject ); DebugTrace( 0, Dbg, "RelatedFileObject = %08lx\n", (ULONG)relatedFileObject ); DebugTrace( 0, Dbg, "FileName = %wZ\n", (ULONG)&fileName ); DebugTrace( 0, Dbg, "DesiredAccess = %08lx\n", desiredAccess ); DebugTrace( 0, Dbg, "Options = %08lx\n", options ); DebugTrace( 0, Dbg, "ShareAccess = %08lx\n", shareAccess ); DebugTrace( 0, Dbg, "Parameters = %08lx\n", (ULONG)parameters ); DebugTrace( 0, Dbg, "MailslotQuota = %08lx\n", mailslotQuota ); DebugTrace( 0, Dbg, "MaximumMesssageSize = %08lx\n", maximumMessageSize ); DebugTrace( 0, Dbg, "CreatorProcess = %08lx\n", (ULONG)creatorProcess );
//
// Get the VCB we are trying to access and extract the
// create disposition.
//
vcb = &MsfsDeviceObject->Vcb; createDisposition = (options >> 24) & 0x000000ff;
//
// Acquire exclusive access to the VCB.
//
MsAcquireExclusiveVcb( vcb );
try {
//
// 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 || fileName.Length < sizeof( WCHAR ) || fileName.Buffer[0] == L'\\') {
DebugTrace(0, Dbg, "Bad file name\n", 0);
try_return( status = STATUS_OBJECT_NAME_INVALID ); }
status = MsFindRelativePrefix( dcb, &fileName, caseInsensitive, &remainingPart, &fcb ); if (!NT_SUCCESS (status)) { try_return( NOTHING ); }
} 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 empty then we better have an FCB
// otherwise we were given a illegal object name.
//
if (remainingPart.Length == 0) {
if (fcb->Header.NodeTypeCode == MSFS_NTC_FCB) {
DebugTrace(0, Dbg, "Attempt to create an existing mailslot, " "Fcb = %08lx\n", (ULONG)fcb );
status = STATUS_OBJECT_NAME_COLLISION;
} else {
DebugTrace(0, Dbg, "Illegal object name\n", 0); status = STATUS_OBJECT_NAME_INVALID;
}
} else {
//
// The remaining name is not empty so we better have the root DCB
// and then have a valid object path.
//
if ( fcb->Header.NodeTypeCode == MSFS_NTC_ROOT_DCB && MsIsNameValid( &remainingPart ) ) {
DebugTrace(0, Dbg, "Create new mailslot, Fcb = %08lx\n", (ULONG)fcb );
Irp->IoStatus = MsCreateMailslot( fcb, fileObject, fileName, desiredAccess, createDisposition, shareAccess, mailslotQuota, maximumMessageSize, readTimeout, creatorProcess, irpSp->Parameters.CreateMailslot.SecurityContext->AccessState );
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, "MsCommonCreateMailslot -> %08lx\n", status); return status; }
IO_STATUS_BLOCK MsCreateMailslot ( IN PROOT_DCB RootDcb, IN PFILE_OBJECT FileObject, IN UNICODE_STRING FileName, IN ACCESS_MASK DesiredAccess, IN ULONG CreateDisposition, IN USHORT ShareAccess, IN ULONG MailslotQuota, IN ULONG MaximumMessageSize, IN LARGE_INTEGER ReadTimeout, IN PEPROCESS CreatorProcess, IN PACCESS_STATE AccessState )
/*++
Routine Description:
This routine performs the operation for creating a new mailslot Fcb. This routine does not complete any IRP, it preforms its function and then returns an iosb.
Arguments:
RootDcb - Supplies the root dcb where this is going to be added.
FileObject - Supplies the file object associated with the mailslot.
FileName - Supplies the name of the mailslot (not qualified i.e., simply "mailslot-name" and not "\mailslot-name".
DesiredAccess - Supplies the caller's desired access.
CreateDisposition - Supplies the caller's create disposition flags.
ShareAccess - Supplies the caller specified share access.
MailslotQuota - Supplies the mailslot quota amount.
MaximumMessageSize - Supplies the size of the largest message that can be written to this mailslot.
CreatorProcess - Supplies the process creating the mailslot.
Return Value:
IO_STATUS_BLOCK - Returns the status of the operation.
--*/
{
IO_STATUS_BLOCK iosb={0}; PFCB fcb; NTSTATUS status;
PAGED_CODE(); DebugTrace(+1, Dbg, "MsCreateMailslot\n", 0 );
//
// Check the parameters that must be supplied for a mailslot
//
if (CreateDisposition == FILE_OPEN) { iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND; return iosb; }
//
// Create a new FCB for the mailslot.
//
status = MsCreateFcb( RootDcb->Vcb, RootDcb, &FileName, CreatorProcess, MailslotQuota, MaximumMessageSize, &fcb );
if (!NT_SUCCESS (status)) { iosb.Status = status; return iosb; }
fcb->Specific.Fcb.ReadTimeout = ReadTimeout;
//
// Set the security descriptor in the Fcb
//
SeLockSubjectContext( &AccessState->SubjectSecurityContext );
status = SeAssignSecurity( NULL, AccessState->SecurityDescriptor, &fcb->SecurityDescriptor, FALSE, &AccessState->SubjectSecurityContext, IoGetFileObjectGenericMapping(), PagedPool );
SeUnlockSubjectContext( &AccessState->SubjectSecurityContext );
if (!NT_SUCCESS(status)) {
DebugTrace(0, Dbg, "Error calling SeAssignSecurity\n", 0 );
MsRemoveFcbName( fcb ); MsDereferenceFcb( fcb ); iosb.Status = status; return iosb; }
//
// Set the new share access.
//
ASSERT (MsIsAcquiredExclusiveVcb(fcb->Vcb)); IoSetShareAccess( DesiredAccess, ShareAccess, FileObject, &fcb->ShareAccess );
//
// Set the file object back pointers and our pointer to the
// server file object.
//
MsSetFileObject( FileObject, fcb, NULL );
fcb->FileObject = FileObject;
//
// Update the FCB timestamps.
//
KeQuerySystemTime( &fcb->Specific.Fcb.CreationTime ); fcb->Specific.Fcb.LastModificationTime = fcb->Specific.Fcb.CreationTime; fcb->Specific.Fcb.LastAccessTime = fcb->Specific.Fcb.CreationTime; fcb->Specific.Fcb.LastChangeTime = fcb->Specific.Fcb.CreationTime;
//
// Set the return status.
//
iosb.Status = STATUS_SUCCESS; iosb.Information = FILE_CREATED;
//
// The root directory has changed. Complete any notify change
// directory requests.
//
MsCheckForNotify( fcb->ParentDcb, TRUE, STATUS_SUCCESS );
//
// Return to the caller.
//
DebugTrace(-1, Dbg, "MsCreateMailslot -> %08lx\n", iosb.Status); return iosb; }
BOOLEAN MsIsNameValid ( PUNICODE_STRING Name )
/*++
Routine Description:
This routine tests for illegal characters in a name. The same character set as Npfs/Ntfs is used. Also preceding backslashes, wildcards, and path names are not allowed.
Arguments:
Name - The name to search for illegal characters
Return Value:
BOOLEAN - TRUE if the name is valid, FALSE otherwise.
--*/
{ ULONG i; WCHAR Char = L'\\';
PAGED_CODE(); for (i=0; i < Name->Length / sizeof(WCHAR); i += 1) {
Char = Name->Buffer[i];
if ( (Char <= 0xff) && (Char != L'\\') && !FsRtlIsAnsiCharacterLegalNtfs(Char, FALSE) ) {
return FALSE; } }
//
// If the last char of the name was slash, we have an illegal name
//
return (Char != L'\\'); }
|