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