Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

717 lines
18 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997.
  5. //
  6. // File: N C R E G 2 . C P P
  7. //
  8. // Contents: Common routines for dealing with the registry.
  9. //
  10. // Notes:
  11. //
  12. // Author: CWill 27 Mar 1997
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.h>
  16. #pragma hdrstop
  17. #include "ncerror.h"
  18. #include "ncipaddr.h"
  19. #include "ncmem.h"
  20. #include "ncreg.h"
  21. #include "ncstring.h"
  22. #include <regstr.h>
  23. static const WCHAR c_szSubkeyServices[] = REGSTR_PATH_SERVICES;
  24. const struct REG_TYPE_MAP
  25. {
  26. DWORD dwPsuedoType;
  27. DWORD dwType;
  28. };
  29. REG_TYPE_MAP c_rgrtmTypes[] =
  30. {
  31. {REG_BOOL, REG_DWORD},
  32. {REG_IP, REG_SZ},
  33. };
  34. DWORD DwRealTypeFromPsuedoType(const DWORD dwPsuedoType)
  35. {
  36. for (UINT cLoop = 0; cLoop < celems(c_rgrtmTypes); cLoop++)
  37. {
  38. if (dwPsuedoType == c_rgrtmTypes[cLoop].dwPsuedoType)
  39. {
  40. return c_rgrtmTypes[cLoop].dwType;
  41. }
  42. }
  43. return dwPsuedoType;
  44. }
  45. struct SPECIAL_KEY_MAP
  46. {
  47. HKEY hkeyPseudo;
  48. HKEY hkeyRoot;
  49. PCWSTR pszSubKey;
  50. };
  51. static const SPECIAL_KEY_MAP c_rgskmSpec[] =
  52. {
  53. HKLM_SVCS, HKEY_LOCAL_MACHINE, c_szSubkeyServices,
  54. };
  55. //+---------------------------------------------------------------------------
  56. //
  57. // Member: HkeyTrueParent
  58. //
  59. // Purpose: To get a real handle to a key from a pseudo handle
  60. //
  61. // Arguments:
  62. // hkeyIn The pseudo key name
  63. // samDesired The access requested of the key
  64. // rghkeySpec An array of the special keys.
  65. //
  66. // Returns: The handle to the opened key or NULL
  67. //
  68. // Author: CWill Apr 30 1997
  69. //
  70. // Notes:
  71. //
  72. HKEY HkeyTrueParent(const HKEY hkeyIn, const REGSAM samDesired,
  73. HKEY rghkeySpec[])
  74. {
  75. HKEY hkeyRet = hkeyIn;
  76. for (UINT cKey = 0; cKey < celems(c_rgskmSpec); cKey++)
  77. {
  78. // Check arb->hkey for one of "our" well known keys.
  79. if (c_rgskmSpec[cKey].hkeyPseudo == hkeyIn)
  80. {
  81. if (!rghkeySpec[cKey])
  82. {
  83. // First time a special key was used. We need to cache it.
  84. #ifdef DBG
  85. HRESULT hr =
  86. #endif // DBG
  87. HrRegOpenKeyEx(
  88. c_rgskmSpec[cKey].hkeyRoot,
  89. c_rgskmSpec[cKey].pszSubKey,
  90. samDesired,
  91. &rghkeySpec[cKey]);
  92. // If we fail to open the key, make sure the output
  93. // parameter was nulled. This will allow us to proceed
  94. // without really handling the error as hkeyParent
  95. // will be set to null below and the following
  96. // HrRegOpenKey will fail. We will then handle the failure
  97. // of that.
  98. AssertSz(FImplies(FAILED(hr), !rghkeySpec[cKey]), "Key not NULL");
  99. }
  100. hkeyRet = rghkeySpec[cKey];
  101. break;
  102. }
  103. }
  104. return hkeyRet;
  105. }
  106. VOID RegSafeCloseKeyArray(HKEY rghkey[], UINT cElems)
  107. {
  108. for (UINT cKey = 0; cKey < cElems; cKey++)
  109. {
  110. RegSafeCloseKey(rghkey[cKey]);
  111. }
  112. return;
  113. }
  114. //+---------------------------------------------------------------------------
  115. //
  116. // Member: TranslateFromRegToData
  117. //
  118. // Purpose: Translates the data retrieved from the registry to a the user
  119. // data's storage format
  120. //
  121. // Arguments:
  122. // dwType The registry pseudo type that is being translated
  123. // pbData Where the data gets stored
  124. // pbBuf A buffer that stores the registry data
  125. //
  126. // Returns: Nothing.
  127. //
  128. // Author: CWill Apr 30 1997
  129. //
  130. // Notes:
  131. //
  132. VOID TranslateFromRegToData(DWORD dwType, BYTE* pbData, BYTE* pbBuf)
  133. {
  134. // Take the data from the registry and happily convert it into
  135. // usable data
  136. switch (dwType)
  137. {
  138. #ifdef DBG
  139. default:
  140. {
  141. AssertSz(FALSE, "Unknown registry type");
  142. break;
  143. }
  144. #endif // DBG
  145. case REG_IP:
  146. {
  147. // Convert the stringized form of the ip address
  148. // into a DWORD. (The actual 32-bit IP address.)
  149. DWORD dwIpAddr = IpPszToHostAddr((WCHAR*)pbBuf);
  150. *((DWORD*)pbData) = dwIpAddr;
  151. break;
  152. }
  153. case REG_BOOL:
  154. {
  155. // Form the boolean as 'TRUE' or 'FALSE' based on
  156. // whether the data is non-zero or zero respectively.
  157. DWORD dwData = *((DWORD*)pbBuf);
  158. *((BOOL*)pbData) = (!!dwData);
  159. break;
  160. }
  161. case REG_DWORD:
  162. {
  163. // DWORDs are direct assignments
  164. *((DWORD*)pbData) = *((DWORD*)pbBuf);
  165. break;
  166. }
  167. case REG_SZ:
  168. {
  169. // Make a copy of the string
  170. *((PWSTR*) pbData) = SzDupSz((PWSTR)pbBuf);
  171. break;
  172. }
  173. }
  174. return;
  175. }
  176. inline VOID UseDefaultRegValue(DWORD dwType, BYTE* pbData, BYTE* pbDefault)
  177. {
  178. AssertSz((pbData && pbDefault), "UseDefaultRegValue : Invalid params");
  179. AssertSz(pbDefault, "There is no default registry value");
  180. TranslateFromRegToData(dwType, pbData, pbDefault);
  181. return;
  182. }
  183. //+---------------------------------------------------------------------------
  184. //
  185. // Member: CbSizeOfDataToReg
  186. //
  187. // Purpose: To determine the size of buffer needed to store the data
  188. //
  189. // Arguments:
  190. // dwType The registry pseudo type that is being translated
  191. // pbData The data that has to be translated
  192. //
  193. // Returns: The size of buffer need to store the data
  194. //
  195. // Author: CWill Apr 30 1997
  196. //
  197. // Notes:
  198. //
  199. DWORD CbSizeOfDataToReg(DWORD dwType, const BYTE* pbData)
  200. {
  201. DWORD cbData = 0;
  202. switch (dwType)
  203. {
  204. #ifdef DBG
  205. default:
  206. {
  207. AssertSz(FALSE, "Unknown registry type");
  208. break;
  209. }
  210. #endif // DBG
  211. case REG_IP:
  212. {
  213. // Convert the 32-bit IP address to a stringized form.
  214. DWORD dwIpAddr = *((DWORD*)pbData);
  215. WCHAR pszIpAddr [32];
  216. IpHostAddrToPsz(dwIpAddr, pszIpAddr);
  217. cbData = CbOfSzAndTerm(pszIpAddr);
  218. break;
  219. }
  220. // Boolean values are stored as DWORDs
  221. case REG_BOOL:
  222. case REG_DWORD:
  223. {
  224. cbData = sizeof(DWORD);
  225. break;
  226. }
  227. case REG_SZ:
  228. case REG_EXPAND_SZ:
  229. {
  230. cbData = CbOfSzAndTerm(*((PCWSTR*)pbData));
  231. break;
  232. }
  233. }
  234. AssertSz(cbData, "We should have a size");
  235. return cbData;
  236. }
  237. //+---------------------------------------------------------------------------
  238. //
  239. // Member: TranslateFromDataToReg
  240. //
  241. // Purpose: Translates user data to a format the can be stored in the
  242. // registry
  243. //
  244. // Arguments:
  245. // dwType The registry pseudo type that is being translated
  246. // pbData The data that has to be translated
  247. // pbBuf A buffer that stores the registry data
  248. //
  249. // Returns: Nothing.
  250. //
  251. // Author: CWill Apr 30 1997
  252. //
  253. // Notes:
  254. //
  255. VOID
  256. TranslateFromDataToReg(
  257. IN DWORD dwType,
  258. IN const BYTE* pbData,
  259. OUT const BYTE* pbBuf)
  260. {
  261. switch (dwType)
  262. {
  263. #ifdef DBG
  264. default:
  265. {
  266. AssertSz(FALSE, "Unknown registry type");
  267. break;
  268. }
  269. #endif // DBG
  270. case REG_IP:
  271. {
  272. // Convert the 32-bit IP address to a stringized form.
  273. DWORD dwIpAddr = *((DWORD*)pbData);
  274. WCHAR pszIpAddr [32];
  275. IpHostAddrToPsz (dwIpAddr, pszIpAddr);
  276. // Copy the string
  277. lstrcpyW((PWSTR)pbBuf, pszIpAddr);
  278. break;
  279. }
  280. case REG_BOOL:
  281. {
  282. // Form the boolean as 'TRUE' or 'FALSE' based on
  283. // whether the data is non-zero or zero respectively.
  284. DWORD dwData = *((DWORD*)pbData);
  285. *((BOOL*)pbBuf) = (!!dwData);
  286. break;
  287. }
  288. case REG_DWORD:
  289. {
  290. // DWORDs are direct assignments
  291. *((DWORD*)pbBuf) = *((DWORD*)pbData);
  292. break;
  293. }
  294. case REG_SZ:
  295. case REG_EXPAND_SZ:
  296. {
  297. // Make a copy of the string
  298. lstrcpyW((PWSTR)pbBuf, *((PCWSTR*)pbData));
  299. AssertSz(CbOfSzAndTerm(*((PCWSTR*)pbData)), "Zero length string");
  300. break;
  301. }
  302. }
  303. return;
  304. }
  305. //+---------------------------------------------------------------------------
  306. //
  307. // Member: RegReadValues
  308. //
  309. // Purpose: To read a table of information from the registry into a user
  310. // defined data structure.
  311. //
  312. // Arguments:
  313. // crb The count of entries in the REGBATCH structure
  314. // arb The pointer to the REGBATCH structure
  315. // pbUserData The pointer to the source structure that is to retrieve
  316. // the data from the registry
  317. // samDesired The requested key access mask
  318. //
  319. // Returns: Nothing.
  320. //
  321. // Author: CWill Apr 30 1997
  322. //
  323. // Notes:
  324. //
  325. VOID RegReadValues(
  326. IN INT crb,
  327. IN const REGBATCH* arb,
  328. OUT const BYTE* pbUserData,
  329. IN REGSAM samDesired)
  330. {
  331. AssertSz(FImplies(crb, arb), "Count without an array");
  332. HRESULT hr = S_OK;
  333. const REGBATCH* prbLast = NULL;
  334. HKEY rghkeySpec[celems(c_rgskmSpec)] = {0};
  335. HKEY hkey = NULL;
  336. while (crb--)
  337. {
  338. BYTE* pbData = (BYTE*)(pbUserData + arb->cbOffset);
  339. // Open the key if we need to.
  340. // We don't need to if it was the same as the previous one used.
  341. if ((!prbLast )
  342. || (prbLast->hkey != arb->hkey)
  343. || (prbLast->pszSubkey != arb->pszSubkey))
  344. {
  345. HKEY hkeyParent;
  346. hkeyParent = HkeyTrueParent (arb->hkey, samDesired, rghkeySpec);
  347. // Close the previous key we used.
  348. RegSafeCloseKey (hkey);
  349. // Open the new key.
  350. #ifdef DBG
  351. hr =
  352. #endif // DBG
  353. HrRegOpenKeyEx (hkeyParent, arb->pszSubkey, samDesired, &hkey);
  354. AssertSz(FImplies(FAILED(hr), !hkey), "HrRegOpenKey not NULLing");
  355. }
  356. // Only continue if we have a key.
  357. if (hkey)
  358. {
  359. DWORD dwType = arb->dwType;
  360. // We can't read NULL registry values
  361. if (REG_CREATE != dwType)
  362. {
  363. DWORD cbData = 0;
  364. BYTE* pbStack = NULL;
  365. DWORD dwRealType = DwRealTypeFromPsuedoType(dwType);
  366. // Ensure that we fail the first time around so that we can see how
  367. // big a buffer is needed
  368. (VOID) HrRegQueryValueEx(hkey, arb->pszValueName, &dwRealType,
  369. NULL, &cbData);
  370. // Allocate memory on the stack to serve as our temporary buffer.
  371. #ifndef STACK_ALLOC_DOESNT_WORK
  372. pbStack = (BYTE*)MemAlloc (cbData);
  373. #else // !STACK_ALLOC_DOESNT_WORK
  374. pbStack = (BYTE*)PvAllocOnStack(cbData);
  375. #endif // !STACK_ALLOC_DOESNT_WORK
  376. hr = HrRegQueryValueEx(hkey, arb->pszValueName, &dwRealType,
  377. pbStack, &cbData);
  378. if (S_OK == hr)
  379. {
  380. // Make sure its the type we were expecting.
  381. AssertSz((dwRealType == DwRealTypeFromPsuedoType(dwType)),
  382. "Value types do no match");
  383. TranslateFromRegToData(dwType, pbData, pbStack);
  384. }
  385. else
  386. {
  387. UseDefaultRegValue(dwType, pbData, arb->pbDefault);
  388. TraceHr (ttidError, FAL, hr,
  389. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr,
  390. "RegReadValues: Could not open value %S", arb->pszValueName);
  391. }
  392. #ifndef STACK_ALLOC_DOESNT_WORK
  393. MemFree (pbStack);
  394. #endif // STACK_ALLOC_DOESNT_WORK
  395. }
  396. }
  397. else
  398. {
  399. TraceTag(ttidError, "RegReadValues: NULL key for %S", arb->pszSubkey);
  400. UseDefaultRegValue(arb->dwType, pbData, arb->pbDefault);
  401. }
  402. // Advance prbLast or set it to the first one if this is the
  403. // first time through.
  404. if (prbLast)
  405. {
  406. prbLast++;
  407. }
  408. else
  409. {
  410. prbLast = arb;
  411. }
  412. arb++;
  413. }
  414. // Clean up
  415. RegSafeCloseKey(hkey);
  416. RegSafeCloseKeyArray(rghkeySpec, celems(rghkeySpec));
  417. return;
  418. }
  419. //+---------------------------------------------------------------------------
  420. //
  421. // Member: HrRegWriteValues
  422. //
  423. // Purpose: To write a table of information to the registry from a user
  424. // defined data structure.
  425. //
  426. // Arguments:
  427. // crb The count of entries in the REGBATCH structure
  428. // arb The pointer to the REGBATCH structure
  429. // pbUserData The pointer to the source structure that provides
  430. // the data that is to be written to the registry
  431. // dwOptions Options to be used when creating the registry keys
  432. // samDesired The requested key access mask
  433. //
  434. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  435. //
  436. // Author: CWill Apr 30 1997
  437. //
  438. // Notes:
  439. //
  440. HRESULT HrRegWriteValues(
  441. INT crb,
  442. const REGBATCH* arb,
  443. const BYTE* pbUserData,
  444. DWORD dwOptions,
  445. REGSAM samDesired)
  446. {
  447. AssertSz(FImplies(crb, arb), "HrWriteValues : Count with no array");
  448. HRESULT hr = S_OK;
  449. const REGBATCH* prbLast = NULL;
  450. HKEY hkey = NULL;
  451. HKEY rghkeySpec[celems(c_rgskmSpec)] = {0};
  452. while (crb--)
  453. {
  454. BYTE* pbData = const_cast<BYTE*>(pbUserData + arb->cbOffset);
  455. // Open the key if we need to.
  456. // We don't need to if it was the same as the previous one used.
  457. if ((!prbLast)
  458. || (prbLast->hkey != arb->hkey)
  459. || (prbLast->pszSubkey != arb->pszSubkey))
  460. {
  461. HKEY hkeyParent;
  462. hkeyParent = HkeyTrueParent(arb->hkey, samDesired, rghkeySpec);
  463. // Close the previous key we used.
  464. RegSafeCloseKey(hkey);
  465. // Open the new key.
  466. DWORD dwDisposition;
  467. hr = HrRegCreateKeyEx(hkeyParent, arb->pszSubkey, dwOptions,
  468. samDesired, NULL, &hkey, &dwDisposition);
  469. AssertSz(FImplies(FAILED(hr), !hkey), "HrRegCreateKey not NULLing");
  470. if (FAILED(hr))
  471. {
  472. TraceError("HrRegWriteValues: failed to open parent key", hr);
  473. break;
  474. }
  475. }
  476. // Should definately have hkey by now.
  477. AssertSz(hkey, "Why no key?");
  478. //
  479. // Format the data to be put into the registry
  480. //
  481. DWORD dwType = arb->dwType;
  482. // If all we want to do is create the key, then we are already done.
  483. if (REG_CREATE != dwType)
  484. {
  485. DWORD dwRealType = DwRealTypeFromPsuedoType(dwType);
  486. DWORD cbReg = CbSizeOfDataToReg(dwType, pbData);
  487. BYTE* pbReg = NULL;
  488. AssertSz(cbReg, "We must have some data");
  489. #ifndef STACK_ALLOC_DOESNT_WORK
  490. pbReg = new BYTE[cbReg];
  491. #else // !STACK_ALLOC_DOESNT_WORK
  492. pbReg = reinterpret_cast<BYTE*>(PvAllocOnStack(cbReg));
  493. #endif // !STACK_ALLOC_DOESNT_WORK
  494. TranslateFromDataToReg(dwType, pbData, pbReg);
  495. // Write the data to the registry.
  496. hr = HrRegSetValueEx(
  497. hkey,
  498. arb->pszValueName,
  499. dwRealType,
  500. pbReg,
  501. cbReg);
  502. #ifndef STACK_ALLOC_DOESNT_WORK
  503. // Must have this call before the break
  504. delete [] pbReg;
  505. #endif // STACK_ALLOC_DOESNT_WORK
  506. }
  507. if (FAILED(hr))
  508. {
  509. break;
  510. }
  511. // Advance prbLast or set it to the first one if this is the
  512. // first time through.
  513. if (prbLast)
  514. {
  515. prbLast++;
  516. }
  517. else
  518. {
  519. prbLast = arb;
  520. }
  521. arb++;
  522. }
  523. RegSafeCloseKey(hkey);
  524. RegSafeCloseKeyArray(rghkeySpec, celems(rghkeySpec));
  525. TraceError("HrWriteValues", hr);
  526. return hr;
  527. }
  528. //+---------------------------------------------------------------------------
  529. //
  530. // Member: HrRegWriteValueTable
  531. //
  532. // Purpose: To write a table of values to the registry from a user
  533. // defined data structure.
  534. //
  535. // Arguments:
  536. // hkeyRoot The key to which the values are written
  537. // cvt The count of entries in the VALUETABLE structure
  538. // avt The pointer to the VALUETABLE structure
  539. // pbUserData The pointer to the source structure that provides
  540. // the data that is to be written to the registry
  541. // dwOptions Options to be used when creating the registry keys
  542. // samDesired The requested key access mask
  543. //
  544. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  545. //
  546. // Author: CWill 06/26/97
  547. //
  548. // Notes:
  549. //
  550. HRESULT HrRegWriteValueTable(
  551. HKEY hkeyRoot,
  552. INT cvt,
  553. const VALUETABLE* avt,
  554. const BYTE* pbUserData,
  555. DWORD dwOptions,
  556. REGSAM samDesired)
  557. {
  558. HRESULT hr = S_OK;
  559. while (cvt--)
  560. {
  561. BYTE* pbData = NULL;
  562. DWORD dwType = REG_NONE;
  563. //
  564. // Format the data to be put into the registry
  565. //
  566. dwType = avt->dwType;
  567. pbData = const_cast<BYTE*>(pbUserData + avt->cbOffset);
  568. // If all we want to do is create the key, then we are already done.
  569. if (REG_CREATE != dwType)
  570. {
  571. DWORD dwRealType = DwRealTypeFromPsuedoType(dwType);
  572. DWORD cbReg = CbSizeOfDataToReg(dwType, pbData);
  573. BYTE* pbReg = NULL;
  574. AssertSz(cbReg, "We must have some data");
  575. #ifndef STACK_ALLOC_DOESNT_WORK
  576. pbReg = new BYTE[cbReg];
  577. #else // !STACK_ALLOC_DOESNT_WORK
  578. pbReg = reinterpret_cast<BYTE*>(PvAllocOnStack(cbReg));
  579. #endif // !STACK_ALLOC_DOESNT_WORK
  580. TranslateFromDataToReg(dwType, pbData, pbReg);
  581. // Write the data to the registry.
  582. hr = HrRegSetValueEx(
  583. hkeyRoot,
  584. avt->pszValueName,
  585. dwRealType,
  586. pbReg,
  587. cbReg);
  588. #ifndef STACK_ALLOC_DOESNT_WORK
  589. // Must have this call before the break
  590. delete [] pbReg;
  591. #endif // STACK_ALLOC_DOESNT_WORK
  592. }
  593. if (FAILED(hr))
  594. {
  595. break;
  596. }
  597. avt++;
  598. }
  599. TraceError("HrRegWriteValueTable", hr);
  600. return hr;
  601. }