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