[NETSTAT] '-p UDP' depends on '-a'
[reactos.git] / base / applications / network / netstat / netstat.c
index 20818c4..97a843b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * PROJECT:     ReactOS netstat utility
  * LICENSE:     GPL - See COPYING in the top level directory
- * FILE:        apps/utils/net/netstat/netstat.c
+ * FILE:        base/applications/network/netstat/netstat.c
  * PURPOSE:     display IP stack statistics
  * COPYRIGHT:   Copyright 2005 Ged Murphy <gedmurphy@gmail.com>
  */
  * command line parser needs more work
  */
 
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+
 #define WIN32_NO_STATUS
-#include <stdarg.h>
 #include <windef.h>
 #include <winbase.h>
 #define _INC_WINDOWS
 #include <winsock2.h>
-#include <tchar.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <iphlpapi.h>
 
+#include <conutils.h>
+
 #include "netstat.h"
+#include "resource.h"
 
 enum ProtoType {IP, TCP, UDP, ICMP} Protocol;
 DWORD Interval; /* time to pause between printing output */
 
 /* TCP endpoint states */
-TCHAR TcpState[][32] = {
-    _T("???"),
-    _T("CLOSED"),
-    _T("LISTENING"),
-    _T("SYN_SENT"),
-    _T("SYN_RCVD"),
-    _T("ESTABLISHED"),
-    _T("FIN_WAIT1"),
-    _T("FIN_WAIT2"),
-    _T("CLOSE_WAIT"),
-    _T("CLOSING"),
-    _T("LAST_ACK"),
-    _T("TIME_WAIT"),
-    _T("DELETE_TCB")
+PCWSTR TcpState[] = {
+    L"???",
+    L"CLOSED",
+    L"LISTENING",
+    L"SYN_SENT",
+    L"SYN_RCVD",
+    L"ESTABLISHED",
+    L"FIN_WAIT1",
+    L"FIN_WAIT2",
+    L"CLOSE_WAIT",
+    L"CLOSING",
+    L"LAST_ACK",
+    L"TIME_WAIT",
+    L"DELETE_TCB"
 };
 
 /*
  * format message string and display output
  */
-DWORD DoFormatMessage(DWORD ErrorCode)
+VOID DoFormatMessage(DWORD ErrorCode)
 {
-    LPVOID lpMsgBuf;
-    DWORD RetVal;
-
-    if ((RetVal = FormatMessage(
-            FORMAT_MESSAGE_ALLOCATE_BUFFER |
-            FORMAT_MESSAGE_FROM_SYSTEM |
-            FORMAT_MESSAGE_IGNORE_INSERTS,
-            NULL,
-            ErrorCode,
-            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
-            (LPTSTR) &lpMsgBuf,
-            0,
-            NULL )))
-    {
-        _tprintf(_T("%s"), (LPTSTR)lpMsgBuf);
+    if (ErrorCode == ERROR_SUCCESS)
+        return;
 
-        LocalFree(lpMsgBuf);
-        /* return number of TCHAR's stored in output buffer
-         * excluding '\0' - as FormatMessage does*/
-        return RetVal;
-    }
-    else
-        return 0;
+    ConMsgPuts(StdErr, FORMAT_MESSAGE_FROM_SYSTEM,
+               NULL, ErrorCode, LANG_USER_DEFAULT);
 }
 
 /*
@@ -81,153 +66,155 @@ DWORD DoFormatMessage(DWORD ErrorCode)
  * Parse command line parameters and set any options
  *
  */
-BOOL ParseCmdline(int argc, char* argv[])
+BOOL ParseCmdline(int argc, wchar_t* argv[])
 {
+    LPWSTR Proto;
+    WCHAR c;
     INT i;
 
-    TCHAR Proto[5];
-
-    if ((argc == 1) || (_istdigit(*argv[1])))
+    if ((argc == 1) || (iswdigit(*argv[1])))
         bNoOptions = TRUE;
 
     /* Parse command line for options we have been given. */
     for (i = 1; i < argc; i++)
     {
-        if ( (argc > 1)&&(argv[i][0] == '-') )
+        if ((argc > 1) && (argv[i][0] == L'-' || argv[i][0] == L'/'))
         {
-            TCHAR c;
-
-            while ((c = *++argv[i]) != '\0')
+            while ((c = *++argv[i]) != L'\0')
             {
-                switch (tolower(c))
+                switch (towlower(c))
                 {
-                    case 'a' :
+                    case L'a':
                         bDoShowAllCons = TRUE;
                         break;
-                    case 'b' :
+                    case L'b':
                         bDoShowProcName = TRUE;
                         break;
-                    case 'e' :
+                    case L'e':
                         bDoShowEthStats = TRUE;
                         break;
-                    case 'n' :
+                    case L'n':
                         bDoShowNumbers = TRUE;
                         break;
-                    case 's' :
-                        bDoShowProtoStats = TRUE;
-                        break;
-                    case 'p' :
+                    case L'p':
                         bDoShowProtoCons = TRUE;
-
-                        strncpy(Proto, (++argv)[i], sizeof(Proto));
-                        if (!_tcsicmp( "IP", Proto ))
+                        Proto = argv[i+1];
+                        if (!_wcsicmp(L"IP", Proto))
                             Protocol = IP;
-                        else if (!_tcsicmp( "ICMP", Proto ))
+                        else if (!_wcsicmp(L"ICMP", Proto))
                             Protocol = ICMP;
-                        else if (!_tcsicmp( "TCP", Proto ))
+                        else if (!_wcsicmp(L"TCP", Proto))
                             Protocol = TCP;
-                        else if (!_tcsicmp( "UDP", Proto ))
+                        else if (!_wcsicmp(L"UDP", Proto))
                             Protocol = UDP;
                         else
                         {
-                            Usage();
-                            return EXIT_FAILURE;
+                            ConResPuts(StdOut, IDS_USAGE);
+                            return FALSE;
                         }
-                        --i; /* move pointer back down to previous argv */
                         break;
-                    case 'r' :
+                    case L'r':
                         bDoShowRouteTable = TRUE;
                         break;
-                    case 'v' :
-                        _tprintf(_T("got v\n"));
+                    case L's':
+                        bDoShowProtoStats = TRUE;
+                        break;
+                    case L'o':
+                        bDoShowProcessId = TRUE;
+                        break;
+                    case L'v':
+                        // FIXME!
+                        ConPuts(StdOut, L"got v\n");
                         bDoDispSeqComp = TRUE;
                         break;
                     default :
-                        Usage();
-                        return EXIT_FAILURE;
+                        ConResPuts(StdOut, IDS_USAGE);
+                        return FALSE;
                 }
             }
         }
-        else if (_istdigit(*argv[i]))
+        else if (iswdigit(*argv[i]) != 0)
         {
-            if (_stscanf(argv[i], "%lu", &Interval) != EOF)
+            if (swscanf(argv[i], L"%lu", &Interval) != EOF)
                 bLoopOutput = TRUE;
             else
-                return EXIT_FAILURE;
+                return FALSE;
         }
 //        else
 //        {
-//            Usage();
-//            EXIT_FAILURE;
+//            ConResPrintf(StdOut, IDS_USAGE);
+//            return FALSE;
 //        }
     }
 
-    return EXIT_SUCCESS;
+    return TRUE;
+}
+
+/*
+ * Display table header
+ */
+VOID DisplayTableHeader(VOID)
+{
+    ConResPuts(StdOut, IDS_DISPLAY_THEADER);
+    if (bDoShowProcessId)
+        ConResPuts(StdOut, IDS_DISPLAY_PROCESS);
+    else
+        ConPuts(StdOut, L"\n");
 }
 
 /*
  * Simulate Microsofts netstat utility output
  */
-BOOL DisplayOutput()
+BOOL DisplayOutput(VOID)
 {
     if (bNoOptions)
     {
-        _tprintf(_T("\n  Proto  Local Address          Foreign Address        State\n"));
-        ShowTcpTable();
-        return EXIT_SUCCESS;
+        DisplayTableHeader();
+        return ShowTcpTable();
     }
 
     if (bDoShowRouteTable)
     {
-        /* mingw doesn't have lib for _tsystem */
-        if (system("route print") == -1)
+        if (_wsystem(L"route print") == -1)
         {
-            _tprintf(_T("cannot find 'route.exe'\n"));
-            return EXIT_FAILURE;
+            ConResPuts(StdErr, IDS_ERROR_ROUTE);
+            return FALSE;
         }
-        return EXIT_SUCCESS;
+        return TRUE;
     }
 
     if (bDoShowEthStats)
     {
         ShowEthernetStatistics();
-        return EXIT_SUCCESS;
+        return TRUE;
     }
 
     if (bDoShowProtoCons)
     {
         switch (Protocol)
         {
-                case IP :
-                    if (bDoShowProtoStats)
-                    {
-                        ShowIpStatistics();
-                        return EXIT_SUCCESS;
-                    }
-                    break;
-                case ICMP :
-                    if (bDoShowProtoStats)
-                    {
-                        ShowIcmpStatistics();
-                        return EXIT_SUCCESS;
-                    }
-                    break;
-                case TCP :
-                    if (bDoShowProtoStats)
-                        ShowTcpStatistics();
-                    _tprintf(_T("\nActive Connections\n"));
-                    _tprintf(_T("\n  Proto  Local Address          Foreign Address        State\n"));
-                    ShowTcpTable();
-                    break;
-                case UDP :
-                    if (bDoShowProtoStats)
-                        ShowUdpStatistics();
-                    _tprintf(_T("\nActive Connections\n"));
-                    _tprintf(_T("\n  Proto  Local Address          Foreign Address        State\n"));
-                    ShowUdpTable();
-                    break;
-                default :
-                    break;
+            case IP:
+                if (bDoShowProtoStats)
+                    ShowIpStatistics();
+                return TRUE;
+            case ICMP:
+                if (bDoShowProtoStats)
+                    ShowIcmpStatistics();
+                return TRUE;
+            case TCP:
+                if (bDoShowProtoStats)
+                    ShowTcpStatistics();
+                ConResPuts(StdOut, IDS_ACTIVE_CONNECT);
+                DisplayTableHeader();
+                return ShowTcpTable();
+            case UDP:
+                if (bDoShowProtoStats)
+                    ShowUdpStatistics();
+                ConResPuts(StdOut, IDS_ACTIVE_CONNECT);
+                DisplayTableHeader();
+                return (bDoShowAllCons ? ShowUdpTable() : TRUE);
+            default:
+                break;
         }
     }
     else if (bDoShowProtoStats)
@@ -236,20 +223,20 @@ BOOL DisplayOutput()
         ShowIcmpStatistics();
         ShowTcpStatistics();
         ShowUdpStatistics();
-        return EXIT_SUCCESS;
+        return TRUE;
     }
     else
     {
-        _tprintf(_T("\nActive Connections\n"));
-        _tprintf(_T("\n  Proto  Local Address          Foreign Address        State\n"));
-        ShowTcpTable();
-               if (bDoShowAllCons)
+        ConResPuts(StdOut, IDS_ACTIVE_CONNECT);
+        DisplayTableHeader();
+        if (ShowTcpTable() && bDoShowAllCons)
             ShowUdpTable();
     }
-    return EXIT_SUCCESS;
+
+    return TRUE;
 }
 
