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.

824 lines
19 KiB

  1. /*
  2. File uitls.c
  3. A set of utilities useful for upgrading mpr v1 to NT 5.0.
  4. Paul Mayfield, 9/11/97
  5. */
  6. #include "upgrade.h"
  7. #include <rtcfg.h>
  8. #include <mprapip.h>
  9. CONST WCHAR c_szSystemCCSServices[] = L"System\\CurrentControlSet\\Services";
  10. static const WCHAR c_szConfigurationFlags[] = L"ConfigurationFlags";
  11. CONST WCHAR c_szRouter[] = L"RemoteAccess";
  12. //
  13. // Initializes a dword table with given initial count
  14. // and maximum string size;
  15. //
  16. DWORD dwtInitialize(
  17. OUT dwt *This,
  18. IN DWORD dwCount,
  19. IN DWORD dwMaxSize)
  20. {
  21. DWORD i;
  22. if (!This)
  23. return ERROR_INVALID_PARAMETER;
  24. // Initialize the structure
  25. ZeroMemory(This, sizeof(dwt));
  26. This->dwCount = 0;
  27. This->dwSize = dwCount;
  28. // Allocate the table
  29. This->pValues = (dwValueNode *) UtlAlloc(
  30. dwCount * sizeof(dwValueNode));
  31. if (!This->pValues)
  32. return ERROR_NOT_ENOUGH_MEMORY;
  33. // Allocate all of the name strings
  34. for (i = 0; i < (DWORD)This->dwSize; i++) {
  35. This->pValues[i].Name = (PWCHAR) UtlAlloc(
  36. dwMaxSize * sizeof(WCHAR));
  37. if (!This->pValues[i].Name)
  38. {
  39. return ERROR_NOT_ENOUGH_MEMORY;
  40. }
  41. }
  42. return NO_ERROR;
  43. }
  44. //
  45. // Free's resources held by the given dword table.
  46. //
  47. DWORD dwtCleanup(
  48. IN dwt * This)
  49. {
  50. DWORD i;
  51. if (!This)
  52. {
  53. return NO_ERROR;
  54. }
  55. for (i = 0; i < (DWORD)This->dwSize; i++)
  56. {
  57. if (This->pValues[i].Name)
  58. {
  59. UtlFree(This->pValues[i].Name);
  60. }
  61. }
  62. if (This->pValues)
  63. {
  64. UtlFree(This->pValues);
  65. }
  66. return NO_ERROR;
  67. }
  68. //
  69. // Retrieves the given value from the table
  70. //
  71. DWORD dwtGetValue(
  72. IN dwt * This,
  73. IN PWCHAR ValName,
  74. OUT LPDWORD pValue)
  75. {
  76. DWORD i;
  77. if (!ValName || !pValue)
  78. {
  79. return ERROR_INVALID_PARAMETER;
  80. }
  81. for (i = 0; i < This->dwCount; i++)
  82. {
  83. if (wcscmp(ValName,This->pValues[i].Name) == 0)
  84. {
  85. *pValue = This->pValues[i].Value;
  86. return NO_ERROR;
  87. }
  88. }
  89. return ERROR_NOT_FOUND;
  90. }
  91. //
  92. // Loads all of the dword values of a given registry
  93. // key into a dword table.
  94. //
  95. DWORD dwtLoadRegistyTable(
  96. OUT dwt *This,
  97. IN HKEY hkParams)
  98. {
  99. DWORD dwErr, dwMaxSize, dwSize, dwCount, i;
  100. DWORD dwDataSize = sizeof(DWORD), dwType = REG_DWORD;
  101. if (!This)
  102. return ERROR_INVALID_PARAMETER;
  103. // Initialize the structure
  104. ZeroMemory(This, sizeof(dwt));
  105. // Find out how many parameters there are.
  106. dwErr = RegQueryInfoKey(
  107. hkParams,
  108. NULL,
  109. NULL,
  110. NULL,
  111. NULL,
  112. NULL,
  113. NULL,
  114. &dwCount,
  115. &dwMaxSize,
  116. NULL,
  117. NULL,
  118. NULL);
  119. if (dwErr != ERROR_SUCCESS)
  120. return dwErr;
  121. if (dwCount == 0)
  122. {
  123. This->dwCount = This->dwSize = 0;
  124. return NO_ERROR;
  125. }
  126. dwMaxSize += 1;
  127. do
  128. {
  129. // Fill in the table
  130. dwtInitialize(This, dwCount, dwMaxSize);
  131. for (i = 0; i < dwCount; i++)
  132. {
  133. dwSize = dwMaxSize;
  134. dwErr = RegEnumValueW(
  135. hkParams,
  136. i,
  137. This->pValues[This->dwCount].Name,
  138. &dwSize,
  139. 0,
  140. &dwType,
  141. NULL,
  142. NULL);
  143. if (dwErr != ERROR_SUCCESS)
  144. {
  145. break;
  146. }
  147. if (dwType != REG_DWORD)
  148. {
  149. continue;
  150. }
  151. dwErr = RegQueryValueExW(
  152. hkParams,
  153. This->pValues[This->dwCount].Name,
  154. 0,
  155. &dwType,
  156. (LPBYTE)&(This->pValues[This->dwCount].Value),
  157. &dwDataSize);
  158. if (dwErr != ERROR_SUCCESS)
  159. {
  160. break;
  161. }
  162. This->dwCount++;
  163. }
  164. } while (FALSE);
  165. return dwErr;
  166. }
  167. DWORD dwtPrint(
  168. IN dwt *This)
  169. {
  170. DWORD i;
  171. if (!This)
  172. return ERROR_INVALID_PARAMETER;
  173. return NO_ERROR;
  174. }
  175. //
  176. // Enumerates all of the subkeys of a given key
  177. //
  178. DWORD
  179. UtlEnumRegistrySubKeys(
  180. IN HKEY hkRoot,
  181. IN PWCHAR pszPath,
  182. IN RegKeyEnumFuncPtr pCallback,
  183. IN HANDLE hData)
  184. {
  185. DWORD dwErr = NO_ERROR, i, dwNameSize = 0, dwCurSize = 0;
  186. DWORD dwCount = 0;
  187. HKEY hkKey = NULL, hkCurKey = NULL;
  188. PWCHAR pszName = NULL;
  189. BOOL bCloseKey = FALSE;
  190. do
  191. {
  192. if (pszPath)
  193. {
  194. bCloseKey = TRUE;
  195. // Open the key to enumerate
  196. //
  197. dwErr = RegOpenKeyExW(
  198. hkRoot,
  199. pszPath,
  200. 0,
  201. KEY_ALL_ACCESS,
  202. &hkKey);
  203. if (dwErr != NO_ERROR)
  204. {
  205. break;
  206. }
  207. }
  208. else
  209. {
  210. bCloseKey = FALSE;
  211. hkKey = hkRoot;
  212. }
  213. // Find out how many sub keys there are
  214. //
  215. dwErr = RegQueryInfoKeyW(
  216. hkKey,
  217. NULL,
  218. NULL,
  219. NULL,
  220. &dwCount,
  221. &dwNameSize,
  222. NULL,
  223. NULL,
  224. NULL,
  225. NULL,
  226. NULL,
  227. NULL);
  228. if (dwErr != ERROR_SUCCESS)
  229. {
  230. return dwErr;
  231. }
  232. dwNameSize++;
  233. // Allocate the name buffer
  234. //
  235. pszName = (PWCHAR) UtlAlloc(dwNameSize * sizeof(WCHAR));
  236. if (pszName == NULL)
  237. {
  238. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  239. break;
  240. }
  241. // Loop through the keys
  242. //
  243. for (i = 0; i < dwCount; i++)
  244. {
  245. dwCurSize = dwNameSize;
  246. // Get the name of the current key
  247. //
  248. dwErr = RegEnumKeyExW(
  249. hkKey,
  250. i,
  251. pszName,
  252. &dwCurSize,
  253. 0,
  254. NULL,
  255. NULL,
  256. NULL);
  257. if (dwErr != ERROR_SUCCESS)
  258. {
  259. continue;
  260. }
  261. // Open the subkey
  262. //
  263. dwErr = RegOpenKeyExW(
  264. hkKey,
  265. pszName,
  266. 0,
  267. KEY_ALL_ACCESS,
  268. &hkCurKey);
  269. if (dwErr != ERROR_SUCCESS)
  270. {
  271. continue;
  272. }
  273. // Call the callback
  274. //
  275. dwErr = pCallback(pszName, hkCurKey, hData);
  276. RegCloseKey(hkCurKey);
  277. if (dwErr != NO_ERROR)
  278. {
  279. break;
  280. }
  281. }
  282. } while (FALSE);
  283. // Cleanup
  284. {
  285. if ((hkKey != NULL) && (bCloseKey))
  286. {
  287. RegCloseKey(hkKey);
  288. }
  289. if (pszName)
  290. {
  291. UtlFree(pszName);
  292. }
  293. }
  294. return dwErr;
  295. }
  296. //
  297. // Enumerates interfaces from the registry
  298. //
  299. DWORD UtlEnumerateInterfaces (
  300. IN IfEnumFuncPtr pCallback,
  301. IN HANDLE hUserData)
  302. {
  303. DWORD dwErr, i, dwIfCount, dwIfTot, dwResume = 0;
  304. DWORD dwPrefBufSize = sizeof(MPR_INTERFACE_0) * 100;
  305. MPR_INTERFACE_0 * pIfs = NULL;
  306. HANDLE hConfig;
  307. BOOL bContinue = TRUE;
  308. // Validate parameters
  309. if (pCallback == NULL)
  310. return ERROR_INVALID_PARAMETER;
  311. // Connect to the configuration server
  312. dwErr = MprConfigServerConnect(NULL, &hConfig);
  313. if (dwErr != NO_ERROR)
  314. return dwErr;
  315. // Get list of all interfaces
  316. dwErr = MprConfigInterfaceEnum(
  317. hConfig,
  318. 0,
  319. (LPBYTE*)&pIfs,
  320. dwPrefBufSize,
  321. &dwIfCount,
  322. &dwIfTot,
  323. &dwResume);
  324. if (dwErr == ERROR_NO_MORE_ITEMS)
  325. return NO_ERROR;
  326. else if ((dwErr != NO_ERROR) && (dwErr != ERROR_MORE_DATA))
  327. return dwErr;
  328. // Loop through the interfaces
  329. do {
  330. // Call the callback for each interface as long
  331. // as we're instructed to continue
  332. for (i = 0; i < dwIfCount; i++) {
  333. if (bContinue) {
  334. bContinue = (*pCallback)(
  335. hConfig,
  336. &(pIfs[i]),
  337. hUserData);
  338. }
  339. }
  340. if (bContinue == FALSE)
  341. break;
  342. // Free up the interface list buffer
  343. if (pIfs)
  344. MprConfigBufferFree(pIfs);
  345. pIfs = NULL;
  346. // Get list of all ip interfaces
  347. dwErr = MprConfigInterfaceEnum(
  348. hConfig,
  349. 0,
  350. (LPBYTE*)&pIfs,
  351. dwPrefBufSize,
  352. &dwIfCount,
  353. &dwIfTot,
  354. &dwResume);
  355. if (dwErr == ERROR_NO_MORE_ITEMS) {
  356. dwErr = NO_ERROR;
  357. break;
  358. }
  359. else if ((dwErr != NO_ERROR) && (dwErr != ERROR_MORE_DATA))
  360. break;
  361. else
  362. continue;
  363. } while (TRUE);
  364. // Cleanup
  365. {
  366. if (pIfs)
  367. MprConfigBufferFree(pIfs);
  368. if (hConfig)
  369. MprConfigServerDisconnect(hConfig);
  370. }
  371. return dwErr;
  372. }
  373. //
  374. // If the given info blob exists in the given toc header
  375. // reset it with the given information, otherwise add
  376. // it as an entry in the TOC.
  377. //
  378. DWORD UtlUpdateInfoBlock (
  379. IN BOOL bOverwrite,
  380. IN LPVOID pHeader,
  381. IN DWORD dwEntryId,
  382. IN DWORD dwSize,
  383. IN DWORD dwCount,
  384. IN LPBYTE pEntry,
  385. OUT LPVOID* ppNewHeader,
  386. OUT LPDWORD lpdwNewSize)
  387. {
  388. PRTR_INFO_BLOCK_HEADER pNewHeader;
  389. DWORD dwErr;
  390. // Attempt to find the entry
  391. dwErr = MprInfoBlockFind(
  392. pHeader,
  393. dwEntryId,
  394. NULL,
  395. NULL,
  396. NULL);
  397. // If we find it, reset it
  398. if (dwErr == NO_ERROR) {
  399. if (bOverwrite) {
  400. dwErr = MprInfoBlockSet(
  401. pHeader,
  402. dwEntryId,
  403. dwSize,
  404. dwCount,
  405. pEntry,
  406. ppNewHeader);
  407. if (dwErr == NO_ERROR) {
  408. pNewHeader = (PRTR_INFO_BLOCK_HEADER)(*ppNewHeader);
  409. *lpdwNewSize = pNewHeader->Size;
  410. }
  411. }
  412. else {
  413. return ERROR_ALREADY_EXISTS;
  414. }
  415. }
  416. // Otherwise, create it
  417. else if (dwErr == ERROR_NOT_FOUND) {
  418. dwErr = MprInfoBlockAdd(
  419. pHeader,
  420. dwEntryId,
  421. dwSize,
  422. dwCount,
  423. pEntry,
  424. ppNewHeader);
  425. if (dwErr == NO_ERROR) {
  426. pNewHeader = (PRTR_INFO_BLOCK_HEADER)(*ppNewHeader);
  427. *lpdwNewSize = pNewHeader->Size;
  428. }
  429. }
  430. return dwErr;
  431. }
  432. // Common allocation routine
  433. PVOID UtlAlloc (DWORD dwSize) {
  434. return RtlAllocateHeap (RtlProcessHeap (), 0, dwSize);
  435. }
  436. // Common deallocation routine
  437. VOID UtlFree (PVOID pvBuffer) {
  438. RtlFreeHeap (RtlProcessHeap (), 0, pvBuffer);
  439. }
  440. // Copies a string
  441. //
  442. PWCHAR
  443. UtlDupString(
  444. IN PWCHAR pszString)
  445. {
  446. PWCHAR pszRet = NULL;
  447. if ((pszString == NULL) || (*pszString == L'\0'))
  448. {
  449. return NULL;
  450. }
  451. pszRet = (PWCHAR) UtlAlloc((wcslen(pszString) + 1) * sizeof(WCHAR));
  452. if (pszRet == NULL)
  453. {
  454. return NULL;
  455. }
  456. wcscpy(pszRet, pszString);
  457. return pszRet;
  458. }
  459. // Error reporting
  460. void UtlPrintErr(DWORD err) {
  461. WCHAR buf[1024];
  462. FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,NULL,err,0,buf,1024,NULL);
  463. PrintMessage(buf);
  464. PrintMessage(L"\n");
  465. }
  466. //----------------------------------------------------------------------------
  467. // Function: UtlAccessRouterKey
  468. //
  469. // Creates/opens the Router key on HKEY_LOCAL_MACHINE.
  470. //----------------------------------------------------------------------------
  471. DWORD UtlAccessRouterKey(HKEY* hkeyRouter) {
  472. LPWSTR lpwsPath;
  473. DWORD dwErr, dwSize;
  474. if (!hkeyRouter)
  475. return ERROR_INVALID_PARAMETER;
  476. *hkeyRouter = NULL;
  477. //
  478. // compute the length of the string
  479. //
  480. dwSize = lstrlen(c_szSystemCCSServices) + 1 + lstrlen(c_szRouter) + 1;
  481. //
  482. // allocate space for the path
  483. //
  484. lpwsPath = (LPWSTR)UtlAlloc(dwSize * sizeof(WCHAR));
  485. if (!lpwsPath)
  486. return ERROR_NOT_ENOUGH_MEMORY;
  487. wsprintf(lpwsPath, L"%s\\%s", c_szSystemCCSServices, c_szRouter);
  488. //
  489. // open the router key
  490. //
  491. dwErr = RegOpenKeyExW(
  492. HKEY_LOCAL_MACHINE, lpwsPath, 0, KEY_ALL_ACCESS, hkeyRouter
  493. );
  494. if (dwErr!=ERROR_SUCCESS) {
  495. PrintMessage(L"ERROR in UtlAccessRouterKey\n");
  496. }
  497. UtlFree(lpwsPath);
  498. return dwErr;
  499. }
  500. //----------------------------------------------------------------------------
  501. // Function: UtlSetupBackupPrivelege
  502. //
  503. // Enables/disables backup privilege for the current process.
  504. //----------------------------------------------------------------------------
  505. DWORD UtlEnablePrivilege(PWCHAR pszPrivilege, BOOL bEnable) {
  506. LUID luid;
  507. HANDLE hToken;
  508. TOKEN_PRIVILEGES tp;
  509. OpenProcessToken(
  510. GetCurrentProcess(),
  511. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
  512. &hToken);
  513. if (! LookupPrivilegeValueW(NULL, pszPrivilege, &luid))
  514. {
  515. return GetLastError();
  516. }
  517. tp.PrivilegeCount = 1;
  518. tp.Privileges[0].Luid = luid;
  519. tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  520. if (! AdjustTokenPrivileges(
  521. hToken,
  522. !bEnable,
  523. &tp,
  524. sizeof(TOKEN_PRIVILEGES),
  525. NULL,
  526. NULL))
  527. {
  528. return GetLastError();
  529. }
  530. return NO_ERROR;
  531. }
  532. DWORD UtlSetupBackupPrivelege(BOOL bEnable) {
  533. return UtlEnablePrivilege(SE_BACKUP_NAME, bEnable);
  534. }
  535. DWORD UtlSetupRestorePrivilege(BOOL bEnable) {
  536. return UtlEnablePrivilege(SE_RESTORE_NAME, bEnable);
  537. }
  538. // Loads the given saved off settings into a temporary key
  539. // and returns a handle to that key.
  540. //
  541. DWORD
  542. UtlLoadSavedSettings(
  543. IN HKEY hkRoot,
  544. IN PWCHAR pszTempKey,
  545. IN PWCHAR pszFile,
  546. OUT HKEY* phkTemp)
  547. {
  548. HKEY hkRestore = NULL;
  549. DWORD dwErr = NO_ERROR, dwDisposition = 0;
  550. BOOL bBackup = FALSE, bRestore = FALSE;
  551. do
  552. {
  553. // Enable the backup and restore priveleges
  554. //
  555. bBackup = (UtlSetupBackupPrivelege (TRUE) == NO_ERROR);
  556. bRestore = (UtlSetupRestorePrivilege(TRUE) == NO_ERROR);
  557. if (!bBackup || !bRestore)
  558. {
  559. return ERROR_CAN_NOT_COMPLETE;
  560. }
  561. // Create a temporary key into which the saved config
  562. // can be loaded.
  563. //
  564. if ((dwErr = RegCreateKeyExW(
  565. hkRoot,
  566. pszTempKey,
  567. 0,
  568. NULL,
  569. REG_OPTION_NON_VOLATILE,
  570. KEY_ALL_ACCESS,
  571. NULL,
  572. &hkRestore,
  573. &dwDisposition)) != NO_ERROR)
  574. {
  575. PrintMessage(L"Unable to create restore key.\n");
  576. break;
  577. }
  578. // Load the saved configuration
  579. //
  580. dwErr = RegRestoreKey(hkRestore, pszFile, 0);
  581. if (dwErr != ERROR_SUCCESS)
  582. {
  583. break;
  584. }
  585. // Assign the return value
  586. //
  587. *phkTemp = hkRestore;
  588. } while (FALSE);
  589. // Cleanup
  590. {
  591. if (bBackup)
  592. {
  593. UtlSetupBackupPrivelege(FALSE);
  594. }
  595. if (bRestore)
  596. {
  597. UtlSetupRestorePrivilege(FALSE);
  598. }
  599. }
  600. return NO_ERROR;
  601. }
  602. //
  603. // Delete the tree of registry values starting at hkRoot
  604. //
  605. DWORD
  606. UtlDeleteRegistryTree(
  607. IN HKEY hkRoot)
  608. {
  609. DWORD dwErr, dwCount, dwNameSize, dwDisposition;
  610. DWORD i, dwCurNameSize;
  611. PWCHAR pszNameBuf;
  612. HKEY hkTemp;
  613. // Find out how many keys there are in the source
  614. dwErr = RegQueryInfoKey (
  615. hkRoot,
  616. NULL,
  617. NULL,
  618. NULL,
  619. &dwCount,
  620. &dwNameSize,
  621. NULL,
  622. NULL,
  623. NULL,
  624. NULL,
  625. NULL,
  626. NULL);
  627. if (dwErr != ERROR_SUCCESS)
  628. return dwErr;
  629. dwNameSize++;
  630. __try {
  631. // Allocate the buffers
  632. pszNameBuf = (PWCHAR)
  633. UtlAlloc(dwNameSize * sizeof(WCHAR));
  634. if (!pszNameBuf)
  635. return ERROR_NOT_ENOUGH_MEMORY;
  636. // Loop through the keys -- deleting all subkey trees
  637. for (i = 0; i < dwCount; i++) {
  638. dwCurNameSize = dwNameSize;
  639. // Get the current source key
  640. dwErr = RegEnumKeyExW(
  641. hkRoot,
  642. i,
  643. pszNameBuf,
  644. &dwCurNameSize,
  645. 0,
  646. NULL,
  647. NULL,
  648. NULL);
  649. if (dwErr != ERROR_SUCCESS)
  650. continue;
  651. // Open the subkey
  652. dwErr = RegCreateKeyExW(
  653. hkRoot,
  654. pszNameBuf,
  655. 0,
  656. NULL,
  657. REG_OPTION_NON_VOLATILE,
  658. KEY_ALL_ACCESS,
  659. NULL,
  660. &hkTemp,
  661. &dwDisposition);
  662. if (dwErr != ERROR_SUCCESS)
  663. continue;
  664. // Delete the subkey tree
  665. UtlDeleteRegistryTree(hkTemp);
  666. // Close the temp handle
  667. RegCloseKey(hkTemp);
  668. }
  669. // Loop through the keys -- deleting all subkeys themselves
  670. for (i = 0; i < dwCount; i++)
  671. {
  672. dwCurNameSize = dwNameSize;
  673. // Get the current source key
  674. dwErr = RegEnumKeyExW(
  675. hkRoot,
  676. 0,
  677. pszNameBuf,
  678. &dwCurNameSize,
  679. 0,
  680. NULL,
  681. NULL,
  682. NULL);
  683. if (dwErr != ERROR_SUCCESS)
  684. continue;
  685. // Delete the subkey tree
  686. dwErr = RegDeleteKey(hkRoot, pszNameBuf);
  687. }
  688. }
  689. __finally {
  690. if (pszNameBuf)
  691. UtlFree(pszNameBuf);
  692. }
  693. return NO_ERROR;
  694. }
  695. DWORD
  696. UtlMarkRouterConfigured()
  697. {
  698. DWORD dwErr, dwVal;
  699. HKEY hkRouter = NULL;
  700. dwErr = UtlAccessRouterKey(&hkRouter);
  701. if (dwErr == NO_ERROR)
  702. {
  703. dwVal = 1;
  704. RegSetValueEx(
  705. hkRouter,
  706. c_szConfigurationFlags,
  707. 0,
  708. REG_DWORD,
  709. (CONST BYTE*)&dwVal,
  710. sizeof(DWORD));
  711. RegCloseKey(hkRouter);
  712. }
  713. return dwErr;
  714. }