1 /*
2 * PROJECT: ReactOS ipconfig utility
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Display IP info for net adapters
5 * COPYRIGHT: Copyright 2005-2006 Ged Murphy <gedmurphy@gmail.com>
6 */
7 /*
8 * TODO:
9 * fix renew / release
10 * implement registerdns, showclassid, setclassid
11 */
12
13 #define WIN32_NO_STATUS
14 #include <stdarg.h>
15 #include <windef.h>
16 #include <winbase.h>
17 #include <winnls.h>
18 #include <winuser.h>
19 #include <winreg.h>
20 #include <winnls.h>
21 #include <stdio.h>
22 #include <tchar.h>
23 #include <time.h>
24 #include <iphlpapi.h>
25 #include <ndk/rtlfuncs.h>
26 #include <inaddr.h>
27 #include <windns.h>
28 #include <windns_undoc.h>
29 #include <strsafe.h>
30 #include <conutils.h>
31
32 #include "resource.h"
33
34 typedef struct _RECORDTYPE
35 {
36 WORD wRecordType;
37 LPTSTR pszRecordName;
38 } RECORDTYPE, *PRECORDTYPE;
39
40 #define GUID_LEN 40
41
42 HINSTANCE hInstance;
43 HANDLE ProcessHeap;
44
45 RECORDTYPE TypeArray[] =
46 {
47 {DNS_TYPE_ZERO, _T("ZERO")},
48 {DNS_TYPE_A, _T("A")},
49 {DNS_TYPE_NS, _T("NS")},
50 {DNS_TYPE_MD, _T("MD")},
51 {DNS_TYPE_MF, _T("MF")},
52 {DNS_TYPE_CNAME, _T("CNAME")},
53 {DNS_TYPE_SOA, _T("SOA")},
54 {DNS_TYPE_MB, _T("MB")},
55 {DNS_TYPE_MG, _T("MG")},
56 {DNS_TYPE_MR, _T("MR")},
57 {DNS_TYPE_NULL, _T("NULL")},
58 {DNS_TYPE_WKS, _T("WKS")},
59 {DNS_TYPE_PTR, _T("PTR")},
60 {DNS_TYPE_HINFO, _T("HINFO")},
61 {DNS_TYPE_MINFO, _T("MINFO")},
62 {DNS_TYPE_MX, _T("MX")},
63 {DNS_TYPE_TEXT, _T("TXT")},
64 {DNS_TYPE_RP, _T("RP")},
65 {DNS_TYPE_AFSDB, _T("AFSDB")},
66 {DNS_TYPE_X25, _T("X25")},
67 {DNS_TYPE_ISDN, _T("ISDN")},
68 {DNS_TYPE_RT, _T("RT")},
69 {DNS_TYPE_NSAP, _T("NSAP")},
70 {DNS_TYPE_NSAPPTR, _T("NSAPPTR")},
71 {DNS_TYPE_SIG, _T("SIG")},
72 {DNS_TYPE_KEY, _T("KEY")},
73 {DNS_TYPE_PX, _T("PX")},
74 {DNS_TYPE_GPOS, _T("GPOS")},
75 {DNS_TYPE_AAAA, _T("AAAA")},
76 {DNS_TYPE_LOC, _T("LOC")},
77 {DNS_TYPE_NXT, _T("NXT")},
78 {DNS_TYPE_EID, _T("EID")},
79 {DNS_TYPE_NIMLOC, _T("NIMLOC")},
80 {DNS_TYPE_SRV, _T("SRV")},
81 {DNS_TYPE_ATMA, _T("ATMA")},
82 {DNS_TYPE_NAPTR, _T("NAPTR")},
83 {DNS_TYPE_KX, _T("KX")},
84 {DNS_TYPE_CERT, _T("CERT")},
85 {DNS_TYPE_A6, _T("A6")},
86 {DNS_TYPE_DNAME, _T("DNAME")},
87 {DNS_TYPE_SINK, _T("SINK")},
88 {DNS_TYPE_OPT, _T("OPT")},
89 {DNS_TYPE_UINFO, _T("UINFO")},
90 {DNS_TYPE_UID, _T("UID")},
91 {DNS_TYPE_GID, _T("GID")},
92 {DNS_TYPE_UNSPEC, _T("UNSPEC")},
93 {DNS_TYPE_ADDRS, _T("ADDRS")},
94 {DNS_TYPE_TKEY, _T("TKEY")},
95 {DNS_TYPE_TSIG, _T("TSIG")},
96 {DNS_TYPE_IXFR, _T("IXFR")},
97 {DNS_TYPE_AXFR, _T("AXFR")},
98 {DNS_TYPE_MAILB, _T("MAILB")},
99 {DNS_TYPE_MAILA, _T("MAILA")},
100 {DNS_TYPE_ALL, _T("ALL")},
101 {0, NULL}
102 };
103
104 LPTSTR
GetRecordTypeName(WORD wType)105 GetRecordTypeName(WORD wType)
106 {
107 static TCHAR szType[8];
108 INT i;
109
110 for (i = 0; ; i++)
111 {
112 if (TypeArray[i].pszRecordName == NULL)
113 break;
114
115 if (TypeArray[i].wRecordType == wType)
116 return TypeArray[i].pszRecordName;
117 }
118
119 _stprintf(szType, _T("%hu"), wType);
120
121 return szType;
122 }
123
124 /* print MAC address */
PrintMacAddr(PBYTE Mac)125 PCHAR PrintMacAddr(PBYTE Mac)
126 {
127 static CHAR MacAddr[20];
128
129 sprintf(MacAddr, "%02X-%02X-%02X-%02X-%02X-%02X",
130 Mac[0], Mac[1], Mac[2], Mac[3], Mac[4], Mac[5]);
131
132 return MacAddr;
133 }
134
135
136 /* convert time_t to localized string */
timeToStr(_In_ time_t TimeStamp)137 _Ret_opt_z_ PTSTR timeToStr(_In_ time_t TimeStamp)
138 {
139 struct tm* ptm;
140 SYSTEMTIME SystemTime;
141 INT DateCchSize, TimeCchSize, TotalCchSize, i;
142 PTSTR DateTimeString, psz;
143
144 /* Convert Unix time to SYSTEMTIME */
145 /* localtime_s may be preferred if available */
146 ptm = localtime(&TimeStamp);
147 if (!ptm)
148 {
149 return NULL;
150 }
151 SystemTime.wYear = ptm->tm_year + 1900;
152 SystemTime.wMonth = ptm->tm_mon + 1;
153 SystemTime.wDay = ptm->tm_mday;
154 SystemTime.wHour = ptm->tm_hour;
155 SystemTime.wMinute = ptm->tm_min;
156 SystemTime.wSecond = ptm->tm_sec;
157
158 /* Get total size in characters required of buffer */
159 DateCchSize = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &SystemTime, NULL, NULL, 0);
160 if (!DateCchSize)
161 {
162 return NULL;
163 }
164 TimeCchSize = GetTimeFormat(LOCALE_USER_DEFAULT, 0, &SystemTime, NULL, NULL, 0);
165 if (!TimeCchSize)
166 {
167 return NULL;
168 }
169 /* Two terminating null are included, the first one will be replaced by space */
170 TotalCchSize = DateCchSize + TimeCchSize;
171
172 /* Allocate buffer and format datetime string */
173 DateTimeString = (PTSTR)HeapAlloc(ProcessHeap, 0, TotalCchSize * sizeof(TCHAR));
174 if (!DateTimeString)
175 {
176 return NULL;
177 }
178
179 /* Get date string */
180 i = GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &SystemTime, NULL, DateTimeString, TotalCchSize);
181 if (i)
182 {
183 /* Append space and move pointer */
184 DateTimeString[i - 1] = _T(' ');
185 psz = DateTimeString + i;
186 TotalCchSize -= i;
187
188 /* Get time string */
189 if (GetTimeFormat(LOCALE_USER_DEFAULT, 0, &SystemTime, NULL, psz, TotalCchSize))
190 {
191 return DateTimeString;
192 }
193 }
194
195 HeapFree(ProcessHeap, 0, DateTimeString);
196 return NULL;
197 }
198
199
DoFormatMessage(LONG ErrorCode)200 VOID DoFormatMessage(LONG ErrorCode)
201 {
202 LPVOID lpMsgBuf;
203 //DWORD ErrorCode;
204
205 if (ErrorCode == 0)
206 ErrorCode = GetLastError();
207
208 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
209 FORMAT_MESSAGE_FROM_SYSTEM |
210 FORMAT_MESSAGE_IGNORE_INSERTS,
211 NULL,
212 ErrorCode,
213 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
214 (LPTSTR) &lpMsgBuf,
215 0,
216 NULL))
217 {
218 _tprintf(_T("%s"), (LPTSTR)lpMsgBuf);
219 LocalFree(lpMsgBuf);
220 }
221 }
222
223 VOID
GetAdapterFriendlyName(_In_ LPSTR lpClass,_In_ DWORD cchFriendlyNameLength,_Out_ LPWSTR pszFriendlyName)224 GetAdapterFriendlyName(
225 _In_ LPSTR lpClass,
226 _In_ DWORD cchFriendlyNameLength,
227 _Out_ LPWSTR pszFriendlyName)
228 {
229 HKEY hKey = NULL;
230 CHAR Path[256];
231 LPSTR PrePath = "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
232 LPSTR PostPath = "\\Connection";
233 DWORD PathSize;
234 DWORD dwType;
235 DWORD dwDataSize;
236
237 /* don't overflow the buffer */
238 PathSize = strlen(PrePath) + strlen(lpClass) + strlen(PostPath) + 1;
239 if (PathSize >= 255)
240 return;
241
242 sprintf(Path, "%s%s%s", PrePath, lpClass, PostPath);
243
244 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
245 Path,
246 0,
247 KEY_READ,
248 &hKey) == ERROR_SUCCESS)
249 {
250 dwDataSize = cchFriendlyNameLength * sizeof(WCHAR);
251 RegQueryValueExW(hKey,
252 L"Name",
253 NULL,
254 &dwType,
255 (PBYTE)pszFriendlyName,
256 &dwDataSize);
257 }
258
259 if (hKey != NULL)
260 RegCloseKey(hKey);
261 }
262
263 VOID
GetInterfaceFriendlyName(_In_ LPWSTR lpDeviceName,_In_ DWORD cchFriendlyNameLength,_Out_ LPWSTR pszFriendlyName)264 GetInterfaceFriendlyName(
265 _In_ LPWSTR lpDeviceName,
266 _In_ DWORD cchFriendlyNameLength,
267 _Out_ LPWSTR pszFriendlyName)
268 {
269 HKEY hKey = NULL;
270 WCHAR Path[256];
271 LPWSTR PrePath = L"SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
272 LPWSTR PostPath = L"\\Connection";
273 LPWSTR DevicePrefix = L"\\DEVICE\\TCPIP_";
274 DWORD PathSize;
275 DWORD dwType;
276 DWORD dwDataSize;
277
278 DWORD dwPrefixLength = wcslen(DevicePrefix);
279
280 /* don't overflow the buffer */
281 PathSize = wcslen(PrePath) + wcslen(lpDeviceName) - dwPrefixLength + wcslen(PostPath) + 1;
282 if (PathSize >= 255)
283 return;
284
285 swprintf(Path, L"%s%s%s", PrePath, &lpDeviceName[dwPrefixLength], PostPath);
286
287 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
288 Path,
289 0,
290 KEY_READ,
291 &hKey) == ERROR_SUCCESS)
292 {
293 dwDataSize = cchFriendlyNameLength * sizeof(WCHAR);
294 RegQueryValueExW(hKey,
295 L"Name",
296 NULL,
297 &dwType,
298 (PBYTE)pszFriendlyName,
299 &dwDataSize);
300 }
301
302 if (hKey != NULL)
303 RegCloseKey(hKey);
304 }
305
306 static
307 VOID
PrintAdapterDescription(LPSTR lpClass)308 PrintAdapterDescription(LPSTR lpClass)
309 {
310 HKEY hBaseKey = NULL;
311 HKEY hClassKey = NULL;
312 LPSTR lpKeyClass = NULL;
313 LPSTR lpConDesc = NULL;
314 LPTSTR lpPath = NULL;
315 TCHAR szPrePath[] = _T("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\");
316 DWORD dwType;
317 DWORD dwDataSize;
318 INT i;
319
320 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
321 szPrePath,
322 0,
323 KEY_READ,
324 &hBaseKey) != ERROR_SUCCESS)
325 {
326 return;
327 }
328
329 for (i = 0; ; i++)
330 {
331 DWORD PathSize;
332 LONG Status;
333 TCHAR szName[10];
334 DWORD NameLen = 9;
335
336 if ((Status = RegEnumKeyEx(hBaseKey,
337 i,
338 szName,
339 &NameLen,
340 NULL,
341 NULL,
342 NULL,
343 NULL)) != ERROR_SUCCESS)
344 {
345 if (Status == ERROR_NO_MORE_ITEMS)
346 {
347 DoFormatMessage(Status);
348 lpConDesc = NULL;
349 goto CLEANUP;
350 }
351 else
352 continue;
353 }
354
355 PathSize = lstrlen(szPrePath) + lstrlen(szName) + 1;
356 lpPath = (LPTSTR)HeapAlloc(ProcessHeap,
357 0,
358 PathSize * sizeof(TCHAR));
359 if (lpPath == NULL)
360 goto CLEANUP;
361
362 wsprintf(lpPath, _T("%s%s"), szPrePath, szName);
363
364 //MessageBox(NULL, lpPath, NULL, 0);
365
366 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
367 lpPath,
368 0,
369 KEY_READ,
370 &hClassKey) != ERROR_SUCCESS)
371 {
372 goto CLEANUP;
373 }
374
375 HeapFree(ProcessHeap, 0, lpPath);
376 lpPath = NULL;
377
378 if (RegQueryValueExA(hClassKey,
379 "NetCfgInstanceId",
380 NULL,
381 &dwType,
382 NULL,
383 &dwDataSize) == ERROR_SUCCESS)
384 {
385 lpKeyClass = (LPSTR)HeapAlloc(ProcessHeap,
386 0,
387 dwDataSize);
388 if (lpKeyClass == NULL)
389 goto CLEANUP;
390
391 if (RegQueryValueExA(hClassKey,
392 "NetCfgInstanceId",
393 NULL,
394 &dwType,
395 (PBYTE)lpKeyClass,
396 &dwDataSize) != ERROR_SUCCESS)
397 {
398 HeapFree(ProcessHeap, 0, lpKeyClass);
399 lpKeyClass = NULL;
400 continue;
401 }
402 }
403 else
404 continue;
405
406 if (!strcmp(lpClass, lpKeyClass))
407 {
408 HeapFree(ProcessHeap, 0, lpKeyClass);
409 lpKeyClass = NULL;
410
411 if (RegQueryValueExA(hClassKey,
412 "DriverDesc",
413 NULL,
414 &dwType,
415 NULL,
416 &dwDataSize) == ERROR_SUCCESS)
417 {
418 lpConDesc = (LPSTR)HeapAlloc(ProcessHeap,
419 0,
420 dwDataSize);
421 if (lpConDesc != NULL)
422 {
423 if (RegQueryValueExA(hClassKey,
424 "DriverDesc",
425 NULL,
426 &dwType,
427 (PBYTE)lpConDesc,
428 &dwDataSize) == ERROR_SUCCESS)
429 {
430 printf("%s", lpConDesc);
431 }
432
433 HeapFree(ProcessHeap, 0, lpConDesc);
434 lpConDesc = NULL;
435 }
436 }
437
438 break;
439 }
440 }
441
442 CLEANUP:
443 if (hBaseKey != NULL)
444 RegCloseKey(hBaseKey);
445 if (hClassKey != NULL)
446 RegCloseKey(hClassKey);
447 if (lpPath != NULL)
448 HeapFree(ProcessHeap, 0, lpPath);
449 if (lpKeyClass != NULL)
450 HeapFree(ProcessHeap, 0, lpKeyClass);
451 }
452
453 static
454 VOID
PrintNodeType(_In_ UINT NodeType)455 PrintNodeType(
456 _In_ UINT NodeType)
457 {
458 switch (NodeType)
459 {
460 case BROADCAST_NODETYPE:
461 ConResPrintf(StdOut, IDS_NODETYPEBCAST);
462 break;
463
464 case PEER_TO_PEER_NODETYPE:
465 ConResPrintf(StdOut, IDS_NODETYPEP2P);
466 break;
467
468 case MIXED_NODETYPE:
469 ConResPrintf(StdOut, IDS_NODETYPEMIXED);
470 break;
471
472 case HYBRID_NODETYPE:
473 ConResPrintf(StdOut, IDS_NODETYPEHYBRID);
474 break;
475
476 default :
477 ConResPrintf(StdOut, IDS_NODETYPEUNKNOWN);
478 break;
479 }
480 }
481
482 static
483 VOID
PrintAdapterTypeAndName(PIP_ADAPTER_INFO pAdapterInfo)484 PrintAdapterTypeAndName(
485 PIP_ADAPTER_INFO pAdapterInfo)
486 {
487 WCHAR szFriendlyName[MAX_PATH];
488
489 GetAdapterFriendlyName(pAdapterInfo->AdapterName, MAX_PATH, szFriendlyName);
490
491 switch (pAdapterInfo->Type)
492 {
493 case MIB_IF_TYPE_OTHER:
494 ConResPrintf(StdOut, IDS_OTHER, szFriendlyName);
495 break;
496
497 case MIB_IF_TYPE_ETHERNET:
498 ConResPrintf(StdOut, IDS_ETH, szFriendlyName);
499 break;
500
501 case MIB_IF_TYPE_TOKENRING:
502 ConResPrintf(StdOut, IDS_TOKEN, szFriendlyName);
503 break;
504
505 case MIB_IF_TYPE_FDDI:
506 ConResPrintf(StdOut, IDS_FDDI, szFriendlyName);
507 break;
508
509 case MIB_IF_TYPE_PPP:
510 ConResPrintf(StdOut, IDS_PPP, szFriendlyName);
511 break;
512
513 case MIB_IF_TYPE_LOOPBACK:
514 ConResPrintf(StdOut, IDS_LOOP, szFriendlyName);
515 break;
516
517 case MIB_IF_TYPE_SLIP:
518 ConResPrintf(StdOut, IDS_SLIP, szFriendlyName);
519 break;
520
521 case IF_TYPE_IEEE80211:
522 ConResPrintf(StdOut, IDS_WIFI, szFriendlyName);
523 break;
524
525 default:
526 ConResPrintf(StdOut, IDS_UNKNOWNADAPTER, szFriendlyName);
527 break;
528 }
529 }
530
531 VOID
ShowInfo(BOOL bShowHeader,BOOL bAll)532 ShowInfo(
533 BOOL bShowHeader,
534 BOOL bAll)
535 {
536 MIB_IFROW mibEntry;
537 PIP_ADAPTER_INFO pAdapterInfo = NULL;
538 PIP_ADAPTER_INFO pAdapter = NULL;
539 ULONG adaptOutBufLen = 0;
540 PFIXED_INFO pFixedInfo = NULL;
541 ULONG netOutBufLen = 0;
542 PIP_PER_ADAPTER_INFO pPerAdapterInfo = NULL;
543 ULONG ulPerAdapterInfoLength = 0;
544 PSTR pszDomainName = NULL;
545 DWORD dwDomainNameSize = 0;
546 ULONG ret = 0;
547
548 GetComputerNameExA(ComputerNameDnsDomain,
549 NULL,
550 &dwDomainNameSize);
551 if (dwDomainNameSize > 0)
552 {
553 pszDomainName = HeapAlloc(ProcessHeap,
554 0,
555 dwDomainNameSize * sizeof(TCHAR));
556 if (pszDomainName != NULL)
557 GetComputerNameExA(ComputerNameDnsDomain,
558 pszDomainName,
559 &dwDomainNameSize);
560 }
561
562 /* call GetAdaptersInfo to obtain the adapter info */
563 ret = GetAdaptersInfo(pAdapterInfo, &adaptOutBufLen);
564 if (ret == ERROR_BUFFER_OVERFLOW)
565 {
566 pAdapterInfo = (IP_ADAPTER_INFO *)HeapAlloc(ProcessHeap, 0, adaptOutBufLen);
567 if (pAdapterInfo == NULL)
568 goto done;
569
570 ret = GetAdaptersInfo(pAdapterInfo, &adaptOutBufLen);
571 if (ret != NO_ERROR)
572 {
573 DoFormatMessage(0);
574 goto done;
575 }
576 }
577 else
578 {
579 if (ret != ERROR_NO_DATA)
580 {
581 DoFormatMessage(0);
582 goto done;
583 }
584 }
585
586 /* call GetNetworkParams to obtain the network info */
587 if (GetNetworkParams(pFixedInfo, &netOutBufLen) == ERROR_BUFFER_OVERFLOW)
588 {
589 pFixedInfo = (FIXED_INFO *)HeapAlloc(ProcessHeap, 0, netOutBufLen);
590 if (pFixedInfo == NULL)
591 {
592 goto done;
593 }
594 if (GetNetworkParams(pFixedInfo, &netOutBufLen) != NO_ERROR)
595 {
596 DoFormatMessage(0);
597 goto done;
598 }
599 }
600 else
601 {
602 DoFormatMessage(0);
603 goto done;
604 }
605
606 pAdapter = pAdapterInfo;
607
608 if (bShowHeader)
609 ConResPrintf(StdOut, IDS_HEADER);
610
611 if (bAll)
612 {
613 ConResPrintf(StdOut, IDS_HOSTNAME, pFixedInfo->HostName);
614 ConResPrintf(StdOut, IDS_PRIMARYDNSSUFFIX, (pszDomainName != NULL) ? pszDomainName : "");
615
616 PrintNodeType(pFixedInfo->NodeType);
617
618 if (pFixedInfo->EnableRouting)
619 ConResPrintf(StdOut, IDS_IPROUTINGYES);
620 else
621 ConResPrintf(StdOut, IDS_IPROUTINGNO);
622
623 if (pAdapter && pAdapter->HaveWins)
624 ConResPrintf(StdOut, IDS_WINSPROXYYES);
625 else
626 ConResPrintf(StdOut, IDS_WINSPROXYNO);
627
628 if (pszDomainName != NULL && pszDomainName[0] != 0)
629 {
630 ConResPrintf(StdOut, IDS_DNSSUFFIXLIST, pszDomainName);
631 ConResPrintf(StdOut, IDS_EMPTYLINE, pFixedInfo->DomainName);
632 }
633 else
634 {
635 ConResPrintf(StdOut, IDS_DNSSUFFIXLIST, pFixedInfo->DomainName);
636 }
637 }
638
639 while (pAdapter)
640 {
641 BOOLEAN bConnected = TRUE;
642
643 mibEntry.dwIndex = pAdapter->Index;
644 GetIfEntry(&mibEntry);
645
646 PrintAdapterTypeAndName(pAdapter);
647
648 if (GetPerAdapterInfo(pAdapter->Index, pPerAdapterInfo, &ulPerAdapterInfoLength) == ERROR_BUFFER_OVERFLOW)
649 {
650 pPerAdapterInfo = (PIP_PER_ADAPTER_INFO)HeapAlloc(ProcessHeap, 0, ulPerAdapterInfoLength);
651 if (pPerAdapterInfo != NULL)
652 {
653 GetPerAdapterInfo(pAdapter->Index, pPerAdapterInfo, &ulPerAdapterInfoLength);
654 }
655 }
656
657 /* check if the adapter is connected to the media */
658 if (mibEntry.dwOperStatus != MIB_IF_OPER_STATUS_CONNECTED && mibEntry.dwOperStatus != MIB_IF_OPER_STATUS_OPERATIONAL)
659 {
660 bConnected = FALSE;
661 ConResPrintf(StdOut, IDS_MEDIADISCONNECTED);
662 }
663 else
664 {
665 ConResPrintf(StdOut, IDS_CONNECTIONDNSSUFFIX, pFixedInfo->DomainName);
666 }
667
668 if (bAll)
669 {
670 ConResPrintf(StdOut, IDS_DESCRIPTION);
671 PrintAdapterDescription(pAdapter->AdapterName);
672 printf("\n");
673
674 ConResPrintf(StdOut, IDS_PHYSICALADDRESS, PrintMacAddr(pAdapter->Address));
675
676 if (bConnected)
677 {
678 if (pAdapter->DhcpEnabled)
679 {
680 ConResPrintf(StdOut, IDS_DHCPYES);
681
682 if (pPerAdapterInfo != NULL)
683 {
684 if (pPerAdapterInfo->AutoconfigEnabled)
685 ConResPrintf(StdOut, IDS_AUTOCONFIGYES);
686 else
687 ConResPrintf(StdOut, IDS_AUTOCONFIGNO);
688 }
689 }
690 else
691 {
692 ConResPrintf(StdOut, IDS_DHCPNO);
693 }
694 }
695 }
696
697 if (!bConnected)
698 {
699 pAdapter = pAdapter->Next;
700 continue;
701 }
702
703 ConResPrintf(StdOut, IDS_IPADDRESS, pAdapter->IpAddressList.IpAddress.String);
704 ConResPrintf(StdOut, IDS_SUBNETMASK, pAdapter->IpAddressList.IpMask.String);
705
706 if (strcmp(pAdapter->GatewayList.IpAddress.String, "0.0.0.0"))
707 ConResPrintf(StdOut, IDS_DEFAULTGATEWAY, pAdapter->GatewayList.IpAddress.String);
708 else
709 ConResPrintf(StdOut, IDS_DEFAULTGATEWAY, "");
710
711 if (bAll)
712 {
713 PIP_ADDR_STRING pIPAddr;
714
715 if (pAdapter->DhcpEnabled)
716 ConResPrintf(StdOut, IDS_DHCPSERVER, pAdapter->DhcpServer.IpAddress.String);
717
718 ConResPrintf(StdOut, IDS_DNSSERVERS, pFixedInfo->DnsServerList.IpAddress.String);
719 pIPAddr = pFixedInfo->DnsServerList.Next;
720 while (pIPAddr)
721 {
722 ConResPrintf(StdOut, IDS_EMPTYLINE, pIPAddr ->IpAddress.String);
723 pIPAddr = pIPAddr->Next;
724 }
725
726 if (pAdapter->HaveWins)
727 {
728 ConResPrintf(StdOut, IDS_PRIMARYWINSSERVER, pAdapter->PrimaryWinsServer.IpAddress.String);
729 ConResPrintf(StdOut, IDS_SECONDARYWINSSERVER, pAdapter->SecondaryWinsServer.IpAddress.String);
730 }
731
732 if (pAdapter->DhcpEnabled && strcmp(pAdapter->DhcpServer.IpAddress.String, "255.255.255.255"))
733 {
734 PTSTR DateTimeString;
735 DateTimeString = timeToStr(pAdapter->LeaseObtained);
736 ConResPrintf(StdOut, IDS_LEASEOBTAINED, DateTimeString ? DateTimeString : _T("N/A"));
737 if (DateTimeString)
738 {
739 HeapFree(ProcessHeap, 0, DateTimeString);
740 }
741 DateTimeString = timeToStr(pAdapter->LeaseExpires);
742 ConResPrintf(StdOut, IDS_LEASEEXPIRES, DateTimeString ? DateTimeString : _T("N/A"));
743 if (DateTimeString)
744 {
745 HeapFree(ProcessHeap, 0, DateTimeString);
746 }
747 }
748 }
749
750 HeapFree(ProcessHeap, 0, pPerAdapterInfo);
751 pPerAdapterInfo = NULL;
752
753 pAdapter = pAdapter->Next;
754 }
755
756 done:
757 if (pszDomainName)
758 HeapFree(ProcessHeap, 0, pszDomainName);
759 if (pFixedInfo)
760 HeapFree(ProcessHeap, 0, pFixedInfo);
761 if (pAdapterInfo)
762 HeapFree(ProcessHeap, 0, pAdapterInfo);
763 }
764
765 static
766 BOOL
MatchWildcard(_In_ PWSTR pszExpression,_In_ PWSTR pszName)767 MatchWildcard(
768 _In_ PWSTR pszExpression,
769 _In_ PWSTR pszName)
770 {
771 WCHAR *pCharE, *pCharN, charE, charN;
772
773 if (pszExpression == NULL)
774 return TRUE;
775
776 if (pszName == NULL)
777 return FALSE;
778
779 pCharE = pszExpression;
780 pCharN = pszName;
781 while (*pCharE != UNICODE_NULL)
782 {
783 charE = towlower(*pCharE);
784 charN = towlower(*pCharN);
785
786 if (charE == L'*')
787 {
788 if (*(pCharE + 1) != charN)
789 pCharN++;
790 else
791 pCharE++;
792 }
793 else if (charE == L'?')
794 {
795 pCharE++;
796 pCharN++;
797 }
798 else if (charE == charN)
799 {
800 pCharE++;
801 pCharN++;
802 }
803 else
804 {
805 return FALSE;
806 }
807 }
808
809 return TRUE;
810 }
811
812 static
813 VOID
BuildAdapterMap(PIP_ADAPTER_INDEX_MAP pAdapterMap,PIP_ADAPTER_INFO pAdapterInfo)814 BuildAdapterMap(
815 PIP_ADAPTER_INDEX_MAP pAdapterMap,
816 PIP_ADAPTER_INFO pAdapterInfo)
817 {
818 int i, l1, l2;
819
820 pAdapterMap->Index = pAdapterInfo->Index;
821
822 wcscpy(pAdapterMap->Name, L"\\DEVICE\\TCPIP_");
823 l1 = wcslen(pAdapterMap->Name);
824 l2 = strlen(pAdapterInfo->AdapterName);
825 for (i = 0; i < l2; i++)
826 pAdapterMap->Name[i + l1] = (WCHAR)pAdapterInfo->AdapterName[i];
827 pAdapterMap->Name[i + l1] = UNICODE_NULL;
828 }
829
830 VOID
Release(LPWSTR pszAdapterName)831 Release(
832 LPWSTR pszAdapterName)
833 {
834 PIP_ADAPTER_INFO pAdapterInfo = NULL;
835 PIP_ADAPTER_INFO pAdapter = NULL;
836 ULONG adaptOutBufLen = 0;
837 ULONG ret = 0;
838 WCHAR szFriendlyName[MAX_PATH];
839 MIB_IFROW mibEntry;
840 IP_ADAPTER_INDEX_MAP AdapterMap;
841 BOOL bFoundAdapter = FALSE;
842
843 ConResPrintf(StdOut, IDS_HEADER);
844
845 /* call GetAdaptersInfo to obtain the adapter info */
846 ret = GetAdaptersInfo(pAdapterInfo, &adaptOutBufLen);
847 if (ret != ERROR_BUFFER_OVERFLOW)
848 {
849 DoFormatMessage(ret);
850 return;
851 }
852
853 pAdapterInfo = (IP_ADAPTER_INFO *)HeapAlloc(ProcessHeap, 0, adaptOutBufLen);
854 if (pAdapterInfo == NULL)
855 {
856 _tprintf(_T("memory allocation error"));
857 return;
858 }
859
860 ret = GetAdaptersInfo(pAdapterInfo, &adaptOutBufLen);
861 if (ret != NO_ERROR)
862 {
863 DoFormatMessage(0);
864 goto done;
865 }
866
867 pAdapter = pAdapterInfo;
868
869 while (pAdapter)
870 {
871 GetAdapterFriendlyName(pAdapter->AdapterName, MAX_PATH, szFriendlyName);
872
873 if ((pszAdapterName == NULL) || MatchWildcard(pszAdapterName, szFriendlyName))
874 {
875 bFoundAdapter = TRUE;
876
877 mibEntry.dwIndex = pAdapter->Index;
878 GetIfEntry(&mibEntry);
879
880 if (mibEntry.dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED ||
881 mibEntry.dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL)
882 {
883 if (pAdapter->DhcpEnabled)
884 {
885 if (strcmp(pAdapter->IpAddressList.IpAddress.String, "0.0.0.0"))
886 {
887 BuildAdapterMap(&AdapterMap, pAdapter);
888
889 /* Call IpReleaseAddress to release the IP address on the specified adapter. */
890 ret = IpReleaseAddress(&AdapterMap);
891 if (ret != NO_ERROR)
892 {
893 ConResPrintf(StdOut, IDS_DHCPRELEASEERROR, szFriendlyName);
894 DoFormatMessage(ret);
895 }
896 }
897 else
898 {
899 ConResPrintf(StdOut, IDS_DHCPRELEASED);
900 }
901 }
902 else
903 {
904 ConResPrintf(StdOut, IDS_DHCPNOTENABLED, szFriendlyName);
905 }
906 }
907 else
908 {
909 ConResPrintf(StdOut, IDS_DHCPNOTCONNECTED, szFriendlyName);
910 }
911 }
912
913 pAdapter = pAdapter->Next;
914 }
915
916 if (bFoundAdapter == FALSE)
917 {
918 ConResPrintf(StdOut, IDS_DHCPNOADAPTER);
919 }
920 else
921 {
922 ShowInfo(FALSE, FALSE);
923 }
924
925 done:
926 if (pAdapterInfo)
927 HeapFree(ProcessHeap, 0, pAdapterInfo);
928 }
929
930 VOID
Renew(LPWSTR pszAdapterName)931 Renew(
932 LPWSTR pszAdapterName)
933 {
934 PIP_ADAPTER_INFO pAdapterInfo = NULL;
935 PIP_ADAPTER_INFO pAdapter = NULL;
936 ULONG adaptOutBufLen = 0;
937 ULONG ret = 0;
938 WCHAR szFriendlyName[MAX_PATH];
939 MIB_IFROW mibEntry;
940 IP_ADAPTER_INDEX_MAP AdapterMap;
941 BOOL bFoundAdapter = FALSE;
942
943 ConResPrintf(StdOut, IDS_HEADER);
944
945 /* call GetAdaptersInfo to obtain the adapter info */
946 ret = GetAdaptersInfo(pAdapterInfo, &adaptOutBufLen);
947 if (ret != ERROR_BUFFER_OVERFLOW)
948 {
949 DoFormatMessage(ret);
950 return;
951 }
952
953 pAdapterInfo = (IP_ADAPTER_INFO *)HeapAlloc(ProcessHeap, 0, adaptOutBufLen);
954 if (pAdapterInfo == NULL)
955 {
956 _tprintf(_T("memory allocation error"));
957 return;
958 }
959
960 ret = GetAdaptersInfo(pAdapterInfo, &adaptOutBufLen);
961 if (ret != NO_ERROR)
962 {
963 DoFormatMessage(0);
964 goto done;
965 }
966
967 pAdapter = pAdapterInfo;
968
969 while (pAdapter)
970 {
971 GetAdapterFriendlyName(pAdapter->AdapterName, MAX_PATH, szFriendlyName);
972
973 if ((pszAdapterName == NULL) || MatchWildcard(pszAdapterName, szFriendlyName))
974 {
975 bFoundAdapter = TRUE;
976
977 mibEntry.dwIndex = pAdapter->Index;
978 GetIfEntry(&mibEntry);
979
980 if (mibEntry.dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED ||
981 mibEntry.dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL)
982 {
983 if (pAdapter->DhcpEnabled)
984 {
985 BuildAdapterMap(&AdapterMap, pAdapter);
986
987 /* Call IpRenewAddress to renew the IP address on the specified adapter. */
988 ret = IpRenewAddress(&AdapterMap);
989 if (ret != NO_ERROR)
990 {
991 ConResPrintf(StdOut, IDS_DHCPRENEWERROR, szFriendlyName);
992 DoFormatMessage(ret);
993 }
994 }
995 else
996 {
997 ConResPrintf(StdOut, IDS_DHCPNOTENABLED, szFriendlyName);
998 }
999 }
1000 else
1001 {
1002 ConResPrintf(StdOut, IDS_DHCPNOTCONNECTED, szFriendlyName);
1003 }
1004 }
1005
1006 pAdapter = pAdapter->Next;
1007 }
1008
1009 if (bFoundAdapter == FALSE)
1010 {
1011 ConResPrintf(StdOut, IDS_DHCPNOADAPTER);
1012 }
1013 else
1014 {
1015 ShowInfo(FALSE, FALSE);
1016 }
1017
1018 done:
1019 if (pAdapterInfo)
1020 HeapFree(ProcessHeap, 0, pAdapterInfo);
1021 }
1022
1023 VOID
FlushDns(VOID)1024 FlushDns(VOID)
1025 {
1026 ConResPrintf(StdOut, IDS_HEADER);
1027
1028 if (DnsFlushResolverCache())
1029 {
1030 ConResPrintf(StdOut, IDS_DNSFLUSHSUCCESS);
1031 }
1032 else
1033 {
1034 ConResPrintf(StdOut, IDS_DNSFLUSHERROR);
1035 DoFormatMessage(GetLastError());
1036 }
1037 }
1038
1039 VOID
RegisterDns(VOID)1040 RegisterDns(VOID)
1041 {
1042 /* FIXME */
1043 _tprintf(_T("\nSorry /registerdns is not implemented yet\n"));
1044 }
1045
1046 static
1047 VOID
DisplayDnsRecord(PWSTR pszName,WORD wType)1048 DisplayDnsRecord(
1049 PWSTR pszName,
1050 WORD wType)
1051 {
1052 PDNS_RECORDW pQueryResults = NULL, pThisRecord, pNextRecord;
1053 WCHAR szBuffer[48];
1054 IN_ADDR Addr4;
1055 IN6_ADDR Addr6;
1056 DNS_STATUS Status;
1057
1058 ConResPrintf(StdOut, IDS_DNSNAME, pszName);
1059 ConResPrintf(StdOut, IDS_DNSLINE);
1060
1061 pQueryResults = NULL;
1062 Status = DnsQuery_W(pszName,
1063 wType,
1064 DNS_QUERY_NO_WIRE_QUERY,
1065 NULL,
1066 (PDNS_RECORD *)&pQueryResults,
1067 NULL);
1068 if (Status != ERROR_SUCCESS)
1069 {
1070 if (Status == DNS_ERROR_RCODE_NAME_ERROR)
1071 {
1072 ConResPrintf(StdOut, IDS_DNSNONAME);
1073 }
1074 else if (Status == DNS_INFO_NO_RECORDS)
1075 {
1076 ConResPrintf(StdOut, IDS_DNSNORECORD, GetRecordTypeName(wType));
1077 }
1078 return;
1079 }
1080
1081 pThisRecord = pQueryResults;
1082 while (pThisRecord != NULL)
1083 {
1084 pNextRecord = pThisRecord->pNext;
1085
1086 ConResPrintf(StdOut, IDS_DNSRECORDNAME, pThisRecord->pName);
1087 ConResPrintf(StdOut, IDS_DNSRECORDTYPE, pThisRecord->wType);
1088 ConResPrintf(StdOut, IDS_DNSRECORDTTL, pThisRecord->dwTtl);
1089 ConResPrintf(StdOut, IDS_DNSRECORDLENGTH, pThisRecord->wDataLength);
1090
1091 switch (pThisRecord->Flags.S.Section)
1092 {
1093 case DnsSectionQuestion:
1094 ConResPrintf(StdOut, IDS_DNSSECTIONQUESTION);
1095 break;
1096
1097 case DnsSectionAnswer:
1098 ConResPrintf(StdOut, IDS_DNSSECTIONANSWER);
1099 break;
1100
1101 case DnsSectionAuthority:
1102 ConResPrintf(StdOut, IDS_DNSSECTIONAUTHORITY);
1103 break;
1104
1105 case DnsSectionAdditional:
1106 ConResPrintf(StdOut, IDS_DNSSECTIONADDITIONAL);
1107 break;
1108 }
1109
1110 switch (pThisRecord->wType)
1111 {
1112 case DNS_TYPE_A:
1113 Addr4.S_un.S_addr = pThisRecord->Data.A.IpAddress;
1114 RtlIpv4AddressToStringW(&Addr4, szBuffer);
1115 ConResPrintf(StdOut, IDS_DNSTYPEA, szBuffer);
1116 break;
1117
1118 case DNS_TYPE_NS:
1119 ConResPrintf(StdOut, IDS_DNSTYPENS, pThisRecord->Data.NS.pNameHost);
1120 break;
1121
1122 case DNS_TYPE_CNAME:
1123 ConResPrintf(StdOut, IDS_DNSTYPECNAME, pThisRecord->Data.CNAME.pNameHost);
1124 break;
1125
1126 case DNS_TYPE_SOA:
1127 ConResPrintf(StdOut, IDS_DNSTYPESOA1,
1128 pThisRecord->Data.SOA.pNamePrimaryServer,
1129 pThisRecord->Data.SOA.pNameAdministrator,
1130 pThisRecord->Data.SOA.dwSerialNo);
1131 ConResPrintf(StdOut, IDS_DNSTYPESOA2,
1132 pThisRecord->Data.SOA.dwRefresh,
1133 pThisRecord->Data.SOA.dwRetry,
1134 pThisRecord->Data.SOA.dwExpire,
1135 pThisRecord->Data.SOA.dwDefaultTtl);
1136 break;
1137
1138 case DNS_TYPE_PTR:
1139 ConResPrintf(StdOut, IDS_DNSTYPEPTR, pThisRecord->Data.PTR.pNameHost);
1140 break;
1141
1142 case DNS_TYPE_MX:
1143 ConResPrintf(StdOut, IDS_DNSTYPEMX,
1144 pThisRecord->Data.MX.pNameExchange,
1145 pThisRecord->Data.MX.wPreference,
1146 pThisRecord->Data.MX.Pad);
1147 break;
1148
1149 case DNS_TYPE_AAAA:
1150 RtlCopyMemory(&Addr6, &pThisRecord->Data.AAAA.Ip6Address, sizeof(IN6_ADDR));
1151 RtlIpv6AddressToStringW(&Addr6, szBuffer);
1152 ConResPrintf(StdOut, IDS_DNSTYPEAAAA, szBuffer);
1153 break;
1154
1155 case DNS_TYPE_ATMA:
1156 ConResPrintf(StdOut, IDS_DNSTYPEATMA);
1157 break;
1158
1159 case DNS_TYPE_SRV:
1160 ConResPrintf(StdOut, IDS_DNSTYPESRV,
1161 pThisRecord->Data.SRV.pNameTarget,
1162 pThisRecord->Data.SRV.wPriority,
1163 pThisRecord->Data.SRV.wWeight,
1164 pThisRecord->Data.SRV.wPort);
1165 break;
1166 }
1167 ConPuts(StdOut, L"\n\n");
1168
1169 pThisRecord = pNextRecord;
1170 }
1171
1172 DnsRecordListFree((PDNS_RECORD)pQueryResults, DnsFreeRecordList);
1173 }
1174
1175 VOID
DisplayDns(VOID)1176 DisplayDns(VOID)
1177 {
1178 PDNS_CACHE_ENTRY DnsEntry = NULL, pThisEntry, pNextEntry;
1179
1180 ConResPrintf(StdOut, IDS_HEADER);
1181
1182 if (!DnsGetCacheDataTable(&DnsEntry))
1183 {
1184 DoFormatMessage(GetLastError());
1185 return;
1186 }
1187
1188 if (DnsEntry == NULL)
1189 return;
1190
1191 pThisEntry = DnsEntry;
1192 while (pThisEntry != NULL)
1193 {
1194 pNextEntry = pThisEntry->pNext;
1195
1196 if (pThisEntry->wType1 != DNS_TYPE_ZERO)
1197 DisplayDnsRecord(pThisEntry->pszName, pThisEntry->wType1);
1198
1199 if (pThisEntry->wType2 != DNS_TYPE_ZERO)
1200 DisplayDnsRecord(pThisEntry->pszName, pThisEntry->wType2);
1201
1202 if (pThisEntry->pszName)
1203 LocalFree(pThisEntry->pszName);
1204 LocalFree(pThisEntry);
1205
1206 pThisEntry = pNextEntry;
1207 }
1208 }
1209
Usage(VOID)1210 VOID Usage(VOID)
1211 {
1212 ConResPrintf(StdOut, IDS_USAGE);
1213 }
1214
wmain(int argc,wchar_t * argv[])1215 int wmain(int argc, wchar_t *argv[])
1216 {
1217 BOOL DoUsage=FALSE;
1218 BOOL DoAll=FALSE;
1219 BOOL DoRelease=FALSE;
1220 BOOL DoRenew=FALSE;
1221 BOOL DoFlushdns=FALSE;
1222 BOOL DoRegisterdns=FALSE;
1223 BOOL DoDisplaydns=FALSE;
1224 BOOL DoShowclassid=FALSE;
1225 BOOL DoSetclassid=FALSE;
1226
1227 /* Initialize the Console Standard Streams */
1228 ConInitStdStreams();
1229
1230 hInstance = GetModuleHandle(NULL);
1231 ProcessHeap = GetProcessHeap();
1232
1233 /* Parse command line for options we have been given. */
1234 if ((argc > 1) && (argv[1][0]=='/' || argv[1][0]=='-'))
1235 {
1236 if (!_tcsicmp(&argv[1][1], _T("?")))
1237 {
1238 DoUsage = TRUE;
1239 }
1240 else if (!_tcsnicmp(&argv[1][1], _T("ALL"), _tcslen(&argv[1][1])))
1241 {
1242 DoAll = TRUE;
1243 }
1244 else if (!_tcsnicmp(&argv[1][1], _T("RELEASE"), _tcslen(&argv[1][1])))
1245 {
1246 DoRelease = TRUE;
1247 }
1248 else if (!_tcsnicmp(&argv[1][1], _T("RENEW"), _tcslen(&argv[1][1])))
1249 {
1250 DoRenew = TRUE;
1251 }
1252 else if (!_tcsnicmp(&argv[1][1], _T("FLUSHDNS"), _tcslen(&argv[1][1])))
1253 {
1254 DoFlushdns = TRUE;
1255 }
1256 else if (!_tcsnicmp(&argv[1][1], _T("FLUSHREGISTERDNS"), _tcslen(&argv[1][1])))
1257 {
1258 DoRegisterdns = TRUE;
1259 }
1260 else if (!_tcsnicmp(&argv[1][1], _T("DISPLAYDNS"), _tcslen(&argv[1][1])))
1261 {
1262 DoDisplaydns = TRUE;
1263 }
1264 else if (!_tcsnicmp(&argv[1][1], _T("SHOWCLASSID"), _tcslen(&argv[1][1])))
1265 {
1266 DoShowclassid = TRUE;
1267 }
1268 else if (!_tcsnicmp(&argv[1][1], _T("SETCLASSID"), _tcslen(&argv[1][1])))
1269 {
1270 DoSetclassid = TRUE;
1271 }
1272 }
1273
1274 switch (argc)
1275 {
1276 case 1: /* Default behaviour if no options are given*/
1277 ShowInfo(TRUE, FALSE);
1278 break;
1279 case 2: /* Process all the options that take no parameters */
1280 if (DoUsage)
1281 Usage();
1282 else if (DoAll)
1283 ShowInfo(TRUE, TRUE);
1284 else if (DoRelease)
1285 Release(NULL);
1286 else if (DoRenew)
1287 Renew(NULL);
1288 else if (DoFlushdns)
1289 FlushDns();
1290 else if (DoRegisterdns)
1291 RegisterDns();
1292 else if (DoDisplaydns)
1293 DisplayDns();
1294 else
1295 Usage();
1296 break;
1297 case 3: /* Process all the options that can have 1 parameter */
1298 if (DoRelease)
1299 Release(argv[2]);
1300 else if (DoRenew)
1301 Renew(argv[2]);
1302 else if (DoShowclassid)
1303 _tprintf(_T("\nSorry /showclassid adapter is not implemented yet\n"));
1304 else if (DoSetclassid)
1305 _tprintf(_T("\nSorry /setclassid adapter is not implemented yet\n"));
1306 else
1307 Usage();
1308 break;
1309 case 4: /* Process all the options that can have 2 parameters */
1310 if (DoSetclassid)
1311 _tprintf(_T("\nSorry /setclassid adapter [classid]is not implemented yet\n"));
1312 else
1313 Usage();
1314 break;
1315 default:
1316 Usage();
1317 }
1318
1319 return 0;
1320 }
1321