--- /dev/null
+/*
+ * PROJECT: ReactOS kernel-mode tests
+ * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
+ * PURPOSE: Kernel-Mode Test Suite for TCPIP.sys
+ * PROGRAMMER: Jérôme Gardou <jerome.gardou@reactos.org>
+ */
+
+#include <kmt_test.h>
+#include <tdikrnl.h>
+
+static
+NTAPI
+NTSTATUS
+IrpCompletionRoutine(
+ _In_ PDEVICE_OBJECT DeviceObject,
+ _In_ PIRP Irp,
+ _In_ PVOID Context)
+{
+ UNREFERENCED_PARAMETER(DeviceObject);
+ UNREFERENCED_PARAMETER(Irp);
+
+ KeSetEvent((PKEVENT)Context, IO_NETWORK_INCREMENT, FALSE);
+
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+static
+VOID
+TestProviderInfo(void)
+{
+ struct
+ {
+ UNICODE_STRING DeviceName;
+ NTSTATUS CreateStatus, IrpStatus;
+ TDI_PROVIDER_INFO ExpectedInfo;
+ } TestData[] =
+ {
+ {
+ RTL_CONSTANT_STRING(L"\\Device\\Tcp"),
+ STATUS_SUCCESS, STATUS_SUCCESS,
+ {
+ 0x0002, // Version
+ 0x3FFFFFFF, // MaxSendSize
+ 0, // MaxConnectionUserData
+ 65515, // MaxDatagramSize
+ TDI_SERVICE_CONNECTION_MODE |
+ TDI_SERVICE_ORDERLY_RELEASE |
+ TDI_SERVICE_CONNECTIONLESS_MODE |
+ TDI_SERVICE_ERROR_FREE_DELIVERY |
+ TDI_SERVICE_BROADCAST_SUPPORTED |
+ TDI_SERVICE_DELAYED_ACCEPTANCE |
+ TDI_SERVICE_EXPEDITED_DATA |
+ TDI_SERVICE_NO_ZERO_LENGTH |
+ TDI_SERVICE_DGRAM_CONNECTION |
+ TDI_SERVICE_FORCE_ACCESS_CHECK |
+ TDI_SERVICE_DIRECT_ACCEPT |
+ TDI_SERVICE_ADDRESS_SECURITY |
+ TDI_SERVICE_NO_PUSH, // ServiceFlags
+ 1, // MinimumLookaheadData
+ 65535, // MaximumLookaheadData
+ 0, // NumberOfResources
+ {{0}} // StartTime
+ }
+ },
+ {
+ RTL_CONSTANT_STRING(L"\\Device\\Udp"),
+ STATUS_SUCCESS, STATUS_SUCCESS,
+ {
+ 0x0002, // Version
+ 0x3FFFFFFF, // MaxSendSize
+ 0, // MaxConnectionUserData
+ 65507, // MaxDatagramSize
+ TDI_SERVICE_CONNECTION_MODE |
+ TDI_SERVICE_ORDERLY_RELEASE |
+ TDI_SERVICE_CONNECTIONLESS_MODE |
+ TDI_SERVICE_ERROR_FREE_DELIVERY |
+ TDI_SERVICE_BROADCAST_SUPPORTED |
+ TDI_SERVICE_DELAYED_ACCEPTANCE |
+ TDI_SERVICE_EXPEDITED_DATA |
+ TDI_SERVICE_NO_ZERO_LENGTH |
+ TDI_SERVICE_DGRAM_CONNECTION |
+ TDI_SERVICE_FORCE_ACCESS_CHECK |
+ TDI_SERVICE_DIRECT_ACCEPT |
+ TDI_SERVICE_ADDRESS_SECURITY, // ServiceFlags
+ 1, // MinimumLookaheadData
+ 65535, // MaximumLookaheadData
+ 0, // NumberOfResources
+ {{0}} // StartTime
+ }
+ },
+ {
+ RTL_CONSTANT_STRING(L"\\Device\\Ip"),
+ STATUS_SUCCESS, STATUS_NOT_IMPLEMENTED,
+ },
+ {
+ RTL_CONSTANT_STRING(L"\\Device\\RawIp"),
+ STATUS_SUCCESS, STATUS_SUCCESS,
+ {
+ 0x0002, // Version
+ 0x3FFFFFFF, // MaxSendSize
+ 0, // MaxConnectionUserData
+ 65515, // MaxDatagramSize
+ TDI_SERVICE_CONNECTION_MODE |
+ TDI_SERVICE_ORDERLY_RELEASE |
+ TDI_SERVICE_CONNECTIONLESS_MODE |
+ TDI_SERVICE_ERROR_FREE_DELIVERY |
+ TDI_SERVICE_BROADCAST_SUPPORTED |
+ TDI_SERVICE_DELAYED_ACCEPTANCE |
+ TDI_SERVICE_EXPEDITED_DATA |
+ TDI_SERVICE_NO_ZERO_LENGTH |
+ TDI_SERVICE_DGRAM_CONNECTION |
+ TDI_SERVICE_FORCE_ACCESS_CHECK |
+ TDI_SERVICE_DIRECT_ACCEPT |
+ TDI_SERVICE_ADDRESS_SECURITY, // ServiceFlags
+ 1, // MinimumLookaheadData
+ 65535, // MaximumLookaheadData
+ 0, // NumberOfResources
+ {{0}} // StartTime
+ }
+ },
+ {
+ RTL_CONSTANT_STRING(L"\\Device\\IPMULTICAST"),
+ STATUS_OBJECT_NAME_NOT_FOUND,
+ },
+ };
+ ULONG i;
+
+ for (i = 0; i < (sizeof(TestData) / sizeof(TestData[0])); i++)
+ {
+ IO_STATUS_BLOCK StatusBlock;
+ NTSTATUS Status;
+ FILE_OBJECT* FileObject;
+ DEVICE_OBJECT* DeviceObject;
+ PIRP Irp;
+ KEVENT Event;
+ PMDL Mdl;
+ TDI_PROVIDER_INFO* ProviderInfo;
+ HANDLE FileHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+
+ trace("Testing device %wZ\n", &TestData[i].DeviceName);
+
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &TestData[i].DeviceName,
+ OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ Status = ZwCreateFile(
+ &FileHandle,
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ &ObjectAttributes,
+ &StatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_OPEN,
+ 0,
+ NULL,
+ 0);
+ ok_eq_hex(Status, TestData[i].CreateStatus);
+ if (!NT_SUCCESS(Status))
+ continue;
+
+ Status = ObReferenceObjectByHandle(
+ FileHandle,
+ GENERIC_READ,
+ *IoFileObjectType,
+ KernelMode,
+ (PVOID*)&FileObject,
+ NULL);
+ ok_eq_hex(Status, STATUS_SUCCESS);
+ if (!NT_SUCCESS(Status))
+ return;
+
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ ok(DeviceObject != NULL, "Device object is NULL!\n");
+ if (!DeviceObject)
+ {
+ ObDereferenceObject(FileObject);
+ return;
+ }
+
+ ProviderInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ProviderInfo), 'tseT');
+ ok(ProviderInfo != NULL, "Ran out of memory.\n");
+ if (!ProviderInfo)
+ {
+ ObDereferenceObject(FileObject);
+ return;
+ }
+
+ Mdl = IoAllocateMdl(ProviderInfo, sizeof(*ProviderInfo), FALSE, FALSE, NULL);
+ ok(Mdl != NULL, "Could not allocate the MDL!\n");
+ if (!Mdl)
+ {
+ ExFreePoolWithTag(ProviderInfo, 'tseT');
+ ObDereferenceObject(FileObject);
+ return;
+ }
+
+ MmBuildMdlForNonPagedPool(Mdl);
+
+ /* Build the IRP */
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
+ ok(Irp != NULL, "TdiBuildInternalDeviceControlIrp returned NULL!\n");
+ if (!Irp)
+ {
+ IoFreeMdl(Mdl);
+ ExFreePoolWithTag(ProviderInfo, 'tseT');
+ ObDereferenceObject(FileObject);
+ return;
+ }
+
+ TdiBuildQueryInformation(
+ Irp,
+ DeviceObject,
+ FileObject,
+ NULL,
+ NULL,
+ TDI_QUERY_PROVIDER_INFO,
+ Mdl);
+
+ IoSetCompletionRoutine(Irp, IrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
+
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ KeWaitForSingleObject(
+ &Event,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ Status = StatusBlock.Status;
+ }
+ ok_eq_hex(Status, TestData[i].IrpStatus);
+
+ IoFreeIrp(Irp);
+ IoFreeMdl(Mdl);
+ ObDereferenceObject(FileObject);
+
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(ProviderInfo, 'tseT');
+ continue;
+ }
+
+ ok_eq_hex(ProviderInfo->Version, TestData[i].ExpectedInfo.Version);
+ ok_eq_ulong(ProviderInfo->MaxSendSize, TestData[i].ExpectedInfo.MaxSendSize);
+ ok_eq_ulong(ProviderInfo->MaxConnectionUserData, TestData[i].ExpectedInfo.MaxConnectionUserData);
+ ok_eq_ulong(ProviderInfo->MaxDatagramSize, TestData[i].ExpectedInfo.MaxDatagramSize);
+ ok_eq_hex(ProviderInfo->ServiceFlags, TestData[i].ExpectedInfo.ServiceFlags);
+ ok_eq_ulong(ProviderInfo->MinimumLookaheadData, TestData[i].ExpectedInfo.MinimumLookaheadData);
+ ok_eq_ulong(ProviderInfo->MaximumLookaheadData, TestData[i].ExpectedInfo.MaximumLookaheadData);
+ ok_eq_ulong(ProviderInfo->NumberOfResources, TestData[i].ExpectedInfo.NumberOfResources);
+
+ ExFreePoolWithTag(ProviderInfo, 'tseT');
+ }
+}
+
+static KSTART_ROUTINE RunTest;
+static
+VOID
+NTAPI
+RunTest(
+ _In_ PVOID Context)
+{
+ UNREFERENCED_PARAMETER(Context);
+
+ TestProviderInfo();
+}
+
+KMT_MESSAGE_HANDLER TestTdi;
+NTSTATUS
+TestTdi(
+ _In_ PDEVICE_OBJECT DeviceObject,
+ _In_ ULONG ControlCode,
+ _In_opt_ PVOID Buffer,
+ _In_ SIZE_T InLength,
+ _Inout_ PSIZE_T OutLength
+)
+{
+ PKTHREAD Thread;
+
+ Thread = KmtStartThread(RunTest, NULL);
+ KmtFinishThread(Thread, NULL);
+
+ return STATUS_SUCCESS;
+}