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