[SYSTEMINFO]
[reactos.git] / rosapps / applications / sysutils / systeminfo / systeminfo.c
index 1e911de..12818ec 100644 (file)
 /* Copyright (C) 2007, Dmitry Chapyshev <lentind@yandex.ru> */
 /* Copyright (C) 2011, Rafal Harabien <rafalh1992@o2.pl> */
 
+#include <wchar.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
+#include <stdarg.h>
 #include <windows.h>
-#include <tchar.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, LPTSTR OutMsg)
+unsigned
+RegGetSZ(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, LPWSTR lpBuf, DWORD cchBuf)
 {
-    TCHAR Msg[BUFFER_SIZE];
-    
-    if (LoadString(GetModuleHandle(NULL), rcID, (LPTSTR)Msg, BUFFER_SIZE))
+    DWORD dwBytes = cchBuf*sizeof(WCHAR), dwType = 0;
+    unsigned cChars;
+
+    /* If SubKey is specified open it */
+    if (lpSubKey && RegOpenKeyExW(hKey,
+                                  lpSubKey,
+                                  0,
+                                  KEY_QUERY_VALUE,
+                                  &hKey) != ERROR_SUCCESS)
     {
-        CharToOem(Msg, OutMsg);
-        return TRUE;
+        wprintf(L"Warning! Cannot open %s. Last error: %lu.\n", lpSubKey, GetLastError());
+        return 0;
     }
-    return FALSE;
-}
 
-/* Load data from registry */
-static
-BOOL
-RegGetSZ(HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPTSTR Buf)
-{
-    DWORD dwBytes = BUFFER_SIZE*sizeof(TCHAR), dwType;
-    BOOL bRet = TRUE;
-    
-    /* If SubKy is specified open it */
-    if (lpSubKey && RegOpenKeyEx(hKey,
-                                 lpSubKey,
-                                 0,
-                                 KEY_QUERY_VALUE,
-                                 &hKey) != ERROR_SUCCESS)
+    /* Query registry value and check its type */
+    if (RegQueryValueExW(hKey,
+                         lpValueName,
+                         NULL,
+                         &dwType,
+                         (LPBYTE)lpBuf,
+                         &dwBytes) != ERROR_SUCCESS || (dwType != REG_SZ && dwType != REG_MULTI_SZ))
     {
-        //_tprintf("Warning! Cannot open %s. Last error: %lu.\n", lpSubKey, GetLastError());
-        return FALSE;
+        wprintf(L"Warning! Cannot query %s. Last error: %lu, type: %lu.\n", lpValueName, GetLastError(), dwType);
+        dwBytes = 0;
     }
-
-    if (RegQueryValueEx(hKey,
-                        lpValueName,
-                        NULL,
-                        &dwType,
-                        (LPBYTE)Buf,
-                        &dwBytes) != ERROR_SUCCESS || (dwType != REG_SZ && dwType != REG_MULTI_SZ))
+    else
     {
-        //_tprintf("Warning! Cannot query %s. Last error: %lu, type: %lu.\n", lpValueName, GetLastError(), dwType);
-        dwBytes = 0;
-        bRet = FALSE;
+        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(TCHAR))] = TEXT('\0');
+    lpBuf[min(cchBuf-1, cChars)] = L'\0';
     
-    return bRet;
+    /* Don't count NULL characters */
+    while(cChars && !lpBuf[cChars-1])
+        --cChars;
+
+    return cChars;
 }
 
+/* Load DWORD from registry */
 static
 BOOL
