Merge from amd64-branch:
[reactos.git] / reactos / dll / win32 / iphlpapi / resinfo_reactos.c
1 /*
2 * iphlpapi dll implementation -- Setting and storing route information
3 *
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.
7 *
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.
13 *
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.
18 *
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
22 */
23
24 #include "config.h"
25 #include "iphlpapi_private.h"
26
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <sys/types.h>
30 #ifdef HAVE_NETINET_IN_H
31 # include <netinet/in.h>
32 #endif
33 #ifdef HAVE_ARPA_INET_H
34 # include <arpa/inet.h>
35 #endif
36 #ifdef HAVE_ARPA_NAMESER_H
37 # include <arpa/nameser.h>
38 #endif
39 #ifdef HAVE_RESOLV_H
40 # include <resolv.h>
41 #endif
42
43 #include "windef.h"
44 #include "winbase.h"
45 #include "winreg.h"
46 #include "resinfo.h"
47 #include "iphlpapi.h"
48 #include "wine/debug.h"
49
50 typedef struct _NAME_SERVER_LIST_PRIVATE {
51 UINT NumServers;
52 IP_ADDR_STRING * pCurrent;
53 } NAME_SERVER_LIST_PRIVATE, *PNAME_SERVER_LIST_PRIVATE;
54
55 NTSYSAPI
56 PVOID
57 NTAPI
58 RtlAllocateHeap (
59 HANDLE Heap,
60 ULONG Flags,
61 SIZE_T Size
62 );
63
64 NTSYSAPI
65 BOOLEAN
66 NTAPI
67 RtlFreeHeap (
68 HANDLE Heap,
69 ULONG Flags,
70 PVOID Address
71 );
72
73 NTSYSAPI
74 NTSTATUS
75 NTAPI
76 RtlUnicodeToMultiByteN (
77 PCHAR MbString,
78 ULONG MbSize,
79 PULONG ResultSize,
80 PWCHAR UnicodeString,
81 ULONG UnicodeSize
82 );
83
84
85 typedef VOID (*EnumInterfacesFunc)( HKEY ChildKeyHandle,
86 PWCHAR ChildKeyName,
87 PVOID Data );
88
89 /*
90 * EnumInterfaces
91 *
92 * Call the enumeration function for each name server.
93 */
94
95 static void EnumInterfaces( PVOID Data, EnumInterfacesFunc cb ) {
96 HKEY RegHandle;
97 HKEY ChildKeyHandle = 0;
98 PWCHAR RegKeyToEnumerate =
99 L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
100 PWCHAR ChildKeyName = 0;
101 DWORD CurrentInterface;
102
103 if (OpenChildKeyRead(HKEY_LOCAL_MACHINE,RegKeyToEnumerate,&RegHandle)) {
104 return;
105 }
106
107 for (CurrentInterface = 0; TRUE; CurrentInterface++) {
108 ChildKeyName = GetNthChildKeyName( RegHandle, CurrentInterface );
109 if (!ChildKeyName) break;
110 if (OpenChildKeyRead(RegHandle,ChildKeyName,
111 &ChildKeyHandle) == 0) {
112 cb( ChildKeyHandle, ChildKeyName, Data );
113 RegCloseKey( ChildKeyHandle );
114 }
115 ConsumeChildKeyName( ChildKeyName );
116 }
117 }
118
119 /*
120 * EnumNameServers
121 */
122
123 void EnumNameServers( HANDLE RegHandle, PWCHAR Interface,
124 PVOID Data, EnumNameServersFunc cb ) {
125 PWCHAR NameServerString =
126 QueryRegistryValueString(RegHandle, L"DhcpNameServer");
127
128 if (!NameServerString)
129 NameServerString = QueryRegistryValueString(RegHandle, L"NameServer");
130
131 if (NameServerString) {
132 /* Now, count the non-empty comma separated */
133 DWORD ch;
134 DWORD LastNameStart = 0;
135 for (ch = 0; NameServerString[ch]; ch++) {
136 if (NameServerString[ch] == ',') {
137 if (ch - LastNameStart > 0) { /* Skip empty entries */
138 PWCHAR NameServer =
139 malloc(((ch - LastNameStart) + 1) * sizeof(WCHAR));
140 if (NameServer) {
141 memcpy(NameServer,NameServerString + LastNameStart,
142 (ch - LastNameStart) * sizeof(WCHAR));
143 NameServer[ch - LastNameStart] = 0;
144 cb( Interface, NameServer, Data );
145 free(NameServer);
146 LastNameStart = ch +1;
147 }
148 }
149 LastNameStart = ch + 1; /* The first one after the comma */
150 }
151 }
152 if (ch - LastNameStart > 0) { /* A last name? */
153 PWCHAR NameServer = malloc(((ch - LastNameStart) + 1) * sizeof(WCHAR));
154 if (NameServer) {
155 memcpy(NameServer,NameServerString + LastNameStart,
156 (ch - LastNameStart) * sizeof(WCHAR));
157 NameServer[ch - LastNameStart] = 0;
158 cb( Interface, NameServer, Data );
159 free(NameServer);
160 }
161 }
162 ConsumeRegValueString(NameServerString);
163 }
164 }
165
166 static void CreateNameServerListEnumNamesFuncCount( PWCHAR Interface,
167 PWCHAR Server,
168 PVOID _Data ) {
169 PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)_Data;
170 Data->NumServers++;
171 }
172
173 static void CreateNameServerListEnumIfFuncCount( HKEY RegHandle,
174 PWCHAR InterfaceName,
175 PVOID _Data ) {
176 PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)_Data;
177 EnumNameServers(RegHandle,InterfaceName,Data,
178 CreateNameServerListEnumNamesFuncCount);
179 }
180
181 VOID CreateNameServerListEnumNamesFunc(
182 PWCHAR Interface,
183 PWCHAR Server,
184 PVOID _Data )
185 {
186 PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)_Data;
187
188 if (WideCharToMultiByte(CP_ACP, 0, Server, -1, Data->pCurrent->IpAddress.String, 16, NULL, NULL))
189 {
190 Data->pCurrent->Next = (struct _IP_ADDR_STRING*)(char*)Data->pCurrent + sizeof(IP_ADDR_STRING);
191 Data->pCurrent = Data->pCurrent->Next;
192 Data->NumServers++;
193 }
194 else
195 {
196 Data->pCurrent->IpAddress.String[0] = '\0';
197 }
198 }
199
200 static void CreateNameServerListEnumIfFunc( HKEY RegHandle,
201 PWCHAR InterfaceName,
202 PVOID _Data ) {
203 PNAME_SERVER_LIST_PRIVATE Data = (PNAME_SERVER_LIST_PRIVATE)_Data;
204 EnumNameServers(RegHandle,InterfaceName,Data,
205 CreateNameServerListEnumNamesFunc);
206 }
207
208 static int CountNameServers( PNAME_SERVER_LIST_PRIVATE PrivateData ) {
209 EnumInterfaces(PrivateData,CreateNameServerListEnumIfFuncCount);
210 return PrivateData->NumServers;
211 }
212
213 static void MakeNameServerList( PNAME_SERVER_LIST_PRIVATE PrivateData ) {
214 EnumInterfaces(PrivateData,CreateNameServerListEnumIfFunc);
215 }
216
217 PIPHLP_RES_INFO getResInfo() {
218 DWORD ServerCount;
219 NAME_SERVER_LIST_PRIVATE PrivateNSEnum;
220 PIPHLP_RES_INFO ResInfo;
221 IP_ADDR_STRING * DnsList;
222
223 PrivateNSEnum.NumServers = 0;
224 ServerCount = CountNameServers( &PrivateNSEnum );
225
226 PrivateNSEnum.NumServers = ServerCount;
227 DnsList = HeapAlloc(GetProcessHeap(), 0, ServerCount * sizeof(IP_ADDR_STRING));
228 if (!DnsList) return NULL;
229
230 ZeroMemory(DnsList, ServerCount * sizeof(IP_ADDR_STRING));
231
232 ResInfo = (PIPHLP_RES_INFO)RtlAllocateHeap ( GetProcessHeap(), 0, sizeof(IPHLP_RES_INFO));
233 if( !ResInfo )
234 {
235 HeapFree( GetProcessHeap(), 0, DnsList );
236 return NULL;
237 }
238
239 PrivateNSEnum.NumServers = 0;
240 PrivateNSEnum.pCurrent = DnsList;
241
242 MakeNameServerList( &PrivateNSEnum );
243 ResInfo->DnsList = DnsList;
244 ResInfo->riCount = PrivateNSEnum.NumServers;
245
246 return ResInfo;
247 }
248
249 VOID disposeResInfo( PIPHLP_RES_INFO InfoPtr )
250 {
251 HeapFree(GetProcessHeap(), 0, InfoPtr->DnsList);
252 RtlFreeHeap( GetProcessHeap(), 0, InfoPtr );
253 }