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.

736 lines
20 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. if(pbStack)
  377. {
  378. hr = HrRegQueryValueEx(hkey, arb->pszValueName, &dwRealType,
  379. pbStack, &cbData);
  380. }
  381. else
  382. {
  383. hr = E_OUTOFMEMORY;
  384. }
  385. if (S_OK == hr)
  386. {
  387. // Make sure its the type we were expecting.
  388. AssertSz((dwRealType == DwRealTypeFromPsuedoType(dwType)),
  389. "Value types do no match");
  390. TranslateFromRegToData(dwType, pbData, pbStack);
  391. }
  392. else
  393. {
  394. UseDefaultRegValue(dwType, pbData, arb->pbDefault);
  395. TraceHr (ttidError, FAL, hr,
  396. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr,
  397. "RegReadValues: Could not open value %S", arb->pszValueName);
  398. }
  399. #ifndef STACK_ALLOC_DOESNT_WORK
  400. MemFree (pbStack);
  401. #endif // STACK_ALLOC_DOESNT_WORK
  402. }
  403. }
  404. else
  405. {
  406. TraceTag(ttidError, "RegReadValues: NULL key for %S", arb->pszSubkey);
  407. UseDefaultRegValue(arb->dwType, pbData, arb->pbDefault);
  408. }
  409. // Advance prbLast or set it to the first one if this is the
  410. // first time through.
  411. if (prbLast)
  412. {
  413. prbLast++;
  414. }
  415. else
  416. {
  417. prbLast = arb;
  418. }
  419. arb++;
  420. }
  421. // Clean up
  422. RegSafeCloseKey(hkey);
  423. RegSafeCloseKeyArray(rghkeySpec, celems(rghkeySpec));
  424. return;
  425. }
  426. //+---------------------------------------------------------------------------
  427. //
  428. // Member: HrRegWriteValues
  429. //
  430. // Purpose: To write a table of information to the registry from a user
  431. // defined data structure.
  432. //
  433. // Arguments:
  434. // crb The count of entries in the REGBATCH structure
  435. // arb The pointer to the REGBATCH structure
  436. // pbUserData The pointer to the source structure that provides
  437. // the data that is to be written to the registry
  438. // dwOptions Options to be used when creating the registry keys
  439. // samDesired The requested key access mask
  440. //
  441. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  442. //
  443. // Author: CWill Apr 30 1997
  444. //
  445. // Notes:
  446. //
  447. HRESULT HrRegWriteValues(
  448. INT crb,
  449. const REGBATCH* arb,
  450. const BYTE* pbUserData,
  451. DWORD dwOptions,
  452. REGSAM samDesired)
  453. {
  454. AssertSz(FImplies(crb, arb), "HrWriteValues : Count with no array");
  455. HRESULT hr = S_OK;
  456. const REGBATCH* prbLast = NULL;
  457. HKEY hkey = NULL;
  458. HKEY rghkeySpec[celems(c_rgskmSpec)] = {0};
  459. while (crb--)
  460. {
  461. BYTE* pbData = const_cast<BYTE*>(pbUserData + arb->cbOffset);
  462. // Open the key if we need to.
  463. // We don't need to if it was the same as the previous one used.
  464. if ((!prbLast)
  465. || (prbLast->hkey != arb->hkey)
  466. || (prbLast->pszSubkey != arb->pszSubkey))
  467. {
  468. HKEY hkeyParent;
  469. hkeyParent = HkeyTrueParent(arb->hkey, samDesired, rghkeySpec);
  470. // Close the previous key we used.
  471. RegSafeCloseKey(hkey);
  472. // Open the new key.
  473. DWORD dwDisposition;
  474. hr = HrRegCreateKeyEx(hkeyParent, arb->pszSubkey, dwOptions,
  475. samDesired, NULL, &hkey, &dwDisposition);
  476. AssertSz(FImplies(FAILED(hr), !hkey), "HrRegCreateKey not NULLing");
  477. if (FAILED(hr))
  478. {
  479. TraceError("HrRegWriteValues: failed to open parent key", hr);
  480. break;
  481. }
  482. }
  483. // Should definately have hkey by now.
  484. AssertSz(hkey, "Why no key?");
  485. //
  486. // Format the data to be put into the registry
  487. //
  488. DWORD dwType = arb->dwType;
  489. // If all we want to do is create the key, then we are already done.
  490. if (REG_CREATE != dwType)
  491. {
  492. DWORD dwRealType = DwRealTypeFromPsuedoType(dwType);
  493. DWORD cbReg = CbSizeOfDataToReg(dwType, pbData);
  494. BYTE* pbReg = NULL;
  495. AssertSz(cbReg, "We must have some data");
  496. #ifndef STACK_ALLOC_DOESNT_WORK
  497. pbReg = new BYTE[cbReg];
  498. #else // !STACK_ALLOC_DOESNT_WORK
  499. pbReg = reinterpret_cast<BYTE*>(PvAllocOnStack(cbReg));
  500. #endif // !STACK_ALLOC_DOESNT_WORK
  501. if(!pbReg)
  502. {
  503. hr = E_OUTOFMEMORY;
  504. break;
  505. }
  506. TranslateFromDataToReg(dwType, pbData, pbReg);
  507. // Write the data to the registry.
  508. hr = HrRegSetValueEx(
  509. hkey,
  510. arb->pszValueName,
  511. dwRealType,
  512. pbReg,
  513. cbReg);
  514. #ifndef STACK_ALLOC_DOESNT_WORK
  515. // Must have this call before the break
  516. delete [] pbReg;
  517. #endif // STACK_ALLOC_DOESNT_WORK
  518. }
  519. if (FAILED(hr))
  520. {
  521. break;
  522. }
  523. // Advance prbLast or set it to the first one if this is the
  524. // first time through.
  525. if (prbLast)
  526. {
  527. prbLast++;
  528. }
  529. else
  530. {
  531. prbLast = arb;
  532. }
  533. arb++;
  534. }
  535. RegSafeCloseKey(hkey);
  536. RegSafeCloseKeyArray(rghkeySpec, celems(rghkeySpec));
  537. TraceError("HrWriteValues", hr);
  538. return hr;
  539. }
  540. //+---------------------------------------------------------------------------
  541. //
  542. // Member: HrRegWriteValueTable
  543. //
  544. // Purpose: To write a table of values to the registry from a user
  545. // defined data structure.
  546. //
  547. // Arguments:
  548. // hkeyRoot The key to which the values are written
  549. // cvt The count of entries in the VALUETABLE structure
  550. // avt The pointer to the VALUETABLE structure
  551. // pbUserData The pointer to the source structure that provides
  552. // the data that is to be written to the registry
  553. // dwOptions Options to be used when creating the registry keys
  554. // samDesired The requested key access mask
  555. //
  556. // Returns: S_OK or an HRESULT_FROM_WIN32 error code.
  557. //
  558. // Author: CWill 06/26/97
  559. //
  560. // Notes:
  561. //
  562. HRESULT HrRegWriteValueTable(
  563. HKEY hkeyRoot,
  564. INT cvt,
  565. const VALUETABLE* avt,
  566. const BYTE* pbUserData,
  567. DWORD dwOptions,
  568. REGSAM samDesired)
  569. {
  570. HRESULT hr = S_OK;
  571. while (cvt--)
  572. {
  573. BYTE* pbData = NULL;
  574. DWORD dwType = REG_NONE;
  575. //
  576. // Format the data to be put into the registry
  577. //
  578. dwType = avt->dwType;
  579. pbData = const_cast<BYTE*>(pbUserData + avt->cbOffset);
  580. // If all we want to do is create the key, then we are already done.
  581. if (REG_CREATE != dwType)
  582. {
  583. DWORD dwRealType = DwRealTypeFromPsuedoType(dwType);
  584. DWORD cbReg = CbSizeOfDataToReg(dwType, pbData);
  585. BYTE* pbReg = NULL;
  586. AssertSz(cbReg, "We must have some data");
  587. #ifndef STACK_ALLOC_DOESNT_WORK
  588. pbReg = new BYTE[cbReg];
  589. #else // !STACK_ALLOC_DOESNT_WORK
  590. pbReg = reinterpret_cast<BYTE*>(PvAllocOnStack(cbReg));
  591. #endif // !STACK_ALLOC_DOESNT_WORK
  592. if(!pbReg)
  593. {
  594. hr = E_OUTOFMEMORY;
  595. break;
  596. }
  597. TranslateFromDataToReg(dwType, pbData, pbReg);
  598. // Write the data to the registry.
  599. hr = HrRegSetValueEx(
  600. hkeyRoot,
  601. avt->pszValueName,
  602. dwRealType,
  603. pbReg,
  604. cbReg);
  605. #ifndef STACK_ALLOC_DOESNT_WORK
  606. // Must have this call before the break
  607. delete [] pbReg;
  608. #endif // STACK_ALLOC_DOESNT_WORK
  609. }
  610. if (FAILED(hr))
  611. {
  612. break;
  613. }
  614. avt++;
  615. }
  616. TraceError("HrRegWriteValueTable", hr);
  617. return hr;
  618. }