mirror of
https://github.com/reactos/reactos.git
synced 2024-06-03 11:11:54 +00:00
309 lines
11 KiB
C
309 lines
11 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* FILE: drivers/net/afd/afd/info.c
|
|
* PURPOSE: Ancillary functions driver
|
|
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
|
|
* UPDATE HISTORY:
|
|
* 20040708 Created
|
|
*/
|
|
|
|
#include "afd.h"
|
|
|
|
NTSTATUS NTAPI
|
|
AfdGetInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|
PIO_STACK_LOCATION IrpSp ) {
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PAFD_INFO InfoReq = LockRequest(Irp, IrpSp, TRUE, NULL);
|
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
|
PAFD_FCB FCB = FileObject->FsContext;
|
|
PLIST_ENTRY CurrentEntry;
|
|
|
|
UNREFERENCED_PARAMETER(DeviceObject);
|
|
|
|
AFD_DbgPrint(MID_TRACE,("Called %p %x\n", InfoReq,
|
|
InfoReq ? InfoReq->InformationClass : 0));
|
|
|
|
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
|
|
|
|
if (!InfoReq)
|
|
return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
|
|
|
|
_SEH2_TRY {
|
|
switch( InfoReq->InformationClass ) {
|
|
case AFD_INFO_RECEIVE_WINDOW_SIZE:
|
|
InfoReq->Information.Ulong = FCB->Recv.Size;
|
|
break;
|
|
|
|
case AFD_INFO_SEND_WINDOW_SIZE:
|
|
InfoReq->Information.Ulong = FCB->Send.Size;
|
|
AFD_DbgPrint(MID_TRACE,("Send window size %u\n", FCB->Send.Size));
|
|
break;
|
|
|
|
case AFD_INFO_GROUP_ID_TYPE:
|
|
InfoReq->Information.LargeInteger.u.HighPart = FCB->GroupType;
|
|
InfoReq->Information.LargeInteger.u.LowPart = FCB->GroupID;
|
|
AFD_DbgPrint(MID_TRACE, ("Group ID: %u Group Type: %u\n", FCB->GroupID, FCB->GroupType));
|
|
break;
|
|
|
|
case AFD_INFO_BLOCKING_MODE:
|
|
InfoReq->Information.Boolean = FCB->NonBlocking;
|
|
break;
|
|
|
|
case AFD_INFO_INLINING_MODE:
|
|
InfoReq->Information.Boolean = FCB->OobInline;
|
|
break;
|
|
|
|
case AFD_INFO_RECEIVE_CONTENT_SIZE:
|
|
InfoReq->Information.Ulong = FCB->Recv.Content - FCB->Recv.BytesUsed;
|
|
break;
|
|
|
|
case AFD_INFO_SENDS_IN_PROGRESS:
|
|
InfoReq->Information.Ulong = 0;
|
|
|
|
/* Count the queued sends */
|
|
CurrentEntry = FCB->PendingIrpList[FUNCTION_SEND].Flink;
|
|
while (CurrentEntry != &FCB->PendingIrpList[FUNCTION_SEND])
|
|
{
|
|
InfoReq->Information.Ulong++;
|
|
CurrentEntry = CurrentEntry->Flink;
|
|
}
|
|
|
|
/* This needs to count too because when this is dispatched
|
|
* the user-mode IRP has already been completed and therefore
|
|
* will NOT be in our pending IRP list. We count this as one send
|
|
* outstanding although it could be multiple since we batch sends
|
|
* when waiting for the in flight request to return, so this number
|
|
* may not be accurate but it really doesn't matter that much since
|
|
* it's more or less a zero/non-zero comparison to determine whether
|
|
* we can shutdown the socket
|
|
*/
|
|
if (FCB->SendIrp.InFlightRequest)
|
|
InfoReq->Information.Ulong++;
|
|
break;
|
|
|
|
default:
|
|
AFD_DbgPrint(MIN_TRACE,("Unknown info id %x\n",
|
|
InfoReq->InformationClass));
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
|
AFD_DbgPrint(MIN_TRACE,("Exception executing GetInfo\n"));
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
} _SEH2_END;
|
|
|
|
AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
|
|
|
|
return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
|
|
}
|
|
|
|
NTSTATUS NTAPI
|
|
AfdSetInfo( PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|
PIO_STACK_LOCATION IrpSp ) {
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PAFD_INFO InfoReq = LockRequest(Irp, IrpSp, FALSE, NULL);
|
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
|
PAFD_FCB FCB = FileObject->FsContext;
|
|
PCHAR NewBuffer;
|
|
|
|
UNREFERENCED_PARAMETER(DeviceObject);
|
|
|
|
if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
|
|
|
|
if (!InfoReq)
|
|
return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
|
|
|
|
_SEH2_TRY {
|
|
switch (InfoReq->InformationClass) {
|
|
case AFD_INFO_BLOCKING_MODE:
|
|
AFD_DbgPrint(MID_TRACE,("Blocking mode set to %u\n", InfoReq->Information.Boolean));
|
|
FCB->NonBlocking = InfoReq->Information.Boolean;
|
|
break;
|
|
case AFD_INFO_INLINING_MODE:
|
|
FCB->OobInline = InfoReq->Information.Boolean;
|
|
break;
|
|
case AFD_INFO_RECEIVE_WINDOW_SIZE:
|
|
if (FCB->State == SOCKET_STATE_CONNECTED ||
|
|
FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)
|
|
{
|
|
/* FIXME: likely not right, check tcpip.sys for TDI_QUERY_MAX_DATAGRAM_INFO */
|
|
if (InfoReq->Information.Ulong > 0 && InfoReq->Information.Ulong < 0xFFFF &&
|
|
InfoReq->Information.Ulong != FCB->Recv.Size)
|
|
{
|
|
NewBuffer = ExAllocatePoolWithTag(PagedPool,
|
|
InfoReq->Information.Ulong,
|
|
TAG_AFD_DATA_BUFFER);
|
|
|
|
if (NewBuffer)
|
|
{
|
|
if (FCB->Recv.Content > InfoReq->Information.Ulong)
|
|
FCB->Recv.Content = InfoReq->Information.Ulong;
|
|
|
|
if (FCB->Recv.Window)
|
|
{
|
|
RtlCopyMemory(NewBuffer,
|
|
FCB->Recv.Window,
|
|
FCB->Recv.Content);
|
|
|
|
ExFreePoolWithTag(FCB->Recv.Window, TAG_AFD_DATA_BUFFER);
|
|
}
|
|
|
|
FCB->Recv.Size = InfoReq->Information.Ulong;
|
|
FCB->Recv.Window = NewBuffer;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
break;
|
|
case AFD_INFO_SEND_WINDOW_SIZE:
|
|
if (FCB->State == SOCKET_STATE_CONNECTED ||
|
|
FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)
|
|
{
|
|
if (InfoReq->Information.Ulong > 0 && InfoReq->Information.Ulong < 0xFFFF &&
|
|
InfoReq->Information.Ulong != FCB->Send.Size)
|
|
{
|
|
NewBuffer = ExAllocatePoolWithTag(PagedPool,
|
|
InfoReq->Information.Ulong,
|
|
TAG_AFD_DATA_BUFFER);
|
|
|
|
if (NewBuffer)
|
|
{
|
|
if (FCB->Send.BytesUsed > InfoReq->Information.Ulong)
|
|
FCB->Send.BytesUsed = InfoReq->Information.Ulong;
|
|
|
|
if (FCB->Send.Window)
|
|
{
|
|
RtlCopyMemory(NewBuffer,
|
|
FCB->Send.Window,
|
|
FCB->Send.BytesUsed);
|
|
|
|
ExFreePoolWithTag(FCB->Send.Window, TAG_AFD_DATA_BUFFER);
|
|
}
|
|
|
|
FCB->Send.Size = InfoReq->Information.Ulong;
|
|
FCB->Send.Window = NewBuffer;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_NO_MEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
break;
|
|
default:
|
|
AFD_DbgPrint(MIN_TRACE,("Unknown request %u\n", InfoReq->InformationClass));
|
|
break;
|
|
}
|
|
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
|
AFD_DbgPrint(MIN_TRACE,("Exception executing SetInfo\n"));
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
} _SEH2_END;
|
|
|
|
AFD_DbgPrint(MID_TRACE,("Returning %x\n", Status));
|
|
|
|
return UnlockAndMaybeComplete(FCB, Status, Irp, 0);
|
|
}
|
|
|
|
NTSTATUS NTAPI
|
|
AfdGetSockName( PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|
PIO_STACK_LOCATION IrpSp ) {
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
|
PAFD_FCB FCB = FileObject->FsContext;
|
|
PMDL Mdl = NULL;
|
|
|
|
UNREFERENCED_PARAMETER(DeviceObject);
|
|
ASSERT(Irp->MdlAddress == NULL);
|
|
|
|
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
|
|
|
|
if( FCB->AddressFile.Object == NULL && FCB->Connection.Object == NULL ) {
|
|
return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 );
|
|
}
|
|
|
|
Mdl = IoAllocateMdl( Irp->UserBuffer,
|
|
IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
|
|
FALSE,
|
|
FALSE,
|
|
NULL );
|
|
|
|
if( Mdl != NULL ) {
|
|
_SEH2_TRY {
|
|
MmProbeAndLockPages( Mdl, Irp->RequestorMode, IoModifyAccess );
|
|
} _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
|
|
AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
|
|
Status = _SEH2_GetExceptionCode();
|
|
} _SEH2_END;
|
|
|
|
if( NT_SUCCESS(Status) ) {
|
|
Status = TdiQueryInformation( FCB->Connection.Object
|
|
? FCB->Connection.Object
|
|
: FCB->AddressFile.Object,
|
|
TDI_QUERY_ADDRESS_INFO,
|
|
Mdl );
|
|
}
|
|
|
|
/* Check if MmProbeAndLockPages or TdiQueryInformation failed and
|
|
* clean up Mdl */
|
|
if (!NT_SUCCESS(Status) && Irp->MdlAddress != Mdl)
|
|
IoFreeMdl(Mdl);
|
|
} else
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
|
|
}
|
|
|
|
NTSTATUS NTAPI
|
|
AfdGetPeerName( PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|
PIO_STACK_LOCATION IrpSp ) {
|
|
NTSTATUS Status;
|
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
|
PAFD_FCB FCB = FileObject->FsContext;
|
|
|
|
UNREFERENCED_PARAMETER(DeviceObject);
|
|
|
|
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
|
|
|
|
if (FCB->RemoteAddress == NULL) {
|
|
AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
|
|
return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, Irp, 0 );
|
|
}
|
|
|
|
if (IrpSp->Parameters.DeviceIoControl.OutputBufferLength >= TaLengthOfTransportAddress(FCB->RemoteAddress))
|
|
{
|
|
RtlCopyMemory(Irp->UserBuffer, FCB->RemoteAddress, TaLengthOfTransportAddress(FCB->RemoteAddress));
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
AFD_DbgPrint(MIN_TRACE,("Buffer too small\n"));
|
|
Status = STATUS_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
|
|
}
|