⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tdi.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * COPYRIGHT:   See COPYING in the top level directory
 * PROJECT:     ReactOS Ancillary Function Driver
 * FILE:        afd/tdi.c
 * PURPOSE:     Transport Driver Interface functions
 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
 * REVISIONS:
 *   CSH 01/09-2000 Created
 */
#include <afd.h>
#include <pseh/pseh.h>
#include "debug.h"
#include "tdiconn.h"
#include "tdi_proto.h"

#ifdef DBG
#if 0
static VOID DisplayBuffer(
    PVOID Buffer,
    ULONG Size)
{
    ULONG i;
    PCHAR p;

    if ((DebugTraceLevel & MAX_TRACE) == 0)
        return;

    if (!Buffer) {
        AFD_DbgPrint(MIN_TRACE, ("Cannot display null buffer.\n"));
        return;
    }

    AFD_DbgPrint(MIN_TRACE, ("Displaying buffer at (0x%X)  Size (%d).\n", Buffer, Size));

    p = (PCHAR)Buffer;
    for (i = 0; i < Size; i++) {
        if (i % 16 == 0)
            DbgPrint("\n");
        DbgPrint("%02X ", (p[i]) & 0xFF);
    }
    DbgPrint("\n");
}
#endif
#endif /* DBG */

static NTSTATUS TdiCall(
    PIRP Irp,
    PDEVICE_OBJECT DeviceObject,
    PKEVENT Event,
    PIO_STATUS_BLOCK Iosb)
/*
 * FUNCTION: Calls a transport driver device
 * ARGUMENTS:
 *     Irp           = Pointer to I/O Request Packet
 *     DeviceObject  = Pointer to device object to call
 *     Event         = An optional pointer to an event handle that will be
 *                     waited upon
 *     Iosb          = Pointer to an IO status block
 * RETURNS:
 *     Status of operation
 */
{
    NTSTATUS Status;

    AFD_DbgPrint(MID_TRACE, ("Called\n"));

    AFD_DbgPrint(MID_TRACE, ("Irp->UserEvent = %x\n", Irp->UserEvent));

    Status = IoCallDriver(DeviceObject, Irp);
    AFD_DbgPrint(MID_TRACE, ("IoCallDriver: %08x\n", Status));

    if ((Status == STATUS_PENDING) && (Event != NULL)) {
        AFD_DbgPrint(MAX_TRACE, ("Waiting on transport.\n"));
        KeWaitForSingleObject(
          Event,
          Executive,
          UserMode,
          FALSE,
          NULL);
        Status = Iosb->Status;
    }

    AFD_DbgPrint(MAX_TRACE, ("Status (0x%X).\n", Status));

    return Status;
}


static NTSTATUS TdiOpenDevice(
    PUNICODE_STRING DeviceName,
    ULONG EaLength,
    PFILE_FULL_EA_INFORMATION EaInfo,
    PHANDLE Handle,
    PFILE_OBJECT *Object)
/*
 * FUNCTION: Opens a device
 * ARGUMENTS:
 *     DeviceName = Pointer to counted string with name of device
 *     EaLength   = Length of EA information
 *     EaInfo     = Pointer to buffer with EA information
 *     Handle     = Address of buffer to place device handle
 *     Object     = Address of buffer to place device object
 * RETURNS:
 *     Status of operation
 */
{
    OBJECT_ATTRIBUTES Attr;
    IO_STATUS_BLOCK Iosb;
    NTSTATUS Status;

    AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)\n", DeviceName));

    InitializeObjectAttributes(&Attr,                   /* Attribute buffer */
                               DeviceName,              /* Device name */
                               OBJ_CASE_INSENSITIVE,    /* Attributes */
                               NULL,                    /* Root directory */
                               NULL);                   /* Security descriptor */

    Status = ZwCreateFile(Handle,                               /* Return file handle */
                          GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,         /* Desired access */
                          &Attr,                                /* Object attributes */
                          &Iosb,                                /* IO status */
                          0,                                    /* Initial allocation size */
                          FILE_ATTRIBUTE_NORMAL,                /* File attributes */
                          FILE_SHARE_READ | FILE_SHARE_WRITE,   /* Share access */
                          FILE_OPEN_IF,                         /* Create disposition */
                          0,                                    /* Create options */
                          EaInfo,                               /* EA buffer */
                          EaLength);                            /* EA length */
    if (NT_SUCCESS(Status)) {
        Status = ObReferenceObjectByHandle(*Handle,                       /* Handle to open file */
                                           GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,  /* Access mode */
                                           NULL,                          /* Object type */
                                           KernelMode,                    /* Access mode */
                                           (PVOID*)Object,                /* Pointer to object */
                                           NULL);                         /* Handle information */
        if (!NT_SUCCESS(Status)) {
          AFD_DbgPrint(MIN_TRACE, ("ObReferenceObjectByHandle() failed with status (0x%X).\n", Status));
            ZwClose(*Handle);
        } else {
          AFD_DbgPrint(MAX_TRACE, ("Got handle (0x%X)  Object (0x%X)\n",
            *Handle, *Object));
        }
    } else {
        AFD_DbgPrint(MIN_TRACE, ("ZwCreateFile() failed with status (0x%X)\n", Status));
        *Handle = NULL;
    }

    return Status;
}


