[KMTEST/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 0x0100, // Version
43 0xFFFFFFFF, // MaxSendSize
44 0, // MaxConnectionUserData
45 65507, // 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_SEND_AND_DISCONNECT |
57 TDI_SERVICE_ACCEPT_LOCAL_ADDR |
58 TDI_SERVICE_ADDRESS_SECURITY |
59 TDI_SERVICE_PREPOST_RECVS |
60 TDI_SERVICE_NO_PUSH, // ServiceFlags
61 1, // MinimumLookaheadData
62 65535, // MaximumLookaheadData
63 0, // NumberOfResources
64 {{0}} // StartTime
65 }
66 },
67 {
68 RTL_CONSTANT_STRING(L"\\Device\\Udp"),
69 STATUS_SUCCESS, STATUS_SUCCESS,
70 {
71 0x0100, // Version
72 0xFFFFFFFF, // MaxSendSize
73 0, // MaxConnectionUserData
74 65507, // MaxDatagramSize
75 TDI_SERVICE_CONNECTION_MODE |
76 TDI_SERVICE_ORDERLY_RELEASE |
77 TDI_SERVICE_CONNECTIONLESS_MODE |
78 TDI_SERVICE_ERROR_FREE_DELIVERY |
79 TDI_SERVICE_BROADCAST_SUPPORTED |
80 TDI_SERVICE_DELAYED_ACCEPTANCE |
81 TDI_SERVICE_EXPEDITED_DATA |
82 TDI_SERVICE_NO_ZERO_LENGTH |
83 TDI_SERVICE_DGRAM_CONNECTION |
84 TDI_SERVICE_FORCE_ACCESS_CHECK |
85 TDI_SERVICE_SEND_AND_DISCONNECT |
86 TDI_SERVICE_ACCEPT_LOCAL_ADDR |
87 TDI_SERVICE_ADDRESS_SECURITY |
88 TDI_SERVICE_PREPOST_RECVS |
89 TDI_SERVICE_NO_PUSH, // ServiceFlags
90 1, // MinimumLookaheadData
91 65535, // MaximumLookaheadData
92 0, // NumberOfResources
93 {{0}} // StartTime
94 }
95 },
96 {
97 RTL_CONSTANT_STRING(L"\\Device\\Ip"),
98 STATUS_SUCCESS, STATUS_NOT_IMPLEMENTED,
99 },
100 {
101 RTL_CONSTANT_STRING(L"\\Device\\RawIp"),
102 STATUS_SUCCESS, STATUS_SUCCESS,
103 {
104 0x0100, // Version
105 0xFFFFFFFF, // MaxSendSize
106 0, // MaxConnectionUserData
107 65507, // MaxDatagramSize
108 TDI_SERVICE_CONNECTION_MODE |
109 TDI_SERVICE_ORDERLY_RELEASE |
110 TDI_SERVICE_CONNECTIONLESS_MODE |
111 TDI_SERVICE_ERROR_FREE_DELIVERY |
112 TDI_SERVICE_BROADCAST_SUPPORTED |
113 TDI_SERVICE_DELAYED_ACCEPTANCE |
114 TDI_SERVICE_EXPEDITED_DATA |
115 TDI_SERVICE_NO_ZERO_LENGTH |
116 TDI_SERVICE_DGRAM_CONNECTION |
117 TDI_SERVICE_FORCE_ACCESS_CHECK |
118 TDI_SERVICE_SEND_AND_DISCONNECT |
119 TDI_SERVICE_ACCEPT_LOCAL_ADDR |
120 TDI_SERVICE_ADDRESS_SECURITY |
121 TDI_SERVICE_PREPOST_RECVS |
122 TDI_SERVICE_NO_PUSH, // ServiceFlags
123 1, // MinimumLookaheadData
124 65535, // MaximumLookaheadData
125 0, // NumberOfResources
126 {{0}} // StartTime
127 }
128 },
129 {
130 RTL_CONSTANT_STRING(L"\\Device\\IPMULTICAST"),
131 STATUS_SUCCESS, STATUS_INVALID_PARAMETER,
132 },
133 };
134 ULONG i;
135
136 for (i = 0; i < (sizeof(TestData) / sizeof(TestData[0])); i++)
137 {
138 IO_STATUS_BLOCK StatusBlock;
139 NTSTATUS Status;
140 FILE_OBJECT* FileObject;
141 DEVICE_OBJECT* DeviceObject;
142 PIRP Irp;
143 KEVENT Event;
144 PMDL Mdl;
145 TDI_PROVIDER_INFO* ProviderInfo;
146 HANDLE FileHandle;
147 OBJECT_ATTRIBUTES ObjectAttributes;
148
149 trace("Testing device %wZ\n", &TestData[i].DeviceName);
150
151 InitializeObjectAttributes(
152 &ObjectAttributes,
153 &TestData[i].DeviceName,
154 OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
155 NULL,
156 NULL);
157
158 Status = ZwCreateFile(
159 &FileHandle,
160 FILE_READ_DATA | FILE_WRITE_DATA,
161 &ObjectAttributes,
162 &StatusBlock,
163 NULL,
164 FILE_ATTRIBUTE_NORMAL,
165 FILE_SHARE_READ | FILE_SHARE_WRITE,
166 FILE_OPEN,
167 0,
168 NULL,
169 0);
170 ok_eq_hex(Status, TestData[i].CreateStatus);
171 if (!NT_SUCCESS(Status))
172 continue;
173
174 Status = ObReferenceObjectByHandle(
175 FileHandle,
176 GENERIC_READ,
177 *IoFileObjectType,
178 KernelMode,
179 (PVOID*)&FileObject,
180 NULL);
181 ok_eq_hex(Status, STATUS_SUCCESS);
182 if (!NT_SUCCESS(Status))
183 return;
184
185 DeviceObject = IoGetRelatedDeviceObject(FileObject);
186 ok(DeviceObject != NULL, "Device object is NULL!\n");
187 if (!DeviceObject)
188 {
189 ObDereferenceObject(FileObject);
190 return;
191 }
192
193 ProviderInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ProviderInfo), 'tseT');
194 ok(ProviderInfo != NULL, "Ran out of memory.\n");
195 if (!ProviderInfo)
196 {
197 ObDereferenceObject(FileObject);
198 return;
199 }
200
201 Mdl = IoAllocateMdl(ProviderInfo, sizeof(*ProviderInfo), FALSE, FALSE, NULL);
202 ok(Mdl != NULL, "Could not allocate the MDL!\n");
203 if (!Mdl)
204 {
205 ExFreePoolWithTag(ProviderInfo, 'tseT');
206 ObDereferenceObject(FileObject);
207 return;
208 }
209
210 MmBuildMdlForNonPagedPool(Mdl);
211
212 /* Build the IRP */
213 KeInitializeEvent(&Event, NotificationEvent, FALSE);
214 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
215 ok(Irp != NULL, "TdiBuildInternalDeviceControlIrp returned NULL!\n");
216 if (!Irp)
217 {
218 IoFreeMdl(Mdl);
219 ExFreePoolWithTag(ProviderInfo, 'tseT');
220 ObDereferenceObject(FileObject);
221 return;
222 }
223
224 TdiBuildQueryInformation(
225 Irp,
226 DeviceObject,
227 FileObject,
228 NULL,
229 NULL,
230 TDI_QUERY_PROVIDER_INFO,
231 Mdl);
232
233 IoSetCompletionRoutine(Irp, IrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
234
235 Status = IoCallDriver(DeviceObject, Irp);
236 if (Status == STATUS_PENDING)
237 {
238 KeWaitForSingleObject(
239 &Event,
240 Executive,
241 KernelMode,
242 FALSE,
243 NULL);
244 Status = StatusBlock.Status;
245 }
246 ok_eq_hex(Status, TestData[i].IrpStatus);
247
248 IoFreeIrp(Irp);
249 IoFreeMdl(Mdl);
250 ObDereferenceObject(FileObject);
251
252 if (!NT_SUCCESS(Status))
253 {
254 ExFreePoolWithTag(ProviderInfo, 'tseT');
255 continue;
256 }
257
258 ok_eq_hex(ProviderInfo->Version, TestData[i].ExpectedInfo.Version);
259 ok_eq_ulong(ProviderInfo->MaxSendSize, TestData[i].ExpectedInfo.MaxSendSize);
260 ok_eq_ulong(ProviderInfo->MaxConnectionUserData, TestData[i].ExpectedInfo.MaxConnectionUserData);
261 ok_eq_ulong(ProviderInfo->MaxDatagramSize, TestData[i].ExpectedInfo.MaxDatagramSize);
262 ok_eq_hex(ProviderInfo->ServiceFlags, TestData[i].ExpectedInfo.ServiceFlags);
263 ok_eq_ulong(ProviderInfo->MinimumLookaheadData, TestData[i].ExpectedInfo.MinimumLookaheadData);
264 ok_eq_ulong(ProviderInfo->MaximumLookaheadData, TestData[i].ExpectedInfo.MaximumLookaheadData);
265 ok_eq_ulong(ProviderInfo->NumberOfResources, TestData[i].ExpectedInfo.NumberOfResources);
266
267 ExFreePoolWithTag(ProviderInfo, 'tseT');
268 }
269 }
270
271 static KSTART_ROUTINE RunTest;
272 static
273 VOID
274 NTAPI
275 RunTest(
276 _In_ PVOID Context)
277 {
278 UNREFERENCED_PARAMETER(Context);
279
280 TestProviderInfo();
281 }
282
283 KMT_MESSAGE_HANDLER TestTdi;
284 NTSTATUS
285 TestTdi(
286 _In_ PDEVICE_OBJECT DeviceObject,
287 _In_ ULONG ControlCode,
288 _In_opt_ PVOID Buffer,
289 _In_ SIZE_T InLength,
290 _Inout_ PSIZE_T OutLength
291 )
292 {
293 PKTHREAD Thread;
294
295 Thread = KmtStartThread(RunTest, NULL);
296 KmtFinishThread(Thread, NULL);
297
298 return STATUS_SUCCESS;
299 }