-RegGetDWORD(HKEY hKey, LPCTSTR lpSubKey, LPCTSTR lpValueName, LPDWORD lpData)
+RegGetDWORD(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, LPDWORD lpData)
 {
     DWORD dwBytes = sizeof(*lpData), dwType;
     BOOL bRet = TRUE;
 
-    /* If SubKy is specified open it */
-    if (lpSubKey && RegOpenKeyEx(hKey,
+    /* 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;
     }
 
-    if (RegQueryValueEx(hKey,
-                        lpValueName,
-                        NULL,
-                        &dwType,
-                        (LPBYTE)lpData,
-                        &dwBytes) != ERROR_SUCCESS || dwType != REG_DWORD)
+    /* Query registry value and check its type */
+    if (RegQueryValueExW(hKey,
+                         lpValueName,
+                         NULL,
+                         &dwType,
+                         (LPBYTE)lpData,
+                         &dwBytes) != ERROR_SUCCESS || dwType != REG_DWORD)
     {
-        //_tprintf("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;
     }
-    
+
     /* Close key if we opened it */
     if (lpSubKey)
         RegCloseKey(hKey);
-    
+
     return bRet;
 }
 
+/* Format bytes */
 static
-void
-FormatBytes(LPTSTR Buf, unsigned cBytes)
+VOID
+FormatBytes(LPWSTR lpBuf, unsigned cBytes)
 {
-    TCHAR szMB[32], Tmp[BUFFER_SIZE];
-    NUMBERFMT fmt;
-    
-    itoa(cBytes / (1024*1024), szMB, 10);
-    
+    WCHAR szMB[32];
+    NUMBERFMTW fmt;
+    unsigned i;
+
+    _itow(cBytes / (1024*1024), szMB, 10);
+
     fmt.NumDigits = 0;
     fmt.LeadingZero = 0;
     fmt.Grouping = 3;
-    fmt.lpDecimalSep = TEXT("");
-    fmt.lpThousandSep = TEXT(" ");
+    fmt.lpDecimalSep = L"";
+    fmt.lpThousandSep = L" ";
     fmt.NegativeOrder = 0;
-    if(!GetNumberFormat(LOCALE_SYSTEM_DEFAULT, 0, szMB, &fmt, Tmp, BUFFER_SIZE))
-        printf("Error! GetNumberFormat failed.\n");
-    
-    CharToOem(Tmp, Buf);
+
+    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
-FormatDateTime(time_t Time, LPTSTR lpBuf)
+VOID
+FormatDateTime(time_t Time, LPWSTR lpBuf)
 {
-    unsigned cchBuf = BUFFER_SIZE, i;
+    unsigned i;
     SYSTEMTIME SysTime;
     const struct tm *lpTm;
-    
+
     lpTm = localtime(&Time);
     SysTime.wYear = (WORD)(1900 + lpTm->tm_year);
     SysTime.wMonth = (WORD)(1 + lpTm->tm_mon);
@@ -158,12 +165,16 @@ FormatDateTime(time_t Time, LPTSTR lpBuf)
     SysTime.wMinute = (WORD)lpTm->tm_min;
     SysTime.wSecond = (WORD)lpTm->tm_sec;
     SysTime.wMilliseconds = 0;
-    
-    i = GetDateFormat(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 */
-    i += _stprintf(lpBuf + i, TEXT(", "));
-    GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &SysTime, NULL, lpBuf + i, cchBuf - i);
+
+    /* Copy time now */
+    i += swprintf(lpBuf + i, L", ");
+    i += 2;
+    GetTimeFormatW(LOCALE_SYSTEM_DEFAULT, 0, &SysTime, NULL, lpBuf + i, BUFFER_SIZE - i);
 }
 
 /* Show usage */
@@ -171,29 +182,64 @@ static
 VOID
 Usage(VOID)
 {
-    TCHAR Buf[BUFFER_SIZE];
-    
-    if(GetOemStrings(IDS_USAGE, Buf))
-        _tprintf("%s", Buf);
+    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 (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;
-    OSVERSIONINFO VersionInfo;
+    DWORD dwCharCount = BUFFER_SIZE, dwTimestamp, dwResult;
+    OSVERSIONINFOW VersionInfo;
     SYSTEM_INFO SysInfo;
-    TCHAR Buf[BUFFER_SIZE], Tmp[BUFFER_SIZE], Msg[BUFFER_SIZE], szSystemDir[MAX_PATH];
-    const TCHAR *lpcszSysType;
+    WCHAR Buf[BUFFER_SIZE], Tmp[BUFFER_SIZE], szSystemDir[MAX_PATH];
+    const WCHAR *lpcszSysType;
+    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 (!GetSystemDirectory(szSystemDir, sizeof(szSystemDir)/sizeof(szSystemDir[0])))
+    if (!GetSystemDirectoryW(szSystemDir, sizeof(szSystemDir)/sizeof(szSystemDir[0])))
     {
-        _tprintf("Error! GetSystemDirectory failed.\n");
+        wprintf(L"Error! GetSystemDirectory failed.\n");
         return;
     }
 
@@ -201,313 +247,380 @@ AllSysInfo(VOID)
 
     // getting computer name
     dwCharCount = BUFFER_SIZE;
-    if (!GetComputerName(Buf, &dwCharCount))
-        _tprintf("Error! GetComputerName failed.\n");
-    else if (GetOemStrings(IDS_HOST_NAME, Msg))
-        _tprintf(Msg, Buf);
+    if (!GetComputerNameW(Buf, &dwCharCount))
+        wprintf(L"Error! GetComputerName failed.\n");
+    else
+        PrintRow(IDS_HOST_NAME, FALSE, L"%s", Buf);
 
     // open CurrentVersion key
-    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                    TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"),
+    if(RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                    L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
                     0,
                     KEY_QUERY_VALUE,
                     &hKey) != ERROR_SUCCESS)
     {
-        _tprintf("Error! RegOpenKeyEx failed.\n");
+        wprintf(L"Error! RegOpenKeyEx failed.\n");
         return;
     }
 
     //getting OS Name
-    RegGetSZ(hKey, NULL, TEXT("ProductName"), Buf);
-    if (GetOemStrings(IDS_OS_NAME, Msg))
-        _tprintf(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);
-    GetVersionEx(&VersionInfo);
-
-    if (GetOemStrings(IDS_OS_VERSION, Msg))
-        _tprintf(Msg,
-               (unsigned)VersionInfo.dwMajorVersion,
-               (unsigned)VersionInfo.dwMinorVersion,
-               (unsigned)VersionInfo.dwBuildNumber,
-               VersionInfo.szCSDVersion,
-               (unsigned)VersionInfo.dwBuildNumber);
+    GetVersionExW(&VersionInfo);
+
+    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, TEXT("CurrentType"), Buf);
-    if (GetOemStrings(IDS_OS_BUILD_TYPE, Msg))
-        _tprintf(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, TEXT("RegisteredOwner"), Buf);
-    if (GetOemStrings(IDS_REG_OWNER, Msg))
-        _tprintf(Msg, Buf);
+    RegGetSZ(hKey, NULL, L"RegisteredOwner", Buf, BUFFER_SIZE);
+    PrintRow(IDS_REG_OWNER, FALSE, L"%s", Buf);
 
     //getting Registered Organization
-    RegGetSZ(hKey, NULL, TEXT("RegisteredOrganization"), Buf);
-    if (GetOemStrings(IDS_REG_ORG, Msg))
-        _tprintf(Msg, Buf);
+    RegGetSZ(hKey, NULL, L"RegisteredOrganization", Buf, BUFFER_SIZE);
+    PrintRow(IDS_REG_ORG, FALSE, L"%s", Buf);
 
     //getting Product ID
-    RegGetSZ(hKey, NULL, TEXT("ProductId"), Buf);
-    if (GetOemStrings(IDS_PRODUCT_ID, Msg))
-        _tprintf(Msg, Buf);
+    RegGetSZ(hKey, NULL, L"ProductId", Buf, BUFFER_SIZE);
+    PrintRow(IDS_PRODUCT_ID, FALSE, L"%s", Buf);
 
     //getting Install Date
-    RegGetDWORD(hKey, NULL, TEXT("InstallDate"), &dwTimestamp);
+    RegGetDWORD(hKey, NULL, L"InstallDate", &dwTimestamp);
     FormatDateTime((time_t)dwTimestamp, Buf);
-    if (GetOemStrings(IDS_INST_DATE, Msg))
-        _tprintf(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))
-        _tprintf(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
-    sprintf(Tmp, "%s\\oeminfo.ini", szSystemDir);
-    GetPrivateProfileString(TEXT("General"),
-                            TEXT("Manufacturer"),
-                            TEXT("To Be Filled By O.E.M."),
-                            Buf,
-                            sizeof(Buf)/sizeof(Buf[0]),
-                            Tmp);
-    if (GetOemStrings(IDS_SYS_MANUFACTURER, Msg))
-        _tprintf(Msg, Buf);
+    swprintf(Tmp, L"%s\\oeminfo.ini", szSystemDir);
+    GetPrivateProfileStringW(L"General",
+                             L"Manufacturer",
+                             L"To Be Filled By O.E.M.",
+                             Buf,
+                             sizeof(Buf)/sizeof(Buf[0]),
+                             Tmp);
+    PrintRow(IDS_SYS_MANUFACTURER, FALSE, L"%s", Buf);
 
     //getting System Model; HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OEMInformation\Model for Win >= 6.0
-    GetPrivateProfileString(TEXT("General"),
-                            TEXT("Model"),
-                            TEXT("To Be Filled By O.E.M."),
-                            Buf,
-                            sizeof(Buf)/sizeof(Buf[0]),
-                            Tmp);
-    if (GetOemStrings(IDS_SYS_MODEL, Msg))
-        _tprintf(Msg, Buf);
+    GetPrivateProfileStringW(L"General",
+                             L"Model",
+                             L"To Be Filled By O.E.M.",
+                             Buf,
+                             sizeof(Buf)/sizeof(Buf[0]),
+                             Tmp);
+    PrintRow(IDS_SYS_MODEL, FALSE, L"%s", Buf);
 
     //getting System type
     switch (SysInfo.wProcessorArchitecture)
     {
         case PROCESSOR_ARCHITECTURE_INTEL:
-            lpcszSysType = TEXT("X86-based PC");
+            lpcszSysType = L"X86-based PC";
             break;
         case PROCESSOR_ARCHITECTURE_IA64:
-            lpcszSysType = TEXT("IA64-based PC");
+            lpcszSysType = L"IA64-based PC";
             break;
         case PROCESSOR_ARCHITECTURE_AMD64:
-            lpcszSysType = TEXT("AMD64-based PC");
+            lpcszSysType = L"AMD64-based PC";
             break;
         default:
-            lpcszSysType = TEXT("Unknown");
+            lpcszSysType = L"Unknown";
             break;
     }
-    if (GetOemStrings(IDS_SYS_TYPE, Msg))
-        _tprintf(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;
-        _tprintf(Msg, (unsigned int)SysInfo.dwNumberOfProcessors);
-        for(i = 0; i < (unsigned int)SysInfo.dwNumberOfProcessors; i++)
-        {
-            sprintf(Tmp, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%u",i);
-
-            RegGetSZ(HKEY_LOCAL_MACHINE, Tmp, TEXT("Identifier"), Buf);
-            _tprintf("                       [%02u]: %s", i+1, Buf);
-
-            RegGetSZ(HKEY_LOCAL_MACHINE, Tmp, TEXT("VendorIdentifier"), Buf);
-            _tprintf(" %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,
-             TEXT("HARDWARE\\DESCRIPTION\\System"),
-             TEXT("SystemBiosVersion"),
-             Buf);
-    if (GetOemStrings(IDS_BIOS_VERSION, Msg))
-        _tprintf(Msg, Buf);
+             L"HARDWARE\\DESCRIPTION\\System",
+             L"SystemBiosVersion",
+             Buf,
+             BUFFER_SIZE);
+    PrintRow(IDS_BIOS_VERSION, FALSE, L"%s", Buf);
 
     //gettings BIOS date
     RegGetSZ(HKEY_LOCAL_MACHINE,
-             TEXT("HARDWARE\\DESCRIPTION\\System"),
-             TEXT("SystemBiosDate"),
-             Buf);
-    if (GetOemStrings(IDS_BIOS_DATE, Msg))
-        _tprintf(Msg, Buf);
+             L"HARDWARE\\DESCRIPTION\\System",
+             L"SystemBiosDate",
+             Buf,
+             BUFFER_SIZE);
+    PrintRow(IDS_BIOS_DATE, FALSE, L"%s", Buf);
 
     //getting ReactOS Directory
-    if (!GetWindowsDirectory(Buf, BUFFER_SIZE))
-        _tprintf("Error! GetWindowsDirectory failed.");
-    else if (GetOemStrings(IDS_ROS_DIR, Msg))
-        _tprintf(Msg, Buf);
+    if (!GetWindowsDirectoryW(Buf, BUFFER_SIZE))
+        wprintf(L"Error! GetWindowsDirectory failed.");
+    else
+        PrintRow(IDS_ROS_DIR, FALSE, L"%s", Buf);
 
     //getting System Directory
-    if (GetOemStrings(IDS_SYS_DIR, Msg))
-        _tprintf(Msg, szSystemDir);
+    PrintRow(IDS_SYS_DIR, 0, L"%s", szSystemDir);
 
     //getting Boot Device
     RegGetSZ(HKEY_LOCAL_MACHINE,
-             TEXT("SYSTEM\\Setup"),
-             TEXT("SystemPartition"),
-             Buf);
-    if (GetOemStrings(IDS_BOOT_DEV, Msg))
-        _tprintf(Msg, Buf);
+             L"SYSTEM\\Setup",
+             L"SystemPartition",
+             Buf,
+             BUFFER_SIZE);
+    PrintRow(IDS_BOOT_DEV, FALSE, L"%s", Buf);
 
     //getting System Locale
-    if (RegGetSZ(HKEY_CURRENT_USER,
-                 TEXT("Control Panel\\International"),
-                 TEXT("Locale"),
-                 Tmp))
+    if (GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, LOCALE_ILANGUAGE, Tmp, BUFFER_SIZE))
         if (RegGetSZ(HKEY_CLASSES_ROOT,
-                     TEXT("MIME\\Database\\Rfc1766"),
+                     L"MIME\\Database\\Rfc1766",
                      Tmp,
-                     Buf))
-            if (GetOemStrings(IDS_SYS_LOCALE, Msg))
-                _tprintf(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,
-                 TEXT("Keyboard Layout\\Preload"),
-                 TEXT("1"),
-                 Buf))
-    {
-        int i, j;
-
-        for(j = 0, i = 4; i <= 8; j++, i++)
-            Tmp[j] = Buf[i];
-
+                 L"Keyboard Layout\\Preload",
+                 L"1",
+                 Tmp,
+                 BUFFER_SIZE) && wcslen(Tmp) > 4)
         if (RegGetSZ(HKEY_CLASSES_ROOT,
-                     TEXT("MIME\\Database\\Rfc1766"),
-                     Tmp,
-                     Buf))
-            if (GetOemStrings(IDS_INPUT_LOCALE, Msg))
-                _tprintf(Msg, Buf);
-    }
+                     L"MIME\\Database\\Rfc1766",
+                     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);
-    
+
     /* Open Time Zones key */
