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