Synchronize with trunk.
[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 &FCB->DisconnectIrp.Iosb,
666 DisconnectComplete,
667 FCB,
668 FCB->ConnectCallInfo,
669 FCB->ConnectReturnInfo);
670 if (Status != STATUS_PENDING)
671 {
672 FCB->DisconnectPending = FALSE;
673 }
674
675 return Status;
676 }
677
678 VOID
679 RetryDisconnectCompletion(PAFD_FCB FCB)
680 {
681 ASSERT(FCB->RemoteAddress);
682
683 if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && !FCB->SendIrp.InFlightRequest && FCB->DisconnectPending)
684 {
685 /* Sends are done; fire off a TDI_DISCONNECT request */
686 DoDisconnect(FCB);
687 }
688 }
689
690 static NTSTATUS NTAPI
691 AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
692 PIO_STACK_LOCATION IrpSp) {
693 PFILE_OBJECT FileObject = IrpSp->FileObject;
694 PAFD_FCB FCB = FileObject->FsContext;
695 PAFD_DISCONNECT_INFO DisReq;
696 NTSTATUS Status = STATUS_SUCCESS;
697 USHORT Flags;
698 PLIST_ENTRY CurrentEntry;
699 PIRP CurrentIrp;
700
701 UNREFERENCED_PARAMETER(DeviceObject);
702
703 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
704
705 if (!(DisReq = LockRequest(Irp, IrpSp, FALSE, NULL)))
706 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
707 Irp, 0 );
708
709 /* Send direction only */
710 if ((DisReq->DisconnectType & AFD_DISCONNECT_SEND) &&
711 !(DisReq->DisconnectType & AFD_DISCONNECT_RECV))
712 {
713 /* Perform a controlled disconnect */
714 Flags = TDI_DISCONNECT_RELEASE;
715 }
716 /* Receive direction or both */
717 else
718 {
719 /* Mark that we can't issue another receive request */
720 FCB->TdiReceiveClosed = TRUE;
721
722 /* Try to cancel a pending TDI receive IRP if there was one in progress */
723 if (FCB->ReceiveIrp.InFlightRequest)
724 IoCancelIrp(FCB->ReceiveIrp.InFlightRequest);
725
726 /* Discard any pending data */
727 FCB->Recv.Content = 0;
728 FCB->Recv.BytesUsed = 0;
729
730 /* Mark us as overread to complete future reads with an error */
731 FCB->Overread = TRUE;
732
733 /* Set a successful receive status to indicate a shutdown on overread */
734 FCB->LastReceiveStatus = STATUS_SUCCESS;
735
736 /* Clear the receive event */
737 FCB->PollState &= ~AFD_EVENT_RECEIVE;
738
739 /* Receive direction only */
740 if ((DisReq->DisconnectType & AFD_DISCONNECT_RECV) &&
741 !(DisReq->DisconnectType & AFD_DISCONNECT_SEND))
742 {
743 /* No need to tell the transport driver for receive direction only */
744 return UnlockAndMaybeComplete( FCB, STATUS_SUCCESS, Irp, 0 );
745 }
746 else
747 {
748 /* Perform an abortive disconnect */
749 Flags = TDI_DISCONNECT_ABORT;
750 }
751 }
752
753 if (!(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS))
754 {
755 if (!FCB->ConnectCallInfo)
756 {
757 AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
758 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
759 Irp, 0 );
760 }
761
762 if (FCB->DisconnectPending)
763 {
764 if (FCB->DisconnectIrp.InFlightRequest)
765 {
766 IoCancelIrp(FCB->DisconnectIrp.InFlightRequest);
767 ASSERT(!FCB->DisconnectIrp.InFlightRequest);
768 }
769 else
770 {
771 while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT]))
772 {
773 CurrentEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_DISCONNECT]);
774 CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
775 CurrentIrp->IoStatus.Status = STATUS_CANCELLED;
776 CurrentIrp->IoStatus.Information = 0;
777 UnlockRequest(CurrentIrp, IoGetCurrentIrpStackLocation(CurrentIrp));
778 (void)IoSetCancelRoutine(CurrentIrp, NULL);
779 IoCompleteRequest(CurrentIrp, IO_NETWORK_INCREMENT );
780 }
781 }
782 }
783
784 FCB->DisconnectFlags = Flags;
785 FCB->DisconnectTimeout = DisReq->Timeout;
786 FCB->DisconnectPending = TRUE;
787 FCB->SendClosed = TRUE;
788 FCB->PollState &= ~AFD_EVENT_SEND;
789
790 Status = QueueUserModeIrp(FCB, Irp, FUNCTION_DISCONNECT);
791 if (Status == STATUS_PENDING)
792 {
793 if ((IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && !FCB->SendIrp.InFlightRequest) ||
794 (FCB->DisconnectFlags & TDI_DISCONNECT_ABORT))
795 {
796 /* Go ahead and execute the disconnect because we're ready for it */
797 Status = DoDisconnect(FCB);
798 }
799
800 if (Status != STATUS_PENDING)
801 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
802 }
803
804 if (Status == STATUS_PENDING)
805 {
806 SocketStateUnlock(FCB);
807
808 return Status;
809 }
810 }
811 else
812 {
813 if (!(Flags & TDI_DISCONNECT_RELEASE))
814 {
815 if (!FCB->RemoteAddress)
816 {
817 AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
818 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
819 }
820
821 ExFreePool(FCB->RemoteAddress);
822
823 FCB->RemoteAddress = NULL;
824 }
825
826 FCB->PollState &= ~AFD_EVENT_SEND;
827 FCB->SendClosed = TRUE;
828 }
829
830 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
831 }
832
833 static DRIVER_DISPATCH AfdDispatch;
834 static NTSTATUS NTAPI
835 AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
836 {
837 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
838 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
839 #if DBG
840 PFILE_OBJECT FileObject = IrpSp->FileObject;
841 #endif
842
843 AFD_DbgPrint(MID_TRACE,("AfdDispatch: %u\n", IrpSp->MajorFunction));
844 if( IrpSp->MajorFunction != IRP_MJ_CREATE) {
845 AFD_DbgPrint(MID_TRACE,("FO %p, IrpSp->FO %p\n",
846 FileObject, IrpSp->FileObject));
847 ASSERT(FileObject == IrpSp->FileObject);
848 }
849
850 Irp->IoStatus.Information = 0;
851
852 switch(IrpSp->MajorFunction)
853 {
854 /* opening and closing handles to the device */
855 case IRP_MJ_CREATE:
856 /* Mostly borrowed from the named pipe file system */
857 return AfdCreateSocket(DeviceObject, Irp, IrpSp);
858
859 case IRP_MJ_CLOSE:
860 /* Ditto the borrowing */
861 return AfdCloseSocket(DeviceObject, Irp, IrpSp);
862
863 case IRP_MJ_CLEANUP:
864 return AfdCleanupSocket(DeviceObject, Irp, IrpSp);
865
866 /* write data */
867 case IRP_MJ_WRITE:
868 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp, TRUE );
869
870 /* read data */
871 case IRP_MJ_READ:
872 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp, TRUE );
873
874 case IRP_MJ_DEVICE_CONTROL:
875 {
876 switch( IrpSp->Parameters.DeviceIoControl.IoControlCode ) {
877 case IOCTL_AFD_BIND:
878 return AfdBindSocket( DeviceObject, Irp, IrpSp );
879
880 case IOCTL_AFD_CONNECT:
881 return AfdStreamSocketConnect( DeviceObject, Irp, IrpSp );
882
883 case IOCTL_AFD_START_LISTEN:
884 return AfdListenSocket( DeviceObject, Irp, IrpSp );
885
886 case IOCTL_AFD_RECV:
887 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp,
888 FALSE );
889
890 case IOCTL_AFD_SELECT:
891 return AfdSelect( DeviceObject, Irp, IrpSp );
892
893 case IOCTL_AFD_EVENT_SELECT:
894 return AfdEventSelect( DeviceObject, Irp, IrpSp );
895
896 case IOCTL_AFD_ENUM_NETWORK_EVENTS:
897 return AfdEnumEvents( DeviceObject, Irp, IrpSp );
898
899 case IOCTL_AFD_RECV_DATAGRAM:
900 return AfdPacketSocketReadData( DeviceObject, Irp, IrpSp );
901
902 case IOCTL_AFD_SEND:
903 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp,
904 FALSE );
905
906 case IOCTL_AFD_SEND_DATAGRAM:
907 return AfdPacketSocketWriteData( DeviceObject, Irp, IrpSp );
908
909 case IOCTL_AFD_GET_INFO:
910 return AfdGetInfo( DeviceObject, Irp, IrpSp );
911
912 case IOCTL_AFD_SET_INFO:
913 return AfdSetInfo( DeviceObject, Irp, IrpSp );
914
915 case IOCTL_AFD_GET_CONTEXT_SIZE:
916 return AfdGetContextSize( DeviceObject, Irp, IrpSp );
917
918 case IOCTL_AFD_GET_CONTEXT:
919 return AfdGetContext( DeviceObject, Irp, IrpSp );
920
921 case IOCTL_AFD_SET_CONTEXT:
922 return AfdSetContext( DeviceObject, Irp, IrpSp );
923
924 case IOCTL_AFD_WAIT_FOR_LISTEN:
925 return AfdWaitForListen( DeviceObject, Irp, IrpSp );
926
927 case IOCTL_AFD_ACCEPT:
928 return AfdAccept( DeviceObject, Irp, IrpSp );
929
930 case IOCTL_AFD_DISCONNECT:
931 return AfdDisconnect( DeviceObject, Irp, IrpSp );
932
933 case IOCTL_AFD_GET_SOCK_NAME:
934 return AfdGetSockName( DeviceObject, Irp, IrpSp );
935
936 case IOCTL_AFD_GET_PEER_NAME:
937 return AfdGetPeerName( DeviceObject, Irp, IrpSp );
938
939 case IOCTL_AFD_GET_CONNECT_DATA:
940 return AfdGetConnectData(DeviceObject, Irp, IrpSp);
941
942 case IOCTL_AFD_SET_CONNECT_DATA:
943 return AfdSetConnectData(DeviceObject, Irp, IrpSp);
944
945 case IOCTL_AFD_SET_DISCONNECT_DATA:
946 return AfdSetDisconnectData(DeviceObject, Irp, IrpSp);
947
948 case IOCTL_AFD_GET_DISCONNECT_DATA:
949 return AfdGetDisconnectData(DeviceObject, Irp, IrpSp);
950
951 case IOCTL_AFD_SET_CONNECT_DATA_SIZE:
952 return AfdSetConnectDataSize(DeviceObject, Irp, IrpSp);
953
954 case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE:
955 return AfdSetDisconnectDataSize(DeviceObject, Irp, IrpSp);
956
957 case IOCTL_AFD_SET_CONNECT_OPTIONS:
958 return AfdSetConnectOptions(DeviceObject, Irp, IrpSp);
959
960 case IOCTL_AFD_SET_DISCONNECT_OPTIONS:
961 return AfdSetDisconnectOptions(DeviceObject, Irp, IrpSp);
962
963 case IOCTL_AFD_GET_CONNECT_OPTIONS:
964 return AfdGetConnectOptions(DeviceObject, Irp, IrpSp);
965
966 case IOCTL_AFD_GET_DISCONNECT_OPTIONS:
967 return AfdGetDisconnectOptions(DeviceObject, Irp, IrpSp);
968
969 case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE:
970 return AfdSetConnectOptionsSize(DeviceObject, Irp, IrpSp);
971
972 case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE:
973 return AfdSetDisconnectOptionsSize(DeviceObject, Irp, IrpSp);
974
975 case IOCTL_AFD_GET_TDI_HANDLES:
976 return AfdGetTdiHandles(DeviceObject, Irp, IrpSp);
977
978 case IOCTL_AFD_DEFER_ACCEPT:
979 DbgPrint("IOCTL_AFD_DEFER_ACCEPT is UNIMPLEMENTED!\n");
980 break;
981
982 case IOCTL_AFD_GET_PENDING_CONNECT_DATA:
983 DbgPrint("IOCTL_AFD_GET_PENDING_CONNECT_DATA is UNIMPLEMENTED!\n");
984 break;
985
986 case IOCTL_AFD_VALIDATE_GROUP:
987 DbgPrint("IOCTL_AFD_VALIDATE_GROUP is UNIMPLEMENTED!\n");
988 break;
989
990 default:
991 Status = STATUS_NOT_SUPPORTED;
992 DbgPrint("Unknown IOCTL (0x%x)\n",
993 IrpSp->Parameters.DeviceIoControl.IoControlCode);
994 break;
995 }
996 break;
997 }
998
999 /* unsupported operations */
1000 default:
1001 {
1002 Status = STATUS_NOT_IMPLEMENTED;
1003 AFD_DbgPrint(MIN_TRACE,
1004 ("Irp: Unknown Major code was %x\n",
1005 IrpSp->MajorFunction));
1006 break;
1007 }
1008 }
1009
1010 AFD_DbgPrint(MID_TRACE, ("Returning %x\n", Status));
1011 Irp->IoStatus.Status = Status;
1012 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1013
1014 return Status;
1015 }
1016
1017 BOOLEAN CheckUnlockExtraBuffers(PAFD_FCB FCB, PIO_STACK_LOCATION IrpSp)
1018 {
1019 if (FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)
1020 {
1021 if (IrpSp->MajorFunction == IRP_MJ_READ || IrpSp->MajorFunction == IRP_MJ_WRITE)
1022 {
1023 /* read()/write() call - no extra buffers */
1024 return FALSE;
1025 }
1026 else if (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
1027 {
1028 if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV_DATAGRAM)
1029 {
1030 /* recvfrom() call - extra buffers */
1031 return TRUE;
1032 }
1033 else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV)
1034 {
1035 /* recv() call - no extra buffers */
1036 return FALSE;
1037 }
1038 else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND ||
1039 IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND_DATAGRAM)
1040 {
1041 /* send()/sendto() call - no extra buffers */
1042 return FALSE;
1043 }
1044 else
1045 {
1046 /* Unknown IOCTL */
1047 ASSERT(FALSE);
1048 return FALSE;
1049 }
1050 }
1051 else
1052 {
1053 /* Unknown IRP_MJ code */
1054 ASSERT(FALSE);
1055 return FALSE;
1056 }
1057 }
1058 else
1059 {
1060 /* Connection-oriented never has extra buffers */
1061 return FALSE;
1062 }
1063 }
1064
1065 VOID
1066 CleanupPendingIrp(PAFD_FCB FCB, PIRP Irp, PIO_STACK_LOCATION IrpSp, PAFD_ACTIVE_POLL Poll)
1067 {
1068 PAFD_RECV_INFO RecvReq;
1069 PAFD_SEND_INFO SendReq;
1070 PAFD_POLL_INFO PollReq;
1071
1072 if (IrpSp->MajorFunction == IRP_MJ_READ)
1073 {
1074 RecvReq = GetLockedData(Irp, IrpSp);
1075 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp));
1076 }
1077 else if (IrpSp->MajorFunction == IRP_MJ_WRITE)
1078 {
1079 SendReq = GetLockedData(Irp, IrpSp);
1080 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp));
1081 }
1082 else
1083 {
1084 ASSERT(IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
1085
1086 if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV)
1087 {
1088 RecvReq = GetLockedData(Irp, IrpSp);
1089 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp));
1090 }
1091 else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND)
1092 {
1093 SendReq = GetLockedData(Irp, IrpSp);
1094 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp));
1095 }
1096 else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SELECT)
1097 {
1098 ASSERT(Poll);
1099
1100 PollReq = Irp->AssociatedIrp.SystemBuffer;
1101 ZeroEvents(PollReq->Handles, PollReq->HandleCount);
1102 SignalSocket(Poll, NULL, PollReq, STATUS_CANCELLED);
1103 }
1104 }
1105 }
1106
1107 VOID
1108 NTAPI
1109 AfdCancelHandler(PDEVICE_OBJECT DeviceObject,
1110 PIRP Irp)
1111 {
1112 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
1113 PFILE_OBJECT FileObject = IrpSp->FileObject;
1114 PAFD_FCB FCB = FileObject->FsContext;
1115 ULONG Function, IoctlCode;
1116 PIRP CurrentIrp;
1117 PLIST_ENTRY CurrentEntry;
1118 PAFD_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
1119 KIRQL OldIrql;
1120 PAFD_ACTIVE_POLL Poll;
1121
1122 IoReleaseCancelSpinLock(Irp->CancelIrql);
1123
1124 if (!SocketAcquireStateLock(FCB))
1125 return;
1126
1127 switch (IrpSp->MajorFunction)
1128 {
1129 case IRP_MJ_DEVICE_CONTROL:
1130 IoctlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
1131 break;
1132
1133 case IRP_MJ_READ:
1134 IoctlCode = IOCTL_AFD_RECV;
1135 break;
1136
1137 case IRP_MJ_WRITE:
1138 IoctlCode = IOCTL_AFD_SEND;
1139 break;
1140
1141 default:
1142 ASSERT(FALSE);
1143 SocketStateUnlock(FCB);
1144 return;
1145 }
1146
1147 switch (IoctlCode)
1148 {
1149 case IOCTL_AFD_RECV:
1150 case IOCTL_AFD_RECV_DATAGRAM:
1151 Function = FUNCTION_RECV;
1152 break;
1153
1154 case IOCTL_AFD_SEND:
1155 case IOCTL_AFD_SEND_DATAGRAM:
1156 Function = FUNCTION_SEND;
1157 break;
1158
1159 case IOCTL_AFD_CONNECT:
1160 Function = FUNCTION_CONNECT;
1161 break;
1162
1163 case IOCTL_AFD_WAIT_FOR_LISTEN:
1164 Function = FUNCTION_PREACCEPT;
1165 break;
1166
1167 case IOCTL_AFD_SELECT:
1168 KeAcquireSpinLock(&DeviceExt->Lock, &OldIrql);
1169
1170 CurrentEntry = DeviceExt->Polls.Flink;
1171 while (CurrentEntry != &DeviceExt->Polls)
1172 {
1173 Poll = CONTAINING_RECORD(CurrentEntry, AFD_ACTIVE_POLL, ListEntry);
1174
1175 if (Irp == Poll->Irp)
1176 {
1177 CleanupPendingIrp(FCB, Irp, IrpSp, Poll);
1178 KeReleaseSpinLock(&DeviceExt->Lock, OldIrql);
1179 SocketStateUnlock(FCB);
1180 return;
1181 }
1182 else
1183 {
1184 CurrentEntry = CurrentEntry->Flink;
1185 }
1186 }
1187
1188 KeReleaseSpinLock(&DeviceExt->Lock, OldIrql);
1189
1190 SocketStateUnlock(FCB);
1191
1192 DbgPrint("WARNING!!! IRP cancellation race could lead to a process hang! (IOCTL_AFD_SELECT)\n");
1193 return;
1194
1195 case IOCTL_AFD_DISCONNECT:
1196 Function = FUNCTION_DISCONNECT;
1197 break;
1198
1199 default:
1200 ASSERT(FALSE);
1201 UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
1202 return;
1203 }
1204
1205 CurrentEntry = FCB->PendingIrpList[Function].Flink;
1206 while (CurrentEntry != &FCB->PendingIrpList[Function])
1207 {
1208 CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
1209
1210 if (CurrentIrp == Irp)
1211 {
1212 RemoveEntryList(CurrentEntry);
1213 CleanupPendingIrp(FCB, Irp, IrpSp, NULL);
1214 UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
1215 return;
1216 }
1217 else
1218 {
1219 CurrentEntry = CurrentEntry->Flink;
1220 }
1221 }
1222
1223 SocketStateUnlock(FCB);
1224
1225 DbgPrint("WARNING!!! IRP cancellation race could lead to a process hang! (Function: %u)\n", Function);
1226 }
1227
1228 static DRIVER_UNLOAD AfdUnload;
1229 static VOID NTAPI
1230 AfdUnload(PDRIVER_OBJECT DriverObject)
1231 {
1232 UNREFERENCED_PARAMETER(DriverObject);
1233 }
1234
1235 NTSTATUS NTAPI
1236 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
1237 {
1238 PDEVICE_OBJECT DeviceObject;
1239 UNICODE_STRING wstrDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Afd");
1240 PAFD_DEVICE_EXTENSION DeviceExt;
1241 NTSTATUS Status;
1242
1243 UNREFERENCED_PARAMETER(RegistryPath);
1244 /* register driver routines */
1245 DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdDispatch;
1246 DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdDispatch;
1247 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = AfdDispatch;
1248 DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdDispatch;
1249 DriverObject->MajorFunction[IRP_MJ_READ] = AfdDispatch;
1250 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch;
1251 DriverObject->DriverUnload = AfdUnload;
1252
1253 Status = IoCreateDevice(DriverObject,
1254 sizeof(AFD_DEVICE_EXTENSION),
1255 &wstrDeviceName,
1256 FILE_DEVICE_NAMED_PIPE,
1257 0,
1258 FALSE,
1259 &DeviceObject);
1260
1261 /* failure */
1262 if (!NT_SUCCESS(Status))
1263 {
1264 return Status;
1265 }
1266
1267 DeviceExt = DeviceObject->DeviceExtension;
1268 KeInitializeSpinLock( &DeviceExt->Lock );
1269 InitializeListHead( &DeviceExt->Polls );
1270
1271 AFD_DbgPrint(MID_TRACE,("Device created: object %p ext %p\n",
1272 DeviceObject, DeviceExt));
1273
1274 return Status;
1275 }
1276
1277 /* EOF */