mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 18:23:21 +00:00
536 lines
15 KiB
C
536 lines
15 KiB
C
/* $Id$
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* FILE: drivers/net/afd/afd/main.c
|
|
* PURPOSE: Ancillary functions driver
|
|
* PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
|
|
* UPDATE HISTORY:
|
|
* 20040630 Created
|
|
*
|
|
* Suggestions: Uniform naming (AfdXxx)
|
|
*/
|
|
|
|
/* INCLUDES */
|
|
|
|
#include "afd.h"
|
|
#include "tdi_proto.h"
|
|
#include "tdiconn.h"
|
|
#include "debug.h"
|
|
|
|
#ifdef DBG
|
|
|
|
/* See debug.h for debug/trace constants */
|
|
//DWORD DebugTraceLevel = DEBUG_ULTRA;
|
|
DWORD DebugTraceLevel = 0;
|
|
|
|
#endif /* DBG */
|
|
|
|
void OskitDumpBuffer( PCHAR Data, UINT Len ) {
|
|
unsigned int i;
|
|
|
|
for( i = 0; i < Len; i++ ) {
|
|
if( i && !(i & 0xf) ) DbgPrint( "\n" );
|
|
if( !(i & 0xf) ) DbgPrint( "%08x: ", (UINT)(Data + i) );
|
|
DbgPrint( " %02x", Data[i] & 0xff );
|
|
}
|
|
DbgPrint("\n");
|
|
}
|
|
|
|
/* FUNCTIONS */
|
|
|
|
NTSTATUS STDCALL
|
|
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
|
|
|
|
static NTSTATUS STDCALL
|
|
AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|
PIO_STACK_LOCATION IrpSp) {
|
|
PAFD_FCB FCB;
|
|
PFILE_OBJECT FileObject;
|
|
PAFD_DEVICE_EXTENSION DeviceExt;
|
|
PFILE_FULL_EA_INFORMATION EaInfo;
|
|
PAFD_CREATE_PACKET ConnectInfo = NULL;
|
|
ULONG EaLength;
|
|
PWCHAR EaInfoValue = NULL;
|
|
UINT Disposition, i;
|
|
|
|
AFD_DbgPrint(MID_TRACE,
|
|
("AfdCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
|
|
|
|
DeviceExt = DeviceObject->DeviceExtension;
|
|
FileObject = IrpSp->FileObject;
|
|
Disposition = (IrpSp->Parameters.Create.Options >> 24) & 0xff;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
EaInfo = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
if( EaInfo ) {
|
|
ConnectInfo = (PAFD_CREATE_PACKET)(EaInfo->EaName + EaInfo->EaNameLength + 1);
|
|
EaInfoValue = (PWCHAR)(((PCHAR)ConnectInfo) + sizeof(AFD_CREATE_PACKET));
|
|
|
|
EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
|
|
EaInfo->EaNameLength +
|
|
EaInfo->EaValueLength;
|
|
|
|
AFD_DbgPrint(MID_TRACE,("EaInfo: %x, EaInfoValue: %x\n",
|
|
EaInfo, EaInfoValue));
|
|
}
|
|
|
|
AFD_DbgPrint(MID_TRACE,("About to allocate the new FCB\n"));
|
|
|
|
FCB = ExAllocatePool(NonPagedPool, sizeof(AFD_FCB));
|
|
if( FCB == NULL ) {
|
|
Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
AFD_DbgPrint(MID_TRACE,("Initializing the new FCB @ %x (FileObject %x Flags %x)\n", FCB, FileObject, ConnectInfo ? ConnectInfo->EndpointFlags : 0));
|
|
|
|
RtlZeroMemory( FCB, sizeof( *FCB ) );
|
|
|
|
FCB->Flags = ConnectInfo ? ConnectInfo->EndpointFlags : 0;
|
|
FCB->State = SOCKET_STATE_CREATED;
|
|
FCB->FileObject = FileObject;
|
|
FCB->DeviceExt = DeviceExt;
|
|
FCB->Recv.Size = DEFAULT_RECEIVE_WINDOW_SIZE;
|
|
FCB->Send.Size = DEFAULT_SEND_WINDOW_SIZE;
|
|
|
|
KeInitializeSpinLock( &FCB->SpinLock );
|
|
ExInitializeFastMutex( &FCB->Mutex );
|
|
KeInitializeEvent( &FCB->StateLockedEvent, NotificationEvent, FALSE );
|
|
|
|
for( i = 0; i < MAX_FUNCTIONS; i++ ) {
|
|
InitializeListHead( &FCB->PendingIrpList[i] );
|
|
}
|
|
|
|
InitializeListHead( &FCB->DatagramList );
|
|
InitializeListHead( &FCB->PendingConnections );
|
|
|
|
AFD_DbgPrint(MID_TRACE,("%x: Checking command channel\n", FCB));
|
|
|
|
if( ConnectInfo ) {
|
|
FCB->TdiDeviceName.Length = ConnectInfo->SizeOfTransportName;
|
|
FCB->TdiDeviceName.MaximumLength = FCB->TdiDeviceName.Length;
|
|
FCB->TdiDeviceName.Buffer =
|
|
ExAllocatePool( NonPagedPool, FCB->TdiDeviceName.Length );
|
|
RtlCopyMemory( FCB->TdiDeviceName.Buffer,
|
|
ConnectInfo->TransportName,
|
|
FCB->TdiDeviceName.Length );
|
|
|
|
if( !FCB->TdiDeviceName.Buffer ) {
|
|
ExFreePool(FCB);
|
|
AFD_DbgPrint(MID_TRACE,("Could not copy target string\n"));
|
|
Irp->IoStatus.Status = STATUS_NO_MEMORY;
|
|
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
|
|
AFD_DbgPrint(MID_TRACE,("Success: %s %wZ\n",
|
|
EaInfo->EaName, &FCB->TdiDeviceName));
|
|
} else {
|
|
AFD_DbgPrint(MID_TRACE,("Success: Control connection\n"));
|
|
}
|
|
|
|
FileObject->FsContext = FCB;
|
|
|
|
/* It seems that UDP sockets are writable from inception */
|
|
if( FCB->Flags & SGID_CONNECTIONLESS ) {
|
|
AFD_DbgPrint(MID_TRACE,("Packet oriented socket\n"));
|
|
/* Allocate our backup buffer */
|
|
FCB->Recv.Window = ExAllocatePool( NonPagedPool, FCB->Recv.Size );
|
|
FCB->Send.Window = ExAllocatePool( NonPagedPool, FCB->Send.Size );
|
|
/* A datagram socket is always sendable */
|
|
FCB->PollState |= AFD_EVENT_SEND;
|
|
PollReeval( FCB->DeviceExt, FCB->FileObject );
|
|
}
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID DestroySocket( PAFD_FCB FCB ) {
|
|
UINT i;
|
|
BOOLEAN ReturnEarly = FALSE;
|
|
PAFD_IN_FLIGHT_REQUEST InFlightRequest[IN_FLIGHT_REQUESTS];
|
|
|
|
AFD_DbgPrint(MIN_TRACE,("Called (%x)\n", FCB));
|
|
|
|
if( !SocketAcquireStateLock( FCB ) ) return;
|
|
|
|
FCB->State = SOCKET_STATE_CLOSED;
|
|
|
|
InFlightRequest[0] = &FCB->ListenIrp;
|
|
InFlightRequest[1] = &FCB->ReceiveIrp;
|
|
InFlightRequest[2] = &FCB->SendIrp;
|
|
InFlightRequest[3] = &FCB->ConnectIrp;
|
|
|
|
/* Return early here because we might be called in the mean time. */
|
|
if( FCB->Critical ||
|
|
FCB->ListenIrp.InFlightRequest ||
|
|
FCB->ReceiveIrp.InFlightRequest ||
|
|
FCB->SendIrp.InFlightRequest ||
|
|
FCB->ConnectIrp.InFlightRequest ) {
|
|
AFD_DbgPrint(MIN_TRACE,("Leaving socket alive (%x %x %x %x)\n",
|
|
FCB->ListenIrp.InFlightRequest,
|
|
FCB->ReceiveIrp.InFlightRequest,
|
|
FCB->SendIrp.InFlightRequest,
|
|
FCB->ConnectIrp.InFlightRequest));
|
|
ReturnEarly = TRUE;
|
|
}
|
|
|
|
/* After PoolReeval, this FCB should not be involved in any outstanding
|
|
* poll requests */
|
|
|
|
/* Cancel our pending requests */
|
|
for( i = 0; i < IN_FLIGHT_REQUESTS; i++ ) {
|
|
if( InFlightRequest[i]->InFlightRequest ) {
|
|
AFD_DbgPrint(MID_TRACE,("Cancelling in flight irp %d (%x)\n",
|
|
i, InFlightRequest[i]->InFlightRequest));
|
|
InFlightRequest[i]->InFlightRequest->IoStatus.Status = STATUS_CANCELLED;
|
|
InFlightRequest[i]->InFlightRequest->IoStatus.Information = 0;
|
|
IoCancelIrp( InFlightRequest[i]->InFlightRequest );
|
|
}
|
|
}
|
|
|
|
SocketStateUnlock( FCB );
|
|
|
|
if( ReturnEarly ) return;
|
|
|
|
if( FCB->Recv.Window )
|
|
ExFreePool( FCB->Recv.Window );
|
|
if( FCB->Send.Window )
|
|
ExFreePool( FCB->Send.Window );
|
|
if( FCB->AddressFrom )
|
|
ExFreePool( FCB->AddressFrom );
|
|
if( FCB->LocalAddress )
|
|
ExFreePool( FCB->LocalAddress );
|
|
if( FCB->RemoteAddress )
|
|
ExFreePool( FCB->RemoteAddress );
|
|
|
|
ExFreePool(FCB->TdiDeviceName.Buffer);
|
|
|
|
ExFreePool(FCB);
|
|
AFD_DbgPrint(MIN_TRACE,("Deleted (%x)\n", FCB));
|
|
|
|
AFD_DbgPrint(MIN_TRACE,("Leaving\n"));
|
|
}
|
|
|
|
static NTSTATUS STDCALL
|
|
AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|
PIO_STACK_LOCATION IrpSp)
|
|
{
|
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
|
PAFD_FCB FCB = FileObject->FsContext;
|
|
|
|
AFD_DbgPrint(MID_TRACE,
|
|
("AfdClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
|
|
|
|
AFD_DbgPrint(MID_TRACE,("FCB %x\n", FCB));
|
|
|
|
FCB->PollState |= AFD_EVENT_CLOSE;
|
|
PollReeval( FCB->DeviceExt, FileObject );
|
|
KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
|
|
|
|
if( FCB->EventSelect ) ObDereferenceObject( FCB->EventSelect );
|
|
|
|
FileObject->FsContext = NULL;
|
|
DestroySocket( FCB );
|
|
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
AFD_DbgPrint(MID_TRACE, ("Returning success.\n"));
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
static NTSTATUS STDCALL
|
|
AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
|
|
PIO_STACK_LOCATION IrpSp) {
|
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
|
PAFD_FCB FCB = FileObject->FsContext;
|
|
PAFD_DISCONNECT_INFO DisReq;
|
|
IO_STATUS_BLOCK Iosb;
|
|
PTDI_CONNECTION_INFORMATION ConnInfo;
|
|
NTSTATUS Status;
|
|
USHORT Flags = 0;
|
|
|
|
if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
|
|
|
|
if( !(DisReq = LockRequest( Irp, IrpSp )) )
|
|
return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
|
|
Irp, 0, NULL );
|
|
|
|
if (NULL == FCB->RemoteAddress)
|
|
{
|
|
ConnInfo = NULL;
|
|
}
|
|
else
|
|
{
|
|
Status = TdiBuildNullConnectionInfo
|
|
( &ConnInfo, FCB->RemoteAddress->Address[0].AddressType );
|
|
|
|
if( !NT_SUCCESS(Status) || !ConnInfo )
|
|
return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
|
|
Irp, 0, NULL );
|
|
}
|
|
|
|
if( DisReq->DisconnectType & AFD_DISCONNECT_SEND )
|
|
Flags |= TDI_DISCONNECT_RELEASE;
|
|
if( DisReq->DisconnectType & AFD_DISCONNECT_RECV ||
|
|
DisReq->DisconnectType & AFD_DISCONNECT_ABORT )
|
|
Flags |= TDI_DISCONNECT_ABORT;
|
|
|
|
Status = TdiDisconnect( FCB->Connection.Object,
|
|
&DisReq->Timeout,
|
|
Flags,
|
|
&Iosb,
|
|
NULL,
|
|
NULL,
|
|
FCB->AddressFrom,
|
|
ConnInfo);
|
|
|
|
if (ConnInfo) ExFreePool( ConnInfo );
|
|
|
|
return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL );
|
|
}
|
|
|
|
static NTSTATUS STDCALL
|
|
AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
#ifdef DBG
|
|
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
|
#endif
|
|
|
|
AFD_DbgPrint(MID_TRACE,("AfdDispatch: %d\n", IrpSp->MajorFunction));
|
|
if( IrpSp->MajorFunction != IRP_MJ_CREATE) {
|
|
AFD_DbgPrint(MID_TRACE,("FO %x, IrpSp->FO %x\n",
|
|
FileObject, IrpSp->FileObject));
|
|
ASSERT(FileObject == IrpSp->FileObject);
|
|
}
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
switch(IrpSp->MajorFunction)
|
|
{
|
|
/* opening and closing handles to the device */
|
|
case IRP_MJ_CREATE:
|
|
/* Mostly borrowed from the named pipe file system */
|
|
return AfdCreateSocket(DeviceObject, Irp, IrpSp);
|
|
|
|
case IRP_MJ_CLOSE:
|
|
/* Ditto the borrowing */
|
|
return AfdCloseSocket(DeviceObject, Irp, IrpSp);
|
|
|
|
/* write data */
|
|
case IRP_MJ_WRITE:
|
|
return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp, TRUE );
|
|
|
|
/* read data */
|
|
case IRP_MJ_READ:
|
|
return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp, TRUE );
|
|
|
|
case IRP_MJ_DEVICE_CONTROL:
|
|
{
|
|
switch( IrpSp->Parameters.DeviceIoControl.IoControlCode ) {
|
|
case IOCTL_AFD_BIND:
|
|
return AfdBindSocket( DeviceObject, Irp, IrpSp );
|
|
|
|
case IOCTL_AFD_CONNECT:
|
|
return AfdStreamSocketConnect( DeviceObject, Irp, IrpSp );
|
|
|
|
case IOCTL_AFD_START_LISTEN:
|
|
return AfdListenSocket( DeviceObject, Irp, IrpSp );
|
|
|
|
case IOCTL_AFD_RECV:
|
|
return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp,
|
|
FALSE );
|
|
|
|
case IOCTL_AFD_SELECT:
|
|
return AfdSelect( DeviceObject, Irp, IrpSp );
|
|
|
|
case IOCTL_AFD_EVENT_SELECT:
|
|
return AfdEventSelect( DeviceObject, Irp, IrpSp );
|
|
|
|
case IOCTL_AFD_ENUM_NETWORK_EVENTS:
|
|
return AfdEnumEvents( DeviceObject, Irp, IrpSp );
|
|
|
|
case IOCTL_AFD_RECV_DATAGRAM:
|
|
return AfdPacketSocketReadData( DeviceObject, Irp, IrpSp );
|
|
|
|
case IOCTL_AFD_SEND:
|
|
return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp,
|
|
FALSE );
|
|
|
|
case IOCTL_AFD_SEND_DATAGRAM:
|
|
return AfdPacketSocketWriteData( DeviceObject, Irp, IrpSp );
|
|
|
|
case IOCTL_AFD_GET_INFO:
|
|
return AfdGetInfo( DeviceObject, Irp, IrpSp );
|
|
|
|
case IOCTL_AFD_GET_CONTEXT:
|
|
return AfdGetContext( DeviceObject, Irp, IrpSp );
|
|
|
|
case IOCTL_AFD_SET_CONTEXT:
|
|
return AfdSetContext( DeviceObject, Irp, IrpSp );
|
|
|
|
case IOCTL_AFD_WAIT_FOR_LISTEN:
|
|
return AfdWaitForListen( DeviceObject, Irp, IrpSp );
|
|
|
|
case IOCTL_AFD_ACCEPT:
|
|
return AfdAccept( DeviceObject, Irp, IrpSp );
|
|
|
|
case IOCTL_AFD_DISCONNECT:
|
|
return AfdDisconnect( DeviceObject, Irp, IrpSp );
|
|
|
|
case IOCTL_AFD_GET_SOCK_NAME:
|
|
return AfdGetSockOrPeerName( DeviceObject, Irp, IrpSp, TRUE );
|
|
|
|
case IOCTL_AFD_GET_PEER_NAME:
|
|
return AfdGetSockOrPeerName( DeviceObject, Irp, IrpSp, FALSE );
|
|
|
|
case IOCTL_AFD_GET_TDI_HANDLES:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_TDI_HANDLES\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_SET_INFO:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_INFO\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_SET_CONNECT_DATA:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_DATA\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_SET_CONNECT_OPTIONS:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_OPTIONS\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_SET_DISCONNECT_DATA:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_DATA\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_SET_DISCONNECT_OPTIONS:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_OPTIONS\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_GET_CONNECT_DATA:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_CONNECT_DATA\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_GET_CONNECT_OPTIONS:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_CONNECT_OPTIONS\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_GET_DISCONNECT_DATA:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_DISCONNECT_DATA\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_GET_DISCONNECT_OPTIONS:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_DISCONNECT_OPTIONS\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_SET_CONNECT_DATA_SIZE:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_DATA_SIZE\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_DATA_SIZE\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_DEFER_ACCEPT:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_DEFER_ACCEPT\n"));
|
|
break;
|
|
|
|
case IOCTL_AFD_GET_PENDING_CONNECT_DATA:
|
|
AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_PENDING_CONNECT_DATA\n"));
|
|
break;
|
|
|
|
default:
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
AFD_DbgPrint(MIN_TRACE, ("Unknown IOCTL (0x%x)\n",
|
|
IrpSp->Parameters.DeviceIoControl.
|
|
IoControlCode));
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* unsupported operations */
|
|
default:
|
|
{
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
AFD_DbgPrint(MIN_TRACE,
|
|
("Irp: Unknown Major code was %x\n",
|
|
IrpSp->MajorFunction));
|
|
break;
|
|
}
|
|
}
|
|
|
|
AFD_DbgPrint(MID_TRACE, ("Returning %x\n", Status));
|
|
Irp->IoStatus.Status = Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return (Status);
|
|
}
|
|
|
|
static VOID STDCALL
|
|
AfdUnload(PDRIVER_OBJECT DriverObject)
|
|
{
|
|
}
|
|
|
|
NTSTATUS STDCALL
|
|
DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
|
|
{
|
|
PDEVICE_OBJECT DeviceObject;
|
|
UNICODE_STRING wstrDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Afd");
|
|
PAFD_DEVICE_EXTENSION DeviceExt;
|
|
NTSTATUS Status;
|
|
|
|
/* register driver routines */
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdDispatch;
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdDispatch;
|
|
DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdDispatch;
|
|
DriverObject->MajorFunction[IRP_MJ_READ] = AfdDispatch;
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch;
|
|
DriverObject->DriverUnload = AfdUnload;
|
|
|
|
Status = IoCreateDevice
|
|
( DriverObject,
|
|
sizeof(AFD_DEVICE_EXTENSION),
|
|
&wstrDeviceName,
|
|
FILE_DEVICE_NAMED_PIPE,
|
|
0,
|
|
FALSE,
|
|
&DeviceObject );
|
|
|
|
/* failure */
|
|
if(!NT_SUCCESS(Status))
|
|
{
|
|
return (Status);
|
|
}
|
|
|
|
DeviceExt = DeviceObject->DeviceExtension;
|
|
KeInitializeSpinLock( &DeviceExt->Lock );
|
|
InitializeListHead( &DeviceExt->Polls );
|
|
|
|
AFD_DbgPrint(MID_TRACE,("Device created: object %x ext %x\n",
|
|
DeviceObject, DeviceExt));
|
|
|
|
return (Status);
|
|
}
|
|
|
|
/* EOF */
|