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

📄 tditest.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * COPYRIGHT:   See COPYING in the top level directory
 * PROJECT:     ReactOS TDI test driver
 * FILE:        tditest.c
 * PURPOSE:     Testing TDI drivers
 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
 *              Vizzini (vizzini@plasmic.com)
 * REVISIONS:
 *   CSH 01/08-2000 Created
 *   26-Nov-2003 Vizzini Updated to run properly on Win2ksp4
 */
#include <tditest.h>


#ifdef DBG

/* See debug.h for debug/trace constants */
ULONG DebugTraceLevel = -1;

#endif /* DBG */


HANDLE TdiTransport             = 0;
PFILE_OBJECT TdiTransportObject = NULL;
ULONG LocalAddress;
BOOLEAN OpenError;
KEVENT StopEvent;
HANDLE SendThread;
HANDLE ReceiveThread;

NTSTATUS TdiCall(
    PIRP Irp,
    PDEVICE_OBJECT DeviceObject,
    PIO_STATUS_BLOCK IoStatusBlock,
    BOOLEAN CanCancel)
/*
 * FUNCTION: Calls a transport driver device
 * ARGUMENTS:
 *     Irp           = Pointer to I/O Request Packet
 *     DeviceObject  = Pointer to device object to call
 *     IoStatusBlock = Address of buffer with I/O status block
 *     CanCancel     = TRUE if the IRP can be cancelled, FALSE if not
 * RETURNS:
 *     Status of operation
 * NOTES
 *     All requests are completed synchronously. A request may be cancelled
 */
{
	KEVENT Event;
	PKEVENT Events[2];
	NTSTATUS Status;
	Events[0] = &StopEvent;
	Events[1] = &Event;

	KeInitializeEvent(&Event, NotificationEvent, FALSE);
	Irp->UserEvent = &Event;
	Irp->UserIosb  = IoStatusBlock;

	Status = IoCallDriver(DeviceObject, Irp);

	if (Status == STATUS_PENDING)
		{
			if (CanCancel)
				{
					Status = KeWaitForMultipleObjects(2, (PVOID)Events, WaitAny, Executive, KernelMode, FALSE, NULL, NULL);

					if (KeReadStateEvent(&StopEvent) != 0)
						{
							if (IoCancelIrp(Irp))
								{
									TDI_DbgPrint(MAX_TRACE, ("Cancelled IRP.\n"));
								}
							else
								{
									TDI_DbgPrint(MIN_TRACE, ("Could not cancel IRP.\n"));
								}
							return STATUS_CANCELLED;
						}
				}
			else
				Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
		}

	return (Status == STATUS_SUCCESS)? IoStatusBlock->Status : STATUS_SUCCESS;
}


NTSTATUS TdiOpenDevice(
    PWSTR Protocol,
    ULONG EaLength,
    PFILE_FULL_EA_INFORMATION EaInfo,
    PHANDLE Handle,
    PFILE_OBJECT *Object)
/*
 * FUNCTION: Opens a device
 * ARGUMENTS:
 *     Protocol = Pointer to buffer 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;
	UNICODE_STRING Name;
	NTSTATUS Status;

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

	Status = ZwCreateFile(
		Handle,                               /* Return file handle */
		GENERIC_READ | GENERIC_WRITE,         /* 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,   /* Access mode */
				NULL,                           /* Object type */
				KernelMode,                     /* Access mode */
				(PVOID*)Object,                 /* Pointer to object */
				NULL);                          /* Handle information */

			if (!NT_SUCCESS(Status))
				{
					TDI_DbgPrint(MIN_TRACE, ("ObReferenceObjectByHandle() failed with status (0x%X).\n", Status));
					ZwClose(*Handle);
				}
		}
	else
		{
			TDI_DbgPrint(MIN_TRACE, ("ZwCreateFile() failed with status (0x%X)\n", Status));
		}

    return Status;
}


NTSTATUS TdiCloseDevice(
    HANDLE Handle,
    PFILE_OBJECT FileObject)
{
	if (FileObject)
		ObDereferenceObject(FileObject);

	if (Handle)
		ZwClose(Handle);

	return STATUS_SUCCESS;
}


NTSTATUS TdiOpenTransport(
    PWSTR Protocol,
    USHORT Port,
    PHANDLE Transport,
    PFILE_OBJECT *TransportObject)