NTSTATUS TdiCloseDevice(
    HANDLE Handle,
    PFILE_OBJECT FileObject)
{
    AFD_DbgPrint(MAX_TRACE, ("Called. Handle (0x%X)  FileObject (0x%X)\n",
      Handle, FileObject));

    if (Handle)
        ZwClose(Handle);

    if (FileObject)
        ObDereferenceObject(FileObject);

    return STATUS_SUCCESS;
}


NTSTATUS TdiOpenAddressFile(
    PUNICODE_STRING DeviceName,
    PTRANSPORT_ADDRESS Name,
    PHANDLE AddressHandle,
    PFILE_OBJECT *AddressObject)
/*
 * FUNCTION: Opens an IPv4 address file object
 * ARGUMENTS:
 *     DeviceName    = Pointer to counted string with name of device
 *     Name          = Pointer to socket name (IPv4 address family)
 *     AddressHandle = Address of buffer to place address file handle
 *     AddressObject = Address of buffer to place address file object
 * RETURNS:
 *     Status of operation
 */
{
  PFILE_FULL_EA_INFORMATION EaInfo;
  NTSTATUS Status;
  ULONG EaLength;
  PTRANSPORT_ADDRESS Address;

  AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)  Name (0x%X)\n",
			   DeviceName, Name));

  /* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
  EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
      TDI_TRANSPORT_ADDRESS_LENGTH +
      TaLengthOfTransportAddress( Name ) + 1;
  EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength);
  if (!EaInfo)
      return STATUS_INSUFFICIENT_RESOURCES;

  RtlZeroMemory(EaInfo, EaLength);
  EaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
  /* Don't copy the terminating 0; we have already zeroed it */
  RtlCopyMemory(EaInfo->EaName,
                TdiTransportAddress,
                TDI_TRANSPORT_ADDRESS_LENGTH);
  EaInfo->EaValueLength = sizeof(TA_IP_ADDRESS);
  Address =
      (PTRANSPORT_ADDRESS)(EaInfo->EaName + TDI_TRANSPORT_ADDRESS_LENGTH + 1); /* 0-terminated */
  TaCopyTransportAddressInPlace( Address, Name );

  Status = TdiOpenDevice(DeviceName,
                         EaLength,
                         EaInfo,
                         AddressHandle,
                         AddressObject);
  ExFreePool(EaInfo);
  return Status;
}


NTSTATUS TdiOpenConnectionEndpointFile(
  PUNICODE_STRING DeviceName,
  PHANDLE ConnectionHandle,
  PFILE_OBJECT *ConnectionObject)
/*
 * FUNCTION: Opens a connection endpoint file object
 * ARGUMENTS:
 *     DeviceName       = Pointer to counted string with name of device
 *     ConnectionHandle = Address of buffer to place connection endpoint file handle
 *     ConnectionObject = Address of buffer to place connection endpoint file object
 * RETURNS:
 *     Status of operation
 */
{
  PFILE_FULL_EA_INFORMATION EaInfo;
  PVOID *ContextArea;
  NTSTATUS Status;
  ULONG EaLength;

  AFD_DbgPrint(MAX_TRACE, ("Called. DeviceName (%wZ)\n", DeviceName));

	/* EaName must be 0-terminated, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
  EaLength = sizeof(FILE_FULL_EA_INFORMATION) +
             TDI_CONNECTION_CONTEXT_LENGTH +
             sizeof(PVOID) + 1;

  EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength);
  if (!EaInfo)
    return STATUS_INSUFFICIENT_RESOURCES;

  RtlZeroMemory(EaInfo, EaLength);
  EaInfo->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
  /* Don't copy the terminating 0; we have already zeroed it */
  RtlCopyMemory(EaInfo->EaName,
                TdiConnectionContext,
                TDI_CONNECTION_CONTEXT_LENGTH);
  EaInfo->EaValueLength = sizeof(PVOID);
  ContextArea = (PVOID*)(EaInfo->EaName + TDI_CONNECTION_CONTEXT_LENGTH + 1); /* 0-terminated */
  /* FIXME: Allocate context area */
  *ContextArea = NULL;
  Status = TdiOpenDevice(DeviceName,
                         EaLength,
                         EaInfo,
                         ConnectionHandle,
                         ConnectionObject);
  ExFreePool(EaInfo);
  return Status;
}


