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"
27 WINE_DEFAULT_DEBUG_CHANNEL(iphlpapi
);
29 typedef struct _NAME_SERVER_LIST_PRIVATE
{
31 IP_ADDR_STRING
* pCurrent
;
32 } NAME_SERVER_LIST_PRIVATE
, *PNAME_SERVER_LIST_PRIVATE
;
34 typedef VOID (*ENUM_INTERFACE_CALLBACK
)(
37 PVOID CallbackContext
);
42 IN LPCWSTR NameServerKey
,
43 OUT LPWSTR
* OutNameServer
)
45 DWORD dwLength
, dwType
;
51 Status
= RegQueryValueExW(hInterface
, NameServerKey
, NULL
, &dwType
, NULL
, &dwLength
);
53 if (Status
!= ERROR_SUCCESS
)
55 /* failed to retrieve size */
56 TRACE("Status %x\n", Status
);
60 /* add terminating null */
61 dwLength
+= sizeof(WCHAR
);
63 /* allocate name server */
64 NameServer
= HeapAlloc(GetProcessHeap(), 0, dwLength
);
69 return ERROR_OUTOFMEMORY
;
73 Status
= RegQueryValueExW(hInterface
, NameServerKey
, NULL
, &dwType
, (LPBYTE
)NameServer
, &dwLength
);
75 if (Status
!= ERROR_SUCCESS
|| dwType
!= REG_SZ
)
77 /* failed to retrieve ns */
78 HeapFree(GetProcessHeap(), 0, NameServer
);
82 /* null terminate it */
83 NameServer
[dwLength
/ sizeof(WCHAR
)] = L
'\0';
86 *OutNameServer
= NameServer
;
88 return STATUS_SUCCESS
;
95 IN LPWSTR InterfaceName
,
96 PVOID ServerCallbackContext
,
97 EnumNameServersFunc CallbackRoutine
)
105 /* query static assigned name server */
106 Status
= QueryNameServer(hInterface
, L
"NameServer", &NameServer
);
107 if (Status
!= ERROR_SUCCESS
)
109 /* query dynamic assigned name server */
110 Status
= QueryNameServer(hInterface
, L
"DhcpNameServer", &NameServer
);
112 if (Status
!= ERROR_SUCCESS
)
114 /* failed to retrieve name servers */
119 /* enumerate all name servers, terminated by comma */
124 /* find next terminator */
125 Comma
= wcschr(Start
, L
',');
129 /* calculate length */
130 Length
= Comma
- Start
;
132 /* copy name server */
133 RtlMoveMemory(Buffer
, Start
, Length
* sizeof(WCHAR
));
135 /* null terminate it */
136 Buffer
[Length
] = L
'\0';
138 /* perform callback */
139 CallbackRoutine(InterfaceName
, Buffer
, ServerCallbackContext
);
144 /* perform callback */
145 CallbackRoutine(InterfaceName
, Start
, ServerCallbackContext
);
151 /* increment offset */
156 /* free name server string */
157 HeapFree(GetProcessHeap(), 0, NameServer
);
160 return ERROR_SUCCESS
;
165 ENUM_INTERFACE_CALLBACK CallbackRoutine
,
166 PVOID InterfaceCallbackContext
)
168 HKEY hKey
, hInterface
;
170 DWORD NumInterfaces
, InterfaceNameLen
, Index
, Length
;
171 LPWSTR InterfaceName
;
173 /* first open interface key */
174 Status
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, L
"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces", 0, KEY_READ
, &hKey
);
176 /* check for success */
177 if (Status
!= ERROR_SUCCESS
)
179 /* failed to open interface key */
183 /* now get maximum interface name length and number of interfaces */
184 Status
= RegQueryInfoKeyW(hKey
, NULL
, NULL
, NULL
, &NumInterfaces
, &InterfaceNameLen
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
185 if (Status
!= ERROR_SUCCESS
)
187 /* failed to get key info */
192 /* RegQueryInfoKey does not include terminating null */
195 /* allocate interface name */
196 InterfaceName
= (LPWSTR
) HeapAlloc(GetProcessHeap(), 0, InterfaceNameLen
* sizeof(WCHAR
));
202 return ERROR_OUTOFMEMORY
;
205 /* no enumerate all interfaces */
206 for(Index
= 0; Index
< NumInterfaces
; Index
++)
208 /* query interface name */
209 Length
= InterfaceNameLen
;
210 Status
= RegEnumKeyExW(hKey
, Index
, InterfaceName
, &Length
, NULL
, NULL
, NULL
, NULL
);
212 if (Status
== ERROR_SUCCESS
)
214 /* make sure it is null terminated */
215 InterfaceName
[Length
] = L
'\0';
217 /* now open child key */
218 Status
= RegOpenKeyExW(hKey
, InterfaceName
, 0, KEY_READ
, &hInterface
);
220 if (Status
== ERROR_SUCCESS
)
222 /* perform enumeration callback */
223 CallbackRoutine(hInterface
, InterfaceName
, InterfaceCallbackContext
);
225 /* close interface key */
226 RegCloseKey(hInterface
);
231 /* free interface name */
232 HeapFree(GetProcessHeap(), 0, InterfaceName
);
234 /* close root interface key */
242 CountNameServerCallback(
243 IN LPWSTR InterfaceName
,
245 IN PVOID CallbackContext
)
248 PNAME_SERVER_LIST_PRIVATE Data
= (PNAME_SERVER_LIST_PRIVATE
)CallbackContext
;
250 /* increment server count */
255 CountServerCallbackTrampoline(
258 PVOID CallbackContext
)
260 EnumNameServers(ChildKeyHandle
, ChildKeyName
, CallbackContext
, CountNameServerCallback
);
265 IN PNAME_SERVER_LIST_PRIVATE PrivateData
)
267 return EnumInterfaces(CountServerCallbackTrampoline
, (PVOID
)PrivateData
);
271 CreateNameServerListCallback(
272 IN LPWSTR InterfaceName
,
274 IN PVOID CallbackContext
)
277 PNAME_SERVER_LIST_PRIVATE Data
= (PNAME_SERVER_LIST_PRIVATE
)CallbackContext
;
279 /* convert to ansi ns string */
280 if (WideCharToMultiByte(CP_ACP
, 0, Server
, -1, Data
->pCurrent
->IpAddress
.String
, 16, NULL
, NULL
))
282 /* store offset to next name server struct */
283 Data
->pCurrent
->Next
= (struct _IP_ADDR_STRING
*)(Data
->pCurrent
+ 1);
285 /* move to next entry */
286 Data
->pCurrent
= Data
->pCurrent
->Next
;
288 /* increment server count */
293 /* failed to convert dns server */
294 Data
->pCurrent
->IpAddress
.String
[0] = '\0';
299 CreateNameServerListCallbackTrampoline(
302 PVOID CallbackContext
)
304 EnumNameServers(ChildKeyHandle
, ChildKeyName
, CallbackContext
, CreateNameServerListCallback
);
309 PNAME_SERVER_LIST_PRIVATE PrivateData
)
311 return EnumInterfaces(CreateNameServerListCallbackTrampoline
, (PVOID
)PrivateData
);
317 NAME_SERVER_LIST_PRIVATE PrivateNSEnum
;
318 PIPHLP_RES_INFO ResInfo
;
319 IP_ADDR_STRING
* DnsList
= NULL
;
322 PrivateNSEnum
.NumServers
= 0;
324 /* count name servers */
325 Status
= CountNameServers(&PrivateNSEnum
);
327 if (Status
!= ERROR_SUCCESS
)
329 /* failed to enumerate name servers */
333 /* are there any servers */
334 if (PrivateNSEnum
.NumServers
)
336 /* allocate dns servers */
337 DnsList
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, PrivateNSEnum
.NumServers
* sizeof(IP_ADDR_STRING
));
346 /* allocate private struct */
347 ResInfo
= (PIPHLP_RES_INFO
)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IPHLP_RES_INFO
));
355 HeapFree( GetProcessHeap(), 0, DnsList
);
360 /* are there any servers */
361 if (PrivateNSEnum
.NumServers
)
363 /* initialize enumeration context */
364 PrivateNSEnum
.NumServers
= 0;
365 PrivateNSEnum
.pCurrent
= DnsList
;
367 /* enumerate servers */
368 MakeNameServerList( &PrivateNSEnum
);
371 ResInfo
->DnsList
= DnsList
;
372 ResInfo
->riCount
= PrivateNSEnum
.NumServers
;
379 VOID
disposeResInfo( PIPHLP_RES_INFO InfoPtr
)
381 HeapFree(GetProcessHeap(), 0, InfoPtr
->DnsList
);
382 RtlFreeHeap( GetProcessHeap(), 0, InfoPtr
);