main.c
来自「一个类似windows」· C语言 代码 · 共 919 行 · 第 1/2 页
C
919 行
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/main.c
* PURPOSE: Driver entry point
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/08-2000 Created
*/
#include "precomp.h"
#define NDEBUG
#ifndef NDEBUG
DWORD DebugTraceLevel = DEBUG_ULTRA & ~(DEBUG_LOCK | DEBUG_PBUFFER);
#else
DWORD DebugTraceLevel = DEBUG_DATALINK;
#endif /* NDEBUG */
PDEVICE_OBJECT TCPDeviceObject = NULL;
PDEVICE_OBJECT UDPDeviceObject = NULL;
PDEVICE_OBJECT IPDeviceObject = NULL;
PDEVICE_OBJECT RawIPDeviceObject = NULL;
NDIS_HANDLE GlobalPacketPool = NULL;
NDIS_HANDLE GlobalBufferPool = NULL;
KSPIN_LOCK EntityListLock;
TDIEntityInfo *EntityList = NULL;
ULONG EntityCount = 0;
ULONG EntityMax = 0;
UDP_STATISTICS UDPStats;
/* Network timers */
KTIMER IPTimer;
KDPC IPTimeoutDpc;
KSPIN_LOCK IpWorkLock;
WORK_QUEUE_ITEM IpWorkItem;
VOID TiWriteErrorLog(
PDRIVER_OBJECT DriverContext,
NTSTATUS ErrorCode,
ULONG UniqueErrorValue,
NTSTATUS FinalStatus,
PWSTR String,
ULONG DumpDataCount,
PULONG DumpData)
/*
* FUNCTION: Writes an error log entry
* ARGUMENTS:
* DriverContext = Pointer to the driver or device object
* ErrorCode = An error code to put in the log entry
* UniqueErrorValue = UniqueErrorValue in the error log packet
* FinalStatus = FinalStatus in the error log packet
* String = If not NULL, a pointer to a string to put in log
* entry
* DumpDataCount = Number of ULONGs of dump data
* DumpData = Pointer to dump data for the log entry
*/
{
#ifdef _MSC_VER
PIO_ERROR_LOG_PACKET LogEntry;
UCHAR EntrySize;
ULONG StringSize;
PUCHAR pString;
static WCHAR DriverName[] = L"TCP/IP";
EntrySize = sizeof(IO_ERROR_LOG_PACKET) +
(DumpDataCount * sizeof(ULONG)) + sizeof(DriverName);
if (String) {
StringSize = (wcslen(String) * sizeof(WCHAR)) + sizeof(UNICODE_NULL);
EntrySize += (UCHAR)StringSize;
}
LogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(
DriverContext, EntrySize);
if (LogEntry) {
LogEntry->MajorFunctionCode = -1;
LogEntry->RetryCount = -1;
LogEntry->DumpDataSize = (USHORT)(DumpDataCount * sizeof(ULONG));
LogEntry->NumberOfStrings = (String == NULL) ? 1 : 2;
LogEntry->StringOffset = sizeof(IO_ERROR_LOG_PACKET) + (DumpDataCount-1) * sizeof(ULONG);
LogEntry->EventCategory = 0;
LogEntry->ErrorCode = ErrorCode;
LogEntry->UniqueErrorValue = UniqueErrorValue;
LogEntry->FinalStatus = FinalStatus;
LogEntry->SequenceNumber = -1;
LogEntry->IoControlCode = 0;
if (DumpDataCount)
RtlCopyMemory(LogEntry->DumpData, DumpData, DumpDataCount * sizeof(ULONG));
pString = ((PUCHAR)LogEntry) + LogEntry->StringOffset;
RtlCopyMemory(pString, DriverName, sizeof(DriverName));
pString += sizeof(DriverName);
if (String)
RtlCopyMemory(pString, String, StringSize);
IoWriteErrorLogEntry(LogEntry);
}
#endif
}
/*
* FUNCTION: Creates a file object
* ARGUMENTS:
* DeviceObject = Pointer to a device object for this driver
* Irp = Pointer to a I/O request packet
* RETURNS:
* Status of the operation
*/
NTSTATUS TiCreateFileObject(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PFILE_FULL_EA_INFORMATION EaInfo;
PTRANSPORT_CONTEXT Context;
PIO_STACK_LOCATION IrpSp;
PTA_IP_ADDRESS Address;
TDI_REQUEST Request;
PVOID ClientContext;
NTSTATUS Status;
ULONG Protocol;
TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp));
EaInfo = Irp->AssociatedIrp.SystemBuffer;
CP
/* Parameter check */
/* No EA information means that we're opening for SET/QUERY_INFORMATION
* style calls. */
#if 0
if (!EaInfo) {
TI_DbgPrint(MIN_TRACE, ("No EA information in IRP.\n"));
return STATUS_INVALID_PARAMETER;
}
#endif
CP
/* Allocate resources here. We release them again if something failed */
Context = ExAllocatePool(NonPagedPool, sizeof(TRANSPORT_CONTEXT));
if (!Context) {
TI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
CP
Context->CancelIrps = FALSE;
KeInitializeEvent(&Context->CleanupEvent, NotificationEvent, FALSE);
CP
IrpSp = IoGetCurrentIrpStackLocation(Irp);
IrpSp->FileObject->FsContext = Context;
Request.RequestContext = Irp;
CP
/* Branch to the right handler */
if (EaInfo &&
(EaInfo->EaNameLength == TDI_TRANSPORT_ADDRESS_LENGTH) &&
(RtlCompareMemory
(&EaInfo->EaName, TdiTransportAddress,
TDI_TRANSPORT_ADDRESS_LENGTH) == TDI_TRANSPORT_ADDRESS_LENGTH)) {
/* This is a request to open an address */
CP
/* XXX This should probably be done in IoCreateFile() */
/* Parameter checks */
Address = (PTA_IP_ADDRESS)(EaInfo->EaName + EaInfo->EaNameLength + 1); //0-term
if ((EaInfo->EaValueLength < sizeof(TA_IP_ADDRESS)) ||
(Address->TAAddressCount != 1) ||
(Address->Address[0].AddressLength < TDI_ADDRESS_LENGTH_IP) ||
(Address->Address[0].AddressType != TDI_ADDRESS_TYPE_IP)) {
TI_DbgPrint(MIN_TRACE, ("Parameters are invalid:\n"));
TI_DbgPrint(MIN_TRACE, ("AddressCount: %d\n", Address->TAAddressCount));
if( Address->TAAddressCount == 1 ) {
TI_DbgPrint(MIN_TRACE, ("AddressLength: %\n",
Address->Address[0].AddressLength));
TI_DbgPrint(MIN_TRACE, ("AddressType: %\n",
Address->Address[0].AddressType));
}
PoolFreeBuffer(Context);
return STATUS_INVALID_PARAMETER;
}
CP
/* Open address file object */
/* Protocol depends on device object so find the protocol */
if (DeviceObject == TCPDeviceObject)
Protocol = IPPROTO_TCP;
else if (DeviceObject == UDPDeviceObject)
Protocol = IPPROTO_UDP;
else if (DeviceObject == IPDeviceObject)
Protocol = IPPROTO_RAW;
else if (DeviceObject == RawIPDeviceObject) {
Status = TiGetProtocolNumber(&IrpSp->FileObject->FileName, &Protocol);
if (!NT_SUCCESS(Status)) {
TI_DbgPrint(MIN_TRACE, ("Raw IP protocol number is invalid.\n"));
PoolFreeBuffer(Context);
return STATUS_INVALID_PARAMETER;
}
} else {
TI_DbgPrint(MIN_TRACE, ("Invalid device object at (0x%X).\n", DeviceObject));
PoolFreeBuffer(Context);
return STATUS_INVALID_PARAMETER;
}
CP
Status = FileOpenAddress(&Request, Address, Protocol, NULL);
if (NT_SUCCESS(Status)) {
IrpSp->FileObject->FsContext2 = (PVOID)TDI_TRANSPORT_ADDRESS_FILE;
Context->Handle.AddressHandle = Request.Handle.AddressHandle;
}
CP
} else if (EaInfo &&
(EaInfo->EaNameLength == TDI_CONNECTION_CONTEXT_LENGTH) &&
(RtlCompareMemory
(&EaInfo->EaName, TdiConnectionContext,
TDI_CONNECTION_CONTEXT_LENGTH) ==
TDI_CONNECTION_CONTEXT_LENGTH)) {
/* This is a request to open a connection endpoint */
CP
/* Parameter checks */
if (EaInfo->EaValueLength < sizeof(PVOID)) {
TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
PoolFreeBuffer(Context);
return STATUS_INVALID_PARAMETER;
}
/* Can only do connection oriented communication using TCP */
if (DeviceObject != TCPDeviceObject) {
TI_DbgPrint(MIN_TRACE, ("Bad device object.\n"));
PoolFreeBuffer(Context);
return STATUS_INVALID_PARAMETER;
}
ClientContext = *((PVOID*)(EaInfo->EaName + EaInfo->EaNameLength));
/* Open connection endpoint file object */
Status = FileOpenConnection(&Request, ClientContext);
if (NT_SUCCESS(Status)) {
IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONNECTION_FILE;
Context->Handle.ConnectionContext = Request.Handle.ConnectionContext;
}
} else {
/* This is a request to open a control connection */
Status = FileOpenControlChannel(&Request);
if (NT_SUCCESS(Status)) {
IrpSp->FileObject->FsContext2 = (PVOID)TDI_CONTROL_CHANNEL_FILE;
Context->Handle.ControlChannel = Request.Handle.ControlChannel;
}
}
if (!NT_SUCCESS(Status))
PoolFreeBuffer(Context);
TI_DbgPrint(DEBUG_IRP, ("Leaving. Status = (0x%X).\n", Status));
Irp->IoStatus.Status = Status;
return Status;
}
VOID TiCleanupFileObjectComplete(
PVOID Context,
NTSTATUS Status)
/*
* FUNCTION: Completes an object cleanup IRP I/O request
* ARGUMENTS:
* Context = Pointer to the IRP for this request
* Status = Final status of the operation
*/
{
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
PTRANSPORT_CONTEXT TranContext;
KIRQL OldIrql;
Irp = (PIRP)Context;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
Irp->IoStatus.Status = Status;
IoAcquireCancelSpinLock(&OldIrql);
KeSetEvent(&TranContext->CleanupEvent, 0, FALSE);
IoReleaseCancelSpinLock(OldIrql);
}
/*
* FUNCTION: Releases resources used by a file object
* ARGUMENTS:
* DeviceObject = Pointer to a device object for this driver
* Irp = Pointer to a I/O request packet
* RETURNS:
* Status of the operation
* NOTES:
* This function does not pend
*/
NTSTATUS TiCleanupFileObject(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
PTRANSPORT_CONTEXT Context;
TDI_REQUEST Request;
NTSTATUS Status;
KIRQL OldIrql;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Context = IrpSp->FileObject->FsContext;
if (!Context) {
TI_DbgPrint(MIN_TRACE, ("Parameters are invalid.\n"));
return STATUS_INVALID_PARAMETER;
}
IoAcquireCancelSpinLock(&OldIrql);
Context->CancelIrps = TRUE;
KeResetEvent(&Context->CleanupEvent);
IoReleaseCancelSpinLock(OldIrql);
Request.RequestNotifyObject = TiCleanupFileObjectComplete;
Request.RequestContext = Irp;
switch ((ULONG_PTR)IrpSp->FileObject->FsContext2) {
case TDI_TRANSPORT_ADDRESS_FILE:
Request.Handle.AddressHandle = Context->Handle.AddressHandle;
Status = FileCloseAddress(&Request);
break;
case TDI_CONNECTION_FILE:
Request.Handle.ConnectionContext = Context->Handle.ConnectionContext;
Status = FileCloseConnection(&Request);
break;
case TDI_CONTROL_CHANNEL_FILE:
Request.Handle.ControlChannel = Context->Handle.ControlChannel;
Status = FileCloseControlChannel(&Request);
break;
default:
/* This should never happen */
TI_DbgPrint(MIN_TRACE, ("Unknown transport context.\n"));
IoAcquireCancelSpinLock(&OldIrql);
Context->CancelIrps = FALSE;
IoReleaseCancelSpinLock(OldIrql);
return STATUS_INVALID_PARAMETER;
}
if (Status != STATUS_PENDING)
TiCleanupFileObjectComplete(Irp, Status);
KeWaitForSingleObject(&Context->CleanupEvent,
UserRequest, KernelMode, FALSE, NULL);
return Irp->IoStatus.Status;
}
NTSTATUS STDCALL
TiDispatchOpenClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
/*
* FUNCTION: Main dispath routine
* ARGUMENTS:
* DeviceObject = Pointer to a device object for this driver
* Irp = Pointer to a I/O request packet
* RETURNS:
* Status of the operation
*/
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
PTRANSPORT_CONTEXT Context;
RIRP(Irp);
TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X).\n", DeviceObject, Irp));
IoMarkIrpPending(Irp);
Irp->IoStatus.Status = STATUS_PENDING;
Irp->IoStatus.Information = 0;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
switch (IrpSp->MajorFunction) {
/* Open an address file, connection endpoint, or control connection */
case IRP_MJ_CREATE:
Status = TiCreateFileObject(DeviceObject, Irp);
break;
/* Close an address file, connection endpoint, or control connection */
case IRP_MJ_CLOSE:
Context = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
if (Context)
PoolFreeBuffer(Context);
Status = STATUS_SUCCESS;
break;
/* Release resources bound to an address file, connection endpoint,
or control connection */
case IRP_MJ_CLEANUP:
Status = TiCleanupFileObject(DeviceObject, Irp);
break;
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
}
TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status));
return IRPFinish( Irp, Status );
}
NTSTATUS
#ifndef _MSC_VER
STDCALL
#endif
TiDispatchInternal(
PDEVICE_OBJECT DeviceObject,
PIRP Irp)
/*
* FUNCTION: Internal IOCTL dispatch routine
* ARGUMENTS:
* DeviceObject = Pointer to a device object for this driver
* Irp = Pointer to a I/O request packet
* RETURNS:
* Status of the operation
*/
{
NTSTATUS Status;
BOOL Complete = TRUE;
PIO_STACK_LOCATION IrpSp;
RIRP(Irp);
IrpSp = IoGetCurrentIrpStackLocation(Irp);
TI_DbgPrint(DEBUG_IRP, ("Called. DeviceObject is at (0x%X), IRP is at (0x%X) MN (%d).\n",
DeviceObject, Irp, IrpSp->MinorFunction));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
switch (IrpSp->MinorFunction) {
case TDI_RECEIVE:
Status = DispTdiReceive(Irp);
Complete = FALSE;
break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?