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