[SYSTEMINFO]
[reactos.git] / rosapps / applications / sysutils / systeminfo / systeminfo.c
index 3f8d354..12818ec 100644 (file)
 
 #include <wchar.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
+#include <stdarg.h>
 #include <windows.h>
 #include <time.h>
 #include <locale.h>
 #include <lm.h>
+#include <shlwapi.h>
+#include <iphlpapi.h>
+#include <winsock2.h>
 
 #include "resource.h"
 
-#define BUFFER_SIZE 32767
+#define BUFFER_SIZE 1024
 
-/* Load from resource and convert to OEM */
+/* Load string from registry */
 static
-BOOL
-GetOemStrings(UINT rcID, LPWSTR OutMsg)
-{
-    if (LoadStringW(GetModuleHandle(NULL), rcID, OutMsg, BUFFER_SIZE))
-        return TRUE;
-
-    return FALSE;
-}
-
-/* Load data from registry */
-static
-BOOL
-RegGetSZ(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, LPWSTR Buf)
+unsigned
+RegGetSZ(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, LPWSTR lpBuf, DWORD cchBuf)
 {
-    DWORD dwBytes = BUFFER_SIZE*sizeof(WCHAR), dwType;
-    BOOL bRet = TRUE;
+    DWORD dwBytes = cchBuf*sizeof(WCHAR), dwType = 0;
+    unsigned cChars;
 
-    /* If SubKy is specified open it */
+    /* If SubKey is specified open it */
     if (lpSubKey && RegOpenKeyExW(hKey,
                                   lpSubKey,
                                   0,
                                   KEY_QUERY_VALUE,
                                   &hKey) != ERROR_SUCCESS)
     {
-        //wprintf("Warning! Cannot open %s. Last error: %lu.\n", lpSubKey, GetLastError());
-        return FALSE;
+        wprintf(L"Warning! Cannot open %s. Last error: %lu.\n", lpSubKey, GetLastError());
+        return 0;
     }
 
+    /* Query registry value and check its type */
     if (RegQueryValueExW(hKey,
                          lpValueName,
                          NULL,
                          &dwType,
-                         (LPBYTE)Buf,
+                         (LPBYTE)lpBuf,
                          &dwBytes) != ERROR_SUCCESS || (dwType != REG_SZ && dwType != REG_MULTI_SZ))
     {
-        //wprintf("Warning! Cannot query %s. Last error: %lu, type: %lu.\n", lpValueName, GetLastError(), dwType);
+        wprintf(L"Warning! Cannot query %s. Last error: %lu, type: %lu.\n", lpValueName, GetLastError(), dwType);
         dwBytes = 0;
-        bRet = FALSE;
+    }
+    else
+    {
+        wcscpy(lpBuf, L"N/A");
+        dwBytes = 6;
     }
 
     /* Close key if we opened it */
     if (lpSubKey)
         RegCloseKey(hKey);
 
+    cChars = dwBytes/sizeof(WCHAR);
+
     /* NULL-terminate string */
-    Buf[min(BUFFER_SIZE-1, dwBytes/sizeof(WCHAR))] = L'\0';
+    lpBuf[min(cchBuf-1, cChars)] = L'\0';
+    
+    /* Don't count NULL characters */
+    while(cChars && !lpBuf[cChars-1])
+        --cChars;
 
-    return bRet;
+    return cChars;
 }
 
+/* Load DWORD from registry */
 static
 BOOL
 RegGetDWORD(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, LPDWORD lpData)
@@ -89,16 +92,18 @@ RegGetDWORD(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, LPDWORD lpData)
     DWORD dwBytes = sizeof(*lpData), dwType;
     BOOL bRet = TRUE;
 
-    /* If SubKy is specified open it */
+    /* If SubKey is specified open it */
     if (lpSubKey && RegOpenKeyExW(hKey,
                                  lpSubKey,
                                  0,
                                  KEY_QUERY_VALUE,
                                  &hKey) != ERROR_SUCCESS)
     {
+        wprintf(L"Warning! Cannot open %s. Last error: %lu.\n", lpSubKey, GetLastError());
         return FALSE;
     }
 
