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.

1394 lines
31 KiB

  1. #include "precomp.h"
  2. CONST WCHAR pszRemoteAccessParamStub[] =
  3. L"SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Parameters\\";
  4. CONST WCHAR pszEnableIn[] = L"EnableIn";
  5. CONST WCHAR pszAllowNetworkAccess[] = L"AllowNetworkAccess";
  6. CONST WCHAR c_szCurrentBuildNumber[] = L"CurrentBuildNumber";
  7. CONST WCHAR c_szWinVersionPath[] =
  8. L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
  9. CONST WCHAR c_szAssignFmt[] = L"%s = %s";
  10. CONST WCHAR c_szAssignFmt10[] = L"%s = %d";
  11. CONST WCHAR c_szAssignFmt16[] = L"%s = %x";
  12. typedef struct _NAME_NODE
  13. {
  14. PWCHAR pszName;
  15. struct _NAME_NODE* pNext;
  16. } NAME_NODE;
  17. DWORD
  18. WINAPI
  19. RutlGetTagToken(
  20. IN HANDLE hModule,
  21. IN OUT LPWSTR *ppwcArguments,
  22. IN DWORD dwCurrentIndex,
  23. IN DWORD dwArgCount,
  24. IN PTAG_TYPE pttTagToken,
  25. IN DWORD dwNumTags,
  26. OUT PDWORD pdwOut
  27. )
  28. /*++
  29. Routine Description:
  30. Identifies each argument based on its tag. It assumes that each argument
  31. has a tag. It also removes tag= from each argument.
  32. Arguments:
  33. ppwcArguments - The argument array. Each argument has tag=value form
  34. dwCurrentIndex - ppwcArguments[dwCurrentIndex] is first arg.
  35. dwArgCount - ppwcArguments[dwArgCount - 1] is last arg.
  36. pttTagToken - Array of tag token ids that are allowed in the args
  37. dwNumTags - Size of pttTagToken
  38. pdwOut - Array identifying the type of each argument.
  39. Return Value:
  40. NO_ERROR, ERROR_INVALID_PARAMETER, ERROR_INVALID_OPTION_TAG
  41. --*/
  42. {
  43. DWORD i,j,len;
  44. PWCHAR pwcTag,pwcTagVal,pwszArg = NULL;
  45. BOOL bFound = FALSE;
  46. //
  47. // This function assumes that every argument has a tag
  48. // It goes ahead and removes the tag.
  49. //
  50. for (i = dwCurrentIndex; i < dwArgCount; i++)
  51. {
  52. len = wcslen(ppwcArguments[i]);
  53. if (len is 0)
  54. {
  55. //
  56. // something wrong with arg
  57. //
  58. pdwOut[i] = (DWORD) -1;
  59. continue;
  60. }
  61. pwszArg = RutlAlloc((len + 1) * sizeof(WCHAR), FALSE);
  62. if (pwszArg is NULL)
  63. {
  64. DisplayError(NULL,
  65. ERROR_NOT_ENOUGH_MEMORY);
  66. return ERROR_NOT_ENOUGH_MEMORY;
  67. }
  68. wcscpy(pwszArg, ppwcArguments[i]);
  69. pwcTag = wcstok(pwszArg, NETSH_ARG_DELIMITER);
  70. //
  71. // Got the first part
  72. // Now if next call returns NULL then there was no tag
  73. //
  74. pwcTagVal = wcstok((PWCHAR)NULL, NETSH_ARG_DELIMITER);
  75. if (pwcTagVal is NULL)
  76. {
  77. DisplayMessage(g_hModule,
  78. ERROR_NO_TAG,
  79. ppwcArguments[i]);
  80. RutlFree(pwszArg);
  81. return ERROR_INVALID_PARAMETER;
  82. }
  83. //
  84. // Got the tag. Now try to match it
  85. //
  86. bFound = FALSE;
  87. pdwOut[i - dwCurrentIndex] = (DWORD) -1;
  88. for ( j = 0; j < dwNumTags; j++)
  89. {
  90. if (MatchToken(pwcTag, pttTagToken[j].pwszTag))
  91. {
  92. //
  93. // Tag matched
  94. //
  95. bFound = TRUE;
  96. pdwOut[i - dwCurrentIndex] = j;
  97. break;
  98. }
  99. }
  100. if (bFound)
  101. {
  102. //
  103. // Remove tag from the argument
  104. //
  105. wcscpy(ppwcArguments[i], pwcTagVal);
  106. }
  107. else
  108. {
  109. DisplayError(NULL,
  110. ERROR_INVALID_OPTION_TAG,
  111. pwcTag);
  112. RutlFree(pwszArg);
  113. return ERROR_INVALID_OPTION_TAG;
  114. }
  115. RutlFree(pwszArg);
  116. }
  117. return NO_ERROR;
  118. }
  119. DWORD
  120. WINAPI
  121. RutlCreateDumpFile(
  122. IN LPCWSTR pwszName,
  123. OUT PHANDLE phFile
  124. )
  125. {
  126. HANDLE hFile;
  127. *phFile = NULL;
  128. // Create/open the file
  129. hFile = CreateFileW(pwszName,
  130. GENERIC_WRITE,
  131. FILE_SHARE_READ | FILE_SHARE_DELETE,
  132. NULL,
  133. OPEN_ALWAYS,
  134. FILE_ATTRIBUTE_NORMAL,
  135. NULL);
  136. if (hFile == INVALID_HANDLE_VALUE)
  137. return GetLastError();
  138. // Go to the end of the file
  139. SetFilePointer(hFile, 0, NULL, FILE_END);
  140. *phFile = hFile;
  141. return NO_ERROR;
  142. }
  143. VOID
  144. WINAPI
  145. RutlCloseDumpFile(
  146. HANDLE hFile
  147. )
  148. {
  149. CloseHandle(hFile);
  150. }
  151. //
  152. // Returns an allocated block of memory conditionally
  153. // zeroed of the given size.
  154. //
  155. PVOID
  156. WINAPI
  157. RutlAlloc(
  158. IN DWORD dwBytes,
  159. IN BOOL bZero
  160. )
  161. {
  162. PVOID pvRet;
  163. DWORD dwFlags = 0;
  164. if (bZero)
  165. {
  166. dwFlags |= HEAP_ZERO_MEMORY;
  167. }
  168. return HeapAlloc(GetProcessHeap(), dwFlags, dwBytes);
  169. }
  170. //
  171. // Conditionally free's a pointer if it is non-null
  172. //
  173. VOID
  174. WINAPI
  175. RutlFree(
  176. IN PVOID pvData
  177. )
  178. {
  179. if (pvData)
  180. {
  181. HeapFree(GetProcessHeap(), 0, pvData);
  182. }
  183. }
  184. //
  185. // Uses RutlAlloc to copy a string
  186. //
  187. PWCHAR
  188. WINAPI
  189. RutlStrDup(
  190. IN LPCWSTR pwszSrc
  191. )
  192. {
  193. PWCHAR pszRet = NULL;
  194. DWORD dwLen;
  195. if ((pwszSrc is NULL) or
  196. ((dwLen = wcslen(pwszSrc)) == 0)
  197. )
  198. {
  199. return NULL;
  200. }
  201. pszRet = (PWCHAR) RutlAlloc((dwLen + 1) * sizeof(WCHAR), FALSE);
  202. if (pszRet isnot NULL)
  203. {
  204. wcscpy(pszRet, pwszSrc);
  205. }
  206. return pszRet;
  207. }
  208. //
  209. // Uses RutlAlloc to copy a dword
  210. //
  211. LPDWORD
  212. WINAPI
  213. RutlDwordDup(
  214. IN DWORD dwSrc
  215. )
  216. {
  217. LPDWORD lpdwRet = NULL;
  218. lpdwRet = (LPDWORD) RutlAlloc(sizeof(DWORD), FALSE);
  219. if (lpdwRet isnot NULL)
  220. {
  221. *lpdwRet = dwSrc;
  222. }
  223. return lpdwRet;
  224. }
  225. //
  226. // Returns the build number of operating system
  227. //
  228. DWORD
  229. WINAPI
  230. RutlGetOsVersion(
  231. IN RASMON_SERVERINFO *pServerInfo
  232. )
  233. {
  234. DWORD dwErr, dwType = REG_SZ, dwLength;
  235. HKEY hkVersion = NULL;
  236. WCHAR pszBuildNumber[64];
  237. //
  238. // Initialize
  239. //
  240. pServerInfo->dwBuild = 0;
  241. do
  242. {
  243. //
  244. // Connect to the remote server
  245. //
  246. dwErr = RegConnectRegistry(
  247. pServerInfo->pszServer,
  248. HKEY_LOCAL_MACHINE,
  249. &pServerInfo->hkMachine);
  250. if ( dwErr != ERROR_SUCCESS )
  251. {
  252. break;
  253. }
  254. //
  255. // Open the windows version key
  256. //
  257. dwErr = RegOpenKeyEx(
  258. pServerInfo->hkMachine,
  259. c_szWinVersionPath,
  260. 0,
  261. KEY_QUERY_VALUE,
  262. &hkVersion
  263. );
  264. if ( dwErr != NO_ERROR )
  265. {
  266. break;
  267. }
  268. //
  269. // Read in the current version key
  270. //
  271. dwLength = sizeof(pszBuildNumber);
  272. dwErr = RegQueryValueEx (
  273. hkVersion,
  274. c_szCurrentBuildNumber,
  275. NULL,
  276. &dwType,
  277. (BYTE*)pszBuildNumber,
  278. &dwLength
  279. );
  280. if (dwErr != NO_ERROR)
  281. {
  282. break;
  283. }
  284. pServerInfo->dwBuild = (DWORD) wcstol(pszBuildNumber, NULL, 10);
  285. } while (FALSE);
  286. // Cleanup
  287. {
  288. if ( hkVersion )
  289. {
  290. RegCloseKey( hkVersion );
  291. }
  292. }
  293. return dwErr;
  294. }
  295. DWORD
  296. WINAPI
  297. RutlParseOptions(
  298. IN OUT LPWSTR *ppwcArguments,
  299. IN DWORD dwCurrentIndex,
  300. IN DWORD dwArgCount,
  301. IN DWORD dwNumArgs,
  302. IN TAG_TYPE* rgTags,
  303. IN DWORD dwTagCount,
  304. OUT LPDWORD* ppdwTagTypes)
  305. /*++
  306. Routine Description:
  307. Based on an array of tag types returns which options are
  308. included in the given command line.
  309. Arguments:
  310. ppwcArguments - Argument array
  311. dwCurrentIndex - ppwcArguments[dwCurrentIndex] is the first arg
  312. dwArgCount - ppwcArguments[dwArgCount - 1] is the last arg
  313. Return Value:
  314. NO_ERROR
  315. --*/
  316. {
  317. LPDWORD pdwTagType;
  318. DWORD i, dwErr = NO_ERROR;
  319. // If there are no arguments, there's nothing to to
  320. //
  321. if ( dwNumArgs == 0 )
  322. {
  323. return NO_ERROR;
  324. }
  325. // Set up the table of present options
  326. pdwTagType = (LPDWORD) RutlAlloc(dwArgCount * sizeof(DWORD), TRUE);
  327. if(pdwTagType is NULL)
  328. {
  329. DisplayError(NULL, ERROR_NOT_ENOUGH_MEMORY);
  330. return ERROR_NOT_ENOUGH_MEMORY;
  331. }
  332. do {
  333. //
  334. // The argument has a tag. Assume all of them have tags
  335. //
  336. if(wcsstr(ppwcArguments[dwCurrentIndex], NETSH_ARG_DELIMITER))
  337. {
  338. dwErr = RutlGetTagToken(
  339. g_hModule,
  340. ppwcArguments,
  341. dwCurrentIndex,
  342. dwArgCount,
  343. rgTags,
  344. dwTagCount,
  345. pdwTagType);
  346. if(dwErr isnot NO_ERROR)
  347. {
  348. if(dwErr is ERROR_INVALID_OPTION_TAG)
  349. {
  350. dwErr = ERROR_INVALID_SYNTAX;
  351. break;
  352. }
  353. }
  354. }
  355. else
  356. {
  357. //
  358. // No tags - all args must be in order
  359. //
  360. for(i = 0; i < dwNumArgs; i++)
  361. {
  362. pdwTagType[i] = i;
  363. }
  364. }
  365. } while (FALSE);
  366. // Cleanup
  367. {
  368. if (dwErr is NO_ERROR)
  369. {
  370. *ppdwTagTypes = pdwTagType;
  371. }
  372. else
  373. {
  374. RutlFree(pdwTagType);
  375. }
  376. }
  377. return dwErr;
  378. }
  379. BOOL
  380. WINAPI
  381. RutlIsHelpToken(
  382. PWCHAR pwszToken
  383. )
  384. {
  385. if(MatchToken(pwszToken, CMD_RAS_HELP1))
  386. return TRUE;
  387. if(MatchToken(pwszToken, CMD_RAS_HELP2))
  388. return TRUE;
  389. return FALSE;
  390. }
  391. PWCHAR
  392. WINAPI
  393. RutlAssignmentFromTokens(
  394. IN HINSTANCE hModule,
  395. IN LPCWSTR pwszToken,
  396. IN LPCWSTR pszString)
  397. {
  398. PWCHAR pszRet = NULL;
  399. LPCWSTR pszCmd = NULL;
  400. DWORD dwErr = NO_ERROR, dwSize;
  401. do
  402. {
  403. pszCmd = pwszToken;
  404. // Compute the string lenghth needed
  405. //
  406. dwSize = wcslen(pszString) +
  407. wcslen(pszCmd) +
  408. wcslen(c_szAssignFmt) +
  409. 1;
  410. dwSize *= sizeof(WCHAR);
  411. // Allocate the return value
  412. pszRet = (PWCHAR) RutlAlloc(dwSize, FALSE);
  413. if (pszRet is NULL)
  414. {
  415. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  416. break;
  417. }
  418. // Copy in the command assignment
  419. wsprintfW(pszRet, c_szAssignFmt, pszCmd, pszString);
  420. } while (FALSE);
  421. // Cleanup
  422. {
  423. if (dwErr isnot NO_ERROR)
  424. {
  425. if (pszRet isnot NULL)
  426. {
  427. RutlFree(pszRet);
  428. }
  429. pszRet = NULL;
  430. }
  431. }
  432. return pszRet;
  433. }
  434. PWCHAR
  435. WINAPI
  436. RutlAssignmentFromTokenAndDword(
  437. IN HINSTANCE hModule,
  438. IN LPCWSTR pwszToken,
  439. IN DWORD dwDword,
  440. IN DWORD dwRadius)
  441. {
  442. PWCHAR pszRet = NULL;
  443. LPCWSTR pszCmd = NULL;
  444. DWORD dwErr = NO_ERROR, dwSize;
  445. do
  446. {
  447. pszCmd = pwszToken;
  448. // Compute the string length needed
  449. //
  450. dwSize = 64 +
  451. wcslen(pszCmd) +
  452. wcslen(c_szAssignFmt10) +
  453. 1;
  454. dwSize *= sizeof(WCHAR);
  455. // Allocate the return value
  456. pszRet = (PWCHAR) RutlAlloc(dwSize, FALSE);
  457. if (pszRet is NULL)
  458. {
  459. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  460. break;
  461. }
  462. // Copy in the command assignment
  463. if (dwRadius == 10)
  464. {
  465. wsprintfW(pszRet, c_szAssignFmt10, pszCmd, dwDword);
  466. }
  467. else
  468. {
  469. wsprintfW(pszRet, c_szAssignFmt16, pszCmd, dwDword);
  470. }
  471. } while (FALSE);
  472. // Cleanup
  473. {
  474. if (dwErr isnot NO_ERROR)
  475. {
  476. if (pszRet isnot NULL)
  477. {
  478. RutlFree(pszRet);
  479. }
  480. pszRet = NULL;
  481. }
  482. }
  483. return pszRet;
  484. }
  485. DWORD
  486. RutlRegReadDword(
  487. IN HKEY hKey,
  488. IN LPCWSTR pszValName,
  489. OUT LPDWORD lpdwValue)
  490. {
  491. DWORD dwSize = sizeof(DWORD), dwType = REG_DWORD, dwErr;
  492. dwErr = RegQueryValueExW(
  493. hKey,
  494. pszValName,
  495. NULL,
  496. &dwType,
  497. (LPBYTE)lpdwValue,
  498. &dwSize);
  499. if (dwErr == ERROR_FILE_NOT_FOUND)
  500. {
  501. dwErr = NO_ERROR;
  502. }
  503. return dwErr;
  504. }
  505. DWORD
  506. RutlRegReadString(
  507. IN HKEY hKey,
  508. IN LPCWSTR pszValName,
  509. OUT LPWSTR* ppszValue)
  510. {
  511. DWORD dwErr = NO_ERROR, dwSize = 0;
  512. *ppszValue = NULL;
  513. // Findout how big the buffer should be
  514. //
  515. dwErr = RegQueryValueExW(
  516. hKey,
  517. pszValName,
  518. NULL,
  519. NULL,
  520. NULL,
  521. &dwSize);
  522. if (dwErr == ERROR_FILE_NOT_FOUND)
  523. {
  524. return NO_ERROR;
  525. }
  526. if (dwErr != ERROR_SUCCESS)
  527. {
  528. return dwErr;
  529. }
  530. // Allocate the string
  531. //
  532. *ppszValue = (PWCHAR) RutlAlloc(dwSize, TRUE);
  533. if (*ppszValue == NULL)
  534. {
  535. return ERROR_NOT_ENOUGH_MEMORY;
  536. }
  537. // Read the value in and return
  538. //
  539. dwErr = RegQueryValueExW(
  540. hKey,
  541. pszValName,
  542. NULL,
  543. NULL,
  544. (LPBYTE)*ppszValue,
  545. &dwSize);
  546. return dwErr;
  547. }
  548. DWORD
  549. RutlRegWriteDword(
  550. IN HKEY hKey,
  551. IN LPCWSTR pszValName,
  552. IN DWORD dwValue)
  553. {
  554. return RegSetValueExW(
  555. hKey,
  556. pszValName,
  557. 0,
  558. REG_DWORD,
  559. (LPBYTE)&dwValue,
  560. sizeof(DWORD));
  561. }
  562. DWORD
  563. RutlRegWriteString(
  564. IN HKEY hKey,
  565. IN LPCWSTR pszValName,
  566. IN LPCWSTR pszValue)
  567. {
  568. return RegSetValueExW(
  569. hKey,
  570. pszValName,
  571. 0,
  572. REG_SZ,
  573. (LPBYTE)pszValue,
  574. (wcslen(pszValue) + 1) * sizeof(WCHAR));
  575. }
  576. //
  577. // Enumerates all of the subkeys of a given key
  578. //
  579. DWORD
  580. RutlRegEnumKeys(
  581. IN HKEY hkKey,
  582. IN RAS_REGKEY_ENUM_FUNC_CB pCallback,
  583. IN HANDLE hData)
  584. {
  585. DWORD dwErr = NO_ERROR, i, dwNameSize = 0, dwCurSize = 0;
  586. DWORD dwCount = 0;
  587. HKEY hkCurKey = NULL;
  588. PWCHAR pszName = NULL;
  589. NAME_NODE *pHead = NULL, *pTemp = NULL;
  590. do
  591. {
  592. // Find out how many sub keys there are
  593. //
  594. dwErr = RegQueryInfoKeyW(
  595. hkKey,
  596. NULL,
  597. NULL,
  598. NULL,
  599. &dwCount,
  600. &dwNameSize,
  601. NULL,
  602. NULL,
  603. NULL,
  604. NULL,
  605. NULL,
  606. NULL);
  607. if (dwErr != ERROR_SUCCESS)
  608. {
  609. return dwErr;
  610. }
  611. dwNameSize++;
  612. // Allocate the name buffer
  613. //
  614. pszName = (PWCHAR) RutlAlloc(dwNameSize * sizeof(WCHAR), FALSE);
  615. if (pszName == NULL)
  616. {
  617. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  618. break;
  619. }
  620. // Loop through the keys building the list
  621. //
  622. for (i = 0; i < dwCount; i++)
  623. {
  624. dwCurSize = dwNameSize;
  625. // Get the name of the current key
  626. //
  627. dwErr = RegEnumKeyExW(
  628. hkKey,
  629. i,
  630. pszName,
  631. &dwCurSize,
  632. 0,
  633. NULL,
  634. NULL,
  635. NULL);
  636. if (dwErr != ERROR_SUCCESS)
  637. {
  638. continue;
  639. }
  640. // Add the key to the list
  641. //
  642. pTemp = (NAME_NODE*) RutlAlloc(sizeof(NAME_NODE), TRUE);
  643. if (pTemp == NULL)
  644. {
  645. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  646. break;
  647. }
  648. pTemp->pszName = RutlStrDup(pszName);
  649. if (pTemp->pszName == NULL)
  650. {
  651. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  652. break;
  653. }
  654. pTemp->pNext = pHead;
  655. pHead = pTemp;
  656. }
  657. BREAK_ON_DWERR(dwErr);
  658. // Now loop through the list, calling the callback.
  659. // The reason the items are added to a list like this
  660. // is that this allows the callback to safely delete
  661. // the reg key without messing up the enumeration
  662. //
  663. pTemp = pHead;
  664. while (pTemp)
  665. {
  666. // Open the subkey
  667. //
  668. dwErr = RegOpenKeyExW(
  669. hkKey,
  670. pTemp->pszName,
  671. 0,
  672. KEY_ALL_ACCESS,
  673. &hkCurKey);
  674. if (dwErr != ERROR_SUCCESS)
  675. {
  676. continue;
  677. }
  678. // Call the callback
  679. //
  680. dwErr = pCallback(pTemp->pszName, hkCurKey, hData);
  681. RegCloseKey(hkCurKey);
  682. if (dwErr != NO_ERROR)
  683. {
  684. break;
  685. }
  686. pTemp = pTemp->pNext;
  687. }
  688. } while (FALSE);
  689. // Cleanup
  690. {
  691. RutlFree(pszName);
  692. while (pHead)
  693. {
  694. RutlFree(pHead->pszName);
  695. pTemp = pHead->pNext;
  696. RutlFree(pHead);
  697. pHead = pTemp;
  698. }
  699. }
  700. return dwErr;
  701. }
  702. //
  703. // Generic parse
  704. //
  705. DWORD
  706. RutlParse(
  707. IN OUT LPWSTR* ppwcArguments,
  708. IN DWORD dwCurrentIndex,
  709. IN DWORD dwArgCount,
  710. IN BOOL* pbDone,
  711. OUT RASMON_CMD_ARG* pRasArgs,
  712. IN DWORD dwRasArgCount)
  713. {
  714. DWORD i, dwNumArgs, dwErr, dwLevel = 0;
  715. LPDWORD pdwTagType = NULL;
  716. TAG_TYPE* pTags = NULL;
  717. RASMON_CMD_ARG* pArg = NULL;
  718. if (dwRasArgCount == 0)
  719. {
  720. return ERROR_INVALID_PARAMETER;
  721. }
  722. do {
  723. // Initialize
  724. dwNumArgs = dwArgCount - dwCurrentIndex;
  725. // Generate a list of the tags
  726. //
  727. pTags = (TAG_TYPE*)
  728. RutlAlloc(dwRasArgCount * sizeof(TAG_TYPE), TRUE);
  729. if (pTags == NULL)
  730. {
  731. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  732. break;
  733. }
  734. for (i = 0; i < dwRasArgCount; i++)
  735. {
  736. CopyMemory(&pTags[i], &pRasArgs[i].rgTag, sizeof(TAG_TYPE));
  737. }
  738. // Get the list of present options
  739. //
  740. dwErr = RutlParseOptions(
  741. ppwcArguments,
  742. dwCurrentIndex,
  743. dwArgCount,
  744. dwNumArgs,
  745. pTags,
  746. dwRasArgCount,
  747. &pdwTagType);
  748. if (dwErr isnot NO_ERROR)
  749. {
  750. break;
  751. }
  752. // Copy the tag info back
  753. //
  754. for (i = 0; i < dwRasArgCount; i++)
  755. {
  756. CopyMemory(&pRasArgs[i].rgTag, &pTags[i], sizeof(TAG_TYPE));
  757. }
  758. for(i = 0; i < dwNumArgs; i++)
  759. {
  760. // Validate the current argument
  761. //
  762. if (pdwTagType[i] >= dwRasArgCount)
  763. {
  764. i = dwNumArgs;
  765. dwErr = ERROR_INVALID_SYNTAX;
  766. break;
  767. }
  768. pArg = &pRasArgs[pdwTagType[i]];
  769. // Get the value of the argument
  770. //
  771. switch (pArg->dwType)
  772. {
  773. case RASMONTR_CMD_TYPE_STRING:
  774. pArg->Val.pszValue =
  775. RutlStrDup(ppwcArguments[i + dwCurrentIndex]);
  776. break;
  777. case RASMONTR_CMD_TYPE_DWORD:
  778. pArg->Val.dwValue =
  779. _wtol(ppwcArguments[i + dwCurrentIndex]);
  780. break;
  781. case RASMONTR_CMD_TYPE_ENUM:
  782. dwErr = MatchEnumTag(g_hModule,
  783. ppwcArguments[i + dwCurrentIndex],
  784. pArg->dwEnumCount,
  785. pArg->rgEnums,
  786. &(pArg->Val.dwValue));
  787. if(dwErr != NO_ERROR)
  788. {
  789. RutlDispTokenErrMsg(
  790. g_hModule,
  791. EMSG_BAD_OPTION_VALUE,
  792. pArg->rgTag.pwszTag,
  793. ppwcArguments[i + dwCurrentIndex]);
  794. i = dwNumArgs;
  795. dwErr = ERROR_INVALID_PARAMETER;
  796. }
  797. break;
  798. }
  799. if (dwErr != NO_ERROR)
  800. {
  801. break;
  802. }
  803. // Mark the argument as present if needed
  804. //
  805. if (pArg->rgTag.bPresent)
  806. {
  807. dwErr = ERROR_TAG_ALREADY_PRESENT;
  808. i = dwNumArgs;
  809. break;
  810. }
  811. pArg->rgTag.bPresent = TRUE;
  812. }
  813. if(dwErr isnot NO_ERROR)
  814. {
  815. break;
  816. }
  817. // Make sure that all of the required parameters have
  818. // been included.
  819. //
  820. for (i = 0; i < dwRasArgCount; i++)
  821. {
  822. if ((pRasArgs[i].rgTag.dwRequired & NS_REQ_PRESENT)
  823. && !pRasArgs[i].rgTag.bPresent)
  824. {
  825. DisplayMessage(g_hModule, EMSG_CANT_FIND_EOPT);
  826. dwErr = ERROR_INVALID_SYNTAX;
  827. break;
  828. }
  829. }
  830. if(dwErr isnot NO_ERROR)
  831. {
  832. break;
  833. }
  834. } while (FALSE);
  835. // Cleanup
  836. {
  837. if (pTags)
  838. {
  839. RutlFree(pTags);
  840. }
  841. if (pdwTagType)
  842. {
  843. RutlFree(pdwTagType);
  844. }
  845. }
  846. return dwErr;
  847. }
  848. DWORD
  849. RutlEnumFiles(
  850. IN LPCWSTR pwszSrchPath,
  851. IN LPCWSTR pwszSrchStr,
  852. IN RAS_FILE_ENUM_FUNC_CB pCallback,
  853. IN HANDLE hData)
  854. {
  855. DWORD dwErr = NO_ERROR, dwSize = 0;
  856. PWCHAR pwszFileSearch = NULL;
  857. HANDLE hSearch = NULL;
  858. WIN32_FIND_DATA FindFileData;
  859. do
  860. {
  861. if (!pwszSrchPath || !pwszSrchStr || !pCallback)
  862. {
  863. dwErr = ERROR_INVALID_PARAMETER;
  864. break;
  865. }
  866. dwSize = lstrlen(pwszSrchPath) + lstrlen(pwszSrchStr) + 1;
  867. if (dwSize < 2)
  868. {
  869. dwErr = ERROR_INVALID_PARAMETER;
  870. break;
  871. }
  872. pwszFileSearch = RutlAlloc(dwSize * sizeof(WCHAR), TRUE);
  873. if (!pwszFileSearch)
  874. {
  875. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  876. break;
  877. }
  878. lstrcpy(pwszFileSearch, pwszSrchPath);
  879. lstrcat(pwszFileSearch, pwszSrchStr);
  880. hSearch = FindFirstFile(pwszFileSearch, &FindFileData);
  881. if (INVALID_HANDLE_VALUE == hSearch)
  882. {
  883. dwErr = GetLastError();
  884. break;
  885. }
  886. for (;;)
  887. {
  888. PWCHAR pwszFileName = NULL;
  889. dwSize = lstrlen(pwszSrchPath) +
  890. lstrlen(FindFileData.cFileName) + 1;
  891. if (dwSize < 2)
  892. {
  893. dwErr = ERROR_INVALID_PARAMETER;
  894. break;
  895. }
  896. pwszFileName = RutlAlloc(dwSize * sizeof(WCHAR), TRUE);
  897. if (!pwszFileName)
  898. {
  899. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  900. break;
  901. }
  902. lstrcpy(pwszFileName, pwszSrchPath);
  903. lstrcat(pwszFileName, FindFileData.cFileName);
  904. //
  905. // Call the callback
  906. //
  907. dwErr = pCallback(pwszFileName, FindFileData.cFileName, hData);
  908. //
  909. // Clean up
  910. //
  911. RutlFree(pwszFileName);
  912. if (dwErr)
  913. {
  914. break;
  915. }
  916. if (!FindNextFile(hSearch, &FindFileData))
  917. {
  918. break;
  919. }
  920. }
  921. FindClose(hSearch);
  922. } while (FALSE);
  923. //
  924. // Clean up
  925. //
  926. RutlFree(pwszFileSearch);
  927. return dwErr;
  928. }
  929. DWORD
  930. RutlEnumEventLogs(
  931. IN LPCWSTR pwszSourceName,
  932. IN LPCWSTR pwszMsdDll,
  933. IN DWORD dwMaxEntries,
  934. IN RAS_EVENT_ENUM_FUNC_CB pCallback,
  935. IN HANDLE hData)
  936. {
  937. DWORD dwErr = NO_ERROR, dwSize, dwRead, dwNeeded, dwCount = 0;
  938. LPBYTE pBuffer = NULL;
  939. HANDLE hLog = NULL;
  940. HMODULE hMod = NULL;
  941. PEVENTLOGRECORD pevlr = NULL;
  942. do
  943. {
  944. hLog = OpenEventLog(NULL, pwszSourceName);
  945. if (!hLog)
  946. {
  947. dwErr = GetLastError();
  948. break;
  949. }
  950. dwSize = 1024 * sizeof(EVENTLOGRECORD);
  951. pBuffer = RutlAlloc(dwSize, FALSE);
  952. if (!pBuffer)
  953. {
  954. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  955. break;
  956. }
  957. hMod = LoadLibrary(pwszMsdDll);
  958. if (!hMod)
  959. {
  960. dwErr = GetLastError();
  961. break;
  962. }
  963. pevlr = (PEVENTLOGRECORD)pBuffer;
  964. //
  965. // Opening the event log positions the file pointer for this
  966. // handle at the beginning of the log. Read the records
  967. // sequentially until there are no more.
  968. //
  969. for (;;)
  970. {
  971. if (!ReadEventLog(
  972. hLog,
  973. EVENTLOG_BACKWARDS_READ | EVENTLOG_SEQUENTIAL_READ,
  974. 0,
  975. pevlr,
  976. dwSize,
  977. &dwRead,
  978. &dwNeeded))
  979. {
  980. dwErr = GetLastError();
  981. break;
  982. }
  983. while ((dwRead > 0) && (dwCount < dwMaxEntries))
  984. {
  985. //
  986. // Call the callback
  987. //
  988. if (pCallback(pevlr, hMod, hData))
  989. {
  990. dwCount++;
  991. }
  992. dwRead -= pevlr->Length;
  993. pevlr = (PEVENTLOGRECORD) ((LPBYTE) pevlr + pevlr->Length);
  994. }
  995. if (dwCount >= dwMaxEntries)
  996. {
  997. break;
  998. }
  999. pevlr = (PEVENTLOGRECORD)pBuffer;
  1000. }
  1001. } while (FALSE);
  1002. //
  1003. // Clean up
  1004. //
  1005. if (hMod)
  1006. {
  1007. FreeLibrary(hMod);
  1008. }
  1009. RutlFree(pBuffer);
  1010. if (hLog)
  1011. {
  1012. CloseEventLog(hLog);
  1013. }
  1014. return dwErr;
  1015. }
  1016. INT
  1017. RutlStrNCmp(
  1018. IN LPCWSTR psz1,
  1019. IN LPCWSTR psz2,
  1020. IN UINT nlLen)
  1021. {
  1022. UINT i;
  1023. for (i = 0; i < nlLen; ++i)
  1024. {
  1025. if (*psz1 == *psz2)
  1026. {
  1027. if (*psz1 == g_pwszNull)
  1028. return 0;
  1029. }
  1030. else if (*psz1 < *psz2)
  1031. return -1;
  1032. else
  1033. return 1;
  1034. ++psz1;
  1035. ++psz2;
  1036. }
  1037. return 0;
  1038. }
  1039. //
  1040. // Returns heap block containing a copy of 0-terminated string 'psz' or
  1041. // NULL on error or is 'psz' is NULL. The output string is converted to
  1042. // MB ANSI. It is caller's responsibility to 'Free' the returned string.
  1043. //
  1044. PCHAR
  1045. RutlStrDupAFromWInternal(
  1046. LPCTSTR psz,
  1047. IN DWORD dwCp)
  1048. {
  1049. CHAR* pszNew = NULL;
  1050. if (psz)
  1051. {
  1052. DWORD cb;
  1053. cb = WideCharToMultiByte(dwCp, 0, psz, -1, NULL, 0, NULL, NULL);
  1054. ASSERT(cb);
  1055. pszNew = (CHAR* )RutlAlloc(cb + 1, FALSE);
  1056. if (!pszNew)
  1057. {
  1058. return NULL;
  1059. }
  1060. cb = WideCharToMultiByte(dwCp, 0, psz, -1, pszNew, cb, NULL, NULL);
  1061. if (cb == 0)
  1062. {
  1063. RutlFree(pszNew);
  1064. return NULL;
  1065. }
  1066. }
  1067. return pszNew;
  1068. }
  1069. PCHAR
  1070. RutlStrDupAFromWAnsi(
  1071. LPCTSTR psz)
  1072. {
  1073. return RutlStrDupAFromWInternal(psz, CP_ACP);
  1074. }
  1075. PCHAR
  1076. RutlStrDupAFromW(
  1077. LPCTSTR psz)
  1078. {
  1079. return RutlStrDupAFromWInternal(psz, CP_UTF8);
  1080. }
  1081. BOOL
  1082. RutlSecondsSince1970ToSystemTime(
  1083. IN DWORD dwSecondsSince1970,
  1084. OUT SYSTEMTIME* pSystemTime)
  1085. {
  1086. LARGE_INTEGER liTime;
  1087. FILETIME ftUTC;
  1088. FILETIME ftLocal;
  1089. //
  1090. // Seconds since the start of 1970 -> 64 bit Time value
  1091. //
  1092. RtlSecondsSince1970ToTime(dwSecondsSince1970, &liTime);
  1093. //
  1094. // The time is in UTC. Convert it to local file time
  1095. //
  1096. ftUTC.dwLowDateTime = liTime.LowPart;
  1097. ftUTC.dwHighDateTime = liTime.HighPart;
  1098. if (FileTimeToLocalFileTime(&ftUTC, &ftLocal) == FALSE)
  1099. {
  1100. return FALSE;
  1101. }
  1102. //
  1103. // Convert local file time to system time.
  1104. //
  1105. if (FileTimeToSystemTime(&ftLocal, pSystemTime) == FALSE)
  1106. {
  1107. return FALSE;
  1108. }
  1109. return TRUE;
  1110. }
  1111. LPWSTR
  1112. RutlGetTimeStr(
  1113. ULONG ulTime,
  1114. LPWSTR wszBuf,
  1115. ULONG cchBuf)
  1116. {
  1117. ULONG cch;
  1118. SYSTEMTIME stGenerated;
  1119. if (RutlSecondsSince1970ToSystemTime(ulTime, &stGenerated))
  1120. {
  1121. cch = GetTimeFormat(LOCALE_USER_DEFAULT,
  1122. 0,
  1123. &stGenerated,
  1124. NULL,
  1125. wszBuf,
  1126. cchBuf);
  1127. if (!cch)
  1128. {
  1129. wszBuf[0] = g_pwszNull;
  1130. }
  1131. }
  1132. return wszBuf;
  1133. }
  1134. LPWSTR
  1135. RutlGetDateStr(
  1136. ULONG ulDate,
  1137. LPWSTR wszBuf,
  1138. ULONG cchBuf)
  1139. {
  1140. ULONG cch;
  1141. SYSTEMTIME stGenerated;
  1142. wszBuf[0] = g_pwszNull;
  1143. do
  1144. {
  1145. if (!RutlSecondsSince1970ToSystemTime(ulDate, &stGenerated))
  1146. {
  1147. break;
  1148. }
  1149. cch = GetDateFormat(LOCALE_USER_DEFAULT,
  1150. DATE_SHORTDATE,
  1151. &stGenerated,
  1152. NULL,
  1153. wszBuf,
  1154. cchBuf);
  1155. if (!cch)
  1156. {
  1157. wszBuf[0] = g_pwszNull;
  1158. }
  1159. } while (FALSE);
  1160. return wszBuf;
  1161. }
  1162. VOID
  1163. RutlConvertGuidToString(
  1164. IN CONST GUID *pGuid,
  1165. OUT LPWSTR pwszBuffer)
  1166. {
  1167. wsprintf(pwszBuffer, L"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
  1168. pGuid->Data1, pGuid->Data2, pGuid->Data3,
  1169. pGuid->Data4[0], pGuid->Data4[1],
  1170. pGuid->Data4[2], pGuid->Data4[3],
  1171. pGuid->Data4[4], pGuid->Data4[5],
  1172. pGuid->Data4[6], pGuid->Data4[7]);
  1173. }
  1174. DWORD
  1175. RutlConvertStringToGuid(
  1176. IN LPCWSTR pwszGuid,
  1177. IN USHORT usStringLen,
  1178. OUT GUID *pGuid)
  1179. {
  1180. UNICODE_STRING Temp;
  1181. Temp.Length = Temp.MaximumLength = usStringLen;
  1182. Temp.Buffer = (LPWSTR)pwszGuid;
  1183. if(RtlGUIDFromString(&Temp, pGuid) isnot STATUS_SUCCESS)
  1184. {
  1185. return ERROR_INVALID_PARAMETER;
  1186. }
  1187. return NO_ERROR;
  1188. }