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.

1856 lines
54 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. registry.c
  5. Abstract:
  6. Miscellaneous routines for the Registry Operation
  7. Author:
  8. Xiaofeng Zang (xiaoz) 17-Sep-2001 Created(most code stole from base\fs\utils\regedit)
  9. Revision History:
  10. <alias> <date> <comments>
  11. xiaoz 09/25/01 add RegResetValue
  12. --*/
  13. #include "StdAfx.h"
  14. #include "clmt.h"
  15. #include <strsafe.h>
  16. #define MAXVALUENAME_LENGTH 256
  17. #define MAXKEYNAME 256
  18. #define ExtraAllocLen(Type) (IsRegStringType((Type)) ? sizeof(TCHAR) : 0)
  19. #define IsRegStringType(x) (((x) == REG_SZ) || ((x) == REG_EXPAND_SZ) || ((x) == REG_MULTI_SZ))
  20. #define TEXT_REG_RESET_PER_USER_SECTION TEXT("RegistryResetPerUser")
  21. #define TEXT_REG_RESET_PER_SYSTEM_SECTION TEXT("RegistryResetPerSystem")
  22. HRESULT MigrateRegSchemes(HINF, HKEY, LPCTSTR);
  23. HRESULT DoRegReset(HKEY, HINF, LPCTSTR, LPCTSTR);
  24. HRESULT RegBinaryDataReset (HKEY, LPTSTR, LPTSTR, PREG_STRING_REPLACE, LPTSTR[]);
  25. HRESULT RegValueDataReset(HKEY, LPTSTR, LPTSTR, LPTSTR, LPTSTR[]);
  26. HRESULT RegValueNameReset(HKEY, LPTSTR, LPTSTR, LPTSTR, LPTSTR[]);
  27. HRESULT RegKeyNameReset(HKEY, LPTSTR, LPTSTR, LPTSTR, LPTSTR[]);
  28. HRESULT RegWideMatchReset(HKEY, LPTSTR, LPTSTR, LPTSTR, LPTSTR[]);
  29. BOOL bIsValidRegStr(DWORD dwType, DWORD cbLen);
  30. /*******************************************************************************
  31. *
  32. * CopyRegistry
  33. *
  34. * DESCRIPTION:
  35. *
  36. * PARAMETERS:
  37. * hSourceKey,
  38. * hDestinationKey,
  39. *
  40. *************************************************************************************/
  41. BOOL
  42. CopyRegistry(
  43. HKEY hSourceKey,
  44. HKEY hDestinationKey
  45. )
  46. {
  47. BOOL fSuccess = TRUE;
  48. DWORD EnumIndex;
  49. DWORD cchValueName;
  50. DWORD cbValueData;
  51. DWORD Type;
  52. HKEY hSourceSubKey;
  53. HKEY hDestinationSubKey;
  54. TCHAR ValueNameBuffer[MAXVALUENAME_LENGTH];
  55. TCHAR KeyNameBuffer[MAXKEYNAME];
  56. //
  57. // Copy all of the value names and their data.
  58. //
  59. EnumIndex = 0;
  60. while (TRUE)
  61. {
  62. PBYTE pbValueData;
  63. cchValueName = ARRAYSIZE(ValueNameBuffer);
  64. // VALUE DATA
  65. // Query for data size
  66. if (RegEnumValue(hSourceKey, EnumIndex++, ValueNameBuffer,
  67. &cchValueName, NULL, &Type, NULL, &cbValueData) != ERROR_SUCCESS)
  68. {
  69. break;
  70. }
  71. // allocate memory for data
  72. pbValueData = LocalAlloc(LPTR, cbValueData+ExtraAllocLen(Type));
  73. if (pbValueData)
  74. {
  75. if (My_QueryValueEx(hSourceKey, ValueNameBuffer,
  76. NULL, &Type, pbValueData, &cbValueData) == ERROR_SUCCESS)
  77. {
  78. RegSetValueEx(hDestinationKey, ValueNameBuffer, 0, Type,
  79. pbValueData, cbValueData);
  80. }
  81. else
  82. {
  83. fSuccess = FALSE;
  84. }
  85. LocalFree(pbValueData);
  86. }
  87. else
  88. {
  89. fSuccess = FALSE;
  90. }
  91. }
  92. if (fSuccess)
  93. {
  94. //
  95. // Copy all of the subkeys and recurse into them.
  96. //
  97. EnumIndex = 0;
  98. while (TRUE) {
  99. if (RegEnumKey(hSourceKey, EnumIndex++, KeyNameBuffer, MAXKEYNAME) !=
  100. ERROR_SUCCESS)
  101. break;
  102. if(RegOpenKeyEx(hSourceKey,KeyNameBuffer,0,KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE,&hSourceSubKey) ==
  103. ERROR_SUCCESS) {
  104. if (RegCreateKey(hDestinationKey, KeyNameBuffer,
  105. &hDestinationSubKey) == ERROR_SUCCESS) {
  106. CopyRegistry(hSourceSubKey, hDestinationSubKey);
  107. RegCloseKey(hDestinationSubKey);
  108. }
  109. RegCloseKey(hSourceSubKey);
  110. }
  111. }
  112. }
  113. return fSuccess;
  114. }
  115. /*******************************************************************************
  116. *
  117. * RegDeleteKeyRecursive
  118. *
  119. * DESCRIPTION:
  120. * Adapted from \\kernel\razzle3,mvdm\wow32\wshell.c,WOWRegDeleteKey().
  121. * The Windows 95 implementation of RegDeleteKey recursively deletes all
  122. * the subkeys of the specified registry branch, but the NT implementation
  123. * only deletes leaf keys.
  124. *
  125. * PARAMETERS:
  126. * (see below)
  127. *
  128. *******************************************************************************/
  129. LONG
  130. RegDeleteKeyRecursive(
  131. IN HKEY hKey,
  132. IN LPCTSTR lpszSubKey
  133. )
  134. /*++
  135. Routine Description:
  136. There is a significant difference between the Win3.1 and Win32
  137. behavior of RegDeleteKey when the key in question has subkeys.
  138. The Win32 API does not allow you to delete a key with subkeys,
  139. while the Win3.1 API deletes a key and all its subkeys.
  140. This routine is a recursive worker that enumerates the subkeys
  141. of a given key, applies itself to each one, then deletes itself.
  142. It specifically does not attempt to deal rationally with the
  143. case where the caller may not have access to some of the subkeys
  144. of the key to be deleted. In this case, all the subkeys which
  145. the caller can delete will be deleted, but the api will still
  146. return ERROR_ACCESS_DENIED.
  147. Arguments:
  148. hKey - Supplies a handle to an open registry key.
  149. lpszSubKey - Supplies the name of a subkey which is to be deleted
  150. along with all of its subkeys.
  151. Return Value:
  152. ERROR_SUCCESS - entire subtree successfully deleted.
  153. ERROR_ACCESS_DENIED - given subkey could not be deleted.
  154. --*/
  155. {
  156. DWORD i;
  157. HKEY Key;
  158. LONG Status;
  159. DWORD ClassLength=0;
  160. DWORD SubKeys;
  161. DWORD MaxSubKey;
  162. DWORD MaxClass;
  163. DWORD Values;
  164. DWORD MaxValueName;
  165. DWORD MaxValueData;
  166. DWORD SecurityLength;
  167. FILETIME LastWriteTime;
  168. LPTSTR NameBuffer;
  169. //
  170. // First open the given key so we can enumerate its subkeys
  171. //
  172. Status = RegOpenKeyEx(hKey,
  173. lpszSubKey,
  174. 0,
  175. KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE,
  176. &Key);
  177. if (Status != ERROR_SUCCESS)
  178. {
  179. //
  180. // possibly we have delete access, but not enumerate/query.
  181. // So go ahead and try the delete call, but don't worry about
  182. // any subkeys. If we have any, the delete will fail anyway.
  183. //
  184. return(RegDeleteKey(hKey,lpszSubKey));
  185. }
  186. //
  187. // Use RegQueryInfoKey to determine how big to allocate the buffer
  188. // for the subkey names.
  189. //
  190. Status = RegQueryInfoKey(Key,
  191. NULL,
  192. &ClassLength,
  193. 0,
  194. &SubKeys,
  195. &MaxSubKey,
  196. &MaxClass,
  197. &Values,
  198. &MaxValueName,
  199. &MaxValueData,
  200. &SecurityLength,
  201. &LastWriteTime);
  202. if ((Status != ERROR_SUCCESS) &&
  203. (Status != ERROR_MORE_DATA) &&
  204. (Status != ERROR_INSUFFICIENT_BUFFER))
  205. {
  206. RegCloseKey(Key);
  207. return(Status);
  208. }
  209. NameBuffer = (LPTSTR) LocalAlloc(LPTR, (MaxSubKey + 1)*sizeof(TCHAR));
  210. if (NameBuffer == NULL)
  211. {
  212. RegCloseKey(Key);
  213. return(ERROR_NOT_ENOUGH_MEMORY);
  214. }
  215. //
  216. // Enumerate subkeys and apply ourselves to each one.
  217. //
  218. i=0;
  219. do
  220. {
  221. Status = RegEnumKey(Key,
  222. i,
  223. NameBuffer,
  224. MaxSubKey+1);
  225. if (Status == ERROR_SUCCESS)
  226. {
  227. Status = RegDeleteKeyRecursive(Key,NameBuffer);
  228. }
  229. if (Status != ERROR_SUCCESS)
  230. {
  231. //
  232. // Failed to delete the key at the specified index. Increment
  233. // the index and keep going. We could probably bail out here,
  234. // since the api is going to fail, but we might as well keep
  235. // going and delete everything we can.
  236. //
  237. ++i;
  238. }
  239. } while ( (Status != ERROR_NO_MORE_ITEMS) && (i < SubKeys) );
  240. LocalFree((HLOCAL) NameBuffer);
  241. RegCloseKey(Key);
  242. return(RegDeleteKey(hKey,lpszSubKey));
  243. }
  244. //-----------------------------------------------------------------------------
  245. //
  246. // Function: RegRenameValueName
  247. //
  248. // Synopsis: Rename the value name in registry by copying the data from
  249. // old value to new value, then delete the old value.
  250. //
  251. // Returns: Win32 Error Code
  252. //
  253. // History: 09/17/2001 Xiaoz Created
  254. // 02/14/2001 rerkboos Add dynamic buffer allocation
  255. // 03/05/2002 rerkboos Code clean up
  256. //
  257. // Notes: hKey parameter must have been opened with KEY_SET_VALUE access
  258. //
  259. //-----------------------------------------------------------------------------
  260. LONG RegRenameValueName(
  261. HKEY hKey, // Handle to registry key containing the value
  262. LPCTSTR lpOldValName, // Old value name to be changed
  263. LPCTSTR lpNewValName // New value name
  264. )
  265. {
  266. LONG lResult;
  267. DWORD dwType;
  268. DWORD cbData;
  269. LPBYTE lpData = NULL;
  270. DWORD ClassLength=0;
  271. DWORD SubKeys;
  272. DWORD MaxSubKey;
  273. DWORD MaxClass;
  274. DWORD Values;
  275. DWORD MaxValueName;
  276. DWORD MaxValueData;
  277. DWORD SecurityLength;
  278. FILETIME LastWriteTime;
  279. if (lpOldValName == NULL || lpNewValName == NULL)
  280. {
  281. // invalid parameter
  282. return ERROR_INVALID_PARAMETER;
  283. }
  284. if (MyStrCmpI(lpOldValName, lpNewValName) == LSTR_EQUAL)
  285. {
  286. return ERROR_SUCCESS;
  287. }
  288. //
  289. // Get the registry info under hkey
  290. //
  291. lResult = RegQueryInfoKey(hKey,
  292. NULL,
  293. &ClassLength,
  294. 0,
  295. &SubKeys,
  296. &MaxSubKey,
  297. &MaxClass,
  298. &Values,
  299. &MaxValueName,
  300. &MaxValueData,
  301. &SecurityLength,
  302. &LastWriteTime);
  303. if ((lResult != ERROR_SUCCESS) &&
  304. (lResult != ERROR_MORE_DATA) &&
  305. (lResult != ERROR_INSUFFICIENT_BUFFER))
  306. {
  307. goto Cleanup;
  308. }
  309. MaxValueData += 2*sizeof(TCHAR);
  310. if (NULL == (lpData = malloc(MaxValueData)))
  311. {
  312. lResult = ERROR_NOT_ENOUGH_MEMORY;
  313. goto Cleanup;
  314. }
  315. //
  316. // Query the value of old value name
  317. //
  318. cbData = MaxValueData;
  319. lResult = My_QueryValueEx(hKey,
  320. lpOldValName,
  321. 0,
  322. &dwType,
  323. lpData,
  324. &cbData);
  325. if (ERROR_SUCCESS != lResult)
  326. {
  327. goto Cleanup;
  328. }
  329. //
  330. // Create a new value name using old data
  331. //
  332. lResult = RegSetValueEx(hKey,
  333. lpNewValName,
  334. 0,
  335. dwType,
  336. lpData,
  337. cbData);
  338. if (lResult != ERROR_SUCCESS)
  339. {
  340. DPF(dlError,
  341. TEXT("RegRenameValueName: Failed to create value [%s]"),
  342. lpNewValName);
  343. goto Cleanup;
  344. }
  345. //
  346. // Delete the old value name, after successfully created a new one
  347. //
  348. lResult = RegDeleteValue(hKey, lpOldValName);
  349. if (lResult != ERROR_SUCCESS)
  350. {
  351. DPF(dlError,
  352. TEXT("RegRenameValueName: Cannot delete old value [%s]"),
  353. lpOldValName);
  354. // if we cannot delete old value, new value shouldn't be created
  355. RegDeleteValue(hKey, lpNewValName);
  356. goto Cleanup;
  357. }
  358. Cleanup:
  359. // BUG 561546: Free the allocated buffer
  360. if (lpData)
  361. {
  362. free(lpData);
  363. }
  364. return lResult;
  365. }
  366. /**
  367. Routine Description:
  368. RegResetValue check whether the current value equals szOldValue,
  369. if yes , change the value to szNewValue,otherwise it does not do anything
  370. however if szOldValue is NULL, then , it will always set value
  371. if szOldValue is "", then , it will add this value
  372. Arguments:
  373. hKeyRoot - Specifies the root of registry key
  374. szKeyName - Specifies registry key path
  375. szValueName - Specifies the name of value field
  376. dwType - specifies string type, should be one of REG_SZ/REG_EXPAND_SZ/REG_MULTI_SZ
  377. szOldValue - specifies the expected old value
  378. szNewValue - specifies the new value
  379. Return Value:
  380. TRUE - Success
  381. FALSE - Failure
  382. --*/
  383. LONG RegResetValue(
  384. HKEY hKeyRoot, // Root of registry key
  385. LPCTSTR lpKeyName, // Registry key path
  386. LPCTSTR lpValueName, // Name of value field
  387. DWORD dwType, // Value type
  388. LPCTSTR lpOldValue, // Expected old value
  389. LPCTSTR lpNewValue, // New value to be set
  390. DWORD dwValueSize, // New value data size
  391. LPCTSTR lpszUsersid // User Sid
  392. )
  393. {
  394. LONG lResult;
  395. HKEY hKey = NULL;
  396. DWORD dw;
  397. DWORD ClassLength=0;
  398. DWORD SubKeys;
  399. DWORD MaxSubKey;
  400. DWORD MaxClass;
  401. DWORD Values;
  402. DWORD MaxValueName;
  403. DWORD MaxValueData;
  404. DWORD SecurityLength;
  405. FILETIME LastWriteTime;
  406. LPTSTR szData = NULL;
  407. DWORD dwSize = 0;
  408. BOOL bTry = TRUE;
  409. BOOL bNeedCLoseKey = TRUE;
  410. //if lpOldValue is NULL , mean Set to lpNewValue and do not care the old one
  411. if ( !lpOldValue || !lpOldValue[0])
  412. {
  413. if (!lpKeyName)
  414. {
  415. hKey = hKeyRoot;
  416. bNeedCLoseKey = FALSE;
  417. goto SkipKeyOpen;
  418. }
  419. if (lpOldValue)
  420. {
  421. DWORD dwDisposition;
  422. TryAgain1:
  423. lResult = RegCreateKeyEx(hKeyRoot,
  424. lpKeyName,
  425. 0,
  426. NULL,
  427. REG_OPTION_NON_VOLATILE,
  428. KEY_ALL_ACCESS,
  429. NULL,
  430. &hKey,
  431. &dwDisposition);
  432. if (lResult != ERROR_SUCCESS)
  433. {
  434. if (bTry && lResult == ERROR_ACCESS_DENIED)
  435. {
  436. AdjustRegSecurity(hKeyRoot, lpKeyName, lpszUsersid, TRUE);
  437. bTry = FALSE;
  438. goto TryAgain1;
  439. }
  440. goto Cleanup;
  441. }
  442. }
  443. else
  444. {
  445. TryAgain2:
  446. lResult = RegOpenKeyEx(hKeyRoot,
  447. lpKeyName,
  448. 0,
  449. KEY_ALL_ACCESS,
  450. &hKey);
  451. if (lResult != ERROR_SUCCESS)
  452. {
  453. if (bTry && lResult == ERROR_ACCESS_DENIED)
  454. {
  455. AdjustRegSecurity(hKeyRoot, lpKeyName, lpszUsersid, TRUE);
  456. bTry = FALSE;
  457. goto TryAgain2;
  458. }
  459. goto Cleanup;
  460. }
  461. }
  462. SkipKeyOpen:
  463. switch (dwType & 0xffff)
  464. {
  465. case REG_SZ:
  466. case REG_EXPAND_SZ:
  467. dwSize = (lstrlen(lpNewValue) + 1) * sizeof(TCHAR);
  468. break;
  469. case REG_MULTI_SZ:
  470. dwSize = MultiSzLen(lpNewValue) * sizeof(TCHAR);
  471. break;
  472. case REG_BINARY:
  473. dwSize = dwValueSize;
  474. break;
  475. }
  476. }
  477. else
  478. {
  479. TryAgain3:
  480. //if lpOldValue !="", it mean set the lpNewValue, but check whether the current
  481. // registry value is szOldValue
  482. //Open the subket and got the handle in hKey
  483. lResult = RegOpenKeyEx(hKeyRoot,
  484. lpKeyName,
  485. 0,
  486. KEY_ALL_ACCESS,
  487. &hKey);
  488. if (lResult != ERROR_SUCCESS)
  489. {
  490. if (bTry && lResult == ERROR_ACCESS_DENIED)
  491. {
  492. AdjustRegSecurity(hKeyRoot, lpKeyName, lpszUsersid, TRUE);
  493. bTry = FALSE;
  494. goto TryAgain3;
  495. }
  496. goto Cleanup;
  497. }
  498. lResult = RegQueryInfoKey(hKey,
  499. NULL,
  500. &ClassLength,
  501. 0,
  502. &SubKeys,
  503. &MaxSubKey,
  504. &MaxClass,
  505. &Values,
  506. &MaxValueName,
  507. &MaxValueData,
  508. &SecurityLength,
  509. &LastWriteTime);
  510. if ((lResult != ERROR_SUCCESS) &&
  511. (lResult != ERROR_MORE_DATA) &&
  512. (lResult != ERROR_INSUFFICIENT_BUFFER))
  513. {
  514. goto Cleanup;
  515. }
  516. MaxValueData += 2*sizeof(TCHAR);
  517. if (NULL == (szData = malloc(MaxValueData)))
  518. {
  519. lResult = ERROR_NOT_ENOUGH_MEMORY;
  520. goto Cleanup;
  521. }
  522. dwSize = MaxValueData;
  523. lResult = My_QueryValueEx (hKey,
  524. lpValueName,
  525. 0,
  526. &dw,
  527. (LPBYTE) szData,
  528. &dwSize);
  529. if (lResult != ERROR_SUCCESS)
  530. {
  531. goto Cleanup;
  532. }
  533. if ( ((dwType & 0xffff) == REG_SZ) || ((dwType & 0xffff) == REG_EXPAND_SZ) )
  534. {
  535. if (MyStrCmpI(szData, lpOldValue) != LSTR_EQUAL)
  536. {
  537. lResult = ERROR_SUCCESS;
  538. goto Cleanup;
  539. }
  540. else
  541. {
  542. dwSize = (lstrlen(lpNewValue) + 1) * sizeof(TCHAR);
  543. }
  544. }
  545. else
  546. {//dwType == REG_MULTI_SZ
  547. if (!CmpMultiSzi(szData, lpOldValue))
  548. {
  549. lResult = ERROR_SUCCESS;
  550. goto Cleanup;
  551. }
  552. else
  553. {
  554. dwSize = MultiSzLen(lpNewValue) * sizeof(TCHAR);
  555. }
  556. }
  557. if ( dwType & 0xffff0000)
  558. {
  559. if ((dwType & 0xffff0000)>>16 != dw )
  560. {
  561. // Key type in registry mismatches the caller-supplied type
  562. lResult = ERROR_SUCCESS;
  563. goto Cleanup;
  564. }
  565. }
  566. else
  567. {
  568. if (dwType != dw)
  569. {
  570. // Key type in registry mismatches the caller-supplied type
  571. lResult = ERROR_SUCCESS;
  572. goto Cleanup;
  573. }
  574. }
  575. }
  576. //
  577. // Set the new value
  578. //
  579. if ( dwType & 0xffff0000)
  580. {
  581. dwType = (dwType & 0xffff0000)>>16;
  582. }
  583. lResult = RegSetValueEx(hKey,
  584. lpValueName,
  585. 0,
  586. dwType,
  587. (LPBYTE) lpNewValue,
  588. dwSize);
  589. Cleanup:
  590. if (hKey && bNeedCLoseKey)
  591. {
  592. RegCloseKey(hKey);
  593. }
  594. if (!bTry)
  595. {
  596. AdjustRegSecurity(hKeyRoot, lpKeyName, lpszUsersid, FALSE);
  597. }
  598. FreePointer(szData);
  599. return lResult;
  600. }
  601. //-----------------------------------------------------------------------------
  602. //
  603. // Function: RegResetValueName
  604. //
  605. // Synopsis: Reset value name to new name if the old name matches the
  606. // user-supply lpOldValueName.
  607. //
  608. // Returns: Win32 Error Code
  609. //
  610. // History: 02/07/2002 Rerkboos Created
  611. //
  612. // Notes: none
  613. //
  614. //-----------------------------------------------------------------------------
  615. LONG RegResetValueName(
  616. HKEY hRootKey, // Root key
  617. LPCTSTR lpSubKeyName, // Sub key name under HKEY_Users\{user hive}
  618. LPCTSTR lpOldValueName, // Old value name to be changed
  619. LPCTSTR lpNewValueName, // New value name
  620. LPCTSTR lpszUsersid // User Sid
  621. )
  622. {
  623. LONG lRet;
  624. HKEY hKey;
  625. BOOL bTry = TRUE;
  626. TryAgain:
  627. lRet = RegOpenKeyEx(hRootKey,
  628. lpSubKeyName,
  629. 0,
  630. KEY_WRITE | KEY_READ,
  631. &hKey);
  632. if (lRet == ERROR_SUCCESS)
  633. {
  634. lRet = RegRenameValueName(hKey,
  635. lpOldValueName,
  636. lpNewValueName);
  637. RegCloseKey(hKey);
  638. if (!bTry)
  639. AdjustRegSecurity(hRootKey, lpSubKeyName, lpszUsersid, FALSE);
  640. } else if (bTry && lRet == ERROR_ACCESS_DENIED)
  641. {
  642. AdjustRegSecurity(hRootKey, lpSubKeyName, lpszUsersid, TRUE);
  643. bTry = FALSE;
  644. goto TryAgain;
  645. }
  646. return lRet;
  647. }
  648. //-----------------------------------------------------------------------------
  649. //
  650. // Function: RegResetKeyName
  651. //
  652. // Synopsis: Reset the registry key
  653. //
  654. // Returns: Win32 Error Code
  655. //
  656. // History: 05/06/2002 Rerkboos Created
  657. //
  658. // Notes: none
  659. //
  660. //-----------------------------------------------------------------------------
  661. LONG RegResetKeyName(
  662. HKEY hRootKey, // Root key
  663. LPCTSTR lpSubKey, // Sub key
  664. LPCTSTR lpOldKeyName, // Old key name to be changed
  665. LPCTSTR lpNewKeyName // New key name
  666. )
  667. {
  668. LONG lRet;
  669. HKEY hKey;
  670. HKEY hOldKey;
  671. HKEY hNewKey;
  672. lRet = RegOpenKeyEx(hRootKey,
  673. lpSubKey,
  674. 0,
  675. KEY_READ | KEY_WRITE,
  676. &hKey);
  677. if (lRet == ERROR_SUCCESS)
  678. {
  679. lRet = RegOpenKeyEx(hKey,
  680. lpOldKeyName,
  681. 0,
  682. KEY_READ | KEY_WRITE,
  683. &hOldKey);
  684. if (lRet == ERROR_SUCCESS)
  685. {
  686. lRet = RegCreateKeyEx(hKey,
  687. lpNewKeyName,
  688. 0,
  689. TEXT(""),
  690. REG_OPTION_NON_VOLATILE,
  691. KEY_WRITE | KEY_READ,
  692. NULL,
  693. &hNewKey,
  694. NULL);
  695. if (lRet == ERROR_SUCCESS)
  696. {
  697. if (CopyRegistry(hOldKey, hNewKey))
  698. {
  699. RegDeleteKeyRecursive(hKey, lpOldKeyName);
  700. }
  701. RegCloseKey(hNewKey);
  702. }
  703. RegCloseKey(hOldKey);
  704. }
  705. RegCloseKey(hKey);
  706. }
  707. return lRet;
  708. }
  709. LONG RegGetValue(
  710. HKEY hKeyRoot,
  711. LPTSTR szKeyName,
  712. LPTSTR szValueName,
  713. LPDWORD lpType,
  714. LPBYTE lpData,
  715. LPDWORD lpcbData)
  716. {
  717. LONG lResult ;
  718. HKEY hKey = NULL;
  719. lResult = RegOpenKeyEx(hKeyRoot,
  720. szKeyName,
  721. 0,
  722. KEY_READ,
  723. &hKey);
  724. if (lResult != ERROR_SUCCESS)
  725. {
  726. goto Cleanup;
  727. }
  728. lResult = My_QueryValueEx (hKey,
  729. szValueName,
  730. 0,
  731. lpType,
  732. lpData,
  733. lpcbData);
  734. Cleanup:
  735. if (hKey)
  736. {
  737. RegCloseKey(hKey);
  738. }
  739. return lResult;
  740. }
  741. HRESULT MigrateRegSchemes(
  742. HINF hInf, // Handle to template INF
  743. HKEY hKey, // Handle to root key
  744. LPCTSTR lpUserName // User name
  745. )
  746. {
  747. HRESULT hr = E_FAIL;
  748. BOOL bRet;
  749. LONG lComponentCount;
  750. LONG lLineIndex;
  751. INFCONTEXT context;
  752. LPCTSTR lpSectionName;
  753. const TCHAR szPerSystemSection[] = TEXT_REG_RESET_PER_SYSTEM_SECTION;
  754. const TCHAR szPerUserSection[] = TEXT_REG_RESET_PER_USER_SECTION;
  755. if (hInf == INVALID_HANDLE_VALUE)
  756. {
  757. return E_INVALIDARG;
  758. }
  759. DPF(REGmsg, TEXT("Enter MigrateRegSchemes:"));
  760. lpSectionName = (lpUserName ? szPerUserSection : szPerSystemSection);
  761. // Get all components from appropriate section
  762. lComponentCount = SetupGetLineCount(hInf, lpSectionName);
  763. for (lLineIndex = 0 ; lLineIndex < lComponentCount ; lLineIndex++)
  764. {
  765. bRet = SetupGetLineByIndex(hInf,
  766. lpSectionName,
  767. lLineIndex,
  768. &context);
  769. if (bRet)
  770. {
  771. TCHAR szComponentName[MAX_PATH];
  772. DWORD cchReqSize;
  773. bRet = SetupGetStringField(&context,
  774. 1,
  775. szComponentName,
  776. ARRAYSIZE(szComponentName),
  777. &cchReqSize);
  778. if (bRet)
  779. {
  780. //
  781. // Do the registry reset
  782. //
  783. hr = DoRegReset(hKey, hInf, szComponentName, lpUserName);
  784. if (FAILED(hr))
  785. {
  786. DPF(REGerr,
  787. TEXT("Failed to do registry migration for [%s] schemes"),
  788. szComponentName);
  789. break;
  790. }
  791. }
  792. }
  793. if (!bRet)
  794. {
  795. hr = HRESULT_FROM_WIN32(GetLastError());
  796. break;
  797. }
  798. }
  799. DPF(REGmsg, TEXT("Exit MigrateRegSchemes:"));
  800. return hr;
  801. }
  802. HRESULT DoRegReset(
  803. HKEY hKey, // Handle to root key
  804. HINF hInf, // Handle to template INF
  805. LPCTSTR lpSection, // Section name in INF
  806. LPCTSTR lpUserName // User name
  807. )
  808. {
  809. #define MAX_VALUE_DATA_RESET_FIELD 6
  810. #define MAX_VALUE_NAME_RESET_FIELD 4
  811. #define MAX_KEY_NAME_RESET_FIELD 4
  812. HRESULT hr = S_OK;
  813. BOOL bRet;
  814. HKEY hRootKey;
  815. LONG lItemCount;
  816. LONG lLineCount;
  817. INFCONTEXT context;
  818. LPTSTR lpSubKey;
  819. LPTSTR lpOutputKey;
  820. LPTSTR lpField[16];
  821. DWORD i;
  822. DWORD dwLastField[] = {
  823. MAX_VALUE_DATA_RESET_FIELD,
  824. MAX_VALUE_NAME_RESET_FIELD,
  825. MAX_KEY_NAME_RESET_FIELD,
  826. MAX_KEY_NAME_RESET_FIELD,
  827. };
  828. if (hInf == INVALID_HANDLE_VALUE || lpSection == NULL)
  829. {
  830. return E_INVALIDARG;
  831. }
  832. DPF(REGmsg, TEXT("Enter DoRegReset for [%s] component"), lpSection);
  833. // Loop through all lines under current component section
  834. lItemCount = SetupGetLineCount(hInf, lpSection);
  835. for (lLineCount = 0 ; lLineCount < lItemCount ; lLineCount++)
  836. {
  837. // Get the INF context for each line under current component
  838. bRet = SetupGetLineByIndex(hInf, lpSection, lLineCount, &context);
  839. if (bRet)
  840. {
  841. TCHAR szResetType[2];
  842. DWORD dwReqSize;
  843. // Get the reset-type from field 1
  844. bRet = SetupGetStringField(&context,
  845. 1,
  846. szResetType,
  847. ARRAYSIZE(szResetType),
  848. &dwReqSize);
  849. if (bRet)
  850. {
  851. LONG lResetType = _ttol(szResetType);
  852. hr = ReadFieldFromContext(&context, lpField, 2, dwLastField[lResetType]);
  853. if (SUCCEEDED(hr))
  854. {
  855. if (hKey == NULL)
  856. {
  857. //
  858. // Per-System reg key
  859. //
  860. lpOutputKey = lpField[2];
  861. Str2KeyPath2(lpField[2], &hRootKey, &lpSubKey);
  862. }
  863. else
  864. {
  865. //
  866. // Per-User reg key
  867. //
  868. lpOutputKey = lpField[2];
  869. lpSubKey = lpField[2];
  870. hRootKey = hKey;
  871. }
  872. switch (lResetType)
  873. {
  874. case 0:
  875. if (MyStrCmpI(lpField[3], TEXT("REG_BINARY")) == 0)
  876. hr = RegBinaryDataReset (hRootKey,
  877. (LPTSTR) lpUserName,
  878. lpSubKey,
  879. &g_StrReplaceTable,
  880. lpField);
  881. else
  882. hr = RegValueDataReset(hRootKey,
  883. (LPTSTR) lpUserName,
  884. lpSubKey,
  885. lpOutputKey,
  886. lpField);
  887. break;
  888. case 1:
  889. hr = RegValueNameReset( hRootKey,
  890. (LPTSTR) lpUserName,
  891. lpSubKey,
  892. lpOutputKey,
  893. lpField);
  894. break;
  895. case 2:
  896. hr = RegKeyNameReset(hRootKey,
  897. (LPTSTR) lpUserName,
  898. lpSubKey,
  899. lpOutputKey,
  900. lpField);
  901. break;
  902. case 3:
  903. hr = RegWideMatchReset(hRootKey,
  904. (LPTSTR) lpUserName,
  905. lpSubKey,
  906. lpOutputKey,
  907. lpField);
  908. break;
  909. }
  910. for (i = 0 ; i <= dwLastField[lResetType] ; i++)
  911. {
  912. MEMFREE(lpField[i]);
  913. }
  914. }
  915. }
  916. }
  917. if (!bRet)
  918. {
  919. hr = HRESULT_FROM_WIN32(GetLastError());
  920. break;
  921. }
  922. }
  923. DPF(REGmsg, TEXT("Exit DoRegReset for [%s] component:"), lpSection);
  924. return hr;
  925. }
  926. //-----------------------------------------------------------------------------
  927. //
  928. // Function: MigrateRegSchemesPerSystem
  929. //
  930. // Synopsis: Migrate Per-System scheme settings in registry to English.
  931. // Scheme settings can be registry value data or
  932. // registry value name.
  933. //
  934. // Returns: S_OK if operation succeed
  935. //
  936. // History: 03/15/2002 Rerkboos Created
  937. //
  938. // Notes: Per-System means that the registry data is not under HKEY_USERS
  939. //
  940. //-----------------------------------------------------------------------------
  941. HRESULT MigrateRegSchemesPerSystem(
  942. HINF hInf
  943. )
  944. {
  945. return MigrateRegSchemes(hInf, NULL, NULL);
  946. }
  947. //-----------------------------------------------------------------------------
  948. //
  949. // Function: MigrateRegSchemesPerUser
  950. //
  951. // Synopsis: Migrate Per-User scheme settings in registry to English.
  952. // Scheme settings can be registry value data or
  953. // registry value name.
  954. //
  955. // Returns: S_OK if operation succeed
  956. //
  957. // History: 03/15/2002 Rerkboos Created
  958. //
  959. // Notes: This is a callback function for LoopUser() function.
  960. // It will be called everytime LoopUser() loads registry hive for
  961. // each user available in the system.
  962. //
  963. //-----------------------------------------------------------------------------
  964. HRESULT MigrateRegSchemesPerUser(
  965. HKEY hKeyUser, // Handle to user's root key
  966. LPCTSTR lpUserName, // User name
  967. LPCTSTR lpDomainName, // Domain name of user name
  968. LPCTSTR lpUserSid // Sid of user
  969. )
  970. {
  971. return MigrateRegSchemes(g_hInf, hKeyUser, lpUserName);
  972. }
  973. HRESULT RegBinaryDataReset (
  974. HKEY hRootKey, // Handle to root key
  975. LPTSTR lpUserName, // (optional) name of user for current hRootKey
  976. LPTSTR lpSubKey, // Sub key used to search in registry
  977. PREG_STRING_REPLACE lpRegStr, // String table
  978. LPTSTR lpField[]) // Pointer to field value from template file
  979. {
  980. HRESULT hr = S_OK;
  981. if (MyStrCmpI(lpField[5], TEXT("UpdatePSTpath")) == 0)
  982. {
  983. hr = UpdatePSTpath(hRootKey, lpUserName, lpSubKey, lpField[4], lpRegStr);
  984. }
  985. return hr;
  986. }
  987. //-----------------------------------------------------------------------------
  988. //
  989. // Function: RegValueDataReset
  990. //
  991. // Synopsis: Reset the value data in registry, one value data at a time.
  992. // The value data to be reset is retrieved from INF line context.
  993. //
  994. // Returns: S_OK if operation succeeded
  995. //
  996. // History: 03/15/2002 Rerkboos Created
  997. //
  998. // Notes: lpUserName can be NULL if this function is to reset per-system
  999. // registry settings. Otherwise, lpUserName contains user name
  1000. // for the supplied hRootKey.
  1001. //
  1002. //-----------------------------------------------------------------------------
  1003. HRESULT RegValueDataReset(
  1004. HKEY hRootKey, // Handle to root key
  1005. LPTSTR lpUserName, // (optional) name of user for current hRootKey
  1006. LPTSTR lpSubKey, // Sub key used to search in registry
  1007. LPTSTR lpOutputKey, // Output registry to save in CLMTDO.inf
  1008. LPTSTR lpField[] // Pointer to field value from template file
  1009. )
  1010. {
  1011. HRESULT hr = S_OK;
  1012. HKEY hKey;
  1013. DWORD cbSize;
  1014. DWORD dwAttrib = 0;
  1015. LONG lRet;
  1016. lRet = RegOpenKeyEx(hRootKey,
  1017. lpSubKey,
  1018. 0,
  1019. KEY_WRITE | KEY_READ,
  1020. &hKey);
  1021. if (lRet == ERROR_SUCCESS)
  1022. {
  1023. lRet = GetRegistryValue(hRootKey,
  1024. lpSubKey, // Sub key
  1025. lpField[4], // Value name
  1026. NULL,
  1027. &cbSize);
  1028. if (lRet == ERROR_SUCCESS)
  1029. {
  1030. LPWSTR lpValue;
  1031. DWORD dwType = Str2REG(lpField[3]); // Registry type
  1032. lpValue = (LPWSTR) MEMALLOC(cbSize);
  1033. if (lpValue)
  1034. {
  1035. GetRegistryValue(hRootKey,
  1036. lpSubKey,
  1037. lpField[4],
  1038. (LPBYTE) lpValue,
  1039. &cbSize);
  1040. // Old value matches, do reg value reset
  1041. if (MyStrCmpI(lpValue, lpField[5]) == LSTR_EQUAL)
  1042. {
  1043. DPF(REGinf, TEXT("Reset registry value [%s]"), lpField[4]);
  1044. //
  1045. // Add the value data to be rename into CLMTDO.INF
  1046. //
  1047. hr = AddRegValueRename(lpOutputKey, // Reg key
  1048. lpField[4], // Value name
  1049. NULL,
  1050. lpField[5], // Old value data
  1051. lpField[6], // New value data
  1052. dwType,
  1053. dwAttrib,
  1054. (LPTSTR) lpUserName);
  1055. if (FAILED(hr))
  1056. {
  1057. DPF(REGwar,
  1058. TEXT("Failed to add registry value [%s] to defer change"),
  1059. lpField[4]);
  1060. }
  1061. }
  1062. MEMFREE(lpValue);
  1063. }
  1064. }
  1065. else if (lRet == ERROR_FILE_NOT_FOUND)
  1066. {
  1067. DPF(REGwar, TEXT("Value [%s] not found in registry"), lpField[4]);
  1068. hr = S_FALSE;
  1069. }
  1070. else
  1071. {
  1072. DPF(REGerr, TEXT("Failed to read value [%s]"), lpField[4]);
  1073. hr = HRESULT_FROM_WIN32(lRet);
  1074. }
  1075. RegCloseKey(hKey);
  1076. }
  1077. else if (lRet == ERROR_FILE_NOT_FOUND)
  1078. {
  1079. DPF(REGwar, TEXT("Key [%s] not found in registry"), lpOutputKey);
  1080. hr = S_FALSE;
  1081. }
  1082. else
  1083. {
  1084. DPF(REGerr, TEXT("Failed to open key [%s]"), lpOutputKey);
  1085. hr = HRESULT_FROM_WIN32(lRet);
  1086. }
  1087. return hr;
  1088. }
  1089. //-----------------------------------------------------------------------------
  1090. //
  1091. // Function: RegValueNameReset
  1092. //
  1093. // Synopsis: Reset the value name in registry, one value name at a time.
  1094. // The value name to be reset is retrieved from INF line context.
  1095. //
  1096. // Returns: S_OK if operation succeeded
  1097. //
  1098. // History: 03/15/2002 Rerkboos Created
  1099. //
  1100. // Notes: lpUserName can be NULL if this function is to reset per-system
  1101. // registry settings. Otherwise, lpUserName contains user name
  1102. // for the supplied hRootKey.
  1103. //
  1104. //-----------------------------------------------------------------------------
  1105. HRESULT RegValueNameReset(
  1106. HKEY hRootKey, // Handle to root key
  1107. LPTSTR lpUserName, // (optional) name of user for current hRootKey
  1108. LPTSTR lpSubKey, // Sub key used to search in registry
  1109. LPTSTR lpOutputKey, // Output registry to save in CLMTDO.inf
  1110. LPTSTR lpField[] // Pointer to field value from template file
  1111. )
  1112. {
  1113. HRESULT hr = S_OK;
  1114. HKEY hKey;
  1115. DWORD cbSize;
  1116. DWORD dwAttrib = 0;
  1117. LONG lRet;
  1118. // Do value name reset If old value name and new value name in INF are different
  1119. if (lstrcmp((LPCTSTR) lpField[3], (LPCTSTR) lpField[4]) != LSTR_EQUAL)
  1120. {
  1121. lRet = RegOpenKeyEx(hRootKey,
  1122. lpSubKey,
  1123. 0,
  1124. KEY_WRITE | KEY_READ,
  1125. &hKey);
  1126. if (lRet == ERROR_SUCCESS)
  1127. {
  1128. lRet = GetRegistryValue(hRootKey,
  1129. lpSubKey,
  1130. lpField[3], // Old value name
  1131. NULL,
  1132. &cbSize);
  1133. if (lRet == ERROR_SUCCESS)
  1134. {
  1135. DPF(REGinf, TEXT("Reset registry value name [%s]"), lpField[3]);
  1136. hr = AddRegValueRename(lpOutputKey,
  1137. lpField[3], // Old value name
  1138. lpField[4], // New value name
  1139. NULL,
  1140. NULL,
  1141. 0,
  1142. dwAttrib,
  1143. (LPTSTR) lpUserName);
  1144. if (FAILED(hr))
  1145. {
  1146. DPF(REGwar,
  1147. TEXT("Failed to add registry value name [%s] to defer change list"),
  1148. lpField[3]);
  1149. }
  1150. }
  1151. else if (lRet == ERROR_FILE_NOT_FOUND)
  1152. {
  1153. DPF(REGwar, TEXT("Value [%s] not found in registry"), lpField[3]);
  1154. hr = S_FALSE;
  1155. }
  1156. else
  1157. {
  1158. DPF(REGerr, TEXT("Failed to read value [%s]"), lpField[3]);
  1159. hr = HRESULT_FROM_WIN32(lRet);
  1160. }
  1161. RegCloseKey(hKey);
  1162. }
  1163. else if (lRet == ERROR_FILE_NOT_FOUND)
  1164. {
  1165. DPF(REGwar, TEXT("Key [%s] not found in registry"), lpOutputKey);
  1166. hr = S_FALSE;
  1167. }
  1168. else
  1169. {
  1170. DPF(REGerr, TEXT("Failed to open key [%s]"), lpOutputKey);
  1171. hr = HRESULT_FROM_WIN32(lRet);
  1172. }
  1173. }
  1174. return hr;
  1175. }
  1176. //-----------------------------------------------------------------------------
  1177. //
  1178. // Function: RegKeyNameReset
  1179. //
  1180. // Synopsis: Reset the key name in registry,
  1181. //
  1182. // Returns: S_OK if operation succeeded
  1183. //
  1184. // History: 03/15/2002 Rerkboos Created
  1185. //
  1186. // Notes: lpUserName can be NULL if this function is to reset per-system
  1187. // registry settings. Otherwise, lpUserName contains user name
  1188. // for the supplied hRootKey.
  1189. //
  1190. //-----------------------------------------------------------------------------
  1191. HRESULT RegKeyNameReset(
  1192. HKEY hRootKey, // Handle to root key
  1193. LPTSTR lpUserName, // (optional) name of user for current hRootKey
  1194. LPTSTR lpSubKey, // Sub key used to search in registry
  1195. LPTSTR lpOutputKey, // Output registry sub key to save in CLMTDO.inf
  1196. LPTSTR lpField[] // Pointer to field value from template file
  1197. )
  1198. {
  1199. HRESULT hr;
  1200. LONG lRet;
  1201. HKEY hKey;
  1202. HKEY hOldKey;
  1203. HKEY hNewKey;
  1204. // Do the key rename if old key name and new key name in INF are different
  1205. if (lstrcmpi(lpField[3], lpField[4]) == LSTR_EQUAL)
  1206. {
  1207. return S_FALSE;
  1208. }
  1209. // Check if we can access the subkey or not
  1210. lRet = RegOpenKeyEx(hRootKey,
  1211. lpSubKey,
  1212. 0,
  1213. KEY_READ | KEY_WRITE,
  1214. &hKey);
  1215. if (lRet == ERROR_SUCCESS)
  1216. {
  1217. // Check the existence of old registry key
  1218. lRet = RegOpenKeyEx(hKey,
  1219. lpField[3],
  1220. 0,
  1221. KEY_READ | KEY_WRITE,
  1222. &hOldKey);
  1223. if (lRet == ERROR_SUCCESS)
  1224. {
  1225. // Old reg key exists. Then, check the existence of new registry key
  1226. lRet = RegOpenKeyEx(hKey,
  1227. lpField[4],
  1228. 0,
  1229. KEY_READ,
  1230. &hNewKey);
  1231. if (lRet == ERROR_SUCCESS)
  1232. {
  1233. hr = S_FALSE;
  1234. RegCloseKey(hNewKey);
  1235. }
  1236. else if (lRet == ERROR_FILE_NOT_FOUND)
  1237. {
  1238. // New key does not exist, ok to rename the old reg key
  1239. hr = AddRegKeyRename(lpOutputKey,
  1240. lpField[3],
  1241. lpField[4],
  1242. lpUserName);
  1243. }
  1244. else
  1245. {
  1246. hr = HRESULT_FROM_WIN32(GetLastError());
  1247. DPF(REGerr, TEXT("Failed to open key [%s\\%s], hr = 0x%x"), lpSubKey, lpField[4], hr);
  1248. }
  1249. RegCloseKey(hOldKey);
  1250. }
  1251. else if (lRet == ERROR_FILE_NOT_FOUND)
  1252. {
  1253. hr = S_FALSE;
  1254. }
  1255. else
  1256. {
  1257. hr = HRESULT_FROM_WIN32(lRet);
  1258. DPF(REGerr, TEXT("Failed to open key [%s\\%s], hr = 0x%x"), lpSubKey, lpField[3], hr);
  1259. }
  1260. RegCloseKey(hKey);
  1261. }
  1262. else if (lRet == ERROR_FILE_NOT_FOUND)
  1263. {
  1264. hr = S_FALSE;
  1265. }
  1266. else
  1267. {
  1268. hr = HRESULT_FROM_WIN32(lRet);
  1269. DPF(REGerr, TEXT("Failed to open key [%s], hr = 0x%x"), lpSubKey, hr);
  1270. }
  1271. return hr;
  1272. }
  1273. //-----------------------------------------------------------------------------
  1274. //
  1275. // Function: ReadFieldFromContext
  1276. //
  1277. // Synopsis: Read fields from INFCONTEXT
  1278. //
  1279. // Returns: S_OK if succeeded
  1280. //
  1281. // History: 03/14/2001 Rerkboos Created
  1282. //
  1283. // Notes: Caller must free the memory allocated in lpField[]
  1284. //
  1285. //-----------------------------------------------------------------------------
  1286. HRESULT ReadFieldFromContext(
  1287. PINFCONTEXT lpContext, // INFCONTEXT for each line
  1288. LPWSTR lpField[], // Pointer point to each field
  1289. DWORD dwFirstField, // First field to read
  1290. DWORD dwLastField // Last field to read
  1291. )
  1292. {
  1293. HRESULT hr = S_OK;
  1294. DWORD dwFieldIndex;
  1295. DWORD cchField;
  1296. DWORD cchReqSize;
  1297. for (dwFieldIndex = 0 ; dwFieldIndex <= dwLastField ; dwFieldIndex++)
  1298. {
  1299. lpField[dwFieldIndex] = NULL;
  1300. }
  1301. //
  1302. // Read data INF context into field buffer
  1303. //
  1304. for (dwFieldIndex = dwFirstField ; dwFieldIndex <= dwLastField ; dwFieldIndex++)
  1305. {
  1306. // Get the require size big enough to store data
  1307. if (SetupGetStringField(lpContext,
  1308. dwFieldIndex,
  1309. NULL,
  1310. 0,
  1311. &cchField))
  1312. {
  1313. //Add one more space in case the string converted to MultiSZ
  1314. cchField ++;
  1315. lpField[dwFieldIndex] = (LPWSTR) MEMALLOC(cchField * sizeof(TCHAR));
  1316. if (lpField[dwFieldIndex] == NULL)
  1317. {
  1318. hr = E_OUTOFMEMORY;
  1319. break;
  1320. }
  1321. // Read data from INF to buffer
  1322. SetupGetStringField(lpContext,
  1323. dwFieldIndex,
  1324. lpField[dwFieldIndex],
  1325. cchField,
  1326. &cchReqSize);
  1327. }
  1328. else
  1329. {
  1330. hr = HRESULT_FROM_WIN32(GetLastError());
  1331. break;
  1332. }
  1333. }
  1334. // Free all the allocated memory if any error occured
  1335. if (FAILED(hr))
  1336. {
  1337. for (dwFieldIndex = 0 ; dwFieldIndex <= dwLastField ; dwFieldIndex++)
  1338. {
  1339. if (lpField[dwFieldIndex])
  1340. {
  1341. MEMFREE(lpField[dwFieldIndex]);
  1342. }
  1343. }
  1344. }
  1345. return hr;
  1346. }
  1347. //-----------------------------------------------------------------------------
  1348. //
  1349. // Function: GetRegistryValue
  1350. //
  1351. // Synopsis: Wrapper function to get registry value
  1352. //
  1353. // Returns: ERROR_SUCCESS if value is successefully get
  1354. //
  1355. // History: 03/14/2001 Rerkboos Created
  1356. //
  1357. // Notes: none
  1358. //
  1359. //-----------------------------------------------------------------------------
  1360. LONG GetRegistryValue(
  1361. HKEY hRootKey,
  1362. LPCTSTR lpSubKey,
  1363. LPCTSTR lpValueName,
  1364. LPBYTE lpBuffer,
  1365. LPDWORD lpcbBuffer
  1366. )
  1367. {
  1368. LONG lStatus;
  1369. HKEY hKey;
  1370. DWORD dwSize;
  1371. lStatus = RegOpenKeyEx(hRootKey,
  1372. lpSubKey,
  1373. 0,
  1374. KEY_READ,
  1375. &hKey);
  1376. if (lStatus == ERROR_SUCCESS)
  1377. {
  1378. dwSize = sizeof(DWORD);
  1379. lStatus = RegQueryValueEx(hKey,
  1380. lpValueName,
  1381. NULL,
  1382. NULL,
  1383. lpBuffer,
  1384. lpcbBuffer);
  1385. RegCloseKey(hKey);
  1386. }
  1387. return lStatus;
  1388. }
  1389. //-----------------------------------------------------------------------------
  1390. //
  1391. // Function: SetRegistryValue
  1392. //
  1393. // Synopsis: Wrapper function to set registry value
  1394. //
  1395. // Returns: ERROR_SUCCESS if value is successefully set
  1396. //
  1397. // History: 03/14/2001 Rerkboos Created
  1398. //
  1399. // Notes: none
  1400. //
  1401. //-----------------------------------------------------------------------------
  1402. LONG SetRegistryValue(
  1403. HKEY hRootKey,
  1404. LPCTSTR lpSubKey,
  1405. LPCTSTR lpValueName,
  1406. DWORD dwType,
  1407. LPBYTE lpData,
  1408. DWORD cbData
  1409. )
  1410. {
  1411. LONG lStatus;
  1412. HKEY hKey;
  1413. lStatus = RegCreateKeyEx(hRootKey,
  1414. lpSubKey,
  1415. 0,
  1416. NULL,
  1417. REG_OPTION_NON_VOLATILE,
  1418. KEY_WRITE,
  1419. NULL,
  1420. &hKey,
  1421. NULL);
  1422. if (lStatus == ERROR_SUCCESS)
  1423. {
  1424. lStatus = RegSetValueEx(hKey,
  1425. lpValueName,
  1426. 0,
  1427. dwType,
  1428. lpData,
  1429. cbData);
  1430. RegCloseKey(hKey);
  1431. }
  1432. return lStatus;
  1433. }
  1434. //--------------------------------------------------------------------------
  1435. //
  1436. // My_QueryValueEx
  1437. //
  1438. // wraps RegQueryValueEx and ensures that the returned string is NULL-
  1439. // terminated
  1440. //
  1441. //--------------------------------------------------------------------------
  1442. LONG My_QueryValueEx(
  1443. HKEY hKey, // handle to key
  1444. LPCTSTR lpValueName, // value name
  1445. LPDWORD lpReserved, // reserved
  1446. LPDWORD lpType, // type buffer
  1447. LPBYTE lpData, // data buffer
  1448. LPDWORD lpcbData // size of data buffer
  1449. )
  1450. {
  1451. DWORD dwMyType;
  1452. LONG lRes;
  1453. LPDWORD lpCurrType = &dwMyType;
  1454. DWORD cbOriginalDataSize = 0;
  1455. LPBYTE lpBuf = NULL;
  1456. if (lpType)
  1457. {
  1458. lpCurrType = lpType;
  1459. }
  1460. if (lpcbData)
  1461. {
  1462. cbOriginalDataSize = *lpcbData;
  1463. }
  1464. lRes = RegQueryValueEx(hKey, lpValueName, lpReserved, lpCurrType, lpData, lpcbData);
  1465. if (lRes == ERROR_SUCCESS
  1466. && IsRegStringType(*lpCurrType)
  1467. && lpcbData
  1468. && bIsValidRegStr(*lpCurrType,*lpcbData)
  1469. )
  1470. {
  1471. LPTSTR psz;
  1472. int cch = (int)(*lpcbData/sizeof(TCHAR));
  1473. if (!lpData) // in this case user is query the buffer size needed
  1474. {
  1475. lpBuf = (LPBYTE) calloc(*lpcbData, sizeof(BYTE));
  1476. if (!lpBuf) {
  1477. lRes = ERROR_NOT_ENOUGH_MEMORY;
  1478. goto Exit;
  1479. }
  1480. lRes = RegQueryValueEx(hKey, lpValueName, lpReserved, lpCurrType, lpBuf, lpcbData);
  1481. if (lRes != ERROR_SUCCESS)
  1482. goto Exit;
  1483. psz = (LPTSTR)lpBuf;
  1484. if (psz[cch-1])
  1485. *lpcbData += 2 * sizeof(TCHAR);
  1486. else if (psz[cch-2])
  1487. *lpcbData += sizeof(TCHAR);
  1488. }
  1489. else
  1490. {
  1491. psz = (LPTSTR)lpData;
  1492. if (REG_MULTI_SZ == *lpCurrType)
  1493. {
  1494. if (psz[cch-1])
  1495. {
  1496. if (*lpcbData >= (cbOriginalDataSize-sizeof(TCHAR)))
  1497. {
  1498. lRes = ERROR_MORE_DATA;
  1499. }
  1500. else
  1501. {
  1502. psz[cch] = 0;
  1503. psz[cch+1] = 0;
  1504. *lpcbData += 2 * sizeof(TCHAR);
  1505. }
  1506. }
  1507. else if (psz[cch-2])
  1508. {
  1509. if (*lpcbData >= cbOriginalDataSize)
  1510. {
  1511. lRes = ERROR_MORE_DATA;
  1512. }
  1513. else
  1514. {
  1515. psz[cch] = 0;
  1516. *lpcbData += sizeof(TCHAR);
  1517. }
  1518. }
  1519. }
  1520. else
  1521. {
  1522. if (psz[cch-1])
  1523. {
  1524. if (*lpcbData >= cbOriginalDataSize)
  1525. {
  1526. lRes = ERROR_MORE_DATA;
  1527. }
  1528. else
  1529. {
  1530. psz[cch] = 0;
  1531. *lpcbData += sizeof(TCHAR);
  1532. }
  1533. }
  1534. }
  1535. }
  1536. }
  1537. Exit:
  1538. if (lpBuf)
  1539. free (lpBuf);
  1540. return lRes;
  1541. }
  1542. BOOL bIsValidRegStr(
  1543. DWORD dwType,
  1544. DWORD cbLen)
  1545. {
  1546. if (!IsRegStringType(dwType))
  1547. {
  1548. return FALSE;
  1549. }
  1550. if (dwType == REG_MULTI_SZ)
  1551. {
  1552. if (cbLen < 2 * sizeof(TCHAR))
  1553. {
  1554. return FALSE;
  1555. }
  1556. }
  1557. else
  1558. {
  1559. if (cbLen < sizeof(TCHAR))
  1560. {
  1561. return FALSE;
  1562. }
  1563. }
  1564. #ifdef UNICODE
  1565. if ( (cbLen % sizeof(TCHAR)) == 1 )
  1566. {
  1567. return FALSE;
  1568. }
  1569. #endif
  1570. return TRUE;
  1571. }
  1572. LONG MyRegSetDWValue(
  1573. HKEY hRootKey, // Root key
  1574. LPCTSTR lpSubKeyName, // Sub key name under HKEY_Users\{user hive}
  1575. LPCTSTR lpValueName, // value name to be changed
  1576. LPCTSTR lpNewValue) // New value
  1577. {
  1578. LONG lRet;
  1579. HKEY hKey = NULL;
  1580. DWORD dwVal;
  1581. lRet = RegOpenKeyEx(hRootKey,
  1582. lpSubKeyName,
  1583. 0,
  1584. KEY_WRITE | KEY_READ,
  1585. &hKey);
  1586. if (ERROR_SUCCESS != lRet)
  1587. {
  1588. hKey = NULL;
  1589. goto exit;
  1590. }
  1591. dwVal = _tstoi(lpNewValue);
  1592. lRet = RegSetValueEx(hKey,lpValueName,0,REG_DWORD,(LPBYTE)&dwVal,sizeof(DWORD));
  1593. exit:
  1594. if (hKey)
  1595. {
  1596. RegCloseKey(hKey);
  1597. }
  1598. return lRet;
  1599. }
  1600. HRESULT RegWideMatchReset(
  1601. HKEY hRootKey, // Handle to root key
  1602. LPTSTR lpUserName, // (optional) name of user for current hRootKey
  1603. LPTSTR lpSubKey, // Sub key used to search in registry
  1604. LPTSTR lpOutputKey, // Output registry sub key to save in CLMTDO.inf
  1605. LPTSTR lpField[]) // Pointer to field value from template file
  1606. {
  1607. REG_STRING_REPLACE myTable;
  1608. HKEY hKey;
  1609. LONG lRet;
  1610. HRESULT hr;
  1611. hr = Sz2MultiSZ(lpField[3],TEXT(';'));
  1612. if (FAILED(hr))
  1613. {
  1614. goto exit;
  1615. }
  1616. hr = Sz2MultiSZ(lpField[4],TEXT(';'));
  1617. if (FAILED(hr))
  1618. {
  1619. goto exit;
  1620. }
  1621. hr = ConstructUIReplaceStringTable(lpField[3], lpField[4],&myTable);
  1622. if (FAILED(hr))
  1623. {
  1624. goto exit;
  1625. }
  1626. lRet = RegOpenKeyEx(hRootKey,
  1627. lpSubKey,
  1628. 0,
  1629. KEY_READ | KEY_WRITE,
  1630. &hKey);
  1631. if (ERROR_SUCCESS != lRet)
  1632. {
  1633. hr = HRESULT_FROM_WIN32(lRet);
  1634. goto exit;
  1635. }
  1636. hr = RegistryAnalyze(hKey,lpUserName,NULL,&myTable,NULL,0,lpOutputKey,FALSE);
  1637. exit:
  1638. return hr;
  1639. }