+    /* Query registry value and check its type */
     if (RegQueryValueExW(hKey,
                          lpValueName,
                          NULL,
@@ -106,7 +111,7 @@ RegGetDWORD(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, LPDWORD lpData)
                          (LPBYTE)lpData,
                          &dwBytes) != ERROR_SUCCESS || dwType != REG_DWORD)
     {
-        //wprintf("Warning! Cannot query %s. Last err: %lu, type: %lu\n", lpValueName, GetLastError(), dwType);
+        wprintf(L"Warning! Cannot query %s. Last err: %lu, type: %lu\n", lpValueName, GetLastError(), dwType);
         *lpData = 0;
         bRet = FALSE;
     }
@@ -118,12 +123,14 @@ RegGetDWORD(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, LPDWORD lpData)
     return bRet;
 }
 
+/* Format bytes */
 static
-void
-FormatBytes(LPWSTR Buf, unsigned cBytes)
+VOID
+FormatBytes(LPWSTR lpBuf, unsigned cBytes)
 {
     WCHAR szMB[32];
     NUMBERFMTW fmt;
+    unsigned i;
 
     _itow(cBytes / (1024*1024), szMB, 10);
 
@@ -134,15 +141,18 @@ FormatBytes(LPWSTR Buf, unsigned cBytes)
     fmt.lpThousandSep = L" ";
     fmt.NegativeOrder = 0;
 
-    if(!GetNumberFormatW(LOCALE_SYSTEM_DEFAULT, 0, szMB, &fmt, Buf, BUFFER_SIZE))
-        wprintf(L"Error! GetNumberFormat failed.\n");
+    i = GetNumberFormatW(LOCALE_SYSTEM_DEFAULT, 0, szMB, &fmt, lpBuf, BUFFER_SIZE - 3);
+    if (i)
+        --i; /* don't count NULL character */
+    wcscpy(lpBuf + i, L" MB");
 }
 
+/* Format date and time */
 static
-void
+VOID
 FormatDateTime(time_t Time, LPWSTR lpBuf)
 {
-    unsigned cchBuf = BUFFER_SIZE, i;
+    unsigned i;
     SYSTEMTIME SysTime;
     const struct tm *lpTm;
 
@@ -156,42 +166,76 @@ FormatDateTime(time_t Time, LPWSTR lpBuf)
     SysTime.wSecond = (WORD)lpTm->tm_sec;
     SysTime.wMilliseconds = 0;
 
-    /* Time first */
-    i = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, 0, &SysTime, NULL, lpBuf, cchBuf);
+    /* Copy date first */
+    i = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, 0, &SysTime, NULL, lpBuf, BUFFER_SIZE - 2);
     if (i)
         --i; /* don't count NULL character */
 
-    /* Time now */
+    /* Copy time now */
     i += swprintf(lpBuf + i, L", ");
-    GetTimeFormatW(LOCALE_SYSTEM_DEFAULT, 0, &SysTime, NULL, lpBuf + i, cchBuf - i);
+    i += 2;
+    GetTimeFormatW(LOCALE_SYSTEM_DEFAULT, 0, &SysTime, NULL, lpBuf + i, BUFFER_SIZE - i);
 }
 
 /* Show usage */
 static
 VOID
 Usage(VOID)
