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