Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

593 lines
15 KiB

/*++
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.
//
try {
status = MsCommonCreateMailslot( MsfsDeviceObject, Irp );
} except(MsExceptionFilter( GetExceptionCode() )) {
//
// We had some trouble trying to perform the requested
// operation, so we'll abort the I/O request with
// the error status that we get back from the
// execption code.
//
status = MsProcessException( MsfsDeviceObject, Irp, GetExceptionCode() );
}
//
// 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) {
DebugTrace(0, Dbg, "Bad file name\n", 0);
MsCompleteRequest( Irp, STATUS_OBJECT_NAME_INVALID );
try_return( status = STATUS_OBJECT_NAME_INVALID );
}
fcb = MsFindRelativePrefix(
dcb,
&fileName,
caseInsensitive,
&remainingPart
);
} 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);
MsCompleteRequest( Irp, STATUS_OBJECT_NAME_INVALID );
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;
}
}
//
// Complete the IRP and return to the caller.
//
MsCompleteRequest( Irp, status );
try_return( NOTHING );
try_exit: NOTHING;
} finally {
MsReleaseVcb( vcb );
}
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.
--*/
{
// FIX, FIX - TEMPORARY ONLY.
UCHAR SDBody[SECURITY_DESCRIPTOR_MIN_LENGTH];
PSECURITY_DESCRIPTOR TmpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&SDBody[0]);
// FIX, FIX - TEMPORARY ONLY.
IO_STATUS_BLOCK iosb;
PFCB fcb;
PAGED_CODE();
DebugTrace(+1, Dbg, "MsCreateMailslot\n", 0 );
fcb = NULL;
iosb.Status = STATUS_UNSUCCESSFUL;
try {
//
// Check the parameters that must be supplied for a mailslot
//
if (CreateDisposition == FILE_OPEN) {
try_return( iosb.Status = STATUS_OBJECT_NAME_NOT_FOUND );
}
//
// Create a new FCB for the mailslot.
//
fcb = MsCreateFcb( RootDcb->Vcb,
RootDcb,
&FileName,
CreatorProcess,
MailslotQuota,
MaximumMessageSize );
fcb->Specific.Fcb.ReadTimeout = ReadTimeout;
//
// Set the security descriptor in the Fcb
//
SeLockSubjectContext( &AccessState->SubjectSecurityContext );
iosb.Status = SeAssignSecurity( NULL,
AccessState->SecurityDescriptor,
&fcb->SecurityDescriptor,
FALSE,
&AccessState->SubjectSecurityContext,
IoGetFileObjectGenericMapping(),
PagedPool );
SeUnlockSubjectContext( &AccessState->SubjectSecurityContext );
if (!NT_SUCCESS(iosb.Status)) {
DebugTrace(0, Dbg, "Error calling SeAssignSecurity\n", 0 );
try_return( iosb.Status );
}
//
// Set the new share access.
//
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 );
try_exit: NOTHING;
} finally {
//
// Now if we ever terminate the preceding try-statement with
// a status that is not successful and the FCB pointer
// is non-null then we need to deallocate the structure.
//
if (!NT_SUCCESS(iosb.Status) && fcb != NULL) {
//
// Remove the Fcb from the prefix table.
//
MsAcquirePrefixTableLock();
RtlRemoveUnicodePrefix( &fcb->Vcb->PrefixTable, &fcb->PrefixTableEntry );
MsReleasePrefixTableLock();
//
// Remove the Fcb from our parent DCB's queue.
//
RemoveEntryList( &fcb->ParentDcbLinks );
MsDeleteFcb( fcb );
}
}
//
// 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;
PAGED_CODE();
for (i=0; i < Name->Length / sizeof(WCHAR); i += 1) {
WCHAR Char = Name->Buffer[i];
if ( (Char <= 0xff) && (Char != L'\\') &&
!FsRtlIsAnsiCharacterLegalNtfs(Char, FALSE) ) {
return FALSE;
}
}
return TRUE;
}