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

tdi.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS Ancillary Function Driver
00004  * FILE:        afd/tdi.c
00005  * PURPOSE:     Transport Driver Interface functions
00006  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
00007  * REVISIONS:
00008  *   CSH 01/09-2000 Created
00009  */
00010 #include <afd.h>
00011 #include <pseh/pseh2.h>
00012 #include "debug.h"
00013 #include "tdiconn.h"
00014 #include "tdi_proto.h"
00015 
00016 #if DBG
00017 #if 0
00018 static VOID DisplayBuffer(
00019     PVOID Buffer,
00020     ULONG Size)
00021 {
00022     ULONG i;
00023     PCHAR p;
00024 
00025     if ((DebugTraceLevel & MAX_TRACE) == 0)
00026         return;
00027 
00028     if (!Buffer) {
00029         AFD_DbgPrint(MIN_TRACE, ("Cannot display null buffer.\n"));
00030         return;
00031     }
00032 
00033     AFD_DbgPrint(MID_TRACE, ("Displaying buffer at (0x%X)  Size (%d).\n", Buffer, Size));
00034 
00035     p = (PCHAR)Buffer;
00036     for (i = 0; i < Size; i++) {
00037         if (i % 16 == 0)
00038             DbgPrint("\n");
00039         DbgPrint("%02X ", (p[i]) & 0xFF);
00040     }
00041     DbgPrint("\n");
00042 }
00043 #endif
00044 #endif /* DBG */
00045 
00046 static NTSTATUS TdiCall(
00047     PIRP Irp,
00048     PDEVICE_OBJECT DeviceObject,
00049     PKEVENT Event,
00050     PIO_STATUS_BLOCK Iosb)
00051 /*
00052  * FUNCTION: Calls a transport driver device
00053  * ARGUMENTS:
00054  *     Irp           = Pointer to I/O Request Packet
00055  *     DeviceObject  = Pointer to device object to call
00056  *     Event         = An optional pointer to an event handle that will be
00057  *                     waited upon
00058  *     Iosb          = Pointer to an IO status block
00059  * RETURNS:
00060  *     Status of operation
00061  */
00062 {
00063     NTSTATUS Status;
00064 
00065     AFD_DbgPrint(MID_TRACE, ("Called\n"));
00066 
00067     AFD_DbgPrint(MID_TRACE, ("Irp->UserEvent = %x\n", Irp->UserEvent));
00068 
00069     Status = IoCallDriver(DeviceObject, Irp);
00070     AFD_DbgPrint(MID_TRACE, ("IoCallDriver: %08x\n", Status));
00071 
00072     if ((Status == STATUS_PENDING) && (Event != NULL)) {
00073         AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
00074         KeWaitForSingleObject(Event,
00075                               Executive,
00076                               KernelMode,
00077                               FALSE,
00078                               NULL);
00079         Status = Iosb->Status;
00080     }
00081 
00082     AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));
00083 
00084     return Status;
00085 }
00086 
00087 
00088 static NTSTATUS TdiOpenDevice(
00089     PUNICODE_STRING DeviceName,
00090     ULONG EaLength,
00091     PFILE_FULL_EA_INFORMATION EaInfo,
00092     PHANDLE Handle,
00093     PFILE_OBJECT *Object)
00094 /*
00095  * FUNCTION: Opens a device
00096  * ARGUMENTS:
00097  *     DeviceName = Pointer to counted string with name of device
00098  *     EaLength   = Length of EA information
00099  *     EaInfo     = Pointer to buffer with EA information
00100  *     Handle     = Address of buffer to place device handle
00101  *     Object     = Address of buffer to place device object
00102  * RETURNS:
00103  *     Status of operation
00104  */
00105 {
00106     OBJECT_ATTRIBUTES Attr;
00107     IO_STATUS_BLOCK Iosb;
00108     NTSTATUS Status;
00109 
00110     AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)\n", DeviceName));
00111 
00112     InitializeObjectAttributes(&Attr,                   /* Attribute buffer */
00113                                DeviceName,              /* Device name */
00114                                OBJ_CASE_INSENSITIVE |   /* Attributes */
00115                                OBJ_KERNEL_HANDLE,
00116                                NULL,                    /* Root directory */
00117                                NULL);                   /* Security descriptor */
00118 
00119     Status = ZwCreateFile(Handle,                               /* Return file handle */
00120                           GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,         /* Desired access */
00121                           &Attr,                                /* Object attributes */
00122                           &Iosb,                                /* IO status */
00123                           0,                                    /* Initial allocation size */
00124                           FILE_ATTRIBUTE_NORMAL,                /* File attributes */
00125                           0,                                    /* Share access */
00126                           FILE_OPEN_IF,                         /* Create disposition */
00127                           0,                                    /* Create options */
00128                           EaInfo,                               /* EA buffer */
00129                           EaLength);                            /* EA length */
00130     if (NT_SUCCESS(Status)) {
00131         Status = ObReferenceObjectByHandle(*Handle,                       /* Handle to open file */
00132                                            GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,  /* Access mode */
00133                                            IoFileObjectType,              /* Object type */
00134                                            KernelMode,                    /* Access mode */
00135                                            (PVOID*)Object,                /* Pointer to object */
00136                                            NULL);                         /* Handle information */
00137         if (!NT_SUCCESS(Status)) {
00138             AFD_DbgPrint(MIN_TRACE, ("ObReferenceObjectByHandle() failed with status (0x%X).\n", Status));
00139             ZwClose(*Handle);
00140         } else {
00141             AFD_DbgPrint(MAX_TRACE, ("Got handle (0x%X)  Object (0x%X)\n",
00142                                      *Handle, *Object));
00143         }
00144     } else {
00145         AFD_DbgPrint(MIN_TRACE, ("ZwCreateFile() failed with status (0x%X)\n", Status));
00146     }
00147 
00148     if (!NT_SUCCESS(Status)) {
00149         *Handle = INVALID_HANDLE_VALUE;
00150         *Object = NULL;
00151     }
00152 
00153     return Status;
00154 }
00155 
00156 NTSTATUS TdiOpenAddressFile(
00157     PUNICODE_STRING DeviceName,
00158     PTRANSPORT_ADDRESS Name,
00159     PHANDLE AddressHandle,
00160     PFILE_OBJECT *AddressObject)
00161 /*
00162  * FUNCTION: Opens an IPv4 address file object
00163  * ARGUMENTS:
00164  *     DeviceName    = Pointer to counted string with name of device
00165  *     Name          = Pointer to socket name (IPv4 address family)
00166  *     AddressHandle = Address of buffer to place address file handle
00167  *     AddressObject = Address of buffer to place address file object
00168  * RETURNS:
00169  *     Status of operation
00170  */
00171 {
00172     PFILE_FULL_EA_INFORMATION EaInfo;
00173     NTSTATUS Status;
00174     ULONG EaLength;
00175     PTRANSPORT_ADDRESS Address;
00176 
00177     AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)  Name (0x%X)\n",
00178                              DeviceName, Name));
00179 
00180     /* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
00181     EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
00182         TDI_TRANSPORT_ADDRESS_LENGTH +
00183         TaLengthOfTransportAddress( Name ) + 1;
00184     EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength);
00185     if (!EaInfo)
00186         return STATUS_INSUFFICIENT_RESOURCES;
00187 
00188     RtlZeroMemory(EaInfo, EaLength);
00189     EaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
00190     /* Don't copy the terminating 0; we have already zeroed it */
00191     RtlCopyMemory(EaInfo->EaName,
00192                   TdiTransportAddress,
00193                   TDI_TRANSPORT_ADDRESS_LENGTH);
00194     EaInfo->EaValueLength = sizeof(TA_IP_ADDRESS);
00195     Address =
00196         (PTRANSPORT_ADDRESS)(EaInfo->EaName + TDI_TRANSPORT_ADDRESS_LENGTH + 1); /* 0-terminated */
00197     TaCopyTransportAddressInPlace( Address, Name );
00198 
00199     Status = TdiOpenDevice(DeviceName,
00200                            EaLength,
00201                            EaInfo,
00202                            AddressHandle,
00203                            AddressObject);
00204     ExFreePool(EaInfo);
00205     return Status;
00206 }
00207 
00208 NTSTATUS TdiQueryMaxDatagramLength(
00209     PFILE_OBJECT FileObject,
00210     PUINT MaxDatagramLength)
00211 {
00212     PMDL Mdl;
00213     PTDI_MAX_DATAGRAM_INFO Buffer;
00214     NTSTATUS Status = STATUS_SUCCESS;
00215 
00216     Buffer = ExAllocatePool(NonPagedPool, sizeof(TDI_MAX_DATAGRAM_INFO));
00217     if (!Buffer) return STATUS_NO_MEMORY;
00218 
00219     Mdl = IoAllocateMdl(Buffer, sizeof(TDI_MAX_DATAGRAM_INFO), FALSE, FALSE, NULL);
00220     if (!Mdl)
00221     {
00222         ExFreePool(Buffer);
00223         return STATUS_NO_MEMORY;
00224     }
00225 
00226     _SEH2_TRY
00227     {
00228          MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);
00229     }
00230     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
00231     {
00232          Status = _SEH2_GetExceptionCode();
00233     }
00234     _SEH2_END;
00235 
00236     if (!NT_SUCCESS(Status))
00237     {
00238         AFD_DbgPrint(MIN_TRACE,("Failed to lock pages\n"));
00239         IoFreeMdl(Mdl);
00240         ExFreePool(Buffer);
00241         return Status;
00242     }
00243 
00244     Status = TdiQueryInformation(FileObject,
00245                                  TDI_QUERY_MAX_DATAGRAM_INFO,
00246                                  Mdl);
00247     if (!NT_SUCCESS(Status))
00248     {
00249         ExFreePool(Buffer);
00250         return Status;
00251     }
00252 
00253     *MaxDatagramLength = Buffer->MaxDatagramSize;
00254 
00255     ExFreePool(Buffer);
00256 
00257     return STATUS_SUCCESS;
00258 }
00259 
00260 NTSTATUS TdiOpenConnectionEndpointFile(
00261     PUNICODE_STRING DeviceName,
00262     PHANDLE ConnectionHandle,
00263     PFILE_OBJECT *ConnectionObject)
00264 /*
00265  * FUNCTION: Opens a connection endpoint file object
00266  * ARGUMENTS:
00267  *     DeviceName       = Pointer to counted string with name of device
00268  *     ConnectionHandle = Address of buffer to place connection endpoint file handle
00269  *     ConnectionObject = Address of buffer to place connection endpoint file object
00270  * RETURNS:
00271  *     Status of operation
00272  */
00273 {
00274     PFILE_FULL_EA_INFORMATION EaInfo;
00275     PVOID *ContextArea;
00276     NTSTATUS Status;
00277     ULONG EaLength;
00278 
00279     AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)\n", DeviceName));
00280 
00281     /* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
00282     EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
00283         TDI_CONNECTION_CONTEXT_LENGTH +
00284         sizeof(PVOID) + 1;
00285 
00286     EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength);
00287     if (!EaInfo)
00288         return STATUS_INSUFFICIENT_RESOURCES;
00289 
00290     RtlZeroMemory(EaInfo, EaLength);
00291     EaInfo->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
00292     /* Don't copy the terminating 0; we have already zeroed it */
00293     RtlCopyMemory(EaInfo->EaName,
00294                   TdiConnectionContext,
00295                   TDI_CONNECTION_CONTEXT_LENGTH);
00296     EaInfo->EaValueLength = sizeof(PVOID);
00297     ContextArea = (PVOID*)(EaInfo->EaName + TDI_CONNECTION_CONTEXT_LENGTH + 1); /* 0-terminated */
00298     /* FIXME: Allocate context area */
00299     *ContextArea = NULL;
00300     Status = TdiOpenDevice(DeviceName,
00301                            EaLength,
00302                            EaInfo,
00303                            ConnectionHandle,
00304                            ConnectionObject);
00305     ExFreePool(EaInfo);
00306     return Status;
00307 }
00308 
00309 
00310 NTSTATUS TdiConnect(
00311     PIRP *Irp,
00312     PFILE_OBJECT ConnectionObject,
00313     PTDI_CONNECTION_INFORMATION ConnectionCallInfo,
00314     PTDI_CONNECTION_INFORMATION ConnectionReturnInfo,
00315     PIO_STATUS_BLOCK Iosb,
00316     PIO_COMPLETION_ROUTINE CompletionRoutine,
00317     PVOID CompletionContext)
00318 /*
00319  * FUNCTION: Connect a connection endpoint to a remote peer
00320  * ARGUMENTS:
00321  *     ConnectionObject = Pointer to connection endpoint file object
00322  *     RemoteAddress    = Pointer to remote address
00323  * RETURNS:
00324  *     Status of operation
00325  */
00326 {
00327     PDEVICE_OBJECT DeviceObject;
00328 
00329     AFD_DbgPrint(MAX_TRACE, ("Called\n"));
00330 
00331     ASSERT(*Irp == NULL);
00332 
00333     if (!ConnectionObject) {
00334         AFD_DbgPrint(MIN_TRACE, ("Bad connection object.\n"));
00335         return STATUS_INVALID_PARAMETER;
00336     }
00337 
00338     DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
00339     if (!DeviceObject) {
00340         AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
00341         return STATUS_INVALID_PARAMETER;
00342     }
00343 
00344     *Irp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT,             /* Sub function */
00345                                             DeviceObject,            /* Device object */
00346                                             ConnectionObject,        /* File object */
00347                                             NULL,                    /* Event */
00348                                             Iosb);                   /* Status */
00349     if (!*Irp) {
00350         return STATUS_INSUFFICIENT_RESOURCES;
00351     }
00352 
00353     TdiBuildConnect(*Irp,                   /* IRP */
00354                     DeviceObject,           /* Device object */
00355                     ConnectionObject,       /* File object */
00356                     CompletionRoutine,      /* Completion routine */
00357                     CompletionContext,      /* Completion routine context */
00358                     NULL,                   /* Time */
00359                     ConnectionCallInfo,     /* Request connection information */
00360                     ConnectionReturnInfo);  /* Return connection information */
00361 
00362     TdiCall(*Irp, DeviceObject, NULL, Iosb);
00363 
00364     return STATUS_PENDING;
00365 }
00366 
00367 
00368 NTSTATUS TdiAssociateAddressFile(
00369     HANDLE AddressHandle,
00370     PFILE_OBJECT ConnectionObject)
00371 /*
00372  * FUNCTION: Associates a connection endpoint to an address file object
00373  * ARGUMENTS:
00374  *     AddressHandle    = Handle to address file object
00375  *     ConnectionObject = Connection endpoint file object
00376  * RETURNS:
00377  *     Status of operation
00378  */
00379 {
00380     PDEVICE_OBJECT DeviceObject;
00381     IO_STATUS_BLOCK Iosb;
00382     KEVENT Event;
00383     PIRP Irp;
00384 
00385     AFD_DbgPrint(MAX_TRACE, ("Called. AddressHandle (0x%X)  ConnectionObject (0x%X)\n",
00386                              AddressHandle, ConnectionObject));
00387 
00388     if (!ConnectionObject) {
00389         AFD_DbgPrint(MIN_TRACE, ("Bad connection object.\n"));
00390         return STATUS_INVALID_PARAMETER;
00391     }
00392 
00393     DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
00394     if (!DeviceObject) {
00395         AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
00396         return STATUS_INVALID_PARAMETER;
00397     }
00398 
00399     KeInitializeEvent(&Event, NotificationEvent, FALSE);
00400 
00401     Irp = TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS,   /* Sub function */
00402                                            DeviceObject,            /* Device object */
00403                                            ConnectionObject,        /* File object */
00404                                            &Event,                  /* Event */
00405                                            &Iosb);                  /* Status */
00406     if (!Irp)
00407         return STATUS_INSUFFICIENT_RESOURCES;
00408 
00409     TdiBuildAssociateAddress(Irp,
00410                              DeviceObject,
00411                              ConnectionObject,
00412                              NULL,
00413                              NULL,
00414                              AddressHandle);
00415 
00416     return TdiCall(Irp, DeviceObject, &Event, &Iosb);
00417 }
00418 
00419 NTSTATUS TdiDisassociateAddressFile(
00420     PFILE_OBJECT ConnectionObject)
00421 /*
00422  * FUNCTION: Disassociates a connection endpoint from an address file object
00423  * ARGUMENTS:
00424  *     ConnectionObject = Connection endpoint file object
00425  * RETURNS:
00426  *     Status of operation
00427  */
00428 {
00429     PDEVICE_OBJECT DeviceObject;
00430     IO_STATUS_BLOCK Iosb;
00431     KEVENT Event;
00432     PIRP Irp;
00433 
00434     AFD_DbgPrint(MAX_TRACE, ("Called. ConnectionObject (0x%X)\n", ConnectionObject));
00435 
00436     if (!ConnectionObject) {
00437         AFD_DbgPrint(MIN_TRACE, ("Bad connection object.\n"));
00438         return STATUS_INVALID_PARAMETER;
00439     }
00440 
00441     DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
00442     if (!DeviceObject) {
00443         AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
00444         return STATUS_INVALID_PARAMETER;
00445     }
00446 
00447     KeInitializeEvent(&Event, NotificationEvent, FALSE);
00448 
00449     Irp = TdiBuildInternalDeviceControlIrp(TDI_DISASSOCIATE_ADDRESS,   /* Sub function */
00450                                            DeviceObject,            /* Device object */
00451                                            ConnectionObject,        /* File object */
00452                                            &Event,                  /* Event */
00453                                            &Iosb);                  /* Status */
00454     if (!Irp)
00455         return STATUS_INSUFFICIENT_RESOURCES;
00456 
00457     TdiBuildDisassociateAddress(Irp,
00458                                 DeviceObject,
00459                                 ConnectionObject,
00460                                 NULL,
00461                                 NULL);
00462 
00463     return TdiCall(Irp, DeviceObject, &Event, &Iosb);
00464 }
00465 
00466 NTSTATUS TdiListen(
00467     PIRP *Irp,
00468     PFILE_OBJECT ConnectionObject,
00469     PTDI_CONNECTION_INFORMATION *RequestConnectionInfo,
00470     PTDI_CONNECTION_INFORMATION *ReturnConnectionInfo,
00471     PIO_STATUS_BLOCK Iosb,
00472     PIO_COMPLETION_ROUTINE  CompletionRoutine,
00473     PVOID CompletionContext)
00474 /*
00475  * FUNCTION: Listen on a connection endpoint for a connection request from a remote peer
00476  * ARGUMENTS:
00477  *     CompletionRoutine = Routine to be called when IRP is completed
00478  *     CompletionContext = Context for CompletionRoutine
00479  * RETURNS:
00480  *     Status of operation
00481  *     May return STATUS_PENDING
00482  */
00483 {
00484     PDEVICE_OBJECT DeviceObject;
00485 
00486     AFD_DbgPrint(MAX_TRACE, ("Called\n"));
00487 
00488     ASSERT(*Irp == NULL);
00489 
00490     if (!ConnectionObject) {
00491         AFD_DbgPrint(MIN_TRACE, ("Bad connection object.\n"));
00492         return STATUS_INVALID_PARAMETER;
00493     }
00494 
00495     DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);
00496     if (!DeviceObject) {
00497         AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
00498         return STATUS_INVALID_PARAMETER;
00499     }
00500 
00501     *Irp = TdiBuildInternalDeviceControlIrp(TDI_LISTEN,              /* Sub function */
00502                                             DeviceObject,            /* Device object */
00503                                             ConnectionObject,        /* File object */
00504                                             NULL,                    /* Event */
00505                                             Iosb);                   /* Status */
00506     if (*Irp == NULL)
00507         return STATUS_INSUFFICIENT_RESOURCES;
00508 
00509     TdiBuildListen(*Irp,                   /* IRP */
00510                    DeviceObject,           /* Device object */
00511                    ConnectionObject,       /* File object */
00512                    CompletionRoutine,      /* Completion routine */
00513                    CompletionContext,      /* Completion routine context */
00514                    0,                      /* Flags */
00515                    *RequestConnectionInfo, /* Request connection information */
00516                    *ReturnConnectionInfo);  /* Return connection information */
00517 
00518     TdiCall(*Irp, DeviceObject, NULL /* Don't wait for completion */, Iosb);
00519 
00520     return STATUS_PENDING;
00521 }
00522 
00523 
00524 NTSTATUS TdiSetEventHandler(
00525     PFILE_OBJECT FileObject,
00526     LONG EventType,
00527     PVOID Handler,
00528     PVOID Context)
00529 /*
00530  * FUNCTION: Sets or resets an event handler
00531  * ARGUMENTS:
00532  *     FileObject = Pointer to file object
00533  *     EventType  = Event code
00534  *     Handler    = Event handler to be called when the event occurs
00535  *     Context    = Context input to handler when the event occurs
00536  * RETURNS:
00537  *     Status of operation
00538  * NOTES:
00539  *     Specify NULL for Handler to stop calling event handler
00540  */
00541 {
00542     PDEVICE_OBJECT DeviceObject;
00543     IO_STATUS_BLOCK Iosb;
00544     KEVENT Event;
00545     PIRP Irp;
00546 
00547     AFD_DbgPrint(MAX_TRACE, ("Called\n"));
00548 
00549     if (!FileObject) {
00550         AFD_DbgPrint(MIN_TRACE, ("Bad file object.\n"));
00551         return STATUS_INVALID_PARAMETER;
00552     }
00553 
00554     DeviceObject = IoGetRelatedDeviceObject(FileObject);
00555     if (!DeviceObject) {
00556         AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
00557         return STATUS_INVALID_PARAMETER;
00558     }
00559 
00560     KeInitializeEvent(&Event, NotificationEvent, FALSE);
00561 
00562     Irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER,   /* Sub function */
00563                                            DeviceObject,            /* Device object */
00564                                            FileObject,              /* File object */
00565                                            &Event,                  /* Event */
00566                                            &Iosb);                  /* Status */
00567     if (!Irp)
00568         return STATUS_INSUFFICIENT_RESOURCES;
00569 
00570 
00571 
00572     TdiBuildSetEventHandler(Irp,
00573                             DeviceObject,
00574                             FileObject,
00575                             NULL,
00576                             NULL,
00577                             EventType,
00578                             Handler,
00579                             Context);
00580 
00581     return TdiCall(Irp, DeviceObject, &Event, &Iosb);
00582 }
00583 
00584 
00585 NTSTATUS TdiQueryDeviceControl(
00586     PFILE_OBJECT FileObject,
00587     ULONG IoControlCode,
00588     PVOID InputBuffer,
00589     ULONG InputBufferLength,
00590     PVOID OutputBuffer,
00591     ULONG OutputBufferLength,
00592     PULONG Return)
00593 /*
00594  * FUNCTION: Queries a device for information
00595  * ARGUMENTS:
00596  *     FileObject         = Pointer to file object
00597  *     IoControlCode      = I/O control code
00598  *     InputBuffer        = Pointer to buffer with input data
00599  *     InputBufferLength  = Length of InputBuffer
00600  *     OutputBuffer       = Address of buffer to place output data
00601  *     OutputBufferLength = Length of OutputBuffer
00602  * RETURNS:
00603  *     Status of operation
00604  */
00605 {
00606     PDEVICE_OBJECT DeviceObject;
00607     IO_STATUS_BLOCK Iosb;
00608     NTSTATUS Status;
00609     KEVENT Event;
00610     PIRP Irp;
00611 
00612     if (!FileObject) {
00613         AFD_DbgPrint(MIN_TRACE, ("Bad file object.\n"));
00614         return STATUS_INVALID_PARAMETER;
00615     }
00616 
00617     DeviceObject = IoGetRelatedDeviceObject(FileObject);
00618     if (!DeviceObject) {
00619         AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
00620         return STATUS_INVALID_PARAMETER;
00621     }
00622 
00623     KeInitializeEvent(&Event, NotificationEvent, FALSE);
00624 
00625     Irp = IoBuildDeviceIoControlRequest(IoControlCode,
00626                                         DeviceObject,
00627                                         InputBuffer,
00628                                         InputBufferLength,
00629                                         OutputBuffer,
00630                                         OutputBufferLength,
00631                                         FALSE,
00632                                         &Event,
00633                                         &Iosb);
00634     if (!Irp)
00635         return STATUS_INSUFFICIENT_RESOURCES;
00636 
00637     Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);
00638 
00639     if (Return)
00640         *Return = Iosb.Information;
00641 
00642     return Status;
00643 }
00644 
00645 
00646 NTSTATUS TdiQueryInformation(
00647     PFILE_OBJECT FileObject,
00648     LONG QueryType,
00649     PMDL MdlBuffer)
00650 /*
00651  * FUNCTION: Query for information
00652  * ARGUMENTS:
00653  *     FileObject   = Pointer to file object
00654  *     QueryType    = Query type
00655  *     MdlBuffer    = Pointer to MDL buffer specific for query type
00656  * RETURNS:
00657  *     Status of operation
00658  */
00659 {
00660     PDEVICE_OBJECT DeviceObject;
00661     IO_STATUS_BLOCK Iosb;
00662     KEVENT Event;
00663     PIRP Irp;
00664 
00665     if (!FileObject) {
00666         AFD_DbgPrint(MIN_TRACE, ("Bad file object.\n"));
00667         return STATUS_INVALID_PARAMETER;
00668     }
00669 
00670     DeviceObject = IoGetRelatedDeviceObject(FileObject);
00671     if (!DeviceObject) {
00672         AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
00673         return STATUS_INVALID_PARAMETER;
00674     }
00675 
00676     KeInitializeEvent(&Event, NotificationEvent, FALSE);
00677 
00678     Irp = TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION,       /* Sub function */
00679                                            DeviceObject,                /* Device object */
00680                                            ConnectionObject,            /* File object */
00681                                            &Event,                      /* Event */
00682                                            &Iosb);                      /* Status */
00683     if (!Irp) {
00684         return STATUS_INSUFFICIENT_RESOURCES;
00685     }
00686 
00687     TdiBuildQueryInformation(Irp,
00688                              DeviceObject,
00689                              FileObject,
00690                              NULL,
00691                              NULL,
00692                              QueryType,
00693                              MdlBuffer);
00694 
00695     return TdiCall(Irp, DeviceObject, &Event, &Iosb);
00696 }
00697 
00698 NTSTATUS TdiQueryInformationEx(
00699     PFILE_OBJECT FileObject,
00700     ULONG Entity,
00701     ULONG Instance,
00702     ULONG Class,
00703     ULONG Type,
00704     ULONG Id,
00705     PVOID OutputBuffer,
00706     PULONG OutputLength)
00707 /*
00708  * FUNCTION: Extended query for information
00709  * ARGUMENTS:
00710  *     FileObject   = Pointer to file object
00711  *     Entity       = Entity
00712  *     Instance     = Instance
00713  *     Class        = Entity class
00714  *     Type         = Entity type
00715  *     Id           = Entity id
00716  *     OutputBuffer = Address of buffer to place data
00717  *     OutputLength = Address of buffer with length of OutputBuffer (updated)
00718  * RETURNS:
00719  *     Status of operation
00720  */
00721 {
00722     TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo;
00723 
00724     RtlZeroMemory(&QueryInfo, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
00725     QueryInfo.ID.toi_entity.tei_entity   = Entity;
00726     QueryInfo.ID.toi_entity.tei_instance = Instance;
00727     QueryInfo.ID.toi_class = Class;
00728     QueryInfo.ID.toi_type  = Type;
00729     QueryInfo.ID.toi_id    = Id;
00730 
00731     return TdiQueryDeviceControl(FileObject,                                /* Transport/connection object */
00732                                  IOCTL_TCP_QUERY_INFORMATION_EX,            /* Control code */
00733                                  &QueryInfo,                                /* Input buffer */
00734                                  sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),  /* Input buffer length */
00735                                  OutputBuffer,                              /* Output buffer */
00736                                  *OutputLength,                             /* Output buffer length */
00737                                  OutputLength);                             /* Return information */
00738 }
00739 
00740 NTSTATUS TdiQueryAddress(
00741     PFILE_OBJECT FileObject,
00742     PULONG Address)
00743 /*
00744  * FUNCTION: Queries for a local IP address
00745  * ARGUMENTS:
00746  *     FileObject = Pointer to file object
00747  *     Address    = Address of buffer to place local address
00748  * RETURNS:
00749  *     Status of operation
00750  */
00751 {
00752     UINT i;
00753     TDIEntityID *Entities;
00754     ULONG EntityCount;
00755     ULONG EntityType;
00756     IPSNMP_INFO SnmpInfo;
00757     PIPADDR_ENTRY IpAddress;
00758     ULONG BufferSize;
00759     NTSTATUS Status = STATUS_SUCCESS;
00760 
00761     AFD_DbgPrint(MAX_TRACE, ("Called\n"));
00762 
00763     BufferSize = sizeof(TDIEntityID) * 20;
00764     Entities   = (TDIEntityID*)ExAllocatePool(NonPagedPool, BufferSize);
00765     if (!Entities) {
00766         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00767         return STATUS_INSUFFICIENT_RESOURCES;
00768     }
00769 
00770     /* Query device for supported entities */
00771 
00772     Status = TdiQueryInformationEx(FileObject,          /* File object */
00773                                    GENERIC_ENTITY,      /* Entity */
00774                                    TL_INSTANCE,         /* Instance */
00775                                    INFO_CLASS_GENERIC,  /* Entity class */
00776                                    INFO_TYPE_PROVIDER,  /* Entity type */
00777                                    ENTITY_LIST_ID,      /* Entity id */
00778                                    Entities,            /* Output buffer */
00779                                    &BufferSize);        /* Output buffer size */
00780     if (!NT_SUCCESS(Status)) {
00781         AFD_DbgPrint(MIN_TRACE, ("Unable to get list of supported entities (Status = 0x%X).\n", Status));
00782         ExFreePool(Entities);
00783         return Status;
00784     }
00785 
00786     /* Locate an IP entity */
00787     EntityCount = BufferSize / sizeof(TDIEntityID);
00788 
00789     AFD_DbgPrint(MAX_TRACE, ("EntityCount = %d\n", EntityCount));
00790 
00791     for (i = 0; i < EntityCount; i++) {
00792         if (Entities[i].tei_entity == CL_NL_ENTITY) {
00793             /* Query device for entity type */
00794 
00795             BufferSize = sizeof(EntityType);
00796             Status = TdiQueryInformationEx(FileObject,                  /* File object */
00797                                            CL_NL_ENTITY,                /* Entity */
00798                                            Entities[i].tei_instance,    /* Instance */
00799                                            INFO_CLASS_GENERIC,          /* Entity class */
00800                                            INFO_TYPE_PROVIDER,          /* Entity type */
00801                                            ENTITY_TYPE_ID,              /* Entity id */
00802                                            &EntityType,                 /* Output buffer */
00803                                            &BufferSize);                /* Output buffer size */
00804             if (!NT_SUCCESS(Status) || (EntityType != CL_NL_IP)) {
00805                 AFD_DbgPrint(MIN_TRACE, ("Unable to get entity of type IP (Status = 0x%X).\n", Status));
00806                 break;
00807             }
00808 
00809             /* Query device for SNMP information */
00810 
00811             BufferSize = sizeof(SnmpInfo);
00812             Status = TdiQueryInformationEx(FileObject,                  /* File object */
00813                                            CL_NL_ENTITY,                /* Entity */
00814                                            Entities[i].tei_instance,    /* Instance */
00815                                            INFO_CLASS_PROTOCOL,         /* Entity class */
00816                                            INFO_TYPE_PROVIDER,          /* Entity type */
00817                                            IP_MIB_STATS_ID,             /* Entity id */
00818                                            &SnmpInfo,                   /* Output buffer */
00819                                            &BufferSize);                /* Output buffer size */
00820             if (!NT_SUCCESS(Status) || (SnmpInfo.NumAddr == 0)) {
00821                 AFD_DbgPrint(MIN_TRACE, ("Unable to get SNMP information or no IP addresses available (Status = 0x%X).\n", Status));
00822                 break;
00823             }
00824 
00825             /* Query device for all IP addresses */
00826 
00827             if (SnmpInfo.NumAddr != 0) {
00828                 BufferSize = SnmpInfo.NumAddr * sizeof(IPADDR_ENTRY);
00829                 IpAddress = (PIPADDR_ENTRY)ExAllocatePool(NonPagedPool, BufferSize);
00830                 if (!IpAddress) {
00831                     AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00832                     break;
00833                 }
00834 
00835                 Status = TdiQueryInformationEx(FileObject,                  /* File object */
00836                                                CL_NL_ENTITY,                /* Entity */
00837                                                Entities[i].tei_instance,    /* Instance */
00838                                                INFO_CLASS_PROTOCOL,         /* Entity class */
00839                                                INFO_TYPE_PROVIDER,          /* Entity type */
00840                                                IP_MIB_ADDRTABLE_ENTRY_ID,   /* Entity id */
00841                                                IpAddress,                   /* Output buffer */
00842                                                &BufferSize);                /* Output buffer size */
00843                 if (!NT_SUCCESS(Status)) {
00844                     AFD_DbgPrint(MIN_TRACE, ("Unable to get IP address (Status = 0x%X).\n", Status));
00845                     ExFreePool(IpAddress);
00846                     break;
00847                 }
00848 
00849                 if (SnmpInfo.NumAddr != 1) {
00850                     /* Skip loopback address */
00851                     *Address = DN2H(IpAddress[1].Addr);
00852                 } else {
00853                     /* Select the first address returned */
00854                     *Address = DN2H(IpAddress->Addr);
00855                 }
00856 
00857                 ExFreePool(IpAddress);
00858             } else {
00859                 Status = STATUS_UNSUCCESSFUL;
00860                 break;
00861             }
00862         }
00863     }
00864 
00865     ExFreePool(Entities);
00866 
00867     AFD_DbgPrint(MAX_TRACE, ("Leaving\n"));
00868 
00869     return Status;
00870 }
00871 
00872 NTSTATUS TdiSend(
00873     PIRP *Irp,
00874     PFILE_OBJECT TransportObject,
00875     USHORT Flags,
00876     PCHAR Buffer,
00877     UINT BufferLength,
00878     PIO_STATUS_BLOCK Iosb,
00879     PIO_COMPLETION_ROUTINE CompletionRoutine,
00880     PVOID CompletionContext)
00881 {
00882     PDEVICE_OBJECT DeviceObject;
00883     PMDL Mdl;
00884 
00885     ASSERT(*Irp == NULL);
00886 
00887     if (!TransportObject) {
00888         AFD_DbgPrint(MIN_TRACE, ("Bad transport object.\n"));
00889         return STATUS_INVALID_PARAMETER;
00890     }
00891 
00892     DeviceObject = IoGetRelatedDeviceObject(TransportObject);
00893     if (!DeviceObject) {
00894         AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
00895         return STATUS_INVALID_PARAMETER;
00896     }
00897 
00898     *Irp = TdiBuildInternalDeviceControlIrp(TDI_SEND,                /* Sub function */
00899                                             DeviceObject,            /* Device object */
00900                                             TransportObject,         /* File object */
00901                                             NULL,                    /* Event */
00902                                             Iosb);                   /* Status */
00903 
00904     if (!*Irp) {
00905         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00906         return STATUS_INSUFFICIENT_RESOURCES;
00907     }
00908 
00909     AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
00910 
00911     Mdl = IoAllocateMdl(Buffer,         /* Virtual address */
00912                         BufferLength,   /* Length of buffer */
00913                         FALSE,          /* Not secondary */
00914                         FALSE,          /* Don't charge quota */
00915                         NULL);          /* Don't use IRP */
00916     if (!Mdl) {
00917         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00918         IoCompleteRequest(*Irp, IO_NO_INCREMENT);
00919         *Irp = NULL;
00920         return STATUS_INSUFFICIENT_RESOURCES;
00921     }
00922 
00923     _SEH2_TRY {
00924         MmProbeAndLockPages(Mdl, (*Irp)->RequestorMode, IoModifyAccess);
00925     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
00926         AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
00927         IoFreeMdl(Mdl);
00928         IoCompleteRequest(*Irp, IO_NO_INCREMENT);
00929         *Irp = NULL;
00930         _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES);
00931     } _SEH2_END;
00932 
00933     AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
00934 
00935     TdiBuildSend(*Irp,                   /* I/O Request Packet */
00936                  DeviceObject,           /* Device object */
00937                  TransportObject,        /* File object */
00938                  CompletionRoutine,      /* Completion routine */
00939                  CompletionContext,      /* Completion context */
00940                  Mdl,                    /* Data buffer */
00941                  Flags,                  /* Flags */
00942                  BufferLength);          /* Length of data */
00943 
00944     TdiCall(*Irp, DeviceObject, NULL, Iosb);
00945     /* Does not block...  The MDL is deleted in the receive completion
00946        routine. */
00947 
00948     return STATUS_PENDING;
00949 }
00950 
00951 NTSTATUS TdiReceive(
00952     PIRP *Irp,
00953     PFILE_OBJECT TransportObject,
00954     USHORT Flags,
00955     PCHAR Buffer,
00956     UINT BufferLength,
00957     PIO_STATUS_BLOCK Iosb,
00958     PIO_COMPLETION_ROUTINE CompletionRoutine,
00959     PVOID CompletionContext)
00960 {
00961     PDEVICE_OBJECT DeviceObject;
00962     PMDL Mdl;
00963 
00964     ASSERT(*Irp == NULL);
00965 
00966     if (!TransportObject) {
00967         AFD_DbgPrint(MIN_TRACE, ("Bad transport object.\n"));
00968         return STATUS_INVALID_PARAMETER;
00969     }
00970 
00971     DeviceObject = IoGetRelatedDeviceObject(TransportObject);
00972     if (!DeviceObject) {
00973         AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
00974         return STATUS_INVALID_PARAMETER;
00975     }
00976 
00977     *Irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE,             /* Sub function */
00978                                             DeviceObject,            /* Device object */
00979                                             TransportObject,         /* File object */
00980                                             NULL,                    /* Event */
00981                                             Iosb);                   /* Status */
00982 
00983     if (!*Irp) {
00984         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00985         return STATUS_INSUFFICIENT_RESOURCES;
00986     }
00987 
00988     AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
00989 
00990     Mdl = IoAllocateMdl(Buffer,         /* Virtual address */
00991                         BufferLength,   /* Length of buffer */
00992                         FALSE,          /* Not secondary */
00993                         FALSE,          /* Don't charge quota */
00994                         NULL);          /* Don't use IRP */
00995     if (!Mdl) {
00996         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
00997         IoCompleteRequest(*Irp, IO_NO_INCREMENT);
00998         *Irp = NULL;
00999         return STATUS_INSUFFICIENT_RESOURCES;
01000     }
01001 
01002     _SEH2_TRY {
01003         AFD_DbgPrint(MID_TRACE, ("probe and lock\n"));
01004         MmProbeAndLockPages(Mdl, (*Irp)->RequestorMode, IoModifyAccess);
01005         AFD_DbgPrint(MID_TRACE, ("probe and lock done\n"));
01006     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
01007         AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
01008         IoFreeMdl(Mdl);
01009         IoCompleteRequest(*Irp, IO_NO_INCREMENT);
01010         *Irp = NULL;
01011         _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES);
01012     } _SEH2_END;
01013 
01014     AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
01015 
01016     TdiBuildReceive(*Irp,                   /* I/O Request Packet */
01017                     DeviceObject,           /* Device object */
01018                     TransportObject,        /* File object */
01019                     CompletionRoutine,      /* Completion routine */
01020                     CompletionContext,      /* Completion context */
01021                     Mdl,                    /* Data buffer */
01022                     Flags,                  /* Flags */
01023                     BufferLength);          /* Length of data */
01024 
01025 
01026     TdiCall(*Irp, DeviceObject, NULL, Iosb);
01027     /* Does not block...  The MDL is deleted in the receive completion
01028        routine. */
01029 
01030     return STATUS_PENDING;
01031 }
01032 
01033 
01034 NTSTATUS TdiReceiveDatagram(
01035     PIRP *Irp,
01036     PFILE_OBJECT TransportObject,
01037     USHORT Flags,
01038     PCHAR Buffer,
01039     UINT BufferLength,
01040     PTDI_CONNECTION_INFORMATION Addr,
01041     PIO_STATUS_BLOCK Iosb,
01042     PIO_COMPLETION_ROUTINE CompletionRoutine,
01043     PVOID CompletionContext)
01044 /*
01045  * FUNCTION: Receives a datagram
01046  * ARGUMENTS:
01047  *     TransportObject = Pointer to transport object
01048  *     From            = Receive filter (NULL if none)
01049  *     Address         = Address of buffer to place remote address
01050  *     Buffer          = Address of buffer to place received data
01051  *     BufferSize      = Address of buffer with length of Buffer (updated)
01052  * RETURNS:
01053  *     Status of operation
01054  */
01055 {
01056     PDEVICE_OBJECT DeviceObject;
01057     PMDL Mdl;
01058 
01059     ASSERT(*Irp == NULL);
01060 
01061     if (!TransportObject) {
01062         AFD_DbgPrint(MIN_TRACE, ("Bad tranport object.\n"));
01063         return STATUS_INVALID_PARAMETER;
01064     }
01065 
01066     DeviceObject = IoGetRelatedDeviceObject(TransportObject);
01067     if (!DeviceObject) {
01068         AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
01069         return STATUS_INVALID_PARAMETER;
01070     }
01071 
01072     *Irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM,    /* Sub function */
01073                                             DeviceObject,            /* Device object */
01074                                             TransportObject,         /* File object */
01075                                             NULL,                    /* Event */
01076                                             Iosb);                   /* Status */
01077 
01078     if (!*Irp) {
01079         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
01080         return STATUS_INSUFFICIENT_RESOURCES;
01081     }
01082 
01083     AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
01084 
01085     Mdl = IoAllocateMdl(Buffer,         /* Virtual address */
01086                         BufferLength,   /* Length of buffer */
01087                         FALSE,          /* Not secondary */
01088                         FALSE,          /* Don't charge quota */
01089                         NULL);          /* Don't use IRP */
01090     if (!Mdl) {
01091         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
01092         IoCompleteRequest(*Irp, IO_NO_INCREMENT);
01093         *Irp = NULL;
01094         return STATUS_INSUFFICIENT_RESOURCES;
01095     }
01096 
01097     _SEH2_TRY {
01098         MmProbeAndLockPages(Mdl, (*Irp)->RequestorMode, IoModifyAccess);
01099     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
01100         AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
01101         IoFreeMdl(Mdl);
01102         IoCompleteRequest(*Irp, IO_NO_INCREMENT);
01103         *Irp = NULL;
01104         _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES);
01105     } _SEH2_END;
01106 
01107     AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
01108 
01109     TdiBuildReceiveDatagram(*Irp,                   /* I/O Request Packet */
01110                             DeviceObject,           /* Device object */
01111                             TransportObject,        /* File object */
01112                             CompletionRoutine,      /* Completion routine */
01113                             CompletionContext,      /* Completion context */
01114                             Mdl,                    /* Data buffer */
01115                             BufferLength,
01116                             Addr,
01117                             Addr,
01118                             Flags);                 /* Length of data */
01119 
01120     TdiCall(*Irp, DeviceObject, NULL, Iosb);
01121     /* Does not block...  The MDL is deleted in the receive completion
01122        routine. */
01123 
01124     return STATUS_PENDING;
01125 }
01126 
01127 
01128 NTSTATUS TdiSendDatagram(
01129     PIRP *Irp,
01130     PFILE_OBJECT TransportObject,
01131     PCHAR Buffer,
01132     UINT BufferLength,
01133     PTDI_CONNECTION_INFORMATION Addr,
01134     PIO_STATUS_BLOCK Iosb,
01135     PIO_COMPLETION_ROUTINE CompletionRoutine,
01136     PVOID CompletionContext)
01137 /*
01138  * FUNCTION: Sends a datagram
01139  * ARGUMENTS:
01140  *     TransportObject = Pointer to transport object
01141  *     From            = Send filter (NULL if none)
01142  *     Address         = Address of buffer to place remote address
01143  *     Buffer          = Address of buffer to place send data
01144  *     BufferSize      = Address of buffer with length of Buffer (updated)
01145  * RETURNS:
01146  *     Status of operation
01147  */
01148 {
01149     PDEVICE_OBJECT DeviceObject;
01150     PMDL Mdl;
01151 
01152     ASSERT(*Irp == NULL);
01153 
01154     if (!TransportObject) {
01155         AFD_DbgPrint(MIN_TRACE, ("Bad transport object.\n"));
01156         return STATUS_INVALID_PARAMETER;
01157     }
01158 
01159     AFD_DbgPrint(MID_TRACE,("Called(TransportObject %x)\n", TransportObject));
01160 
01161     DeviceObject = IoGetRelatedDeviceObject(TransportObject);
01162     if (!DeviceObject) {
01163         AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
01164         return STATUS_INVALID_PARAMETER;
01165     }
01166 
01167     *Irp = TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM,       /* Sub function */
01168                                             DeviceObject,            /* Device object */
01169                                             TransportObject,         /* File object */
01170                                             NULL,                    /* Event */
01171                                             Iosb);                   /* Status */
01172 
01173     if (!*Irp) {
01174         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
01175         return STATUS_INSUFFICIENT_RESOURCES;
01176     }
01177 
01178     AFD_DbgPrint(MID_TRACE, ("Allocating irp for %x:%d\n", Buffer,BufferLength));
01179 
01180     Mdl = IoAllocateMdl(Buffer,         /* Virtual address */
01181                         BufferLength,   /* Length of buffer */
01182                         FALSE,          /* Not secondary */
01183                         FALSE,          /* Don't charge quota */
01184                         NULL);          /* Don't use IRP */
01185 
01186     if (!Mdl) {
01187         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
01188         IoCompleteRequest(*Irp, IO_NO_INCREMENT);
01189         *Irp = NULL;
01190         return STATUS_INSUFFICIENT_RESOURCES;
01191     }
01192 
01193     _SEH2_TRY {
01194         MmProbeAndLockPages(Mdl, (*Irp)->RequestorMode, IoModifyAccess);
01195     } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
01196         AFD_DbgPrint(MIN_TRACE, ("MmProbeAndLockPages() failed.\n"));
01197         IoFreeMdl(Mdl);
01198         IoCompleteRequest(*Irp, IO_NO_INCREMENT);
01199         *Irp = NULL;
01200         _SEH2_YIELD(return STATUS_INSUFFICIENT_RESOURCES);
01201     } _SEH2_END;
01202 
01203     AFD_DbgPrint(MID_TRACE,("AFD>>> Got an MDL: %x\n", Mdl));
01204 
01205     TdiBuildSendDatagram(*Irp,                   /* I/O Request Packet */
01206                          DeviceObject,           /* Device object */
01207                          TransportObject,        /* File object */
01208                          CompletionRoutine,      /* Completion routine */
01209                          CompletionContext,      /* Completion context */
01210                          Mdl,                    /* Data buffer */
01211                          BufferLength,           /* Bytes to send */
01212                          Addr);                  /* Address */
01213 
01214     TdiCall(*Irp, DeviceObject, NULL, Iosb);
01215     /* Does not block...  The MDL is deleted in the send completion
01216        routine. */
01217 
01218     return STATUS_PENDING;
01219 }
01220 
01221 NTSTATUS TdiDisconnect(
01222     PIRP *Irp,
01223     PFILE_OBJECT TransportObject,
01224     PLARGE_INTEGER Time,
01225     USHORT Flags,
01226     PIO_STATUS_BLOCK Iosb,
01227     PIO_COMPLETION_ROUTINE CompletionRoutine,
01228     PVOID CompletionContext,
01229     PTDI_CONNECTION_INFORMATION RequestConnectionInfo,
01230     PTDI_CONNECTION_INFORMATION ReturnConnectionInfo) {
01231     PDEVICE_OBJECT DeviceObject;
01232 
01233     if (!TransportObject) {
01234         AFD_DbgPrint(MIN_TRACE, ("Bad transport object.\n"));
01235         return STATUS_INVALID_PARAMETER;
01236     }
01237 
01238     AFD_DbgPrint(MID_TRACE,("Called(TransportObject %x)\n", TransportObject));
01239 
01240     DeviceObject = IoGetRelatedDeviceObject(TransportObject);
01241     if (!DeviceObject) {
01242         AFD_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
01243         return STATUS_INVALID_PARAMETER;
01244     }
01245 
01246     *Irp = TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT,          /* Sub function */
01247                                             DeviceObject,            /* Device object */
01248                                             TransportObject,         /* File object */
01249                                             NULL,                    /* Event */
01250                                             Iosb);                   /* Status */
01251 
01252     if (!*Irp) {
01253         AFD_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
01254         return STATUS_INSUFFICIENT_RESOURCES;
01255     }
01256 
01257     TdiBuildDisconnect(*Irp,                   /* I/O Request Packet */
01258                        DeviceObject,           /* Device object */
01259                        TransportObject,        /* File object */
01260                        CompletionRoutine,      /* Completion routine */
01261                        CompletionContext,      /* Completion context */
01262                        Time,                   /* Time */
01263                        Flags,                  /* Disconnect flags */
01264                        RequestConnectionInfo,  /* Indication of who to disconnect */
01265                        ReturnConnectionInfo);  /* Indication of who disconnected */
01266 
01267     TdiCall(*Irp, DeviceObject, NULL, Iosb);
01268 
01269     return STATUS_PENDING;
01270 }
01271 
01272 /* EOF */

Generated on Sat May 26 2012 04:26:36 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.