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.

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