winhlp32: Remove redundant comparison.
[wine.git] / programs / ipconfig / ipconfig.c
blob936dfa2ea85a67a1883a7a443ebebd28e6db7e77
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 sizeof(msg_buffer)/sizeof(*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,
84 sizeof(msg_buffer)/sizeof(WCHAR));
86 __ms_va_start(va_args, msg);
87 len = ipconfig_vprintfW(msg_buffer, va_args);
88 __ms_va_end(va_args);
90 return len;
93 static int ipconfig_message(int msg)
95 static const WCHAR formatW[] = {'%','1',0};
96 WCHAR msg_buffer[8192];
98 LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer,
99 sizeof(msg_buffer)/sizeof(WCHAR));
101 return ipconfig_printfW(formatW, msg_buffer);
104 static const WCHAR *iftype_to_string(DWORD type)
106 static WCHAR msg_buffer[50];
108 int msg;
110 switch (type)
112 case IF_TYPE_ETHERNET_CSMACD:
113 /* The loopback adapter appears as an Ethernet device. */
114 case IF_TYPE_SOFTWARE_LOOPBACK:
115 msg = STRING_ETHERNET;
116 break;
117 default:
118 msg = STRING_UNKNOWN;
121 LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer,
122 sizeof(msg_buffer)/sizeof(WCHAR));
124 return msg_buffer;
127 static void print_field(int msg, const WCHAR *value)
129 static const WCHAR formatW[] = {' ',' ',' ',' ','%','1',':',' ','%','2','\n',0};
131 WCHAR field[] = {'.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',
132 ' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ',0};
133 WCHAR name_buffer[sizeof(field)/sizeof(WCHAR)];
135 LoadStringW(GetModuleHandleW(NULL), msg, name_buffer, sizeof(name_buffer)/sizeof(WCHAR));
136 memcpy(field, name_buffer, sizeof(WCHAR) * min(strlenW(name_buffer), sizeof(field)/sizeof(WCHAR) - 1));
138 ipconfig_printfW(formatW, field, value);
141 static void print_value(const WCHAR *value)
143 static const WCHAR formatW[] = {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
144 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
145 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
146 ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',
147 '%','1','\n',0};
149 ipconfig_printfW(formatW, value);
152 static BOOL socket_address_to_string(WCHAR *buf, DWORD len, SOCKET_ADDRESS *addr)
154 return WSAAddressToStringW(addr->lpSockaddr,
155 addr->iSockaddrLength, NULL,
156 buf, &len) == 0;
159 static void print_basic_information(void)
161 IP_ADAPTER_ADDRESSES *adapters;
162 ULONG out = 0;
164 if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_GATEWAYS,
165 NULL, NULL, &out) == ERROR_BUFFER_OVERFLOW)
167 adapters = HeapAlloc(GetProcessHeap(), 0, out);
168 if (!adapters)
169 exit(1);
171 if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_GATEWAYS,
172 NULL, adapters, &out) == ERROR_SUCCESS)
174 IP_ADAPTER_ADDRESSES *p;
176 for (p = adapters; p; p = p->Next)
178 static const WCHAR newlineW[] = {'\n',0};
179 static const WCHAR emptyW[] = {0};
181 IP_ADAPTER_UNICAST_ADDRESS *addr;
182 IP_ADAPTER_GATEWAY_ADDRESS_LH *gateway;
183 WCHAR addr_buf[54];
185 ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY, iftype_to_string(p->IfType), p->FriendlyName);
186 ipconfig_printfW(newlineW);
187 print_field(STRING_CONN_DNS_SUFFIX, p->DnsSuffix);
189 for (addr = p->FirstUnicastAddress; addr; addr = addr->Next)
191 if (addr->Address.lpSockaddr->sa_family == AF_INET &&
192 socket_address_to_string(addr_buf, sizeof(addr_buf)/sizeof(WCHAR), &addr->Address))
193 print_field(STRING_IP_ADDRESS, addr_buf);
194 else if (addr->Address.lpSockaddr->sa_family == AF_INET6 &&
195 socket_address_to_string(addr_buf, sizeof(addr_buf)/sizeof(WCHAR), &addr->Address))
196 print_field(STRING_IP6_ADDRESS, addr_buf);
197 /* FIXME: Output corresponding subnet mask. */
200 if (p->FirstGatewayAddress)
202 if (socket_address_to_string(addr_buf, sizeof(addr_buf)/sizeof(WCHAR), &p->FirstGatewayAddress->Address))
203 print_field(STRING_DEFAULT_GATEWAY, addr_buf);
205 for (gateway = p->FirstGatewayAddress->Next; gateway; gateway = gateway->Next)
207 if (socket_address_to_string(addr_buf, sizeof(addr_buf)/sizeof(WCHAR), &gateway->Address))
208 print_value(addr_buf);
211 else
212 print_field(STRING_DEFAULT_GATEWAY, emptyW);
214 ipconfig_printfW(newlineW);
218 HeapFree(GetProcessHeap(), 0, adapters);
222 static const WCHAR *nodetype_to_string(DWORD type)
224 static WCHAR msg_buffer[50];
226 int msg;
228 switch (type)
230 case BROADCAST_NODETYPE:
231 msg = STRING_BROADCAST;
232 break;
233 case PEER_TO_PEER_NODETYPE:
234 msg = STRING_PEER_TO_PEER;
235 break;
236 case MIXED_NODETYPE:
237 msg = STRING_MIXED;
238 break;
239 case HYBRID_NODETYPE:
240 msg = STRING_HYBRID;
241 break;
242 default:
243 msg = STRING_UNKNOWN;
246 LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer,
247 sizeof(msg_buffer)/sizeof(WCHAR));
249 return msg_buffer;
252 static WCHAR *physaddr_to_string(WCHAR *buf, BYTE *addr, DWORD len)
254 static const WCHAR fmtW[] = {'%','0','2','X','-',0};
255 static const WCHAR fmt2W[] = {'%','0','2','X',0};
257 if (!len)
258 *buf = '\0';
259 else
261 WCHAR *p = buf;
262 DWORD i;
264 for (i = 0; i < len - 1; i++)
266 sprintfW(p, fmtW, addr[i]);
267 p += 3;
269 sprintfW(p, fmt2W, addr[i]);
272 return buf;
275 static const WCHAR *boolean_to_string(int value)
277 static WCHAR msg_buffer[15];
279 LoadStringW(GetModuleHandleW(NULL), value ? STRING_YES : STRING_NO,
280 msg_buffer, sizeof(msg_buffer)/sizeof(WCHAR));
282 return msg_buffer;
285 static void print_full_information(void)
287 static const WCHAR newlineW[] = {'\n',0};
288 static const WCHAR emptyW[] = {0};
290 FIXED_INFO *info;
291 IP_ADAPTER_ADDRESSES *adapters;
292 ULONG out = 0;
294 if (GetNetworkParams(NULL, &out) == ERROR_BUFFER_OVERFLOW)
296 info = HeapAlloc(GetProcessHeap(), 0, out);
297 if (!info)
298 exit(1);
300 if (GetNetworkParams(info, &out) == ERROR_SUCCESS)
302 WCHAR hostnameW[MAX_HOSTNAME_LEN + 4];
304 MultiByteToWideChar(CP_ACP, 0, info->HostName, -1, hostnameW, sizeof(hostnameW)/sizeof(hostnameW[0]));
305 print_field(STRING_HOSTNAME, hostnameW);
307 /* FIXME: Output primary DNS suffix. */
309 print_field(STRING_NODE_TYPE, nodetype_to_string(info->NodeType));
310 print_field(STRING_IP_ROUTING, boolean_to_string(info->EnableRouting));
312 /* FIXME: Output WINS proxy status and DNS suffix search list. */
314 ipconfig_printfW(newlineW);
317 HeapFree(GetProcessHeap(), 0, info);
320 if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_GATEWAYS,
321 NULL, NULL, &out) == ERROR_BUFFER_OVERFLOW)
323 adapters = HeapAlloc(GetProcessHeap(), 0, out);
324 if (!adapters)
325 exit(1);
327 if (GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_ALL_GATEWAYS,
328 NULL, adapters, &out) == ERROR_SUCCESS)
330 IP_ADAPTER_ADDRESSES *p;
332 for (p = adapters; p; p = p->Next)
334 IP_ADAPTER_UNICAST_ADDRESS *addr;
335 WCHAR physaddr_buf[3 * MAX_ADAPTER_ADDRESS_LENGTH];
336 IP_ADAPTER_GATEWAY_ADDRESS_LH *gateway;
337 WCHAR addr_buf[54];
339 ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY, iftype_to_string(p->IfType), p->FriendlyName);
340 ipconfig_printfW(newlineW);
341 print_field(STRING_CONN_DNS_SUFFIX, p->DnsSuffix);
342 print_field(STRING_DESCRIPTION, p->Description);
343 print_field(STRING_PHYS_ADDR, physaddr_to_string(physaddr_buf, p->PhysicalAddress, p->PhysicalAddressLength));
344 print_field(STRING_DHCP_ENABLED, boolean_to_string(p->u1.Flags & IP_ADAPTER_DHCP_ENABLED));
346 /* FIXME: Output autoconfiguration status. */
348 for (addr = p->FirstUnicastAddress; addr; addr = addr->Next)
350 if (addr->Address.lpSockaddr->sa_family == AF_INET &&
351 socket_address_to_string(addr_buf, sizeof(addr_buf)/sizeof(WCHAR), &addr->Address))
352 print_field(STRING_IP_ADDRESS, addr_buf);
353 else if (addr->Address.lpSockaddr->sa_family == AF_INET6 &&
354 socket_address_to_string(addr_buf, sizeof(addr_buf)/sizeof(WCHAR), &addr->Address))
355 print_field(STRING_IP6_ADDRESS, addr_buf);
356 /* FIXME: Output corresponding subnet mask. */
359 if (p->FirstGatewayAddress)
361 if (socket_address_to_string(addr_buf, sizeof(addr_buf)/sizeof(WCHAR), &p->FirstGatewayAddress->Address))
362 print_field(STRING_DEFAULT_GATEWAY, addr_buf);
364 for (gateway = p->FirstGatewayAddress->Next; gateway; gateway = gateway->Next)
366 if (socket_address_to_string(addr_buf, sizeof(addr_buf)/sizeof(WCHAR), &gateway->Address))
367 print_value(addr_buf);
370 else
371 print_field(STRING_DEFAULT_GATEWAY, emptyW);
373 ipconfig_printfW(newlineW);
377 HeapFree(GetProcessHeap(), 0, adapters);
381 int wmain(int argc, WCHAR *argv[])
383 static const WCHAR slashHelp[] = {'/','?',0};
384 static const WCHAR slashAll[] = {'/','a','l','l',0};
386 WSADATA data;
388 if (WSAStartup(MAKEWORD(2, 2), &data))
389 return 1;
391 if (argc > 1)
393 if (!strcmpW(slashHelp, argv[1]))
395 ipconfig_message(STRING_USAGE);
396 WSACleanup();
397 return 1;
399 else if (!strcmpiW(slashAll, argv[1]))
401 if (argv[2])
403 ipconfig_message(STRING_INVALID_CMDLINE);
404 ipconfig_message(STRING_USAGE);
405 WSACleanup();
406 return 1;
409 print_full_information();
411 else
413 ipconfig_message(STRING_INVALID_CMDLINE);
414 ipconfig_message(STRING_USAGE);
415 WSACleanup();
416 return 1;
419 else
420 print_basic_information();
422 WSACleanup();
423 return 0;