Merge from amd64 branch:
[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 #if 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 NTAPI
42 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
43
44 NTSTATUS NTAPI
45 AfdGetDisconnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp,
46 PIO_STACK_LOCATION IrpSp)
47 {
48 PFILE_OBJECT FileObject = IrpSp->FileObject;
49 PAFD_FCB FCB = FileObject->FsContext;
50 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
51
52 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
53
54 if (FCB->DisconnectOptionsSize == 0)
55 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
56
57 ASSERT(FCB->DisconnectOptions);
58
59 if (FCB->FilledDisconnectOptions < BufferSize) BufferSize = FCB->FilledDisconnectOptions;
60
61 RtlCopyMemory(Irp->UserBuffer,
62 FCB->DisconnectOptions,
63 BufferSize);
64
65 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize);
66 }
67
68 NTSTATUS
69 NTAPI
70 AfdSetDisconnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp,
71 PIO_STACK_LOCATION IrpSp)
72 {
73 PFILE_OBJECT FileObject = IrpSp->FileObject;
74 PAFD_FCB FCB = FileObject->FsContext;
75 PVOID DisconnectOptions = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
76 UINT DisconnectOptionsSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
77
78 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
79
80 if (FCB->DisconnectOptions)
81 {
82 ExFreePool(FCB->DisconnectOptions);
83 FCB->DisconnectOptions = NULL;
84 FCB->DisconnectOptionsSize = 0;
85 FCB->FilledDisconnectOptions = 0;
86 }
87
88 FCB->DisconnectOptions = ExAllocatePool(PagedPool, DisconnectOptionsSize);
89 if (!FCB->DisconnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
90
91 RtlCopyMemory(FCB->DisconnectOptions,
92 DisconnectOptions,
93 DisconnectOptionsSize);
94
95 FCB->DisconnectOptionsSize = DisconnectOptionsSize;
96
97 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
98 }
99
100 NTSTATUS
101 NTAPI
102 AfdSetDisconnectOptionsSize(PDEVICE_OBJECT DeviceObject, PIRP Irp,
103 PIO_STACK_LOCATION IrpSp)
104 {
105 PFILE_OBJECT FileObject = IrpSp->FileObject;
106 PAFD_FCB FCB = FileObject->FsContext;
107 PUINT DisconnectOptionsSize = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
108 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
109
110 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
111
112 if (BufferSize < sizeof(UINT))
113 return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0);
114
115 if (FCB->DisconnectOptions)
116 {
117 ExFreePool(FCB->DisconnectOptions);
118 FCB->DisconnectOptionsSize = 0;
119 FCB->FilledDisconnectOptions = 0;
120 }
121
122 FCB->DisconnectOptions = ExAllocatePool(PagedPool, *DisconnectOptionsSize);
123 if (!FCB->DisconnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
124
125 FCB->DisconnectOptionsSize = *DisconnectOptionsSize;
126
127 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
128 }
129
130 NTSTATUS NTAPI
131 AfdGetDisconnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
132 PIO_STACK_LOCATION IrpSp)
133 {
134 PFILE_OBJECT FileObject = IrpSp->FileObject;
135 PAFD_FCB FCB = FileObject->FsContext;
136 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
137
138 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
139
140 if (FCB->DisconnectDataSize == 0)
141 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
142
143 ASSERT(FCB->DisconnectData);
144
145 if (FCB->FilledDisconnectData < BufferSize) BufferSize = FCB->FilledDisconnectData;
146
147 RtlCopyMemory(Irp->UserBuffer,
148 FCB->DisconnectData,
149 BufferSize);
150
151 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize);
152 }
153
154 NTSTATUS
155 NTAPI
156 AfdSetDisconnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
157 PIO_STACK_LOCATION IrpSp)
158 {
159 PFILE_OBJECT FileObject = IrpSp->FileObject;
160 PAFD_FCB FCB = FileObject->FsContext;
161 PVOID DisconnectData = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
162 UINT DisconnectDataSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
163
164 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
165
166 if (FCB->DisconnectData)
167 {
168 ExFreePool(FCB->DisconnectData);
169 FCB->DisconnectData = NULL;
170 FCB->DisconnectDataSize = 0;
171 FCB->FilledDisconnectData = 0;
172 }
173
174 FCB->DisconnectData = ExAllocatePool(PagedPool, DisconnectDataSize);
175 if (!FCB->DisconnectData) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
176
177 RtlCopyMemory(FCB->DisconnectData,
178 DisconnectData,
179 DisconnectDataSize);
180
181 FCB->DisconnectDataSize = DisconnectDataSize;
182
183 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
184 }
185
186 NTSTATUS
187 NTAPI
188 AfdSetDisconnectDataSize(PDEVICE_OBJECT DeviceObject, PIRP Irp,
189 PIO_STACK_LOCATION IrpSp)
190 {
191 PFILE_OBJECT FileObject = IrpSp->FileObject;
192 PAFD_FCB FCB = FileObject->FsContext;
193 PUINT DisconnectDataSize = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
194 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
195
196 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
197
198 if (BufferSize < sizeof(UINT))
199 return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0);
200
201 if (FCB->DisconnectData)
202 {
203 ExFreePool(FCB->DisconnectData);
204 FCB->DisconnectDataSize = 0;
205 FCB->FilledDisconnectData = 0;
206 }
207
208 FCB->DisconnectData = ExAllocatePool(PagedPool, *DisconnectDataSize);
209 if (!FCB->DisconnectData) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
210
211 FCB->DisconnectDataSize = *DisconnectDataSize;
212
213 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
214 }
215
216 static NTSTATUS NTAPI
217 AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
218 PIO_STACK_LOCATION IrpSp) {
219 PAFD_FCB FCB;
220 PFILE_OBJECT FileObject;
221 PAFD_DEVICE_EXTENSION DeviceExt;
222 PFILE_FULL_EA_INFORMATION EaInfo;
223 PAFD_CREATE_PACKET ConnectInfo = NULL;
224 ULONG EaLength;
225 PWCHAR EaInfoValue = NULL;
226 UINT Disposition, i;
227 NTSTATUS Status = STATUS_SUCCESS;
228
229 AFD_DbgPrint(MID_TRACE,
230 ("AfdCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
231
232 DeviceExt = DeviceObject->DeviceExtension;
233 FileObject = IrpSp->FileObject;
234 Disposition = (IrpSp->Parameters.Create.Options >> 24) & 0xff;
235
236 Irp->IoStatus.Information = 0;
237
238 EaInfo = Irp->AssociatedIrp.SystemBuffer;
239
240 if( EaInfo ) {
241 ConnectInfo = (PAFD_CREATE_PACKET)(EaInfo->EaName + EaInfo->EaNameLength + 1);
242 EaInfoValue = (PWCHAR)(((PCHAR)ConnectInfo) + sizeof(AFD_CREATE_PACKET));
243
244 EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
245 EaInfo->EaNameLength +
246 EaInfo->EaValueLength;
247
248 AFD_DbgPrint(MID_TRACE,("EaInfo: %x, EaInfoValue: %x\n",
249 EaInfo, EaInfoValue));
250 }
251
252 AFD_DbgPrint(MID_TRACE,("About to allocate the new FCB\n"));
253
254 FCB = ExAllocatePool(NonPagedPool, sizeof(AFD_FCB));
255 if( FCB == NULL ) {
256 Irp->IoStatus.Status = STATUS_NO_MEMORY;
257 IoCompleteRequest(Irp, IO_NO_INCREMENT);
258 return STATUS_NO_MEMORY;
259 }
260
261 AFD_DbgPrint(MID_TRACE,("Initializing the new FCB @ %x (FileObject %x Flags %x)\n", FCB, FileObject, ConnectInfo ? ConnectInfo->EndpointFlags : 0));
262
263 RtlZeroMemory( FCB, sizeof( *FCB ) );
264
265 FCB->Flags = ConnectInfo ? ConnectInfo->EndpointFlags : 0;
266 FCB->GroupID = ConnectInfo ? ConnectInfo->GroupID : 0;
267 FCB->GroupType = 0; /* FIXME */
268 FCB->State = SOCKET_STATE_CREATED;
269 FCB->FileObject = FileObject;
270 FCB->DeviceExt = DeviceExt;
271 FCB->AddressFile.Handle = INVALID_HANDLE_VALUE;
272 FCB->Connection.Handle = INVALID_HANDLE_VALUE;
273
274 KeInitializeMutex( &FCB->Mutex, 0 );
275
276 for( i = 0; i < MAX_FUNCTIONS; i++ ) {
277 InitializeListHead( &FCB->PendingIrpList[i] );
278 }
279
280 InitializeListHead( &FCB->DatagramList );
281 InitializeListHead( &FCB->PendingConnections );
282
283 AFD_DbgPrint(MID_TRACE,("%x: Checking command channel\n", FCB));
284
285 if( ConnectInfo ) {
286 FCB->TdiDeviceName.Length = ConnectInfo->SizeOfTransportName;
287 FCB->TdiDeviceName.MaximumLength = FCB->TdiDeviceName.Length;
288 FCB->TdiDeviceName.Buffer =
289 ExAllocatePool( NonPagedPool, FCB->TdiDeviceName.Length );
290
291 if( !FCB->TdiDeviceName.Buffer ) {
292 ExFreePool(FCB);
293 AFD_DbgPrint(MID_TRACE,("Could not copy target string\n"));
294 Irp->IoStatus.Status = STATUS_NO_MEMORY;
295 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
296 return STATUS_NO_MEMORY;
297 }
298
299 RtlCopyMemory( FCB->TdiDeviceName.Buffer,
300 ConnectInfo->TransportName,
301 FCB->TdiDeviceName.Length );
302
303 AFD_DbgPrint(MID_TRACE,("Success: %s %wZ\n",
304 EaInfo->EaName, &FCB->TdiDeviceName));
305 } else {
306 AFD_DbgPrint(MID_TRACE,("Success: Control connection\n"));
307 }
308
309 FileObject->FsContext = FCB;
310
311 /* It seems that UDP sockets are writable from inception */
312 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) {
313 AFD_DbgPrint(MID_TRACE,("Packet oriented socket\n"));
314
315 /* A datagram socket is always sendable */
316 FCB->PollState |= AFD_EVENT_SEND;
317 PollReeval( FCB->DeviceExt, FCB->FileObject );
318 }
319
320 if( !NT_SUCCESS(Status) ) {
321 if( FCB->TdiDeviceName.Buffer ) ExFreePool( FCB->TdiDeviceName.Buffer );
322 ExFreePool( FCB );
323 FileObject->FsContext = NULL;
324 }
325
326 Irp->IoStatus.Status = Status;
327 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
328
329 return Status;
330 }
331
332 static NTSTATUS NTAPI
333 AfdCleanupSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
334 PIO_STACK_LOCATION IrpSp)
335 {
336 PFILE_OBJECT FileObject = IrpSp->FileObject;
337 PAFD_FCB FCB = FileObject->FsContext;
338 PLIST_ENTRY CurrentEntry, NextEntry;
339 UINT Function;
340 PIRP CurrentIrp;
341
342 if( !SocketAcquireStateLock( FCB ) ) return LostSocket(Irp);
343
344 for (Function = 0; Function < MAX_FUNCTIONS; Function++)
345 {
346 CurrentEntry = FCB->PendingIrpList[Function].Flink;
347 while (CurrentEntry != &FCB->PendingIrpList[Function])
348 {
349 NextEntry = CurrentEntry->Flink;
350 CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
351
352 /* The cancel routine will remove the IRP from the list */
353 IoCancelIrp(CurrentIrp);
354
355 CurrentEntry = NextEntry;
356 }
357 }
358
359 KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
360
361 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
362 }
363
364 static NTSTATUS NTAPI
365 AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
366 PIO_STACK_LOCATION IrpSp)
367 {
368 PFILE_OBJECT FileObject = IrpSp->FileObject;
369 PAFD_FCB FCB = FileObject->FsContext;
370 UINT i;
371 PAFD_IN_FLIGHT_REQUEST InFlightRequest[IN_FLIGHT_REQUESTS];
372
373 AFD_DbgPrint(MID_TRACE,
374 ("AfdClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
375
376 if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED;
377
378 FCB->State = SOCKET_STATE_CLOSED;
379 FCB->PollState = AFD_EVENT_CLOSE;
380 PollReeval( FCB->DeviceExt, FCB->FileObject );
381
382 InFlightRequest[0] = &FCB->ListenIrp;
383 InFlightRequest[1] = &FCB->ReceiveIrp;
384 InFlightRequest[2] = &FCB->SendIrp;
385 InFlightRequest[3] = &FCB->ConnectIrp;
386
387 /* Cancel our pending requests */
388 for( i = 0; i < IN_FLIGHT_REQUESTS; i++ ) {
389 if( InFlightRequest[i]->InFlightRequest ) {
390 AFD_DbgPrint(MID_TRACE,("Cancelling in flight irp %d (%x)\n",
391 i, InFlightRequest[i]->InFlightRequest));
392 IoCancelIrp(InFlightRequest[i]->InFlightRequest);
393 }
394 }
395
396 KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
397
398 SocketStateUnlock( FCB );
399
400 if( FCB->EventSelect )
401 ObDereferenceObject( FCB->EventSelect );
402
403 if( FCB->Context )
404 ExFreePool( FCB->Context );
405
406 if( FCB->Recv.Window )
407 ExFreePool( FCB->Recv.Window );
408
409 if( FCB->Send.Window )
410 ExFreePool( FCB->Send.Window );
411
412 if( FCB->AddressFrom )
413 ExFreePool( FCB->AddressFrom );
414
415 if( FCB->ConnectInfo )
416 ExFreePool( FCB->ConnectInfo );
417
418 if( FCB->ConnectData )
419 ExFreePool( FCB->ConnectData );
420
421 if( FCB->DisconnectData )
422 ExFreePool( FCB->DisconnectData );
423
424 if( FCB->ConnectOptions )
425 ExFreePool( FCB->ConnectOptions );
426
427 if( FCB->DisconnectOptions )
428 ExFreePool( FCB->DisconnectOptions );
429
430 if( FCB->LocalAddress )
431 ExFreePool( FCB->LocalAddress );
432
433 if( FCB->RemoteAddress )
434 ExFreePool( FCB->RemoteAddress );
435
436 if( FCB->Connection.Object )
437 ObDereferenceObject(FCB->Connection.Object);
438
439 if( FCB->AddressFile.Object )
440 ObDereferenceObject(FCB->AddressFile.Object);
441
442 if( FCB->AddressFile.Handle != INVALID_HANDLE_VALUE )
443 {
444 if (ZwClose(FCB->AddressFile.Handle) == STATUS_INVALID_HANDLE)
445 {
446 DbgPrint("INVALID ADDRESS FILE HANDLE VALUE: %x %x\n", FCB->AddressFile.Handle, FCB->AddressFile.Object);
447 }
448 }
449
450 if( FCB->Connection.Handle != INVALID_HANDLE_VALUE )
451 {
452 if (ZwClose(FCB->Connection.Handle) == STATUS_INVALID_HANDLE)
453 {
454 DbgPrint("INVALID CONNECTION HANDLE VALUE: %x %x\n", FCB->Connection.Handle, FCB->Connection.Object);
455 }
456 }
457
458 if( FCB->TdiDeviceName.Buffer )
459 ExFreePool(FCB->TdiDeviceName.Buffer);
460
461 ExFreePool(FCB);
462
463 Irp->IoStatus.Status = STATUS_SUCCESS;
464 Irp->IoStatus.Information = 0;
465 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
466
467 AFD_DbgPrint(MID_TRACE, ("Returning success.\n"));
468
469 return STATUS_SUCCESS;
470 }
471
472 static NTSTATUS NTAPI
473 AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
474 PIO_STACK_LOCATION IrpSp) {
475 PFILE_OBJECT FileObject = IrpSp->FileObject;
476 PAFD_FCB FCB = FileObject->FsContext;
477 PAFD_DISCONNECT_INFO DisReq;
478 IO_STATUS_BLOCK Iosb;
479 PTDI_CONNECTION_INFORMATION ConnectionReturnInfo;
480 NTSTATUS Status = STATUS_SUCCESS;
481 USHORT Flags = 0;
482
483 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
484
485 if( !(DisReq = LockRequest( Irp, IrpSp )) )
486 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
487 Irp, 0 );
488
489 if (!(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS))
490 {
491 if( !FCB->ConnectInfo )
492 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
493 Irp, 0 );
494
495 ASSERT(FCB->RemoteAddress);
496
497 Status = TdiBuildNullConnectionInfo
498 ( &ConnectionReturnInfo, FCB->RemoteAddress->Address[0].AddressType );
499
500 if( !NT_SUCCESS(Status) )
501 return UnlockAndMaybeComplete( FCB, Status,
502 Irp, 0 );
503
504 if( DisReq->DisconnectType & AFD_DISCONNECT_SEND )
505 Flags |= TDI_DISCONNECT_RELEASE;
506 if( DisReq->DisconnectType & AFD_DISCONNECT_RECV ||
507 DisReq->DisconnectType & AFD_DISCONNECT_ABORT )
508 Flags |= TDI_DISCONNECT_ABORT;
509
510 FCB->ConnectInfo->UserData = FCB->DisconnectData;
511 FCB->ConnectInfo->UserDataLength = FCB->DisconnectDataSize;
512 FCB->ConnectInfo->Options = FCB->DisconnectOptions;
513 FCB->ConnectInfo->OptionsLength = FCB->DisconnectOptionsSize;
514
515 Status = TdiDisconnect( FCB->Connection.Object,
516 &DisReq->Timeout,
517 Flags,
518 &Iosb,
519 NULL,
520 NULL,
521 FCB->ConnectInfo,
522 ConnectionReturnInfo);
523
524 if (NT_SUCCESS(Status)) {
525 FCB->FilledDisconnectData = MIN(FCB->DisconnectDataSize, ConnectionReturnInfo->UserDataLength);
526 if (FCB->FilledDisconnectData)
527 {
528 RtlCopyMemory(FCB->DisconnectData,
529 ConnectionReturnInfo->UserData,
530 FCB->FilledDisconnectData);
531 }
532
533 FCB->FilledDisconnectOptions = MIN(FCB->DisconnectOptionsSize, ConnectionReturnInfo->OptionsLength);
534 if (FCB->FilledDisconnectOptions)
535 {
536 RtlCopyMemory(FCB->DisconnectOptions,
537 ConnectionReturnInfo->Options,
538 FCB->FilledDisconnectOptions);
539 }
540 }
541
542 ExFreePool( ConnectionReturnInfo );
543
544 FCB->PollState |= AFD_EVENT_DISCONNECT;
545 PollReeval( FCB->DeviceExt, FCB->FileObject );
546 } else
547 Status = STATUS_INVALID_PARAMETER;
548
549 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
550 }
551
552 static NTSTATUS NTAPI
553 AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
554 {
555 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
556 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
557 #if DBG
558 PFILE_OBJECT FileObject = IrpSp->FileObject;
559 #endif
560
561 AFD_DbgPrint(MID_TRACE,("AfdDispatch: %d\n", IrpSp->MajorFunction));
562 if( IrpSp->MajorFunction != IRP_MJ_CREATE) {
563 AFD_DbgPrint(MID_TRACE,("FO %x, IrpSp->FO %x\n",
564 FileObject, IrpSp->FileObject));
565 ASSERT(FileObject == IrpSp->FileObject);
566 }
567
568 Irp->IoStatus.Information = 0;
569
570 switch(IrpSp->MajorFunction)
571 {
572 /* opening and closing handles to the device */
573 case IRP_MJ_CREATE:
574 /* Mostly borrowed from the named pipe file system */
575 return AfdCreateSocket(DeviceObject, Irp, IrpSp);
576
577 case IRP_MJ_CLOSE:
578 /* Ditto the borrowing */
579 return AfdCloseSocket(DeviceObject, Irp, IrpSp);
580
581 case IRP_MJ_CLEANUP:
582 return AfdCleanupSocket(DeviceObject, Irp, IrpSp);
583
584 /* write data */
585 case IRP_MJ_WRITE:
586 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp, TRUE );
587
588 /* read data */
589 case IRP_MJ_READ:
590 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp, TRUE );
591
592 case IRP_MJ_DEVICE_CONTROL:
593 {
594 switch( IrpSp->Parameters.DeviceIoControl.IoControlCode ) {
595 case IOCTL_AFD_BIND:
596 return AfdBindSocket( DeviceObject, Irp, IrpSp );
597
598 case IOCTL_AFD_CONNECT:
599 return AfdStreamSocketConnect( DeviceObject, Irp, IrpSp );
600
601 case IOCTL_AFD_START_LISTEN:
602 return AfdListenSocket( DeviceObject, Irp, IrpSp );
603
604 case IOCTL_AFD_RECV:
605 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp,
606 FALSE );
607
608 case IOCTL_AFD_SELECT:
609 return AfdSelect( DeviceObject, Irp, IrpSp );
610
611 case IOCTL_AFD_EVENT_SELECT:
612 return AfdEventSelect( DeviceObject, Irp, IrpSp );
613
614 case IOCTL_AFD_ENUM_NETWORK_EVENTS:
615 return AfdEnumEvents( DeviceObject, Irp, IrpSp );
616
617 case IOCTL_AFD_RECV_DATAGRAM:
618 return AfdPacketSocketReadData( DeviceObject, Irp, IrpSp );
619
620 case IOCTL_AFD_SEND:
621 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp,
622 FALSE );
623
624 case IOCTL_AFD_SEND_DATAGRAM:
625 return AfdPacketSocketWriteData( DeviceObject, Irp, IrpSp );
626
627 case IOCTL_AFD_GET_INFO:
628 return AfdGetInfo( DeviceObject, Irp, IrpSp );
629
630 case IOCTL_AFD_SET_INFO:
631 return AfdSetInfo( DeviceObject, Irp, IrpSp );
632
633 case IOCTL_AFD_GET_CONTEXT_SIZE:
634 return AfdGetContextSize( DeviceObject, Irp, IrpSp );
635
636 case IOCTL_AFD_GET_CONTEXT:
637 return AfdGetContext( DeviceObject, Irp, IrpSp );
638
639 case IOCTL_AFD_SET_CONTEXT:
640 return AfdSetContext( DeviceObject, Irp, IrpSp );
641
642 case IOCTL_AFD_WAIT_FOR_LISTEN:
643 return AfdWaitForListen( DeviceObject, Irp, IrpSp );
644
645 case IOCTL_AFD_ACCEPT:
646 return AfdAccept( DeviceObject, Irp, IrpSp );
647
648 case IOCTL_AFD_DISCONNECT:
649 return AfdDisconnect( DeviceObject, Irp, IrpSp );
650
651 case IOCTL_AFD_GET_SOCK_NAME:
652 return AfdGetSockName( DeviceObject, Irp, IrpSp );
653
654 case IOCTL_AFD_GET_PEER_NAME:
655 return AfdGetPeerName( DeviceObject, Irp, IrpSp );
656
657 case IOCTL_AFD_GET_CONNECT_DATA:
658 return AfdGetConnectData(DeviceObject, Irp, IrpSp);
659
660 case IOCTL_AFD_SET_CONNECT_DATA:
661 return AfdSetConnectData(DeviceObject, Irp, IrpSp);
662
663 case IOCTL_AFD_SET_DISCONNECT_DATA:
664 return AfdSetDisconnectData(DeviceObject, Irp, IrpSp);
665
666 case IOCTL_AFD_GET_DISCONNECT_DATA:
667 return AfdGetDisconnectData(DeviceObject, Irp, IrpSp);
668
669 case IOCTL_AFD_SET_CONNECT_DATA_SIZE:
670 return AfdSetConnectDataSize(DeviceObject, Irp, IrpSp);
671
672 case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE:
673 return AfdSetDisconnectDataSize(DeviceObject, Irp, IrpSp);
674
675 case IOCTL_AFD_SET_CONNECT_OPTIONS:
676 return AfdSetConnectOptions(DeviceObject, Irp, IrpSp);
677
678 case IOCTL_AFD_SET_DISCONNECT_OPTIONS:
679 return AfdSetDisconnectOptions(DeviceObject, Irp, IrpSp);
680
681 case IOCTL_AFD_GET_CONNECT_OPTIONS:
682 return AfdGetConnectOptions(DeviceObject, Irp, IrpSp);
683
684 case IOCTL_AFD_GET_DISCONNECT_OPTIONS:
685 return AfdGetDisconnectOptions(DeviceObject, Irp, IrpSp);
686
687 case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE:
688 return AfdSetConnectOptionsSize(DeviceObject, Irp, IrpSp);
689
690 case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE:
691 return AfdSetDisconnectOptionsSize(DeviceObject, Irp, IrpSp);
692
693 case IOCTL_AFD_GET_TDI_HANDLES:
694 DbgPrint("IOCTL_AFD_GET_TDI_HANDLES is UNIMPLEMENTED!\n");
695 break;
696
697 case IOCTL_AFD_DEFER_ACCEPT:
698 DbgPrint("IOCTL_AFD_DEFER_ACCEPT is UNIMPLEMENTED!\n");
699 break;
700
701 case IOCTL_AFD_GET_PENDING_CONNECT_DATA:
702 DbgPrint("IOCTL_AFD_GET_PENDING_CONNECT_DATA is UNIMPLEMENTED!\n");
703 break;
704
705 case IOCTL_AFD_VALIDATE_GROUP:
706 DbgPrint("IOCTL_AFD_VALIDATE_GROUP is UNIMPLEMENTED!\n");
707 break;
708
709 default:
710 Status = STATUS_NOT_SUPPORTED;
711 DbgPrint("Unknown IOCTL (0x%x)\n",
712 IrpSp->Parameters.DeviceIoControl.IoControlCode);
713 break;
714 }
715 break;
716 }
717
718 /* unsupported operations */
719 default:
720 {
721 Status = STATUS_NOT_IMPLEMENTED;
722 AFD_DbgPrint(MIN_TRACE,
723 ("Irp: Unknown Major code was %x\n",
724 IrpSp->MajorFunction));
725 break;
726 }
727 }
728
729 AFD_DbgPrint(MID_TRACE, ("Returning %x\n", Status));
730 Irp->IoStatus.Status = Status;
731 IoCompleteRequest(Irp, IO_NO_INCREMENT);
732
733 return (Status);
734 }
735
736 VOID NTAPI
737 AfdCancelHandler(PDEVICE_OBJECT DeviceObject,
738 PIRP Irp)
739 {
740 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
741 PFILE_OBJECT FileObject = IrpSp->FileObject;
742 PAFD_FCB FCB = FileObject->FsContext;
743 UINT Function;
744 PAFD_RECV_INFO RecvReq;
745 PAFD_SEND_INFO SendReq;
746 PLIST_ENTRY CurrentEntry;
747 PIRP CurrentIrp;
748 PAFD_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
749 KIRQL OldIrql;
750 PAFD_ACTIVE_POLL Poll;
751 PAFD_POLL_INFO PollReq;
752
753 IoReleaseCancelSpinLock(Irp->CancelIrql);
754
755 if (!SocketAcquireStateLock(FCB))
756 return;
757
758 ASSERT(IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
759
760 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
761 {
762 case IOCTL_AFD_RECV:
763 RecvReq = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
764 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
765 /* Fall through */
766
767 case IOCTL_AFD_RECV_DATAGRAM:
768 Function = FUNCTION_RECV;
769 break;
770
771 case IOCTL_AFD_SEND:
772 SendReq = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
773 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
774 /* Fall through */
775
776 case IOCTL_AFD_SEND_DATAGRAM:
777 Function = FUNCTION_SEND;
778 break;
779
780 case IOCTL_AFD_CONNECT:
781 Function = FUNCTION_CONNECT;
782 break;
783
784 case IOCTL_AFD_WAIT_FOR_LISTEN:
785 Function = FUNCTION_PREACCEPT;
786 break;
787
788 case IOCTL_AFD_SELECT:
789 KeAcquireSpinLock(&DeviceExt->Lock, &OldIrql);
790
791 CurrentEntry = DeviceExt->Polls.Flink;
792 while (CurrentEntry != &DeviceExt->Polls)
793 {
794 Poll = CONTAINING_RECORD(CurrentEntry, AFD_ACTIVE_POLL, ListEntry);
795 CurrentIrp = Poll->Irp;
796 PollReq = CurrentIrp->AssociatedIrp.SystemBuffer;
797
798 if (CurrentIrp == Irp)
799 {
800 ZeroEvents(PollReq->Handles, PollReq->HandleCount);
801 SignalSocket(Poll, NULL, PollReq, STATUS_CANCELLED);
802 break;
803 }
804 else
805 {
806 CurrentEntry = CurrentEntry->Flink;
807 }
808 }
809
810 KeReleaseSpinLock(&DeviceExt->Lock, OldIrql);
811
812 /* IRP already completed by SignalSocket */
813 SocketStateUnlock(FCB);
814 return;
815
816 default:
817 ASSERT(FALSE);
818 UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
819 return;
820 }
821
822 CurrentEntry = FCB->PendingIrpList[Function].Flink;
823 while (CurrentEntry != &FCB->PendingIrpList[Function])
824 {
825 CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
826
827 if (CurrentIrp == Irp)
828 {
829 RemoveEntryList(CurrentEntry);
830 break;
831 }
832 else
833 {
834 CurrentEntry = CurrentEntry->Flink;
835 }
836 }
837
838 UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
839 }
840
841 static VOID NTAPI
842 AfdUnload(PDRIVER_OBJECT DriverObject)
843 {
844 }
845
846 NTSTATUS NTAPI
847 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
848 {
849 PDEVICE_OBJECT DeviceObject;
850 UNICODE_STRING wstrDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Afd");
851 PAFD_DEVICE_EXTENSION DeviceExt;
852 NTSTATUS Status;
853
854 /* register driver routines */
855 DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdDispatch;
856 DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdDispatch;
857 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = AfdDispatch;
858 DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdDispatch;
859 DriverObject->MajorFunction[IRP_MJ_READ] = AfdDispatch;
860 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch;
861 DriverObject->DriverUnload = AfdUnload;
862
863 Status = IoCreateDevice
864 ( DriverObject,
865 sizeof(AFD_DEVICE_EXTENSION),
866 &wstrDeviceName,
867 FILE_DEVICE_NAMED_PIPE,
868 0,
869 FALSE,
870 &DeviceObject );
871
872 /* failure */
873 if(!NT_SUCCESS(Status))
874 {
875 return (Status);
876 }
877
878 DeviceExt = DeviceObject->DeviceExtension;
879 KeInitializeSpinLock( &DeviceExt->Lock );
880 InitializeListHead( &DeviceExt->Polls );
881
882 AFD_DbgPrint(MID_TRACE,("Device created: object %x ext %x\n",
883 DeviceObject, DeviceExt));
884
885 return (Status);
886 }
887
888 /* EOF */