[IPCONFIG] Fix crash on 'ipconfig /all'
[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 flushdns, registerdns, displaydns, showclassid, setclassid
12 * allow globbing on adapter names
13 */
14
15 #include <stdarg.h>
16 #include <windef.h>
17 #include <winbase.h>
18 #include <winuser.h>
19 #include <winreg.h>
20 #include <stdio.h>
21 #include <tchar.h>
22 #include <time.h>
23 #include <iphlpapi.h>
24
25 #include "resource.h"
26
27 #define GUID_LEN 40
28
29 HINSTANCE hInstance;
30 HANDLE ProcessHeap;
31
32 int LoadStringAndOem(HINSTANCE hInst,
33 UINT uID,
34 LPTSTR szNode,
35 int byteSize
36 )
37 {
38 TCHAR *szTmp;
39 int res;
40
41 szTmp = (LPTSTR)HeapAlloc(ProcessHeap, 0, byteSize);
42 if (szTmp == NULL)
43 {
44 return 0;
45 }
46 res = LoadString(hInst, uID, szTmp, byteSize);
47 CharToOem(szTmp, szNode);
48 HeapFree(ProcessHeap, 0, szTmp);
49 return res;
50 }
51
52 LPTSTR GetNodeTypeName(UINT NodeType)
53 {
54 static TCHAR szNode[14];
55
56 switch (NodeType)
57 {
58 case 1:
59 if (!LoadStringAndOem(hInstance, IDS_BCAST, szNode, sizeof(szNode)))
60 return NULL;
61 break;
62
63 case 2:
64 if (!LoadStringAndOem(hInstance, IDS_P2P, szNode, sizeof(szNode)))
65 return NULL;
66 break;
67
68 case 4:
69 if (!LoadStringAndOem(hInstance, IDS_MIXED, szNode, sizeof(szNode)))
70 return NULL;
71 break;
72
73 case 8:
74 if (!LoadStringAndOem(hInstance, IDS_HYBRID, szNode, sizeof(szNode)))
75 return NULL;
76 break;
77
78 default :
79 if (!LoadStringAndOem(hInstance, IDS_UNKNOWN, szNode, sizeof(szNode)))
80 return NULL;
81 break;
82 }
83
84 return szNode;
85 }
86
87
88 LPTSTR GetInterfaceTypeName(UINT InterfaceType)
89 {
90 static TCHAR szIntType[25];
91
92 switch (InterfaceType)
93 {
94 case MIB_IF_TYPE_OTHER:
95 if (!LoadStringAndOem(hInstance, IDS_OTHER, szIntType, sizeof(szIntType)))
96 return NULL;
97 break;
98
99 case MIB_IF_TYPE_ETHERNET:
100 if (!LoadStringAndOem(hInstance, IDS_ETH, szIntType, sizeof(szIntType)))
101 return NULL;
102 break;
103
104 case MIB_IF_TYPE_TOKENRING:
105 if (!LoadStringAndOem(hInstance, IDS_TOKEN, szIntType, sizeof(szIntType)))
106 return NULL;
107 break;
108
109 case MIB_IF_TYPE_FDDI:
110 if (!LoadStringAndOem(hInstance, IDS_FDDI, szIntType, sizeof(szIntType)))
111 return NULL;
112 break;
113
114 case MIB_IF_TYPE_PPP:
115 if (!LoadStringAndOem(hInstance, IDS_PPP, szIntType, sizeof(szIntType)))
116 return NULL;
117 break;
118
119 case MIB_IF_TYPE_LOOPBACK:
120 if (!LoadStringAndOem(hInstance, IDS_LOOP, szIntType, sizeof(szIntType)))
121 return NULL;
122 break;
123
124 case MIB_IF_TYPE_SLIP:
125 if (!LoadStringAndOem(hInstance, IDS_SLIP, szIntType, sizeof(szIntType)))
126 return NULL;
127 break;
128
129 default:
130 if (!LoadStringAndOem(hInstance, IDS_UNKNOWN, szIntType, sizeof(szIntType)))
131 return NULL;
132 break;
133 }
134
135 return szIntType;
136 }
137
138
139 /* print MAC address */
140 PTCHAR PrintMacAddr(PBYTE Mac)
141 {
142 static TCHAR MacAddr[20];
143
144 _stprintf(MacAddr, _T("%02x-%02x-%02x-%02x-%02x-%02x"),
145 Mac[0], Mac[1], Mac[2], Mac[3], Mac[4], Mac[5]);
146
147 return MacAddr;
148 }
149
150
151 VOID DoFormatMessage(LONG ErrorCode)
152 {
153 LPVOID lpMsgBuf;
154 //DWORD ErrorCode;
155
156 if (ErrorCode == 0)
157 ErrorCode = GetLastError();
158
159 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
160 FORMAT_MESSAGE_FROM_SYSTEM |
161 FORMAT_MESSAGE_IGNORE_INSERTS,
162 NULL,
163 ErrorCode,
164 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
165 (LPTSTR) &lpMsgBuf,
166 0,
167 NULL))
168 {
169 _tprintf(_T("%s"), (LPTSTR)lpMsgBuf);
170 LocalFree(lpMsgBuf);
171 }
172 }
173
174
175 LPTSTR GetConnectionType(LPTSTR lpClass)
176 {
177 HKEY hKey = NULL;
178 LPTSTR ConType = NULL;
179 LPTSTR ConTypeTmp = NULL;
180 TCHAR Path[256];
181 LPTSTR PrePath = _T("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\");
182 LPTSTR PostPath = _T("\\Connection");
183 DWORD PathSize;
184 DWORD dwType;
185 DWORD dwDataSize;
186
187 /* don't overflow the buffer */
188 PathSize = lstrlen(PrePath) + lstrlen(lpClass) + lstrlen(PostPath) + 1;
189 if (PathSize >= 255)
190 return NULL;
191
192 wsprintf(Path, _T("%s%s%s"), PrePath, lpClass, PostPath);
193
194 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
195 Path,
196 0,
197 KEY_READ,
198 &hKey) == ERROR_SUCCESS)
199 {
200 if(RegQueryValueEx(hKey,
201 _T("Name"),
202 NULL,
203 &dwType,
204 NULL,
205 &dwDataSize) == ERROR_SUCCESS)
206 {
207 ConTypeTmp = (LPTSTR)HeapAlloc(ProcessHeap,
208 0,
209 dwDataSize);
210
211 if (ConTypeTmp == NULL)
212 return NULL;
213
214 ConType = (LPTSTR)HeapAlloc(ProcessHeap,
215 0,
216 dwDataSize);
217
218 if (ConType == NULL)
219 {
220 HeapFree(ProcessHeap, 0, ConTypeTmp);
221 return NULL;
222 }
223
224 if(RegQueryValueEx(hKey,
225 _T("Name"),
226 NULL,
227 &dwType,
228 (PBYTE)ConTypeTmp,
229 &dwDataSize) != ERROR_SUCCESS)
230 {
231 HeapFree(ProcessHeap,
232 0,
233 ConType);
234
235 ConType = NULL;
236 }
237
238 if (ConType) CharToOem(ConTypeTmp, ConType);
239 HeapFree(ProcessHeap, 0, ConTypeTmp);
240 }
241 }
242
243 if (hKey != NULL)
244 RegCloseKey(hKey);
245
246 return ConType;
247 }
248
249
250 LPTSTR GetConnectionDescription(LPTSTR lpClass)
251 {
252 HKEY hBaseKey = NULL;
253 HKEY hClassKey = NULL;
254 LPTSTR lpKeyClass = NULL;
255 LPTSTR lpConDesc = NULL;
256 LPTSTR lpPath = NULL;
257 TCHAR szPrePath[] = _T("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\");
258 DWORD dwType;
259 DWORD dwDataSize;
260 INT i;
261
262 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
263 szPrePath,
264 0,
265 KEY_READ,
266 &hBaseKey) != ERROR_SUCCESS)
267 {
268 return NULL;
269 }
270
271 for (i=0; ; i++)
272 {
273 DWORD PathSize;
274 LONG Status;
275 TCHAR szName[10];
276 DWORD NameLen = 9;
277
278 if ((Status = RegEnumKeyEx(hBaseKey,
279 i,
280 szName,
281 &NameLen,
282 NULL,
283 NULL,
284 NULL,
285 NULL)) != ERROR_SUCCESS)
286 {
287 if (Status == ERROR_NO_MORE_ITEMS)
288 {
289 DoFormatMessage(Status);
290 lpConDesc = NULL;
291 goto CLEANUP;
292 }
293 else
294 continue;
295 }
296
297 PathSize = lstrlen(szPrePath) + lstrlen(szName) + 1;
298 lpPath = (LPTSTR)HeapAlloc(ProcessHeap,
299 0,
300 PathSize * sizeof(TCHAR));
301 if (lpPath == NULL)
302 goto CLEANUP;
303
304 wsprintf(lpPath, _T("%s%s"), szPrePath, szName);
305
306 //MessageBox(NULL, lpPath, NULL, 0);
307
308 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
309 lpPath,
310 0,
311 KEY_READ,
312 &hClassKey) != ERROR_SUCCESS)
313 {
314 goto CLEANUP;
315 }
316
317 HeapFree(ProcessHeap, 0, lpPath);
318 lpPath = NULL;
319
320 if(RegQueryValueEx(hClassKey,
321 _T("NetCfgInstanceId"),
322 NULL,
323 &dwType,
324 NULL,
325 &dwDataSize) == ERROR_SUCCESS)
326 {
327 lpKeyClass = (LPTSTR)HeapAlloc(ProcessHeap,
328 0,
329 dwDataSize);
330 if (lpKeyClass == NULL)
331 goto CLEANUP;
332
333 if(RegQueryValueEx(hClassKey,
334 _T("NetCfgInstanceId"),
335 NULL,
336 &dwType,
337 (PBYTE)lpKeyClass,
338 &dwDataSize) != ERROR_SUCCESS)
339 {
340 HeapFree(ProcessHeap, 0, lpKeyClass);
341 lpKeyClass = NULL;
342 continue;
343 }
344 }
345 else
346 continue;
347
348 if (!lstrcmp(lpClass, lpKeyClass))
349 {
350 HeapFree(ProcessHeap, 0, lpKeyClass);
351 lpKeyClass = NULL;
352
353 if(RegQueryValueEx(hClassKey,
354 _T("DriverDesc"),
355 NULL,
356 &dwType,
357 NULL,
358 &dwDataSize) == ERROR_SUCCESS)
359 {
360 lpConDesc = (LPTSTR)HeapAlloc(ProcessHeap,
361 0,
362 dwDataSize);
363 if (lpConDesc == NULL)
364 goto CLEANUP;
365
366 if(RegQueryValueEx(hClassKey,
367 _T("DriverDesc"),
368 NULL,
369 &dwType,
370 (PBYTE)lpConDesc,
371 &dwDataSize) != ERROR_SUCCESS)
372 {
373 HeapFree(ProcessHeap, 0, lpConDesc);
374 lpConDesc = NULL;
375 goto CLEANUP;
376 }
377 }
378 else
379 lpConDesc = NULL;
380
381 break;
382 }
383 }
384
385 CLEANUP:
386 if (hBaseKey != NULL)
387 RegCloseKey(hBaseKey);
388 if (hClassKey != NULL)
389 RegCloseKey(hClassKey);
390 if (lpPath != NULL)
391 HeapFree(ProcessHeap, 0, lpPath);
392 if (lpKeyClass != NULL)
393 HeapFree(ProcessHeap, 0, lpKeyClass);
394
395 return lpConDesc;
396 }
397
398
399 VOID ShowInfo(BOOL bAll)
400 {
401 MIB_IFROW mibEntry;
402 PIP_ADAPTER_INFO pAdapterInfo = NULL;
403 PIP_ADAPTER_INFO pAdapter = NULL;
404 ULONG adaptOutBufLen = 0;
405 PFIXED_INFO pFixedInfo = NULL;
406 ULONG netOutBufLen = 0;
407 ULONG ret = 0;
408
409 /* call GetAdaptersInfo to obtain the adapter info */
410 ret = GetAdaptersInfo(pAdapterInfo, &adaptOutBufLen);
411 if (ret == ERROR_BUFFER_OVERFLOW)
412 {
413 pAdapterInfo = (IP_ADAPTER_INFO *)HeapAlloc(ProcessHeap, 0, adaptOutBufLen);
414 if (pAdapterInfo == NULL)
415 return;
416
417 ret = GetAdaptersInfo(pAdapterInfo, &adaptOutBufLen);
418 if (ret != NO_ERROR)
419 {
420 DoFormatMessage(0);
421 HeapFree(ProcessHeap, 0, pAdapterInfo);
422 return;
423 }
424 }
425 else
426 {
427 if( ERROR_NO_DATA != ret )
428 {
429 DoFormatMessage(0);
430 return;
431 }
432 }
433
434 /* call GetNetworkParams to obtain the network info */
435 if(GetNetworkParams(pFixedInfo, &netOutBufLen) == ERROR_BUFFER_OVERFLOW)
436 {
437 pFixedInfo = (FIXED_INFO *)HeapAlloc(ProcessHeap, 0, netOutBufLen);
438 if (pFixedInfo == NULL)
439 {
440 if (pAdapterInfo)
441 HeapFree(ProcessHeap, 0, pAdapterInfo);
442 return;
443 }
444 if (GetNetworkParams(pFixedInfo, &netOutBufLen) != NO_ERROR)
445 {
446 DoFormatMessage(0);
447 if (pAdapterInfo)
448 HeapFree(ProcessHeap, 0, pAdapterInfo);
449 HeapFree(ProcessHeap, 0, pFixedInfo);
450 return;
451 }
452 }
453 else
454 {
455 if (pAdapterInfo)
456 HeapFree(ProcessHeap, 0, pAdapterInfo);
457 DoFormatMessage(0);
458 return;
459 }
460
461 pAdapter = pAdapterInfo;
462
463 _tprintf(_T("\nReactOS IP Configuration\n\n"));
464 if (bAll)
465 {
466 _tprintf(_T("\tHost Name . . . . . . . . . . . . : %s\n"), pFixedInfo->HostName);
467 _tprintf(_T("\tPrimary DNS Suffix. . . . . . . . : \n"));
468 _tprintf(_T("\tNode Type . . . . . . . . . . . . : %s\n"), GetNodeTypeName(pFixedInfo->NodeType));
469 if (pFixedInfo->EnableRouting)
470 _tprintf(_T("\tIP Routing Enabled. . . . . . . . : Yes\n"));
471 else
472 _tprintf(_T("\tIP Routing Enabled. . . . . . . . : No\n"));
473 if (pAdapter && pAdapter->HaveWins)
474 _tprintf(_T("\tWINS Proxy enabled. . . . . . . . : Yes\n"));
475 else
476 _tprintf(_T("\tWINS Proxy enabled. . . . . . . . : No\n"));
477 _tprintf(_T("\tDNS Suffix Search List. . . . . . : %s\n"), pFixedInfo->DomainName);
478 }
479
480 while (pAdapter)
481 {
482 LPTSTR IntType, myConType;
483
484 mibEntry.dwIndex = pAdapter->Index;
485 GetIfEntry(&mibEntry);
486
487 IntType = GetInterfaceTypeName(pAdapter->Type);
488 myConType = GetConnectionType(pAdapter->AdapterName);
489
490 _tprintf(_T("\n%s %s: \n\n"), IntType , myConType);
491
492 if (myConType != NULL) HeapFree(ProcessHeap, 0, myConType);
493
494 /* check if the adapter is connected to the media */
495 if (mibEntry.dwOperStatus != MIB_IF_OPER_STATUS_CONNECTED && mibEntry.dwOperStatus != MIB_IF_OPER_STATUS_OPERATIONAL)
496 {
497 _tprintf(_T("\tMedia State . . . . . . . . . . . : Media disconnected\n"));
498 pAdapter = pAdapter->Next;
499 continue;
500 }
501
502 _tprintf(_T("\tConnection-specific DNS Suffix. . : %s\n"), pFixedInfo->DomainName);
503
504 if (bAll)
505 {
506 LPTSTR lpDesc = GetConnectionDescription(pAdapter->AdapterName);
507 _tprintf(_T("\tDescription . . . . . . . . . . . : %s\n"), lpDesc);
508 HeapFree(ProcessHeap, 0, lpDesc);
509 _tprintf(_T("\tPhysical Address. . . . . . . . . : %s\n"), PrintMacAddr(pAdapter->Address));
510 if (pAdapter->DhcpEnabled)
511 _tprintf(_T("\tDHCP Enabled. . . . . . . . . . . : Yes\n"));
512 else
513 _tprintf(_T("\tDHCP Enabled. . . . . . . . . . . : No\n"));
514 _tprintf(_T("\tAutoconfiguration Enabled . . . . : \n"));
515 }
516
517 _tprintf(_T("\tIP Address. . . . . . . . . . . . : %s\n"), pAdapter->IpAddressList.IpAddress.String);
518 _tprintf(_T("\tSubnet Mask . . . . . . . . . . . : %s\n"), pAdapter->IpAddressList.IpMask.String);
519 if (pAdapter->GatewayList.IpAddress.String[0] != '0')
520 _tprintf(_T("\tDefault Gateway . . . . . . . . . : %s\n"), pAdapter->GatewayList.IpAddress.String);
521 else
522 _tprintf(_T("\tDefault Gateway . . . . . . . . . :\n"));
523
524 if (bAll)
525 {
526 PIP_ADDR_STRING pIPAddr;
527
528 if (pAdapter->DhcpEnabled)
529 _tprintf(_T("\tDHCP Server . . . . . . . . . . . : %s\n"), pAdapter->DhcpServer.IpAddress.String);
530
531 _tprintf(_T("\tDNS Servers . . . . . . . . . . . : "));
532 _tprintf(_T("%s\n"), pFixedInfo->DnsServerList.IpAddress.String);
533 pIPAddr = pFixedInfo->DnsServerList.Next;
534 while (pIPAddr)
535 {
536 _tprintf(_T("\t\t\t\t\t %s\n"), pIPAddr ->IpAddress.String );
537 pIPAddr = pIPAddr->Next;
538 }
539
540 if (pAdapter->HaveWins)
541 {
542 _tprintf(_T("\tPrimary WINS Server . . . . . . . : %s\n"), pAdapter->PrimaryWinsServer.IpAddress.String);
543 _tprintf(_T("\tSecondary WINS Server . . . . . . : %s\n"), pAdapter->SecondaryWinsServer.IpAddress.String);
544 }
545
546 if (pAdapter->DhcpEnabled && _tcscmp(pAdapter->DhcpServer.IpAddress.String, _T("255.255.255.255")))
547 {
548 _tprintf(_T("\tLease Obtained. . . . . . . . . . : %s"), _tasctime(localtime(&pAdapter->LeaseObtained)));
549 _tprintf(_T("\tLease Expires . . . . . . . . . . : %s"), _tasctime(localtime(&pAdapter->LeaseExpires)));
550 }
551 }
552 _tprintf(_T("\n"));
553
554 pAdapter = pAdapter->Next;
555
556 }
557
558 HeapFree(ProcessHeap, 0, pFixedInfo);
559 if (pAdapterInfo)
560 HeapFree(ProcessHeap, 0, pAdapterInfo);
561 }
562
563 VOID Release(LPTSTR Index)
564 {
565 IP_ADAPTER_INDEX_MAP AdapterInfo;
566 DWORD ret;
567 DWORD i;
568
569 /* if interface is not given, query GetInterfaceInfo */
570 if (Index == NULL)
571 {
572 PIP_INTERFACE_INFO pInfo = NULL;
573 ULONG ulOutBufLen = 0;
574
575 if (GetInterfaceInfo(pInfo, &ulOutBufLen) == ERROR_INSUFFICIENT_BUFFER)
576 {
577 pInfo = (IP_INTERFACE_INFO *)HeapAlloc(ProcessHeap, 0, ulOutBufLen);
578 if (pInfo == NULL)
579 return;
580
581 if (GetInterfaceInfo(pInfo, &ulOutBufLen) == NO_ERROR )
582 {
583 for (i = 0; i < pInfo->NumAdapters; i++)
584 {
585 CopyMemory(&AdapterInfo, &pInfo->Adapter[i], sizeof(IP_ADAPTER_INDEX_MAP));
586 _tprintf(_T("name - %ls\n"), pInfo->Adapter[i].Name);
587
588 /* Call IpReleaseAddress to release the IP address on the specified adapter. */
589 if ((ret = IpReleaseAddress(&AdapterInfo)) != NO_ERROR)
590 {
591 _tprintf(_T("\nAn error occured while releasing interface %ls : \n"), AdapterInfo.Name);
592 DoFormatMessage(ret);
593 }
594 }
595
596 HeapFree(ProcessHeap, 0, pInfo);
597 }
598 else
599 {
600 DoFormatMessage(0);
601 HeapFree(ProcessHeap, 0, pInfo);
602 return;
603 }
604 }
605 else
606 {
607 DoFormatMessage(0);
608 return;
609 }
610 }
611 else
612 {
613 ;
614 /* FIXME:
615 * we need to be able to release connections by name with support for globbing
616 * i.e. ipconfig /release Eth* will release all cards starting with Eth...
617 * ipconfig /release *con* will release all cards with 'con' in their name
618 */
619 }
620 }
621
622
623
624
625 VOID Renew(LPTSTR Index)
626 {
627 IP_ADAPTER_INDEX_MAP AdapterInfo;
628 DWORD i;
629
630 /* if interface is not given, query GetInterfaceInfo */
631 if (Index == NULL)
632 {
633 PIP_INTERFACE_INFO pInfo;
634 ULONG ulOutBufLen = 0;
635
636 pInfo = (IP_INTERFACE_INFO *)HeapAlloc(ProcessHeap, 0, sizeof(IP_INTERFACE_INFO));
637 if (pInfo == NULL)
638 {
639 _tprintf(_T("memory allocation error"));
640 return;
641 }
642
643 /* Make an initial call to GetInterfaceInfo to get
644 * the necessary size into the ulOutBufLen variable */
645 if ( GetInterfaceInfo(pInfo, &ulOutBufLen) == ERROR_INSUFFICIENT_BUFFER)
646 {
647 HeapFree(ProcessHeap, 0, pInfo);
648 pInfo = (IP_INTERFACE_INFO *)HeapAlloc(ProcessHeap, 0, ulOutBufLen);
649 if (pInfo == NULL)
650 {
651 _tprintf(_T("memory allocation error"));
652 return;
653 }
654 }
655
656 /* Make a second call to GetInterfaceInfo to get the actual data we want */
657 if (GetInterfaceInfo(pInfo, &ulOutBufLen) == NO_ERROR )
658 {
659 for (i = 0; i < pInfo->NumAdapters; i++)
660 {
661 CopyMemory(&AdapterInfo, &pInfo->Adapter[i], sizeof(IP_ADAPTER_INDEX_MAP));
662 _tprintf(_T("name - %ls\n"), pInfo->Adapter[i].Name);
663
664
665 /* Call IpRenewAddress to renew the IP address on the specified adapter. */
666 if (IpRenewAddress(&AdapterInfo) != NO_ERROR)
667 {
668 _tprintf(_T("\nAn error occured while renew interface %s : "), _T("*name*"));
669 DoFormatMessage(0);
670 }
671 }
672 }
673 else
674 {
675 _tprintf(_T("\nGetInterfaceInfo failed : "));
676 DoFormatMessage(0);
677 }
678
679 HeapFree(ProcessHeap, 0, pInfo);
680 }
681 else
682 {
683 ;
684 /* FIXME:
685 * we need to be able to renew connections by name with support for globbing
686 * i.e. ipconfig /renew Eth* will renew all cards starting with Eth...
687 * ipconfig /renew *con* will renew all cards with 'con' in their name
688 */
689 }
690 }
691
692
693
694 VOID Usage(VOID)
695 {
696 HRSRC hRes;
697 LPTSTR lpUsage;
698 DWORD Size;
699
700 LPTSTR lpName = (LPTSTR)MAKEINTRESOURCE((IDS_USAGE >> 4) + 1);
701
702 hRes = FindResource(hInstance,
703 lpName,
704 RT_STRING);
705 if (hRes != NULL)
706 {
707 if ((Size = SizeofResource(hInstance,
708 hRes)))
709 {
710 lpUsage = (LPTSTR)HeapAlloc(ProcessHeap,
711 0,
712 Size);
713 if (lpUsage == NULL)
714 return;
715
716 if (LoadStringAndOem(hInstance,
717 IDS_USAGE,
718 lpUsage,
719 Size))
720 {
721 _tprintf(_T("%s"), lpUsage);
722 }
723
724 HeapFree(ProcessHeap, 0, lpUsage);
725 }
726 }
727
728
729 }
730
731 int main(int argc, char *argv[])
732 {
733 BOOL DoUsage=FALSE;
734 BOOL DoAll=FALSE;
735 BOOL DoRelease=FALSE;
736 BOOL DoRenew=FALSE;
737 BOOL DoFlushdns=FALSE;
738 BOOL DoRegisterdns=FALSE;
739 BOOL DoDisplaydns=FALSE;
740 BOOL DoShowclassid=FALSE;
741 BOOL DoSetclassid=FALSE;
742
743 hInstance = GetModuleHandle(NULL);
744 ProcessHeap = GetProcessHeap();
745
746 /* Parse command line for options we have been given. */
747 if ( (argc > 1)&&(argv[1][0]=='/' || argv[1][0]=='-') )
748 {
749 if( !_tcsicmp( &argv[1][1], _T("?") ))
750 {
751 DoUsage = TRUE;
752 }
753 else if( !_tcsnicmp( &argv[1][1], _T("ALL"), _tcslen(&argv[1][1]) ))
754 {
755 DoAll = TRUE;
756 }
757 else if( !_tcsnicmp( &argv[1][1], _T("RELEASE"), _tcslen(&argv[1][1]) ))
758 {
759 DoRelease = TRUE;
760 }
761 else if( ! _tcsnicmp( &argv[1][1], _T("RENEW"), _tcslen(&argv[1][1]) ))
762 {
763 DoRenew = TRUE;
764 }
765 else if( ! _tcsnicmp( &argv[1][1], _T("FLUSHDNS"), _tcslen(&argv[1][1]) ))
766 {
767 DoFlushdns = TRUE;
768 }
769 else if( ! _tcsnicmp( &argv[1][1], _T("FLUSHREGISTERDNS"), _tcslen(&argv[1][1]) ))
770 {
771 DoRegisterdns = TRUE;
772 }
773 else if( ! _tcsnicmp( &argv[1][1], _T("DISPLAYDNS"), _tcslen(&argv[1][1]) ))
774 {
775 DoDisplaydns = TRUE;
776 }
777 else if( ! _tcsnicmp( &argv[1][1], _T("SHOWCLASSID"), _tcslen(&argv[1][1]) ))
778 {
779 DoShowclassid = TRUE;
780 }
781 else if( ! _tcsnicmp( &argv[1][1], _T("SETCLASSID"), _tcslen(&argv[1][1]) ))
782 {
783 DoSetclassid = TRUE;
784 }
785 }
786
787 switch (argc)
788 {
789 case 1: /* Default behaviour if no options are given*/
790 ShowInfo(FALSE);
791 break;
792 case 2: /* Process all the options that take no parameters */
793 if (DoUsage)
794 Usage();
795 else if (DoAll)
796 ShowInfo(TRUE);
797 else if (DoRelease)
798 Release(NULL);
799 else if (DoRenew)
800 Renew(NULL);
801 else if (DoFlushdns)
802 _tprintf(_T("\nSorry /flushdns is not implemented yet\n"));
803 else if (DoRegisterdns)
804 _tprintf(_T("\nSorry /registerdns is not implemented yet\n"));
805 else if (DoDisplaydns)
806 _tprintf(_T("\nSorry /displaydns is not implemented yet\n"));
807 else
808 Usage();
809 break;
810 case 3: /* Process all the options that can have 1 parameter */
811 if (DoRelease)
812 _tprintf(_T("\nSorry /release [adapter] is not implemented yet\n"));
813 //Release(argv[2]);
814 else if (DoRenew)
815 _tprintf(_T("\nSorry /renew [adapter] is not implemented yet\n"));
816 else if (DoShowclassid)
817 _tprintf(_T("\nSorry /showclassid adapter is not implemented yet\n"));
818 else if (DoSetclassid)
819 _tprintf(_T("\nSorry /setclassid adapter is not implemented yet\n"));
820 else
821 Usage();
822 break;
823 case 4: /* Process all the options that can have 2 parameters */
824 if (DoSetclassid)
825 _tprintf(_T("\nSorry /setclassid adapter [classid]is not implemented yet\n"));
826 else
827 Usage();
828 break;
829 default:
830 Usage();
831 }
832
833 return 0;
834 }