2 * iphlpapi dll implementation -- Setting and storing route information
4 * These are stubs for functions that set routing information on the target
5 * operating system. They are grouped here because their implementation will
6 * vary widely by operating system.
8 * Copyright (C) 2004 Art Yerkes
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "iphlpapi_private.h"
29 #include <sys/types.h>
30 #ifdef HAVE_NETINET_IN_H
31 # include <netinet/in.h>
33 #ifdef HAVE_ARPA_INET_H
34 # include <arpa/inet.h>
36 #ifdef HAVE_ARPA_NAMESER_H
37 # include <arpa/nameser.h>
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi
);
52 typedef struct _NAME_SERVER_LIST_PRIVATE
{
54 IP_ADDR_STRING
* pCurrent
;
55 } NAME_SERVER_LIST_PRIVATE
, *PNAME_SERVER_LIST_PRIVATE
;
57 typedef VOID (*ENUM_INTERFACE_CALLBACK
)(
60 PVOID CallbackContext
);
65 IN LPCWSTR NameServerKey
,
66 OUT LPWSTR
* OutNameServer
)
68 DWORD dwLength
, dwType
;
74 Status
= RegQueryValueExW(hInterface
, NameServerKey
, NULL
, &dwType
, NULL
, &dwLength
);
76 if (Status
!= ERROR_SUCCESS
)
78 /* failed to retrieve size */
79 TRACE("Status %x\n", Status
);
83 /* add terminating null */
84 dwLength
+= sizeof(WCHAR
);
86 /* allocate name server */
87 NameServer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
92 return ERROR_OUTOFMEMORY
;
96 Status
= RegQueryValueExW(hInterface
, NameServerKey
, NULL
, &dwType
, (LPBYTE
)NameServer
, &dwLength
);
98 if (Status
!= ERROR_SUCCESS
|| dwType
!= REG_SZ
)
100 /* failed to retrieve ns */
101 HeapFree(GetProcessHeap(), 0, NameServer
);
105 /* null terminate it */
106 NameServer
[dwLength
/ sizeof(WCHAR
)] = L
'\0';
109 *OutNameServer
= NameServer
;
111 return STATUS_SUCCESS
;
118 IN LPWSTR InterfaceName
,
119 PVOID ServerCallbackContext
,
120 EnumNameServersFunc CallbackRoutine
)
128 /* query static assigned name server */
129 Status
= QueryNameServer(hInterface
, L
"NameServer", &NameServer
);
130 if (Status
!= ERROR_SUCCESS
)
132 /* query dynamic assigned name server */
133 Status
= QueryNameServer(hInterface
, L
"DhcpNameServer", &NameServer
);
135 if (Status
!= ERROR_SUCCESS
)
137 /* failed to retrieve name servers */
142 /* enumerate all name servers, terminated by comma */
147 /* find next terminator */
148 Comma
= wcschr(Start
, L
',');
152 /* calculate length */
153 Length
= Comma
- Start
;
155 /* copy name server */
156 RtlMoveMemory(Buffer
, Start
, Length
* sizeof(WCHAR
));
158 /* null terminate it */
159 Buffer
[Length
] = L
'\0';
161 /* perform callback */
162 CallbackRoutine(InterfaceName
, Buffer
, ServerCallbackContext
);
167 /* perform callback */
168 CallbackRoutine(InterfaceName
, Start
, ServerCallbackContext
);
174 /* increment offset */
179 /* free name server string */
180 HeapFree(GetProcessHeap(), 0, NameServer
);
183 return ERROR_SUCCESS
;
188 ENUM_INTERFACE_CALLBACK CallbackRoutine
,
189 PVOID InterfaceCallbackContext
)
191 HKEY hKey
, hInterface
;
193 DWORD NumInterfaces
, InterfaceNameLen
, Index
, Length
;
194 LPWSTR InterfaceName
;
196 /* first open interface key */
197 Status
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces", 0, KEY_READ
, &hKey
);
199 /* check for success */
200 if (Status
!= ERROR_SUCCESS
)
202 /* failed to open interface key */
206 /* now get maximum interface name length and number of interfaces */
207 Status
= RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, &NumInterfaces
, &InterfaceNameLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
208 if (Status
!= ERROR_SUCCESS
)
210 /* failed to get key info */
215 /* RegQueryInfoKey does not include terminating null */
218 /* allocate interface name */
219 InterfaceName
= (LPWSTR
) HeapAlloc(GetProcessHeap(), 0, InterfaceNameLen
* sizeof(WCHAR
));
225 return ERROR_OUTOFMEMORY
;
228 /* no enumerate all interfaces */
229 for(Index
= 0; Index
< NumInterfaces
; Index
++)
231 /* query interface name */
232 Length
= InterfaceNameLen
;
233 Status
= RegEnumKeyExW(hKey
, Index
, InterfaceName
, &Length
, NULL
, NULL
, NULL
, NULL
);
235 if (Status
== ERROR_SUCCESS
)
237 /* make sure it is null terminated */
238 InterfaceName
[Length
] = L
'\0';
240 /* now open child key */
241 Status
= RegOpenKeyExW(hKey
, InterfaceName
, 0, KEY_READ
, &hInterface
);
243 if (Status
== ERROR_SUCCESS
)
245 /* perform enumeration callback */
246 CallbackRoutine(hInterface
, InterfaceName
, InterfaceCallbackContext
);
248 /* close interface key */
249 RegCloseKey(hInterface
);
254 /* free interface name */
255 HeapFree(GetProcessHeap(), 0, InterfaceName
);
257 /* close root interface key */
265 CountNameServerCallback(
266 IN LPWSTR InterfaceName
,
268 IN PVOID CallbackContext
)
271 PNAME_SERVER_LIST_PRIVATE Data
= (PNAME_SERVER_LIST_PRIVATE
)CallbackContext
;
273 /* increment server count */
278 CountServerCallbackTrampoline(
281 PVOID CallbackContext
)
283 EnumNameServers(ChildKeyHandle
, ChildKeyName
, CallbackContext
, CountNameServerCallback
);
288 IN PNAME_SERVER_LIST_PRIVATE PrivateData
)
290 return EnumInterfaces(CountServerCallbackTrampoline
, (PVOID
)PrivateData
);
294 CreateNameServerListCallback(
295 IN LPWSTR InterfaceName
,
297 IN PVOID CallbackContext
)
300 PNAME_SERVER_LIST_PRIVATE Data
= (PNAME_SERVER_LIST_PRIVATE
)CallbackContext
;
302 /* convert to ansi ns string */
303 if (WideCharToMultiByte(CP_ACP
, 0, Server
, -1, Data
->pCurrent
->IpAddress
.String
, 16, NULL
, NULL
))
305 /* store offset to next name server struct */
306 Data
->pCurrent
->Next
= (struct _IP_ADDR_STRING
*)(Data
->pCurrent
+ 1);
308 /* move to next entry */
309 Data
->pCurrent
= Data
->pCurrent
->Next
;
311 /* increment server count */
316 /* failed to convert dns server */
317 Data
->pCurrent
->IpAddress
.String
[0] = '\0';
322 CreateNameServerListCallbackTrampoline(
325 PVOID CallbackContext
)
327 EnumNameServers(ChildKeyHandle
, ChildKeyName
, CallbackContext
, CreateNameServerListCallback
);
332 PNAME_SERVER_LIST_PRIVATE PrivateData
)
334 return EnumInterfaces(CreateNameServerListCallbackTrampoline
, (PVOID
)PrivateData
);
340 NAME_SERVER_LIST_PRIVATE PrivateNSEnum
;
341 PIPHLP_RES_INFO ResInfo
;
342 IP_ADDR_STRING
* DnsList
= NULL
;
345 PrivateNSEnum
.NumServers
= 0;
347 /* count name servers */
348 Status
= CountNameServers(&PrivateNSEnum
);
350 if (Status
!= ERROR_SUCCESS
)
352 /* failed to enumerate name servers */
356 /* are there any servers */
357 if (PrivateNSEnum
.NumServers
)
359 /* allocate dns servers */
360 DnsList
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, PrivateNSEnum
.NumServers
* sizeof(IP_ADDR_STRING
));
369 /* allocate private struct */
370 ResInfo
= (PIPHLP_RES_INFO
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IPHLP_RES_INFO
));
378 HeapFree( GetProcessHeap(), 0, DnsList
);
383 /* are there any servers */
384 if (PrivateNSEnum
.NumServers
)
386 /* initialize enumeration context */
387 PrivateNSEnum
.NumServers
= 0;
388 PrivateNSEnum
.pCurrent
= DnsList
;
390 /* enumerate servers */
391 MakeNameServerList( &PrivateNSEnum
);
394 ResInfo
->DnsList
= DnsList
;
395 ResInfo
->riCount
= PrivateNSEnum
.NumServers
;
402 VOID
disposeResInfo( PIPHLP_RES_INFO InfoPtr
)
404 HeapFree(GetProcessHeap(), 0, InfoPtr
->DnsList
);
405 RtlFreeHeap( GetProcessHeap(), 0, InfoPtr
);