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.

1046 lines
22 KiB

  1. #include "precomp.h"
  2. const WCHAR c_szCurrentBuildNumber[] = L"CurrentBuildNumber";
  3. const WCHAR c_szWinVersionPath[] =
  4. L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
  5. const WCHAR c_szAssignFmt[] = L"%s = %s";
  6. const WCHAR c_szAssignFmt10[] = L"%s = %d";
  7. const WCHAR c_szAssignFmt16[] = L"%s = %x";
  8. WCHAR pszRemoteAccessParamStub[] =
  9. L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\";
  10. WCHAR pszEnableIn[] = L"EnableIn";
  11. WCHAR pszAllowNetworkAccess[] = L"AllowNetworkAccess";
  12. typedef struct _NAME_NODE
  13. {
  14. PWCHAR pszName;
  15. struct _NAME_NODE* pNext;
  16. } NAME_NODE;
  17. #if 0
  18. DWORD
  19. RutlDispTokenErrMsg(
  20. IN HANDLE hModule,
  21. IN DWORD dwMsgId,
  22. IN DWORD dwTagId,
  23. IN LPCWSTR pwszValue
  24. )
  25. /*++
  26. Routine Description:
  27. Displays error message with token arguments.
  28. Arguments:
  29. dwMsgId - Message to be printed
  30. dwTagId - The tag string id
  31. pwszValue - the value specified for the tag in the
  32. Return Value:
  33. NO_ERROR
  34. --*/
  35. {
  36. PWCHAR pwszTag;
  37. pwszTag = MakeString(hModule,
  38. dwTagId);
  39. DisplayMessage(hModule,
  40. dwMsgId,
  41. pwszValue,
  42. pwszTag);
  43. FreeString(pwszTag);
  44. return NO_ERROR;
  45. }
  46. #endif
  47. DWORD
  48. WINAPI
  49. RutlGetTagToken(
  50. IN HANDLE hModule,
  51. IN OUT LPWSTR *ppwcArguments,
  52. IN DWORD dwCurrentIndex,
  53. IN DWORD dwArgCount,
  54. IN PTAG_TYPE pttTagToken,
  55. IN DWORD dwNumTags,
  56. OUT PDWORD pdwOut
  57. )
  58. /*++
  59. Routine Description:
  60. Identifies each argument based on its tag. It assumes that each argument
  61. has a tag. It also removes tag= from each argument.
  62. Arguments:
  63. ppwcArguments - The argument array. Each argument has tag=value form
  64. dwCurrentIndex - ppwcArguments[dwCurrentIndex] is first arg.
  65. dwArgCount - ppwcArguments[dwArgCount - 1] is last arg.
  66. pttTagToken - Array of tag token ids that are allowed in the args
  67. dwNumTags - Size of pttTagToken
  68. pdwOut - Array identifying the type of each argument.
  69. Return Value:
  70. NO_ERROR, ERROR_INVALID_PARAMETER, ERROR_INVALID_OPTION_TAG
  71. --*/
  72. {
  73. DWORD i,j,len;
  74. PWCHAR pwcTag,pwcTagVal,pwszArg = NULL;
  75. BOOL bFound = FALSE;
  76. //
  77. // This function assumes that every argument has a tag
  78. // It goes ahead and removes the tag.
  79. //
  80. for (i = dwCurrentIndex; i < dwArgCount; i++)
  81. {
  82. len = wcslen(ppwcArguments[i]);
  83. if (len is 0)
  84. {
  85. //
  86. // something wrong with arg
  87. //
  88. pdwOut[i] = (DWORD) -1;
  89. continue;
  90. }
  91. pwszArg = RutlAlloc((len + 1) * sizeof(WCHAR), FALSE);
  92. if (pwszArg is NULL)
  93. {
  94. DisplayError(NULL,
  95. ERROR_NOT_ENOUGH_MEMORY);
  96. return ERROR_NOT_ENOUGH_MEMORY;
  97. }
  98. wcscpy(pwszArg, ppwcArguments[i]);
  99. pwcTag = wcstok(pwszArg, NETSH_ARG_DELIMITER);
  100. //
  101. // Got the first part
  102. // Now if next call returns NULL then there was no tag
  103. //
  104. pwcTagVal = wcstok((PWCHAR)NULL, NETSH_ARG_DELIMITER);
  105. if (pwcTagVal is NULL)
  106. {
  107. DisplayMessage(g_hModule,
  108. ERROR_NO_TAG,
  109. ppwcArguments[i]);
  110. RutlFree(pwszArg);
  111. return ERROR_INVALID_PARAMETER;
  112. }
  113. //
  114. // Got the tag. Now try to match it
  115. //
  116. bFound = FALSE;
  117. pdwOut[i - dwCurrentIndex] = (DWORD) -1;
  118. for ( j = 0; j < dwNumTags; j++)
  119. {
  120. if (MatchToken(pwcTag, pttTagToken[j].pwszTag))
  121. {
  122. //
  123. // Tag matched
  124. //
  125. bFound = TRUE;
  126. pdwOut[i - dwCurrentIndex] = j;
  127. break;
  128. }
  129. }
  130. if (bFound)
  131. {
  132. //
  133. // Remove tag from the argument
  134. //
  135. wcscpy(ppwcArguments[i], pwcTagVal);
  136. }
  137. else
  138. {
  139. DisplayError(NULL,
  140. ERROR_INVALID_OPTION_TAG,
  141. pwcTag);
  142. RutlFree(pwszArg);
  143. return ERROR_INVALID_OPTION_TAG;
  144. }
  145. RutlFree(pwszArg);
  146. }
  147. return NO_ERROR;
  148. }
  149. DWORD
  150. WINAPI
  151. RutlCreateDumpFile(
  152. IN LPCWSTR pwszName,
  153. OUT PHANDLE phFile
  154. )
  155. {
  156. HANDLE hFile;
  157. *phFile = NULL;
  158. // Create/open the file
  159. hFile = CreateFileW(pwszName,
  160. GENERIC_WRITE,
  161. FILE_SHARE_READ | FILE_SHARE_DELETE,
  162. NULL,
  163. OPEN_ALWAYS,
  164. FILE_ATTRIBUTE_NORMAL,
  165. NULL);
  166. if (hFile == INVALID_HANDLE_VALUE)
  167. return GetLastError();
  168. // Go to the end of the file
  169. SetFilePointer(hFile, 0, NULL, FILE_END);
  170. *phFile = hFile;
  171. return NO_ERROR;
  172. }
  173. VOID
  174. WINAPI
  175. RutlCloseDumpFile(
  176. HANDLE hFile
  177. )
  178. {
  179. CloseHandle(hFile);
  180. }
  181. //
  182. // Returns an allocated block of memory conditionally
  183. // zeroed of the given size.
  184. //
  185. PVOID
  186. WINAPI
  187. RutlAlloc(
  188. IN DWORD dwBytes,
  189. IN BOOL bZero
  190. )
  191. {
  192. PVOID pvRet;
  193. DWORD dwFlags = 0;
  194. if (bZero)
  195. {
  196. dwFlags |= HEAP_ZERO_MEMORY;
  197. }
  198. return HeapAlloc(GetProcessHeap(), dwFlags, dwBytes);
  199. }
  200. //
  201. // Conditionally free's a pointer if it is non-null
  202. //
  203. VOID
  204. WINAPI
  205. RutlFree(
  206. IN PVOID pvData
  207. )
  208. {
  209. if (pvData)
  210. {
  211. HeapFree(GetProcessHeap(), 0, pvData);
  212. }
  213. }
  214. //
  215. // Uses RutlAlloc to copy a string
  216. //
  217. PWCHAR
  218. WINAPI
  219. RutlStrDup(
  220. IN LPCWSTR pwszSrc
  221. )
  222. {
  223. PWCHAR pszRet = NULL;
  224. DWORD dwLen;
  225. if ((pwszSrc is NULL) or
  226. ((dwLen = wcslen(pwszSrc)) == 0)
  227. )
  228. {
  229. return NULL;
  230. }
  231. pszRet = (PWCHAR) RutlAlloc((dwLen + 1) * sizeof(WCHAR), FALSE);
  232. if (pszRet isnot NULL)
  233. {
  234. wcscpy(pszRet, pwszSrc);
  235. }
  236. return pszRet;
  237. }
  238. //
  239. // Uses RutlAlloc to copy a dword
  240. //
  241. LPDWORD
  242. WINAPI
  243. RutlDwordDup(
  244. IN DWORD dwSrc
  245. )
  246. {
  247. LPDWORD lpdwRet = NULL;
  248. lpdwRet = (LPDWORD) RutlAlloc(sizeof(DWORD), FALSE);
  249. if (lpdwRet isnot NULL)
  250. {
  251. *lpdwRet = dwSrc;
  252. }
  253. return lpdwRet;
  254. }
  255. //
  256. // Returns the build number of operating system
  257. //
  258. DWORD
  259. WINAPI
  260. RutlGetOsVersion(
  261. IN RASMON_SERVERINFO *pServerInfo
  262. )
  263. {
  264. DWORD dwErr, dwType = REG_SZ, dwLength;
  265. HKEY hkVersion = NULL;
  266. WCHAR pszBuildNumber[64];
  267. //
  268. // Initialize
  269. //
  270. pServerInfo->dwBuild = 0;
  271. do
  272. {
  273. //
  274. // Connect to the remote server
  275. //
  276. dwErr = RegConnectRegistry(
  277. pServerInfo->pszServer,
  278. HKEY_LOCAL_MACHINE,
  279. &pServerInfo->hkMachine);
  280. if ( dwErr != ERROR_SUCCESS )
  281. {
  282. break;
  283. }
  284. //
  285. // Open the windows version key
  286. //
  287. dwErr = RegOpenKeyEx(
  288. pServerInfo->hkMachine,
  289. c_szWinVersionPath,
  290. 0,
  291. KEY_QUERY_VALUE,
  292. &hkVersion
  293. );
  294. if ( dwErr != NO_ERROR )
  295. {
  296. break;
  297. }
  298. //
  299. // Read in the current version key
  300. //
  301. dwLength = sizeof(pszBuildNumber);
  302. dwErr = RegQueryValueEx (
  303. hkVersion,
  304. c_szCurrentBuildNumber,
  305. NULL,
  306. &dwType,
  307. (BYTE*)pszBuildNumber,
  308. &dwLength
  309. );
  310. if (dwErr != NO_ERROR)
  311. {
  312. break;
  313. }
  314. pServerInfo->dwBuild = (DWORD) wcstol(pszBuildNumber, NULL, 10);
  315. } while (FALSE);
  316. // Cleanup
  317. {
  318. if ( hkVersion )
  319. {
  320. RegCloseKey( hkVersion );
  321. }
  322. }
  323. return dwErr;
  324. }
  325. DWORD
  326. WINAPI
  327. RutlParseOptions(
  328. IN OUT LPWSTR *ppwcArguments,
  329. IN DWORD dwCurrentIndex,
  330. IN DWORD dwArgCount,
  331. IN DWORD dwNumArgs,
  332. IN TAG_TYPE* rgTags,
  333. IN DWORD dwTagCount,
  334. OUT LPDWORD* ppdwTagTypes)
  335. /*++
  336. Routine Description:
  337. Based on an array of tag types returns which options are
  338. included in the given command line.
  339. Arguments:
  340. ppwcArguments - Argument array
  341. dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
  342. dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
  343. Return Value:
  344. NO_ERROR
  345. --*/
  346. {
  347. LPDWORD pdwTagType;
  348. DWORD i, dwErr = NO_ERROR;
  349. // If there are no arguments, there's nothing to to
  350. //
  351. if ( dwNumArgs == 0 )
  352. {
  353. return NO_ERROR;
  354. }
  355. // Set up the table of present options
  356. pdwTagType = (LPDWORD) RutlAlloc(dwArgCount * sizeof(DWORD), TRUE);
  357. if(pdwTagType is NULL)
  358. {
  359. DisplayError(NULL, ERROR_NOT_ENOUGH_MEMORY);
  360. return ERROR_NOT_ENOUGH_MEMORY;
  361. }
  362. do {
  363. //
  364. // The argument has a tag. Assume all of them have tags
  365. //
  366. if(wcsstr(ppwcArguments[dwCurrentIndex], NETSH_ARG_DELIMITER))
  367. {
  368. dwErr = RutlGetTagToken(
  369. g_hModule,
  370. ppwcArguments,
  371. dwCurrentIndex,
  372. dwArgCount,
  373. rgTags,
  374. dwTagCount,
  375. pdwTagType);
  376. if(dwErr isnot NO_ERROR)
  377. {
  378. if(dwErr is ERROR_INVALID_OPTION_TAG)
  379. {
  380. dwErr = ERROR_INVALID_SYNTAX;
  381. break;
  382. }
  383. }
  384. }
  385. else
  386. {
  387. //
  388. // No tags - all args must be in order
  389. //
  390. for(i = 0; i < dwNumArgs; i++)
  391. {
  392. pdwTagType[i] = i;
  393. }
  394. }
  395. } while (FALSE);
  396. // Cleanup
  397. {
  398. if (dwErr is NO_ERROR)
  399. {
  400. *ppdwTagTypes = pdwTagType;
  401. }
  402. else
  403. {
  404. RutlFree(pdwTagType);
  405. }
  406. }
  407. return dwErr;
  408. }
  409. BOOL
  410. WINAPI
  411. RutlIsHelpToken(
  412. PWCHAR pwszToken
  413. )
  414. {
  415. if(MatchToken(pwszToken, CMD_RAS_HELP1))
  416. return TRUE;
  417. if(MatchToken(pwszToken, CMD_RAS_HELP2))
  418. return TRUE;
  419. return FALSE;
  420. }
  421. PWCHAR
  422. WINAPI
  423. RutlAssignmentFromTokens(
  424. IN HINSTANCE hModule,
  425. IN LPCWSTR pwszToken,
  426. IN LPCWSTR pszString)
  427. {
  428. PWCHAR pszRet = NULL;
  429. LPCWSTR pszCmd = NULL;
  430. DWORD dwErr = NO_ERROR, dwSize;
  431. do
  432. {
  433. pszCmd = pwszToken;
  434. // Compute the string lenghth needed
  435. //
  436. dwSize = wcslen(pszString) +
  437. wcslen(pszCmd) +
  438. wcslen(c_szAssignFmt) +
  439. 1;
  440. dwSize *= sizeof(WCHAR);
  441. // Allocate the return value
  442. pszRet = (PWCHAR) RutlAlloc(dwSize, FALSE);
  443. if (pszRet is NULL)
  444. {
  445. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  446. break;
  447. }
  448. // Copy in the command assignment
  449. wsprintfW(pszRet, c_szAssignFmt, pszCmd, pszString);
  450. } while (FALSE);
  451. // Cleanup
  452. {
  453. if (dwErr isnot NO_ERROR)
  454. {
  455. if (pszRet isnot NULL)
  456. {
  457. RutlFree(pszRet);
  458. }
  459. pszRet = NULL;
  460. }
  461. }
  462. return pszRet;
  463. }
  464. PWCHAR
  465. WINAPI
  466. RutlAssignmentFromTokenAndDword(
  467. IN HINSTANCE hModule,
  468. IN LPCWSTR pwszToken,
  469. IN DWORD dwDword,
  470. IN DWORD dwRadius)
  471. {
  472. PWCHAR pszRet = NULL;
  473. LPCWSTR pszCmd = NULL;
  474. DWORD dwErr = NO_ERROR, dwSize;
  475. do
  476. {
  477. pszCmd = pwszToken;
  478. // Compute the string length needed
  479. //
  480. dwSize = 64 +
  481. wcslen(pszCmd) +
  482. wcslen(c_szAssignFmt10) +
  483. 1;
  484. dwSize *= sizeof(WCHAR);
  485. // Allocate the return value
  486. pszRet = (PWCHAR) RutlAlloc(dwSize, FALSE);
  487. if (pszRet is NULL)
  488. {
  489. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  490. break;
  491. }
  492. // Copy in the command assignment
  493. if (dwRadius == 10)
  494. {
  495. wsprintfW(pszRet, c_szAssignFmt10, pszCmd, dwDword);
  496. }
  497. else
  498. {
  499. wsprintfW(pszRet, c_szAssignFmt16, pszCmd, dwDword);
  500. }
  501. } while (FALSE);
  502. // Cleanup
  503. {
  504. if (dwErr isnot NO_ERROR)
  505. {
  506. if (pszRet isnot NULL)
  507. {
  508. RutlFree(pszRet);
  509. }
  510. pszRet = NULL;
  511. }
  512. }
  513. return pszRet;
  514. }
  515. DWORD
  516. RutlRegReadDword(
  517. IN HKEY hKey,
  518. IN LPCWSTR pszValName,
  519. OUT LPDWORD lpdwValue)
  520. {
  521. DWORD dwSize = sizeof(DWORD), dwType = REG_DWORD, dwErr;
  522. dwErr = RegQueryValueExW(
  523. hKey,
  524. pszValName,
  525. NULL,
  526. &dwType,
  527. (LPBYTE)lpdwValue,
  528. &dwSize);
  529. if (dwErr == ERROR_FILE_NOT_FOUND)
  530. {
  531. dwErr = NO_ERROR;
  532. }
  533. return dwErr;
  534. }
  535. DWORD
  536. RutlRegReadString(
  537. IN HKEY hKey,
  538. IN LPCWSTR pszValName,
  539. OUT LPWSTR* ppszValue)
  540. {
  541. DWORD dwErr = NO_ERROR, dwSize = 0;
  542. *ppszValue = NULL;
  543. // Findout how big the buffer should be
  544. //
  545. dwErr = RegQueryValueExW(
  546. hKey,
  547. pszValName,
  548. NULL,
  549. NULL,
  550. NULL,
  551. &dwSize);
  552. if (dwErr == ERROR_FILE_NOT_FOUND)
  553. {
  554. return NO_ERROR;
  555. }
  556. if (dwErr != ERROR_SUCCESS)
  557. {
  558. return dwErr;
  559. }
  560. // Allocate the string
  561. //
  562. *ppszValue = (PWCHAR) RutlAlloc(dwSize, TRUE);
  563. if (*ppszValue == NULL)
  564. {
  565. return ERROR_NOT_ENOUGH_MEMORY;
  566. }
  567. // Read the value in and return
  568. //
  569. dwErr = RegQueryValueExW(
  570. hKey,
  571. pszValName,
  572. NULL,
  573. NULL,
  574. (LPBYTE)*ppszValue,
  575. &dwSize);
  576. return dwErr;
  577. }
  578. DWORD
  579. RutlRegWriteDword(
  580. IN HKEY hKey,
  581. IN LPCWSTR pszValName,
  582. IN DWORD dwValue)
  583. {
  584. return RegSetValueExW(
  585. hKey,
  586. pszValName,
  587. 0,
  588. REG_DWORD,
  589. (LPBYTE)&dwValue,
  590. sizeof(DWORD));
  591. }
  592. DWORD
  593. RutlRegWriteString(
  594. IN HKEY hKey,
  595. IN LPCWSTR pszValName,
  596. IN LPCWSTR pszValue)
  597. {
  598. return RegSetValueExW(
  599. hKey,
  600. pszValName,
  601. 0,
  602. REG_SZ,
  603. (LPBYTE)pszValue,
  604. (wcslen(pszValue) + 1) * sizeof(WCHAR));
  605. }
  606. //
  607. // Enumerates all of the subkeys of a given key
  608. //
  609. DWORD
  610. RutlRegEnumKeys(
  611. IN HKEY hkKey,
  612. IN RAS_REGKEY_ENUM_FUNC_CB pCallback,
  613. IN HANDLE hData)
  614. {
  615. DWORD dwErr = NO_ERROR, i, dwNameSize = 0, dwCurSize = 0;
  616. DWORD dwCount = 0;
  617. HKEY hkCurKey = NULL;
  618. PWCHAR pszName = NULL;
  619. NAME_NODE *pHead = NULL, *pTemp = NULL;
  620. do
  621. {
  622. // Find out how many sub keys there are
  623. //
  624. dwErr = RegQueryInfoKeyW(
  625. hkKey,
  626. NULL,
  627. NULL,
  628. NULL,
  629. &dwCount,
  630. &dwNameSize,
  631. NULL,
  632. NULL,
  633. NULL,
  634. NULL,
  635. NULL,
  636. NULL);
  637. if (dwErr != ERROR_SUCCESS)
  638. {
  639. return dwErr;
  640. }
  641. dwNameSize++;
  642. // Allocate the name buffer
  643. //
  644. pszName = (PWCHAR) RutlAlloc(dwNameSize * sizeof(WCHAR), FALSE);
  645. if (pszName == NULL)
  646. {
  647. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  648. break;
  649. }
  650. // Loop through the keys building the list
  651. //
  652. for (i = 0; i < dwCount; i++)
  653. {
  654. dwCurSize = dwNameSize;
  655. // Get the name of the current key
  656. //
  657. dwErr = RegEnumKeyExW(
  658. hkKey,
  659. i,
  660. pszName,
  661. &dwCurSize,
  662. 0,
  663. NULL,
  664. NULL,
  665. NULL);
  666. if (dwErr != ERROR_SUCCESS)
  667. {
  668. continue;
  669. }
  670. // Add the key to the list
  671. //
  672. pTemp = (NAME_NODE*) RutlAlloc(sizeof(NAME_NODE), TRUE);
  673. if (pTemp == NULL)
  674. {
  675. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  676. break;
  677. }
  678. pTemp->pszName = RutlStrDup(pszName);
  679. if (pTemp->pszName == NULL)
  680. {
  681. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  682. break;
  683. }
  684. pTemp->pNext = pHead;
  685. pHead = pTemp;
  686. }
  687. BREAK_ON_DWERR(dwErr);
  688. // Now loop through the list, calling the callback.
  689. // The reason the items are added to a list like this
  690. // is that this allows the callback to safely delete
  691. // the reg key without messing up the enumeration
  692. //
  693. pTemp = pHead;
  694. while (pTemp)
  695. {
  696. // Open the subkey
  697. //
  698. dwErr = RegOpenKeyExW(
  699. hkKey,
  700. pTemp->pszName,
  701. 0,
  702. KEY_ALL_ACCESS,
  703. &hkCurKey);
  704. if (dwErr != ERROR_SUCCESS)
  705. {
  706. continue;
  707. }
  708. // Call the callback
  709. //
  710. dwErr = pCallback(pTemp->pszName, hkCurKey, hData);
  711. RegCloseKey(hkCurKey);
  712. if (dwErr != NO_ERROR)
  713. {
  714. break;
  715. }
  716. pTemp = pTemp->pNext;
  717. }
  718. } while (FALSE);
  719. // Cleanup
  720. {
  721. RutlFree(pszName);
  722. while (pHead)
  723. {
  724. RutlFree(pHead->pszName);
  725. pTemp = pHead->pNext;
  726. RutlFree(pHead);
  727. pHead = pTemp;
  728. }
  729. }
  730. return dwErr;
  731. }
  732. //
  733. // Generic parse
  734. //
  735. DWORD
  736. RutlParse(
  737. IN OUT LPWSTR* ppwcArguments,
  738. IN DWORD dwCurrentIndex,
  739. IN DWORD dwArgCount,
  740. IN BOOL* pbDone,
  741. OUT RASMON_CMD_ARG* pRasArgs,
  742. IN DWORD dwRasArgCount)
  743. {
  744. DWORD i, dwNumArgs, dwErr, dwLevel = 0;
  745. LPDWORD pdwTagType = NULL;
  746. TAG_TYPE* pTags = NULL;
  747. RASMON_CMD_ARG* pArg = NULL;
  748. if (dwRasArgCount == 0)
  749. {
  750. return ERROR_INVALID_PARAMETER;
  751. }
  752. do {
  753. // Initialize
  754. dwNumArgs = dwArgCount - dwCurrentIndex;
  755. // Generate a list of the tags
  756. //
  757. pTags = (TAG_TYPE*)
  758. RutlAlloc(dwRasArgCount * sizeof(TAG_TYPE), TRUE);
  759. if (pTags == NULL)
  760. {
  761. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  762. break;
  763. }
  764. for (i = 0; i < dwRasArgCount; i++)
  765. {
  766. CopyMemory(&pTags[i], &pRasArgs[i].rgTag, sizeof(TAG_TYPE));
  767. }
  768. // Get the list of present options
  769. //
  770. dwErr = RutlParseOptions(
  771. ppwcArguments,
  772. dwCurrentIndex,
  773. dwArgCount,
  774. dwNumArgs,
  775. pTags,
  776. dwRasArgCount,
  777. &pdwTagType);
  778. if (dwErr isnot NO_ERROR)
  779. {
  780. break;
  781. }
  782. // Copy the tag info back
  783. //
  784. for (i = 0; i < dwRasArgCount; i++)
  785. {
  786. CopyMemory(&pRasArgs[i].rgTag, &pTags[i], sizeof(TAG_TYPE));
  787. }
  788. for(i = 0; i < dwNumArgs; i++)
  789. {
  790. // Validate the current argument
  791. //
  792. if (pdwTagType[i] >= dwRasArgCount)
  793. {
  794. i = dwNumArgs;
  795. dwErr = ERROR_INVALID_SYNTAX;
  796. break;
  797. }
  798. pArg = &pRasArgs[pdwTagType[i]];
  799. // Get the value of the argument
  800. //
  801. switch (pArg->dwType)
  802. {
  803. case RASMONTR_CMD_TYPE_STRING:
  804. pArg->Val.pszValue =
  805. RutlStrDup(ppwcArguments[i + dwCurrentIndex]);
  806. break;
  807. case RASMONTR_CMD_TYPE_DWORD:
  808. pArg->Val.dwValue =
  809. _wtol(ppwcArguments[i + dwCurrentIndex]);
  810. break;
  811. case RASMONTR_CMD_TYPE_ENUM:
  812. dwErr = MatchEnumTag(g_hModule,
  813. ppwcArguments[i + dwCurrentIndex],
  814. pArg->dwEnumCount,
  815. pArg->rgEnums,
  816. &(pArg->Val.dwValue));
  817. if(dwErr != NO_ERROR)
  818. {
  819. RutlDispTokenErrMsg(
  820. g_hModule,
  821. EMSG_BAD_OPTION_VALUE,
  822. pArg->rgTag.pwszTag,
  823. ppwcArguments[i + dwCurrentIndex]);
  824. i = dwNumArgs;
  825. dwErr = ERROR_INVALID_PARAMETER;
  826. }
  827. break;
  828. }
  829. if (dwErr != NO_ERROR)
  830. {
  831. break;
  832. }
  833. // Mark the argument as present if needed
  834. //
  835. if (pArg->rgTag.bPresent)
  836. {
  837. dwErr = ERROR_TAG_ALREADY_PRESENT;
  838. i = dwNumArgs;
  839. break;
  840. }
  841. pArg->rgTag.bPresent = TRUE;
  842. }
  843. if(dwErr isnot NO_ERROR)
  844. {
  845. break;
  846. }
  847. // Make sure that all of the required parameters have
  848. // been included.
  849. //
  850. for (i = 0; i < dwRasArgCount; i++)
  851. {
  852. if ((pRasArgs[i].rgTag.dwRequired & NS_REQ_PRESENT)
  853. && !pRasArgs[i].rgTag.bPresent)
  854. {
  855. DisplayMessage(g_hModule, EMSG_CANT_FIND_EOPT);
  856. dwErr = ERROR_INVALID_SYNTAX;
  857. break;
  858. }
  859. }
  860. if(dwErr isnot NO_ERROR)
  861. {
  862. break;
  863. }
  864. } while (FALSE);
  865. // Cleanup
  866. {
  867. if (pTags)
  868. {
  869. RutlFree(pTags);
  870. }
  871. if (pdwTagType)
  872. {
  873. RutlFree(pdwTagType);
  874. }
  875. }
  876. return dwErr;
  877. }