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