+{
+    WCHAR Buf[4096];
+    if (LoadStringW(GetModuleHandle(NULL), IDS_USAGE, Buf, 4096))
+        wprintf(L"%s", Buf);
+}
+
+static
+VOID
+PrintRow(UINT nTitleID, BOOL bIndent, LPWSTR lpFormat, ...)
 {
     WCHAR Buf[BUFFER_SIZE];
+    va_list Args;
+    unsigned c;
 
-    if(GetOemStrings(IDS_USAGE, Buf))
-        wprintf(L"%s", Buf);
+    if (nTitleID)
+    {
+        c = LoadStringW(GetModuleHandle(NULL), nTitleID, Buf, BUFFER_SIZE - 2);
+        if (!c)
+            return;
+
+        wcscpy(Buf + c, L": ");
+    } else
+        Buf[0] = L'\0';
+
+    if (!bIndent)
+        wprintf(L"%-32s", Buf);
+    else if (Buf[0])
+        wprintf(L"%38s%-16s", L"", Buf);
+    else
+        wprintf(L"%38s", L"");
+
+    va_start(Args, lpFormat);
+    vwprintf(lpFormat, Args);
+    va_end(Args);
+
+    wprintf(L"\n");
 }
 
 /* Print all system information */
 VOID
 AllSysInfo(VOID)
 {
-    DWORD dwCharCount = BUFFER_SIZE, dwTimestamp;
+    DWORD dwCharCount = BUFFER_SIZE, dwTimestamp, dwResult;
     OSVERSIONINFOW VersionInfo;
     SYSTEM_INFO SysInfo;
-    WCHAR Buf[BUFFER_SIZE], Tmp[BUFFER_SIZE], Msg[BUFFER_SIZE], szSystemDir[MAX_PATH];
+    WCHAR Buf[BUFFER_SIZE], Tmp[BUFFER_SIZE], szSystemDir[MAX_PATH];
     const WCHAR *lpcszSysType;
-    LPWSTR lpNetBuffer;
+    LPWSTR lpBuffer;
     NETSETUP_JOIN_STATUS NetJoinStatus;
     MEMORYSTATUS MemoryStatus;
-    unsigned int cSeconds;
+    unsigned int cSeconds, i, j;
     TIME_ZONE_INFORMATION TimeZoneInfo;
     HKEY hKey;
+    PIP_ADAPTER_ADDRESSES pAdapters;
+    ULONG cbAdapters;
 
     if (!GetSystemDirectoryW(szSystemDir, sizeof(szSystemDir)/sizeof(szSystemDir[0])))
     {
@@ -205,8 +249,8 @@ AllSysInfo(VOID)
     dwCharCount = BUFFER_SIZE;
     if (!GetComputerNameW(Buf, &dwCharCount))
         wprintf(L"Error! GetComputerName failed.\n");
-    else if (GetOemStrings(IDS_HOST_NAME, Msg))
-        wprintf(Msg, Buf);
+    else
+        PrintRow(IDS_HOST_NAME, FALSE, L"%s", Buf);
 
     // open CurrentVersion key
     if(RegOpenKeyExW(HKEY_LOCAL_MACHINE,
@@ -220,60 +264,60 @@ AllSysInfo(VOID)
     }
 
     //getting OS Name
-    RegGetSZ(hKey, NULL, L"ProductName", Buf);
-    if (GetOemStrings(IDS_OS_NAME, Msg))
-        wprintf(Msg, Buf);
+    RegGetSZ(hKey, NULL, L"ProductName", Buf, BUFFER_SIZE);
+    PrintRow(IDS_OS_NAME, FALSE, L"%s", Buf);
 
     //getting OS Version
     ZeroMemory(&VersionInfo, sizeof(VersionInfo));
     VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
     GetVersionExW(&VersionInfo);
 
-    if (GetOemStrings(IDS_OS_VERSION, Msg))
-        wprintf(Msg,
-               (unsigned)VersionInfo.dwMajorVersion,
-               (unsigned)VersionInfo.dwMinorVersion,
-               (unsigned)VersionInfo.dwBuildNumber,
-               VersionInfo.szCSDVersion,
-               (unsigned)VersionInfo.dwBuildNumber);
+    if (!LoadStringW(GetModuleHandle(NULL), IDS_BUILD, Tmp, BUFFER_SIZE))
+        Tmp[0] = L'\0';
+    PrintRow(IDS_OS_VERSION,
+             FALSE,
+             L"%lu.%lu.%lu %s %s %lu",
+             VersionInfo.dwMajorVersion,
+             VersionInfo.dwMinorVersion,
+             VersionInfo.dwBuildNumber,
+             VersionInfo.szCSDVersion,
+             Tmp,
+             VersionInfo.dwBuildNumber);
 
     //getting OS Manufacturer
 
     //getting OS Configuration
 
     //getting OS Build Type
-    RegGetSZ(hKey, NULL, L"CurrentType", Buf);
-    if (GetOemStrings(IDS_OS_BUILD_TYPE, Msg))
-        wprintf(Msg, Buf);
+    RegGetSZ(hKey, NULL, L"CurrentType", Buf, BUFFER_SIZE);
+    PrintRow(IDS_OS_BUILD_TYPE, FALSE, L"%s", Buf);
 
     //getting Registered Owner
-    RegGetSZ(hKey, NULL, L"RegisteredOwner", Buf);
-    if (GetOemStrings(IDS_REG_OWNER, Msg))
-        wprintf(Msg, Buf);
+    RegGetSZ(hKey, NULL, L"RegisteredOwner", Buf, BUFFER_SIZE);
+    PrintRow(IDS_REG_OWNER, FALSE, L"%s", Buf);
 
     //getting Registered Organization
-    RegGetSZ(hKey, NULL, L"RegisteredOrganization", Buf);
-    if (GetOemStrings(IDS_REG_ORG, Msg))
-        wprintf(Msg, Buf);
+    RegGetSZ(hKey, NULL, L"RegisteredOrganization", Buf, BUFFER_SIZE);
+    PrintRow(IDS_REG_ORG, FALSE, L"%s", Buf);
 
     //getting Product ID
-    RegGetSZ(hKey, NULL, L"ProductId", Buf);
-    if (GetOemStrings(IDS_PRODUCT_ID, Msg))
-        wprintf(Msg, Buf);
+    RegGetSZ(hKey, NULL, L"ProductId", Buf, BUFFER_SIZE);
+    PrintRow(IDS_PRODUCT_ID, FALSE, L"%s", Buf);
 
     //getting Install Date
     RegGetDWORD(hKey, NULL, L"InstallDate", &dwTimestamp);
     FormatDateTime((time_t)dwTimestamp, Buf);
-    if (GetOemStrings(IDS_INST_DATE, Msg))
-        wprintf(Msg, Buf);
+    PrintRow(IDS_INST_DATE, FALSE, L"%s", Buf);
 
     // close Current Version key now
     RegCloseKey(hKey);
 
     //getting System Up Time
     cSeconds = GetTickCount() / 1000;
-    if (GetOemStrings(IDS_UP_TIME, Msg))
-        wprintf(Msg, cSeconds / (60*60*24), (cSeconds / (60*60)) % 24, (cSeconds / 60) % 60, cSeconds % 60);
+    if (!LoadStringW(GetModuleHandle(NULL), IDS_UP_TIME_FORMAT, Tmp, BUFFER_SIZE))
+        Tmp[0] = L'\0';
+    swprintf(Buf, Tmp, cSeconds / (60*60*24), (cSeconds / (60*60)) % 24, (cSeconds / 60) % 60, cSeconds % 60);
+    PrintRow(IDS_UP_TIME, FALSE, L"%s", Buf);
 
     //getting System Manufacturer; HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OEMInformation\Manufacturer for Win >= 6.0
     swprintf(Tmp, L"%s\\oeminfo.ini", szSystemDir);
@@ -283,8 +327,7 @@ AllSysInfo(VOID)
                              Buf,
                              sizeof(Buf)/sizeof(Buf[0]),
                              Tmp);
-    if (GetOemStrings(IDS_SYS_MANUFACTURER, Msg))
-        wprintf(Msg, Buf);
+    PrintRow(IDS_SYS_MANUFACTURER, FALSE, L"%s", Buf);
 
     //getting System Model; HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OEMInformation\Model for Win >= 6.0
     GetPrivateProfileStringW(L"General",
@@ -293,8 +336,7 @@ AllSysInfo(VOID)
                              Buf,
                              sizeof(Buf)/sizeof(Buf[0]),
                              Tmp);
-    if (GetOemStrings(IDS_SYS_MODEL, Msg))
-        wprintf(Msg, Buf);
+    PrintRow(IDS_SYS_MODEL, FALSE, L"%s", Buf);
 
     //getting System type
     switch (SysInfo.wProcessorArchitecture)
@@ -312,90 +354,94 @@ AllSysInfo(VOID)
             lpcszSysType = L"Unknown";
             break;
     }
-    if (GetOemStrings(IDS_SYS_TYPE, Msg))
-        wprintf(Msg, lpcszSysType);
+    PrintRow(IDS_SYS_TYPE, FALSE, L"%s", lpcszSysType);
 
     //getting Processor(s)
-    if (GetOemStrings(IDS_PROCESSORS, Msg))
+    if (!LoadStringW(GetModuleHandle(NULL), IDS_PROCESSORS_FORMAT, Tmp, BUFFER_SIZE))
+        Tmp[0] = L'\0';
+    swprintf(Buf, Tmp, (unsigned)SysInfo.dwNumberOfProcessors);
+    PrintRow(IDS_PROCESSORS, FALSE, L"%s", Buf);
+    for(i = 0; i < (unsigned int)SysInfo.dwNumberOfProcessors; i++)
     {
-        unsigned int i;
-        wprintf(Msg, (unsigned int)SysInfo.dwNumberOfProcessors);
-        for(i = 0; i < (unsigned int)SysInfo.dwNumberOfProcessors; i++)
-        {
-            swprintf(Tmp, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%u", i);
-
-            RegGetSZ(HKEY_LOCAL_MACHINE, Tmp, L"Identifier", Buf);
-            wprintf(L"                       [%02u]: %s", i+1, Buf);
-
-            RegGetSZ(HKEY_LOCAL_MACHINE, Tmp, L"VendorIdentifier", Buf);
-            wprintf(L" %s\n", Buf);
-        }
+        swprintf(Tmp, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%u", i);
+        j = swprintf(Buf, L"[%02u]: ", i + 1);
+        
+        j += RegGetSZ(HKEY_LOCAL_MACHINE, Tmp, L"Identifier", Buf + j, BUFFER_SIZE - j);
+        if(j + 1 < BUFFER_SIZE)
+            Buf[j++] = L' ';
+        RegGetSZ(HKEY_LOCAL_MACHINE, Tmp, L"VendorIdentifier", Buf + j, BUFFER_SIZE - j);
+        
+        PrintRow(0, FALSE, L"%s", Buf);
     }
 
     //getting BIOS Version
     RegGetSZ(HKEY_LOCAL_MACHINE,
              L"HARDWARE\\DESCRIPTION\\System",
              L"SystemBiosVersion",
-             Buf);
-    if (GetOemStrings(IDS_BIOS_VERSION, Msg))
-        wprintf(Msg, Buf);
+             Buf,
+             BUFFER_SIZE);
+    PrintRow(IDS_BIOS_VERSION, FALSE, L"%s", Buf);
 
     //gettings BIOS date
     RegGetSZ(HKEY_LOCAL_MACHINE,
              L"HARDWARE\\DESCRIPTION\\System",
              L"SystemBiosDate",
-             Buf);
-    if (GetOemStrings(IDS_BIOS_DATE, Msg))
-        wprintf(Msg, Buf);
+             Buf,
+             BUFFER_SIZE);
+    PrintRow(IDS_BIOS_DATE, FALSE, L"%s", Buf);
 
     //getting ReactOS Directory
     if (!GetWindowsDirectoryW(Buf, BUFFER_SIZE))
         wprintf(L"Error! GetWindowsDirectory failed.");
-    else if (GetOemStrings(IDS_ROS_DIR, Msg))
-        wprintf(Msg, Buf);
+    else
+        PrintRow(IDS_ROS_DIR, FALSE, L"%s", Buf);
 
     //getting System Directory
-    if (GetOemStrings(IDS_SYS_DIR, Msg))
-        wprintf(Msg, szSystemDir);
+    PrintRow(IDS_SYS_DIR, 0, L"%s", szSystemDir);
 
     //getting Boot Device
     RegGetSZ(HKEY_LOCAL_MACHINE,
              L"SYSTEM\\Setup",
              L"SystemPartition",
-             Buf);
-    if (GetOemStrings(IDS_BOOT_DEV, Msg))
-        wprintf(Msg, Buf);
+             Buf,
+             BUFFER_SIZE);
+    PrintRow(IDS_BOOT_DEV, FALSE, L"%s", Buf);
 
     //getting System Locale
