Leaked source code of windows server 2003
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.

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