-VOID ShowIpStatistics()
+VOID ShowIpStatistics(VOID)
 {
     PMIB_IPSTATS pIpStats;
     DWORD dwRetVal;
@@ -258,32 +245,34 @@ VOID ShowIpStatistics()
 
     if ((dwRetVal = GetIpStatistics(pIpStats)) == NO_ERROR)
     {
-        _tprintf(_T("\nIPv4 Statistics\n\n"));
-        _tprintf(_T("  %-34s = %lu\n"), _T("Packets Received"), pIpStats->dwInReceives);
-        _tprintf(_T("  %-34s = %lu\n"), _T("Received Header Errors"), pIpStats->dwInHdrErrors);
-        _tprintf(_T("  %-34s = %lu\n"), _T("Received Address Errors"), pIpStats->dwInAddrErrors);
-        _tprintf(_T("  %-34s = %lu\n"), _T("Datagrams Forwarded"), pIpStats->dwForwDatagrams);
-        _tprintf(_T("  %-34s = %lu\n"), _T("Unknown Protocols Received"), pIpStats->dwInUnknownProtos);
-        _tprintf(_T("  %-34s = %lu\n"), _T("Received Packets Discarded"), pIpStats->dwInDiscards);
-        _tprintf(_T("  %-34s = %lu\n"), _T("Received Packets Delivered"), pIpStats->dwInDelivers);
-        _tprintf(_T("  %-34s = %lu\n"), _T("Output Requests"), pIpStats->dwOutRequests);
-        _tprintf(_T("  %-34s = %lu\n"), _T("Routing Discards"), pIpStats->dwRoutingDiscards);
-        _tprintf(_T("  %-34s = %lu\n"), _T("Discarded Output Packets"), pIpStats->dwOutDiscards);
-        _tprintf(_T("  %-34s = %lu\n"), _T("Output Packets No Route"), pIpStats->dwOutNoRoutes);
-        _tprintf(_T("  %-34s = %lu\n"), _T("Reassembly Required"), pIpStats->dwReasmReqds);
-        _tprintf(_T("  %-34s = %lu\n"), _T("Reassembly Succesful"), pIpStats->dwReasmOks);
-        _tprintf(_T("  %-34s = %lu\n"), _T("Reassembly Failures"), pIpStats->dwReasmFails);
-       // _tprintf(_T("  %-34s = %lu\n"), _T("Datagrams succesfully fragmented"), NULL); /* FIXME: what is this one? */
-        _tprintf(_T("  %-34s = %lu\n"), _T("Datagrams Failing Fragmentation"), pIpStats->dwFragFails);
-        _tprintf(_T("  %-34s = %lu\n"), _T("Fragments Created"), pIpStats->dwFragCreates);
+        ConResPuts(StdOut, IDS_IP4_STAT_HEADER);
+        ConResPrintf(StdOut, IDS_IP_PACK_REC, pIpStats->dwInReceives);
+        ConResPrintf(StdOut, IDS_IP_HEAD_REC_ERROR, pIpStats->dwInHdrErrors);
+        ConResPrintf(StdOut, IDS_IP_ADDR_REC_ERROR, pIpStats->dwInAddrErrors);
+        ConResPrintf(StdOut, IDS_IP_DATAG_FWD, pIpStats->dwForwDatagrams);
+        ConResPrintf(StdOut, IDS_IP_UNKNOWN_PRO_REC, pIpStats->dwInUnknownProtos);
+        ConResPrintf(StdOut, IDS_IP_REC_PACK_DISCARD, pIpStats->dwInDiscards);
+        ConResPrintf(StdOut, IDS_IP_REC_PACK_DELIVER, pIpStats->dwInDelivers);
+        ConResPrintf(StdOut, IDS_IP_OUT_REQUEST, pIpStats->dwOutRequests);
+        ConResPrintf(StdOut, IDS_IP_ROUTE_DISCARD, pIpStats->dwRoutingDiscards);
+        ConResPrintf(StdOut, IDS_IP_DISCARD_OUT_PACK, pIpStats->dwOutDiscards);
+        ConResPrintf(StdOut, IDS_IP_OUT_PACKET_NO_ROUTE, pIpStats->dwOutNoRoutes);
+        ConResPrintf(StdOut, IDS_IP_REASSEMBLE_REQUIRED, pIpStats->dwReasmReqds);
+        ConResPrintf(StdOut, IDS_IP_REASSEMBLE_SUCCESS, pIpStats->dwReasmOks);
+        ConResPrintf(StdOut, IDS_IP_REASSEMBLE_FAILURE, pIpStats->dwReasmFails);
+        ConResPrintf(StdOut, IDS_IP_DATAG_FRAG_SUCCESS, pIpStats->dwFragOks);
+        ConResPrintf(StdOut, IDS_IP_DATAG_FRAG_FAILURE, pIpStats->dwFragFails);
+        ConResPrintf(StdOut, IDS_IP_DATAG_FRAG_CREATE, pIpStats->dwFragCreates);
     }
     else
+    {
         DoFormatMessage(dwRetVal);
+    }
 
     HeapFree(GetProcessHeap(), 0, pIpStats);
 }
 
