summaryrefslogblamecommitdiffstats
path: root/private/ntos/afd/create.c
blob: 7b2cf5a39028516086f65a817a6b314211469069 (plain) (tree)









































































































































































































































































































                                                                                            
/*++

Copyright (c) 1989  Microsoft Corporation

Module Name:

    dispatch.c

Abstract:

    This module contains code for opening a handle to AFD.

Author:

    David Treadwell (davidtr)    21-Feb-1992

Revision History:

--*/

#include "afdp.h"

#ifdef ALLOC_PRAGMA
#pragma alloc_text( PAGE, AfdCreate )
#endif

extern PSECURITY_DESCRIPTOR AfdRawSecurityDescriptor;



NTSTATUS
AfdCreate (
    IN PIRP Irp,
    IN PIO_STACK_LOCATION IrpSp
    )

/*++

Routine Description:

    This is the routine that handles Create IRPs in AFD.  If creates an
    AFD_ENDPOINT structure and fills it in with the information
    specified in the open packet.

Arguments:

    Irp - Pointer to I/O request packet.

    IrpSp - pointer to the IO stack location to use for this request.

Return Value:

    NTSTATUS -- Indicates whether the request was successfully queued.

--*/

{
    PAFD_OPEN_PACKET openPacket;
    PAFD_ENDPOINT endpoint;
    PFILE_FULL_EA_INFORMATION eaBuffer;
    UNICODE_STRING transportDeviceName;
    NTSTATUS status;

    PAGED_CODE( );

    DEBUG endpoint = NULL;

    //
    // Find the open packet from the EA buffer in the system buffer of
    // the associated IRP.  Fail the request if there was no EA
    // buffer specified.
    //

    eaBuffer = Irp->AssociatedIrp.SystemBuffer;

    if ( eaBuffer == NULL ) {

        //
        // Allocate an AFD "helper" endpoint.
        //

        status = AfdAllocateEndpoint(
                     &endpoint,
                     NULL,
                     0
                     );

        if( !NT_SUCCESS(status) ) {
            return status;
        }

    } else {

        openPacket = (PAFD_OPEN_PACKET)(eaBuffer->EaName +
                                            eaBuffer->EaNameLength + 1);

        //
        // Validate parameters in the open packet.
        //

        if ( openPacket->EndpointType < MIN_AFD_ENDPOINT_TYPE ||
                 openPacket->EndpointType > MAX_AFD_ENDPOINT_TYPE ) {
            return STATUS_INVALID_PARAMETER;
        }

        //
        // Make sure that the transport address fits within the specified
        // EA buffer.
        //

        if ( eaBuffer->EaValueLength <
                 sizeof(AFD_OPEN_PACKET) + openPacket->TransportDeviceNameLength ) {
            return STATUS_ACCESS_VIOLATION;
        }

        //
        // Set up a string that describes the transport device name.
        //

        transportDeviceName.Buffer = openPacket->TransportDeviceName;
        transportDeviceName.Length = (USHORT)openPacket->TransportDeviceNameLength;
        transportDeviceName.MaximumLength =
            transportDeviceName.Length + sizeof(WCHAR);

        //
        // If this is an open of a  raw endpoint, perform an access check.
        //
        if ( ( openPacket->EndpointType == AfdEndpointTypeRaw ) &&
             !AfdDisableRawSecurity
           )
        {
            BOOLEAN               accessGranted;
            PACCESS_STATE         accessState;
            PIO_SECURITY_CONTEXT  securityContext;
            NTSTATUS              status;
            PPRIVILEGE_SET        privileges = NULL;
            ACCESS_MASK           grantedAccess;


            securityContext = IrpSp->Parameters.Create.SecurityContext;
            accessState = securityContext->AccessState;

            SeLockSubjectContext(&accessState->SubjectSecurityContext);

            accessGranted = SeAccessCheck(
                                AfdRawSecurityDescriptor,
                                &accessState->SubjectSecurityContext,
                                TRUE,
                                IrpSp->Parameters.Create.SecurityContext->DesiredAccess,
                                0,
                                &privileges,
                                IoGetFileObjectGenericMapping(),
                                UserMode,
                                &grantedAccess,
                                &status
                                );


            if (privileges) {
                (VOID) SeAppendPrivileges(
                           accessState,
                           privileges
                           );
                SeFreePrivileges(privileges);
            }

            if (accessGranted) {
                accessState->PreviouslyGrantedAccess |= grantedAccess;
                accessState->RemainingDesiredAccess &= ~( grantedAccess | MAXIMUM_ALLOWED );
            }

            SeUnlockSubjectContext(&accessState->SubjectSecurityContext);

            if (!accessGranted) {
                return STATUS_ACCESS_DENIED;
            }
        }

        //
        // Allocate an AFD endpoint.
        //

        status = AfdAllocateEndpoint(
                     &endpoint,
                     &transportDeviceName,
                     openPacket->GroupID
                     );

        if( !NT_SUCCESS(status) ) {
            return status;
        }
    }

    ASSERT( endpoint != NULL );

    //
    // Set up a pointer to the endpoint in the file object so that we
    // can find the endpoint in future calls.
    //

    IrpSp->FileObject->FsContext = endpoint;

    IF_DEBUG(OPEN_CLOSE) {
        KdPrint(( "AfdCreate: opened file object = %lx, endpoint = %lx\n",
                      IrpSp->FileObject, endpoint ));

    }

    //
    // Remember the type of endpoint that this is.  If this is a datagram
    // endpoint, change the block type to reflect this.
    //

    if ( eaBuffer != NULL ) {
        if (openPacket->EndpointType == AfdEndpointTypeRaw) {
            //
            // There is no other distinction between a raw endpoint and
            // a datagram endpoint, so we mark them all as datagram.
            //
            endpoint->EndpointType = AfdEndpointTypeDatagram;
        }
        else {
            endpoint->EndpointType = openPacket->EndpointType;
        }
    }

    if ( IS_DGRAM_ENDPOINT(endpoint) ) {

        if ( eaBuffer == NULL ) {

           DEREFERENCE_ENDPOINT( endpoint );
           AfdCloseEndpoint( endpoint );

           return STATUS_INVALID_PARAMETER;
        }

        endpoint->Type = AfdBlockTypeDatagram;

        //
        // Initialize lists which exist only in datagram endpoints.
        //

        InitializeListHead( &endpoint->ReceiveDatagramIrpListHead );
        InitializeListHead( &endpoint->PeekDatagramIrpListHead );
        InitializeListHead( &endpoint->ReceiveDatagramBufferListHead );

        //
        // Charge quota for the endpoint to account for the data
        // bufferring we'll do on behalf of the process.
        //

        try {

            PsChargePoolQuota(
                endpoint->OwningProcess,
                NonPagedPool,
                AfdReceiveWindowSize + AfdSendWindowSize
                );
            AfdRecordQuotaHistory(
                endpoint->OwningProcess,
                (LONG)(AfdReceiveWindowSize + AfdSendWindowSize),
                "Create dgram",
                endpoint
                );
            AfdRecordPoolQuotaCharged(
                AfdReceiveWindowSize + AfdSendWindowSize
                );

        } except ( EXCEPTION_EXECUTE_HANDLER ) {

#if DBG
           DbgPrint( "AfdCreate: PsChargePoolQuota failed.\n" );
#endif

           DEREFERENCE_ENDPOINT( endpoint );
           AfdCloseEndpoint( endpoint );

           return STATUS_QUOTA_EXCEEDED;
        }

        endpoint->Common.Datagram.MaxBufferredReceiveBytes = AfdReceiveWindowSize;
        endpoint->Common.Datagram.MaxBufferredReceiveCount =
            (CSHORT)(AfdReceiveWindowSize / AfdBufferMultiplier);
        endpoint->Common.Datagram.MaxBufferredSendBytes = AfdSendWindowSize;
        endpoint->Common.Datagram.MaxBufferredSendCount =
            (CSHORT)(AfdSendWindowSize / AfdBufferMultiplier);
    }

    //
    // The open worked.  Dereference the endpoint and return success.
    //

    DEREFERENCE_ENDPOINT( endpoint );

    return STATUS_SUCCESS;

} // AfdCreate