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