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