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.

2313 lines
56 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. routing\netsh\shell\utils.c
  5. Abstract:
  6. Utilities.
  7. Revision History:
  8. 6/12/96 V Raman
  9. --*/
  10. #include "precomp.h"
  11. #include <wincon.h>
  12. #include <winbase.h>
  13. #define STOP_EVENT L"NetshStopRefreshEvent"
  14. extern HANDLE g_hModule;
  15. BOOL
  16. WINAPI
  17. MatchCmdLine(
  18. IN LPWSTR *ppwcArguments,
  19. IN DWORD dwArgCount,
  20. IN LPCWSTR pwszCmdToken,
  21. OUT PDWORD pdwNumMatched
  22. )
  23. {
  24. LPCWSTR pwcToken;
  25. DWORD dwCount;
  26. WCHAR wcszBuffer[256];
  27. //
  28. // Compare the two strings
  29. //
  30. dwCount = 0;
  31. if (!ppwcArguments || !pwszCmdToken || !pdwNumMatched)
  32. {
  33. return FALSE;
  34. }
  35. *pdwNumMatched = 0; // init OUT parameter
  36. if ( (wcslen(pwszCmdToken) + 1) > (sizeof(wcszBuffer)/sizeof(wcszBuffer[0])) )
  37. {
  38. // incoming command string is too large for processing
  39. return FALSE;
  40. }
  41. // copy into a buffer which wcstok can munge
  42. wcscpy(wcszBuffer, pwszCmdToken);
  43. if((pwcToken = wcstok(wcszBuffer,
  44. NETSH_CMD_DELIMITER)) != NULL)
  45. {
  46. do
  47. {
  48. if (dwCount < dwArgCount &&
  49. (_wcsnicmp(ppwcArguments[dwCount],
  50. pwcToken,
  51. wcslen(ppwcArguments[dwCount])) == 0))
  52. {
  53. dwCount++;
  54. }
  55. else
  56. {
  57. return FALSE;
  58. }
  59. } while((pwcToken = wcstok((LPWSTR) NULL, NETSH_CMD_DELIMITER )) != NULL);
  60. }
  61. *pdwNumMatched = dwCount;
  62. return TRUE;
  63. }
  64. #if 0
  65. BOOL
  66. WINAPI
  67. MatchCmdTokenId(
  68. IN HANDLE hModule,
  69. IN LPCWSTR *ppwcArguments,
  70. IN DWORD dwArgCount,
  71. IN DWORD dwCmdId,
  72. OUT PDWORD pdwNumMatched
  73. )
  74. /*++
  75. Routine Description:
  76. Tries to match a command in the given command line.
  77. The function takes the id of the command of the command message.
  78. A command message consists of command words separated by white space.
  79. The function tokenises this messages into separate words and then
  80. tries to match the first N arguments against the N separate tokens that
  81. constitute the command.
  82. e.g if the command is "add if neighbour" - the function will generate
  83. 3 tokens "add" "if" and "neighbour". It will then try and match the
  84. all these to the given arg array.
  85. Arguments:
  86. ppwcArguments - Argument array
  87. dwArgCount - Number of arguments
  88. dwTokenId - Token Id of command
  89. pdwNumMatched - Number of arguments matched in the array
  90. Return Value:
  91. TRUE if matched else FALSE
  92. --*/
  93. {
  94. WCHAR pwszTemp[NETSH_MAX_CMD_TOKEN_LENGTH];
  95. LPCWSTR pwcToken;
  96. DWORD dwCount;
  97. if(!LoadStringW(hModule,
  98. dwCmdId,
  99. pwszTemp,
  100. NETSH_MAX_CMD_TOKEN_LENGTH) )
  101. {
  102. return FALSE;
  103. }
  104. //
  105. // Compare the two strings
  106. //
  107. dwCount = 0;
  108. if((pwcToken = wcstok(pwszTemp,
  109. NETSH_CMD_DELIMITER)) != NULL)
  110. {
  111. do
  112. {
  113. if (dwCount < dwArgCount &&
  114. (_wcsnicmp(ppwcArguments[dwCount],
  115. pwcToken,
  116. wcslen(ppwcArguments[dwCount])) == 0))
  117. {
  118. dwCount++;
  119. }
  120. else
  121. {
  122. *pdwNumMatched = 0;
  123. return FALSE;
  124. }
  125. } while((pwcToken = wcstok((LPCWSTR) NULL, NETSH_CMD_DELIMITER )) != NULL);
  126. }
  127. *pdwNumMatched = dwCount;
  128. return TRUE;
  129. }
  130. #endif
  131. DWORD
  132. WINAPI
  133. MatchEnumTag(
  134. IN HANDLE hModule,
  135. IN LPCWSTR pwcArg,
  136. IN DWORD dwNumArg,
  137. IN CONST TOKEN_VALUE *pEnumTable,
  138. OUT PDWORD pdwValue
  139. )
  140. /*++
  141. Routine Description:
  142. Used for options that take a specific set of values. Matches argument
  143. with the set of values specified and returns corresponding value.
  144. Arguments:
  145. pwcArg - Argument
  146. dwNumArg - Number of possible values.
  147. Return Value:
  148. NO_ERROR
  149. ERROR_NOT_FOUND
  150. --*/
  151. {
  152. DWORD i;
  153. if ( (!pdwValue) || (!pEnumTable) )
  154. {
  155. return ERROR_INVALID_PARAMETER;
  156. }
  157. for (i = 0; i < dwNumArg; i++)
  158. {
  159. if (MatchToken(pwcArg,
  160. pEnumTable[i].pwszToken))
  161. {
  162. *pdwValue = pEnumTable[i].dwValue;
  163. return NO_ERROR;
  164. }
  165. }
  166. return ERROR_NOT_FOUND;
  167. }
  168. DWORD
  169. MatchTagsInCmdLine(
  170. IN HANDLE hModule,
  171. IN OUT LPWSTR *ppwcArguments,
  172. IN DWORD dwCurrentIndex,
  173. IN DWORD dwArgCount,
  174. IN OUT PTAG_TYPE pttTagToken,
  175. IN DWORD dwNumTags,
  176. OUT PDWORD pdwOut
  177. )
  178. /*++
  179. Routine Description:
  180. Identifies each argument based on its tag.
  181. It also removes tag= from each argument.
  182. It also sets the bPresent flag in the tags present.
  183. Arguments:
  184. ppwcArguments - The argument array. Each argument has tag=value form
  185. dwCurrentIndex - ppwcArguments[dwCurrentIndex] is first arg.
  186. dwArgCount - ppwcArguments[dwArgCount - 1] is last arg.
  187. pttTagToken - Array of tag token ids that are allowed in the args
  188. dwNumTags - Size of pttTagToken
  189. pdwOut - Array identifying the type of each argument, where
  190. pdwOut[0] is for ppwcArguments[dwCurrentIndex]
  191. Return Value:
  192. NO_ERROR, ERROR_INVALID_PARAMETER, ERROR_INVALID_OPTION_TAG
  193. --*/
  194. {
  195. DWORD i,j,len;
  196. LPCWSTR pwcTag;
  197. LPWSTR pwcTagVal, pwszArg;
  198. BOOL bFound = FALSE;
  199. //
  200. // This function assumes that every argument has a tag
  201. // It goes ahead and removes the tag.
  202. //
  203. for (i = dwCurrentIndex; i < dwArgCount; i++)
  204. {
  205. if (!wcspbrk(ppwcArguments[i], NETSH_ARG_DELIMITER))
  206. {
  207. pdwOut[i - dwCurrentIndex] = (DWORD) -2;
  208. continue;
  209. }
  210. len = wcslen(ppwcArguments[i]);
  211. if (len is 0)
  212. {
  213. //
  214. // something wrong with arg
  215. //
  216. pdwOut[i - dwCurrentIndex] = (DWORD) -1;
  217. continue;
  218. }
  219. pwszArg = HeapAlloc(GetProcessHeap(),0,(len + 1) * sizeof(WCHAR));
  220. if (pwszArg is NULL)
  221. {
  222. PrintMessageFromModule(g_hModule, MSG_NOT_ENOUGH_MEMORY);
  223. return ERROR_NOT_ENOUGH_MEMORY;
  224. }
  225. wcscpy(pwszArg, ppwcArguments[i]);
  226. pwcTag = wcstok(pwszArg, NETSH_ARG_DELIMITER);
  227. //
  228. // Got the first part
  229. // Now if next call returns NULL then there was no tag
  230. //
  231. pwcTagVal = wcstok((LPWSTR)NULL, NETSH_ARG_DELIMITER);
  232. if (pwcTagVal is NULL)
  233. {
  234. PrintMessageFromModule(g_hModule, ERROR_NO_TAG, ppwcArguments[i]);
  235. HeapFree(GetProcessHeap(),0,pwszArg);
  236. return ERROR_INVALID_PARAMETER;
  237. }
  238. //
  239. // Got the tag. Now try to match it
  240. //
  241. bFound = FALSE;
  242. pdwOut[i - dwCurrentIndex] = (DWORD) -1;
  243. for ( j = 0; j < dwNumTags; j++)
  244. {
  245. if (MatchToken(pwcTag, pttTagToken[j].pwszTag))
  246. {
  247. //
  248. // Tag matched
  249. //
  250. if (pttTagToken[j].bPresent
  251. && !(pttTagToken[j].dwRequired & NS_REQ_ALLOW_MULTIPLE))
  252. {
  253. HeapFree(GetProcessHeap(),0,pwszArg);
  254. PrintMessageFromModule(g_hModule, ERROR_TAG_ALREADY_PRESENT, pwcTag);
  255. return ERROR_TAG_ALREADY_PRESENT;
  256. }
  257. bFound = TRUE;
  258. pdwOut[i - dwCurrentIndex] = j;
  259. pttTagToken[j].bPresent = TRUE;
  260. break;
  261. }
  262. }
  263. if (bFound)
  264. {
  265. //
  266. // Remove tag from the argument
  267. //
  268. wcscpy(ppwcArguments[i], pwcTagVal);
  269. }
  270. else
  271. {
  272. PrintMessageFromModule(g_hModule, ERROR_INVALID_OPTION_TAG, pwcTag);
  273. HeapFree(GetProcessHeap(),0,pwszArg);
  274. return ERROR_INVALID_OPTION_TAG;
  275. }
  276. HeapFree(GetProcessHeap(),0,pwszArg);
  277. }
  278. // Now tag all untagged arguments
  279. for (i = dwCurrentIndex; i < dwArgCount; i++)
  280. {
  281. if ( pdwOut[i - dwCurrentIndex] != -2)
  282. {
  283. continue;
  284. }
  285. bFound = FALSE;
  286. for ( j = 0; j < dwNumTags; j++)
  287. {
  288. if (!pttTagToken[j].bPresent)
  289. {
  290. bFound = TRUE;
  291. pdwOut[i - dwCurrentIndex] = j;
  292. pttTagToken[j].bPresent = TRUE;
  293. break;
  294. }
  295. }
  296. if (!bFound)
  297. {
  298. pdwOut[i - dwCurrentIndex] = (DWORD) -1;
  299. }
  300. }
  301. return NO_ERROR;
  302. }
  303. BOOL
  304. WINAPI
  305. MatchToken(
  306. IN LPCWSTR pwszUserToken,
  307. IN LPCWSTR pwszCmdToken
  308. )
  309. {
  310. if ( (!pwszUserToken) || (!pwszCmdToken) )
  311. {
  312. return ERROR_INVALID_PARAMETER;
  313. }
  314. return !_wcsnicmp(pwszUserToken,
  315. pwszCmdToken,
  316. wcslen(pwszUserToken));
  317. }
  318. BOOL
  319. WINAPI
  320. MatchTokenId( // changed this name since I don't think anything will use it
  321. IN HANDLE hModule,
  322. IN LPCWSTR pwszToken,
  323. IN DWORD dwTokenId
  324. )
  325. /*++
  326. Routine Description:
  327. Sees if the given string and the string corresponding to dwTokenId
  328. are the same.
  329. Arguments:
  330. pwszToken - Token string
  331. dwTokenId - Token Id
  332. Return Value:
  333. TRUE is matched else FALSE
  334. --*/
  335. {
  336. WCHAR pwszTemp[NETSH_MAX_TOKEN_LENGTH];
  337. if(!LoadStringW(hModule,
  338. dwTokenId,
  339. pwszTemp,
  340. NETSH_MAX_TOKEN_LENGTH))
  341. {
  342. return FALSE;
  343. }
  344. return MatchToken(pwszToken, pwszTemp);
  345. }
  346. extern HANDLE g_hLogFile;
  347. //+--------------------------------------------------------------------------
  348. //
  349. // Function: GetPasswdStr
  350. //
  351. // Synopsis: Reads a password string from stdin without echoing the keystrokes
  352. //
  353. // Arguments: [buf - OUT] : buffer to put string in
  354. // [buflen - IN] : size of the buffer
  355. // [&len - OUT] : length of the string placed into the buffer
  356. //
  357. // Returns: DWORD : 0 or ERROR_INSUFFICIENT_BUFFER if user typed too much.
  358. // Buffer contents are only valid on 0 return.
  359. //
  360. // History: 07-Dec-2001 deonb Copied from dscmd parseutil.cpp sources
  361. // 07-Sep-2000 JeffJon Created
  362. //
  363. //---------------------------------------------------------------------------
  364. #define CR 0xD
  365. #define BACKSPACE 0x8
  366. DWORD GetPasswdStr(IN LPTSTR buf,
  367. IN DWORD buflen,
  368. IN PDWORD len)
  369. {
  370. TCHAR ch;
  371. TCHAR *bufPtr = buf;
  372. DWORD c;
  373. int err;
  374. DWORD mode;
  375. buflen -= 1; /* make space for null terminator */
  376. *len = 0; /* GP fault probe (a la API's) */
  377. GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode);
  378. SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE),
  379. (~(ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT)) & mode);
  380. while (TRUE)
  381. {
  382. err = ReadConsole(GetStdHandle(STD_INPUT_HANDLE), &ch, 1, &c, 0);
  383. if (!err || c != 1)
  384. ch = 0xffff;
  385. if ((ch == CR) || (ch == 0xffff)) /* end of the line */
  386. break;
  387. if (ch == BACKSPACE)
  388. { /* back up one or two */
  389. /*
  390. * IF bufPtr == buf then the next two lines are
  391. * a no op.
  392. */
  393. if (bufPtr != buf)
  394. {
  395. bufPtr--;
  396. (*len)--;
  397. }
  398. }
  399. else
  400. {
  401. *bufPtr = ch;
  402. if (*len < buflen)
  403. bufPtr++ ; /* don't overflow buf */
  404. (*len)++; /* always increment len */
  405. }
  406. }
  407. SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
  408. *bufPtr = TEXT('\0'); /* null terminate the string */
  409. putwchar(TEXT('\n'));
  410. return ((*len <= buflen) ? 0 : ERROR_INSUFFICIENT_BUFFER);
  411. }
  412. LPWSTR
  413. OEMfgets(
  414. OUT PDWORD pdwLen,
  415. IN FILE *fp
  416. )
  417. {
  418. LPWSTR pwszUnicode;
  419. DWORD dwErr = NO_ERROR;
  420. DWORD dwLen;
  421. CHAR buff[MAX_CMD_LEN];
  422. fflush(stdout);
  423. if (fgets( buff, sizeof(buff), fp ) is NULL)
  424. {
  425. return NULL;
  426. }
  427. dwLen = MultiByteToWideChar( GetConsoleOutputCP(),
  428. 0,
  429. buff,
  430. -1,
  431. NULL,
  432. 0 );
  433. if (g_hLogFile)
  434. {
  435. DWORD dwWritten;
  436. CHAR szCrLf[] = "\r\n";
  437. if (0 == WriteFile( g_hLogFile, buff, dwLen-2, &dwWritten, NULL ))
  438. {
  439. CloseHandle(g_hLogFile);
  440. g_hLogFile = NULL;
  441. PrintError(NULL, GetLastError());
  442. }
  443. if (0 == WriteFile( g_hLogFile, szCrLf, 2, &dwWritten, NULL ))
  444. {
  445. CloseHandle(g_hLogFile);
  446. g_hLogFile = NULL;
  447. PrintError(NULL, GetLastError());
  448. }
  449. }
  450. pwszUnicode = MALLOC(dwLen * sizeof(WCHAR));
  451. if (pwszUnicode)
  452. {
  453. MultiByteToWideChar( GetConsoleOutputCP(),
  454. 0,
  455. buff,
  456. sizeof(buff),
  457. pwszUnicode,
  458. dwLen );
  459. }
  460. *pdwLen = dwLen;
  461. return pwszUnicode;
  462. }
  463. VOID
  464. OEMfprintf(
  465. IN HANDLE hHandle,
  466. IN LPCWSTR pwszUnicode
  467. )
  468. {
  469. PCHAR achOem;
  470. DWORD dwLen, dwWritten;
  471. dwLen = WideCharToMultiByte( GetConsoleOutputCP(),
  472. 0,
  473. pwszUnicode,
  474. -1,
  475. NULL,
  476. 0,
  477. NULL,
  478. NULL );
  479. achOem = MALLOC(dwLen);
  480. if (achOem)
  481. {
  482. WideCharToMultiByte( GetConsoleOutputCP(),
  483. 0,
  484. pwszUnicode,
  485. -1,
  486. achOem,
  487. dwLen,
  488. NULL,
  489. NULL );
  490. WriteFile( hHandle, achOem, dwLen-1, &dwWritten, NULL );
  491. if (g_hLogFile)
  492. {
  493. if (0 == WriteFile( g_hLogFile, achOem, dwLen-1, &dwWritten, NULL ))
  494. {
  495. CloseHandle(g_hLogFile);
  496. g_hLogFile = NULL;
  497. PrintError(NULL, GetLastError());
  498. }
  499. }
  500. FREE(achOem);
  501. }
  502. }
  503. #define OEMprintf(pwszUnicode) \
  504. OEMfprintf( GetStdHandle(STD_OUTPUT_HANDLE), pwszUnicode)
  505. LPWSTR
  506. WINAPI
  507. GetEnumString(
  508. IN HANDLE hModule,
  509. IN DWORD dwValue,
  510. IN DWORD dwNumVal,
  511. IN PTOKEN_VALUE pEnumTable
  512. )
  513. /*++
  514. Routine Description:
  515. This routine looks up the value specified, dwValue, in the Value table
  516. pEnumTable and returns the string corresponding to the value
  517. Arguments :
  518. hModule - handle to current module
  519. dwValue - Value whose display string is required
  520. dwNumVal - Number of elements in pEnumTable
  521. pEnumTable - Table of enumerated value and corresp. string IDs
  522. Return Value :
  523. NULL - Value not found in pEnumTable
  524. Pointer to string on success
  525. --*/
  526. {
  527. DWORD dwInd;
  528. for ( dwInd = 0; dwInd < dwNumVal; dwInd++ )
  529. {
  530. if ( pEnumTable[ dwInd ].dwValue == dwValue )
  531. {
  532. // ISSUE: const_cast
  533. return (LPWSTR)pEnumTable[ dwInd ].pwszToken;
  534. }
  535. }
  536. return NULL;
  537. }
  538. LPWSTR
  539. WINAPI
  540. MakeString(
  541. IN HANDLE hModule,
  542. IN DWORD dwMsgId,
  543. ...
  544. )
  545. {
  546. DWORD dwMsgLen;
  547. LPWSTR pwszInput, pwszOutput = NULL;
  548. va_list arglist;
  549. do
  550. {
  551. va_start( arglist, dwMsgId );
  552. pwszInput = HeapAlloc(GetProcessHeap(),
  553. 0,
  554. MAX_MSG_LENGTH * sizeof(WCHAR) );
  555. if ( pwszInput == NULL )
  556. {
  557. break;
  558. }
  559. if ( !LoadStringW(hModule,
  560. dwMsgId,
  561. pwszInput,
  562. MAX_MSG_LENGTH) )
  563. {
  564. break;
  565. }
  566. FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  567. pwszInput,
  568. 0,
  569. 0L, // Default country ID.
  570. (LPWSTR)&pwszOutput,
  571. 0,
  572. &arglist);
  573. } while ( FALSE );
  574. if ( pwszInput ) { HeapFree( GetProcessHeap(), 0, pwszInput ); }
  575. return pwszOutput;
  576. }
  577. VOID
  578. WINAPI
  579. FreeString(
  580. IN LPWSTR pwszMadeString
  581. )
  582. /*++
  583. Routine Description:
  584. Frees string allocated by make string.
  585. Arguments:
  586. Return Value:
  587. --*/
  588. {
  589. LocalFree( pwszMadeString );
  590. }
  591. LPWSTR
  592. WINAPI
  593. MakeQuotedString(
  594. IN LPCWSTR pwszOrigString
  595. )
  596. {
  597. LPWSTR pwszNewString;
  598. pwszNewString = HeapAlloc(GetProcessHeap(),
  599. 0,
  600. (wcslen(pwszOrigString) + 3) * sizeof(WCHAR));
  601. if(pwszNewString == NULL)
  602. {
  603. return NULL;
  604. }
  605. wsprintfW(pwszNewString, L"\"%s\"",pwszOrigString);
  606. pwszNewString[wcslen(pwszOrigString) + 2] = UNICODE_NULL;
  607. return pwszNewString;
  608. }
  609. VOID
  610. WINAPI
  611. FreeQuotedString(
  612. LPWSTR pwszString
  613. )
  614. {
  615. HeapFree(GetProcessHeap(),
  616. 0,
  617. pwszString);
  618. }
  619. DWORD
  620. PrintError(
  621. IN HANDLE hModule, OPTIONAL
  622. IN DWORD dwErrId,
  623. ...
  624. )
  625. /*++
  626. Routine Description:
  627. Displays an error message.
  628. We first search for the error code in the module specified by the caller
  629. (if one is specified)
  630. If no module is given, or the error code doesnt exist we look for MPR
  631. errors, RAS errors and Win32 errors - in that order
  632. Arguments:
  633. hModule - Module to load the string from
  634. dwMsgId - Message to be printed
  635. ... - Insert strings
  636. Return Value:
  637. Message length
  638. --*/
  639. {
  640. DWORD dwMsgLen;
  641. LPWSTR pwszOutput = NULL;
  642. WCHAR rgwcInput[MAX_MSG_LENGTH + 1];
  643. va_list arglist;
  644. va_start(arglist, dwErrId);
  645. if(hModule)
  646. {
  647. if(LoadStringW(hModule,
  648. dwErrId,
  649. rgwcInput,
  650. MAX_MSG_LENGTH))
  651. {
  652. //
  653. // Found the message in the callers module
  654. //
  655. dwMsgLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_STRING,
  656. rgwcInput,
  657. 0,
  658. 0L,
  659. (LPWSTR)&pwszOutput,
  660. 0,
  661. &arglist);
  662. if(dwMsgLen == 0)
  663. {
  664. ASSERT(pwszOutput == NULL);
  665. }
  666. else
  667. {
  668. OEMprintf(pwszOutput);
  669. LocalFree(pwszOutput);
  670. return dwMsgLen;
  671. }
  672. }
  673. else
  674. {
  675. return 0;
  676. }
  677. }
  678. //
  679. // Next try, local errors
  680. //
  681. if((dwErrId > NETSH_ERROR_BASE) &&
  682. (dwErrId < NETSH_ERROR_END))
  683. {
  684. if(LoadStringW(g_hModule,
  685. dwErrId,
  686. rgwcInput,
  687. MAX_MSG_LENGTH))
  688. {
  689. //
  690. // Found the message in our module
  691. //
  692. dwMsgLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_STRING,
  693. rgwcInput,
  694. 0,
  695. 0L,
  696. (LPWSTR)&pwszOutput,
  697. 0,
  698. &arglist);
  699. if(dwMsgLen == 0)
  700. {
  701. ASSERT(pwszOutput == NULL);
  702. }
  703. else
  704. {
  705. OEMprintf(pwszOutput);
  706. LocalFree(pwszOutput);
  707. return dwMsgLen;
  708. }
  709. }
  710. }
  711. //
  712. // Next try MPR errors
  713. //
  714. if (MprAdminGetErrorString(dwErrId,
  715. &pwszOutput) == NO_ERROR)
  716. {
  717. wcscpy(rgwcInput, pwszOutput);
  718. LocalFree(pwszOutput);
  719. wcscat(rgwcInput, L"\r\n");
  720. OEMprintf(rgwcInput);
  721. dwMsgLen = wcslen(rgwcInput);
  722. return dwMsgLen;
  723. }
  724. //
  725. // Next try RAS errors
  726. //
  727. if (RasGetErrorStringW(dwErrId,
  728. rgwcInput,
  729. MAX_MSG_LENGTH) == NO_ERROR)
  730. {
  731. wcscat(rgwcInput, L"\r\n");
  732. OEMprintf(rgwcInput);
  733. dwMsgLen = wcslen(rgwcInput);
  734. return dwMsgLen;
  735. }
  736. //
  737. // Finally try Win32
  738. //
  739. dwMsgLen = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
  740. NULL,
  741. dwErrId,
  742. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  743. rgwcInput,
  744. MAX_MSG_LENGTH,
  745. &arglist);
  746. if(dwMsgLen)
  747. {
  748. OEMprintf(rgwcInput);
  749. return dwMsgLen;
  750. }
  751. return 0;
  752. }
  753. DWORD
  754. DisplayMessageVA(
  755. IN LPCWSTR pwszFormat,
  756. IN va_list *parglist
  757. )
  758. {
  759. DWORD dwMsgLen = 0;
  760. LPWSTR pwszOutput = NULL;
  761. do
  762. {
  763. dwMsgLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
  764. |FORMAT_MESSAGE_FROM_STRING,
  765. pwszFormat,
  766. 0,
  767. 0L, // Default country ID.
  768. (LPWSTR)&pwszOutput,
  769. 0,
  770. parglist);
  771. if(dwMsgLen == 0)
  772. {
  773. // ISSUE: Unlocalized string.
  774. wprintf( L"Error %d in FormatMessageW()\n", GetLastError());
  775. ASSERT(pwszOutput == NULL);
  776. break;
  777. }
  778. OEMprintf( pwszOutput );
  779. } while ( FALSE );
  780. if ( pwszOutput) { LocalFree( pwszOutput ); }
  781. return dwMsgLen;
  782. }
  783. DWORD
  784. PrintMessage(
  785. IN LPCWSTR rgwcInput,
  786. ...
  787. )
  788. {
  789. DWORD dwMsgLen = 0;
  790. LPCWSTR pwszOutput = NULL;
  791. va_list arglist;
  792. va_start(arglist, rgwcInput);
  793. if (!rgwcInput)
  794. {
  795. return ERROR_INVALID_PARAMETER;
  796. }
  797. return DisplayMessageVA(rgwcInput, &arglist);
  798. }
  799. DWORD
  800. PrintMessageFromModule(
  801. IN HANDLE hModule,
  802. IN DWORD dwMsgId,
  803. ...
  804. )
  805. {
  806. WCHAR rgwcInput[MAX_MSG_LENGTH + 1];
  807. va_list arglist;
  808. if ( !LoadStringW(hModule,
  809. dwMsgId,
  810. rgwcInput,
  811. MAX_MSG_LENGTH) )
  812. {
  813. return 0;
  814. }
  815. va_start(arglist, dwMsgId);
  816. return DisplayMessageVA(rgwcInput, &arglist);
  817. }
  818. DWORD
  819. DisplayMessageM(
  820. IN HANDLE hModule,
  821. IN DWORD dwMsgId,
  822. ...
  823. )
  824. {
  825. DWORD dwMsgLen;
  826. LPWSTR pwszOutput = NULL;
  827. va_list arglist;
  828. do
  829. {
  830. va_start(arglist, dwMsgId);
  831. dwMsgLen = FormatMessageW(
  832. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  833. FORMAT_MESSAGE_FROM_HMODULE,
  834. hModule,
  835. dwMsgId,
  836. 0L,
  837. (LPWSTR)&pwszOutput,
  838. 0,
  839. &arglist
  840. );
  841. if(dwMsgLen == 0)
  842. {
  843. DWORD dwErr;
  844. dwErr = GetLastError();
  845. ASSERT(pwszOutput == NULL);
  846. break;
  847. }
  848. OEMprintf( pwszOutput );
  849. } while ( FALSE );
  850. if ( pwszOutput) { LocalFree( pwszOutput ); }
  851. return dwMsgLen;
  852. }
  853. DWORD
  854. DisplayMessageToConsole(
  855. IN HANDLE hModule,
  856. IN HANDLE hConsole,
  857. IN DWORD dwMsgId,
  858. ...
  859. )
  860. {
  861. DWORD dwMsgLen = 0;
  862. LPWSTR pwszInput, pwszOutput = NULL;
  863. va_list arglist;
  864. DWORD dwNumWritten;
  865. do
  866. {
  867. va_start(arglist, dwMsgId);
  868. pwszInput = HeapAlloc(GetProcessHeap(),
  869. 0,
  870. MAX_MSG_LENGTH * sizeof(WCHAR));
  871. if ( pwszInput == (LPCWSTR) NULL )
  872. {
  873. break;
  874. }
  875. if ( !LoadStringW(hModule,
  876. dwMsgId,
  877. pwszInput,
  878. MAX_MSG_LENGTH) )
  879. {
  880. break;
  881. }
  882. dwMsgLen = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING,
  883. pwszInput,
  884. 0,
  885. 0L, // Default country ID.
  886. (LPWSTR)&pwszOutput,
  887. 0,
  888. &arglist);
  889. if ( dwMsgLen == 0 )
  890. {
  891. break;
  892. }
  893. OEMfprintf( hConsole, pwszOutput );
  894. fflush(stdout);
  895. } while ( FALSE );
  896. if ( pwszInput ) { HeapFree( GetProcessHeap(), 0, pwszInput ); }
  897. if ( pwszOutput) { LocalFree( pwszOutput ); }
  898. return dwMsgLen;
  899. }
  900. BOOL
  901. WINAPI
  902. HandlerRoutine(
  903. DWORD dwCtrlType // control signal type
  904. )
  905. {
  906. HANDLE hStop;
  907. if (dwCtrlType == CTRL_C_EVENT)
  908. {
  909. hStop = OpenEvent(EVENT_ALL_ACCESS,
  910. FALSE,
  911. STOP_EVENT);
  912. if (hStop isnot NULL)
  913. {
  914. SetEvent(hStop);
  915. CloseHandle(hStop);
  916. }
  917. return TRUE;
  918. }
  919. else
  920. {
  921. // Need to handle the other events...
  922. // CTRL_BREAK_EVENT
  923. // CTRL_CLOSE_EVENT
  924. // CTRL_LOGOFF_EVENT
  925. // Need to clean up, free all the dll's we loaded.
  926. //
  927. FreeHelpers();
  928. FreeDlls();
  929. // Always need to return false for these events, otherwise the app will hang.
  930. //
  931. return FALSE;
  932. }
  933. };
  934. void
  935. cls(
  936. IN HANDLE hConsole
  937. )
  938. {
  939. COORD coordScreen = { 0, 0 };
  940. BOOL bSuccess;
  941. DWORD cCharsWritten;
  942. CONSOLE_SCREEN_BUFFER_INFO csbi;
  943. DWORD dwConSize;
  944. WORD wAttr;
  945. bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi);
  946. dwConSize = (WORD) csbi.dwSize.X * (WORD) csbi.dwSize.Y;
  947. bSuccess = FillConsoleOutputCharacter(hConsole,
  948. _TEXT(' '),
  949. dwConSize,
  950. coordScreen,
  951. &cCharsWritten);
  952. //
  953. // get the current text attribute
  954. //
  955. bSuccess = GetConsoleScreenBufferInfo(hConsole, &csbi);
  956. //
  957. // Make the background and foreground the same
  958. //
  959. wAttr = (csbi.wAttributes & 0xFFF0) | ((csbi.wAttributes & 0x00F0) >> 4);
  960. //
  961. // now set the buffer's attributes accordingly
  962. //
  963. bSuccess = FillConsoleOutputAttribute(hConsole,
  964. wAttr,
  965. dwConSize,
  966. coordScreen,
  967. &cCharsWritten);
  968. bSuccess = SetConsoleCursorPosition(hConsole, coordScreen);
  969. return;
  970. }
  971. BOOL
  972. WINAPI
  973. InitializeConsole(
  974. IN OUT PDWORD pdwRR,
  975. OUT HANDLE *phMib,
  976. OUT HANDLE *phConsole
  977. )
  978. {
  979. HANDLE hMib, hStdOut, hConsole;
  980. CONSOLE_SCREEN_BUFFER_INFO csbi;
  981. hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
  982. if (hStdOut is INVALID_HANDLE_VALUE)
  983. {
  984. return FALSE;
  985. }
  986. if (!*pdwRR)
  987. {
  988. //
  989. // No refresh. Display to standard output
  990. //
  991. *phConsole = hStdOut;
  992. *phMib = (HANDLE) NULL;
  993. return TRUE;
  994. }
  995. do
  996. {
  997. hMib = CreateEvent( NULL, TRUE, FALSE, STOP_EVENT);
  998. if (hMib == NULL)
  999. {
  1000. *pdwRR = 0;
  1001. *phConsole = hStdOut;
  1002. *phMib = (HANDLE) NULL;
  1003. break;
  1004. }
  1005. *phMib = hMib;
  1006. hConsole = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
  1007. 0, // NO sharing
  1008. NULL,
  1009. CONSOLE_TEXTMODE_BUFFER,
  1010. NULL);
  1011. if (hConsole is INVALID_HANDLE_VALUE)
  1012. {
  1013. //
  1014. // No refresh will be done
  1015. //
  1016. *pdwRR = 0;
  1017. *phConsole = hStdOut;
  1018. *phMib = (HANDLE) NULL;
  1019. break;
  1020. }
  1021. else
  1022. {
  1023. GetConsoleScreenBufferInfo(hStdOut, &csbi);
  1024. csbi.dwSize.X = 80;
  1025. SetConsoleScreenBufferSize(hConsole, csbi.dwSize);
  1026. SetConsoleActiveScreenBuffer(hConsole);
  1027. SetConsoleCtrlHandler(HandlerRoutine,TRUE);
  1028. *phConsole = hConsole;
  1029. }
  1030. }while (FALSE);
  1031. return TRUE;
  1032. }
  1033. DWORD
  1034. WINAPI
  1035. RefreshConsole(
  1036. IN HANDLE hMib,
  1037. IN HANDLE hConsole,
  1038. IN DWORD dwRR
  1039. )
  1040. {
  1041. COORD origin = {0,0};
  1042. if (dwRR)
  1043. {
  1044. SetConsoleCursorPosition(hConsole, origin);
  1045. if (WaitForSingleObject(hMib, dwRR) == WAIT_OBJECT_0)
  1046. {
  1047. //
  1048. // End of refresh
  1049. //
  1050. ResetEvent(hMib);
  1051. SetConsoleCtrlHandler(HandlerRoutine,FALSE);
  1052. CloseHandle(hMib);
  1053. CloseHandle(hConsole);
  1054. // SetConsoleActiveScreenBuffer(g_hStdOut);
  1055. return FALSE;
  1056. }
  1057. else
  1058. {
  1059. //
  1060. // Go in loop again
  1061. //
  1062. cls(hConsole);
  1063. return TRUE;
  1064. }
  1065. }
  1066. return FALSE;
  1067. }
  1068. #define HT_TOP 0
  1069. #define HT_CONTEXT 1
  1070. #define HT_GROUP 2
  1071. typedef struct {
  1072. HANDLE hModule;
  1073. LPCWSTR pwszContext;
  1074. DWORD dwType;
  1075. LPCWSTR pwszCommand;
  1076. DWORD dwDescr;
  1077. LPCWSTR pwszDescr;
  1078. LPCWSTR pwszGroup;
  1079. } help_t;
  1080. #define MAX_HELP_COMMANDS 100
  1081. help_t help[MAX_HELP_COMMANDS];
  1082. ULONG ulNumHelpCommands = 0;
  1083. DWORD
  1084. FindHelpCommand(
  1085. IN LPCWSTR pwszCommand
  1086. )
  1087. {
  1088. ULONG i;
  1089. for (i=0; i<ulNumHelpCommands; i++)
  1090. {
  1091. if (!wcscmp(pwszCommand, help[i].pwszCommand))
  1092. {
  1093. return i;
  1094. }
  1095. }
  1096. return -1;
  1097. }
  1098. DWORD
  1099. AddHelpCommand(
  1100. IN HANDLE hModule,
  1101. IN LPCWSTR pwszContext,
  1102. IN DWORD dwType,
  1103. IN LPCWSTR pwszCommand,
  1104. IN DWORD dwDescr,
  1105. IN LPCWSTR pwszDescr,
  1106. IN LPCWSTR pwszGroup
  1107. )
  1108. {
  1109. ULONG i;
  1110. ASSERT(ulNumHelpCommands < MAX_HELP_COMMANDS); // XXX
  1111. i = ulNumHelpCommands++;
  1112. help[i].hModule = hModule;
  1113. help[i].pwszContext = pwszContext;
  1114. help[i].dwType = dwType;
  1115. help[i].pwszCommand = pwszCommand;
  1116. help[i].dwDescr = dwDescr;
  1117. help[i].pwszDescr = pwszDescr;
  1118. help[i].pwszGroup = pwszGroup;
  1119. return NO_ERROR;
  1120. }
  1121. int
  1122. __cdecl
  1123. helpcmp(
  1124. const void *a,
  1125. const void *b
  1126. )
  1127. {
  1128. return _wcsicmp(((help_t*)a)->pwszCommand, ((help_t*)b)->pwszCommand);
  1129. }
  1130. DWORD
  1131. DisplayAllHelpCommands(
  1132. )
  1133. {
  1134. ULONG i;
  1135. // Sort
  1136. qsort( (void*)help, ulNumHelpCommands, sizeof(help_t), helpcmp );
  1137. for (i=0; i<ulNumHelpCommands; i++)
  1138. {
  1139. if ((HT_GROUP == help[i].dwType) && help[i].pwszGroup)
  1140. {
  1141. LPWSTR pwszGroupFullCmd = (LPWSTR)
  1142. MALLOC( ( wcslen(help[i].pwszGroup) +
  1143. wcslen(help[i].pwszCommand) +
  1144. 2 // for blank and NULL characters
  1145. ) * sizeof(WCHAR)
  1146. );
  1147. if (NULL == pwszGroupFullCmd)
  1148. {
  1149. PrintMessage( MSG_HELP_START, help[i].pwszCommand );
  1150. }
  1151. else
  1152. {
  1153. wcscpy(pwszGroupFullCmd, help[i].pwszGroup);
  1154. wcscat(pwszGroupFullCmd, L" ");
  1155. wcscat(pwszGroupFullCmd, help[i].pwszCommand);
  1156. PrintMessage( MSG_HELP_START, pwszGroupFullCmd );
  1157. FREE(pwszGroupFullCmd);
  1158. }
  1159. }
  1160. else
  1161. {
  1162. PrintMessage( MSG_HELP_START, help[i].pwszCommand );
  1163. }
  1164. if (!PrintMessageFromModule( help[i].hModule, help[i].dwDescr, help[i].pwszDescr,
  1165. help[i].pwszContext,
  1166. (help[i].pwszContext[0])? L" " : L"" ))
  1167. {
  1168. PrintMessage(MSG_NEWLINE);
  1169. }
  1170. }
  1171. // Delete all help commands
  1172. ulNumHelpCommands = 0;
  1173. return NO_ERROR;
  1174. }
  1175. VOID
  1176. DisplayContextsHere(
  1177. IN ULONG ulNumContexts,
  1178. IN PBYTE pByteContexts,
  1179. IN DWORD dwContextSize,
  1180. IN DWORD dwDisplayFlags
  1181. )
  1182. {
  1183. DWORD i;
  1184. PCNS_CONTEXT_ATTRIBUTES pContext;
  1185. if (!ulNumContexts)
  1186. {
  1187. return;
  1188. }
  1189. PrintMessageFromModule(g_hModule, MSG_SUBCONTEXT_LIST);
  1190. for (i = 0; i < ulNumContexts; i++)
  1191. {
  1192. pContext = (PCNS_CONTEXT_ATTRIBUTES)(pByteContexts + i*dwContextSize);
  1193. if (pContext->dwFlags & ~dwDisplayFlags)
  1194. {
  1195. continue;
  1196. }
  1197. if (!VerifyOsVersion(pContext->pfnOsVersionCheck))
  1198. {
  1199. continue;
  1200. }
  1201. PrintMessage(L" %1!s!", pContext->pwszContext);
  1202. }
  1203. PrintMessage(MSG_NEWLINE);
  1204. }
  1205. DWORD
  1206. DisplayContextHelp(
  1207. IN PCNS_CONTEXT_ATTRIBUTES pContext,
  1208. IN DWORD dwDisplayFlags,
  1209. IN DWORD dwCmdFlags,
  1210. IN DWORD dwArgsRemaining,
  1211. IN LPCWSTR pwszGroup
  1212. )
  1213. {
  1214. DWORD i, j, dwErr;
  1215. PNS_HELPER_TABLE_ENTRY pHelper;
  1216. ULONG ulNumContexts;
  1217. DWORD dwContextSize;
  1218. PBYTE pByteContexts;
  1219. PNS_DLL_TABLE_ENTRY pDll;
  1220. PCNS_CONTEXT_ATTRIBUTES pSubContext;
  1221. LPWSTR pwszFullContextName = NULL;
  1222. dwErr = GetHelperEntry(&pContext->guidHelper, &pHelper);
  1223. if (dwErr)
  1224. {
  1225. return dwErr;
  1226. }
  1227. dwErr = GetDllEntry( pHelper->dwDllIndex, &pDll );
  1228. if (dwErr)
  1229. {
  1230. return dwErr;
  1231. }
  1232. dwErr = AppendFullContextName(pContext, &pwszFullContextName);
  1233. ulNumContexts = pHelper->ulNumSubContexts;
  1234. dwContextSize = pHelper->ulSubContextSize;
  1235. pByteContexts = pHelper->pSubContextTable;
  1236. // First set up flags
  1237. if (dwCmdFlags & CMD_FLAG_INTERACTIVE)
  1238. {
  1239. dwDisplayFlags |= CMD_FLAG_INTERACTIVE;
  1240. }
  1241. if (dwCmdFlags & CMD_FLAG_ONLINE)
  1242. {
  1243. dwDisplayFlags |= CMD_FLAG_ONLINE;
  1244. }
  1245. if (dwCmdFlags & CMD_FLAG_LOCAL)
  1246. {
  1247. dwDisplayFlags |= CMD_FLAG_LOCAL;
  1248. }
  1249. if (IsImmediate(dwCmdFlags, dwArgsRemaining))
  1250. {
  1251. dwCmdFlags |= CMD_FLAG_IMMEDIATE;
  1252. }
  1253. // Turn on any flags not used to limit commands
  1254. // so they won't cause commands to not be displayed
  1255. dwDisplayFlags |= ~CMD_FLAG_LIMIT_MASK;
  1256. if (dwDisplayFlags & CMD_FLAG_PRIVATE)
  1257. {
  1258. PrintMessageFromModule(g_hModule, MSG_SHELL_CMD_HELP_HEADER);
  1259. }
  1260. // dwDisplayFlags has PRIVATE set *unless* this is called as a result of
  1261. // printing help in the parent context, and non-inheritable commands
  1262. // should not be printed.
  1263. //
  1264. // dwCmdFlags has IMMEDIATE set *unless* this is called from a parent
  1265. // context, in which case parent help should not be printed.
  1266. if ((!(dwDisplayFlags & CMD_FLAG_PRIVATE)
  1267. || (dwCmdFlags & CMD_FLAG_IMMEDIATE)))
  1268. {
  1269. // Print help on inherited commands
  1270. PCNS_CONTEXT_ATTRIBUTES pParentContext;
  1271. dwErr = GetParentContext( pContext, &pParentContext );
  1272. if (dwErr is NO_ERROR)
  1273. {
  1274. dwErr = DisplayContextHelp( pParentContext,
  1275. dwDisplayFlags & ~CMD_FLAG_PRIVATE,
  1276. dwCmdFlags,
  1277. dwArgsRemaining,
  1278. pwszGroup );
  1279. }
  1280. }
  1281. for(i = 0; !pwszGroup && (i < pContext->ulNumTopCmds); i++)
  1282. {
  1283. if (((*pContext->pTopCmds)[i].dwCmdHlpToken == MSG_NULL)
  1284. || ((*pContext->pTopCmds)[i].dwFlags & ~dwDisplayFlags))
  1285. {
  1286. continue;
  1287. }
  1288. if (!VerifyOsVersion((*pContext->pTopCmds)[i].pOsVersionCheck))
  1289. {
  1290. continue;
  1291. }
  1292. AddHelpCommand( pDll->hDll,
  1293. pwszFullContextName,
  1294. HT_TOP,
  1295. (*pContext->pTopCmds)[i].pwszCmdToken,
  1296. (*pContext->pTopCmds)[i].dwShortCmdHelpToken,
  1297. NULL, NULL );
  1298. }
  1299. for(i = 0; i < pContext->ulNumGroups; i++)
  1300. {
  1301. if (((*pContext->pCmdGroups)[i].dwShortCmdHelpToken == MSG_NULL)
  1302. || ((*pContext->pCmdGroups)[i].dwFlags & ~dwDisplayFlags))
  1303. {
  1304. continue;
  1305. }
  1306. if (!(*pContext->pCmdGroups)[i].pwszCmdGroupToken[0])
  1307. {
  1308. continue;
  1309. }
  1310. if (pwszGroup)
  1311. {
  1312. if (_wcsicmp(pwszGroup, (*pContext->pCmdGroups)[i].pwszCmdGroupToken))
  1313. {
  1314. continue;
  1315. }
  1316. if (!VerifyOsVersion((*pContext->pCmdGroups)[i].pOsVersionCheck))
  1317. {
  1318. continue;
  1319. }
  1320. for (j = 0; j < (*pContext->pCmdGroups)[i].ulCmdGroupSize; j++)
  1321. {
  1322. if ((*pContext->pCmdGroups)[i].pCmdGroup[j].dwFlags & ~dwDisplayFlags)
  1323. {
  1324. continue;
  1325. }
  1326. if (!VerifyOsVersion((*pContext->pCmdGroups)[i].pCmdGroup[j].pOsVersionCheck))
  1327. {
  1328. continue;
  1329. }
  1330. AddHelpCommand( pDll->hDll,
  1331. pwszFullContextName,
  1332. HT_GROUP,
  1333. (*pContext->pCmdGroups)[i].pCmdGroup[j].pwszCmdToken,
  1334. (*pContext->pCmdGroups)[i].pCmdGroup[j].dwShortCmdHelpToken,
  1335. NULL,
  1336. pwszGroup);
  1337. }
  1338. }
  1339. else
  1340. {
  1341. if (!VerifyOsVersion((*pContext->pCmdGroups)[i].pOsVersionCheck))
  1342. {
  1343. continue;
  1344. }
  1345. AddHelpCommand( pDll->hDll,
  1346. pwszFullContextName,
  1347. HT_GROUP,
  1348. (*pContext->pCmdGroups)[i].pwszCmdGroupToken,
  1349. (*pContext->pCmdGroups)[i].dwShortCmdHelpToken,
  1350. NULL, NULL );
  1351. }
  1352. }
  1353. for (i = 0; !pwszGroup && (i < ulNumContexts); i++)
  1354. {
  1355. pSubContext = (PCNS_CONTEXT_ATTRIBUTES)(pByteContexts + i * dwContextSize);
  1356. if ((pSubContext->dwFlags & ~dwDisplayFlags))
  1357. {
  1358. continue;
  1359. }
  1360. if (!VerifyOsVersion(pSubContext->pfnOsVersionCheck))
  1361. {
  1362. continue;
  1363. }
  1364. AddHelpCommand( g_hModule,
  1365. pwszFullContextName,
  1366. HT_CONTEXT,
  1367. pSubContext->pwszContext,
  1368. MSG_HELPER_HELP,
  1369. pSubContext->pwszContext, NULL );
  1370. }
  1371. if (dwDisplayFlags & CMD_FLAG_PRIVATE)
  1372. {
  1373. // Add any ubiquitous commands that aren't already added
  1374. for(i = 0; !pwszGroup && (i < g_ulNumUbiqCmds); i++)
  1375. {
  1376. if ((g_UbiqCmds[i].dwCmdHlpToken == MSG_NULL)
  1377. || (g_UbiqCmds[i].dwFlags & ~dwDisplayFlags))
  1378. {
  1379. continue;
  1380. }
  1381. if (FindHelpCommand(g_UbiqCmds[i].pwszCmdToken) isnot -1)
  1382. {
  1383. continue;
  1384. }
  1385. AddHelpCommand( g_hModule,
  1386. pwszFullContextName,
  1387. HT_TOP,
  1388. g_UbiqCmds[i].pwszCmdToken,
  1389. g_UbiqCmds[i].dwShortCmdHelpToken,
  1390. NULL, NULL );
  1391. }
  1392. }
  1393. if (ulNumHelpCommands > 0)
  1394. {
  1395. if (dwDisplayFlags & CMD_FLAG_PRIVATE)
  1396. {
  1397. PrintMessageFromModule( g_hModule, MSG_LOCAL_COMMANDS );
  1398. }
  1399. else if (help[0].pwszContext[0])
  1400. {
  1401. PrintMessageFromModule( g_hModule,
  1402. MSG_INHERITED_COMMANDS,
  1403. help[0].pwszContext );
  1404. }
  1405. else
  1406. {
  1407. PrintMessageFromModule( g_hModule, MSG_GLOBAL_COMMANDS );
  1408. }
  1409. DisplayAllHelpCommands();
  1410. }
  1411. // Once we've popped the stack back up to the original context
  1412. // in which the help command was run, display all the subcontexts
  1413. // available here.
  1414. if ((dwDisplayFlags & CMD_FLAG_PRIVATE) && !pwszGroup)
  1415. {
  1416. DisplayContextsHere( pHelper->ulNumSubContexts,
  1417. pHelper->pSubContextTable,
  1418. pHelper->ulSubContextSize,
  1419. dwDisplayFlags );
  1420. PrintMessageFromModule( g_hModule, MSG_HELP_FOOTER, CMD_HELP2 );
  1421. }
  1422. if (pwszFullContextName)
  1423. {
  1424. FREE(pwszFullContextName);
  1425. }
  1426. return NO_ERROR;
  1427. }
  1428. DWORD
  1429. WINAPI
  1430. DisplayHelp(
  1431. IN CONST GUID *pguidHelper,
  1432. IN LPCWSTR pwszContext,
  1433. IN DWORD dwDisplayFlags,
  1434. IN DWORD dwCmdFlags,
  1435. IN DWORD dwArgsRemaining,
  1436. IN LPCWSTR pwszGroup
  1437. )
  1438. {
  1439. DWORD i, j, dwErr;
  1440. PCNS_CONTEXT_ATTRIBUTES pContext;
  1441. PNS_HELPER_TABLE_ENTRY pHelper;
  1442. // Locate helper
  1443. dwErr = GetHelperEntry( pguidHelper, &pHelper );
  1444. // Locate context
  1445. dwErr = GetContextEntry( pHelper, pwszContext, &pContext );
  1446. if (dwErr)
  1447. {
  1448. return dwErr;
  1449. }
  1450. return DisplayContextHelp( pContext,
  1451. dwDisplayFlags,
  1452. dwCmdFlags,
  1453. dwArgsRemaining,
  1454. pwszGroup );
  1455. }
  1456. DWORD
  1457. WINAPI
  1458. PreprocessCommand(
  1459. IN HANDLE hModule,
  1460. IN OUT LPWSTR *ppwcArguments,
  1461. IN DWORD dwCurrentIndex,
  1462. IN DWORD dwArgCount,
  1463. IN OUT PTAG_TYPE pttTags,
  1464. IN DWORD dwTagCount,
  1465. IN DWORD dwMinArgs,
  1466. IN DWORD dwMaxArgs,
  1467. OUT DWORD *pdwTagType
  1468. )
  1469. /*++
  1470. Description:
  1471. Make sure the number of arguments is valid.
  1472. Make sure there are no duplicate or unrecognized tags.
  1473. Arguments:
  1474. ppwcArguments - Argument array
  1475. dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
  1476. dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
  1477. pttTags - Legal tags
  1478. dwTagCount - Number of legal tags
  1479. dwMinArgs - minimum # of args required
  1480. dwMaxArgs - maximum # of args required
  1481. pdwTagType - Index into pttTags for each argument
  1482. --*/
  1483. {
  1484. DWORD dwNumArgs, i;
  1485. DWORD dwErr = NO_ERROR;
  1486. DWORD dwTagEnum;
  1487. if ( (!ppwcArguments) || (!pttTags) || (!pdwTagType) )
  1488. {
  1489. return ERROR_INVALID_PARAMETER;
  1490. }
  1491. for (dwTagEnum = 0; dwTagEnum < dwTagCount; dwTagEnum++)
  1492. {
  1493. pttTags->bPresent = FALSE;
  1494. }
  1495. #ifdef EXTRA_DEBUG
  1496. PRINT("PreHandleCommand:");
  1497. for( i = 0; i < dwArgCount; i++)
  1498. {
  1499. PRINT(ppwcArguments[i]);
  1500. }
  1501. #endif
  1502. dwNumArgs = dwArgCount - dwCurrentIndex;
  1503. if((dwNumArgs < dwMinArgs) or
  1504. (dwNumArgs > dwMaxArgs))
  1505. {
  1506. //
  1507. // Wrong number of arguments specified
  1508. //
  1509. return ERROR_INVALID_SYNTAX;
  1510. }
  1511. if ( dwNumArgs > 0 )
  1512. {
  1513. dwErr = MatchTagsInCmdLine(hModule,
  1514. ppwcArguments,
  1515. dwCurrentIndex,
  1516. dwArgCount,
  1517. pttTags,
  1518. dwTagCount,
  1519. pdwTagType);
  1520. if (dwErr isnot NO_ERROR)
  1521. {
  1522. if (dwErr is ERROR_INVALID_OPTION_TAG)
  1523. {
  1524. return ERROR_INVALID_SYNTAX;
  1525. }
  1526. return dwErr;
  1527. }
  1528. }
  1529. // Make sure we don't have duplicate or unrecognized tags
  1530. for(i = 0; i < dwNumArgs; i ++)
  1531. {
  1532. if ((int) pdwTagType[i] < 0 || pdwTagType[i] >= dwTagCount)
  1533. {
  1534. dwErr = ERROR_INVALID_SYNTAX;
  1535. break;
  1536. }
  1537. }
  1538. switch(dwErr)
  1539. {
  1540. case NO_ERROR:
  1541. {
  1542. break;
  1543. }
  1544. default:
  1545. {
  1546. return dwErr;
  1547. }
  1548. }
  1549. // Make sure every required tag is present
  1550. for(i = 0; i < dwTagCount; i++)
  1551. {
  1552. if ((pttTags[i].dwRequired & NS_REQ_PRESENT)
  1553. && !pttTags[i].bPresent)
  1554. {
  1555. PrintMessageFromModule(g_hModule, ERROR_MISSING_OPTION);
  1556. return ERROR_INVALID_SYNTAX;
  1557. }
  1558. }
  1559. return NO_ERROR;
  1560. }
  1561. #define HISTORY_MASK (NS_EVENT_LAST_N | NS_EVENT_FROM_N | \
  1562. NS_EVENT_FROM_START | NS_EVENT_LAST_SECS)
  1563. DWORD
  1564. SetupEventLogSeekPtr(
  1565. OUT PHANDLE phEventLog,
  1566. IN PEVENT_PRINT_INFO pEventInfo
  1567. )
  1568. /*++
  1569. Routine Description:
  1570. This function opens a handle to the appropriate event log and "rewinds"
  1571. to the correct point as specified by the fflags. When the function returns
  1572. the eventlog handle is setup such that reading the log sequentially in a
  1573. forward direction will get the events the caller wants
  1574. Locks:
  1575. None
  1576. Arguments:
  1577. See above, args are passed pretty much the same
  1578. Return Value:
  1579. Win32
  1580. --*/
  1581. {
  1582. DWORD dwResult, dwRead, dwNeed, i, dwHistoryContext;
  1583. BYTE Buffer[2048]; // Huge buffer
  1584. DWORD_PTR pNextEvent;
  1585. BOOL bResult, bDone;
  1586. LPCWSTR pwszComponent;
  1587. EVENTLOGRECORD *pStartEvent;
  1588. dwResult = NO_ERROR;
  1589. //
  1590. // Open the event log
  1591. //
  1592. *phEventLog = OpenEventLogW(g_pwszRouterName,
  1593. pEventInfo->pwszLogName);
  1594. if(*phEventLog is NULL)
  1595. {
  1596. return GetLastError();
  1597. }
  1598. if(pEventInfo->fFlags is 0)
  1599. {
  1600. //
  1601. // If no history is being requested, just return. Our seek ptr
  1602. // will be already setup
  1603. //
  1604. return NO_ERROR;
  1605. }
  1606. if(pEventInfo->fFlags & NS_EVENT_FROM_START)
  1607. {
  1608. //
  1609. // We can use the same matching for this as we do for NS_EVENT_FROM_N
  1610. // by setting component to eventlog and dwHistoryContext to 6005
  1611. //
  1612. pwszComponent = L"eventlog";
  1613. dwHistoryContext = 6005;
  1614. }
  1615. else
  1616. {
  1617. pwszComponent = pEventInfo->pwszComponent;
  1618. dwHistoryContext = pEventInfo->dwHistoryContext;
  1619. }
  1620. //
  1621. // Okay so she wants history. Either way we read backwards
  1622. //
  1623. i = 0;
  1624. pStartEvent = NULL;
  1625. bDone = FALSE;
  1626. //
  1627. // Read the event log till we find a record to stop at
  1628. // This is signalled by the code setting bDone to TRUE
  1629. //
  1630. while(!bDone)
  1631. {
  1632. //
  1633. // Get a bunch of events
  1634. //
  1635. bResult = ReadEventLogW(
  1636. *phEventLog,
  1637. EVENTLOG_SEQUENTIAL_READ | EVENTLOG_BACKWARDS_READ,
  1638. 0,
  1639. (PVOID)Buffer,
  1640. sizeof(Buffer),
  1641. &dwRead,
  1642. &dwNeed
  1643. );
  1644. if(bResult isnot TRUE)
  1645. {
  1646. dwResult = GetLastError();
  1647. if(dwResult is ERROR_HANDLE_EOF)
  1648. {
  1649. //
  1650. // If we have reached the end of the log, break out
  1651. //
  1652. bDone = TRUE;
  1653. break;
  1654. }
  1655. else
  1656. {
  1657. return dwResult;
  1658. }
  1659. }
  1660. //
  1661. // Start at the beginning of the buffer we just read
  1662. //
  1663. pNextEvent = (DWORD_PTR)Buffer;
  1664. //
  1665. // Read till we walk off the end of the buffer or find a record
  1666. //
  1667. // If we find the starting record, we set pStartEvent to one after that
  1668. // It may so happen that the starting record is the last one in
  1669. // the block that we have read. In that case, we set pStartEvent
  1670. // to NULL but bDone to TRUE
  1671. //
  1672. while((pNextEvent < (DWORD_PTR)Buffer + dwRead) and !bDone)
  1673. {
  1674. EVENTLOGRECORD *pCurrentEvent;
  1675. pCurrentEvent = (EVENTLOGRECORD *)pNextEvent;
  1676. pNextEvent += pCurrentEvent->Length;
  1677. switch(pEventInfo->fFlags)
  1678. {
  1679. case NS_EVENT_LAST_N:
  1680. case NS_EVENT_LAST_SECS:
  1681. {
  1682. //
  1683. // We are being asked to go back N (of our records)
  1684. // or go back N secs
  1685. //
  1686. if(!IsOurRecord(pCurrentEvent,
  1687. pEventInfo))
  1688. {
  1689. //
  1690. // Not one of ours
  1691. //
  1692. continue;
  1693. }
  1694. if(pEventInfo->fFlags is NS_EVENT_LAST_N)
  1695. {
  1696. //
  1697. // i is the count of events
  1698. //
  1699. i++;
  1700. }
  1701. else
  1702. {
  1703. time_t CurrentTime;
  1704. //
  1705. // i is the time difference in seconds
  1706. // = currentTime - eventTime
  1707. //
  1708. time(&CurrentTime);
  1709. //
  1710. // Subtract and truncate
  1711. //
  1712. i = (DWORD)(CurrentTime - pCurrentEvent->TimeGenerated);
  1713. }
  1714. if(i >= dwHistoryContext)
  1715. {
  1716. //
  1717. // Have gone back N (records or seconds)
  1718. //
  1719. if(pNextEvent < (DWORD_PTR)Buffer + dwRead)
  1720. {
  1721. //
  1722. // Have some more records in this buffer, so
  1723. // set pStartEvent to the next one
  1724. //
  1725. pStartEvent = (EVENTLOGRECORD *)pNextEvent;
  1726. }
  1727. else
  1728. {
  1729. pStartEvent = NULL;
  1730. }
  1731. //
  1732. // Done, break out of while(pNextEvent... and
  1733. // while(!bDone)
  1734. //
  1735. bDone = TRUE;
  1736. break;
  1737. }
  1738. break;
  1739. }
  1740. case NS_EVENT_FROM_N:
  1741. case NS_EVENT_FROM_START:
  1742. {
  1743. //
  1744. // We are being asked to go to the the most recent
  1745. // occurance of a certain event.
  1746. //
  1747. if(_wcsicmp((LPCWSTR)((DWORD_PTR)pCurrentEvent + sizeof(*pCurrentEvent)),
  1748. pwszComponent) == 0)
  1749. {
  1750. if(pCurrentEvent->EventID is dwHistoryContext)
  1751. {
  1752. if(pNextEvent < (DWORD_PTR)Buffer + dwRead)
  1753. {
  1754. pStartEvent = (EVENTLOGRECORD *)pNextEvent;
  1755. }
  1756. else
  1757. {
  1758. pStartEvent = NULL;
  1759. }
  1760. //
  1761. // Done, break out of while(pCurrent...
  1762. // and while(!bDone)
  1763. //
  1764. bDone = TRUE;
  1765. break;
  1766. }
  1767. }
  1768. }
  1769. default:
  1770. {
  1771. ASSERT(FALSE);
  1772. }
  1773. }
  1774. }
  1775. }
  1776. if(pStartEvent)
  1777. {
  1778. //
  1779. // So we found a record at which to start.
  1780. // API wants a buffer even if we set the size to 0
  1781. //
  1782. bResult = ReadEventLogW(*phEventLog,
  1783. EVENTLOG_SEEK_READ | EVENTLOG_FORWARDS_READ,
  1784. pStartEvent->RecordNumber,
  1785. (PVOID)Buffer,
  1786. 0,
  1787. &dwRead,
  1788. &dwNeed);
  1789. if(dwNeed < sizeof(Buffer))
  1790. {
  1791. ReadEventLogW(*phEventLog,
  1792. EVENTLOG_SEEK_READ | EVENTLOG_FORWARDS_READ,
  1793. pStartEvent->RecordNumber,
  1794. (PVOID)Buffer,
  1795. dwNeed,
  1796. &dwRead,
  1797. &dwNeed);
  1798. }
  1799. }
  1800. return NO_ERROR;
  1801. }
  1802. BOOL
  1803. IsOurRecord(
  1804. IN EVENTLOGRECORD *pRecord,
  1805. IN PEVENT_PRINT_INFO pEventInfo
  1806. )
  1807. {
  1808. BOOL bRet;
  1809. DWORD i;
  1810. if(_wcsicmp((LPCWSTR)((DWORD_PTR)pRecord + sizeof(*pRecord)),
  1811. pEventInfo->pwszComponent) isnot 0)
  1812. {
  1813. return FALSE;
  1814. }
  1815. bRet = TRUE;
  1816. //
  1817. // If ulEventCount is 0 means any event. So return TRUE
  1818. //
  1819. for(i = 0; i < pEventInfo->ulEventCount; i++)
  1820. {
  1821. bRet = (pRecord->EventID is pEventInfo->pdwEventIds[i]);
  1822. if(bRet)
  1823. {
  1824. break;
  1825. }
  1826. }
  1827. if(bRet)
  1828. {
  1829. if(pEventInfo->pfnEventFilter)
  1830. {
  1831. if(!(pEventInfo->pfnEventFilter)(pRecord,
  1832. pEventInfo->pwszLogName,
  1833. pEventInfo->pwszComponent,
  1834. pEventInfo->pwszSubComponent,
  1835. pEventInfo->pvFilterContext))
  1836. {
  1837. //
  1838. // It fell in our subcomp, but the caller doesnt
  1839. // consider it so
  1840. //
  1841. bRet = FALSE;
  1842. }
  1843. }
  1844. }
  1845. return bRet;
  1846. }