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>
10 #include <ndk/rtlfuncs.h>
12 #include <sys/param.h>
16 #define TAG_TEST 'tseT'
18 #if BYTE_ORDER == LITTLE_ENDIAN
22 return ((x
& 0x00FF) << 8) | ((x
& 0xFF00) >> 8);
32 _In_ PDEVICE_OBJECT DeviceObject
,
36 UNREFERENCED_PARAMETER(DeviceObject
);
37 UNREFERENCED_PARAMETER(Irp
);
39 KeSetEvent((PKEVENT
)Context
, IO_NETWORK_INCREMENT
, FALSE
);
41 return STATUS_MORE_PROCESSING_REQUIRED
;
49 HANDLE AddressHandle
, ConnectionHandle
;
50 FILE_OBJECT
* ConnectionFileObject
;
51 DEVICE_OBJECT
* DeviceObject
;
52 UNICODE_STRING TcpDeviceName
= RTL_CONSTANT_STRING(L
"\\Device\\Tcp");
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
;
61 LPCWSTR AddressTerminator
;
62 CONNECTION_CONTEXT ConnectionContext
= (CONNECTION_CONTEXT
)0xC0CAC01A;
64 TDI_CONNECTION_INFORMATION RequestInfo
, ReturnInfo
;
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
,
71 ok(FileInfo
!= NULL
, "");
72 RtlZeroMemory(FileInfo
, FileInfoSize
);
74 FileInfo
->EaNameLength
= TDI_TRANSPORT_ADDRESS_LENGTH
;
75 FileInfo
->EaValueLength
= sizeof(TA_IP_ADDRESS
);
76 RtlCopyMemory(&FileInfo
->EaName
[0], TdiTransportAddress
, TDI_TRANSPORT_ADDRESS_LENGTH
);
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
;
87 InitializeObjectAttributes(&ObjectAttributes
,
89 OBJ_CASE_INSENSITIVE
| OBJ_KERNEL_HANDLE
,
93 Status
= ZwCreateFile(
95 GENERIC_READ
| GENERIC_WRITE
,
99 FILE_ATTRIBUTE_NORMAL
,
100 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
105 ok_eq_hex(Status
, STATUS_SUCCESS
);
107 ExFreePoolWithTag(FileInfo
, TAG_TEST
);
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
,
114 ok(FileInfo
!= NULL
, "");
115 RtlZeroMemory(FileInfo
, FileInfoSize
);
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
;
122 Status
= ZwCreateFile(
124 GENERIC_READ
| GENERIC_WRITE
,
128 FILE_ATTRIBUTE_NORMAL
,
129 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
134 ok_eq_hex(Status
, STATUS_SUCCESS
);
136 ExFreePoolWithTag(FileInfo
, TAG_TEST
);
138 /* Get the file and device object for the upcoming IRPs */
139 Status
= ObReferenceObjectByHandle(
144 (PVOID
*)&ConnectionFileObject
,
146 ok_eq_hex(Status
, STATUS_SUCCESS
);
147 DeviceObject
= IoGetRelatedDeviceObject(ConnectionFileObject
);
148 ok(DeviceObject
!= NULL
, "Device object is NULL!\n");
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");
155 TdiBuildAssociateAddress(Irp
, DeviceObject
, ConnectionFileObject
, NULL
, NULL
, AddressHandle
);
156 IoSetCompletionRoutine(Irp
, IrpCompletionRoutine
, &Event
, TRUE
, TRUE
, TRUE
);
158 Status
= IoCallDriver(DeviceObject
, Irp
);
159 if (Status
== STATUS_PENDING
)
161 trace("Associate address IRP is pending.\n");
162 KeWaitForSingleObject(
168 Status
= Irp
->IoStatus
.Status
;
170 ok_eq_hex(Status
, STATUS_SUCCESS
);
174 KeClearEvent(&Event
);
176 /* Build the connect IRP. */
177 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
178 ok(Irp
!= NULL
, "IoAllocateIrp failed.\n");
180 /* Prepare the request */
181 RtlZeroMemory(&RequestInfo
, sizeof(RequestInfo
));
182 RtlZeroMemory(&ConnectAddress
, sizeof(ConnectAddress
));
183 RequestInfo
.RemoteAddressLength
= sizeof(TA_IP_ADDRESS
);
184 RequestInfo
.RemoteAddress
= &ConnectAddress
;
185 ConnectAddress
.TAAddressCount
= 1;
186 ConnectAddress
.Address
[0].AddressType
= TDI_ADDRESS_TYPE_IP
;
187 ConnectAddress
.Address
[0].AddressLength
= TDI_ADDRESS_LENGTH_IP
;
188 ConnectAddress
.Address
[0].Address
[0].sin_port
= htons(TEST_CONNECT_SERVER_PORT
);
189 Status
= RtlIpv4StringToAddressW(L
"127.0.0.1", TRUE
, &AddressTerminator
, &InAddr
);
190 ConnectAddress
.Address
[0].Address
[0].in_addr
= InAddr
.S_un
.S_addr
;
192 /* See what we will get in exchange */
193 RtlZeroMemory(&ReturnInfo
, sizeof(ReturnInfo
));
194 RtlZeroMemory(&ReturnAddress
, sizeof(ReturnAddress
));
195 ReturnInfo
.RemoteAddressLength
= sizeof(TA_IP_ADDRESS
);
196 ReturnInfo
.RemoteAddress
= &ReturnAddress
;
200 ConnectionFileObject
,
206 IoSetCompletionRoutine(Irp
, IrpCompletionRoutine
, &Event
, TRUE
, TRUE
, TRUE
);
208 Status
= IoCallDriver(DeviceObject
, Irp
);
209 if (Status
== STATUS_PENDING
)
211 trace("Connect IRP is pending.\n");
212 KeWaitForSingleObject(
218 Status
= Irp
->IoStatus
.Status
;
219 trace("Connect IRP completed.\n");
221 ok_eq_hex(Status
, STATUS_SUCCESS
);
224 /* The IRP doesn't touch the return info */
225 ok_eq_long(ReturnInfo
.RemoteAddressLength
, sizeof(TA_IP_ADDRESS
));
226 ok_eq_pointer(ReturnInfo
.RemoteAddress
, &ReturnAddress
);
227 ok_eq_long(ReturnInfo
.OptionsLength
, 0);
228 ok_eq_pointer(ReturnInfo
.Options
, NULL
);
229 ok_eq_long(ReturnInfo
.UserDataLength
, 0);
230 ok_eq_pointer(ReturnInfo
.UserData
, NULL
);
232 ok_eq_long(ReturnAddress
.TAAddressCount
, 0);
233 ok_eq_hex(ReturnAddress
.Address
[0].AddressType
, 0);
234 ok_eq_hex(ReturnAddress
.Address
[0].AddressLength
, 0);
235 ok_eq_hex(ReturnAddress
.Address
[0].Address
[0].sin_port
, 0);
236 ok_eq_hex(ReturnAddress
.Address
[0].Address
[0].in_addr
, 0);
238 ObDereferenceObject(ConnectionFileObject
);
240 ZwClose(ConnectionHandle
);
241 ZwClose(AddressHandle
);
244 static KSTART_ROUTINE RunTest
;
251 UNREFERENCED_PARAMETER(Context
);
256 KMT_MESSAGE_HANDLER TestConnect
;
259 _In_ PDEVICE_OBJECT DeviceObject
,
260 _In_ ULONG ControlCode
,
261 _In_opt_ PVOID Buffer
,
262 _In_ SIZE_T InLength
,
263 _Inout_ PSIZE_T OutLength
268 Thread
= KmtStartThread(RunTest
, NULL
);
269 KmtFinishThread(Thread
, NULL
);
271 return STATUS_SUCCESS
;