- Print a message to the debug log if ZwClose returns STATUS_INVALID_HANDLE
[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 static NTSTATUS NTAPI
45 AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
46 PIO_STACK_LOCATION IrpSp) {
47 PAFD_FCB FCB;
48 PFILE_OBJECT FileObject;
49 PAFD_DEVICE_EXTENSION DeviceExt;
50 PFILE_FULL_EA_INFORMATION EaInfo;
51 PAFD_CREATE_PACKET ConnectInfo = NULL;
52 ULONG EaLength;
53 PWCHAR EaInfoValue = NULL;
54 UINT Disposition, i;
55 NTSTATUS Status = STATUS_SUCCESS;
56
57 AFD_DbgPrint(MID_TRACE,
58 ("AfdCreate(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
59
60 DeviceExt = DeviceObject->DeviceExtension;
61 FileObject = IrpSp->FileObject;
62 Disposition = (IrpSp->Parameters.Create.Options >> 24) & 0xff;
63
64 Irp->IoStatus.Information = 0;
65
66 EaInfo = Irp->AssociatedIrp.SystemBuffer;
67
68 if( EaInfo ) {
69 ConnectInfo = (PAFD_CREATE_PACKET)(EaInfo->EaName + EaInfo->EaNameLength + 1);
70 EaInfoValue = (PWCHAR)(((PCHAR)ConnectInfo) + sizeof(AFD_CREATE_PACKET));
71
72 EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
73 EaInfo->EaNameLength +
74 EaInfo->EaValueLength;
75
76 AFD_DbgPrint(MID_TRACE,("EaInfo: %x, EaInfoValue: %x\n",
77 EaInfo, EaInfoValue));
78 }
79
80 AFD_DbgPrint(MID_TRACE,("About to allocate the new FCB\n"));
81
82 FCB = ExAllocatePool(NonPagedPool, sizeof(AFD_FCB));
83 if( FCB == NULL ) {
84 Irp->IoStatus.Status = STATUS_NO_MEMORY;
85 IoCompleteRequest(Irp, IO_NO_INCREMENT);
86 return STATUS_NO_MEMORY;
87 }
88
89 AFD_DbgPrint(MID_TRACE,("Initializing the new FCB @ %x (FileObject %x Flags %x)\n", FCB, FileObject, ConnectInfo ? ConnectInfo->EndpointFlags : 0));
90
91 RtlZeroMemory( FCB, sizeof( *FCB ) );
92
93 FCB->Flags = ConnectInfo ? ConnectInfo->EndpointFlags : 0;
94 FCB->State = SOCKET_STATE_CREATED;
95 FCB->FileObject = FileObject;
96 FCB->DeviceExt = DeviceExt;
97 FCB->Recv.Size = DEFAULT_RECEIVE_WINDOW_SIZE;
98 FCB->Send.Size = DEFAULT_SEND_WINDOW_SIZE;
99 FCB->AddressFile.Handle = INVALID_HANDLE_VALUE;
100 FCB->Connection.Handle = INVALID_HANDLE_VALUE;
101
102 KeInitializeSpinLock( &FCB->SpinLock );
103 ExInitializeFastMutex( &FCB->Mutex );
104 KeInitializeEvent( &FCB->StateLockedEvent, NotificationEvent, FALSE );
105
106 for( i = 0; i < MAX_FUNCTIONS; i++ ) {
107 InitializeListHead( &FCB->PendingIrpList[i] );
108 }
109
110 InitializeListHead( &FCB->DatagramList );
111 InitializeListHead( &FCB->PendingConnections );
112
113 AFD_DbgPrint(MID_TRACE,("%x: Checking command channel\n", FCB));
114
115 if( ConnectInfo ) {
116 FCB->TdiDeviceName.Length = ConnectInfo->SizeOfTransportName;
117 FCB->TdiDeviceName.MaximumLength = FCB->TdiDeviceName.Length;
118 FCB->TdiDeviceName.Buffer =
119 ExAllocatePool( NonPagedPool, FCB->TdiDeviceName.Length );
120
121 if( !FCB->TdiDeviceName.Buffer ) {
122 ExFreePool(FCB);
123 AFD_DbgPrint(MID_TRACE,("Could not copy target string\n"));
124 Irp->IoStatus.Status = STATUS_NO_MEMORY;
125 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
126 return STATUS_NO_MEMORY;
127 }
128
129 RtlCopyMemory( FCB->TdiDeviceName.Buffer,
130 ConnectInfo->TransportName,
131 FCB->TdiDeviceName.Length );
132
133 AFD_DbgPrint(MID_TRACE,("Success: %s %wZ\n",
134 EaInfo->EaName, &FCB->TdiDeviceName));
135 } else {
136 AFD_DbgPrint(MID_TRACE,("Success: Control connection\n"));
137 }
138
139 FileObject->FsContext = FCB;
140
141 /* It seems that UDP sockets are writable from inception */
142 if( FCB->Flags & SGID_CONNECTIONLESS ) {
143 AFD_DbgPrint(MID_TRACE,("Packet oriented socket\n"));
144 /* Allocate our backup buffer */
145 FCB->Recv.Window = ExAllocatePool( NonPagedPool, FCB->Recv.Size );
146 if( !FCB->Recv.Window ) Status = STATUS_NO_MEMORY;
147 if( NT_SUCCESS(Status) )
148 {
149 FCB->Send.Window = ExAllocatePool( NonPagedPool, FCB->Send.Size );
150 if( !FCB->Send.Window ) {
151 if( FCB->Recv.Window ) ExFreePool( FCB->Recv.Window );
152 Status = STATUS_NO_MEMORY;
153 }
154 }
155 /* A datagram socket is always sendable */
156 FCB->PollState |= AFD_EVENT_SEND;
157 PollReeval( FCB->DeviceExt, FCB->FileObject );
158 }
159
160 if( !NT_SUCCESS(Status) ) {
161 if( FCB->TdiDeviceName.Buffer ) ExFreePool( FCB->TdiDeviceName.Buffer );
162 ExFreePool( FCB );
163 FileObject->FsContext = NULL;
164 }
165
166 Irp->IoStatus.Status = Status;
167 IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
168
169 return Status;
170 }
171
172 static NTSTATUS NTAPI
173 AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
174 PIO_STACK_LOCATION IrpSp)
175 {
176 PFILE_OBJECT FileObject = IrpSp->FileObject;
177 PAFD_FCB FCB = FileObject->FsContext;
178 UINT i;
179 PAFD_IN_FLIGHT_REQUEST InFlightRequest[IN_FLIGHT_REQUESTS];
180
181 AFD_DbgPrint(MID_TRACE,
182 ("AfdClose(DeviceObject %p Irp %p)\n", DeviceObject, Irp));
183
184 if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED;
185
186 FCB->State = SOCKET_STATE_CLOSED;
187 FCB->PollState = AFD_EVENT_CLOSE;
188 PollReeval( FCB->DeviceExt, FCB->FileObject );
189
190 InFlightRequest[0] = &FCB->ListenIrp;
191 InFlightRequest[1] = &FCB->ReceiveIrp;
192 InFlightRequest[2] = &FCB->SendIrp;
193 InFlightRequest[3] = &FCB->ConnectIrp;
194
195 /* Cancel our pending requests */
196 for( i = 0; i < IN_FLIGHT_REQUESTS; i++ ) {
197 if( InFlightRequest[i]->InFlightRequest ) {
198 AFD_DbgPrint(MID_TRACE,("Cancelling in flight irp %d (%x)\n",
199 i, InFlightRequest[i]->InFlightRequest));
200 IoCancelIrp(InFlightRequest[i]->InFlightRequest);
201 }
202 }
203
204 KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
205
206 SocketStateUnlock( FCB );
207
208 if( FCB->EventSelect )
209 ObDereferenceObject( FCB->EventSelect );
210
211 if( FCB->Context )
212 ExFreePool( FCB->Context );
213
214 if( FCB->Recv.Window )
215 ExFreePool( FCB->Recv.Window );
216
217 if( FCB->Send.Window )
218 ExFreePool( FCB->Send.Window );
219
220 if( FCB->AddressFrom )
221 ExFreePool( FCB->AddressFrom );
222
223 if( FCB->LocalAddress )
224 ExFreePool( FCB->LocalAddress );
225
226 if( FCB->RemoteAddress )
227 ExFreePool( FCB->RemoteAddress );
228
229 if( FCB->Connection.Object )
230 ObDereferenceObject(FCB->Connection.Object);
231
232 if( FCB->AddressFile.Object )
233 ObDereferenceObject(FCB->AddressFile.Object);
234
235 if( FCB->AddressFile.Handle != INVALID_HANDLE_VALUE )
236 {
237 if (ZwClose(FCB->AddressFile.Handle) == STATUS_INVALID_HANDLE)
238 {
239 DbgPrint("INVALID ADDRESS FILE HANDLE VALUE: %x %x\n", FCB->AddressFile.Handle, FCB->AddressFile.Object);
240 }
241 }
242
243 if( FCB->Connection.Handle != INVALID_HANDLE_VALUE )
244 {
245 if (ZwClose(FCB->Connection.Handle) == STATUS_INVALID_HANDLE)
246 {
247 DbgPrint("INVALID CONNECTION HANDLE VALUE: %x %x\n", FCB->Connection.Handle, FCB->Connection.Object);
248 }
249 }
250
251 if( FCB->TdiDeviceName.Buffer )
252 ExFreePool(FCB->TdiDeviceName.Buffer);
253
254 ExFreePool(FCB);
255
256 Irp->IoStatus.Status = STATUS_SUCCESS;
257 Irp->IoStatus.Information = 0;
258 IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
259
260 AFD_DbgPrint(MID_TRACE, ("Returning success.\n"));
261
262 return STATUS_SUCCESS;
263 }
264
265 static NTSTATUS NTAPI
266 AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
267 PIO_STACK_LOCATION IrpSp) {
268 PFILE_OBJECT FileObject = IrpSp->FileObject;
269 PAFD_FCB FCB = FileObject->FsContext;
270 PAFD_DISCONNECT_INFO DisReq;
271 IO_STATUS_BLOCK Iosb;
272 PTDI_CONNECTION_INFORMATION ConnInfo;
273 NTSTATUS Status;
274 USHORT Flags = 0;
275
276 if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp );
277
278 if( !(DisReq = LockRequest( Irp, IrpSp )) )
279 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
280 Irp, 0 );
281
282 if (NULL == FCB->RemoteAddress)
283 {
284 ConnInfo = NULL;
285 }
286 else
287 {
288 Status = TdiBuildNullConnectionInfo
289 ( &ConnInfo, FCB->RemoteAddress->Address[0].AddressType );
290
291 if( !NT_SUCCESS(Status) || !ConnInfo )
292 return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
293 Irp, 0 );
294 }
295
296 if( DisReq->DisconnectType & AFD_DISCONNECT_SEND )
297 Flags |= TDI_DISCONNECT_RELEASE;
298 if( DisReq->DisconnectType & AFD_DISCONNECT_RECV ||
299 DisReq->DisconnectType & AFD_DISCONNECT_ABORT )
300 Flags |= TDI_DISCONNECT_ABORT;
301
302 Status = TdiDisconnect( FCB->Connection.Object,
303 &DisReq->Timeout,
304 Flags,
305 &Iosb,
306 NULL,
307 NULL,
308 FCB->AddressFrom,
309 ConnInfo);
310
311 if (ConnInfo) ExFreePool( ConnInfo );
312
313 FCB->PollState |= AFD_EVENT_DISCONNECT;
314 PollReeval( FCB->DeviceExt, FCB->FileObject );
315
316 return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
317 }
318
319 static NTSTATUS NTAPI
320 AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
321 {
322 PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
323 NTSTATUS Status = STATUS_SUCCESS;
324 #if DBG
325 PFILE_OBJECT FileObject = IrpSp->FileObject;
326 #endif
327
328 AFD_DbgPrint(MID_TRACE,("AfdDispatch: %d\n", IrpSp->MajorFunction));
329 if( IrpSp->MajorFunction != IRP_MJ_CREATE) {
330 AFD_DbgPrint(MID_TRACE,("FO %x, IrpSp->FO %x\n",
331 FileObject, IrpSp->FileObject));
332 ASSERT(FileObject == IrpSp->FileObject);
333 }
334
335 Irp->IoStatus.Information = 0;
336
337 switch(IrpSp->MajorFunction)
338 {
339 /* opening and closing handles to the device */
340 case IRP_MJ_CREATE:
341 /* Mostly borrowed from the named pipe file system */
342 return AfdCreateSocket(DeviceObject, Irp, IrpSp);
343
344 case IRP_MJ_CLOSE:
345 /* Ditto the borrowing */
346 return AfdCloseSocket(DeviceObject, Irp, IrpSp);
347
348 /* write data */
349 case IRP_MJ_WRITE:
350 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp, TRUE );
351
352 /* read data */
353 case IRP_MJ_READ:
354 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp, TRUE );
355
356 case IRP_MJ_DEVICE_CONTROL:
357 {
358 switch( IrpSp->Parameters.DeviceIoControl.IoControlCode ) {
359 case IOCTL_AFD_BIND:
360 return AfdBindSocket( DeviceObject, Irp, IrpSp );
361
362 case IOCTL_AFD_CONNECT:
363 return AfdStreamSocketConnect( DeviceObject, Irp, IrpSp );
364
365 case IOCTL_AFD_START_LISTEN:
366 return AfdListenSocket( DeviceObject, Irp, IrpSp );
367
368 case IOCTL_AFD_RECV:
369 return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp,
370 FALSE );
371
372 case IOCTL_AFD_SELECT:
373 return AfdSelect( DeviceObject, Irp, IrpSp );
374
375 case IOCTL_AFD_EVENT_SELECT:
376 return AfdEventSelect( DeviceObject, Irp, IrpSp );
377
378 case IOCTL_AFD_ENUM_NETWORK_EVENTS:
379 return AfdEnumEvents( DeviceObject, Irp, IrpSp );
380
381 case IOCTL_AFD_RECV_DATAGRAM:
382 return AfdPacketSocketReadData( DeviceObject, Irp, IrpSp );
383
384 case IOCTL_AFD_SEND:
385 return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp,
386 FALSE );
387
388 case IOCTL_AFD_SEND_DATAGRAM:
389 return AfdPacketSocketWriteData( DeviceObject, Irp, IrpSp );
390
391 case IOCTL_AFD_GET_INFO:
392 return AfdGetInfo( DeviceObject, Irp, IrpSp );
393
394 case IOCTL_AFD_SET_INFO:
395 return AfdSetInfo( DeviceObject, Irp, IrpSp );
396
397 case IOCTL_AFD_GET_CONTEXT:
398 return AfdGetContext( DeviceObject, Irp, IrpSp );
399
400 case IOCTL_AFD_SET_CONTEXT:
401 return AfdSetContext( DeviceObject, Irp, IrpSp );
402
403 case IOCTL_AFD_WAIT_FOR_LISTEN:
404 return AfdWaitForListen( DeviceObject, Irp, IrpSp );
405
406 case IOCTL_AFD_ACCEPT:
407 return AfdAccept( DeviceObject, Irp, IrpSp );
408
409 case IOCTL_AFD_DISCONNECT:
410 return AfdDisconnect( DeviceObject, Irp, IrpSp );
411
412 case IOCTL_AFD_GET_SOCK_NAME:
413 return AfdGetSockName( DeviceObject, Irp, IrpSp );
414
415 case IOCTL_AFD_GET_PEER_NAME:
416 return AfdGetPeerName( DeviceObject, Irp, IrpSp );
417
418 case IOCTL_AFD_GET_TDI_HANDLES:
419 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_TDI_HANDLES\n"));
420 break;
421
422 case IOCTL_AFD_SET_CONNECT_DATA:
423 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_DATA\n"));
424 break;
425
426 case IOCTL_AFD_SET_CONNECT_OPTIONS:
427 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_OPTIONS\n"));
428 break;
429
430 case IOCTL_AFD_SET_DISCONNECT_DATA:
431 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_DATA\n"));
432 break;
433
434 case IOCTL_AFD_SET_DISCONNECT_OPTIONS:
435 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_OPTIONS\n"));
436 break;
437
438 case IOCTL_AFD_GET_CONNECT_DATA:
439 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_CONNECT_DATA\n"));
440 break;
441
442 case IOCTL_AFD_GET_CONNECT_OPTIONS:
443 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_CONNECT_OPTIONS\n"));
444 break;
445
446 case IOCTL_AFD_GET_DISCONNECT_DATA:
447 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_DISCONNECT_DATA\n"));
448 break;
449
450 case IOCTL_AFD_GET_DISCONNECT_OPTIONS:
451 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_DISCONNECT_OPTIONS\n"));
452 break;
453
454 case IOCTL_AFD_SET_CONNECT_DATA_SIZE:
455 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_DATA_SIZE\n"));
456 break;
457
458 case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE:
459 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE\n"));
460 break;
461
462 case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE:
463 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_DATA_SIZE\n"));
464 break;
465
466 case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE:
467 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE\n"));
468 break;
469
470 case IOCTL_AFD_DEFER_ACCEPT:
471 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_DEFER_ACCEPT\n"));
472 break;
473
474 case IOCTL_AFD_GET_PENDING_CONNECT_DATA:
475 AFD_DbgPrint(MIN_TRACE, ("IOCTL_AFD_GET_PENDING_CONNECT_DATA\n"));
476 break;
477
478 default:
479 Status = STATUS_NOT_IMPLEMENTED;
480 AFD_DbgPrint(MIN_TRACE, ("Unknown IOCTL (0x%x)\n",
481 IrpSp->Parameters.DeviceIoControl.
482 IoControlCode));
483 break;
484 }
485 break;
486 }
487
488 /* unsupported operations */
489 default:
490 {
491 Status = STATUS_NOT_IMPLEMENTED;
492 AFD_DbgPrint(MIN_TRACE,
493 ("Irp: Unknown Major code was %x\n",
494 IrpSp->MajorFunction));
495 break;
496 }
497 }
498
499 AFD_DbgPrint(MID_TRACE, ("Returning %x\n", Status));
500 Irp->IoStatus.Status = Status;
501 IoCompleteRequest(Irp, IO_NO_INCREMENT);
502
503 return (Status);
504 }
505
506 static VOID NTAPI
507 AfdUnload(PDRIVER_OBJECT DriverObject)
508 {
509 }
510
511 NTSTATUS NTAPI
512 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
513 {
514 PDEVICE_OBJECT DeviceObject;
515 UNICODE_STRING wstrDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Afd");
516 PAFD_DEVICE_EXTENSION DeviceExt;
517 NTSTATUS Status;
518
519 /* register driver routines */
520 DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdDispatch;
521 DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdDispatch;
522 DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdDispatch;
523 DriverObject->MajorFunction[IRP_MJ_READ] = AfdDispatch;
524 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch;
525 DriverObject->DriverUnload = AfdUnload;
526
527 Status = IoCreateDevice
528 ( DriverObject,
529 sizeof(AFD_DEVICE_EXTENSION),
530 &wstrDeviceName,
531 FILE_DEVICE_NAMED_PIPE,
532 0,
533 FALSE,
534 &DeviceObject );
535
536 /* failure */
537 if(!NT_SUCCESS(Status))
538 {
539 return (Status);
540 }
541
542 DeviceExt = DeviceObject->DeviceExtension;
543 KeInitializeSpinLock( &DeviceExt->Lock );
544 InitializeListHead( &DeviceExt->Polls );
545
546 AFD_DbgPrint(MID_TRACE,("Device created: object %x ext %x\n",
547 DeviceObject, DeviceExt));
548
549 return (Status);
550 }
551
552 /* EOF */