Reactos
at master 1003 lines 26 kB view raw
1/* 2 * PROJECT: ReactOS NetSh 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Network Shell context management functions 5 * COPYRIGHT: Copyright 2023 Eric Kohl <eric.kohl@reactos.org> 6 */ 7 8/* INCLUDES *******************************************************************/ 9 10#include "precomp.h" 11 12#define NDEBUG 13#include <debug.h> 14 15/* GLOBALS ********************************************************************/ 16 17typedef struct _CONTEXT_STACK_ENTRY 18{ 19 struct _CONTEXT_STACK_ENTRY *pPrev; 20 struct _CONTEXT_STACK_ENTRY *pNext; 21 22 PCONTEXT_ENTRY pContext; 23} CONTEXT_STACK_ENTRY, *PCONTEXT_STACK_ENTRY; 24 25 26PCONTEXT_ENTRY pRootContext = NULL; 27PCONTEXT_ENTRY pCurrentContext = NULL; 28 29PCONTEXT_STACK_ENTRY pContextStackHead = NULL; 30PCONTEXT_STACK_ENTRY pContextStackTail = NULL; 31 32PWSTR pszMachine = NULL; 33 34static BOOL bOnline = TRUE; 35 36/* FUNCTIONS ******************************************************************/ 37 38PCONTEXT_ENTRY 39AddContext( 40 PCONTEXT_ENTRY pParentContext, 41 PWSTR pszName, 42 GUID *pGuid) 43{ 44 PCONTEXT_ENTRY pEntry; 45 46 DPRINT("AddContext(%S)\n", pszName); 47 if (pParentContext) 48 { 49 DPRINT("ParentContext %S\n", pParentContext->pszContextName); 50 } 51 52 if (pParentContext != NULL && pszName == NULL) 53 return NULL; 54 55 /* Allocate the entry */ 56 pEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CONTEXT_ENTRY)); 57 if (pEntry == NULL) 58 return NULL; 59 60 /* Allocate the name buffer */ 61 if (pszName != NULL) 62 { 63 pEntry->pszContextName = HeapAlloc(GetProcessHeap(), 64 HEAP_ZERO_MEMORY, 65 (wcslen(pszName) + 1) * sizeof(WCHAR)); 66 if (pEntry->pszContextName == NULL) 67 { 68 HeapFree(GetProcessHeap(), 0, pEntry); 69 return NULL; 70 } 71 72 /* Fill the entry */ 73 wcscpy(pEntry->pszContextName, pszName); 74 } 75 76 pEntry->pParentContext = pParentContext; 77 if (pGuid != NULL) 78 CopyMemory(&pEntry->Guid, pGuid, sizeof(pEntry->Guid)); 79 80 /* Insert it */ 81 if (pParentContext != NULL) 82 { 83 if ((pParentContext->pSubContextHead == NULL) && (pParentContext->pSubContextTail == NULL)) 84 { 85 pParentContext->pSubContextHead = pEntry; 86 pParentContext->pSubContextTail = pEntry; 87 } 88 else 89 { 90 pEntry->pPrev = pParentContext->pSubContextTail; 91 pParentContext->pSubContextTail->pNext = pEntry; 92 pParentContext->pSubContextTail = pEntry; 93 } 94 } 95 96 return pEntry; 97} 98 99 100PCOMMAND_ENTRY 101AddContextCommand( 102 PCONTEXT_ENTRY pContext, 103 LPCWSTR pwszCmdToken, 104 PFN_HANDLE_CMD pfnCmdHandler, 105 DWORD dwShortCmdHelpToken, 106 DWORD dwCmdHlpToken, 107 DWORD dwFlags) 108{ 109 PCOMMAND_ENTRY pEntry; 110 111 if (pfnCmdHandler == NULL) 112 return NULL; 113 114 /* Allocate the entry */ 115 pEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMMAND_ENTRY)); 116 if (pEntry == NULL) 117 return NULL; 118 119 pEntry->pwszCmdToken = HeapAlloc(GetProcessHeap(), 120 HEAP_ZERO_MEMORY, 121 (wcslen(pwszCmdToken) + 1) * sizeof(WCHAR)); 122 if (pEntry->pwszCmdToken == NULL) 123 { 124 HeapFree(GetProcessHeap(), 0, pEntry); 125 return NULL; 126 } 127 128 wcscpy((LPWSTR)pEntry->pwszCmdToken, pwszCmdToken); 129 130 pEntry->pfnCmdHandler = pfnCmdHandler; 131 pEntry->dwShortCmdHelpToken = dwShortCmdHelpToken; 132 pEntry->dwCmdHlpToken = dwCmdHlpToken; 133 pEntry->dwFlags = dwFlags; 134 135 if (pContext->pCommandListHead == NULL && pContext->pCommandListTail == NULL) 136 { 137 pContext->pCommandListHead = pEntry; 138 pContext->pCommandListTail = pEntry; 139 } 140 else 141 { 142 pEntry->pPrev = pContext->pCommandListTail; 143 pContext->pCommandListTail->pNext = pEntry; 144 pContext->pCommandListTail = pEntry; 145 } 146 147 return pEntry; 148} 149 150 151PCOMMAND_GROUP 152AddCommandGroup( 153 PCONTEXT_ENTRY pContext, 154 LPCWSTR pwszCmdGroupToken, 155 DWORD dwShortCmdHelpToken, 156 DWORD dwFlags) 157{ 158 PCOMMAND_GROUP pEntry; 159 160 DPRINT("AddCommandGroup(%S %lu)\n", pwszCmdGroupToken, dwShortCmdHelpToken); 161 162 /* Allocate the entry */ 163 pEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMMAND_GROUP)); 164 if (pEntry == NULL) 165 return NULL; 166 167 pEntry->pwszCmdGroupToken = HeapAlloc(GetProcessHeap(), 168 HEAP_ZERO_MEMORY, 169 (wcslen(pwszCmdGroupToken) + 1) * sizeof(WCHAR)); 170 if (pEntry->pwszCmdGroupToken == NULL) 171 { 172 HeapFree(GetProcessHeap(), 0, pEntry); 173 return NULL; 174 } 175 176 wcscpy((LPWSTR)pEntry->pwszCmdGroupToken, pwszCmdGroupToken); 177 pEntry->dwShortCmdHelpToken = dwShortCmdHelpToken; 178 pEntry->dwFlags = dwFlags; 179 180 if (pContext->pGroupListHead == NULL && pContext->pGroupListTail == NULL) 181 { 182 pContext->pGroupListHead = pEntry; 183 pContext->pGroupListTail = pEntry; 184 } 185 else 186 { 187 pEntry->pPrev = pContext->pGroupListTail; 188 pContext->pGroupListTail->pNext = pEntry; 189 pContext->pGroupListTail = pEntry; 190 } 191 192 return pEntry; 193} 194 195 196PCOMMAND_ENTRY 197AddGroupCommand( 198 PCOMMAND_GROUP pGroup, 199 LPCWSTR pwszCmdToken, 200 PFN_HANDLE_CMD pfnCmdHandler, 201 DWORD dwShortCmdHelpToken, 202 DWORD dwCmdHlpToken, 203 DWORD dwFlags) 204{ 205 PCOMMAND_ENTRY pEntry; 206 207 if (pfnCmdHandler == NULL) 208 return NULL; 209 210 /* Allocate the entry */ 211 pEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMMAND_ENTRY)); 212 if (pEntry == NULL) 213 return NULL; 214 215 pEntry->pwszCmdToken = HeapAlloc(GetProcessHeap(), 216 HEAP_ZERO_MEMORY, 217 (wcslen(pwszCmdToken) + 1) * sizeof(WCHAR)); 218 if (pEntry->pwszCmdToken == NULL) 219 { 220 HeapFree(GetProcessHeap(), 0, pEntry); 221 return NULL; 222 } 223 224 wcscpy((LPWSTR)pEntry->pwszCmdToken, pwszCmdToken); 225 226 pEntry->pfnCmdHandler = pfnCmdHandler; 227 pEntry->dwShortCmdHelpToken = dwShortCmdHelpToken; 228 pEntry->dwCmdHlpToken = dwCmdHlpToken; 229 pEntry->dwFlags = dwFlags; 230 231 if (pGroup->pCommandListHead == NULL && pGroup->pCommandListTail == NULL) 232 { 233 pGroup->pCommandListHead = pEntry; 234 pGroup->pCommandListTail = pEntry; 235 } 236 else 237 { 238 pEntry->pPrev = pGroup->pCommandListTail; 239 pGroup->pCommandListTail->pNext = pEntry; 240 pGroup->pCommandListTail = pEntry; 241 } 242 243 return pEntry; 244} 245 246 247VOID 248RemoveContextFromStack( 249 _In_ PCONTEXT_ENTRY pContextEntry) 250{ 251 PCONTEXT_STACK_ENTRY pStackEntry, pNextEntry; 252 253 if (pContextStackHead == NULL) 254 return; 255 256 pStackEntry = pContextStackHead; 257 while (1) 258 { 259 if (pStackEntry->pContext == pContextEntry) 260 { 261 if (pStackEntry == pContextStackHead && pStackEntry == pContextStackHead) 262 { 263 pContextStackHead = NULL; 264 pContextStackTail = NULL; 265 HeapFree(GetProcessHeap(), 0, pStackEntry); 266 return; 267 } 268 else if (pStackEntry == pContextStackHead) 269 { 270 pStackEntry->pNext->pPrev = NULL; 271 pContextStackHead = pStackEntry->pNext; 272 HeapFree(GetProcessHeap(), 0, pStackEntry); 273 pStackEntry = pContextStackHead; 274 } 275 else if (pStackEntry == pContextStackTail) 276 { 277 pStackEntry->pPrev->pNext = NULL; 278 pContextStackTail = pStackEntry->pPrev; 279 HeapFree(GetProcessHeap(), 0, pStackEntry); 280 return; 281 } 282 else 283 { 284 pNextEntry = pStackEntry->pNext; 285 pStackEntry->pPrev->pNext = pStackEntry->pNext; 286 pStackEntry->pNext->pPrev = pStackEntry->pPrev; 287 HeapFree(GetProcessHeap(), 0, pStackEntry); 288 pStackEntry = pNextEntry; 289 } 290 } 291 else 292 { 293 if (pStackEntry == pContextStackTail) 294 return; 295 296 pStackEntry = pStackEntry->pNext; 297 } 298 } 299} 300 301 302VOID 303DeleteContext( 304 PWSTR pszName) 305{ 306 /* Remove the context from the stack */ 307 /* RemoveContextFromStack(); */ 308 309 /* Delete all commands */ 310 /* Delete the context */ 311} 312 313 314static 315int 316ContextCompare( 317 _In_ const void *p1, 318 _In_ const void *p2) 319{ 320 return ((PCONTEXT_ENTRY)p1)->ulPriority - ((PCONTEXT_ENTRY)p2)->ulPriority; 321} 322 323 324static 325DWORD 326DumpContext( 327 _In_ PCONTEXT_ENTRY pContext, 328 _In_ LPCWSTR pwszMachine, 329 _In_ LPWSTR *ppwcArguments, 330 _In_ DWORD dwArgCount, 331 _In_ LPCVOID pvData) 332{ 333 PCONTEXT_ENTRY pSubContext, *pSortArray = NULL; 334 DWORD dwCount, dwIndex; 335 DWORD dwError = ERROR_SUCCESS; 336 337 DPRINT("DumpContext()\n"); 338 339 if (pContext->pfnDumpFn) 340 { 341 dwError = pContext->pfnDumpFn(pwszMachine, 342 ppwcArguments, 343 dwArgCount, 344 pvData); 345 if (dwError != ERROR_SUCCESS) 346 { 347 DPRINT1("Dump function failed (Error %lu)\n", dwError); 348 return dwError; 349 } 350 } 351 352 if (pContext->pSubContextHead == NULL) 353 return dwError; 354 355 /* Count the sub-contexts */ 356 dwCount = 0; 357 pSubContext = pContext->pSubContextHead; 358 while (pSubContext) 359 { 360 dwCount++; 361 pSubContext = pSubContext->pNext; 362 } 363 364 /* Allocate the sort array */ 365 pSortArray = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(PCONTEXT_ENTRY)); 366 if (pSortArray == NULL) 367 return ERROR_NOT_ENOUGH_MEMORY; 368 369 /* Fill the sort array */ 370 dwIndex = 0; 371 pSubContext = pContext->pSubContextHead; 372 while (pSubContext) 373 { 374 pSortArray[dwIndex] = pSubContext; 375 dwIndex++; 376 pSubContext = pSubContext->pNext; 377 } 378 379 /* Sort the array */ 380 qsort(pSortArray, dwCount, sizeof(PCONTEXT_ENTRY), ContextCompare); 381 382 /* Dump the sub-contexts */ 383 for (dwIndex = 0; dwIndex < dwCount; dwIndex++) 384 { 385 dwError = DumpContext(pSortArray[dwIndex], 386 pwszMachine, 387 ppwcArguments, 388 dwArgCount, 389 pvData); 390 if (dwError != ERROR_SUCCESS) 391 { 392 DPRINT1("Dump function failed (Error %lu)\n", dwError); 393 break; 394 } 395 } 396 397 /* Free the sort array */ 398 HeapFree(GetProcessHeap(), 0, pSortArray); 399 400 return dwError; 401} 402 403static 404DWORD 405CommitContext( 406 _In_ PCONTEXT_ENTRY pContext, 407 _In_ DWORD dwAction) 408{ 409 PCONTEXT_ENTRY pSubContext, *pSortArray = NULL; 410 DWORD dwCount, dwIndex; 411 DWORD dwError = ERROR_SUCCESS; 412 413 DPRINT1("CommitContext(%p %lu)\n", pContext, dwAction); 414 415 if (pContext->pfnCommitFn) 416 { 417 dwError = pContext->pfnCommitFn(dwAction); 418 if (dwError != ERROR_SUCCESS) 419 { 420 DPRINT1("Commit function failed (Error %lu)\n", dwError); 421 return dwError; 422 } 423 } 424 425 if (pContext->pSubContextHead == NULL) 426 return dwError; 427 428 /* Count the sub-contexts */ 429 dwCount = 0; 430 pSubContext = pContext->pSubContextHead; 431 while (pSubContext) 432 { 433 dwCount++; 434 pSubContext = pSubContext->pNext; 435 } 436 437 /* Allocate the sort array */ 438 pSortArray = HeapAlloc(GetProcessHeap(), 0, dwCount * sizeof(PCONTEXT_ENTRY)); 439 if (pSortArray == NULL) 440 return ERROR_NOT_ENOUGH_MEMORY; 441 442 /* Fill the sort array */ 443 dwIndex = 0; 444 pSubContext = pContext->pSubContextHead; 445 while (pSubContext) 446 { 447 pSortArray[dwIndex] = pSubContext; 448 dwIndex++; 449 pSubContext = pSubContext->pNext; 450 } 451 452 /* Sort the array */ 453 qsort(pSortArray, dwCount, sizeof(PCONTEXT_ENTRY), ContextCompare); 454 455 /* Commit the sub-contexts */ 456 for (dwIndex = 0; dwIndex < dwCount; dwIndex++) 457 { 458 dwError = CommitContext(pSortArray[dwIndex], 459 dwAction); 460 if (dwError != ERROR_SUCCESS) 461 { 462 DPRINT1("Commit function failed (Error %lu)\n", dwError); 463 break; 464 } 465 } 466 467 /* Free the sort array */ 468 HeapFree(GetProcessHeap(), 0, pSortArray); 469 470 return dwError; 471} 472 473 474DWORD 475WINAPI 476UpCommand( 477 _In_ LPCWSTR pwszMachine, 478 _In_ LPWSTR *argv, 479 _In_ DWORD dwCurrentIndex, 480 _In_ DWORD dwArgCount, 481 _In_ DWORD dwFlags, 482 _In_ LPCVOID pvData, 483 _Out_ BOOL *pbDone) 484{ 485 if (pCurrentContext != pRootContext) 486 pCurrentContext = pCurrentContext->pParentContext; 487 488 return ERROR_SUCCESS; 489} 490 491 492DWORD 493WINAPI 494AbortCommand( 495 _In_ LPCWSTR pwszMachine, 496 _In_ LPWSTR *argv, 497 _In_ DWORD dwCurrentIndex, 498 _In_ DWORD dwArgCount, 499 _In_ DWORD dwFlags, 500 _In_ LPCVOID pvData, 501 _Out_ BOOL *pbDone) 502{ 503 DPRINT("AbortCommand()\n"); 504 CommitContext(pRootContext, NETSH_FLUSH); 505 return ERROR_SUCCESS; 506} 507 508 509DWORD 510WINAPI 511CommitCommand( 512 _In_ LPCWSTR pwszMachine, 513 _In_ LPWSTR *argv, 514 _In_ DWORD dwCurrentIndex, 515 _In_ DWORD dwArgCount, 516 _In_ DWORD dwFlags, 517 _In_ LPCVOID pvData, 518 _Out_ BOOL *pbDone) 519{ 520 DPRINT("CommitCommand()\n"); 521 CommitContext(pRootContext, NETSH_SAVE); 522 return ERROR_SUCCESS; 523} 524 525 526DWORD 527WINAPI 528DumpCommand( 529 _In_ LPCWSTR pwszMachine, 530 _In_ LPWSTR *ppwcArguments, 531 _In_ DWORD dwCurrentIndex, 532 _In_ DWORD dwArgCount, 533 _In_ DWORD dwFlags, 534 _In_ LPCVOID pvData, 535 _Out_ BOOL *pbDone) 536{ 537 DPRINT("DumpCommand()\n"); 538 539 return DumpContext(pCurrentContext, 540 pwszMachine, 541 ppwcArguments, 542 dwArgCount, 543 pvData); 544} 545 546 547DWORD 548WINAPI 549ExecCommand( 550 _In_ LPCWSTR pwszMachine, 551 _In_ LPWSTR *argv, 552 _In_ DWORD dwCurrentIndex, 553 _In_ DWORD dwArgCount, 554 _In_ DWORD dwFlags, 555 _In_ LPCVOID pvData, 556 _Out_ BOOL *pbDone) 557{ 558 DPRINT("ExecCommand()\n"); 559 560 if (dwArgCount - dwCurrentIndex != 1) 561 return ERROR_SHOW_USAGE; 562 563 return RunScript(argv[dwCurrentIndex]); 564} 565 566 567DWORD 568WINAPI 569ExitCommand( 570 _In_ LPCWSTR pwszMachine, 571 _In_ LPWSTR *argv, 572 _In_ DWORD dwCurrentIndex, 573 _In_ DWORD dwArgCount, 574 _In_ DWORD dwFlags, 575 _In_ LPCVOID pvData, 576 _Out_ BOOL *pbDone) 577{ 578 if (bOnline == FALSE) 579 CommitContext(pRootContext, NETSH_FLUSH); 580 581 *pbDone = TRUE; 582 return ERROR_SUCCESS; 583} 584 585 586DWORD 587WINAPI 588RemCommand( 589 _In_ LPCWSTR pwszMachine, 590 _In_ LPWSTR *argv, 591 _In_ DWORD dwCurrentIndex, 592 _In_ DWORD dwArgCount, 593 _In_ DWORD dwFlags, 594 _In_ LPCVOID pvData, 595 _Out_ BOOL *pbDone) 596{ 597 return ERROR_SUCCESS; 598} 599 600 601DWORD 602WINAPI 603OfflineCommand( 604 _In_ LPCWSTR pwszMachine, 605 _In_ LPWSTR *argv, 606 _In_ DWORD dwCurrentIndex, 607 _In_ DWORD dwArgCount, 608 _In_ DWORD dwFlags, 609 _In_ LPCVOID pvData, 610 _Out_ BOOL *pbDone) 611{ 612 DPRINT("OfflineCommand()\n"); 613 CommitContext(pRootContext, NETSH_UNCOMMIT); 614 bOnline = FALSE; 615 return ERROR_SUCCESS; 616} 617 618 619DWORD 620WINAPI 621OnlineCommand( 622 _In_ LPCWSTR pwszMachine, 623 _In_ LPWSTR *argv, 624 _In_ DWORD dwCurrentIndex, 625 _In_ DWORD dwArgCount, 626 _In_ DWORD dwFlags, 627 _In_ LPCVOID pvData, 628 _Out_ BOOL *pbDone) 629{ 630 DPRINT("OnlineCommand()\n"); 631 CommitContext(pRootContext, NETSH_COMMIT); 632 bOnline = TRUE; 633 return ERROR_SUCCESS; 634} 635 636 637DWORD 638WINAPI 639PopdCommand( 640 _In_ LPCWSTR pwszMachine, 641 _In_ LPWSTR *argv, 642 _In_ DWORD dwCurrentIndex, 643 _In_ DWORD dwArgCount, 644 _In_ DWORD dwFlags, 645 _In_ LPCVOID pvData, 646 _Out_ BOOL *pbDone) 647{ 648 PCONTEXT_STACK_ENTRY pEntry; 649 650 DPRINT("PopdCommand()\n"); 651 652 if (pContextStackHead == NULL) 653 return ERROR_SUCCESS; 654 655 pEntry = pContextStackHead; 656 657 pCurrentContext = pEntry->pContext; 658 659 if (pContextStackTail == pEntry) 660 { 661 pContextStackHead = NULL; 662 pContextStackTail = NULL; 663 } 664 else 665 { 666 pContextStackHead = pEntry->pNext; 667 pContextStackHead->pPrev = NULL; 668 } 669 670 HeapFree(GetProcessHeap(), 0, pEntry); 671 672 return ERROR_SUCCESS; 673} 674 675 676DWORD 677WINAPI 678PushdCommand( 679 _In_ LPCWSTR pwszMachine, 680 _In_ LPWSTR *argv, 681 _In_ DWORD dwCurrentIndex, 682 _In_ DWORD dwArgCount, 683 _In_ DWORD dwFlags, 684 _In_ LPCVOID pvData, 685 _Out_ BOOL *pbDone) 686{ 687 PCONTEXT_STACK_ENTRY pEntry; 688 689 DPRINT("PushdCommand()\n"); 690 691 pEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CONTEXT_STACK_ENTRY)); 692 if (pEntry == NULL) 693 return ERROR_NOT_ENOUGH_MEMORY; 694 695 pEntry->pContext = pCurrentContext; 696 if (pContextStackHead == NULL) 697 { 698 pContextStackHead = pEntry; 699 pContextStackTail = pEntry; 700 } 701 else 702 { 703 pEntry->pNext = pContextStackHead; 704 pContextStackHead->pPrev = pEntry; 705 pContextStackHead = pEntry; 706 } 707 708 return ERROR_SUCCESS; 709} 710 711 712DWORD 713WINAPI 714SetMachineCommand( 715 _In_ LPCWSTR pwszMachine, 716 _In_ LPWSTR *argv, 717 _In_ DWORD dwCurrentIndex, 718 _In_ DWORD dwArgCount, 719 _In_ DWORD dwFlags, 720 _In_ LPCVOID pvData, 721 _Out_ BOOL *pbDone) 722{ 723 DWORD dwError = ERROR_SUCCESS; 724 725 DPRINT("SetMachineCommand(pwszMachine %S dwCurrentIndex %lu dwArgCount %lu)\n", 726 pwszMachine, dwCurrentIndex, dwArgCount); 727 728 if ((dwArgCount - dwCurrentIndex) > 1) 729 return ERROR_SHOW_USAGE; 730 731 if (pszMachine != NULL) 732 { 733 HeapFree(GetProcessHeap(), 0, pszMachine); 734 pszMachine = NULL; 735 } 736 737 if ((dwArgCount - dwCurrentIndex) == 1) 738 { 739 pszMachine = HeapAlloc(GetProcessHeap(), 0, (sizeof(argv[dwCurrentIndex]) + 1) * sizeof(WCHAR)); 740 if (pszMachine == NULL) 741 return ERROR_NOT_ENOUGH_MEMORY; 742 wcscpy(pszMachine, argv[dwCurrentIndex]); 743 } 744 745 return dwError; 746} 747 748 749DWORD 750WINAPI 751SetModeCommand( 752 _In_ LPCWSTR pwszMachine, 753 _In_ LPWSTR *argv, 754 _In_ DWORD dwCurrentIndex, 755 _In_ DWORD dwArgCount, 756 _In_ DWORD dwFlags, 757 _In_ LPCVOID pvData, 758 _Out_ BOOL *pbDone) 759{ 760 DWORD dwError = ERROR_SUCCESS; 761 762 DPRINT("SetModeCommand(pwszMachine %S dwCurrentIndex %lu dwArgCount %lu)\n", 763 pwszMachine, dwCurrentIndex, dwArgCount); 764 765 if ((dwArgCount - dwCurrentIndex) != 1) 766 return ERROR_SHOW_USAGE; 767 768 if (!_wcsicmp(argv[dwCurrentIndex], L"offline")) 769 { 770 CommitContext(pRootContext, NETSH_UNCOMMIT); 771 bOnline = FALSE; 772 } 773 else if (!_wcsicmp(argv[dwCurrentIndex], L"online")) 774 { 775 CommitContext(pRootContext, NETSH_COMMIT); 776 bOnline = TRUE; 777 } 778 else 779 { 780 dwError = ERROR_INVALID_SYNTAX; 781 } 782 783 return dwError; 784} 785 786 787DWORD 788WINAPI 789ShowModeCommand( 790 _In_ LPCWSTR pwszMachine, 791 _In_ LPWSTR *argv, 792 _In_ DWORD dwCurrentIndex, 793 _In_ DWORD dwArgCount, 794 _In_ DWORD dwFlags, 795 _In_ LPCVOID pvData, 796 _Out_ BOOL *pbDone) 797{ 798 DPRINT("ShowModeCommand()\n"); 799 ConPuts(StdOut, bOnline ? L"online\n\n" : L"offline\n\n"); 800 return ERROR_SUCCESS; 801} 802 803 804BOOL 805CreateRootContext(VOID) 806{ 807 PCOMMAND_GROUP pGroup; 808 809 pRootContext = AddContext(NULL, L"netsh", NULL); 810 DPRINT("pRootContext: %p\n", pRootContext); 811 if (pRootContext == NULL) 812 return FALSE; 813 814 pRootContext->hModule = hModule; 815 816 AddContextCommand(pRootContext, L"..", UpCommand, IDS_HLP_UP, IDS_HLP_UP_EX, 0); 817 AddContextCommand(pRootContext, L"?", NULL, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0); 818 AddContextCommand(pRootContext, L"abort", AbortCommand, IDS_HLP_ABORT, IDS_HLP_ABORT_EX, 0); 819 AddContextCommand(pRootContext, L"alias", AliasCommand, IDS_HLP_ALIAS, IDS_HLP_ALIAS_EX, 0); 820 AddContextCommand(pRootContext, L"bye", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0); 821 AddContextCommand(pRootContext, L"commit", CommitCommand, IDS_HLP_COMMIT, IDS_HLP_COMMIT_EX, 0); 822 AddContextCommand(pRootContext, L"dump", DumpCommand, IDS_HLP_DUMP, IDS_HLP_DUMP_EX, 0); 823 AddContextCommand(pRootContext, L"exec", ExecCommand, IDS_HLP_EXEC, IDS_HLP_EXEC_EX, 0); 824 AddContextCommand(pRootContext, L"exit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0); 825 AddContextCommand(pRootContext, L"help", NULL, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0); 826 AddContextCommand(pRootContext, L"offline", OfflineCommand, IDS_HLP_OFFLINE, IDS_HLP_OFFLINE_EX, 0); 827 AddContextCommand(pRootContext, L"online", OnlineCommand, IDS_HLP_ONLINE, IDS_HLP_ONLINE_EX, 0); 828 AddContextCommand(pRootContext, L"popd", PopdCommand, IDS_HLP_POPD, IDS_HLP_POPD_EX, 0); 829 AddContextCommand(pRootContext, L"pushd", PushdCommand, IDS_HLP_PUSHD, IDS_HLP_PUSHD_EX, 0); 830 AddContextCommand(pRootContext, L"quit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0); 831 AddContextCommand(pRootContext, L"unalias", UnaliasCommand, IDS_HLP_UNALIAS, IDS_HLP_UNALIAS_EX, 0); 832 833 pGroup = AddCommandGroup(pRootContext, L"add", IDS_HLP_GROUP_ADD, 0); 834 if (pGroup) 835 { 836 AddGroupCommand(pGroup, L"helper", AddHelperCommand, IDS_HLP_ADD_HELPER, IDS_HLP_ADD_HELPER_EX, 0); 837 } 838 839 pGroup = AddCommandGroup(pRootContext, L"delete", IDS_HLP_GROUP_DELETE, 0); 840 if (pGroup) 841 { 842 AddGroupCommand(pGroup, L"helper", DeleteHelperCommand, IDS_HLP_DEL_HELPER, IDS_HLP_DEL_HELPER_EX, 0); 843 } 844 845 pGroup = AddCommandGroup(pRootContext, L"set", IDS_HLP_GROUP_SET, 0); 846 if (pGroup) 847 { 848 AddGroupCommand(pGroup, L"machine", SetMachineCommand, IDS_HLP_SET_MACHINE, IDS_HLP_SET_MACHINE_EX, 0); 849 AddGroupCommand(pGroup, L"mode", SetModeCommand, IDS_HLP_SET_MODE, IDS_HLP_SET_MODE_EX, 0); 850 } 851 852 pGroup = AddCommandGroup(pRootContext, L"show", IDS_HLP_GROUP_SHOW, 0); 853 if (pGroup) 854 { 855 AddGroupCommand(pGroup, L"alias", ShowAliasCommand, IDS_HLP_SHOW_ALIAS, IDS_HLP_SHOW_ALIAS_EX, 0); 856 AddGroupCommand(pGroup, L"helper", ShowHelperCommand, IDS_HLP_SHOW_HELPER, IDS_HLP_SHOW_HELPER_EX, 0); 857 AddGroupCommand(pGroup, L"mode", ShowModeCommand, IDS_HLP_SHOW_MODE, IDS_HLP_SHOW_MODE_EX, 0); 858 } 859 860 pCurrentContext = pRootContext; 861 862 return TRUE; 863} 864 865 866static 867PCONTEXT_ENTRY 868FindSubContextByGuid( 869 PCONTEXT_ENTRY pContext, 870 const GUID *pGuid) 871{ 872 PCONTEXT_ENTRY pResultContext, pSubContext; 873 874 DPRINT("FindSubContextByGuid(%p)\n", pContext); 875 DPRINT("%lx <--> %lx\n", pContext->Guid.Data1, pGuid->Data1); 876 877 if (IsEqualGUID(&pContext->Guid, pGuid)) 878 { 879 DPRINT("Found!\n"); 880 return pContext; 881 } 882 883 pSubContext = pContext->pSubContextHead; 884 while (pSubContext) 885 { 886 pResultContext = FindSubContextByGuid(pSubContext, pGuid); 887 if (pResultContext) 888 return pResultContext; 889 890 pSubContext = pSubContext->pNext; 891 } 892 893 return NULL; 894} 895 896 897PCONTEXT_ENTRY 898FindContextByGuid( 899 const GUID *pGuid) 900{ 901 if (pRootContext == NULL) 902 return NULL; 903 return FindSubContextByGuid(pRootContext, pGuid); 904} 905 906 907DWORD 908WINAPI 909RegisterContext( 910 _In_ const NS_CONTEXT_ATTRIBUTES *pChildContext) 911{ 912 PHELPER_ENTRY pHelper; 913 PCONTEXT_ENTRY pContext, pParentContext; 914 PCOMMAND_GROUP pGroup; 915 DWORD i, j; 916 917 DPRINT1("RegisterContext(%p)\n", pChildContext); 918 if (pChildContext == NULL) 919 { 920 DPRINT1("Invalid child context!\n"); 921 return ERROR_INVALID_PARAMETER; 922 } 923 924 if ((pChildContext->pwszContext == NULL) || 925 (wcslen(pChildContext->pwszContext) == 0) || 926 (wcschr(pChildContext->pwszContext, L' ') != 0) || 927 (wcschr(pChildContext->pwszContext, L'=') != 0)) 928 { 929 DPRINT1("Invalid context name!\n"); 930 return ERROR_INVALID_PARAMETER; 931 } 932 933 DPRINT("Name: %S\n", pChildContext->pwszContext); 934 DPRINT("Groups: %lu\n", pChildContext->ulNumGroups); 935 DPRINT("Top commands: %lu\n", pChildContext->ulNumTopCmds); 936 937 pHelper = FindHelper(&pChildContext->guidHelper, pHelperListHead); 938 DPRINT("Helper %p\n", pHelper); 939 pParentContext = pRootContext; 940 if (pHelper != NULL) 941 { 942 pParentContext = FindContextByGuid(&pHelper->ParentHelperGuid); 943 DPRINT("pParentContext %p\n", pParentContext); 944 if (pParentContext == NULL) 945 pParentContext = pRootContext; 946 } 947 948 pContext = AddContext(pParentContext, pChildContext->pwszContext, (GUID*)&pChildContext->guidHelper); 949 if (pContext != NULL) 950 { 951 pContext->pfnCommitFn = pChildContext->pfnCommitFn; 952 pContext->pfnDumpFn = pChildContext->pfnDumpFn; 953 pContext->pfnConnectFn = pChildContext->pfnConnectFn; 954 pContext->ulPriority = (pChildContext->dwFlags & CMD_FLAG_PRIORITY) ? 955 pChildContext->ulPriority : DEFAULT_CONTEXT_PRIORITY; 956 957 if ((pHelper != NULL) && (pHelper->pDllEntry != NULL)) 958 { 959 pContext->hModule = pHelper->pDllEntry->hModule; 960 } 961 962 for (i = 0; i < pChildContext->ulNumTopCmds; i++) 963 { 964 AddContextCommand(pContext, 965 pChildContext->pTopCmds[i].pwszCmdToken, 966 pChildContext->pTopCmds[i].pfnCmdHandler, 967 pChildContext->pTopCmds[i].dwShortCmdHelpToken, 968 pChildContext->pTopCmds[i].dwCmdHlpToken, 969 pChildContext->pTopCmds[i].dwFlags); 970 } 971 972 /* Add command groups */ 973 for (i = 0; i < pChildContext->ulNumGroups; i++) 974 { 975 pGroup = AddCommandGroup(pContext, 976 pChildContext->pCmdGroups[i].pwszCmdGroupToken, 977 pChildContext->pCmdGroups[i].dwShortCmdHelpToken, 978 pChildContext->pCmdGroups[i].dwFlags); 979 if (pGroup != NULL) 980 { 981 for (j = 0; j < pChildContext->pCmdGroups[i].ulCmdGroupSize; j++) 982 { 983 AddGroupCommand(pGroup, 984 pChildContext->pCmdGroups[i].pCmdGroup[j].pwszCmdToken, 985 pChildContext->pCmdGroups[i].pCmdGroup[j].pfnCmdHandler, 986 pChildContext->pCmdGroups[i].pCmdGroup[j].dwShortCmdHelpToken, 987 pChildContext->pCmdGroups[i].pCmdGroup[j].dwCmdHlpToken, 988 pChildContext->pCmdGroups[i].pCmdGroup[j].dwFlags); 989 } 990 } 991 } 992 } 993 994 return ERROR_SUCCESS; 995} 996 997 998VOID 999CleanupContext(VOID) 1000{ 1001 /* Delete the context stack */ 1002 1003}