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