14f88d0d49d7d5b3b3fa15ef56265d3814be7a3f
[reactos.git] / reactos / drivers / net / afd / afd / main.c
1 /* $Id$
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: drivers/net/afd/afd/main.c
5 * PURPOSE: Ancillary functions driver
6 * PROGRAMMER: Art Yerkes (ayerkes@speakeasy.net)
7 * UPDATE HISTORY:
8 * 20040630 Created
9 *
10 * Suggestions: Uniform naming (AfdXxx)
11 */
12
13 /* INCLUDES */
14
15 #include "afd.h"
16 #include "tdi_proto.h"
17 #include "tdiconn.h"
18 #include "debug.h"
19
20 #ifdef DBG
21
22 /* See debug.h for debug/trace constants */
23 //DWORD DebugTraceLevel = DEBUG_ULTRA;
24 DWORD DebugTraceLevel = 0;
25
26 #endif /* DBG */
27
28 void OskitDumpBuffer( PCHAR Data, UINT Len ) {
29 unsigned int i;
30
31 for( i = 0; i < Len; i++ ) {
32 if( i && !(i & 0xf) ) DbgPrint( "\n" );
33 if( !(i & 0xf) ) DbgPrint( "%08x: ", (UINT)(Data + i) );
34 DbgPrint( " %02x", Data[i] & 0xff );
35 }
36 DbgPrint("\n");
37 }
38
39 /* FUNCTIONS */
40
41 NTSTATUS STDCALL
42 AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
43 PIO_STACK_LOCATION IrpSp) {
44 PAFD_FCB FCB;
45 PFILE_OBJECT FileObject;
46 PAFD_DEVICE_EXTENSION DeviceExt;
47 PFILE_FULL_EA_INFORMATION EaInfo;
48 PAFD_CREATE_PACKET ConnectInfo = NULL;
49 ULONG EaLength;
50 PWCHAR EaInfoValue = NULL;
51 UINT Disposition, i;
52
53 AFD_DbgPrint(MID_TRACE,
54 ("AfdCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
55
56 DeviceExt = DeviceObject->DeviceExtension;
57 FileObject = IrpSp->FileObject;
58 Disposition = (IrpSp->Parameters.Create.Options >> 24) & 0xff;
59
60 Irp->IoStatus.Information = 0;
61
62 EaInfo = Irp->AssociatedIrp.SystemBuffer;
63
64 if( EaInfo ) {
65 ConnectInfo = (PAFD_CREATE_PACKET)(EaInfo->EaName + EaInfo->EaNameLength + 1);
66 EaInfoValue = (PWCHAR)(((PCHAR)ConnectInfo) + sizeof(AFD_CREATE_PACKET));
67
68 EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
69 EaInfo->EaNameLength +
70 EaInfo->EaValueLength;
71
72 AFD_DbgPrint(MID_TRACE,("EaInfo: %x, EaInfoValue: %x\n",
73 EaInfo, EaInfoValue));
74 }
75
76 AFD_DbgPrint(MID_TRACE,("About to allocate the new FCB\n"));
77
78 FCB = ExAllocatePool(NonPagedPool, sizeof(AFD_FCB));
79 if( FCB == NULL ) {
80 Irp->IoStatus.Status = STATUS_NO_MEMORY;
81 IoCompleteRequest(Irp, IO_NO_INCREMENT);
82 return STATUS_NO_MEMORY;
83 }
84
85 AFD_DbgPrint(MID_TRACE,("Initializing the new FCB @ %x (FileObject %x Flags %x)\n", FCB, FileObject, ConnectInfo ? ConnectInfo->EndpointFlags : 0));
86
87 RtlZeroMemory( FCB, sizeof( *FCB ) );
88
89 FCB->Flags = ConnectInfo ? ConnectInfo->EndpointFlags : 0;
90 FCB->State = SOCKET_STATE_CREATED;
91 FCB->FileObject = FileObject;
92 FCB->DeviceExt = DeviceExt;
93 FCB->Recv.Size = DEFAULT_RECEIVE_WINDOW_SIZE;
94 FCB->Send.Size = DEFAULT_SEND_WINDOW_SIZE;
95
96 KeInitializeSpinLock( &FCB->SpinLock );
97 ExInitializeFastMutex( &FCB->Mutex );
98 KeInitializeEvent( &FCB->StateLockedEvent, NotificationEvent, FALSE );
99
100 for( i = 0; i < MAX_FUNCTIONS; i++ ) {
101 InitializeListHead( &FCB->PendingIrpList[i] );
102 }
103
104 InitializeListHead( &FCB->DatagramList );
105 InitializeListHead( &FCB->PendingConnections );
106
107 AFD_DbgPrint(MID_TRACE,("%x: Checking command channel\n", FCB));
108
109 if( ConnectInfo ) {
110 FCB->TdiDeviceName.Length = ConnectInfo->SizeOfTransportName;
111 FCB->TdiDeviceName.MaximumLength = FCB->TdiDeviceName.Length;
112 FCB->TdiDeviceName.Buffer =
113 ExAllocatePool( NonPagedPool, FCB->TdiDeviceName.Length );
114 RtlCopyMemory( FCB->TdiDeviceName.Buffer,
115 ConnectInfo->TransportName,
116 FCB->TdiDeviceName.Length );
117
118 if( !FCB->TdiDeviceName.Buffer ) {
119 ExFreePool(FCB);
120 AFD_DbgPrint(MID_TRACE,("Could not copy target string\n"));
121 Irp->IoStatus.Status = STATUS_NO_MEMORY;
122 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
123 return STATUS_NO_MEMORY;
124 }
125
126 AFD_DbgPrint(MID_TRACE,("Success: %s %wZ\n",
127 EaInfo->EaName, &FCB->TdiDeviceName));
128 } else {
129 AFD_DbgPrint(MID_TRACE,("Success: Control connection\n"));
130 }
131
132 FileObject->FsContext = FCB;
133
134 /* It seems that UDP sockets are writable from inception */
135 if( FCB->Flags & SGID_CONNECTIONLESS ) {
136 AFD_DbgPrint(MID_TRACE,("Packet oriented socket\n"));
137 /* Allocate our backup buffer */
138 FCB->Recv.Window = ExAllocatePool( NonPagedPool, FCB->Recv.Size );
139 FCB->Send.Window = ExAllocatePool( NonPagedPool, FCB->Send.Size );
140 /* A datagram socket is always sendable */
141 FCB->PollState |= AFD_EVENT_SEND;
142 PollReeval( FCB->DeviceExt, FCB->FileObject );
143 }
144
145 Irp->IoStatus.Status = STATUS_SUCCESS;
146 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
147
148 return STATUS_SUCCESS;
149 }
150
151 VOID DestroySocket( PAFD_FCB FCB ) {
152 UINT i;
153 BOOLEAN ReturnEarly = FALSE;
154 PAFD_IN_FLIGHT_REQUEST InFlightRequest[IN_FLIGHT_REQUESTS];
155
156 AFD_DbgPrint(MIN_TRACE,("Called (%x)\n", FCB));
157
158 if( !SocketAcquireStateLock( FCB ) ) return;
159
160 FCB->State = SOCKET_STATE_CLOSED;
161
162 InFlightRequest[0] = &FCB->ListenIrp;
163 InFlightRequest[1] = &FCB->ReceiveIrp;
164 InFlightRequest[2] = &FCB->SendIrp;
165
166 /* Return early here because we might be called in the mean time. */
167 if( FCB->Critical ||
168 FCB->ListenIrp.InFlightRequest ||
169 FCB->ReceiveIrp.InFlightRequest ||
170 FCB->SendIrp.InFlightRequest ) {
171 AFD_DbgPrint(MIN_TRACE,("Leaving socket alive (%x %x %x)\n",
172 FCB->ListenIrp.InFlightRequest,
173 FCB->ReceiveIrp.InFlightRequest,
174 FCB->SendIrp.InFlightRequest));
175 ReturnEarly = TRUE;
176 }
177
178 /* After PoolReeval, this FCB should not be involved in any outstanding
179 * poll requests */
180
181 /* Cancel our pending requests */
182 for( i = 0; i < IN_FLIGHT_REQUESTS; i++ ) {
183 NTSTATUS Status = STATUS_NO_SUCH_FILE;
184 if( InFlightRequest[i]->InFlightRequest ) {
185 AFD_DbgPrint(MID_TRACE,("Cancelling in flight irp %d (%x)\n",
186 i, InFlightRequest[i]->InFlightRequest));
187 InFlightRequest[i]->InFlightRequest->IoStatus.Status = Status;
188 InFlightRequest[i]->InFlightRequest->IoStatus.Information = 0;
189 IoCancelIrp( InFlightRequest[i]->InFlightRequest );
190 }
191 }
192
193 SocketStateUnlock( FCB );
194
195 if( ReturnEarly ) return;
196
197 if( FCB->Recv.Window )
198 ExFreePool( FCB->Recv.Window );
199 if( FCB->Send.Window )
200 ExFreePool( FCB->Send.Window );
201 if( FCB->AddressFrom )
202 ExFreePool( FCB->AddressFrom );
203 if( FCB->LocalAddress )
204 ExFreePool( FCB->LocalAddress );
205
206 ExFreePool(FCB->TdiDeviceName.Buffer);
207
208 ExFreePool(FCB);
209 AFD_DbgPrint(MIN_TRACE,("Deleted (%x)\n", FCB));
210
211 AFD_DbgPrint(MIN_TRACE,("Leaving\n"));
212 }
213
214 NTSTATUS STDCALL
215 AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
216 PIO_STACK_LOCATION IrpSp)
217 {
218 PFILE_OBJECT FileObject = IrpSp->FileObject;
219 PAFD_FCB FCB = FileObject->FsContext;
220
221 AFD_DbgPrint(MID_TRACE,
222 ("AfdClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
223
224 AFD_DbgPrint(MID_TRACE,("FCB %x\n", FCB));
225
226 FCB->PollState |= AFD_EVENT_CLOSE;
227 PollReeval( FCB->DeviceExt, FileObject );
228 KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
229
230 if( FCB->EventSelect ) ObDereferenceObject( FCB->EventSelect );
231
232 FileObject->FsContext = NULL;
233 DestroySocket( FCB );
234
235 Irp->IoStatus.Status = STATUS_SUCCESS;
236 Irp->IoStatus.Information = 0;
237 IoCompleteRequest(Irp, IO_NO_INCREMENT);
238
239 AFD_DbgPrint(MID_TRACE, ("Returning success.\n"));
240
241 return STATUS_SUCCESS;
242 }
243
244 NTSTATUS STDCALL
245 AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
246 PIO_STACK_LOCATION IrpSp) {
247 PFILE_OBJECT FileObject = IrpSp->FileObject;
248 PAFD_FCB FCB = FileObject->FsContext;
249 PAFD_DISCONNECT_INFO DisReq;
250 IO_STATUS_BLOCK Iosb;
251 PTDI_CONNECTION_INFORMATION ConnInfo;
252 NTSTATUS Status;
253 USHORT Flags = 0;
254
255 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp, FALSE );
256
257 if( !(DisReq = LockRequest( Irp, IrpSp )) )
258 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
259 Irp, 0, NULL, FALSE );
260
261 if (NULL == FCB->RemoteAddress)
262 {
263 ConnInfo = NULL;
264 }
265 else
266 {
267 Status = TdiBuildNullConnectionInfo
268 ( &ConnInfo, FCB->RemoteAddress->Address[0].AddressType );
269
270 if( !NT_SUCCESS(Status) || !ConnInfo )
271 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
272 Irp, 0, NULL, TRUE );
273 }
274
275 if( DisReq->DisconnectType & AFD_DISCONNECT_SEND )
276 Flags |= TDI_DISCONNECT_RELEASE;
277 if( DisReq->DisconnectType & AFD_DISCONNECT_RECV ||
278 DisReq->DisconnectType & AFD_DISCONNECT_ABORT )
279 Flags |= TDI_DISCONNECT_ABORT;
280
281 Status = TdiDisconnect( FCB->Connection.Object,
282 &DisReq->Timeout,
283 Flags,
284 &Iosb,
285 NULL,
286 NULL,
287 FCB->AddressFrom,
288 ConnInfo);
289
290 ExFreePool( ConnInfo );
291
292 return UnlockAndMaybeComplete( FCB, Status, Irp, 0, NULL, TRUE );
293 }
294
295 NTSTATUS STDCALL
296 AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
297 {
298 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
299 NTSTATUS Status = STATUS_SUCCESS;
300 #ifdef DBG
301 PFILE_OBJECT FileObject = IrpSp->FileObject;
302 #endif
303
304 AFD_DbgPrint(MID_TRACE,("AfdDispatch: %d\n", IrpSp->MajorFunction));
305 if( IrpSp->MajorFunction != IRP_MJ_CREATE) {
306 AFD_DbgPrint(MID_TRACE,("FO %x, IrpSp->FO %x\n",
307 FileObject, IrpSp->FileObject));
308 ASSERT(FileObject == IrpSp->FileObject);
309 }
310
311 switch(IrpSp->MajorFunction)
312 {
313 /* opening and closing handles to the device */
314 case IRP_MJ_CREATE:
315 /* Mostly borrowed from the named pipe file system */
316 return AfdCreateSocket(DeviceObject, Irp, IrpSp);
317
318 case IRP_MJ_CLOSE:
319 /* Ditto the borrowing */
320 return AfdCloseSocket(DeviceObject, Irp, IrpSp);
321
322 /* write data */
323 case IRP_MJ_WRITE:
324 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp, TRUE );
325
326 /* read data */
327 case IRP_MJ_READ:
328 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp, TRUE );
329
330 case IRP_MJ_DEVICE_CONTROL:
331 {
332 switch( IrpSp->Parameters.DeviceIoControl.IoControlCode ) {
333 case IOCTL_AFD_BIND:
334 return AfdBindSocket( DeviceObject, Irp, IrpSp );
335
336 case IOCTL_AFD_CONNECT:
337 return AfdStreamSocketConnect( DeviceObject, Irp, IrpSp );
338
339 case IOCTL_AFD_START_LISTEN:
340 return AfdListenSocket( DeviceObject, Irp, IrpSp );
341
342 case IOCTL_AFD_RECV:
343 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp,
344 FALSE );
345
346 case IOCTL_AFD_SELECT:
347 return AfdSelect( DeviceObject, Irp, IrpSp );
348
349 case IOCTL_AFD_EVENT_SELECT:
350 return AfdEventSelect( DeviceObject, Irp, IrpSp );
351
352 case IOCTL_AFD_ENUM_NETWORK_EVENTS:
353 return AfdEnumEvents( DeviceObject, Irp, IrpSp );
354
355 case IOCTL_AFD_RECV_DATAGRAM:
356 return AfdPacketSocketReadData( DeviceObject, Irp, IrpSp );
357
358 case IOCTL_AFD_SEND:
359 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp,
360 FALSE );
361
362 case IOCTL_AFD_SEND_DATAGRAM:
363 return AfdPacketSocketWriteData( DeviceObject, Irp, IrpSp );
364
365 case IOCTL_AFD_GET_INFO:
366 return AfdGetInfo( DeviceObject, Irp, IrpSp );
367
368 case IOCTL_AFD_GET_CONTEXT:
369 return AfdGetContext( DeviceObject, Irp, IrpSp );
370
371 case IOCTL_AFD_SET_CONTEXT:
372 return AfdSetContext( DeviceObject, Irp, IrpSp );
373
374 case IOCTL_AFD_WAIT_FOR_LISTEN:
375 return AfdWaitForListen( DeviceObject, Irp, IrpSp );
376
377 case IOCTL_AFD_ACCEPT:
378 return AfdAccept( DeviceObject, Irp, IrpSp );
379
380 case IOCTL_AFD_DISCONNECT:
381 return AfdDisconnect( DeviceObject, Irp, IrpSp );
382
383 case IOCTL_AFD_GET_SOCK_NAME:
384 return AfdGetSockOrPeerName( DeviceObject, Irp, IrpSp, TRUE );
385
386 case IOCTL_AFD_GET_PEER_NAME:
387 return AfdGetSockOrPeerName( DeviceObject, Irp, IrpSp, FALSE );
388
389 case IOCTL_AFD_GET_TDI_HANDLES:
390 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_TDI_HANDLES\n"));
391 break;
392
393 case IOCTL_AFD_SET_INFO:
394 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_INFO\n"));
395 break;
396
397 case IOCTL_AFD_SET_CONNECT_DATA:
398 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_DATA\n"));
399 break;
400
401 case IOCTL_AFD_SET_CONNECT_OPTIONS:
402 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_OPTIONS\n"));
403 break;
404
405 case IOCTL_AFD_SET_DISCONNECT_DATA:
406 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_DATA\n"));
407 break;
408
409 case IOCTL_AFD_SET_DISCONNECT_OPTIONS:
410 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_OPTIONS\n"));
411 break;
412
413 case IOCTL_AFD_GET_CONNECT_DATA:
414 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_CONNECT_DATA\n"));
415 break;
416
417 case IOCTL_AFD_GET_CONNECT_OPTIONS:
418 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_CONNECT_OPTIONS\n"));
419 break;
420
421 case IOCTL_AFD_GET_DISCONNECT_DATA:
422 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_DISCONNECT_DATA\n"));
423 break;
424
425 case IOCTL_AFD_GET_DISCONNECT_OPTIONS:
426 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_DISCONNECT_OPTIONS\n"));
427 break;
428
429 case IOCTL_AFD_SET_CONNECT_DATA_SIZE:
430 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_DATA_SIZE\n"));
431 break;
432
433 case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE:
434 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE\n"));
435 break;
436
437 case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE:
438 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_DATA_SIZE\n"));
439 break;
440
441 case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE:
442 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE\n"));
443 break;
444
445 case IOCTL_AFD_DEFER_ACCEPT:
446 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_DEFER_ACCEPT\n"));
447 break;
448
449 case IOCTL_AFD_GET_PENDING_CONNECT_DATA:
450 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_PENDING_CONNECT_DATA\n"));
451 break;
452
453 default:
454 Status = STATUS_NOT_IMPLEMENTED;
455 Irp->IoStatus.Information = 0;
456 AFD_DbgPrint(MIN_TRACE, ("Unknown IOCTL (0x%x)\n",
457 IrpSp->Parameters.DeviceIoControl.
458 IoControlCode));
459 break;
460 }
461 break;
462 }
463
464 /* unsupported operations */
465 default:
466 {
467 Status = STATUS_NOT_IMPLEMENTED;
468 AFD_DbgPrint(MIN_TRACE,
469 ("Irp: Unknown Major code was %x\n",
470 IrpSp->MajorFunction));
471 break;
472 }
473 }
474
475 AFD_DbgPrint(MID_TRACE, ("Returning %x\n", Status));
476 Irp->IoStatus.Status = Status;
477 IoCompleteRequest(Irp, IO_NO_INCREMENT);
478
479 return (Status);
480 }
481
482 VOID STDCALL
483 AfdUnload(PDRIVER_OBJECT DriverObject)
484 {
485 }
486
487 NTSTATUS STDCALL
488 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
489 {
490 PDEVICE_OBJECT DeviceObject;
491 UNICODE_STRING wstrDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Afd");
492 PAFD_DEVICE_EXTENSION DeviceExt;
493 NTSTATUS Status;
494
495 /* register driver routines */
496 DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdDispatch;
497 DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdDispatch;
498 DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdDispatch;
499 DriverObject->MajorFunction[IRP_MJ_READ] = AfdDispatch;
500 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch;
501 DriverObject->DriverUnload = AfdUnload;
502
503 Status = IoCreateDevice
504 ( DriverObject,
505 sizeof(AFD_DEVICE_EXTENSION),
506 &wstrDeviceName,
507 FILE_DEVICE_NAMED_PIPE,
508 0,
509 FALSE,
510 &DeviceObject );
511
512 /* failure */
513 if(!NT_SUCCESS(Status))
514 {
515 return (Status);
516 }
517
518 DeviceExt = DeviceObject->DeviceExtension;
519 KeInitializeSpinLock( &DeviceExt->Lock );
520 InitializeListHead( &DeviceExt->Polls );
521
522 AFD_DbgPrint(MID_TRACE,("Device created: object %x ext %x\n",
523 DeviceObject, DeviceExt));
524
525 return (Status);
526 }
527
528 /* EOF */