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

dispatch.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS TCP/IP protocol driver
00004  * FILE:        tcpip/dispatch.h
00005  * PURPOSE:     TDI dispatch routines
00006  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
00007  * REVISIONS:
00008  *   CSH 01/08-2000 Created
00009  * TODO:        Validate device object in all dispatch routines
00010  */
00011 
00012 #include "precomp.h"
00013 
00014 NTSTATUS IRPFinish( PIRP Irp, NTSTATUS Status ) {
00015     KIRQL OldIrql;
00016 
00017     Irp->IoStatus.Status = Status;
00018 
00019     if( Status == STATUS_PENDING )
00020     IoMarkIrpPending( Irp );
00021     else {
00022         IoAcquireCancelSpinLock(&OldIrql);
00023     (void)IoSetCancelRoutine( Irp, NULL );
00024         IoReleaseCancelSpinLock(OldIrql);
00025 
00026     IoCompleteRequest( Irp, IO_NETWORK_INCREMENT );
00027     }
00028 
00029     return Status;
00030 }
00031 
00032 NTSTATUS DispPrepareIrpForCancel(
00033     PTRANSPORT_CONTEXT Context,
00034     PIRP Irp,
00035     PDRIVER_CANCEL CancelRoutine)
00036 /*
00037  * FUNCTION: Prepare an IRP for cancellation
00038  * ARGUMENTS:
00039  *     Context       = Pointer to context information
00040  *     Irp           = Pointer to an I/O request packet
00041  *     CancelRoutine = Routine to be called when I/O request is cancelled
00042  * RETURNS:
00043  *     Status of operation
00044  */
00045 {
00046     KIRQL OldIrql;
00047     PIO_STACK_LOCATION IrpSp;
00048     PTRANSPORT_CONTEXT TransContext;
00049 
00050     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
00051 
00052     IrpSp       = IoGetCurrentIrpStackLocation(Irp);
00053     TransContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
00054 
00055     IoAcquireCancelSpinLock(&OldIrql);
00056 
00057     if (!Irp->Cancel && !TransContext->CancelIrps) {
00058         (void)IoSetCancelRoutine(Irp, CancelRoutine);
00059         IoReleaseCancelSpinLock(OldIrql);
00060 
00061         TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP at 0x%X can now be cancelled).\n", Irp));
00062 
00063         return STATUS_SUCCESS;
00064     }
00065 
00066     /* IRP has already been cancelled */
00067 
00068     IoReleaseCancelSpinLock(OldIrql);
00069 
00070     Irp->IoStatus.Status      = STATUS_CANCELLED;
00071     Irp->IoStatus.Information = 0;
00072 
00073     TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP was already cancelled).\n"));
00074 
00075     return Irp->IoStatus.Status;
00076 }
00077 
00078 VOID DispDataRequestComplete(
00079     PVOID Context,
00080     NTSTATUS Status,
00081     ULONG Count)
00082 /*
00083  * FUNCTION: Completes a send/receive IRP
00084  * ARGUMENTS:
00085  *     Context = Pointer to context information (IRP)
00086  *     Status  = Status of the request
00087  *     Count   = Number of bytes sent or received
00088  */
00089 {
00090     PIRP Irp = Context;
00091 
00092     TI_DbgPrint(DEBUG_IRP, ("Called for irp %x (%x, %d).\n",
00093                 Irp, Status, Count));
00094 
00095     Irp->IoStatus.Status      = Status;
00096     Irp->IoStatus.Information = Count;
00097 
00098     TI_DbgPrint(MID_TRACE, ("Irp->IoStatus.Status = %x\n",
00099                 Irp->IoStatus.Status));
00100     TI_DbgPrint(MID_TRACE, ("Irp->IoStatus.Information = %d\n",
00101                 Irp->IoStatus.Information));
00102     TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
00103 
00104     IRPFinish(Irp, Status);
00105 
00106     TI_DbgPrint(DEBUG_IRP, ("Done Completing IRP\n"));
00107 }
00108 
00109 VOID NTAPI DispCancelRequest(
00110     PDEVICE_OBJECT Device,
00111     PIRP Irp)
00112 /*
00113  * FUNCTION: Cancels an IRP
00114  * ARGUMENTS:
00115  *     Device = Pointer to device object
00116  *     Irp    = Pointer to an I/O request packet
00117  */
00118 {
00119     PIO_STACK_LOCATION IrpSp;
00120     PTRANSPORT_CONTEXT TranContext;
00121     PFILE_OBJECT FileObject;
00122     UCHAR MinorFunction;
00123     PCONNECTION_ENDPOINT Connection;
00124     BOOLEAN DequeuedIrp = TRUE;
00125 
00126     IoReleaseCancelSpinLock(Irp->CancelIrql);
00127 
00128     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
00129 
00130     IrpSp         = IoGetCurrentIrpStackLocation(Irp);
00131     FileObject    = IrpSp->FileObject;
00132     TranContext   = (PTRANSPORT_CONTEXT)FileObject->FsContext;
00133     MinorFunction = IrpSp->MinorFunction;
00134 
00135     TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X)  MinorFunction (0x%X)  IrpSp (0x%X).\n", Irp, MinorFunction, IrpSp));
00136 
00137     Irp->IoStatus.Status = STATUS_CANCELLED;
00138     Irp->IoStatus.Information = 0;
00139 
00140 #if DBG
00141     if (!Irp->Cancel)
00142         TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n"));
00143 #endif
00144 
00145     /* Try canceling the request */
00146     switch(MinorFunction) {
00147     case TDI_SEND:
00148     case TDI_RECEIVE:
00149     DequeuedIrp = TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
00150         break;
00151 
00152     case TDI_SEND_DATAGRAM:
00153         if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
00154             TI_DbgPrint(MIN_TRACE, ("TDI_SEND_DATAGRAM, but no address file.\n"));
00155             break;
00156         }
00157 
00158         DequeuedIrp = DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
00159         break;
00160 
00161     case TDI_RECEIVE_DATAGRAM:
00162         if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
00163             TI_DbgPrint(MIN_TRACE, ("TDI_RECEIVE_DATAGRAM, but no address file.\n"));
00164             break;
00165         }
00166 
00167         DequeuedIrp = DGRemoveIRP(TranContext->Handle.AddressHandle, Irp);
00168         break;
00169 
00170     case TDI_CONNECT:
00171         DequeuedIrp = TCPRemoveIRP(TranContext->Handle.ConnectionContext, Irp);
00172         break;
00173             
00174     case TDI_DISCONNECT:
00175         Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
00176 
00177         DequeuedIrp = TCPRemoveIRP(TranContext->Handle.ConnectionContext, Irp);
00178         if (DequeuedIrp)
00179         {
00180             if (KeCancelTimer(&Connection->DisconnectTimer))
00181             {
00182                 DereferenceObject(Connection);
00183             }
00184         }
00185         break;
00186 
00187     default:
00188         TI_DbgPrint(MIN_TRACE, ("Unknown IRP. MinorFunction (0x%X).\n", MinorFunction));
00189         ASSERT(FALSE);
00190         break;
00191     }
00192 
00193     if (DequeuedIrp)
00194        IRPFinish(Irp, STATUS_CANCELLED);
00195 
00196     TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
00197 }
00198 
00199 
00200 VOID NTAPI DispCancelListenRequest(
00201     PDEVICE_OBJECT Device,
00202     PIRP Irp)
00203 /*
00204  * FUNCTION: Cancels a listen IRP
00205  * ARGUMENTS:
00206  *     Device = Pointer to device object
00207  *     Irp    = Pointer to an I/O request packet
00208  */
00209 {
00210     PIO_STACK_LOCATION IrpSp;
00211     PTRANSPORT_CONTEXT TranContext;
00212     PFILE_OBJECT FileObject;
00213     PCONNECTION_ENDPOINT Connection;
00214 
00215     IoReleaseCancelSpinLock(Irp->CancelIrql);
00216 
00217     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
00218 
00219     IrpSp         = IoGetCurrentIrpStackLocation(Irp);
00220     FileObject    = IrpSp->FileObject;
00221     TranContext   = (PTRANSPORT_CONTEXT)FileObject->FsContext;
00222     ASSERT( TDI_LISTEN == IrpSp->MinorFunction);
00223 
00224     TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X).\n", Irp));
00225 
00226 #if DBG
00227     if (!Irp->Cancel)
00228         TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n"));
00229 #endif
00230 
00231     /* Try canceling the request */
00232     Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
00233 
00234     if (TCPAbortListenForSocket(Connection->AddressFile->Listener,
00235                                 Connection))
00236     {
00237         Irp->IoStatus.Information = 0;
00238         IRPFinish(Irp, STATUS_CANCELLED);
00239     }
00240 
00241     TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
00242 }
00243 
00244 
00245 NTSTATUS DispTdiAccept(
00246   PIRP Irp)
00247 /*
00248  * FUNCTION: TDI_ACCEPT handler
00249  * ARGUMENTS:
00250  *     Irp = Pointer to an I/O request packet
00251  * RETURNS:
00252  *     Status of operation
00253  */
00254 {
00255   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
00256 
00257   return STATUS_NOT_IMPLEMENTED;
00258 }
00259 
00260 
00261 NTSTATUS DispTdiAssociateAddress(
00262     PIRP Irp)
00263 /*
00264  * FUNCTION: TDI_ASSOCIATE_ADDRESS handler
00265  * ARGUMENTS:
00266  *     Irp = Pointer to an I/O request packet
00267  * RETURNS:
00268  *     Status of operation
00269  */
00270 {
00271   PTDI_REQUEST_KERNEL_ASSOCIATE Parameters;
00272   PTRANSPORT_CONTEXT TranContext;
00273   PIO_STACK_LOCATION IrpSp;
00274   PCONNECTION_ENDPOINT Connection, LastConnection;
00275   PFILE_OBJECT FileObject;
00276   PADDRESS_FILE AddrFile = NULL;
00277   NTSTATUS Status;
00278   KIRQL OldIrql;
00279 
00280   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
00281 
00282   IrpSp = IoGetCurrentIrpStackLocation(Irp);
00283 
00284   /* Get associated connection endpoint file object. Quit if none exists */
00285 
00286   TranContext = IrpSp->FileObject->FsContext;
00287   if (!TranContext) {
00288     TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
00289     return STATUS_INVALID_PARAMETER;
00290   }
00291 
00292   Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
00293   if (!Connection) {
00294     TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
00295     return STATUS_INVALID_PARAMETER;
00296   }
00297 
00298   Parameters = (PTDI_REQUEST_KERNEL_ASSOCIATE)&IrpSp->Parameters;
00299 
00300   Status = ObReferenceObjectByHandle(
00301     Parameters->AddressHandle,
00302     0,
00303     IoFileObjectType,
00304     KernelMode,
00305     (PVOID*)&FileObject,
00306     NULL);
00307   if (!NT_SUCCESS(Status)) {
00308     TI_DbgPrint(MID_TRACE, ("Bad address file object handle (0x%X): %x.\n",
00309       Parameters->AddressHandle, Status));
00310     return STATUS_INVALID_PARAMETER;
00311   }
00312 
00313   LockObject(Connection, &OldIrql);
00314 
00315   if (Connection->AddressFile) {
00316     ObDereferenceObject(FileObject);
00317     UnlockObject(Connection, OldIrql);
00318     TI_DbgPrint(MID_TRACE, ("An address file is already asscociated.\n"));
00319     return STATUS_INVALID_PARAMETER;
00320   }
00321 
00322   if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
00323     ObDereferenceObject(FileObject);
00324     UnlockObject(Connection, OldIrql);
00325     TI_DbgPrint(MID_TRACE, ("Bad address file object. Magic (0x%X).\n",
00326       FileObject->FsContext2));
00327     return STATUS_INVALID_PARAMETER;
00328   }
00329 
00330   /* Get associated address file object. Quit if none exists */
00331 
00332   TranContext = FileObject->FsContext;
00333   if (!TranContext) {
00334     ObDereferenceObject(FileObject);
00335     UnlockObject(Connection, OldIrql);
00336     TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
00337     return STATUS_INVALID_PARAMETER;
00338   }
00339 
00340   AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
00341   if (!AddrFile) {
00342       UnlockObject(Connection, OldIrql);
00343       ObDereferenceObject(FileObject);
00344       TI_DbgPrint(MID_TRACE, ("No address file object.\n"));
00345       return STATUS_INVALID_PARAMETER;
00346   }
00347 
00348   LockObjectAtDpcLevel(AddrFile);
00349 
00350   ReferenceObject(AddrFile);
00351   Connection->AddressFile = AddrFile;
00352 
00353   /* Add connection endpoint to the address file */
00354   ReferenceObject(Connection);
00355   if (AddrFile->Connection == NULL)
00356       AddrFile->Connection = Connection;
00357   else
00358   {
00359       LastConnection = AddrFile->Connection;
00360       while (LastConnection->Next != NULL)
00361          LastConnection = LastConnection->Next;
00362       LastConnection->Next = Connection;
00363   }
00364 
00365   ObDereferenceObject(FileObject);
00366 
00367   UnlockObjectFromDpcLevel(AddrFile);
00368   UnlockObject(Connection, OldIrql);
00369 
00370   return STATUS_SUCCESS;
00371 }
00372 
00373 
00374 NTSTATUS DispTdiConnect(
00375   PIRP Irp)
00376 /*
00377  * FUNCTION: TDI_CONNECT handler
00378  * ARGUMENTS:
00379  *     Irp = Pointer to an I/O request packet
00380  * RETURNS:
00381  *     Status of operation
00382  */
00383 {
00384   PCONNECTION_ENDPOINT Connection;
00385   PTDI_REQUEST_KERNEL Parameters;
00386   PTRANSPORT_CONTEXT TranContext;
00387   PIO_STACK_LOCATION IrpSp;
00388   NTSTATUS Status;
00389 
00390   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
00391 
00392   IrpSp = IoGetCurrentIrpStackLocation(Irp);
00393 
00394   /* Get associated connection endpoint file object. Quit if none exists */
00395 
00396   TranContext = IrpSp->FileObject->FsContext;
00397   if (!TranContext) {
00398     TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
00399     Status = STATUS_INVALID_PARAMETER;
00400     goto done;
00401   }
00402 
00403   Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
00404   if (!Connection) {
00405     TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
00406     Status = STATUS_INVALID_PARAMETER;
00407     goto done;
00408   }
00409 
00410   Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
00411 
00412   Status = DispPrepareIrpForCancel(TranContext->Handle.ConnectionContext,
00413                                    Irp,
00414                                    DispCancelRequest);
00415 
00416   if (NT_SUCCESS(Status)) {
00417       Status = TCPConnect(
00418           TranContext->Handle.ConnectionContext,
00419           Parameters->RequestConnectionInformation,
00420           Parameters->ReturnConnectionInformation,
00421           DispDataRequestComplete,
00422           Irp );
00423   }
00424 
00425 done:
00426   if (Status != STATUS_PENDING) {
00427       DispDataRequestComplete(Irp, Status, 0);
00428   } else
00429       IoMarkIrpPending(Irp);
00430 
00431   TI_DbgPrint(MAX_TRACE, ("TCP Connect returned %08x\n", Status));
00432 
00433   return Status;
00434 }
00435 
00436 
00437 NTSTATUS DispTdiDisassociateAddress(
00438   PIRP Irp)
00439 /*
00440  * FUNCTION: TDI_DISASSOCIATE_ADDRESS handler
00441  * ARGUMENTS:
00442  *     Irp = Pointer to an I/O request packet
00443  * RETURNS:
00444  *     Status of operation
00445  */
00446 {
00447   PCONNECTION_ENDPOINT Connection;
00448   PTRANSPORT_CONTEXT TranContext;
00449   PIO_STACK_LOCATION IrpSp;
00450 
00451   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
00452 
00453   IrpSp = IoGetCurrentIrpStackLocation(Irp);
00454 
00455   /* Get associated connection endpoint file object. Quit if none exists */
00456 
00457   TranContext = IrpSp->FileObject->FsContext;
00458   if (!TranContext) {
00459     TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
00460     return STATUS_INVALID_PARAMETER;
00461   }
00462 
00463   Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
00464   if (!Connection) {
00465     TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
00466     return STATUS_INVALID_PARAMETER;
00467   }
00468 
00469   /* NO-OP because we need the address to deallocate the port when the connection closes */
00470 
00471   return STATUS_SUCCESS;
00472 }
00473 
00474 
00475 NTSTATUS DispTdiDisconnect(
00476   PIRP Irp)
00477 /*
00478  * FUNCTION: TDI_DISCONNECT handler
00479  * ARGUMENTS:
00480  *     Irp = Pointer to an I/O request packet
00481  * RETURNS:
00482  *     Status of operation
00483  */
00484 {
00485   NTSTATUS Status;
00486   PTDI_REQUEST_KERNEL_DISCONNECT DisReq;
00487   PCONNECTION_ENDPOINT Connection;
00488   PTRANSPORT_CONTEXT TranContext;
00489   PIO_STACK_LOCATION IrpSp;
00490 
00491   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
00492 
00493   IrpSp = IoGetCurrentIrpStackLocation(Irp);
00494   DisReq = (PTDI_REQUEST_KERNEL_DISCONNECT)&IrpSp->Parameters;
00495 
00496   /* Get associated connection endpoint file object. Quit if none exists */
00497 
00498   TranContext = IrpSp->FileObject->FsContext;
00499   if (!TranContext) {
00500     TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
00501     Status = STATUS_INVALID_PARAMETER;
00502     goto done;
00503   }
00504 
00505   Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
00506   if (!Connection) {
00507     TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
00508     Status = STATUS_INVALID_PARAMETER;
00509     goto done;
00510   }
00511     
00512   Status = DispPrepareIrpForCancel
00513     (TranContext->Handle.ConnectionContext,
00514      Irp,
00515      (PDRIVER_CANCEL)DispCancelRequest);
00516 
00517   if (NT_SUCCESS(Status))
00518   {
00519       Status = TCPDisconnect(TranContext->Handle.ConnectionContext,
00520                              DisReq->RequestFlags,
00521                              DisReq->RequestSpecific,
00522                              DisReq->RequestConnectionInformation,
00523                              DisReq->ReturnConnectionInformation,
00524                              DispDataRequestComplete,
00525                              Irp);
00526   }
00527 
00528 done:
00529    if (Status != STATUS_PENDING) {
00530        DispDataRequestComplete(Irp, Status, 0);
00531    } else
00532        IoMarkIrpPending(Irp);
00533 
00534   TI_DbgPrint(MAX_TRACE, ("TCP Disconnect returned %08x\n", Status));
00535 
00536   return Status;
00537 }
00538 
00539 
00540 NTSTATUS DispTdiListen(
00541   PIRP Irp)
00542 /*
00543  * FUNCTION: TDI_LISTEN handler
00544  * ARGUMENTS:
00545  *     Irp = Pointer to an I/O request packet
00546  * RETURNS:
00547  *     Status of operation
00548  */
00549 {
00550   PCONNECTION_ENDPOINT Connection;
00551   PTDI_REQUEST_KERNEL Parameters;
00552   PTRANSPORT_CONTEXT TranContext;
00553   PIO_STACK_LOCATION IrpSp;
00554   NTSTATUS Status = STATUS_SUCCESS;
00555   KIRQL OldIrql;
00556 
00557   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
00558 
00559   IrpSp = IoGetCurrentIrpStackLocation(Irp);
00560 
00561   /* Get associated connection endpoint file object. Quit if none exists */
00562 
00563   TranContext = IrpSp->FileObject->FsContext;
00564   if (TranContext == NULL)
00565     {
00566       TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
00567       Status = STATUS_INVALID_PARAMETER;
00568       goto done;
00569     }
00570 
00571   Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
00572   if (Connection == NULL)
00573     {
00574       TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
00575       Status = STATUS_INVALID_PARAMETER;
00576       goto done;
00577     }
00578 
00579   Parameters = (PTDI_REQUEST_KERNEL)&IrpSp->Parameters;
00580 
00581   Status = DispPrepareIrpForCancel
00582       (TranContext->Handle.ConnectionContext,
00583        Irp,
00584        (PDRIVER_CANCEL)DispCancelListenRequest);
00585 
00586   LockObject(Connection, &OldIrql);
00587 
00588   if (Connection->AddressFile == NULL)
00589   {
00590      TI_DbgPrint(MID_TRACE, ("No associated address file\n"));
00591      UnlockObject(Connection, OldIrql);
00592      Status = STATUS_INVALID_PARAMETER;
00593      goto done;
00594   }
00595 
00596   LockObjectAtDpcLevel(Connection->AddressFile);
00597 
00598   /* Listening will require us to create a listening socket and store it in
00599    * the address file.  It will be signalled, and attempt to complete an irp
00600    * when a new connection arrives. */
00601   /* The important thing to note here is that the irp we'll complete belongs
00602    * to the socket to be accepted onto, not the listener */
00603   if( NT_SUCCESS(Status) && !Connection->AddressFile->Listener ) {
00604       Connection->AddressFile->Listener =
00605       TCPAllocateConnectionEndpoint( NULL );
00606 
00607       if( !Connection->AddressFile->Listener )
00608       Status = STATUS_NO_MEMORY;
00609 
00610       if( NT_SUCCESS(Status) ) {
00611           ReferenceObject(Connection->AddressFile);
00612       Connection->AddressFile->Listener->AddressFile =
00613           Connection->AddressFile;
00614 
00615       Status = TCPSocket( Connection->AddressFile->Listener,
00616                   Connection->AddressFile->Family,
00617                   SOCK_STREAM,
00618                   Connection->AddressFile->Protocol );
00619       }
00620 
00621       if( NT_SUCCESS(Status) )
00622       Status = TCPListen( Connection->AddressFile->Listener, 1024 );
00623       /* BACKLOG */
00624   }
00625 
00626   if( NT_SUCCESS(Status) ) {
00627       Status = TCPAccept
00628       ( (PTDI_REQUEST)Parameters,
00629         Connection->AddressFile->Listener,
00630         Connection,
00631         DispDataRequestComplete,
00632         Irp );
00633   }
00634 
00635   UnlockObjectFromDpcLevel(Connection->AddressFile);
00636   UnlockObject(Connection, OldIrql);
00637 
00638 done:
00639   if (Status != STATUS_PENDING) {
00640       DispDataRequestComplete(Irp, Status, 0);
00641   } else
00642       IoMarkIrpPending(Irp);
00643 
00644   TI_DbgPrint(MID_TRACE,("Leaving %x\n", Status));
00645 
00646   return Status;
00647 }
00648 
00649 
00650 NTSTATUS DispTdiQueryInformation(
00651   PDEVICE_OBJECT DeviceObject,
00652   PIRP Irp)
00653 /*
00654  * FUNCTION: TDI_QUERY_INFORMATION handler
00655  * ARGUMENTS:
00656  *     DeviceObject = Pointer to device object structure
00657  *     Irp          = Pointer to an I/O request packet
00658  * RETURNS:
00659  *     Status of operation
00660  */
00661 {
00662   PTDI_REQUEST_KERNEL_QUERY_INFORMATION Parameters;
00663   PTRANSPORT_CONTEXT TranContext;
00664   PIO_STACK_LOCATION IrpSp;
00665 
00666   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
00667 
00668   IrpSp = IoGetCurrentIrpStackLocation(Irp);
00669   Parameters = (PTDI_REQUEST_KERNEL_QUERY_INFORMATION)&IrpSp->Parameters;
00670 
00671   TranContext = IrpSp->FileObject->FsContext;
00672   if (!TranContext) {
00673     TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
00674     return STATUS_INVALID_PARAMETER;
00675   }
00676 
00677   switch (Parameters->QueryType)
00678   {
00679     case TDI_QUERY_ADDRESS_INFO:
00680       {
00681         PTDI_ADDRESS_INFO AddressInfo;
00682         PADDRESS_FILE AddrFile;
00683         PTA_IP_ADDRESS Address;
00684         PCONNECTION_ENDPOINT Endpoint = NULL;
00685 
00686 
00687         if (MmGetMdlByteCount(Irp->MdlAddress) <
00688             (FIELD_OFFSET(TDI_ADDRESS_INFO, Address.Address[0].Address) +
00689              sizeof(TDI_ADDRESS_IP))) {
00690           TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
00691           return STATUS_BUFFER_TOO_SMALL;
00692         }
00693 
00694         AddressInfo = (PTDI_ADDRESS_INFO)MmGetSystemAddressForMdl(Irp->MdlAddress);
00695         Address = (PTA_IP_ADDRESS)&AddressInfo->Address;
00696 
00697         switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
00698           case TDI_TRANSPORT_ADDRESS_FILE:
00699             AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
00700 
00701             Address->TAAddressCount = 1;
00702             Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
00703             Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
00704             Address->Address[0].Address[0].sin_port = AddrFile->Port;
00705             Address->Address[0].Address[0].in_addr = AddrFile->Address.Address.IPv4Address;
00706             RtlZeroMemory(
00707                 &Address->Address[0].Address[0].sin_zero,
00708                 sizeof(Address->Address[0].Address[0].sin_zero));
00709             return STATUS_SUCCESS;
00710 
00711           case TDI_CONNECTION_FILE:
00712             Endpoint =
00713                 (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
00714                 
00715             Address->TAAddressCount = 1;
00716             Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
00717             Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
00718             Address->Address[0].Address[0].sin_port = Endpoint->AddressFile->Port;
00719             Address->Address[0].Address[0].in_addr = Endpoint->AddressFile->Address.Address.IPv4Address;
00720             RtlZeroMemory(
00721                 &Address->Address[0].Address[0].sin_zero,
00722                 sizeof(Address->Address[0].Address[0].sin_zero));
00723             return STATUS_SUCCESS;
00724 
00725           default:
00726             TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
00727             return STATUS_INVALID_PARAMETER;
00728         }
00729       }
00730 
00731     case TDI_QUERY_CONNECTION_INFO:
00732       {
00733         PTDI_CONNECTION_INFO ConnectionInfo;
00734         //PCONNECTION_ENDPOINT Endpoint;
00735 
00736         if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(*ConnectionInfo)) {
00737           TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
00738           return STATUS_BUFFER_TOO_SMALL;
00739         }
00740 
00741         ConnectionInfo = (PTDI_CONNECTION_INFO)
00742           MmGetSystemAddressForMdl(Irp->MdlAddress);
00743 
00744         switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
00745           case TDI_CONNECTION_FILE:
00746             //Endpoint = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
00747             RtlZeroMemory(ConnectionInfo, sizeof(*ConnectionInfo));
00748             return STATUS_SUCCESS;
00749 
00750           default:
00751             TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
00752             return STATUS_INVALID_PARAMETER;
00753         }
00754       }
00755 
00756       case TDI_QUERY_MAX_DATAGRAM_INFO:
00757       {
00758           PTDI_MAX_DATAGRAM_INFO MaxDatagramInfo;
00759           
00760           if (MmGetMdlByteCount(Irp->MdlAddress) < sizeof(*MaxDatagramInfo)) {
00761               TI_DbgPrint(MID_TRACE, ("MDL buffer too small.\n"));
00762               return STATUS_BUFFER_TOO_SMALL;
00763           }
00764           
00765           MaxDatagramInfo = (PTDI_MAX_DATAGRAM_INFO)
00766             MmGetSystemAddressForMdl(Irp->MdlAddress);
00767 
00768           MaxDatagramInfo->MaxDatagramSize = 0xFFFF;
00769 
00770           return STATUS_SUCCESS;
00771      }
00772   }
00773 
00774   return STATUS_NOT_IMPLEMENTED;
00775 }
00776 
00777 
00778 NTSTATUS DispTdiReceive(
00779   PIRP Irp)
00780 /*
00781  * FUNCTION: TDI_RECEIVE handler
00782  * ARGUMENTS:
00783  *     Irp = Pointer to an I/O request packet
00784  * RETURNS:
00785  *     Status of operation
00786  */
00787 {
00788   PIO_STACK_LOCATION IrpSp;
00789   PTDI_REQUEST_KERNEL_RECEIVE ReceiveInfo;
00790   PTRANSPORT_CONTEXT TranContext;
00791   NTSTATUS Status;
00792   ULONG BytesReceived = 0;
00793 
00794   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
00795 
00796   IrpSp = IoGetCurrentIrpStackLocation(Irp);
00797   ReceiveInfo = (PTDI_REQUEST_KERNEL_RECEIVE)&(IrpSp->Parameters);
00798 
00799   TranContext = IrpSp->FileObject->FsContext;
00800   if (TranContext == NULL)
00801     {
00802       TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
00803       Status = STATUS_INVALID_PARAMETER;
00804       goto done;
00805     }
00806 
00807   if (TranContext->Handle.ConnectionContext == NULL)
00808     {
00809       TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
00810       Status = STATUS_INVALID_PARAMETER;
00811       goto done;
00812     }
00813 
00814   /* Initialize a receive request */
00815   Status = DispPrepareIrpForCancel
00816       (TranContext->Handle.ConnectionContext,
00817        Irp,
00818        (PDRIVER_CANCEL)DispCancelRequest);
00819 
00820   TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress));
00821   if (NT_SUCCESS(Status))
00822     {
00823       Status = TCPReceiveData(
00824       TranContext->Handle.ConnectionContext,
00825       (PNDIS_BUFFER)Irp->MdlAddress,
00826       ReceiveInfo->ReceiveLength,
00827       &BytesReceived,
00828       ReceiveInfo->ReceiveFlags,
00829       DispDataRequestComplete,
00830       Irp);
00831     }
00832 
00833 done:
00834   if (Status != STATUS_PENDING) {
00835       DispDataRequestComplete(Irp, Status, BytesReceived);
00836   } else
00837       IoMarkIrpPending(Irp);
00838 
00839   TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
00840 
00841   return Status;
00842 }
00843 
00844 
00845 NTSTATUS DispTdiReceiveDatagram(
00846     PIRP Irp)
00847 /*
00848  * FUNCTION: TDI_RECEIVE_DATAGRAM handler
00849  * ARGUMENTS:
00850  *     Irp = Pointer to an I/O request packet
00851  * RETURNS:
00852  *     Status of operation
00853  */
00854 {
00855   PIO_STACK_LOCATION IrpSp;
00856   PTDI_REQUEST_KERNEL_RECEIVEDG DgramInfo;
00857   PTRANSPORT_CONTEXT TranContext;
00858   TDI_REQUEST Request;
00859   NTSTATUS Status;
00860   ULONG BytesReceived = 0;
00861 
00862   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
00863 
00864   IrpSp     = IoGetCurrentIrpStackLocation(Irp);
00865   DgramInfo = (PTDI_REQUEST_KERNEL_RECEIVEDG)&(IrpSp->Parameters);
00866 
00867   TranContext = IrpSp->FileObject->FsContext;
00868   if (TranContext == NULL)
00869     {
00870       TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
00871       Status = STATUS_INVALID_PARAMETER;
00872       goto done;
00873     }
00874 
00875   /* Initialize a receive request */
00876   Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
00877   Request.RequestNotifyObject  = DispDataRequestComplete;
00878   Request.RequestContext       = Irp;
00879 
00880   Status = DispPrepareIrpForCancel(
00881     IrpSp->FileObject->FsContext,
00882     Irp,
00883     (PDRIVER_CANCEL)DispCancelRequest);
00884 
00885   if (NT_SUCCESS(Status))
00886     {
00887     PVOID DataBuffer;
00888     UINT BufferSize;
00889 
00890     NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress,
00891              &DataBuffer,
00892              &BufferSize );
00893 
00894       Status = DGReceiveDatagram(
00895       Request.Handle.AddressHandle,
00896       DgramInfo->ReceiveDatagramInformation,
00897       DataBuffer,
00898       DgramInfo->ReceiveLength,
00899       DgramInfo->ReceiveFlags,
00900       DgramInfo->ReturnDatagramInformation,
00901       &BytesReceived,
00902       (PDATAGRAM_COMPLETION_ROUTINE)DispDataRequestComplete,
00903       Irp,
00904           Irp);
00905     }
00906 
00907 done:
00908    if (Status != STATUS_PENDING) {
00909        DispDataRequestComplete(Irp, Status, BytesReceived);
00910    } else
00911        IoMarkIrpPending(Irp);
00912 
00913   TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
00914 
00915   return Status;
00916 }
00917 
00918 
00919 NTSTATUS DispTdiSend(
00920     PIRP Irp)
00921 /*
00922  * FUNCTION: TDI_SEND handler
00923  * ARGUMENTS:
00924  *     Irp = Pointer to an I/O request packet
00925  * RETURNS:
00926  *     Status of operation
00927  */
00928 {
00929   PIO_STACK_LOCATION IrpSp;
00930   PTDI_REQUEST_KERNEL_SEND SendInfo;
00931   PTRANSPORT_CONTEXT TranContext;
00932   NTSTATUS Status;
00933   ULONG BytesSent = 0;
00934 
00935   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
00936 
00937   IrpSp = IoGetCurrentIrpStackLocation(Irp);
00938   SendInfo = (PTDI_REQUEST_KERNEL_SEND)&(IrpSp->Parameters);
00939 
00940   TranContext = IrpSp->FileObject->FsContext;
00941   if (TranContext == NULL)
00942     {
00943       TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
00944       Status = STATUS_INVALID_PARAMETER;
00945       goto done;
00946     }
00947 
00948   if (TranContext->Handle.ConnectionContext == NULL)
00949     {
00950       TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
00951       Status = STATUS_INVALID_PARAMETER;
00952       goto done;
00953     }
00954 
00955   Status = DispPrepareIrpForCancel(
00956     IrpSp->FileObject->FsContext,
00957     Irp,
00958     (PDRIVER_CANCEL)DispCancelRequest);
00959 
00960   TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress));
00961   if (NT_SUCCESS(Status))
00962     {
00963     PVOID Data;
00964     UINT Len;
00965 
00966     NdisQueryBuffer( Irp->MdlAddress, &Data, &Len );
00967 
00968     TI_DbgPrint(MID_TRACE,("About to TCPSendData\n"));
00969     Status = TCPSendData(
00970         TranContext->Handle.ConnectionContext,
00971         Data,
00972         SendInfo->SendLength,
00973         &BytesSent,
00974         SendInfo->SendFlags,
00975         DispDataRequestComplete,
00976         Irp);
00977     }
00978 
00979 done:
00980    if (Status != STATUS_PENDING) {
00981        DispDataRequestComplete(Irp, Status, BytesSent);
00982    } else
00983        IoMarkIrpPending(Irp);
00984 
00985   TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
00986 
00987   return Status;
00988 }
00989 
00990 
00991 NTSTATUS DispTdiSendDatagram(
00992     PIRP Irp)
00993 /*
00994  * FUNCTION: TDI_SEND_DATAGRAM handler
00995  * ARGUMENTS:
00996  *     Irp = Pointer to an I/O request packet
00997  * RETURNS:
00998  *     Status of operation
00999  */
01000 {
01001     PIO_STACK_LOCATION IrpSp;
01002     TDI_REQUEST Request;
01003     PTDI_REQUEST_KERNEL_SENDDG DgramInfo;
01004     PTRANSPORT_CONTEXT TranContext;
01005     NTSTATUS Status;
01006 
01007     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
01008 
01009     IrpSp       = IoGetCurrentIrpStackLocation(Irp);
01010     DgramInfo   = (PTDI_REQUEST_KERNEL_SENDDG)&(IrpSp->Parameters);
01011 
01012     TranContext = IrpSp->FileObject->FsContext;
01013     if (TranContext == NULL)
01014     {
01015       TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
01016       Status = STATUS_INVALID_PARAMETER;
01017       goto done;
01018     }
01019 
01020     /* Initialize a send request */
01021     Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
01022     Request.RequestNotifyObject  = DispDataRequestComplete;
01023     Request.RequestContext       = Irp;
01024 
01025     Status = DispPrepareIrpForCancel(
01026         IrpSp->FileObject->FsContext,
01027         Irp,
01028         (PDRIVER_CANCEL)DispCancelRequest);
01029 
01030     if (NT_SUCCESS(Status)) {
01031     PVOID DataBuffer;
01032     UINT BufferSize;
01033 
01034     TI_DbgPrint(MID_TRACE,("About to query buffer %x\n", Irp->MdlAddress));
01035 
01036     NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress,
01037              &DataBuffer,
01038              &BufferSize );
01039 
01040         /* FIXME: DgramInfo->SendDatagramInformation->RemoteAddress
01041            must be of type PTDI_ADDRESS_IP */
01042     TI_DbgPrint(MID_TRACE,
01043             ("About to call send routine %x\n",
01044              (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)));
01045 
01046         if( (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send != NULL) )
01047         {
01048             ULONG DataUsed = 0;
01049             Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)(
01050                 Request.Handle.AddressHandle,
01051                 DgramInfo->SendDatagramInformation,
01052                 DataBuffer,
01053                 BufferSize,
01054                 &DataUsed);
01055             Irp->IoStatus.Information = DataUsed;
01056         }
01057         else {
01058             Status = STATUS_UNSUCCESSFUL;
01059             ASSERT(FALSE);
01060         }
01061     }
01062 
01063 done:
01064     if (Status != STATUS_PENDING) {
01065         DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information);
01066     } else
01067         IoMarkIrpPending(Irp);
01068 
01069     TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
01070 
01071     return Status;
01072 }
01073 
01074 
01075 NTSTATUS DispTdiSetEventHandler(PIRP Irp)
01076 /*
01077  * FUNCTION: TDI_SET_EVENT_HANDER handler
01078  * ARGUMENTS:
01079  *     Irp = Pointer to a I/O request packet
01080  * RETURNS:
01081  *     Status of operation
01082  */
01083 {
01084   PTDI_REQUEST_KERNEL_SET_EVENT Parameters;
01085   PTRANSPORT_CONTEXT TranContext;
01086   PIO_STACK_LOCATION IrpSp;
01087   PADDRESS_FILE AddrFile;
01088   NTSTATUS Status;
01089   KIRQL OldIrql;
01090 
01091   TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
01092 
01093   IrpSp = IoGetCurrentIrpStackLocation(Irp);
01094 
01095   /* Get associated address file object. Quit if none exists */
01096 
01097   TranContext = IrpSp->FileObject->FsContext;
01098   if (!TranContext) {
01099     TI_DbgPrint(MIN_TRACE, ("Bad transport context.\n"));
01100     return STATUS_INVALID_PARAMETER;
01101   }
01102 
01103   AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
01104   if (!AddrFile) {
01105     TI_DbgPrint(MIN_TRACE, ("No address file object.\n"));
01106     return STATUS_INVALID_PARAMETER;
01107   }
01108 
01109   Parameters = (PTDI_REQUEST_KERNEL_SET_EVENT)&IrpSp->Parameters;
01110   Status     = STATUS_SUCCESS;
01111 
01112   LockObject(AddrFile, &OldIrql);
01113 
01114   /* Set the event handler. if an event handler is associated with
01115      a specific event, it's flag (RegisteredXxxHandler) is TRUE.
01116      If an event handler is not used it's flag is FALSE */
01117   switch (Parameters->EventType) {
01118   case TDI_EVENT_CONNECT:
01119     if (!Parameters->EventHandler) {
01120       AddrFile->ConnectHandlerContext    = NULL;
01121       AddrFile->RegisteredConnectHandler = FALSE;
01122     } else {
01123       AddrFile->ConnectHandler =
01124         (PTDI_IND_CONNECT)Parameters->EventHandler;
01125       AddrFile->ConnectHandlerContext    = Parameters->EventContext;
01126       AddrFile->RegisteredConnectHandler = TRUE;
01127     }
01128     break;
01129 
01130   case TDI_EVENT_DISCONNECT:
01131     if (!Parameters->EventHandler) {
01132       AddrFile->DisconnectHandlerContext    = NULL;
01133       AddrFile->RegisteredDisconnectHandler = FALSE;
01134     } else {
01135       AddrFile->DisconnectHandler =
01136         (PTDI_IND_DISCONNECT)Parameters->EventHandler;
01137       AddrFile->DisconnectHandlerContext    = Parameters->EventContext;
01138       AddrFile->RegisteredDisconnectHandler = TRUE;
01139     }
01140     break;
01141 
01142     case TDI_EVENT_ERROR:
01143     if (Parameters->EventHandler == NULL) {
01144       AddrFile->ErrorHandlerContext    = NULL;
01145       AddrFile->RegisteredErrorHandler = FALSE;
01146     } else {
01147       AddrFile->ErrorHandler =
01148         (PTDI_IND_ERROR)Parameters->EventHandler;
01149       AddrFile->ErrorHandlerContext    = Parameters->EventContext;
01150       AddrFile->RegisteredErrorHandler = TRUE;
01151     }
01152     break;
01153 
01154   case TDI_EVENT_RECEIVE:
01155     if (Parameters->EventHandler == NULL) {
01156       AddrFile->ReceiveHandlerContext    = NULL;
01157       AddrFile->RegisteredReceiveHandler = FALSE;
01158     } else {
01159       AddrFile->ReceiveHandler =
01160         (PTDI_IND_RECEIVE)Parameters->EventHandler;
01161       AddrFile->ReceiveHandlerContext    = Parameters->EventContext;
01162       AddrFile->RegisteredReceiveHandler = TRUE;
01163     }
01164     break;
01165 
01166   case TDI_EVENT_RECEIVE_DATAGRAM:
01167     if (Parameters->EventHandler == NULL) {
01168       AddrFile->ReceiveDatagramHandlerContext    = NULL;
01169       AddrFile->RegisteredReceiveDatagramHandler = FALSE;
01170     } else {
01171       AddrFile->ReceiveDatagramHandler =
01172         (PTDI_IND_RECEIVE_DATAGRAM)Parameters->EventHandler;
01173       AddrFile->ReceiveDatagramHandlerContext    = Parameters->EventContext;
01174       AddrFile->RegisteredReceiveDatagramHandler = TRUE;
01175     }
01176     break;
01177 
01178   case TDI_EVENT_RECEIVE_EXPEDITED:
01179     if (Parameters->EventHandler == NULL) {
01180       AddrFile->ExpeditedReceiveHandlerContext    = NULL;
01181       AddrFile->RegisteredExpeditedReceiveHandler = FALSE;
01182     } else {
01183       AddrFile->ExpeditedReceiveHandler =
01184         (PTDI_IND_RECEIVE_EXPEDITED)Parameters->EventHandler;
01185       AddrFile->ExpeditedReceiveHandlerContext    = Parameters->EventContext;
01186       AddrFile->RegisteredExpeditedReceiveHandler = TRUE;
01187     }
01188     break;
01189 
01190   case TDI_EVENT_CHAINED_RECEIVE:
01191     if (Parameters->EventHandler == NULL) {
01192       AddrFile->ChainedReceiveHandlerContext    = NULL;
01193       AddrFile->RegisteredChainedReceiveHandler = FALSE;
01194     } else {
01195       AddrFile->ChainedReceiveHandler =
01196         (PTDI_IND_CHAINED_RECEIVE)Parameters->EventHandler;
01197       AddrFile->ChainedReceiveHandlerContext    = Parameters->EventContext;
01198       AddrFile->RegisteredChainedReceiveHandler = TRUE;
01199     }
01200     break;
01201 
01202   case TDI_EVENT_CHAINED_RECEIVE_DATAGRAM:
01203     if (Parameters->EventHandler == NULL) {
01204       AddrFile->ChainedReceiveDatagramHandlerContext    = NULL;
01205       AddrFile->RegisteredChainedReceiveDatagramHandler = FALSE;
01206     } else {
01207       AddrFile->ChainedReceiveDatagramHandler =
01208         (PTDI_IND_CHAINED_RECEIVE_DATAGRAM)Parameters->EventHandler;
01209       AddrFile->ChainedReceiveDatagramHandlerContext    = Parameters->EventContext;
01210       AddrFile->RegisteredChainedReceiveDatagramHandler = TRUE;
01211     }
01212     break;
01213 
01214   case TDI_EVENT_CHAINED_RECEIVE_EXPEDITED:
01215     if (Parameters->EventHandler == NULL) {
01216       AddrFile->ChainedReceiveExpeditedHandlerContext    = NULL;
01217       AddrFile->RegisteredChainedReceiveExpeditedHandler = FALSE;
01218     } else {
01219       AddrFile->ChainedReceiveExpeditedHandler =
01220         (PTDI_IND_CHAINED_RECEIVE_EXPEDITED)Parameters->EventHandler;
01221       AddrFile->ChainedReceiveExpeditedHandlerContext    = Parameters->EventContext;
01222       AddrFile->RegisteredChainedReceiveExpeditedHandler = TRUE;
01223     }
01224     break;
01225 
01226   default:
01227     TI_DbgPrint(MIN_TRACE, ("Unknown event type (0x%X).\n",
01228       Parameters->EventType));
01229 
01230     Status = STATUS_INVALID_PARAMETER;
01231   }
01232 
01233   UnlockObject(AddrFile, OldIrql);
01234 
01235   return Status;
01236 }
01237 
01238 
01239 NTSTATUS DispTdiSetInformation(
01240     PIRP Irp)
01241 /*
01242  * FUNCTION: TDI_SET_INFORMATION handler
01243  * ARGUMENTS:
01244  *     Irp = Pointer to an I/O request packet
01245  * RETURNS:
01246  *     Status of operation
01247  */
01248 {
01249     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
01250 
01251     return STATUS_NOT_IMPLEMENTED;
01252 }
01253 
01254 
01255 VOID DispTdiQueryInformationExComplete(
01256     PVOID Context,
01257     ULONG Status,
01258     UINT ByteCount)
01259 /*
01260  * FUNCTION: Completes a TDI QueryInformationEx request
01261  * ARGUMENTS:
01262  *     Context   = Pointer to the IRP for the request
01263  *     Status    = TDI status of the request
01264  *     ByteCount = Number of bytes returned in output buffer
01265  */
01266 {
01267     PTI_QUERY_CONTEXT QueryContext;
01268 
01269     QueryContext = (PTI_QUERY_CONTEXT)Context;
01270     if (NT_SUCCESS(Status)) {
01271         CopyBufferToBufferChain(
01272             QueryContext->InputMdl,
01273             FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context),
01274             (PCHAR)&QueryContext->QueryInfo.Context,
01275             CONTEXT_SIZE);
01276     }
01277 
01278     MmUnlockPages(QueryContext->InputMdl);
01279     IoFreeMdl(QueryContext->InputMdl);
01280     if( QueryContext->OutputMdl ) {
01281     MmUnlockPages(QueryContext->OutputMdl);
01282     IoFreeMdl(QueryContext->OutputMdl);
01283     }
01284 
01285     QueryContext->Irp->IoStatus.Information = ByteCount;
01286     QueryContext->Irp->IoStatus.Status      = Status;
01287 
01288     ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG);
01289 }
01290 
01291 
01292 NTSTATUS DispTdiQueryInformationEx(
01293     PIRP Irp,
01294     PIO_STACK_LOCATION IrpSp)
01295 /*
01296  * FUNCTION: TDI QueryInformationEx handler
01297  * ARGUMENTS:
01298  *     Irp   = Pointer to I/O request packet
01299  *     IrpSp = Pointer to current stack location of Irp
01300  * RETURNS:
01301  *     Status of operation
01302  */
01303 {
01304     PTCP_REQUEST_QUERY_INFORMATION_EX InputBuffer;
01305     PTRANSPORT_CONTEXT TranContext;
01306     PTI_QUERY_CONTEXT QueryContext;
01307     PVOID OutputBuffer;
01308     TDI_REQUEST Request;
01309     UINT Size;
01310     UINT InputBufferLength;
01311     UINT OutputBufferLength;
01312     BOOLEAN InputMdlLocked  = FALSE;
01313     BOOLEAN OutputMdlLocked = FALSE;
01314     PMDL InputMdl           = NULL;
01315     PMDL OutputMdl          = NULL;
01316     NTSTATUS Status         = STATUS_SUCCESS;
01317 
01318     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
01319 
01320     TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
01321 
01322     switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
01323     case TDI_TRANSPORT_ADDRESS_FILE:
01324         Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
01325         break;
01326 
01327     case TDI_CONNECTION_FILE:
01328         Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
01329         break;
01330 
01331     case TDI_CONTROL_CHANNEL_FILE:
01332         Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
01333         break;
01334 
01335     default:
01336         TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
01337         return STATUS_INVALID_PARAMETER;
01338     }
01339 
01340     InputBufferLength  = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
01341     OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
01342 
01343     /* Validate parameters */
01344     if ((InputBufferLength == sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)) &&
01345         (OutputBufferLength != 0)) {
01346 
01347         InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
01348             IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
01349         OutputBuffer = Irp->UserBuffer;
01350 
01351         QueryContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(TI_QUERY_CONTEXT), QUERY_CONTEXT_TAG);
01352         if (QueryContext) {
01353         _SEH2_TRY {
01354                 InputMdl = IoAllocateMdl(InputBuffer,
01355                     sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
01356                     FALSE, TRUE, NULL);
01357 
01358                 OutputMdl = IoAllocateMdl(OutputBuffer,
01359                     OutputBufferLength, FALSE, TRUE, NULL);
01360 
01361                 if (InputMdl && OutputMdl) {
01362 
01363                     MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
01364                         IoModifyAccess);
01365 
01366                     InputMdlLocked = TRUE;
01367 
01368                     MmProbeAndLockPages(OutputMdl, Irp->RequestorMode,
01369                         IoWriteAccess);
01370 
01371                     OutputMdlLocked = TRUE;
01372 
01373                     RtlCopyMemory(&QueryContext->QueryInfo,
01374                         InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
01375                 } else
01376                     Status = STATUS_INSUFFICIENT_RESOURCES;
01377             } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
01378                 Status = _SEH2_GetExceptionCode();
01379             } _SEH2_END;
01380 
01381             if (NT_SUCCESS(Status)) {
01382                 Size = MmGetMdlByteCount(OutputMdl);
01383 
01384                 QueryContext->Irp       = Irp;
01385                 QueryContext->InputMdl  = InputMdl;
01386                 QueryContext->OutputMdl = OutputMdl;
01387 
01388                 Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
01389                 Request.RequestContext      = QueryContext;
01390                 Status = InfoTdiQueryInformationEx(&Request,
01391                     &QueryContext->QueryInfo.ID, OutputMdl,
01392                     &Size, &QueryContext->QueryInfo.Context);
01393                 DispTdiQueryInformationExComplete(QueryContext, Status, Size);
01394 
01395                 TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
01396 
01397                 return Status;
01398             }
01399 
01400             /* An error occurred if we get here */
01401 
01402             if (InputMdl) {
01403                 if (InputMdlLocked)
01404                     MmUnlockPages(InputMdl);
01405                 IoFreeMdl(InputMdl);
01406             }
01407 
01408             if (OutputMdl) {
01409                 if (OutputMdlLocked)
01410                     MmUnlockPages(OutputMdl);
01411                 IoFreeMdl(OutputMdl);
01412             }
01413 
01414             ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG);
01415         } else
01416             Status = STATUS_INSUFFICIENT_RESOURCES;
01417     } else if( InputBufferLength ==
01418            sizeof(TCP_REQUEST_QUERY_INFORMATION_EX) ) {
01419     /* Handle the case where the user is probing the buffer for length */
01420     TI_DbgPrint(MAX_TRACE, ("InputBufferLength %d OutputBufferLength %d\n",
01421                 InputBufferLength, OutputBufferLength));
01422         InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
01423             IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
01424 
01425     Size = 0;
01426 
01427         QueryContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(TI_QUERY_CONTEXT), QUERY_CONTEXT_TAG);
01428         if (!QueryContext) return STATUS_INSUFFICIENT_RESOURCES;
01429 
01430     _SEH2_TRY {
01431         InputMdl = IoAllocateMdl(InputBuffer,
01432                      sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
01433                      FALSE, TRUE, NULL);
01434 
01435         MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
01436                 IoModifyAccess);
01437 
01438         InputMdlLocked = TRUE;
01439         Status = STATUS_SUCCESS;
01440     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
01441         TI_DbgPrint(MAX_TRACE, ("Failed to acquire client buffer\n"));
01442         Status = _SEH2_GetExceptionCode();
01443     } _SEH2_END;
01444 
01445     if( !NT_SUCCESS(Status) || !InputMdl ) {
01446         if( InputMdl ) IoFreeMdl( InputMdl );
01447         ExFreePoolWithTag(QueryContext, QUERY_CONTEXT_TAG);
01448         return Status;
01449     }
01450 
01451     RtlCopyMemory(&QueryContext->QueryInfo,
01452               InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
01453 
01454     QueryContext->Irp       = Irp;
01455     QueryContext->InputMdl  = InputMdl;
01456     QueryContext->OutputMdl = NULL;
01457 
01458     Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
01459     Request.RequestContext      = QueryContext;
01460     Status = InfoTdiQueryInformationEx(&Request,
01461                        &QueryContext->QueryInfo.ID,
01462                        NULL,
01463                        &Size,
01464                        &QueryContext->QueryInfo.Context);
01465     DispTdiQueryInformationExComplete(QueryContext, Status, Size);
01466     TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
01467     } else Status = STATUS_INVALID_PARAMETER;
01468 
01469     TI_DbgPrint(MIN_TRACE, ("Leaving. Status = (0x%X)\n", Status));
01470 
01471     return Status;
01472 }
01473 
01474 
01475 NTSTATUS DispTdiSetInformationEx(
01476     PIRP Irp,
01477     PIO_STACK_LOCATION IrpSp)
01478 /*
01479  * FUNCTION: TDI SetInformationEx handler
01480  * ARGUMENTS:
01481  *     Irp   = Pointer to I/O request packet
01482  *     IrpSp = Pointer to current stack location of Irp
01483  * RETURNS:
01484  *     Status of operation
01485  */
01486 {
01487     PTRANSPORT_CONTEXT TranContext;
01488     PTCP_REQUEST_SET_INFORMATION_EX Info;
01489     TDI_REQUEST Request;
01490     TDI_STATUS Status;
01491 
01492     TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
01493 
01494     TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
01495     Info        = (PTCP_REQUEST_SET_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer;
01496 
01497     switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
01498     case TDI_TRANSPORT_ADDRESS_FILE:
01499         Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
01500         break;
01501 
01502     case TDI_CONNECTION_FILE:
01503         Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
01504         break;
01505 
01506     case TDI_CONTROL_CHANNEL_FILE:
01507         Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
01508         break;
01509 
01510     default:
01511         Irp->IoStatus.Status      = STATUS_INVALID_PARAMETER;
01512         Irp->IoStatus.Information = 0;
01513 
01514         TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
01515 
01516         return Irp->IoStatus.Status;
01517     }
01518 
01519     Request.RequestNotifyObject = NULL;
01520     Request.RequestContext      = NULL;
01521 
01522     Status = InfoTdiSetInformationEx(&Request, &Info->ID,
01523             &Info->Buffer, Info->BufferSize);
01524 
01525     return Status;
01526 }
01527 
01528 /* TODO: Support multiple addresses per interface.
01529  * For now just set the nte context to the interface index.
01530  *
01531  * Later on, create an NTE context and NTE instance
01532  */
01533 
01534 NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
01535     NTSTATUS Status = STATUS_DEVICE_DOES_NOT_EXIST;
01536     PIP_SET_ADDRESS IpAddrChange =
01537         (PIP_SET_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
01538     IF_LIST_ITER(IF);
01539 
01540     TI_DbgPrint(MID_TRACE,("Setting IP Address for adapter %d\n",
01541                IpAddrChange->NteIndex));
01542 
01543     ForEachInterface(IF) {
01544     TI_DbgPrint(MID_TRACE,("Looking at adapter %d\n", IF->Index));
01545 
01546         if( IF->Unicast.Address.IPv4Address == IpAddrChange->Address ) {
01547             Status = STATUS_DUPLICATE_OBJECTID;
01548             break;
01549         }
01550         if( IF->Index == IpAddrChange->NteIndex ) {
01551             IPRemoveInterfaceRoute( IF );
01552 
01553             IF->Unicast.Type = IP_ADDRESS_V4;
01554             IF->Unicast.Address.IPv4Address = IpAddrChange->Address;
01555 
01556             IF->Netmask.Type = IP_ADDRESS_V4;
01557             IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask;
01558             
01559             IF->Broadcast.Type = IP_ADDRESS_V4;
01560         IF->Broadcast.Address.IPv4Address =
01561         IF->Unicast.Address.IPv4Address |
01562         ~IF->Netmask.Address.IPv4Address;
01563 
01564             TI_DbgPrint(MID_TRACE,("New Unicast Address: %x\n",
01565                                    IF->Unicast.Address.IPv4Address));
01566             TI_DbgPrint(MID_TRACE,("New Netmask        : %x\n",
01567                                    IF->Netmask.Address.IPv4Address));
01568 
01569             IPAddInterfaceRoute( IF );
01570 
01571             IpAddrChange->Address = IF->Index;
01572             Status = STATUS_SUCCESS;
01573             Irp->IoStatus.Information = IF->Index;
01574             break;
01575         }
01576     } EndFor(IF);
01577 
01578     Irp->IoStatus.Status = Status;
01579     return Status;
01580 }
01581 
01582 NTSTATUS DispTdiDeleteIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
01583     NTSTATUS Status = STATUS_UNSUCCESSFUL;
01584     PUSHORT NteIndex = Irp->AssociatedIrp.SystemBuffer;
01585     IF_LIST_ITER(IF);
01586 
01587     ForEachInterface(IF) {
01588         if( IF->Index == *NteIndex ) {
01589             IPRemoveInterfaceRoute( IF );
01590             IF->Unicast.Type = IP_ADDRESS_V4;
01591             IF->Unicast.Address.IPv4Address = 0;
01592 
01593             IF->Netmask.Type = IP_ADDRESS_V4;
01594             IF->Netmask.Address.IPv4Address = 0;
01595 
01596             IF->Broadcast.Type = IP_ADDRESS_V4;
01597             IF->Broadcast.Address.IPv4Address = 0;
01598 
01599             Status = STATUS_SUCCESS;
01600         }
01601     } EndFor(IF);
01602 
01603     Irp->IoStatus.Status = Status;
01604     return Status;
01605 }
01606 
01607 /* EOF */

Generated on Thu May 24 2012 04:20:31 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.