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 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 */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 1040 RegisterDns(VOID) 1041 { 1042 /* FIXME */ 1043 _tprintf(_T("\nSorry /registerdns is not implemented yet\n")); 1044 } 1045 1046 static 1047 VOID 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 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 1210 VOID Usage(VOID) 1211 { 1212 ConResPrintf(StdOut, IDS_USAGE); 1213 } 1214 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