Andrew Nguyen : ipconfig: Partially implement basic adapter information output.

Alexandre Julliard julliard at winehq.org
Tue Aug 17 11:31:18 CDT 2010


Module: wine
Branch: master
Commit: 6ffd8d49be532d62b8e7d0ab2564e78939661fd4
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6ffd8d49be532d62b8e7d0ab2564e78939661fd4

Author: Andrew Nguyen <anguyen at codeweavers.com>
Date:   Mon Aug 16 21:27:32 2010 -0500

ipconfig: Partially implement basic adapter information output.

---

 programs/ipconfig/En.rc       |    5 ++
 programs/ipconfig/Makefile.in |    2 +-
 programs/ipconfig/ipconfig.c  |  130 +++++++++++++++++++++++++++++++++++++++--
 programs/ipconfig/ipconfig.h  |    5 ++
 4 files changed, 136 insertions(+), 6 deletions(-)

diff --git a/programs/ipconfig/En.rc b/programs/ipconfig/En.rc
index 4635ff6..7eeffdf 100644
--- a/programs/ipconfig/En.rc
+++ b/programs/ipconfig/En.rc
@@ -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"
 }
diff --git a/programs/ipconfig/Makefile.in b/programs/ipconfig/Makefile.in
index 18a7714..cd0c2dc 100644
--- a/programs/ipconfig/Makefile.in
+++ b/programs/ipconfig/Makefile.in
@@ -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
 
diff --git a/programs/ipconfig/ipconfig.c b/programs/ipconfig/ipconfig.c
index 7c988bb..89ea8a4 100644
--- a/programs/ipconfig/ipconfig.c
+++ b/programs/ipconfig/ipconfig.c
@@ -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;
 }
diff --git a/programs/ipconfig/ipconfig.h b/programs/ipconfig/ipconfig.h
index f02792d..e555b87 100644
--- a/programs/ipconfig/ipconfig.h
+++ b/programs/ipconfig/ipconfig.h
@@ -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




More information about the wine-cvs mailing list