/*
 * FUNCTION: Opens a transport driver
 * ARGUMENTS:
 *     Protocol        = Pointer to buffer with name of device
 *     Port            = Port number to use
 *     Transport       = Address of buffer to place transport device handle
 *     TransportObject = Address of buffer to place transport object
 * RETURNS:
 *     Status of operation
 */
{
	PFILE_FULL_EA_INFORMATION EaInfo;
	PTA_IP_ADDRESS Address;
	NTSTATUS Status;
	ULONG EaLength;

	/* EaName must be 0-termed, even though TDI_TRANSPORT_ADDRESS_LENGTH does *not* include the 0 */
	EaLength = sizeof(FILE_FULL_EA_INFORMATION) + TDI_TRANSPORT_ADDRESS_LENGTH + sizeof(TA_IP_ADDRESS) + 1;
	EaInfo = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(NonPagedPool, EaLength);

	if (!EaInfo)
		{
			TDI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
			return STATUS_INSUFFICIENT_RESOURCES;
		}

	RtlZeroMemory(EaInfo, EaLength);

	EaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;

	/* don't copy the 0; we have already zeroed it */
	RtlCopyMemory(EaInfo->EaName, TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH);

	EaInfo->EaValueLength = sizeof(TA_IP_ADDRESS);
	Address = (PTA_IP_ADDRESS)(EaInfo->EaName + TDI_TRANSPORT_ADDRESS_LENGTH + 1); // 0-term
	Address->TAAddressCount                 = 1;
	Address->Address[0].AddressLength       = TDI_ADDRESS_LENGTH_IP;
	Address->Address[0].AddressType         = TDI_ADDRESS_TYPE_IP;
	Address->Address[0].Address[0].sin_port = WH2N(Port);
	Address->Address[0].Address[0].in_addr  = 0;

	Status = TdiOpenDevice(Protocol, EaLength, EaInfo, Transport, TransportObject);

	ExFreePool(EaInfo);

	return Status;
}


NTSTATUS TdiQueryDeviceControl(
    PFILE_OBJECT FileObject,
    ULONG IoControlCode,
    PVOID InputBuffer,
    ULONG InputBufferLength,
    PVOID OutputBuffer,
    ULONG OutputBufferLength,
    PULONG Return)
/*
 * FUNCTION: Queries a device for information
 * ARGUMENTS:
 *     FileObject         = Pointer to device object
 *     IoControlCode      = I/O control code
 *     InputBuffer        = Pointer to buffer with input data
 *     InputBufferLength  = Length of InputBuffer
 *     OutputBuffer       = Address of buffer to place output data
 *     OutputBufferLength = Length of OutputBuffer
 * RETURNS:
 *     Status of operation
 */
{
	PDEVICE_OBJECT DeviceObject;
	PIO_STACK_LOCATION IoStack;
	IO_STATUS_BLOCK Iosb;
	NTSTATUS Status;
	PIRP Irp;

	DeviceObject = IoGetRelatedDeviceObject(FileObject);
	Irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceObject, InputBuffer, InputBufferLength, OutputBuffer,
		OutputBufferLength, FALSE, NULL, NULL);

	if (!Irp)
		{
			TDI_DbgPrint(MIN_TRACE, ("IoBuildDeviceIoControlRequest() failed.\n"));
			return STATUS_INSUFFICIENT_RESOURCES;
		}

	IoStack               = IoGetNextIrpStackLocation(Irp);
	IoStack->DeviceObject = DeviceObject;
	IoStack->FileObject   = FileObject;
	Status = TdiCall(Irp, DeviceObject, &Iosb, FALSE);

	if (Return)
		*Return = Iosb.Information;

	return Status;
}


NTSTATUS TdiQueryInformationEx(
    PFILE_OBJECT FileObject,
    ULONG Entity,
    ULONG Instance,
    ULONG Class,
    ULONG Type,
    ULONG Id,
    PVOID OutputBuffer,
    PULONG OutputLength)
/*
 * FUNCTION: Extended query for information
 * ARGUMENTS:
 *     FileObject   = Pointer to transport object
 *     Entity       = Entity
 *     Instance     = Instance
 *     Class        = Entity class
 *     Type         = Entity type
 *     Id           = Entity id
 *     OutputBuffer = Address of buffer to place data
 *     OutputLength = Address of buffer with length of OutputBuffer (updated)
 * RETURNS:
 *     Status of operation
 */
{
 	TCP_REQUEST_QUERY_INFORMATION_EX QueryInfo;

	RtlZeroMemory(&QueryInfo, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
	QueryInfo.ID.toi_entity.tei_entity   = Entity;
	QueryInfo.ID.toi_entity.tei_instance = Instance;
	QueryInfo.ID.toi_class = Class;
	QueryInfo.ID.toi_type  = Type;
	QueryInfo.ID.toi_id    = Id;

	return TdiQueryDeviceControl(
		FileObject,                                /* Transport/connection object */
		IOCTL_TCP_QUERY_INFORMATION_EX,            /* Control code */
		&QueryInfo,                                /* Input buffer */
		sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),  /* Input buffer length */
		OutputBuffer,                              /* Output buffer */
		*OutputLength,                             /* Output buffer length */
		OutputLength);                             /* Return information */
}


NTSTATUS TdiQueryAddress(
    PFILE_OBJECT FileObject,
    PULONG Address)
