[AFD] Respond to FileFsDeviceInformation.
[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 NTSTATUS
851 AfdQueryFsDeviceInfo(PDEVICE_OBJECT DeviceObject, PFILE_FS_DEVICE_INFORMATION Buffer, PULONG Length)
852 {
853 if (*Length >= sizeof(FILE_FS_DEVICE_INFORMATION))
854 {
855 Buffer->Characteristics = 0;
856 Buffer->DeviceType = FILE_DEVICE_NAMED_PIPE;
857
858 *Length -= sizeof(FILE_FS_DEVICE_INFORMATION);
859
860 return STATUS_SUCCESS;
861 }
862 else
863 {
864 ASSERT(*Length >= sizeof(FILE_FS_DEVICE_INFORMATION));
865 return STATUS_INFO_LENGTH_MISMATCH;
866 }
867 }
868
869 static NTSTATUS NTAPI
870 AfdQueryVolumeInformation(PDEVICE_OBJECT DeviceObject, PIRP Irp, PIO_STACK_LOCATION IrpSp)
871 {
872 FS_INFORMATION_CLASS InfoClass;
873 PVOID Buffer;
874 ULONG Length;
875 NTSTATUS Status = STATUS_INVALID_INFO_CLASS;
876
877 Buffer = Irp->AssociatedIrp.SystemBuffer;
878 Length = IrpSp->Parameters.QueryVolume.Length;
879 InfoClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
880
881 switch (InfoClass)
882 {
883 case FileFsDeviceInformation:
884 Status = AfdQueryFsDeviceInfo(DeviceObject, Buffer, &Length);
885 break;
886 default:
887 break;
888 }
889
890 Irp->IoStatus.Status = Status;
891 Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
892 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
893
894 return Status;
895 }
896
897 static DRIVER_DISPATCH AfdDispatch;
898 static NTSTATUS NTAPI
899 AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
900 {
901 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
902 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
903 #if DBG
904 PFILE_OBJECT FileObject = IrpSp->FileObject;
905 #endif
906
907 AFD_DbgPrint(MID_TRACE,("AfdDispatch: %u\n", IrpSp->MajorFunction));
908 if( IrpSp->MajorFunction != IRP_MJ_CREATE) {
909 AFD_DbgPrint(MID_TRACE,("FO %p, IrpSp->FO %p\n",
910 FileObject, IrpSp->FileObject));
911 ASSERT(FileObject == IrpSp->FileObject);
912 }
913
914 Irp->IoStatus.Information = 0;
915
916 switch(IrpSp->MajorFunction)
917 {
918 /* opening and closing handles to the device */
919 case IRP_MJ_CREATE:
920 /* Mostly borrowed from the named pipe file system */
921 return AfdCreateSocket(DeviceObject, Irp, IrpSp);
922
923 case IRP_MJ_CLOSE:
924 /* Ditto the borrowing */
925 return AfdCloseSocket(DeviceObject, Irp, IrpSp);
926
927 case IRP_MJ_CLEANUP:
928 return AfdCleanupSocket(DeviceObject, Irp, IrpSp);
929
930 /* write data */
931 case IRP_MJ_WRITE:
932 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp, TRUE );
933
934 /* read data */
935 case IRP_MJ_READ:
936 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp, TRUE );
937
938 /* query volume info */
939 case IRP_MJ_QUERY_VOLUME_INFORMATION:
940 return AfdQueryVolumeInformation(DeviceObject, Irp, IrpSp);
941
942 case IRP_MJ_DEVICE_CONTROL:
943 {
944 switch( IrpSp->Parameters.DeviceIoControl.IoControlCode ) {
945 case IOCTL_AFD_BIND:
946 return AfdBindSocket( DeviceObject, Irp, IrpSp );
947
948 case IOCTL_AFD_CONNECT:
949 return AfdStreamSocketConnect( DeviceObject, Irp, IrpSp );
950
951 case IOCTL_AFD_START_LISTEN:
952 return AfdListenSocket( DeviceObject, Irp, IrpSp );
953
954 case IOCTL_AFD_RECV:
955 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp,
956 FALSE );
957
958 case IOCTL_AFD_SELECT:
959 return AfdSelect( DeviceObject, Irp, IrpSp );
960
961 case IOCTL_AFD_EVENT_SELECT:
962 return AfdEventSelect( DeviceObject, Irp, IrpSp );
963
964 case IOCTL_AFD_ENUM_NETWORK_EVENTS:
965 return AfdEnumEvents( DeviceObject, Irp, IrpSp );
966
967 case IOCTL_AFD_RECV_DATAGRAM:
968 return AfdPacketSocketReadData( DeviceObject, Irp, IrpSp );
969
970 case IOCTL_AFD_SEND:
971 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp,
972 FALSE );
973
974 case IOCTL_AFD_SEND_DATAGRAM:
975 return AfdPacketSocketWriteData( DeviceObject, Irp, IrpSp );
976
977 case IOCTL_AFD_GET_INFO:
978 return AfdGetInfo( DeviceObject, Irp, IrpSp );
979
980 case IOCTL_AFD_SET_INFO:
981 return AfdSetInfo( DeviceObject, Irp, IrpSp );
982
983 case IOCTL_AFD_GET_CONTEXT_SIZE:
984 return AfdGetContextSize( DeviceObject, Irp, IrpSp );
985
986 case IOCTL_AFD_GET_CONTEXT:
987 return AfdGetContext( DeviceObject, Irp, IrpSp );
988
989 case IOCTL_AFD_SET_CONTEXT:
990 return AfdSetContext( DeviceObject, Irp, IrpSp );
991
992 case IOCTL_AFD_WAIT_FOR_LISTEN:
993 return AfdWaitForListen( DeviceObject, Irp, IrpSp );
994
995 case IOCTL_AFD_ACCEPT:
996 return AfdAccept( DeviceObject, Irp, IrpSp );
997
998 case IOCTL_AFD_DISCONNECT:
999 return AfdDisconnect( DeviceObject, Irp, IrpSp );
1000
1001 case IOCTL_AFD_GET_SOCK_NAME:
1002 return AfdGetSockName( DeviceObject, Irp, IrpSp );
1003
1004 case IOCTL_AFD_GET_PEER_NAME:
1005 return AfdGetPeerName( DeviceObject, Irp, IrpSp );
1006
1007 case IOCTL_AFD_GET_CONNECT_DATA:
1008 return AfdGetConnectData(DeviceObject, Irp, IrpSp);
1009
1010 case IOCTL_AFD_SET_CONNECT_DATA:
1011 return AfdSetConnectData(DeviceObject, Irp, IrpSp);
1012
1013 case IOCTL_AFD_SET_DISCONNECT_DATA:
1014 return AfdSetDisconnectData(DeviceObject, Irp, IrpSp);
1015
1016 case IOCTL_AFD_GET_DISCONNECT_DATA:
1017 return AfdGetDisconnectData(DeviceObject, Irp, IrpSp);
1018
1019 case IOCTL_AFD_SET_CONNECT_DATA_SIZE:
1020 return AfdSetConnectDataSize(DeviceObject, Irp, IrpSp);
1021
1022 case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE:
1023 return AfdSetDisconnectDataSize(DeviceObject, Irp, IrpSp);
1024
1025 case IOCTL_AFD_SET_CONNECT_OPTIONS:
1026 return AfdSetConnectOptions(DeviceObject, Irp, IrpSp);
1027
1028 case IOCTL_AFD_SET_DISCONNECT_OPTIONS:
1029 return AfdSetDisconnectOptions(DeviceObject, Irp, IrpSp);
1030
1031 case IOCTL_AFD_GET_CONNECT_OPTIONS:
1032 return AfdGetConnectOptions(DeviceObject, Irp, IrpSp);
1033
1034 case IOCTL_AFD_GET_DISCONNECT_OPTIONS:
1035 return AfdGetDisconnectOptions(DeviceObject, Irp, IrpSp);
1036
1037 case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE:
1038 return AfdSetConnectOptionsSize(DeviceObject, Irp, IrpSp);
1039
1040 case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE:
1041 return AfdSetDisconnectOptionsSize(DeviceObject, Irp, IrpSp);
1042
1043 case IOCTL_AFD_GET_TDI_HANDLES:
1044 return AfdGetTdiHandles(DeviceObject, Irp, IrpSp);
1045
1046 case IOCTL_AFD_DEFER_ACCEPT:
1047 DbgPrint("IOCTL_AFD_DEFER_ACCEPT is UNIMPLEMENTED!\n");
1048 break;
1049
1050 case IOCTL_AFD_GET_PENDING_CONNECT_DATA:
1051 DbgPrint("IOCTL_AFD_GET_PENDING_CONNECT_DATA is UNIMPLEMENTED!\n");
1052 break;
1053
1054 case IOCTL_AFD_VALIDATE_GROUP:
1055 DbgPrint("IOCTL_AFD_VALIDATE_GROUP is UNIMPLEMENTED!\n");
1056 break;
1057
1058 default:
1059 Status = STATUS_NOT_SUPPORTED;
1060 DbgPrint("Unknown IOCTL (0x%x)\n",
1061 IrpSp->Parameters.DeviceIoControl.IoControlCode);
1062 break;
1063 }
1064 break;
1065 }
1066
1067 /* unsupported operations */
1068 default:
1069 {
1070 Status = STATUS_NOT_IMPLEMENTED;
1071 AFD_DbgPrint(MIN_TRACE,
1072 ("Irp: Unknown Major code was %x\n",
1073 IrpSp->MajorFunction));
1074 break;
1075 }
1076 }
1077
1078 AFD_DbgPrint(MID_TRACE, ("Returning %x\n", Status));
1079 Irp->IoStatus.Status = Status;
1080 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1081
1082 return Status;
1083 }
1084
1085 BOOLEAN CheckUnlockExtraBuffers(PAFD_FCB FCB, PIO_STACK_LOCATION IrpSp)
1086 {
1087 if (FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)
1088 {
1089 if (IrpSp->MajorFunction == IRP_MJ_READ || IrpSp->MajorFunction == IRP_MJ_WRITE)
1090 {
1091 /* read()/write() call - no extra buffers */
1092 return FALSE;
1093 }
1094 else if (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
1095 {
1096 if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV_DATAGRAM)
1097 {
1098 /* recvfrom() call - extra buffers */
1099 return TRUE;
1100 }
1101 else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV)
1102 {
1103 /* recv() call - no extra buffers */
1104 return FALSE;
1105 }
1106 else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND ||
1107 IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND_DATAGRAM)
1108 {
1109 /* send()/sendto() call - no extra buffers */
1110 return FALSE;
1111 }
1112 else
1113 {
1114 /* Unknown IOCTL */
1115 ASSERT(FALSE);
1116 return FALSE;
1117 }
1118 }
1119 else
1120 {
1121 /* Unknown IRP_MJ code */
1122 ASSERT(FALSE);
1123 return FALSE;
1124 }
1125 }
1126 else
1127 {
1128 /* Connection-oriented never has extra buffers */
1129 return FALSE;
1130 }
1131 }
1132
1133 VOID
1134 CleanupPendingIrp(PAFD_FCB FCB, PIRP Irp, PIO_STACK_LOCATION IrpSp, PAFD_ACTIVE_POLL Poll)
1135 {
1136 PAFD_RECV_INFO RecvReq;
1137 PAFD_SEND_INFO SendReq;
1138 PAFD_POLL_INFO PollReq;
1139
1140 if (IrpSp->MajorFunction == IRP_MJ_READ)
1141 {
1142 RecvReq = GetLockedData(Irp, IrpSp);
1143 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp));
1144 }
1145 else if (IrpSp->MajorFunction == IRP_MJ_WRITE)
1146 {
1147 SendReq = GetLockedData(Irp, IrpSp);
1148 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp));
1149 }
1150 else
1151 {
1152 ASSERT(IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
1153
1154 if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV)
1155 {
1156 RecvReq = GetLockedData(Irp, IrpSp);
1157 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp));
1158 }
1159 else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND)
1160 {
1161 SendReq = GetLockedData(Irp, IrpSp);
1162 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp));
1163 }
1164 else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SELECT)
1165 {
1166 ASSERT(Poll);
1167
1168 PollReq = Irp->AssociatedIrp.SystemBuffer;
1169 ZeroEvents(PollReq->Handles, PollReq->HandleCount);
1170 SignalSocket(Poll, NULL, PollReq, STATUS_CANCELLED);
1171 }
1172 }
1173 }
1174
1175 VOID
1176 NTAPI
1177 AfdCancelHandler(PDEVICE_OBJECT DeviceObject,
1178 PIRP Irp)
1179 {
1180 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
1181 PFILE_OBJECT FileObject = IrpSp->FileObject;
1182 PAFD_FCB FCB = FileObject->FsContext;
1183 ULONG Function, IoctlCode;
1184 PIRP CurrentIrp;
1185 PLIST_ENTRY CurrentEntry;
1186 PAFD_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
1187 KIRQL OldIrql;
1188 PAFD_ACTIVE_POLL Poll;
1189
1190 IoReleaseCancelSpinLock(Irp->CancelIrql);
1191
1192 if (!SocketAcquireStateLock(FCB))
1193 return;
1194
1195 switch (IrpSp->MajorFunction)
1196 {
1197 case IRP_MJ_DEVICE_CONTROL:
1198 IoctlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
1199 break;
1200
1201 case IRP_MJ_READ:
1202 IoctlCode = IOCTL_AFD_RECV;
1203 break;
1204
1205 case IRP_MJ_WRITE:
1206 IoctlCode = IOCTL_AFD_SEND;
1207 break;
1208
1209 default:
1210 ASSERT(FALSE);
1211 SocketStateUnlock(FCB);
1212 return;
1213 }
1214
1215 switch (IoctlCode)
1216 {
1217 case IOCTL_AFD_RECV:
1218 case IOCTL_AFD_RECV_DATAGRAM:
1219 Function = FUNCTION_RECV;
1220 break;
1221
1222 case IOCTL_AFD_SEND:
1223 case IOCTL_AFD_SEND_DATAGRAM:
1224 Function = FUNCTION_SEND;
1225 break;
1226
1227 case IOCTL_AFD_CONNECT:
1228 Function = FUNCTION_CONNECT;
1229 break;
1230
1231 case IOCTL_AFD_WAIT_FOR_LISTEN:
1232 Function = FUNCTION_PREACCEPT;
1233 break;
1234
1235 case IOCTL_AFD_SELECT:
1236 KeAcquireSpinLock(&DeviceExt->Lock, &OldIrql);
1237
1238 CurrentEntry = DeviceExt->Polls.Flink;
1239 while (CurrentEntry != &DeviceExt->Polls)
1240 {
1241 Poll = CONTAINING_RECORD(CurrentEntry, AFD_ACTIVE_POLL, ListEntry);
1242
1243 if (Irp == Poll->Irp)
1244 {
1245 CleanupPendingIrp(FCB, Irp, IrpSp, Poll);
1246 KeReleaseSpinLock(&DeviceExt->Lock, OldIrql);
1247 SocketStateUnlock(FCB);
1248 return;
1249 }
1250 else
1251 {
1252 CurrentEntry = CurrentEntry->Flink;
1253 }
1254 }
1255
1256 KeReleaseSpinLock(&DeviceExt->Lock, OldIrql);
1257
1258 SocketStateUnlock(FCB);
1259
1260 DbgPrint("WARNING!!! IRP cancellation race could lead to a process hang! (IOCTL_AFD_SELECT)\n");
1261 return;
1262
1263 case IOCTL_AFD_DISCONNECT:
1264 Function = FUNCTION_DISCONNECT;
1265 break;
1266
1267 default:
1268 ASSERT(FALSE);
1269 UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
1270 return;
1271 }
1272
1273 CurrentEntry = FCB->PendingIrpList[Function].Flink;
1274 while (CurrentEntry != &FCB->PendingIrpList[Function])
1275 {
1276 CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
1277
1278 if (CurrentIrp == Irp)
1279 {
1280 RemoveEntryList(CurrentEntry);
1281 CleanupPendingIrp(FCB, Irp, IrpSp, NULL);
1282 UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
1283 return;
1284 }
1285 else
1286 {
1287 CurrentEntry = CurrentEntry->Flink;
1288 }
1289 }
1290
1291 SocketStateUnlock(FCB);
1292
1293 DbgPrint("WARNING!!! IRP cancellation race could lead to a process hang! (Function: %u)\n", Function);
1294 }
1295
1296 static DRIVER_UNLOAD AfdUnload;
1297 static VOID NTAPI
1298 AfdUnload(PDRIVER_OBJECT DriverObject)
1299 {
1300 UNREFERENCED_PARAMETER(DriverObject);
1301 }
1302
1303 NTSTATUS NTAPI
1304 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
1305 {
1306 PDEVICE_OBJECT DeviceObject;
1307 UNICODE_STRING wstrDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Afd");
1308 PAFD_DEVICE_EXTENSION DeviceExt;
1309 NTSTATUS Status;
1310
1311 UNREFERENCED_PARAMETER(RegistryPath);
1312 /* register driver routines */
1313 DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdDispatch;
1314 DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdDispatch;
1315 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = AfdDispatch;
1316 DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdDispatch;
1317 DriverObject->MajorFunction[IRP_MJ_READ] = AfdDispatch;
1318 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch;
1319 DriverObject->MajorFunction[IRP_MJ_QUERY_VOLUME_INFORMATION] = AfdDispatch;
1320 DriverObject->DriverUnload = AfdUnload;
1321
1322 Status = IoCreateDevice(DriverObject,
1323 sizeof(AFD_DEVICE_EXTENSION),
1324 &wstrDeviceName,
1325 FILE_DEVICE_NAMED_PIPE,
1326 0,
1327 FALSE,
1328 &DeviceObject);
1329
1330 /* failure */
1331 if (!NT_SUCCESS(Status))
1332 {
1333 return Status;
1334 }
1335
1336 DeviceExt = DeviceObject->DeviceExtension;
1337 KeInitializeSpinLock( &DeviceExt->Lock );
1338 InitializeListHead( &DeviceExt->Polls );
1339
1340 AFD_DbgPrint(MID_TRACE,("Device created: object %p ext %p\n",
1341 DeviceObject, DeviceExt));
1342
1343 return Status;
1344 }
1345
1346 /* EOF */