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
24 #include <wine/unicode.h>
28 static int ipconfig_vprintfW(const WCHAR
*msg
, va_list va_args
)
32 WCHAR msg_buffer
[8192];
34 wlen
= vsprintfW(msg_buffer
, msg
, va_args
);
36 ret
= WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE
), msg_buffer
, wlen
, &count
, NULL
);
42 len
= WideCharToMultiByte(GetConsoleOutputCP(), 0, msg_buffer
, wlen
,
44 msgA
= HeapAlloc(GetProcessHeap(), 0, len
);
48 WideCharToMultiByte(GetConsoleOutputCP(), 0, msg_buffer
, wlen
, msgA
, len
,
50 WriteFile(GetStdHandle(STD_OUTPUT_HANDLE
), msgA
, len
, &count
, FALSE
);
51 HeapFree(GetProcessHeap(), 0, msgA
);
57 static int ipconfig_printfW(const WCHAR
*msg
, ...)
62 va_start(va_args
, msg
);
63 len
= ipconfig_vprintfW(msg
, va_args
);
69 static int ipconfig_message_printfW(int msg
, ...)
72 WCHAR msg_buffer
[8192];
75 LoadStringW(GetModuleHandleW(NULL
), msg
, msg_buffer
,
76 sizeof(msg_buffer
)/sizeof(WCHAR
));
78 va_start(va_args
, msg
);
79 len
= ipconfig_vprintfW(msg_buffer
, va_args
);
85 static int ipconfig_message(int msg
)
87 static const WCHAR formatW
[] = {'%','s',0};
88 WCHAR msg_buffer
[8192];
90 LoadStringW(GetModuleHandleW(NULL
), msg
, msg_buffer
,
91 sizeof(msg_buffer
)/sizeof(WCHAR
));
93 return ipconfig_printfW(formatW
, msg_buffer
);
96 static const WCHAR
*iftype_to_string(DWORD type
)
98 static WCHAR msg_buffer
[50];
104 case IF_TYPE_ETHERNET_CSMACD
:
105 /* The loopback adapter appears as an Ethernet device. */
106 case IF_TYPE_SOFTWARE_LOOPBACK
:
107 msg
= STRING_ETHERNET
;
110 msg
= STRING_UNKNOWN
;
113 LoadStringW(GetModuleHandleW(NULL
), msg
, msg_buffer
,
114 sizeof(msg_buffer
)/sizeof(WCHAR
));
119 static void print_field(int msg
, const WCHAR
*value
)
121 static const WCHAR formatW
[] = {' ',' ',' ',' ','%','s',':',' ','%','s','\n',0};
123 WCHAR field
[] = {'.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',
124 ' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ',0};
125 WCHAR name_buffer
[sizeof(field
)/sizeof(WCHAR
)];
127 LoadStringW(GetModuleHandleW(NULL
), msg
, name_buffer
, sizeof(name_buffer
)/sizeof(WCHAR
));
128 memcpy(field
, name_buffer
, sizeof(WCHAR
) * min(strlenW(name_buffer
), sizeof(field
)/sizeof(WCHAR
) - 1));
130 ipconfig_printfW(formatW
, field
, value
);
133 static void print_basic_information(void)
135 IP_ADAPTER_ADDRESSES
*adapters
;
138 if (GetAdaptersAddresses(AF_UNSPEC
, 0, NULL
, NULL
, &out
) == ERROR_BUFFER_OVERFLOW
)
140 adapters
= HeapAlloc(GetProcessHeap(), 0, out
);
144 if (GetAdaptersAddresses(AF_UNSPEC
, 0, NULL
, adapters
, &out
) == ERROR_SUCCESS
)
146 IP_ADAPTER_ADDRESSES
*p
;
148 for (p
= adapters
; p
; p
= p
->Next
)
150 static const WCHAR newlineW
[] = {'\n',0};
152 IP_ADAPTER_UNICAST_ADDRESS
*addr
;
154 ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY
, iftype_to_string(p
->IfType
), p
->FriendlyName
);
155 ipconfig_printfW(newlineW
);
156 print_field(STRING_CONN_DNS_SUFFIX
, p
->DnsSuffix
);
158 for (addr
= p
->FirstUnicastAddress
; addr
; addr
= addr
->Next
)
161 DWORD len
= sizeof(addr_buf
)/sizeof(WCHAR
);
163 if (WSAAddressToStringW(addr
->Address
.lpSockaddr
,
164 addr
->Address
.iSockaddrLength
, NULL
,
165 addr_buf
, &len
) == 0)
166 print_field(STRING_IP_ADDRESS
, addr_buf
);
167 /* FIXME: Output corresponding subnet mask. */
170 /* FIXME: Output default gateway address. */
171 ipconfig_printfW(newlineW
);
175 HeapFree(GetProcessHeap(), 0, adapters
);
179 static const WCHAR
*nodetype_to_string(DWORD type
)
181 static WCHAR msg_buffer
[50];
187 case BROADCAST_NODETYPE
:
188 msg
= STRING_BROADCAST
;
190 case PEER_TO_PEER_NODETYPE
:
191 msg
= STRING_PEER_TO_PEER
;
196 case HYBRID_NODETYPE
:
200 msg
= STRING_UNKNOWN
;
203 LoadStringW(GetModuleHandleW(NULL
), msg
, msg_buffer
,
204 sizeof(msg_buffer
)/sizeof(WCHAR
));
209 static WCHAR
*physaddr_to_string(WCHAR
*buf
, BYTE
*addr
, DWORD len
)
211 static const WCHAR fmtW
[] = {'%','0','2','X','-',0};
212 static const WCHAR fmt2W
[] = {'%','0','2','X',0};
221 for (i
= 0; i
< len
- 1; i
++)
223 sprintfW(p
, fmtW
, addr
[i
]);
226 sprintfW(p
, fmt2W
, addr
[i
]);
232 static const WCHAR
*boolean_to_string(int value
)
234 static WCHAR msg_buffer
[15];
236 LoadStringW(GetModuleHandleW(NULL
), value
? STRING_YES
: STRING_NO
,
237 msg_buffer
, sizeof(msg_buffer
)/sizeof(WCHAR
));
242 static void print_full_information(void)
244 static const WCHAR newlineW
[] = {'\n',0};
247 IP_ADAPTER_ADDRESSES
*adapters
;
250 if (GetNetworkParams(NULL
, &out
) == ERROR_BUFFER_OVERFLOW
)
252 info
= HeapAlloc(GetProcessHeap(), 0, out
);
256 if (GetNetworkParams(info
, &out
) == ERROR_SUCCESS
)
258 WCHAR hostnameW
[MAX_HOSTNAME_LEN
+ 4];
260 MultiByteToWideChar(CP_ACP
, 0, info
->HostName
, -1, hostnameW
, sizeof(hostnameW
));
261 print_field(STRING_HOSTNAME
, hostnameW
);
263 /* FIXME: Output primary DNS suffix. */
265 print_field(STRING_NODE_TYPE
, nodetype_to_string(info
->NodeType
));
266 print_field(STRING_IP_ROUTING
, boolean_to_string(info
->EnableRouting
));
268 /* FIXME: Output WINS proxy status and DNS suffix search list. */
270 ipconfig_printfW(newlineW
);
273 HeapFree(GetProcessHeap(), 0, info
);
276 if (GetAdaptersAddresses(AF_UNSPEC
, 0, NULL
, NULL
, &out
) == ERROR_BUFFER_OVERFLOW
)
278 adapters
= HeapAlloc(GetProcessHeap(), 0, out
);
282 if (GetAdaptersAddresses(AF_UNSPEC
, 0, NULL
, adapters
, &out
) == ERROR_SUCCESS
)
284 IP_ADAPTER_ADDRESSES
*p
;
286 for (p
= adapters
; p
; p
= p
->Next
)
288 IP_ADAPTER_UNICAST_ADDRESS
*addr
;
289 WCHAR physaddr_buf
[3 * MAX_ADAPTER_ADDRESS_LENGTH
];
291 ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY
, iftype_to_string(p
->IfType
), p
->FriendlyName
);
292 ipconfig_printfW(newlineW
);
293 print_field(STRING_CONN_DNS_SUFFIX
, p
->DnsSuffix
);
294 print_field(STRING_DESCRIPTION
, p
->Description
);
295 print_field(STRING_PHYS_ADDR
, physaddr_to_string(physaddr_buf
, p
->PhysicalAddress
, p
->PhysicalAddressLength
));
296 print_field(STRING_DHCP_ENABLED
, boolean_to_string(p
->Flags
& IP_ADAPTER_DHCP_ENABLED
));
298 /* FIXME: Output autoconfiguration status. */
300 for (addr
= p
->FirstUnicastAddress
; addr
; addr
= addr
->Next
)
303 DWORD len
= sizeof(addr_buf
)/sizeof(WCHAR
);
305 if (WSAAddressToStringW(addr
->Address
.lpSockaddr
,
306 addr
->Address
.iSockaddrLength
, NULL
,
307 addr_buf
, &len
) == 0)
308 print_field(STRING_IP_ADDRESS
, addr_buf
);
309 /* FIXME: Output corresponding subnet mask. */
312 /* FIXME: Output default gateway address. */
314 ipconfig_printfW(newlineW
);
318 HeapFree(GetProcessHeap(), 0, adapters
);
322 int wmain(int argc
, WCHAR
*argv
[])
324 static const WCHAR slashHelp
[] = {'/','?',0};
325 static const WCHAR slashAll
[] = {'/','a','l','l',0};
329 if (WSAStartup(MAKEWORD(2, 2), &data
))
334 if (!strcmpW(slashHelp
, argv
[1]))
336 ipconfig_message(STRING_USAGE
);
340 else if (!strcmpiW(slashAll
, argv
[1]))
344 ipconfig_message(STRING_INVALID_CMDLINE
);
345 ipconfig_message(STRING_USAGE
);
350 print_full_information();
354 ipconfig_message(STRING_INVALID_CMDLINE
);
355 ipconfig_message(STRING_USAGE
);
361 print_basic_information();