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