[GDI32_APITEST] Fix MSVC build
[reactos.git] / modules / rostests / kmtests / tcpip / connect.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 #include <ndk/rtlfuncs.h>
11
12 #include <sys/param.h>
13
14 #include "tcpip.h"
15
16 #define TAG_TEST 'tseT'
17
18 #if BYTE_ORDER == LITTLE_ENDIAN
19 USHORT
20 htons(USHORT x)
21 {
22 return ((x & 0x00FF) << 8) | ((x & 0xFF00) >> 8);
23 }
24 #else
25 #define htons(x) (x)
26 #endif
27
28 static
29 NTSTATUS
30 NTAPI
31 IrpCompletionRoutine(
32 _In_ PDEVICE_OBJECT DeviceObject,
33 _In_ PIRP Irp,
34 _In_ PVOID Context)
35 {
36 UNREFERENCED_PARAMETER(DeviceObject);
37 UNREFERENCED_PARAMETER(Irp);
38
39 KeSetEvent((PKEVENT)Context, IO_NETWORK_INCREMENT, FALSE);
40
41 return STATUS_MORE_PROCESSING_REQUIRED;
42 }
43
44 static
45 VOID
46 TestTcpConnect(void)
47 {
48 PIRP Irp;
49 HANDLE AddressHandle, ConnectionHandle;
50 FILE_OBJECT* ConnectionFileObject;
51 DEVICE_OBJECT* DeviceObject;
52 UNICODE_STRING TcpDeviceName = RTL_CONSTANT_STRING(L"\\Device\\Tcp");
53 NTSTATUS Status;
54 PFILE_FULL_EA_INFORMATION FileInfo;
55 TA_IP_ADDRESS* IpAddress;
56 TA_IP_ADDRESS ConnectAddress, ReturnAddress;
57 OBJECT_ATTRIBUTES ObjectAttributes;
58 IO_STATUS_BLOCK StatusBlock;
59 ULONG FileInfoSize;
60 IN_ADDR InAddr;
61 LPCWSTR AddressTerminator;
62 CONNECTION_CONTEXT ConnectionContext = (CONNECTION_CONTEXT)(ULONG_PTR)0xC0CAC01AC0CAC01AULL;
63 KEVENT Event;
64 TDI_CONNECTION_INFORMATION RequestInfo, ReturnInfo;
65
66 /* Create a TCP address file */
67 FileInfoSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[TDI_TRANSPORT_ADDRESS_LENGTH]) + 1 + sizeof(TA_IP_ADDRESS);
68 FileInfo = ExAllocatePoolWithTag(NonPagedPool,
69 FileInfoSize,
70 TAG_TEST);
71 ok(FileInfo != NULL, "FileInfo is NULL!\n");
72 RtlZeroMemory(FileInfo, FileInfoSize);
73
74 FileInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
75 FileInfo->EaValueLength = sizeof(TA_IP_ADDRESS);
76 RtlCopyMemory(&FileInfo->EaName[0], TdiTransportAddress, TDI_TRANSPORT_ADDRESS_LENGTH);
77
78 IpAddress = (PTA_IP_ADDRESS)(&FileInfo->EaName[TDI_TRANSPORT_ADDRESS_LENGTH + 1]);
79 IpAddress->TAAddressCount = 1;
80 IpAddress->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
81 IpAddress->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
82 IpAddress->Address[0].Address[0].sin_port = htons(TEST_CONNECT_CLIENT_PORT);
83 Status = RtlIpv4StringToAddressW(L"127.0.0.1", TRUE, &AddressTerminator, &InAddr);
84 ok_eq_hex(Status, STATUS_SUCCESS);
85 IpAddress->Address[0].Address[0].in_addr = InAddr.S_un.S_addr;
86
87 InitializeObjectAttributes(&ObjectAttributes,
88 &TcpDeviceName,
89 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
90 NULL,
91 NULL);
92
93 Status = ZwCreateFile(
94 &AddressHandle,
95 GENERIC_READ | GENERIC_WRITE,
96 &ObjectAttributes,
97 &StatusBlock,
98 0,
99 FILE_ATTRIBUTE_NORMAL,
100 FILE_SHARE_READ | FILE_SHARE_WRITE,
101 FILE_OPEN_IF,
102 0L,
103 FileInfo,
104 FileInfoSize);
105 ok_eq_hex(Status, STATUS_SUCCESS);
106
107 ExFreePoolWithTag(FileInfo, TAG_TEST);
108
109 /* Create a TCP connection file */
110 FileInfoSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[TDI_CONNECTION_CONTEXT_LENGTH]) + 1 + sizeof(CONNECTION_CONTEXT);
111 FileInfo = ExAllocatePoolWithTag(NonPagedPool,
112 FileInfoSize,
113 TAG_TEST);
114 ok(FileInfo != NULL, "FileInfo is NULL!\n");
115 RtlZeroMemory(FileInfo, FileInfoSize);
116
117 FileInfo->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
118 FileInfo->EaValueLength = sizeof(CONNECTION_CONTEXT);
119 RtlCopyMemory(&FileInfo->EaName[0], TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH);
120 *((CONNECTION_CONTEXT*)&FileInfo->EaName[TDI_CONNECTION_CONTEXT_LENGTH + 1]) = ConnectionContext;
121
122 Status = ZwCreateFile(
123 &ConnectionHandle,
124 GENERIC_READ | GENERIC_WRITE,
125 &ObjectAttributes,
126 &StatusBlock,
127 0,
128 FILE_ATTRIBUTE_NORMAL,
129 FILE_SHARE_READ | FILE_SHARE_WRITE,
130 FILE_OPEN_IF,
131 0L,
132 FileInfo,
133 FileInfoSize);
134 ok_eq_hex(Status, STATUS_SUCCESS);
135
136 ExFreePoolWithTag(FileInfo, TAG_TEST);
137
138 /* Get the file and device object for the upcoming IRPs */
139 Status = ObReferenceObjectByHandle(
140 ConnectionHandle,
141 GENERIC_READ,
142 *IoFileObjectType,
143 KernelMode,
144 (PVOID*)&ConnectionFileObject,
145 NULL);
146 ok_eq_hex(Status, STATUS_SUCCESS);
147 DeviceObject = IoGetRelatedDeviceObject(ConnectionFileObject);
148 ok(DeviceObject != NULL, "Device object is NULL!\n");
149
150 /* Associate the connection file and the address */
151 KeInitializeEvent(&Event, NotificationEvent, FALSE);
152 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
153 ok(Irp != NULL, "IoAllocateIrp failed.\n");
154
155 TdiBuildAssociateAddress(Irp, DeviceObject, ConnectionFileObject, NULL, NULL, AddressHandle);
156 IoSetCompletionRoutine(Irp, IrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
157
158 Status = IoCallDriver(DeviceObject, Irp);
159 if (Status == STATUS_PENDING)
160 {
161 trace("Associate address IRP is pending.\n");
162 KeWaitForSingleObject(
163 &Event,
164 Executive,
165 KernelMode,
166 FALSE,
167 NULL);
168 Status = Irp->IoStatus.Status;
169 trace("Associate address IRP completed.\n");
170 }
171 ok_eq_hex(Status, STATUS_SUCCESS);
172 IoFreeIrp(Irp);
173
174
175 KeClearEvent(&Event);
176
177 /* Build the connect IRP. */
178 Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
179 ok(Irp != NULL, "IoAllocateIrp failed.\n");
180
181 /* Prepare the request */
182 RtlZeroMemory(&RequestInfo, sizeof(RequestInfo));
183 RtlZeroMemory(&ConnectAddress, sizeof(ConnectAddress));
184 RequestInfo.RemoteAddressLength = sizeof(TA_IP_ADDRESS);
185 RequestInfo.RemoteAddress = &ConnectAddress;
186 ConnectAddress.TAAddressCount = 1;
187 ConnectAddress.Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
188 ConnectAddress.Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
189 ConnectAddress.Address[0].Address[0].sin_port = htons(TEST_CONNECT_SERVER_PORT);
190 Status = RtlIpv4StringToAddressW(L"127.0.0.1", TRUE, &AddressTerminator, &InAddr);
191 ConnectAddress.Address[0].Address[0].in_addr = InAddr.S_un.S_addr;
192
193 /* See what we will get in exchange */
194 RtlZeroMemory(&ReturnInfo, sizeof(ReturnInfo));
195 RtlZeroMemory(&ReturnAddress, sizeof(ReturnAddress));
196 ReturnInfo.RemoteAddressLength = sizeof(TA_IP_ADDRESS);
197 ReturnInfo.RemoteAddress = &ReturnAddress;
198
199 TdiBuildConnect(Irp,
200 DeviceObject,
201 ConnectionFileObject,
202 NULL,
203 NULL,
204 NULL,
205 &RequestInfo,
206 &ReturnInfo);
207 IoSetCompletionRoutine(Irp, IrpCompletionRoutine, &Event, TRUE, TRUE, TRUE);
208
209 Status = IoCallDriver(DeviceObject, Irp);
210 if (Status == STATUS_PENDING)
211 {
212 trace("Connect IRP is pending.\n");
213 KeWaitForSingleObject(
214 &Event,
215 Executive,
216 KernelMode,
217 FALSE,
218 NULL);
219 Status = Irp->IoStatus.Status;
220 trace("Connect IRP completed.\n");
221 }
222 ok_eq_hex(Status, STATUS_SUCCESS);
223 IoFreeIrp(Irp);
224
225 /* The IRP doesn't touch the return info */
226 ok_eq_long(ReturnInfo.RemoteAddressLength, sizeof(TA_IP_ADDRESS));
227 ok_eq_pointer(ReturnInfo.RemoteAddress, &ReturnAddress);
228 ok_eq_long(ReturnInfo.OptionsLength, 0);
229 ok_eq_pointer(ReturnInfo.Options, NULL);
230 ok_eq_long(ReturnInfo.UserDataLength, 0);
231 ok_eq_pointer(ReturnInfo.UserData, NULL);
232
233 ok_eq_long(ReturnAddress.TAAddressCount, 1);
234 ok_eq_hex(ReturnAddress.Address[0].AddressType, TDI_ADDRESS_TYPE_IP);
235 ok_eq_hex(ReturnAddress.Address[0].AddressLength, TDI_ADDRESS_LENGTH_IP);
236 ok_eq_hex(ReturnAddress.Address[0].Address[0].sin_port, htons(TEST_CONNECT_SERVER_PORT));
237 ok_eq_hex(ReturnAddress.Address[0].Address[0].in_addr, InAddr.S_un.S_addr);
238
239 ObDereferenceObject(ConnectionFileObject);
240
241 ZwClose(ConnectionHandle);
242 ZwClose(AddressHandle);
243 }
244
245 static KSTART_ROUTINE RunTest;
246 static
247 VOID
248 NTAPI
249 RunTest(
250 _In_ PVOID Context)
251 {
252 UNREFERENCED_PARAMETER(Context);
253
254 TestTcpConnect();
255 }
256
257 KMT_MESSAGE_HANDLER TestConnect;
258 NTSTATUS
259 TestConnect(
260 _In_ PDEVICE_OBJECT DeviceObject,
261 _In_ ULONG ControlCode,
262 _In_opt_ PVOID Buffer,
263 _In_ SIZE_T InLength,
264 _Inout_ PSIZE_T OutLength
265 )
266 {
267 PKTHREAD Thread;
268
269 Thread = KmtStartThread(RunTest, NULL);
270 KmtFinishThread(Thread, NULL);
271
272 return STATUS_SUCCESS;
273 }