-    if (RegGetSZ(HKEY_CURRENT_USER,
-                 L"Control Panel\\International",
-                 L"Locale",
-                 Tmp))
+    if (GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, LOCALE_ILANGUAGE, Tmp, BUFFER_SIZE))
         if (RegGetSZ(HKEY_CLASSES_ROOT,
                      L"MIME\\Database\\Rfc1766",
                      Tmp,
-                     Buf))
-            if (GetOemStrings(IDS_SYS_LOCALE, Msg))
-                wprintf(Msg, Buf);
+                     Buf,
+                     BUFFER_SIZE))
+        {
+            /* get rid of @filename,resource */
+            lpBuffer = wcschr(Buf, L';');
+            if (lpBuffer)
+                SHLoadIndirectString(lpBuffer+1, lpBuffer+1, BUFFER_SIZE - (lpBuffer-Buf) - 1, NULL);
+
+            PrintRow(IDS_SYS_LOCALE, FALSE, L"%s", Buf);
+        }
 
     //getting Input Locale
     if (RegGetSZ(HKEY_CURRENT_USER,
                  L"Keyboard Layout\\Preload",
                  L"1",
-                 Buf))
-    {
-        int i, j;
-
-        for(j = 0, i = 4; i <= 8; j++, i++)
-            Tmp[j] = Buf[i];
-
+                 Tmp,
+                 BUFFER_SIZE) && wcslen(Tmp) > 4)
         if (RegGetSZ(HKEY_CLASSES_ROOT,
                      L"MIME\\Database\\Rfc1766",
-                     Tmp,
-                     Buf))
-            if (GetOemStrings(IDS_INPUT_LOCALE, Msg))
-                wprintf(Msg, Buf);
-    }
+                     Tmp + 4,
+                     Buf,
+                     BUFFER_SIZE))
+        {
+            /* get rid of @filename,resource */
+            lpBuffer = wcschr(Buf, L';');
+            if (lpBuffer)
+                SHLoadIndirectString(lpBuffer+1, lpBuffer+1, BUFFER_SIZE - (lpBuffer-Buf) - 1, NULL);
+
+            PrintRow(IDS_INPUT_LOCALE, FALSE, L"%s", Buf);
+        }
 
     //getting Time Zone
     GetTimeZoneInformation(&TimeZoneInfo);
