[KMTESTS/TCPIP]
[reactos.git] / rostests / kmtests / tcpip / tdi.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: LGPLv2+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite for TCPIP.sys
5 * PROGRAMMER: Jérôme Gardou <jerome.gardou@reactos.org>
6 */
7
8 #include <kmt_test.h>
9 #include <tdikrnl.h>
10
11 static
12 NTSTATUS
13 NTAPI
14 IrpCompletionRoutine(
15 _In_ PDEVICE_OBJECT DeviceObject,
16 _In_ PIRP Irp,
17 _In_ PVOID Context)
18 {
19 UNREFERENCED_PARAMETER(DeviceObject);
20 UNREFERENCED_PARAMETER(Irp);
21
22 KeSetEvent((PKEVENT)Context, IO_NETWORK_INCREMENT, FALSE);
23
24 return STATUS_MORE_PROCESSING_REQUIRED;
25 }
26
27 static
28 VOID
29 TestProviderInfo(void)
30 {
31 struct
32 {
33 UNICODE_STRING DeviceName;
34 NTSTATUS CreateStatus, IrpStatus;
35 TDI_PROVIDER_INFO ExpectedInfo;
36 } TestData[] =
37 {
38 {
39 RTL_CONSTANT_STRING(L"\\Device\\Tcp"),
40 STATUS_SUCCESS, STATUS_SUCCESS,
41 {
42 0x0002, // Version
43 0x3FFFFFFF, // MaxSendSize
44 0, // MaxConnectionUserData
45 65515, // MaxDatagramSize
46 TDI_SERVICE_CONNECTION_MODE |
47 TDI_SERVICE_ORDERLY_RELEASE |
48 TDI_SERVICE_CONNECTIONLESS_MODE |
49 TDI_SERVICE_ERROR_FREE_DELIVERY |
50 TDI_SERVICE_BROADCAST_SUPPORTED |
51 TDI_SERVICE_DELAYED_ACCEPTANCE |
52 TDI_SERVICE_EXPEDITED_DATA |
53 TDI_SERVICE_NO_ZERO_LENGTH |
54 TDI_SERVICE_DGRAM_CONNECTION |
55 TDI_SERVICE_FORCE_ACCESS_CHECK |
56 TDI_SERVICE_DIRECT_ACCEPT |
57 TDI_SERVICE_ADDRESS_SECURITY |
58 TDI_SERVICE_NO_PUSH, // ServiceFlags
59 1, // MinimumLookaheadData
60 65535, // MaximumLookaheadData
61 0, // NumberOfResources
62 {{0}} // StartTime
63 }
64 },
65 {
66 RTL_CONSTANT_STRING(L"\\Device\\Udp"),
67 STATUS_SUCCESS, STATUS_SUCCESS,
68 {
69 0x0002, // Version
70 0x3FFFFFFF, // MaxSendSize
71 0, // MaxConnectionUserData
72 65507, // MaxDatagramSize
73 TDI_SERVICE_CONNECTION_MODE |
74 TDI_SERVICE_ORDERLY_RELEASE |
75 TDI_SERVICE_CONNECTIONLESS_MODE |
76 TDI_SERVICE_ERROR_FREE_DELIVERY |
77 TDI_SERVICE_BROADCAST_SUPPORTED |
78 TDI_SERVICE_DELAYED_ACCEPTANCE |
79 TDI_SERVICE_EXPEDITED_DATA |
80 TDI_SERVICE_NO_ZERO_LENGTH |
81 TDI_SERVICE_DGRAM_CONNECTION |
82 TDI_SERVICE_FORCE_ACCESS_CHECK |
83 TDI_SERVICE_DIRECT_ACCEPT |
84 TDI_SERVICE_ADDRESS_SECURITY, // ServiceFlags
85 1, // MinimumLookaheadData
86 65535, // MaximumLookaheadData
87 0, // NumberOfResources
88 {{0}} // StartTime
89 }
90 },
91 {
92 RTL_CONSTANT_STRING(L"\\Device\\Ip"),
93 STATUS_SUCCESS, STATUS_NOT_IMPLEMENTED,
94 },
95 {
96 RTL_CONSTANT_STRING(L"\\Device\\RawIp"),
97 STATUS_SUCCESS, STATUS_SUCCESS,
98 {
99 0x0002, // Version
100 0x3FFFFFFF, // MaxSendSize
101 0, // MaxConnectionUserData
102 65515, // MaxDatagramSize
103 TDI_SERVICE_CONNECTION_MODE |
104 TDI_SERVICE_ORDERLY_RELEASE |
105 TDI_SERVICE_CONNECTIONLESS_MODE |
106 TDI_SERVICE_ERROR_FREE_DELIVERY |
107 TDI_SERVICE_BROADCAST_SUPPORTED |
108 TDI_SERVICE_DELAYED_ACCEPTANCE |
109 TDI_SERVICE_EXPEDITED_DATA |
110 TDI_SERVICE_NO_ZERO_LENGTH |
111 TDI_SERVICE_DGRAM_CONNECTION |
112 TDI_SERVICE_FORCE_ACCESS_CHECK |
113 TDI_SERVICE_DIRECT_ACCEPT |
114 TDI_SERVICE_ADDRESS_SECURITY, // ServiceFlags
115 1, // MinimumLookaheadData
116 65535, // MaximumLookaheadData
117 0, // NumberOfResources
118 {{0}} // StartTime
119 }
120 },
121 {
122 RTL_CONSTANT_STRING(L"\\Device\\IPMULTICAST"),
123 STATUS_OBJECT_NAME_NOT_FOUND,
124 },
125 };
126 ULONG i;
127
128 for (i = 0; i < (sizeof(TestData) / sizeof(TestData[0])); i++)
129 {
130 IO_STATUS_BLOCK StatusBlock;
131 NTSTATUS Status;
132 FILE_OBJECT* FileObject;
133 DEVICE_OBJECT* DeviceObject;
134 PIRP Irp;
135 KEVENT Event;
136 PMDL Mdl;
137 TDI_PROVIDER_INFO* ProviderInfo;
138 HANDLE FileHandle;
139 OBJECT_ATTRIBUTES ObjectAttributes;
140
141 trace("Testing device %wZ\n", &TestData[i].DeviceName);
142
143 InitializeObjectAttributes(
144 &ObjectAttributes,
145 &TestData[i].DeviceName,
146 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
147 NULL,
148 NULL);
149
150 Status = ZwCreateFile(
151 &FileHandle,
152 FILE_READ_DATA | FILE_WRITE_DATA,
153 &ObjectAttributes,
154 &StatusBlock,
155 NULL,
156 FILE_ATTRIBUTE_NORMAL,
157 FILE_SHARE_READ | FILE_SHARE_WRITE,
158 FILE_OPEN,
159 0,
160 NULL,
161 0);
162 ok_eq_hex(Status, TestData[i].CreateStatus);
163 if (!NT_SUCCESS(Status))
164 continue;
165
166 Status = ObReferenceObjectByHandle(
167 FileHandle,
168 GENERIC_READ,
169 *IoFileObjectType,
170 KernelMode,
171 (PVOID*)&FileObject,
172 NULL);
173 ok_eq_hex(Status, STATUS_SUCCESS);
174 if (!NT_SUCCESS(Status))
175 return;
176
177 DeviceObject = IoGetRelatedDeviceObject(FileObject);
178 ok(DeviceObject != NULL, "Device object is NULL!\n");
179 if (!DeviceObject)
180 {
181 ObDereferenceObject(FileObject);
182 return;
183 }
184
185 ProviderInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ProviderInfo), 'tseT');
186 ok(ProviderInfo != NULL, "Ran out of memory.\n");
187 if (!ProviderInfo)
188 {
189 ObDereferenceObject(FileObject);
190 return;
191 }
192
193 Mdl = IoAllocateMdl(ProviderInfo, sizeof(*ProviderInfo), FALSE, FALSE, NULL);
194 ok(Mdl != NULL, "Could not allocate the MDL!\n");
195 if (!Mdl)
196 {
197 ExFreePoolWithTag(ProviderInfo, 'tseT');
198 ObDereferenceObject(FileObject);
199 return;
200 }
201
202 MmBuildMdlForNonPagedPool(Mdl);
203
204 /* Build the IRP */
205 KeInitializeEvent(&Event, NotificationEvent, FALSE);
206 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
207 ok(Irp != NULL, "TdiBuildInternalDeviceControlIrp returned NULL!\n");
208 if (!Irp)
209 {
210 IoFreeMdl(Mdl);
211 ExFreePoolWithTag(ProviderInfo, 'tseT');
212 ObDereferenceObject(FileObject);
213 return;
214 }
215
216 TdiBuildQueryInformation(
217 Irp,
218 DeviceObject,
219 FileObject,
220 NULL,
221 NULL,
222 TDI_QUERY_PROVIDER_INFO,
223 Mdl);
224
225 IoSetCompletionRoutine(Irp, IrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
226
227 Status = IoCallDriver(DeviceObject, Irp);
228 if (Status == STATUS_PENDING)
229 {
230 KeWaitForSingleObject(
231 &Event,
232 Executive,
233 KernelMode,
234 FALSE,
235 NULL);
236 Status = StatusBlock.Status;
237 }
238 ok_eq_hex(Status, TestData[i].IrpStatus);
239
240 IoFreeIrp(Irp);
241 IoFreeMdl(Mdl);
242 ObDereferenceObject(FileObject);
243
244 if (!NT_SUCCESS(Status))
245 {
246 ExFreePoolWithTag(ProviderInfo, 'tseT');
247 continue;
248 }
249
250 ok_eq_hex(ProviderInfo->Version, TestData[i].ExpectedInfo.Version);
251 ok_eq_ulong(ProviderInfo->MaxSendSize, TestData[i].ExpectedInfo.MaxSendSize);
252 ok_eq_ulong(ProviderInfo->MaxConnectionUserData, TestData[i].ExpectedInfo.MaxConnectionUserData);
253 ok_eq_ulong(ProviderInfo->MaxDatagramSize, TestData[i].ExpectedInfo.MaxDatagramSize);
254 ok_eq_hex(ProviderInfo->ServiceFlags, TestData[i].ExpectedInfo.ServiceFlags);
255 ok_eq_ulong(ProviderInfo->MinimumLookaheadData, TestData[i].ExpectedInfo.MinimumLookaheadData);
256 ok_eq_ulong(ProviderInfo->MaximumLookaheadData, TestData[i].ExpectedInfo.MaximumLookaheadData);
257 ok_eq_ulong(ProviderInfo->NumberOfResources, TestData[i].ExpectedInfo.NumberOfResources);
258
259 ExFreePoolWithTag(ProviderInfo, 'tseT');
260 }
261 }
262
263 static KSTART_ROUTINE RunTest;
264 static
265 VOID
266 NTAPI
267 RunTest(
268 _In_ PVOID Context)
269 {
270 UNREFERENCED_PARAMETER(Context);
271
272 TestProviderInfo();
273 }
274
275 KMT_MESSAGE_HANDLER TestTdi;
276 NTSTATUS
277 TestTdi(
278 _In_ PDEVICE_OBJECT DeviceObject,
279 _In_ ULONG ControlCode,
280 _In_opt_ PVOID Buffer,
281 _In_ SIZE_T InLength,
282 _Inout_ PSIZE_T OutLength
283 )
284 {
285 PKTHREAD Thread;
286
287 Thread = KmtStartThread(RunTest, NULL);
288 KmtFinishThread(Thread, NULL);
289
290 return STATUS_SUCCESS;
291 }