[IPCONFIG] Revert changes that were not meant to be published yet
[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 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 }