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