NTSTATUS TdiConnect(
    PIRP *Irp,
    PFILE_OBJECT ConnectionObject,
    PTDI_CONNECTION_INFORMATION RemoteAddress,
    PIO_STATUS_BLOCK Iosb,
    PIO_COMPLETION_ROUTINE CompletionRoutine,
    PVOID CompletionContext)
/*
 * FUNCTION: Connect a connection endpoint to a remote peer
 * ARGUMENTS:
 *     ConnectionObject = Pointer to connection endpoint file object
 *     RemoteAddress    = Pointer to remote address
 * RETURNS:
 *     Status of operation
 */
{
  PDEVICE_OBJECT DeviceObject;
  NTSTATUS Status;

  AFD_DbgPrint(MAX_TRACE, ("Called\n"));

  assert(ConnectionObject);

  DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);

  *Irp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT,             /* Sub function */
					  DeviceObject,            /* Device object */
					  ConnectionObject,        /* File object */
					  NULL,                    /* Event */
					  Iosb);                   /* Status */
  if (!*Irp) {
    return STATUS_INSUFFICIENT_RESOURCES;
  }

  TdiBuildConnect(*Irp,                   /* IRP */
                  DeviceObject,           /* Device object */
                  ConnectionObject,       /* File object */
                  CompletionRoutine,      /* Completion routine */
                  CompletionContext,      /* Completion routine context */
                  NULL,                   /* Time */
                  RemoteAddress,          /* Request connection information */
                  RemoteAddress);         /* Return connection information */

  Status = TdiCall(*Irp, DeviceObject, NULL, Iosb);

  return Status;
}


NTSTATUS TdiAssociateAddressFile(
  HANDLE AddressHandle,
  PFILE_OBJECT ConnectionObject)
/*
 * FUNCTION: Associates a connection endpoint to an address file object
 * ARGUMENTS:
 *     AddressHandle    = Handle to address file object
 *     ConnectionObject = Connection endpoint file object
 * RETURNS:
 *     Status of operation
 */
{
  PDEVICE_OBJECT DeviceObject;
  IO_STATUS_BLOCK Iosb;
  NTSTATUS Status;
  KEVENT Event;
  PIRP Irp;

  AFD_DbgPrint(MAX_TRACE, ("Called. AddressHandle (0x%X)  ConnectionObject (0x%X)\n",
    AddressHandle, ConnectionObject));

  assert(ConnectionObject);

  DeviceObject = IoGetRelatedDeviceObject(ConnectionObject);

  KeInitializeEvent(&Event, NotificationEvent, FALSE);

  Irp = TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS,   /* Sub function */
                                         DeviceObject,            /* Device object */
                                         ConnectionObject,        /* File object */
                                         &Event,                  /* Event */
                                         &Iosb);                  /* Status */
  if (!Irp)
    return STATUS_INSUFFICIENT_RESOURCES;

  TdiBuildAssociateAddress(Irp,
                           DeviceObject,
                           ConnectionObject,
                           NULL,
                           NULL,
                           AddressHandle);

  Status = TdiCall(Irp, DeviceObject, &Event, &Iosb);

  return Status;
}


NTSTATUS TdiListen
( PIRP *Irp,
  PFILE_OBJECT ConnectionObject,
  PTDI_CONNECTION_INFORMATION *RequestConnectionInfo,
  PTDI_CONNECTION_INFORMATION *ReturnConnectionInfo,
  PIO_STATUS_BLOCK Iosb,
  PIO_COMPLETION_ROUTINE  CompletionRoutine,
  PVOID CompletionContext)
/*
 * FUNCTION: Listen on a connection endpoint for a connection request from a remote peer
 * ARGUMENTS:
 *     CompletionRoutine = Routine to be called when IRP is completed
 *     CompletionContext = Context for CompletionRoutine
 * RETURNS:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -