d5ee736cb62208a5b98c293fccde56b7d60ec689
[reactos.git] / reactos / lib / iphlpapi / iphlpapi.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Winsock 2 IP Helper API DLL
4 * FILE: iphlpapi.c
5 * PURPOSE: DLL entry
6 * PROGRAMMERS: Robert Dickenson (robd@reactos.org)
7 * REVISIONS:
8 * RDD August 18, 2002 Created
9 */
10
11 #include <stdio.h>
12 #include <windows.h>
13 #include <tchar.h>
14 #include <time.h>
15 #include <stdlib.h>
16
17 #include <winsock2.h>
18 #include <ws2tcpip.h>
19 #include <iptypes.h>
20 #include <ipexport.h>
21 #include <iphlpapi.h>
22 #include <icmpapi.h>
23
24 #include "ipprivate.h"
25 #include "ipregprivate.h"
26 #include "debug.h"
27 //#include "trace.h"
28
29 #ifdef __GNUC__
30 #define EXPORT STDCALL
31 #else
32 #define EXPORT CALLBACK
33 #endif
34
35 #ifdef DBG
36
37 /* See debug.h for debug/trace constants */
38 DWORD DebugTraceLevel = MAX_TRACE;
39
40 #endif /* DBG */
41
42 /* To make the linker happy */
43 //VOID STDCALL KeBugCheck (ULONG BugCheckCode) {}
44
45
46 BOOL
47 EXPORT
48 DllMain(HANDLE hInstDll,
49 ULONG dwReason,
50 PVOID Reserved)
51 {
52 //WSH_DbgPrint(MIN_TRACE, ("DllMain of iphlpapi.dll\n"));
53
54 switch (dwReason) {
55 case DLL_PROCESS_ATTACH:
56 /* Don't need thread attach notifications
57 so disable them to improve performance */
58 DisableThreadLibraryCalls(hInstDll);
59 break;
60
61 case DLL_THREAD_ATTACH:
62 break;
63
64 case DLL_THREAD_DETACH:
65 break;
66
67 case DLL_PROCESS_DETACH:
68 break;
69 }
70 return TRUE;
71 }
72
73
74 /*
75 * @unimplemented
76 */
77 DWORD
78 STDCALL
79 AddIPAddress(IPAddr Address, IPMask IpMask, DWORD IfIndex, PULONG NTEContext, PULONG NTEInstance)
80 {
81 UNIMPLEMENTED
82 return 0L;
83 }
84
85
86 /*
87 * @unimplemented
88 */
89 DWORD
90 STDCALL
91 SetIpNetEntry(PMIB_IPNETROW pArpEntry)
92 {
93 UNIMPLEMENTED
94 return 0L;
95 }
96
97
98 /*
99 * @unimplemented
100 */
101 DWORD
102 STDCALL
103 CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute)
104 {
105 UNIMPLEMENTED
106 return 0L;
107 }
108
109
110 /*
111 * @unimplemented
112 */
113 DWORD
114 STDCALL
115 GetAdapterIndex(LPWSTR AdapterName, PULONG IfIndex)
116 {
117 return 0;
118 }
119
120
121 /*
122 * @unimplemented
123 */
124 DWORD
125 STDCALL
126 GetAdaptersInfo(PIP_ADAPTER_INFO pAdapterInfo, PULONG pOutBufLen)
127 {
128 LONG lErr;
129 DWORD dwSize;
130 DWORD dwIndex;
131 BYTE* pNextMemFree = (BYTE*) pAdapterInfo;
132 ULONG uUsedMemory = 0;
133 PIP_ADAPTER_INFO pPrevAdapter = NULL;
134 PIP_ADAPTER_INFO pCurrentAdapter = NULL;
135 HKEY hAdapters;
136 HKEY hAdapter;
137 HKEY hIpConfig;
138 wchar_t* strAdapter;
139 wchar_t* strTemp1;
140 wchar_t* strTemp2;
141 DWORD dwAdapterLen;
142 char strTemp[MAX_ADAPTER_NAME_LENGTH + 4];
143
144 if(pAdapterInfo == NULL && pOutBufLen == NULL)
145 return ERROR_INVALID_PARAMETER;
146 ZeroMemory(pAdapterInfo, *pOutBufLen);
147
148 lErr = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
149 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Adapters", 0, KEY_READ, &hAdapters);
150 if(lErr != ERROR_SUCCESS)
151 return lErr;
152
153 // Determine the size of the largest name of any adapter and the number of adapters.
154 lErr = RegQueryInfoKeyW(hAdapters, NULL, NULL, NULL, NULL, &dwAdapterLen, NULL, NULL, NULL, NULL, NULL, NULL);
155 if(lErr != ERROR_SUCCESS)
156 {
157 RegCloseKey(hAdapters);
158 return lErr;
159 }
160 dwAdapterLen++; // RegQueryInfoKeyW return value does not include terminating null.
161
162 strAdapter = (wchar_t*) malloc(dwAdapterLen * sizeof(wchar_t));
163
164 // Enumerate all adapters in SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Adapters.
165 for(dwIndex = 0; ; dwIndex++)
166 {
167 dwSize = dwAdapterLen; // Reset size of the strAdapterLen buffer.
168 lErr = RegEnumKeyExW(hAdapters, dwIndex, strAdapter, &dwSize, NULL, NULL, NULL, NULL);
169 if(lErr == ERROR_NO_MORE_ITEMS)
170 break;
171
172 // TODO Skip NdisWanIP???
173 if(wcsstr(strAdapter, L"NdisWanIp") != 0)
174 continue;
175
176 lErr = RegOpenKeyExW(hAdapters, strAdapter, 0, KEY_READ, &hAdapter);
177 if(lErr != ERROR_SUCCESS)
178 continue;
179
180 // Read the IpConfig value.
181 lErr = RegQueryValueExW(hAdapter, L"IpConfig", NULL, NULL, NULL, &dwSize);
182 if(lErr != ERROR_SUCCESS)
183 continue;
184
185 strTemp1 = (wchar_t*) malloc(dwSize);
186 strTemp2 = (wchar_t*) malloc(dwSize + 35 * sizeof(wchar_t));
187 lErr = RegQueryValueExW(hAdapter, L"IpConfig", NULL, NULL, (BYTE*) strTemp1, &dwSize);
188 if(lErr != ERROR_SUCCESS)
189 {
190 free(strTemp1);
191 free(strTemp2);
192 continue;
193 }
194 swprintf(strTemp2, L"SYSTEM\\CurrentControlSet\\Services\\%s", strTemp1);
195
196 // Open the IpConfig key.
197 lErr = RegOpenKeyExW(HKEY_LOCAL_MACHINE, strTemp2, 0, KEY_READ, &hIpConfig);
198 if(lErr != ERROR_SUCCESS)
199 {
200 free(strTemp1);
201 free(strTemp2);
202 continue;
203 }
204 free((void*) strTemp1);
205 free((void*) strTemp2);
206
207
208 // Fill IP_ADAPTER_INFO block.
209 pCurrentAdapter = (IP_ADAPTER_INFO*) pNextMemFree;
210 pNextMemFree += sizeof(IP_ADAPTER_INFO);
211 uUsedMemory += sizeof(IP_ADAPTER_INFO);
212 if(uUsedMemory > *pOutBufLen)
213 return ERROR_BUFFER_OVERFLOW; // TODO return the needed size
214
215 // struct _IP_ADAPTER_INFO* Next
216 if(pPrevAdapter != NULL)
217 pPrevAdapter->Next = pCurrentAdapter;
218 // TODO DWORD ComboIndex
219 // char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4]
220 wcstombs(strTemp, strAdapter, MAX_ADAPTER_NAME_LENGTH + 4);
221 strcpy(pCurrentAdapter->AdapterName, strTemp);
222 // TODO char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4]
223 // TODO UINT AddressLength
224 // TODO BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH]
225 // TODO DWORD Index
226 // TODO UINT Type
227 // TODO UINT DhcpEnabled
228 // TODO PIP_ADDR_STRING CurrentIpAddress
229 // IP_ADDR_STRING IpAddressList
230 dwSize = 16; lErr = RegQueryValueExW(hIpConfig, L"IPAddress", NULL, NULL, (BYTE*) &pCurrentAdapter->IpAddressList.IpAddress, &dwSize);
231 dwSize = 16; lErr = RegQueryValueExW(hIpConfig, L"SubnetMask", NULL, NULL, (BYTE*) &pCurrentAdapter->IpAddressList.IpMask, &dwSize);
232 if(strstr(pCurrentAdapter->IpAddressList.IpAddress.String, "0.0.0.0") != 0)
233 {
234 dwSize = 16; lErr = RegQueryValueExW(hIpConfig, L"DhcpIPAddress", NULL, NULL, (BYTE*) &pCurrentAdapter->IpAddressList.IpAddress, &dwSize);
235 dwSize = 16; lErr = RegQueryValueExW(hIpConfig, L"DhcpSubnetMask", NULL, NULL, (BYTE*) &pCurrentAdapter->IpAddressList.IpMask, &dwSize);
236 }
237 // TODO IP_ADDR_STRING GatewayList
238 // IP_ADDR_STRING DhcpServer
239 dwSize = 16; lErr = RegQueryValueExW(hIpConfig, L"DhcpServer", NULL, NULL, (BYTE*) &pCurrentAdapter->DhcpServer.IpAddress, &dwSize);
240 dwSize = 16; lErr = RegQueryValueExW(hIpConfig, L"DhcpSubnetMask", NULL, NULL, (BYTE*) &pCurrentAdapter->DhcpServer.IpMask, &dwSize);
241 // TODO BOOL HaveWins
242 // TODO IP_ADDR_STRING PrimaryWinsServer
243 // TODO IP_ADDR_STRING SecondaryWinsServer
244 // TODO time_t LeaseObtained
245 // TODO time_t LeaseExpires
246
247 pPrevAdapter = pCurrentAdapter;
248 RegCloseKey(hAdapter);
249 RegCloseKey(hIpConfig);
250 }
251
252 // Cleanup
253 free(strAdapter);
254 RegCloseKey(hAdapters);
255
256 return ERROR_SUCCESS;
257 }
258
259
260 ////////////////////////////////////////////////////////////////////////////////
261
262 /*
263 * @implemented
264 */
265 DWORD
266 STDCALL
267 GetNumberOfInterfaces(OUT PDWORD pdwNumIf)
268 {
269 DWORD result = NO_ERROR;
270 HKEY hKey;
271 LONG errCode;
272 int i = 0;
273
274 if (pdwNumIf == NULL) return ERROR_INVALID_PARAMETER;
275 *pdwNumIf = 0;
276 errCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Linkage", 0, KEY_READ, &hKey);
277 if (errCode == ERROR_SUCCESS) {
278 DWORD dwSize;
279 errCode = RegQueryValueExW(hKey, L"Bind", NULL, NULL, NULL, &dwSize);
280 if (errCode == ERROR_SUCCESS) {
281 wchar_t* pData = (wchar_t*)malloc(dwSize * sizeof(wchar_t));
282 errCode = RegQueryValueExW(hKey, L"Bind", NULL, NULL, (LPBYTE)pData, &dwSize);
283 if (errCode == ERROR_SUCCESS) {
284 wchar_t* pStr = pData;
285 for (i = 0; *pStr != L'\0'; i++) {
286 pStr = pStr + wcslen(pStr) + 1; // next string
287 }
288 }
289 free(pData);
290 }
291 RegCloseKey(hKey);
292 *pdwNumIf = i;
293 } else {
294 result = errCode;
295 }
296 return result;
297 }
298
299
300 /*
301 * @implemented
302 */
303 DWORD
304 STDCALL
305 GetInterfaceInfo(PIP_INTERFACE_INFO pIfTable, PULONG pOutBufLen)
306 {
307 DWORD result = ERROR_SUCCESS;
308 DWORD dwSize;
309 DWORD dwOutBufLen;
310 DWORD dwNumIf;
311 HKEY hKey;
312 LONG errCode;
313 int i = 0;
314
315 if ((errCode = GetNumberOfInterfaces(&dwNumIf)) != NO_ERROR) {
316 _tprintf(_T("GetInterfaceInfo() failed with code 0x%08X - Use FormatMessage to obtain the message string for the returned error\n"), (int)errCode);
317 return errCode;
318 }
319 if (dwNumIf == 0) return ERROR_NO_DATA; // No adapter information exists for the local computer
320 if (pOutBufLen == NULL) return ERROR_INVALID_PARAMETER;
321 dwOutBufLen = sizeof(IP_INTERFACE_INFO) + dwNumIf * sizeof(IP_ADAPTER_INDEX_MAP);
322 if (*pOutBufLen < dwOutBufLen || pIfTable == NULL) {
323 *pOutBufLen = dwOutBufLen;
324 return ERROR_INSUFFICIENT_BUFFER;
325 }
326 memset(pIfTable, 0, dwOutBufLen);
327 pIfTable->NumAdapters = dwNumIf - 1;
328 errCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Linkage", 0, KEY_READ, &hKey);
329 if (errCode == ERROR_SUCCESS) {
330 errCode = RegQueryValueExW(hKey, L"Bind", NULL, NULL, NULL, &dwSize);
331 if (errCode == ERROR_SUCCESS) {
332 wchar_t* pData = (wchar_t*)malloc(dwSize * sizeof(wchar_t));
333 errCode = RegQueryValueExW(hKey, L"Bind", NULL, NULL, (LPBYTE)pData, &dwSize);
334 if (errCode == ERROR_SUCCESS) {
335 wchar_t* pStr = pData;
336 for (i = 0; i < pIfTable->NumAdapters && *pStr != L'\0'; pStr += wcslen(pStr) + 1) {
337 if (wcsstr(pStr, L"\\Device\\NdisWanIp") == 0) {
338 wcsncpy(pIfTable->Adapter[i].Name, pStr, MAX_ADAPTER_NAME);
339 pIfTable->Adapter[i].Index = i;
340 i++;
341 }
342 }
343
344 }
345 free(pData);
346 }
347 RegCloseKey(hKey);
348 } else {
349 result = errCode;
350 }
351 return result;
352 }
353
354 /*
355 * EnumNameServers
356 */
357
358 static void EnumNameServers( HANDLE RegHandle, PWCHAR Interface,
359 PVOID Data, EnumNameServersFunc cb ) {
360 PWCHAR NameServerString = QueryRegistryValueString(RegHandle, L"NameServer");
361 /* Now, count the non-empty comma separated */
362 if (NameServerString) {
363 DWORD ch;
364 DWORD LastNameStart = 0;
365 for (ch = 0; NameServerString[ch]; ch++) {
366 if (NameServerString[ch] == ',') {
367 if (ch - LastNameStart > 0) { /* Skip empty entries */
368 PWCHAR NameServer = malloc(sizeof(WCHAR) * (ch - LastNameStart + 1));
369 if (NameServer) {
370 memcpy(NameServer,NameServerString + LastNameStart,
371 (ch - LastNameStart) * sizeof(WCHAR));
372 NameServer[ch - LastNameStart] = 0;
373 cb( Interface, NameServer, Data );
374 free(NameServer);
375 }
376 }
377 LastNameStart = ch + 1; /* The first one after the comma */
378 }
379 }
380 if (ch - LastNameStart > 0) { /* A last name? */
381 PWCHAR NameServer = malloc(sizeof(WCHAR) * (ch - LastNameStart + 1));
382 memcpy(NameServer,NameServerString + LastNameStart,
383 (ch - LastNameStart) * sizeof(WCHAR));
384 NameServer[ch - LastNameStart] = 0;
385 cb( Interface, NameServer, Data );
386 free(NameServer);
387 }
388 ConsumeRegValueString(NameServerString);
389 }
390 }
391
392 /*
393 * EnumInterfaces
394 *
395 * Call the enumeration function for each name server.
396 */
397
398 static void EnumInterfaces( PVOID Data, EnumInterfacesFunc cb ) {
399 HKEY RegHandle;
400 HKEY ChildKeyHandle = 0;
401 PWCHAR RegKeyToEnumerate =
402 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
403 PWCHAR ChildKeyName = 0;
404 DWORD CurrentInterface;
405
406 if (OpenChildKeyRead(HKEY_LOCAL_MACHINE,RegKeyToEnumerate,&RegHandle)) {
407 return;
408 }
409
410 for (CurrentInterface = 0; TRUE; CurrentInterface++) {
411 ChildKeyName = GetNthChildKeyName( RegHandle, CurrentInterface );
412 if (!ChildKeyName) break;
413 if (OpenChildKeyRead(RegHandle,ChildKeyName,
414 &ChildKeyHandle) == 0) {
415 cb( ChildKeyHandle, ChildKeyName, Data );
416 RegCloseKey( ChildKeyHandle );
417 }
418 ConsumeChildKeyName( ChildKeyName );
419 }
420 }
421
422 static void CreateNameServerListEnumNamesFuncCount( PWCHAR Interface,
423 PWCHAR Server,
424 PVOID _Data ) {
425 PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)_Data;
426 Data->NumServers++;
427 }
428
429 static void CreateNameServerListEnumIfFuncCount( HANDLE RegHandle,
430 PWCHAR InterfaceName,
431 PVOID _Data ) {
432 PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)_Data;
433 EnumNameServers(RegHandle,InterfaceName,Data,
434 CreateNameServerListEnumNamesFuncCount);
435 }
436
437 static void CreateNameServerListEnumNamesFunc( PWCHAR Interface,
438 PWCHAR Server,
439 PVOID _Data ) {
440 PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)_Data;
441 wcstombs(Data->AddrString[Data->CurrentName].IpAddress.String,
442 Server,
443 sizeof(IP_ADDRESS_STRING));
444 strcpy(Data->AddrString[Data->CurrentName].IpMask.String,"0.0.0.0");
445 Data->AddrString[Data->CurrentName].Context = 0;
446 if (Data->CurrentName < Data->NumServers - 1) {
447 Data->AddrString[Data->CurrentName].Next =
448 &Data->AddrString[Data->CurrentName+1];
449 } else
450 Data->AddrString[Data->CurrentName].Next = 0;
451
452 Data->CurrentName++;
453 }
454
455 static void CreateNameServerListEnumIfFunc( HANDLE RegHandle,
456 PWCHAR InterfaceName,
457 PVOID _Data ) {
458 PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)_Data;
459 EnumNameServers(RegHandle,InterfaceName,Data,
460 CreateNameServerListEnumNamesFunc);
461 }
462
463 static int CountNameServers( PNAME_SERVER_LIST_PRIVATE PrivateData ) {
464 EnumInterfaces(PrivateData,CreateNameServerListEnumIfFuncCount);
465 return PrivateData->NumServers;
466 }
467
468 static void MakeNameServerList( PNAME_SERVER_LIST_PRIVATE PrivateData ) {
469 EnumInterfaces(PrivateData,CreateNameServerListEnumIfFunc);
470 }
471
472 /*
473 * @implemented
474 */
475 DWORD
476 STDCALL
477 GetNetworkParams(PFIXED_INFO pFixedInfo, PULONG pOutBufLen)
478 {
479 DWORD result = ERROR_SUCCESS;
480 DWORD dwSize;
481 HKEY hKey;
482 LONG errCode;
483 NAME_SERVER_LIST_PRIVATE PrivateNSEnum = { 0 };
484
485 CountNameServers( &PrivateNSEnum );
486
487 if (pOutBufLen == NULL) return ERROR_INVALID_PARAMETER;
488
489 if (*pOutBufLen < sizeof(FIXED_INFO))
490 {
491 *pOutBufLen = sizeof(FIXED_INFO) +
492 ((PrivateNSEnum.NumServers - 1) * sizeof(IP_ADDR_STRING));
493 return ERROR_BUFFER_OVERFLOW;
494 }
495 if (pFixedInfo == NULL) return ERROR_INVALID_PARAMETER;
496 memset(pFixedInfo, 0, sizeof(FIXED_INFO));
497
498 errCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
499 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0, KEY_READ, &hKey);
500 if (errCode == ERROR_SUCCESS)
501 {
502 dwSize = sizeof(pFixedInfo->HostName);
503 errCode = RegQueryValueExA(hKey, "Hostname", NULL, NULL, (LPBYTE)&pFixedInfo->HostName, &dwSize);
504 dwSize = sizeof(pFixedInfo->DomainName);
505 errCode = RegQueryValueExA(hKey, "Domain", NULL, NULL, (LPBYTE)&pFixedInfo->DomainName, &dwSize);
506 if (errCode != ERROR_SUCCESS)
507 {
508 dwSize = sizeof(pFixedInfo->DomainName);
509 errCode = RegQueryValueExA(hKey, "DhcpDomain", NULL, NULL, (LPBYTE)&pFixedInfo->DomainName, &dwSize);
510 }
511 dwSize = sizeof(pFixedInfo->EnableRouting);
512 errCode = RegQueryValueExW(hKey, L"IPEnableRouter", NULL, NULL, (LPBYTE)&pFixedInfo->EnableRouting, &dwSize);
513 RegCloseKey(hKey);
514
515 /* Get the number of name servers */
516 PIP_ADDR_STRING AddressAfterFixedInfo;
517 AddressAfterFixedInfo = (PIP_ADDR_STRING)&pFixedInfo[1];
518 DWORD NumberOfServersAllowed = 0, CurrentServer = 0;
519
520 while( &AddressAfterFixedInfo[NumberOfServersAllowed] <
521 (PIP_ADDR_STRING)(((PCHAR)pFixedInfo) + *pOutBufLen) )
522 NumberOfServersAllowed++;
523
524 NumberOfServersAllowed++; /* One struct is built in */
525
526 /* Since the first part of the struct is built in, we have to do some
527 fiddling */
528 PrivateNSEnum.AddrString =
529 malloc(NumberOfServersAllowed * sizeof(IP_ADDR_STRING));
530 if (PrivateNSEnum.NumServers > NumberOfServersAllowed)
531 PrivateNSEnum.NumServers = NumberOfServersAllowed;
532 MakeNameServerList( &PrivateNSEnum );
533
534 /* Now we have the name servers, place the first one in the struct,
535 and follow it with the rest */
536 if (!PrivateNSEnum.NumServers)
537 RtlZeroMemory( &pFixedInfo->DnsServerList,
538 sizeof(pFixedInfo->DnsServerList) );
539 else
540 memcpy( &pFixedInfo->DnsServerList, &PrivateNSEnum.AddrString[0],
541 sizeof(PrivateNSEnum.AddrString[0]) );
542
543 if (PrivateNSEnum.NumServers > 1) {
544 pFixedInfo->CurrentDnsServer = &pFixedInfo->DnsServerList;
545 memcpy( &AddressAfterFixedInfo[0],
546 &PrivateNSEnum.AddrString[1],
547 sizeof(IP_ADDR_STRING) * (PrivateNSEnum.NumServers - 1) );
548 } else if (PrivateNSEnum.NumServers == 0) {
549 pFixedInfo->CurrentDnsServer = &pFixedInfo->DnsServerList;
550 } else {
551 pFixedInfo->CurrentDnsServer = 0;
552 }
553
554 for( CurrentServer = 0;
555 PrivateNSEnum.NumServers &&
556 CurrentServer < PrivateNSEnum.NumServers - 1;
557 CurrentServer++ ) {
558 pFixedInfo->CurrentDnsServer->Next = &AddressAfterFixedInfo[CurrentServer];
559 pFixedInfo->CurrentDnsServer = &AddressAfterFixedInfo[CurrentServer];
560 pFixedInfo->CurrentDnsServer->Next = 0;
561 }
562
563 /* For now, set the first server as the current server, if there are any */
564 if( PrivateNSEnum.NumServers ) {
565 pFixedInfo->CurrentDnsServer = &pFixedInfo->DnsServerList;
566 }
567
568 free(PrivateNSEnum.AddrString);
569 }
570 else
571 {
572 WSH_DbgPrint( MIN_TRACE,
573 ("Open Tcpip parameters key: error %08x\n", errCode ));
574 result = ERROR_NO_DATA; // No adapter information exists for the local computer
575 }
576
577 errCode = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters", 0, KEY_READ, &hKey);
578 if (errCode == ERROR_SUCCESS)
579 {
580 dwSize = sizeof(pFixedInfo->ScopeId);
581 errCode = RegQueryValueExA(hKey, "ScopeId", NULL, NULL, (LPBYTE)&pFixedInfo->ScopeId, &dwSize);
582 if (errCode != ERROR_SUCCESS)
583 {
584 dwSize = sizeof(pFixedInfo->ScopeId);
585 errCode = RegQueryValueExA(hKey, "DhcpScopeId", NULL, NULL, (LPBYTE)&pFixedInfo->ScopeId, &dwSize);
586 }
587 dwSize = sizeof(pFixedInfo->NodeType);
588 errCode = RegQueryValueExW(hKey, L"NodeType", NULL, NULL, (LPBYTE)&pFixedInfo->NodeType, &dwSize);
589 if (errCode != ERROR_SUCCESS)
590 {
591 dwSize = sizeof(pFixedInfo->NodeType);
592 errCode = RegQueryValueExA(hKey, "DhcpNodeType", NULL, NULL, (LPBYTE)&pFixedInfo->NodeType, &dwSize);
593 }
594 dwSize = sizeof(pFixedInfo->EnableProxy);
595 errCode = RegQueryValueExW(hKey, L"EnableProxy", NULL, NULL, (LPBYTE)&pFixedInfo->EnableProxy, &dwSize);
596 dwSize = sizeof(pFixedInfo->EnableDns);
597 errCode = RegQueryValueExW(hKey, L"EnableDNS", NULL, NULL, (LPBYTE)&pFixedInfo->EnableDns, &dwSize);
598 RegCloseKey(hKey);
599 }
600 else
601 {
602 WSH_DbgPrint(MIN_TRACE,
603 ("iphlpapi: Ignoring lack of netbios data for now.\n"));
604 #if 0
605 result = ERROR_NO_DATA; // No adapter information exists for the local computer
606 #endif
607 }
608
609 return result;
610 }
611
612
613 /*
614 * @unimplemented
615 */
616 DWORD
617 STDCALL
618 GetTcpStatistics(PMIB_TCPSTATS pStats)
619 {
620 DWORD result = NO_ERROR;
621
622 result = ERROR_NO_DATA;
623
624 return result;
625 }
626
627
628 /*
629 * @unimplemented
630 */
631 DWORD
632 STDCALL
633 GetTcpTable(PMIB_TCPTABLE pTcpTable, PDWORD pdwSize, BOOL bOrder)
634 {
635 DWORD result = NO_ERROR;
636
637 result = ERROR_NO_DATA;
638
639 return result;
640 }
641
642
643 /*
644 * @unimplemented
645 */
646 DWORD
647 STDCALL
648 GetUdpStatistics(PMIB_UDPSTATS pStats)
649 {
650 DWORD result = NO_ERROR;
651
652 result = ERROR_NO_DATA;
653
654 return result;
655 }
656
657
658 /*
659 * @unimplemented
660 */
661 DWORD
662 STDCALL
663 GetUdpTable(PMIB_UDPTABLE pUdpTable, PDWORD pdwSize, BOOL bOrder)
664 {
665 DWORD result = NO_ERROR;
666
667 result = ERROR_NO_DATA;
668
669 return result;
670 }
671
672
673 /*
674 * @unimplemented
675 */
676 DWORD
677 STDCALL
678 FlushIpNetTable(DWORD dwIfIndex)
679 {
680 DWORD result = NO_ERROR;
681
682 return result;
683 }
684
685 /******************************************************************
686 * GetIfEntry (IPHLPAPI.@)
687 *
688 *
689 * PARAMS
690 *
691 * pIfRow [In/Out]
692 *
693 * RETURNS
694 *
695 * DWORD
696 *
697 */
698 DWORD
699 STDCALL
700 GetIfEntry(PMIB_IFROW pIfRow)
701 {
702 DWORD result = NO_ERROR;
703
704 return result;
705 }
706
707
708 /******************************************************************
709 * GetIfTable (IPHLPAPI.@)
710 *
711 *
712 * PARAMS
713 *
714 * pIfTable [In/Out]
715 * pdwSize [In/Out]
716 * bOrder [In]
717 *
718 * RETURNS
719 *
720 * DWORD
721 *
722 */
723 DWORD
724 STDCALL
725 GetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder)
726 {
727 DWORD result = NO_ERROR;
728
729 return result;
730 }
731
732 /*
733 * @unimplemented
734 */
735 DWORD STDCALL GetIpAddrTable(PMIB_IPADDRTABLE pIpAddrTable, PULONG pdwSize,
736 BOOL bOrder)
737 {
738 UNIMPLEMENTED
739 return 0L;
740 }
741
742 /*
743 * @unimplemented
744 */
745 DWORD STDCALL GetIpNetTable(PMIB_IPNETTABLE pIpNetTable, PULONG pdwSize,
746 BOOL bOrder)
747 {
748 UNIMPLEMENTED
749 return 0L;
750 }
751
752 /*
753 * @unimplemented
754 */
755 DWORD STDCALL GetIpForwardTable(PMIB_IPFORWARDTABLE pIpForwardTable,
756 PULONG pdwSize, BOOL bOrder)
757 {
758 UNIMPLEMENTED
759 return 0L;
760 }
761
762 /*
763 * @unimplemented
764 */
765 DWORD STDCALL GetIpStatistics(PMIB_IPSTATS pStats)
766 {
767 UNIMPLEMENTED
768 return 0L;
769 }
770
771 /*
772 * @unimplemented
773 */
774 DWORD STDCALL GetIpStatisticsEx(PMIB_IPSTATS pStats, DWORD dwFamily)
775 {
776 UNIMPLEMENTED
777 return 0L;
778 }
779
780 /*
781 * @unimplemented
782 */
783 DWORD STDCALL GetIcmpStatistics(PMIB_ICMP pStats)
784 {
785 UNIMPLEMENTED
786 return 0L;
787 }
788
789 /*
790 * @unimplemented
791 */
792 DWORD STDCALL GetTcpStatisticsEx(PMIB_TCPSTATS pStats, DWORD dwFamily)
793 {
794 UNIMPLEMENTED
795 return 0L;
796 }
797
798 /*
799 * @unimplemented
800 */
801 DWORD STDCALL GetUdpStatisticsEx(PMIB_UDPSTATS pStats, DWORD dwFamily)
802 {
803 UNIMPLEMENTED
804 return 0L;
805 }
806
807 /*
808 * @unimplemented
809 */
810 DWORD STDCALL SetIfEntry(PMIB_IFROW pIfRow)
811 {
812 UNIMPLEMENTED
813 return 0L;
814 }
815
816 /*
817 * @unimplemented
818 */
819 DWORD STDCALL SetIpForwardEntry(PMIB_IPFORWARDROW pRoute)
820 {
821 UNIMPLEMENTED
822 return 0L;
823 }
824
825 /*
826 * @unimplemented
827 */
828 DWORD STDCALL DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute)
829 {
830 UNIMPLEMENTED
831 return 0L;
832 }
833
834 /*
835 * @unimplemented
836 */
837 DWORD STDCALL SetIpStatistics(PMIB_IPSTATS pIpStats)
838 {
839 UNIMPLEMENTED
840 return 0L;
841 }
842
843 /*
844 * @unimplemented
845 */
846 DWORD STDCALL SetIpTTL(UINT nTTL)
847 {
848 UNIMPLEMENTED
849 return 0L;
850 }
851
852 /*
853 * @unimplemented
854 */
855 DWORD STDCALL CreateIpNetEntry(PMIB_IPNETROW pArpEntry)
856 {
857 UNIMPLEMENTED
858 return 0L;
859 }
860
861 /*
862 * @unimplemented
863 */
864 DWORD STDCALL DeleteIpNetEntry(PMIB_IPNETROW pArpEntry)
865 {
866 UNIMPLEMENTED
867 return 0L;
868 }
869
870 /*
871 * @unimplemented
872 */
873 DWORD STDCALL CreateProxyArpEntry(DWORD dwAddress, DWORD dwMask,
874 DWORD dwIfIndex)
875 {
876 UNIMPLEMENTED
877 return 0L;
878 }
879
880 /*
881 * @unimplemented
882 */
883 DWORD STDCALL DeleteProxyArpEntry(DWORD dwAddress, DWORD dwMask,
884 DWORD dwIfIndex)
885 {
886 UNIMPLEMENTED
887 return 0L;
888 }
889
890 /*
891 * @unimplemented
892 */
893 DWORD STDCALL SetTcpEntry(PMIB_TCPROW pTcpRow)
894 {
895 UNIMPLEMENTED
896 return 0L;
897 }
898
899 /*
900 * @unimplemented
901 */
902 DWORD STDCALL GetUniDirectionalAdapterInfo(
903 PIP_UNIDIRECTIONAL_ADAPTER_ADDRESS pIPIfInfo, PULONG dwOutBufLen)
904 {
905 UNIMPLEMENTED
906 return 0L;
907 }
908
909 /*
910 * @unimplemented
911 */
912 DWORD STDCALL GetBestInterface(IPAddr dwDestAddr, PDWORD pdwBestIfIndex)
913 {
914 UNIMPLEMENTED
915 return 0L;
916 }
917
918 /*
919 * @unimplemented
920 */
921 DWORD STDCALL GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr,
922 PMIB_IPFORWARDROW pBestRoute)
923 {
924 UNIMPLEMENTED
925 return 0L;
926 }
927
928 /*
929 * @unimplemented
930 */
931 DWORD STDCALL NotifyAddrChange(PHANDLE Handle, LPOVERLAPPED overlapped)
932 {
933 UNIMPLEMENTED
934 return 0L;
935 }
936
937 /*
938 * @unimplemented
939 */
940 DWORD STDCALL NotifyRouteChange(PHANDLE Handle, LPOVERLAPPED overlapped)
941 {
942 UNIMPLEMENTED
943 return 0L;
944 }
945
946 /*
947 * @unimplemented
948 */
949 DWORD STDCALL DeleteIPAddress(ULONG NTEContext)
950 {
951 UNIMPLEMENTED
952 return 0L;
953 }
954
955 /*
956 * @unimplemented
957 */
958 DWORD STDCALL GetPerAdapterInfo(ULONG IfIndex,
959 PIP_PER_ADAPTER_INFO pPerAdapterInfo, PULONG pOutBufLen)
960 {
961 UNIMPLEMENTED
962 return 0L;
963 }
964
965 /*
966 * @unimplemented
967 */
968 DWORD STDCALL IpReleaseAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
969 {
970 UNIMPLEMENTED
971 return 0L;
972 }
973
974 /*
975 * @unimplemented
976 */
977 DWORD STDCALL IpRenewAddress(PIP_ADAPTER_INDEX_MAP AdapterInfo)
978 {
979 UNIMPLEMENTED
980 return 0L;
981 }
982
983 /*
984 * @unimplemented
985 */
986 DWORD STDCALL SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr,
987 PULONG PhyAddrLen)
988 {
989 UNIMPLEMENTED
990 return 0L;
991 }
992
993 /*
994 * @unimplemented
995 */
996 BOOL STDCALL GetRTTAndHopCount(IPAddr DestIpAddress, PULONG HopCount,
997 ULONG MaxHops, PULONG RTT)
998 {
999 UNIMPLEMENTED
1000 return 0L;
1001 }
1002
1003 /*
1004 * @unimplemented
1005 */
1006 DWORD STDCALL GetFriendlyIfIndex(DWORD IfIndex)
1007 {
1008 UNIMPLEMENTED
1009 return 0L;
1010 }
1011
1012 /*
1013 * @unimplemented
1014 */
1015 DWORD STDCALL EnableRouter(HANDLE* pHandle, OVERLAPPED* pOverlapped)
1016 {
1017 UNIMPLEMENTED
1018 return 0L;
1019 }
1020
1021 /*
1022 * @unimplemented
1023 */
1024 DWORD STDCALL UnenableRouter(OVERLAPPED* pOverlapped, LPDWORD lpdwEnableCount)
1025 {
1026 UNIMPLEMENTED
1027 return 0L;
1028 }
1029
1030 /*
1031 * @unimplemented
1032 */
1033 DWORD STDCALL GetIcmpStatisticsEx(PMIB_ICMP_EX pStats,DWORD dwFamily)
1034 {
1035 UNIMPLEMENTED
1036 return 0L;
1037 }
1038
1039 /*
1040 * @unimplemented
1041 */
1042 DWORD STDCALL NhpAllocateAndGetInterfaceInfoFromStack(IP_INTERFACE_NAME_INFO **ppTable,PDWORD pdwCount,BOOL bOrder,HANDLE hHeap,DWORD dwFlags)
1043 {
1044 UNIMPLEMENTED
1045 return 0L;
1046 }
1047
1048 /*
1049 * @unimplemented
1050 */
1051 DWORD STDCALL GetBestInterfaceEx(struct sockaddr *pDestAddr,PDWORD pdwBestIfIndex)
1052 {
1053 UNIMPLEMENTED
1054 return 0L;
1055 }
1056
1057 /*
1058 * @unimplemented
1059 */
1060 BOOL STDCALL CancelIPChangeNotify(LPOVERLAPPED notifyOverlapped)
1061 {
1062 UNIMPLEMENTED
1063 return 0L;
1064 }
1065
1066 /*
1067 * @unimplemented
1068 */
1069 PIP_ADAPTER_ORDER_MAP STDCALL GetAdapterOrderMap(VOID)
1070 {
1071 UNIMPLEMENTED
1072 return 0L;
1073 }
1074
1075 /*
1076 * @unimplemented
1077 */
1078 DWORD STDCALL GetAdaptersAddresses(ULONG Family,DWORD Flags,PVOID Reserved,PIP_ADAPTER_ADDRESSES pAdapterAddresses,PULONG pOutBufLen)
1079 {
1080 UNIMPLEMENTED
1081 return 0L;
1082 }
1083
1084 /*
1085 * @unimplemented
1086 */
1087 DWORD STDCALL DisableMediaSense(HANDLE *pHandle,OVERLAPPED *pOverLapped)
1088 {
1089 UNIMPLEMENTED
1090 return 0L;
1091 }
1092
1093 /*
1094 * @unimplemented
1095 */
1096 DWORD STDCALL RestoreMediaSense(OVERLAPPED* pOverlapped,LPDWORD lpdwEnableCount)
1097 {
1098 UNIMPLEMENTED
1099 return 0L;
1100 }
1101
1102 /*
1103 * @unimplemented
1104 */
1105 DWORD STDCALL GetIpErrorString(IP_STATUS ErrorCode,PWCHAR Buffer,PDWORD Size)
1106 {
1107 UNIMPLEMENTED
1108 return 0L;
1109 }
1110
1111 /*
1112 * @unimplemented
1113 */
1114 HANDLE STDCALL IcmpCreateFile(
1115 VOID
1116 )
1117 {
1118 UNIMPLEMENTED
1119 return 0L;
1120 }
1121
1122 /*
1123 * @unimplemented
1124 */
1125 HANDLE STDCALL Icmp6CreateFile(
1126 VOID
1127 )
1128 {
1129 UNIMPLEMENTED
1130 return 0L;
1131 }
1132
1133 /*
1134 * @unimplemented
1135 */
1136 BOOL STDCALL IcmpCloseHandle(
1137 HANDLE IcmpHandle
1138 )
1139 {
1140 UNIMPLEMENTED
1141 return 0L;
1142 }
1143
1144 /*
1145 * @unimplemented
1146 */
1147 DWORD STDCALL IcmpSendEcho(
1148 HANDLE IcmpHandle,
1149 IPAddr DestinationAddress,
1150 LPVOID RequestData,
1151 WORD RequestSize,
1152 PIP_OPTION_INFORMATION RequestOptions,
1153 LPVOID ReplyBuffer,
1154 DWORD ReplySize,
1155 DWORD Timeout
1156 )
1157 {
1158 UNIMPLEMENTED
1159 return 0L;
1160 }
1161
1162 /*
1163 * @unimplemented
1164 */
1165 DWORD
1166 STDCALL
1167 IcmpSendEcho2(
1168 HANDLE IcmpHandle,
1169 HANDLE Event,
1170 FARPROC ApcRoutine,
1171 PVOID ApcContext,
1172 IPAddr DestinationAddress,
1173 LPVOID RequestData,
1174 WORD RequestSize,
1175 PIP_OPTION_INFORMATION RequestOptions,
1176 LPVOID ReplyBuffer,
1177 DWORD ReplySize,
1178 DWORD Timeout
1179 )
1180 {
1181 UNIMPLEMENTED
1182 return 0L;
1183 }
1184
1185 /*
1186 * @unimplemented
1187 */
1188 DWORD
1189 STDCALL
1190 Icmp6SendEcho2(
1191 HANDLE IcmpHandle,
1192 HANDLE Event,
1193 FARPROC ApcRoutine,
1194 PVOID ApcContext,
1195 struct sockaddr_in6 *SourceAddress,
1196 struct sockaddr_in6 *DestinationAddress,
1197 LPVOID RequestData,
1198 WORD RequestSize,
1199 PIP_OPTION_INFORMATION RequestOptions,
1200 LPVOID ReplyBuffer,
1201 DWORD ReplySize,
1202 DWORD Timeout
1203 )
1204 {
1205 UNIMPLEMENTED
1206 return 0L;
1207 }
1208
1209 /*
1210 * @unimplemented
1211 */
1212 DWORD
1213 STDCALL
1214 IcmpParseReplies(
1215 LPVOID ReplyBuffer,
1216 DWORD ReplySize
1217 )
1218 {
1219 UNIMPLEMENTED
1220 return 0L;
1221 }
1222
1223 /*
1224 * @unimplemented
1225 */
1226 DWORD
1227 STDCALL
1228 Icmp6ParseReplies(
1229 LPVOID ReplyBuffer,
1230 DWORD ReplySize
1231 )
1232 {
1233 UNIMPLEMENTED
1234 return 0L;
1235 }
1236
1237 /*
1238 * @unimplemented
1239 */
1240 DWORD STDCALL AllocateAndGetIfTableFromStack(PMIB_IFTABLE *ppIfTable,
1241 BOOL bOrder, HANDLE heap, DWORD flags)
1242 {
1243 UNIMPLEMENTED
1244 return 0L;
1245 }
1246
1247 /*
1248 * @unimplemented
1249 */
1250 DWORD STDCALL AllocateAndGetIpAddrTableFromStack(PMIB_IPADDRTABLE *ppIpAddrTable,
1251 BOOL bOrder, HANDLE heap, DWORD flags)
1252 {
1253 UNIMPLEMENTED
1254 return 0L;
1255 }
1256
1257 /*
1258 * @unimplemented
1259 */
1260 DWORD STDCALL AllocateAndGetIpForwardTableFromStack(PMIB_IPFORWARDTABLE *
1261 ppIpForwardTable, BOOL bOrder, HANDLE heap, DWORD flags)
1262 {
1263 UNIMPLEMENTED
1264 return 0L;
1265 }
1266
1267 /*
1268 * @unimplemented
1269 */
1270 DWORD STDCALL AllocateAndGetIpNetTableFromStack(PMIB_IPNETTABLE *ppIpNetTable,
1271 BOOL bOrder, HANDLE heap, DWORD flags)
1272 {
1273 UNIMPLEMENTED
1274 return 0L;
1275 }
1276
1277 /*
1278 * @unimplemented
1279 */
1280 DWORD STDCALL AllocateAndGetTcpTableFromStack(PMIB_TCPTABLE *ppTcpTable,
1281 BOOL bOrder, HANDLE heap, DWORD flags)
1282 {
1283 UNIMPLEMENTED
1284 return 0L;
1285 }
1286
1287 /*
1288 * @unimplemented
1289 */
1290 DWORD STDCALL AllocateAndGetUdpTableFromStack(PMIB_UDPTABLE *ppUdpTable,
1291 BOOL bOrder, HANDLE heap, DWORD flags)
1292 {
1293 UNIMPLEMENTED
1294 return 0L;
1295 }