ipconfig: Partially implement basic adapter information output.

This commit is contained in:
Andrew Nguyen 2010-08-16 21:27:32 -05:00 committed by Alexandre Julliard
parent 2e0a7e7f4a
commit 6ffd8d49be
4 changed files with 136 additions and 6 deletions

View File

@ -27,4 +27,9 @@ STRINGTABLE
{
STRING_USAGE, "Usage: ipconfig [ /? | /all ]\n"
STRING_INVALID_CMDLINE, "Error: Unknown or invalid command line parameters specified\n"
STRING_ADAPTER_FRIENDLY, "%s adapter %s\n"
STRING_ETHERNET, "Ethernet"
STRING_UNKNOWN, "Unknown"
STRING_CONN_DNS_SUFFIX, "Connection-specific DNS suffix"
STRING_IP_ADDRESS, "IP address"
}

View File

@ -5,7 +5,7 @@ SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = ipconfig.exe
APPMODE = -mconsole -municode
IMPORTS = user32
IMPORTS = iphlpapi ws2_32 user32
C_SRCS = ipconfig.c

View File

@ -20,6 +20,7 @@
*/
#include <windows.h>
#include <iphlpapi.h>
#include <wine/debug.h>
#include <wine/unicode.h>
@ -27,16 +28,13 @@
WINE_DEFAULT_DEBUG_CHANNEL(ipconfig);
static int ipconfig_printfW(const WCHAR *msg, ...)
static int ipconfig_vprintfW(const WCHAR *msg, va_list va_args)
{
va_list va_args;
int wlen;
DWORD count, ret;
WCHAR msg_buffer[8192];
va_start(va_args, msg);
wlen = vsprintfW(msg_buffer, msg, va_args);
va_end(va_args);
ret = WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), msg_buffer, wlen, &count, NULL);
if (!ret)
@ -59,6 +57,34 @@ static int ipconfig_printfW(const WCHAR *msg, ...)
return count;
}
static int ipconfig_printfW(const WCHAR *msg, ...)
{
va_list va_args;
int len;
va_start(va_args, msg);
len = ipconfig_vprintfW(msg, va_args);
va_end(va_args);
return len;
}
static int ipconfig_message_printfW(int msg, ...)
{
va_list va_args;
WCHAR msg_buffer[8192];
int len;
LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer,
sizeof(msg_buffer)/sizeof(WCHAR));
va_start(va_args, msg);
len = ipconfig_vprintfW(msg_buffer, va_args);
va_end(va_args);
return len;
}
static int ipconfig_message(int msg)
{
static const WCHAR formatW[] = {'%','s',0};
@ -66,19 +92,109 @@ static int ipconfig_message(int msg)
LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer,
sizeof(msg_buffer)/sizeof(WCHAR));
return ipconfig_printfW(formatW, msg_buffer);
}
static const WCHAR *iftype_to_string(DWORD type)
{
static WCHAR msg_buffer[50];
int msg;
switch (type)
{
case IF_TYPE_ETHERNET_CSMACD:
/* The loopback adapter appears as an Ethernet device. */
case IF_TYPE_SOFTWARE_LOOPBACK:
msg = STRING_ETHERNET;
break;
default:
msg = STRING_UNKNOWN;
}
LoadStringW(GetModuleHandleW(NULL), msg, msg_buffer,
sizeof(msg_buffer)/sizeof(WCHAR));
return msg_buffer;
}
static void print_field(int msg, const WCHAR *value)
{
static const WCHAR formatW[] = {' ',' ',' ',' ','%','s',':',' ','%','s','\n',0};
WCHAR field[] = {'.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',
' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ','.',' ',0};
WCHAR name_buffer[sizeof(field)/sizeof(WCHAR)];
LoadStringW(GetModuleHandleW(NULL), msg, name_buffer, sizeof(name_buffer)/sizeof(WCHAR));
memcpy(field, name_buffer, sizeof(WCHAR) * min(strlenW(name_buffer), sizeof(field)/sizeof(WCHAR) - 1));
ipconfig_printfW(formatW, field, value);
}
static void print_basic_information(void)
{
IP_ADAPTER_ADDRESSES *adapters;
ULONG out = 0;
if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &out) == ERROR_BUFFER_OVERFLOW)
{
adapters = HeapAlloc(GetProcessHeap(), 0, out);
if (!adapters)
exit(1);
if (GetAdaptersAddresses(AF_UNSPEC, 0, NULL, adapters, &out) == ERROR_SUCCESS)
{
IP_ADAPTER_ADDRESSES *p;
for (p = adapters; p; p = p->Next)
{
static const WCHAR newlineW[] = {'\n',0};
IP_ADAPTER_UNICAST_ADDRESS *addr;
ipconfig_message_printfW(STRING_ADAPTER_FRIENDLY, iftype_to_string(p->IfType), p->FriendlyName);
ipconfig_printfW(newlineW);
print_field(STRING_CONN_DNS_SUFFIX, p->DnsSuffix);
for (addr = p->FirstUnicastAddress; addr; addr = addr->Next)
{
WCHAR addr_buf[54];
DWORD len = sizeof(addr_buf)/sizeof(WCHAR);
if (WSAAddressToStringW(addr->Address.lpSockaddr,
addr->Address.iSockaddrLength, NULL,
addr_buf, &len) == 0)
print_field(STRING_IP_ADDRESS, addr_buf);
/* FIXME: Output corresponding subnet mask. */
}
/* FIXME: Output default gateway address. */
ipconfig_printfW(newlineW);
}
}
HeapFree(GetProcessHeap(), 0, adapters);
}
}
int wmain(int argc, WCHAR *argv[])
{
static const WCHAR slashHelp[] = {'/','?',0};
static const WCHAR slashAll[] = {'/','a','l','l',0};
WSADATA data;
if (WSAStartup(MAKEWORD(2, 2), &data))
return 1;
if (argc > 1)
{
if (!strcmpW(slashHelp, argv[1]))
{
ipconfig_message(STRING_USAGE);
WSACleanup();
return 1;
}
else if (!strcmpiW(slashAll, argv[1]))
@ -87,6 +203,7 @@ int wmain(int argc, WCHAR *argv[])
{
ipconfig_message(STRING_INVALID_CMDLINE);
ipconfig_message(STRING_USAGE);
WSACleanup();
return 1;
}
@ -96,10 +213,13 @@ int wmain(int argc, WCHAR *argv[])
{
ipconfig_message(STRING_INVALID_CMDLINE);
ipconfig_message(STRING_USAGE);
WSACleanup();
return 1;
}
}
else
print_basic_information();
WINE_FIXME("Network interface output is not currently implemented\n");
WSACleanup();
return 0;
}

View File

@ -23,3 +23,8 @@
/* Translation IDs. */
#define STRING_USAGE 101
#define STRING_INVALID_CMDLINE 102
#define STRING_ADAPTER_FRIENDLY 103
#define STRING_ETHERNET 104
#define STRING_UNKNOWN 105
#define STRING_CONN_DNS_SUFFIX 106
#define STRING_IP_ADDRESS 107