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