Reactos

[NETSH] Context stack and helper improvements

- Add the context stack including the PUSHD and POPD commands.
- Add the required changes to the HELP command and command execution to support the context stack.
- Add support for sub helpers.

Eric Kohl 3f663903 359205bc

+577 -121
+197 -17
base/applications/network/netsh/context.c
··· 14 14 15 15 /* GLOBALS ********************************************************************/ 16 16 17 + typedef 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 + 17 26 PCONTEXT_ENTRY pRootContext = NULL; 18 27 PCONTEXT_ENTRY pCurrentContext = NULL; 28 + 29 + PCONTEXT_STACK_ENTRY pContextStackHead = NULL; 30 + PCONTEXT_STACK_ENTRY pContextStackTail = NULL; 19 31 20 32 /* FUNCTIONS ******************************************************************/ 21 33 ··· 135 147 { 136 148 PCOMMAND_GROUP pEntry; 137 149 150 + DPRINT("AddCommandGroup(%S %lu)\n", pwszCmdGroupToken, dwShortCmdHelpToken); 151 + 138 152 /* Allocate the entry */ 139 153 pEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(COMMAND_GROUP)); 140 154 if (pEntry == NULL) ··· 221 235 222 236 223 237 VOID 238 + RemoveContextFromStack( 239 + _In_ PCONTEXT_ENTRY pContextEntry) 240 + { 241 + PCONTEXT_STACK_ENTRY pStackEntry, pNextEntry; 242 + 243 + if (pContextStackHead == NULL) 244 + return; 245 + 246 + pStackEntry = pContextStackHead; 247 + while (1) 248 + { 249 + if (pStackEntry->pContext == pContextEntry) 250 + { 251 + if (pStackEntry == pContextStackHead && pStackEntry == pContextStackHead) 252 + { 253 + pContextStackHead = NULL; 254 + pContextStackTail = NULL; 255 + HeapFree(GetProcessHeap(), 0, pStackEntry); 256 + return; 257 + } 258 + else if (pStackEntry == pContextStackHead) 259 + { 260 + pStackEntry->pNext->pPrev = NULL; 261 + pContextStackHead = pStackEntry->pNext; 262 + HeapFree(GetProcessHeap(), 0, pStackEntry); 263 + pStackEntry = pContextStackHead; 264 + } 265 + else if (pStackEntry == pContextStackTail) 266 + { 267 + pStackEntry->pPrev->pNext = NULL; 268 + pContextStackTail = pStackEntry->pPrev; 269 + HeapFree(GetProcessHeap(), 0, pStackEntry); 270 + return; 271 + } 272 + else 273 + { 274 + pNextEntry = pStackEntry->pNext; 275 + pStackEntry->pPrev->pNext = pStackEntry->pNext; 276 + pStackEntry->pNext->pPrev = pStackEntry->pPrev; 277 + HeapFree(GetProcessHeap(), 0, pStackEntry); 278 + pStackEntry = pNextEntry; 279 + } 280 + } 281 + else 282 + { 283 + if (pStackEntry == pContextStackTail) 284 + return; 285 + 286 + pStackEntry = pStackEntry->pNext; 287 + } 288 + } 289 + } 290 + 291 + 292 + VOID 224 293 DeleteContext( 225 294 PWSTR pszName) 226 295 { 296 + /* Remove the context from the stack */ 297 + /* RemoveContextFromStack(); */ 298 + 227 299 /* Delete all commands */ 228 300 /* Delete the context */ 229 301 } ··· 278 350 } 279 351 280 352 353 + DWORD 354 + WINAPI 355 + PopdCommand( 356 + LPCWSTR pwszMachine, 357 + LPWSTR *argv, 358 + DWORD dwCurrentIndex, 359 + DWORD dwArgCount, 360 + DWORD dwFlags, 361 + LPCVOID pvData, 362 + BOOL *pbDone) 363 + { 364 + PCONTEXT_STACK_ENTRY pEntry; 365 + 366 + DPRINT("PopdCommand()\n"); 367 + 368 + if (pContextStackHead == NULL) 369 + return 0; 370 + 371 + pEntry = pContextStackHead; 372 + 373 + pCurrentContext = pEntry->pContext; 374 + 375 + if (pContextStackTail == pEntry) 376 + { 377 + pContextStackHead = NULL; 378 + pContextStackTail = NULL; 379 + } 380 + else 381 + { 382 + pContextStackHead = pEntry->pNext; 383 + pContextStackHead->pPrev = NULL; 384 + } 385 + 386 + HeapFree(GetProcessHeap(), 0, pEntry); 387 + 388 + return 0; 389 + } 390 + 391 + 392 + DWORD 393 + WINAPI 394 + PushdCommand( 395 + LPCWSTR pwszMachine, 396 + LPWSTR *argv, 397 + DWORD dwCurrentIndex, 398 + DWORD dwArgCount, 399 + DWORD dwFlags, 400 + LPCVOID pvData, 401 + _Out_ BOOL *pbDone) 402 + { 403 + PCONTEXT_STACK_ENTRY pEntry; 404 + 405 + DPRINT("PushdCommand()\n"); 406 + 407 + pEntry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CONTEXT_STACK_ENTRY)); 408 + if (pEntry == NULL) 409 + return 1; 410 + 411 + pEntry->pContext = pCurrentContext; 412 + if (pContextStackHead == NULL) 413 + { 414 + pContextStackHead = pEntry; 415 + pContextStackTail = pEntry; 416 + } 417 + else 418 + { 419 + pEntry->pNext = pContextStackHead; 420 + pContextStackHead->pPrev = pEntry; 421 + pContextStackHead = pEntry; 422 + } 423 + 424 + return 0; 425 + } 426 + 427 + 281 428 BOOL 282 429 CreateRootContext(VOID) 283 430 { ··· 290 437 291 438 pRootContext->hModule = GetModuleHandle(NULL); 292 439 293 - AddContextCommand(pRootContext, L"..", UpCommand, IDS_HLP_UP, IDS_HLP_UP_EX, 0); 294 - AddContextCommand(pRootContext, L"?", HelpCommand, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0); 295 - AddContextCommand(pRootContext, L"bye", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0); 296 - AddContextCommand(pRootContext, L"exit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0); 297 - AddContextCommand(pRootContext, L"help", HelpCommand, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0); 298 - AddContextCommand(pRootContext, L"quit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0); 440 + AddContextCommand(pRootContext, L"..", UpCommand, IDS_HLP_UP, IDS_HLP_UP_EX, 0); 441 + AddContextCommand(pRootContext, L"?", NULL, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0); 442 + AddContextCommand(pRootContext, L"bye", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0); 443 + AddContextCommand(pRootContext, L"exit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0); 444 + AddContextCommand(pRootContext, L"help", NULL, IDS_HLP_HELP, IDS_HLP_HELP_EX, 0); 445 + AddContextCommand(pRootContext, L"popd", PopdCommand, IDS_HLP_POPD, IDS_HLP_POPD_EX, 0); 446 + AddContextCommand(pRootContext, L"pushd", PushdCommand, IDS_HLP_PUSHD, IDS_HLP_PUSHD_EX, 0); 447 + AddContextCommand(pRootContext, L"quit", ExitCommand, IDS_HLP_EXIT, IDS_HLP_EXIT_EX, 0); 299 448 300 449 pGroup = AddCommandGroup(pRootContext, L"add", IDS_HLP_GROUP_ADD, 0); 301 450 if (pGroup) ··· 326 475 RegisterContext( 327 476 _In_ const NS_CONTEXT_ATTRIBUTES *pChildContext) 328 477 { 478 + PHELPER_ENTRY pHelper; 329 479 PCONTEXT_ENTRY pContext; 330 - DWORD i; 480 + PCOMMAND_GROUP pGroup; 481 + DWORD i, j; 331 482 332 483 DPRINT1("RegisterContext(%p)\n", pChildContext); 333 484 if (pChildContext == NULL) ··· 345 496 return ERROR_INVALID_PARAMETER; 346 497 } 347 498 348 - DPRINT1("Name: %S\n", pChildContext->pwszContext); 499 + DPRINT("Name: %S\n", pChildContext->pwszContext); 500 + DPRINT("Groups: %lu\n", pChildContext->ulNumGroups); 501 + DPRINT("Top commands: %lu\n", pChildContext->ulNumTopCmds); 502 + 503 + pHelper = FindHelper(&pChildContext->guidHelper, pHelperListHead); 349 504 350 505 pContext = AddContext(pRootContext, pChildContext->pwszContext, (GUID*)&pChildContext->guidHelper); 351 506 if (pContext != NULL) 352 507 { 508 + if ((pHelper != NULL) && (pHelper->pDllEntry != NULL)) 509 + { 510 + pContext->hModule = pHelper->pDllEntry->hModule; 511 + } 512 + 353 513 for (i = 0; i < pChildContext->ulNumTopCmds; i++) 354 514 { 355 515 AddContextCommand(pContext, 356 - pChildContext->pTopCmds[i].pwszCmdToken, 357 - pChildContext->pTopCmds[i].pfnCmdHandler, 358 - pChildContext->pTopCmds[i].dwShortCmdHelpToken, 359 - pChildContext->pTopCmds[i].dwCmdHlpToken, 360 - pChildContext->pTopCmds[i].dwFlags); 516 + pChildContext->pTopCmds[i].pwszCmdToken, 517 + pChildContext->pTopCmds[i].pfnCmdHandler, 518 + pChildContext->pTopCmds[i].dwShortCmdHelpToken, 519 + pChildContext->pTopCmds[i].dwCmdHlpToken, 520 + pChildContext->pTopCmds[i].dwFlags); 361 521 } 362 522 363 523 /* Add command groups */ 364 524 for (i = 0; i < pChildContext->ulNumGroups; i++) 365 525 { 366 - AddCommandGroup(pContext, 367 - pChildContext->pCmdGroups[i].pwszCmdGroupToken, 368 - pChildContext->pCmdGroups[i].dwShortCmdHelpToken, 369 - pChildContext->pCmdGroups[i].dwFlags); 526 + pGroup = AddCommandGroup(pContext, 527 + pChildContext->pCmdGroups[i].pwszCmdGroupToken, 528 + pChildContext->pCmdGroups[i].dwShortCmdHelpToken, 529 + pChildContext->pCmdGroups[i].dwFlags); 530 + if (pGroup != NULL) 531 + { 532 + for (j = 0; j < pChildContext->pCmdGroups[i].ulCmdGroupSize; j++) 533 + { 534 + AddGroupCommand(pGroup, 535 + pChildContext->pCmdGroups[i].pCmdGroup[j].pwszCmdToken, 536 + pChildContext->pCmdGroups[i].pCmdGroup[j].pfnCmdHandler, 537 + pChildContext->pCmdGroups[i].pCmdGroup[j].dwShortCmdHelpToken, 538 + pChildContext->pCmdGroups[i].pCmdGroup[j].dwCmdHlpToken, 539 + pChildContext->pCmdGroups[i].pCmdGroup[j].dwFlags); 540 + } 541 + } 370 542 } 371 543 } 372 544 373 545 return ERROR_SUCCESS; 374 546 } 547 + 548 + 549 + VOID 550 + CleanupContext(VOID) 551 + { 552 + /* Delete the context stack */ 553 + 554 + }
+209 -37
base/applications/network/netsh/help.c
··· 36 36 37 37 static 38 38 VOID 39 - HelpContext( 40 - PCONTEXT_ENTRY pContext) 39 + PrintCurrentContextHeader( 40 + _In_ PCONTEXT_ENTRY pContext) 41 41 { 42 - PCONTEXT_ENTRY pSubContext; 43 - PCOMMAND_ENTRY pCommand; 44 - PCOMMAND_GROUP pGroup; 45 42 WCHAR szBuffer[80]; 46 - 47 - if (pContext != pRootContext) 48 - HelpContext(pContext->pParentContext); 49 43 50 44 if (pContext == pCurrentContext) 51 45 { ··· 60 54 GetContextFullName(pContext, szBuffer, 80); 61 55 ConPrintf(StdOut, L"\nCommands in the %s-context:\n", szBuffer); 62 56 } 57 + } 58 + 59 + 60 + static 61 + VOID 62 + PrintShortCommands( 63 + _In_ PCONTEXT_ENTRY pContext) 64 + { 65 + PCOMMAND_ENTRY pCommand; 66 + WCHAR szBuffer[80]; 63 67 64 68 pCommand = pContext->pCommandListHead; 65 69 while (pCommand != NULL) ··· 69 73 ConPrintf(StdOut, L"%-15s - %s\n", pCommand->pwszCmdToken, szBuffer); 70 74 pCommand = pCommand->pNext; 71 75 } 76 + } 77 + 78 + 79 + static 80 + VOID 81 + PrintShortGroups( 82 + _In_ PCONTEXT_ENTRY pContext) 83 + { 84 + PCOMMAND_GROUP pGroup; 85 + WCHAR szBuffer[80]; 72 86 73 87 pGroup = pContext->pGroupListHead; 74 88 while (pGroup != NULL) ··· 78 92 ConPrintf(StdOut, L"%-15s - %s\n", pGroup->pwszCmdGroupToken, szBuffer); 79 93 pGroup = pGroup->pNext; 80 94 } 95 + } 96 + 97 + 98 + static 99 + VOID 100 + PrintShortSubContexts( 101 + _In_ PCONTEXT_ENTRY pContext) 102 + { 103 + PCONTEXT_ENTRY pSubContext; 104 + WCHAR szBuffer[80]; 81 105 82 106 pSubContext = pContext->pSubContextHead; 83 107 while (pSubContext != NULL) ··· 88 112 } 89 113 } 90 114 91 - 115 + static 92 116 VOID 93 - HelpGroup( 94 - PCOMMAND_GROUP pGroup) 117 + PrintShortGroupCommands( 118 + _In_ PCONTEXT_ENTRY pContext, 119 + _In_ PCOMMAND_GROUP pGroup) 95 120 { 96 121 PCOMMAND_ENTRY pCommand; 97 - WCHAR szBuffer[64]; 98 - 99 - ConResPrintf(StdOut, IDS_HELP_HEADER); 100 - 101 - ConPrintf(StdOut, L"\nCommands in this context:\n"); 122 + WCHAR szBuffer1[64]; 123 + WCHAR szBuffer2[80]; 102 124 103 125 pCommand = pGroup->pCommandListHead; 104 126 while (pCommand != NULL) 105 127 { 106 - swprintf(szBuffer, L"%s %s", pGroup->pwszCmdGroupToken, pCommand->pwszCmdToken); 107 - ConPrintf(StdOut, L"%-15s - ", szBuffer); 108 - ConResPuts(StdOut, pCommand->dwShortCmdHelpToken); 128 + swprintf(szBuffer1, L"%s %s", pGroup->pwszCmdGroupToken, pCommand->pwszCmdToken); 129 + LoadStringW(pContext->hModule, pCommand->dwShortCmdHelpToken, szBuffer2, 80); 130 + 131 + ConPrintf(StdOut, L"%-15s - %s\n", szBuffer1, szBuffer2); 109 132 pCommand = pCommand->pNext; 110 133 } 111 134 } 112 135 113 136 114 - DWORD 115 - WINAPI 116 - HelpCommand( 117 - LPCWSTR pwszMachine, 118 - LPWSTR *ppwcArguments, 119 - DWORD dwCurrentIndex, 120 - DWORD dwArgCount, 121 - DWORD dwFlags, 122 - LPCVOID pvData, 123 - BOOL *pbDone) 137 + static 138 + VOID 139 + PrintLongCommand( 140 + _In_ PCONTEXT_ENTRY pContext, 141 + _In_ PCOMMAND_ENTRY pCommand) 142 + { 143 + WCHAR szBuffer[80]; 144 + 145 + LoadStringW(pContext->hModule, pCommand->dwCmdHlpToken, szBuffer, 80); 146 + ConPrintf(StdOut, szBuffer); 147 + } 148 + 149 + 150 + static 151 + VOID 152 + PrintContext( 153 + _In_ PCONTEXT_ENTRY pContext) 124 154 { 125 - PCONTEXT_ENTRY pContext; 155 + DPRINT1("PrintContext()\n"); 156 + 157 + if (pContext != pRootContext) 158 + PrintContext(pContext->pParentContext); 159 + 160 + PrintCurrentContextHeader(pContext); 161 + 162 + PrintShortCommands(pContext); 163 + 164 + PrintShortGroups(pContext); 165 + 166 + PrintShortSubContexts(pContext); 167 + } 126 168 127 - ConResPrintf(StdOut, IDS_HELP_HEADER); 128 169 129 - pContext = pCurrentContext; 130 - if (pContext == NULL) 170 + static 171 + VOID 172 + PrintGroup( 173 + _In_ PCONTEXT_ENTRY pContext, 174 + _In_ LPWSTR pszGroupName, 175 + _In_ BOOL bRecurse) 176 + { 177 + PCOMMAND_GROUP pGroup; 178 + 179 + if (bRecurse) 131 180 { 132 - DPRINT1("HelpCommand: invalid context %p\n", pContext); 133 - return 1; 181 + if (pContext != pRootContext) 182 + PrintGroup(pContext->pParentContext, pszGroupName, bRecurse); 134 183 } 135 184 136 - HelpContext(pContext); 185 + pGroup = pContext->pGroupListHead; 186 + while (pGroup != NULL) 187 + { 188 + if (_wcsicmp(pszGroupName, pGroup->pwszCmdGroupToken) == 0) 189 + { 190 + PrintCurrentContextHeader(pContext); 191 + PrintShortGroupCommands(pContext, pGroup); 192 + } 193 + pGroup = pGroup->pNext; 194 + } 195 + } 137 196 197 + 198 + static 199 + VOID 200 + PrintSubcontexts( 201 + _In_ PCONTEXT_ENTRY pContext) 202 + { 138 203 if (pCurrentContext->pSubContextHead != NULL) 139 204 { 140 205 ConResPrintf(StdOut, IDS_SUBCONTEXT_HEADER); ··· 146 211 } 147 212 ConPuts(StdOut, L"\n"); 148 213 } 149 - ConPuts(StdOut, L"\n"); 214 + } 215 + 216 + 217 + BOOL 218 + ProcessHelp( 219 + _In_ PCONTEXT_ENTRY pContext, 220 + _In_ DWORD dwArgCount, 221 + _In_ LPWSTR *argv, 222 + _In_ DWORD dwCurrentIndex, 223 + _In_ DWORD dwHelpLevel) 224 + { 225 + PCONTEXT_ENTRY pSubContext; 226 + PCOMMAND_ENTRY pCommand; 227 + PCOMMAND_GROUP pGroup; 228 + 229 + DPRINT("ProcessHelp(dwCurrentIndex %lu dwArgCount %lu dwHelpLevel %lu)\n", dwCurrentIndex, dwArgCount, dwHelpLevel); 230 + 231 + if (dwHelpLevel == dwCurrentIndex) 232 + { 233 + ConResPrintf(StdOut, IDS_HELP_HEADER); 234 + PrintContext(pContext); 235 + PrintSubcontexts(pContext); 236 + ConResPrintf(StdOut, IDS_HELP_FOOTER); 237 + return TRUE; 238 + } 239 + 240 + pCommand = pContext->pCommandListHead; 241 + while (pCommand != NULL) 242 + { 243 + if (_wcsicmp(argv[dwCurrentIndex], pCommand->pwszCmdToken) == 0) 244 + { 245 + if (dwHelpLevel == dwCurrentIndex + 1) 246 + { 247 + PrintLongCommand(pContext, pCommand); 248 + return TRUE; 249 + } 250 + } 251 + 252 + pCommand = pCommand->pNext; 253 + } 254 + 255 + pGroup = pContext->pGroupListHead; 256 + while (pGroup != NULL) 257 + { 258 + if (_wcsicmp(argv[dwCurrentIndex], pGroup->pwszCmdGroupToken) == 0) 259 + { 260 + if (dwHelpLevel == dwCurrentIndex + 1) 261 + { 262 + ConResPrintf(StdOut, IDS_HELP_HEADER); 263 + PrintGroup(pContext, argv[dwCurrentIndex], (dwHelpLevel == 1)); 264 + return TRUE; 265 + } 266 + 267 + pCommand = pGroup->pCommandListHead; 268 + while (pCommand != NULL) 269 + { 270 + if ((dwArgCount > dwCurrentIndex + 1) && (_wcsicmp(argv[dwCurrentIndex + 1], pCommand->pwszCmdToken) == 0)) 271 + { 272 + if (dwHelpLevel == dwCurrentIndex + 2) 273 + { 274 + PrintLongCommand(pContext, pCommand); 275 + return TRUE; 276 + } 277 + } 278 + 279 + pCommand = pCommand->pNext; 280 + } 281 + 282 + // ConResPrintf(StdOut, IDS_HELP_HEADER); 283 + // PrintGroup(pContext, pGroup); 284 + return FALSE; 285 + } 286 + 287 + pGroup = pGroup->pNext; 288 + } 289 + 290 + if (pContext == pCurrentContext) 291 + { 292 + pSubContext = pContext->pSubContextHead; 293 + while (pSubContext != NULL) 294 + { 295 + if (_wcsicmp(argv[dwCurrentIndex], pSubContext->pszContextName) == 0) 296 + { 297 + return ProcessHelp(pSubContext, 298 + dwArgCount, 299 + argv, 300 + dwCurrentIndex + 1, 301 + dwHelpLevel); 302 + } 303 + 304 + pSubContext = pSubContext->pNext; 305 + } 306 + } 150 307 308 + return FALSE; 309 + } 310 + 311 + 312 + DWORD 313 + WINAPI 314 + HelpCommand( 315 + LPCWSTR pwszMachine, 316 + LPWSTR *ppwcArguments, 317 + DWORD dwCurrentIndex, 318 + DWORD dwArgCount, 319 + DWORD dwFlags, 320 + LPCVOID pvData, 321 + BOOL *pbDone) 322 + { 151 323 return ERROR_SUCCESS; 152 324 }
+31 -12
base/applications/network/netsh/helper.c
··· 26 26 27 27 static 28 28 VOID 29 - StartHelpers(VOID) 29 + StartHelpers( 30 + PHELPER_ENTRY pHelper) 30 31 { 31 - PHELPER_ENTRY pHelper; 32 + PHELPER_ENTRY pSubHelper; 32 33 DWORD dwError; 33 34 34 - pHelper = pHelperListHead; 35 35 while (pHelper != NULL) 36 36 { 37 37 if (pHelper->bStarted == FALSE) ··· 42 42 if (dwError == ERROR_SUCCESS) 43 43 pHelper->bStarted = TRUE; 44 44 } 45 + } 46 + 47 + pSubHelper = pHelper->pSubHelperHead; 48 + while (pSubHelper != NULL) 49 + { 50 + StartHelpers(pSubHelper); 51 + pSubHelper = pSubHelper->pNext; 45 52 } 46 53 47 54 pHelper = pHelper->pNext; ··· 310 317 311 318 RegCloseKey(hKey); 312 319 313 - StartHelpers(); 320 + StartHelpers(pHelperListHead); 314 321 } 315 322 316 323 ··· 336 343 337 344 PHELPER_ENTRY 338 345 FindHelper( 339 - _In_ const GUID *pguidHelper) 346 + _In_ const GUID *pguidHelper, 347 + _In_ PHELPER_ENTRY pHelper) 340 348 { 341 - PHELPER_ENTRY pHelper; 349 + PHELPER_ENTRY pFoundHelper; 342 350 343 - pHelper = pHelperListHead; 351 + // pHelper = pHelperListHead; 344 352 while (pHelper != NULL) 345 353 { 346 354 if (IsEqualGUID(pguidHelper, &pHelper->Attributes.guidHelper)) 347 355 return pHelper; 356 + 357 + pFoundHelper = FindHelper(pguidHelper, pHelper->pSubHelperHead); 358 + if (pFoundHelper) 359 + return pFoundHelper; 348 360 349 361 pHelper = pHelper->pNext; 350 362 } ··· 364 376 365 377 DPRINT("RegisterHelper(%p %p)\n", pguidParentHelper, pHelperAttributes); 366 378 367 - if (FindHelper(&pHelperAttributes->guidHelper) != NULL) 379 + if (FindHelper(&pHelperAttributes->guidHelper, pHelperListHead) != NULL) 368 380 { 369 381 DPRINT1("The Helper has already been registered!\n"); 370 382 return 1; ··· 397 409 } 398 410 else 399 411 { 400 - pParentHelper = FindHelper(&pHelperAttributes->guidHelper); 412 + pParentHelper = FindHelper(pguidParentHelper, pHelperListHead); 401 413 if (pParentHelper == NULL) 414 + { 415 + DPRINT("Parent helper not found!\n"); 402 416 return ERROR_INVALID_PARAMETER; 417 + } 403 418 404 419 if (pParentHelper->pSubHelperHead == NULL && pParentHelper->pSubHelperTail == NULL) 405 420 { ··· 446 461 if (dwError != ERROR_SUCCESS) 447 462 return dwError; 448 463 449 - StartHelpers(); 464 + StartHelpers(pHelperListHead); 450 465 451 466 return ERROR_SUCCESS; 452 467 } ··· 528 543 WCHAR szPrefix[22]; 529 544 DWORD i; 530 545 546 + DPRINT("PrintSubContext(%p %lu)\n", pParentContext, dwLevel); 547 + 531 548 if (pParentContext == NULL) 532 549 return; 533 550 534 551 pContext = pParentContext->pSubContextHead; 535 552 while (pContext != NULL) 536 553 { 537 - pHelper = FindHelper(&pContext->Guid); 554 + pHelper = FindHelper(&pContext->Guid, pHelperListHead); 538 555 if (pHelper != NULL) 539 556 { 540 557 if (dwLevel > 10) ··· 542 559 543 560 for (i = 0; i < dwLevel * 2; i++) 544 561 szPrefix[i] = L' '; 545 - szPrefix[i] = UNICODE_NULL; 562 + szPrefix[dwLevel * 2] = UNICODE_NULL; 563 + 564 + DPRINT("Level %lu \"%S\" %S\n", dwLevel, szPrefix, pContext->pszContextName); 546 565 547 566 ConPrintf(StdOut, L"{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X} %-16s %s%s\n", 548 567 pHelper->Attributes.guidHelper.Data1,
+87 -46
base/applications/network/netsh/interpreter.c
··· 15 15 /* FUNCTIONS *****************************************************************/ 16 16 17 17 BOOL 18 - InterpretCommand( 18 + ProcessCommand( 19 + _In_ PCONTEXT_ENTRY pContext, 20 + _In_ DWORD dwArgCount, 19 21 _In_ LPWSTR *argv, 20 - _In_ DWORD dwArgCount) 22 + _In_ DWORD dwCurrentIndex, 23 + _In_ DWORD dwHelpLevel, 24 + _Inout_ PBOOL bDone) 21 25 { 22 - PCONTEXT_ENTRY pContext, pSubContext; 26 + PCONTEXT_ENTRY pSubContext; 23 27 PCOMMAND_ENTRY pCommand; 24 28 PCOMMAND_GROUP pGroup; 25 - BOOL bDone = FALSE; 26 - DWORD dwHelpLevel = 0; 27 29 DWORD dwError = ERROR_SUCCESS; 28 30 29 31 /* If no args provided */ ··· 51 53 { 52 54 if (_wcsicmp(argv[0], pCommand->pwszCmdToken) == 0) 53 55 { 54 - if (dwHelpLevel == 1) 56 + dwError = pCommand->pfnCmdHandler(NULL, argv, dwCurrentIndex, dwArgCount, 0, NULL, bDone); 57 + if (dwError != ERROR_SUCCESS) 55 58 { 59 + ConPrintf(StdOut, L"Error: %lu\n\n", dwError); 56 60 ConResPrintf(StdOut, pCommand->dwCmdHlpToken); 57 - return TRUE; 58 61 } 59 - else 60 - { 61 - dwError = pCommand->pfnCmdHandler(NULL, argv, 0, dwArgCount, 0, NULL, &bDone); 62 - if (dwError != ERROR_SUCCESS) 63 - { 64 - ConPrintf(StdOut, L"Error: %lu\n\n"); 65 - ConResPrintf(StdOut, pCommand->dwCmdHlpToken); 66 - } 67 - return !bDone; 68 - } 62 + return TRUE; 69 63 } 70 64 71 65 pCommand = pCommand->pNext; ··· 76 70 { 77 71 if (_wcsicmp(argv[0], pGroup->pwszCmdGroupToken) == 0) 78 72 { 79 - if (dwHelpLevel == 1) 73 + if (dwArgCount == 1) 80 74 { 81 - HelpGroup(pGroup); 75 + ProcessHelp(pContext, dwArgCount, argv, dwCurrentIndex, dwHelpLevel + 1); 82 76 return TRUE; 83 77 } 84 - 85 - pCommand = pGroup->pCommandListHead; 86 - while (pCommand != NULL) 78 + else 87 79 { 88 - if ((dwArgCount > 1) && (_wcsicmp(argv[1], pCommand->pwszCmdToken) == 0)) 80 + pCommand = pGroup->pCommandListHead; 81 + while (pCommand != NULL) 89 82 { 90 - if (dwHelpLevel == 2) 83 + if ((dwArgCount > 1) && (_wcsicmp(argv[1], pCommand->pwszCmdToken) == 0)) 84 + // if ((dwArgCount > dwCurrentIndex + 1) && (wcsicmp(argv[dwCurrentIndex + 1], pCommand->pwszCmdToken) == 0)) 91 85 { 92 - ConResPrintf(StdOut, pCommand->dwCmdHlpToken); 93 - return TRUE; 94 - } 95 - else 96 - { 97 - dwError = pCommand->pfnCmdHandler(NULL, argv, 1, dwArgCount, 0, NULL, &bDone); 86 + dwError = pCommand->pfnCmdHandler(NULL, argv, dwCurrentIndex + 1, dwArgCount, 0, NULL, bDone); 98 87 if (dwError != ERROR_SUCCESS) 99 88 { 100 - ConPrintf(StdOut, L"Error: %lu\n\n"); 89 + ConPrintf(StdOut, L"Error: %lu\n\n", dwError); 101 90 ConResPrintf(StdOut, pCommand->dwCmdHlpToken); 102 - return TRUE; 103 91 } 104 - return !bDone; 92 + return TRUE; 105 93 } 94 + 95 + pCommand = pCommand->pNext; 106 96 } 107 97 108 - pCommand = pCommand->pNext; 98 + return FALSE; 109 99 } 110 - 111 - HelpGroup(pGroup); 112 - return TRUE; 113 100 } 114 101 115 102 pGroup = pGroup->pNext; ··· 122 109 { 123 110 if (_wcsicmp(argv[0], pSubContext->pszContextName) == 0) 124 111 { 125 - pCurrentContext = pSubContext; 126 - return TRUE; 112 + DPRINT("%S ==> dwCurrentIndex: %lu dwArgCount: %lu\n", argv[dwCurrentIndex], dwCurrentIndex, dwArgCount); 113 + if (dwArgCount == dwCurrentIndex + 1) 114 + { 115 + pCurrentContext = pSubContext; 116 + return TRUE; 117 + } 118 + else 119 + { 120 + return ProcessCommand(pSubContext, 121 + dwArgCount, 122 + argv, 123 + dwCurrentIndex + 1, 124 + dwHelpLevel, 125 + bDone); 126 + } 127 127 } 128 128 129 129 pSubContext = pSubContext->pNext; ··· 136 136 pContext = pContext->pParentContext; 137 137 } 138 138 139 - ConResPrintf(StdErr, IDS_INVALID_COMMAND, argv[0]); 139 + return FALSE; 140 + } 141 + 142 + 143 + BOOL 144 + InterpretCommand( 145 + _In_ LPWSTR *argv, 146 + _In_ DWORD dwArgCount, 147 + _Inout_ PBOOL bDone) 148 + { 149 + /* If no args provided */ 150 + if (dwArgCount == 0) 151 + return TRUE; 140 152 141 - return TRUE; 153 + if (pCurrentContext == NULL) 154 + { 155 + DPRINT("InterpretCmd: invalid context %p\n", pCurrentContext); 156 + return FALSE; 157 + } 158 + 159 + if ((_wcsicmp(argv[dwArgCount - 1], L"?") == 0) || 160 + (_wcsicmp(argv[dwArgCount - 1], L"help") == 0)) 161 + { 162 + return ProcessHelp(pCurrentContext, 163 + dwArgCount, 164 + argv, 165 + 0, 166 + dwArgCount - 1); 167 + } 168 + else 169 + { 170 + return ProcessCommand(pCurrentContext, 171 + dwArgCount, 172 + argv, 173 + 0, 174 + 0, 175 + bDone); 176 + } 142 177 } 143 178 144 179 ··· 153 188 LPWSTR args_vector[MAX_ARGS_COUNT]; 154 189 DWORD dwArgCount = 0; 155 190 BOOL bWhiteSpace = TRUE; 191 + BOOL bDone = FALSE; 156 192 LPWSTR ptr; 157 193 158 194 memset(args_vector, 0, sizeof(args_vector)); ··· 180 216 } 181 217 182 218 /* sends the string to find the command */ 183 - return InterpretCommand(args_vector, dwArgCount); 219 + return InterpretCommand(args_vector, dwArgCount, &bDone) == ERROR_SUCCESS; 184 220 } 185 221 186 222 ··· 191 227 LPWSTR args_vector[MAX_ARGS_COUNT]; 192 228 DWORD dwArgCount = 0; 193 229 BOOL bWhiteSpace = TRUE; 194 - BOOL bRun = TRUE; 230 + BOOL bDone = FALSE; 195 231 LPWSTR ptr; 196 232 197 - while (bRun != FALSE) 233 + for (;;) 198 234 { 199 235 dwArgCount = 0; 200 236 memset(args_vector, 0, sizeof(args_vector)); 201 237 202 238 /* Shown just before the input where the user places commands */ 203 - // ConResPuts(StdOut, IDS_APP_PROMPT); 204 239 ConPuts(StdOut, L"netsh"); 205 240 if (pCurrentContext != pRootContext) 206 241 { ··· 233 268 } 234 269 235 270 /* Send the string to find the command */ 236 - bRun = InterpretCommand(args_vector, dwArgCount); 271 + if (InterpretCommand(args_vector, dwArgCount, &bDone) == FALSE) 272 + { 273 + ConResPrintf(StdErr, IDS_INVALID_COMMAND, input_line); 274 + } 275 + 276 + if (bDone) 277 + break; 237 278 } 238 279 }
+7 -1
base/applications/network/netsh/lang/en-US.rc
··· 19 19 20 20 STRINGTABLE 21 21 BEGIN 22 - IDS_HELP_HEADER "\nThe following commands are available:\n" 22 + IDS_HELP_HEADER "\nThe following commands are available:\n" 23 + IDS_HELP_FOOTER "\nHelp Footer\n\n" 23 24 IDS_SUBCONTEXT_HEADER "\nThe following sub-contexts are available:\n" 25 + 24 26 IDS_HLP_UP "Goes up one context level." 25 27 IDS_HLP_UP_EX "Syntax: ..\n\n Goes up one context level.\n\n" 26 28 IDS_HLP_EXIT "Exits the program." 27 29 IDS_HLP_EXIT_EX "Syntax: exit\n\n Exits the program.\n\n" 28 30 IDS_HLP_HELP "Displays a list of commands." 29 31 IDS_HLP_HELP_EX "Syntax: help\n\n Displays a list of commands.\n\n" 32 + IDS_HLP_POPD "Changes to the context on the stack." 33 + IDS_HLP_POPD_EX "Syntax: popd\n\n Changes to the context on the stack.\n\n" 34 + IDS_HLP_PUSHD "Stores the current context on the stack." 35 + IDS_HLP_PUSHD_EX "Syntax: pushd\n\n Stores the current context on the stack.\n\n" 30 36 31 37 IDS_HLP_ADD_HELPER "Installs a helper DLL." 32 38 IDS_HLP_ADD_HELPER_EX "Syntax: add helper <dll file name>\n\n Installs the specified helper DLL in netsh.\n\n"
+5 -3
base/applications/network/netsh/netsh.c
··· 58 58 LPCWSTR pszFileName = NULL; 59 59 int index; 60 60 int result = EXIT_SUCCESS; 61 + BOOL bDone = FALSE; 61 62 62 - DPRINT("main()\n"); 63 + DPRINT("wmain(%S)\n", GetCommandLineW()); 63 64 64 65 /* Initialize the Console Standard Streams */ 65 66 ConInitStdStreams(); ··· 93 94 } 94 95 95 96 /* Run a command from the command line */ 96 - if (InterpretCommand((LPWSTR*)&argv[index], argc - index) == FALSE) 97 + if (InterpretCommand((LPWSTR*)&argv[index], argc - index, &bDone) != ERROR_SUCCESS) 97 98 result = EXIT_FAILURE; 98 99 goto done; 99 100 } ··· 186 187 187 188 done: 188 189 /* FIXME: Cleanup code goes here */ 190 + CleanupContext(); 189 191 UnloadHelpers(); 190 192 191 193 return result; ··· 247 249 va_list ap; 248 250 249 251 va_start(ap, pwszFormat); 250 - Length = ConPrintf(StdOut, pwszFormat); 252 + Length = ConPrintfV(StdOut, pwszFormat, ap); 251 253 va_end(ap); 252 254 253 255 return Length;
+35 -4
base/applications/network/netsh/precomp.h
··· 100 100 struct _CONTEXT_ENTRY *pNext; 101 101 102 102 struct _CONTEXT_ENTRY *pParentContext; 103 + // PHELPER_ENTRY pHelper; 103 104 104 105 PWSTR pszContextName; 105 106 GUID Guid; ··· 121 122 extern PCONTEXT_ENTRY pRootContext; 122 123 extern PCONTEXT_ENTRY pCurrentContext; 123 124 125 + extern PHELPER_ENTRY pHelperListHead; 124 126 125 127 /* PROTOTYPES *****************************************************************/ 126 128 ··· 129 131 BOOL 130 132 CreateRootContext(VOID); 131 133 134 + VOID 135 + CleanupContext(VOID); 136 + 132 137 133 138 /* help.c */ 139 + 140 + BOOL 141 + ProcessHelp( 142 + _In_ PCONTEXT_ENTRY pContext, 143 + _In_ DWORD dwCurrentIndex, 144 + _In_ LPWSTR *argv, 145 + _In_ DWORD dwArgCount, 146 + _In_ DWORD dwHelpLevel); 147 + 148 + 134 149 DWORD 135 150 WINAPI 136 151 HelpCommand( ··· 142 157 LPCVOID pvData, 143 158 BOOL *pbDone); 144 159 160 + #if 0 145 161 VOID 146 162 HelpGroup( 147 - PCOMMAND_GROUP pGroup); 163 + PCONTEXT_ENTRY pContext, 164 + LPWSTR pszGroupName, 165 + BOOL bRecurse); 166 + 167 + VOID 168 + HelpContext( 169 + PCONTEXT_ENTRY pContext); 148 170 171 + VOID 172 + HelpSubcontexts( 173 + PCONTEXT_ENTRY pContext); 174 + #endif 149 175 150 176 /* helper.c */ 151 177 VOID ··· 154 180 VOID 155 181 UnloadHelpers(VOID); 156 182 183 + PHELPER_ENTRY 184 + FindHelper( 185 + _In_ const GUID *pguidHelper, 186 + _In_ PHELPER_ENTRY pHelper); 157 187 158 188 DWORD 159 189 WINAPI ··· 192 222 /* interpreter.c */ 193 223 BOOL 194 224 InterpretScript( 195 - LPWSTR pszFileName); 225 + _In_ LPWSTR pszFileName); 196 226 197 227 BOOL 198 228 InterpretCommand( 199 - LPWSTR *argv, 200 - DWORD dwArgCount); 229 + _In_ LPWSTR *argv, 230 + _In_ DWORD dwArgCount, 231 + _Inout_ PBOOL bDone); 201 232 202 233 VOID 203 234 InterpretInteractive(VOID);
+6 -1
base/applications/network/netsh/resource.h
··· 16 16 #define IDS_INVALID_SYNTAX 104 17 17 18 18 #define IDS_HELP_HEADER 200 19 - #define IDS_SUBCONTEXT_HEADER 201 19 + #define IDS_HELP_FOOTER 201 20 + #define IDS_SUBCONTEXT_HEADER 202 20 21 21 22 #define IDS_HLP_EXIT 300 22 23 #define IDS_HLP_EXIT_EX 301 ··· 24 25 #define IDS_HLP_HELP_EX 303 25 26 #define IDS_HLP_UP 304 26 27 #define IDS_HLP_UP_EX 305 28 + #define IDS_HLP_POPD 306 29 + #define IDS_HLP_POPD_EX 307 30 + #define IDS_HLP_PUSHD 308 31 + #define IDS_HLP_PUSHD_EX 309 27 32 28 33 #define IDS_HLP_ADD_HELPER 310 29 34 #define IDS_HLP_ADD_HELPER_EX 311