/*
 * FUNCTION: Queries for a local IP address
 * ARGUMENTS:
 *     FileObject = Pointer to file object
 *     Address    = Address of buffer to place local address
 * RETURNS:
 *     Status of operation
 */
{
	ULONG i;
	TDIEntityID *Entities;
	ULONG EntityCount;
	ULONG EntityType;
	IPSNMP_INFO SnmpInfo;
	PIPADDR_ENTRY IpAddress;
	ULONG BufferSize;
	NTSTATUS Status = STATUS_SUCCESS;

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

	BufferSize = sizeof(TDIEntityID) * 20;
	Entities   = (TDIEntityID*)ExAllocatePool(NonPagedPool, BufferSize);

	if (!Entities)
		{
			TDI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
			return STATUS_INSUFFICIENT_RESOURCES;
		}

	/* Query device for supported entities */
	Status = TdiQueryInformationEx(
		FileObject,          /* File object */
		GENERIC_ENTITY,      /* Entity */
		TL_INSTANCE,         /* Instance */
		INFO_CLASS_GENERIC,  /* Entity class */
		INFO_TYPE_PROVIDER,  /* Entity type */
		ENTITY_LIST_ID,      /* Entity id */
		Entities,            /* Output buffer */
		&BufferSize);        /* Output buffer size */

	if (!NT_SUCCESS(Status))
		{
			TDI_DbgPrint(MIN_TRACE, ("Unable to get list of supported entities (Status = 0x%X).\n", Status));
			ExFreePool(Entities);
			return Status;
		}

	/* Locate an IP entity */
	EntityCount = BufferSize / sizeof(TDIEntityID);

	TDI_DbgPrint(MAX_TRACE, ("EntityCount = %d\n", EntityCount));

	for (i = 0; i < EntityCount; i++)
		{
			if (Entities[i].tei_entity == CL_NL_ENTITY)
				{
					/* Query device for entity type */
					BufferSize = sizeof(EntityType);
					Status = TdiQueryInformationEx(
						FileObject,                  /* File object */
						CL_NL_ENTITY,                /* Entity */
						Entities[i].tei_instance,    /* Instance */
						INFO_CLASS_GENERIC,          /* Entity class */
						INFO_TYPE_PROVIDER,          /* Entity type */
						ENTITY_TYPE_ID,              /* Entity id */
						&EntityType,                 /* Output buffer */
						&BufferSize);                /* Output buffer size */

					if (!NT_SUCCESS(Status) || (EntityType != CL_NL_IP))
						{
							TDI_DbgPrint(MIN_TRACE, ("Unable to get entity of type IP (Status = 0x%X).\n", Status));
							break;
						}

					/* Query device for SNMP information */
					BufferSize = sizeof(SnmpInfo);
 					Status = TdiQueryInformationEx(
						FileObject,                  /* File object */
						CL_NL_ENTITY,                /* Entity */
						Entities[i].tei_instance,    /* Instance */
						INFO_CLASS_PROTOCOL,         /* Entity class */
						INFO_TYPE_PROVIDER,          /* Entity type */
						IP_MIB_STATS_ID,             /* Entity id */
						&SnmpInfo,                   /* Output buffer */
						&BufferSize);                /* Output buffer size */

					if (!NT_SUCCESS(Status) || (SnmpInfo.NumAddr == 0))
						{
							TDI_DbgPrint(MIN_TRACE, ("Unable to get SNMP information or no IP addresses available (Status = 0x%X).\n", Status));
							break;
						}

					/* Query device for all IP addresses */
					if (SnmpInfo.NumAddr != 0)
						{
							BufferSize = SnmpInfo.NumAddr * sizeof(IPADDR_ENTRY);
							IpAddress = (PIPADDR_ENTRY)ExAllocatePool(NonPagedPool, BufferSize);
							if (!IpAddress)
								{
									TDI_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
									break;
								}

						Status = TdiQueryInformationEx(
							FileObject,                  /* File object */
							CL_NL_ENTITY,                /* Entity */
							Entities[i].tei_instance,    /* Instance */
							INFO_CLASS_PROTOCOL,         /* Entity class */
							INFO_TYPE_PROVIDER,          /* Entity type */
							IP_MIB_ADDRTABLE_ENTRY_ID,   /* Entity id */
							IpAddress,                   /* Output buffer */
							&BufferSize);                /* Output buffer size */

						if (!NT_SUCCESS(Status))
							{
								TDI_DbgPrint(MIN_TRACE, ("Unable to get IP address (Status = 0x%X).\n", Status));
								ExFreePool(IpAddress);
								break;
							}

						if (SnmpInfo.NumAddr != 1)
							{
								/* Skip loopback address */
								*Address = DN2H(((PIPADDR_ENTRY)((ULONG)IpAddress + sizeof(IPADDR_ENTRY)))->Addr);
							}
						else
							{
								/* Select the first address returned */
								*Address = DN2H(IpAddress->Addr);
							}
								ExFreePool(IpAddress);

						}
					else
						{
							Status = STATUS_UNSUCCESSFUL;
							break;
					}
			}
	}

	ExFreePool(Entities);

	TDI_DbgPrint(MAX_TRACE, ("Leaving\n"));

	return Status;
}


NTSTATUS TdiSendDatagram(
    PFILE_OBJECT TransportObject,
    USHORT Port,
    ULONG Address,
    PVOID Buffer,
    ULONG BufferSize)
/*
 * FUNCTION: Sends a datagram
 * ARGUMENTS:
 *     TransportObject = Pointer to transport object
 *     Port            = Remote port
 *     Address         = Remote address

⌨️ 快捷键说明

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