558 lines
14 KiB
C
558 lines
14 KiB
C
/*++
|
||
|
||
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'\\');
|
||
}
|