1 /* 2 * PROJECT: ReactOS ipconfig utility 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/applications/network/ipconfig/ipconfig.c 5 * PURPOSE: Display IP info for net adapters 6 * PROGRAMMERS: Copyright 2005 - 2006 Ged Murphy (gedmurphy@gmail.com) 7 */ 8 /* 9 * TODO: 10 * fix renew / release 11 * implement registerdns, showclassid, setclassid 12 * allow globbing on adapter names 13 */ 14 15 #define WIN32_NO_STATUS 16 #include <stdarg.h> 17 #include <windef.h> 18 #include <winbase.h> 19 #include <winuser.h> 20 #include <winreg.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 30 #include "resource.h" 31 32 #define GUID_LEN 40 33 34 HINSTANCE hInstance; 35 HANDLE ProcessHeap; 36 37 int LoadStringAndOem(HINSTANCE hInst, 38 UINT uID, 39 LPTSTR szNode, 40 int byteSize) 41 { 42 TCHAR *szTmp; 43 int res; 44 45 szTmp = (LPTSTR)HeapAlloc(ProcessHeap, 0, byteSize); 46 if (szTmp == NULL) 47 { 48 return 0; 49 } 50 51 res = LoadString(hInst, uID, szTmp, byteSize); 52 CharToOem(szTmp, szNode); 53 HeapFree(ProcessHeap, 0, szTmp); 54 return res; 55 } 56 57 LPTSTR GetNodeTypeName(UINT NodeType) 58 { 59 static TCHAR szNode[14]; 60 61 switch (NodeType) 62 { 63 case 1: 64 if (!LoadStringAndOem(hInstance, IDS_BCAST, szNode, sizeof(szNode))) 65 return NULL; 66 break; 67 68 case 2: 69 if (!LoadStringAndOem(hInstance, IDS_P2P, szNode, sizeof(szNode))) 70 return NULL; 71 break; 72 73 case 4: 74 if (!LoadStringAndOem(hInstance, IDS_MIXED, szNode, sizeof(szNode))) 75 return NULL; 76 break; 77 78 case 8: 79 if (!LoadStringAndOem(hInstance, IDS_HYBRID, szNode, sizeof(szNode))) 80 return NULL; 81 break; 82 83 default : 84 if (!LoadStringAndOem(hInstance, IDS_UNKNOWN, szNode, sizeof(szNode))) 85 return NULL; 86 break; 87 } 88 89 return szNode; 90 } 91 92 93 LPTSTR GetInterfaceTypeName(UINT InterfaceType) 94 { 95 static TCHAR szIntType[25]; 96 97 switch (InterfaceType) 98 { 99 case MIB_IF_TYPE_OTHER: 100 if (!LoadStringAndOem(hInstance, IDS_OTHER, szIntType, sizeof(szIntType))) 101 return NULL; 102 break; 103 104 case MIB_IF_TYPE_ETHERNET: 105 if (!LoadStringAndOem(hInstance, IDS_ETH, szIntType, sizeof(szIntType))) 106 return NULL; 107 break; 108 109 case MIB_IF_TYPE_TOKENRING: 110 if (!LoadStringAndOem(hInstance, IDS_TOKEN, szIntType, sizeof(szIntType))) 111 return NULL; 112 break; 113 114 case MIB_IF_TYPE_FDDI: 115 if (!LoadStringAndOem(hInstance, IDS_FDDI, szIntType, sizeof(szIntType))) 116 return NULL; 117 break; 118 119 case MIB_IF_TYPE_PPP: 120 if (!LoadStringAndOem(hInstance, IDS_PPP, szIntType, sizeof(szIntType))) 121 return NULL; 122 break; 123 124 case MIB_IF_TYPE_LOOPBACK: 125 if (!LoadStringAndOem(hInstance, IDS_LOOP, szIntType, sizeof(szIntType))) 126 return NULL; 127 break; 128 129 case MIB_IF_TYPE_SLIP: 130 if (!LoadStringAndOem(hInstance, IDS_SLIP, szIntType, sizeof(szIntType))) 131 return NULL; 132 break; 133 134 default: 135 if (!LoadStringAndOem(hInstance, IDS_UNKNOWN, szIntType, sizeof(szIntType))) 136 return NULL; 137 break; 138 } 139 140 return szIntType; 141 } 142 143 144 /* print MAC address */ 145 PTCHAR PrintMacAddr(PBYTE Mac) 146 { 147 static TCHAR MacAddr[20]; 148 149 _stprintf(MacAddr, _T("%02x-%02x-%02x-%02x-%02x-%02x"), 150 Mac[0], Mac[1], Mac[2], Mac[3], Mac[4], Mac[5]); 151 152 return MacAddr; 153 } 154 155 156 VOID DoFormatMessage(LONG ErrorCode) 157 { 158 LPVOID lpMsgBuf; 159 //DWORD ErrorCode; 160 161 if (ErrorCode == 0) 162 ErrorCode = GetLastError(); 163 164 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 165 FORMAT_MESSAGE_FROM_SYSTEM | 166 FORMAT_MESSAGE_IGNORE_INSERTS, 167 NULL, 168 ErrorCode, 169 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ 170 (LPTSTR) &lpMsgBuf, 171 0, 172 NULL)) 173 { 174 _tprintf(_T("%s"), (LPTSTR)lpMsgBuf); 175 LocalFree(lpMsgBuf); 176 } 177 } 178 179 180 LPTSTR GetConnectionType(LPTSTR lpClass) 181 { 182 HKEY hKey = NULL; 183 LPTSTR ConType = NULL; 184 LPTSTR ConTypeTmp = NULL; 185 TCHAR Path[256]; 186 LPTSTR PrePath = _T("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\"); 187 LPTSTR PostPath = _T("\\Connection"); 188 DWORD PathSize; 189 DWORD dwType; 190 DWORD dwDataSize; 191 192 /* don't overflow the buffer */ 193 PathSize = lstrlen(PrePath) + lstrlen(lpClass) + lstrlen(PostPath) + 1; 194 if (PathSize >= 255) 195 return NULL; 196 197 wsprintf(Path, _T("%s%s%s"), PrePath, lpClass, PostPath); 198 199 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 200 Path, 201 0, 202 KEY_READ, 203 &hKey) == ERROR_SUCCESS) 204 { 205 if (RegQueryValueEx(hKey, 206 _T("Name"), 207 NULL, 208 &dwType, 209 NULL, 210 &dwDataSize) == ERROR_SUCCESS) 211 { 212 ConTypeTmp = (LPTSTR)HeapAlloc(ProcessHeap, 213 0, 214 dwDataSize); 215 216 if (ConTypeTmp == NULL) 217 return NULL; 218 219 ConType = (LPTSTR)HeapAlloc(ProcessHeap, 220 0, 221 dwDataSize); 222 223 if (ConType == NULL) 224 { 225 HeapFree(ProcessHeap, 0, ConTypeTmp); 226 return NULL; 227 } 228 229 if (RegQueryValueEx(hKey, 230 _T("Name"), 231 NULL, 232 &dwType, 233 (PBYTE)ConTypeTmp, 234 &dwDataSize) != ERROR_SUCCESS) 235 { 236 HeapFree(ProcessHeap, 237 0, 238 ConType); 239 240 ConType = NULL; 241 } 242 243 if (ConType) 244 CharToOem(ConTypeTmp, ConType); 245 HeapFree(ProcessHeap, 0, ConTypeTmp); 246 } 247 } 248 249 if (hKey != NULL) 250 RegCloseKey(hKey); 251 252 return ConType; 253 } 254 255 256 LPTSTR GetConnectionDescription(LPTSTR lpClass) 257 { 258 HKEY hBaseKey = NULL; 259 HKEY hClassKey = NULL; 260 LPTSTR lpKeyClass = NULL; 261 LPTSTR lpConDesc = NULL; 262 LPTSTR lpPath = NULL; 263 TCHAR szPrePath[] = _T("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\"); 264 DWORD dwType; 265 DWORD dwDataSize; 266 INT i; 267 268 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 269 szPrePath, 270 0, 271 KEY_READ, 272 &hBaseKey) != ERROR_SUCCESS) 273 { 274 return NULL; 275 } 276 277 for (i = 0; ; i++) 278 { 279 DWORD PathSize; 280 LONG Status; 281 TCHAR szName[10]; 282 DWORD NameLen = 9; 283 284 if ((Status = RegEnumKeyEx(hBaseKey, 285 i, 286 szName, 287 &NameLen, 288 NULL, 289 NULL, 290 NULL, 291 NULL)) != ERROR_SUCCESS) 292 { 293 if (Status == ERROR_NO_MORE_ITEMS) 294 { 295 DoFormatMessage(Status); 296 lpConDesc = NULL; 297 goto CLEANUP; 298 } 299 else 300 continue; 301 } 302 303 PathSize = lstrlen(szPrePath) + lstrlen(szName) + 1; 304 lpPath = (LPTSTR)HeapAlloc(ProcessHeap, 305 0, 306 PathSize * sizeof(TCHAR)); 307 if (lpPath == NULL) 308 goto CLEANUP; 309 310 wsprintf(lpPath, _T("%s%s"), szPrePath, szName); 311 312 //MessageBox(NULL, lpPath, NULL, 0); 313 314 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 315 lpPath, 316 0, 317 KEY_READ, 318 &hClassKey) != ERROR_SUCCESS) 319 { 320 goto CLEANUP; 321 } 322 323 HeapFree(ProcessHeap, 0, lpPath); 324 lpPath = NULL; 325 326 if (RegQueryValueEx(hClassKey, 327 _T("NetCfgInstanceId"), 328 NULL, 329 &dwType, 330 NULL, 331 &dwDataSize) == ERROR_SUCCESS) 332 { 333 lpKeyClass = (LPTSTR)HeapAlloc(ProcessHeap, 334 0, 335 dwDataSize); 336 if (lpKeyClass == NULL) 337 goto CLEANUP; 338 339 if (RegQueryValueEx(hClassKey, 340 _T("NetCfgInstanceId"), 341 NULL, 342 &dwType, 343 (PBYTE)lpKeyClass, 344 &dwDataSize) != ERROR_SUCCESS) 345 { 346 HeapFree(ProcessHeap, 0, lpKeyClass); 347 lpKeyClass = NULL; 348 continue; 349 } 350 } 351 else 352 continue; 353 354 if (!lstrcmp(lpClass, lpKeyClass)) 355 { 356 HeapFree(ProcessHeap, 0, lpKeyClass); 357 lpKeyClass = NULL; 358 359 if (RegQueryValueEx(hClassKey, 360 _T("DriverDesc"), 361 NULL, 362 &dwType, 363 NULL, 364 &dwDataSize) == ERROR_SUCCESS) 365 { 366 lpConDesc = (LPTSTR)HeapAlloc(ProcessHeap, 367 0, 368 dwDataSize); 369 if (lpConDesc == NULL) 370 goto CLEANUP; 371 372 if (RegQueryValueEx(hClassKey, 373 _T("DriverDesc"), 374 NULL, 375 &dwType, 376 (PBYTE)lpConDesc, 377 &dwDataSize) != ERROR_SUCCESS) 378 { 379 HeapFree(ProcessHeap, 0, lpConDesc); 380 lpConDesc = NULL; 381 goto CLEANUP; 382 } 383 } 384 else 385 { 386 lpConDesc = NULL; 387 } 388 389 break; 390 } 391 } 392 393 CLEANUP: 394 if (hBaseKey != NULL) 395 RegCloseKey(hBaseKey); 396 if (hClassKey != NULL) 397 RegCloseKey(hClassKey); 398 if (lpPath != NULL) 399 HeapFree(ProcessHeap, 0, lpPath); 400 if (lpKeyClass != NULL) 401 HeapFree(ProcessHeap, 0, lpKeyClass); 402 403 return lpConDesc; 404 } 405 406 407 VOID ShowInfo(BOOL bAll) 408 { 409 MIB_IFROW mibEntry; 410 PIP_ADAPTER_INFO pAdapterInfo = NULL; 411 PIP_ADAPTER_INFO pAdapter = NULL; 412 ULONG adaptOutBufLen = 0; 413 PFIXED_INFO pFixedInfo = NULL; 414 ULONG netOutBufLen = 0; 415 PIP_PER_ADAPTER_INFO pPerAdapterInfo = NULL; 416 ULONG ulPerAdapterInfoLength = 0; 417 ULONG ret = 0; 418 419 /* call GetAdaptersInfo to obtain the adapter info */ 420 ret = GetAdaptersInfo(pAdapterInfo, &adaptOutBufLen); 421 if (ret == ERROR_BUFFER_OVERFLOW) 422 { 423 pAdapterInfo = (IP_ADAPTER_INFO *)HeapAlloc(ProcessHeap, 0, adaptOutBufLen); 424 if (pAdapterInfo == NULL) 425 return; 426 427 ret = GetAdaptersInfo(pAdapterInfo, &adaptOutBufLen); 428 if (ret != NO_ERROR) 429 { 430 DoFormatMessage(0); 431 HeapFree(ProcessHeap, 0, pAdapterInfo); 432 return; 433 } 434 } 435 else 436 { 437 if (ret != ERROR_NO_DATA) 438 { 439 DoFormatMessage(0); 440 return; 441 } 442 } 443 444 /* call GetNetworkParams to obtain the network info */ 445 if (GetNetworkParams(pFixedInfo, &netOutBufLen) == ERROR_BUFFER_OVERFLOW) 446 { 447 pFixedInfo = (FIXED_INFO *)HeapAlloc(ProcessHeap, 0, netOutBufLen); 448 if (pFixedInfo == NULL) 449 { 450 if (pAdapterInfo) 451 HeapFree(ProcessHeap, 0, pAdapterInfo); 452 return; 453 } 454 if (GetNetworkParams(pFixedInfo, &netOutBufLen) != NO_ERROR) 455 { 456 DoFormatMessage(0); 457 if (pAdapterInfo) 458 HeapFree(ProcessHeap, 0, pAdapterInfo); 459 HeapFree(ProcessHeap, 0, pFixedInfo); 460 return; 461 } 462 } 463 else 464 { 465 if (pAdapterInfo) 466 HeapFree(ProcessHeap, 0, pAdapterInfo); 467 DoFormatMessage(0); 468 return; 469 } 470 471 pAdapter = pAdapterInfo; 472 473 _tprintf(_T("\nReactOS IP Configuration\n\n")); 474 if (bAll) 475 { 476 _tprintf(_T("\tHost Name . . . . . . . . . . . . : %s\n"), pFixedInfo->HostName); 477 _tprintf(_T("\tPrimary DNS Suffix. . . . . . . . : \n")); 478 _tprintf(_T("\tNode Type . . . . . . . . . . . . : %s\n"), GetNodeTypeName(pFixedInfo->NodeType)); 479 if (pFixedInfo->EnableRouting) 480 _tprintf(_T("\tIP Routing Enabled. . . . . . . . : Yes\n")); 481 else 482 _tprintf(_T("\tIP Routing Enabled. . . . . . . . : No\n")); 483 if (pAdapter && pAdapter->HaveWins) 484 _tprintf(_T("\tWINS Proxy enabled. . . . . . . . : Yes\n")); 485 else 486 _tprintf(_T("\tWINS Proxy enabled. . . . . . . . : No\n")); 487 _tprintf(_T("\tDNS Suffix Search List. . . . . . : %s\n"), pFixedInfo->DomainName); 488 } 489 490 while (pAdapter) 491 { 492 LPTSTR IntType, myConType; 493 BOOLEAN bConnected = TRUE; 494 495 mibEntry.dwIndex = pAdapter->Index; 496 GetIfEntry(&mibEntry); 497 498 IntType = GetInterfaceTypeName(pAdapter->Type); 499 myConType = GetConnectionType(pAdapter->AdapterName); 500 501 _tprintf(_T("\n%s %s: \n\n"), IntType , myConType); 502 503 if (myConType != NULL) HeapFree(ProcessHeap, 0, myConType); 504 505 if (GetPerAdapterInfo(pAdapter->Index, pPerAdapterInfo, &ulPerAdapterInfoLength) == ERROR_BUFFER_OVERFLOW) 506 { 507 pPerAdapterInfo = (PIP_PER_ADAPTER_INFO)HeapAlloc(ProcessHeap, 0, ulPerAdapterInfoLength); 508 if (pPerAdapterInfo != NULL) 509 { 510 GetPerAdapterInfo(pAdapter->Index, pPerAdapterInfo, &ulPerAdapterInfoLength); 511 } 512 } 513 514 /* check if the adapter is connected to the media */ 515 if (mibEntry.dwOperStatus != MIB_IF_OPER_STATUS_CONNECTED && mibEntry.dwOperStatus != MIB_IF_OPER_STATUS_OPERATIONAL) 516 { 517 bConnected = FALSE; 518 _tprintf(_T("\tMedia State . . . . . . . . . . . : Media disconnected\n")); 519 } 520 else 521 { 522 _tprintf(_T("\tConnection-specific DNS Suffix. . : %s\n"), pFixedInfo->DomainName); 523 } 524 525 if (bAll) 526 { 527 LPTSTR lpDesc = GetConnectionDescription(pAdapter->AdapterName); 528 _tprintf(_T("\tDescription . . . . . . . . . . . : %s\n"), lpDesc); 529 HeapFree(ProcessHeap, 0, lpDesc); 530 _tprintf(_T("\tPhysical Address. . . . . . . . . : %s\n"), PrintMacAddr(pAdapter->Address)); 531 if (bConnected) 532 { 533 if (pAdapter->DhcpEnabled) 534 { 535 _tprintf(_T("\tDHCP Enabled. . . . . . . . . . . : Yes\n")); 536 if (pPerAdapterInfo != NULL) 537 { 538 if (pPerAdapterInfo->AutoconfigEnabled) 539 _tprintf(_T("\tAutoconfiguration Enabled . . . . : Yes\n")); 540 else 541 _tprintf(_T("\tAutoconfiguration Enabled . . . . : No\n")); 542 } 543 } 544 else 545 { 546 _tprintf(_T("\tDHCP Enabled. . . . . . . . . . . : No\n")); 547 } 548 } 549 } 550 551 if (!bConnected) 552 { 553 pAdapter = pAdapter->Next; 554 continue; 555 } 556 557 _tprintf(_T("\tIP Address. . . . . . . . . . . . : %s\n"), pAdapter->IpAddressList.IpAddress.String); 558 _tprintf(_T("\tSubnet Mask . . . . . . . . . . . : %s\n"), pAdapter->IpAddressList.IpMask.String); 559 if (pAdapter->GatewayList.IpAddress.String[0] != '0') 560 _tprintf(_T("\tDefault Gateway . . . . . . . . . : %s\n"), pAdapter->GatewayList.IpAddress.String); 561 else 562 _tprintf(_T("\tDefault Gateway . . . . . . . . . :\n")); 563 564 if (bAll) 565 { 566 PIP_ADDR_STRING pIPAddr; 567 568 if (pAdapter->DhcpEnabled) 569 _tprintf(_T("\tDHCP Server . . . . . . . . . . . : %s\n"), pAdapter->DhcpServer.IpAddress.String); 570 571 _tprintf(_T("\tDNS Servers . . . . . . . . . . . : ")); 572 _tprintf(_T("%s\n"), pFixedInfo->DnsServerList.IpAddress.String); 573 pIPAddr = pFixedInfo->DnsServerList.Next; 574 while (pIPAddr) 575 { 576 _tprintf(_T("\t\t\t\t\t %s\n"), pIPAddr ->IpAddress.String ); 577 pIPAddr = pIPAddr->Next; 578 } 579 580 if (pAdapter->HaveWins) 581 { 582 _tprintf(_T("\tPrimary WINS Server . . . . . . . : %s\n"), pAdapter->PrimaryWinsServer.IpAddress.String); 583 _tprintf(_T("\tSecondary WINS Server . . . . . . : %s\n"), pAdapter->SecondaryWinsServer.IpAddress.String); 584 } 585 586 if (pAdapter->DhcpEnabled && _tcscmp(pAdapter->DhcpServer.IpAddress.String, _T("255.255.255.255"))) 587 { 588 _tprintf(_T("\tLease Obtained. . . . . . . . . . : %s"), _tasctime(localtime(&pAdapter->LeaseObtained))); 589 _tprintf(_T("\tLease Expires . . . . . . . . . . : %s"), _tasctime(localtime(&pAdapter->LeaseExpires))); 590 } 591 } 592 _tprintf(_T("\n")); 593 594 HeapFree(ProcessHeap, 0, pPerAdapterInfo); 595 pPerAdapterInfo = NULL; 596 597 pAdapter = pAdapter->Next; 598 } 599 600 HeapFree(ProcessHeap, 0, pFixedInfo); 601 if (pAdapterInfo) 602 HeapFree(ProcessHeap, 0, pAdapterInfo); 603 } 604 605 VOID Release(LPTSTR Index) 606 { 607 IP_ADAPTER_INDEX_MAP AdapterInfo; 608 DWORD ret; 609 DWORD i; 610 611 /* if interface is not given, query GetInterfaceInfo */ 612 if (Index == NULL) 613 { 614 PIP_INTERFACE_INFO pInfo = NULL; 615 ULONG ulOutBufLen = 0; 616 617 if (GetInterfaceInfo(pInfo, &ulOutBufLen) == ERROR_INSUFFICIENT_BUFFER) 618 { 619 pInfo = (IP_INTERFACE_INFO *)HeapAlloc(ProcessHeap, 0, ulOutBufLen); 620 if (pInfo == NULL) 621 return; 622 623 if (GetInterfaceInfo(pInfo, &ulOutBufLen) == NO_ERROR ) 624 { 625 for (i = 0; i < pInfo->NumAdapters; i++) 626 { 627 CopyMemory(&AdapterInfo, &pInfo->Adapter[i], sizeof(IP_ADAPTER_INDEX_MAP)); 628 _tprintf(_T("name - %ls\n"), pInfo->Adapter[i].Name); 629 630 /* Call IpReleaseAddress to release the IP address on the specified adapter. */ 631 if ((ret = IpReleaseAddress(&AdapterInfo)) != NO_ERROR) 632 { 633 _tprintf(_T("\nAn error occured while releasing interface %ls : \n"), AdapterInfo.Name); 634 DoFormatMessage(ret); 635 } 636 } 637 638 HeapFree(ProcessHeap, 0, pInfo); 639 } 640 else 641 { 642 DoFormatMessage(0); 643 HeapFree(ProcessHeap, 0, pInfo); 644 return; 645 } 646 } 647 else 648 { 649 DoFormatMessage(0); 650 return; 651 } 652 } 653 else 654 { 655 ; 656 /* FIXME: 657 * we need to be able to release connections by name with support for globbing 658 * i.e. ipconfig /release Eth* will release all cards starting with Eth... 659 * ipconfig /release *con* will release all cards with 'con' in their name 660 */ 661 } 662 } 663 664 665 666 667 VOID Renew(LPTSTR Index) 668 { 669 IP_ADAPTER_INDEX_MAP AdapterInfo; 670 DWORD i; 671 672 /* if interface is not given, query GetInterfaceInfo */ 673 if (Index == NULL) 674 { 675 PIP_INTERFACE_INFO pInfo; 676 ULONG ulOutBufLen = 0; 677 678 pInfo = (IP_INTERFACE_INFO *)HeapAlloc(ProcessHeap, 0, sizeof(IP_INTERFACE_INFO)); 679 if (pInfo == NULL) 680 { 681 _tprintf(_T("memory allocation error")); 682 return; 683 } 684 685 /* Make an initial call to GetInterfaceInfo to get 686 * the necessary size into the ulOutBufLen variable */ 687 if (GetInterfaceInfo(pInfo, &ulOutBufLen) == ERROR_INSUFFICIENT_BUFFER) 688 { 689 HeapFree(ProcessHeap, 0, pInfo); 690 pInfo = (IP_INTERFACE_INFO *)HeapAlloc(ProcessHeap, 0, ulOutBufLen); 691 if (pInfo == NULL) 692 { 693 _tprintf(_T("memory allocation error")); 694 return; 695 } 696 } 697 698 /* Make a second call to GetInterfaceInfo to get the actual data we want */ 699 if (GetInterfaceInfo(pInfo, &ulOutBufLen) == NO_ERROR) 700 { 701 for (i = 0; i < pInfo->NumAdapters; i++) 702 { 703 CopyMemory(&AdapterInfo, &pInfo->Adapter[i], sizeof(IP_ADAPTER_INDEX_MAP)); 704 _tprintf(_T("name - %ls\n"), pInfo->Adapter[i].Name); 705 706 /* Call IpRenewAddress to renew the IP address on the specified adapter. */ 707 if (IpRenewAddress(&AdapterInfo) != NO_ERROR) 708 { 709 _tprintf(_T("\nAn error occured while renew interface %s : "), _T("*name*")); 710 DoFormatMessage(0); 711 } 712 } 713 } 714 else 715 { 716 _tprintf(_T("\nGetInterfaceInfo failed : ")); 717 DoFormatMessage(0); 718 } 719 720 HeapFree(ProcessHeap, 0, pInfo); 721 } 722 else 723 { 724 ; 725 /* FIXME: 726 * we need to be able to renew connections by name with support for globbing 727 * i.e. ipconfig /renew Eth* will renew all cards starting with Eth... 728 * ipconfig /renew *con* will renew all cards with 'con' in their name 729 */ 730 } 731 } 732 733 VOID 734 FlushDns(VOID) 735 { 736 _tprintf(_T("\nReactOS IP Configuration\n\n")); 737 738 if (DnsFlushResolverCache()) 739 _tprintf(_T("The DNS Resolver Cache has been deleted.\n")); 740 else 741 DoFormatMessage(GetLastError()); 742 } 743 744 745 static 746 VOID 747 DisplayDnsRecord( 748 PWSTR pszName, 749 WORD wType) 750 { 751 PDNS_RECORDW pQueryResults = NULL, pThisRecord, pNextRecord; 752 WCHAR szBuffer[48]; 753 IN_ADDR Addr4; 754 IN6_ADDR Addr6; 755 DNS_STATUS Status; 756 757 pQueryResults = NULL; 758 Status = DnsQuery_W(pszName, 759 wType, 760 DNS_QUERY_NO_WIRE_QUERY, 761 NULL, 762 (PDNS_RECORD *)&pQueryResults, 763 NULL); 764 if (Status != ERROR_SUCCESS) 765 { 766 #if 0 767 if (wType != 0) 768 { 769 _tprintf(_T("\t%S\n"), pszName); 770 _tprintf(_T("\t----------------------------------------\n")); 771 _tprintf(_T("\tNo records of type %hu\n\n"), wType); 772 } 773 #endif 774 return; 775 } 776 777 _tprintf(_T("\t%S\n"), pszName); 778 _tprintf(_T("\t----------------------------------------\n")); 779 780 pThisRecord = pQueryResults; 781 while (pThisRecord != NULL) 782 { 783 pNextRecord = pThisRecord->pNext; 784 785 _tprintf(_T("\tRecord Name . . . . . : %S\n"), pThisRecord->pName); 786 _tprintf(_T("\tRecord Type . . . . . : %hu\n"), pThisRecord->wType); 787 _tprintf(_T("\tTime To Live. . . . . : %lu\n"), pThisRecord->dwTtl); 788 _tprintf(_T("\tData Length . . . . . : %hu\n"), pThisRecord->wDataLength); 789 790 switch (pThisRecord->Flags.S.Section) 791 { 792 case DnsSectionQuestion: 793 _tprintf(_T("\tSection . . . . . . . : Question\n")); 794 break; 795 796 case DnsSectionAnswer: 797 _tprintf(_T("\tSection . . . . . . . : Answer\n")); 798 break; 799 800 case DnsSectionAuthority: 801 _tprintf(_T("\tSection . . . . . . . : Authority\n")); 802 break; 803 804 case DnsSectionAdditional: 805 _tprintf(_T("\tSection . . . . . . . : Additional\n")); 806 break; 807 } 808 809 switch (pThisRecord->wType) 810 { 811 case DNS_TYPE_A: 812 Addr4.S_un.S_addr = pThisRecord->Data.A.IpAddress; 813 RtlIpv4AddressToStringW(&Addr4, szBuffer); 814 _tprintf(_T("\tA (Host) Record . . . : %S\n"), szBuffer); 815 break; 816 817 case DNS_TYPE_PTR: 818 _tprintf(_T("\tPTR Record. . . . . . : %S\n"), pThisRecord->Data.PTR.pNameHost); 819 break; 820 821 case DNS_TYPE_NS: 822 _tprintf(_T("\tNS Record . . . . . . : %S\n"), pThisRecord->Data.NS.pNameHost); 823 break; 824 825 case DNS_TYPE_CNAME: 826 _tprintf(_T("\tCNAME Record. . . . . : %S\n"), pThisRecord->Data.CNAME.pNameHost); 827 break; 828 829 case DNS_TYPE_AAAA: 830 RtlCopyMemory(&Addr6, &pThisRecord->Data.AAAA.Ip6Address, sizeof(IN6_ADDR)); 831 RtlIpv6AddressToStringW(&Addr6, szBuffer); 832 _tprintf(_T("\tAAAA Record . . . . . : %S\n"), szBuffer); 833 break; 834 } 835 _tprintf(_T("\n\n")); 836 837 pThisRecord = pNextRecord; 838 } 839 840 DnsRecordListFree((PDNS_RECORD)pQueryResults, DnsFreeRecordList); 841 } 842 843 844 VOID 845 DisplayDns(VOID) 846 { 847 PDNS_CACHE_ENTRY DnsEntry = NULL, pThisEntry, pNextEntry; 848 849 _tprintf(_T("\nReactOS IP Configuration\n\n")); 850 851 if (!DnsGetCacheDataTable(&DnsEntry)) 852 { 853 DoFormatMessage(GetLastError()); 854 return; 855 } 856 857 if (DnsEntry == NULL) 858 return; 859 860 pThisEntry = DnsEntry; 861 while (pThisEntry != NULL) 862 { 863 pNextEntry = pThisEntry->pNext; 864 865 DisplayDnsRecord(pThisEntry->pszName, pThisEntry->wType1); 866 if (pThisEntry->wType2 != 0) 867 DisplayDnsRecord(pThisEntry->pszName, pThisEntry->wType2); 868 869 if (pThisEntry->pszName) 870 LocalFree(pThisEntry->pszName); 871 LocalFree(pThisEntry); 872 873 pThisEntry = pNextEntry; 874 } 875 } 876 877 VOID Usage(VOID) 878 { 879 HRSRC hRes; 880 LPTSTR lpUsage; 881 DWORD Size; 882 883 LPTSTR lpName = (LPTSTR)MAKEINTRESOURCE((IDS_USAGE >> 4) + 1); 884 885 hRes = FindResource(hInstance, 886 lpName, 887 RT_STRING); 888 if (hRes != NULL) 889 { 890 if ((Size = SizeofResource(hInstance, 891 hRes))) 892 { 893 lpUsage = (LPTSTR)HeapAlloc(ProcessHeap, 894 0, 895 Size); 896 if (lpUsage == NULL) 897 return; 898 899 if (LoadStringAndOem(hInstance, 900 IDS_USAGE, 901 lpUsage, 902 Size)) 903 { 904 _tprintf(_T("%s"), lpUsage); 905 } 906 907 HeapFree(ProcessHeap, 0, lpUsage); 908 } 909 } 910 } 911 912 int main(int argc, char *argv[]) 913 { 914 BOOL DoUsage=FALSE; 915 BOOL DoAll=FALSE; 916 BOOL DoRelease=FALSE; 917 BOOL DoRenew=FALSE; 918 BOOL DoFlushdns=FALSE; 919 BOOL DoRegisterdns=FALSE; 920 BOOL DoDisplaydns=FALSE; 921 BOOL DoShowclassid=FALSE; 922 BOOL DoSetclassid=FALSE; 923 924 hInstance = GetModuleHandle(NULL); 925 ProcessHeap = GetProcessHeap(); 926 927 /* Parse command line for options we have been given. */ 928 if ((argc > 1) && (argv[1][0]=='/' || argv[1][0]=='-')) 929 { 930 if (!_tcsicmp(&argv[1][1], _T("?"))) 931 { 932 DoUsage = TRUE; 933 } 934 else if (!_tcsnicmp(&argv[1][1], _T("ALL"), _tcslen(&argv[1][1]))) 935 { 936 DoAll = TRUE; 937 } 938 else if (!_tcsnicmp(&argv[1][1], _T("RELEASE"), _tcslen(&argv[1][1]))) 939 { 940 DoRelease = TRUE; 941 } 942 else if (!_tcsnicmp(&argv[1][1], _T("RENEW"), _tcslen(&argv[1][1]))) 943 { 944 DoRenew = TRUE; 945 } 946 else if (!_tcsnicmp(&argv[1][1], _T("FLUSHDNS"), _tcslen(&argv[1][1]))) 947 { 948 DoFlushdns = TRUE; 949 } 950 else if (!_tcsnicmp(&argv[1][1], _T("FLUSHREGISTERDNS"), _tcslen(&argv[1][1]))) 951 { 952 DoRegisterdns = TRUE; 953 } 954 else if (!_tcsnicmp(&argv[1][1], _T("DISPLAYDNS"), _tcslen(&argv[1][1]))) 955 { 956 DoDisplaydns = TRUE; 957 } 958 else if (!_tcsnicmp(&argv[1][1], _T("SHOWCLASSID"), _tcslen(&argv[1][1]))) 959 { 960 DoShowclassid = TRUE; 961 } 962 else if (!_tcsnicmp(&argv[1][1], _T("SETCLASSID"), _tcslen(&argv[1][1]))) 963 { 964 DoSetclassid = TRUE; 965 } 966 } 967 968 switch (argc) 969 { 970 case 1: /* Default behaviour if no options are given*/ 971 ShowInfo(FALSE); 972 break; 973 case 2: /* Process all the options that take no parameters */ 974 if (DoUsage) 975 Usage(); 976 else if (DoAll) 977 ShowInfo(TRUE); 978 else if (DoRelease) 979 Release(NULL); 980 else if (DoRenew) 981 Renew(NULL); 982 else if (DoFlushdns) 983 FlushDns(); 984 else if (DoRegisterdns) 985 _tprintf(_T("\nSorry /registerdns is not implemented yet\n")); 986 else if (DoDisplaydns) 987 DisplayDns(); 988 else 989 Usage(); 990 break; 991 case 3: /* Process all the options that can have 1 parameter */ 992 if (DoRelease) 993 _tprintf(_T("\nSorry /release [adapter] is not implemented yet\n")); 994 //Release(argv[2]); 995 else if (DoRenew) 996 _tprintf(_T("\nSorry /renew [adapter] is not implemented yet\n")); 997 else if (DoShowclassid) 998 _tprintf(_T("\nSorry /showclassid adapter is not implemented yet\n")); 999 else if (DoSetclassid) 1000 _tprintf(_T("\nSorry /setclassid adapter is not implemented yet\n")); 1001 else 1002 Usage(); 1003 break; 1004 case 4: /* Process all the options that can have 2 parameters */ 1005 if (DoSetclassid) 1006 _tprintf(_T("\nSorry /setclassid adapter [classid]is not implemented yet\n")); 1007 else 1008 Usage(); 1009 break; 1010 default: 1011 Usage(); 1012 } 1013 1014 return 0; 1015 } 1016