📄 tdi.c
字号:
/*
* 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 + -