-    if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                    TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"),
-                    0,
-                    KEY_ENUMERATE_SUB_KEYS|KEY_READ,
-                    &hKey) == ERROR_SUCCESS)
+    if(RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                     L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
+                     0,
+                     KEY_ENUMERATE_SUB_KEYS|KEY_READ,
+                     &hKey) == ERROR_SUCCESS)
     {
         unsigned i;
-        
+
         /* Find current timezone */
-        dwCharCount = 256; // Windows seems to have a bug - it doesnt accept BUFFER_SIZE here
-        for(i = 0; RegEnumKeyEx(hKey, i, Tmp, &dwCharCount, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; ++i, dwCharCount = 255)
+        dwCharCount = BUFFER_SIZE;
+        for(i = 0; RegEnumKeyExW(hKey, i, Tmp, &dwCharCount, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; ++i, dwCharCount = 255)
         {
-#ifdef _UNICODE
-            RegGetSZ(hKey, Tmp, TEXT("Std"), Buf);
-            
-            if(!wcscmp(wBuf, TimeZoneInfo.StandardName))
-#else
-            wchar_t wBuf[BUFFER_SIZE];
+            RegGetSZ(hKey, Tmp, L"Std", Buf, BUFFER_SIZE);
 
-            RegGetSZ(hKey, Tmp, TEXT("Std"), Buf);
-            mbstowcs(wBuf, Buf, BUFFER_SIZE);
-            
-            if(!wcscmp(wBuf, TimeZoneInfo.StandardName))
-#endif
+            if (!wcscmp(Buf, TimeZoneInfo.StandardName))
             {
-                RegGetSZ(hKey, Tmp, TEXT("Display"), Buf);
+                RegGetSZ(hKey, Tmp, L"Display", Buf, BUFFER_SIZE);
 
-                if (GetOemStrings(IDS_TIME_ZONE, Msg))
-                    _tprintf(Msg, Buf);
+                PrintRow(IDS_TIME_ZONE, FALSE, L"%s", Buf);
 
                 break;
             }
         }
         RegCloseKey(hKey);
     }
-    
-    
+
     //getting Total Physical Memory
     GlobalMemoryStatus(&MemoryStatus);
     FormatBytes(Buf, MemoryStatus.dwTotalPhys);
-    if (GetOemStrings(IDS_TOTAL_PHYS_MEM, Msg))
-        _tprintf(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))
-        _tprintf(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))
-        _tprintf(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))
-        _tprintf(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))
-        _tprintf(Msg, Buf);
+    PrintRow(IDS_VIRT_MEM_INUSE, FALSE, L"%s", Buf);
 
     //getting Page File Location(s)
     if (RegGetSZ(HKEY_LOCAL_MACHINE,
-                 TEXT("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management"),
-                 TEXT("PagingFiles"),
-                 Buf))
+                 L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management",
+                 L"PagingFiles",
+                 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))
-            _tprintf(Msg, Buf);
+
+        PrintRow(IDS_PAGEFILE_LOC, FALSE, L"%s", Buf);
     }
 
     //getting Domain
-    if (RegGetSZ(HKEY_LOCAL_MACHINE,
-                 TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"),
-                 TEXT("CachePrimaryDomain"),
-                 Buf))
-        if(GetOemStrings(IDS_DOMINE, Msg))
-            _tprintf(Msg, Buf);
+    if (NetGetJoinInformation (NULL, &lpBuffer, &NetJoinStatus) == NERR_Success)
+    {
+        if (NetJoinStatus == NetSetupWorkgroupName || NetJoinStatus == NetSetupDomainName)
+            PrintRow(IDS_DOMAIN, FALSE, L"%s", lpBuffer);
+
+        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[])
 {
-    if (argc > 1 && (!strcmp(argv[1], "/?") || !strcmp(argv[1], "-?")))
+    WSADATA WsaData;
+    int i;
+
+    setlocale(LC_ALL, "");
+
+    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();