[IPHLPAPI_APITEST]
[reactos.git] / rostests / apitests / iphlpapi / SendARP.c
1 /*
2 * PROJECT: ReactOS api tests
3 * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory
4 * PURPOSE: Test for SendARP
5 * PROGRAMMER: Pierre Schweitzer <pierre@reactos.org>
6 */
7
8 #include <apitest.h>
9 #include <winsock2.h>
10 #include <iphlpapi.h>
11 #include <tcpioctl.h>
12 #define NTOS_MODE_USER
13 #include <ndk/iofuncs.h>
14 #include <ndk/obfuncs.h>
15 #include <ndk/rtlfuncs.h>
16
17 static VOID TestUM(IPAddr * Source)
18 {
19 DWORD Err;
20 ULONG Hw[2];
21 DWORD Size;
22 BOOL Tested = FALSE;
23 PIP_ADAPTER_ADDRESSES Addresses, Current;
24
25 Err = SendARP(0, 0, NULL, NULL);
26 ok(Err == ERROR_INVALID_PARAMETER, "Expected error: ERROR_INVALID_PARAMETER. Got: %lx\n", Err);
27
28 Size = 4;
29 Err = SendARP(0, 0, Hw, &Size);
30 ok(Err == ERROR_GEN_FAILURE, "Expected error: ERROR_GEN_FAILURE. Got: %lx\n", Err);
31
32 Size = 6;
33 Err = SendARP(0, 0, Hw, &Size);
34 ok(Err == ERROR_GEN_FAILURE, "Expected error: ERROR_GEN_FAILURE. Got: %lx\n", Err);
35
36 Size = 8;
37 Err = SendARP(0, 0, Hw, &Size);
38 ok(Err == ERROR_GEN_FAILURE, "Expected error: ERROR_GEN_FAILURE. Got: %lx\n", Err);
39
40 Size = sizeof(IP_ADAPTER_ADDRESSES);
41 Addresses = (PIP_ADAPTER_ADDRESSES)malloc(Size);
42 if (!Addresses)
43 {
44 skip("Memory failure\n");
45 return;
46 }
47
48 Err = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST, NULL, Addresses, &Size);
49 if (Err == ERROR_BUFFER_OVERFLOW)
50 {
51 free(Addresses);
52 Addresses = (PIP_ADAPTER_ADDRESSES)malloc(Size);
53 if (!Addresses)
54 {
55 skip("Memory failure\n");
56 return;
57 }
58
59 Err = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_FRIENDLY_NAME | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST, NULL, Addresses, &Size);
60 }
61
62 if (Err != ERROR_SUCCESS)
63 {
64 skip("GetAdaptersAddresses() failure\n");
65 free(Addresses);
66 return;
67 }
68
69 for (Current = Addresses; Current; Current = Current->Next)
70 {
71 PSOCKADDR_IN SockAddr;
72 IPAddr IpAddr;
73
74 if (Current->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
75 continue;
76
77 if (Current->OperStatus != IfOperStatusUp)
78 continue;
79
80 if (!Current->FirstUnicastAddress)
81 continue;
82
83 ok(Current->FirstUnicastAddress->Address.iSockaddrLength == sizeof(SOCKADDR_IN), "Unexpected length: %u\n", Current->FirstUnicastAddress->Address.iSockaddrLength);
84 SockAddr = (PSOCKADDR_IN)Current->FirstUnicastAddress->Address.lpSockaddr;
85 IpAddr = SockAddr->sin_addr.S_un.S_addr;
86
87 trace("IP address found: %lu.%lu.%lu.%lu\n", IpAddr & 0xFF, (IpAddr >> 8) & 0xFF, (IpAddr >> 16) & 0xFF, (IpAddr >> 24) & 0xFF);
88
89 Size = 4;
90 Err = SendARP(IpAddr, 0, Hw, &Size);
91 ok(Err == ERROR_NO_SYSTEM_RESOURCES, "Expected error: ERROR_NO_SYSTEM_RESOURCES. Got: %lx\n", Err);
92
93 Size = 6;
94 Err = SendARP(IpAddr, 0, Hw, &Size);
95 ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
96
97 Size = 8;
98 Err = SendARP(IpAddr, 0, Hw, &Size);
99 ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
100 Err = SendARP(IpAddr, 0x08080808, Hw, &Size);
101 ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
102
103 Size = 4;
104 Err = SendARP(IpAddr, IpAddr, Hw, &Size);
105 ok(Err == ERROR_NO_SYSTEM_RESOURCES, "Expected error: ERROR_NO_SYSTEM_RESOURCES. Got: %lx\n", Err);
106
107 Size = 6;
108 Err = SendARP(IpAddr, IpAddr, Hw, &Size);
109 ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
110
111 Size = 8;
112 Err = SendARP(IpAddr, IpAddr, Hw, &Size);
113 ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
114
115 *Source = IpAddr;
116 Tested = TRUE;
117 break;
118 }
119
120 if (!Tested)
121 {
122 skip("No suitable interface found\n");
123 }
124
125 free(Addresses);
126 }
127
128 static VOID TestKM(IPAddr Source)
129 {
130 HANDLE hDevice;
131 NTSTATUS Status;
132 IO_STATUS_BLOCK IoStatusBlock;
133 UNICODE_STRING DevName = RTL_CONSTANT_STRING(L"\\Device\\Ip");
134 OBJECT_ATTRIBUTES ObjectAttributes;
135 HANDLE hEvent;
136 ULONG Hw[2];
137 ULONG Ip[2];
138
139 InitializeObjectAttributes(&ObjectAttributes,
140 &DevName,
141 OBJ_CASE_INSENSITIVE,
142 NULL,
143 NULL);
144
145 Status = NtCreateFile(&hDevice, GENERIC_EXECUTE, &ObjectAttributes,
146 &IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF,
147 0, NULL, 0);
148 if (!NT_SUCCESS(Status))
149 {
150 skip("NtCreateFile() failed with status: %lx\n", Status);
151 return;
152 }
153
154 hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
155 if (!hEvent)
156 {
157 skip("CreateEventW() with error: %lx\n", GetLastError());
158 CloseHandle(hDevice);
159 return;
160 }
161
162 IoStatusBlock.Status = STATUS_SUCCESS;
163 IoStatusBlock.Information = 0;
164 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, NULL, 0, NULL, 0);
165 if (Status == STATUS_PENDING)
166 {
167 NtWaitForSingleObject(hEvent, FALSE, NULL);
168 Status = IoStatusBlock.Status;
169 }
170 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
171 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
172
173 memset(Ip, 0, sizeof(Ip));
174 ResetEvent(hEvent);
175 IoStatusBlock.Status = STATUS_SUCCESS;
176 IoStatusBlock.Information = 0;
177 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), NULL, 0);
178 if (Status == STATUS_PENDING)
179 {
180 NtWaitForSingleObject(hEvent, FALSE, NULL);
181 Status = IoStatusBlock.Status;
182 }
183 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
184 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
185
186 ResetEvent(hEvent);
187 IoStatusBlock.Status = STATUS_SUCCESS;
188 IoStatusBlock.Information = 0;
189 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 4);
190 if (Status == STATUS_PENDING)
191 {
192 NtWaitForSingleObject(hEvent, FALSE, NULL);
193 Status = IoStatusBlock.Status;
194 }
195 ok(Status == STATUS_UNSUCCESSFUL, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
196 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
197
198 ResetEvent(hEvent);
199 IoStatusBlock.Status = STATUS_SUCCESS;
200 IoStatusBlock.Information = 0;
201 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 6);
202 if (Status == STATUS_PENDING)
203 {
204 NtWaitForSingleObject(hEvent, FALSE, NULL);
205 Status = IoStatusBlock.Status;
206 }
207 ok(Status == STATUS_UNSUCCESSFUL, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
208 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
209
210 ResetEvent(hEvent);
211 IoStatusBlock.Status = STATUS_SUCCESS;
212 IoStatusBlock.Information = 0;
213 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
214 if (Status == STATUS_PENDING)
215 {
216 NtWaitForSingleObject(hEvent, FALSE, NULL);
217 Status = IoStatusBlock.Status;
218 }
219 ok(Status == STATUS_UNSUCCESSFUL, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
220 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
221
222 Ip[0] = Source;
223 ResetEvent(hEvent);
224 IoStatusBlock.Status = STATUS_SUCCESS;
225 IoStatusBlock.Information = 0;
226 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip[0]), NULL, 0);
227 if (Status == STATUS_PENDING)
228 {
229 NtWaitForSingleObject(hEvent, FALSE, NULL);
230 Status = IoStatusBlock.Status;
231 }
232 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
233 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
234
235 ResetEvent(hEvent);
236 IoStatusBlock.Status = STATUS_SUCCESS;
237 IoStatusBlock.Information = 0;
238 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip[0]), Hw, 4);
239 if (Status == STATUS_PENDING)
240 {
241 NtWaitForSingleObject(hEvent, FALSE, NULL);
242 Status = IoStatusBlock.Status;
243 }
244 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
245 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
246
247 ResetEvent(hEvent);
248 IoStatusBlock.Status = STATUS_SUCCESS;
249 IoStatusBlock.Information = 0;
250 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip[0]), Hw, 6);
251 if (Status == STATUS_PENDING)
252 {
253 NtWaitForSingleObject(hEvent, FALSE, NULL);
254 Status = IoStatusBlock.Status;
255 }
256 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
257 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
258
259 ResetEvent(hEvent);
260 IoStatusBlock.Status = STATUS_SUCCESS;
261 IoStatusBlock.Information = 0;
262 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip[0]), Hw, 8);
263 if (Status == STATUS_PENDING)
264 {
265 NtWaitForSingleObject(hEvent, FALSE, NULL);
266 Status = IoStatusBlock.Status;
267 }
268 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
269 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
270
271 ResetEvent(hEvent);
272 IoStatusBlock.Status = STATUS_SUCCESS;
273 IoStatusBlock.Information = 0;
274 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), NULL, 0);
275 if (Status == STATUS_PENDING)
276 {
277 NtWaitForSingleObject(hEvent, FALSE, NULL);
278 Status = IoStatusBlock.Status;
279 }
280 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
281 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
282
283 ResetEvent(hEvent);
284 IoStatusBlock.Status = STATUS_SUCCESS;
285 IoStatusBlock.Information = 0;
286 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 4);
287 if (Status == STATUS_PENDING)
288 {
289 NtWaitForSingleObject(hEvent, FALSE, NULL);
290 Status = IoStatusBlock.Status;
291 }
292 ok(Status == STATUS_INSUFFICIENT_RESOURCES, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
293 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
294
295 ResetEvent(hEvent);
296 IoStatusBlock.Status = STATUS_SUCCESS;
297 IoStatusBlock.Information = 0;
298 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 6);
299 if (Status == STATUS_PENDING)
300 {
301 NtWaitForSingleObject(hEvent, FALSE, NULL);
302 Status = IoStatusBlock.Status;
303 }
304 ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
305 ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
306
307 ResetEvent(hEvent);
308 IoStatusBlock.Status = STATUS_SUCCESS;
309 IoStatusBlock.Information = 0;
310 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
311 if (Status == STATUS_PENDING)
312 {
313 NtWaitForSingleObject(hEvent, FALSE, NULL);
314 Status = IoStatusBlock.Status;
315 }
316 ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
317 ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
318
319 Ip[1] = Source;
320 ResetEvent(hEvent);
321 IoStatusBlock.Status = STATUS_SUCCESS;
322 IoStatusBlock.Information = 0;
323 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), NULL, 0);
324 if (Status == STATUS_PENDING)
325 {
326 NtWaitForSingleObject(hEvent, FALSE, NULL);
327 Status = IoStatusBlock.Status;
328 }
329 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
330 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
331
332 ResetEvent(hEvent);
333 IoStatusBlock.Status = STATUS_SUCCESS;
334 IoStatusBlock.Information = 0;
335 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 4);
336 if (Status == STATUS_PENDING)
337 {
338 NtWaitForSingleObject(hEvent, FALSE, NULL);
339 Status = IoStatusBlock.Status;
340 }
341 ok(Status == STATUS_INSUFFICIENT_RESOURCES, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
342 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
343
344 ResetEvent(hEvent);
345 IoStatusBlock.Status = STATUS_SUCCESS;
346 IoStatusBlock.Information = 0;
347 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 6);
348 if (Status == STATUS_PENDING)
349 {
350 NtWaitForSingleObject(hEvent, FALSE, NULL);
351 Status = IoStatusBlock.Status;
352 }
353 ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
354 ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
355
356 ResetEvent(hEvent);
357 IoStatusBlock.Status = STATUS_SUCCESS;
358 IoStatusBlock.Information = 0;
359 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
360 if (Status == STATUS_PENDING)
361 {
362 NtWaitForSingleObject(hEvent, FALSE, NULL);
363 Status = IoStatusBlock.Status;
364 }
365 ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
366 ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
367
368 Ip[1] = 0x08080808;
369 ResetEvent(hEvent);
370 IoStatusBlock.Status = STATUS_SUCCESS;
371 IoStatusBlock.Information = 0;
372 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
373 if (Status == STATUS_PENDING)
374 {
375 NtWaitForSingleObject(hEvent, FALSE, NULL);
376 Status = IoStatusBlock.Status;
377 }
378 ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
379 ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
380
381 CloseHandle(hEvent);
382 CloseHandle(hDevice);
383 }
384
385 START_TEST(SendARP)
386 {
387 IPAddr Source = 0;
388
389 TestUM(&Source);
390 if (!Source)
391 {
392 skip("No suitable interface found\n");
393 return;
394 }
395
396 TestKM(Source);
397 }