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 
TestUM(IPAddr * Source,IPAddr * Gateway)17 static VOID TestUM(IPAddr * Source, IPAddr * Gateway)
18 {
19     DWORD Err;
20     ULONG Hw[2];
21     DWORD Size;
22     BOOL Tested = FALSE;
23     PIP_ADAPTER_ADDRESSES Addresses, Current;
24     PIP_ADAPTER_INFO Adapters, CurrentA;
25 
26     Err = SendARP(0, 0, NULL, NULL);
27     ok(Err == ERROR_INVALID_PARAMETER, "Expected error: ERROR_INVALID_PARAMETER. Got: %lx\n", Err);
28 
29     Size = 4;
30     Err = SendARP(0, 0, Hw, &Size);
31     ok(Err == ERROR_GEN_FAILURE, "Expected error: ERROR_GEN_FAILURE. Got: %lx\n", Err);
32 
33     Size = 6;
34     Err = SendARP(0, 0, Hw, &Size);
35     ok(Err == ERROR_GEN_FAILURE, "Expected error: ERROR_GEN_FAILURE. Got: %lx\n", Err);
36 
37     Size = 8;
38     Err = SendARP(0, 0, Hw, &Size);
39     ok(Err == ERROR_GEN_FAILURE, "Expected error: ERROR_GEN_FAILURE. Got: %lx\n", Err);
40 
41     Size = sizeof(IP_ADAPTER_ADDRESSES);
42     Addresses = (PIP_ADAPTER_ADDRESSES)malloc(Size);
43     if (!Addresses)
44     {
45         skip("Memory failure\n");
46         return;
47     }
48 
49     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);
50     if (Err == ERROR_BUFFER_OVERFLOW)
51     {
52         free(Addresses);
53         Addresses = (PIP_ADAPTER_ADDRESSES)malloc(Size);
54         if (!Addresses)
55         {
56             skip("Memory failure\n");
57             return;
58         }
59 
60         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);
61     }
62 
63     if (Err != ERROR_SUCCESS)
64     {
65         skip("GetAdaptersAddresses() failure\n");
66         free(Addresses);
67         return;
68     }
69 
70     for (Current = Addresses; Current; Current = Current->Next)
71     {
72         PSOCKADDR_IN SockAddr;
73         IPAddr IpAddr;
74 
75         if (Current->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
76             continue;
77 
78         if (Current->OperStatus != IfOperStatusUp)
79             continue;
80 
81         if (!Current->FirstUnicastAddress)
82             continue;
83 
84         ok(Current->FirstUnicastAddress->Address.iSockaddrLength == sizeof(SOCKADDR_IN), "Unexpected length: %u\n", Current->FirstUnicastAddress->Address.iSockaddrLength);
85         SockAddr = (PSOCKADDR_IN)Current->FirstUnicastAddress->Address.lpSockaddr;
86         IpAddr = SockAddr->sin_addr.S_un.S_addr;
87 
88         trace("IP address found: %lu.%lu.%lu.%lu\n", IpAddr & 0xFF, (IpAddr >> 8) & 0xFF, (IpAddr >> 16) & 0xFF, (IpAddr >> 24) & 0xFF);
89 
90         Size = 4;
91         Err = SendARP(IpAddr, 0, Hw, &Size);
92         ok(Err == ERROR_NO_SYSTEM_RESOURCES, "Expected error: ERROR_NO_SYSTEM_RESOURCES. Got: %lx\n", Err);
93 
94         Size = 6;
95         Err = SendARP(IpAddr, 0, Hw, &Size);
96         ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
97 
98         Size = 8;
99         Err = SendARP(IpAddr, 0, Hw, &Size);
100         ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
101         Err = SendARP(IpAddr, 0x08080808, Hw, &Size);
102         ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
103 
104         Size = 4;
105         Err = SendARP(IpAddr, IpAddr, Hw, &Size);
106         ok(Err == ERROR_NO_SYSTEM_RESOURCES, "Expected error: ERROR_NO_SYSTEM_RESOURCES. Got: %lx\n", Err);
107 
108         Size = 6;
109         Err = SendARP(IpAddr, IpAddr, Hw, &Size);
110         ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
111 
112         Size = 8;
113         Err = SendARP(IpAddr, IpAddr, Hw, &Size);
114         ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
115 
116         *Source = IpAddr;
117         Tested = TRUE;
118         break;
119     }
120 
121     free(Addresses);
122 
123     if (!Tested)
124     {
125         skip("No suitable interface found\n");
126         return;
127     }
128 
129     Size = sizeof(IP_ADAPTER_INFO);
130     Adapters = (PIP_ADAPTER_INFO)malloc(Size);
131     if (!Adapters)
132     {
133         skip("Memory failure\n");
134         return;
135     }
136 
137     Err = GetAdaptersInfo(Adapters, &Size);
138     if (Err == ERROR_BUFFER_OVERFLOW)
139     {
140         free(Adapters);
141         Adapters = (PIP_ADAPTER_INFO)malloc(Size);
142         if (!Adapters)
143         {
144             skip("Memory failure\n");
145             return;
146         }
147 
148         Err = GetAdaptersInfo(Adapters, &Size);
149     }
150 
151     if (Err != ERROR_SUCCESS)
152     {
153         skip("GetAdaptersInfo() failure\n");
154         free(Adapters);
155         return;
156     }
157 
158     Tested = FALSE;
159     for (CurrentA = Adapters; CurrentA; CurrentA = CurrentA->Next)
160     {
161         IPAddr IpAddr;
162         NTSTATUS Status;
163         const CHAR * Terminator;
164 
165         Status = RtlIpv4StringToAddressA(CurrentA->IpAddressList.IpAddress.String, TRUE, &Terminator, (struct in_addr *)&IpAddr);
166         if (!NT_SUCCESS(Status))
167             continue;
168 
169         if (IpAddr != *Source)
170             continue;
171 
172         Status = RtlIpv4StringToAddressA(CurrentA->GatewayList.IpAddress.String, TRUE, &Terminator, (struct in_addr *)&IpAddr);
173         if (NT_SUCCESS(Status))
174         {
175             trace("Gateway found: %lu.%lu.%lu.%lu\n", IpAddr & 0xFF, (IpAddr >> 8) & 0xFF, (IpAddr >> 16) & 0xFF, (IpAddr >> 24) & 0xFF);
176             Tested = TRUE;
177             *Gateway = IpAddr;
178         }
179 
180         break;
181     }
182 
183     free(Adapters);
184 
185     if (!Tested)
186     {
187         skip("No suitable gateway found\n");
188         return;
189     }
190 
191     Size = 4;
192     Err = SendARP(*Gateway, *Source, Hw, &Size);
193     ok(Err == ERROR_GEN_FAILURE, "Expected error: ERROR_GEN_FAILURE. Got: %lx\n", Err);
194 
195     Size = 6;
196     Err = SendARP(*Gateway, *Source, Hw, &Size);
197     ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
198 
199     Size = 8;
200     Err = SendARP(*Gateway, *Source, Hw, &Size);
201     ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
202 
203     Size = 4;
204     Err = SendARP(*Source, *Gateway, Hw, &Size);
205     ok(Err == ERROR_NO_SYSTEM_RESOURCES, "Expected error: ERROR_NO_SYSTEM_RESOURCES. Got: %lx\n", Err);
206 
207     Size = 6;
208     Err = SendARP(*Source, *Gateway, Hw, &Size);
209     ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
210 
211     Size = 8;
212     Err = SendARP(*Source, *Gateway, Hw, &Size);
213     ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
214 
215     Size = 4;
216     Err = SendARP(*Gateway, 0x08080808, Hw, &Size);
217     ok(Err == ERROR_GEN_FAILURE, "Expected error: ERROR_GEN_FAILURE. Got: %lx\n", Err);
218 
219     Size = 6;
220     Err = SendARP(*Gateway, 0x08080808, Hw, &Size);
221     ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
222 
223     Size = 8;
224     Err = SendARP(*Gateway, 0x08080808, Hw, &Size);
225     ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
226 
227     Size = 4;
228     Err = SendARP(*Source, 0x08080808, Hw, &Size);
229     ok(Err == ERROR_NO_SYSTEM_RESOURCES, "Expected error: ERROR_NO_SYSTEM_RESOURCES. Got: %lx\n", Err);
230 
231     Size = 6;
232     Err = SendARP(*Source, 0x08080808, Hw, &Size);
233     ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
234 
235     Size = 8;
236     Err = SendARP(*Source, 0x08080808, Hw, &Size);
237     ok(Err == ERROR_SUCCESS, "Expected error: ERROR_SUCCESS. Got: %lx\n", Err);
238 }
239 
TestKM(IPAddr Source,IPAddr Gateway)240 static VOID TestKM(IPAddr Source, IPAddr Gateway)
241 {
242     HANDLE hDevice;
243     NTSTATUS Status;
244     IO_STATUS_BLOCK IoStatusBlock;
245     UNICODE_STRING DevName = RTL_CONSTANT_STRING(L"\\Device\\Ip");
246     OBJECT_ATTRIBUTES ObjectAttributes;
247     HANDLE hEvent;
248     ULONG Hw[2];
249     ULONG Ip[2];
250 
251     InitializeObjectAttributes(&ObjectAttributes,
252                                &DevName,
253                                OBJ_CASE_INSENSITIVE,
254                                NULL,
255                                NULL);
256 
257     Status = NtCreateFile(&hDevice, GENERIC_EXECUTE, &ObjectAttributes,
258                           &IoStatusBlock, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF,
259                           0, NULL, 0);
260     if (!NT_SUCCESS(Status))
261     {
262         skip("NtCreateFile() failed with status: %lx\n", Status);
263         return;
264     }
265 
266     hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
267     if (!hEvent)
268     {
269         skip("CreateEventW() with error: %lx\n", GetLastError());
270         CloseHandle(hDevice);
271         return;
272     }
273 
274     IoStatusBlock.Status = STATUS_SUCCESS;
275     IoStatusBlock.Information = 0;
276     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, NULL, 0, NULL, 0);
277     if (Status == STATUS_PENDING)
278     {
279         NtWaitForSingleObject(hEvent, FALSE, NULL);
280         Status = IoStatusBlock.Status;
281     }
282     ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
283     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
284 
285     memset(Ip, 0, sizeof(Ip));
286     ResetEvent(hEvent);
287     IoStatusBlock.Status = STATUS_SUCCESS;
288     IoStatusBlock.Information = 0;
289     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), NULL, 0);
290     if (Status == STATUS_PENDING)
291     {
292         NtWaitForSingleObject(hEvent, FALSE, NULL);
293         Status = IoStatusBlock.Status;
294     }
295     ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
296     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
297 
298     ResetEvent(hEvent);
299     IoStatusBlock.Status = STATUS_SUCCESS;
300     IoStatusBlock.Information = 0;
301     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 4);
302     if (Status == STATUS_PENDING)
303     {
304         NtWaitForSingleObject(hEvent, FALSE, NULL);
305         Status = IoStatusBlock.Status;
306     }
307     ok(Status == STATUS_UNSUCCESSFUL, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
308     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
309 
310     ResetEvent(hEvent);
311     IoStatusBlock.Status = STATUS_SUCCESS;
312     IoStatusBlock.Information = 0;
313     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 6);
314     if (Status == STATUS_PENDING)
315     {
316         NtWaitForSingleObject(hEvent, FALSE, NULL);
317         Status = IoStatusBlock.Status;
318     }
319     ok(Status == STATUS_UNSUCCESSFUL, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
320     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
321 
322     ResetEvent(hEvent);
323     IoStatusBlock.Status = STATUS_SUCCESS;
324     IoStatusBlock.Information = 0;
325     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
326     if (Status == STATUS_PENDING)
327     {
328         NtWaitForSingleObject(hEvent, FALSE, NULL);
329         Status = IoStatusBlock.Status;
330     }
331     ok(Status == STATUS_UNSUCCESSFUL, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
332     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
333 
334     Ip[0] = Source;
335     ResetEvent(hEvent);
336     IoStatusBlock.Status = STATUS_SUCCESS;
337     IoStatusBlock.Information = 0;
338     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip[0]), NULL, 0);
339     if (Status == STATUS_PENDING)
340     {
341         NtWaitForSingleObject(hEvent, FALSE, NULL);
342         Status = IoStatusBlock.Status;
343     }
344     ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
345     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
346 
347     ResetEvent(hEvent);
348     IoStatusBlock.Status = STATUS_SUCCESS;
349     IoStatusBlock.Information = 0;
350     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip[0]), Hw, 4);
351     if (Status == STATUS_PENDING)
352     {
353         NtWaitForSingleObject(hEvent, FALSE, NULL);
354         Status = IoStatusBlock.Status;
355     }
356     ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
357     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
358 
359     ResetEvent(hEvent);
360     IoStatusBlock.Status = STATUS_SUCCESS;
361     IoStatusBlock.Information = 0;
362     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip[0]), Hw, 6);
363     if (Status == STATUS_PENDING)
364     {
365         NtWaitForSingleObject(hEvent, FALSE, NULL);
366         Status = IoStatusBlock.Status;
367     }
368     ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
369     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
370 
371     ResetEvent(hEvent);
372     IoStatusBlock.Status = STATUS_SUCCESS;
373     IoStatusBlock.Information = 0;
374     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip[0]), Hw, 8);
375     if (Status == STATUS_PENDING)
376     {
377         NtWaitForSingleObject(hEvent, FALSE, NULL);
378         Status = IoStatusBlock.Status;
379     }
380     ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
381     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
382 
383     ResetEvent(hEvent);
384     IoStatusBlock.Status = STATUS_SUCCESS;
385     IoStatusBlock.Information = 0;
386     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), NULL, 0);
387     if (Status == STATUS_PENDING)
388     {
389         NtWaitForSingleObject(hEvent, FALSE, NULL);
390         Status = IoStatusBlock.Status;
391     }
392     ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
393     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
394 
395     ResetEvent(hEvent);
396     IoStatusBlock.Status = STATUS_SUCCESS;
397     IoStatusBlock.Information = 0;
398     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 4);
399     if (Status == STATUS_PENDING)
400     {
401         NtWaitForSingleObject(hEvent, FALSE, NULL);
402         Status = IoStatusBlock.Status;
403     }
404     ok(Status == STATUS_INSUFFICIENT_RESOURCES, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
405     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
406 
407     ResetEvent(hEvent);
408     IoStatusBlock.Status = STATUS_SUCCESS;
409     IoStatusBlock.Information = 0;
410     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 6);
411     if (Status == STATUS_PENDING)
412     {
413         NtWaitForSingleObject(hEvent, FALSE, NULL);
414         Status = IoStatusBlock.Status;
415     }
416     ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
417     ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
418 
419     ResetEvent(hEvent);
420     IoStatusBlock.Status = STATUS_SUCCESS;
421     IoStatusBlock.Information = 0;
422     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
423     if (Status == STATUS_PENDING)
424     {
425         NtWaitForSingleObject(hEvent, FALSE, NULL);
426         Status = IoStatusBlock.Status;
427     }
428     ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
429     ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
430 
431     Ip[1] = Source;
432     ResetEvent(hEvent);
433     IoStatusBlock.Status = STATUS_SUCCESS;
434     IoStatusBlock.Information = 0;
435     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), NULL, 0);
436     if (Status == STATUS_PENDING)
437     {
438         NtWaitForSingleObject(hEvent, FALSE, NULL);
439         Status = IoStatusBlock.Status;
440     }
441     ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
442     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
443 
444     ResetEvent(hEvent);
445     IoStatusBlock.Status = STATUS_SUCCESS;
446     IoStatusBlock.Information = 0;
447     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 4);
448     if (Status == STATUS_PENDING)
449     {
450         NtWaitForSingleObject(hEvent, FALSE, NULL);
451         Status = IoStatusBlock.Status;
452     }
453     ok(Status == STATUS_INSUFFICIENT_RESOURCES, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
454     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
455 
456     ResetEvent(hEvent);
457     IoStatusBlock.Status = STATUS_SUCCESS;
458     IoStatusBlock.Information = 0;
459     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 6);
460     if (Status == STATUS_PENDING)
461     {
462         NtWaitForSingleObject(hEvent, FALSE, NULL);
463         Status = IoStatusBlock.Status;
464     }
465     ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
466     ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
467 
468     ResetEvent(hEvent);
469     IoStatusBlock.Status = STATUS_SUCCESS;
470     IoStatusBlock.Information = 0;
471     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
472     if (Status == STATUS_PENDING)
473     {
474         NtWaitForSingleObject(hEvent, FALSE, NULL);
475         Status = IoStatusBlock.Status;
476     }
477     ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
478     ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
479 
480     Ip[1] = 0x08080808;
481     ResetEvent(hEvent);
482     IoStatusBlock.Status = STATUS_SUCCESS;
483     IoStatusBlock.Information = 0;
484     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
485     if (Status == STATUS_PENDING)
486     {
487         NtWaitForSingleObject(hEvent, FALSE, NULL);
488         Status = IoStatusBlock.Status;
489     }
490     ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
491     ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
492 
493     if (!Gateway)
494     {
495         skip("No suitable gateway found\n");
496         CloseHandle(hEvent);
497         CloseHandle(hDevice);
498         return;
499     }
500 
501     Ip[0] = Gateway;
502     Ip[1] = Source;
503     ResetEvent(hEvent);
504     IoStatusBlock.Status = STATUS_SUCCESS;
505     IoStatusBlock.Information = 0;
506     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), NULL, 0);
507     if (Status == STATUS_PENDING)
508     {
509         NtWaitForSingleObject(hEvent, FALSE, NULL);
510         Status = IoStatusBlock.Status;
511     }
512     ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
513     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
514 
515     ResetEvent(hEvent);
516     IoStatusBlock.Status = STATUS_SUCCESS;
517     IoStatusBlock.Information = 0;
518     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 4);
519     if (Status == STATUS_PENDING)
520     {
521         NtWaitForSingleObject(hEvent, FALSE, NULL);
522         Status = IoStatusBlock.Status;
523     }
524     ok(Status == STATUS_UNSUCCESSFUL, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
525     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
526 
527     ResetEvent(hEvent);
528     IoStatusBlock.Status = STATUS_SUCCESS;
529     IoStatusBlock.Information = 0;
530     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 6);
531     if (Status == STATUS_PENDING)
532     {
533         NtWaitForSingleObject(hEvent, FALSE, NULL);
534         Status = IoStatusBlock.Status;
535     }
536     ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
537     ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
538 
539     ResetEvent(hEvent);
540     IoStatusBlock.Status = STATUS_SUCCESS;
541     IoStatusBlock.Information = 0;
542     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
543     if (Status == STATUS_PENDING)
544     {
545         NtWaitForSingleObject(hEvent, FALSE, NULL);
546         Status = IoStatusBlock.Status;
547     }
548     ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
549     ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
550 
551     Ip[0] = Source;
552     Ip[1] = Gateway;
553     ResetEvent(hEvent);
554     IoStatusBlock.Status = STATUS_SUCCESS;
555     IoStatusBlock.Information = 0;
556     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), NULL, 0);
557     if (Status == STATUS_PENDING)
558     {
559         NtWaitForSingleObject(hEvent, FALSE, NULL);
560         Status = IoStatusBlock.Status;
561     }
562     ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
563     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
564 
565     ResetEvent(hEvent);
566     IoStatusBlock.Status = STATUS_SUCCESS;
567     IoStatusBlock.Information = 0;
568     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 4);
569     if (Status == STATUS_PENDING)
570     {
571         NtWaitForSingleObject(hEvent, FALSE, NULL);
572         Status = IoStatusBlock.Status;
573     }
574     ok(Status == STATUS_INSUFFICIENT_RESOURCES, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
575     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
576 
577     ResetEvent(hEvent);
578     IoStatusBlock.Status = STATUS_SUCCESS;
579     IoStatusBlock.Information = 0;
580     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 6);
581     if (Status == STATUS_PENDING)
582     {
583         NtWaitForSingleObject(hEvent, FALSE, NULL);
584         Status = IoStatusBlock.Status;
585     }
586     ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
587     ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
588 
589     ResetEvent(hEvent);
590     IoStatusBlock.Status = STATUS_SUCCESS;
591     IoStatusBlock.Information = 0;
592     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
593     if (Status == STATUS_PENDING)
594     {
595         NtWaitForSingleObject(hEvent, FALSE, NULL);
596         Status = IoStatusBlock.Status;
597     }
598     ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
599     ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
600 
601     Ip[0] = Gateway;
602     Ip[1] = 0x08080808;
603     ResetEvent(hEvent);
604     IoStatusBlock.Status = STATUS_SUCCESS;
605     IoStatusBlock.Information = 0;
606     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), NULL, 0);
607     if (Status == STATUS_PENDING)
608     {
609         NtWaitForSingleObject(hEvent, FALSE, NULL);
610         Status = IoStatusBlock.Status;
611     }
612     ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
613     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
614 
615     ResetEvent(hEvent);
616     IoStatusBlock.Status = STATUS_SUCCESS;
617     IoStatusBlock.Information = 0;
618     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 4);
619     if (Status == STATUS_PENDING)
620     {
621         NtWaitForSingleObject(hEvent, FALSE, NULL);
622         Status = IoStatusBlock.Status;
623     }
624     ok(Status == STATUS_UNSUCCESSFUL, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
625     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
626 
627     ResetEvent(hEvent);
628     IoStatusBlock.Status = STATUS_SUCCESS;
629     IoStatusBlock.Information = 0;
630     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 6);
631     if (Status == STATUS_PENDING)
632     {
633         NtWaitForSingleObject(hEvent, FALSE, NULL);
634         Status = IoStatusBlock.Status;
635     }
636     ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
637     ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
638 
639     ResetEvent(hEvent);
640     IoStatusBlock.Status = STATUS_SUCCESS;
641     IoStatusBlock.Information = 0;
642     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
643     if (Status == STATUS_PENDING)
644     {
645         NtWaitForSingleObject(hEvent, FALSE, NULL);
646         Status = IoStatusBlock.Status;
647     }
648     ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
649     ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
650 
651     Ip[0] = Source;
652     ResetEvent(hEvent);
653     IoStatusBlock.Status = STATUS_SUCCESS;
654     IoStatusBlock.Information = 0;
655     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), NULL, 0);
656     if (Status == STATUS_PENDING)
657     {
658         NtWaitForSingleObject(hEvent, FALSE, NULL);
659         Status = IoStatusBlock.Status;
660     }
661     ok(Status == STATUS_INVALID_BUFFER_SIZE, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
662     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
663 
664     ResetEvent(hEvent);
665     IoStatusBlock.Status = STATUS_SUCCESS;
666     IoStatusBlock.Information = 0;
667     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 4);
668     if (Status == STATUS_PENDING)
669     {
670         NtWaitForSingleObject(hEvent, FALSE, NULL);
671         Status = IoStatusBlock.Status;
672     }
673     ok(Status == STATUS_INSUFFICIENT_RESOURCES, "NtDeviceIoControlFile() failed with unexpected status: %lx\n", Status);
674     ok(IoStatusBlock.Information == 0, "Excepted 0, got: %lu\n", IoStatusBlock.Information);
675 
676     ResetEvent(hEvent);
677     IoStatusBlock.Status = STATUS_SUCCESS;
678     IoStatusBlock.Information = 0;
679     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 6);
680     if (Status == STATUS_PENDING)
681     {
682         NtWaitForSingleObject(hEvent, FALSE, NULL);
683         Status = IoStatusBlock.Status;
684     }
685     ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
686     ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
687 
688     ResetEvent(hEvent);
689     IoStatusBlock.Status = STATUS_SUCCESS;
690     IoStatusBlock.Information = 0;
691     Status = NtDeviceIoControlFile(hDevice, hEvent, NULL, NULL, &IoStatusBlock, IOCTL_QUERY_IP_HW_ADDRESS, Ip, sizeof(Ip), Hw, 8);
692     if (Status == STATUS_PENDING)
693     {
694         NtWaitForSingleObject(hEvent, FALSE, NULL);
695         Status = IoStatusBlock.Status;
696     }
697     ok(Status == STATUS_SUCCESS, "NtDeviceIoControlFile() failed with status: %lx\n", Status);
698     ok(IoStatusBlock.Information == 6, "Excepted 6, got: %lu\n", IoStatusBlock.Information);
699 
700     CloseHandle(hEvent);
701     CloseHandle(hDevice);
702 }
703 
START_TEST(SendARP)704 START_TEST(SendARP)
705 {
706     IPAddr Source = 0;
707     IPAddr Gateway = 0;
708 
709     TestUM(&Source, &Gateway);
710     if (!Source)
711     {
712         skip("No suitable interface found\n");
713         return;
714     }
715 
716     TestKM(Source, Gateway);
717 }
718