diff options
Diffstat (limited to 'private/ntos/afd/create.c')
-rw-r--r-- | private/ntos/afd/create.c | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/private/ntos/afd/create.c b/private/ntos/afd/create.c new file mode 100644 index 000000000..7b2cf5a39 --- /dev/null +++ b/private/ntos/afd/create.c @@ -0,0 +1,298 @@ +/*++ + +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 + |