hidclass.sys: Use IoRegisterDeviceInterface.
[wine.git] / programs / ipconfig / ipconfig.c
blob4370a28a447cb2063f6c985bb5d3cb9974caaa4f
1 /*
2 * IP configuration utility
4 * Copyright 2008 Andrew Riedi
5 * Copyright 2010 Andrew Nguyen
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #define NONAMELESSUNION
24 #include <winsock2.h>
25 #include <windows.h>
26 #include <iphlpapi.h>
27 #include <wine/unicode.h>
29 #include "ipconfig.h"
31 static int ipconfig_vprintfW(const WCHAR *msg, __ms_va_list va_args)
33 int wlen;
34 DWORD count, ret;
35 WCHAR msg_buffer[8192];
37 wlen = FormatMessageW(FORMAT_MESSAGE_FROM_STRING, msg, 0, 0, msg_buffer,
38 ARRAY_SIZE(msg_buffer), &va_args);
40 ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), msg_buffer, wlen, &count, NULL);
41 if (!ret)
43 DWORD len;
44 char *msgA;
46 /* On Windows WriteConsoleW() fails if the output is redirected. So fall
47 * back to WriteFile(), assuming the console encoding is still the right
48 * one in that case.
50 len = WideCharToMultiByte(GetConsoleOutputCP(), 0, msg_buffer, wlen,
51 NULL, 0, NULL, NULL);
52 msgA = HeapAlloc(GetProcessHeap(), 0, len);
53 if (!msgA)
54 return 0;
56 WideCharToMultiByte(GetConsoleOutputCP(), 0, msg_buffer, wlen, msgA, len,
57 NULL, NULL);
58 WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), msgA, len, &count, FALSE);
59 HeapFree(GetProcessHeap(), 0, msgA);
62 return count;
65 static int WINAPIV ipconfig_printfW(const WCHAR *msg, ...)
67 __ms_va_list va_args;
68 int len;
70 __ms_va_start(va_args, msg);
71 len = ipconfig_vprintfW(msg, va_args);
72 __ms_va_end(va_args);
74 return len;
77 static int WINAPIV ipconfig_message_printfW(int msg, ...)
79 __ms_va_list va_args;
80 WCHAR msg_buffer[8192];
81 int len;
83 LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer));
85 __ms_va_start(va_args, msg);
86 len = ipconfig_vprintfW(msg_buffer, va_args);
87 __ms_va_end(va_args);
89 return len;
92 static int ipconfig_message(int msg)
94 static const WCHAR formatW[] = {'%','1',0};
95 WCHAR msg_buffer[8192];
97 LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer));
99 return ipconfig_printfW(formatW, msg_buffer);
102 static const WCHAR *iftype_to_string(DWORD type)
104 static WCHAR msg_buffer[50];
106 int msg;
108 switch (type)
110 case IF_TYPE_ETHERNET_CSMACD:
111 /* The loopback adapter appears as an Ethernet device. */
112 case IF_TYPE_SOFTWARE_LOOPBACK:
113 msg = STRING_ETHERNET;
114 break;
115 default:
116 msg = STRING_UNKNOWN;
119 LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer));
121 return msg_buffer;
124 static void print_field(int msg, const WCHAR *value)
126 static const WCHAR formatW[] = {' ',' ',' ',' ','%','1',':',' ','%','2','\n',0};
128 WCHAR field[] = {'.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',
129 ' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ',0};
130 WCHAR name_buffer[ARRAY_SIZE(field)];
132 LoadStringW(GetModuleHandleW(NULL), msg, name_buffer, ARRAY_SIZE(name_buffer));
133 memcpy(field, name_buffer, sizeof(WCHAR) * min(strlenW(name_buffer), ARRAY_SIZE(field) - 1));
135 ipconfig_printfW(formatW, field, value);
138 static void print_value(const WCHAR *value)
140 static const WCHAR formatW[] = {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
141 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
142 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
143 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
144 '%','1','\n',0};
146 ipconfig_printfW(formatW, value);
149 static BOOL socket_address_to_string(WCHAR *buf, DWORD len, SOCKET_ADDRESS *addr)
151 return WSAAddressToStringW(addr->lpSockaddr,
152 addr->iSockaddrLength, NULL,
153 buf, &len) == 0;
156 static void print_basic_information(void)
158 IP_ADAPTER_ADDRESSES *adapters;
159 ULONG out = 0;
161 if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_GATEWAYS,
162 NULL, NULL, &out) == ERROR_BUFFER_OVERFLOW)
164 adapters = HeapAlloc(GetProcessHeap(), 0, out);
165 if (!adapters)
166 exit(1);
168 if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_GATEWAYS,
169 NULL, adapters, &out) == ERROR_SUCCESS)
171 IP_ADAPTER_ADDRESSES *p;
173 for (p = adapters; p; p = p->Next)
175 static const WCHAR newlineW[] = {'\n',0};
176 static const WCHAR emptyW[] = {0};
178 IP_ADAPTER_UNICAST_ADDRESS *addr;
179 IP_ADAPTER_GATEWAY_ADDRESS_LH *gateway;
180 WCHAR addr_buf[54];
182 ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY, iftype_to_string(p->IfType), p->FriendlyName);
183 ipconfig_printfW(newlineW);
184 print_field(STRING_CONN_DNS_SUFFIX, p->DnsSuffix);
186 for (addr = p->FirstUnicastAddress; addr; addr = addr->Next)
188 if (addr->Address.lpSockaddr->sa_family == AF_INET &&
189 socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &addr->Address))
190 print_field(STRING_IP_ADDRESS, addr_buf);
191 else if (addr->Address.lpSockaddr->sa_family == AF_INET6 &&
192 socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &addr->Address))
193 print_field(STRING_IP6_ADDRESS, addr_buf);
194 /* FIXME: Output corresponding subnet mask. */
197 if (p->FirstGatewayAddress)
199 if (socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &p->FirstGatewayAddress->Address))
200 print_field(STRING_DEFAULT_GATEWAY, addr_buf);
202 for (gateway = p->FirstGatewayAddress->Next; gateway; gateway = gateway->Next)
204 if (socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &gateway->Address))
205 print_value(addr_buf);
208 else
209 print_field(STRING_DEFAULT_GATEWAY, emptyW);
211 ipconfig_printfW(newlineW);
215 HeapFree(GetProcessHeap(), 0, adapters);
219 static const WCHAR *nodetype_to_string(DWORD type)
221 static WCHAR msg_buffer[50];
223 int msg;
225 switch (type)
227 case BROADCAST_NODETYPE:
228 msg = STRING_BROADCAST;
229 break;
230 case PEER_TO_PEER_NODETYPE:
231 msg = STRING_PEER_TO_PEER;
232 break;
233 case MIXED_NODETYPE:
234 msg = STRING_MIXED;
235 break;
236 case HYBRID_NODETYPE:
237 msg = STRING_HYBRID;
238 break;
239 default:
240 msg = STRING_UNKNOWN;
243 LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer, ARRAY_SIZE(msg_buffer));
245 return msg_buffer;
248 static WCHAR *physaddr_to_string(WCHAR *buf, BYTE *addr, DWORD len)
250 static const WCHAR fmtW[] = {'%','0','2','X','-',0};
251 static const WCHAR fmt2W[] = {'%','0','2','X',0};
253 if (!len)
254 *buf = '\0';
255 else
257 WCHAR *p = buf;
258 DWORD i;
260 for (i = 0; i < len - 1; i++)
262 sprintfW(p, fmtW, addr[i]);
263 p += 3;
265 sprintfW(p, fmt2W, addr[i]);
268 return buf;
271 static const WCHAR *boolean_to_string(int value)
273 static WCHAR msg_buffer[15];
275 LoadStringW(GetModuleHandleW(NULL), value ? STRING_YES : STRING_NO,
276 msg_buffer, ARRAY_SIZE(msg_buffer));
278 return msg_buffer;
281 static void print_full_information(void)
283 static const WCHAR newlineW[] = {'\n',0};
284 static const WCHAR emptyW[] = {0};
286 FIXED_INFO *info;
287 IP_ADAPTER_ADDRESSES *adapters;
288 ULONG out = 0;
290 if (GetNetworkParams(NULL, &out) == ERROR_BUFFER_OVERFLOW)
292 info = HeapAlloc(GetProcessHeap(), 0, out);
293 if (!info)
294 exit(1);
296 if (GetNetworkParams(info, &out) == ERROR_SUCCESS)
298 WCHAR hostnameW[MAX_HOSTNAME_LEN + 4];
300 MultiByteToWideChar(CP_ACP, 0, info->HostName, -1, hostnameW, ARRAY_SIZE(hostnameW));
301 print_field(STRING_HOSTNAME, hostnameW);
303 /* FIXME: Output primary DNS suffix. */
305 print_field(STRING_NODE_TYPE, nodetype_to_string(info->NodeType));
306 print_field(STRING_IP_ROUTING, boolean_to_string(info->EnableRouting));
308 /* FIXME: Output WINS proxy status and DNS suffix search list. */
310 ipconfig_printfW(newlineW);
313 HeapFree(GetProcessHeap(), 0, info);
316 if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_GATEWAYS,
317 NULL, NULL, &out) == ERROR_BUFFER_OVERFLOW)
319 adapters = HeapAlloc(GetProcessHeap(), 0, out);
320 if (!adapters)
321 exit(1);
323 if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_GATEWAYS,
324 NULL, adapters, &out) == ERROR_SUCCESS)
326 IP_ADAPTER_ADDRESSES *p;
328 for (p = adapters; p; p = p->Next)
330 IP_ADAPTER_UNICAST_ADDRESS *addr;
331 WCHAR physaddr_buf[3 * MAX_ADAPTER_ADDRESS_LENGTH];
332 IP_ADAPTER_GATEWAY_ADDRESS_LH *gateway;
333 WCHAR addr_buf[54];
335 ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY, iftype_to_string(p->IfType), p->FriendlyName);
336 ipconfig_printfW(newlineW);
337 print_field(STRING_CONN_DNS_SUFFIX, p->DnsSuffix);
338 print_field(STRING_DESCRIPTION, p->Description);
339 print_field(STRING_PHYS_ADDR, physaddr_to_string(physaddr_buf, p->PhysicalAddress, p->PhysicalAddressLength));
340 print_field(STRING_DHCP_ENABLED, boolean_to_string(p->u1.Flags & IP_ADAPTER_DHCP_ENABLED));
342 /* FIXME: Output autoconfiguration status. */
344 for (addr = p->FirstUnicastAddress; addr; addr = addr->Next)
346 if (addr->Address.lpSockaddr->sa_family == AF_INET &&
347 socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &addr->Address))
348 print_field(STRING_IP_ADDRESS, addr_buf);
349 else if (addr->Address.lpSockaddr->sa_family == AF_INET6 &&
350 socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &addr->Address))
351 print_field(STRING_IP6_ADDRESS, addr_buf);
352 /* FIXME: Output corresponding subnet mask. */
355 if (p->FirstGatewayAddress)
357 if (socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &p->FirstGatewayAddress->Address))
358 print_field(STRING_DEFAULT_GATEWAY, addr_buf);
360 for (gateway = p->FirstGatewayAddress->Next; gateway; gateway = gateway->Next)
362 if (socket_address_to_string(addr_buf, ARRAY_SIZE(addr_buf), &gateway->Address))
363 print_value(addr_buf);
366 else
367 print_field(STRING_DEFAULT_GATEWAY, emptyW);
369 ipconfig_printfW(newlineW);
373 HeapFree(GetProcessHeap(), 0, adapters);
377 int wmain(int argc, WCHAR *argv[])
379 static const WCHAR slashHelp[] = {'/','?',0};
380 static const WCHAR slashAll[] = {'/','a','l','l',0};
382 WSADATA data;
384 if (WSAStartup(MAKEWORD(2, 2), &data))
385 return 1;
387 if (argc > 1)
389 if (!strcmpW(slashHelp, argv[1]))
391 ipconfig_message(STRING_USAGE);
392 WSACleanup();
393 return 1;
395 else if (!strcmpiW(slashAll, argv[1]))
397 if (argv[2])
399 ipconfig_message(STRING_INVALID_CMDLINE);
400 ipconfig_message(STRING_USAGE);
401 WSACleanup();
402 return 1;
405 print_full_information();
407 else
409 ipconfig_message(STRING_INVALID_CMDLINE);
410 ipconfig_message(STRING_USAGE);
411 WSACleanup();
412 return 1;
415 else
416 print_basic_information();
418 WSACleanup();
419 return 0;