1 /*
2  * PROJECT:     ReactOS API Tests
3  * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4  * PURPOSE:     Tests for network interface name resolving functions
5  * COPYRIGHT:   Copyright 2017 Stanislav Motylkov
6  */
7 
8 #include <apitest.h>
9 
10 #define WIN32_NO_STATUS
11 #include <iphlpapi.h>
12 #include <ndk/rtlfuncs.h>
13 #include <initguid.h>
14 
15 DEFINE_GUID(MY_TEST_GUID, 0x8D1AB70F, 0xADF0, 0x49FC, 0x9D, 0x07, 0x4E, 0x89, 0x29, 0x2D, 0xC5, 0x2B);
16 static DWORD (WINAPI * pNhGetInterfaceNameFromGuid)(PVOID, PVOID, PULONG, DWORD, DWORD);
17 static DWORD (WINAPI * pNhGetInterfaceNameFromDeviceGuid)(PVOID, PVOID, PULONG, DWORD, DWORD);
18 
19 /*
20  * Tests for NhGetInterfaceNameFromGuid
21  */
22 static
23 VOID
24 test_NhGetInterfaceNameFromGuid(GUID AdapterGUID, DWORD par1, DWORD par2)
25 {
26     DWORD ApiReturn, Error;
27     ULONG ulOutBufLen;
28     WCHAR Name[MAX_INTERFACE_NAME_LEN + 4];
29     GUID UniqueGUID = MY_TEST_GUID;
30     SIZE_T Length;
31 
32     // Test NULL GUID
33     SetLastError(0xbeeffeed);
34     Error = 0xbeeffeed;
35     ZeroMemory(&Name, sizeof(Name));
36     ApiReturn = ERROR_SUCCESS;
37     ulOutBufLen = sizeof(Name);
38     StartSeh()
39         ApiReturn = pNhGetInterfaceNameFromGuid(NULL, &Name, &ulOutBufLen, par1, par2);
40         Error = GetLastError();
41     EndSeh(((GetVersion() & 0xFF) >= 6) ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION);
42 
43     ok_long(ApiReturn, ((GetVersion() & 0xFF) >= 6) ? ERROR_INVALID_PARAMETER : ERROR_SUCCESS);
44     ok(Error == 0xbeeffeed,
45        "GetLastError() returned %ld, expected 0xbeeffeed\n",
46        Error);
47     ok(ulOutBufLen == sizeof(Name),
48        "ulOutBufLen is %ld, expected = sizeof(Name)\n",
49        ulOutBufLen);
50     ok_wstr(L"", Name);
51 
52     // Test correct GUID, but NULL name
53     SetLastError(0xbeeffeed);
54     ZeroMemory(&Name, sizeof(Name));
55     ApiReturn = pNhGetInterfaceNameFromGuid(&AdapterGUID, NULL, &ulOutBufLen, par1, par2);
56     Error = GetLastError();
57 
58     ok_long(ApiReturn, ((GetVersion() & 0xFF) >= 6) ? ERROR_INVALID_PARAMETER : ERROR_SUCCESS);
59     ok_long(Error, ((GetVersion() & 0xFF) >= 6) ? ERROR_SUCCESS : 0xbeeffeed);
60     ok(ulOutBufLen > 0,
61        "ulOutBufLen is %ld, expected > 0\n",
62        ulOutBufLen);
63     ok_wstr(L"", Name);
64 
65     // NhGetInterfaceNameFromGuid will throw exception if pOutBufLen is NULL
66     SetLastError(0xbeeffeed);
67     Error = 0xbeeffeed;
68     ZeroMemory(&Name, sizeof(Name));
69     ApiReturn = 0xdeadbeef;
70     StartSeh()
71         ApiReturn = pNhGetInterfaceNameFromGuid(&AdapterGUID, &Name, NULL, par1, par2);
72         Error = GetLastError();
73     EndSeh(STATUS_ACCESS_VIOLATION);
74 
75     ok(ApiReturn == 0xdeadbeef,
76        "ApiReturn returned %ld, expected 0xdeadbeef\n",
77        ApiReturn);
78     ok(Error == 0xbeeffeed,
79        "GetLastError() returned %ld, expected 0xbeeffeed\n",
80        Error);
81     ok(ulOutBufLen > 0,
82        "ulOutBufLen is %ld, expected > 0\n",
83        ulOutBufLen);
84     ok_wstr(L"", Name);
85 
86     // Test correct values
87     SetLastError(0xbeeffeed);
88     ZeroMemory(&Name, sizeof(Name));
89     ulOutBufLen = sizeof(Name);
90     ApiReturn = pNhGetInterfaceNameFromGuid(&AdapterGUID, &Name, &ulOutBufLen, par1, par2);
91     Error = GetLastError();
92 
93     ok(ApiReturn == ERROR_SUCCESS,
94        "ApiReturn returned %ld, expected ERROR_SUCCESS\n",
95        ApiReturn);
96     ok_long(Error, ((GetVersion() & 0xFF) >= 6) ? 0 : 0xbeeffeed);
97     ok(ulOutBufLen > 0,
98        "ulOutBufLen is %ld, expected > 0\n",
99        ulOutBufLen);
100     Length = wcslen(Name);
101     ok(Length > 0,
102        "wcslen(Name) is %ld, expected > 0\n",
103        Length);
104     if (Length > 0)
105         trace("Adapter name: \"%S\"\n", Name);
106 
107     // Test correct values, but with new unique GUID
108     SetLastError(0xbeeffeed);
109     ZeroMemory(&Name, sizeof(Name));
110     ulOutBufLen = sizeof(Name);
111     ApiReturn = pNhGetInterfaceNameFromGuid((PVOID)&UniqueGUID, &Name, &ulOutBufLen, par1, par2);
112     Error = GetLastError();
113 
114     ok_long(ApiReturn, ((GetVersion() & 0xFF) >= 6) ? ERROR_INVALID_PARAMETER : ERROR_NOT_FOUND);
115     ok_long(Error, 0);
116     ok(ulOutBufLen == sizeof(Name),
117        "ulOutBufLen is %ld, expected = sizeof(Name)\n",
118        ulOutBufLen);
119     ok_wstr(L"", Name);
120 
121     // Test correct values, but with small length
122     SetLastError(0xbeeffeed);
123     ZeroMemory(&Name, sizeof(Name));
124     ulOutBufLen = 0;
125     ApiReturn = pNhGetInterfaceNameFromGuid(&AdapterGUID, &Name, &ulOutBufLen, par1, par2);
126     Error = GetLastError();
127 
128     ok_long(ApiReturn, ((GetVersion() & 0xFF) >= 6) ? ERROR_NOT_ENOUGH_MEMORY : ERROR_INSUFFICIENT_BUFFER);
129     ok_long(Error, ((GetVersion() & 0xFF) >= 6) ? 0 : 0xbeeffeed);
130     ok_long(ulOutBufLen, MAX_INTERFACE_NAME_LEN * 2 + ((GetVersion() & 0xFF) >= 6 ? 2 : 0));
131     ok_wstr(L"", Name);
132 }
133 
134 /*
135  * Tests for NhGetInterfaceNameFromDeviceGuid
136  */
137 static
138 VOID
139 test_NhGetInterfaceNameFromDeviceGuid(GUID AdapterGUID, DWORD par1, DWORD par2)
140 {
141     DWORD ApiReturn, Error;
142     ULONG ulOutBufLen;
143     WCHAR Name[MAX_INTERFACE_NAME_LEN];
144     GUID UniqueGUID = MY_TEST_GUID;
145     SIZE_T Length;
146 
147     // Test NULL GUID
148     // Windows XP: NhGetInterfaceNameFromDeviceGuid throws exception here
149     SetLastError(0xbeeffeed);
150     Error = 0xbeeffeed;
151     ZeroMemory(&Name, sizeof(Name));
152     ApiReturn = ERROR_SUCCESS;
153     ulOutBufLen = sizeof(Name);
154     StartSeh()
155         ApiReturn = pNhGetInterfaceNameFromDeviceGuid(NULL, &Name, &ulOutBufLen, par1, par2);
156         Error = GetLastError();
157     EndSeh(((GetVersion() & 0xFF) >= 6) ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION);
158 
159     ok_long(ApiReturn, ((GetVersion() & 0xFF) >= 6) ? ERROR_INVALID_PARAMETER : 0);
160     ok(Error == 0xbeeffeed,
161        "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
162        Error);
163     ok(ulOutBufLen == sizeof(Name),
164        "ulOutBufLen is %ld, expected = sizeof(Name)\n",
165        ulOutBufLen);
166     ok_wstr(L"", Name);
167 
168     // Test correct GUID, but NULL name
169     SetLastError(0xbeeffeed);
170     Error = 0xbeeffeed;
171     ZeroMemory(&Name, sizeof(Name));
172     ApiReturn = ERROR_SUCCESS;
173     StartSeh()
174         ApiReturn = pNhGetInterfaceNameFromDeviceGuid(&AdapterGUID, NULL, &ulOutBufLen, par1, par2);
175         Error = GetLastError();
176     EndSeh(((GetVersion() & 0xFF) >= 6) ? STATUS_SUCCESS : STATUS_ACCESS_VIOLATION);
177 
178     ok_long(ApiReturn, ((GetVersion() & 0xFF) >= 6) ? ERROR_INVALID_PARAMETER : 0);
179     ok_long(Error, ((GetVersion() & 0xFF) >= 6) ? ERROR_SUCCESS : 0xbeeffeed);
180     ok(ulOutBufLen > 0,
181        "ulOutBufLen is %ld, expected > 0\n",
182        ulOutBufLen);
183     ok_wstr(L"", Name);
184 
185     // NhGetInterfaceNameFromDeviceGuid will throw exception if pOutBufLen is NULL
186     SetLastError(0xbeeffeed);
187     Error = 0xbeeffeed;
188     ZeroMemory(&Name, sizeof(Name));
189     ApiReturn = ERROR_SUCCESS;
190     StartSeh()
191         ApiReturn = pNhGetInterfaceNameFromDeviceGuid(&AdapterGUID, &Name, NULL, par1, par2);
192         Error = GetLastError();
193     EndSeh(STATUS_ACCESS_VIOLATION);
194 
195     ok_long(ApiReturn, 0);
196     ok_long(Error, 0xbeeffeed);
197     ok(ulOutBufLen > 0,
198        "ulOutBufLen is %ld, expected > 0\n",
199        ulOutBufLen);
200     ok_wstr(L"", Name);
201 
202     // Test correct values
203     SetLastError(0xbeeffeed);
204     ZeroMemory(&Name, sizeof(Name));
205     ulOutBufLen = sizeof(Name);
206     ApiReturn = pNhGetInterfaceNameFromDeviceGuid(&AdapterGUID, &Name, &ulOutBufLen, par1, par2);
207     Error = GetLastError();
208 
209     ok(ApiReturn == ERROR_SUCCESS,
210        "ApiReturn returned %ld, expected ERROR_SUCCESS\n",
211        ApiReturn);
212     ok(Error == ERROR_SUCCESS,
213        "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
214        Error);
215     ok(ulOutBufLen > 0,
216        "ulOutBufLen is %ld, expected > 0\n",
217        ulOutBufLen);
218     Length = wcslen(Name);
219     ok(Length > 0,
220        "wcslen(Name) is %ld, expected > 0\n",
221        Length);
222     if (Length > 0)
223         trace("Adapter name: \"%S\"\n", Name);
224 
225     // Test correct values, but with new unique GUID
226     SetLastError(0xbeeffeed);
227     ZeroMemory(&Name, sizeof(Name));
228     ulOutBufLen = sizeof(Name);
229     ApiReturn = pNhGetInterfaceNameFromDeviceGuid((PVOID)&UniqueGUID, &Name, &ulOutBufLen, par1, par2);
230     Error = GetLastError();
231 
232     ok_long(ApiReturn, ((GetVersion() & 0xFF) >= 6) ? ERROR_INVALID_PARAMETER : ERROR_NOT_FOUND);
233     ok(Error == ERROR_SUCCESS,
234        "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
235        Error);
236     ok(ulOutBufLen == sizeof(Name),
237        "ulOutBufLen is %ld, expected = sizeof(Name)\n",
238        ulOutBufLen);
239     ok_wstr(L"", Name);
240 
241     // Test correct values, but with small length
242     SetLastError(0xbeeffeed);
243     ZeroMemory(&Name, sizeof(Name));
244     ulOutBufLen = 0;
245     ApiReturn = pNhGetInterfaceNameFromDeviceGuid(&AdapterGUID, &Name, &ulOutBufLen, par1, par2);
246     Error = GetLastError();
247 
248     ok_long(ApiReturn, ((GetVersion() & 0xFF) >= 6) ? ERROR_NOT_ENOUGH_MEMORY : ERROR_INSUFFICIENT_BUFFER);
249     ok(Error == ERROR_SUCCESS,
250        "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
251        Error);
252     ok_long(ulOutBufLen, MAX_INTERFACE_NAME_LEN * 2 + (((GetVersion() & 0xFF) >= 6) ? 2 : 0));
253     ok_wstr(L"", Name);
254 }
255 
256 static
257 VOID
258 test_GetInterfaceName(VOID)
259 {
260     PIP_INTERFACE_INFO pInfo = NULL;
261     ULONG ulOutBufLen = 0;
262     DWORD ApiReturn;
263     WCHAR Name[MAX_ADAPTER_NAME];
264     UNICODE_STRING GuidString;
265     GUID AdapterGUID;
266     HINSTANCE hIpHlpApi;
267 
268     ApiReturn = GetInterfaceInfo(pInfo, &ulOutBufLen);
269     ok(ApiReturn == ERROR_INSUFFICIENT_BUFFER,
270        "GetInterfaceInfo(pInfo, &ulOutBufLen) returned %ld, expected ERROR_INSUFFICIENT_BUFFER\n",
271        ApiReturn);
272     if (ApiReturn != ERROR_INSUFFICIENT_BUFFER)
273     {
274         skip("Can't determine size of IP_INTERFACE_INFO. Can't proceed\n");
275         return;
276     }
277 
278     pInfo = (IP_INTERFACE_INFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulOutBufLen);
279     if (pInfo == NULL)
280     {
281         skip("pInfo is NULL. Can't proceed\n");
282         return;
283     }
284 
285     ApiReturn = GetInterfaceInfo(pInfo, &ulOutBufLen);
286     ok(ApiReturn == NO_ERROR,
287         "GetInterfaceInfo(pInfo, &ulOutBufLen) returned %ld, expected NO_ERROR\n",
288         ApiReturn);
289     if (ApiReturn != NO_ERROR || ulOutBufLen == 0)
290     {
291         skip("GetInterfaceInfo failed with error %ld. Can't proceed\n", ApiReturn);
292         return;
293     }
294 
295     if (pInfo->NumAdapters > 0)
296         CopyMemory(&Name, &pInfo->Adapter[0].Name, sizeof(Name));
297 
298     if (pInfo->NumAdapters == 0)
299     {
300         HeapFree(GetProcessHeap(), 0, pInfo);
301         skip("pInfo->NumAdapters = 0. Can't proceed\n");
302         return;
303     }
304     trace("pInfo->NumAdapters: %lu\n", pInfo->NumAdapters);
305 
306     HeapFree(GetProcessHeap(), 0, pInfo);
307 
308     ApiReturn = wcsncmp(Name, L"\\DEVICE\\TCPIP_", 14);
309     ok(ApiReturn == 0,
310        "wcsncmp(Name, L\"\\DEVICE\\TCPIP_\", 14) returned %ld, expected 0\n",
311        ApiReturn);
312     if (ApiReturn != 0)
313     {
314         if (wcslen(Name) == 0)
315         {
316             skip("pInfo->Adapter[0].Name is empty. Can't proceed\n");
317             return;
318         }
319         else
320         {
321             // workaround for ReactOS
322             trace("pInfo->Adapter[0].Name = \"%ls\" is incorrect.\n", Name);
323             RtlInitUnicodeString(&GuidString, &Name[0]);
324         }
325     }
326     else
327     {
328         RtlInitUnicodeString(&GuidString, &Name[14]);
329     }
330 
331     ApiReturn = RtlGUIDFromString(&GuidString, &AdapterGUID);
332     if (ApiReturn != 0)
333     {
334         skip("RtlGUIDFromString failed. Can't proceed\n");
335         return;
336     }
337 
338     hIpHlpApi = GetModuleHandleW(L"iphlpapi.dll");
339     if (!hIpHlpApi)
340     {
341         skip("Failed to load iphlpapi.dll. Can't proceed\n");
342         return;
343     }
344 
345     pNhGetInterfaceNameFromGuid = (void *)GetProcAddress(hIpHlpApi, "NhGetInterfaceNameFromGuid");
346 
347     if (!pNhGetInterfaceNameFromGuid)
348         skip("NhGetInterfaceNameFromGuid not found. Can't proceed\n");
349     else
350         test_NhGetInterfaceNameFromGuid(AdapterGUID, 0, 0);
351 
352     pNhGetInterfaceNameFromDeviceGuid = (void *)GetProcAddress(hIpHlpApi, "NhGetInterfaceNameFromDeviceGuid");
353 
354     if (!pNhGetInterfaceNameFromDeviceGuid)
355         skip("NhGetInterfaceNameFromDeviceGuid not found. Can't proceed\n");
356     else
357         test_NhGetInterfaceNameFromDeviceGuid(AdapterGUID, 1, 0);
358 }
359 
360 START_TEST(GetInterfaceName)
361 {
362     test_GetInterfaceName();
363 }
364