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'\\');
|
|||
|
}
|