@@ -410,17 +456,16 @@ AllSysInfo(VOID)
         unsigned i;
 
         /* Find current timezone */
-        dwCharCount = 256; // Windows seems to have a bug - it doesnt accept BUFFER_SIZE here
+        dwCharCount = BUFFER_SIZE;
         for(i = 0; RegEnumKeyExW(hKey, i, Tmp, &dwCharCount, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; ++i, dwCharCount = 255)
         {
-            RegGetSZ(hKey, Tmp, L"Std", Buf);
+            RegGetSZ(hKey, Tmp, L"Std", Buf, BUFFER_SIZE);
 
-            if(!wcscmp(Buf, TimeZoneInfo.StandardName))
+            if (!wcscmp(Buf, TimeZoneInfo.StandardName))
             {
-                RegGetSZ(hKey, Tmp, L"Display", Buf);
+                RegGetSZ(hKey, Tmp, L"Display", Buf, BUFFER_SIZE);
 
-                if (GetOemStrings(IDS_TIME_ZONE, Msg))
-                    wprintf(Msg, Buf);
+                PrintRow(IDS_TIME_ZONE, FALSE, L"%s", Buf);
 
                 break;
             }
@@ -431,78 +476,151 @@ AllSysInfo(VOID)
     //getting Total Physical Memory
     GlobalMemoryStatus(&MemoryStatus);
     FormatBytes(Buf, MemoryStatus.dwTotalPhys);
-    if (GetOemStrings(IDS_TOTAL_PHYS_MEM, Msg))
-        wprintf(Msg, Buf);
+    PrintRow(IDS_TOTAL_PHYS_MEM, FALSE, L"%s", Buf);
 
     //getting Available Physical Memory
     FormatBytes(Buf, MemoryStatus.dwAvailPhys);
-    if (GetOemStrings(IDS_AVAIL_PHISICAL_MEM,Msg))
-        wprintf(Msg, Buf);
+    PrintRow(IDS_AVAIL_PHISICAL_MEM, FALSE, L"%s", Buf);
 
     //getting Virtual Memory: Max Size
     FormatBytes(Buf, MemoryStatus.dwTotalVirtual);
-    if (GetOemStrings(IDS_VIRT_MEM_MAX, Msg))
-        wprintf(Msg, Buf);
+    PrintRow(IDS_VIRT_MEM_MAX, FALSE, L"%s", Buf);
 
     //getting Virtual Memory: Available
     FormatBytes(Buf, MemoryStatus.dwAvailVirtual);
-    if (GetOemStrings(IDS_VIRT_MEM_AVAIL, Msg))
-        wprintf(Msg, Buf);
+    PrintRow(IDS_VIRT_MEM_AVAIL, FALSE, L"%s", Buf);
 
     //getting Virtual Memory: In Use
     FormatBytes(Buf, MemoryStatus.dwTotalVirtual-MemoryStatus.dwAvailVirtual);
-    if (GetOemStrings(IDS_VIRT_MEM_INUSE, Msg))
-        wprintf(Msg, Buf);
+    PrintRow(IDS_VIRT_MEM_INUSE, FALSE, L"%s", Buf);
 
     //getting Page File Location(s)
     if (RegGetSZ(HKEY_LOCAL_MACHINE,
                  L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management",
                  L"PagingFiles",
-                 Buf))
+                 Buf,
+                 BUFFER_SIZE))
     {
         int i;
 
-        for(i = 0; i < strlen((char*)Buf); i++)
+        for(i = 0; Buf[i]; i++)
         {
-            if (Buf[i] == TEXT(' '))
+            if (Buf[i] == L' ')
             {
-                Buf[i] = TEXT('\0');
+                Buf[i] = L'\0';
                 break;
             }
         }
 
-        if(GetOemStrings(IDS_PAGEFILE_LOC, Msg))
-            wprintf(Msg, Buf);
+        PrintRow(IDS_PAGEFILE_LOC, FALSE, L"%s", Buf);
     }
 
     //getting Domain
