[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 SockAddr = (PSOCKADDR_IN)Current->FirstUnicastAddress->Address.lpSockaddr;
84 IpAddr = SockAddr->sin_addr.S_un.S_addr;
85
86 Size = 4;
87 Err = SendARP(IpAddr, 0, Hw, &Size);
88 ok(Err == ERROR_NO_SYSTEM_RESOURCES, "Expected error: ERROR_NO_SYSTEM_RESOURCES. Got: %lx\n", Err);
89
90 Size = 6;
91 Err = SendARP(IpAddr, 0, Hw, &Size);
92 ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
93
94 Size = 8;
95 Err = SendARP(IpAddr, 0, Hw, &Size);
96 ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
97 Err = SendARP(IpAddr, 0x08080808, Hw, &Size);
98 ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
99
100 Size = 4;
101 Err = SendARP(IpAddr, IpAddr, Hw, &Size);
102 ok(Err == ERROR_NO_SYSTEM_RESOURCES, "Expected error: ERROR_NO_SYSTEM_RESOURCES. Got: %lx\n", Err);
103
104 Size = 6;
105 Err = SendARP(IpAddr, IpAddr, Hw, &Size);
106 ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
107
108 Size = 8;
109 Err = SendARP(IpAddr, IpAddr, Hw, &Size);
110 ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
111
112 *Source = IpAddr;
113 Tested = TRUE;
114 break;
115 }
116
117 if (!Tested)
118 {
119 skip("No suitable interface found\n");
120 }
121
122 free(Addresses);
123 }
124
125 static VOID TestKM(IPAddr Source)
126 {
127 HANDLE hDevice;
128 NTSTATUS Status;
129 IO_STATUS_BLOCK IoStatusBlock;
130 UNICODE_STRING DevName = RTL_CONSTANT_STRING(L"\\Device\\Ip");
131 OBJECT_ATTRIBUTES ObjectAttributes;
132 HANDLE hEvent;
133 ULONG Hw[2];
134 ULONG Ip[2];
135
136 InitializeObjectAttributes(&ObjectAttributes,
137 &DevName,
138 OBJ_CASE_INSENSITIVE,
139 NULL,
140 NULL);
141
142 Status = NtCreateFile(&hDevice, GENERIC_EXECUTE, &ObjectAttributes,
143 &IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF,
144 0, NULL, 0);
145 if (!NT_SUCCESS(Status))
146 {
147 skip("NtCreateFile() failed with status: %lx\n", Status);
148 return;
149 }
150
151 hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
152 if (!hEvent)
153 {
154 skip("CreateEventW() with error: %lx\n", GetLastError());
155 CloseHandle(hDevice);
156 return;
157 }
158
159 IoStatusBlock.Status = STATUS_SUCCESS;
160 IoStatusBlock.Information = 0;
161 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, NULL, 0, NULL, 0);
162 if (Status == STATUS_PENDING)
163 {
164 NtWaitForSingleObject(hEvent, FALSE, NULL);
165 Status = IoStatusBlock.Status;
166 }
167 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
168 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
169
170 memset(Ip, 0, sizeof(Ip));
171 ResetEvent(hEvent);
172 IoStatusBlock.Status = STATUS_SUCCESS;
173 IoStatusBlock.Information = 0;
174 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), NULL, 0);
175 if (Status == STATUS_PENDING)
176 {
177 NtWaitForSingleObject(hEvent, FALSE, NULL);
178 Status = IoStatusBlock.Status;
179 }
180 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
181 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
182
183 ResetEvent(hEvent);
184 IoStatusBlock.Status = STATUS_SUCCESS;
185 IoStatusBlock.Information = 0;
186 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 4);
187 if (Status == STATUS_PENDING)
188 {
189 NtWaitForSingleObject(hEvent, FALSE, NULL);
190 Status = IoStatusBlock.Status;
191 }
192 ok(Status == STATUS_UNSUCCESSFUL, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
193 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
194
195 ResetEvent(hEvent);
196 IoStatusBlock.Status = STATUS_SUCCESS;
197 IoStatusBlock.Information = 0;
198 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 6);
199 if (Status == STATUS_PENDING)
200 {
201 NtWaitForSingleObject(hEvent, FALSE, NULL);
202 Status = IoStatusBlock.Status;
203 }
204 ok(Status == STATUS_UNSUCCESSFUL, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
205 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
206
207 ResetEvent(hEvent);
208 IoStatusBlock.Status = STATUS_SUCCESS;
209 IoStatusBlock.Information = 0;
210 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
211 if (Status == STATUS_PENDING)
212 {
213 NtWaitForSingleObject(hEvent, FALSE, NULL);
214 Status = IoStatusBlock.Status;
215 }
216 ok(Status == STATUS_UNSUCCESSFUL, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
217 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
218
219 Ip[0] = Source;
220 ResetEvent(hEvent);
221 IoStatusBlock.Status = STATUS_SUCCESS;
222 IoStatusBlock.Information = 0;
223 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip[0]), NULL, 0);
224 if (Status == STATUS_PENDING)
225 {
226 NtWaitForSingleObject(hEvent, FALSE, NULL);
227 Status = IoStatusBlock.Status;
228 }
229 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
230 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
231
232 ResetEvent(hEvent);
233 IoStatusBlock.Status = STATUS_SUCCESS;
234 IoStatusBlock.Information = 0;
235 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip[0]), Hw, 4);
236 if (Status == STATUS_PENDING)
237 {
238 NtWaitForSingleObject(hEvent, FALSE, NULL);
239 Status = IoStatusBlock.Status;
240 }
241 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
242 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
243
244 ResetEvent(hEvent);
245 IoStatusBlock.Status = STATUS_SUCCESS;
246 IoStatusBlock.Information = 0;
247 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip[0]), Hw, 6);
248 if (Status == STATUS_PENDING)
249 {
250 NtWaitForSingleObject(hEvent, FALSE, NULL);
251 Status = IoStatusBlock.Status;
252 }
253 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
254 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
255
256 ResetEvent(hEvent);
257 IoStatusBlock.Status = STATUS_SUCCESS;
258 IoStatusBlock.Information = 0;
259 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip[0]), Hw, 8);
260 if (Status == STATUS_PENDING)
261 {
262 NtWaitForSingleObject(hEvent, FALSE, NULL);
263 Status = IoStatusBlock.Status;
264 }
265 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
266 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
267
268 ResetEvent(hEvent);
269 IoStatusBlock.Status = STATUS_SUCCESS;
270 IoStatusBlock.Information = 0;
271 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), NULL, 0);
272 if (Status == STATUS_PENDING)
273 {
274 NtWaitForSingleObject(hEvent, FALSE, NULL);
275 Status = IoStatusBlock.Status;
276 }
277 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
278 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
279
280 ResetEvent(hEvent);
281 IoStatusBlock.Status = STATUS_SUCCESS;
282 IoStatusBlock.Information = 0;
283 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 4);
284 if (Status == STATUS_PENDING)
285 {
286 NtWaitForSingleObject(hEvent, FALSE, NULL);
287 Status = IoStatusBlock.Status;
288 }
289 ok(Status == STATUS_INSUFFICIENT_RESOURCES, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
290 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
291
292 ResetEvent(hEvent);
293 IoStatusBlock.Status = STATUS_SUCCESS;
294 IoStatusBlock.Information = 0;
295 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 6);
296 if (Status == STATUS_PENDING)
297 {
298 NtWaitForSingleObject(hEvent, FALSE, NULL);
299 Status = IoStatusBlock.Status;
300 }
301 ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
302 ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
303
304 ResetEvent(hEvent);
305 IoStatusBlock.Status = STATUS_SUCCESS;
306 IoStatusBlock.Information = 0;
307 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
308 if (Status == STATUS_PENDING)
309 {
310 NtWaitForSingleObject(hEvent, FALSE, NULL);
311 Status = IoStatusBlock.Status;
312 }
313 ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
314 ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
315
316 Ip[1] = Source;
317 ResetEvent(hEvent);
318 IoStatusBlock.Status = STATUS_SUCCESS;
319 IoStatusBlock.Information = 0;
320 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), NULL, 0);
321 if (Status == STATUS_PENDING)
322 {
323 NtWaitForSingleObject(hEvent, FALSE, NULL);
324 Status = IoStatusBlock.Status;
325 }
326 ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
327 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
328
329 ResetEvent(hEvent);
330 IoStatusBlock.Status = STATUS_SUCCESS;
331 IoStatusBlock.Information = 0;
332 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 4);
333 if (Status == STATUS_PENDING)
334 {
335 NtWaitForSingleObject(hEvent, FALSE, NULL);
336 Status = IoStatusBlock.Status;
337 }
338 ok(Status == STATUS_INSUFFICIENT_RESOURCES, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
339 ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
340
341 ResetEvent(hEvent);
342 IoStatusBlock.Status = STATUS_SUCCESS;
343 IoStatusBlock.Information = 0;
344 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 6);
345 if (Status == STATUS_PENDING)
346 {
347 NtWaitForSingleObject(hEvent, FALSE, NULL);
348 Status = IoStatusBlock.Status;
349 }
350 ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
351 ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
352
353 ResetEvent(hEvent);
354 IoStatusBlock.Status = STATUS_SUCCESS;
355 IoStatusBlock.Information = 0;
356 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
357 if (Status == STATUS_PENDING)
358 {
359 NtWaitForSingleObject(hEvent, FALSE, NULL);
360 Status = IoStatusBlock.Status;
361 }
362 ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
363 ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
364
365 Ip[1] = 0x08080808;
366 ResetEvent(hEvent);
367 IoStatusBlock.Status = STATUS_SUCCESS;
368 IoStatusBlock.Information = 0;
369 Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
370 if (Status == STATUS_PENDING)
371 {
372 NtWaitForSingleObject(hEvent, FALSE, NULL);
373 Status = IoStatusBlock.Status;
374 }
375 ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
376 ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
377
378 CloseHandle(hEvent);
379 CloseHandle(hDevice);
380 }
381
382 START_TEST(SendARP)
383 {
384 IPAddr Source = 0;
385
386 TestUM(&Source);
387 if (!Source)
388 {
389 skip("No suitable interface found\n");
390 return;
391 }
392
393 TestKM(Source);
394 }