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(STATUS_SUCCESS);
42 
43     ok(ApiReturn == ERROR_INVALID_PARAMETER,
44        "ApiReturn returned %ld, expected ERROR_INVALID_PARAMETER\n",
45        ApiReturn);
46     ok(Error == 0xbeeffeed,
47        "GetLastError() returned %ld, expected 0xbeeffeed\n",
48        Error);
49     ok(ulOutBufLen == sizeof(Name),
50        "ulOutBufLen is %ld, expected = sizeof(Name)\n",
51        ulOutBufLen);
52     ok_wstr(L"", Name);
53 
54     // Test correct GUID, but NULL name
55     SetLastError(0xbeeffeed);
56     ZeroMemory(&Name, sizeof(Name));
57     ApiReturn = pNhGetInterfaceNameFromGuid(&AdapterGUID, NULL, &ulOutBufLen, par1, par2);
58     Error = GetLastError();
59 
60     ok(ApiReturn == ERROR_SUCCESS,
61        "ApiReturn returned %ld, expected ERROR_SUCCESS\n",
62        ApiReturn);
63     ok(Error == 0xbeeffeed,
64        "GetLastError() returned %ld, expected 0xbeeffeed\n",
65        Error);
66     ok(ulOutBufLen > 0,
67        "ulOutBufLen is %ld, expected > 0\n",
68        ulOutBufLen);
69     ok_wstr(L"", Name);
70 
71     // NhGetInterfaceNameFromGuid will throw exception if pOutBufLen is NULL
72     SetLastError(0xbeeffeed);
73     Error = 0xbeeffeed;
74     ZeroMemory(&Name, sizeof(Name));
75     ApiReturn = ERROR_SUCCESS;
76     StartSeh()
77         ApiReturn = pNhGetInterfaceNameFromGuid(&AdapterGUID, &Name, NULL, par1, par2);
78         Error = GetLastError();
79     EndSeh(STATUS_SUCCESS);
80 
81     ok(ApiReturn == ERROR_INVALID_PARAMETER,
82        "ApiReturn returned %ld, expected ERROR_INVALID_PARAMETER\n",
83        ApiReturn);
84     ok(Error == 0xbeeffeed,
85        "GetLastError() returned %ld, expected 0xbeeffeed\n",
86        Error);
87     ok(ulOutBufLen > 0,
88        "ulOutBufLen is %ld, expected > 0\n",
89        ulOutBufLen);
90     ok_wstr(L"", Name);
91 
92     // Test correct values
93     SetLastError(0xbeeffeed);
94     ZeroMemory(&Name, sizeof(Name));
95     ulOutBufLen = sizeof(Name);
96     ApiReturn = pNhGetInterfaceNameFromGuid(&AdapterGUID, &Name, &ulOutBufLen, par1, par2);
97     Error = GetLastError();
98 
99     ok(ApiReturn == ERROR_SUCCESS,
100        "ApiReturn returned %ld, expected ERROR_SUCCESS\n",
101        ApiReturn);
102     ok(Error == 0xbeeffeed,
103        "GetLastError() returned %ld, expected 0xbeeffeed\n",
104        Error);
105     ok(ulOutBufLen > 0,
106        "ulOutBufLen is %ld, expected > 0\n",
107        ulOutBufLen);
108     Length = wcslen(Name);
109     ok(Length > 0,
110        "wcslen(Name) is %ld, expected > 0\n",
111        Length);
112     if (Length > 0)
113         trace("Adapter name: \"%S\"\n", Name);
114 
115     // Test correct values, but with new unique GUID
116     SetLastError(0xbeeffeed);
117     ZeroMemory(&Name, sizeof(Name));
118     ulOutBufLen = sizeof(Name);
119     ApiReturn = pNhGetInterfaceNameFromGuid((PVOID)&UniqueGUID, &Name, &ulOutBufLen, par1, par2);
120     Error = GetLastError();
121 
122     ok(ApiReturn == ERROR_NOT_FOUND,
123        "ApiReturn returned %ld, expected ERROR_NOT_FOUND\n",
124        ApiReturn);
125     ok(Error == ERROR_PATH_NOT_FOUND,
126        "GetLastError() returned %ld, expected ERROR_PATH_NOT_FOUND\n",
127        Error);
128     ok(ulOutBufLen == sizeof(Name),
129        "ulOutBufLen is %ld, expected = sizeof(Name)\n",
130        ulOutBufLen);
131     ok_wstr(L"", Name);
132 
133     // Test correct values, but with small length
134     SetLastError(0xbeeffeed);
135     ZeroMemory(&Name, sizeof(Name));
136     ulOutBufLen = 0;
137     ApiReturn = pNhGetInterfaceNameFromGuid(&AdapterGUID, &Name, &ulOutBufLen, par1, par2);
138     Error = GetLastError();
139 
140     ok(ApiReturn == ERROR_INSUFFICIENT_BUFFER,
141        "ApiReturn returned %ld, expected ERROR_INSUFFICIENT_BUFFER\n",
142        ApiReturn);
143     ok(Error == 0xbeeffeed,
144        "GetLastError() returned %ld, expected 0xbeeffeed\n",
145        Error);
146     ok(ulOutBufLen == MAX_INTERFACE_NAME_LEN * 2,
147        "ulOutBufLen is %ld, expected = MAX_INTERFACE_NAME_LEN * 2\n",
148        ulOutBufLen);
149     ok_wstr(L"", Name);
150 }
151 
152 /*
153  * Tests for NhGetInterfaceNameFromDeviceGuid
154  */
155 static
156 VOID
157 test_NhGetInterfaceNameFromDeviceGuid(GUID AdapterGUID, DWORD par1, DWORD par2)
158 {
159     DWORD ApiReturn, Error;
160     ULONG ulOutBufLen;
161     WCHAR Name[MAX_INTERFACE_NAME_LEN];
162     GUID UniqueGUID = MY_TEST_GUID;
163     SIZE_T Length;
164 
165     // Test NULL GUID
166     // Windows XP: NhGetInterfaceNameFromDeviceGuid throws exception here
167     SetLastError(0xbeeffeed);
168     Error = 0xbeeffeed;
169     ZeroMemory(&Name, sizeof(Name));
170     ApiReturn = ERROR_SUCCESS;
171     ulOutBufLen = sizeof(Name);
172     StartSeh()
173         ApiReturn = pNhGetInterfaceNameFromDeviceGuid(NULL, &Name, &ulOutBufLen, par1, par2);
174         Error = GetLastError();
175     EndSeh(STATUS_SUCCESS);
176 
177     ok(ApiReturn == ERROR_INVALID_PARAMETER,
178        "ApiReturn returned %ld, expected ERROR_INVALID_PARAMETER\n",
179        ApiReturn);
180     ok(Error == ERROR_SUCCESS,
181        "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
182        Error);
183     ok(ulOutBufLen == sizeof(Name),
184        "ulOutBufLen is %ld, expected = sizeof(Name)\n",
185        ulOutBufLen);
186     ok_wstr(L"", Name);
187 
188     // Test correct GUID, but NULL name
189     SetLastError(0xbeeffeed);
190     Error = 0xbeeffeed;
191     ZeroMemory(&Name, sizeof(Name));
192     ApiReturn = ERROR_SUCCESS;
193     StartSeh()
194         ApiReturn = pNhGetInterfaceNameFromDeviceGuid(&AdapterGUID, NULL, &ulOutBufLen, par1, par2);
195         Error = GetLastError();
196     EndSeh(STATUS_SUCCESS);
197 
198     ok(ApiReturn == ERROR_INVALID_PARAMETER,
199        "ApiReturn returned %ld, expected ERROR_INVALID_PARAMETER\n",
200        ApiReturn);
201     ok(Error == ERROR_SUCCESS,
202        "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
203        Error);
204     ok(ulOutBufLen > 0,
205        "ulOutBufLen is %ld, expected > 0\n",
206        ulOutBufLen);
207     ok_wstr(L"", Name);
208 
209     // NhGetInterfaceNameFromDeviceGuid will throw exception if pOutBufLen is NULL
210     SetLastError(0xbeeffeed);
211     Error = 0xbeeffeed;
212     ZeroMemory(&Name, sizeof(Name));
213     ApiReturn = ERROR_SUCCESS;
214     StartSeh()
215         ApiReturn = pNhGetInterfaceNameFromDeviceGuid(&AdapterGUID, &Name, NULL, par1, par2);
216         Error = GetLastError();
217     EndSeh(STATUS_SUCCESS);
218 
219     ok(ApiReturn == ERROR_INVALID_PARAMETER,
220        "ApiReturn returned %ld, expected ERROR_INVALID_PARAMETER\n",
221        ApiReturn);
222     ok(Error == ERROR_SUCCESS,
223        "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
224        Error);
225     ok(ulOutBufLen > 0,
226        "ulOutBufLen is %ld, expected > 0\n",
227        ulOutBufLen);
228     ok_wstr(L"", Name);
229 
230     // Test correct values
231     SetLastError(0xbeeffeed);
232     ZeroMemory(&Name, sizeof(Name));
233     ulOutBufLen = sizeof(Name);
234     ApiReturn = pNhGetInterfaceNameFromDeviceGuid(&AdapterGUID, &Name, &ulOutBufLen, par1, par2);
235     Error = GetLastError();
236 
237     ok(ApiReturn == ERROR_SUCCESS,
238        "ApiReturn returned %ld, expected ERROR_SUCCESS\n",
239        ApiReturn);
240     ok(Error == ERROR_SUCCESS,
241        "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
242        Error);
243     ok(ulOutBufLen > 0,
244        "ulOutBufLen is %ld, expected > 0\n",
245        ulOutBufLen);
246     Length = wcslen(Name);
247     ok(Length > 0,
248        "wcslen(Name) is %ld, expected > 0\n",
249        Length);
250     if (Length > 0)
251         trace("Adapter name: \"%S\"\n", Name);
252 
253     // Test correct values, but with new unique GUID
254     SetLastError(0xbeeffeed);
255     ZeroMemory(&Name, sizeof(Name));
256     ulOutBufLen = sizeof(Name);
257     ApiReturn = pNhGetInterfaceNameFromDeviceGuid((PVOID)&UniqueGUID, &Name, &ulOutBufLen, par1, par2);
258     Error = GetLastError();
259 
260     ok(ApiReturn == ERROR_NOT_FOUND,
261        "ApiReturn returned %ld, expected ERROR_NOT_FOUND\n",
262        ApiReturn);
263     ok(Error == ERROR_SUCCESS,
264        "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
265        Error);
266     ok(ulOutBufLen == sizeof(Name),
267        "ulOutBufLen is %ld, expected = sizeof(Name)\n",
268        ulOutBufLen);
269     ok_wstr(L"", Name);
270 
271     // Test correct values, but with small length
272     SetLastError(0xbeeffeed);
273     ZeroMemory(&Name, sizeof(Name));
274     ulOutBufLen = 0;
275     ApiReturn = pNhGetInterfaceNameFromDeviceGuid(&AdapterGUID, &Name, &ulOutBufLen, par1, par2);
276     Error = GetLastError();
277 
278     ok(ApiReturn == ERROR_INSUFFICIENT_BUFFER,
279        "ApiReturn returned %ld, expected ERROR_INSUFFICIENT_BUFFER\n",
280        ApiReturn);
281     ok(Error == ERROR_SUCCESS,
282        "GetLastError() returned %ld, expected ERROR_SUCCESS\n",
283        Error);
284     ok(ulOutBufLen == MAX_INTERFACE_NAME_LEN * 2,
285        "ulOutBufLen is %ld, expected = MAX_INTERFACE_NAME_LEN * 2\n",
286        ulOutBufLen);
287     ok_wstr(L"", Name);
288 }
289 
290 static
291 VOID
292 test_GetInterfaceName(VOID)
293 {
294     PIP_INTERFACE_INFO pInfo = NULL;
295     ULONG ulOutBufLen = 0;
296     DWORD ApiReturn;
297     WCHAR Name[MAX_ADAPTER_NAME];
298     UNICODE_STRING GuidString;
299     GUID AdapterGUID;
300     HINSTANCE hIpHlpApi;
301 
302     ApiReturn = GetInterfaceInfo(pInfo, &ulOutBufLen);
303     ok(ApiReturn == ERROR_INSUFFICIENT_BUFFER,
304        "GetInterfaceInfo(pInfo, &ulOutBufLen) returned %ld, expected ERROR_INSUFFICIENT_BUFFER\n",
305        ApiReturn);
306     if (ApiReturn != ERROR_INSUFFICIENT_BUFFER)
307     {
308         skip("Can't determine size of IP_INTERFACE_INFO. Can't proceed\n");
309         return;
310     }
311 
312     pInfo = (IP_INTERFACE_INFO *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ulOutBufLen);
313     if (pInfo == NULL)
314     {
315         skip("pInfo is NULL. Can't proceed\n");
316         return;
317     }
318 
319     ApiReturn = GetInterfaceInfo(pInfo, &ulOutBufLen);
320     ok(ApiReturn == NO_ERROR,
321         "GetInterfaceInfo(pInfo, &ulOutBufLen) returned %ld, expected NO_ERROR\n",
322         ApiReturn);
323     if (ApiReturn != NO_ERROR || ulOutBufLen == 0)
324     {
325         skip("GetInterfaceInfo failed with error %ld. Can't proceed\n", ApiReturn);
326         return;
327     }
328 
329     if (pInfo->NumAdapters > 0)
330         CopyMemory(&Name, &pInfo->Adapter[0].Name, sizeof(Name));
331 
332     if (pInfo->NumAdapters == 0)
333     {
334         HeapFree(GetProcessHeap(), 0, pInfo);
335         skip("pInfo->NumAdapters = 0. Can't proceed\n");
336         return;
337     }
338     trace("pInfo->NumAdapters: %lu\n", pInfo->NumAdapters);
339 
340     HeapFree(GetProcessHeap(), 0, pInfo);
341 
342     ApiReturn = wcsncmp(Name, L"\\DEVICE\\TCPIP_", 14);
343     ok(ApiReturn == 0,
344        "wcsncmp(Name, L\"\\DEVICE\\TCPIP_\", 14) returned %ld, expected 0\n",
345        ApiReturn);
346     if (ApiReturn != 0)
347     {
348         if (wcslen(Name) == 0)
349         {
350             skip("pInfo->Adapter[0].Name is empty. Can't proceed\n");
351             return;
352         }
353         else
354         {
355             // workaround for ReactOS
356             trace("pInfo->Adapter[0].Name = \"%ls\" is incorrect.\n", Name);
357             RtlInitUnicodeString(&GuidString, &Name[0]);
358         }
359     }
360     else
361     {
362         RtlInitUnicodeString(&GuidString, &Name[14]);
363     }
364 
365     ApiReturn = RtlGUIDFromString(&GuidString, &AdapterGUID);
366     if (ApiReturn != 0)
367     {
368         skip("RtlGUIDFromString failed. Can't proceed\n");
369         return;
370     }
371 
372     hIpHlpApi = GetModuleHandleW(L"iphlpapi.dll");
373     if (!hIpHlpApi)
374     {
375         skip("Failed to load iphlpapi.dll. Can't proceed\n");
376         return;
377     }
378 
379     pNhGetInterfaceNameFromGuid = (void *)GetProcAddress(hIpHlpApi, "NhGetInterfaceNameFromGuid");
380 
381     if (!pNhGetInterfaceNameFromGuid)
382         skip("NhGetInterfaceNameFromGuid not found. Can't proceed\n");
383     else
384         test_NhGetInterfaceNameFromGuid(AdapterGUID, 0, 0);
385 
386     pNhGetInterfaceNameFromDeviceGuid = (void *)GetProcAddress(hIpHlpApi, "NhGetInterfaceNameFromDeviceGuid");
387 
388     if (!pNhGetInterfaceNameFromDeviceGuid)
389         skip("NhGetInterfaceNameFromDeviceGuid not found. Can't proceed\n");
390     else
391         test_NhGetInterfaceNameFromDeviceGuid(AdapterGUID, 1, 0);
392 }
393 
394 START_TEST(GetInterfaceName)
395 {
396     test_GetInterfaceName();
397 }
398