ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

main.c
Go to the documentation of this file.
00001 /* $Id: main.c 56389 2012-04-22 13:11:54Z tfaber $
00002  * COPYRIGHT:        See COPYING in the top level directory
00003  * PROJECT:          ReactOS kernel
00004  * FILE:             drivers/net/afd/afd/main.c
00005  * PURPOSE:          Ancillary functions driver
00006  * PROGRAMMER:       Art Yerkes (ayerkes@speakeasy.net)
00007  * UPDATE HISTORY:
00008  * 20040630 Created
00009  *
00010  * Suggestions: Uniform naming (AfdXxx)
00011  */
00012 
00013 /* INCLUDES */
00014 
00015 #include "afd.h"
00016 
00017 #if DBG
00018 
00019 /* See debug.h for debug/trace constants */
00020 //DWORD DebugTraceLevel = DEBUG_ULTRA;
00021 DWORD DebugTraceLevel = MIN_TRACE;
00022 
00023 #endif /* DBG */
00024 
00025 void OskitDumpBuffer( PCHAR Data, UINT Len ) {
00026     unsigned int i;
00027 
00028     for( i = 0; i < Len; i++ ) {
00029         if( i && !(i & 0xf) ) DbgPrint( "\n" );
00030         if( !(i & 0xf) ) DbgPrint( "%08x: ", (UINT)(Data + i) );
00031         DbgPrint( " %02x", Data[i] & 0xff );
00032     }
00033     DbgPrint("\n");
00034 }
00035 
00036 /* FUNCTIONS */
00037 
00038 NTSTATUS NTAPI
00039 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath);
00040 
00041 NTSTATUS NTAPI
00042 AfdGetDisconnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp,
00043                         PIO_STACK_LOCATION IrpSp)
00044 {
00045     PFILE_OBJECT FileObject = IrpSp->FileObject;
00046     PAFD_FCB FCB = FileObject->FsContext;
00047     UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
00048 
00049     if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
00050 
00051     if (FCB->DisconnectOptionsSize == 0)
00052     {
00053         AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
00054         return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
00055     }
00056 
00057     ASSERT(FCB->DisconnectOptions);
00058 
00059     if (FCB->FilledDisconnectOptions < BufferSize) BufferSize = FCB->FilledDisconnectOptions;
00060 
00061     RtlCopyMemory(Irp->UserBuffer,
00062                   FCB->DisconnectOptions,
00063                   BufferSize);
00064 
00065     return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize);
00066 }
00067 
00068 NTSTATUS
00069 NTAPI
00070 AfdSetDisconnectOptions(PDEVICE_OBJECT DeviceObject, PIRP Irp,
00071                         PIO_STACK_LOCATION IrpSp)
00072 {
00073     PFILE_OBJECT FileObject = IrpSp->FileObject;
00074     PAFD_FCB FCB = FileObject->FsContext;
00075     PVOID DisconnectOptions = LockRequest(Irp, IrpSp);
00076     UINT DisconnectOptionsSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
00077 
00078     if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
00079 
00080     if (!DisconnectOptions)
00081         return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
00082 
00083     if (FCB->DisconnectOptions)
00084     {
00085         ExFreePool(FCB->DisconnectOptions);
00086         FCB->DisconnectOptions = NULL;
00087         FCB->DisconnectOptionsSize = 0;
00088         FCB->FilledDisconnectOptions = 0;
00089     }
00090 
00091     FCB->DisconnectOptions = ExAllocatePool(PagedPool, DisconnectOptionsSize);
00092     if (!FCB->DisconnectOptions)
00093         return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
00094 
00095     RtlCopyMemory(FCB->DisconnectOptions,
00096                   DisconnectOptions,
00097                   DisconnectOptionsSize);
00098 
00099     FCB->DisconnectOptionsSize = DisconnectOptionsSize;
00100 
00101     return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
00102 }
00103 
00104 NTSTATUS
00105 NTAPI
00106 AfdSetDisconnectOptionsSize(PDEVICE_OBJECT DeviceObject, PIRP Irp,
00107                       PIO_STACK_LOCATION IrpSp)
00108 {
00109     PFILE_OBJECT FileObject = IrpSp->FileObject;
00110     PAFD_FCB FCB = FileObject->FsContext;
00111     PUINT DisconnectOptionsSize = LockRequest(Irp, IrpSp);
00112     UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
00113 
00114     if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
00115 
00116     if (!DisconnectOptionsSize)
00117         return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
00118 
00119     if (BufferSize < sizeof(UINT))
00120     {
00121         AFD_DbgPrint(MIN_TRACE,("Buffer too small\n"));
00122         return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0);
00123     }
00124 
00125     if (FCB->DisconnectOptions)
00126     {
00127         ExFreePool(FCB->DisconnectOptions);
00128         FCB->DisconnectOptionsSize = 0;
00129         FCB->FilledDisconnectOptions = 0;
00130     }
00131 
00132     FCB->DisconnectOptions = ExAllocatePool(PagedPool, *DisconnectOptionsSize);
00133     if (!FCB->DisconnectOptions) return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
00134 
00135     FCB->DisconnectOptionsSize = *DisconnectOptionsSize;
00136 
00137     return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
00138 }
00139 
00140 NTSTATUS NTAPI
00141 AfdGetDisconnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
00142                   PIO_STACK_LOCATION IrpSp)
00143 {
00144     PFILE_OBJECT FileObject = IrpSp->FileObject;
00145     PAFD_FCB FCB = FileObject->FsContext;
00146     UINT BufferSize = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
00147 
00148     if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
00149 
00150     if (FCB->DisconnectDataSize == 0)
00151     {
00152         AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
00153         return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
00154     }
00155 
00156     ASSERT(FCB->DisconnectData);
00157 
00158     if (FCB->FilledDisconnectData < BufferSize)
00159         BufferSize = FCB->FilledDisconnectData;
00160 
00161     RtlCopyMemory(Irp->UserBuffer,
00162                   FCB->DisconnectData,
00163                   BufferSize);
00164 
00165     return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, BufferSize);
00166 }
00167 
00168 NTSTATUS
00169 NTAPI
00170 AfdSetDisconnectData(PDEVICE_OBJECT DeviceObject, PIRP Irp,
00171                      PIO_STACK_LOCATION IrpSp)
00172 {
00173     PFILE_OBJECT FileObject = IrpSp->FileObject;
00174     PAFD_FCB FCB = FileObject->FsContext;
00175     PVOID DisconnectData = LockRequest(Irp, IrpSp);
00176     UINT DisconnectDataSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
00177 
00178     if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
00179 
00180     if (!DisconnectData)
00181         return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
00182 
00183     if (FCB->DisconnectData)
00184     {
00185         ExFreePool(FCB->DisconnectData);
00186         FCB->DisconnectData = NULL;
00187         FCB->DisconnectDataSize = 0;
00188         FCB->FilledDisconnectData = 0;
00189     }
00190 
00191     FCB->DisconnectData = ExAllocatePool(PagedPool, DisconnectDataSize);
00192     if (!FCB->DisconnectData)
00193         return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
00194 
00195     RtlCopyMemory(FCB->DisconnectData,
00196                   DisconnectData,
00197                   DisconnectDataSize);
00198 
00199     FCB->DisconnectDataSize = DisconnectDataSize;
00200 
00201     return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
00202 }
00203 
00204 NTSTATUS
00205 NTAPI
00206 AfdSetDisconnectDataSize(PDEVICE_OBJECT DeviceObject, PIRP Irp,
00207                       PIO_STACK_LOCATION IrpSp)
00208 {
00209     PFILE_OBJECT FileObject = IrpSp->FileObject;
00210     PAFD_FCB FCB = FileObject->FsContext;
00211     PUINT DisconnectDataSize = LockRequest(Irp, IrpSp);
00212     UINT BufferSize = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
00213 
00214     if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
00215 
00216     if (!DisconnectDataSize)
00217         return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
00218 
00219     if (BufferSize < sizeof(UINT))
00220     {
00221         AFD_DbgPrint(MIN_TRACE,("Buffer too small\n"));
00222         return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0);
00223     }
00224 
00225     if (FCB->DisconnectData)
00226     {
00227         ExFreePool(FCB->DisconnectData);
00228         FCB->DisconnectDataSize = 0;
00229         FCB->FilledDisconnectData = 0;
00230     }
00231 
00232     FCB->DisconnectData = ExAllocatePool(PagedPool, *DisconnectDataSize);
00233     if (!FCB->DisconnectData)
00234         return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
00235 
00236     FCB->DisconnectDataSize = *DisconnectDataSize;
00237 
00238     return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
00239 }
00240 
00241 static NTSTATUS NTAPI
00242 AfdGetTdiHandles(PDEVICE_OBJECT DeviceObject, PIRP Irp,
00243                 PIO_STACK_LOCATION IrpSp)
00244 {
00245     PFILE_OBJECT FileObject = IrpSp->FileObject;
00246     PAFD_FCB FCB = FileObject->FsContext;
00247     PULONG HandleFlags = LockRequest(Irp, IrpSp);
00248     PAFD_TDI_HANDLE_DATA HandleData = Irp->UserBuffer;
00249 
00250     if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
00251 
00252     if (!HandleFlags)
00253         return UnlockAndMaybeComplete(FCB, STATUS_NO_MEMORY, Irp, 0);
00254 
00255     if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG) ||
00256         IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(*HandleData))
00257     {
00258         AFD_DbgPrint(MIN_TRACE,("Buffer too small\n"));
00259         return UnlockAndMaybeComplete(FCB, STATUS_BUFFER_TOO_SMALL, Irp, 0);
00260     }
00261 
00262     if ((*HandleFlags) & AFD_ADDRESS_HANDLE)
00263         HandleData->TdiAddressHandle = FCB->AddressFile.Handle;
00264 
00265     if ((*HandleFlags) & AFD_CONNECTION_HANDLE)
00266         HandleData->TdiConnectionHandle = FCB->Connection.Handle;
00267 
00268     return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
00269 }
00270 
00271 static NTSTATUS NTAPI
00272 AfdCreateSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
00273                 PIO_STACK_LOCATION IrpSp) {
00274     PAFD_FCB FCB;
00275     PFILE_OBJECT FileObject;
00276     PAFD_DEVICE_EXTENSION DeviceExt;
00277     PFILE_FULL_EA_INFORMATION EaInfo;
00278     PAFD_CREATE_PACKET ConnectInfo = NULL;
00279     //ULONG EaLength;
00280     PWCHAR EaInfoValue = NULL;
00281     //UINT Disposition;
00282     UINT i;
00283     NTSTATUS Status = STATUS_SUCCESS;
00284 
00285     AFD_DbgPrint(MID_TRACE,("AfdCreate(DeviceObject %p Irp %p)\n",
00286                             DeviceObject, Irp));
00287 
00288     DeviceExt = DeviceObject->DeviceExtension;
00289     FileObject = IrpSp->FileObject;
00290     //Disposition = (IrpSp->Parameters.Create.Options >> 24) & 0xff;
00291 
00292     Irp->IoStatus.Information = 0;
00293 
00294     EaInfo = Irp->AssociatedIrp.SystemBuffer;
00295 
00296     if( EaInfo ) {
00297         ConnectInfo = (PAFD_CREATE_PACKET)(EaInfo->EaName + EaInfo->EaNameLength + 1);
00298         EaInfoValue = (PWCHAR)(((PCHAR)ConnectInfo) + sizeof(AFD_CREATE_PACKET));
00299 
00300         //EaLength = sizeof(FILE_FULL_EA_INFORMATION) + EaInfo->EaNameLength + EaInfo->EaValueLength;
00301 
00302         AFD_DbgPrint(MID_TRACE,("EaInfo: %x, EaInfoValue: %x\n",
00303                                 EaInfo, EaInfoValue));
00304     }
00305 
00306     AFD_DbgPrint(MID_TRACE,("About to allocate the new FCB\n"));
00307 
00308     FCB = ExAllocatePool(NonPagedPool, sizeof(AFD_FCB));
00309     if( FCB == NULL ) {
00310         Irp->IoStatus.Status = STATUS_NO_MEMORY;
00311         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00312         return STATUS_NO_MEMORY;
00313     }
00314 
00315     AFD_DbgPrint(MID_TRACE,("Initializing the new FCB @ %x (FileObject %x Flags %x)\n",
00316                             FCB, FileObject, ConnectInfo ? ConnectInfo->EndpointFlags : 0));
00317 
00318     RtlZeroMemory( FCB, sizeof( *FCB ) );
00319 
00320     FCB->Flags = ConnectInfo ? ConnectInfo->EndpointFlags : 0;
00321     FCB->GroupID = ConnectInfo ? ConnectInfo->GroupID : 0;
00322     FCB->GroupType = 0; /* FIXME */
00323     FCB->State = SOCKET_STATE_CREATED;
00324     FCB->FileObject = FileObject;
00325     FCB->DeviceExt = DeviceExt;
00326     FCB->AddressFile.Handle = INVALID_HANDLE_VALUE;
00327     FCB->Connection.Handle = INVALID_HANDLE_VALUE;
00328 
00329     KeInitializeMutex( &FCB->Mutex, 0 );
00330 
00331     for( i = 0; i < MAX_FUNCTIONS; i++ ) {
00332         InitializeListHead( &FCB->PendingIrpList[i] );
00333     }
00334 
00335     InitializeListHead( &FCB->DatagramList );
00336     InitializeListHead( &FCB->PendingConnections );
00337 
00338     AFD_DbgPrint(MID_TRACE,("%x: Checking command channel\n", FCB));
00339 
00340     if( ConnectInfo ) {
00341         FCB->TdiDeviceName.Length = ConnectInfo->SizeOfTransportName;
00342         FCB->TdiDeviceName.MaximumLength = FCB->TdiDeviceName.Length;
00343         FCB->TdiDeviceName.Buffer =
00344             ExAllocatePool( NonPagedPool, FCB->TdiDeviceName.Length );
00345 
00346         if( !FCB->TdiDeviceName.Buffer ) {
00347             ExFreePool(FCB);
00348             AFD_DbgPrint(MID_TRACE,("Could not copy target string\n"));
00349             Irp->IoStatus.Status = STATUS_NO_MEMORY;
00350             IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
00351             return STATUS_NO_MEMORY;
00352         }
00353 
00354         RtlCopyMemory( FCB->TdiDeviceName.Buffer,
00355                        ConnectInfo->TransportName,
00356                        FCB->TdiDeviceName.Length );
00357 
00358         AFD_DbgPrint(MID_TRACE,("Success: %s %wZ\n",
00359                                 EaInfo->EaName, &FCB->TdiDeviceName));
00360     } else {
00361         AFD_DbgPrint(MID_TRACE,("Success: Control connection\n"));
00362     }
00363 
00364     FileObject->FsContext = FCB;
00365 
00366     /* It seems that UDP sockets are writable from inception */
00367     if( FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS ) {
00368         AFD_DbgPrint(MID_TRACE,("Packet oriented socket\n"));
00369 
00370         /* A datagram socket is always sendable */
00371         FCB->PollState |= AFD_EVENT_SEND;
00372         FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS;
00373         PollReeval( FCB->DeviceExt, FCB->FileObject );
00374     }
00375 
00376     if( !NT_SUCCESS(Status) ) {
00377         if( FCB->TdiDeviceName.Buffer ) ExFreePool( FCB->TdiDeviceName.Buffer );
00378         ExFreePool( FCB );
00379         FileObject->FsContext = NULL;
00380     }
00381 
00382     Irp->IoStatus.Status = Status;
00383     IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
00384 
00385     return Status;
00386 }
00387 
00388 static NTSTATUS NTAPI
00389 AfdCleanupSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
00390                  PIO_STACK_LOCATION IrpSp)
00391 {
00392     PFILE_OBJECT FileObject = IrpSp->FileObject;
00393     PAFD_FCB FCB = FileObject->FsContext;
00394     PLIST_ENTRY CurrentEntry, NextEntry;
00395     UINT Function;
00396     PIRP CurrentIrp;
00397 
00398     if( !SocketAcquireStateLock( FCB ) ) return LostSocket(Irp);
00399 
00400     for (Function = 0; Function < MAX_FUNCTIONS; Function++)
00401     {
00402         CurrentEntry = FCB->PendingIrpList[Function].Flink;
00403         while (CurrentEntry != &FCB->PendingIrpList[Function])
00404         {
00405            NextEntry = CurrentEntry->Flink;
00406            CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
00407 
00408            /* The cancel routine will remove the IRP from the list */
00409            IoCancelIrp(CurrentIrp);
00410 
00411            CurrentEntry = NextEntry;
00412         }
00413     }
00414 
00415     KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
00416 
00417     return UnlockAndMaybeComplete(FCB, STATUS_SUCCESS, Irp, 0);
00418 }
00419 
00420 static NTSTATUS NTAPI
00421 AfdCloseSocket(PDEVICE_OBJECT DeviceObject, PIRP Irp,
00422                PIO_STACK_LOCATION IrpSp)
00423 {
00424     PFILE_OBJECT FileObject = IrpSp->FileObject;
00425     PAFD_FCB FCB = FileObject->FsContext;
00426     UINT i;
00427     PAFD_IN_FLIGHT_REQUEST InFlightRequest[IN_FLIGHT_REQUESTS];
00428     PAFD_TDI_OBJECT_QELT Qelt;
00429     PLIST_ENTRY QeltEntry;
00430 
00431 
00432     AFD_DbgPrint(MID_TRACE,("AfdClose(DeviceObject %p Irp %p)\n",
00433                             DeviceObject, Irp));
00434 
00435     if( !SocketAcquireStateLock( FCB ) ) return STATUS_FILE_CLOSED;
00436 
00437     FCB->State = SOCKET_STATE_CLOSED;
00438 
00439     InFlightRequest[0] = &FCB->ListenIrp;
00440     InFlightRequest[1] = &FCB->ReceiveIrp;
00441     InFlightRequest[2] = &FCB->SendIrp;
00442     InFlightRequest[3] = &FCB->ConnectIrp;
00443     InFlightRequest[4] = &FCB->DisconnectIrp;
00444 
00445     /* Cancel our pending requests */
00446     for( i = 0; i < IN_FLIGHT_REQUESTS; i++ ) {
00447         if( InFlightRequest[i]->InFlightRequest ) {
00448             AFD_DbgPrint(MID_TRACE,("Cancelling in flight irp %d (%x)\n",
00449                                     i, InFlightRequest[i]->InFlightRequest));
00450             IoCancelIrp(InFlightRequest[i]->InFlightRequest);
00451         }
00452     }
00453 
00454     KillSelectsForFCB( FCB->DeviceExt, FileObject, FALSE );
00455 
00456     ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_CONNECT]));
00457     ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]));
00458     ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV]));
00459     ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_PREACCEPT]));
00460     ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT]));
00461 
00462     while (!IsListEmpty(&FCB->PendingConnections))
00463     {
00464         QeltEntry = RemoveHeadList(&FCB->PendingConnections);
00465         Qelt = CONTAINING_RECORD(QeltEntry, AFD_TDI_OBJECT_QELT, ListEntry);
00466 
00467         /* We have to close all pending connections or the listen won't get closed */
00468         TdiDisassociateAddressFile(Qelt->Object.Object);
00469         ObDereferenceObject(Qelt->Object.Object);
00470         ZwClose(Qelt->Object.Handle);
00471 
00472         ExFreePool(Qelt);
00473     }
00474 
00475     SocketStateUnlock( FCB );
00476 
00477     if( FCB->EventSelect )
00478         ObDereferenceObject( FCB->EventSelect );
00479 
00480     if( FCB->Context )
00481         ExFreePool( FCB->Context );
00482 
00483     if( FCB->Recv.Window )
00484         ExFreePool( FCB->Recv.Window );
00485 
00486     if( FCB->Send.Window )
00487         ExFreePool( FCB->Send.Window );
00488 
00489     if( FCB->AddressFrom )
00490         ExFreePool( FCB->AddressFrom );
00491 
00492     if( FCB->ConnectCallInfo )
00493         ExFreePool( FCB->ConnectCallInfo );
00494 
00495     if( FCB->ConnectReturnInfo )
00496         ExFreePool( FCB->ConnectReturnInfo );
00497 
00498     if( FCB->ConnectData )
00499         ExFreePool( FCB->ConnectData );
00500 
00501     if( FCB->DisconnectData )
00502         ExFreePool( FCB->DisconnectData );
00503 
00504     if( FCB->ConnectOptions )
00505         ExFreePool( FCB->ConnectOptions );
00506 
00507     if( FCB->DisconnectOptions )
00508         ExFreePool( FCB->DisconnectOptions );
00509 
00510     if( FCB->LocalAddress )
00511         ExFreePool( FCB->LocalAddress );
00512 
00513     if( FCB->RemoteAddress )
00514         ExFreePool( FCB->RemoteAddress );
00515 
00516     if( FCB->Connection.Object )
00517     {
00518         TdiDisassociateAddressFile(FCB->Connection.Object);
00519         ObDereferenceObject(FCB->Connection.Object);
00520     }
00521 
00522     if( FCB->AddressFile.Object )
00523         ObDereferenceObject(FCB->AddressFile.Object);
00524 
00525     if( FCB->AddressFile.Handle != INVALID_HANDLE_VALUE )
00526     {
00527         if (ZwClose(FCB->AddressFile.Handle) == STATUS_INVALID_HANDLE)
00528         {
00529             DbgPrint("INVALID ADDRESS FILE HANDLE VALUE: %x %x\n", FCB->AddressFile.Handle, FCB->AddressFile.Object);
00530         }
00531     }
00532 
00533     if( FCB->Connection.Handle != INVALID_HANDLE_VALUE )
00534     {
00535         if (ZwClose(FCB->Connection.Handle) == STATUS_INVALID_HANDLE)
00536         {
00537             DbgPrint("INVALID CONNECTION HANDLE VALUE: %x %x\n", FCB->Connection.Handle, FCB->Connection.Object);
00538         }
00539     }
00540 
00541     if( FCB->TdiDeviceName.Buffer )
00542         ExFreePool(FCB->TdiDeviceName.Buffer);
00543 
00544     ExFreePool(FCB);
00545 
00546     Irp->IoStatus.Status = STATUS_SUCCESS;
00547     Irp->IoStatus.Information = 0;
00548     IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
00549 
00550     AFD_DbgPrint(MID_TRACE, ("Returning success.\n"));
00551 
00552     return STATUS_SUCCESS;
00553 }
00554 
00555 static
00556 NTSTATUS
00557 NTAPI
00558 DisconnectComplete(PDEVICE_OBJECT DeviceObject,
00559                    PIRP Irp,
00560                    PVOID Context)
00561 {
00562     PAFD_FCB FCB = Context;
00563     PIRP CurrentIrp;
00564     PLIST_ENTRY CurrentEntry;
00565 
00566     if (!SocketAcquireStateLock(FCB))
00567         return STATUS_FILE_CLOSED;
00568 
00569     ASSERT(FCB->DisconnectIrp.InFlightRequest == Irp);
00570     FCB->DisconnectIrp.InFlightRequest = NULL;
00571 
00572     ASSERT(FCB->DisconnectPending);
00573     ASSERT((IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && !FCB->SendIrp.InFlightRequest) ||
00574            (FCB->DisconnectFlags & TDI_DISCONNECT_ABORT));
00575 
00576     if (NT_SUCCESS(Irp->IoStatus.Status) && (FCB->DisconnectFlags & TDI_DISCONNECT_RELEASE))
00577     {
00578         FCB->FilledDisconnectData = MIN(FCB->DisconnectDataSize, FCB->ConnectReturnInfo->UserDataLength);
00579         if (FCB->FilledDisconnectData)
00580         {
00581             RtlCopyMemory(FCB->DisconnectData,
00582                           FCB->ConnectReturnInfo->UserData,
00583                           FCB->FilledDisconnectData);
00584         }
00585 
00586         FCB->FilledDisconnectOptions = MIN(FCB->DisconnectOptionsSize, FCB->ConnectReturnInfo->OptionsLength);
00587         if (FCB->FilledDisconnectOptions)
00588         {
00589             RtlCopyMemory(FCB->DisconnectOptions,
00590                           FCB->ConnectReturnInfo->Options,
00591                           FCB->FilledDisconnectOptions);
00592         }
00593     }
00594 
00595     FCB->DisconnectPending = FALSE;
00596 
00597     while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT]))
00598     {
00599         CurrentEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_DISCONNECT]);
00600         CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
00601         CurrentIrp->IoStatus.Status = Irp->IoStatus.Status;
00602         CurrentIrp->IoStatus.Information = 0;
00603         UnlockRequest(CurrentIrp, IoGetCurrentIrpStackLocation(CurrentIrp));
00604         (void)IoSetCancelRoutine(CurrentIrp, NULL);
00605         IoCompleteRequest(CurrentIrp, IO_NETWORK_INCREMENT );
00606     }
00607 
00608     if (!(FCB->DisconnectFlags & TDI_DISCONNECT_RELEASE))
00609     {
00610         /* Signal complete connection closure immediately */
00611         FCB->PollState |= AFD_EVENT_ABORT;
00612         FCB->PollStatus[FD_CLOSE_BIT] = Irp->IoStatus.Status;
00613         PollReeval(FCB->DeviceExt, FCB->FileObject);
00614     }
00615 
00616     SocketStateUnlock(FCB);
00617 
00618     return Irp->IoStatus.Status;
00619 }
00620 
00621 static
00622 NTSTATUS
00623 DoDisconnect(PAFD_FCB FCB)
00624 {
00625     NTSTATUS Status;
00626 
00627     ASSERT(FCB->DisconnectPending);
00628     ASSERT((IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && !FCB->SendIrp.InFlightRequest) ||
00629            (FCB->DisconnectFlags & TDI_DISCONNECT_ABORT));
00630 
00631     if (FCB->DisconnectIrp.InFlightRequest)
00632     {
00633         return STATUS_PENDING;
00634     }
00635 
00636     FCB->ConnectCallInfo->UserData = FCB->DisconnectData;
00637     FCB->ConnectCallInfo->UserDataLength = FCB->DisconnectDataSize;
00638     FCB->ConnectCallInfo->Options = FCB->DisconnectOptions;
00639     FCB->ConnectCallInfo->OptionsLength = FCB->DisconnectOptionsSize;
00640 
00641     Status = TdiDisconnect(&FCB->DisconnectIrp.InFlightRequest,
00642                            FCB->Connection.Object,
00643                            &FCB->DisconnectTimeout,
00644                            FCB->DisconnectFlags,
00645                            &FCB->DisconnectIrp.Iosb,
00646                            DisconnectComplete,
00647                            FCB,
00648                            FCB->ConnectCallInfo,
00649                            FCB->ConnectReturnInfo);
00650     if (Status != STATUS_PENDING)
00651     {
00652         FCB->DisconnectPending = FALSE;
00653     }
00654 
00655     return Status;
00656 }
00657 
00658 VOID
00659 RetryDisconnectCompletion(PAFD_FCB FCB)
00660 {
00661     ASSERT(FCB->RemoteAddress);
00662 
00663     if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && !FCB->SendIrp.InFlightRequest && FCB->DisconnectPending)
00664     {
00665         /* Sends are done; fire off a TDI_DISCONNECT request */
00666         DoDisconnect(FCB);
00667     }
00668 }
00669 
00670 static NTSTATUS NTAPI
00671 AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp,
00672               PIO_STACK_LOCATION IrpSp) {
00673     PFILE_OBJECT FileObject = IrpSp->FileObject;
00674     PAFD_FCB FCB = FileObject->FsContext;
00675     PAFD_DISCONNECT_INFO DisReq;
00676     NTSTATUS Status = STATUS_SUCCESS;
00677     USHORT Flags;
00678     PLIST_ENTRY CurrentEntry;
00679     PIRP CurrentIrp;
00680 
00681     if (!SocketAcquireStateLock(FCB)) return LostSocket(Irp);
00682 
00683     if (!(DisReq = LockRequest(Irp, IrpSp)))
00684         return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY,
00685                                        Irp, 0 );
00686 
00687     /* Send direction only */
00688     if ((DisReq->DisconnectType & AFD_DISCONNECT_SEND) &&
00689         !(DisReq->DisconnectType & AFD_DISCONNECT_RECV))
00690     {
00691         /* Perform a controlled disconnect */
00692         Flags = TDI_DISCONNECT_RELEASE;
00693     }
00694     /* Receive direction or both */
00695     else
00696     {
00697         /* Mark that we can't issue another receive request */
00698         FCB->TdiReceiveClosed = TRUE;
00699 
00700         /* Try to cancel a pending TDI receive IRP if there was one in progress */
00701         if (FCB->ReceiveIrp.InFlightRequest)
00702             IoCancelIrp(FCB->ReceiveIrp.InFlightRequest);
00703 
00704         /* Discard any pending data */
00705         FCB->Recv.Content = 0;
00706         FCB->Recv.BytesUsed = 0;
00707 
00708         /* Mark us as overread to complete future reads with an error */
00709         FCB->Overread = TRUE;
00710 
00711         /* Set a successful close status to indicate a shutdown on overread */
00712         FCB->PollStatus[FD_CLOSE_BIT] = STATUS_SUCCESS;
00713 
00714         /* Clear the receive event */
00715         FCB->PollState &= ~AFD_EVENT_RECEIVE;
00716 
00717         /* Receive direction only */
00718         if ((DisReq->DisconnectType & AFD_DISCONNECT_RECV) &&
00719             !(DisReq->DisconnectType & AFD_DISCONNECT_SEND))
00720         {
00721             /* No need to tell the transport driver for receive direction only */
00722             return UnlockAndMaybeComplete( FCB, STATUS_SUCCESS, Irp, 0 );
00723         }
00724         else
00725         {
00726             /* Perform an abortive disconnect */
00727             Flags = TDI_DISCONNECT_ABORT;
00728         }
00729     }
00730 
00731     if (!(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS))
00732     {
00733         if (!FCB->ConnectCallInfo)
00734         {
00735             AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
00736             return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER,
00737                                            Irp, 0 );
00738         }
00739 
00740         if (FCB->DisconnectPending)
00741         {
00742             if (FCB->DisconnectIrp.InFlightRequest)
00743             {
00744                 IoCancelIrp(FCB->DisconnectIrp.InFlightRequest);
00745                 ASSERT(!FCB->DisconnectIrp.InFlightRequest);
00746             }
00747             else
00748             {
00749                 while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT]))
00750                 {
00751                     CurrentEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_DISCONNECT]);
00752                     CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
00753                     CurrentIrp->IoStatus.Status = STATUS_CANCELLED;
00754                     CurrentIrp->IoStatus.Information = 0;
00755                     UnlockRequest(CurrentIrp, IoGetCurrentIrpStackLocation(CurrentIrp));
00756                     (void)IoSetCancelRoutine(CurrentIrp, NULL);
00757                     IoCompleteRequest(CurrentIrp, IO_NETWORK_INCREMENT );
00758                 }
00759             }
00760         }
00761 
00762         FCB->DisconnectFlags = Flags;
00763         FCB->DisconnectTimeout = DisReq->Timeout;
00764         FCB->DisconnectPending = TRUE;
00765         FCB->SendClosed = TRUE;
00766         FCB->PollState &= ~AFD_EVENT_SEND;
00767 
00768         Status = QueueUserModeIrp(FCB, Irp, FUNCTION_DISCONNECT);
00769         if (Status == STATUS_PENDING)
00770         {
00771             if ((IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) && !FCB->SendIrp.InFlightRequest) ||
00772                 (FCB->DisconnectFlags & TDI_DISCONNECT_ABORT))
00773             {
00774                 /* Go ahead and execute the disconnect because we're ready for it */
00775                 Status = DoDisconnect(FCB);
00776             }
00777 
00778             if (Status != STATUS_PENDING)
00779                 RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
00780         }
00781 
00782         if (Status == STATUS_PENDING)
00783         {
00784             SocketStateUnlock(FCB);
00785 
00786             return Status;
00787         }
00788     }
00789     else
00790     {
00791         if (!(Flags & TDI_DISCONNECT_RELEASE))
00792         {
00793             if (!FCB->RemoteAddress)
00794             {
00795                 AFD_DbgPrint(MIN_TRACE,("Invalid parameter\n"));
00796                 return UnlockAndMaybeComplete(FCB, STATUS_INVALID_PARAMETER, Irp, 0);
00797             }
00798 
00799             ExFreePool(FCB->RemoteAddress);
00800 
00801             FCB->RemoteAddress = NULL;
00802         }
00803 
00804         FCB->PollState &= ~AFD_EVENT_SEND;
00805         FCB->SendClosed = TRUE;
00806     }
00807 
00808     return UnlockAndMaybeComplete( FCB, Status, Irp, 0 );
00809 }
00810 
00811 static NTSTATUS NTAPI
00812 AfdDispatch(PDEVICE_OBJECT DeviceObject, PIRP Irp)
00813 {
00814     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
00815     NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
00816 #if DBG
00817     PFILE_OBJECT FileObject = IrpSp->FileObject;
00818 #endif
00819 
00820     AFD_DbgPrint(MID_TRACE,("AfdDispatch: %d\n", IrpSp->MajorFunction));
00821     if( IrpSp->MajorFunction != IRP_MJ_CREATE) {
00822         AFD_DbgPrint(MID_TRACE,("FO %x, IrpSp->FO %x\n",
00823                                 FileObject, IrpSp->FileObject));
00824         ASSERT(FileObject == IrpSp->FileObject);
00825     }
00826 
00827     Irp->IoStatus.Information = 0;
00828 
00829     switch(IrpSp->MajorFunction)
00830     {
00831         /* opening and closing handles to the device */
00832     case IRP_MJ_CREATE:
00833         /* Mostly borrowed from the named pipe file system */
00834         return AfdCreateSocket(DeviceObject, Irp, IrpSp);
00835 
00836     case IRP_MJ_CLOSE:
00837         /* Ditto the borrowing */
00838         return AfdCloseSocket(DeviceObject, Irp, IrpSp);
00839 
00840     case IRP_MJ_CLEANUP:
00841         return AfdCleanupSocket(DeviceObject, Irp, IrpSp);
00842 
00843     /* write data */
00844     case IRP_MJ_WRITE:
00845         return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp, TRUE );
00846 
00847     /* read data */
00848     case IRP_MJ_READ:
00849         return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp, TRUE );
00850 
00851     case IRP_MJ_DEVICE_CONTROL:
00852     {
00853         switch( IrpSp->Parameters.DeviceIoControl.IoControlCode ) {
00854         case IOCTL_AFD_BIND:
00855             return AfdBindSocket( DeviceObject, Irp, IrpSp );
00856 
00857         case IOCTL_AFD_CONNECT:
00858             return AfdStreamSocketConnect( DeviceObject, Irp, IrpSp );
00859 
00860         case IOCTL_AFD_START_LISTEN:
00861             return AfdListenSocket( DeviceObject, Irp, IrpSp );
00862 
00863         case IOCTL_AFD_RECV:
00864             return AfdConnectedSocketReadData( DeviceObject, Irp, IrpSp,
00865                                                FALSE );
00866 
00867         case IOCTL_AFD_SELECT:
00868             return AfdSelect( DeviceObject, Irp, IrpSp );
00869 
00870         case IOCTL_AFD_EVENT_SELECT:
00871             return AfdEventSelect( DeviceObject, Irp, IrpSp );
00872 
00873         case IOCTL_AFD_ENUM_NETWORK_EVENTS:
00874             return AfdEnumEvents( DeviceObject, Irp, IrpSp );
00875 
00876         case IOCTL_AFD_RECV_DATAGRAM:
00877             return AfdPacketSocketReadData( DeviceObject, Irp, IrpSp );
00878 
00879         case IOCTL_AFD_SEND:
00880             return AfdConnectedSocketWriteData( DeviceObject, Irp, IrpSp,
00881                                                 FALSE );
00882 
00883         case IOCTL_AFD_SEND_DATAGRAM:
00884             return AfdPacketSocketWriteData( DeviceObject, Irp, IrpSp );
00885 
00886         case IOCTL_AFD_GET_INFO:
00887             return AfdGetInfo( DeviceObject, Irp, IrpSp );
00888 
00889         case IOCTL_AFD_SET_INFO:
00890             return AfdSetInfo( DeviceObject, Irp, IrpSp );
00891 
00892         case IOCTL_AFD_GET_CONTEXT_SIZE:
00893             return AfdGetContextSize( DeviceObject, Irp, IrpSp );
00894 
00895         case IOCTL_AFD_GET_CONTEXT:
00896             return AfdGetContext( DeviceObject, Irp, IrpSp );
00897 
00898         case IOCTL_AFD_SET_CONTEXT:
00899             return AfdSetContext( DeviceObject, Irp, IrpSp );
00900 
00901         case IOCTL_AFD_WAIT_FOR_LISTEN:
00902             return AfdWaitForListen( DeviceObject, Irp, IrpSp );
00903 
00904         case IOCTL_AFD_ACCEPT:
00905             return AfdAccept( DeviceObject, Irp, IrpSp );
00906 
00907         case IOCTL_AFD_DISCONNECT:
00908             return AfdDisconnect( DeviceObject, Irp, IrpSp );
00909 
00910         case IOCTL_AFD_GET_SOCK_NAME:
00911             return AfdGetSockName( DeviceObject, Irp, IrpSp );
00912 
00913         case IOCTL_AFD_GET_PEER_NAME:
00914             return AfdGetPeerName( DeviceObject, Irp, IrpSp );
00915 
00916         case IOCTL_AFD_GET_CONNECT_DATA:
00917             return AfdGetConnectData(DeviceObject, Irp, IrpSp);
00918 
00919         case IOCTL_AFD_SET_CONNECT_DATA:
00920             return AfdSetConnectData(DeviceObject, Irp, IrpSp);
00921 
00922         case IOCTL_AFD_SET_DISCONNECT_DATA:
00923             return AfdSetDisconnectData(DeviceObject, Irp, IrpSp);
00924 
00925         case IOCTL_AFD_GET_DISCONNECT_DATA:
00926             return AfdGetDisconnectData(DeviceObject, Irp, IrpSp);
00927 
00928         case IOCTL_AFD_SET_CONNECT_DATA_SIZE:
00929             return AfdSetConnectDataSize(DeviceObject, Irp, IrpSp);
00930 
00931         case IOCTL_AFD_SET_DISCONNECT_DATA_SIZE:
00932             return AfdSetDisconnectDataSize(DeviceObject, Irp, IrpSp);
00933 
00934         case IOCTL_AFD_SET_CONNECT_OPTIONS:
00935             return AfdSetConnectOptions(DeviceObject, Irp, IrpSp);
00936 
00937         case IOCTL_AFD_SET_DISCONNECT_OPTIONS:
00938             return AfdSetDisconnectOptions(DeviceObject, Irp, IrpSp);
00939 
00940         case IOCTL_AFD_GET_CONNECT_OPTIONS:
00941             return AfdGetConnectOptions(DeviceObject, Irp, IrpSp);
00942 
00943         case IOCTL_AFD_GET_DISCONNECT_OPTIONS:
00944             return AfdGetDisconnectOptions(DeviceObject, Irp, IrpSp);
00945 
00946         case IOCTL_AFD_SET_CONNECT_OPTIONS_SIZE:
00947             return AfdSetConnectOptionsSize(DeviceObject, Irp, IrpSp);
00948 
00949         case IOCTL_AFD_SET_DISCONNECT_OPTIONS_SIZE:
00950             return AfdSetDisconnectOptionsSize(DeviceObject, Irp, IrpSp);
00951 
00952         case IOCTL_AFD_GET_TDI_HANDLES:
00953             return AfdGetTdiHandles(DeviceObject, Irp, IrpSp);
00954 
00955         case IOCTL_AFD_DEFER_ACCEPT:
00956             DbgPrint("IOCTL_AFD_DEFER_ACCEPT is UNIMPLEMENTED!\n");
00957             break;
00958 
00959         case IOCTL_AFD_GET_PENDING_CONNECT_DATA:
00960             DbgPrint("IOCTL_AFD_GET_PENDING_CONNECT_DATA is UNIMPLEMENTED!\n");
00961             break;
00962 
00963         case IOCTL_AFD_VALIDATE_GROUP:
00964             DbgPrint("IOCTL_AFD_VALIDATE_GROUP is UNIMPLEMENTED!\n");
00965             break;
00966 
00967         default:
00968             Status = STATUS_NOT_SUPPORTED;
00969             DbgPrint("Unknown IOCTL (0x%x)\n",
00970                      IrpSp->Parameters.DeviceIoControl.IoControlCode);
00971             break;
00972         }
00973         break;
00974     }
00975 
00976 /* unsupported operations */
00977     default:
00978     {
00979         Status = STATUS_NOT_IMPLEMENTED;
00980         AFD_DbgPrint(MIN_TRACE,
00981                      ("Irp: Unknown Major code was %x\n",
00982                       IrpSp->MajorFunction));
00983         break;
00984     }
00985     }
00986 
00987     AFD_DbgPrint(MID_TRACE, ("Returning %x\n", Status));
00988     Irp->IoStatus.Status = Status;
00989     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00990 
00991     return Status;
00992 }
00993 
00994 BOOLEAN CheckUnlockExtraBuffers(PAFD_FCB FCB, PIO_STACK_LOCATION IrpSp)
00995 {
00996     if (FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)
00997     {
00998         if (IrpSp->MajorFunction == IRP_MJ_READ || IrpSp->MajorFunction == IRP_MJ_WRITE)
00999         {
01000             /* read()/write() call - no extra buffers */
01001             return FALSE;
01002         }
01003         else if (IrpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL)
01004         {
01005             if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV_DATAGRAM)
01006             {
01007                 /* recvfrom() call - extra buffers */
01008                 return TRUE;
01009             }
01010             else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV)
01011             {
01012                 /* recv() call - no extra buffers */
01013                 return FALSE;
01014             }
01015             else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND ||
01016                      IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND_DATAGRAM)
01017             {
01018                 /* send()/sendto() call - no extra buffers */
01019                 return FALSE;
01020             }
01021             else
01022             {
01023                 /* Unknown IOCTL */
01024                 ASSERT(FALSE);
01025                 return FALSE;
01026             }
01027         }
01028         else
01029         {
01030             /* Unknown IRP_MJ code */
01031             ASSERT(FALSE);
01032             return FALSE;
01033         }
01034     }
01035     else
01036     {
01037         /* Connection-oriented never has extra buffers */
01038         return FALSE;
01039     }
01040 }
01041 
01042 VOID
01043 CleanupPendingIrp(PAFD_FCB FCB, PIRP Irp, PIO_STACK_LOCATION IrpSp, PAFD_ACTIVE_POLL Poll)
01044 {
01045     PAFD_RECV_INFO RecvReq;
01046     PAFD_SEND_INFO SendReq;
01047     PAFD_POLL_INFO PollReq;
01048 
01049     if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_RECV ||
01050         IrpSp->MajorFunction == IRP_MJ_READ)
01051     {
01052         RecvReq = GetLockedData(Irp, IrpSp);
01053         UnlockBuffers(RecvReq->BufferArray, RecvReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp));
01054     }
01055     else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SEND ||
01056              IrpSp->MajorFunction == IRP_MJ_WRITE)
01057     {
01058         SendReq = GetLockedData(Irp, IrpSp);
01059         UnlockBuffers(SendReq->BufferArray, SendReq->BufferCount, CheckUnlockExtraBuffers(FCB, IrpSp));
01060     }
01061     else if (IrpSp->Parameters.DeviceIoControl.IoControlCode == IOCTL_AFD_SELECT)
01062     {
01063         PollReq = Irp->AssociatedIrp.SystemBuffer;
01064         ZeroEvents(PollReq->Handles, PollReq->HandleCount);
01065         SignalSocket(Poll, NULL, PollReq, STATUS_CANCELLED);
01066     }
01067 }
01068 
01069 VOID NTAPI
01070 AfdCancelHandler(PDEVICE_OBJECT DeviceObject,
01071                  PIRP Irp)
01072 {
01073     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
01074     PFILE_OBJECT FileObject = IrpSp->FileObject;
01075     PAFD_FCB FCB = FileObject->FsContext;
01076     ULONG Function, IoctlCode;
01077     PIRP CurrentIrp;
01078     PLIST_ENTRY CurrentEntry;
01079     PAFD_DEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
01080     KIRQL OldIrql;
01081     PAFD_ACTIVE_POLL Poll;
01082 
01083     IoReleaseCancelSpinLock(Irp->CancelIrql);
01084 
01085     if (!SocketAcquireStateLock(FCB))
01086         return;
01087 
01088     switch (IrpSp->MajorFunction)
01089     {
01090         case IRP_MJ_DEVICE_CONTROL:
01091             IoctlCode = IrpSp->Parameters.DeviceIoControl.IoControlCode;
01092             break;
01093 
01094         case IRP_MJ_READ:
01095             IoctlCode = IOCTL_AFD_RECV;
01096             break;
01097 
01098         case IRP_MJ_WRITE:
01099             IoctlCode = IOCTL_AFD_SEND;
01100             break;
01101 
01102         default:
01103             ASSERT(FALSE);
01104             SocketStateUnlock(FCB);
01105             return;
01106     }
01107 
01108     switch (IoctlCode)
01109     {
01110         case IOCTL_AFD_RECV:
01111         case IOCTL_AFD_RECV_DATAGRAM:
01112             Function = FUNCTION_RECV;
01113             break;
01114 
01115         case IOCTL_AFD_SEND:
01116         case IOCTL_AFD_SEND_DATAGRAM:
01117             Function = FUNCTION_SEND;
01118             break;
01119 
01120         case IOCTL_AFD_CONNECT:
01121             Function = FUNCTION_CONNECT;
01122             break;
01123 
01124         case IOCTL_AFD_WAIT_FOR_LISTEN:
01125             Function = FUNCTION_PREACCEPT;
01126             break;
01127 
01128         case IOCTL_AFD_SELECT:
01129             KeAcquireSpinLock(&DeviceExt->Lock, &OldIrql);
01130 
01131             CurrentEntry = DeviceExt->Polls.Flink;
01132             while (CurrentEntry != &DeviceExt->Polls)
01133             {
01134                 Poll = CONTAINING_RECORD(CurrentEntry, AFD_ACTIVE_POLL, ListEntry);
01135 
01136                 if (Irp == Poll->Irp)
01137                 {
01138                     CleanupPendingIrp(FCB, Irp, IrpSp, Poll);
01139                     KeReleaseSpinLock(&DeviceExt->Lock, OldIrql);
01140                     SocketStateUnlock(FCB);
01141                     return;
01142                 }
01143                 else
01144                 {
01145                     CurrentEntry = CurrentEntry->Flink;
01146                 }
01147             }
01148 
01149             KeReleaseSpinLock(&DeviceExt->Lock, OldIrql);
01150 
01151             SocketStateUnlock(FCB);
01152 
01153             DbgPrint("WARNING!!! IRP cancellation race could lead to a process hang! (IOCTL_AFD_SELECT)\n");
01154             return;
01155 
01156         case IOCTL_AFD_DISCONNECT:
01157             Function = FUNCTION_DISCONNECT;
01158             break;
01159 
01160         default:
01161             ASSERT(FALSE);
01162             UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
01163             return;
01164     }
01165 
01166     CurrentEntry = FCB->PendingIrpList[Function].Flink;
01167     while (CurrentEntry != &FCB->PendingIrpList[Function])
01168     {
01169         CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry);
01170 
01171         if (CurrentIrp == Irp)
01172         {
01173             RemoveEntryList(CurrentEntry);
01174             CleanupPendingIrp(FCB, Irp, IrpSp, NULL);
01175             UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
01176             return;
01177         }
01178         else
01179         {
01180             CurrentEntry = CurrentEntry->Flink;
01181         }
01182     }
01183 
01184     SocketStateUnlock(FCB);
01185 
01186     DbgPrint("WARNING!!! IRP cancellation race could lead to a process hang! (Function: %d)\n", Function);
01187 }
01188 
01189 static VOID NTAPI
01190 AfdUnload(PDRIVER_OBJECT DriverObject)
01191 {
01192 }
01193 
01194 NTSTATUS NTAPI
01195 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
01196 {
01197     PDEVICE_OBJECT DeviceObject;
01198     UNICODE_STRING wstrDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Afd");
01199     PAFD_DEVICE_EXTENSION DeviceExt;
01200     NTSTATUS Status;
01201 
01202     /* register driver routines */
01203     DriverObject->MajorFunction[IRP_MJ_CLOSE] = AfdDispatch;
01204     DriverObject->MajorFunction[IRP_MJ_CREATE] = AfdDispatch;
01205     DriverObject->MajorFunction[IRP_MJ_CLEANUP] = AfdDispatch;
01206     DriverObject->MajorFunction[IRP_MJ_WRITE] = AfdDispatch;
01207     DriverObject->MajorFunction[IRP_MJ_READ] = AfdDispatch;
01208     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = AfdDispatch;
01209     DriverObject->DriverUnload = AfdUnload;
01210 
01211     Status = IoCreateDevice(DriverObject,
01212                             sizeof(AFD_DEVICE_EXTENSION),
01213                             &wstrDeviceName,
01214                             FILE_DEVICE_NAMED_PIPE,
01215                             0,
01216                             FALSE,
01217                             &DeviceObject);
01218 
01219     /* failure */
01220     if (!NT_SUCCESS(Status))
01221     {
01222         return Status;
01223     }
01224 
01225     DeviceExt = DeviceObject->DeviceExtension;
01226     KeInitializeSpinLock( &DeviceExt->Lock );
01227     InitializeListHead( &DeviceExt->Polls );
01228 
01229     AFD_DbgPrint(MID_TRACE,("Device created: object %x ext %x\n",
01230                             DeviceObject, DeviceExt));
01231 
01232     return Status;
01233 }
01234 
01235 /* EOF */

Generated on Mon May 28 2012 04:16:48 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.