-    if (NetGetJoinInformation (NULL, &lpNetBuffer, &NetJoinStatus) == NERR_Success)
+    if (NetGetJoinInformation (NULL, &lpBuffer, &NetJoinStatus) == NERR_Success)
     {
-        if(GetOemStrings(IDS_DOMAIN, Msg))
-            wprintf(Msg, lpNetBuffer);
+        if (NetJoinStatus == NetSetupWorkgroupName || NetJoinStatus == NetSetupDomainName)
+            PrintRow(IDS_DOMAIN, FALSE, L"%s", lpBuffer);
 
-        NetApiBufferFree(lpNetBuffer);
+        NetApiBufferFree(lpBuffer);
     }
 
     //getting Logon Server
 
     //getting NetWork Card(s)
-    if(GetOemStrings(IDS_NETWORK_CARDS, Msg))
+    cbAdapters = 4096;
+    pAdapters = malloc(cbAdapters);
+    while((dwResult = GetAdaptersAddresses(AF_UNSPEC, 0x0002, NULL, pAdapters, &cbAdapters)) == ERROR_BUFFER_OVERFLOW)
+    {
+        cbAdapters += 4096;
+        pAdapters = (PIP_ADAPTER_ADDRESSES)realloc(pAdapters, cbAdapters);
+    }
+
+    if (dwResult == ERROR_SUCCESS)
     {
+        PIP_ADAPTER_ADDRESSES pCurrentAdapter = pAdapters;
+        unsigned cAdapters = 0;
 
+        /* Count adapters */
+        for(i = 0; pCurrentAdapter; ++i)
+        {
+            if (pCurrentAdapter->IfType != 24 && pCurrentAdapter->IfType != 131)
+                ++cAdapters;
+            pCurrentAdapter = pCurrentAdapter->Next;
+        }
+            
+
+        /* Print adapters count */
+        if (!LoadStringW(GetModuleHandle(NULL), IDS_NETWORK_CARDS_FORMAT, Tmp, BUFFER_SIZE))
+            Tmp[0] = L'\0';
+        swprintf(Buf, Tmp, cAdapters);
+        PrintRow(IDS_NETWORK_CARDS, FALSE, L"%s", Buf);
+
+        /* Show information about each adapter */
+        pCurrentAdapter = pAdapters;
+        for(i = 0; pCurrentAdapter; ++i)
+        {
+            if (pCurrentAdapter->IfType != 24 && pCurrentAdapter->IfType != 131)//IF_TYPE_SOFTWARE_LOOPBACK)
+            {
+                PIP_ADAPTER_UNICAST_ADDRESS pAddress;
+
+                PrintRow(0, FALSE, L"[%02u]: %s", i + 1, pCurrentAdapter->Description);
+                PrintRow(IDS_CONNECTION_NAME, TRUE, L"%s", pCurrentAdapter->FriendlyName);
+                if (!(pCurrentAdapter->Flags & 0x0004))
+                {
+                    if (!LoadStringW(GetModuleHandle(NULL), IDS_NO, Buf, BUFFER_SIZE))
+                        Buf[0] = L'\0';
+                    PrintRow(IDS_DHCP_ENABLED, TRUE, Buf);
+                }
+                if (pCurrentAdapter->OperStatus == IfOperStatusDown)
+                {
+                    if (!LoadStringW(GetModuleHandle(NULL), IDS_MEDIA_DISCONNECTED, Buf, BUFFER_SIZE))
+                        Buf[0] = L'\0';
+                    PrintRow(IDS_STATUS, TRUE, Buf);
+                }
+                else
+                {
+                    if (!LoadStringW(GetModuleHandle(NULL), IDS_IP_ADDRESSES, Buf, BUFFER_SIZE))
+                        Buf[0] = L'\0';
+                    PrintRow(0, TRUE, Buf);
+                    pAddress = pCurrentAdapter->FirstUnicastAddress;
+                    for (j = 0; pAddress; ++j)
+                    {
+                        dwCharCount = BUFFER_SIZE;
+                        WSAAddressToStringW(pAddress->Address.lpSockaddr, pAddress->Address.iSockaddrLength, NULL, Buf, &dwCharCount);
+                        PrintRow(0, TRUE, L"[%02u]: %s", j + 1, Buf);
+                        pAddress = pAddress->Next;
+                    }
+                }
+            }
+            pCurrentAdapter = pCurrentAdapter->Next;
+        }
     }
+    free(pAdapters);
 }
 
 /* Main program */
 int
 main(int argc, char *argv[])
 {
+    WSADATA WsaData;
+    int i;
+
     setlocale(LC_ALL, "");
 
-    if (argc > 1 && (!strcmp(argv[1], "/?") || !strcmp(argv[1], "-?")))
+    WSAStartup(MAKEWORD(2, 2), &WsaData);
+
+    for (i = 1; i < argc; ++i)
     {
-        Usage();
-        return 0;
+        if (!strcmp(argv[i], "/?") || !strcmp(argv[i], "-?"))
+        {
+            Usage();
+            return 0;
+        }
+        else
+        {
+            printf("Unsupported argument: %s\n", argv[i]);
+            return -1;
+        }
     }
 
     AllSysInfo();