299 lines
7.8 KiB
C
299 lines
7.8 KiB
C
/*++
|
||
|
||
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
|
||
|