-VOID ShowIcmpStatistics()
+VOID ShowIcmpStatistics(VOID)
 {
     PMIB_ICMP pIcmpStats;
     DWORD dwRetVal;
@@ -292,89 +281,87 @@ VOID ShowIcmpStatistics()
 
     if ((dwRetVal = GetIcmpStatistics(pIcmpStats)) == NO_ERROR)
     {
-        _tprintf(_T("\nICMPv4 Statistics\n\n"));
-        _tprintf(_T("                            Received    Sent\n"));
-        _tprintf(_T("  %-25s %-11lu %lu\n"), _T("Messages"),
+        ConResPuts(StdOut, IDS_ICMP4_STAT_HEADER);
+        ConResPuts(StdOut, IDS_ICMP_THEADER);
+        ConResPrintf(StdOut, IDS_ICMP_MSG,
             pIcmpStats->stats.icmpInStats.dwMsgs, pIcmpStats->stats.icmpOutStats.dwMsgs);
-        _tprintf(_T("  %-25s %-11lu %lu\n"), _T("Errors"),
+        ConResPrintf(StdOut, IDS_ICMP_ERROR,
             pIcmpStats->stats.icmpInStats.dwErrors, pIcmpStats->stats.icmpOutStats.dwErrors);
-        _tprintf(_T("  %-25s %-11lu %lu\n"), _T("Destination Unreachable"),
+        ConResPrintf(StdOut, IDS_ICMP_DEST_UNREACH,
             pIcmpStats->stats.icmpInStats.dwDestUnreachs, pIcmpStats->stats.icmpOutStats.dwDestUnreachs);
-        _tprintf(_T("  %-25s %-11lu %lu\n"), _T("Time Exceeded"),
+        ConResPrintf(StdOut, IDS_ICMP_TIME_EXCEED,
             pIcmpStats->stats.icmpInStats.dwTimeExcds, pIcmpStats->stats.icmpOutStats.dwTimeExcds);
-        _tprintf(_T("  %-25s %-11lu %lu\n"), _T("Parameter Problems"),
+        ConResPrintf(StdOut, IDS_ICMP_PARAM_PROBLEM,
             pIcmpStats->stats.icmpInStats.dwParmProbs, pIcmpStats->stats.icmpOutStats.dwParmProbs);
-        _tprintf(_T("  %-25s %-11lu %lu\n"), _T("Source Quenches"),
+        ConResPrintf(StdOut, IDS_ICMP_SRC_QUENCHES,
             pIcmpStats->stats.icmpInStats.dwSrcQuenchs, pIcmpStats->stats.icmpOutStats.dwSrcQuenchs);
-        _tprintf(_T("  %-25s %-11lu %lu\n"), _T("Redirects"),
+        ConResPrintf(StdOut, IDS_ICMP_REDIRECT,
             pIcmpStats->stats.icmpInStats.dwRedirects, pIcmpStats->stats.icmpOutStats.dwRedirects);
-        _tprintf(_T("  %-25s %-11lu %lu\n"), _T("Echos"),
+        ConResPrintf(StdOut, IDS_ICMP_ECHO,
             pIcmpStats->stats.icmpInStats.dwEchos, pIcmpStats->stats.icmpOutStats.dwEchos);
-        _tprintf(_T("  %-25s %-11lu %lu\n"), _T("Echo Replies"),
+        ConResPrintf(StdOut, IDS_ICMP_ECHO_REPLY,
             pIcmpStats->stats.icmpInStats.dwEchoReps, pIcmpStats->stats.icmpOutStats.dwEchoReps);
-        _tprintf(_T("  %-25s %-11lu %lu\n"), _T("Timestamps"),
+        ConResPrintf(StdOut, IDS_ICMP_TIMESTAMP,
             pIcmpStats->stats.icmpInStats.dwTimestamps, pIcmpStats->stats.icmpOutStats.dwTimestamps);
-        _tprintf(_T("  %-25s %-11lu %lu\n"), _T("Timestamp Replies"),
+        ConResPrintf(StdOut, IDS_ICMP_TIMESTAMP_REPLY,
             pIcmpStats->stats.icmpInStats.dwTimestampReps, pIcmpStats->stats.icmpOutStats.dwTimestampReps);
-        _tprintf(_T("  %-25s %-11lu %lu\n"), _T("Address Masks"),
+        ConResPrintf(StdOut, IDS_ICMP_ADDRESSS_MASK,
             pIcmpStats->stats.icmpInStats.dwAddrMasks, pIcmpStats->stats.icmpOutStats.dwAddrMasks);
-        _tprintf(_T("  %-25s %-11lu %lu\n"), _T("Address Mask Replies"),
+        ConResPrintf(StdOut, IDS_ICMP_ADDRESSS_MASK_REPLY,
             pIcmpStats->stats.icmpInStats.dwAddrMaskReps, pIcmpStats->stats.icmpOutStats.dwAddrMaskReps);
     }
     else
+    {
         DoFormatMessage(dwRetVal);
+    }
 
     HeapFree(GetProcessHeap(), 0, pIcmpStats);
 
 }
 
-VOID ShowTcpStatistics()
+VOID ShowTcpStatistics(VOID)
 {
-    PMIB_TCPSTATS pTcpStats;
+    MIB_TCPSTATS tcpStats;
     DWORD dwRetVal;
 
-    pTcpStats = (MIB_TCPSTATS*) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_TCPSTATS));
-
-    if ((dwRetVal = GetTcpStatistics(pTcpStats)) == NO_ERROR)
+    if ((dwRetVal = GetTcpStatistics(&tcpStats)) == NO_ERROR)
     {
-        _tprintf(_T("\nTCP Statistics for IPv4\n\n"));
-        _tprintf(_T("  %-35s = %lu\n"), _T("Active Opens"), pTcpStats->dwActiveOpens);
-        _tprintf(_T("  %-35s = %lu\n"), _T("Passive Opens"), pTcpStats->dwPassiveOpens);
-        _tprintf(_T("  %-35s = %lu\n"), _T("Failed Connection Attempts"), pTcpStats->dwAttemptFails);
-        _tprintf(_T("  %-35s = %lu\n"), _T("Reset Connections"), pTcpStats->dwEstabResets);
-        _tprintf(_T("  %-35s = %lu\n"), _T("Current Connections"), pTcpStats->dwCurrEstab);
-        _tprintf(_T("  %-35s = %lu\n"), _T("Segments Received"), pTcpStats->dwInSegs);
-        _tprintf(_T("  %-35s = %lu\n"), _T("Segments Sent"), pTcpStats->dwOutSegs);
-        _tprintf(_T("  %-35s = %lu\n"), _T("Segments Retransmitted"), pTcpStats->dwRetransSegs);
+        ConResPuts(StdOut, IDS_TCP4_HEADER);
+        ConResPrintf(StdOut, IDS_TCP_ACTIVE_OPEN, tcpStats.dwActiveOpens);
+        ConResPrintf(StdOut, IDS_TCP_PASS_OPEN, tcpStats.dwPassiveOpens);
+        ConResPrintf(StdOut, IDS_TCP_FAIL_CONNECT, tcpStats.dwAttemptFails);
+        ConResPrintf(StdOut, IDS_TCP_RESET_CONNECT, tcpStats.dwEstabResets);
+        ConResPrintf(StdOut, IDS_TCP_CURRENT_CONNECT, tcpStats.dwCurrEstab);
+        ConResPrintf(StdOut, IDS_TCP_SEG_RECEIVE, tcpStats.dwInSegs);
+        ConResPrintf(StdOut, IDS_TCP_SEG_SENT, tcpStats.dwOutSegs);
+        ConResPrintf(StdOut, IDS_TCP_SEG_RETRANSMIT, tcpStats.dwRetransSegs);
     }
     else
+    {
         DoFormatMessage(dwRetVal);
-
-    HeapFree(GetProcessHeap(), 0, pTcpStats);
+    }
 }
 
-VOID ShowUdpStatistics()
+VOID ShowUdpStatistics(VOID)
 {
-    PMIB_UDPSTATS pUdpStats;
+    MIB_UDPSTATS udpStats;
     DWORD dwRetVal;
 
-    pUdpStats = (MIB_UDPSTATS*) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_UDPSTATS));
-
-    if ((dwRetVal = GetUdpStatistics(pUdpStats)) == NO_ERROR)
+    if ((dwRetVal = GetUdpStatistics(&udpStats)) == NO_ERROR)
     {
-        _tprintf(_T("\nUDP Statistics for IPv4\n\n"));
-        _tprintf(_T("  %-21s = %lu\n"), _T("Datagrams Received"), pUdpStats->dwInDatagrams);
-        _tprintf(_T("  %-21s = %lu\n"), _T("No Ports"), pUdpStats->dwNoPorts);
-        _tprintf(_T("  %-21s = %lu\n"), _T("Receive Errors"), pUdpStats->dwInErrors);
-        _tprintf(_T("  %-21s = %lu\n"), _T("Datagrams Sent"), pUdpStats->dwOutDatagrams);
+        ConResPuts(StdOut, IDS_UDP_IP4_HEADER);
+        ConResPrintf(StdOut, IDS_UDP_DATAG_RECEIVE, udpStats.dwInDatagrams);
+        ConResPrintf(StdOut, IDS_UDP_NO_PORT, udpStats.dwNoPorts);
+        ConResPrintf(StdOut, IDS_UDP_RECEIVE_ERROR, udpStats.dwInErrors);
+        ConResPrintf(StdOut, IDS_UDP_DATAG_SEND, udpStats.dwOutDatagrams);
     }
     else
+    {
         DoFormatMessage(dwRetVal);
-
-    HeapFree(GetProcessHeap(), 0, pUdpStats);
+    }
 }
 
-VOID ShowEthernetStatistics()
+VOID ShowEthernetStatistics(VOID)
 {
     PMIB_IFTABLE pIfTable;
     DWORD dwSize = 0;
@@ -389,45 +376,48 @@ VOID ShowEthernetStatistics()
 
         if ((dwRetVal = GetIfTable(pIfTable, &dwSize, 0)) == NO_ERROR)
         {
-            _tprintf(_T("Interface Statistics\n\n"));
-            _tprintf(_T("                           Received            Sent\n\n"));
-            _tprintf(_T("%-20s %14lu %15lu\n"), _T("Bytes"),
+            ConResPuts(StdOut, IDS_ETHERNET_INTERFACE_STAT);
+            ConResPuts(StdOut, IDS_ETHERNET_THEADER);
+            ConResPrintf(StdOut, IDS_ETHERNET_BYTES,
                 pIfTable->table[0].dwInOctets, pIfTable->table[0].dwOutOctets);
-            _tprintf(_T("%-20s %14lu %15lu\n"), _T("Unicast packets"),
+            ConResPrintf(StdOut, IDS_ETHERNET_UNICAST_PACKET,
                 pIfTable->table[0].dwInUcastPkts, pIfTable->table[0].dwOutUcastPkts);
-            _tprintf(_T("%-20s %14lu %15lu\n"), _T("Non-unicast packets"),
+            ConResPrintf(StdOut, IDS_ETHERNET_NON_UNICAST_PACKET,
                 pIfTable->table[0].dwInNUcastPkts, pIfTable->table[0].dwOutNUcastPkts);
-            _tprintf(_T("%-20s %14lu %15lu\n"), _T("Discards"),
+            ConResPrintf(StdOut, IDS_ETHERNET_DISCARD,
                 pIfTable->table[0].dwInDiscards, pIfTable->table[0].dwOutDiscards);
-            _tprintf(_T("%-20s %14lu %15lu\n"), _T("Errors"),
+            ConResPrintf(StdOut, IDS_ETHERNET_ERROR,
                 pIfTable->table[0].dwInErrors, pIfTable->table[0].dwOutErrors);
-            _tprintf(_T("%-20s %14lu\n"), _T("Unknown Protocols"),
+            ConResPrintf(StdOut, IDS_ETHERNET_UNKNOWN,
                 pIfTable->table[0].dwInUnknownProtos);
         }
         else
+        {
             DoFormatMessage(dwRetVal);
+        }
     }
     HeapFree(GetProcessHeap(), 0, pIfTable);
 }
 
-VOID ShowTcpTable()
+BOOL ShowTcpTable(VOID)
 {
-    PMIB_TCPTABLE tcpTable;
+    PMIB_TCPTABLE_OWNER_PID tcpTable;
     DWORD error, dwSize;
     DWORD i;
     CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN];
     CHAR RemoteIp[HOSTNAMELEN], RemotePort[PORTNAMELEN];
     CHAR Host[ADDRESSLEN];
     CHAR Remote[ADDRESSLEN];
+    CHAR PID[64];
 
     /* Get the table of TCP endpoints */
-    dwSize = sizeof (MIB_TCPTABLE);
+    dwSize = sizeof (MIB_TCPTABLE_OWNER_PID);
     /* Should also work when we get new connections between 2 GetTcpTable()
      * calls: */
     do
     {
-        tcpTable = (PMIB_TCPTABLE) HeapAlloc(GetProcessHeap(), 0, dwSize);
-        error = GetTcpTable(tcpTable, &dwSize, TRUE);
+        tcpTable = (PMIB_TCPTABLE_OWNER_PID) HeapAlloc(GetProcessHeap(), 0, dwSize);
+        error = GetExtendedTcpTable(tcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0);
         if ( error != NO_ERROR )
             HeapFree(GetProcessHeap(), 0, tcpTable);
     }
@@ -435,9 +425,10 @@ VOID ShowTcpTable()
 
     if (error != NO_ERROR)
     {
-        printf("Failed to snapshot TCP endpoints.\n");
+        ConResPrintf(StdErr, IDS_ERROR_TCP_SNAPSHOT);
         DoFormatMessage(error);
-        exit(EXIT_FAILURE);
+        HeapFree(GetProcessHeap(), 0, tcpTable);
+        return FALSE;
     }
 
     /* Dump the TCP table */
@@ -450,46 +441,65 @@ VOID ShowTcpTable()
             || (tcpTable->table[i].dwState ==  MIB_TCP_STATE_TIME_WAIT))
         {
             /* I've split this up so it's easier to follow */
-            GetIpHostName(TRUE, tcpTable->table[i].dwLocalAddr, HostIp, HOSTNAMELEN);
-            GetPortName(tcpTable->table[i].dwLocalPort, "tcp", HostPort, PORTNAMELEN);
-            GetIpHostName(FALSE, tcpTable->table[i].dwRemoteAddr, RemoteIp, HOSTNAMELEN);
-            GetPortName(tcpTable->table[i].dwRemotePort, "tcp", RemotePort, PORTNAMELEN);
-
+            GetIpHostName(TRUE, tcpTable->table[i].dwLocalAddr, HostIp, sizeof(HostIp));
+            GetPortName(tcpTable->table[i].dwLocalPort, "tcp", HostPort, sizeof(HostPort));
             sprintf(Host, "%s:%s", HostIp, HostPort);
-            sprintf(Remote, "%s:%s", RemoteIp, RemotePort);
 
-            _tprintf(_T("  %-6s %-22s %-22s %s\n"), _T("TCP"),
-            Host, Remote, TcpState[tcpTable->table[i].dwState]);
+            if (tcpTable->table[i].dwState ==  MIB_TCP_STATE_LISTEN)
+            {
+                sprintf(Remote, "%s:0", HostIp);
+            }
+            else
+            {
+                GetIpHostName(FALSE, tcpTable->table[i].dwRemoteAddr, RemoteIp, sizeof(RemoteIp));
+                GetPortName(tcpTable->table[i].dwRemotePort, "tcp", RemotePort, sizeof(RemotePort));
+                sprintf(Remote, "%s:%s", RemoteIp, RemotePort);
+            }
+
+            if (bDoShowProcessId)
+            {
+                sprintf(PID, "%ld", tcpTable->table[i].dwOwningPid);
+            }
+            else
+            {
+                PID[0] = 0;
+            }
+
+            ConPrintf(StdOut, L"  %-6s %-22S %-22S %-11s %S\n", L"TCP",
+                      Host, Remote, TcpState[tcpTable->table[i].dwState], PID);
         }
     }
+
     HeapFree(GetProcessHeap(), 0, tcpTable);
+    return TRUE;
 }
 
-VOID ShowUdpTable()
+BOOL ShowUdpTable(VOID)
 {
-    PMIB_UDPTABLE udpTable;
+    PMIB_UDPTABLE_OWNER_PID udpTable;
     DWORD error, dwSize;
     DWORD i;
     CHAR HostIp[HOSTNAMELEN], HostPort[PORTNAMELEN];
     CHAR Host[ADDRESSLEN];
+    CHAR PID[64];
 
     /* Get the table of UDP endpoints */
     dwSize = 0;
-    error = GetUdpTable(NULL, &dwSize, TRUE);
+    error = GetExtendedUdpTable(NULL, &dwSize, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0);
     if (error != ERROR_INSUFFICIENT_BUFFER)
     {
-        printf("Failed to snapshot UDP endpoints.\n");
+        ConResPuts(StdErr, IDS_ERROR_UDP_ENDPOINT);
         DoFormatMessage(error);
-        exit(EXIT_FAILURE);
+        return FALSE;
     }
-    udpTable = (PMIB_UDPTABLE) HeapAlloc(GetProcessHeap(), 0, dwSize);
-    error = GetUdpTable(udpTable, &dwSize, TRUE);
+    udpTable = (PMIB_UDPTABLE_OWNER_PID) HeapAlloc(GetProcessHeap(), 0, dwSize);
+    error = GetExtendedUdpTable(udpTable, &dwSize, TRUE, AF_INET, UDP_TABLE_OWNER_PID, 0);
     if (error)
     {
-        printf("Failed to snapshot UDP endpoints table.\n");
+        ConResPuts(StdErr, IDS_ERROR_UDP_ENDPOINT_TABLE);
         DoFormatMessage(error);
         HeapFree(GetProcessHeap(), 0, udpTable);
-        exit(EXIT_FAILURE);
+        return FALSE;
     }
 
     /* Dump the UDP table */
@@ -497,15 +507,25 @@ VOID ShowUdpTable()
     {
 
         /* I've split this up so it's easier to follow */
-        GetIpHostName(TRUE, udpTable->table[i].dwLocalAddr, HostIp, HOSTNAMELEN);
-        GetPortName(udpTable->table[i].dwLocalPort, "tcp", HostPort, PORTNAMELEN);
+        GetIpHostName(TRUE, udpTable->table[i].dwLocalAddr, HostIp, sizeof(HostIp));
+        GetPortName(udpTable->table[i].dwLocalPort, "udp", HostPort, sizeof(HostPort));
 
         sprintf(Host, "%s:%s", HostIp, HostPort);
 
-        _tprintf(_T("  %-6s %-22s %-22s\n"), _T("UDP"), Host,  _T("*:*"));
+        if (bDoShowProcessId)
+        {
+            sprintf(PID, "%ld", udpTable->table[i].dwOwningPid);
+        }
+        else
+        {
+            PID[0] = 0;
+        }
+
+        ConPrintf(StdOut, L"  %-6s %-22S %-34s %S\n", L"UDP", Host, L"*:*", PID);
     }
 
     HeapFree(GetProcessHeap(), 0, udpTable);
+    return TRUE;
 }
 
 /*
@@ -514,7 +534,7 @@ VOID ShowUdpTable()
 PCHAR
 GetPortName(UINT Port, PCSTR Proto, CHAR Name[], INT NameLen)
 {
-    struct servent *pSrvent;
+    struct servent *pServent;
 
     if (bDoShowNumbers)
     {
@@ -522,8 +542,8 @@ GetPortName(UINT Port, PCSTR Proto, CHAR Name[], INT NameLen)
         return Name;
     }
     /* Try to translate to a name */
-    if ((pSrvent = getservbyport(Port, Proto)))
-        strcpy(Name, pSrvent->s_name );
+    if ((pServent = getservbyport(Port, Proto)))
+        strcpy(Name, pServent->s_name );
     else
         sprintf(Name, "%d", htons((WORD)Port));
     return Name;
@@ -533,7 +553,7 @@ GetPortName(UINT Port, PCSTR Proto, CHAR Name[], INT NameLen)
  * convert addresses into dotted decimal or hostname
  */
 PCHAR
-GetIpHostName(BOOL Local, UINT IpAddr, CHAR Name[], int NameLen)
+GetIpHostName(BOOL Local, UINT IpAddr, CHAR Name[], INT NameLen)
 {
 //  struct hostent *phostent;
     UINT nIpAddr;
@@ -549,7 +569,7 @@ GetIpHostName(BOOL Local, UINT IpAddr, CHAR Name[], int NameLen)
         return Name;
     }
 
-    Name[0] = _T('\0');
+    Name[0] = '\0';
 
     /* try to resolve the name */
     if (!IpAddr) {
@@ -568,7 +588,7 @@ GetIpHostName(BOOL Local, UINT IpAddr, CHAR Name[], int NameLen)
             if (gethostname(Name, NameLen) != 0)
                 DoFormatMessage(WSAGetLastError());
         } else {
-            _tcsncpy(Name, _T("localhost"), 10);
+            strncpy(Name, "localhost", 10);
         }
 //  } else if (phostent = gethostbyaddr((char*)&ipaddr, sizeof(nipaddr), PF_INET)) {
 //      strcpy(name, phostent->h_name);
@@ -582,57 +602,36 @@ GetIpHostName(BOOL Local, UINT IpAddr, CHAR Name[], int NameLen)
     return Name;
 }
 
-VOID Usage()
-{
-    _tprintf(_T("\nDisplays current TCP/IP protocol statistics and network connections.\n\n"
-    "NETSTAT [-a] [-e] [-n] [-s] [-p proto] [-r] [interval]\n\n"
-    "  -a            Displays all connections and listening ports.\n"
-    "  -e            Displays Ethernet statistics. May be combined with -s\n"
-    "                option\n"
-    "  -n            Displays address and port numbers in numeric form.\n"
-    "  -p proto      Shows connections for protocol 'proto' TCP or UDP.\n"
-    "                If used with the -s option to display\n"
-    "                per-protocol statistics, 'proto' may be TCP, UDP, or IP.\n"
-    "  -r            Displays the current routing table.\n"
-    "  -s            Displays per-protocol statistics. By default, Statistics are\n"
-    "                shown for IP, ICMP, TCP and UDP;\n"
-    "                the -p option may be used to specify a subset of the default.\n"
-    "  interval      Redisplays selected statistics every 'interval' seconds.\n"
-    "                Press CTRL+C to stop redisplaying. By default netstat will\n"
-    "                print the current information only once.\n"));
-}
-
 /*
  *
  * Parse command line parameters and set any options
  * Run display output, looping over set intervals if a number is given
  *
  */
-int main(int argc, char *argv[])
+int wmain(int argc, wchar_t *argv[])
 {
+    BOOL Success;
     WSADATA wsaData;
 
+    /* Initialize the Console Standard Streams */
+    ConInitStdStreams();
+
+    if (!ParseCmdline(argc, argv))
+        return EXIT_FAILURE;
+
     if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
     {
-        _tprintf(_T("WSAStartup() failed : %d\n"), WSAGetLastError());
-        return -1;
+        ConResPrintf(StdErr, IDS_ERROR_WSA_START, WSAGetLastError());
+        return EXIT_FAILURE;
     }
 
-    if (ParseCmdline(argc, argv))
-        return -1;
-
-    if (bLoopOutput)
+    Success = DisplayOutput();
+    while (bLoopOutput && Success)
     {
-        while (1)
-        {
-            if (DisplayOutput())
-                return -1;
-            Sleep(Interval*1000);
-        }
+        Sleep(Interval*1000);
+        Success = DisplayOutput();
     }
 
-    if (DisplayOutput())
-        return -1;
-    else
-        return 0;
+    WSACleanup();
+    return (Success ? EXIT_SUCCESS : EXIT_FAILURE);
 }