c4feb08dbe44b329172120aacf43b61421359fa8
[reactos.git] / drivers / network / afd / afd / main.c
1 /*
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
17 #if DBG
18
19 /* See debug.h for debug/trace constants */
20 //DWORD DebugTraceLevel = DEBUG_ULTRA;
21 DWORD DebugTraceLevel = MIN_TRACE;
22
23 #endif /* DBG */
24
25 void OskitDumpBuffer( PCHAR Data, UINT Len ) {
26 unsigned int i;
27
28 for( i = 0; i < Len; i++ ) {
29 if( i && !(i & 0xf) ) DbgPrint( "\n" );
30 if( !(i & 0xf) ) DbgPrint( "%08x: ", (UINT)(Data + i) );
31 DbgPrint( " %02x", Data[i] & 0xff );
32 }
33 DbgPrint("\n");
34 }
35
36 /* FUNCTIONS */
37
38 NTSTATUS NTAPI
39 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
40
41 NTSTATUS NTAPI
42 AfdGetDisconnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp,
43 PIO_STACK_LOCATION IrpSp)
44 {
45 PFILE_OBJECT FileObject = IrpSp->FileObject;
46 PAFD_FCB FCB = FileObject->FsContext;
47 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
48
49 UNREFERENCED_PARAMETER(DeviceObject);
50
51 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
52
53 if (FCB->DisconnectOptionsSize == 0)
54 {
55 AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
56 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
57 }
58
59 ASSERT(FCB->DisconnectOptions);
60
61 if (FCB->FilledDisconnectOptions < BufferSize) BufferSize = FCB->FilledDisconnectOptions;
62
63 RtlCopyMemory(Irp->UserBuffer,
64 FCB->DisconnectOptions,
65 BufferSize);
66
67 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize);
68 }
69
70 NTSTATUS
71 NTAPI
72 AfdSetDisconnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp,
73 PIO_STACK_LOCATION IrpSp)
74 {
75 PFILE_OBJECT FileObject = IrpSp->FileObject;
76 PAFD_FCB FCB = FileObject->FsContext;
77 PVOID DisconnectOptions = LockRequest(Irp, IrpSp, FALSE, NULL);
78 UINT DisconnectOptionsSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
79
80 UNREFERENCED_PARAMETER(DeviceObject);
81
82 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
83
84 if (!DisconnectOptions)
85 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
86
87 if (FCB->DisconnectOptions)
88 {
89 ExFreePool(FCB->DisconnectOptions);
90 FCB->DisconnectOptions = NULL;
91 FCB->DisconnectOptionsSize = 0;
92 FCB->FilledDisconnectOptions = 0;
93 }
94
95 FCB->DisconnectOptions = ExAllocatePool(PagedPool, DisconnectOptionsSize);
96 if (!FCB->DisconnectOptions)
97 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
98
99 RtlCopyMemory(FCB->DisconnectOptions,
100 DisconnectOptions,
101 DisconnectOptionsSize);
102
103 FCB->DisconnectOptionsSize = DisconnectOptionsSize;
104
105 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
106 }
107
108 NTSTATUS
109 NTAPI
110 AfdSetDisconnectOptionsSize(PDEVICE_OBJECT DeviceObject, PIRP Irp,
111 PIO_STACK_LOCATION IrpSp)
112 {
113 PFILE_OBJECT FileObject = IrpSp->FileObject;
114 PAFD_FCB FCB = FileObject->FsContext;
115 PUINT DisconnectOptionsSize = LockRequest(Irp, IrpSp, FALSE, NULL);
116 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
117
118 UNREFERENCED_PARAMETER(DeviceObject);
119
120 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
121
122 if (!DisconnectOptionsSize)
123 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
124
125 if (BufferSize < sizeof(UINT))
126 {
127 AFD_DbgPrint(MIN_TRACE,("Buffer too small\n"));
128 return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0);
129 }
130
131 if (FCB->DisconnectOptions)
132 {
133 ExFreePool(FCB->DisconnectOptions);
134 FCB->DisconnectOptionsSize = 0;
135 FCB->FilledDisconnectOptions = 0;
136 }
137
138 FCB->DisconnectOptions = ExAllocatePool(PagedPool, *DisconnectOptionsSize);
139 if (!FCB->DisconnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
140
141 FCB->DisconnectOptionsSize = *DisconnectOptionsSize;
142
143 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
144 }
145
146 NTSTATUS NTAPI
147 AfdGetDisconnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
148 PIO_STACK_LOCATION IrpSp)
149 {
150 PFILE_OBJECT FileObject = IrpSp->FileObject;
151 PAFD_FCB FCB = FileObject->FsContext;
152 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
153
154 UNREFERENCED_PARAMETER(DeviceObject);
155
156 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
157
158 if (FCB->DisconnectDataSize == 0)
159 {
160 AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
161 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
162 }
163
164 ASSERT(FCB->DisconnectData);
165
166 if (FCB->FilledDisconnectData < BufferSize)
167 BufferSize = FCB->FilledDisconnectData;
168
169 RtlCopyMemory(Irp->UserBuffer,
170 FCB->DisconnectData,
171 BufferSize);
172
173 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize);
174 }
175
176 NTSTATUS
177 NTAPI
178 AfdSetDisconnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
179 PIO_STACK_LOCATION IrpSp)
180 {
181 PFILE_OBJECT FileObject = IrpSp->FileObject;
182 PAFD_FCB FCB = FileObject->FsContext;
183 PVOID DisconnectData = LockRequest(Irp, IrpSp, FALSE, NULL);
184 UINT DisconnectDataSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
185
186 UNREFERENCED_PARAMETER(DeviceObject);
187
188 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
189
190 if (!DisconnectData)
191 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
192
193 if (FCB->DisconnectData)
194 {
195 ExFreePool(FCB->DisconnectData);
196 FCB->DisconnectData = NULL;
197 FCB->DisconnectDataSize = 0;
198 FCB->FilledDisconnectData = 0;
199 }
200
201 FCB->DisconnectData = ExAllocatePool(PagedPool, DisconnectDataSize);
202 if (!FCB->DisconnectData)
203 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
204
205 RtlCopyMemory(FCB->DisconnectData,
206 DisconnectData,
207 DisconnectDataSize);
208
209 FCB->DisconnectDataSize = DisconnectDataSize;
210
211 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
212 }
213
214 NTSTATUS
215 NTAPI
216 AfdSetDisconnectDataSize(PDEVICE_OBJECT DeviceObject, PIRP Irp,
217 PIO_STACK_LOCATION IrpSp)
218 {
219 PFILE_OBJECT FileObject = IrpSp->FileObject;
220 PAFD_FCB FCB = FileObject->FsContext;
221 PUINT DisconnectDataSize = LockRequest(Irp, IrpSp, FALSE, NULL);
222 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
223
224 UNREFERENCED_PARAMETER(DeviceObject);
225
226 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
227
228 if (!DisconnectDataSize)
229 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
230
231 if (BufferSize < sizeof(UINT))
232 {
233 AFD_DbgPrint(MIN_TRACE,("Buffer too small\n"));
234 return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0);
235 }
236
237 if (FCB->DisconnectData)
238 {
239 ExFreePool(FCB->DisconnectData);
240 FCB->DisconnectDataSize = 0;
241 FCB->FilledDisconnectData = 0;
242 }
243
244 FCB->DisconnectData = ExAllocatePool(PagedPool, *DisconnectDataSize);
245 if (!FCB->DisconnectData)
246 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
247
248 FCB->DisconnectDataSize = *DisconnectDataSize;
249
250 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
251 }
252
253 static NTSTATUS NTAPI
254 AfdGetTdiHandles(PDEVICE_OBJECT DeviceObject, PIRP Irp,
255 PIO_STACK_LOCATION IrpSp)
256 {
257 PFILE_OBJECT FileObject = IrpSp->FileObject;
258 PAFD_FCB FCB = FileObject->FsContext;
259 PULONG HandleFlags = LockRequest(Irp, IrpSp, TRUE, NULL);
260 PAFD_TDI_HANDLE_DATA HandleData = Irp->UserBuffer;
261
262 UNREFERENCED_PARAMETER(DeviceObject);
263
264 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
265
266 if (!HandleFlags)
267 return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
268
269 if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG) ||
270 IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(*HandleData))
271 {
272 AFD_DbgPrint(MIN_TRACE,("Buffer too small\n"));
273 return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0);
274 }
275
276 if ((*HandleFlags) & AFD_ADDRESS_HANDLE)
277 HandleData->TdiAddressHandle = FCB->AddressFile.Handle;
278
279 if ((*HandleFlags) & AFD_CONNECTION_HANDLE)
280 HandleData->TdiConnectionHandle = FCB->Connection.Handle;
281
282 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
283 }
284
285 static NTSTATUS NTAPI
286 AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
287 PIO_STACK_LOCATION IrpSp) {
288 PAFD_FCB FCB;
289 PFILE_OBJECT FileObject;
290 PAFD_DEVICE_EXTENSION DeviceExt;
291 PFILE_FULL_EA_INFORMATION EaInfo;
292 PAFD_CREATE_PACKET ConnectInfo = NULL;
293 //ULONG EaLength;
294 PWCHAR EaInfoValue = NULL;
295 //UINT Disposition;
296 UINT i;
297 NTSTATUS Status = STATUS_SUCCESS;
298
299 AFD_DbgPrint(MID_TRACE,("AfdCreate(DeviceObject %p Irp %p)\n",
300 DeviceObject, Irp));
301
302 DeviceExt = DeviceObject->DeviceExtension;
303 FileObject = IrpSp->FileObject;
304 //Disposition = (IrpSp->Parameters.Create.Options >> 24) & 0xff;
305
306 Irp->IoStatus.Information = 0;
307
308 EaInfo = Irp->AssociatedIrp.SystemBuffer;
309
310 if( EaInfo ) {
311 ConnectInfo = (PAFD_CREATE_PACKET)(EaInfo->EaName + EaInfo->EaNameLength + 1);
312 EaInfoValue = (PWCHAR)(((PCHAR)ConnectInfo) + sizeof(AFD_CREATE_PACKET));
313
314 //EaLength = sizeof(FILE_FULL_EA_INFORMATION) + EaInfo->EaNameLength + EaInfo->EaValueLength;
315
316 AFD_DbgPrint(MID_TRACE,("EaInfo: %p, EaInfoValue: %p\n",
317 EaInfo, EaInfoValue));
318 }
319
320 AFD_DbgPrint(MID_TRACE,("About to allocate the new FCB\n"));
321
322 FCB = ExAllocatePool(NonPagedPool, sizeof(AFD_FCB));
323 if( FCB == NULL ) {
324 Irp->IoStatus.Status = STATUS_NO_MEMORY;
325 IoCompleteRequest(Irp, IO_NO_INCREMENT);
326 return STATUS_NO_MEMORY;
327 }
328
329 AFD_DbgPrint(MID_TRACE,("Initializing the new FCB @ %p (FileObject %p Flags %x)\n",
330 FCB, FileObject, ConnectInfo ? ConnectInfo->EndpointFlags : 0));
331
332 RtlZeroMemory( FCB, sizeof( *FCB ) );
333
334 FCB->Flags = ConnectInfo ? ConnectInfo->EndpointFlags : 0;
335 FCB->GroupID = ConnectInfo ? ConnectInfo->GroupID : 0;
336 FCB->GroupType = 0; /* FIXME */
337 FCB->State = SOCKET_STATE_CREATED;
338 FCB->FileObject = FileObject;
339 FCB->DeviceExt = DeviceExt;
340 FCB->AddressFile.Handle = INVALID_HANDLE_VALUE;
341 FCB->Connection.Handle = INVALID_HANDLE_VALUE;
342
343 KeInitializeMutex( &FCB->Mutex, 0 );
344
345 for( i = 0; i < MAX_FUNCTIONS; i++ ) {
346 InitializeListHead( &FCB->PendingIrpList[i] );
347 }
348
349 InitializeListHead( &FCB->DatagramList );
350 InitializeListHead( &FCB->PendingConnections );
351
352 AFD_DbgPrint(MID_TRACE,("%p: Checking command channel\n", FCB));
353
354 if( ConnectInfo ) {
355 FCB->TdiDeviceName.Length = ConnectInfo->SizeOfTransportName;
356 FCB->TdiDeviceName.MaximumLength = FCB->TdiDeviceName.Length;
357 FCB->TdiDeviceName.Buffer =
358 ExAllocatePool( NonPagedPool, FCB->TdiDeviceName.Length );
359
360 if( !FCB->TdiDeviceName.Buffer ) {
361 ExFreePool(FCB);
362 AFD_DbgPrint(MID_TRACE,("Could not copy target string\n"));
363 Irp->IoStatus.Status = STATUS_NO_MEMORY;
364 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
365 return STATUS_NO_MEMORY;
366 }
367
368 RtlCopyMemory( FCB->TdiDeviceName.Buffer,
369 ConnectInfo->TransportName,
370 FCB->TdiDeviceName.Length );
371
372 AFD_DbgPrint(MID_TRACE,("Success: %s %wZ\n",
373 EaInfo->EaName, &FCB->TdiDeviceName));
374 } else {
375 AFD_DbgPrint(MID_TRACE,("Success: Control connection\n"));
376 }
377
378 FileObject->FsContext = FCB;
379
380 /* It seems that UDP sockets are writable from inception */
381 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) {
382 AFD_DbgPrint(MID_TRACE,("Packet oriented socket\n"));
383
384 /* A datagram socket is always sendable */
385 FCB->PollState |= AFD_EVENT_SEND;
386 FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
387 PollReeval( FCB->DeviceExt, FCB->FileObject );
388 }
389
390 if( !NT_SUCCESS(Status) ) {
391 if( FCB->TdiDeviceName.Buffer ) ExFreePool( FCB->TdiDeviceName.Buffer );
392 ExFreePool( FCB );
393 FileObject->FsContext = NULL;
394 }
395
396 Irp->IoStatus.Status = Status;
397 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
398
399 return Status;
400 }
401
402 static NTSTATUS NTAPI
403 AfdCleanupSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
404 PIO_STACK_LOCATION IrpSp)
405 {
406 PFILE_OBJECT FileObject = IrpSp->FileObject;
407 PAFD_FCB FCB = FileObject->FsContext;
408 PLIST_ENTRY CurrentEntry, NextEntry;
409 UINT Function;
410 PIRP CurrentIrp;
411
412 UNREFERENCED_PARAMETER(DeviceObject);
413
414 if( !SocketAcquireStateLock( FCB ) ) return LostSocket(Irp);
415
416 for (Function = 0; Function < MAX_FUNCTIONS; Function++)
417 {
418 CurrentEntry = FCB->PendingIrpList[Function].Flink;
419 while (CurrentEntry != &FCB->PendingIrpList[Function])
420 {
421 NextEntry = CurrentEntry->Flink;
422 CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
423
424 /* The cancel routine will remove the IRP from the list */
425 IoCancelIrp(CurrentIrp);
426
427 CurrentEntry = NextEntry;
428 }
429 }
430
431 KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
432
433 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
434 }
435
436 static NTSTATUS NTAPI
437 AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
438 PIO_STACK_LOCATION IrpSp)
439 {
440 PFILE_OBJECT FileObject = IrpSp->FileObject;
441 PAFD_FCB FCB = FileObject->FsContext;
442 UINT i;
443 PAFD_IN_FLIGHT_REQUEST InFlightRequest[IN_FLIGHT_REQUESTS];
444 PAFD_TDI_OBJECT_QELT Qelt;
445 PLIST_ENTRY QeltEntry;
446
447
448 AFD_DbgPrint(MID_TRACE,("AfdClose(DeviceObject %p Irp %p)\n",
449 DeviceObject, Irp));
450
451 if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED;
452
453 FCB->State = SOCKET_STATE_CLOSED;
454
455 InFlightRequest[0] = &FCB->ListenIrp;
456 InFlightRequest[1] = &FCB->ReceiveIrp;
457 InFlightRequest[2] = &FCB->SendIrp;
458 InFlightRequest[3] = &FCB->ConnectIrp;
459 InFlightRequest[4] = &FCB->DisconnectIrp;
460
461 /* Cancel our pending requests */
462 for( i = 0; i < IN_FLIGHT_REQUESTS; i++ ) {
463 if( InFlightRequest[i]->InFlightRequest ) {
464 AFD_DbgPrint(MID_TRACE,("Cancelling in flight irp %u (%p)\n",
465 i, InFlightRequest[i]->InFlightRequest));
466 IoCancelIrp(InFlightRequest[i]->InFlightRequest);
467 }
468 }
469
470 KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
471
472 ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_CONNECT]));
473 ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]));
474 ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]));
475 ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_PREACCEPT]));
476 ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT]));
477
478 while (!IsListEmpty(&FCB->PendingConnections))
479 {
480 QeltEntry = RemoveHeadList(&FCB->PendingConnections);
481 Qelt = CONTAINING_RECORD(QeltEntry, AFD_TDI_OBJECT_QELT, ListEntry);
482
483 /* We have to close all pending connections or the listen won't get closed */
484 TdiDisassociateAddressFile(Qelt->Object.Object);
485 ObDereferenceObject(Qelt->Object.Object);
486 ZwClose(Qelt->Object.Handle);
487
488 ExFreePool(Qelt);
489 }
490
491 SocketStateUnlock( FCB );
492
493 if( FCB->EventSelect )
494 ObDereferenceObject( FCB->EventSelect );
495
496 if( FCB->Context )
497 ExFreePool( FCB->Context );
498
499 if( FCB->Recv.Window )
500 ExFreePool( FCB->Recv.Window );
501
502 if( FCB->Send.Window )
503 ExFreePool( FCB->Send.Window );
504
505 if( FCB->AddressFrom )
506 ExFreePool( FCB->AddressFrom );
507
508 if( FCB->ConnectCallInfo )
509 ExFreePool( FCB->ConnectCallInfo );
510
511 if( FCB->ConnectReturnInfo )
512 ExFreePool( FCB->ConnectReturnInfo );
513
514 if( FCB->ConnectData )
515 ExFreePool( FCB->ConnectData );
516
517 if( FCB->DisconnectData )
518 ExFreePool( FCB->DisconnectData );
519
520 if( FCB->ConnectOptions )
521 ExFreePool( FCB->ConnectOptions );
522
523 if( FCB->DisconnectOptions )
524 ExFreePool( FCB->DisconnectOptions );
525
526 if( FCB->LocalAddress )
527 ExFreePool( FCB->LocalAddress );
528
529 if( FCB->RemoteAddress )
530 ExFreePool( FCB->RemoteAddress );
531
532 if( FCB->Connection.Object )
533 {
534 TdiDisassociateAddressFile(FCB->Connection.Object);
535 ObDereferenceObject(FCB->Connection.Object);
536 }
537
538 if( FCB->AddressFile.Object )
539 ObDereferenceObject(FCB->AddressFile.Object);
540
541 if( FCB->AddressFile.Handle != INVALID_HANDLE_VALUE )
542 {
543 if (ZwClose(FCB->AddressFile.Handle) == STATUS_INVALID_HANDLE)
544 {
545 DbgPrint("INVALID ADDRESS FILE HANDLE VALUE: %p %p\n", FCB->AddressFile.Handle, FCB->AddressFile.Object);
546 }
547 }
548
549 if( FCB->Connection.Handle != INVALID_HANDLE_VALUE )
550 {
551 if (ZwClose(FCB->Connection.Handle) == STATUS_INVALID_HANDLE)
552 {
553 DbgPrint("INVALID CONNECTION HANDLE VALUE: %p %p\n", FCB->Connection.Handle, FCB->Connection.Object);
554 }
555 }
556
557 if( FCB->TdiDeviceName.Buffer )
558 ExFreePool(FCB->TdiDeviceName.Buffer);
559
560 ExFreePool(FCB);
561
562 Irp->IoStatus.Status = STATUS_SUCCESS;
563 Irp->IoStatus.Information = 0;
564 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
565
566 AFD_DbgPrint(MID_TRACE, ("Returning success.\n"));
567
568 return STATUS_SUCCESS;
569 }
570
571 static IO_COMPLETION_ROUTINE DisconnectComplete;
572 static
573 NTSTATUS
574 NTAPI
575 DisconnectComplete(PDEVICE_OBJECT DeviceObject,
576 PIRP Irp,
577 PVOID Context)
578 {
579 PAFD_FCB FCB = Context;
580 PIRP CurrentIrp;
581 PLIST_ENTRY CurrentEntry;
582
583 UNREFERENCED_PARAMETER(DeviceObject);
584
585 if (!SocketAcquireStateLock(FCB))
586 return STATUS_FILE_CLOSED;
587
588 ASSERT(FCB->DisconnectIrp.InFlightRequest == Irp);
589 FCB->DisconnectIrp.InFlightRequest = NULL;
590
591 ASSERT(FCB->DisconnectPending);
592 ASSERT((IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && !FCB->SendIrp.InFlightRequest) ||
593 (FCB->DisconnectFlags & TDI_DISCONNECT_ABORT));
594
595 if (NT_SUCCESS(Irp->IoStatus.Status) && (FCB->DisconnectFlags & TDI_DISCONNECT_RELEASE))
596 {
597 FCB->FilledDisconnectData = MIN(FCB->DisconnectDataSize, FCB->ConnectReturnInfo->UserDataLength);
598 if (FCB->FilledDisconnectData)
599 {
600 RtlCopyMemory(FCB->DisconnectData,
601 FCB->ConnectReturnInfo->UserData,
602 FCB->FilledDisconnectData);
603 }
604
605 FCB->FilledDisconnectOptions = MIN(FCB->DisconnectOptionsSize, FCB->ConnectReturnInfo->OptionsLength);
606 if (FCB->FilledDisconnectOptions)
607 {
608 RtlCopyMemory(FCB->DisconnectOptions,
609 FCB->ConnectReturnInfo->Options,
610 FCB->FilledDisconnectOptions);
611 }
612 }
613
614 FCB->DisconnectPending = FALSE;
615
616 while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT]))
617 {
618 CurrentEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_DISCONNECT]);
619 CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
620 CurrentIrp->IoStatus.Status = Irp->IoStatus.Status;
621 CurrentIrp->IoStatus.Information = 0;
622 UnlockRequest(CurrentIrp, IoGetCurrentIrpStackLocation(CurrentIrp));
623 (void)IoSetCancelRoutine(CurrentIrp, NULL);
624 IoCompleteRequest(CurrentIrp, IO_NETWORK_INCREMENT );
625 }
626
627 if (!(FCB->DisconnectFlags & TDI_DISCONNECT_RELEASE))
628 {
629 /* Signal complete connection closure immediately */
630 FCB->PollState |= AFD_EVENT_ABORT;
631 FCB->PollStatus[FD_CLOSE_BIT] = Irp->IoStatus.Status;
632 FCB->LastReceiveStatus = STATUS_FILE_CLOSED;
633 PollReeval(FCB->DeviceExt, FCB->FileObject);
634 }
635
636 SocketStateUnlock(FCB);
637
638 return Irp->IoStatus.Status;
639 }
640
641 static
642 NTSTATUS
643 DoDisconnect(PAFD_FCB FCB)
644 {
645 NTSTATUS Status;
646
647 ASSERT(FCB->DisconnectPending);
648 ASSERT((IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && !FCB->SendIrp.InFlightRequest) ||
649 (FCB->DisconnectFlags & TDI_DISCONNECT_ABORT));
650
651 if (FCB->DisconnectIrp.InFlightRequest)
652 {
653 return STATUS_PENDING;
654 }
655
656 FCB->ConnectCallInfo->UserData = FCB->DisconnectData;
657 FCB->ConnectCallInfo->UserDataLength = FCB->DisconnectDataSize;
658 FCB->ConnectCallInfo->Options = FCB->DisconnectOptions;
659 FCB->ConnectCallInfo->OptionsLength = FCB->DisconnectOptionsSize;
660
661 Status = TdiDisconnect(&FCB->DisconnectIrp.InFlightRequest,
662 FCB->Connection.Object,
663 &FCB->DisconnectTimeout,
664 FCB->DisconnectFlags,
665 DisconnectComplete,
666 FCB,
667 FCB->ConnectCallInfo,
668 FCB->ConnectReturnInfo);
669 if (Status != STATUS_PENDING)
670 {
671 FCB->DisconnectPending = FALSE;
672 }
673
674 return Status;
675 }
676
677 VOID
678 RetryDisconnectCompletion(PAFD_FCB FCB)
679 {
680 ASSERT(FCB->RemoteAddress);
681
682 if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && !FCB->SendIrp.InFlightRequest && FCB->DisconnectPending)
683 {
684 /* Sends are done; fire off a TDI_DISCONNECT request */
685 DoDisconnect(FCB);
686 }
687 }
688
689 static NTSTATUS NTAPI
690 AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
691 PIO_STACK_LOCATION IrpSp) {
692 PFILE_OBJECT FileObject = IrpSp->FileObject;
693 PAFD_FCB FCB = FileObject->FsContext;
694 PAFD_DISCONNECT_INFO DisReq;
695 NTSTATUS Status = STATUS_SUCCESS;
696 USHORT Flags;
697 PLIST_ENTRY CurrentEntry;
698 PIRP CurrentIrp;
699
700 UNREFERENCED_PARAMETER(DeviceObject);
701
702 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
703
704 if (!(DisReq = LockRequest(Irp, IrpSp, FALSE, NULL)))
705 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
706 Irp, 0 );
707
708 /* Send direction only */
709 if ((DisReq->DisconnectType & AFD_DISCONNECT_SEND) &&
710 !(DisReq->DisconnectType & AFD_DISCONNECT_RECV))
711 {
712 /* Perform a controlled disconnect */
713 Flags = TDI_DISCONNECT_RELEASE;
714 }
715 /* Receive direction or both */
716 else
717 {
718 /* Mark that we can't issue another receive request */
719 FCB->TdiReceiveClosed = TRUE;
720
721 /* Try to cancel a pending TDI receive IRP if there was one in progress */
722 if (FCB->ReceiveIrp.InFlightRequest)
723 IoCancelIrp(FCB->ReceiveIrp.InFlightRequest);
724
725 /* Discard any pending data */
726 FCB->Recv.Content = 0;
727 FCB->Recv.BytesUsed = 0;
728
729 /* Mark us as overread to complete future reads with an error */
730 FCB->Overread = TRUE;
731
732 /* Set a successful receive status to indicate a shutdown on overread */
733 FCB->LastReceiveStatus = STATUS_SUCCESS;
734
735 /* Clear the receive event */
736 FCB->PollState &= ~AFD_EVENT_RECEIVE;
737
738 /* Receive direction only */
739 if ((DisReq->DisconnectType & AFD_DISCONNECT_RECV) &&
740 !(DisReq->DisconnectType & AFD_DISCONNECT_SEND))
741 {
742 /* No need to tell the transport driver for receive direction only */
743 return UnlockAndMaybeComplete( FCB, STATUS_SUCCESS, Irp, 0 );
744 }
745 else
746 {
747 /* Perform an abortive disconnect */
748 Flags = TDI_DISCONNECT_ABORT;
749 }
750 }
751
752 if (!(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS))
753 {
754 if (!FCB->ConnectCallInfo)
755 {
756 AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
757 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
758 Irp, 0 );
759 }
760
761 if (FCB->DisconnectPending)
762 {
763 if (FCB->DisconnectIrp.InFlightRequest)
764 {
765 IoCancelIrp(FCB->DisconnectIrp.InFlightRequest);
766 ASSERT(!FCB->DisconnectIrp.InFlightRequest);
767 }
768 else
769 {
770 while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT]))
771 {
772 CurrentEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_DISCONNECT]);
773 CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
774 CurrentIrp->IoStatus.Status = STATUS_CANCELLED;
775 CurrentIrp->IoStatus.Information = 0;
776 UnlockRequest(CurrentIrp, IoGetCurrentIrpStackLocation(CurrentIrp));
777 (void)IoSetCancelRoutine(CurrentIrp, NULL);
778 IoCompleteRequest(CurrentIrp, IO_NETWORK_INCREMENT );
779 }
780 }
781 }
782
783 FCB->DisconnectFlags = Flags;
784 FCB->DisconnectTimeout = DisReq->Timeout;
785 FCB->DisconnectPending = TRUE;
786 FCB->SendClosed = TRUE;
787 FCB->PollState &= ~AFD_EVENT_SEND;
788
789 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_DISCONNECT);
790 if (Status == STATUS_PENDING)
791 {
792 if ((IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && !FCB->SendIrp.InFlightRequest) ||
793 (FCB->DisconnectFlags & TDI_DISCONNECT_ABORT))
794 {
795 /* Go ahead and execute the disconnect because we're ready for it */
796 Status = DoDisconnect(FCB);
797 }
798
799 if (Status != STATUS_PENDING)
800 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
801 }
802
803 if (Status == STATUS_PENDING)
804 {
805 SocketStateUnlock(FCB);
806
807 return Status;
808 }
809 }
810 else
811 {
812 if (!(Flags & TDI_DISCONNECT_RELEASE))
813 {
814 if (!FCB->RemoteAddress)
815 {
816 AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
817 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
818 }
819
820 ExFreePool(FCB->RemoteAddress);
821
822 FCB->RemoteAddress = NULL;
823 }
824
825 FCB->PollState &= ~AFD_EVENT_SEND;
826 FCB->SendClosed = TRUE;
827 }
828
829 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
830 }
831
832 static DRIVER_DISPATCH AfdDispatch;
833 static NTSTATUS NTAPI
834 AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
835 {
836 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
837 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
838 #if DBG
839 PFILE_OBJECT FileObject = IrpSp->FileObject;
840 #endif
841
842 AFD_DbgPrint(MID_TRACE,("AfdDispatch: %u\n", IrpSp->MajorFunction));
843 if( IrpSp->MajorFunction != IRP_MJ_CREATE) {
844 AFD_DbgPrint(MID_TRACE,("FO %p, IrpSp->FO %p\n",
845 FileObject, IrpSp->FileObject));
846 ASSERT(FileObject == IrpSp->FileObject);
847 }
848
849 Irp->IoStatus.Information = 0;
850
851 switch(IrpSp->MajorFunction)
852 {
853 /* opening and closing handles to the device */
854 case IRP_MJ_CREATE:
855 /* Mostly borrowed from the named pipe file system */
856 return AfdCreateSocket(DeviceObject, Irp, IrpSp);
857
858 case IRP_MJ_CLOSE:
859 /* Ditto the borrowing */
860 return AfdCloseSocket(DeviceObject, Irp, IrpSp);
861
862 case IRP_MJ_CLEANUP:
863 return AfdCleanupSocket(DeviceObject, Irp, IrpSp);
864
865 /* write data */
866 case IRP_MJ_WRITE:
867 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp, TRUE );
868
869 /* read data */
870 case IRP_MJ_READ:
871 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp, TRUE );
872
873 case IRP_MJ_DEVICE_CONTROL:
874 {
875 switch( IrpSp->Parameters.DeviceIoControl.IoControlCode ) {
876 case IOCTL_AFD_BIND:
877 return AfdBindSocket( DeviceObject, Irp, IrpSp );
878
879 case IOCTL_AFD_CONNECT:
880 return AfdStreamSocketConnect( DeviceObject, Irp, IrpSp );
881
882 case IOCTL_AFD_START_LISTEN:
883 return AfdListenSocket( DeviceObject, Irp, IrpSp );
884
885 case IOCTL_AFD_RECV:
886 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp,
887 FALSE );
888
889 case IOCTL_AFD_SELECT:
890 return AfdSelect( DeviceObject, Irp, IrpSp );
891
892 case IOCTL_AFD_EVENT_SELECT:
893 return AfdEventSelect( DeviceObject, Irp, IrpSp );
894
895 case IOCTL_AFD_ENUM_NETWORK_EVENTS:
896 return AfdEnumEvents( DeviceObject, Irp, IrpSp );
897
898 case IOCTL_AFD_RECV_DATAGRAM:
899 return AfdPacketSocketReadData( DeviceObject, Irp, IrpSp );
900
901 case IOCTL_AFD_SEND:
902 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp,
903 FALSE );
904
905 case IOCTL_AFD_SEND_DATAGRAM:
906 return AfdPacketSocketWriteData( DeviceObject, Irp, IrpSp );
907
908 case IOCTL_AFD_GET_INFO:
909 return AfdGetInfo( DeviceObject, Irp, IrpSp );
910
911 case IOCTL_AFD_SET_INFO:
912 return AfdSetInfo( DeviceObject, Irp, IrpSp );
913
914 case IOCTL_AFD_GET_CONTEXT_SIZE:
915 return AfdGetContextSize( DeviceObject, Irp, IrpSp );
916
917 case IOCTL_AFD_GET_CONTEXT:
918 return AfdGetContext( DeviceObject, Irp, IrpSp );
919
920 case IOCTL_AFD_SET_CONTEXT:
921 return AfdSetContext( DeviceObject, Irp, IrpSp );
922
923 case IOCTL_AFD_WAIT_FOR_LISTEN:
924 return AfdWaitForListen( DeviceObject, Irp, IrpSp );
925
926 case IOCTL_AFD_ACCEPT:
927 return AfdAccept( DeviceObject, Irp, IrpSp );
928
929 case IOCTL_AFD_DISCONNECT:
930 return AfdDisconnect( DeviceObject, Irp, IrpSp );
931
932 case IOCTL_AFD_GET_SOCK_NAME:
933 return AfdGetSockName( DeviceObject, Irp, IrpSp );
934
935 case IOCTL_AFD_GET_PEER_NAME:
936 return AfdGetPeerName( DeviceObject, Irp, IrpSp );
937
938 case IOCTL_AFD_GET_CONNECT_DATA:
939 return AfdGetConnectData(DeviceObject, Irp, IrpSp);
940
941 case IOCTL_AFD_SET_CONNECT_DATA:
942 return AfdSetConnectData(DeviceObject, Irp, IrpSp);
943
944 case IOCTL_AFD_SET_DISCONNECT_DATA:
945 return AfdSetDisconnectData(DeviceObject, Irp, IrpSp);
946
947 case IOCTL_AFD_GET_DISCONNECT_DATA:
948 return AfdGetDisconnectData(DeviceObject, Irp, IrpSp);
949
950 case IOCTL_AFD_SET_CONNECT_DATA_SIZE:
951 return AfdSetConnectDataSize(DeviceObject, Irp, IrpSp);
952
953 case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE:
954 return AfdSetDisconnectDataSize(DeviceObject, Irp, IrpSp);
955
956 case IOCTL_AFD_SET_CONNECT_OPTIONS:
957 return AfdSetConnectOptions(DeviceObject, Irp, IrpSp);
958
959 case IOCTL_AFD_SET_DISCONNECT_OPTIONS:
960 return AfdSetDisconnectOptions(DeviceObject, Irp, IrpSp);
961
962 case IOCTL_AFD_GET_CONNECT_OPTIONS:
963 return AfdGetConnectOptions(DeviceObject, Irp, IrpSp);
964
965 case IOCTL_AFD_GET_DISCONNECT_OPTIONS:
966 return AfdGetDisconnectOptions(DeviceObject, Irp, IrpSp);
967
968 case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE:
969 return AfdSetConnectOptionsSize(DeviceObject, Irp, IrpSp);
970
971 case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE:
972 return AfdSetDisconnectOptionsSize(DeviceObject, Irp, IrpSp);
973
974 case IOCTL_AFD_GET_TDI_HANDLES:
975 return AfdGetTdiHandles(DeviceObject, Irp, IrpSp);
976
977 case IOCTL_AFD_DEFER_ACCEPT:
978 DbgPrint("IOCTL_AFD_DEFER_ACCEPT is UNIMPLEMENTED!\n");
979 break;
980
981 case IOCTL_AFD_GET_PENDING_CONNECT_DATA:
982 DbgPrint("IOCTL_AFD_GET_PENDING_CONNECT_DATA is UNIMPLEMENTED!\n");
983 break;
984
985 case IOCTL_AFD_VALIDATE_GROUP:
986 DbgPrint("IOCTL_AFD_VALIDATE_GROUP is UNIMPLEMENTED!\n");
987 break;
988
989 default:
990 Status = STATUS_NOT_SUPPORTED;
991 DbgPrint("Unknown IOCTL (0x%x)\n",
992 IrpSp->Parameters.DeviceIoControl.IoControlCode);
993 break;
994 }
995 break;
996 }
997
998 /* unsupported operations */
999 default:
1000 {
1001 Status = STATUS_NOT_IMPLEMENTED;
1002 AFD_DbgPrint(MIN_TRACE,
1003 ("Irp: Unknown Major code was %x\n",
1004 IrpSp->MajorFunction));
1005 break;
1006 }
1007 }
1008
1009 AFD_DbgPrint(MID_TRACE, ("Returning %x\n", Status));
1010 Irp->IoStatus.Status = Status;
1011 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1012
1013 return Status;
1014 }
1015
1016 BOOLEAN CheckUnlockExtraBuffers(PAFD_FCB FCB, PIO_STACK_LOCATION IrpSp)
1017 {
1018 if (FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)
1019 {
1020 if (IrpSp->MajorFunction == IRP_MJ_READ || IrpSp->MajorFunction == IRP_MJ_WRITE)
1021 {
1022 /* read()/write() call - no extra buffers */
1023 return FALSE;
1024 }
1025 else if (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
1026 {
1027 if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV_DATAGRAM)
1028 {
1029 /* recvfrom() call - extra buffers */
1030 return TRUE;
1031 }
1032 else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV)
1033 {
1034 /* recv() call - no extra buffers */
1035 return FALSE;
1036 }
1037 else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND ||
1038 IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND_DATAGRAM)
1039 {
1040 /* send()/sendto() call - no extra buffers */
1041 return FALSE;
1042 }
1043 else
1044 {
1045 /* Unknown IOCTL */
1046 ASSERT(FALSE);
1047 return FALSE;
1048 }
1049 }
1050 else
1051 {
1052 /* Unknown IRP_MJ code */
1053 ASSERT(FALSE);
1054 return FALSE;
1055 }
1056 }
1057 else
1058 {
1059 /* Connection-oriented never has extra buffers */
1060 return FALSE;
1061 }
1062 }
1063
1064 VOID
1065 CleanupPendingIrp(PAFD_FCB FCB, PIRP Irp, PIO_STACK_LOCATION IrpSp, PAFD_ACTIVE_POLL Poll)
1066 {
1067 PAFD_RECV_INFO RecvReq;
1068 PAFD_SEND_INFO SendReq;
1069 PAFD_POLL_INFO PollReq;
1070
1071 if (IrpSp->MajorFunction == IRP_MJ_READ)
1072 {
1073 RecvReq = GetLockedData(Irp, IrpSp);
1074 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp));
1075 }
1076 else if (IrpSp->MajorFunction == IRP_MJ_WRITE)
1077 {
1078 SendReq = GetLockedData(Irp, IrpSp);
1079 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp));
1080 }
1081 else
1082 {
1083 ASSERT(IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
1084
1085 if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV)
1086 {
1087 RecvReq = GetLockedData(Irp, IrpSp);
1088 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp));
1089 }
1090 else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND)
1091 {
1092 SendReq = GetLockedData(Irp, IrpSp);
1093 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp));
1094 }
1095 else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SELECT)
1096 {
1097 ASSERT(Poll);
1098
1099 PollReq = Irp->AssociatedIrp.SystemBuffer;
1100 ZeroEvents(PollReq->Handles, PollReq->HandleCount);
1101 SignalSocket(Poll, NULL, PollReq, STATUS_CANCELLED);
1102 }
1103 }
1104 }
1105
1106 VOID
1107 NTAPI
1108 AfdCancelHandler(PDEVICE_OBJECT DeviceObject,
1109 PIRP Irp)
1110 {
1111 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
1112 PFILE_OBJECT FileObject = IrpSp->FileObject;
1113 PAFD_FCB FCB = FileObject->FsContext;
1114 ULONG Function, IoctlCode;
1115 PIRP CurrentIrp;
1116 PLIST_ENTRY CurrentEntry;
1117 PAFD_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
1118 KIRQL OldIrql;
1119 PAFD_ACTIVE_POLL Poll;
1120
1121 IoReleaseCancelSpinLock(Irp->CancelIrql);
1122
1123 if (!SocketAcquireStateLock(FCB))
1124 return;
1125
1126 switch (IrpSp->MajorFunction)
1127 {
1128 case IRP_MJ_DEVICE_CONTROL:
1129 IoctlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
1130 break;
1131
1132 case IRP_MJ_READ:
1133 IoctlCode = IOCTL_AFD_RECV;
1134 break;
1135
1136 case IRP_MJ_WRITE:
1137 IoctlCode = IOCTL_AFD_SEND;
1138 break;
1139
1140 default:
1141 ASSERT(FALSE);
1142 SocketStateUnlock(FCB);
1143 return;
1144 }
1145
1146 switch (IoctlCode)
1147 {
1148 case IOCTL_AFD_RECV:
1149 case IOCTL_AFD_RECV_DATAGRAM:
1150 Function = FUNCTION_RECV;
1151 break;
1152
1153 case IOCTL_AFD_SEND:
1154 case IOCTL_AFD_SEND_DATAGRAM:
1155 Function = FUNCTION_SEND;
1156 break;
1157
1158 case IOCTL_AFD_CONNECT:
1159 Function = FUNCTION_CONNECT;
1160 break;
1161
1162 case IOCTL_AFD_WAIT_FOR_LISTEN:
1163 Function = FUNCTION_PREACCEPT;
1164 break;
1165
1166 case IOCTL_AFD_SELECT:
1167 KeAcquireSpinLock(&DeviceExt->Lock, &OldIrql);
1168
1169 CurrentEntry = DeviceExt->Polls.Flink;
1170 while (CurrentEntry != &DeviceExt->Polls)
1171 {
1172 Poll = CONTAINING_RECORD(CurrentEntry, AFD_ACTIVE_POLL, ListEntry);
1173
1174 if (Irp == Poll->Irp)
1175 {
1176 CleanupPendingIrp(FCB, Irp, IrpSp, Poll);
1177 KeReleaseSpinLock(&DeviceExt->Lock, OldIrql);
1178 SocketStateUnlock(FCB);
1179 return;
1180 }
1181 else
1182 {
1183 CurrentEntry = CurrentEntry->Flink;
1184 }
1185 }
1186
1187 KeReleaseSpinLock(&DeviceExt->Lock, OldIrql);
1188
1189 SocketStateUnlock(FCB);
1190
1191 DbgPrint("WARNING!!! IRP cancellation race could lead to a process hang! (IOCTL_AFD_SELECT)\n");
1192 return;
1193
1194 case IOCTL_AFD_DISCONNECT:
1195 Function = FUNCTION_DISCONNECT;
1196 break;
1197
1198 default:
1199 ASSERT(FALSE);
1200 UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
1201 return;
1202 }
1203
1204 CurrentEntry = FCB->PendingIrpList[Function].Flink;
1205 while (CurrentEntry != &FCB->PendingIrpList[Function])
1206 {
1207 CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
1208
1209 if (CurrentIrp == Irp)
1210 {
1211 RemoveEntryList(CurrentEntry);
1212 CleanupPendingIrp(FCB, Irp, IrpSp, NULL);
1213 UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
1214 return;
1215 }
1216 else
1217 {
1218 CurrentEntry = CurrentEntry->Flink;
1219 }
1220 }
1221
1222 SocketStateUnlock(FCB);
1223
1224 DbgPrint("WARNING!!! IRP cancellation race could lead to a process hang! (Function: %u)\n", Function);
1225 }
1226
1227 static DRIVER_UNLOAD AfdUnload;
1228 static VOID NTAPI
1229 AfdUnload(PDRIVER_OBJECT DriverObject)
1230 {
1231 UNREFERENCED_PARAMETER(DriverObject);
1232 }
1233
1234 NTSTATUS NTAPI
1235 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
1236 {
1237 PDEVICE_OBJECT DeviceObject;
1238 UNICODE_STRING wstrDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Afd");
1239 PAFD_DEVICE_EXTENSION DeviceExt;
1240 NTSTATUS Status;
1241
1242 UNREFERENCED_PARAMETER(RegistryPath);
1243 /* register driver routines */
1244 DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdDispatch;
1245 DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdDispatch;
1246 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = AfdDispatch;
1247 DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdDispatch;
1248 DriverObject->MajorFunction[IRP_MJ_READ] = AfdDispatch;
1249 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch;
1250 DriverObject->DriverUnload = AfdUnload;
1251
1252 Status = IoCreateDevice(DriverObject,
1253 sizeof(AFD_DEVICE_EXTENSION),
1254 &wstrDeviceName,
1255 FILE_DEVICE_NAMED_PIPE,
1256 0,
1257 FALSE,
1258 &DeviceObject);
1259
1260 /* failure */
1261 if (!NT_SUCCESS(Status))
1262 {
1263 return Status;
1264 }
1265
1266 DeviceExt = DeviceObject->DeviceExtension;
1267 KeInitializeSpinLock( &DeviceExt->Lock );
1268 InitializeListHead( &DeviceExt->Polls );
1269
1270 AFD_DbgPrint(MID_TRACE,("Device created: object %p ext %p\n",
1271 DeviceObject, DeviceExt));
1272
1273 return Status;
1274 }
1275
1276 /* EOF */