1 /*
2    This program is free software; you can redistribute it and/or modify
3    it under the terms of the GNU General Public License as published by
4    the Free Software Foundation; either version 2 of the License, or
5    (at your option) any later version.
6 
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU General Public License for more details.
11 
12    You should have received a copy of the GNU General Public License
13    along with this program; if not, write to the Free Software
14    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16 /* Copyright (C) 2007, Dmitry Chapyshev <lentind@yandex.ru> */
17 /* Copyright (C) 2011, Rafal Harabien <rafalh1992@o2.pl> */
18 
19 #include <wchar.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdarg.h>
23 #include <windows.h>
24 #include <time.h>
25 #include <locale.h>
26 #include <lm.h>
27 #include <shlwapi.h>
28 #include <iphlpapi.h>
29 #include <winsock2.h>
30 #include <udmihelp.h>
31 #include <dmilib.h>
32 
33 #include "resource.h"
34 
35 #define BUFFER_SIZE 1024
36 
37 /* Load string from registry */
38 static
39 unsigned
40 RegGetSZ(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, LPWSTR lpBuf, DWORD cchBuf)
41 {
42     DWORD dwBytes = cchBuf*sizeof(WCHAR), dwType = 0;
43     unsigned cChars;
44 
45     /* If SubKey is specified open it */
46     if (lpSubKey && RegOpenKeyExW(hKey,
47                                   lpSubKey,
48                                   0,
49                                   KEY_QUERY_VALUE,
50                                   &hKey) != ERROR_SUCCESS)
51     {
52         wprintf(L"Warning! Cannot open %s. Last error: %lu.\n", lpSubKey, GetLastError());
53         return 0;
54     }
55 
56     /* Query registry value and check its type */
57     if (RegQueryValueExW(hKey,
58                          lpValueName,
59                          NULL,
60                          &dwType,
61                          (LPBYTE)lpBuf,
62                          &dwBytes) != ERROR_SUCCESS || (dwType != REG_SZ && dwType != REG_MULTI_SZ))
63     {
64         wprintf(L"Warning! Cannot query %s. Last error: %lu, type: %lu.\n", lpValueName, GetLastError(), dwType);
65         dwBytes = 0;
66     }
67     else if (dwBytes == 0)
68     {
69         wcscpy(lpBuf, L"N/A");
70         dwBytes = 6;
71     }
72 
73     /* Close key if we opened it */
74     if (lpSubKey)
75         RegCloseKey(hKey);
76 
77     cChars = dwBytes/sizeof(WCHAR);
78 
79     /* NULL-terminate string */
80     lpBuf[min(cchBuf-1, cChars)] = L'\0';
81 
82     /* Don't count NULL characters */
83     while(cChars && !lpBuf[cChars-1])
84         --cChars;
85 
86     return cChars;
87 }
88 
89 /* Load DWORD from registry */
90 static
91 BOOL
92 RegGetDWORD(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, LPDWORD lpData)
93 {
94     DWORD dwBytes = sizeof(*lpData), dwType;
95     BOOL bRet = TRUE;
96 
97     /* If SubKey is specified open it */
98     if (lpSubKey && RegOpenKeyExW(hKey,
99                                  lpSubKey,
100                                  0,
101                                  KEY_QUERY_VALUE,
102                                  &hKey) != ERROR_SUCCESS)
103     {
104         wprintf(L"Warning! Cannot open %s. Last error: %lu.\n", lpSubKey, GetLastError());
105         return FALSE;
106     }
107 
108     /* Query registry value and check its type */
109     if (RegQueryValueExW(hKey,
110                          lpValueName,
111                          NULL,
112                          &dwType,
113                          (LPBYTE)lpData,
114                          &dwBytes) != ERROR_SUCCESS || dwType != REG_DWORD)
115     {
116         wprintf(L"Warning! Cannot query %s. Last err: %lu, type: %lu\n", lpValueName, GetLastError(), dwType);
117         *lpData = 0;
118         bRet = FALSE;
119     }
120 
121     /* Close key if we opened it */
122     if (lpSubKey)
123         RegCloseKey(hKey);
124 
125     return bRet;
126 }
127 
128 /* Format bytes */
129 static
130 VOID
131 FormatBytes(LPWSTR lpBuf, unsigned cBytes)
132 {
133     WCHAR szMB[32];
134     NUMBERFMTW fmt;
135     unsigned i;
136 
137     _itow(cBytes / (1024*1024), szMB, 10);
138 
139     fmt.NumDigits = 0;
140     fmt.LeadingZero = 0;
141     fmt.Grouping = 3;
142     fmt.lpDecimalSep = L"";
143     fmt.lpThousandSep = L" ";
144     fmt.NegativeOrder = 0;
145 
146     i = GetNumberFormatW(LOCALE_SYSTEM_DEFAULT, 0, szMB, &fmt, lpBuf, BUFFER_SIZE - 3);
147     if (i)
148         --i; /* don't count NULL character */
149     wcscpy(lpBuf + i, L" MB");
150 }
151 
152 /* Format date and time */
153 static
154 VOID
155 FormatDateTime(time_t Time, LPWSTR lpBuf)
156 {
157     unsigned i;
158     SYSTEMTIME SysTime;
159     const struct tm *lpTm;
160 
161     lpTm = localtime(&Time);
162     SysTime.wYear = (WORD)(1900 + lpTm->tm_year);
163     SysTime.wMonth = (WORD)(1 + lpTm->tm_mon);
164     SysTime.wDayOfWeek = (WORD)lpTm->tm_wday;
165     SysTime.wDay = (WORD)lpTm->tm_mday;
166     SysTime.wHour = (WORD)lpTm->tm_hour;
167     SysTime.wMinute = (WORD)lpTm->tm_min;
168     SysTime.wSecond = (WORD)lpTm->tm_sec;
169     SysTime.wMilliseconds = 0;
170 
171     /* Copy date first */
172     i = GetDateFormatW(LOCALE_SYSTEM_DEFAULT, 0, &SysTime, NULL, lpBuf, BUFFER_SIZE - 2);
173     if (i)
174         --i; /* don't count NULL character */
175 
176     /* Copy time now */
177     i += swprintf(lpBuf + i, L", ");
178 
179     GetTimeFormatW(LOCALE_SYSTEM_DEFAULT, 0, &SysTime, NULL, lpBuf + i, BUFFER_SIZE - i);
180 }
181 
182 /* Show usage */
183 static
184 VOID
185 Usage(VOID)
186 {
187     WCHAR Buf[4096];
188     if (LoadStringW(GetModuleHandle(NULL), IDS_USAGE, Buf, 4096))
189         wprintf(L"%s", Buf);
190 }
191 
192 static
193 VOID
194 PrintRow(UINT nTitleID, BOOL bIndent, LPWSTR lpFormat, ...)
195 {
196     WCHAR Buf[BUFFER_SIZE];
197     va_list Args;
198     unsigned c;
199 
200     if (nTitleID)
201     {
202         c = LoadStringW(GetModuleHandle(NULL), nTitleID, Buf, BUFFER_SIZE - 2);
203         if (!c)
204             return;
205 
206         wcscpy(Buf + c, L": ");
207     } else
208         Buf[0] = L'\0';
209 
210     if (!bIndent)
211         wprintf(L"%-32s", Buf);
212     else if (Buf[0])
213         wprintf(L"%38s%-16s", L"", Buf);
214     else
215         wprintf(L"%38s", L"");
216 
217     va_start(Args, lpFormat);
218     vwprintf(lpFormat, Args);
219     va_end(Args);
220 
221     wprintf(L"\n");
222 }
223 
224 /* Print all system information */
225 VOID
226 AllSysInfo(VOID)
227 {
228     DWORD dwCharCount = BUFFER_SIZE, dwTimestamp, dwResult;
229     OSVERSIONINFOW VersionInfo;
230     SYSTEM_INFO SysInfo;
231     WCHAR Buf[BUFFER_SIZE], Tmp[BUFFER_SIZE], szSystemDir[MAX_PATH];
232     const WCHAR *lpcszSysType;
233     LPWSTR lpBuffer;
234     NETSETUP_JOIN_STATUS NetJoinStatus;
235     MEMORYSTATUS MemoryStatus;
236     unsigned int cSeconds, i, j;
237     TIME_ZONE_INFORMATION TimeZoneInfo;
238     HKEY hKey;
239     PIP_ADAPTER_ADDRESSES pAdapters;
240     ULONG cbAdapters;
241     PVOID SMBiosBuf;
242     PCHAR DmiStrings[ID_STRINGS_MAX] = { 0 };
243 
244     if (!GetSystemDirectoryW(szSystemDir, sizeof(szSystemDir)/sizeof(szSystemDir[0])))
245     {
246         wprintf(L"Error! GetSystemDirectory failed.\n");
247         return;
248     }
249 
250     GetSystemInfo(&SysInfo);
251 
252     // getting computer name
253     dwCharCount = BUFFER_SIZE;
254     if (!GetComputerNameW(Buf, &dwCharCount))
255         wprintf(L"Error! GetComputerName failed.\n");
256     else
257         PrintRow(IDS_HOST_NAME, FALSE, L"%s", Buf);
258 
259     // open CurrentVersion key
260     if(RegOpenKeyExW(HKEY_LOCAL_MACHINE,
261                     L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
262                     0,
263                     KEY_QUERY_VALUE,
264                     &hKey) != ERROR_SUCCESS)
265     {
266         wprintf(L"Error! RegOpenKeyEx failed.\n");
267         return;
268     }
269 
270     //getting OS Name
271     RegGetSZ(hKey, NULL, L"ProductName", Buf, BUFFER_SIZE);
272     PrintRow(IDS_OS_NAME, FALSE, L"%s", Buf);
273 
274     //getting OS Version
275     ZeroMemory(&VersionInfo, sizeof(VersionInfo));
276     VersionInfo.dwOSVersionInfoSize = sizeof(VersionInfo);
277     GetVersionExW(&VersionInfo);
278 
279     if (!LoadStringW(GetModuleHandle(NULL), IDS_BUILD, Tmp, BUFFER_SIZE))
280         Tmp[0] = L'\0';
281     PrintRow(IDS_OS_VERSION,
282              FALSE,
283              L"%lu.%lu.%lu %s %s %lu",
284              VersionInfo.dwMajorVersion,
285              VersionInfo.dwMinorVersion,
286              VersionInfo.dwBuildNumber,
287              VersionInfo.szCSDVersion,
288              Tmp,
289              VersionInfo.dwBuildNumber);
290 
291     //getting OS Manufacturer
292 
293     //getting OS Configuration
294 
295     //getting OS Build Type
296     RegGetSZ(hKey, NULL, L"CurrentType", Buf, BUFFER_SIZE);
297     PrintRow(IDS_OS_BUILD_TYPE, FALSE, L"%s", Buf);
298 
299     //getting Registered Owner
300     RegGetSZ(hKey, NULL, L"RegisteredOwner", Buf, BUFFER_SIZE);
301     PrintRow(IDS_REG_OWNER, FALSE, L"%s", Buf);
302 
303     //getting Registered Organization
304     RegGetSZ(hKey, NULL, L"RegisteredOrganization", Buf, BUFFER_SIZE);
305     PrintRow(IDS_REG_ORG, FALSE, L"%s", Buf);
306 
307     //getting Product ID
308     RegGetSZ(hKey, NULL, L"ProductId", Buf, BUFFER_SIZE);
309     PrintRow(IDS_PRODUCT_ID, FALSE, L"%s", Buf);
310 
311     //getting Install Date
312     RegGetDWORD(hKey, NULL, L"InstallDate", &dwTimestamp);
313     FormatDateTime((time_t)dwTimestamp, Buf);
314     PrintRow(IDS_INST_DATE, FALSE, L"%s", Buf);
315 
316     // close Current Version key now
317     RegCloseKey(hKey);
318 
319     //getting System Up Time
320     cSeconds = GetTickCount() / 1000;
321     if (!LoadStringW(GetModuleHandle(NULL), IDS_UP_TIME_FORMAT, Tmp, BUFFER_SIZE))
322         Tmp[0] = L'\0';
323     swprintf(Buf, Tmp, cSeconds / (60*60*24), (cSeconds / (60*60)) % 24, (cSeconds / 60) % 60, cSeconds % 60);
324     PrintRow(IDS_UP_TIME, FALSE, L"%s", Buf);
325 
326     // prepare SMBIOS data
327     SMBiosBuf = LoadSMBiosData(DmiStrings);
328 
329     //getting System Manufacturer; HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OEMInformation\Manufacturer for Win >= 6.0
330     swprintf(Tmp, L"%s\\oeminfo.ini", szSystemDir);
331     GetPrivateProfileStringW(L"General",
332                              L"Manufacturer",
333                              L"",
334                              Buf,
335                              sizeof(Buf)/sizeof(Buf[0]),
336                              Tmp);
337     if (wcslen(Buf) == 0 && SMBiosBuf)
338     {
339         GetSMBiosStringW(DmiStrings[SYS_VENDOR], Buf, _countof(Buf), FALSE);
340     }
341     PrintRow(IDS_SYS_MANUFACTURER, FALSE, L"%s", Buf);
342 
343     //getting System Model; HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OEMInformation\Model for Win >= 6.0
344     GetPrivateProfileStringW(L"General",
345                              L"Model",
346                              L"",
347                              Buf,
348                              sizeof(Buf)/sizeof(Buf[0]),
349                              Tmp);
350     if (wcslen(Buf) == 0 && SMBiosBuf)
351     {
352         GetSMBiosStringW(DmiStrings[SYS_PRODUCT], Buf, _countof(Buf), FALSE);
353     }
354     PrintRow(IDS_SYS_MODEL, FALSE, L"%s", Buf);
355 
356     //getting System type
357     switch (SysInfo.wProcessorArchitecture)
358     {
359         case PROCESSOR_ARCHITECTURE_INTEL:
360             lpcszSysType = L"X86-based PC";
361             break;
362         case PROCESSOR_ARCHITECTURE_IA64:
363             lpcszSysType = L"IA64-based PC";
364             break;
365         case PROCESSOR_ARCHITECTURE_AMD64:
366             lpcszSysType = L"AMD64-based PC";
367             break;
368         default:
369             lpcszSysType = L"Unknown";
370             break;
371     }
372     PrintRow(IDS_SYS_TYPE, FALSE, L"%s", lpcszSysType);
373 
374     //getting Processor(s)
375     if (!LoadStringW(GetModuleHandle(NULL), IDS_PROCESSORS_FORMAT, Tmp, BUFFER_SIZE))
376         Tmp[0] = L'\0';
377     swprintf(Buf, Tmp, (unsigned)SysInfo.dwNumberOfProcessors);
378     PrintRow(IDS_PROCESSORS, FALSE, L"%s", Buf);
379     for(i = 0; i < (unsigned int)SysInfo.dwNumberOfProcessors; i++)
380     {
381         swprintf(Tmp, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\%u", i);
382         j = swprintf(Buf, L"[%02u]: ", i + 1);
383 
384         j += RegGetSZ(HKEY_LOCAL_MACHINE, Tmp, L"Identifier", Buf + j, BUFFER_SIZE - j);
385         if(j + 1 < BUFFER_SIZE)
386             Buf[j++] = L' ';
387         RegGetSZ(HKEY_LOCAL_MACHINE, Tmp, L"VendorIdentifier", Buf + j, BUFFER_SIZE - j);
388 
389         PrintRow(0, FALSE, L"%s", Buf);
390     }
391 
392     //getting BIOS Version
393     if (SMBiosBuf)
394     {
395         j = GetSMBiosStringW(DmiStrings[BIOS_VENDOR], Buf, BUFFER_SIZE, TRUE);
396         if (j + 1 < BUFFER_SIZE)
397         {
398             Buf[j++] = L' ';
399             Buf[j] = L'\0';
400         }
401         GetSMBiosStringW(DmiStrings[BIOS_VERSION], Buf + j, BUFFER_SIZE - j, TRUE);
402     }
403     else
404     {
405         RegGetSZ(HKEY_LOCAL_MACHINE,
406                  L"HARDWARE\\DESCRIPTION\\System",
407                  L"SystemBiosVersion",
408                  Buf,
409                  BUFFER_SIZE);
410     }
411     PrintRow(IDS_BIOS_VERSION, FALSE, L"%s", Buf);
412 
413     //gettings BIOS date
414     if (SMBiosBuf)
415     {
416         GetSMBiosStringW(DmiStrings[BIOS_DATE], Buf, BUFFER_SIZE, TRUE);
417     }
418     else
419     {
420         RegGetSZ(HKEY_LOCAL_MACHINE,
421                  L"HARDWARE\\DESCRIPTION\\System",
422                  L"SystemBiosDate",
423                  Buf,
424                  BUFFER_SIZE);
425     }
426     PrintRow(IDS_BIOS_DATE, FALSE, L"%s", Buf);
427 
428     // clean SMBIOS data
429     FreeSMBiosData(SMBiosBuf);
430 
431     //getting ReactOS Directory
432     if (!GetWindowsDirectoryW(Buf, BUFFER_SIZE))
433         wprintf(L"Error! GetWindowsDirectory failed.");
434     else
435         PrintRow(IDS_ROS_DIR, FALSE, L"%s", Buf);
436 
437     //getting System Directory
438     PrintRow(IDS_SYS_DIR, 0, L"%s", szSystemDir);
439 
440     //getting Boot Device
441     RegGetSZ(HKEY_LOCAL_MACHINE,
442              L"SYSTEM\\Setup",
443              L"SystemPartition",
444              Buf,
445              BUFFER_SIZE);
446     PrintRow(IDS_BOOT_DEV, FALSE, L"%s", Buf);
447 
448     //getting System Locale
449     if (GetLocaleInfoW(LOCALE_SYSTEM_DEFAULT, LOCALE_ILANGUAGE, Tmp, BUFFER_SIZE))
450         if (RegGetSZ(HKEY_CLASSES_ROOT,
451                      L"MIME\\Database\\Rfc1766",
452                      Tmp,
453                      Buf,
454                      BUFFER_SIZE))
455         {
456             /* get rid of @filename,resource */
457             lpBuffer = wcschr(Buf, L';');
458             if (lpBuffer)
459                 SHLoadIndirectString(lpBuffer+1, lpBuffer+1, BUFFER_SIZE - (lpBuffer-Buf) - 1, NULL);
460 
461             PrintRow(IDS_SYS_LOCALE, FALSE, L"%s", Buf);
462         }
463 
464     //getting Input Locale
465     if (RegGetSZ(HKEY_CURRENT_USER,
466                  L"Keyboard Layout\\Preload",
467                  L"1",
468                  Tmp,
469                  BUFFER_SIZE) && wcslen(Tmp) > 4)
470         if (RegGetSZ(HKEY_CLASSES_ROOT,
471                      L"MIME\\Database\\Rfc1766",
472                      Tmp + 4,
473                      Buf,
474                      BUFFER_SIZE))
475         {
476             /* get rid of @filename,resource */
477             lpBuffer = wcschr(Buf, L';');
478             if (lpBuffer)
479                 SHLoadIndirectString(lpBuffer+1, lpBuffer+1, BUFFER_SIZE - (lpBuffer-Buf) - 1, NULL);
480 
481             PrintRow(IDS_INPUT_LOCALE, FALSE, L"%s", Buf);
482         }
483 
484     //getting Time Zone
485     GetTimeZoneInformation(&TimeZoneInfo);
486 
487     /* Open Time Zones key */
488     if(RegOpenKeyExW(HKEY_LOCAL_MACHINE,
489                      L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
490                      0,
491                      KEY_ENUMERATE_SUB_KEYS|KEY_READ,
492                      &hKey) == ERROR_SUCCESS)
493     {
494         unsigned i;
495 
496         /* Find current timezone */
497         dwCharCount = BUFFER_SIZE;
498         for(i = 0; RegEnumKeyExW(hKey, i, Tmp, &dwCharCount, NULL, NULL, NULL, NULL) == ERROR_SUCCESS; ++i, dwCharCount = 255)
499         {
500             RegGetSZ(hKey, Tmp, L"Std", Buf, BUFFER_SIZE);
501 
502             if (!wcscmp(Buf, TimeZoneInfo.StandardName))
503             {
504                 RegGetSZ(hKey, Tmp, L"Display", Buf, BUFFER_SIZE);
505 
506                 PrintRow(IDS_TIME_ZONE, FALSE, L"%s", Buf);
507 
508                 break;
509             }
510         }
511         RegCloseKey(hKey);
512     }
513 
514     //getting Total Physical Memory
515     GlobalMemoryStatus(&MemoryStatus);
516     FormatBytes(Buf, MemoryStatus.dwTotalPhys);
517     PrintRow(IDS_TOTAL_PHYS_MEM, FALSE, L"%s", Buf);
518 
519     //getting Available Physical Memory
520     FormatBytes(Buf, MemoryStatus.dwAvailPhys);
521     PrintRow(IDS_AVAIL_PHISICAL_MEM, FALSE, L"%s", Buf);
522 
523     //getting Virtual Memory: Max Size
524     FormatBytes(Buf, MemoryStatus.dwTotalVirtual);
525     PrintRow(IDS_VIRT_MEM_MAX, FALSE, L"%s", Buf);
526 
527     //getting Virtual Memory: Available
528     FormatBytes(Buf, MemoryStatus.dwAvailVirtual);
529     PrintRow(IDS_VIRT_MEM_AVAIL, FALSE, L"%s", Buf);
530 
531     //getting Virtual Memory: In Use
532     FormatBytes(Buf, MemoryStatus.dwTotalVirtual-MemoryStatus.dwAvailVirtual);
533     PrintRow(IDS_VIRT_MEM_INUSE, FALSE, L"%s", Buf);
534 
535     //getting Page File Location(s)
536     if (RegGetSZ(HKEY_LOCAL_MACHINE,
537                  L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management",
538                  L"PagingFiles",
539                  Buf,
540                  BUFFER_SIZE))
541     {
542         int i;
543 
544         for(i = 0; Buf[i]; i++)
545         {
546             if (Buf[i] == L' ')
547             {
548                 Buf[i] = L'\0';
549                 break;
550             }
551         }
552 
553         PrintRow(IDS_PAGEFILE_LOC, FALSE, L"%s", Buf);
554     }
555 
556     //getting Domain
557     if (NetGetJoinInformation (NULL, &lpBuffer, &NetJoinStatus) == NERR_Success)
558     {
559         if (NetJoinStatus == NetSetupWorkgroupName || NetJoinStatus == NetSetupDomainName)
560             PrintRow(IDS_DOMAIN, FALSE, L"%s", lpBuffer);
561 
562         NetApiBufferFree(lpBuffer);
563     }
564 
565     //getting Logon Server
566 
567     //getting NetWork Card(s)
568     cbAdapters = 4096;
569     pAdapters = malloc(cbAdapters);
570     while((dwResult = GetAdaptersAddresses(AF_UNSPEC, 0x0002, NULL, pAdapters, &cbAdapters)) == ERROR_BUFFER_OVERFLOW)
571     {
572         cbAdapters += 4096;
573         pAdapters = (PIP_ADAPTER_ADDRESSES)realloc(pAdapters, cbAdapters);
574     }
575 
576     if (dwResult == ERROR_SUCCESS)
577     {
578         PIP_ADAPTER_ADDRESSES pCurrentAdapter = pAdapters;
579         unsigned cAdapters = 0;
580 
581         /* Count adapters */
582         for(i = 0; pCurrentAdapter; ++i)
583         {
584             if (pCurrentAdapter->IfType != 24 && pCurrentAdapter->IfType != 131)
585                 ++cAdapters;
586             pCurrentAdapter = pCurrentAdapter->Next;
587         }
588 
589 
590         /* Print adapters count */
591         if (!LoadStringW(GetModuleHandle(NULL), IDS_NETWORK_CARDS_FORMAT, Tmp, BUFFER_SIZE))
592             Tmp[0] = L'\0';
593         swprintf(Buf, Tmp, cAdapters);
594         PrintRow(IDS_NETWORK_CARDS, FALSE, L"%s", Buf);
595 
596         /* Show information about each adapter */
597         pCurrentAdapter = pAdapters;
598         for(i = 0; pCurrentAdapter; ++i)
599         {
600             if (pCurrentAdapter->IfType != 24 && pCurrentAdapter->IfType != 131)//IF_TYPE_SOFTWARE_LOOPBACK)
601             {
602                 PIP_ADAPTER_UNICAST_ADDRESS pAddress;
603 
604                 PrintRow(0, FALSE, L"[%02u]: %s", i + 1, pCurrentAdapter->Description);
605                 PrintRow(IDS_CONNECTION_NAME, TRUE, L"%s", pCurrentAdapter->FriendlyName);
606                 if (!(pCurrentAdapter->Flags & 0x0004))
607                 {
608                     if (!LoadStringW(GetModuleHandle(NULL), IDS_NO, Buf, BUFFER_SIZE))
609                         Buf[0] = L'\0';
610                     PrintRow(IDS_DHCP_ENABLED, TRUE, Buf);
611                 }
612                 if (pCurrentAdapter->OperStatus == IfOperStatusDown)
613                 {
614                     if (!LoadStringW(GetModuleHandle(NULL), IDS_MEDIA_DISCONNECTED, Buf, BUFFER_SIZE))
615                         Buf[0] = L'\0';
616                     PrintRow(IDS_STATUS, TRUE, Buf);
617                 }
618                 else
619                 {
620                     if (!LoadStringW(GetModuleHandle(NULL), IDS_IP_ADDRESSES, Buf, BUFFER_SIZE))
621                         Buf[0] = L'\0';
622                     PrintRow(0, TRUE, Buf);
623                     pAddress = pCurrentAdapter->FirstUnicastAddress;
624                     for (j = 0; pAddress; ++j)
625                     {
626                         dwCharCount = BUFFER_SIZE;
627                         WSAAddressToStringW(pAddress->Address.lpSockaddr, pAddress->Address.iSockaddrLength, NULL, Buf, &dwCharCount);
628                         PrintRow(0, TRUE, L"[%02u]: %s", j + 1, Buf);
629                         pAddress = pAddress->Next;
630                     }
631                 }
632             }
633             pCurrentAdapter = pCurrentAdapter->Next;
634         }
635     }
636     free(pAdapters);
637 }
638 
639 /* Main program */
640 int
641 main(int argc, char *argv[])
642 {
643     WSADATA WsaData;
644     int i;
645 
646     setlocale(LC_ALL, "");
647 
648     WSAStartup(MAKEWORD(2, 2), &WsaData);
649 
650     for (i = 1; i < argc; ++i)
651     {
652         if (!strcmp(argv[i], "/?") || !strcmp(argv[i], "-?"))
653         {
654             Usage();
655             return 0;
656         }
657         else
658         {
659             printf("Unsupported argument: %s\n", argv[i]);
660             return -1;
661         }
662     }
663 
664     AllSysInfo();
665 
666     return 0;
667 }
668