- Implement IOCTL_AFD_GET_CONNECT_DATA, IOCTL_AFD_SET_CONNECT_DATA, IOCTL_AFD_SET_CO...
[reactos.git] / drivers / network / afd / afd / main.c
1 /* $Id$
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 #include "tdi_proto.h"
17 #include "tdiconn.h"
18 #include "debug.h"
19
20 #if DBG
21
22 /* See debug.h for debug/trace constants */
23 //DWORD DebugTraceLevel = DEBUG_ULTRA;
24 DWORD DebugTraceLevel = 0;
25
26 #endif /* DBG */
27
28 void OskitDumpBuffer( PCHAR Data, UINT Len ) {
29 unsigned int i;
30
31 for( i = 0; i < Len; i++ ) {
32 if( i && !(i & 0xf) ) DbgPrint( "\n" );
33 if( !(i & 0xf) ) DbgPrint( "%08x: ", (UINT)(Data + i) );
34 DbgPrint( " %02x", Data[i] & 0xff );
35 }
36 DbgPrint("\n");
37 }
38
39 /* FUNCTIONS */
40
41 NTSTATUS NTAPI
42 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
43
44 NTSTATUS NTAPI
45 AfdGetDisconnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp,
46 PIO_STACK_LOCATION IrpSp)
47 {
48 PFILE_OBJECT FileObject = IrpSp->FileObject;
49 PAFD_FCB FCB = FileObject->FsContext;
50 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
51
52 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
53
54 if (FCB->DisconnectOptionsSize == 0)
55 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
56
57 ASSERT(FCB->DisconnectOptions);
58
59 if (FCB->FilledDisconnectOptions < BufferSize) BufferSize = FCB->FilledDisconnectOptions;
60
61 RtlCopyMemory(Irp->UserBuffer,
62 FCB->DisconnectOptions,
63 BufferSize);
64
65 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize);
66 }
67
68 NTSTATUS
69 NTAPI
70 AfdSetDisconnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp,
71 PIO_STACK_LOCATION IrpSp)
72 {
73 PFILE_OBJECT FileObject = IrpSp->FileObject;
74 PAFD_FCB FCB = FileObject->FsContext;
75 PVOID DisconnectOptions = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
76 UINT DisconnectOptionsSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
77
78 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
79
80 if (FCB->DisconnectOptions)
81 {
82 ExFreePool(FCB->DisconnectOptions);
83 FCB->DisconnectOptions = NULL;
84 FCB->DisconnectOptionsSize = 0;
85 FCB->FilledDisconnectOptions = 0;
86 }
87
88 FCB->DisconnectOptions = ExAllocatePool(PagedPool, DisconnectOptionsSize);
89 if (!FCB->DisconnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
90
91 RtlCopyMemory(FCB->DisconnectOptions,
92 DisconnectOptions,
93 DisconnectOptionsSize);
94
95 FCB->DisconnectOptionsSize = DisconnectOptionsSize;
96
97 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
98 }
99
100 NTSTATUS
101 NTAPI
102 AfdSetDisconnectOptionsSize(PDEVICE_OBJECT DeviceObject, PIRP Irp,
103 PIO_STACK_LOCATION IrpSp)
104 {
105 PFILE_OBJECT FileObject = IrpSp->FileObject;
106 PAFD_FCB FCB = FileObject->FsContext;
107 PUINT DisconnectOptionsSize = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
108 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
109
110 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
111
112 if (BufferSize < sizeof(UINT))
113 return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0);
114
115 if (FCB->DisconnectOptions)
116 {
117 ExFreePool(FCB->DisconnectOptions);
118 FCB->DisconnectOptionsSize = 0;
119 FCB->FilledDisconnectOptions = 0;
120 }
121
122 FCB->DisconnectOptions = ExAllocatePool(PagedPool, *DisconnectOptionsSize);
123 if (!FCB->DisconnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
124
125 FCB->DisconnectOptionsSize = *DisconnectOptionsSize;
126
127 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
128 }
129
130 NTSTATUS NTAPI
131 AfdGetDisconnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
132 PIO_STACK_LOCATION IrpSp)
133 {
134 PFILE_OBJECT FileObject = IrpSp->FileObject;
135 PAFD_FCB FCB = FileObject->FsContext;
136 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
137
138 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
139
140 if (FCB->DisconnectDataSize == 0)
141 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
142
143 ASSERT(FCB->DisconnectData);
144
145 if (FCB->FilledDisconnectData < BufferSize) BufferSize = FCB->FilledDisconnectData;
146
147 RtlCopyMemory(Irp->UserBuffer,
148 FCB->DisconnectData,
149 BufferSize);
150
151 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize);
152 }
153
154 NTSTATUS
155 NTAPI
156 AfdSetDisconnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
157 PIO_STACK_LOCATION IrpSp)
158 {
159 PFILE_OBJECT FileObject = IrpSp->FileObject;
160 PAFD_FCB FCB = FileObject->FsContext;
161 PVOID DisconnectData = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
162 UINT DisconnectDataSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
163
164 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
165
166 if (FCB->DisconnectData)
167 {
168 ExFreePool(FCB->DisconnectData);
169 FCB->DisconnectData = NULL;
170 FCB->DisconnectDataSize = 0;
171 FCB->FilledDisconnectData = 0;
172 }
173
174 FCB->DisconnectData = ExAllocatePool(PagedPool, DisconnectDataSize);
175 if (!FCB->DisconnectData) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
176
177 RtlCopyMemory(FCB->DisconnectData,
178 DisconnectData,
179 DisconnectDataSize);
180
181 FCB->DisconnectDataSize = DisconnectDataSize;
182
183 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
184 }
185
186 NTSTATUS
187 NTAPI
188 AfdSetDisconnectDataSize(PDEVICE_OBJECT DeviceObject, PIRP Irp,
189 PIO_STACK_LOCATION IrpSp)
190 {
191 PFILE_OBJECT FileObject = IrpSp->FileObject;
192 PAFD_FCB FCB = FileObject->FsContext;
193 PUINT DisconnectDataSize = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
194 UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
195
196 if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
197
198 if (BufferSize < sizeof(UINT))
199 return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0);
200
201 if (FCB->DisconnectData)
202 {
203 ExFreePool(FCB->DisconnectData);
204 FCB->DisconnectDataSize = 0;
205 FCB->FilledDisconnectData = 0;
206 }
207
208 FCB->DisconnectData = ExAllocatePool(PagedPool, *DisconnectDataSize);
209 if (!FCB->DisconnectData) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
210
211 FCB->DisconnectDataSize = *DisconnectDataSize;
212
213 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
214 }
215
216 static NTSTATUS NTAPI
217 AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
218 PIO_STACK_LOCATION IrpSp) {
219 PAFD_FCB FCB;
220 PFILE_OBJECT FileObject;
221 PAFD_DEVICE_EXTENSION DeviceExt;
222 PFILE_FULL_EA_INFORMATION EaInfo;
223 PAFD_CREATE_PACKET ConnectInfo = NULL;
224 ULONG EaLength;
225 PWCHAR EaInfoValue = NULL;
226 UINT Disposition, i;
227 NTSTATUS Status = STATUS_SUCCESS;
228
229 AFD_DbgPrint(MID_TRACE,
230 ("AfdCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
231
232 DeviceExt = DeviceObject->DeviceExtension;
233 FileObject = IrpSp->FileObject;
234 Disposition = (IrpSp->Parameters.Create.Options >> 24) & 0xff;
235
236 Irp->IoStatus.Information = 0;
237
238 EaInfo = Irp->AssociatedIrp.SystemBuffer;
239
240 if( EaInfo ) {
241 ConnectInfo = (PAFD_CREATE_PACKET)(EaInfo->EaName + EaInfo->EaNameLength + 1);
242 EaInfoValue = (PWCHAR)(((PCHAR)ConnectInfo) + sizeof(AFD_CREATE_PACKET));
243
244 EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
245 EaInfo->EaNameLength +
246 EaInfo->EaValueLength;
247
248 AFD_DbgPrint(MID_TRACE,("EaInfo: %x, EaInfoValue: %x\n",
249 EaInfo, EaInfoValue));
250 }
251
252 AFD_DbgPrint(MID_TRACE,("About to allocate the new FCB\n"));
253
254 FCB = ExAllocatePool(NonPagedPool, sizeof(AFD_FCB));
255 if( FCB == NULL ) {
256 Irp->IoStatus.Status = STATUS_NO_MEMORY;
257 IoCompleteRequest(Irp, IO_NO_INCREMENT);
258 return STATUS_NO_MEMORY;
259 }
260
261 AFD_DbgPrint(MID_TRACE,("Initializing the new FCB @ %x (FileObject %x Flags %x)\n", FCB, FileObject, ConnectInfo ? ConnectInfo->EndpointFlags : 0));
262
263 RtlZeroMemory( FCB, sizeof( *FCB ) );
264
265 FCB->Flags = ConnectInfo ? ConnectInfo->EndpointFlags : 0;
266 FCB->GroupID = ConnectInfo ? ConnectInfo->GroupID : 0;
267 FCB->GroupType = 0; /* FIXME */
268 FCB->State = SOCKET_STATE_CREATED;
269 FCB->FileObject = FileObject;
270 FCB->DeviceExt = DeviceExt;
271 FCB->Recv.Size = DEFAULT_RECEIVE_WINDOW_SIZE;
272 FCB->Send.Size = DEFAULT_SEND_WINDOW_SIZE;
273 FCB->AddressFile.Handle = INVALID_HANDLE_VALUE;
274 FCB->Connection.Handle = INVALID_HANDLE_VALUE;
275
276 KeInitializeMutex( &FCB->Mutex, 0 );
277
278 for( i = 0; i < MAX_FUNCTIONS; i++ ) {
279 InitializeListHead( &FCB->PendingIrpList[i] );
280 }
281
282 InitializeListHead( &FCB->DatagramList );
283 InitializeListHead( &FCB->PendingConnections );
284
285 AFD_DbgPrint(MID_TRACE,("%x: Checking command channel\n", FCB));
286
287 if( ConnectInfo ) {
288 FCB->TdiDeviceName.Length = ConnectInfo->SizeOfTransportName;
289 FCB->TdiDeviceName.MaximumLength = FCB->TdiDeviceName.Length;
290 FCB->TdiDeviceName.Buffer =
291 ExAllocatePool( NonPagedPool, FCB->TdiDeviceName.Length );
292
293 if( !FCB->TdiDeviceName.Buffer ) {
294 ExFreePool(FCB);
295 AFD_DbgPrint(MID_TRACE,("Could not copy target string\n"));
296 Irp->IoStatus.Status = STATUS_NO_MEMORY;
297 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
298 return STATUS_NO_MEMORY;
299 }
300
301 RtlCopyMemory( FCB->TdiDeviceName.Buffer,
302 ConnectInfo->TransportName,
303 FCB->TdiDeviceName.Length );
304
305 AFD_DbgPrint(MID_TRACE,("Success: %s %wZ\n",
306 EaInfo->EaName, &FCB->TdiDeviceName));
307 } else {
308 AFD_DbgPrint(MID_TRACE,("Success: Control connection\n"));
309 }
310
311 FileObject->FsContext = FCB;
312
313 /* It seems that UDP sockets are writable from inception */
314 if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) {
315 AFD_DbgPrint(MID_TRACE,("Packet oriented socket\n"));
316 FCB->Send.Window = ExAllocatePool( PagedPool, FCB->Send.Size );
317 if (FCB->Send.Window)
318 {
319 /* A datagram socket is always sendable */
320 FCB->PollState |= AFD_EVENT_SEND;
321 PollReeval( FCB->DeviceExt, FCB->FileObject );
322 } else Status = STATUS_NO_MEMORY;
323 }
324
325 if( !NT_SUCCESS(Status) ) {
326 if( FCB->TdiDeviceName.Buffer ) ExFreePool( FCB->TdiDeviceName.Buffer );
327 ExFreePool( FCB );
328 FileObject->FsContext = NULL;
329 }
330
331 Irp->IoStatus.Status = Status;
332 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
333
334 return Status;
335 }
336
337 static NTSTATUS NTAPI
338 AfdCleanupSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
339 PIO_STACK_LOCATION IrpSp)
340 {
341 PFILE_OBJECT FileObject = IrpSp->FileObject;
342 PAFD_FCB FCB = FileObject->FsContext;
343 PLIST_ENTRY CurrentEntry, NextEntry;
344 UINT Function;
345 PIRP CurrentIrp;
346
347 if( !SocketAcquireStateLock( FCB ) ) return LostSocket(Irp);
348
349 for (Function = 0; Function < MAX_FUNCTIONS; Function++)
350 {
351 CurrentEntry = FCB->PendingIrpList[Function].Flink;
352 while (CurrentEntry != &FCB->PendingIrpList[Function])
353 {
354 NextEntry = CurrentEntry->Flink;
355 CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
356
357 /* The cancel routine will remove the IRP from the list */
358 IoCancelIrp(CurrentIrp);
359
360 CurrentEntry = NextEntry;
361 }
362 }
363
364 KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
365
366 return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
367 }
368
369 static NTSTATUS NTAPI
370 AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
371 PIO_STACK_LOCATION IrpSp)
372 {
373 PFILE_OBJECT FileObject = IrpSp->FileObject;
374 PAFD_FCB FCB = FileObject->FsContext;
375 UINT i;
376 PAFD_IN_FLIGHT_REQUEST InFlightRequest[IN_FLIGHT_REQUESTS];
377
378 AFD_DbgPrint(MID_TRACE,
379 ("AfdClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
380
381 if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED;
382
383 FCB->State = SOCKET_STATE_CLOSED;
384 FCB->PollState = AFD_EVENT_CLOSE;
385 PollReeval( FCB->DeviceExt, FCB->FileObject );
386
387 InFlightRequest[0] = &FCB->ListenIrp;
388 InFlightRequest[1] = &FCB->ReceiveIrp;
389 InFlightRequest[2] = &FCB->SendIrp;
390 InFlightRequest[3] = &FCB->ConnectIrp;
391
392 /* Cancel our pending requests */
393 for( i = 0; i < IN_FLIGHT_REQUESTS; i++ ) {
394 if( InFlightRequest[i]->InFlightRequest ) {
395 AFD_DbgPrint(MID_TRACE,("Cancelling in flight irp %d (%x)\n",
396 i, InFlightRequest[i]->InFlightRequest));
397 IoCancelIrp(InFlightRequest[i]->InFlightRequest);
398 }
399 }
400
401 KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
402
403 SocketStateUnlock( FCB );
404
405 if( FCB->EventSelect )
406 ObDereferenceObject( FCB->EventSelect );
407
408 if( FCB->Context )
409 ExFreePool( FCB->Context );
410
411 if( FCB->Recv.Window )
412 ExFreePool( FCB->Recv.Window );
413
414 if( FCB->Send.Window )
415 ExFreePool( FCB->Send.Window );
416
417 if( FCB->AddressFrom )
418 ExFreePool( FCB->AddressFrom );
419
420 if( FCB->ConnectInfo )
421 ExFreePool( FCB->ConnectInfo );
422
423 if( FCB->ConnectData )
424 ExFreePool( FCB->ConnectData );
425
426 if( FCB->DisconnectData )
427 ExFreePool( FCB->DisconnectData );
428
429 if( FCB->ConnectOptions )
430 ExFreePool( FCB->ConnectOptions );
431
432 if( FCB->DisconnectOptions )
433 ExFreePool( FCB->DisconnectOptions );
434
435 if( FCB->LocalAddress )
436 ExFreePool( FCB->LocalAddress );
437
438 if( FCB->RemoteAddress )
439 ExFreePool( FCB->RemoteAddress );
440
441 if( FCB->Connection.Object )
442 ObDereferenceObject(FCB->Connection.Object);
443
444 if( FCB->AddressFile.Object )
445 ObDereferenceObject(FCB->AddressFile.Object);
446
447 if( FCB->AddressFile.Handle != INVALID_HANDLE_VALUE )
448 {
449 if (ZwClose(FCB->AddressFile.Handle) == STATUS_INVALID_HANDLE)
450 {
451 DbgPrint("INVALID ADDRESS FILE HANDLE VALUE: %x %x\n", FCB->AddressFile.Handle, FCB->AddressFile.Object);
452 }
453 }
454
455 if( FCB->Connection.Handle != INVALID_HANDLE_VALUE )
456 {
457 if (ZwClose(FCB->Connection.Handle) == STATUS_INVALID_HANDLE)
458 {
459 DbgPrint("INVALID CONNECTION HANDLE VALUE: %x %x\n", FCB->Connection.Handle, FCB->Connection.Object);
460 }
461 }
462
463 if( FCB->TdiDeviceName.Buffer )
464 ExFreePool(FCB->TdiDeviceName.Buffer);
465
466 ExFreePool(FCB);
467
468 Irp->IoStatus.Status = STATUS_SUCCESS;
469 Irp->IoStatus.Information = 0;
470 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
471
472 AFD_DbgPrint(MID_TRACE, ("Returning success.\n"));
473
474 return STATUS_SUCCESS;
475 }
476
477 static NTSTATUS NTAPI
478 AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
479 PIO_STACK_LOCATION IrpSp) {
480 PFILE_OBJECT FileObject = IrpSp->FileObject;
481 PAFD_FCB FCB = FileObject->FsContext;
482 PAFD_DISCONNECT_INFO DisReq;
483 IO_STATUS_BLOCK Iosb;
484 PTDI_CONNECTION_INFORMATION ConnectionReturnInfo;
485 NTSTATUS Status = STATUS_SUCCESS;
486 USHORT Flags = 0;
487
488 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
489
490 if( !(DisReq = LockRequest( Irp, IrpSp )) )
491 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
492 Irp, 0 );
493
494 if (!(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS))
495 {
496 if( !FCB->ConnectInfo )
497 return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
498 Irp, 0 );
499
500 ASSERT(FCB->RemoteAddress);
501
502 Status = TdiBuildNullConnectionInfo
503 ( &ConnectionReturnInfo, FCB->RemoteAddress->Address[0].AddressType );
504
505 if( !NT_SUCCESS(Status) )
506 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
507 Irp, 0 );
508
509 if( DisReq->DisconnectType & AFD_DISCONNECT_SEND )
510 Flags |= TDI_DISCONNECT_RELEASE;
511 if( DisReq->DisconnectType & AFD_DISCONNECT_RECV ||
512 DisReq->DisconnectType & AFD_DISCONNECT_ABORT )
513 Flags |= TDI_DISCONNECT_ABORT;
514
515 FCB->ConnectInfo->UserData = FCB->DisconnectData;
516 FCB->ConnectInfo->UserDataLength = FCB->DisconnectDataSize;
517 FCB->ConnectInfo->Options = FCB->DisconnectOptions;
518 FCB->ConnectInfo->OptionsLength = FCB->DisconnectOptionsSize;
519
520 Status = TdiDisconnect( FCB->Connection.Object,
521 &DisReq->Timeout,
522 Flags,
523 &Iosb,
524 NULL,
525 NULL,
526 FCB->ConnectInfo,
527 ConnectionReturnInfo);
528
529 if (NT_SUCCESS(Status)) {
530 FCB->FilledDisconnectData = MIN(FCB->DisconnectDataSize, ConnectionReturnInfo->UserDataLength);
531 if (FCB->FilledDisconnectData)
532 {
533 RtlCopyMemory(FCB->DisconnectData,
534 ConnectionReturnInfo->UserData,
535 FCB->FilledDisconnectData);
536 }
537
538 FCB->FilledDisconnectOptions = MIN(FCB->DisconnectOptionsSize, ConnectionReturnInfo->OptionsLength);
539 if (FCB->FilledDisconnectOptions)
540 {
541 RtlCopyMemory(FCB->DisconnectOptions,
542 ConnectionReturnInfo->Options,
543 FCB->FilledDisconnectOptions);
544 }
545 }
546
547 ExFreePool( ConnectionReturnInfo );
548
549 FCB->PollState |= AFD_EVENT_DISCONNECT;
550 PollReeval( FCB->DeviceExt, FCB->FileObject );
551 } else
552 Status = STATUS_INVALID_PARAMETER;
553
554 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
555 }
556
557 static NTSTATUS NTAPI
558 AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
559 {
560 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
561 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
562 #if DBG
563 PFILE_OBJECT FileObject = IrpSp->FileObject;
564 #endif
565
566 AFD_DbgPrint(MID_TRACE,("AfdDispatch: %d\n", IrpSp->MajorFunction));
567 if( IrpSp->MajorFunction != IRP_MJ_CREATE) {
568 AFD_DbgPrint(MID_TRACE,("FO %x, IrpSp->FO %x\n",
569 FileObject, IrpSp->FileObject));
570 ASSERT(FileObject == IrpSp->FileObject);
571 }
572
573 Irp->IoStatus.Information = 0;
574
575 switch(IrpSp->MajorFunction)
576 {
577 /* opening and closing handles to the device */
578 case IRP_MJ_CREATE:
579 /* Mostly borrowed from the named pipe file system */
580 return AfdCreateSocket(DeviceObject, Irp, IrpSp);
581
582 case IRP_MJ_CLOSE:
583 /* Ditto the borrowing */
584 return AfdCloseSocket(DeviceObject, Irp, IrpSp);
585
586 case IRP_MJ_CLEANUP:
587 return AfdCleanupSocket(DeviceObject, Irp, IrpSp);
588
589 /* write data */
590 case IRP_MJ_WRITE:
591 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp, TRUE );
592
593 /* read data */
594 case IRP_MJ_READ:
595 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp, TRUE );
596
597 case IRP_MJ_DEVICE_CONTROL:
598 {
599 switch( IrpSp->Parameters.DeviceIoControl.IoControlCode ) {
600 case IOCTL_AFD_BIND:
601 return AfdBindSocket( DeviceObject, Irp, IrpSp );
602
603 case IOCTL_AFD_CONNECT:
604 return AfdStreamSocketConnect( DeviceObject, Irp, IrpSp );
605
606 case IOCTL_AFD_START_LISTEN:
607 return AfdListenSocket( DeviceObject, Irp, IrpSp );
608
609 case IOCTL_AFD_RECV:
610 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp,
611 FALSE );
612
613 case IOCTL_AFD_SELECT:
614 return AfdSelect( DeviceObject, Irp, IrpSp );
615
616 case IOCTL_AFD_EVENT_SELECT:
617 return AfdEventSelect( DeviceObject, Irp, IrpSp );
618
619 case IOCTL_AFD_ENUM_NETWORK_EVENTS:
620 return AfdEnumEvents( DeviceObject, Irp, IrpSp );
621
622 case IOCTL_AFD_RECV_DATAGRAM:
623 return AfdPacketSocketReadData( DeviceObject, Irp, IrpSp );
624
625 case IOCTL_AFD_SEND:
626 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp,
627 FALSE );
628
629 case IOCTL_AFD_SEND_DATAGRAM:
630 return AfdPacketSocketWriteData( DeviceObject, Irp, IrpSp );
631
632 case IOCTL_AFD_GET_INFO:
633 return AfdGetInfo( DeviceObject, Irp, IrpSp );
634
635 case IOCTL_AFD_SET_INFO:
636 return AfdSetInfo( DeviceObject, Irp, IrpSp );
637
638 case IOCTL_AFD_GET_CONTEXT_SIZE:
639 return AfdGetContextSize( DeviceObject, Irp, IrpSp );
640
641 case IOCTL_AFD_GET_CONTEXT:
642 return AfdGetContext( DeviceObject, Irp, IrpSp );
643
644 case IOCTL_AFD_SET_CONTEXT:
645 return AfdSetContext( DeviceObject, Irp, IrpSp );
646
647 case IOCTL_AFD_WAIT_FOR_LISTEN:
648 return AfdWaitForListen( DeviceObject, Irp, IrpSp );
649
650 case IOCTL_AFD_ACCEPT:
651 return AfdAccept( DeviceObject, Irp, IrpSp );
652
653 case IOCTL_AFD_DISCONNECT:
654 return AfdDisconnect( DeviceObject, Irp, IrpSp );
655
656 case IOCTL_AFD_GET_SOCK_NAME:
657 return AfdGetSockName( DeviceObject, Irp, IrpSp );
658
659 case IOCTL_AFD_GET_PEER_NAME:
660 return AfdGetPeerName( DeviceObject, Irp, IrpSp );
661
662 case IOCTL_AFD_GET_CONNECT_DATA:
663 return AfdGetConnectData(DeviceObject, Irp, IrpSp);
664
665 case IOCTL_AFD_SET_CONNECT_DATA:
666 return AfdSetConnectData(DeviceObject, Irp, IrpSp);
667
668 case IOCTL_AFD_SET_DISCONNECT_DATA:
669 return AfdSetDisconnectData(DeviceObject, Irp, IrpSp);
670
671 case IOCTL_AFD_GET_DISCONNECT_DATA:
672 return AfdGetDisconnectData(DeviceObject, Irp, IrpSp);
673
674 case IOCTL_AFD_SET_CONNECT_DATA_SIZE:
675 return AfdSetConnectDataSize(DeviceObject, Irp, IrpSp);
676
677 case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE:
678 return AfdSetDisconnectDataSize(DeviceObject, Irp, IrpSp);
679
680 case IOCTL_AFD_SET_CONNECT_OPTIONS:
681 return AfdSetConnectOptions(DeviceObject, Irp, IrpSp);
682
683 case IOCTL_AFD_SET_DISCONNECT_OPTIONS:
684 return AfdSetDisconnectOptions(DeviceObject, Irp, IrpSp);
685
686 case IOCTL_AFD_GET_CONNECT_OPTIONS:
687 return AfdGetConnectOptions(DeviceObject, Irp, IrpSp);
688
689 case IOCTL_AFD_GET_DISCONNECT_OPTIONS:
690 return AfdGetDisconnectOptions(DeviceObject, Irp, IrpSp);
691
692 case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE:
693 return AfdSetConnectOptionsSize(DeviceObject, Irp, IrpSp);
694
695 case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE:
696 return AfdSetDisconnectOptionsSize(DeviceObject, Irp, IrpSp);
697
698 case IOCTL_AFD_GET_TDI_HANDLES:
699 DbgPrint("IOCTL_AFD_GET_TDI_HANDLES is UNIMPLEMENTED!\n");
700 break;
701
702 case IOCTL_AFD_DEFER_ACCEPT:
703 DbgPrint("IOCTL_AFD_DEFER_ACCEPT is UNIMPLEMENTED!\n");
704 break;
705
706 case IOCTL_AFD_GET_PENDING_CONNECT_DATA:
707 DbgPrint("IOCTL_AFD_GET_PENDING_CONNECT_DATA is UNIMPLEMENTED!\n");
708 break;
709
710 case IOCTL_AFD_VALIDATE_GROUP:
711 DbgPrint("IOCTL_AFD_VALIDATE_GROUP is UNIMPLEMENTED!\n");
712 break;
713
714 default:
715 Status = STATUS_NOT_SUPPORTED;
716 DbgPrint("Unknown IOCTL (0x%x)\n",
717 IrpSp->Parameters.DeviceIoControl.IoControlCode);
718 break;
719 }
720 break;
721 }
722
723 /* unsupported operations */
724 default:
725 {
726 Status = STATUS_NOT_IMPLEMENTED;
727 AFD_DbgPrint(MIN_TRACE,
728 ("Irp: Unknown Major code was %x\n",
729 IrpSp->MajorFunction));
730 break;
731 }
732 }
733
734 AFD_DbgPrint(MID_TRACE, ("Returning %x\n", Status));
735 Irp->IoStatus.Status = Status;
736 IoCompleteRequest(Irp, IO_NO_INCREMENT);
737
738 return (Status);
739 }
740
741 VOID NTAPI
742 AfdCancelHandler(PDEVICE_OBJECT DeviceObject,
743 PIRP Irp)
744 {
745 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
746 PFILE_OBJECT FileObject = IrpSp->FileObject;
747 PAFD_FCB FCB = FileObject->FsContext;
748 UINT Function;
749 PAFD_RECV_INFO RecvReq;
750 PAFD_SEND_INFO SendReq;
751 PLIST_ENTRY CurrentEntry;
752 PIRP CurrentIrp;
753 PAFD_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
754 KIRQL OldIrql;
755 PAFD_ACTIVE_POLL Poll;
756 PAFD_POLL_INFO PollReq;
757
758 IoReleaseCancelSpinLock(Irp->CancelIrql);
759
760 if (!SocketAcquireStateLock(FCB))
761 return;
762
763 ASSERT(IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL);
764
765 switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
766 {
767 case IOCTL_AFD_RECV:
768 RecvReq = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
769 UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, FALSE);
770 /* Fall through */
771
772 case IOCTL_AFD_RECV_DATAGRAM:
773 Function = FUNCTION_RECV;
774 break;
775
776 case IOCTL_AFD_SEND:
777 SendReq = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
778 UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, FALSE);
779 /* Fall through */
780
781 case IOCTL_AFD_SEND_DATAGRAM:
782 Function = FUNCTION_SEND;
783 break;
784
785 case IOCTL_AFD_CONNECT:
786 Function = FUNCTION_CONNECT;
787 break;
788
789 case IOCTL_AFD_WAIT_FOR_LISTEN:
790 Function = FUNCTION_PREACCEPT;
791 break;
792
793 case IOCTL_AFD_SELECT:
794 KeAcquireSpinLock(&DeviceExt->Lock, &OldIrql);
795
796 CurrentEntry = DeviceExt->Polls.Flink;
797 while (CurrentEntry != &DeviceExt->Polls)
798 {
799 Poll = CONTAINING_RECORD(CurrentEntry, AFD_ACTIVE_POLL, ListEntry);
800 CurrentIrp = Poll->Irp;
801 PollReq = CurrentIrp->AssociatedIrp.SystemBuffer;
802
803 if (CurrentIrp == Irp)
804 {
805 ZeroEvents(PollReq->Handles, PollReq->HandleCount);
806 SignalSocket(Poll, NULL, PollReq, STATUS_CANCELLED);
807 break;
808 }
809 else
810 {
811 CurrentEntry = CurrentEntry->Flink;
812 }
813 }
814
815 KeReleaseSpinLock(&DeviceExt->Lock, OldIrql);
816
817 /* IRP already completed by SignalSocket */
818 SocketStateUnlock(FCB);
819 return;
820
821 default:
822 ASSERT(FALSE);
823 UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
824 return;
825 }
826
827 CurrentEntry = FCB->PendingIrpList[Function].Flink;
828 while (CurrentEntry != &FCB->PendingIrpList[Function])
829 {
830 CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
831
832 if (CurrentIrp == Irp)
833 {
834 RemoveEntryList(CurrentEntry);
835 break;
836 }
837 else
838 {
839 CurrentEntry = CurrentEntry->Flink;
840 }
841 }
842
843 UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
844 }
845
846 static VOID NTAPI
847 AfdUnload(PDRIVER_OBJECT DriverObject)
848 {
849 }
850
851 NTSTATUS NTAPI
852 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
853 {
854 PDEVICE_OBJECT DeviceObject;
855 UNICODE_STRING wstrDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Afd");
856 PAFD_DEVICE_EXTENSION DeviceExt;
857 NTSTATUS Status;
858
859 /* register driver routines */
860 DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdDispatch;
861 DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdDispatch;
862 DriverObject->MajorFunction[IRP_MJ_CLEANUP] = AfdDispatch;
863 DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdDispatch;
864 DriverObject->MajorFunction[IRP_MJ_READ] = AfdDispatch;
865 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch;
866 DriverObject->DriverUnload = AfdUnload;
867
868 Status = IoCreateDevice
869 ( DriverObject,
870 sizeof(AFD_DEVICE_EXTENSION),
871 &wstrDeviceName,
872 FILE_DEVICE_NAMED_PIPE,
873 0,
874 FALSE,
875 &DeviceObject );
876
877 /* failure */
878 if(!NT_SUCCESS(Status))
879 {
880 return (Status);
881 }
882
883 DeviceExt = DeviceObject->DeviceExtension;
884 KeInitializeSpinLock( &DeviceExt->Lock );
885 InitializeListHead( &DeviceExt->Polls );
886
887 AFD_DbgPrint(MID_TRACE,("Device created: object %x ext %x\n",
888 DeviceObject, DeviceExt));
889
890 return (Status);
891 }
892
893 /* EOF */