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.

2688 lines
64 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: reg.cpp
  7. //
  8. // Contents: Cert Server wrapper routines
  9. //
  10. //---------------------------------------------------------------------------
  11. #include <pch.cpp>
  12. #pragma hdrstop
  13. #include <sddl.h>
  14. #include <assert.h>
  15. #include "certacl.h"
  16. #include "polreg.h"
  17. #define __dwFILE__ __dwFILE_CERTLIB_REG_CPP__
  18. HRESULT
  19. myFormCertRegPath(
  20. IN WCHAR const *pwszName1,
  21. IN WCHAR const *pwszName2,
  22. IN WCHAR const *pwszName3,
  23. IN BOOL fConfigLevel, // from CertSrv if FALSE
  24. OUT WCHAR **ppwszPath)
  25. {
  26. HRESULT hr;
  27. WCHAR *pwszPath = NULL;
  28. DWORD len1;
  29. DWORD len2;
  30. DWORD len3;
  31. len1 = NULL != pwszName1 ? wcslen(pwszName1) + 1 : 0;
  32. len2 = 0 != len1 && NULL != pwszName2 ? wcslen(pwszName2) + 1 : 0;
  33. len3 = 0 != len2 && NULL != pwszName3 ? wcslen(pwszName3) + 1 : 0;
  34. pwszPath = (WCHAR*)LocalAlloc(
  35. LMEM_FIXED | LMEM_ZEROINIT,
  36. ((fConfigLevel?
  37. WSZARRAYSIZE(wszREGKEYCONFIGPATH) :
  38. WSZARRAYSIZE(wszREGKEYCERTSVCPATH)) +
  39. len1 +
  40. len2 +
  41. len3 +
  42. 1) * sizeof(WCHAR));
  43. if (NULL == pwszPath)
  44. {
  45. hr = E_OUTOFMEMORY;
  46. _JumpError(hr, error, "LocalAlloc");
  47. }
  48. wcscpy(pwszPath, fConfigLevel? wszREGKEYCONFIGPATH : wszREGKEYCERTSVCPATH);
  49. if (NULL != pwszName1)
  50. {
  51. wcscat(pwszPath, L"\\");
  52. wcscat(pwszPath, pwszName1);
  53. if (NULL != pwszName2)
  54. {
  55. wcscat(pwszPath, L"\\");
  56. wcscat(pwszPath, pwszName2);
  57. if (NULL != pwszName3)
  58. {
  59. wcscat(pwszPath, L"\\");
  60. wcscat(pwszPath, pwszName3);
  61. }
  62. }
  63. }
  64. *ppwszPath = pwszPath;
  65. pwszPath = NULL;
  66. hr = S_OK;
  67. error:
  68. if (NULL != pwszPath)
  69. {
  70. LocalFree(pwszPath);
  71. }
  72. CSASSERT(S_OK == hr || FAILED(hr));
  73. return(hr);
  74. }
  75. HRESULT
  76. myDeleteCertRegValueEx(
  77. OPTIONAL IN WCHAR const *pwszName1,
  78. OPTIONAL IN WCHAR const *pwszName2,
  79. OPTIONAL IN WCHAR const *pwszName3,
  80. OPTIONAL IN WCHAR const *pwszValueName,
  81. IN BOOL fAbsolutePath)
  82. {
  83. HRESULT hr;
  84. HKEY hKey = NULL;
  85. WCHAR *pwszTemp = NULL;
  86. if (!fAbsolutePath)
  87. {
  88. hr = myFormCertRegPath(pwszName1, pwszName2, pwszName3, TRUE, &pwszTemp);
  89. _JumpIfError(hr, error, "myFormCertRegPath");
  90. }
  91. else
  92. {
  93. CSASSERT(NULL == pwszName2 && NULL == pwszName3);
  94. }
  95. hr = RegOpenKeyEx(
  96. HKEY_LOCAL_MACHINE,
  97. fAbsolutePath ? pwszName1 : pwszTemp,
  98. 0,
  99. KEY_ALL_ACCESS,
  100. &hKey);
  101. _JumpIfError(hr, error, "RegOpenKeyEx");
  102. hr = RegDeleteValue(hKey, pwszValueName);
  103. if ((HRESULT) ERROR_FILE_NOT_FOUND != hr)
  104. {
  105. _JumpIfError(hr, error, "RegDeleteValue");
  106. }
  107. hr = S_OK;
  108. error:
  109. if (NULL != pwszTemp)
  110. {
  111. LocalFree(pwszTemp);
  112. }
  113. if (NULL != hKey)
  114. {
  115. RegCloseKey(hKey);
  116. }
  117. return(myHError(hr));
  118. }
  119. HRESULT
  120. myDeleteCertRegValue(
  121. OPTIONAL IN WCHAR const *pwszName1,
  122. OPTIONAL IN WCHAR const *pwszName2,
  123. OPTIONAL IN WCHAR const *pwszName3,
  124. OPTIONAL IN WCHAR const *pwszValueName)
  125. {
  126. return myDeleteCertRegValueEx(pwszName1,
  127. pwszName2,
  128. pwszName3,
  129. pwszValueName,
  130. FALSE);
  131. }
  132. HRESULT
  133. myDeleteCertRegKeyEx(
  134. OPTIONAL IN WCHAR const *pwszName1,
  135. OPTIONAL IN WCHAR const *pwszName2,
  136. OPTIONAL IN WCHAR const *pwszName3,
  137. IN BOOL fConfigLevel)
  138. {
  139. HRESULT hr;
  140. WCHAR *pwszTemp = NULL;
  141. hr = myFormCertRegPath(pwszName1, pwszName2, pwszName3, fConfigLevel, &pwszTemp);
  142. _JumpIfError(hr, error, "myFormCertRegPath");
  143. hr = RegDeleteKey(
  144. HKEY_LOCAL_MACHINE,
  145. pwszTemp);
  146. _JumpIfError(hr, error, "RegDeleteKey");
  147. hr = S_OK;
  148. error:
  149. if (NULL != pwszTemp)
  150. {
  151. LocalFree(pwszTemp);
  152. }
  153. return(myHError(hr));
  154. }
  155. HRESULT
  156. myDeleteCertRegKey(
  157. OPTIONAL IN WCHAR const *pwszName1,
  158. OPTIONAL IN WCHAR const *pwszName2,
  159. OPTIONAL IN WCHAR const *pwszName3)
  160. {
  161. return myDeleteCertRegKeyEx(pwszName1, pwszName2, pwszName3, TRUE);
  162. }
  163. HRESULT
  164. myCreateCertRegKeyEx(
  165. IN BOOL fSetAcl,
  166. OPTIONAL IN WCHAR const *pwszName1,
  167. OPTIONAL IN WCHAR const *pwszName2,
  168. OPTIONAL IN WCHAR const *pwszName3)
  169. {
  170. HRESULT hr;
  171. HKEY hKey = NULL;
  172. DWORD dwDisposition;
  173. WCHAR *pwszTemp = NULL;
  174. PSECURITY_DESCRIPTOR pSD = NULL;
  175. hr = myFormCertRegPath(pwszName1, pwszName2, pwszName3, TRUE, &pwszTemp);
  176. _JumpIfError(hr, error, "myFormCertRegPath");
  177. hr = RegCreateKeyEx(
  178. HKEY_LOCAL_MACHINE,
  179. pwszTemp,
  180. 0,
  181. NULL,
  182. REG_OPTION_NON_VOLATILE,
  183. KEY_ALL_ACCESS,
  184. NULL,
  185. &hKey,
  186. &dwDisposition);
  187. _JumpIfError(hr, error, "RegCreateKeyEx");
  188. if (fSetAcl)
  189. {
  190. // construct correct reg acl for the key if upgrade
  191. hr = myGetSDFromTemplate(WSZ_DEFAULT_UPGRADE_SECURITY,
  192. NULL,
  193. &pSD);
  194. if (S_OK == hr)
  195. {
  196. // set to correct acl
  197. hr = RegSetKeySecurity(hKey,
  198. DACL_SECURITY_INFORMATION,
  199. pSD);
  200. _PrintIfErrorStr(hr, "RegSetKeySecurity", pwszTemp);
  201. }
  202. else
  203. {
  204. _PrintErrorStr(hr, "myGetSDFromTemplate", pwszTemp);
  205. }
  206. }
  207. hr = S_OK;
  208. error:
  209. if (NULL != pwszTemp)
  210. {
  211. LocalFree(pwszTemp);
  212. }
  213. if (NULL != hKey)
  214. {
  215. RegCloseKey(hKey);
  216. }
  217. if (NULL != pSD)
  218. {
  219. LocalFree(pSD);
  220. }
  221. return(myHError(hr));
  222. }
  223. HRESULT
  224. myCreateCertRegKey(
  225. OPTIONAL IN WCHAR const *pwszName1,
  226. OPTIONAL IN WCHAR const *pwszName2,
  227. OPTIONAL IN WCHAR const *pwszName3)
  228. {
  229. return myCreateCertRegKeyEx(FALSE, // not upgrade
  230. pwszName1,
  231. pwszName2,
  232. pwszName3);
  233. }
  234. HRESULT
  235. mySetCertRegValueEx(
  236. OPTIONAL IN WCHAR const *pwszMachine,
  237. OPTIONAL IN WCHAR const *pwszName1,
  238. OPTIONAL IN WCHAR const *pwszName2,
  239. OPTIONAL IN WCHAR const *pwszName3,
  240. IN BOOL fConfigLevel,
  241. OPTIONAL IN WCHAR const *pwszValueName,
  242. IN DWORD const dwValueType,
  243. IN BYTE const *pbData,
  244. IN DWORD const cbData,
  245. IN BOOL fAbsolutePath)
  246. {
  247. HRESULT hr;
  248. HKEY hKey = NULL;
  249. WCHAR *pwszTemp = NULL;
  250. DWORD dwDisposition;
  251. HKEY hBaseKey = NULL;
  252. DWORD cbD = cbData;
  253. if (!fAbsolutePath)
  254. {
  255. hr = myFormCertRegPath(pwszName1, pwszName2, pwszName3, fConfigLevel, &pwszTemp);
  256. _JumpIfError(hr, error, "myFormCertRegPath");
  257. }
  258. if (pwszMachine)
  259. {
  260. hr = RegConnectRegistry(pwszMachine, HKEY_LOCAL_MACHINE, &hBaseKey);
  261. _JumpIfErrorStr(hr, error, "RegConnectRegistry", pwszMachine);
  262. }
  263. else
  264. hBaseKey = HKEY_LOCAL_MACHINE;
  265. hr = RegCreateKeyEx(
  266. hBaseKey,
  267. fAbsolutePath ? pwszName1 : pwszTemp,
  268. 0,
  269. NULL,
  270. REG_OPTION_NON_VOLATILE,
  271. KEY_ALL_ACCESS,
  272. NULL,
  273. &hKey,
  274. &dwDisposition);
  275. _JumpIfError(hr, error, "RegCreateKeyEx");
  276. if (NULL != pwszValueName)
  277. {
  278. if(NULL == pbData || 0 == cbData)
  279. {
  280. switch(dwValueType)
  281. {
  282. case REG_EXPAND_SZ:
  283. case REG_SZ:
  284. pbData = (BYTE*) L"";
  285. cbD = sizeof (L"");
  286. break;
  287. case REG_MULTI_SZ:
  288. pbData = (BYTE*) L"\0";
  289. cbD = sizeof (L"\0");
  290. break;
  291. }
  292. }
  293. hr = RegSetValueEx(
  294. hKey,
  295. pwszValueName,
  296. 0,
  297. dwValueType,
  298. pbData,
  299. cbD);
  300. _JumpIfError(hr, error, "RegSetValueEx");
  301. }
  302. hr = S_OK;
  303. error:
  304. if ((NULL != hBaseKey) && (HKEY_LOCAL_MACHINE != hBaseKey))
  305. {
  306. RegCloseKey(hBaseKey);
  307. }
  308. if (NULL != pwszTemp)
  309. {
  310. LocalFree(pwszTemp);
  311. }
  312. if (NULL != hKey)
  313. {
  314. RegCloseKey(hKey);
  315. }
  316. return(myHError(hr));
  317. }
  318. HRESULT
  319. mySetCertRegValue(
  320. OPTIONAL IN WCHAR const *pwszMachine,
  321. OPTIONAL IN WCHAR const *pwszName1,
  322. OPTIONAL IN WCHAR const *pwszName2,
  323. OPTIONAL IN WCHAR const *pwszName3,
  324. OPTIONAL IN WCHAR const *pwszValueName,
  325. IN DWORD const dwValueType,
  326. IN BYTE const *pbData,
  327. IN DWORD const cbData,
  328. IN BOOL fAbsolutePath)
  329. {
  330. return mySetCertRegValueEx(pwszMachine,
  331. pwszName1,
  332. pwszName2,
  333. pwszName3,
  334. TRUE, //from Configuration
  335. pwszValueName,
  336. dwValueType,
  337. pbData,
  338. cbData,
  339. fAbsolutePath);
  340. }
  341. HRESULT
  342. myRegQueryValueEx(
  343. IN HKEY hKey,
  344. IN LPCTSTR pwszValueName,
  345. OUT LPDWORD pValueType,
  346. OUT LPBYTE *ppbData,
  347. OUT LPDWORD pcbData)
  348. {
  349. HRESULT hr;
  350. DWORD dwType;
  351. DWORD dwLen;
  352. BYTE *pbData = NULL;
  353. DWORD cbZero = 0;
  354. *ppbData = NULL;
  355. if (NULL != pcbData)
  356. {
  357. *pcbData = 0;
  358. }
  359. if (NULL != pValueType)
  360. {
  361. *pValueType = REG_NONE;
  362. }
  363. for (;;)
  364. {
  365. hr = RegQueryValueEx(
  366. hKey,
  367. pwszValueName,
  368. 0,
  369. &dwType,
  370. pbData,
  371. &dwLen);
  372. _JumpIfErrorStr2(
  373. hr,
  374. error,
  375. "RegQueryValueEx",
  376. pwszValueName,
  377. ERROR_FILE_NOT_FOUND);
  378. if (NULL != pbData)
  379. {
  380. ZeroMemory(&pbData[dwLen], cbZero);
  381. break;
  382. }
  383. // Enforce WCHAR-aligned double null termination for malformed values.
  384. // Some callers need to treat REG_SZ values as REG_MULTI_SZ.
  385. if (REG_MULTI_SZ == dwType || REG_SZ == dwType)
  386. {
  387. cbZero = 2 * sizeof(WCHAR);
  388. if (dwLen & (sizeof(WCHAR) - 1))
  389. {
  390. cbZero++;
  391. }
  392. }
  393. pbData = (BYTE *) LocalAlloc(LMEM_FIXED, dwLen + cbZero);
  394. if (NULL == pbData)
  395. {
  396. hr = E_OUTOFMEMORY;
  397. _JumpError(hr, error, "LocalAlloc");
  398. }
  399. }
  400. if (NULL != pValueType)
  401. {
  402. *pValueType = dwType;
  403. }
  404. if (NULL != pcbData)
  405. {
  406. *pcbData = dwLen;
  407. }
  408. *ppbData = pbData;
  409. hr = S_OK;
  410. error:
  411. return(myHError(hr));
  412. }
  413. HRESULT
  414. myGetCertRegValueEx(
  415. OPTIONAL IN WCHAR const *pwszMachine,
  416. OPTIONAL IN WCHAR const *pwszName1,
  417. OPTIONAL IN WCHAR const *pwszName2,
  418. OPTIONAL IN WCHAR const *pwszName3,
  419. IN BOOL fConfigLevel,
  420. IN WCHAR const *pwszValueName,
  421. OUT BYTE **ppbData,
  422. OPTIONAL OUT DWORD *pcbData,
  423. OPTIONAL OUT DWORD *pValueType)
  424. {
  425. HRESULT hr;
  426. HKEY hKey = NULL;
  427. WCHAR *pwszTemp = NULL;
  428. HKEY hBaseKey = NULL;
  429. hr = myFormCertRegPath(pwszName1, pwszName2, pwszName3, fConfigLevel, &pwszTemp);
  430. _JumpIfError(hr, error, "myFormCertRegPath");
  431. if (pwszMachine)
  432. {
  433. hr = RegConnectRegistry(pwszMachine, HKEY_LOCAL_MACHINE, &hBaseKey);
  434. _JumpIfErrorStr(hr, error, "RegConnectRegistry", pwszMachine);
  435. }
  436. else
  437. hBaseKey = HKEY_LOCAL_MACHINE;
  438. hr = RegOpenKeyEx(
  439. hBaseKey,
  440. pwszTemp,
  441. 0,
  442. KEY_READ,
  443. &hKey);
  444. _JumpIfError2(hr, error, "RegOpenKeyEx", ERROR_FILE_NOT_FOUND);
  445. hr = myRegQueryValueEx(
  446. hKey,
  447. pwszValueName,
  448. pValueType,
  449. ppbData,
  450. pcbData);
  451. _JumpIfErrorStr2(
  452. hr,
  453. error,
  454. "myRegQueryValueEx",
  455. pwszValueName,
  456. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  457. error:
  458. if ((NULL != hBaseKey) && (hBaseKey != HKEY_LOCAL_MACHINE))
  459. {
  460. RegCloseKey(hBaseKey);
  461. }
  462. if (NULL != pwszTemp)
  463. {
  464. LocalFree(pwszTemp);
  465. }
  466. if (NULL != hKey)
  467. {
  468. RegCloseKey(hKey);
  469. }
  470. return(myHError(hr));
  471. }
  472. HRESULT
  473. myGetCertRegValue(
  474. OPTIONAL IN WCHAR const *pwszMachine,
  475. OPTIONAL IN WCHAR const *pwszName1,
  476. OPTIONAL IN WCHAR const *pwszName2,
  477. OPTIONAL IN WCHAR const *pwszName3,
  478. IN WCHAR const *pwszValueName,
  479. OUT BYTE **ppbData,
  480. OPTIONAL OUT DWORD *pcbData,
  481. OPTIONAL OUT DWORD *pValueType)
  482. {
  483. return myGetCertRegValueEx(pwszMachine,
  484. pwszName1,
  485. pwszName2,
  486. pwszName3,
  487. TRUE, //from Configuration
  488. pwszValueName,
  489. ppbData,
  490. pcbData,
  491. pValueType);
  492. }
  493. HRESULT
  494. mySetCertRegMultiStrValue(
  495. OPTIONAL IN WCHAR const *pwszName1,
  496. OPTIONAL IN WCHAR const *pwszName2,
  497. OPTIONAL IN WCHAR const *pwszName3,
  498. OPTIONAL IN WCHAR const *pwszValueName,
  499. IN WCHAR const *pwszzValue)
  500. {
  501. DWORD cwc = 0;
  502. DWORD cwcT;
  503. WCHAR const *pwc;
  504. if (NULL != pwszzValue)
  505. {
  506. for (pwc = pwszzValue; L'\0' != *pwc; cwc += cwcT, pwc += cwcT)
  507. {
  508. cwcT = wcslen(pwc) + 1;
  509. }
  510. cwc++;
  511. }
  512. return(mySetCertRegValue(
  513. NULL,
  514. pwszName1,
  515. pwszName2,
  516. pwszName3,
  517. pwszValueName,
  518. REG_MULTI_SZ,
  519. (BYTE const *) pwszzValue,
  520. cwc * sizeof(WCHAR),
  521. FALSE));
  522. }
  523. HRESULT
  524. mySetCertRegStrValue(
  525. OPTIONAL IN WCHAR const *pwszName1,
  526. OPTIONAL IN WCHAR const *pwszName2,
  527. OPTIONAL IN WCHAR const *pwszName3,
  528. OPTIONAL IN WCHAR const *pwszValueName,
  529. IN WCHAR const *pwszValue)
  530. {
  531. DWORD cwc = 0;
  532. if (NULL != pwszValue)
  533. {
  534. cwc = wcslen(pwszValue) + 1;
  535. }
  536. return mySetCertRegValue(
  537. NULL,
  538. pwszName1,
  539. pwszName2,
  540. pwszName3,
  541. pwszValueName,
  542. REG_SZ,
  543. (BYTE const *) pwszValue,
  544. cwc * sizeof(WCHAR),
  545. FALSE);
  546. }
  547. HRESULT
  548. mySetAbsRegMultiStrValue(
  549. IN WCHAR const *pwszName,
  550. IN WCHAR const *pwszValueName,
  551. IN WCHAR const *pwszzValue)
  552. {
  553. DWORD cwc = 0;
  554. DWORD cwcT;
  555. WCHAR const *pwc;
  556. if (NULL != pwszzValue)
  557. {
  558. for (pwc = pwszzValue; L'\0' != *pwc; cwc += cwcT, pwc += cwcT)
  559. {
  560. cwcT = wcslen(pwc) + 1;
  561. }
  562. cwc++;
  563. }
  564. return(mySetCertRegValue(
  565. NULL,
  566. pwszName,
  567. NULL,
  568. NULL,
  569. pwszValueName,
  570. REG_MULTI_SZ,
  571. (BYTE const *) pwszzValue,
  572. cwc * sizeof(WCHAR),
  573. TRUE));
  574. }
  575. HRESULT
  576. mySetAbsRegStrValue(
  577. IN WCHAR const *pwszName,
  578. IN WCHAR const *pwszValueName,
  579. IN WCHAR const *pwszValue)
  580. {
  581. DWORD cwc = 0;
  582. if (NULL != pwszValue)
  583. {
  584. cwc = wcslen(pwszValue) + 1;
  585. }
  586. return mySetCertRegValue(
  587. NULL,
  588. pwszName,
  589. NULL,
  590. NULL,
  591. pwszValueName,
  592. REG_SZ,
  593. (BYTE const *)pwszValue,
  594. cwc*sizeof(WCHAR),
  595. TRUE);
  596. }
  597. HRESULT
  598. mySetCertRegDWValue(
  599. OPTIONAL IN WCHAR const *pwszName1,
  600. OPTIONAL IN WCHAR const *pwszName2,
  601. OPTIONAL IN WCHAR const *pwszName3,
  602. OPTIONAL IN WCHAR const *pwszValueName,
  603. IN DWORD const dwValue)
  604. {
  605. return mySetCertRegValue(
  606. NULL,
  607. pwszName1,
  608. pwszName2,
  609. pwszName3,
  610. pwszValueName,
  611. REG_DWORD,
  612. (BYTE const *)&dwValue,
  613. sizeof(DWORD),
  614. FALSE);
  615. }
  616. HRESULT
  617. myGetCertRegMultiStrValue(
  618. OPTIONAL IN WCHAR const *pwszName1,
  619. OPTIONAL IN WCHAR const *pwszName2,
  620. OPTIONAL IN WCHAR const *pwszName3,
  621. OPTIONAL IN WCHAR const *pwszValueName,
  622. OUT WCHAR **ppwszzValue)
  623. {
  624. HRESULT hr;
  625. DWORD dwType;
  626. hr = myGetCertRegValue(
  627. NULL,
  628. pwszName1,
  629. pwszName2,
  630. pwszName3,
  631. pwszValueName,
  632. (BYTE **) ppwszzValue,
  633. NULL,
  634. &dwType);
  635. _JumpIfErrorStr2(
  636. hr,
  637. error,
  638. "myGetCertRegValue",
  639. pwszValueName,
  640. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  641. if (REG_MULTI_SZ != dwType && REG_SZ != dwType)
  642. {
  643. LocalFree(*ppwszzValue);
  644. *ppwszzValue = NULL;
  645. hr = E_INVALIDARG;
  646. _JumpError(hr, error, "not REG_SZ or REG_MULTI_SZ");
  647. }
  648. hr = S_OK;
  649. error:
  650. CSASSERT(S_OK == hr || FAILED(hr));
  651. return(hr);
  652. }
  653. HRESULT
  654. myGetCertRegBinaryValue(
  655. OPTIONAL IN WCHAR const *pwszName1,
  656. OPTIONAL IN WCHAR const *pwszName2,
  657. OPTIONAL IN WCHAR const *pwszName3,
  658. IN WCHAR const *pwszValueName,
  659. OUT BYTE **ppbValue)
  660. {
  661. HRESULT hr;
  662. DWORD dwType;
  663. hr = myGetCertRegValue(
  664. NULL,
  665. pwszName1,
  666. pwszName2,
  667. pwszName3,
  668. pwszValueName,
  669. ppbValue,
  670. NULL,
  671. &dwType);
  672. _JumpIfErrorStr2(
  673. hr,
  674. error,
  675. "myGetCertRegValue",
  676. pwszName1,
  677. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  678. if (REG_BINARY != dwType)
  679. {
  680. LocalFree(*ppbValue);
  681. *ppbValue = NULL;
  682. hr = E_INVALIDARG;
  683. _JumpError(hr, error, "not REG_BINARY");
  684. }
  685. hr = S_OK;
  686. error:
  687. return hr;
  688. }
  689. HRESULT
  690. myGetCertRegStrValue(
  691. OPTIONAL IN WCHAR const *pwszName1,
  692. OPTIONAL IN WCHAR const *pwszName2,
  693. OPTIONAL IN WCHAR const *pwszName3,
  694. IN WCHAR const *pwszValueName,
  695. OUT WCHAR **ppwszValue)
  696. {
  697. HRESULT hr;
  698. DWORD dwType;
  699. hr = myGetCertRegValue(
  700. NULL,
  701. pwszName1,
  702. pwszName2,
  703. pwszName3,
  704. pwszValueName,
  705. (BYTE **) ppwszValue,
  706. NULL,
  707. &dwType);
  708. _JumpIfErrorStr2(
  709. hr,
  710. error,
  711. "myGetCertRegValue",
  712. pwszName1,
  713. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  714. if (REG_SZ != dwType)
  715. {
  716. LocalFree(*ppwszValue);
  717. *ppwszValue = NULL;
  718. hr = E_INVALIDARG;
  719. _JumpError(hr, error, "not REG_SZ");
  720. }
  721. hr = S_OK;
  722. error:
  723. return hr;
  724. }
  725. HRESULT
  726. myGetCertRegDWValue(
  727. OPTIONAL IN WCHAR const *pwszName1,
  728. OPTIONAL IN WCHAR const *pwszName2,
  729. OPTIONAL IN WCHAR const *pwszName3,
  730. IN WCHAR const *pwszValueName,
  731. OUT DWORD *pdwValue)
  732. {
  733. HRESULT hr;
  734. DWORD *pdw = NULL;
  735. DWORD dwType;
  736. *pdwValue = 0;
  737. hr = myGetCertRegValue(
  738. NULL,
  739. pwszName1,
  740. pwszName2,
  741. pwszName3,
  742. pwszValueName,
  743. (BYTE **) &pdw,
  744. NULL,
  745. &dwType);
  746. _JumpIfErrorStr2(
  747. hr,
  748. error,
  749. "myGetCertRegValue",
  750. pwszValueName,
  751. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  752. if (REG_DWORD != dwType)
  753. {
  754. hr = E_INVALIDARG;
  755. _JumpErrorStr(hr, error, "not REG_DWORD", pwszValueName);
  756. }
  757. *pdwValue = *pdw;
  758. hr = S_OK;
  759. error:
  760. if (NULL != pdw)
  761. {
  762. LocalFree(pdw);
  763. }
  764. CSASSERT(S_OK == hr || FAILED(hr));
  765. return(hr);
  766. }
  767. HRESULT
  768. myCopyCertRegStrValue(
  769. OPTIONAL IN WCHAR const *pwszSrcName1,
  770. OPTIONAL IN WCHAR const *pwszSrcName2,
  771. OPTIONAL IN WCHAR const *pwszSrcName3,
  772. IN WCHAR const *pwszSrcValueName,
  773. OPTIONAL IN WCHAR const *pwszDesName1,
  774. OPTIONAL IN WCHAR const *pwszDesName2,
  775. OPTIONAL IN WCHAR const *pwszDesName3,
  776. OPTIONAL IN WCHAR const *pwszDesValueName,
  777. IN BOOL fMultiStr)
  778. {
  779. HRESULT hr;
  780. WCHAR *pwszOrzzValue = NULL;
  781. WCHAR const *pwszName = NULL != pwszDesValueName?
  782. pwszDesValueName : pwszSrcValueName;
  783. // get value from source
  784. if (fMultiStr)
  785. {
  786. hr = myGetCertRegMultiStrValue(
  787. pwszSrcName1,
  788. pwszSrcName2,
  789. pwszSrcName3,
  790. pwszSrcValueName,
  791. &pwszOrzzValue);
  792. _JumpIfErrorStr(hr, error, "myGetCertRegMultiStrValue", pwszSrcValueName);
  793. // set it to destination
  794. hr = mySetCertRegMultiStrValue(
  795. pwszDesName1,
  796. pwszDesName2,
  797. pwszDesName3,
  798. pwszName,
  799. pwszOrzzValue);
  800. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValue", pwszName);
  801. }
  802. else
  803. {
  804. hr = myGetCertRegStrValue(
  805. pwszSrcName1,
  806. pwszSrcName2,
  807. pwszSrcName3,
  808. pwszSrcValueName,
  809. &pwszOrzzValue);
  810. _JumpIfErrorStr(hr, error, "myGetCertRegStrValue", pwszSrcValueName);
  811. // set it to destination
  812. hr = mySetCertRegStrValue(
  813. pwszDesName1,
  814. pwszDesName2,
  815. pwszDesName3,
  816. pwszName,
  817. pwszOrzzValue);
  818. _JumpIfErrorStr(hr, error, "mySetCertRegStrValue", pwszName);
  819. }
  820. hr = S_OK;
  821. error:
  822. if (NULL != pwszOrzzValue)
  823. {
  824. LocalFree(pwszOrzzValue);
  825. }
  826. CSASSERT(S_OK == hr || FAILED(hr));
  827. return(hr);
  828. }
  829. HRESULT
  830. myMoveCertRegStrValue(
  831. OPTIONAL IN WCHAR const *pwszSrcName1,
  832. OPTIONAL IN WCHAR const *pwszSrcName2,
  833. OPTIONAL IN WCHAR const *pwszSrcName3,
  834. IN WCHAR const *pwszSrcValueName,
  835. OPTIONAL IN WCHAR const *pwszDesName1,
  836. OPTIONAL IN WCHAR const *pwszDesName2,
  837. OPTIONAL IN WCHAR const *pwszDesName3,
  838. OPTIONAL IN WCHAR const *pwszDesValueName,
  839. IN BOOL fMultiStr)
  840. {
  841. HRESULT hr;
  842. hr = myCopyCertRegStrValue(
  843. pwszSrcName1,
  844. pwszSrcName2,
  845. pwszSrcName3,
  846. pwszSrcValueName,
  847. pwszDesName1,
  848. pwszDesName2,
  849. pwszDesName3,
  850. pwszDesValueName,
  851. fMultiStr);
  852. _JumpIfErrorStr(hr, error, "myCopyCertRegStrValue", pwszSrcValueName);
  853. hr = myDeleteCertRegValue(
  854. pwszSrcName1,
  855. pwszSrcName2,
  856. pwszSrcName3,
  857. pwszSrcValueName);
  858. _PrintIfErrorStr(hr, "myDeleteCertRegValue", pwszSrcValueName);
  859. hr = S_OK;
  860. error:
  861. CSASSERT(S_OK == hr || FAILED(hr));
  862. return(hr);
  863. }
  864. HRESULT
  865. myMoveOrCopyCertRegStrValue(
  866. OPTIONAL IN WCHAR const *pwszSrcName1,
  867. OPTIONAL IN WCHAR const *pwszSrcName2,
  868. OPTIONAL IN WCHAR const *pwszSrcName3,
  869. IN WCHAR const *pwszSrcValueName,
  870. OPTIONAL IN WCHAR const *pwszDesName1,
  871. OPTIONAL IN WCHAR const *pwszDesName2,
  872. OPTIONAL IN WCHAR const *pwszDesName3,
  873. OPTIONAL IN WCHAR const *pwszDesValueName,
  874. IN BOOL fMultiStr,
  875. IN BOOL fMove)
  876. {
  877. HRESULT hr;
  878. if (fMove)
  879. {
  880. hr = myMoveCertRegStrValue(
  881. pwszSrcName1,
  882. pwszSrcName2,
  883. pwszSrcName3,
  884. pwszSrcValueName,
  885. pwszDesName1,
  886. pwszDesName2,
  887. pwszDesName3,
  888. pwszDesValueName,
  889. fMultiStr);
  890. }
  891. else
  892. {
  893. hr = myCopyCertRegStrValue(
  894. pwszSrcName1,
  895. pwszSrcName2,
  896. pwszSrcName3,
  897. pwszSrcValueName,
  898. pwszDesName1,
  899. pwszDesName2,
  900. pwszDesName3,
  901. pwszDesValueName,
  902. fMultiStr);
  903. }
  904. return hr;
  905. }
  906. // Description: it does the same thing as mySetCertRegStrValue but it takes
  907. // upgrade flag, if upgrade and entry exists, do nothing
  908. HRESULT
  909. mySetCertRegStrValueEx(
  910. IN BOOL fUpgrade,
  911. OPTIONAL IN WCHAR const *pwszName1,
  912. OPTIONAL IN WCHAR const *pwszName2,
  913. OPTIONAL IN WCHAR const *pwszName3,
  914. OPTIONAL IN WCHAR const *pwszValueName,
  915. IN WCHAR const *pwszValue)
  916. {
  917. HRESULT hr;
  918. WCHAR *pwszDummy = NULL;
  919. if (fUpgrade)
  920. {
  921. // see if it exists
  922. hr = myGetCertRegStrValue(
  923. pwszName1,
  924. pwszName2,
  925. pwszName3,
  926. pwszValueName,
  927. &pwszDummy);
  928. if (S_OK == hr)
  929. {
  930. if (NULL != pwszDummy && L'\0' != pwszDummy[0])
  931. {
  932. goto error; // keep existing entry
  933. }
  934. }
  935. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  936. {
  937. _JumpErrorStr(hr, error, "myGetCertRegStrValue", pwszValueName);
  938. }
  939. }
  940. // cases: 1) not upgrade
  941. // 2) upgrade but no existing entry
  942. // 3) upgrade, existing but empty reg string
  943. hr = mySetCertRegStrValue(
  944. pwszName1,
  945. pwszName2,
  946. pwszName3,
  947. pwszValueName,
  948. pwszValue);
  949. _JumpIfErrorStr(hr, error, "mySetCertRegStrValue", pwszValueName);
  950. error:
  951. if (NULL != pwszDummy)
  952. {
  953. LocalFree(pwszDummy);
  954. }
  955. CSASSERT(S_OK == hr || FAILED(hr));
  956. return(hr);
  957. }
  958. // calculate multi string character length including double zero terminators
  959. DWORD
  960. myWCSZZLength(
  961. IN WCHAR const *pwszz)
  962. {
  963. DWORD cwc = 0;
  964. if (NULL != pwszz)
  965. {
  966. WCHAR const *pwsz;
  967. for (pwsz = pwszz; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  968. {
  969. }
  970. cwc = SAFE_SUBTRACT_POINTERS(pwsz, pwszz) + 1;
  971. if (1 == cwc)
  972. {
  973. CSASSERT(L'\0' == pwsz[1]);
  974. cwc++; // empty values are double terminated, too
  975. }
  976. }
  977. return(cwc);
  978. }
  979. // merge two multi strings into one
  980. // ignore redundant strings
  981. HRESULT
  982. myMergeMultiStrings(
  983. IN WCHAR const *pwszzStr1,
  984. IN WCHAR const *pwszzStr2,
  985. OUT WCHAR **ppwszzStr)
  986. {
  987. HRESULT hr;
  988. DWORD cwcStr1 = myWCSZZLength(pwszzStr1);
  989. DWORD cwcStr2; // doesn't include second terminator
  990. DWORD iStr2;
  991. DWORD cStr2;
  992. WCHAR const *pwsz1;
  993. WCHAR const *pwsz2;
  994. WCHAR *pwsz;
  995. BOOL *pfRedundant = NULL;
  996. WCHAR *pwszzMerge = NULL;
  997. *ppwszzStr = NULL;
  998. // calculate string count
  999. cStr2 = 0;
  1000. for (pwsz2 = pwszzStr2; L'\0' != *pwsz2; pwsz2 += wcslen(pwsz2) + 1)
  1001. {
  1002. cStr2++;
  1003. }
  1004. cwcStr2 = 0;
  1005. if (0 == cStr2)
  1006. {
  1007. goto only_str1; // no merge needed
  1008. }
  1009. pfRedundant = (BOOL *) LocalAlloc(
  1010. LMEM_FIXED | LMEM_ZEROINIT,
  1011. cStr2 * sizeof(*pfRedundant));
  1012. if (NULL == pfRedundant)
  1013. {
  1014. hr = E_OUTOFMEMORY;
  1015. _JumpError(hr, error, "LocalAlloc");
  1016. }
  1017. // calculate size
  1018. iStr2 = 0;
  1019. for (pwsz2 = pwszzStr2; L'\0' != *pwsz2; pwsz2 += wcslen(pwsz2) + 1)
  1020. {
  1021. for (pwsz1 = pwszzStr1; L'\0' != *pwsz1; pwsz1 += wcslen(pwsz1) + 1)
  1022. {
  1023. if (0 == mylstrcmpiL(pwsz2, pwsz1))
  1024. {
  1025. // pwsz2 exists in pwszzStr1, skip it -- save redundant flag
  1026. pfRedundant[iStr2] = TRUE;
  1027. break; // for pwsz1
  1028. }
  1029. }
  1030. if (L'\0' == *pwsz1) // if not redundant ...
  1031. {
  1032. cwcStr2 += wcslen(pwsz2) + 1;
  1033. }
  1034. iStr2++;
  1035. }
  1036. only_str1:
  1037. pwszzMerge = (WCHAR *) LocalAlloc(
  1038. LMEM_FIXED,
  1039. (cwcStr1 + cwcStr2) * sizeof(WCHAR));
  1040. if (NULL == pwszzMerge)
  1041. {
  1042. hr = E_OUTOFMEMORY;
  1043. _JumpError(hr, error, "LocalAlloc");
  1044. }
  1045. // copy existing
  1046. CopyMemory(pwszzMerge, pwszzStr1, cwcStr1 * sizeof(WCHAR));
  1047. if (0 < cStr2)
  1048. {
  1049. // merge begins
  1050. // point to end at 2nd terminator
  1051. iStr2 = 0;
  1052. pwsz = &pwszzMerge[cwcStr1 - 1];
  1053. if (L'\0' == *pwszzMerge)
  1054. {
  1055. CSASSERT(2 == cwcStr1);
  1056. pwsz = pwszzMerge;
  1057. }
  1058. for (pwsz2 = pwszzStr2; L'\0' != *pwsz2; pwsz2 += wcslen(pwsz2) + 1)
  1059. {
  1060. if (!pfRedundant[iStr2])
  1061. {
  1062. wcscpy(pwsz, pwsz2);
  1063. pwsz += wcslen(pwsz) + 1;
  1064. }
  1065. iStr2++;
  1066. }
  1067. *pwsz = L'\0'; // double terminate
  1068. CSASSERT(
  1069. SAFE_SUBTRACT_POINTERS(pwsz, pwszzMerge) + 1 <= cwcStr1 + cwcStr2);
  1070. }
  1071. CSASSERT(myWCSZZLength(pwszzMerge) <= cwcStr1 + cwcStr2);
  1072. *ppwszzStr = pwszzMerge;
  1073. pwszzMerge = NULL;
  1074. hr = S_OK;
  1075. error:
  1076. if (NULL != pfRedundant)
  1077. {
  1078. LocalFree(pfRedundant);
  1079. }
  1080. if (NULL != pwszzMerge)
  1081. {
  1082. LocalFree(pwszzMerge);
  1083. }
  1084. return(hr);
  1085. }
  1086. // append one multi_sz to another
  1087. HRESULT
  1088. myAppendMultiStrings(
  1089. IN WCHAR const *pwszzStr1,
  1090. IN WCHAR const *pwszzStr2,
  1091. OUT WCHAR **ppwszzStr)
  1092. {
  1093. HRESULT hr;
  1094. DWORD cwcStr1 = myWCSZZLength(pwszzStr1);
  1095. DWORD cwcStr2 = myWCSZZLength(pwszzStr2);
  1096. WCHAR *pwszzMerge;
  1097. WCHAR *pwsz;
  1098. *ppwszzStr = NULL;
  1099. pwszzMerge = (WCHAR *) LocalAlloc(
  1100. LMEM_FIXED,
  1101. (cwcStr1 + cwcStr2 - 1) * sizeof(WCHAR));
  1102. if (NULL == pwszzMerge)
  1103. {
  1104. hr = E_OUTOFMEMORY;
  1105. _JumpError(hr, error, "LocalAlloc");
  1106. }
  1107. // copy existing
  1108. CopyMemory(pwszzMerge, pwszzStr1, (cwcStr1 - 1) * sizeof(WCHAR));
  1109. // append second
  1110. pwsz = &pwszzMerge[cwcStr1 - 1];
  1111. if (L'\0' == *pwszzMerge)
  1112. {
  1113. CSASSERT(2 == cwcStr1);
  1114. pwsz = pwszzMerge;
  1115. }
  1116. CopyMemory(pwsz, pwszzStr2, cwcStr2 * sizeof(WCHAR));
  1117. CSASSERT(myWCSZZLength(pwszzMerge) <= cwcStr1 + cwcStr2);
  1118. *ppwszzStr = pwszzMerge;
  1119. hr = S_OK;
  1120. error:
  1121. return(hr);
  1122. }
  1123. // Description: mySetCertRegMultiStrValueEx is the same as
  1124. // mySetCertRegMultiStrValue but it takes an upgrade | append flag.
  1125. // if upgrade and entry exists, do nothing.
  1126. // if upgrade & append, merge existing entry with input pwszz.
  1127. HRESULT
  1128. mySetCertRegMultiStrValueEx(
  1129. IN DWORD dwFlags, // CSREG_UPGRADE | CSREG_APPEND | CSREG_REPLACE | CSREG_MERGE
  1130. OPTIONAL IN WCHAR const *pwszName1,
  1131. OPTIONAL IN WCHAR const *pwszName2,
  1132. OPTIONAL IN WCHAR const *pwszName3,
  1133. OPTIONAL IN WCHAR const *pwszValueName,
  1134. IN WCHAR const *pwszzValue)
  1135. {
  1136. HRESULT hr;
  1137. WCHAR *pwszzExisting = NULL;
  1138. WCHAR const *pwszzFinal = pwszzValue; // default
  1139. WCHAR *pwszzMerge = NULL;
  1140. if (0 == (CSREG_REPLACE & dwFlags) && (CSREG_UPGRADE & dwFlags))
  1141. {
  1142. // to see if it exist
  1143. hr = myGetCertRegMultiStrValue(
  1144. pwszName1,
  1145. pwszName2,
  1146. pwszName3,
  1147. pwszValueName,
  1148. &pwszzExisting);
  1149. if (S_OK == hr)
  1150. {
  1151. if (NULL != pwszzExisting)
  1152. {
  1153. if (0 == ((CSREG_MERGE | CSREG_APPEND) & dwFlags))
  1154. {
  1155. goto error; // keep existing entry
  1156. }
  1157. if (CSREG_MERGE & dwFlags)
  1158. {
  1159. hr = myMergeMultiStrings(
  1160. pwszzExisting,
  1161. pwszzValue,
  1162. &pwszzMerge);
  1163. _JumpIfError(hr, error, "myMergeMultiStrings");
  1164. }
  1165. else if (CSREG_APPEND & dwFlags)
  1166. {
  1167. hr = myAppendMultiStrings(
  1168. pwszzExisting,
  1169. pwszzValue,
  1170. &pwszzMerge);
  1171. _JumpIfError(hr, error, "myAppendMultiStrings");
  1172. }
  1173. pwszzFinal = pwszzMerge;
  1174. }
  1175. }
  1176. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  1177. {
  1178. _JumpErrorStr(hr, error, "myGetCertRegMultiStrValue", pwszValueName);
  1179. }
  1180. }
  1181. hr = mySetCertRegMultiStrValue(
  1182. pwszName1,
  1183. pwszName2,
  1184. pwszName3,
  1185. pwszValueName,
  1186. pwszzFinal);
  1187. _JumpIfErrorStr(hr, error, "mySetCertRegMultiStrValue", pwszValueName);
  1188. error:
  1189. if (NULL != pwszzExisting)
  1190. {
  1191. LocalFree(pwszzExisting);
  1192. }
  1193. if (NULL != pwszzMerge)
  1194. {
  1195. LocalFree(pwszzMerge);
  1196. }
  1197. CSASSERT(S_OK == hr || FAILED(hr));
  1198. return(hr);
  1199. }
  1200. // Description: it does the same thing as mySetCertRegDWValue but it takes
  1201. // upgrade flag, if upgrade and entry exists, do nothing
  1202. HRESULT
  1203. mySetCertRegDWValueEx(
  1204. IN BOOL fUpgrade,
  1205. OPTIONAL IN WCHAR const *pwszName1,
  1206. OPTIONAL IN WCHAR const *pwszName2,
  1207. OPTIONAL IN WCHAR const *pwszName3,
  1208. OPTIONAL IN WCHAR const *pwszValueName,
  1209. IN DWORD const dwValue)
  1210. {
  1211. HRESULT hr;
  1212. DWORD dwDummy;
  1213. if (fUpgrade)
  1214. {
  1215. // to see if it exist
  1216. hr = myGetCertRegDWValue(
  1217. pwszName1,
  1218. pwszName2,
  1219. pwszName3,
  1220. pwszValueName,
  1221. &dwDummy);
  1222. if (S_OK == hr)
  1223. {
  1224. goto error; // keep existing entry
  1225. }
  1226. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  1227. {
  1228. _JumpErrorStr(hr, error, "myGetCertRegDWValue", pwszValueName);
  1229. }
  1230. }
  1231. hr = mySetCertRegDWValue(
  1232. pwszName1,
  1233. pwszName2,
  1234. pwszName3,
  1235. pwszValueName,
  1236. dwValue);
  1237. _JumpIfErrorStr(hr, error, "mySetCertRegDWValue", pwszValueName);
  1238. error:
  1239. CSASSERT(S_OK == hr || FAILED(hr));
  1240. return(hr);
  1241. }
  1242. WCHAR const *
  1243. wszRegCertChoice(
  1244. IN DWORD dwRegHashChoice)
  1245. {
  1246. WCHAR const *pwsz;
  1247. switch (dwRegHashChoice)
  1248. {
  1249. case CSRH_CASIGCERT:
  1250. pwsz = wszREGCACERTHASH;
  1251. break;
  1252. case CSRH_CAXCHGCERT:
  1253. pwsz = wszREGCAXCHGCERTHASH;
  1254. break;
  1255. case CSRH_CAKRACERT:
  1256. pwsz = wszREGKRACERTHASH;
  1257. break;
  1258. default:
  1259. CSASSERT(CSExpr(!"dwRegHashChoice"));
  1260. pwsz = L"";
  1261. break;
  1262. }
  1263. return(pwsz);
  1264. }
  1265. WCHAR const g_wszNoHash[] = L"-";
  1266. HRESULT myShrinkCARegHash(
  1267. IN WCHAR const *pwszSanitizedCAName,
  1268. IN DWORD dwRegHashChoice,
  1269. IN DWORD Index)
  1270. {
  1271. HRESULT hr = S_OK;
  1272. DWORD i;
  1273. DWORD dwType;
  1274. DWORD count;
  1275. WCHAR *pwszzOld = NULL;
  1276. WCHAR *pwchr = NULL; // no free
  1277. hr = myGetCertRegValue(
  1278. NULL,
  1279. pwszSanitizedCAName,
  1280. NULL,
  1281. NULL,
  1282. wszRegCertChoice(dwRegHashChoice),
  1283. (BYTE **) &pwszzOld,
  1284. &i, // ignore &cb
  1285. &dwType);
  1286. _JumpIfErrorStr(hr, error, "myGetCertRegValue", wszRegCertChoice(dwRegHashChoice));
  1287. for (count = 0, pwchr = pwszzOld;
  1288. count < Index && L'\0' != *pwchr;
  1289. count++, pwchr += wcslen(pwchr) + 1)
  1290. NULL;
  1291. // valid only if shrinking the list
  1292. if(L'\0' == *pwchr)
  1293. {
  1294. hr = E_INVALIDARG;
  1295. _JumpError(hr, error, "new hash count should be smaller than current count");
  1296. }
  1297. *pwchr = L'\0';
  1298. hr = mySetCertRegValue(
  1299. NULL,
  1300. pwszSanitizedCAName,
  1301. NULL,
  1302. NULL,
  1303. wszRegCertChoice(dwRegHashChoice),
  1304. REG_MULTI_SZ,
  1305. (BYTE const *) pwszzOld,
  1306. (SAFE_SUBTRACT_POINTERS(pwchr, pwszzOld) + 1) * sizeof(WCHAR),
  1307. FALSE);
  1308. _JumpIfError(hr, error, "mySetCertRegValue");
  1309. error:
  1310. if(pwszzOld)
  1311. LocalFree(pwszzOld);
  1312. return hr;
  1313. }
  1314. HRESULT
  1315. mySetCARegHash(
  1316. IN WCHAR const *pwszSanitizedCAName,
  1317. IN DWORD dwRegHashChoice,
  1318. IN DWORD Index,
  1319. IN CERT_CONTEXT const *pCert)
  1320. {
  1321. HRESULT hr;
  1322. BSTR strHash = NULL;
  1323. BYTE abHash[CBMAX_CRYPT_HASH_LEN];
  1324. DWORD cbHash;
  1325. WCHAR *pwszzOld = NULL;
  1326. WCHAR *pwszzNew = NULL;
  1327. DWORD cOld;
  1328. DWORD i;
  1329. DWORD cNew;
  1330. DWORD cwcNew;
  1331. WCHAR const **apwsz = NULL;
  1332. DWORD dwType;
  1333. WCHAR *pwc;
  1334. if (NULL == pwszSanitizedCAName)
  1335. {
  1336. hr = E_POINTER;
  1337. _JumpError(hr, error, "empty ca name");
  1338. }
  1339. cbHash = sizeof(abHash);
  1340. if (!CertGetCertificateContextProperty(
  1341. pCert,
  1342. CERT_HASH_PROP_ID,
  1343. abHash,
  1344. &cbHash))
  1345. {
  1346. hr = myHLastError();
  1347. _JumpError(hr, error, "CertGetCertificateContextProperty");
  1348. }
  1349. hr = MultiByteIntegerToBstr(TRUE, cbHash, abHash, &strHash);
  1350. _JumpIfError(hr, error, "MultiByteIntegerToBstr");
  1351. cOld = 0;
  1352. hr = myGetCertRegValue(
  1353. NULL,
  1354. pwszSanitizedCAName,
  1355. NULL,
  1356. NULL,
  1357. wszRegCertChoice(dwRegHashChoice),
  1358. (BYTE **) &pwszzOld,
  1359. &i, // ignore &cb
  1360. &dwType);
  1361. _PrintIfError2(hr, "myGetCertRegValue", HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  1362. if (S_OK == hr && REG_MULTI_SZ == dwType)
  1363. {
  1364. for (pwc = pwszzOld; L'\0' != *pwc; pwc += wcslen(pwc) + 1)
  1365. {
  1366. cOld++;
  1367. }
  1368. }
  1369. cNew = max(Index + 1, cOld);
  1370. apwsz = (WCHAR const **) LocalAlloc(LMEM_FIXED, cNew * sizeof(*apwsz));
  1371. if (NULL == apwsz)
  1372. {
  1373. hr = E_OUTOFMEMORY;
  1374. _JumpError(hr, error, "LocalAlloc");
  1375. }
  1376. i = 0;
  1377. if (0 != cOld)
  1378. {
  1379. for (pwc = pwszzOld; L'\0' != *pwc; pwc += wcslen(pwc) + 1)
  1380. {
  1381. DBGPRINT((DBG_SS_CERTLIBI, "Old CARegHash[%u] = \"%ws\"\n", i, pwc));
  1382. apwsz[i++] = pwc;
  1383. }
  1384. CSASSERT(i == cOld);
  1385. }
  1386. while (i < Index)
  1387. {
  1388. DBGPRINT((DBG_SS_CERTLIBI, "CARegHash[%u] Unused\n", i));
  1389. apwsz[i++] = g_wszNoHash;
  1390. }
  1391. if (Index < cOld)
  1392. {
  1393. DBGPRINT((
  1394. DBG_SS_CERTLIBI,
  1395. "Replacing CARegHash[%u] = \"%ws\"\n",
  1396. Index,
  1397. apwsz[Index]));
  1398. }
  1399. DBGPRINT((
  1400. DBG_SS_CERTLIBI,
  1401. "Adding CARegHash[%u] = \"%ws\"\n",
  1402. Index,
  1403. strHash));
  1404. apwsz[Index] = strHash;
  1405. cwcNew = 1; // wszz double termination
  1406. for (i = 0; i < cNew; i++)
  1407. {
  1408. cwcNew += wcslen(apwsz[i]) + 1;
  1409. }
  1410. pwszzNew = (WCHAR *) LocalAlloc(LMEM_FIXED, cwcNew * sizeof(WCHAR));
  1411. if (NULL == pwszzNew)
  1412. {
  1413. hr = E_OUTOFMEMORY;
  1414. _JumpError(hr, error, "LocalAlloc");
  1415. }
  1416. pwc = pwszzNew;
  1417. for (i = 0; i < cNew; i++)
  1418. {
  1419. wcscpy(pwc, apwsz[i]);
  1420. DBGPRINT((DBG_SS_CERTLIBI, "New CARegHash[%u] = \"%ws\"\n", i, pwc));
  1421. pwc += wcslen(pwc) + 1;
  1422. }
  1423. *pwc = L'\0';
  1424. CSASSERT(&pwszzNew[cwcNew - 1] == pwc);
  1425. hr = mySetCertRegValue(
  1426. NULL,
  1427. pwszSanitizedCAName,
  1428. NULL,
  1429. NULL,
  1430. wszRegCertChoice(dwRegHashChoice),
  1431. REG_MULTI_SZ,
  1432. (BYTE const *) pwszzNew,
  1433. cwcNew * sizeof(WCHAR),
  1434. FALSE);
  1435. _JumpIfError(hr, error, "mySetCertRegValue");
  1436. error:
  1437. if (NULL != apwsz)
  1438. {
  1439. LocalFree(apwsz);
  1440. }
  1441. if (NULL != pwszzOld)
  1442. {
  1443. LocalFree(pwszzOld);
  1444. }
  1445. if (NULL != pwszzNew)
  1446. {
  1447. LocalFree(pwszzNew);
  1448. }
  1449. if (NULL != strHash)
  1450. {
  1451. SysFreeString(strHash);
  1452. }
  1453. return(hr);
  1454. }
  1455. HRESULT
  1456. myGetCARegHash(
  1457. IN WCHAR const *pwszSanitizedCAName,
  1458. IN DWORD dwRegHashChoice,
  1459. IN DWORD Index,
  1460. OUT BYTE **ppbHash,
  1461. OUT DWORD *pcbHash)
  1462. {
  1463. HRESULT hr;
  1464. WCHAR *pwszz = NULL;
  1465. DWORD cb;
  1466. DWORD dwType;
  1467. WCHAR *pwc;
  1468. DWORD i;
  1469. *ppbHash = NULL;
  1470. hr = myGetCertRegValue(
  1471. NULL,
  1472. pwszSanitizedCAName,
  1473. NULL,
  1474. NULL,
  1475. wszRegCertChoice(dwRegHashChoice),
  1476. (BYTE **) &pwszz,
  1477. &cb,
  1478. &dwType);
  1479. _JumpIfError(hr, error, "myGetCertRegValue");
  1480. if (REG_MULTI_SZ != dwType)
  1481. {
  1482. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  1483. _JumpError(hr, error, "dwType");
  1484. }
  1485. pwc = pwszz;
  1486. for (i = 0; i < Index; i++)
  1487. {
  1488. if (L'\0' == *pwc)
  1489. {
  1490. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  1491. _JumpError(hr, error, "Index too large");
  1492. }
  1493. pwc += wcslen(pwc) + 1;
  1494. }
  1495. if (0 == lstrcmp(g_wszNoHash, pwc))
  1496. {
  1497. hr = S_FALSE;
  1498. _JumpError2(hr, error, "Unused hash", S_FALSE);
  1499. }
  1500. hr = WszToMultiByteInteger(TRUE, pwc, pcbHash, ppbHash);
  1501. _JumpIfError(hr, error, "WszToMultiByteInteger");
  1502. error:
  1503. if (NULL != pwszz)
  1504. {
  1505. LocalFree(pwszz);
  1506. }
  1507. return(hr);
  1508. }
  1509. HRESULT
  1510. myGetCARegHashCount(
  1511. IN WCHAR const *pwszSanitizedCAName,
  1512. IN DWORD dwRegHashChoice,
  1513. OUT DWORD *pCount)
  1514. {
  1515. HRESULT hr;
  1516. WCHAR *pwszz = NULL;
  1517. DWORD cb;
  1518. DWORD dwType;
  1519. WCHAR *pwc;
  1520. DWORD Count = 0;
  1521. hr = myGetCertRegValue(
  1522. NULL,
  1523. pwszSanitizedCAName,
  1524. NULL,
  1525. NULL,
  1526. wszRegCertChoice(dwRegHashChoice),
  1527. (BYTE **) &pwszz,
  1528. &cb,
  1529. &dwType);
  1530. if (S_OK == hr)
  1531. {
  1532. if (REG_MULTI_SZ == dwType)
  1533. {
  1534. for (pwc = pwszz; L'\0' != *pwc; pwc += wcslen(pwc) + 1)
  1535. {
  1536. Count++;
  1537. }
  1538. }
  1539. }
  1540. else if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) != hr)
  1541. {
  1542. _JumpError(hr, error, "myGetCertRegValue");
  1543. }
  1544. hr = S_OK;
  1545. error:
  1546. *pCount = Count;
  1547. if (NULL != pwszz)
  1548. {
  1549. LocalFree(pwszz);
  1550. }
  1551. return(hr);
  1552. }
  1553. HRESULT
  1554. myFindCACertByHash(
  1555. IN HCERTSTORE hStore,
  1556. IN BYTE const *pbHash,
  1557. IN DWORD cbHash,
  1558. OUT OPTIONAL DWORD *pdwNameId,
  1559. CERT_CONTEXT const **ppCACert)
  1560. {
  1561. HRESULT hr;
  1562. CRYPT_DATA_BLOB Hash;
  1563. CSASSERT(
  1564. NULL != hStore &&
  1565. NULL != pbHash &&
  1566. NULL != ppCACert);
  1567. *ppCACert = NULL;
  1568. Hash.pbData = const_cast<BYTE *>(pbHash);
  1569. Hash.cbData = cbHash;
  1570. *ppCACert = CertFindCertificateInStore(
  1571. hStore,
  1572. X509_ASN_ENCODING,
  1573. 0,
  1574. CERT_FIND_HASH,
  1575. &Hash,
  1576. NULL);
  1577. if (NULL == *ppCACert)
  1578. {
  1579. hr = myHLastError();
  1580. _JumpError(hr, error, "CertFindCertificateInStore");
  1581. }
  1582. if (NULL != pdwNameId)
  1583. {
  1584. *pdwNameId = MAXDWORD;
  1585. hr = myGetNameId(*ppCACert, pdwNameId);
  1586. _PrintIfError(hr, "myGetNameId");
  1587. }
  1588. hr = S_OK;
  1589. error:
  1590. return(hr);
  1591. }
  1592. HRESULT
  1593. myFindCACertByHashIndex(
  1594. IN HCERTSTORE hStore,
  1595. IN WCHAR const *pwszSanitizedCAName,
  1596. IN DWORD dwRegHashChoice,
  1597. IN DWORD Index,
  1598. OPTIONAL OUT DWORD *pdwNameId,
  1599. CERT_CONTEXT const **ppCACert)
  1600. {
  1601. HRESULT hr;
  1602. DWORD cbHash;
  1603. BYTE *pbHash = NULL;
  1604. CSASSERT(NULL != hStore && NULL != ppCACert);
  1605. if (NULL != pdwNameId)
  1606. {
  1607. *pdwNameId = MAXDWORD;
  1608. }
  1609. *ppCACert = NULL;
  1610. hr = myGetCARegHash(
  1611. pwszSanitizedCAName,
  1612. dwRegHashChoice,
  1613. Index,
  1614. &pbHash,
  1615. &cbHash);
  1616. _JumpIfError2(hr, error, "myGetCARegHash", S_FALSE);
  1617. hr = myFindCACertByHash(hStore, pbHash, cbHash, pdwNameId, ppCACert);
  1618. _JumpIfError(hr, error, "myFindCACertByHash");
  1619. error:
  1620. if (NULL != pbHash)
  1621. {
  1622. LocalFree(pbHash);
  1623. }
  1624. return(hr);
  1625. }
  1626. HRESULT
  1627. GetSetupStatus(
  1628. OPTIONAL IN WCHAR const *pwszSanitizedCAName,
  1629. OUT DWORD *pdwStatus)
  1630. {
  1631. HRESULT hr;
  1632. hr = myGetCertRegDWValue(
  1633. pwszSanitizedCAName,
  1634. NULL,
  1635. NULL,
  1636. wszREGSETUPSTATUS,
  1637. pdwStatus);
  1638. _JumpIfErrorStr2(
  1639. hr,
  1640. error,
  1641. "myGetCertRegDWValue",
  1642. wszREGSETUPSTATUS,
  1643. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  1644. DBGPRINT((DBG_SS_CERTLIBI, "GetSetupStatus(%ws) --> %x\n", pwszSanitizedCAName, *pdwStatus));
  1645. error:
  1646. return(hr);
  1647. }
  1648. HRESULT
  1649. SetSetupStatus(
  1650. OPTIONAL IN WCHAR const *pwszSanitizedCAName,
  1651. IN const DWORD dwFlag,
  1652. IN const BOOL fSetBit)
  1653. {
  1654. HRESULT hr;
  1655. DWORD dwCurrentStatus;
  1656. DWORD dwStatus = dwFlag;
  1657. hr = myGetCertRegDWValue(
  1658. pwszSanitizedCAName,
  1659. NULL,
  1660. NULL,
  1661. wszREGSETUPSTATUS,
  1662. &dwCurrentStatus);
  1663. _PrintIfError2(
  1664. hr,
  1665. "myGetCertRegDWValue",
  1666. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  1667. // check to if there is existing status
  1668. if (S_OK == hr || 0xFFFFFFFF == dwStatus)
  1669. {
  1670. // existing status, set according to dwFlag
  1671. if (fSetBit)
  1672. {
  1673. // set corresponding bit
  1674. dwStatus = dwCurrentStatus | dwStatus;
  1675. }
  1676. else
  1677. {
  1678. // unset corresponding
  1679. dwStatus = dwCurrentStatus & ~dwStatus;
  1680. }
  1681. }
  1682. else if(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)==hr)
  1683. {
  1684. hr = S_OK;
  1685. // entry doesn't exist, if fSetBit, keep dwStatus=dwFlag
  1686. if (!fSetBit)
  1687. {
  1688. // otherwise set all 0
  1689. dwStatus = 0;
  1690. }
  1691. }
  1692. else
  1693. {
  1694. _JumpIfError(hr, error, "myGetCertRegDWValue(wszREGSETUPSTATUS)");
  1695. }
  1696. hr = mySetCertRegDWValue(
  1697. pwszSanitizedCAName,
  1698. NULL,
  1699. NULL,
  1700. wszREGSETUPSTATUS,
  1701. dwStatus);
  1702. _JumpIfError(hr, error, "mySetCertRegDWValue");
  1703. DBGPRINT((DBG_SS_CERTLIBI, "SetSetupStatus(%ws, %x)\n", pwszSanitizedCAName, dwStatus));
  1704. error:
  1705. return(hr);
  1706. }
  1707. HRESULT
  1708. myGetActiveManageModule(
  1709. OPTIONAL IN WCHAR const *pwszMachine,
  1710. IN WCHAR const *pwszSanitizedCAName,
  1711. IN BOOL fPolicyModule,
  1712. IN DWORD Index,
  1713. OUT LPOLESTR *ppwszProgIdManageModule, // CoTaskMem*
  1714. OUT CLSID *pclsidManageModule)
  1715. {
  1716. DWORD dw;
  1717. PBYTE pb = NULL;
  1718. DWORD cbClassName;
  1719. LPOLESTR lpszProgID = NULL;
  1720. LPWSTR szClassName = NULL;
  1721. if (NULL != *ppwszProgIdManageModule)
  1722. {
  1723. CoTaskMemFree(*ppwszProgIdManageModule);
  1724. *ppwszProgIdManageModule = NULL;
  1725. }
  1726. dw = myGetActiveModule(
  1727. pwszMachine,
  1728. pwszSanitizedCAName,
  1729. fPolicyModule,
  1730. Index,
  1731. &lpszProgID,
  1732. NULL);
  1733. if (S_OK != dw)
  1734. goto error;
  1735. {
  1736. // terminate class name at first '.'
  1737. LPWSTR pAddTermination = wcschr(lpszProgID, L'.');
  1738. if (NULL != pAddTermination)
  1739. {
  1740. pAddTermination[0] = L'\0';
  1741. }
  1742. }
  1743. cbClassName = (wcslen(lpszProgID) + 1) * sizeof(WCHAR);
  1744. cbClassName += (fPolicyModule) ? sizeof(wszCERTMANAGEPOLICY_POSTFIX) : sizeof(wszCERTMANAGEEXIT_POSTFIX);
  1745. szClassName = (LPWSTR) CoTaskMemAlloc(cbClassName);
  1746. if (NULL == szClassName)
  1747. goto error;
  1748. wcscpy(szClassName, lpszProgID);
  1749. wcscat(szClassName, fPolicyModule? wszCERTMANAGEPOLICY_POSTFIX : wszCERTMANAGEEXIT_POSTFIX);
  1750. // Now we have class module name, cvt to clsid
  1751. dw = CLSIDFromProgID(szClassName, pclsidManageModule);
  1752. if (S_OK != dw)
  1753. goto error; // clsid not found?
  1754. error:
  1755. if (pb)
  1756. LocalFree(pb);
  1757. // intermediate ProgId
  1758. if (lpszProgID)
  1759. CoTaskMemFree(lpszProgID);
  1760. *ppwszProgIdManageModule = szClassName;
  1761. return dw;
  1762. }
  1763. HRESULT
  1764. myGetActiveModule(
  1765. OPTIONAL IN WCHAR const *pwszMachine,
  1766. IN WCHAR const *pwszSanitizedCAName,
  1767. IN BOOL fPolicyModule,
  1768. IN DWORD Index,
  1769. OPTIONAL OUT LPOLESTR *ppwszProgIdModule, // CoTaskMem*
  1770. OPTIONAL OUT CLSID *pclsidModule)
  1771. {
  1772. HRESULT hr;
  1773. WCHAR *pwszzValue = NULL;
  1774. WCHAR *pwsz;
  1775. DWORD dwType;
  1776. DWORD cb = 0;
  1777. LPWSTR pwszModuleSubkey = NULL;
  1778. DWORD chModule;
  1779. chModule = wcslen(pwszSanitizedCAName) + 1 + 1; // (L'\\' + trailing L'\0');
  1780. chModule += fPolicyModule?
  1781. WSZARRAYSIZE(wszREGKEYPOLICYMODULES) :
  1782. WSZARRAYSIZE(wszREGKEYEXITMODULES);
  1783. pwszModuleSubkey = (LPWSTR) LocalAlloc(
  1784. LMEM_FIXED,
  1785. chModule * sizeof(WCHAR));
  1786. if (NULL == pwszModuleSubkey)
  1787. {
  1788. hr = E_OUTOFMEMORY;
  1789. _JumpError(hr, error, "LocalAlloc");
  1790. }
  1791. wcscpy(pwszModuleSubkey, pwszSanitizedCAName);
  1792. wcscat(pwszModuleSubkey, L"\\");
  1793. wcscat(
  1794. pwszModuleSubkey,
  1795. fPolicyModule? wszREGKEYPOLICYMODULES : wszREGKEYEXITMODULES);
  1796. // grab entry under CA with the active module ProgID
  1797. hr = myGetCertRegValue(
  1798. pwszMachine,
  1799. pwszModuleSubkey,
  1800. NULL,
  1801. NULL,
  1802. wszREGACTIVE,
  1803. (BYTE **) &pwszzValue,
  1804. &cb,
  1805. &dwType);
  1806. _JumpIfError(hr, error, "myGetCertRegValue");
  1807. hr = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
  1808. // might or might not have an active entry
  1809. if (REG_SZ != dwType && REG_MULTI_SZ != dwType)
  1810. {
  1811. _JumpError(hr, error, "Bad active entry type");
  1812. }
  1813. if (0 == cb || NULL == pwszzValue)
  1814. {
  1815. _JumpError(hr, error, "No active entry");
  1816. }
  1817. if (0 != Index && (REG_SZ == dwType || fPolicyModule))
  1818. {
  1819. _JumpError(hr, error, "only one policy module or REG_SZ entry");
  1820. }
  1821. pwsz = pwszzValue;
  1822. if (REG_MULTI_SZ == dwType)
  1823. {
  1824. // look for Index'th entry
  1825. for ( ; 0 != Index; pwsz += wcslen(pwsz) + 1, Index--)
  1826. {
  1827. if (L'\0' == *pwsz)
  1828. {
  1829. _JumpError(hr, error, "No more active entries");
  1830. }
  1831. }
  1832. }
  1833. // Verify nth entry exists
  1834. if (L'\0' == *pwsz)
  1835. {
  1836. _JumpError(hr, error, "No active entries");
  1837. }
  1838. if (NULL != pclsidModule)
  1839. {
  1840. hr = CLSIDFromProgID(pwsz, pclsidModule);
  1841. _JumpIfError(hr, error, "CLSIDFromProgID");
  1842. }
  1843. if (NULL != ppwszProgIdModule)
  1844. {
  1845. *ppwszProgIdModule = (LPOLESTR) CoTaskMemAlloc(
  1846. (wcslen(pwsz) + 1) * sizeof(WCHAR));
  1847. if (NULL == *ppwszProgIdModule)
  1848. {
  1849. hr = E_OUTOFMEMORY;
  1850. _JumpError(hr, error, "CoTaskMemAlloc");
  1851. }
  1852. wcscpy(*ppwszProgIdModule, pwsz);
  1853. }
  1854. hr = S_OK; // not reset after ERROR_MOD_NOT_FOUND in all cases
  1855. error:
  1856. if (NULL != pwszModuleSubkey)
  1857. {
  1858. LocalFree(pwszModuleSubkey);
  1859. }
  1860. if (NULL != pwszzValue)
  1861. {
  1862. LocalFree(pwszzValue);
  1863. }
  1864. return(hr);
  1865. }
  1866. BOOL
  1867. IsPrefix(
  1868. WCHAR const *pwszPrefix,
  1869. WCHAR const *pwszString,
  1870. DWORD cwcPrefix)
  1871. {
  1872. return(
  1873. 0 == _wcsnicmp(pwszPrefix, pwszString, cwcPrefix) &&
  1874. (L'\\' == pwszString[cwcPrefix] ||
  1875. L'\0' == pwszString[cwcPrefix]));
  1876. }
  1877. //+------------------------------------------------------------------------
  1878. // Function: myRegOpenRelativeKey
  1879. //
  1880. // Synopsis: Compute CA-relative, Policy-relative or Exit-relative registry
  1881. // path, and retrieve the value, type, and parent registry key.
  1882. //
  1883. // IN params:
  1884. //
  1885. // pwszConfig is the config string of the CA:
  1886. // if NULL, the local machine's first active CA is used.
  1887. // if a server name (no \CAName is present), the specified machine's
  1888. // first active CA is used.
  1889. //
  1890. // pwszRegName can specify any of the following the targets:
  1891. // Passed String: ValueName Relative Key Opened:
  1892. // ------------- ------------------------------
  1893. // "ValueName" Configuration key
  1894. // "CA[\ValueName]" CAName key
  1895. // "policy[\ValueName]" CAName\PolicyModules\<ActivePolicy>
  1896. // "policy\ModuleProgId[\ValueName]" CAName\PolicyModules\ModuleProgId
  1897. // "exit[\ValueName]" CAName\ExitModules\<ActiveExit>
  1898. // "exit\ModuleProgId[\ValueName]" CAName\ExitModules\ModuleProgId
  1899. // "Template[\ValueName]" Template
  1900. //
  1901. //
  1902. // RORKF_FULLPATH specifies whether the path returned is relative from HKLM or
  1903. // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration.
  1904. //
  1905. // RORKF_CREATESUBKEYS will allow subkeys to be created if necessary and the
  1906. // returned hkey opened for WRITE access
  1907. //
  1908. // RORKF_CREATEKEY will allow the top level key to be created if necessary
  1909. //
  1910. // On successful execution:
  1911. //
  1912. // *ppwszPath will contain a LocalAlloc'd registry path relative to
  1913. // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration.
  1914. //
  1915. // *ppwszName will contain a LocalAlloc'd registry value name string relative to
  1916. // the returned parent key. If NULL, pwszRegName specifies a key, not a value.
  1917. //
  1918. // *phkey contains the opened reg key, if phkey non-NULL. Caller is responsible
  1919. // for freeing this key.
  1920. //-------------------------------------------------------------------------
  1921. HRESULT
  1922. myRegOpenRelativeKey(
  1923. OPTIONAL IN WCHAR const *pwszConfig,
  1924. IN WCHAR const *pwszRegName,
  1925. IN DWORD Flags, // RORKF_*
  1926. OUT WCHAR **ppwszPath,
  1927. OUT OPTIONAL WCHAR **ppwszName,
  1928. OUT OPTIONAL HKEY *phkey)
  1929. {
  1930. HRESULT hr;
  1931. WCHAR awc[MAX_PATH];
  1932. WCHAR awc2[MAX_PATH];
  1933. HKEY hkeyRoot = HKEY_LOCAL_MACHINE;
  1934. HKEY hkeyConfig = NULL;
  1935. HKEY hkeyMod = NULL;
  1936. HKEY hkeyRequested = NULL;
  1937. WCHAR *pwszMachine = NULL;
  1938. WCHAR const *pwszModules = NULL;
  1939. WCHAR const *pwszName;
  1940. WCHAR const *pwsz;
  1941. DWORD dwType;
  1942. DWORD cb;
  1943. DWORD cwc;
  1944. DWORD i;
  1945. BOOL fTemplateCache;
  1946. DWORD dwDisposition;
  1947. // Parameter checking
  1948. if (NULL != phkey)
  1949. {
  1950. *phkey = NULL;
  1951. }
  1952. if (NULL != ppwszName)
  1953. {
  1954. *ppwszName = NULL;
  1955. }
  1956. if (NULL == ppwszPath)
  1957. {
  1958. hr = E_POINTER;
  1959. _JumpError(hr, error, "ppwszPath not optional");
  1960. }
  1961. *ppwszPath = NULL;
  1962. fTemplateCache = IsPrefix(L"Template", pwszRegName, 8);
  1963. if (fTemplateCache && (RORKF_USERKEY & Flags))
  1964. {
  1965. hkeyRoot = HKEY_CURRENT_USER;
  1966. }
  1967. // take care of remote machine access
  1968. if (NULL != pwszConfig)
  1969. {
  1970. BOOL fLocal;
  1971. hr = myIsConfigLocal(pwszConfig, &pwszMachine, &fLocal);
  1972. _JumpIfError(hr, error, "myIsConfigLocal");
  1973. if (!fLocal)
  1974. {
  1975. hr = RegConnectRegistry(pwszMachine, hkeyRoot, &hkeyRoot);
  1976. _JumpIfErrorStr(hr, error, "RegConnectRegistry", pwszMachine);
  1977. }
  1978. }
  1979. if (!fTemplateCache)
  1980. {
  1981. hr = RegOpenKeyEx(
  1982. hkeyRoot,
  1983. wszREGKEYCONFIGPATH,
  1984. 0,
  1985. (RORKF_CREATESUBKEYS & Flags)? KEY_ALL_ACCESS : KEY_READ,
  1986. &hkeyConfig);
  1987. if ((HRESULT) ERROR_FILE_NOT_FOUND == hr && (RORKF_CREATEKEY & Flags))
  1988. {
  1989. _PrintError(hr, "RegOpenKey(config)");
  1990. hr = RegCreateKey(hkeyRoot, wszREGKEYCONFIGPATH, &hkeyConfig);
  1991. _JumpIfError(hr, error, "RegCreateKey(config)");
  1992. }
  1993. _JumpIfError(hr, error, "RegOpenKey(config)");
  1994. }
  1995. // value or key\value passed in under pwszRegName?
  1996. pwsz = wcschr(pwszRegName, L'\\');
  1997. if (NULL == pwsz &&
  1998. !IsPrefix(L"CA", pwszRegName, 2) &&
  1999. !IsPrefix(L"Policy", pwszRegName, 6) &&
  2000. !IsPrefix(L"Exit", pwszRegName, 4) &&
  2001. !IsPrefix(L"Restore", pwszRegName, 7) &&
  2002. !IsPrefix(L"Config", pwszRegName, 6) &&
  2003. !fTemplateCache)
  2004. {
  2005. // Operate on registry value under the Configuration registry key
  2006. pwszName = pwszRegName;
  2007. // this is the final key we'll open
  2008. hkeyRequested = hkeyConfig;
  2009. hkeyConfig = NULL;
  2010. awc[0] = L'\0';
  2011. }
  2012. else if (fTemplateCache)
  2013. {
  2014. pwszName = &pwszRegName[8];
  2015. wcscpy(awc, wszCERTTYPECACHE);
  2016. }
  2017. else
  2018. {
  2019. //printf("RegName = '%ws'\n", pwszRegName);
  2020. // load config of the active CA
  2021. awc[0] = L'\0';
  2022. if (!IsPrefix(L"Config", pwszRegName, 6))
  2023. {
  2024. cb = sizeof(awc);
  2025. hr = RegQueryValueEx(
  2026. hkeyConfig,
  2027. wszREGACTIVE,
  2028. NULL,
  2029. &dwType,
  2030. (BYTE *) awc,
  2031. &cb);
  2032. _JumpIfErrorStr(hr, error, "RegQueryValueEx", wszREGACTIVE);
  2033. if (REG_SZ != dwType && REG_MULTI_SZ != dwType)
  2034. {
  2035. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  2036. _JumpIfErrorStr(hr, error, "RegQueryValueEx TYPE", wszREGACTIVE);
  2037. }
  2038. //printf("Active CA = '%ws'\n", awc);
  2039. }
  2040. // operate on key\value
  2041. // first, subdivide into policymodules\exitmodules subkey
  2042. if (IsPrefix(L"CA", pwszRegName, 2))
  2043. {
  2044. // Operate on registry value under the Active CA registry key
  2045. pwszName = &pwszRegName[2];
  2046. }
  2047. else if (IsPrefix(L"Policy", pwszRegName, 6))
  2048. {
  2049. // Operate on registry value under a Policy Module registry key
  2050. pwszModules = wszREGKEYPOLICYMODULES;
  2051. pwszName = &pwszRegName[6];
  2052. }
  2053. else if (IsPrefix(L"Exit", pwszRegName, 4))
  2054. {
  2055. // Operate on registry value under an Exit Module registry key
  2056. pwszModules = wszREGKEYEXITMODULES;
  2057. pwszName = &pwszRegName[4];
  2058. }
  2059. else if (IsPrefix(L"Restore", pwszRegName, 7))
  2060. {
  2061. // Operate on registry value under Restore registry key
  2062. pwszName = &pwszRegName[7];
  2063. wcscpy(awc, wszREGKEYRESTOREINPROGRESS);
  2064. }
  2065. else if (IsPrefix(L"Config", pwszRegName, 6))
  2066. {
  2067. // Operate on registry value under Configuration registry key
  2068. pwszName = &pwszRegName[6];
  2069. }
  2070. else
  2071. {
  2072. hr = E_INVALIDARG;
  2073. _JumpError(hr, error, "pwszRegName: no subkey description");
  2074. }
  2075. // expand module ProgId if necessary: get active ProgId
  2076. if (NULL != pwszModules) // if a policy or exit module
  2077. {
  2078. wcscat(awc, L"\\");
  2079. wcscat(awc, pwszModules);
  2080. }
  2081. //printf("CA|restore|policy|exit key = '%ws'\n", awc);
  2082. if (NULL != ppwszName) // if a registry value expected
  2083. {
  2084. // Find active policy/exit module's ProgId
  2085. hr = RegOpenKeyEx(
  2086. hkeyConfig,
  2087. awc,
  2088. 0,
  2089. KEY_READ,
  2090. &hkeyMod);
  2091. _JumpIfErrorStr(hr, error, "RegOpenKey", awc);
  2092. if (NULL != pwszModules) // if a policy or exit module
  2093. {
  2094. cb = sizeof(awc2);
  2095. hr = RegQueryValueEx(
  2096. hkeyMod,
  2097. wszREGACTIVE,
  2098. NULL,
  2099. &dwType,
  2100. (BYTE *) awc2,
  2101. &cb);
  2102. _JumpIfErrorStr(hr, error, "RegQueryValueEx", wszREGACTIVE);
  2103. if (REG_SZ != dwType && REG_MULTI_SZ != dwType)
  2104. {
  2105. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  2106. _JumpIfErrorStr(hr, error, "RegQueryValueEx Active Module", awc);
  2107. }
  2108. //printf("Active Module = '%ws'\n", awc2);
  2109. wcscat(awc, L"\\");
  2110. wcscat(awc, awc2);
  2111. }
  2112. }
  2113. else // else a registry key name is expected
  2114. {
  2115. // key\value: ProgId was passed in
  2116. // concatenate key name (including the \\ prefix) onto end of awc
  2117. if (NULL != pwsz)
  2118. {
  2119. CSASSERT(L'\\' == *pwsz);
  2120. wcscat(awc, pwsz);
  2121. }
  2122. }
  2123. } // end if (operate on key/value or value)
  2124. if (NULL == hkeyRequested)
  2125. {
  2126. //printf("Creating key = '%ws'\n", awc);
  2127. // open this key
  2128. hr = RegCreateKeyEx(
  2129. NULL != hkeyConfig? hkeyConfig : hkeyRoot,
  2130. awc,
  2131. 0,
  2132. NULL,
  2133. 0,
  2134. (RORKF_CREATESUBKEYS & Flags)? KEY_ALL_ACCESS : KEY_READ,
  2135. NULL,
  2136. &hkeyRequested,
  2137. &dwDisposition);
  2138. _JumpIfErrorStr(hr, error, "RegCreateKeyEx(parent)", awc);
  2139. } // end if (operate on key/value or value)
  2140. if (L'\\' == *pwszName)
  2141. {
  2142. pwszName++;
  2143. }
  2144. if (NULL != ppwszName && L'\0' != *pwszName)
  2145. {
  2146. // Look for case-ignore matching registry value name, & use the value's
  2147. // correct upper/lower case spelling if an existing registry value:
  2148. for (i = 0; ; i++)
  2149. {
  2150. cwc = ARRAYSIZE(awc2);
  2151. hr = RegEnumValue(hkeyRequested, i, awc2, &cwc, NULL, NULL, NULL, NULL);
  2152. if (S_OK != hr)
  2153. {
  2154. hr = S_OK;
  2155. break;
  2156. }
  2157. if (0 == mylstrcmpiL(awc2, pwszName))
  2158. {
  2159. pwszName = awc2;
  2160. break;
  2161. }
  2162. }
  2163. }
  2164. cb = (wcslen(awc) + 1) * sizeof(WCHAR);
  2165. if (!fTemplateCache && (RORKF_FULLPATH & Flags))
  2166. {
  2167. cb += WSZARRAYSIZE(wszREGKEYCONFIGPATH_BS) * sizeof(WCHAR);
  2168. }
  2169. *ppwszPath = (WCHAR *) LocalAlloc(LMEM_FIXED, cb);
  2170. if (NULL == *ppwszPath)
  2171. {
  2172. hr = E_OUTOFMEMORY;
  2173. _JumpError(hr, error, "LocalAlloc");
  2174. }
  2175. (*ppwszPath)[0] = L'\0';
  2176. if (!fTemplateCache && (RORKF_FULLPATH & Flags))
  2177. {
  2178. wcscpy(*ppwszPath, wszREGKEYCONFIGPATH_BS);
  2179. }
  2180. wcscat(*ppwszPath, awc);
  2181. CSASSERT((wcslen(*ppwszPath) + 1) * sizeof(WCHAR) == cb);
  2182. if (L'\0' == awc[0] && L'\\' == (*ppwszPath)[cb / sizeof(WCHAR) - 2])
  2183. {
  2184. (*ppwszPath)[cb / sizeof(WCHAR) - 2] = L'\0';
  2185. }
  2186. if (NULL != ppwszName)
  2187. {
  2188. *ppwszName = (WCHAR *) LocalAlloc(
  2189. LMEM_FIXED,
  2190. (wcslen(pwszName) + 1) * sizeof(WCHAR));
  2191. if (NULL == *ppwszName)
  2192. {
  2193. hr = E_OUTOFMEMORY;
  2194. _JumpError(hr, error, "LocalAlloc");
  2195. }
  2196. wcscpy(*ppwszName, pwszName);
  2197. }
  2198. if (NULL != phkey)
  2199. {
  2200. *phkey = hkeyRequested;
  2201. hkeyRequested = NULL;
  2202. }
  2203. hr = S_OK;
  2204. //printf("key path = '%ws'\n", *ppwszPath);
  2205. //if (NULL != ppwszName) printf("value name = '%ws'\n", *ppwszName);
  2206. error:
  2207. if (HKEY_LOCAL_MACHINE != hkeyRoot && HKEY_CURRENT_USER != hkeyRoot)
  2208. {
  2209. RegCloseKey(hkeyRoot);
  2210. }
  2211. if (NULL != hkeyConfig)
  2212. {
  2213. RegCloseKey(hkeyConfig);
  2214. }
  2215. if (NULL != hkeyMod)
  2216. {
  2217. RegCloseKey(hkeyMod);
  2218. }
  2219. if (NULL != hkeyRequested)
  2220. {
  2221. RegCloseKey(hkeyRequested);
  2222. }
  2223. if (NULL != pwszMachine)
  2224. {
  2225. LocalFree(pwszMachine);
  2226. }
  2227. if (S_OK != hr)
  2228. {
  2229. if (NULL != ppwszPath && NULL != *ppwszPath)
  2230. {
  2231. LocalFree(*ppwszPath);
  2232. *ppwszPath = NULL;
  2233. }
  2234. if (NULL != ppwszName && NULL != *ppwszName)
  2235. {
  2236. LocalFree(*ppwszName);
  2237. *ppwszName = NULL;
  2238. }
  2239. }
  2240. return(myHError(hr));
  2241. }
  2242. #define wszTEMPLATE wszFCSAPARM_SERVERDNSNAME L"_" wszFCSAPARM_SANITIZEDCANAME
  2243. #define cwcTEMPLATE WSZARRAYSIZE(wszTEMPLATE)
  2244. HRESULT
  2245. mySetCARegFileNameTemplate(
  2246. IN WCHAR const *pwszRegValueName,
  2247. IN WCHAR const *pwszServerName,
  2248. IN WCHAR const *pwszSanitizedName,
  2249. IN WCHAR const *pwszFileName)
  2250. {
  2251. HRESULT hr;
  2252. WCHAR *pwszMatch = NULL;
  2253. WCHAR *pwszMatchIn;
  2254. WCHAR const *pwszBase;
  2255. WCHAR const *pwszExt;
  2256. DWORD cwcPath;
  2257. DWORD cwcBase;
  2258. DWORD cwcMatch;
  2259. DWORD cwcT;
  2260. WCHAR *pwszT = NULL;
  2261. WCHAR *pwszT2;
  2262. pwszBase = wcsrchr(pwszFileName, L'\\');
  2263. if (NULL == pwszBase)
  2264. {
  2265. hr = HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND);
  2266. _JumpErrorStr(hr, error, "bad path", pwszFileName);
  2267. }
  2268. pwszBase++;
  2269. cwcPath = SAFE_SUBTRACT_POINTERS(pwszBase, pwszFileName);
  2270. pwszExt = wcsrchr(pwszBase, L'.');
  2271. if (NULL == pwszExt)
  2272. {
  2273. pwszExt = &pwszBase[wcslen(pwszBase)];
  2274. }
  2275. cwcBase = SAFE_SUBTRACT_POINTERS(pwszExt, pwszBase);
  2276. cwcMatch = wcslen(pwszServerName) + 1 + wcslen(pwszSanitizedName);
  2277. if (cwcBase == cwcMatch)
  2278. {
  2279. // Allocate space for both strings at once:
  2280. pwszMatch = (WCHAR *) LocalAlloc(
  2281. LMEM_FIXED,
  2282. 2 * (cwcMatch + 1) * sizeof(WCHAR));
  2283. if (NULL == pwszMatch)
  2284. {
  2285. hr = E_OUTOFMEMORY;
  2286. _JumpError(hr, error, "LocalAlloc");
  2287. }
  2288. wcscpy(pwszMatch, pwszServerName);
  2289. wcscat(pwszMatch, L"_");
  2290. wcscat(pwszMatch, pwszSanitizedName);
  2291. pwszMatchIn = &pwszMatch[cwcMatch + 1];
  2292. CopyMemory(pwszMatchIn, pwszBase, cwcMatch * sizeof(WCHAR));
  2293. pwszMatchIn[cwcMatch] = L'\0';
  2294. if (0 == mylstrcmpiL(pwszMatch, pwszMatchIn))
  2295. {
  2296. pwszBase = wszTEMPLATE;
  2297. cwcBase = cwcTEMPLATE;
  2298. }
  2299. }
  2300. cwcT = cwcPath +
  2301. cwcBase +
  2302. WSZARRAYSIZE(wszFCSAPARM_CERTFILENAMESUFFIX) +
  2303. wcslen(pwszExt);
  2304. pwszT = (WCHAR *) LocalAlloc(
  2305. LMEM_FIXED,
  2306. (cwcT + 1) * sizeof(WCHAR));
  2307. if (NULL == pwszT)
  2308. {
  2309. hr = E_OUTOFMEMORY;
  2310. _JumpError(hr, error, "LocalAlloc");
  2311. }
  2312. pwszT2 = pwszT;
  2313. CopyMemory(pwszT2, pwszFileName, cwcPath * sizeof(WCHAR));
  2314. pwszT2 += cwcPath;
  2315. CopyMemory(pwszT2, pwszBase, cwcBase * sizeof(WCHAR));
  2316. pwszT2 += cwcBase;
  2317. wcscpy(pwszT2, wszFCSAPARM_CERTFILENAMESUFFIX);
  2318. wcscat(pwszT2, pwszExt);
  2319. hr = mySetCertRegStrValue(
  2320. pwszSanitizedName,
  2321. NULL,
  2322. NULL,
  2323. pwszRegValueName,
  2324. pwszT);
  2325. _JumpIfErrorStr(hr, error, "mySetCertRegStrValue", pwszRegValueName);
  2326. error:
  2327. if (NULL != pwszMatch)
  2328. {
  2329. LocalFree(pwszMatch);
  2330. }
  2331. if (NULL != pwszT)
  2332. {
  2333. LocalFree(pwszT);
  2334. }
  2335. return(hr);
  2336. }
  2337. HRESULT
  2338. myGetCARegFileNameTemplate(
  2339. IN WCHAR const *pwszRegValueName,
  2340. IN WCHAR const *pwszServerName,
  2341. IN WCHAR const *pwszSanitizedName,
  2342. IN DWORD iCert,
  2343. IN DWORD iCRL,
  2344. OUT WCHAR **ppwszFileName)
  2345. {
  2346. HRESULT hr;
  2347. WCHAR *pwszT = NULL;
  2348. *ppwszFileName = NULL;
  2349. hr = myGetCertRegStrValue(
  2350. pwszSanitizedName,
  2351. NULL,
  2352. NULL,
  2353. pwszRegValueName,
  2354. &pwszT);
  2355. _JumpIfErrorStr2(
  2356. hr,
  2357. error,
  2358. "myGetCertRegStrValue",
  2359. pwszRegValueName,
  2360. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  2361. hr = myFormatCertsrvStringArray(
  2362. FALSE, // fURL
  2363. pwszServerName, // pwszServerName_p1_2
  2364. pwszSanitizedName, // pwszSanitizedName_p3_7
  2365. iCert, // iCert_p4
  2366. MAXDWORD, // iCertTarget_p4
  2367. L"", // pwszDomainDN_p5
  2368. L"", // pwszConfigDN_p6
  2369. iCRL, // iCRL_p8
  2370. FALSE, // fDeltaCRL_p9
  2371. FALSE, // fDSAttrib_p10_11
  2372. 1, // cStrings
  2373. (LPCWSTR *) &pwszT, // apwszStringsIn
  2374. ppwszFileName); // apwszStringsOut
  2375. _JumpIfError(hr, error, "myFormatCertsrvStringArray");
  2376. error:
  2377. if (NULL != pwszT)
  2378. {
  2379. LocalFree(pwszT);
  2380. }
  2381. return(hr);
  2382. }