Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

914 lines
19 KiB

  1. #include "precomp.h"
  2. #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
  3. #define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
  4. DWORD
  5. HandleShowAlias(
  6. LPCWSTR pwszMachine,
  7. LPWSTR *ppwcArguments,
  8. DWORD dwCurrentIndex,
  9. DWORD dwArgCount,
  10. DWORD dwFlags,
  11. LPCVOID pvData,
  12. BOOL *pbDone
  13. )
  14. {
  15. return PrintAliasTable();
  16. }
  17. DWORD
  18. HandleShellExit(
  19. LPCWSTR pwszMachine,
  20. LPWSTR *ppwcArguments,
  21. DWORD dwCurrentIndex,
  22. DWORD dwArgCount,
  23. DWORD dwFlags,
  24. LPCVOID pvData,
  25. BOOL *pbDone
  26. )
  27. {
  28. BOOL bTmp;
  29. CallCommit(NETSH_COMMIT_STATE, &bTmp);
  30. if (!bTmp)
  31. {
  32. CallCommit(NETSH_FLUSH, &bTmp);
  33. }
  34. *pbDone = TRUE;
  35. return NO_ERROR;
  36. }
  37. DWORD
  38. HandleShellLoad(
  39. LPCWSTR pwszMachine,
  40. LPWSTR *ppwcArguments,
  41. DWORD dwCurrentIndex,
  42. DWORD dwArgCount,
  43. DWORD dwFlags,
  44. LPCVOID pvData,
  45. BOOL *pbDone
  46. )
  47. {
  48. DWORD dwErr, dwNumArgs;
  49. dwNumArgs = dwArgCount - dwCurrentIndex;
  50. //
  51. // Load Command
  52. //
  53. switch (dwNumArgs)
  54. {
  55. case 1 :
  56. return LoadScriptFile(ppwcArguments[dwCurrentIndex]);
  57. default :
  58. return ERROR_INVALID_SYNTAX;
  59. }
  60. return NO_ERROR;
  61. }
  62. DWORD
  63. HandleShellSave(
  64. LPCWSTR pwszMachine,
  65. LPWSTR *ppwcArguments,
  66. DWORD dwCurrentIndex,
  67. DWORD dwArgCount,
  68. DWORD dwFlags,
  69. LPCVOID pvData,
  70. BOOL *pbDone
  71. )
  72. {
  73. BOOL bTmp;
  74. CallCommit(NETSH_SAVE, &bTmp);
  75. return NO_ERROR;
  76. }
  77. DWORD
  78. HandleShellUncommit(
  79. LPCWSTR pwszMachine,
  80. LPWSTR *ppwcArguments,
  81. DWORD dwCurrentIndex,
  82. DWORD dwArgCount,
  83. DWORD dwFlags,
  84. LPCVOID pvData,
  85. BOOL *pbDone
  86. )
  87. {
  88. BOOL bTmp;
  89. CallCommit(NETSH_UNCOMMIT, &bTmp);
  90. return NO_ERROR;
  91. }
  92. DWORD
  93. HandleSetMachine(
  94. LPCWSTR pwszMachine,
  95. LPWSTR *ppwcArguments,
  96. DWORD dwCurrentIndex,
  97. DWORD dwArgCount,
  98. DWORD dwFlags,
  99. LPCVOID pvData,
  100. BOOL *pbDone
  101. )
  102. {
  103. TAG_TYPE pttTags[] = {{TOKEN_NAME, FALSE, FALSE }};
  104. DWORD dwNumTags = sizeof(pttTags)/sizeof(TAG_TYPE);
  105. PDWORD pdwTagType;
  106. DWORD dwErr, dwNumArg, dwMode, i;
  107. BOOL bTmp;
  108. dwNumArg = dwArgCount - dwCurrentIndex;
  109. if (dwNumArg < 1)
  110. {
  111. return SetMachine(NULL);
  112. }
  113. if (dwNumArg < 1)
  114. {
  115. return SetMachine(NULL);
  116. }
  117. if ((dwNumArg != 1) || IsHelpToken(ppwcArguments[dwCurrentIndex]))
  118. {
  119. return ERROR_SHOW_USAGE;
  120. }
  121. pdwTagType = MALLOC(dwNumArg * sizeof(DWORD));
  122. if (pdwTagType is NULL)
  123. {
  124. return ERROR_NOT_ENOUGH_MEMORY;
  125. }
  126. dwErr = MatchTagsInCmdLine(g_hModule,
  127. ppwcArguments,
  128. dwCurrentIndex,
  129. dwArgCount,
  130. pttTags,
  131. dwNumTags,
  132. pdwTagType);
  133. if (dwErr isnot NO_ERROR)
  134. {
  135. FREE(pdwTagType);
  136. if (dwErr is ERROR_INVALID_OPTION_TAG)
  137. {
  138. return ERROR_INVALID_SYNTAX;
  139. }
  140. return dwErr;
  141. }
  142. for ( i = 0; i < dwNumArg; i++)
  143. {
  144. switch (pdwTagType[i])
  145. {
  146. case 0: // NAME
  147. {
  148. SetMachine(ppwcArguments[i + dwCurrentIndex]);
  149. break;
  150. }
  151. default :
  152. {
  153. i = dwNumArg;
  154. dwErr = ERROR_INVALID_SYNTAX;
  155. break;
  156. }
  157. }
  158. }
  159. FREE(pdwTagType);
  160. switch(dwErr)
  161. {
  162. case NO_ERROR :
  163. break;
  164. case ERROR_TAG_ALREADY_PRESENT:
  165. PrintMessageFromModule(g_hModule, ERROR_TAG_ALREADY_PRESENT);
  166. return dwErr;
  167. default:
  168. return dwErr;
  169. }
  170. return dwErr;
  171. }
  172. extern HANDLE g_hLogFile;
  173. DWORD
  174. HandleSetFile(
  175. LPCWSTR pwszMachine,
  176. LPWSTR *ppwcArguments,
  177. DWORD dwCurrentIndex,
  178. DWORD dwArgCount,
  179. DWORD dwFlags,
  180. LPCVOID pvData,
  181. BOOL *pbDone
  182. )
  183. {
  184. TAG_TYPE pttTags[] = {
  185. {TOKEN_MODE, TRUE, FALSE },
  186. {TOKEN_NAME, FALSE, FALSE },
  187. };
  188. DWORD dwNumTags = sizeof(pttTags)/sizeof(TAG_TYPE);
  189. PDWORD pdwTagType;
  190. DWORD dwErr, dwNumArg, dwMode, i;
  191. BOOL bTmp;
  192. LPCWSTR wszFileName = NULL;
  193. HANDLE hLogFile = NULL;
  194. dwNumArg = dwArgCount - dwCurrentIndex;
  195. if ((!dwNumArg) || (dwNumArg > 2) || IsHelpToken(ppwcArguments[dwCurrentIndex]))
  196. {
  197. return ERROR_SHOW_USAGE;
  198. }
  199. pdwTagType = MALLOC(dwNumArg * sizeof(DWORD));
  200. if (pdwTagType is NULL)
  201. {
  202. return ERROR_NOT_ENOUGH_MEMORY;
  203. }
  204. dwErr = MatchTagsInCmdLine(g_hModule,
  205. ppwcArguments,
  206. dwCurrentIndex,
  207. dwArgCount,
  208. pttTags,
  209. dwNumTags,
  210. pdwTagType);
  211. if (dwErr isnot NO_ERROR)
  212. {
  213. FREE(pdwTagType);
  214. if (dwErr is ERROR_INVALID_OPTION_TAG)
  215. {
  216. return ERROR_INVALID_SYNTAX;
  217. }
  218. return dwErr;
  219. }
  220. for ( i = 0; i < dwNumArg; i++)
  221. {
  222. switch (pdwTagType[i])
  223. {
  224. case 0: // Mode
  225. {
  226. TOKEN_VALUE rgEnums[] = {{TOKEN_VALUE_OPEN, 0},
  227. {TOKEN_VALUE_APPEND, 1},
  228. {TOKEN_VALUE_CLOSE, 2}};
  229. dwErr = MatchEnumTag(g_hModule,
  230. ppwcArguments[i + dwCurrentIndex],
  231. sizeof(rgEnums)/sizeof(TOKEN_VALUE),
  232. rgEnums,
  233. &dwMode);
  234. if (dwErr != NO_ERROR)
  235. {
  236. PrintMessageFromModule( g_hModule,
  237. ERROR_INVALID_OPTION_VALUE,
  238. pttTags[pdwTagType[i]].pwszTag,
  239. ppwcArguments[i + dwCurrentIndex]);
  240. i = dwNumArg;
  241. dwErr = ERROR_SHOW_USAGE;
  242. break;
  243. }
  244. break;
  245. }
  246. case 1: // Name
  247. {
  248. wszFileName = ppwcArguments[i + dwCurrentIndex];
  249. break;
  250. }
  251. default :
  252. {
  253. i = dwNumArg;
  254. dwErr = ERROR_INVALID_SYNTAX;
  255. break;
  256. }
  257. }
  258. }
  259. FREE(pdwTagType);
  260. switch(dwErr)
  261. {
  262. case NO_ERROR :
  263. break;
  264. case ERROR_TAG_ALREADY_PRESENT:
  265. PrintMessageFromModule(g_hModule, ERROR_TAG_ALREADY_PRESENT);
  266. return dwErr;
  267. default:
  268. return dwErr;
  269. }
  270. switch(dwMode)
  271. {
  272. case 0: // open
  273. if (!wszFileName)
  274. return ERROR_SHOW_USAGE;
  275. if (g_hLogFile)
  276. {
  277. CloseHandle(g_hLogFile);
  278. g_hLogFile = NULL;
  279. }
  280. hLogFile = CreateFile(wszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  281. if (INVALID_HANDLE_VALUE == hLogFile)
  282. return GetLastError();
  283. g_hLogFile = hLogFile;
  284. break;
  285. case 1: // append
  286. if (!wszFileName)
  287. return ERROR_SHOW_USAGE;
  288. if (g_hLogFile)
  289. {
  290. CloseHandle(g_hLogFile);
  291. g_hLogFile = NULL;
  292. }
  293. hLogFile = CreateFile(wszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  294. if (INVALID_HANDLE_VALUE == hLogFile)
  295. return GetLastError();
  296. if (INVALID_SET_FILE_POINTER == SetFilePointer(hLogFile, 0, NULL, FILE_END))
  297. return GetLastError();
  298. g_hLogFile = hLogFile;
  299. break;
  300. case 2: // close
  301. if (wszFileName)
  302. return ERROR_SHOW_USAGE;
  303. if (g_hLogFile)
  304. {
  305. CloseHandle(g_hLogFile);
  306. g_hLogFile = NULL;
  307. }
  308. break;
  309. }
  310. return dwErr;
  311. }
  312. DWORD
  313. HandleSetMode(
  314. LPCWSTR pwszMachine,
  315. LPWSTR *ppwcArguments,
  316. DWORD dwCurrentIndex,
  317. DWORD dwArgCount,
  318. DWORD dwFlags,
  319. LPCVOID pvData,
  320. BOOL *pbDone
  321. )
  322. {
  323. TAG_TYPE pttTags[] = {{TOKEN_MODE, TRUE, FALSE }};
  324. DWORD dwNumTags = sizeof(pttTags)/sizeof(TAG_TYPE);
  325. PDWORD pdwTagType;
  326. DWORD dwErr, dwNumArg, dwMode, i;
  327. BOOL bTmp;
  328. dwNumArg = dwArgCount - dwCurrentIndex;
  329. if ((dwNumArg != 1) || IsHelpToken(ppwcArguments[dwCurrentIndex]))
  330. {
  331. return ERROR_SHOW_USAGE;
  332. }
  333. pdwTagType = MALLOC(dwNumArg * sizeof(DWORD));
  334. if (pdwTagType is NULL)
  335. {
  336. return ERROR_NOT_ENOUGH_MEMORY;
  337. }
  338. dwErr = MatchTagsInCmdLine(g_hModule,
  339. ppwcArguments,
  340. dwCurrentIndex,
  341. dwArgCount,
  342. pttTags,
  343. dwNumTags,
  344. pdwTagType);
  345. if (dwErr isnot NO_ERROR)
  346. {
  347. FREE(pdwTagType);
  348. if (dwErr is ERROR_INVALID_OPTION_TAG)
  349. {
  350. return ERROR_INVALID_SYNTAX;
  351. }
  352. return dwErr;
  353. }
  354. for ( i = 0; i < dwNumArg; i++)
  355. {
  356. switch (pdwTagType[i])
  357. {
  358. case 0: // LOGLEVEL
  359. {
  360. TOKEN_VALUE rgEnums[] = {{TOKEN_VALUE_ONLINE, TRUE},
  361. {TOKEN_VALUE_OFFLINE, FALSE}};
  362. dwErr = MatchEnumTag(g_hModule,
  363. ppwcArguments[i + dwCurrentIndex],
  364. sizeof(rgEnums)/sizeof(TOKEN_VALUE),
  365. rgEnums,
  366. &dwMode);
  367. if (dwErr != NO_ERROR)
  368. {
  369. PrintMessageFromModule( g_hModule,
  370. ERROR_INVALID_OPTION_VALUE,
  371. pttTags[pdwTagType[i]].pwszTag,
  372. ppwcArguments[i + dwCurrentIndex]);
  373. i = dwNumArg;
  374. dwErr = ERROR_INVALID_PARAMETER;
  375. break;
  376. }
  377. break;
  378. }
  379. default :
  380. {
  381. i = dwNumArg;
  382. dwErr = ERROR_INVALID_SYNTAX;
  383. break;
  384. }
  385. }
  386. }
  387. FREE(pdwTagType);
  388. switch(dwErr)
  389. {
  390. case NO_ERROR :
  391. break;
  392. case ERROR_TAG_ALREADY_PRESENT:
  393. PrintMessageFromModule(g_hModule, ERROR_TAG_ALREADY_PRESENT);
  394. return dwErr;
  395. default:
  396. return dwErr;
  397. }
  398. switch(dwMode) {
  399. case TRUE: // set to online
  400. dwErr = CallCommit(NETSH_COMMIT, &bTmp);
  401. break;
  402. case FALSE: // set to offline
  403. dwErr = CallCommit(NETSH_UNCOMMIT, &bTmp);
  404. break;
  405. }
  406. return dwErr;
  407. }
  408. DWORD
  409. HandleShellCommit(
  410. LPCWSTR pwszMachine,
  411. LPWSTR *ppwcArguments,
  412. DWORD dwCurrentIndex,
  413. DWORD dwArgCount,
  414. DWORD dwFlags,
  415. LPCVOID pvData,
  416. BOOL *pbDone
  417. )
  418. {
  419. BOOL bTmp;
  420. CallCommit(NETSH_COMMIT, &bTmp);
  421. return NO_ERROR;
  422. }
  423. DWORD
  424. HandleShellFlush(
  425. LPCWSTR pwszMachine,
  426. LPWSTR *ppwcArguments,
  427. DWORD dwCurrentIndex,
  428. DWORD dwArgCount,
  429. DWORD dwFlags,
  430. LPCVOID pvData,
  431. BOOL *pbDone
  432. )
  433. {
  434. BOOL bTmp;
  435. CallCommit(NETSH_FLUSH, &bTmp);
  436. return NO_ERROR;
  437. }
  438. DWORD
  439. HandleShellUnalias(
  440. LPCWSTR pwszMachine,
  441. LPWSTR *ppwcArguments,
  442. DWORD dwCurrentIndex,
  443. DWORD dwArgCount,
  444. DWORD dwFlags,
  445. LPCVOID pvData,
  446. BOOL *pbDone
  447. )
  448. {
  449. DWORD dwNumArgs;
  450. DWORD dwRes = NO_ERROR;
  451. dwNumArgs = dwArgCount - dwCurrentIndex;
  452. //
  453. // Unalias Command
  454. //
  455. switch (dwNumArgs)
  456. {
  457. case 1 :
  458. dwRes = ATDeleteAlias(ppwcArguments[dwCurrentIndex]);
  459. if (dwRes is NO_ERROR)
  460. {
  461. dwRes = ERROR_OKAY;
  462. break;
  463. }
  464. PrintMessageFromModule(g_hModule, MSG_ALIAS_NOT_FOUND, ppwcArguments[dwCurrentIndex]);
  465. break;
  466. default :
  467. dwRes = ERROR_INVALID_SYNTAX;
  468. break;
  469. }
  470. return dwRes;
  471. }
  472. DWORD
  473. HandleShellAlias(
  474. LPCWSTR pwszMachine,
  475. LPWSTR *ppwcArguments,
  476. DWORD dwCurrentIndex,
  477. DWORD dwArgCount,
  478. DWORD dwFlags,
  479. LPCVOID pvData,
  480. BOOL *pbDone
  481. )
  482. {
  483. LPWSTR pwszAliasString;
  484. WCHAR wszAliasString[MAX_CMD_LEN];
  485. DWORD i, dwNumArgs, dwRes = NO_ERROR;
  486. dwNumArgs = dwArgCount - dwCurrentIndex;
  487. //
  488. // An alias command
  489. //
  490. switch (dwNumArgs)
  491. {
  492. case 0 :
  493. //
  494. // Display all aliases in use
  495. //
  496. PrintAliasTable();
  497. break;
  498. case 1 :
  499. //
  500. // Display string for given alias
  501. //
  502. ATLookupAliasTable(ppwcArguments[dwCurrentIndex], &pwszAliasString);
  503. if (pwszAliasString)
  504. {
  505. PrintMessage(L"%1!s!\n",pwszAliasString);
  506. }
  507. else
  508. {
  509. PrintMessageFromModule( g_hModule,
  510. MSG_ALIAS_NOT_FOUND,
  511. ppwcArguments[dwCurrentIndex] );
  512. }
  513. break;
  514. default :
  515. //
  516. // Set alias
  517. //
  518. if (IsLocalCommand(ppwcArguments[dwCurrentIndex], 0))
  519. {
  520. PrintMessageFromModule(g_hModule, EMSG_ALIASING_KEYWORD);
  521. break;
  522. }
  523. wszAliasString[0] = L'\0';
  524. for ( i = dwCurrentIndex+1 ; i < dwArgCount ; i++)
  525. {
  526. wcscat(wszAliasString, ppwcArguments[i]);
  527. wcscat(wszAliasString,L" ");
  528. }
  529. wszAliasString[wcslen(wszAliasString)-1] = L'\0';
  530. dwRes = ATAddAlias(ppwcArguments[dwCurrentIndex], wszAliasString);
  531. if (dwRes is NO_ERROR)
  532. {
  533. dwRes = ERROR_OKAY;
  534. break;
  535. }
  536. //
  537. // Error in set alias
  538. //
  539. PrintMessageFromModule(g_hModule, MSG_CMD_FAILED);
  540. break;
  541. }
  542. return dwRes;
  543. }
  544. DWORD
  545. HandleUbiqDump(
  546. LPCWSTR pwszMachine,
  547. LPWSTR *ppwcArguments,
  548. DWORD dwCurrentIndex,
  549. DWORD dwArgCount,
  550. DWORD dwFlags,
  551. LPCVOID pvData,
  552. BOOL *pbDone
  553. )
  554. {
  555. DWORD dwErr = NO_ERROR;
  556. PNS_HELPER_TABLE_ENTRY pHelper;
  557. //
  558. // Dump Command
  559. //
  560. do {
  561. dwErr = DumpContext( g_CurrentContext,
  562. ppwcArguments,
  563. dwArgCount,
  564. pvData);
  565. } while (FALSE);
  566. return dwErr;
  567. }
  568. DWORD
  569. HandleUbiqHelp(
  570. LPCWSTR pwszMachine,
  571. LPWSTR *ppwcArguments,
  572. DWORD dwCurrentIndex,
  573. DWORD dwArgCount,
  574. DWORD dwFlags,
  575. LPCVOID pvData,
  576. BOOL *pbDone
  577. )
  578. {
  579. DWORD dwDisplayFlags = CMD_FLAG_PRIVATE;
  580. if (g_bInteractive)
  581. {
  582. dwDisplayFlags |= CMD_FLAG_INTERACTIVE;
  583. }
  584. return DisplayContextHelp( g_CurrentContext,
  585. dwDisplayFlags,
  586. dwFlags,
  587. dwArgCount-2+1,
  588. NULL );
  589. }
  590. DWORD
  591. HandleShowMode(
  592. LPCWSTR pwszMachine,
  593. LPWSTR *ppwcArguments,
  594. DWORD dwCurrentIndex,
  595. DWORD dwArgCount,
  596. DWORD dwFlags,
  597. LPCVOID pvData,
  598. BOOL *pbDone
  599. )
  600. {
  601. BOOL bTmp;
  602. CallCommit(NETSH_COMMIT_STATE, &bTmp);
  603. if (bTmp)
  604. {
  605. PrintMessage(CMD_COMMIT);
  606. }
  607. else
  608. {
  609. PrintMessage(CMD_UNCOMMIT);
  610. }
  611. PrintMessage(MSG_NEWLINE);
  612. return NO_ERROR;
  613. }
  614. DWORD
  615. HandleShellUplevel(
  616. LPCWSTR pwszMachine,
  617. LPWSTR *ppwcArguments,
  618. DWORD dwCurrentIndex,
  619. DWORD dwArgCount,
  620. DWORD dwFlags,
  621. LPCVOID pvData,
  622. BOOL *pbDone
  623. )
  624. {
  625. DWORD dwRes;
  626. PLIST_ENTRY pleHead, ple;
  627. PARG_ENTRY pae;
  628. // Convert current context to list
  629. dwRes = ConvertBufferToArgList(&pleHead, g_pwszContext);
  630. if (dwRes isnot NO_ERROR)
  631. {
  632. return dwRes;
  633. }
  634. // Remove last element if more than two
  635. if (!IsListEmpty(pleHead) and (pleHead->Flink->Flink isnot pleHead))
  636. {
  637. // Delete the last element of the context list
  638. // (Try inheriting a command from one level up)
  639. ple = pleHead->Blink;
  640. pae = CONTAINING_RECORD(ple, ARG_ENTRY, le);
  641. if (pae->pwszArg)
  642. FREE(pae->pwszArg);
  643. RemoveEntryList(ple);
  644. FREE(pae);
  645. }
  646. // Convert back to buffer
  647. dwRes = ConvertArgListToBuffer(pleHead, g_pwszContext);
  648. FREE_ARG_LIST(pleHead);
  649. return NO_ERROR;
  650. }
  651. typedef struct {
  652. LIST_ENTRY le;
  653. WCHAR wszBuffer[MAX_CMD_LEN];
  654. } CONTEXT_BUFFER, *PCONTEXT_BUFFER;
  655. LIST_ENTRY leContextStackHead;
  656. BOOL bContextStackInit = FALSE;
  657. VOID
  658. InitContextStack()
  659. {
  660. if (bContextStackInit)
  661. return;
  662. bContextStackInit = TRUE;
  663. InitializeListHead(&leContextStackHead);
  664. }
  665. DWORD
  666. HandleShellPushd(
  667. LPCWSTR pwszMachine,
  668. LPWSTR *ppwcArguments,
  669. DWORD dwCurrentIndex,
  670. DWORD dwArgCount,
  671. DWORD dwFlags,
  672. LPCVOID pvData,
  673. BOOL *pbDone
  674. )
  675. {
  676. PCONTEXT_BUFFER pcb;
  677. DWORD dwErr = NO_ERROR;
  678. InitContextStack();
  679. // Malloc another buffer
  680. pcb = MALLOC(sizeof(CONTEXT_BUFFER));
  681. if (!pcb)
  682. {
  683. return ERROR_NOT_ENOUGH_MEMORY;
  684. }
  685. wcscpy(pcb->wszBuffer, g_pwszContext);
  686. // Push buffer on stack
  687. InsertHeadList(&leContextStackHead, &pcb->le);
  688. if (dwArgCount > dwCurrentIndex)
  689. {
  690. LPWSTR pwszBuffer;
  691. // execute the rest of the arguments as a new command
  692. // Copy arg array to a buffer
  693. ConvertArgArrayToBuffer( dwArgCount - dwCurrentIndex,
  694. ppwcArguments + dwCurrentIndex,
  695. &pwszBuffer );
  696. if (!pwszBuffer)
  697. {
  698. return ERROR_NOT_ENOUGH_MEMORY;
  699. }
  700. dwErr = ProcessCommand(pwszBuffer, pbDone);
  701. if (dwErr)
  702. {
  703. dwErr = ERROR_SUPPRESS_OUTPUT;
  704. }
  705. FREE(pwszBuffer);
  706. // XXX If the command failed, we probably want to set the
  707. // XXX current context to some NULL context so all commands fail
  708. }
  709. return dwErr;
  710. }
  711. DWORD
  712. HandleShellPopd(
  713. LPCWSTR pwszMachine,
  714. LPWSTR *ppwcArguments,
  715. DWORD dwCurrentIndex,
  716. DWORD dwArgCount,
  717. DWORD dwFlags,
  718. LPCVOID pvData,
  719. BOOL *pbDone
  720. )
  721. {
  722. PLIST_ENTRY ple;
  723. PCONTEXT_BUFFER pcb;
  724. InitContextStack();
  725. if (IsListEmpty(&leContextStackHead))
  726. return NO_ERROR;
  727. // Pop buffer off stack
  728. ple = leContextStackHead.Flink;
  729. pcb = CONTAINING_RECORD(ple, CONTEXT_BUFFER, le);
  730. RemoveEntryList(ple);
  731. // Copy buffer to current context
  732. wcscpy( g_pwszContext, pcb->wszBuffer );
  733. // Free buffer
  734. FREE(pcb);
  735. return NO_ERROR;
  736. }