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.

5634 lines
127 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: inf.cpp
  7. //
  8. // Contents: Cert Server INF file processing routines
  9. //
  10. //---------------------------------------------------------------------------
  11. #include <pch.cpp>
  12. #pragma hdrstop
  13. #include <certca.h>
  14. #include "csdisp.h"
  15. #include "initcert.h"
  16. #include "clibres.h"
  17. #include "csber.h"
  18. #define __dwFILE__ __dwFILE_CERTLIB_INF_CPP__
  19. #define wszBSCAPOLICYFILE L"\\" wszCAPOLICYFILE
  20. #define wszINFKEY_CONTINUE L"_continue_"
  21. #define wszINFKEY_VERSION L"Version"
  22. #define wszINFSECTION_EXTENSIONS L"Extensions"
  23. #define cwcINFLINEMAX 1024
  24. #define wcBOM (WCHAR) 0xfffe
  25. #define wcBOMBIGENDIAN (WCHAR) 0xfeff
  26. static WCHAR *s_pwszSection = NULL;
  27. static WCHAR *s_pwszKey = NULL;
  28. static WCHAR *s_pwszValue = NULL;
  29. static HRESULT s_hr = S_OK;
  30. static WCHAR g_wcBOM = L'\0';
  31. static BOOL g_fIgnoreReferencedSections = FALSE;
  32. VOID
  33. infClearString(
  34. IN OUT WCHAR **ppwsz)
  35. {
  36. if (NULL != ppwsz && NULL != *ppwsz)
  37. {
  38. LocalFree(*ppwsz);
  39. *ppwsz = NULL;
  40. }
  41. }
  42. BOOL
  43. infCopyString(
  44. OPTIONAL IN WCHAR const *pwszIn,
  45. OPTIONAL OUT WCHAR **ppwszOut)
  46. {
  47. HRESULT hr;
  48. if (NULL != pwszIn && NULL == *ppwszOut)
  49. {
  50. hr = myDupString(pwszIn, ppwszOut);
  51. _JumpIfError(hr, error, "myDupString");
  52. }
  53. hr = S_OK;
  54. error:
  55. return(S_OK == hr);
  56. }
  57. #define INFSTRINGSELECT(pwsz) (NULL != (pwsz)? (pwsz) : L"")
  58. #if DBG_CERTSRV
  59. # define INFSETERROR(hr, pwszSection, pwszKey, pwszValue) \
  60. { \
  61. _PrintError3(hr, "infSetError", ERROR_LINE_NOT_FOUND, S_FALSE); \
  62. infSetError(hr, pwszSection, pwszKey, pwszValue, __LINE__); \
  63. }
  64. #else
  65. # define INFSETERROR infSetError
  66. #endif
  67. VOID
  68. infSetError(
  69. IN HRESULT hr,
  70. OPTIONAL IN WCHAR const *pwszSection,
  71. OPTIONAL IN WCHAR const *pwszKey,
  72. OPTIONAL IN WCHAR const *pwszValue
  73. DBGPARM(IN DWORD dwLine))
  74. {
  75. DBGPRINT((
  76. DBG_SS_CERTLIBI,
  77. "inf.cpp(%u): infSetError Begin: [%ws] %ws = %ws\n",
  78. dwLine,
  79. INFSTRINGSELECT(pwszSection),
  80. INFSTRINGSELECT(pwszKey),
  81. INFSTRINGSELECT(pwszValue)));
  82. s_hr = hr;
  83. infCopyString(pwszSection, &s_pwszSection);
  84. infCopyString(pwszKey, &s_pwszKey);
  85. infCopyString(pwszValue, &s_pwszValue);
  86. DBGPRINT((
  87. DBG_SS_CERTLIBI,
  88. "inf.cpp(%u): infSetError End: [%ws] %ws = %ws\n",
  89. dwLine,
  90. INFSTRINGSELECT(s_pwszSection),
  91. INFSTRINGSELECT(s_pwszKey),
  92. INFSTRINGSELECT(s_pwszValue)));
  93. }
  94. WCHAR *
  95. myInfGetError()
  96. {
  97. DWORD cwc = 1;
  98. WCHAR *pwsz = NULL;
  99. if (NULL != s_pwszSection)
  100. {
  101. cwc += wcslen(s_pwszSection) + 2;
  102. }
  103. if (NULL != s_pwszKey)
  104. {
  105. cwc += wcslen(s_pwszKey) + 1 + 2;
  106. }
  107. if (NULL != s_pwszValue)
  108. {
  109. cwc += wcslen(s_pwszValue) + 1;
  110. }
  111. if (1 == cwc)
  112. {
  113. goto error;
  114. }
  115. pwsz = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  116. if (NULL == pwsz)
  117. {
  118. goto error;
  119. }
  120. *pwsz = L'\0';
  121. if (NULL != s_pwszSection)
  122. {
  123. wcscat(pwsz, wszLBRACKET);
  124. wcscat(pwsz, s_pwszSection);
  125. wcscat(pwsz, wszRBRACKET);
  126. }
  127. if (NULL != s_pwszKey && L'\0' != s_pwszKey[0])
  128. {
  129. wcscat(pwsz, L" ");
  130. wcscat(pwsz, s_pwszKey);
  131. wcscat(pwsz, L" =");
  132. }
  133. if (NULL != s_pwszValue && L'\0' != s_pwszValue[0])
  134. {
  135. wcscat(pwsz, L" ");
  136. wcscat(pwsz, s_pwszValue);
  137. }
  138. error:
  139. return(pwsz);
  140. }
  141. VOID
  142. myInfClearError()
  143. {
  144. s_hr = S_OK;
  145. infClearString(&s_pwszSection);
  146. infClearString(&s_pwszKey);
  147. infClearString(&s_pwszValue);
  148. }
  149. typedef struct _SECTIONINFO {
  150. DWORD dwRefCount;
  151. WCHAR *pwszSection;
  152. struct _SECTIONINFO *pNext;
  153. } SECTIONINFO;
  154. SECTIONINFO *g_pSectionInfo = NULL;
  155. HRESULT
  156. infSaveSectionName(
  157. IN WCHAR const *pwszSection)
  158. {
  159. HRESULT hr;
  160. SECTIONINFO *psi = NULL;
  161. if (0 != LSTRCMPIS(pwszSection, wszINFKEY_VERSION))
  162. {
  163. psi = (SECTIONINFO *) LocalAlloc(
  164. LMEM_FIXED | LMEM_ZEROINIT,
  165. sizeof(*psi));
  166. if (NULL == psi)
  167. {
  168. hr = E_OUTOFMEMORY;
  169. _JumpError(hr, error, "LocalAlloc");
  170. }
  171. hr = myDupString(pwszSection, &psi->pwszSection);
  172. _JumpIfError(hr, error, "myDupString");
  173. psi->pNext = g_pSectionInfo;
  174. g_pSectionInfo = psi;
  175. psi = NULL;
  176. }
  177. hr = S_OK;
  178. error:
  179. if (NULL != psi)
  180. {
  181. LocalFree(psi);
  182. }
  183. return(hr);
  184. }
  185. VOID
  186. infFreeSectionNames()
  187. {
  188. SECTIONINFO *psi;
  189. psi = g_pSectionInfo;
  190. g_pSectionInfo = NULL;
  191. while (NULL != psi)
  192. {
  193. SECTIONINFO *psiNext;
  194. if (NULL != psi->pwszSection)
  195. {
  196. LocalFree(psi->pwszSection);
  197. }
  198. psiNext = psi->pNext;
  199. LocalFree(psi);
  200. psi = psiNext;
  201. }
  202. }
  203. HRESULT
  204. myInfGetUnreferencedSectionNames(
  205. OUT WCHAR **ppwszzSectionNames)
  206. {
  207. HRESULT hr;
  208. DWORD cwc;
  209. SECTIONINFO *psi;
  210. *ppwszzSectionNames = NULL;
  211. cwc = 0;
  212. for (psi = g_pSectionInfo; NULL != psi; psi = psi->pNext)
  213. {
  214. if (0 == psi->dwRefCount)
  215. {
  216. cwc += wcslen(psi->pwszSection) + 3;
  217. }
  218. }
  219. if (0 != cwc)
  220. {
  221. WCHAR *pwszz;
  222. WCHAR *pwsz;
  223. pwszz = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  224. if (NULL == pwszz)
  225. {
  226. hr = E_OUTOFMEMORY;
  227. _JumpError(hr, error, "LocalAlloc");
  228. }
  229. pwsz = pwszz;
  230. for (psi = g_pSectionInfo; NULL != psi; psi = psi->pNext)
  231. {
  232. if (0 == psi->dwRefCount)
  233. {
  234. *pwsz++ = wcLBRACKET;
  235. wcscpy(pwsz, psi->pwszSection);
  236. pwsz += wcslen(pwsz);
  237. *pwsz++ = wcRBRACKET;
  238. *pwsz++ = L'\0';
  239. }
  240. }
  241. *pwsz = L'\0';
  242. CSASSERT(cwc == SAFE_SUBTRACT_POINTERS(pwsz, pwszz));
  243. *ppwszzSectionNames = pwszz;
  244. }
  245. hr = S_OK;
  246. error:
  247. return(hr);
  248. }
  249. HRESULT
  250. infReferenceSectionName(
  251. IN WCHAR const *pwszSection)
  252. {
  253. HRESULT hr;
  254. SECTIONINFO *psi;
  255. if (!g_fIgnoreReferencedSections)
  256. {
  257. for (psi = g_pSectionInfo; NULL != psi; psi = psi->pNext)
  258. {
  259. if (0 == mylstrcmpiL(pwszSection, psi->pwszSection))
  260. {
  261. psi->dwRefCount++;
  262. break;
  263. }
  264. }
  265. if (NULL == psi)
  266. {
  267. hr = SPAPI_E_LINE_NOT_FOUND; // don't ignore this error
  268. _JumpError(hr, error, "unexpected section");
  269. }
  270. }
  271. hr = S_OK;
  272. error:
  273. return(hr);
  274. }
  275. HRESULT
  276. inffopen(
  277. IN WCHAR const *pwszfn,
  278. OUT FILE **ppf)
  279. {
  280. HRESULT hr;
  281. FILE *pf = NULL;
  282. *ppf = NULL;
  283. g_fIgnoreReferencedSections = FALSE;
  284. g_wcBOM = L'\0';
  285. pf = _wfopen(pwszfn, L"r"); // Assume Ansi INF file
  286. if (NULL == pf)
  287. {
  288. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  289. _JumpError(hr, error, "_wfopen");
  290. }
  291. g_wcBOM = (WCHAR) fgetc(pf) << 8;
  292. g_wcBOM |= fgetc(pf);
  293. if (!feof(pf))
  294. {
  295. if (wcBOM == g_wcBOM) // Oops, Unicode INF file
  296. {
  297. fclose(pf);
  298. pf = _wfopen(pwszfn, L"rb");
  299. if (NULL == pf)
  300. {
  301. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  302. _JumpError(hr, error, "fopen");
  303. }
  304. }
  305. else if (wcBOMBIGENDIAN == g_wcBOM)
  306. {
  307. g_fIgnoreReferencedSections = TRUE;
  308. fclose(pf);
  309. pf = NULL;
  310. }
  311. else
  312. {
  313. if (fseek(pf, 0L, SEEK_SET))
  314. {
  315. hr = HRESULT_FROM_WIN32(ERROR_HANDLE_EOF);
  316. _JumpError(hr, error, "fseek");
  317. }
  318. }
  319. }
  320. *ppf = pf;
  321. hr = S_OK;
  322. error:
  323. return(hr);
  324. }
  325. WCHAR *
  326. inffgetws(
  327. OUT WCHAR *pwcLine,
  328. IN DWORD cwcLine,
  329. IN FILE *pfInf)
  330. {
  331. HRESULT hr;
  332. WCHAR *pwc = NULL;
  333. WCHAR *pwsz = NULL;
  334. char achLine[cwcINFLINEMAX];
  335. char *pch;
  336. if (wcBOM == g_wcBOM)
  337. {
  338. pwc = fgetws(pwcLine, cwcLine, pfInf);
  339. }
  340. else
  341. {
  342. pch = fgets(achLine, ARRAYSIZE(achLine), pfInf);
  343. if (NULL == pch)
  344. {
  345. goto error;
  346. }
  347. if (!myConvertSzToWsz(&pwsz, achLine, -1))
  348. {
  349. hr = E_OUTOFMEMORY;
  350. _JumpError(hr, error, "myConvertSzToWsz");
  351. }
  352. wcsncpy(pwcLine, pwsz, cwcLine);
  353. pwcLine[cwcLine - 1] = L'\0';
  354. pwc = pwcLine;
  355. }
  356. error:
  357. if (NULL != pwsz)
  358. {
  359. LocalFree(pwsz);
  360. }
  361. return(pwc);
  362. }
  363. #define ISBLANK(ch) (L' ' == (ch) || L'\t' == (ch))
  364. HRESULT
  365. infCollectSectionNames(
  366. IN WCHAR const *pwszfnInf)
  367. {
  368. HRESULT hr;
  369. FILE *pfInf = NULL;
  370. WCHAR awcLine[cwcINFLINEMAX];
  371. WCHAR *pwszEnd;
  372. hr = inffopen(pwszfnInf, &pfInf);
  373. _JumpIfError(hr, error, "inffopen");
  374. if (!g_fIgnoreReferencedSections)
  375. {
  376. while (NULL != inffgetws(awcLine, ARRAYSIZE(awcLine), pfInf))
  377. {
  378. WCHAR *pwsz;
  379. awcLine[wcscspn(awcLine, L";=\r\n")] = L'\0';
  380. pwsz = wcschr(awcLine, wcLBRACKET);
  381. if (NULL == pwsz)
  382. {
  383. continue;
  384. }
  385. pwsz++;
  386. pwszEnd = wcschr(awcLine, wcRBRACKET);
  387. if (NULL == pwszEnd)
  388. {
  389. continue;
  390. }
  391. *pwszEnd = L'\0';
  392. while (ISBLANK(*pwsz))
  393. {
  394. pwsz++;
  395. }
  396. while (--pwszEnd >= pwsz && ISBLANK(*pwszEnd))
  397. {
  398. *pwszEnd = L'\0';
  399. }
  400. hr = infSaveSectionName(pwsz);
  401. _JumpIfError(hr, error, "infSaveSectionName");
  402. }
  403. }
  404. hr = S_OK;
  405. error:
  406. if (NULL != pfInf)
  407. {
  408. fclose(pfInf);
  409. }
  410. return(hr);
  411. }
  412. HRESULT
  413. infGetCurrentKeyValueAndAlloc(
  414. IN OUT INFCONTEXT *pInfContext,
  415. IN DWORD Index,
  416. OUT WCHAR **ppwszValue)
  417. {
  418. HRESULT hr;
  419. WCHAR *pwszValue = NULL;
  420. DWORD cwc;
  421. if (!SetupGetStringField(pInfContext, Index, NULL, 0, &cwc))
  422. {
  423. hr = myHLastError();
  424. _JumpError2(hr, error, "SetupGetStringField", E_INVALIDARG);
  425. }
  426. pwszValue = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  427. if (NULL == pwszValue)
  428. {
  429. hr = E_OUTOFMEMORY;
  430. _JumpError(hr, error, "LocalAlloc");
  431. }
  432. if (!SetupGetStringField(pInfContext, Index, pwszValue, cwc, NULL))
  433. {
  434. hr = myHLastError();
  435. _JumpError(hr, error, "SetupGetStringField");
  436. }
  437. *ppwszValue = pwszValue;
  438. pwszValue = NULL;
  439. hr = S_OK;
  440. error:
  441. if (NULL != pwszValue)
  442. {
  443. LocalFree(pwszValue);
  444. }
  445. return(hr);
  446. }
  447. HRESULT
  448. infGetCurrentKeyValue(
  449. IN OUT INFCONTEXT *pInfContext,
  450. OPTIONAL IN WCHAR const *pwszSection, // for error logging only
  451. OPTIONAL IN WCHAR const *pwszKey, // for error logging only
  452. IN DWORD Index,
  453. IN BOOL fLastValue,
  454. OUT WCHAR **ppwszValue)
  455. {
  456. HRESULT hr;
  457. WCHAR *pwszValue = NULL;
  458. WCHAR *pwszValueExtra = NULL;
  459. WCHAR *pwszValueError = NULL;
  460. DWORD cwc;
  461. WCHAR *pwszT = NULL;
  462. INFCONTEXT InfContext;
  463. *ppwszValue = NULL;
  464. hr = infGetCurrentKeyValueAndAlloc(pInfContext, Index, &pwszValue);
  465. _JumpIfError2(hr, error, "infGetCurrentKeyValueAndAlloc", E_INVALIDARG);
  466. if (1 == Index)
  467. {
  468. InfContext = *pInfContext;
  469. for (;;)
  470. {
  471. WCHAR *pwsz;
  472. if (!SetupFindNextLine(&InfContext, &InfContext))
  473. {
  474. break;
  475. }
  476. hr = infGetCurrentKeyValueAndAlloc(&InfContext, 0, &pwszT);
  477. _JumpIfError2(hr, error, "infGetCurrentKeyValueAndAlloc", E_INVALIDARG);
  478. if (0 != LSTRCMPIS(pwszT, wszINFKEY_CONTINUE))
  479. {
  480. break;
  481. }
  482. LocalFree(pwszT);
  483. pwszT = NULL;
  484. hr = infGetCurrentKeyValueAndAlloc(&InfContext, 1, &pwszT);
  485. _JumpIfError2(hr, error, "infGetCurrentKeyValueAndAlloc", E_INVALIDARG);
  486. cwc = wcslen(pwszValue) + wcslen(pwszT);
  487. pwsz = (WCHAR *) LocalAlloc(LMEM_FIXED, (cwc + 1) * sizeof(WCHAR));
  488. if (NULL == pwsz)
  489. {
  490. hr = E_OUTOFMEMORY;
  491. _JumpError(hr, error, "LocalAlloc");
  492. }
  493. wcscpy(pwsz, pwszValue);
  494. wcscat(pwsz, pwszT);
  495. LocalFree(pwszValue);
  496. pwszValue = pwsz;
  497. LocalFree(pwszT);
  498. pwszT = NULL;
  499. }
  500. }
  501. if (fLastValue)
  502. {
  503. DWORD cValue;
  504. cValue = SetupGetFieldCount(pInfContext);
  505. if (Index != cValue)
  506. {
  507. DWORD i;
  508. for (i = Index + 5; i > Index; i--)
  509. {
  510. hr = infGetCurrentKeyValue(
  511. pInfContext,
  512. pwszSection,
  513. pwszKey,
  514. i,
  515. FALSE, // fLastValue
  516. &pwszValueExtra);
  517. if (S_OK == hr)
  518. {
  519. DWORD j;
  520. cwc = wcslen(pwszValue) + i - 1 + wcslen(pwszValueExtra);
  521. pwszValueError = (WCHAR *) LocalAlloc(
  522. LMEM_FIXED,
  523. (cwc + 1) * sizeof(WCHAR));
  524. if (NULL == pwszValueError)
  525. {
  526. hr = E_OUTOFMEMORY;
  527. _JumpError(hr, error, "LocalAlloc");
  528. }
  529. pwszValueError[0] = L'\0';
  530. for (j = 1; j < Index; j++)
  531. {
  532. wcscat(pwszValueError, L",");
  533. }
  534. wcscat(pwszValueError, pwszValue);
  535. for (j = Index; j < i; j++)
  536. {
  537. wcscat(pwszValueError, L",");
  538. }
  539. wcscat(pwszValueError, pwszValueExtra);
  540. CSASSERT(wcslen(pwszValueError) == cwc);
  541. hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  542. INFSETERROR(hr, pwszSection, pwszKey, pwszValueError);
  543. _PrintErrorStr(hr, "extra values", pwszKey);
  544. _JumpErrorStr(hr, error, "extra values", pwszValueError);
  545. }
  546. }
  547. }
  548. }
  549. *ppwszValue = pwszValue;
  550. pwszValue = NULL;
  551. hr = S_OK;
  552. error:
  553. if (NULL != pwszT)
  554. {
  555. LocalFree(pwszT);
  556. }
  557. if (NULL != pwszValue)
  558. {
  559. LocalFree(pwszValue);
  560. }
  561. if (NULL != pwszValueExtra)
  562. {
  563. LocalFree(pwszValueExtra);
  564. }
  565. if (NULL != pwszValueError)
  566. {
  567. LocalFree(pwszValueError);
  568. }
  569. return(hr);
  570. }
  571. HRESULT
  572. infFindNextKey(
  573. IN WCHAR const *pwszKey,
  574. IN OUT INFCONTEXT *pInfContext)
  575. {
  576. HRESULT hr;
  577. WCHAR *pwszKeyT = NULL;
  578. for (;;)
  579. {
  580. if (!SetupFindNextLine(pInfContext, pInfContext))
  581. {
  582. hr = myHLastError();
  583. _PrintErrorStr2(hr, "SetupFindNextLine", pwszKey, hr);
  584. if ((HRESULT) ERROR_LINE_NOT_FOUND == hr)
  585. {
  586. hr = S_FALSE;
  587. }
  588. _JumpError2(hr, error, "SetupFindNextLine", hr);
  589. }
  590. if (NULL != pwszKeyT)
  591. {
  592. LocalFree(pwszKeyT);
  593. pwszKeyT = NULL;
  594. }
  595. hr = infGetCurrentKeyValue(
  596. pInfContext,
  597. NULL, // pwszSection
  598. NULL, // pwszKey
  599. 0,
  600. FALSE, // fLastValue
  601. &pwszKeyT);
  602. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  603. if (0 == mylstrcmpiL(pwszKey, pwszKeyT))
  604. {
  605. break;
  606. }
  607. }
  608. hr = S_OK;
  609. error:
  610. if (NULL != pwszKeyT)
  611. {
  612. LocalFree(pwszKeyT);
  613. }
  614. return(hr);
  615. }
  616. HRESULT
  617. infSetupFindFirstLine(
  618. IN HINF hInf,
  619. IN WCHAR const *pwszSection,
  620. OPTIONAL IN WCHAR const *pwszKey,
  621. IN BOOL fUniqueKey,
  622. IN DWORD cValueMax,
  623. OPTIONAL WCHAR const * const *ppwszValidKeys,
  624. IN BOOL fUniqueValidKeys,
  625. OUT INFCONTEXT *pInfContext)
  626. {
  627. HRESULT hr;
  628. WCHAR *pwszValue = NULL;
  629. WCHAR *pwszKeyT = NULL;
  630. WCHAR *pwszValueT = NULL;
  631. if (!SetupFindFirstLine(hInf, pwszSection, pwszKey, pInfContext))
  632. {
  633. // if the [Section] or Key = does not exist, see if the section is
  634. // completely empty. It exists and is empty if SetupGetLineCount
  635. // returns 0, or if the Empty key is found in the section.
  636. hr = myHLastError();
  637. if ((HRESULT) ERROR_LINE_NOT_FOUND == hr &&
  638. (0 == SetupGetLineCount(hInf, pwszSection) ||
  639. SetupFindFirstLine(
  640. hInf,
  641. pwszSection,
  642. wszINFKEY_EMPTY,
  643. pInfContext)))
  644. {
  645. hr = infReferenceSectionName(pwszSection);
  646. _JumpIfErrorStr(hr, error, "infReferenceSectionName", pwszKey);
  647. hr = S_FALSE; // Section exists, but is empty
  648. }
  649. _JumpErrorStr3(
  650. hr,
  651. error,
  652. "SetupFindFirstLine",
  653. pwszSection,
  654. ERROR_LINE_NOT_FOUND,
  655. S_FALSE);
  656. }
  657. hr = infReferenceSectionName(pwszSection);
  658. _JumpIfErrorStr(hr, error, "infReferenceSectionName", pwszKey);
  659. if (NULL != pwszKey)
  660. {
  661. if (fUniqueKey)
  662. {
  663. INFCONTEXT InfContext = *pInfContext;
  664. hr = infFindNextKey(pwszKey, &InfContext);
  665. if (S_OK == hr)
  666. {
  667. hr = infGetCurrentKeyValue(
  668. &InfContext,
  669. pwszSection,
  670. pwszKey,
  671. 1,
  672. FALSE, // fLastValue
  673. &pwszValue);
  674. _PrintIfError(hr, "infGetCurrentKeyValue");
  675. hr = HRESULT_FROM_WIN32(RPC_S_ENTRY_ALREADY_EXISTS);
  676. INFSETERROR(hr, pwszSection, pwszKey, pwszValue);
  677. _JumpErrorStr(hr, error, "duplicate key", pwszKey);
  678. }
  679. }
  680. if (0 != cValueMax)
  681. {
  682. hr = infGetCurrentKeyValue(
  683. pInfContext,
  684. pwszSection,
  685. pwszKey,
  686. cValueMax,
  687. TRUE, // fLastValue
  688. &pwszValue);
  689. _JumpIfErrorStr(hr, error, "infGetCurrentKeyValue", pwszKey);
  690. }
  691. }
  692. if (NULL != ppwszValidKeys)
  693. {
  694. INFCONTEXT InfContext;
  695. WCHAR const * const *ppwszKey;
  696. if (!SetupFindFirstLine(hInf, pwszSection, NULL, &InfContext))
  697. {
  698. hr = myHLastError();
  699. _JumpErrorStr(hr, error, "SetupFindFirstLine", pwszSection)
  700. }
  701. for (;;)
  702. {
  703. hr = infGetCurrentKeyValue(
  704. &InfContext,
  705. pwszSection,
  706. NULL, // pwszKey
  707. 0,
  708. FALSE, // fLastValue
  709. &pwszKeyT);
  710. _JumpIfErrorStr(hr, error, "infGetCurrentKeyValue", pwszSection);
  711. for (ppwszKey = ppwszValidKeys; NULL != *ppwszKey; ppwszKey++)
  712. {
  713. if (0 == mylstrcmpiL(*ppwszKey, pwszKeyT))
  714. {
  715. break;
  716. }
  717. }
  718. if (NULL == *ppwszKey)
  719. {
  720. hr = infGetCurrentKeyValue(
  721. &InfContext,
  722. pwszSection,
  723. pwszKeyT,
  724. 1,
  725. FALSE, // fLastValue
  726. &pwszValueT);
  727. _PrintIfError(hr, "infGetCurrentKeyValue");
  728. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  729. INFSETERROR(hr, pwszSection, pwszKeyT, pwszValueT);
  730. _JumpErrorStr(hr, error, "invalid key", pwszKeyT);
  731. }
  732. if (fUniqueValidKeys)
  733. {
  734. INFCONTEXT InfContextT = InfContext;
  735. hr = infFindNextKey(pwszKeyT, &InfContextT);
  736. if (S_OK == hr)
  737. {
  738. hr = infGetCurrentKeyValue(
  739. &InfContextT,
  740. pwszSection,
  741. pwszKeyT,
  742. 1,
  743. FALSE, // fLastValue
  744. &pwszValueT);
  745. _PrintIfError(hr, "infGetCurrentKeyValue");
  746. hr = HRESULT_FROM_WIN32(RPC_S_ENTRY_ALREADY_EXISTS);
  747. INFSETERROR(hr, pwszSection, pwszKeyT, pwszValueT);
  748. _JumpErrorStr(hr, error, "duplicate key", pwszKeyT);
  749. }
  750. }
  751. LocalFree(pwszKeyT);
  752. pwszKeyT = NULL;
  753. if (!SetupFindNextLine(&InfContext, &InfContext))
  754. {
  755. hr = myHLastError();
  756. _PrintErrorStr2(hr, "SetupFindNextLine", pwszSection, hr);
  757. break;
  758. }
  759. }
  760. }
  761. hr = S_OK;
  762. error:
  763. if (NULL != pwszKeyT)
  764. {
  765. LocalFree(pwszKeyT);
  766. }
  767. if (NULL != pwszValueT)
  768. {
  769. LocalFree(pwszValueT);
  770. }
  771. if (NULL != pwszValue)
  772. {
  773. LocalFree(pwszValue);
  774. }
  775. return(hr);
  776. }
  777. HRESULT
  778. infBuildPolicyElement(
  779. IN OUT INFCONTEXT *pInfContext,
  780. OPTIONAL OUT CERT_POLICY_QUALIFIER_INFO *pcpqi)
  781. {
  782. HRESULT hr;
  783. WCHAR *pwszKey = NULL;
  784. BOOL fURL = FALSE;
  785. BOOL fNotice = FALSE;
  786. WCHAR *pwszValue = NULL;
  787. WCHAR *pwszURL = NULL;
  788. BYTE *pbData = NULL;
  789. DWORD cbData;
  790. hr = infGetCurrentKeyValue(
  791. pInfContext,
  792. NULL, // pwszSection
  793. NULL, // pwszKey
  794. 0,
  795. FALSE, // fLastValue
  796. &pwszKey);
  797. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  798. DBGPRINT((DBG_SS_CERTLIBI, "Element = %ws\n", pwszKey));
  799. if (0 == LSTRCMPIS(pwszKey, wszINFKEY_URL))
  800. {
  801. fURL = TRUE;
  802. }
  803. else
  804. if (0 == LSTRCMPIS(pwszKey, wszINFKEY_NOTICE))
  805. {
  806. fNotice = TRUE;
  807. }
  808. else
  809. {
  810. if (0 != LSTRCMPIS(pwszKey, wszINFKEY_OID) &&
  811. 0 != LSTRCMPIS(pwszKey, wszINFKEY_CONTINUE))
  812. {
  813. hr = E_INVALIDARG;
  814. _JumpErrorStr(hr, error, "unknown key", pwszKey);
  815. }
  816. hr = S_FALSE; // Skip this key
  817. _JumpError2(hr, error, "skip OID key", hr);
  818. }
  819. hr = infGetCurrentKeyValue(
  820. pInfContext,
  821. NULL, // pwszSection
  822. pwszKey,
  823. 1,
  824. TRUE, // fLastValue
  825. &pwszValue);
  826. _JumpIfErrorStr(hr, error, "infGetCurrentKeyValue", pwszKey);
  827. DBGPRINT((DBG_SS_CERTLIBI, "%ws = %ws\n", pwszKey, pwszValue));
  828. if (fURL)
  829. {
  830. CERT_NAME_VALUE NameValue;
  831. hr = myInternetCanonicalizeUrl(pwszValue, &pwszURL);
  832. _JumpIfError(hr, error, "myInternetCanonicalizeUrl");
  833. NameValue.dwValueType = CERT_RDN_IA5_STRING;
  834. NameValue.Value.pbData = (BYTE *) pwszURL;
  835. NameValue.Value.cbData = 0;
  836. if (NULL != pcpqi)
  837. {
  838. CSILOG(S_OK, IDS_ILOG_CAPOLICY_ELEMENT, pwszURL, NULL, NULL);
  839. }
  840. if (!myEncodeObject(
  841. X509_ASN_ENCODING,
  842. X509_UNICODE_NAME_VALUE,
  843. &NameValue,
  844. 0,
  845. CERTLIB_USE_LOCALALLOC,
  846. &pbData,
  847. &cbData))
  848. {
  849. hr = myHLastError();
  850. _JumpError(hr, error, "myEncodeObject");
  851. }
  852. }
  853. else
  854. {
  855. CERT_POLICY_QUALIFIER_USER_NOTICE UserNotice;
  856. ZeroMemory(&UserNotice, sizeof(UserNotice));
  857. UserNotice.pszDisplayText = pwszValue;
  858. if (NULL != pcpqi)
  859. {
  860. CSILOG(S_OK, IDS_ILOG_CAPOLICY_ELEMENT, pwszValue, NULL, NULL);
  861. }
  862. if (!myEncodeObject(
  863. X509_ASN_ENCODING,
  864. X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
  865. &UserNotice,
  866. 0,
  867. CERTLIB_USE_LOCALALLOC,
  868. &pbData,
  869. &cbData))
  870. {
  871. hr = myHLastError();
  872. _JumpError(hr, error, "myEncodeObject");
  873. }
  874. }
  875. if (NULL != pcpqi)
  876. {
  877. pcpqi->pszPolicyQualifierId = fURL?
  878. szOID_PKIX_POLICY_QUALIFIER_CPS :
  879. szOID_PKIX_POLICY_QUALIFIER_USERNOTICE;
  880. pcpqi->Qualifier.pbData = pbData;
  881. pcpqi->Qualifier.cbData = cbData;
  882. pbData = NULL;
  883. }
  884. hr = S_OK;
  885. error:
  886. if (S_OK != hr && S_FALSE != hr)
  887. {
  888. INFSETERROR(hr, NULL, pwszKey, pwszValue);
  889. }
  890. if (NULL != pwszKey)
  891. {
  892. LocalFree(pwszKey);
  893. }
  894. if (NULL != pwszValue)
  895. {
  896. LocalFree(pwszValue);
  897. }
  898. if (NULL != pwszURL)
  899. {
  900. LocalFree(pwszURL);
  901. }
  902. if (NULL != pbData)
  903. {
  904. LocalFree(pbData);
  905. }
  906. return(hr);
  907. }
  908. HRESULT
  909. infBuildPolicy(
  910. IN HINF hInf,
  911. IN WCHAR const *pwszSection,
  912. IN OUT CERT_POLICY_INFO *pcpi)
  913. {
  914. HRESULT hr;
  915. INFCONTEXT InfContext;
  916. DWORD i;
  917. WCHAR *pwszValue = NULL;
  918. static WCHAR const * const s_apwszKeys[] =
  919. {
  920. wszINFKEY_OID,
  921. wszINFKEY_URL,
  922. wszINFKEY_NOTICE,
  923. wszINFKEY_CONTINUE,
  924. NULL
  925. };
  926. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  927. hr = infSetupFindFirstLine(
  928. hInf,
  929. pwszSection,
  930. wszINFKEY_OID,
  931. TRUE, // fUniqueKey
  932. 1, // cValueMax
  933. s_apwszKeys,
  934. FALSE, // fUniqueValidKeys
  935. &InfContext);
  936. if (S_OK != hr)
  937. {
  938. if ((HRESULT) ERROR_LINE_NOT_FOUND == hr)
  939. {
  940. hr = SPAPI_E_LINE_NOT_FOUND; // don't ignore this error
  941. }
  942. INFSETERROR(hr, NULL, wszINFKEY_OID, NULL);
  943. _JumpErrorStr(hr, error, "infSetupFindFirstLine", pwszSection);
  944. }
  945. hr = infGetCurrentKeyValue(
  946. &InfContext,
  947. pwszSection,
  948. wszINFKEY_OID,
  949. 1,
  950. TRUE, // fLastValue
  951. &pwszValue);
  952. _JumpIfErrorStr(hr, error, "infGetCurrentKeyValue", wszINFKEY_OID);
  953. hr = myVerifyObjId(pwszValue);
  954. _JumpIfErrorStr(hr, error, "myVerifyObjId", pwszValue);
  955. if (!ConvertWszToSz(&pcpi->pszPolicyIdentifier, pwszValue, -1))
  956. {
  957. hr = E_OUTOFMEMORY;
  958. _JumpError(hr, error, "ConvertWszToSz");
  959. }
  960. DBGPRINT((DBG_SS_CERTLIBI, "OID = %hs\n", pcpi->pszPolicyIdentifier));
  961. hr = infSetupFindFirstLine(
  962. hInf,
  963. pwszSection,
  964. NULL, // pwszKey
  965. FALSE, // fUniqueKey
  966. 0, // cValueMax
  967. NULL, // apwszKeys
  968. FALSE, // fUniqueValidKeys
  969. &InfContext);
  970. _JumpIfErrorStr(hr, error, "infSetupFindFirstLine", pwszSection);
  971. for (i = 0; ; )
  972. {
  973. hr = infBuildPolicyElement(&InfContext, NULL);
  974. if (S_FALSE != hr)
  975. {
  976. _JumpIfErrorStr(hr, error, "infBuildPolicyElement", pwszSection);
  977. i++;
  978. }
  979. if (!SetupFindNextLine(&InfContext, &InfContext))
  980. {
  981. hr = myHLastError();
  982. _PrintErrorStr2(hr, "SetupFindNextLine", pwszSection, hr);
  983. break;
  984. }
  985. }
  986. pcpi->cPolicyQualifier = i;
  987. pcpi->rgPolicyQualifier = (CERT_POLICY_QUALIFIER_INFO *) LocalAlloc(
  988. LMEM_FIXED | LMEM_ZEROINIT,
  989. pcpi->cPolicyQualifier *
  990. sizeof(pcpi->rgPolicyQualifier[0]));
  991. if (NULL == pcpi->rgPolicyQualifier)
  992. {
  993. hr = E_OUTOFMEMORY;
  994. _JumpError(hr, error, "LocalAlloc");
  995. }
  996. hr = infSetupFindFirstLine(
  997. hInf,
  998. pwszSection,
  999. NULL, // pwszKey
  1000. FALSE, // fUniqueKey
  1001. 0, // cValueMax
  1002. NULL, // apwszKeys
  1003. FALSE, // fUniqueValidKeys
  1004. &InfContext);
  1005. _JumpIfErrorStr(hr, error, "infSetupFindFirstLine", pwszSection);
  1006. for (i = 0; ; )
  1007. {
  1008. // handle one URL or text message
  1009. hr = infBuildPolicyElement(&InfContext, &pcpi->rgPolicyQualifier[i]);
  1010. if (S_FALSE != hr)
  1011. {
  1012. _JumpIfErrorStr(hr, error, "infBuildPolicyElement", pwszSection);
  1013. i++;
  1014. }
  1015. if (!SetupFindNextLine(&InfContext, &InfContext))
  1016. {
  1017. hr = myHLastError();
  1018. _PrintErrorStr2(hr, "SetupFindNextLine", pwszSection, hr);
  1019. break;
  1020. }
  1021. }
  1022. CSASSERT(i == pcpi->cPolicyQualifier);
  1023. hr = S_OK;
  1024. error:
  1025. if (S_OK != hr && S_FALSE != hr)
  1026. {
  1027. INFSETERROR(hr, pwszSection, NULL, L"");
  1028. }
  1029. CSILOG(hr, IDS_ILOG_CAPOLICY_BUILD, pwszSection, pwszValue, NULL);
  1030. if (NULL != pwszValue)
  1031. {
  1032. LocalFree(pwszValue);
  1033. }
  1034. return(hr);
  1035. }
  1036. VOID
  1037. infFreePolicy(
  1038. IN OUT CERT_POLICY_INFO *pcpi)
  1039. {
  1040. DWORD i;
  1041. CERT_POLICY_QUALIFIER_INFO *pcpqi;
  1042. if (NULL != pcpi->pszPolicyIdentifier)
  1043. {
  1044. LocalFree(pcpi->pszPolicyIdentifier);
  1045. }
  1046. if (NULL != pcpi->rgPolicyQualifier)
  1047. {
  1048. for (i = 0; i < pcpi->cPolicyQualifier; i++)
  1049. {
  1050. pcpqi = &pcpi->rgPolicyQualifier[i];
  1051. if (NULL != pcpqi->Qualifier.pbData)
  1052. {
  1053. LocalFree(pcpqi->Qualifier.pbData);
  1054. }
  1055. }
  1056. LocalFree(pcpi->rgPolicyQualifier);
  1057. }
  1058. }
  1059. HRESULT
  1060. myInfOpenFile(
  1061. OPTIONAL IN WCHAR const *pwszfnPolicy,
  1062. OUT HINF *phInf,
  1063. OUT DWORD *pErrorLine)
  1064. {
  1065. HRESULT hr;
  1066. WCHAR wszPath[MAX_PATH];
  1067. UINT ErrorLine;
  1068. DWORD Flags;
  1069. *phInf = INVALID_HANDLE_VALUE;
  1070. *pErrorLine = 0;
  1071. myInfClearError();
  1072. if (NULL == pwszfnPolicy)
  1073. {
  1074. DWORD cwc;
  1075. cwc = GetEnvironmentVariable(
  1076. L"SystemRoot",
  1077. wszPath,
  1078. ARRAYSIZE(wszPath) - ARRAYSIZE(wszBSCAPOLICYFILE));
  1079. if (0 == cwc ||
  1080. ARRAYSIZE(wszPath) - ARRAYSIZE(wszBSCAPOLICYFILE) <= cwc)
  1081. {
  1082. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  1083. _JumpError(hr, error, "GetEnvironmentVariable");
  1084. }
  1085. wcscat(wszPath, wszBSCAPOLICYFILE);
  1086. pwszfnPolicy = wszPath;
  1087. }
  1088. else
  1089. {
  1090. if (NULL == wcschr(pwszfnPolicy, L'\\'))
  1091. {
  1092. if (ARRAYSIZE(wszPath) <= 2 + wcslen(pwszfnPolicy))
  1093. {
  1094. hr = HRESULT_FROM_WIN32(ERROR_FILENAME_EXCED_RANGE);
  1095. _JumpErrorStr(hr, error, "filename too long", pwszfnPolicy);
  1096. }
  1097. wcscpy(wszPath, L".\\");
  1098. wcscat(wszPath, pwszfnPolicy);
  1099. pwszfnPolicy = wszPath;
  1100. }
  1101. }
  1102. hr = infCollectSectionNames(pwszfnPolicy);
  1103. _JumpIfErrorStr(hr, error, "infCollectSectionNames", pwszfnPolicy);
  1104. Flags = INF_STYLE_WIN4;
  1105. for (;;)
  1106. {
  1107. ErrorLine = 0;
  1108. *phInf = SetupOpenInfFile(
  1109. pwszfnPolicy,
  1110. NULL,
  1111. Flags,
  1112. &ErrorLine);
  1113. *pErrorLine = ErrorLine;
  1114. if (INVALID_HANDLE_VALUE != *phInf)
  1115. {
  1116. break;
  1117. }
  1118. hr = myHLastError();
  1119. if ((HRESULT) ERROR_WRONG_INF_STYLE == hr && INF_STYLE_WIN4 == Flags)
  1120. {
  1121. Flags = INF_STYLE_OLDNT;
  1122. continue;
  1123. }
  1124. CSILOG(
  1125. hr,
  1126. IDS_ILOG_CAPOLICY_OPEN_FAILED,
  1127. pwszfnPolicy,
  1128. NULL,
  1129. 0 == *pErrorLine? NULL : pErrorLine);
  1130. _JumpErrorStr(hr, error, "SetupOpenInfFile", pwszfnPolicy);
  1131. }
  1132. CSILOG(S_OK, IDS_ILOG_CAPOLICY_OPEN, pwszfnPolicy, NULL, NULL);
  1133. hr = S_OK;
  1134. error:
  1135. DBGPRINT((
  1136. DBG_SS_CERTLIBI,
  1137. "myInfOpenFile(%ws) hr=%x --> h=%x\n",
  1138. pwszfnPolicy,
  1139. hr,
  1140. *phInf));
  1141. return(hr);
  1142. }
  1143. VOID
  1144. myInfCloseFile(
  1145. IN HINF hInf)
  1146. {
  1147. if (NULL != hInf && INVALID_HANDLE_VALUE != hInf)
  1148. {
  1149. WCHAR *pwszInfError = myInfGetError();
  1150. SetupCloseInfFile(hInf);
  1151. CSILOG(S_OK, IDS_ILOG_CAPOLICY_CLOSE, pwszInfError, NULL, NULL);
  1152. if (NULL != pwszInfError)
  1153. {
  1154. LocalFree(pwszInfError);
  1155. }
  1156. }
  1157. myInfClearError();
  1158. infFreeSectionNames();
  1159. DBGPRINT((DBG_SS_CERTLIBI, "myInfCloseFile(%x)\n", hInf));
  1160. }
  1161. HRESULT
  1162. myInfParseBooleanValue(
  1163. IN WCHAR const *pwszValue,
  1164. OUT BOOL *pfValue)
  1165. {
  1166. HRESULT hr;
  1167. DWORD i;
  1168. static WCHAR const * const s_apwszTrue[] = { L"True", L"Yes", L"On", L"1" };
  1169. static WCHAR const * const s_apwszFalse[] = { L"False", L"No", L"Off", L"0" };
  1170. *pfValue = FALSE;
  1171. for (i = 0; i < ARRAYSIZE(s_apwszTrue); i++)
  1172. {
  1173. if (0 == mylstrcmpiL(pwszValue, s_apwszTrue[i]))
  1174. {
  1175. *pfValue = TRUE;
  1176. break;
  1177. }
  1178. }
  1179. if (i == ARRAYSIZE(s_apwszTrue))
  1180. {
  1181. for (i = 0; i < ARRAYSIZE(s_apwszFalse); i++)
  1182. {
  1183. if (0 == mylstrcmpiL(pwszValue, s_apwszFalse[i]))
  1184. {
  1185. break;
  1186. }
  1187. }
  1188. if (i == ARRAYSIZE(s_apwszFalse))
  1189. {
  1190. hr = E_INVALIDARG;
  1191. _JumpErrorStr(hr, error, "bad boolean value string", pwszValue);
  1192. }
  1193. }
  1194. hr = S_OK;
  1195. error:
  1196. if (S_OK != hr)
  1197. {
  1198. INFSETERROR(hr, NULL, NULL, pwszValue);
  1199. }
  1200. return(hr);
  1201. }
  1202. HRESULT
  1203. myInfGetBooleanValue(
  1204. IN HINF hInf,
  1205. IN WCHAR const *pwszSection,
  1206. IN WCHAR const *pwszKey,
  1207. IN BOOL fIgnoreMissingKey,
  1208. OUT BOOL *pfValue)
  1209. {
  1210. HRESULT hr;
  1211. INFCONTEXT InfContext;
  1212. WCHAR *pwszValue = NULL;
  1213. *pfValue = FALSE;
  1214. myInfClearError();
  1215. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  1216. hr = infSetupFindFirstLine(
  1217. hInf,
  1218. pwszSection,
  1219. pwszKey, // pwszKey
  1220. TRUE, // fUniqueKey
  1221. 1, // cValueMax
  1222. NULL, // apwszKeys
  1223. FALSE, // fUniqueValidKeys
  1224. &InfContext);
  1225. _PrintIfErrorStr3(
  1226. hr,
  1227. "infSetupFindFirstLine",
  1228. pwszSection,
  1229. ERROR_LINE_NOT_FOUND,
  1230. S_FALSE);
  1231. _JumpIfErrorStr3(
  1232. hr,
  1233. error,
  1234. "infSetupFindFirstLine",
  1235. pwszKey,
  1236. ERROR_LINE_NOT_FOUND,
  1237. S_FALSE);
  1238. hr = infGetCurrentKeyValue(
  1239. &InfContext,
  1240. pwszSection,
  1241. pwszKey,
  1242. 1,
  1243. TRUE, // fLastValue
  1244. &pwszValue);
  1245. _JumpIfErrorStr(hr, error, "infGetCurrentKeyValue", pwszKey);
  1246. DBGPRINT((
  1247. DBG_SS_CERTLIBI,
  1248. "myInfGetBooleanValue --> '%ws'\n",
  1249. pwszValue));
  1250. hr = myInfParseBooleanValue(pwszValue, pfValue);
  1251. _JumpIfError(hr, error, "myInfParseBooleanValue");
  1252. error:
  1253. if (S_OK != hr &&
  1254. ((HRESULT) ERROR_LINE_NOT_FOUND != hr || !fIgnoreMissingKey))
  1255. {
  1256. INFSETERROR(hr, pwszSection, pwszKey, pwszValue);
  1257. CSILOG(hr, IDS_ILOG_BAD_BOOLEAN, pwszSection, pwszKey, NULL);
  1258. }
  1259. DBGPRINT((
  1260. DBG_SS_CERTLIBI,
  1261. "myInfGetBooleanValue(%ws, %ws) hr=%x --> f=%d\n",
  1262. pwszSection,
  1263. pwszKey,
  1264. hr,
  1265. *pfValue));
  1266. if (NULL != pwszValue)
  1267. {
  1268. LocalFree(pwszValue);
  1269. }
  1270. return(hr);
  1271. }
  1272. HRESULT
  1273. infGetCriticalFlag(
  1274. IN HINF hInf,
  1275. IN WCHAR const *pwszSection,
  1276. IN BOOL fDefault,
  1277. OUT BOOL *pfCritical)
  1278. {
  1279. HRESULT hr;
  1280. hr = myInfGetBooleanValue(
  1281. hInf,
  1282. pwszSection,
  1283. wszINFKEY_CRITICAL,
  1284. TRUE,
  1285. pfCritical);
  1286. if (S_OK != hr)
  1287. {
  1288. *pfCritical = fDefault;
  1289. if ((HRESULT) ERROR_LINE_NOT_FOUND != hr && S_FALSE != hr)
  1290. {
  1291. _JumpErrorStr(hr, error, "myInfGetBooleanValue", pwszSection);
  1292. }
  1293. hr = S_OK;
  1294. }
  1295. error:
  1296. DBGPRINT((
  1297. DBG_SS_CERTLIBI,
  1298. "infGetCriticalFlag(%ws) hr=%x --> f=%d\n",
  1299. pwszSection,
  1300. hr,
  1301. *pfCritical));
  1302. return(hr);
  1303. }
  1304. //+------------------------------------------------------------------------
  1305. // infGetPolicyStatementExtensionSub -- build policy extension from INF file
  1306. //
  1307. // [pwszSection]
  1308. // Policies = LegalPolicy, LimitedUsePolicy, ExtraPolicy
  1309. //
  1310. // [LegalPolicy]
  1311. // OID = 1.3.6.1.4.1.311.21.43
  1312. // Notice = "Legal policy statement text."
  1313. //
  1314. // [LimitedUsePolicy]
  1315. // OID = 1.3.6.1.4.1.311.21.47
  1316. // URL = "http://http.site.com/some where/default.asp"
  1317. // URL = "ftp://ftp.site.com/some where else/default.asp"
  1318. // Notice = "Limited use policy statement text."
  1319. // URL = "ldap://ldap.site.com/some where else again/default.asp"
  1320. //
  1321. // [ExtraPolicy]
  1322. // OID = 1.3.6.1.4.1.311.21.53
  1323. // URL = http://extra.site.com/Extra Policy/default.asp
  1324. //
  1325. // Return S_OK if extension has been constructed from the INF file
  1326. // Return S_FALSE if empty section detected in INF file
  1327. // Return other error if no section detected in INF file
  1328. //-------------------------------------------------------------------------
  1329. HRESULT
  1330. infGetPolicyStatementExtensionSub(
  1331. IN HINF hInf,
  1332. IN WCHAR const *pwszSection,
  1333. IN char const *pszObjId,
  1334. OUT CERT_EXTENSION *pext)
  1335. {
  1336. HRESULT hr;
  1337. CERT_POLICIES_INFO PoliciesInfo;
  1338. INFCONTEXT InfContext;
  1339. DWORD i;
  1340. WCHAR *pwszValue = NULL;
  1341. static WCHAR const * const s_apwszKeys[] =
  1342. { wszINFKEY_POLICIES, wszINFKEY_CRITICAL, NULL };
  1343. ZeroMemory(&PoliciesInfo, sizeof(PoliciesInfo));
  1344. ZeroMemory(pext, sizeof(*pext));
  1345. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  1346. hr = infSetupFindFirstLine(
  1347. hInf,
  1348. pwszSection,
  1349. wszINFKEY_POLICIES,
  1350. TRUE, // fUniqueKey
  1351. 0, // cValueMax
  1352. s_apwszKeys,
  1353. TRUE, // fUniqueValidKeys
  1354. &InfContext);
  1355. if (S_OK != hr)
  1356. {
  1357. CSILOG(
  1358. hr,
  1359. IDS_ILOG_CAPOLICY_NOKEY,
  1360. pwszSection,
  1361. wszINFKEY_POLICIES,
  1362. NULL);
  1363. _JumpErrorStr3(
  1364. hr,
  1365. error,
  1366. "infSetupFindFirstLine",
  1367. pwszSection,
  1368. S_FALSE,
  1369. (HRESULT) ERROR_LINE_NOT_FOUND);
  1370. }
  1371. // First, count the policies.
  1372. PoliciesInfo.cPolicyInfo = SetupGetFieldCount(&InfContext);
  1373. if (0 == PoliciesInfo.cPolicyInfo)
  1374. {
  1375. hr = S_FALSE;
  1376. _JumpError(hr, error, "SetupGetFieldCount");
  1377. }
  1378. // Next, allocate memory.
  1379. PoliciesInfo.rgPolicyInfo = (CERT_POLICY_INFO *) LocalAlloc(
  1380. LMEM_FIXED | LMEM_ZEROINIT,
  1381. PoliciesInfo.cPolicyInfo * sizeof(PoliciesInfo.rgPolicyInfo[0]));
  1382. if (NULL == PoliciesInfo.rgPolicyInfo)
  1383. {
  1384. hr = E_OUTOFMEMORY;
  1385. _JumpError(hr, error, "LocalAlloc");
  1386. }
  1387. // Finally! Fill in the policies data.
  1388. for (i = 0; i < PoliciesInfo.cPolicyInfo; i++)
  1389. {
  1390. if (NULL != pwszValue)
  1391. {
  1392. LocalFree(pwszValue);
  1393. pwszValue = NULL;
  1394. }
  1395. hr = infGetCurrentKeyValue(
  1396. &InfContext,
  1397. pwszSection,
  1398. wszINFKEY_POLICIES,
  1399. i + 1,
  1400. FALSE, // fLastValue
  1401. &pwszValue);
  1402. _JumpIfErrorStr(hr, error, "infGetCurrentKeyValue", wszINFKEY_POLICIES);
  1403. DBGPRINT((DBG_SS_CERTLIBI, "%ws[%u] = %ws\n", wszINFKEY_POLICIES, i, pwszValue));
  1404. hr = infBuildPolicy(hInf, pwszValue, &PoliciesInfo.rgPolicyInfo[i]);
  1405. _JumpIfErrorStr(hr, error, "infBuildPolicy", pwszValue);
  1406. }
  1407. hr = infGetCriticalFlag(hInf, pwszSection, FALSE, &pext->fCritical);
  1408. _JumpIfError(hr, error, "infGetCriticalFlag");
  1409. if (!myEncodeObject(
  1410. X509_ASN_ENCODING,
  1411. X509_CERT_POLICIES,
  1412. &PoliciesInfo,
  1413. 0,
  1414. CERTLIB_USE_LOCALALLOC,
  1415. &pext->Value.pbData,
  1416. &pext->Value.cbData))
  1417. {
  1418. hr = myHLastError();
  1419. _JumpError(hr, error, "myEncodeObject");
  1420. }
  1421. error:
  1422. if (S_OK != hr && S_FALSE != hr)
  1423. {
  1424. INFSETERROR(hr, pwszSection, wszINFKEY_POLICIES, pwszValue);
  1425. }
  1426. CSILOG(hr, IDS_ILOG_CAPOLICY_EXTENSION, pwszValue, NULL, NULL);
  1427. pext->pszObjId = const_cast<char *>(pszObjId); // on error, too!
  1428. if (NULL != PoliciesInfo.rgPolicyInfo)
  1429. {
  1430. for (i = 0; i < PoliciesInfo.cPolicyInfo; i++)
  1431. {
  1432. infFreePolicy(&PoliciesInfo.rgPolicyInfo[i]);
  1433. }
  1434. LocalFree(PoliciesInfo.rgPolicyInfo);
  1435. }
  1436. if (NULL != pwszValue)
  1437. {
  1438. LocalFree(pwszValue);
  1439. }
  1440. return(hr);
  1441. }
  1442. //+------------------------------------------------------------------------
  1443. // myInfGetPolicyStatementExtension -- build policy extension from INF file
  1444. //
  1445. // [PolicyStatementExtension]
  1446. // Policies = LegalPolicy, LimitedUsePolicy, ExtraPolicy
  1447. // ...
  1448. //
  1449. // OR
  1450. //
  1451. // [CAPolicy]
  1452. // Policies = LegalPolicy, LimitedUsePolicy, ExtraPolicy
  1453. // ...
  1454. //
  1455. // Return S_OK if extension has been constructed from the INF file
  1456. // Return S_FALSE if empty section detected in INF file
  1457. // Return other error if no section detected in INF file
  1458. //-------------------------------------------------------------------------
  1459. FNMYINFGETEXTENSION myInfGetPolicyStatementExtension;
  1460. HRESULT
  1461. myInfGetPolicyStatementExtension(
  1462. IN HINF hInf,
  1463. OUT CERT_EXTENSION *pext)
  1464. {
  1465. HRESULT hr;
  1466. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  1467. {
  1468. hr = E_HANDLE;
  1469. _JumpError2(hr, error, "hInf", hr);
  1470. }
  1471. myInfClearError();
  1472. hr = infGetPolicyStatementExtensionSub(
  1473. hInf,
  1474. wszINFSECTION_POLICYSTATEMENT,
  1475. szOID_CERT_POLICIES,
  1476. pext);
  1477. if (S_OK != hr)
  1478. {
  1479. HRESULT hr2;
  1480. hr2 = infGetPolicyStatementExtensionSub(
  1481. hInf,
  1482. wszINFSECTION_CAPOLICY,
  1483. szOID_CERT_POLICIES,
  1484. pext);
  1485. if (S_OK == hr2 ||
  1486. (S_FALSE == hr2 && (HRESULT) ERROR_LINE_NOT_FOUND == hr))
  1487. {
  1488. hr = hr2;
  1489. }
  1490. }
  1491. _JumpIfErrorStr3(
  1492. hr,
  1493. error,
  1494. "infGetPolicyStatementExtensionSub",
  1495. wszINFSECTION_POLICYSTATEMENT,
  1496. ERROR_LINE_NOT_FOUND,
  1497. S_FALSE);
  1498. error:
  1499. DBGPRINT((
  1500. DBG_SS_CERTLIBI,
  1501. "myInfGetPolicyStatementExtension hr=%x --> f=%d, cb=%x\n",
  1502. hr,
  1503. pext->fCritical,
  1504. pext->Value.cbData));
  1505. return(hr);
  1506. }
  1507. //+------------------------------------------------------------------------
  1508. // myInfGetApplicationPolicyStatementExtension -- build application policy
  1509. // extension from INF file
  1510. //
  1511. // [ApplicationPolicyStatementExtension]
  1512. // Policies = LegalPolicy, LimitedUsePolicy, ExtraPolicy
  1513. // ...
  1514. //
  1515. // Return S_OK if extension has been constructed from the INF file
  1516. // Return S_FALSE if empty section detected in INF file
  1517. // Return other error if no section detected in INF file
  1518. //-------------------------------------------------------------------------
  1519. FNMYINFGETEXTENSION myInfGetApplicationPolicyStatementExtension;
  1520. HRESULT
  1521. myInfGetApplicationPolicyStatementExtension(
  1522. IN HINF hInf,
  1523. OUT CERT_EXTENSION *pext)
  1524. {
  1525. HRESULT hr;
  1526. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  1527. {
  1528. hr = E_HANDLE;
  1529. _JumpError2(hr, error, "hInf", hr);
  1530. }
  1531. myInfClearError();
  1532. hr = infGetPolicyStatementExtensionSub(
  1533. hInf,
  1534. wszINFSECTION_APPLICATIONPOLICYSTATEMENT,
  1535. szOID_APPLICATION_CERT_POLICIES,
  1536. pext);
  1537. _JumpIfErrorStr3(
  1538. hr,
  1539. error,
  1540. "infGetPolicyStatementExtensionSub",
  1541. wszINFSECTION_APPLICATIONPOLICYSTATEMENT,
  1542. S_FALSE,
  1543. (HRESULT) ERROR_LINE_NOT_FOUND);
  1544. error:
  1545. DBGPRINT((
  1546. DBG_SS_CERTLIBI,
  1547. "myInfGetApplicationPolicyStatementExtension hr=%x --> f=%d, cb=%x\n",
  1548. hr,
  1549. pext->fCritical,
  1550. pext->Value.cbData));
  1551. return(hr);
  1552. }
  1553. HRESULT
  1554. myInfGetCRLPublicationParams(
  1555. IN HINF hInf,
  1556. IN WCHAR const *pwszKeyCRLPeriodString,
  1557. IN WCHAR const *pwszKeyCRLPeriodCount,
  1558. OUT WCHAR **ppwszCRLPeriodString,
  1559. OUT DWORD *pdwCRLPeriodCount)
  1560. {
  1561. HRESULT hr;
  1562. WCHAR const *pwszKey;
  1563. // Retrieve units count and string. If either fails, both are discarded.
  1564. *ppwszCRLPeriodString = NULL;
  1565. pwszKey = pwszKeyCRLPeriodCount;
  1566. hr = myInfGetNumericKeyValue(
  1567. hInf,
  1568. TRUE, // fLog
  1569. wszINFSECTION_CERTSERVER,
  1570. pwszKey,
  1571. 1,
  1572. TRUE, // fLastValue
  1573. pdwCRLPeriodCount);
  1574. _JumpIfErrorStr2(
  1575. hr,
  1576. error,
  1577. "myInfGetNumericKeyValue",
  1578. pwszKeyCRLPeriodCount,
  1579. ERROR_LINE_NOT_FOUND);
  1580. pwszKey = pwszKeyCRLPeriodString;
  1581. hr = myInfGetKeyValue(
  1582. hInf,
  1583. TRUE, // fLog
  1584. wszINFSECTION_CERTSERVER,
  1585. pwszKey,
  1586. 1,
  1587. TRUE, // fLastValue
  1588. ppwszCRLPeriodString);
  1589. _JumpIfErrorStr2(
  1590. hr,
  1591. error,
  1592. "myInfGetKeyValue",
  1593. pwszKeyCRLPeriodString,
  1594. ERROR_LINE_NOT_FOUND);
  1595. error:
  1596. if (S_OK != hr)
  1597. {
  1598. INFSETERROR(hr, wszINFSECTION_CERTSERVER, pwszKey, NULL);
  1599. }
  1600. return(hr);
  1601. }
  1602. //+------------------------------------------------------------------------
  1603. // myInfGetKeyValue -- fetch a string value from INF file
  1604. //
  1605. // [pwszSection]
  1606. // pwszKey = string
  1607. //
  1608. // Returns: allocated string key value
  1609. //-------------------------------------------------------------------------
  1610. HRESULT
  1611. myInfGetKeyValue(
  1612. IN HINF hInf,
  1613. IN BOOL fLog,
  1614. IN WCHAR const *pwszSection,
  1615. IN WCHAR const *pwszKey,
  1616. IN DWORD Index,
  1617. IN BOOL fLastValue,
  1618. OUT WCHAR **ppwszValue)
  1619. {
  1620. HRESULT hr;
  1621. INFCONTEXT InfContext;
  1622. WCHAR *pwszValue = NULL;
  1623. *ppwszValue = NULL;
  1624. myInfClearError();
  1625. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  1626. hr = infSetupFindFirstLine(
  1627. hInf,
  1628. pwszSection,
  1629. pwszKey,
  1630. TRUE, // fUniqueKey
  1631. fLastValue? Index : 0, // cValueMax
  1632. NULL, // apwszKeys
  1633. FALSE, // fUniqueValidKeys
  1634. &InfContext);
  1635. if (S_OK != hr)
  1636. {
  1637. if (fLog)
  1638. {
  1639. CSILOG(hr, IDS_ILOG_CAPOLICY_NOKEY, pwszSection, pwszKey, NULL);
  1640. }
  1641. _JumpErrorStr2(
  1642. hr,
  1643. error,
  1644. "infSetupFindFirstLine",
  1645. pwszKey,
  1646. ERROR_LINE_NOT_FOUND);
  1647. }
  1648. hr = infGetCurrentKeyValue(
  1649. &InfContext,
  1650. pwszSection,
  1651. pwszKey,
  1652. Index,
  1653. fLastValue,
  1654. &pwszValue);
  1655. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  1656. *ppwszValue = pwszValue;
  1657. pwszValue = NULL;
  1658. hr = S_OK;
  1659. //wprintf(L"%ws = %ws\n", pwszKey, *ppwszValue);
  1660. error:
  1661. if (NULL != pwszValue)
  1662. {
  1663. LocalFree(pwszValue);
  1664. }
  1665. if (S_OK != hr && fLog)
  1666. {
  1667. INFSETERROR(hr, pwszSection, pwszKey, NULL);
  1668. }
  1669. return(hr);
  1670. }
  1671. //+------------------------------------------------------------------------
  1672. // myInfGetNumericKeyValue -- fetch a numeric value from INF file
  1673. //
  1674. // [pwszSection]
  1675. // pwszKey = 2048
  1676. //
  1677. // Returns: DWORD key value
  1678. //-------------------------------------------------------------------------
  1679. HRESULT
  1680. myInfGetNumericKeyValue(
  1681. IN HINF hInf,
  1682. IN BOOL fLog,
  1683. IN WCHAR const *pwszSection,
  1684. IN WCHAR const *pwszKey,
  1685. IN DWORD Index,
  1686. IN BOOL fLastValue,
  1687. OUT DWORD *pdwValue)
  1688. {
  1689. HRESULT hr;
  1690. INFCONTEXT InfContext;
  1691. WCHAR *pwszValue = NULL;
  1692. INT Value;
  1693. myInfClearError();
  1694. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  1695. hr = infSetupFindFirstLine(
  1696. hInf,
  1697. pwszSection,
  1698. pwszKey,
  1699. TRUE, // fUniqueKey
  1700. fLastValue? Index : 0, // cValueMax
  1701. NULL, // apwszKeys
  1702. FALSE, // fUniqueValidKeys
  1703. &InfContext);
  1704. if (S_OK != hr)
  1705. {
  1706. if (fLog)
  1707. {
  1708. CSILOG(hr, IDS_ILOG_CAPOLICY_NOKEY, pwszSection, pwszKey, NULL);
  1709. }
  1710. _PrintErrorStr2(
  1711. hr,
  1712. "infSetupFindFirstLine",
  1713. pwszKey,
  1714. ERROR_LINE_NOT_FOUND);
  1715. _JumpErrorStr2(
  1716. hr,
  1717. error,
  1718. "infSetupFindFirstLine",
  1719. pwszSection,
  1720. ERROR_LINE_NOT_FOUND);
  1721. }
  1722. if (fLastValue)
  1723. {
  1724. hr = infGetCurrentKeyValue(
  1725. &InfContext,
  1726. pwszSection,
  1727. pwszKey,
  1728. Index,
  1729. fLastValue,
  1730. &pwszValue);
  1731. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  1732. }
  1733. if (!SetupGetIntField(&InfContext, Index, &Value))
  1734. {
  1735. hr = myHLastError();
  1736. if (fLog)
  1737. {
  1738. CSILOG(hr, IDS_ILOG_BAD_NUMERICFIELD, pwszSection, pwszKey, NULL);
  1739. }
  1740. _JumpErrorStr(hr, error, "SetupGetIntField", pwszKey);
  1741. }
  1742. *pdwValue = Value;
  1743. DBGPRINT((DBG_SS_CERTLIBI, "%ws = %u\n", pwszKey, *pdwValue));
  1744. hr = S_OK;
  1745. error:
  1746. if (NULL != pwszValue)
  1747. {
  1748. LocalFree(pwszValue);
  1749. }
  1750. if (S_OK != hr && fLog)
  1751. {
  1752. INFSETERROR(hr, pwszSection, pwszKey, NULL);
  1753. }
  1754. return(hr);
  1755. }
  1756. //+------------------------------------------------------------------------
  1757. // myInfGetKeyLength -- fetch the renewal key length from CAPolicy.inf
  1758. //
  1759. // [certsrv_server]
  1760. // RenewalKeyLength = 2048
  1761. //
  1762. // Returns: DWORD key kength
  1763. //-------------------------------------------------------------------------
  1764. HRESULT
  1765. myInfGetKeyLength(
  1766. IN HINF hInf,
  1767. OUT DWORD *pdwKeyLength)
  1768. {
  1769. HRESULT hr;
  1770. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  1771. {
  1772. hr = E_HANDLE;
  1773. _JumpError2(hr, error, "hInf", hr);
  1774. }
  1775. myInfClearError();
  1776. hr = myInfGetNumericKeyValue(
  1777. hInf,
  1778. TRUE, // fLog
  1779. wszINFSECTION_CERTSERVER,
  1780. wszINFKEY_RENEWALKEYLENGTH,
  1781. 1,
  1782. TRUE, // fLastValue
  1783. pdwKeyLength);
  1784. _JumpIfErrorStr2(
  1785. hr,
  1786. error,
  1787. "myInfGetNumericKeyValue",
  1788. wszINFKEY_RENEWALKEYLENGTH,
  1789. ERROR_LINE_NOT_FOUND);
  1790. error:
  1791. DBGPRINT((
  1792. DBG_SS_CERTLIBI,
  1793. "myInfGetKeyLength hr=%x --> len=%x\n",
  1794. hr,
  1795. *pdwKeyLength));
  1796. return(hr);
  1797. }
  1798. //+------------------------------------------------------------------------
  1799. // infGetValidityPeriodSub -- fetch validity period & units from CAPolicy.inf
  1800. //
  1801. // [certsrv_server]
  1802. // xxxxValidityPeriod = Years (string)
  1803. // xxxxValidityPeriodUnits = 8 (count)
  1804. //
  1805. // Returns: validity period count and enum
  1806. //-------------------------------------------------------------------------
  1807. HRESULT
  1808. infGetValidityPeriodSub(
  1809. IN HINF hInf,
  1810. IN BOOL fLog,
  1811. IN WCHAR const *pwszInfKeyNameCount,
  1812. IN WCHAR const *pwszInfKeyNameString,
  1813. OPTIONAL IN WCHAR const *pwszValidityPeriodCount,
  1814. OPTIONAL IN WCHAR const *pwszValidityPeriodString,
  1815. OUT DWORD *pdwValidityPeriodCount,
  1816. OUT ENUM_PERIOD *penumValidityPeriod)
  1817. {
  1818. HRESULT hr;
  1819. WCHAR *pwszStringValue = NULL;
  1820. BOOL fValidCount = TRUE;
  1821. UINT idsLog = IDS_ILOG_BAD_VALIDITY_STRING;
  1822. *pdwValidityPeriodCount = 0;
  1823. *penumValidityPeriod = ENUM_PERIOD_INVALID;
  1824. hr = S_OK;
  1825. if (NULL == pwszValidityPeriodCount && NULL == pwszValidityPeriodString)
  1826. {
  1827. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  1828. {
  1829. hr = E_HANDLE;
  1830. _JumpError2(hr, error, "hInf", hr);
  1831. }
  1832. hr = myInfGetNumericKeyValue(
  1833. hInf,
  1834. fLog,
  1835. wszINFSECTION_CERTSERVER,
  1836. pwszInfKeyNameCount,
  1837. 1,
  1838. TRUE, // fLastValue
  1839. pdwValidityPeriodCount);
  1840. _JumpIfErrorStr2(
  1841. hr,
  1842. error,
  1843. "myInfGetNumericKeyValue",
  1844. pwszInfKeyNameCount,
  1845. ERROR_LINE_NOT_FOUND);
  1846. hr = myInfGetKeyValue(
  1847. hInf,
  1848. fLog,
  1849. wszINFSECTION_CERTSERVER,
  1850. pwszInfKeyNameString,
  1851. 1,
  1852. TRUE, // fLastValue
  1853. &pwszStringValue);
  1854. if (S_OK != hr && fLog)
  1855. {
  1856. INFSETERROR(hr, wszINFSECTION_CERTSERVER, pwszInfKeyNameString, NULL);
  1857. }
  1858. _JumpIfErrorStr(hr, error, "myInfGetKeyValue", pwszInfKeyNameString);
  1859. pwszValidityPeriodString = pwszStringValue;
  1860. }
  1861. else
  1862. {
  1863. if (NULL != pwszValidityPeriodCount)
  1864. {
  1865. *pdwValidityPeriodCount = myWtoI(
  1866. pwszValidityPeriodCount,
  1867. &fValidCount);
  1868. }
  1869. idsLog = IDS_ILOG_BAD_VALIDITY_STRING_UNATTEND;
  1870. }
  1871. DBGPRINT((
  1872. DBG_SS_CERTLIBI,
  1873. "%ws = %u -- %ws = %ws\n",
  1874. pwszInfKeyNameCount,
  1875. *pdwValidityPeriodCount,
  1876. pwszInfKeyNameString,
  1877. pwszValidityPeriodString));
  1878. if (NULL != pwszValidityPeriodString)
  1879. {
  1880. if (0 == LSTRCMPIS(pwszValidityPeriodString, wszPERIODYEARS))
  1881. {
  1882. *penumValidityPeriod = ENUM_PERIOD_YEARS;
  1883. }
  1884. else if (0 == LSTRCMPIS(pwszValidityPeriodString, wszPERIODMONTHS))
  1885. {
  1886. *penumValidityPeriod = ENUM_PERIOD_MONTHS;
  1887. }
  1888. else if (0 == LSTRCMPIS(pwszValidityPeriodString, wszPERIODWEEKS))
  1889. {
  1890. *penumValidityPeriod = ENUM_PERIOD_WEEKS;
  1891. }
  1892. else if (0 == LSTRCMPIS(pwszValidityPeriodString, wszPERIODDAYS))
  1893. {
  1894. *penumValidityPeriod = ENUM_PERIOD_DAYS;
  1895. }
  1896. else if (fLog)
  1897. {
  1898. INFSETERROR(
  1899. hr,
  1900. wszINFSECTION_CERTSERVER,
  1901. pwszInfKeyNameString,
  1902. pwszValidityPeriodString);
  1903. }
  1904. }
  1905. DBGPRINT((
  1906. DBG_SS_CERTLIBI,
  1907. "%ws = %u (%ws)\n",
  1908. pwszInfKeyNameString,
  1909. *penumValidityPeriod,
  1910. pwszValidityPeriodString));
  1911. if (!fValidCount ||
  1912. (ENUM_PERIOD_YEARS == *penumValidityPeriod &&
  1913. fValidCount && 9999 < *pdwValidityPeriodCount))
  1914. {
  1915. hr = E_INVALIDARG;
  1916. if (fLog)
  1917. {
  1918. WCHAR awcCount[cwcDWORDSPRINTF];
  1919. if (NULL == pwszValidityPeriodCount)
  1920. {
  1921. wsprintf(awcCount, L"%d", *pdwValidityPeriodCount);
  1922. }
  1923. INFSETERROR(
  1924. hr,
  1925. wszINFSECTION_CERTSERVER,
  1926. pwszInfKeyNameCount,
  1927. NULL != pwszValidityPeriodCount?
  1928. pwszValidityPeriodCount : awcCount);
  1929. CSILOG(
  1930. hr,
  1931. idsLog,
  1932. wszINFSECTION_CERTSERVER,
  1933. NULL == pwszValidityPeriodCount? pwszInfKeyNameCount : NULL,
  1934. pdwValidityPeriodCount);
  1935. }
  1936. _JumpIfErrorStr(
  1937. hr,
  1938. error,
  1939. "bad ValidityPeriod count value",
  1940. pwszValidityPeriodCount);
  1941. }
  1942. hr = S_OK;
  1943. error:
  1944. if (NULL != pwszStringValue)
  1945. {
  1946. LocalFree(pwszStringValue);
  1947. }
  1948. return(hr);
  1949. }
  1950. //+------------------------------------------------------------------------
  1951. // myInfGetValidityPeriod -- fetch renewal period & units from CAPolicy.inf
  1952. //
  1953. // [certsrv_server]
  1954. // xxxxValidityPeriod = Years (string)
  1955. // xxxxValidityPeriodUnits = 8 (count)
  1956. //
  1957. // Returns: validity period count and enum
  1958. //-------------------------------------------------------------------------
  1959. HRESULT
  1960. myInfGetValidityPeriod(
  1961. IN HINF hInf,
  1962. OPTIONAL IN WCHAR const *pwszValidityPeriodCount,
  1963. OPTIONAL IN WCHAR const *pwszValidityPeriodString,
  1964. OUT DWORD *pdwValidityPeriodCount,
  1965. OUT ENUM_PERIOD *penumValidityPeriod,
  1966. OPTIONAL OUT BOOL *pfSwap)
  1967. {
  1968. HRESULT hr;
  1969. if ((NULL == hInf || INVALID_HANDLE_VALUE == hInf) &&
  1970. NULL == pwszValidityPeriodCount &&
  1971. NULL == pwszValidityPeriodString)
  1972. {
  1973. hr = E_HANDLE;
  1974. _JumpError2(hr, error, "hInf", hr);
  1975. }
  1976. myInfClearError();
  1977. if (NULL != pfSwap)
  1978. {
  1979. *pfSwap = FALSE;
  1980. }
  1981. // Try correct order:
  1982. // [certsrv_server]
  1983. // xxxxValidityPeriod = Years (string)
  1984. // xxxxValidityPeriodUnits = 8 (count)
  1985. hr = infGetValidityPeriodSub(
  1986. hInf,
  1987. TRUE,
  1988. wszINFKEY_RENEWALVALIDITYPERIODCOUNT,
  1989. wszINFKEY_RENEWALVALIDITYPERIODSTRING,
  1990. pwszValidityPeriodCount,
  1991. pwszValidityPeriodString,
  1992. pdwValidityPeriodCount,
  1993. penumValidityPeriod);
  1994. _PrintIfError2(hr, "infGetValidityPeriodSub", ERROR_LINE_NOT_FOUND);
  1995. if (S_OK != hr)
  1996. {
  1997. // Try backwards:
  1998. // [certsrv_server]
  1999. // xxxxValidityPeriodUnits = Years (string)
  2000. // xxxxValidityPeriod = 8 (count)
  2001. hr = infGetValidityPeriodSub(
  2002. hInf,
  2003. FALSE,
  2004. wszINFKEY_RENEWALVALIDITYPERIODSTRING,
  2005. wszINFKEY_RENEWALVALIDITYPERIODCOUNT,
  2006. pwszValidityPeriodString,
  2007. pwszValidityPeriodCount,
  2008. pdwValidityPeriodCount,
  2009. penumValidityPeriod);
  2010. _JumpIfError2(
  2011. hr,
  2012. error,
  2013. "infGetValidityPeriodSub",
  2014. ERROR_LINE_NOT_FOUND);
  2015. if (NULL != pfSwap)
  2016. {
  2017. *pfSwap = TRUE;
  2018. }
  2019. }
  2020. error:
  2021. DBGPRINT((
  2022. DBG_SS_CERTLIBI,
  2023. "myInfGetValidityPeriod hr=%x --> c=%d, enum=%d\n",
  2024. hr,
  2025. *pdwValidityPeriodCount,
  2026. *penumValidityPeriod));
  2027. return(hr);
  2028. }
  2029. //+------------------------------------------------------------------------
  2030. // myInfGetKeyList -- fetch a list of key values from CAPolicy.inf
  2031. //
  2032. // [pwszSection]
  2033. // pwszKey = Value1
  2034. // pwszKey = Value2
  2035. //
  2036. // Returns: double null terminated list of values
  2037. //-------------------------------------------------------------------------
  2038. HRESULT
  2039. myInfGetKeyList(
  2040. IN HINF hInf,
  2041. IN WCHAR const *pwszSection,
  2042. OPTIONAL IN WCHAR const *pwszKey,
  2043. OPTIONAL WCHAR const * const *ppwszValidKeys,
  2044. OPTIONAL OUT BOOL *pfCritical,
  2045. OPTIONAL OUT WCHAR **ppwszz)
  2046. {
  2047. HRESULT hr;
  2048. INFCONTEXT InfContext;
  2049. DWORD iVal;
  2050. DWORD cwc;
  2051. WCHAR *pwsz;
  2052. WCHAR **apwszVal = NULL;
  2053. DWORD cVal;
  2054. if (NULL != pfCritical)
  2055. {
  2056. *pfCritical = FALSE;
  2057. }
  2058. if (NULL != ppwszz)
  2059. {
  2060. *ppwszz = NULL;
  2061. }
  2062. myInfClearError();
  2063. cVal = 0;
  2064. if (NULL == pwszKey)
  2065. {
  2066. if (NULL == ppwszValidKeys || NULL != pfCritical || NULL != ppwszz)
  2067. {
  2068. hr = E_INVALIDARG;
  2069. _JumpErrorStr(hr, error, "NULL/non-NULL parms", pwszSection);
  2070. }
  2071. }
  2072. else if (NULL == ppwszz)
  2073. {
  2074. hr = E_INVALIDARG;
  2075. _JumpErrorStr(hr, error, "ppwszz parms", pwszKey);
  2076. }
  2077. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  2078. {
  2079. hr = E_HANDLE;
  2080. _JumpError2(hr, error, "hInf", hr);
  2081. }
  2082. hr = infSetupFindFirstLine(
  2083. hInf,
  2084. pwszSection,
  2085. pwszKey,
  2086. FALSE, // fUniqueKey
  2087. NULL == pwszKey? 0 : 1, // cValueMax
  2088. ppwszValidKeys,
  2089. FALSE, // fUniqueValidKeys
  2090. &InfContext);
  2091. if (S_OK != hr)
  2092. {
  2093. CSILOG(hr, IDS_ILOG_CAPOLICY_NOKEY, pwszSection, pwszKey, NULL);
  2094. _JumpErrorStr3(
  2095. hr,
  2096. error,
  2097. "infSetupFindFirstLine",
  2098. pwszSection,
  2099. S_FALSE,
  2100. (HRESULT) ERROR_LINE_NOT_FOUND);
  2101. }
  2102. if (NULL != pwszKey)
  2103. {
  2104. for (;;)
  2105. {
  2106. cVal++;
  2107. hr = infFindNextKey(pwszKey, &InfContext);
  2108. if (S_FALSE == hr)
  2109. {
  2110. break;
  2111. }
  2112. _JumpIfErrorStr(hr, error, "infFindNextKey", pwszKey);
  2113. }
  2114. apwszVal = (WCHAR **) LocalAlloc(
  2115. LMEM_FIXED | LMEM_ZEROINIT,
  2116. cVal * sizeof(apwszVal[0]));
  2117. if (NULL == apwszVal)
  2118. {
  2119. hr = E_OUTOFMEMORY;
  2120. _JumpError(hr, error, "LocalAlloc");
  2121. }
  2122. hr = infSetupFindFirstLine(
  2123. hInf,
  2124. pwszSection,
  2125. pwszKey,
  2126. FALSE, // fUniqueKey
  2127. 1, // cValueMax
  2128. NULL, // apwszKeys
  2129. FALSE, // fUniqueValidKeys
  2130. &InfContext);
  2131. _JumpIfErrorStr(hr, error, "infSetupFindFirstLine", pwszSection);
  2132. cwc = 1;
  2133. iVal = 0;
  2134. for (;;)
  2135. {
  2136. hr = infGetCurrentKeyValue(
  2137. &InfContext,
  2138. pwszSection,
  2139. pwszKey,
  2140. 1,
  2141. TRUE, // fLastValue
  2142. &apwszVal[iVal]);
  2143. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  2144. DBGPRINT((DBG_SS_CERTLIBI, "%ws = %ws\n", pwszKey, apwszVal[iVal]));
  2145. cwc += wcslen(apwszVal[iVal]) + 1;
  2146. iVal++;
  2147. hr = infFindNextKey(pwszKey, &InfContext);
  2148. if (S_FALSE == hr)
  2149. {
  2150. break;
  2151. }
  2152. _JumpIfErrorStr(hr, error, "infFindNextKey", pwszKey);
  2153. }
  2154. CSASSERT(iVal == cVal);
  2155. *ppwszz = (WCHAR *) LocalAlloc(LMEM_FIXED, cwc * sizeof(WCHAR));
  2156. if (NULL == *ppwszz)
  2157. {
  2158. hr = E_OUTOFMEMORY;
  2159. _JumpError(hr, error, "LocalAlloc");
  2160. }
  2161. pwsz = *ppwszz;
  2162. for (iVal = 0; iVal < cVal; iVal++)
  2163. {
  2164. wcscpy(pwsz, apwszVal[iVal]);
  2165. pwsz += wcslen(pwsz) + 1;
  2166. }
  2167. *pwsz = L'\0';
  2168. CSASSERT(cwc == 1 + SAFE_SUBTRACT_POINTERS(pwsz, *ppwszz));
  2169. if (NULL != pfCritical)
  2170. {
  2171. hr = infGetCriticalFlag(hInf, pwszSection, FALSE, pfCritical);
  2172. _JumpIfError(hr, error, "infGetCriticalFlag");
  2173. }
  2174. }
  2175. hr = S_OK;
  2176. error:
  2177. if (S_OK != hr)
  2178. {
  2179. INFSETERROR(hr, pwszSection, pwszKey, NULL);
  2180. }
  2181. if (NULL != apwszVal)
  2182. {
  2183. for (iVal = 0; iVal < cVal; iVal++)
  2184. {
  2185. if (NULL != apwszVal[iVal])
  2186. {
  2187. LocalFree(apwszVal[iVal]);
  2188. }
  2189. }
  2190. LocalFree(apwszVal);
  2191. }
  2192. return(hr);
  2193. }
  2194. //+------------------------------------------------------------------------
  2195. // myInfGetCRLDistributionPoints -- fetch CDP URLs from CAPolicy.inf
  2196. //
  2197. // [CRLDistributionPoint]
  2198. // URL = http://CRLhttp.site.com/Public/MyCA.crl
  2199. // URL = ftp://CRLftp.site.com/Public/MyCA.crl
  2200. //
  2201. // Returns: double null terminated list of CDP URLs
  2202. //-------------------------------------------------------------------------
  2203. HRESULT
  2204. myInfGetCRLDistributionPoints(
  2205. IN HINF hInf,
  2206. OUT BOOL *pfCritical,
  2207. OUT WCHAR **ppwszz)
  2208. {
  2209. HRESULT hr;
  2210. static WCHAR const * const s_apwszKeys[] =
  2211. { wszINFKEY_URL, wszINFKEY_CRITICAL, NULL };
  2212. hr = myInfGetKeyList(
  2213. hInf,
  2214. wszINFSECTION_CDP,
  2215. wszINFKEY_URL,
  2216. s_apwszKeys,
  2217. pfCritical,
  2218. ppwszz);
  2219. _JumpIfErrorStr4(
  2220. hr,
  2221. error,
  2222. "myInfGetKeyList",
  2223. wszINFSECTION_CDP,
  2224. ERROR_LINE_NOT_FOUND,
  2225. S_FALSE,
  2226. E_HANDLE);
  2227. error:
  2228. DBGPRINT((
  2229. DBG_SS_CERTLIBI,
  2230. "myInfGetCRLDistributionPoints hr=%x --> f=%d\n",
  2231. hr,
  2232. *pfCritical));
  2233. return(hr);
  2234. }
  2235. //+------------------------------------------------------------------------
  2236. // myInfGetAuthorityInformationAccess -- fetch AIA URLs from CAPolicy.inf
  2237. //
  2238. // [AuthorityInformationAccess]
  2239. // URL = http://CRThttp.site.com/Public/MyCA.crt
  2240. // URL = ftp://CRTftp.site.com/Public/MyCA.crt
  2241. //
  2242. // Returns: double null terminated list of AIA URLs
  2243. //-------------------------------------------------------------------------
  2244. HRESULT
  2245. myInfGetAuthorityInformationAccess(
  2246. IN HINF hInf,
  2247. OUT BOOL *pfCritical,
  2248. OUT WCHAR **ppwszz)
  2249. {
  2250. HRESULT hr;
  2251. static WCHAR const * const s_apwszKeys[] =
  2252. { wszINFKEY_URL, wszINFKEY_CRITICAL, NULL };
  2253. hr = myInfGetKeyList(
  2254. hInf,
  2255. wszINFSECTION_AIA,
  2256. wszINFKEY_URL,
  2257. s_apwszKeys,
  2258. pfCritical,
  2259. ppwszz);
  2260. _JumpIfErrorStr4(
  2261. hr,
  2262. error,
  2263. "myInfGetKeyList",
  2264. wszINFSECTION_AIA,
  2265. ERROR_LINE_NOT_FOUND,
  2266. S_FALSE,
  2267. E_HANDLE);
  2268. error:
  2269. DBGPRINT((
  2270. DBG_SS_CERTLIBI,
  2271. "myInfGetAuthorityInformationAccess hr=%x --> f=%d\n",
  2272. hr,
  2273. *pfCritical));
  2274. return(hr);
  2275. }
  2276. //+------------------------------------------------------------------------
  2277. // myInfGetEnhancedKeyUsage -- fetch EKU OIDS from CAPolicy.inf
  2278. //
  2279. // [EnhancedKeyUsage]
  2280. // OID = 1.2.3.4.5
  2281. // OID = 1.2.3.4.6
  2282. //
  2283. // Returns: double null terminated list of EKU OIDs
  2284. //-------------------------------------------------------------------------
  2285. HRESULT
  2286. myInfGetEnhancedKeyUsage(
  2287. IN HINF hInf,
  2288. OUT BOOL *pfCritical,
  2289. OUT WCHAR **ppwszz)
  2290. {
  2291. HRESULT hr;
  2292. WCHAR *pwszz = NULL;
  2293. WCHAR const *pwsz;
  2294. static WCHAR const * const s_apwszKeys[] =
  2295. { wszINFKEY_OID, wszINFKEY_CRITICAL, NULL };
  2296. *ppwszz = NULL;
  2297. hr = myInfGetKeyList(
  2298. hInf,
  2299. wszINFSECTION_EKU,
  2300. wszINFKEY_OID,
  2301. s_apwszKeys,
  2302. pfCritical,
  2303. &pwszz);
  2304. _JumpIfErrorStr4(
  2305. hr,
  2306. error,
  2307. "myInfGetKeyList",
  2308. wszINFSECTION_EKU,
  2309. ERROR_LINE_NOT_FOUND,
  2310. S_FALSE,
  2311. E_HANDLE);
  2312. for (pwsz = pwszz; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  2313. {
  2314. hr = myVerifyObjId(pwsz);
  2315. if (S_OK != hr)
  2316. {
  2317. INFSETERROR(hr, wszINFSECTION_EKU, wszINFKEY_OID, pwsz);
  2318. _JumpErrorStr(hr, error, "myVerifyObjId", pwsz);
  2319. }
  2320. }
  2321. *ppwszz = pwszz;
  2322. pwszz = NULL;
  2323. error:
  2324. DBGPRINT((
  2325. DBG_SS_CERTLIBI,
  2326. "myInfGetEnhancedKeyUsage hr=%x --> f=%d\n",
  2327. hr,
  2328. *pfCritical));
  2329. if (NULL != pwszz)
  2330. {
  2331. LocalFree(pwszz);
  2332. }
  2333. return(hr);
  2334. }
  2335. //+--------------------------------------------------------------------------
  2336. // infGetBasicConstraints2CAExtension -- fetch basic constraints extension
  2337. // from INF file, setting the SubjectType flag to CA
  2338. //
  2339. // If the INF handle is bad, or if the INF section does not exist, construct
  2340. // a default extension only if fDefault is set, otherwise fail.
  2341. //
  2342. // [BasicConstraintsExtension]
  2343. // ; Subject Type is not supported -- always set to CA
  2344. // ; maximum subordinate CA path length
  2345. // PathLength = 3
  2346. //
  2347. // Return S_OK if extension has been constructed from INF file.
  2348. //
  2349. // Returns: encoded basic constraints extension
  2350. //+--------------------------------------------------------------------------
  2351. HRESULT
  2352. infGetBasicConstraints2CAExtension(
  2353. IN BOOL fDefault,
  2354. IN HINF hInf,
  2355. OUT CERT_EXTENSION *pext)
  2356. {
  2357. HRESULT hr;
  2358. CERT_BASIC_CONSTRAINTS2_INFO bc2i;
  2359. INFCONTEXT InfContext;
  2360. static WCHAR const * const s_apwszKeys[] =
  2361. { wszINFKEY_PATHLENGTH, wszINFKEY_CRITICAL, NULL };
  2362. ZeroMemory(pext, sizeof(*pext));
  2363. ZeroMemory(&bc2i, sizeof(bc2i));
  2364. myInfClearError();
  2365. pext->fCritical = TRUE; // default value for both INF and default cases
  2366. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  2367. {
  2368. if (!fDefault)
  2369. {
  2370. hr = E_HANDLE;
  2371. _JumpError2(hr, error, "hInf", hr);
  2372. }
  2373. }
  2374. else
  2375. {
  2376. hr = infSetupFindFirstLine(
  2377. hInf,
  2378. wszINFSECTION_BASICCONSTRAINTS,
  2379. NULL, // pwszKey
  2380. FALSE, // fUniqueKey
  2381. 0, // cValueMax
  2382. s_apwszKeys,
  2383. TRUE, // fUniqueValidKeys
  2384. &InfContext);
  2385. if (S_OK != hr)
  2386. {
  2387. if (!fDefault)
  2388. {
  2389. _JumpErrorStr3(
  2390. hr,
  2391. error,
  2392. "infSetupFindFirstLine",
  2393. wszINFSECTION_BASICCONSTRAINTS,
  2394. S_FALSE,
  2395. (HRESULT) ERROR_LINE_NOT_FOUND);
  2396. }
  2397. }
  2398. else
  2399. {
  2400. hr = infGetCriticalFlag(
  2401. hInf,
  2402. wszINFSECTION_BASICCONSTRAINTS,
  2403. pext->fCritical, // fDefault
  2404. &pext->fCritical);
  2405. _JumpIfError(hr, error, "infGetCriticalFlag");
  2406. bc2i.fPathLenConstraint = TRUE;
  2407. hr = myInfGetNumericKeyValue(
  2408. hInf,
  2409. TRUE, // fLog
  2410. wszINFSECTION_BASICCONSTRAINTS,
  2411. wszINFKEY_PATHLENGTH,
  2412. 1,
  2413. TRUE, // fLastValue
  2414. &bc2i.dwPathLenConstraint);
  2415. if (S_OK != hr)
  2416. {
  2417. _PrintErrorStr2(
  2418. hr,
  2419. "myInfGetNumericKeyValue",
  2420. wszINFKEY_PATHLENGTH,
  2421. ERROR_LINE_NOT_FOUND);
  2422. if ((HRESULT) ERROR_LINE_NOT_FOUND != hr)
  2423. {
  2424. goto error;
  2425. }
  2426. bc2i.dwPathLenConstraint = 0;
  2427. bc2i.fPathLenConstraint = FALSE;
  2428. }
  2429. }
  2430. }
  2431. bc2i.fCA = TRUE;
  2432. if (!myEncodeObject(
  2433. X509_ASN_ENCODING,
  2434. X509_BASIC_CONSTRAINTS2,
  2435. &bc2i,
  2436. 0,
  2437. CERTLIB_USE_LOCALALLOC,
  2438. &pext->Value.pbData,
  2439. &pext->Value.cbData))
  2440. {
  2441. hr = myHLastError();
  2442. _JumpError(hr, error, "myEncodeObject");
  2443. }
  2444. hr = S_OK;
  2445. error:
  2446. if (S_OK != hr)
  2447. {
  2448. INFSETERROR(hr, wszINFSECTION_BASICCONSTRAINTS, NULL, NULL);
  2449. }
  2450. pext->pszObjId = szOID_BASIC_CONSTRAINTS2; // on error, too!
  2451. DBGPRINT((
  2452. DBG_SS_CERTLIBI,
  2453. "myInfGetBasicConstraints2CAExtension hr=%x --> f=%d, cb=%x\n",
  2454. hr,
  2455. pext->fCritical,
  2456. pext->Value.cbData));
  2457. return(hr);
  2458. }
  2459. //+--------------------------------------------------------------------------
  2460. // myInfGetBasicConstraints2CAExtension -- fetch basic constraints extension
  2461. // from INF file, setting the SubjectType flag to CA
  2462. //
  2463. // [BasicConstraintsExtension]
  2464. // ; Subject Type is not supported -- always set to CA
  2465. // ; maximum subordinate CA path length
  2466. // PathLength = 3
  2467. //
  2468. // Return S_OK if extension has been constructed from INF file.
  2469. //
  2470. // Returns: encoded basic constraints extension
  2471. //+--------------------------------------------------------------------------
  2472. FNMYINFGETEXTENSION myInfGetBasicConstraints2CAExtension;
  2473. HRESULT
  2474. myInfGetBasicConstraints2CAExtension(
  2475. IN HINF hInf,
  2476. OUT CERT_EXTENSION *pext)
  2477. {
  2478. HRESULT hr;
  2479. hr = infGetBasicConstraints2CAExtension(FALSE, hInf, pext);
  2480. _JumpIfError3(
  2481. hr,
  2482. error,
  2483. "infGetBasicConstraints2CAExtension",
  2484. S_FALSE,
  2485. (HRESULT) ERROR_LINE_NOT_FOUND);
  2486. error:
  2487. return(hr);
  2488. }
  2489. FNMYINFGETEXTENSION myInfGetBasicConstraints2CAExtensionOrDefault;
  2490. HRESULT
  2491. myInfGetBasicConstraints2CAExtensionOrDefault(
  2492. IN HINF hInf,
  2493. OUT CERT_EXTENSION *pext)
  2494. {
  2495. HRESULT hr;
  2496. hr = infGetBasicConstraints2CAExtension(TRUE, hInf, pext);
  2497. _JumpIfError(hr, error, "infGetBasicConstraints2CAExtension");
  2498. error:
  2499. return(hr);
  2500. }
  2501. //+--------------------------------------------------------------------------
  2502. // myInfGetEnhancedKeyUsageExtension -- fetch EKU extension from INF file
  2503. //
  2504. // [EnhancedKeyUsageExtension]
  2505. // OID = 1.2.3.4.5
  2506. // OID = 1.2.3.4.6
  2507. //
  2508. // Return S_OK if extension has been constructed from INF file.
  2509. // Return S_FALSE if empty section detected in INF file
  2510. // Return other error if no section detected in INF file
  2511. //
  2512. // Returns: encoded enhanced key usage extension
  2513. //+--------------------------------------------------------------------------
  2514. FNMYINFGETEXTENSION myInfGetEnhancedKeyUsageExtension;
  2515. HRESULT
  2516. myInfGetEnhancedKeyUsageExtension(
  2517. IN HINF hInf,
  2518. OUT CERT_EXTENSION *pext)
  2519. {
  2520. HRESULT hr;
  2521. DWORD i;
  2522. DWORD cEKU = 0;
  2523. WCHAR *pwszzEKU = NULL;
  2524. WCHAR *pwszCurrentEKU;
  2525. CERT_ENHKEY_USAGE ceku;
  2526. ceku.rgpszUsageIdentifier = NULL;
  2527. ceku.cUsageIdentifier = 0;
  2528. ZeroMemory(pext, sizeof(*pext));
  2529. myInfClearError();
  2530. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  2531. {
  2532. hr = E_HANDLE;
  2533. _JumpError2(hr, error, "hInf", hr);
  2534. }
  2535. hr = myInfGetEnhancedKeyUsage(hInf, &pext->fCritical, &pwszzEKU);
  2536. _JumpIfError3(
  2537. hr,
  2538. error,
  2539. "myInfGetEnhancedKeyUsage",
  2540. S_FALSE,
  2541. (HRESULT) ERROR_LINE_NOT_FOUND);
  2542. pwszCurrentEKU = pwszzEKU;
  2543. if (NULL != pwszCurrentEKU)
  2544. {
  2545. while (L'\0' != *pwszCurrentEKU)
  2546. {
  2547. cEKU++;
  2548. pwszCurrentEKU += wcslen(pwszCurrentEKU) + 1;
  2549. }
  2550. }
  2551. if (0 == cEKU)
  2552. {
  2553. hr = S_FALSE;
  2554. goto error;
  2555. }
  2556. ceku.cUsageIdentifier = cEKU;
  2557. ceku.rgpszUsageIdentifier = (char **) LocalAlloc(
  2558. LMEM_FIXED | LMEM_ZEROINIT,
  2559. sizeof(ceku.rgpszUsageIdentifier[0]) * cEKU);
  2560. if (NULL == ceku.rgpszUsageIdentifier)
  2561. {
  2562. hr = E_OUTOFMEMORY;
  2563. _JumpIfError(hr, error, "LocalAlloc");
  2564. }
  2565. cEKU = 0;
  2566. pwszCurrentEKU = pwszzEKU;
  2567. while (L'\0' != *pwszCurrentEKU)
  2568. {
  2569. if (!ConvertWszToSz(&ceku.rgpszUsageIdentifier[cEKU], pwszCurrentEKU, -1))
  2570. {
  2571. hr = E_OUTOFMEMORY;
  2572. _JumpError(hr, error, "ConvertWszToSz");
  2573. }
  2574. cEKU++;
  2575. pwszCurrentEKU += wcslen(pwszCurrentEKU) + 1;
  2576. }
  2577. CSASSERT(ceku.cUsageIdentifier == cEKU);
  2578. if (!myEncodeObject(
  2579. X509_ASN_ENCODING,
  2580. X509_ENHANCED_KEY_USAGE,
  2581. &ceku,
  2582. 0,
  2583. CERTLIB_USE_LOCALALLOC,
  2584. &pext->Value.pbData,
  2585. &pext->Value.cbData))
  2586. {
  2587. hr = myHLastError();
  2588. _JumpIfError(hr, error, "myEncodeObject");
  2589. }
  2590. error:
  2591. if (S_OK != hr && E_HANDLE != hr)
  2592. {
  2593. INFSETERROR(hr, wszINFSECTION_EKU, NULL, NULL);
  2594. }
  2595. pext->pszObjId = szOID_ENHANCED_KEY_USAGE; // on error, too!
  2596. DBGPRINT((
  2597. DBG_SS_CERTLIBI,
  2598. "myInfGetEnhancedKeyUsageExtension hr=%x --> f=%d, cb=%x\n",
  2599. hr,
  2600. pext->fCritical,
  2601. pext->Value.cbData));
  2602. if (NULL != ceku.rgpszUsageIdentifier)
  2603. {
  2604. for (i = 0; i < ceku.cUsageIdentifier; i++)
  2605. {
  2606. if (NULL != ceku.rgpszUsageIdentifier[i])
  2607. {
  2608. LocalFree(ceku.rgpszUsageIdentifier[i]);
  2609. }
  2610. }
  2611. LocalFree(ceku.rgpszUsageIdentifier);
  2612. }
  2613. if (NULL != pwszzEKU)
  2614. {
  2615. LocalFree(pwszzEKU);
  2616. }
  2617. return(hr);
  2618. }
  2619. HRESULT
  2620. infAddAttribute(
  2621. IN CRYPT_ATTR_BLOB const *pAttribute,
  2622. IN OUT DWORD *pcAttribute,
  2623. IN OUT CRYPT_ATTR_BLOB **ppaAttribute)
  2624. {
  2625. HRESULT hr;
  2626. CRYPT_ATTR_BLOB *pAttribT;
  2627. if (NULL == *ppaAttribute)
  2628. {
  2629. CSASSERT(0 == *pcAttribute);
  2630. pAttribT = (CRYPT_ATTR_BLOB *) LocalAlloc(
  2631. LMEM_FIXED,
  2632. sizeof(**ppaAttribute));
  2633. }
  2634. else
  2635. {
  2636. CSASSERT(0 != *pcAttribute);
  2637. pAttribT = (CRYPT_ATTR_BLOB *) LocalReAlloc(
  2638. *ppaAttribute,
  2639. (*pcAttribute + 1) * sizeof(**ppaAttribute),
  2640. LMEM_MOVEABLE);
  2641. }
  2642. if (NULL == pAttribT)
  2643. {
  2644. hr = E_OUTOFMEMORY;
  2645. _JumpError(
  2646. hr,
  2647. error,
  2648. NULL == *ppaAttribute? "LocalAlloc" : "LocalReAlloc");
  2649. }
  2650. *ppaAttribute = pAttribT;
  2651. pAttribT[(*pcAttribute)++] = *pAttribute;
  2652. hr = S_OK;
  2653. error:
  2654. return(hr);
  2655. }
  2656. VOID
  2657. myInfFreeRequestAttributes(
  2658. IN DWORD cAttribute,
  2659. IN OUT CRYPT_ATTR_BLOB *paAttribute)
  2660. {
  2661. if (NULL != paAttribute)
  2662. {
  2663. DWORD i;
  2664. for (i = 0; i < cAttribute; i++)
  2665. {
  2666. if (NULL != paAttribute[i].pbData)
  2667. {
  2668. LocalFree(paAttribute[i].pbData);
  2669. }
  2670. }
  2671. LocalFree(paAttribute);
  2672. }
  2673. }
  2674. //+------------------------------------------------------------------------
  2675. // myInfGetRequestAttributes -- fetch request attributes from INF file
  2676. //
  2677. // [RequestAttributes]
  2678. // AttributeName1 = AttributeValue1
  2679. // AttributeName2 = AttributeValue2
  2680. // ...
  2681. // AttributeNameN = AttributeValueN
  2682. //
  2683. // Returns: array of encoded attribute blobs
  2684. //-------------------------------------------------------------------------
  2685. HRESULT
  2686. myInfGetRequestAttributes(
  2687. IN HINF hInf,
  2688. OUT DWORD *pcAttribute,
  2689. OUT CRYPT_ATTR_BLOB **ppaAttribute,
  2690. OUT WCHAR **ppwszTemplateName)
  2691. {
  2692. HRESULT hr;
  2693. INFCONTEXT InfContext;
  2694. WCHAR *pwszName = NULL;
  2695. WCHAR *pwszValue = NULL;
  2696. DWORD cAttribute = 0;
  2697. CRYPT_ATTR_BLOB Attribute;
  2698. WCHAR *pwszTemplateName = NULL;
  2699. *ppwszTemplateName = NULL;
  2700. *pcAttribute = 0;
  2701. *ppaAttribute = NULL;
  2702. Attribute.pbData = NULL;
  2703. myInfClearError();
  2704. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  2705. {
  2706. hr = E_HANDLE;
  2707. _JumpError2(hr, error, "hInf", hr);
  2708. }
  2709. hr = infSetupFindFirstLine(
  2710. hInf,
  2711. wszINFSECTION_REQUESTATTRIBUTES,
  2712. NULL, // pwszKey
  2713. FALSE, // fUniqueKey
  2714. 0, // cValueMax
  2715. NULL, // apwszKeys
  2716. FALSE, // fUniqueValidKeys
  2717. &InfContext);
  2718. _JumpIfErrorStr2(
  2719. hr,
  2720. error,
  2721. "infSetupFindFirstLine",
  2722. wszINFSECTION_REQUESTATTRIBUTES,
  2723. ERROR_LINE_NOT_FOUND);
  2724. for (;;)
  2725. {
  2726. CRYPT_ENROLLMENT_NAME_VALUE_PAIR NamePair;
  2727. if (NULL != pwszName)
  2728. {
  2729. LocalFree(pwszName);
  2730. pwszName = NULL;
  2731. }
  2732. if (NULL != pwszValue)
  2733. {
  2734. LocalFree(pwszValue);
  2735. pwszValue = NULL;
  2736. }
  2737. hr = infGetCurrentKeyValue(
  2738. &InfContext,
  2739. wszINFSECTION_REQUESTATTRIBUTES,
  2740. NULL, // pwszKey
  2741. 0,
  2742. FALSE, // fLastValue
  2743. &pwszName);
  2744. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  2745. hr = infGetCurrentKeyValue(
  2746. &InfContext,
  2747. wszINFSECTION_REQUESTATTRIBUTES,
  2748. pwszName,
  2749. 1,
  2750. TRUE, // fLastValue
  2751. &pwszValue);
  2752. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  2753. //wprintf(L"%ws = %ws\n", pwszName, pwszValue);
  2754. NamePair.pwszName = pwszName;
  2755. NamePair.pwszValue = pwszValue;
  2756. if (0 == LSTRCMPIS(pwszName, wszPROPCERTTEMPLATE))
  2757. {
  2758. if (NULL != pwszTemplateName)
  2759. {
  2760. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  2761. _JumpError(hr, error, "Duplicate cert template");
  2762. }
  2763. pwszTemplateName = pwszValue;
  2764. pwszValue = NULL;
  2765. }
  2766. if (!myEncodeObject(
  2767. X509_ASN_ENCODING,
  2768. // X509__ENROLLMENT_NAME_VALUE_PAIR
  2769. szOID_ENROLLMENT_NAME_VALUE_PAIR,
  2770. &NamePair,
  2771. 0,
  2772. CERTLIB_USE_LOCALALLOC,
  2773. &Attribute.pbData,
  2774. &Attribute.cbData))
  2775. {
  2776. hr = myHLastError();
  2777. _JumpError(hr, error, "myEncodeObject");
  2778. }
  2779. hr = infAddAttribute(&Attribute, &cAttribute, ppaAttribute);
  2780. _JumpIfError(hr, error, "infAddAttribute");
  2781. Attribute.pbData = NULL;
  2782. if (!SetupFindNextLine(&InfContext, &InfContext))
  2783. {
  2784. hr = myHLastError();
  2785. _PrintError2(hr, "SetupFindNextLine(end)", hr);
  2786. break;
  2787. }
  2788. }
  2789. *pcAttribute = cAttribute;
  2790. cAttribute = 0;
  2791. *ppwszTemplateName = pwszTemplateName;
  2792. pwszTemplateName = NULL;
  2793. hr = S_OK;
  2794. error:
  2795. if (S_OK != hr)
  2796. {
  2797. INFSETERROR(hr, wszINFSECTION_REQUESTATTRIBUTES, pwszName, pwszValue);
  2798. }
  2799. if (NULL != pwszName)
  2800. {
  2801. LocalFree(pwszName);
  2802. }
  2803. if (NULL != pwszValue)
  2804. {
  2805. LocalFree(pwszValue);
  2806. }
  2807. if (NULL != pwszTemplateName)
  2808. {
  2809. LocalFree(pwszTemplateName);
  2810. }
  2811. if (NULL != Attribute.pbData)
  2812. {
  2813. LocalFree(Attribute.pbData);
  2814. }
  2815. if (0 != cAttribute)
  2816. {
  2817. myInfFreeRequestAttributes(cAttribute, *ppaAttribute);
  2818. *ppaAttribute = NULL;
  2819. }
  2820. DBGPRINT((
  2821. DBG_SS_CERTLIBI,
  2822. "myInfGetRequestAttributes hr=%x --> c=%d\n",
  2823. hr,
  2824. *pcAttribute));
  2825. return(hr);
  2826. }
  2827. typedef struct _SUBTREEINFO
  2828. {
  2829. BOOL fEmptyDefault;
  2830. DWORD dwInfMinMaxIndexBase;
  2831. DWORD dwAltNameChoice;
  2832. WCHAR const *pwszKey;
  2833. } SUBTREEINFO;
  2834. SUBTREEINFO g_aSubTreeInfo[] = {
  2835. { TRUE, 2, CERT_ALT_NAME_OTHER_NAME, wszINFKEY_UPN },
  2836. { TRUE, 2, CERT_ALT_NAME_RFC822_NAME, wszINFKEY_EMAIL },
  2837. { TRUE, 2, CERT_ALT_NAME_DNS_NAME, wszINFKEY_DNS },
  2838. { TRUE, 2, CERT_ALT_NAME_DIRECTORY_NAME, wszINFKEY_DIRECTORYNAME },
  2839. { TRUE, 2, CERT_ALT_NAME_URL, wszINFKEY_URL },
  2840. { TRUE, 3, CERT_ALT_NAME_IP_ADDRESS, wszINFKEY_IPADDRESS },
  2841. { FALSE, 2, CERT_ALT_NAME_REGISTERED_ID, wszINFKEY_REGISTEREDID },
  2842. { FALSE, 3, CERT_ALT_NAME_OTHER_NAME, wszINFKEY_OTHERNAME },
  2843. };
  2844. #define CSUBTREEINFO ARRAYSIZE(g_aSubTreeInfo)
  2845. #define STII_OTHERNAMEUPN 0 // CERT_ALT_NAME_OTHER_NAME pOtherName
  2846. #define STII_RFC822NAME 1 // CERT_ALT_NAME_RFC822_NAME pwszRfc822Name
  2847. #define STII_DNSNAME 2 // CERT_ALT_NAME_DNS_NAME pwszDNSName
  2848. #define STII_DIRECTORYNAME 3 // CERT_ALT_NAME_DIRECTORY_NAME DirectoryName
  2849. #define STII_URL 4 // CERT_ALT_NAME_URL pwszURL
  2850. #define STII_IPADDRESS 5 // CERT_ALT_NAME_IP_ADDRESS IPAddress
  2851. #define STII_REGISTEREDID 6 // CERT_ALT_NAME_REGISTERED_ID pszRegisteredID
  2852. #define STII_OTHERNAMEOID 7 // CERT_ALT_NAME_OTHER_NAME pOtherName
  2853. VOID
  2854. infFreeGeneralSubTreeElement(
  2855. IN OUT CERT_GENERAL_SUBTREE *pSubTree)
  2856. {
  2857. CERT_ALT_NAME_ENTRY *pName = &pSubTree->Base;
  2858. VOID **ppv = NULL;
  2859. DBGPRINT((
  2860. DBG_SS_CERTLIBI,
  2861. "infFreeGeneralSubTreeElement: p=%x, choice=%x\n",
  2862. pSubTree,
  2863. pName->dwAltNameChoice));
  2864. switch (pName->dwAltNameChoice)
  2865. {
  2866. case CERT_ALT_NAME_OTHER_NAME:
  2867. ppv = (VOID **) &pName->pOtherName;
  2868. if (NULL != pName->pOtherName)
  2869. {
  2870. if (NULL != pName->pOtherName->Value.pbData)
  2871. {
  2872. DBGPRINT((
  2873. DBG_SS_CERTLIBI,
  2874. "infFreeGeneralSubTreeElement: p=%x, Free(other.pbData=%x)\n",
  2875. pSubTree,
  2876. pName->pOtherName->Value.pbData));
  2877. LocalFree(pName->pOtherName->Value.pbData);
  2878. }
  2879. if (NULL != pName->pOtherName->pszObjId)
  2880. {
  2881. DBGPRINT((
  2882. DBG_SS_CERTLIBI,
  2883. "infFreeGeneralSubTreeElement: p=%x, Free(other.pszObjId=%x)\n",
  2884. pSubTree,
  2885. pName->pOtherName->pszObjId));
  2886. LocalFree(pName->pOtherName->pszObjId);
  2887. }
  2888. }
  2889. break;
  2890. case CERT_ALT_NAME_RFC822_NAME:
  2891. ppv = (VOID **) &pName->pwszRfc822Name;
  2892. break;
  2893. case CERT_ALT_NAME_DNS_NAME:
  2894. ppv = (VOID **) &pName->pwszDNSName;
  2895. break;
  2896. case CERT_ALT_NAME_DIRECTORY_NAME:
  2897. ppv = (VOID **) &pName->DirectoryName.pbData;
  2898. break;
  2899. case CERT_ALT_NAME_URL:
  2900. ppv = (VOID **) &pName->pwszURL;
  2901. break;
  2902. case CERT_ALT_NAME_IP_ADDRESS:
  2903. ppv = (VOID **) &pName->IPAddress.pbData;
  2904. break;
  2905. case CERT_ALT_NAME_REGISTERED_ID:
  2906. ppv = (VOID **) &pName->pszRegisteredID;
  2907. break;
  2908. }
  2909. if (NULL != ppv && NULL != *ppv)
  2910. {
  2911. DBGPRINT((
  2912. DBG_SS_CERTLIBI,
  2913. "infFreeGeneralSubTreeElement: p=%x, Free(pv=%x)\n",
  2914. pSubTree,
  2915. *ppv));
  2916. LocalFree(*ppv);
  2917. }
  2918. }
  2919. VOID
  2920. infFreeGeneralSubTree(
  2921. IN DWORD cSubTree,
  2922. IN OUT CERT_GENERAL_SUBTREE *pSubTree)
  2923. {
  2924. if (NULL != pSubTree)
  2925. {
  2926. DWORD i;
  2927. DBGPRINT((
  2928. DBG_SS_CERTLIBI,
  2929. "infFreeGeneralSubTree: p=%x, c=%x\n",
  2930. pSubTree,
  2931. cSubTree));
  2932. for (i = 0; i < cSubTree; i++)
  2933. {
  2934. infFreeGeneralSubTreeElement(&pSubTree[i]);
  2935. }
  2936. LocalFree(pSubTree);
  2937. }
  2938. }
  2939. HRESULT
  2940. infParseIPAddressAndMask(
  2941. IN WCHAR const *pwszIPAddress,
  2942. IN WCHAR const *pwszIPAddressMask,
  2943. OUT BYTE **ppbData,
  2944. OUT DWORD *pcbData)
  2945. {
  2946. HRESULT hr;
  2947. BYTE ab[2 * CB_IPV6ADDRESS];
  2948. DWORD cb;
  2949. DWORD cbAddress;
  2950. DWORD cbMask=0;
  2951. WCHAR const *pwszValue = pwszIPAddress;
  2952. *ppbData = NULL;
  2953. *pcbData = 0;
  2954. // if pwszValue is an empty string, encode zero length blob.
  2955. cb = 0;
  2956. if (L'\0' != *pwszIPAddress && L'\0' != *pwszIPAddressMask)
  2957. {
  2958. cbAddress = sizeof(ab) / 2;
  2959. hr = myParseIPAddress(pwszIPAddress, ab, &cbAddress);
  2960. _JumpIfError(hr, error, "myParseIPAddress");
  2961. if (L'\0' != *pwszIPAddressMask)
  2962. {
  2963. cbMask = sizeof(ab) / 2;
  2964. pwszValue = pwszIPAddressMask;
  2965. hr = myParseIPAddress(pwszIPAddressMask, &ab[cbAddress], &cbMask);
  2966. _JumpIfError(hr, error, "infParseIPMask");
  2967. }
  2968. if (cbAddress != cbMask)
  2969. {
  2970. hr = E_INVALIDARG;
  2971. _JumpError(hr, error, "address and mask lengths differ");
  2972. }
  2973. cb = cbAddress + cbMask;
  2974. }
  2975. else if (L'\0' != *pwszIPAddress || L'\0' != *pwszIPAddressMask)
  2976. {
  2977. hr = E_INVALIDARG;
  2978. _JumpError(hr, error, "address or mask missing");
  2979. }
  2980. *ppbData = (BYTE *) LocalAlloc(LMEM_FIXED, cb);
  2981. if (NULL == *ppbData)
  2982. {
  2983. hr = E_OUTOFMEMORY;
  2984. _JumpError(hr, error, "LocalAlloc");
  2985. }
  2986. *pcbData = cb;
  2987. CopyMemory(*ppbData, ab, cb);
  2988. DBGDUMPHEX((
  2989. DBG_SS_CERTLIBI,
  2990. DH_NOADDRESS | DH_NOTABPREFIX | 8,
  2991. *ppbData,
  2992. *pcbData));
  2993. hr = S_OK;
  2994. error:
  2995. if (S_OK != hr)
  2996. {
  2997. INFSETERROR(hr, NULL, NULL, pwszValue);
  2998. }
  2999. return(hr);
  3000. }
  3001. HRESULT
  3002. infVerifySubtreeElement(
  3003. IN CERT_GENERAL_SUBTREE const *pSubTree)
  3004. {
  3005. HRESULT hr;
  3006. BYTE *pb = NULL;
  3007. DWORD cb;
  3008. CERT_NAME_CONSTRAINTS_INFO *pnci = NULL;
  3009. CERT_NAME_CONSTRAINTS_INFO nci;
  3010. ZeroMemory(&nci, sizeof(nci));
  3011. nci.cPermittedSubtree = 1;
  3012. nci.rgPermittedSubtree = const_cast<CERT_GENERAL_SUBTREE *>(pSubTree);
  3013. if (!myEncodeObject(
  3014. X509_ASN_ENCODING,
  3015. X509_NAME_CONSTRAINTS,
  3016. &nci,
  3017. 0,
  3018. CERTLIB_USE_LOCALALLOC,
  3019. &pb,
  3020. &cb))
  3021. {
  3022. hr = myHLastError();
  3023. _JumpError(hr, error, "myEncodeObject");
  3024. }
  3025. if (!myDecodeObject(
  3026. X509_ASN_ENCODING,
  3027. X509_NAME_CONSTRAINTS,
  3028. pb,
  3029. cb,
  3030. CERTLIB_USE_LOCALALLOC,
  3031. (VOID **) &pnci,
  3032. &cb))
  3033. {
  3034. hr = myHLastError();
  3035. _JumpError(hr, error, "myDecodeObject");
  3036. }
  3037. hr = S_OK;
  3038. error:
  3039. if (NULL != pb)
  3040. {
  3041. LocalFree(pb);
  3042. }
  3043. if (NULL != pnci)
  3044. {
  3045. LocalFree(pnci);
  3046. }
  3047. return(hr);
  3048. }
  3049. // [NameConstraintsPermitted]/[NameConstraintsExcluded]
  3050. // ; the numeric second and third arguments are optional
  3051. // ; when present, the second argument is the minimum depth
  3052. // ; when present, the third argument is the maximum depth
  3053. // ; The IETF recommends against specifying dwMinimum & dwMaximum
  3054. // DNS = [email protected]
  3055. // DNS = domain1.domain.com, 3, 6
  3056. HRESULT
  3057. infBuildSubTreeElement(
  3058. IN OUT INFCONTEXT *pInfContext,
  3059. OPTIONAL IN WCHAR const *pwszEmptyEntry, // NULL means read INF file
  3060. IN DWORD iSubTreeInfo,
  3061. OPTIONAL OUT CERT_GENERAL_SUBTREE *pSubTree)
  3062. {
  3063. HRESULT hr;
  3064. SUBTREEINFO const *pSubTreeInfo = &g_aSubTreeInfo[iSubTreeInfo];
  3065. CERT_GENERAL_SUBTREE SubTree;
  3066. WCHAR *pwszValueRead = NULL;
  3067. WCHAR *pwszValueRead2 = NULL;
  3068. WCHAR const *pwszValue = NULL;
  3069. WCHAR const *pwszValue2;
  3070. ZeroMemory(&SubTree, sizeof(SubTree));
  3071. if (NULL != pSubTree)
  3072. {
  3073. ZeroMemory(pSubTree, sizeof(*pSubTree));
  3074. }
  3075. // If pwszEmptyEntry is NULL, read the value from the INF file.
  3076. // Otherwise, encode the specified (empty string) value.
  3077. if (NULL == pwszEmptyEntry)
  3078. {
  3079. INT Value;
  3080. hr = infGetCurrentKeyValue(
  3081. pInfContext,
  3082. NULL, // pwszSection
  3083. NULL, // pwszKey
  3084. 1,
  3085. 2 == pSubTreeInfo->dwInfMinMaxIndexBase, // fLastValue
  3086. &pwszValueRead);
  3087. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  3088. pwszValue = pwszValueRead;
  3089. if (!SetupGetIntField(
  3090. pInfContext,
  3091. pSubTreeInfo->dwInfMinMaxIndexBase,
  3092. &Value))
  3093. {
  3094. hr = myHLastError();
  3095. _PrintError2(hr, "SetupGetIntField:2", hr);
  3096. Value = 0;
  3097. }
  3098. SubTree.dwMinimum = Value;
  3099. SubTree.fMaximum = TRUE;
  3100. if (!SetupGetIntField(
  3101. pInfContext,
  3102. pSubTreeInfo->dwInfMinMaxIndexBase + 1,
  3103. &Value))
  3104. {
  3105. hr = myHLastError();
  3106. _PrintError2(hr, "SetupGetIntField:3", hr);
  3107. Value = 0;
  3108. SubTree.fMaximum = FALSE;
  3109. }
  3110. SubTree.dwMaximum = Value;
  3111. }
  3112. else
  3113. {
  3114. pwszValue = pwszEmptyEntry;
  3115. }
  3116. SubTree.Base.dwAltNameChoice = pSubTreeInfo->dwAltNameChoice;
  3117. if (NULL != pSubTree)
  3118. {
  3119. WCHAR **ppwsz = NULL;
  3120. CSASSERT(CSUBTREEINFO > iSubTreeInfo);
  3121. switch (iSubTreeInfo)
  3122. {
  3123. case STII_OTHERNAMEUPN:
  3124. case STII_OTHERNAMEOID:
  3125. {
  3126. CERT_NAME_VALUE nameUpn;
  3127. SubTree.Base.pOtherName = (CERT_OTHER_NAME *) LocalAlloc(
  3128. LMEM_FIXED | LMEM_ZEROINIT,
  3129. sizeof(*SubTree.Base.pOtherName));
  3130. if (NULL == SubTree.Base.pOtherName)
  3131. {
  3132. hr = E_OUTOFMEMORY;
  3133. _JumpError(hr, error, "LocalAlloc");
  3134. }
  3135. if (STII_OTHERNAMEUPN == iSubTreeInfo)
  3136. {
  3137. hr = myDupStringA(
  3138. szOID_NT_PRINCIPAL_NAME,
  3139. &SubTree.Base.pOtherName->pszObjId);
  3140. _JumpIfError(hr, error, "myDupStringA");
  3141. nameUpn.dwValueType = CERT_RDN_UTF8_STRING;
  3142. nameUpn.Value.pbData = (BYTE *) pwszValue;
  3143. nameUpn.Value.cbData = 0;
  3144. if (!myEncodeObject(
  3145. X509_ASN_ENCODING,
  3146. X509_UNICODE_ANY_STRING,
  3147. &nameUpn,
  3148. 0,
  3149. CERTLIB_USE_LOCALALLOC,
  3150. &SubTree.Base.pOtherName->Value.pbData,
  3151. &SubTree.Base.pOtherName->Value.cbData))
  3152. {
  3153. hr = myHLastError();
  3154. _JumpError(hr, error, "myEncodeObject");
  3155. }
  3156. }
  3157. else
  3158. {
  3159. hr = myVerifyObjId(pwszValue);
  3160. _JumpIfErrorStr(hr, error, "myVerifyObjId", pwszValue);
  3161. if (!myConvertWszToSz(
  3162. &SubTree.Base.pOtherName->pszObjId,
  3163. pwszValue,
  3164. -1))
  3165. {
  3166. hr = E_OUTOFMEMORY;
  3167. _JumpError(hr, error, "ConvertWszToSz");
  3168. }
  3169. if (NULL == pwszEmptyEntry)
  3170. {
  3171. hr = infGetCurrentKeyValue(
  3172. pInfContext,
  3173. NULL, // pwszSection
  3174. NULL, // pwszKey
  3175. 2,
  3176. TRUE, // fLastValue
  3177. &pwszValueRead2);
  3178. _PrintIfError2(hr, "infGetCurrentKeyValue", hr);
  3179. pwszValue2 = pwszValueRead2;
  3180. }
  3181. else
  3182. {
  3183. pwszValue2 = pwszEmptyEntry;
  3184. }
  3185. if (NULL == pwszValue2 || L'\0' == *pwszValue2)
  3186. {
  3187. pwszValue2 = wszPROPOCTETTAG;
  3188. }
  3189. hr = myEncodeOtherNameBinary(
  3190. pwszValue2,
  3191. &SubTree.Base.pOtherName->Value.pbData,
  3192. &SubTree.Base.pOtherName->Value.cbData);
  3193. _JumpIfError(hr, error, "myEncodeOtherNameBinary");
  3194. }
  3195. DBGPRINT((
  3196. DBG_SS_CERTLIBI,
  3197. "infBuildSubTreeElement: p=%x, OtherName=%x,%x,%x\n",
  3198. pSubTree,
  3199. SubTree.Base.pOtherName,
  3200. SubTree.Base.pOtherName->pszObjId,
  3201. SubTree.Base.pOtherName->Value.pbData));
  3202. break;
  3203. }
  3204. case STII_RFC822NAME:
  3205. ppwsz = &SubTree.Base.pwszRfc822Name;
  3206. break;
  3207. case STII_DNSNAME:
  3208. ppwsz = &SubTree.Base.pwszDNSName;
  3209. break;
  3210. case STII_DIRECTORYNAME:
  3211. hr = myCertStrToName(
  3212. X509_ASN_ENCODING,
  3213. pwszValue, // pszX500
  3214. CERT_NAME_STR_REVERSE_FLAG,
  3215. NULL, // pvReserved
  3216. &SubTree.Base.DirectoryName.pbData,
  3217. &SubTree.Base.DirectoryName.cbData,
  3218. NULL); // ppszError
  3219. _JumpIfError(hr, error, "myCertStrToName");
  3220. DBGPRINT((
  3221. DBG_SS_CERTLIBI,
  3222. "infBuildSubTreeElement: p=%x, DirName=%x\n",
  3223. pSubTree,
  3224. SubTree.Base.DirectoryName.pbData));
  3225. break;
  3226. case STII_URL:
  3227. ppwsz = &SubTree.Base.pwszURL;
  3228. break;
  3229. case STII_IPADDRESS:
  3230. // convert INF string value to binary IP Address
  3231. if (NULL == pwszEmptyEntry)
  3232. {
  3233. hr = infGetCurrentKeyValue(
  3234. pInfContext,
  3235. NULL, // pwszSection
  3236. NULL, // pwszKey
  3237. 2,
  3238. TRUE, // fLastValue
  3239. &pwszValueRead2);
  3240. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  3241. pwszValue2 = pwszValueRead2;
  3242. }
  3243. else
  3244. {
  3245. pwszValue2 = pwszEmptyEntry;
  3246. }
  3247. hr = infParseIPAddressAndMask(
  3248. pwszValue,
  3249. pwszValue2,
  3250. &SubTree.Base.IPAddress.pbData,
  3251. &SubTree.Base.IPAddress.cbData);
  3252. _JumpIfError(hr, error, "infParseIPAddressAndMask");
  3253. DBGPRINT((
  3254. DBG_SS_CERTLIBI,
  3255. "infBuildSubTreeElement: p=%x, IPAddress=%x\n",
  3256. pSubTree,
  3257. SubTree.Base.IPAddress.pbData));
  3258. break;
  3259. case STII_REGISTEREDID:
  3260. if (!myConvertWszToSz(
  3261. &SubTree.Base.pszRegisteredID,
  3262. pwszValue,
  3263. -1))
  3264. {
  3265. hr = E_OUTOFMEMORY;
  3266. _JumpError(hr, error, "ConvertWszToSz");
  3267. }
  3268. DBGPRINT((
  3269. DBG_SS_CERTLIBI,
  3270. "infBuildSubTreeElement: p=%x, psz=%x\n",
  3271. pSubTree,
  3272. SubTree.Base.pszRegisteredID));
  3273. break;
  3274. }
  3275. if (NULL != ppwsz)
  3276. {
  3277. hr = myDupString(pwszValue, ppwsz);
  3278. _JumpIfError(hr, error, "myDupString");
  3279. DBGPRINT((
  3280. DBG_SS_CERTLIBI,
  3281. "infBuildSubTreeElement: p=%x, pwsz=%x\n",
  3282. pSubTree,
  3283. *ppwsz));
  3284. }
  3285. hr = infVerifySubtreeElement(&SubTree);
  3286. _JumpIfErrorStr(hr, error, "infVerifySubTreeElement", pSubTreeInfo->pwszKey);
  3287. *pSubTree = SubTree;
  3288. ZeroMemory(&SubTree, sizeof(SubTree));
  3289. }
  3290. hr = S_OK;
  3291. error:
  3292. if (S_OK != hr)
  3293. {
  3294. INFSETERROR(hr, NULL, NULL, pwszValue);
  3295. }
  3296. infFreeGeneralSubTreeElement(&SubTree);
  3297. if (NULL != pwszValueRead)
  3298. {
  3299. LocalFree(pwszValueRead);
  3300. }
  3301. if (NULL != pwszValueRead2)
  3302. {
  3303. LocalFree(pwszValueRead2);
  3304. }
  3305. return(hr);
  3306. }
  3307. HRESULT
  3308. infGetGeneralSubTreeByType(
  3309. IN HINF hInf,
  3310. IN WCHAR const *pwszSection,
  3311. OPTIONAL IN WCHAR const *pwszEmptyEntry,
  3312. IN DWORD iSubTreeInfo,
  3313. IN OUT DWORD *pcName,
  3314. OPTIONAL OUT CERT_GENERAL_SUBTREE *pSubTree)
  3315. {
  3316. HRESULT hr;
  3317. SUBTREEINFO const *pSubTreeInfo = &g_aSubTreeInfo[iSubTreeInfo];
  3318. INFCONTEXT InfContext;
  3319. DWORD iName;
  3320. DWORD cName = MAXDWORD;
  3321. BOOL fIgnore = FALSE;
  3322. if (NULL == pSubTree)
  3323. {
  3324. *pcName = 0;
  3325. }
  3326. else
  3327. {
  3328. cName = *pcName;
  3329. }
  3330. // If pwszEmptyEntry is NULL, read the value from the INF file.
  3331. // Otherwise, encode the specified (empty string) value.
  3332. if (!SetupFindFirstLine(
  3333. hInf,
  3334. pwszSection,
  3335. pSubTreeInfo->pwszKey,
  3336. &InfContext))
  3337. {
  3338. hr = myHLastError();
  3339. _PrintErrorStr2(
  3340. hr,
  3341. "SetupFindFirstLine",
  3342. pwszSection,
  3343. ERROR_LINE_NOT_FOUND);
  3344. // INF file entry does not exist. Create an empty name constraints
  3345. // entry only if asked to do so (if pwszEmptyEntry is non-NULL).
  3346. if (NULL == pwszEmptyEntry)
  3347. {
  3348. fIgnore = (HRESULT) ERROR_LINE_NOT_FOUND == hr;
  3349. goto error;
  3350. }
  3351. }
  3352. else
  3353. {
  3354. // INF file entry exists; don't create an empty name constraints entry.
  3355. pwszEmptyEntry = NULL;
  3356. }
  3357. for (iName = 0; ; )
  3358. {
  3359. CSASSERT(NULL == pSubTree || iName < cName);
  3360. hr = infBuildSubTreeElement(
  3361. &InfContext,
  3362. pwszEmptyEntry,
  3363. iSubTreeInfo,
  3364. pSubTree);
  3365. _JumpIfErrorStr(hr, error, "infBuildSubTreeElement", pSubTreeInfo->pwszKey);
  3366. DBGPRINT((
  3367. DBG_SS_CERTLIBI,
  3368. "infBuildSubTreeElement: &p[%u]=%x, type=%ws\n",
  3369. iName,
  3370. pSubTree,
  3371. pSubTreeInfo->pwszKey));
  3372. iName++;
  3373. if (NULL != pSubTree)
  3374. {
  3375. pSubTree++;
  3376. }
  3377. if (NULL == pwszEmptyEntry)
  3378. {
  3379. hr = infFindNextKey(pSubTreeInfo->pwszKey, &InfContext);
  3380. }
  3381. else
  3382. {
  3383. hr = S_FALSE;
  3384. }
  3385. if (S_FALSE == hr)
  3386. {
  3387. break;
  3388. }
  3389. _JumpIfErrorStr(hr, error, "infFindNextKey", pSubTreeInfo->pwszKey);
  3390. }
  3391. DBGPRINT((
  3392. DBG_SS_CERTLIBI,
  3393. "infGetGeneralSubTreeByType: i=%x, c=%x\n",
  3394. iName,
  3395. cName));
  3396. CSASSERT(NULL == pSubTree || iName <= cName);
  3397. *pcName = iName;
  3398. hr = S_OK;
  3399. error:
  3400. if (S_OK != hr && !fIgnore)
  3401. {
  3402. INFSETERROR(hr, pwszSection, pSubTreeInfo->pwszKey, NULL);
  3403. }
  3404. return(hr);
  3405. }
  3406. HRESULT
  3407. infGetGeneralSubTree(
  3408. IN HINF hInf,
  3409. IN WCHAR const *pwszSection,
  3410. IN WCHAR const *pwszKey, // key value is sub-section name
  3411. OPTIONAL IN WCHAR const *pwszEmptyEntry,
  3412. OUT DWORD *pcSubTree,
  3413. OUT CERT_GENERAL_SUBTREE **ppSubTree)
  3414. {
  3415. HRESULT hr;
  3416. WCHAR *pwszSubTreeSection = NULL;
  3417. DWORD cSubTree = 0;
  3418. CERT_GENERAL_SUBTREE *rgSubTree = NULL;
  3419. CERT_GENERAL_SUBTREE *pSubTree;
  3420. DWORD iSubTreeInfo;
  3421. DWORD count;
  3422. DWORD cRemain;
  3423. SUBTREEINFO const *pSubTreeInfo;
  3424. INFCONTEXT InfContext;
  3425. static WCHAR const * const s_apwszKeys[] =
  3426. {
  3427. wszINFKEY_UPN,
  3428. wszINFKEY_EMAIL,
  3429. wszINFKEY_DNS,
  3430. wszINFKEY_DIRECTORYNAME,
  3431. wszINFKEY_URL,
  3432. wszINFKEY_IPADDRESS,
  3433. wszINFKEY_REGISTEREDID,
  3434. wszINFKEY_OTHERNAME,
  3435. NULL
  3436. };
  3437. *pcSubTree = 0;
  3438. *ppSubTree = NULL;
  3439. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  3440. hr = myInfGetKeyValue(
  3441. hInf,
  3442. TRUE, // fLog
  3443. pwszSection,
  3444. pwszKey,
  3445. 1,
  3446. TRUE, // fLastValue
  3447. &pwszSubTreeSection);
  3448. _JumpIfErrorStr2(
  3449. hr,
  3450. error,
  3451. "myInfGetKeyValue",
  3452. pwszKey,
  3453. ERROR_LINE_NOT_FOUND);
  3454. hr = infSetupFindFirstLine(
  3455. hInf,
  3456. pwszSubTreeSection,
  3457. NULL, // pwszKey
  3458. FALSE, // fUniqueKey
  3459. 0, // cValueMax
  3460. s_apwszKeys,
  3461. FALSE, // fUniqueValidKeys
  3462. &InfContext);
  3463. // if S_FALSE is returned if the section is empty. In this case,
  3464. // allow execution to continue, to fill in the empty permitted names.
  3465. if (S_OK != hr &&
  3466. S_FALSE != hr)
  3467. {
  3468. if ((HRESULT) ERROR_LINE_NOT_FOUND == hr)
  3469. {
  3470. hr = SPAPI_E_LINE_NOT_FOUND; // don't ignore this error
  3471. }
  3472. INFSETERROR(hr, pwszSubTreeSection, L"", L"");
  3473. _JumpErrorStr(hr, error, "infSetupFindFirstLine", pwszSubTreeSection);
  3474. }
  3475. for (iSubTreeInfo = 0; iSubTreeInfo < CSUBTREEINFO; iSubTreeInfo++)
  3476. {
  3477. pSubTreeInfo = &g_aSubTreeInfo[iSubTreeInfo];
  3478. hr = infGetGeneralSubTreeByType(
  3479. hInf,
  3480. pwszSubTreeSection,
  3481. pSubTreeInfo->fEmptyDefault? pwszEmptyEntry : NULL,
  3482. iSubTreeInfo,
  3483. &count,
  3484. NULL);
  3485. DBGPRINT((
  3486. DBG_SS_CERTLIBI,
  3487. "infGetGeneralSubTreeByType(%ws, %ws, NULL) -> hr=%x, c=%x\n",
  3488. pwszSubTreeSection,
  3489. pSubTreeInfo->pwszKey,
  3490. hr,
  3491. count));
  3492. if (S_OK != hr)
  3493. {
  3494. _PrintErrorStr2(
  3495. hr,
  3496. "infGetGeneralSubTreeByType",
  3497. pSubTreeInfo->pwszKey,
  3498. ERROR_LINE_NOT_FOUND);
  3499. if ((HRESULT) ERROR_LINE_NOT_FOUND != hr)
  3500. {
  3501. _JumpErrorStr(
  3502. hr,
  3503. error,
  3504. "infGetGeneralSubTreeByType",
  3505. pSubTreeInfo->pwszKey);
  3506. }
  3507. count = 0;
  3508. }
  3509. cSubTree += count;
  3510. }
  3511. if (0 == cSubTree)
  3512. {
  3513. hr = SPAPI_E_LINE_NOT_FOUND; // don't ignore this error
  3514. INFSETERROR(hr, pwszSubTreeSection, L"", L"");
  3515. _JumpErrorStr(hr, error, "infSetupFindFirstLine", pwszSubTreeSection);
  3516. }
  3517. rgSubTree = (CERT_GENERAL_SUBTREE *) LocalAlloc(
  3518. LMEM_FIXED | LMEM_ZEROINIT,
  3519. cSubTree * sizeof(rgSubTree[0]));
  3520. if (NULL == rgSubTree)
  3521. {
  3522. hr = E_OUTOFMEMORY;
  3523. _JumpError(hr, error, "LocalAlloc");
  3524. }
  3525. DBGPRINT((
  3526. DBG_SS_CERTLIBI,
  3527. "infGetGeneralSubTree: rg=%x, total=%x\n",
  3528. rgSubTree,
  3529. cSubTree));
  3530. pSubTree = rgSubTree;
  3531. cRemain = cSubTree;
  3532. for (iSubTreeInfo = 0; iSubTreeInfo < CSUBTREEINFO; iSubTreeInfo++)
  3533. {
  3534. pSubTreeInfo = &g_aSubTreeInfo[iSubTreeInfo];
  3535. count = cRemain;
  3536. hr = infGetGeneralSubTreeByType(
  3537. hInf,
  3538. pwszSubTreeSection,
  3539. pSubTreeInfo->fEmptyDefault? pwszEmptyEntry : NULL,
  3540. iSubTreeInfo,
  3541. &count,
  3542. pSubTree);
  3543. DBGPRINT((
  3544. DBG_SS_CERTLIBI,
  3545. "infGetGeneralSubTreeByType(%ws, %ws, &p[%x]=%x) -> hr=%x, c=%x\n",
  3546. pwszSubTreeSection,
  3547. pSubTreeInfo->pwszKey,
  3548. SAFE_SUBTRACT_POINTERS(pSubTree, rgSubTree),
  3549. pSubTree,
  3550. hr,
  3551. count));
  3552. if (S_OK != hr)
  3553. {
  3554. _PrintErrorStr2(
  3555. hr,
  3556. "infGetGeneralSubTreeByType",
  3557. pSubTreeInfo->pwszKey,
  3558. ERROR_LINE_NOT_FOUND);
  3559. if ((HRESULT) ERROR_LINE_NOT_FOUND != hr)
  3560. {
  3561. _JumpErrorStr(
  3562. hr,
  3563. error,
  3564. "infGetGeneralSubTreeByType",
  3565. pSubTreeInfo->pwszKey);
  3566. }
  3567. if (0 < cRemain)
  3568. {
  3569. ZeroMemory(pSubTree, sizeof(*pSubTree));
  3570. }
  3571. count = 0;
  3572. }
  3573. cRemain -= count;
  3574. pSubTree += count;
  3575. }
  3576. CSASSERT(0 == cRemain);
  3577. *pcSubTree = cSubTree;
  3578. *ppSubTree = rgSubTree;
  3579. rgSubTree = NULL;
  3580. hr = S_OK;
  3581. error:
  3582. if (S_OK != hr)
  3583. {
  3584. INFSETERROR(hr, pwszSection, pwszKey, pwszSubTreeSection);
  3585. }
  3586. if (NULL != pwszSubTreeSection)
  3587. {
  3588. LocalFree(pwszSubTreeSection);
  3589. }
  3590. if (NULL != rgSubTree)
  3591. {
  3592. infFreeGeneralSubTree(cSubTree, rgSubTree);
  3593. }
  3594. return(hr);
  3595. }
  3596. //+------------------------------------------------------------------------
  3597. // myInfGetNameConstraintsExtension -- fetch name constraints extension from INF file
  3598. //
  3599. // [NameConstraintsExtension]
  3600. // Include = NameConstraintsPermitted
  3601. // Exclude = NameConstraintsExcluded
  3602. //
  3603. // [NameConstraintsPermitted]
  3604. // ; the numeric second and third arguments are optional
  3605. // ; when present, the second argument is the minimum depth
  3606. // ; when present, the third argument is the maximum depth
  3607. // ; The IETF recommends against specifying dwMinimum & dwMaximum
  3608. // DNS = [email protected]
  3609. // DNS = domain1.domain.com, 3, 6
  3610. //
  3611. // [NameConstraintsExcluded]
  3612. // DNS = domain.com
  3613. // DNS = domain2.com
  3614. //
  3615. // Returns: encoded name constraints extension
  3616. //-------------------------------------------------------------------------
  3617. FNMYINFGETEXTENSION myInfGetNameConstraintsExtension;
  3618. HRESULT
  3619. myInfGetNameConstraintsExtension(
  3620. IN HINF hInf,
  3621. OUT CERT_EXTENSION *pext)
  3622. {
  3623. HRESULT hr;
  3624. WCHAR const *pwszKey = NULL;
  3625. CERT_NAME_CONSTRAINTS_INFO NameConstraints;
  3626. INFCONTEXT InfContext;
  3627. static WCHAR const * const s_apwszKeys[] =
  3628. { wszINFKEY_EXCLUDE, wszINFKEY_INCLUDE, wszINFKEY_CRITICAL, NULL };
  3629. ZeroMemory(&NameConstraints, sizeof(NameConstraints));
  3630. ZeroMemory(pext, sizeof(*pext));
  3631. myInfClearError();
  3632. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  3633. {
  3634. hr = E_HANDLE;
  3635. _JumpError2(hr, error, "hInf", hr);
  3636. }
  3637. hr = infSetupFindFirstLine(
  3638. hInf,
  3639. wszINFSECTION_NAMECONSTRAINTS,
  3640. NULL, // pwszKey
  3641. FALSE, // fUniqueKey
  3642. 0, // cValueMax
  3643. s_apwszKeys,
  3644. TRUE, // fUniqueValidKeys
  3645. &InfContext);
  3646. _JumpIfErrorStr2(
  3647. hr,
  3648. error,
  3649. "infSetupFindFirstLine",
  3650. wszINFSECTION_NAMECONSTRAINTS,
  3651. ERROR_LINE_NOT_FOUND);
  3652. pwszKey = wszINFKEY_INCLUDE;
  3653. hr = infGetGeneralSubTree(
  3654. hInf,
  3655. wszINFSECTION_NAMECONSTRAINTS,
  3656. pwszKey,
  3657. L"",
  3658. &NameConstraints.cPermittedSubtree,
  3659. &NameConstraints.rgPermittedSubtree);
  3660. _PrintIfErrorStr2(
  3661. hr,
  3662. "infGetGeneralSubTree",
  3663. pwszKey,
  3664. ERROR_LINE_NOT_FOUND);
  3665. if (S_OK != hr && (HRESULT) ERROR_LINE_NOT_FOUND != hr)
  3666. {
  3667. goto error;
  3668. }
  3669. pwszKey = wszINFKEY_EXCLUDE;
  3670. hr = infGetGeneralSubTree(
  3671. hInf,
  3672. wszINFSECTION_NAMECONSTRAINTS,
  3673. pwszKey,
  3674. NULL,
  3675. &NameConstraints.cExcludedSubtree,
  3676. &NameConstraints.rgExcludedSubtree);
  3677. _PrintIfErrorStr2(
  3678. hr,
  3679. "infGetGeneralSubTree",
  3680. pwszKey,
  3681. ERROR_LINE_NOT_FOUND);
  3682. if (S_OK != hr && (HRESULT) ERROR_LINE_NOT_FOUND != hr)
  3683. {
  3684. goto error;
  3685. }
  3686. pwszKey = NULL;
  3687. if (NULL == NameConstraints.rgPermittedSubtree &&
  3688. NULL == NameConstraints.rgExcludedSubtree)
  3689. {
  3690. hr = S_FALSE;
  3691. _JumpError2(hr, error, "no data", hr);
  3692. }
  3693. hr = infGetCriticalFlag(
  3694. hInf,
  3695. wszINFSECTION_NAMECONSTRAINTS,
  3696. FALSE,
  3697. &pext->fCritical);
  3698. _JumpIfError(hr, error, "infGetCriticalFlag");
  3699. if (!myEncodeObject(
  3700. X509_ASN_ENCODING,
  3701. X509_NAME_CONSTRAINTS,
  3702. &NameConstraints,
  3703. 0,
  3704. CERTLIB_USE_LOCALALLOC,
  3705. &pext->Value.pbData,
  3706. &pext->Value.cbData))
  3707. {
  3708. hr = myHLastError();
  3709. _JumpError(hr, error, "myEncodeObject");
  3710. }
  3711. error:
  3712. if (S_OK != hr && S_FALSE != hr)
  3713. {
  3714. INFSETERROR(hr, wszINFSECTION_NAMECONSTRAINTS, pwszKey, NULL);
  3715. }
  3716. pext->pszObjId = szOID_NAME_CONSTRAINTS; // on error, too!
  3717. if (NULL != NameConstraints.rgPermittedSubtree)
  3718. {
  3719. infFreeGeneralSubTree(
  3720. NameConstraints.cPermittedSubtree,
  3721. NameConstraints.rgPermittedSubtree);
  3722. }
  3723. if (NULL != NameConstraints.rgExcludedSubtree)
  3724. {
  3725. infFreeGeneralSubTree(
  3726. NameConstraints.cExcludedSubtree,
  3727. NameConstraints.rgExcludedSubtree);
  3728. }
  3729. DBGPRINT((
  3730. DBG_SS_CERTLIBI,
  3731. "myInfGetNameConstraintsExtension hr=%x --> f=%d, cb=%x\n",
  3732. hr,
  3733. pext->fCritical,
  3734. pext->Value.cbData));
  3735. return(hr);
  3736. }
  3737. VOID
  3738. infFreePolicyMappings(
  3739. IN DWORD cPolicyMapping,
  3740. IN OUT CERT_POLICY_MAPPING *pPolicyMapping)
  3741. {
  3742. if (NULL != pPolicyMapping)
  3743. {
  3744. DWORD i;
  3745. for (i = 0; i < cPolicyMapping; i++)
  3746. {
  3747. CERT_POLICY_MAPPING *pMap = &pPolicyMapping[i];
  3748. if (NULL != pMap->pszIssuerDomainPolicy)
  3749. {
  3750. LocalFree(pMap->pszIssuerDomainPolicy);
  3751. }
  3752. if (NULL != pMap->pszSubjectDomainPolicy)
  3753. {
  3754. LocalFree(pMap->pszSubjectDomainPolicy);
  3755. }
  3756. }
  3757. LocalFree(pPolicyMapping);
  3758. }
  3759. }
  3760. HRESULT
  3761. infGetPolicyMappingsSub(
  3762. IN HINF hInf,
  3763. IN WCHAR const *pwszSection,
  3764. IN OUT DWORD *pcPolicyMapping,
  3765. OPTIONAL OUT CERT_POLICY_MAPPING *pPolicyMapping)
  3766. {
  3767. HRESULT hr;
  3768. INFCONTEXT InfContext;
  3769. WCHAR *pwszIssuer = NULL;
  3770. WCHAR *pwszSubject = NULL;
  3771. DWORD cPolicyMappingIn;
  3772. DWORD cPolicyMapping = 0;
  3773. cPolicyMappingIn = MAXDWORD;
  3774. if (NULL != pPolicyMapping)
  3775. {
  3776. cPolicyMappingIn = *pcPolicyMapping;
  3777. }
  3778. *pcPolicyMapping = 0;
  3779. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  3780. cPolicyMapping = 0;
  3781. hr = infSetupFindFirstLine(
  3782. hInf,
  3783. pwszSection,
  3784. NULL, // pwszKey
  3785. FALSE, // fUniqueKey
  3786. 0, // cValueMax
  3787. NULL, // apwszKeys
  3788. FALSE, // fUniqueValidKeys
  3789. &InfContext);
  3790. _JumpIfErrorStr3(
  3791. hr,
  3792. error,
  3793. "infSetupFindFirstLine",
  3794. pwszSection,
  3795. S_FALSE,
  3796. (HRESULT) ERROR_LINE_NOT_FOUND);
  3797. for (;;)
  3798. {
  3799. if (NULL != pwszIssuer)
  3800. {
  3801. LocalFree(pwszIssuer);
  3802. pwszIssuer = NULL;
  3803. }
  3804. if (NULL != pwszSubject)
  3805. {
  3806. LocalFree(pwszSubject);
  3807. pwszSubject = NULL;
  3808. }
  3809. hr = infGetCurrentKeyValue(
  3810. &InfContext,
  3811. pwszSection,
  3812. NULL, // pwszKey
  3813. 0,
  3814. FALSE, // fLastValue
  3815. &pwszIssuer);
  3816. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  3817. if (!iswdigit(pwszIssuer[0]))
  3818. {
  3819. if (0 != LSTRCMPIS(pwszIssuer, wszINFKEY_CRITICAL))
  3820. {
  3821. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  3822. _JumpErrorStr(hr, error, "bad key", pwszIssuer);
  3823. }
  3824. }
  3825. else
  3826. {
  3827. hr = myVerifyObjId(pwszIssuer);
  3828. _JumpIfErrorStr(hr, error, "myVerifyObjId", pwszIssuer);
  3829. hr = infGetCurrentKeyValue(
  3830. &InfContext,
  3831. pwszSection,
  3832. pwszIssuer,
  3833. 1,
  3834. TRUE, // fLastValue
  3835. &pwszSubject);
  3836. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  3837. hr = myVerifyObjId(pwszSubject);
  3838. _JumpIfErrorStr(hr, error, "myVerifyObjId", pwszSubject);
  3839. if (NULL != pPolicyMapping)
  3840. {
  3841. CERT_POLICY_MAPPING *pMap;
  3842. if (cPolicyMappingIn <= cPolicyMapping)
  3843. {
  3844. hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  3845. _JumpError(hr, error, "*pcPolicyMapping");
  3846. }
  3847. pMap = &pPolicyMapping[cPolicyMapping];
  3848. if (!ConvertWszToSz(&pMap->pszIssuerDomainPolicy, pwszIssuer, -1) ||
  3849. !ConvertWszToSz(&pMap->pszSubjectDomainPolicy, pwszSubject, -1))
  3850. {
  3851. hr = E_OUTOFMEMORY;
  3852. _JumpError(hr, error, "ConvertWszToSz");
  3853. }
  3854. }
  3855. DBGPRINT((
  3856. DBG_SS_CERTLIBI,
  3857. "Map[%u]: %ws = %ws\n",
  3858. cPolicyMapping,
  3859. pwszIssuer,
  3860. pwszSubject));
  3861. cPolicyMapping++;
  3862. }
  3863. if (!SetupFindNextLine(&InfContext, &InfContext))
  3864. {
  3865. hr = myHLastError();
  3866. _PrintError2(hr, "SetupFindNextLine", hr);
  3867. break;
  3868. }
  3869. }
  3870. *pcPolicyMapping = cPolicyMapping;
  3871. hr = S_OK;
  3872. error:
  3873. if (S_OK != hr)
  3874. {
  3875. INFSETERROR(hr, pwszSection, pwszIssuer, pwszSubject);
  3876. }
  3877. if (NULL != pwszIssuer)
  3878. {
  3879. LocalFree(pwszIssuer);
  3880. }
  3881. if (NULL != pwszSubject)
  3882. {
  3883. LocalFree(pwszSubject);
  3884. }
  3885. return(hr);
  3886. }
  3887. HRESULT
  3888. infGetPolicyMappings(
  3889. IN HINF hInf,
  3890. IN WCHAR const *pwszSection,
  3891. OUT DWORD *pcPolicyMapping,
  3892. OUT CERT_POLICY_MAPPING **ppPolicyMapping)
  3893. {
  3894. HRESULT hr;
  3895. DWORD cPolicyMapping = 0;
  3896. CERT_POLICY_MAPPING *pPolicyMapping = NULL;
  3897. *pcPolicyMapping = 0;
  3898. *ppPolicyMapping = NULL;
  3899. CSASSERT(NULL != hInf && INVALID_HANDLE_VALUE != hInf);
  3900. cPolicyMapping = 0;
  3901. hr = infGetPolicyMappingsSub(
  3902. hInf,
  3903. pwszSection,
  3904. &cPolicyMapping,
  3905. NULL);
  3906. _JumpIfError3(
  3907. hr,
  3908. error,
  3909. "infGetPolicyMappingsSub",
  3910. S_FALSE,
  3911. (HRESULT) ERROR_LINE_NOT_FOUND);
  3912. *pcPolicyMapping = cPolicyMapping;
  3913. pPolicyMapping = (CERT_POLICY_MAPPING *) LocalAlloc(
  3914. LMEM_FIXED | LMEM_ZEROINIT,
  3915. cPolicyMapping * sizeof(*pPolicyMapping));
  3916. if (NULL == pPolicyMapping)
  3917. {
  3918. hr = E_OUTOFMEMORY;
  3919. _JumpError(hr, error, "LocalAlloc");
  3920. }
  3921. hr = infGetPolicyMappingsSub(
  3922. hInf,
  3923. pwszSection,
  3924. &cPolicyMapping,
  3925. pPolicyMapping);
  3926. _JumpIfError(hr, error, "infGetPolicyMappingsSub");
  3927. CSASSERT(*pcPolicyMapping == cPolicyMapping);
  3928. *ppPolicyMapping = pPolicyMapping;
  3929. pPolicyMapping = NULL;
  3930. hr = S_OK;
  3931. error:
  3932. if (NULL != pPolicyMapping)
  3933. {
  3934. infFreePolicyMappings(*pcPolicyMapping, pPolicyMapping);
  3935. }
  3936. return(hr);
  3937. }
  3938. //+------------------------------------------------------------------------
  3939. // infGetPolicyMappingSub -- fetch policy mapping extension from INF file
  3940. //
  3941. // [pwszSection]
  3942. // ; list of user defined policy mappings
  3943. // ; The first OID is for the Issuer Domain Policy, the second is for the
  3944. // ; Subject Domain Policy. Each entry maps one Issuer Domain policy OID
  3945. // ; to a Subject Domain policy OID
  3946. //
  3947. // 1.3.6.1.4.1.311.21.53 = 1.2.3.4.87
  3948. // 1.3.6.1.4.1.311.21.53 = 1.2.3.4.89
  3949. //
  3950. // Returns: encoded policy mapping extension
  3951. //-------------------------------------------------------------------------
  3952. HRESULT
  3953. infGetPolicyMappingExtensionSub(
  3954. IN HINF hInf,
  3955. IN WCHAR const *pwszSection,
  3956. IN char const *pszObjId,
  3957. OUT CERT_EXTENSION *pext)
  3958. {
  3959. HRESULT hr;
  3960. CERT_POLICY_MAPPINGS_INFO PolicyMappings;
  3961. ZeroMemory(&PolicyMappings, sizeof(PolicyMappings));
  3962. ZeroMemory(pext, sizeof(*pext));
  3963. myInfClearError();
  3964. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  3965. {
  3966. hr = E_HANDLE;
  3967. _JumpError2(hr, error, "hInf", hr);
  3968. }
  3969. hr = infGetPolicyMappings(
  3970. hInf,
  3971. pwszSection,
  3972. &PolicyMappings.cPolicyMapping,
  3973. &PolicyMappings.rgPolicyMapping);
  3974. _JumpIfErrorStr3(
  3975. hr,
  3976. error,
  3977. "infGetPolicyMappings",
  3978. pwszSection,
  3979. S_FALSE,
  3980. (HRESULT) ERROR_LINE_NOT_FOUND);
  3981. hr = infGetCriticalFlag(
  3982. hInf,
  3983. pwszSection,
  3984. FALSE,
  3985. &pext->fCritical);
  3986. _JumpIfError(hr, error, "infGetCriticalFlag");
  3987. if (!myEncodeObject(
  3988. X509_ASN_ENCODING,
  3989. X509_POLICY_MAPPINGS,
  3990. &PolicyMappings,
  3991. 0,
  3992. CERTLIB_USE_LOCALALLOC,
  3993. &pext->Value.pbData,
  3994. &pext->Value.cbData))
  3995. {
  3996. hr = myHLastError();
  3997. _JumpError(hr, error, "myEncodeObject");
  3998. }
  3999. error:
  4000. if (S_OK != hr && S_FALSE != hr)
  4001. {
  4002. INFSETERROR(hr, pwszSection, NULL, NULL);
  4003. }
  4004. pext->pszObjId = const_cast<char *>(pszObjId); // on error, too!
  4005. if (NULL != PolicyMappings.rgPolicyMapping)
  4006. {
  4007. infFreePolicyMappings(
  4008. PolicyMappings.cPolicyMapping,
  4009. PolicyMappings.rgPolicyMapping);
  4010. }
  4011. return(hr);
  4012. }
  4013. //+------------------------------------------------------------------------
  4014. // myInfGetPolicyMapping -- fetch policy mapping extension from INF file
  4015. //
  4016. // [PolicyMappingExtension]
  4017. // ; list of user defined policy mappings
  4018. // ; The first OID is for the Issuer Domain Policy, the second is for the
  4019. // ; Subject Domain Policy. Each entry maps one Issuer Domain policy OID
  4020. // ; to a Subject Domain policy OID
  4021. //
  4022. // 1.3.6.1.4.1.311.21.53 = 1.2.3.4.87
  4023. // 1.3.6.1.4.1.311.21.53 = 1.2.3.4.89
  4024. //
  4025. // Returns: encoded policy mapping extension
  4026. //-------------------------------------------------------------------------
  4027. FNMYINFGETEXTENSION myInfGetPolicyMappingExtension;
  4028. HRESULT
  4029. myInfGetPolicyMappingExtension(
  4030. IN HINF hInf,
  4031. OUT CERT_EXTENSION *pext)
  4032. {
  4033. HRESULT hr;
  4034. hr = infGetPolicyMappingExtensionSub(
  4035. hInf,
  4036. wszINFSECTION_POLICYMAPPINGS,
  4037. szOID_POLICY_MAPPINGS,
  4038. pext);
  4039. _JumpIfErrorStr3(
  4040. hr,
  4041. error,
  4042. "infGetPolicyMappingExtensionSub",
  4043. wszINFSECTION_POLICYMAPPINGS,
  4044. S_FALSE,
  4045. (HRESULT) ERROR_LINE_NOT_FOUND);
  4046. error:
  4047. DBGPRINT((
  4048. DBG_SS_CERTLIBI,
  4049. "myInfGetPolicyMappingExtension hr=%x --> f=%d, cb=%x\n",
  4050. hr,
  4051. pext->fCritical,
  4052. pext->Value.cbData));
  4053. return(hr);
  4054. }
  4055. //+------------------------------------------------------------------------
  4056. // myInfGetApplicationPolicyMapping -- fetch application policy mapping
  4057. // extension from INF file
  4058. //
  4059. // [ApplicationPolicyMappingExtension]
  4060. // ; list of user defined policy mappings
  4061. // ; The first OID is for the Issuer Domain Policy, the second is for the
  4062. // ; Subject Domain Policy. Each entry maps one Issuer Domain policy OID
  4063. // ; to a Subject Domain policy OID
  4064. //
  4065. // 1.3.6.1.4.1.311.21.53 = 1.2.3.4.87
  4066. // 1.3.6.1.4.1.311.21.53 = 1.2.3.4.89
  4067. //
  4068. // Returns: encoded policy mapping extension
  4069. //-------------------------------------------------------------------------
  4070. FNMYINFGETEXTENSION myInfGetApplicationPolicyMappingExtension;
  4071. HRESULT
  4072. myInfGetApplicationPolicyMappingExtension(
  4073. IN HINF hInf,
  4074. OUT CERT_EXTENSION *pext)
  4075. {
  4076. HRESULT hr;
  4077. hr = infGetPolicyMappingExtensionSub(
  4078. hInf,
  4079. wszINFSECTION_APPLICATIONPOLICYMAPPINGS,
  4080. szOID_APPLICATION_POLICY_MAPPINGS,
  4081. pext);
  4082. _JumpIfErrorStr3(
  4083. hr,
  4084. error,
  4085. "infGetPolicyMappingExtensionSub",
  4086. wszINFSECTION_APPLICATIONPOLICYMAPPINGS,
  4087. S_FALSE,
  4088. (HRESULT) ERROR_LINE_NOT_FOUND);
  4089. error:
  4090. DBGPRINT((
  4091. DBG_SS_CERTLIBI,
  4092. "myInfGetApplicationPolicyMappingExtension hr=%x --> f=%d, cb=%x\n",
  4093. hr,
  4094. pext->fCritical,
  4095. pext->Value.cbData));
  4096. return(hr);
  4097. }
  4098. //+------------------------------------------------------------------------
  4099. // infGetPolicyConstraintsExtensionSub -- get policy constraints ext from INF
  4100. //
  4101. // [pwszSection]
  4102. // ; consists of two optional DWORDs
  4103. // ; They refer to the depth of the CA hierarchy that requires and inhibits
  4104. // ; Policy Mapping
  4105. // RequireExplicitPolicy = 3
  4106. // InhibitPolicyMapping = 5
  4107. //
  4108. // Returns: encoded policy constraints extension
  4109. //-------------------------------------------------------------------------
  4110. HRESULT
  4111. infGetPolicyConstraintsExtensionSub(
  4112. IN HINF hInf,
  4113. IN WCHAR const *pwszSection,
  4114. IN char const *pszObjId,
  4115. OUT CERT_EXTENSION *pext)
  4116. {
  4117. HRESULT hr;
  4118. CERT_POLICY_CONSTRAINTS_INFO PolicyConstraints;
  4119. WCHAR const *pwszKey = NULL;
  4120. INFCONTEXT InfContext;
  4121. static WCHAR const * const s_apwszKeys[] =
  4122. {
  4123. wszINFKEY_REQUIREEXPLICITPOLICY,
  4124. wszINFKEY_INHIBITPOLICYMAPPING,
  4125. wszINFKEY_CRITICAL,
  4126. NULL
  4127. };
  4128. ZeroMemory(&PolicyConstraints, sizeof(PolicyConstraints));
  4129. ZeroMemory(pext, sizeof(*pext));
  4130. myInfClearError();
  4131. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  4132. {
  4133. hr = E_HANDLE;
  4134. _JumpError2(hr, error, "hInf", hr);
  4135. }
  4136. hr = infSetupFindFirstLine(
  4137. hInf,
  4138. pwszSection,
  4139. NULL, // pwszKey
  4140. FALSE, // fUniqueKey
  4141. 0, // cValueMax
  4142. s_apwszKeys,
  4143. TRUE, // fUniqueValidKeys
  4144. &InfContext);
  4145. _JumpIfErrorStr2(
  4146. hr,
  4147. error,
  4148. "infSetupFindFirstLine",
  4149. pwszSection,
  4150. ERROR_LINE_NOT_FOUND);
  4151. PolicyConstraints.fRequireExplicitPolicy = TRUE;
  4152. pwszKey = wszINFKEY_REQUIREEXPLICITPOLICY;
  4153. hr = myInfGetNumericKeyValue(
  4154. hInf,
  4155. TRUE, // fLog
  4156. pwszSection,
  4157. pwszKey,
  4158. 1,
  4159. TRUE, // fLastValue
  4160. &PolicyConstraints.dwRequireExplicitPolicySkipCerts);
  4161. if (S_OK != hr)
  4162. {
  4163. if ((HRESULT) ERROR_LINE_NOT_FOUND != hr)
  4164. {
  4165. _JumpError(hr, error, "myInfGetNumericKeyValue");
  4166. }
  4167. _PrintErrorStr2(
  4168. hr,
  4169. "myInfGetNumericKeyValue",
  4170. wszINFKEY_REQUIREEXPLICITPOLICY,
  4171. hr);
  4172. PolicyConstraints.dwRequireExplicitPolicySkipCerts = 0;
  4173. PolicyConstraints.fRequireExplicitPolicy = FALSE;
  4174. }
  4175. PolicyConstraints.fInhibitPolicyMapping = TRUE;
  4176. pwszKey = wszINFKEY_INHIBITPOLICYMAPPING;
  4177. hr = myInfGetNumericKeyValue(
  4178. hInf,
  4179. TRUE, // fLog
  4180. pwszSection,
  4181. pwszKey,
  4182. 1,
  4183. TRUE, // fLastValue
  4184. &PolicyConstraints.dwInhibitPolicyMappingSkipCerts);
  4185. if (S_OK != hr)
  4186. {
  4187. if ((HRESULT) ERROR_LINE_NOT_FOUND != hr)
  4188. {
  4189. _JumpError(hr, error, "myInfGetNumericKeyValue");
  4190. }
  4191. _PrintErrorStr2(
  4192. hr,
  4193. "myInfGetNumericKeyValue",
  4194. wszINFKEY_INHIBITPOLICYMAPPING,
  4195. hr);
  4196. PolicyConstraints.dwInhibitPolicyMappingSkipCerts = 0;
  4197. PolicyConstraints.fInhibitPolicyMapping = FALSE;
  4198. }
  4199. pwszKey = NULL;
  4200. if (!PolicyConstraints.fRequireExplicitPolicy &&
  4201. !PolicyConstraints.fInhibitPolicyMapping)
  4202. {
  4203. hr = S_FALSE;
  4204. _JumpError2(hr, error, "no policy constraints", hr);
  4205. }
  4206. hr = infGetCriticalFlag(
  4207. hInf,
  4208. pwszSection,
  4209. FALSE,
  4210. &pext->fCritical);
  4211. _JumpIfError(hr, error, "infGetCriticalFlag");
  4212. if (!myEncodeObject(
  4213. X509_ASN_ENCODING,
  4214. X509_POLICY_CONSTRAINTS,
  4215. &PolicyConstraints,
  4216. 0,
  4217. CERTLIB_USE_LOCALALLOC,
  4218. &pext->Value.pbData,
  4219. &pext->Value.cbData))
  4220. {
  4221. hr = myHLastError();
  4222. _JumpError(hr, error, "myEncodeObject");
  4223. }
  4224. error:
  4225. if (S_OK != hr && S_FALSE != hr)
  4226. {
  4227. INFSETERROR(hr, pwszSection, pwszKey, NULL);
  4228. }
  4229. pext->pszObjId = const_cast<char *>(pszObjId); // on error, too!
  4230. return(hr);
  4231. }
  4232. //+------------------------------------------------------------------------
  4233. // myInfGetPolicyConstraintsExtension -- get policy constraints ext from INF
  4234. //
  4235. // [PolicyConstraintsExtension]
  4236. // ; consists of two optional DWORDs
  4237. // ; They refer to the depth of the CA hierarchy that requires and inhibits
  4238. // ; Policy Mapping
  4239. // RequireExplicitPolicy = 3
  4240. // InhibitPolicyMapping = 5
  4241. //
  4242. // Returns: encoded policy constraints extension
  4243. //-------------------------------------------------------------------------
  4244. FNMYINFGETEXTENSION myInfGetPolicyConstraintsExtension;
  4245. HRESULT
  4246. myInfGetPolicyConstraintsExtension(
  4247. IN HINF hInf,
  4248. OUT CERT_EXTENSION *pext)
  4249. {
  4250. HRESULT hr;
  4251. hr = infGetPolicyConstraintsExtensionSub(
  4252. hInf,
  4253. wszINFSECTION_POLICYCONSTRAINTS,
  4254. szOID_POLICY_CONSTRAINTS,
  4255. pext);
  4256. _JumpIfErrorStr3(
  4257. hr,
  4258. error,
  4259. "infGetPolicyConstraintsExtensionSub",
  4260. wszINFSECTION_POLICYCONSTRAINTS,
  4261. S_FALSE,
  4262. (HRESULT) ERROR_LINE_NOT_FOUND);
  4263. error:
  4264. DBGPRINT((
  4265. DBG_SS_CERTLIBI,
  4266. "myInfGetPolicyConstraintsExtension hr=%x --> f=%d, cb=%x\n",
  4267. hr,
  4268. pext->fCritical,
  4269. pext->Value.cbData));
  4270. return(hr);
  4271. }
  4272. //+------------------------------------------------------------------------
  4273. // myInfGetApplicationPolicyConstraintsExtension -- get application policy
  4274. // constraints extension from INF
  4275. //
  4276. // [ApplicationPolicyConstraintsExtension]
  4277. // ; consists of two optional DWORDs
  4278. // ; They refer to the depth of the CA hierarchy that requires and inhibits
  4279. // ; Policy Mapping
  4280. // RequireExplicitPolicy = 3
  4281. // InhibitPolicyMapping = 5
  4282. //
  4283. // Returns: encoded policy constraints extension
  4284. //-------------------------------------------------------------------------
  4285. FNMYINFGETEXTENSION myInfGetApplicationPolicyConstraintsExtension;
  4286. HRESULT
  4287. myInfGetApplicationPolicyConstraintsExtension(
  4288. IN HINF hInf,
  4289. OUT CERT_EXTENSION *pext)
  4290. {
  4291. HRESULT hr;
  4292. hr = infGetPolicyConstraintsExtensionSub(
  4293. hInf,
  4294. wszINFSECTION_APPLICATIONPOLICYCONSTRAINTS,
  4295. szOID_APPLICATION_POLICY_CONSTRAINTS,
  4296. pext);
  4297. _JumpIfErrorStr3(
  4298. hr,
  4299. error,
  4300. "infGetPolicyConstraintsExtensionSub",
  4301. wszINFSECTION_APPLICATIONPOLICYCONSTRAINTS,
  4302. S_FALSE,
  4303. (HRESULT) ERROR_LINE_NOT_FOUND);
  4304. error:
  4305. DBGPRINT((
  4306. DBG_SS_CERTLIBI,
  4307. "myInfGetApplicationPolicyConstraintsExtension hr=%x --> f=%d, cb=%x\n",
  4308. hr,
  4309. pext->fCritical,
  4310. pext->Value.cbData));
  4311. return(hr);
  4312. }
  4313. //+------------------------------------------------------------------------
  4314. // myInfGetCrossCertDistributionPointsExtension -- fetch Cross CertDist Point
  4315. // URLs from CAPolicy.inf
  4316. //
  4317. // [CrossCertificateDistributionPointsExtension]
  4318. // SyncDeltaTime = 24
  4319. // URL = http://CRLhttp.site.com/Public/MyCA.crt
  4320. // URL = ftp://CRLftp.site.com/Public/MyCA.crt
  4321. //
  4322. // Returns: encoded cross cert dist points extension
  4323. //-------------------------------------------------------------------------
  4324. FNMYINFGETEXTENSION myInfGetCrossCertDistributionPointsExtension;
  4325. HRESULT
  4326. myInfGetCrossCertDistributionPointsExtension(
  4327. IN HINF hInf,
  4328. OUT CERT_EXTENSION *pext)
  4329. {
  4330. HRESULT hr;
  4331. INFCONTEXT InfContext;
  4332. CROSS_CERT_DIST_POINTS_INFO ccdpi;
  4333. CERT_ALT_NAME_INFO AltNameInfo;
  4334. CERT_ALT_NAME_ENTRY *rgAltEntry = NULL;
  4335. WCHAR const *pwsz;
  4336. WCHAR *pwszzURL = NULL;
  4337. DWORD i;
  4338. WCHAR const *pwszKey = NULL;
  4339. static WCHAR const * const s_apwszKeys[] =
  4340. { wszINFKEY_CCDPSYNCDELTATIME, wszINFKEY_URL, wszINFKEY_CRITICAL, NULL };
  4341. ZeroMemory(&ccdpi, sizeof(ccdpi));
  4342. ZeroMemory(&AltNameInfo, sizeof(AltNameInfo));
  4343. ZeroMemory(pext, sizeof(*pext));
  4344. myInfClearError();
  4345. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  4346. {
  4347. hr = E_HANDLE;
  4348. _JumpError2(hr, error, "hInf", hr);
  4349. }
  4350. hr = infSetupFindFirstLine(
  4351. hInf,
  4352. wszINFSECTION_CCDP,
  4353. NULL, // pwszKey
  4354. FALSE, // fUniqueKey
  4355. 0, // cValueMax
  4356. s_apwszKeys,
  4357. FALSE, // fUniqueValidKeys
  4358. &InfContext);
  4359. _JumpIfErrorStr3(
  4360. hr,
  4361. error,
  4362. "infSetupFindFirstLine",
  4363. wszINFSECTION_CCDP,
  4364. S_FALSE,
  4365. (HRESULT) ERROR_LINE_NOT_FOUND);
  4366. pwszKey = wszINFKEY_CCDPSYNCDELTATIME;
  4367. hr = myInfGetNumericKeyValue(
  4368. hInf,
  4369. TRUE, // fLog
  4370. wszINFSECTION_CCDP,
  4371. pwszKey,
  4372. 1,
  4373. TRUE, // fLastValue
  4374. &ccdpi.dwSyncDeltaTime);
  4375. if (S_OK != hr)
  4376. {
  4377. _PrintErrorStr2(
  4378. hr,
  4379. "myInfGetNumericKeyValue",
  4380. pwszKey,
  4381. ERROR_LINE_NOT_FOUND);
  4382. ccdpi.dwSyncDeltaTime = 0;
  4383. }
  4384. pwszKey = wszINFKEY_URL;
  4385. hr = myInfGetKeyList(
  4386. hInf,
  4387. wszINFSECTION_CCDP,
  4388. pwszKey,
  4389. NULL, // apwszKeys
  4390. &pext->fCritical,
  4391. &pwszzURL);
  4392. _JumpIfErrorStr3(
  4393. hr,
  4394. error,
  4395. "myInfGetKeyList",
  4396. pwszKey,
  4397. ERROR_LINE_NOT_FOUND,
  4398. S_FALSE);
  4399. pwszKey = NULL;
  4400. if (NULL != pwszzURL)
  4401. {
  4402. for (pwsz = pwszzURL; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  4403. {
  4404. AltNameInfo.cAltEntry++;
  4405. }
  4406. }
  4407. if (0 != AltNameInfo.cAltEntry)
  4408. {
  4409. ccdpi.cDistPoint = 1;
  4410. ccdpi.rgDistPoint = &AltNameInfo;
  4411. AltNameInfo.rgAltEntry = (CERT_ALT_NAME_ENTRY *) LocalAlloc(
  4412. LMEM_FIXED | LMEM_ZEROINIT,
  4413. AltNameInfo.cAltEntry * sizeof(AltNameInfo.rgAltEntry[0]));
  4414. if (NULL == AltNameInfo.rgAltEntry)
  4415. {
  4416. hr = E_OUTOFMEMORY;
  4417. _JumpError(hr, error, "LocalAlloc");
  4418. }
  4419. i = 0;
  4420. for (pwsz = pwszzURL; L'\0' != *pwsz; pwsz += wcslen(pwsz) + 1)
  4421. {
  4422. AltNameInfo.rgAltEntry[i].pwszURL = const_cast<WCHAR *>(pwsz);
  4423. AltNameInfo.rgAltEntry[i].dwAltNameChoice = CERT_ALT_NAME_URL;
  4424. i++;
  4425. }
  4426. CSASSERT(i == AltNameInfo.cAltEntry);
  4427. }
  4428. if (!myEncodeObject(
  4429. X509_ASN_ENCODING,
  4430. X509_CROSS_CERT_DIST_POINTS,
  4431. &ccdpi,
  4432. 0,
  4433. CERTLIB_USE_LOCALALLOC,
  4434. &pext->Value.pbData,
  4435. &pext->Value.cbData))
  4436. {
  4437. hr = myHLastError();
  4438. _JumpError(hr, error, "myEncodeObject");
  4439. }
  4440. error:
  4441. if (S_OK != hr && S_FALSE != hr)
  4442. {
  4443. INFSETERROR(hr, wszINFSECTION_CCDP, pwszKey, NULL);
  4444. }
  4445. pext->pszObjId = szOID_CROSS_CERT_DIST_POINTS; // on error, too!
  4446. DBGPRINT((
  4447. DBG_SS_CERTLIBI,
  4448. "myInfGetCrossCertDistributionPointsExtension hr=%x --> f=%d, cb=%x\n",
  4449. hr,
  4450. pext->fCritical,
  4451. pext->Value.cbData));
  4452. if (NULL != AltNameInfo.rgAltEntry)
  4453. {
  4454. LocalFree(AltNameInfo.rgAltEntry);
  4455. }
  4456. if (NULL != pwszzURL)
  4457. {
  4458. LocalFree(pwszzURL);
  4459. }
  4460. if (NULL != rgAltEntry)
  4461. {
  4462. LocalFree(rgAltEntry);
  4463. }
  4464. return(hr);
  4465. }
  4466. HRESULT
  4467. infAddKey(
  4468. IN WCHAR const *pwszName,
  4469. IN OUT DWORD *pcValues,
  4470. IN OUT INFVALUES **prgInfValues,
  4471. OUT INFVALUES **ppInfValues)
  4472. {
  4473. HRESULT hr;
  4474. INFVALUES *rgInfValues;
  4475. WCHAR *pwszKeyT = NULL;
  4476. hr = myDupString(pwszName, &pwszKeyT);
  4477. _JumpIfError(hr, error, "myDupString");
  4478. if (NULL == *prgInfValues)
  4479. {
  4480. CSASSERT(0 == *pcValues);
  4481. rgInfValues = (INFVALUES *) LocalAlloc(
  4482. LMEM_FIXED | LMEM_ZEROINIT,
  4483. sizeof(**prgInfValues));
  4484. }
  4485. else
  4486. {
  4487. CSASSERT(0 != *pcValues);
  4488. rgInfValues = (INFVALUES *) LocalReAlloc(
  4489. *prgInfValues,
  4490. (*pcValues + 1) * sizeof(**prgInfValues),
  4491. LMEM_MOVEABLE | LMEM_ZEROINIT);
  4492. }
  4493. if (NULL == rgInfValues)
  4494. {
  4495. hr = E_OUTOFMEMORY;
  4496. _JumpError(
  4497. hr,
  4498. error,
  4499. NULL == *prgInfValues? "LocalAlloc" : "LocalReAlloc");
  4500. }
  4501. *prgInfValues = rgInfValues;
  4502. *ppInfValues = &rgInfValues[*pcValues];
  4503. (*pcValues)++;
  4504. (*ppInfValues)->pwszKey = pwszKeyT;
  4505. pwszKeyT = NULL;
  4506. hr = S_OK;
  4507. error:
  4508. if (NULL != pwszKeyT)
  4509. {
  4510. LocalFree(pwszKeyT);
  4511. }
  4512. return(hr);
  4513. }
  4514. HRESULT
  4515. infAddValue(
  4516. IN WCHAR const *pwszValue,
  4517. IN OUT INFVALUES *pInfValues)
  4518. {
  4519. HRESULT hr;
  4520. WCHAR *pwszValueT = NULL;
  4521. WCHAR **rgpwszValues = NULL;
  4522. hr = myDupString(pwszValue, &pwszValueT);
  4523. _JumpIfError(hr, error, "myDupString");
  4524. if (NULL == pInfValues->rgpwszValues)
  4525. {
  4526. CSASSERT(0 == pInfValues->cValues);
  4527. rgpwszValues = (WCHAR **) LocalAlloc(
  4528. LMEM_FIXED,
  4529. sizeof(*pInfValues->rgpwszValues));
  4530. }
  4531. else
  4532. {
  4533. CSASSERT(0 != pInfValues->cValues);
  4534. rgpwszValues = (WCHAR **) LocalReAlloc(
  4535. pInfValues->rgpwszValues,
  4536. (pInfValues->cValues + 1) * sizeof(*pInfValues->rgpwszValues),
  4537. LMEM_MOVEABLE);
  4538. }
  4539. if (NULL == rgpwszValues)
  4540. {
  4541. hr = E_OUTOFMEMORY;
  4542. _JumpError(
  4543. hr,
  4544. error,
  4545. NULL == pInfValues->rgpwszValues? "LocalAlloc" : "LocalReAlloc");
  4546. }
  4547. pInfValues->rgpwszValues = rgpwszValues;
  4548. pInfValues->rgpwszValues[pInfValues->cValues] = pwszValueT;
  4549. pInfValues->cValues++;
  4550. pwszValueT = NULL;
  4551. hr = S_OK;
  4552. error:
  4553. if (NULL != pwszValueT)
  4554. {
  4555. LocalFree(pwszValueT);
  4556. }
  4557. return(hr);
  4558. }
  4559. VOID
  4560. myInfFreeSectionValues(
  4561. IN DWORD cInfValues,
  4562. IN OUT INFVALUES *rgInfValues)
  4563. {
  4564. DWORD i;
  4565. DWORD ival;
  4566. INFVALUES *pInfValues;
  4567. if (NULL != rgInfValues)
  4568. {
  4569. for (i = 0; i < cInfValues; i++)
  4570. {
  4571. pInfValues = &rgInfValues[i];
  4572. if (NULL != pInfValues->pwszKey)
  4573. {
  4574. LocalFree(pInfValues->pwszKey);
  4575. }
  4576. if (NULL != pInfValues->rgpwszValues)
  4577. {
  4578. for (ival = 0; ival < pInfValues->cValues; ival++)
  4579. {
  4580. if (NULL != pInfValues->rgpwszValues[ival])
  4581. {
  4582. LocalFree(pInfValues->rgpwszValues[ival]);
  4583. }
  4584. }
  4585. LocalFree(pInfValues->rgpwszValues);
  4586. }
  4587. }
  4588. LocalFree(rgInfValues);
  4589. }
  4590. }
  4591. //+------------------------------------------------------------------------
  4592. // myInfGetSectionValues -- fetch all section values from INF file
  4593. //
  4594. // [pwszSection]
  4595. // KeyName1 = KeyValue1a, KeyValue1b, ...
  4596. // KeyName2 = KeyValue2a, KeyValue2b, ...
  4597. // ...
  4598. // KeyNameN = KeyValueNa, KeyValueNb, ...
  4599. //
  4600. // Returns: array of key names and values
  4601. //-------------------------------------------------------------------------
  4602. HRESULT
  4603. myInfGetSectionValues(
  4604. IN HINF hInf,
  4605. IN WCHAR const *pwszSection,
  4606. OUT DWORD *pcInfValues,
  4607. OUT INFVALUES **prgInfValues)
  4608. {
  4609. HRESULT hr;
  4610. INFCONTEXT InfContext;
  4611. WCHAR *pwszName = NULL;
  4612. WCHAR *pwszValue = NULL;
  4613. DWORD i;
  4614. DWORD cInfValues = 0;
  4615. INFVALUES *rgInfValues = NULL;
  4616. INFVALUES *pInfValues;
  4617. *pcInfValues = 0;
  4618. *prgInfValues = NULL;
  4619. myInfClearError();
  4620. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  4621. {
  4622. hr = E_HANDLE;
  4623. _JumpError2(hr, error, "hInf", hr);
  4624. }
  4625. hr = infSetupFindFirstLine(
  4626. hInf,
  4627. pwszSection,
  4628. NULL, // pwszKey
  4629. FALSE, // fUniqueKey
  4630. 0, // cValueMax
  4631. NULL, // apwszKeys
  4632. FALSE, // fUniqueValidKeys
  4633. &InfContext);
  4634. _JumpIfErrorStr(hr, error, "infSetupFindFirstLine", pwszSection);
  4635. for (;;)
  4636. {
  4637. DWORD cValue;
  4638. if (NULL != pwszName)
  4639. {
  4640. LocalFree(pwszName);
  4641. pwszName = NULL;
  4642. }
  4643. hr = infGetCurrentKeyValue(
  4644. &InfContext,
  4645. pwszSection,
  4646. NULL, // pwszKey
  4647. 0,
  4648. FALSE, // fLastValue
  4649. &pwszName);
  4650. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  4651. //wprintf(L"%ws[0]:\n", pwszName);
  4652. hr = infAddKey(pwszName, &cInfValues, &rgInfValues, &pInfValues);
  4653. _JumpIfError(hr, error, "infAddKey");
  4654. cValue = SetupGetFieldCount(&InfContext);
  4655. if (0 == cValue)
  4656. {
  4657. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  4658. INFSETERROR(hr, pwszSection, pwszName, L"");
  4659. _JumpErrorStr(hr, error, "SetupGetFieldCount", pwszName);
  4660. }
  4661. for (i = 0; i < cValue; i++)
  4662. {
  4663. if (NULL != pwszValue)
  4664. {
  4665. LocalFree(pwszValue);
  4666. pwszValue = NULL;
  4667. }
  4668. hr = infGetCurrentKeyValue(
  4669. &InfContext,
  4670. pwszSection,
  4671. pwszName,
  4672. i + 1,
  4673. FALSE, // fLastValue
  4674. &pwszValue);
  4675. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  4676. //wprintf(L"%ws[%u] = %ws\n", pwszName, i, pwszValue);
  4677. hr = infAddValue(pwszValue, pInfValues);
  4678. _JumpIfError(hr, error, "infAddValue");
  4679. }
  4680. if (!SetupFindNextLine(&InfContext, &InfContext))
  4681. {
  4682. hr = myHLastError();
  4683. _PrintError2(hr, "SetupFindNextLine(end)", hr);
  4684. break;
  4685. }
  4686. }
  4687. *pcInfValues = cInfValues;
  4688. *prgInfValues = rgInfValues;
  4689. rgInfValues = NULL;
  4690. hr = S_OK;
  4691. error:
  4692. if (S_OK != hr && S_FALSE != hr)
  4693. {
  4694. INFSETERROR(hr, pwszSection, pwszName, pwszValue);
  4695. }
  4696. if (NULL != rgInfValues)
  4697. {
  4698. myInfFreeSectionValues(cInfValues, rgInfValues);
  4699. }
  4700. if (NULL != pwszName)
  4701. {
  4702. LocalFree(pwszName);
  4703. }
  4704. if (NULL != pwszValue)
  4705. {
  4706. LocalFree(pwszValue);
  4707. }
  4708. DBGPRINT((
  4709. DBG_SS_CERTLIBI,
  4710. "myInfGetSectionValues hr=%x --> c=%d\n",
  4711. hr,
  4712. *pcInfValues));
  4713. return(hr);
  4714. }
  4715. HRESULT
  4716. myInfGetEnableKeyCounting(
  4717. IN HINF hInf,
  4718. OUT BOOL *pfValue)
  4719. {
  4720. HRESULT hr;
  4721. *pfValue = FALSE;
  4722. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  4723. {
  4724. hr = E_HANDLE;
  4725. _JumpError2(hr, error, "hInf", hr);
  4726. }
  4727. myInfClearError();
  4728. hr = myInfGetBooleanValue(
  4729. hInf,
  4730. wszINFSECTION_CERTSERVER,
  4731. wszINFKEY_ENABLEKEYCOUNTING,
  4732. TRUE,
  4733. pfValue);
  4734. _JumpIfError2(hr, error, "myDupString", ERROR_LINE_NOT_FOUND);
  4735. error:
  4736. return(hr);
  4737. }
  4738. VOID
  4739. myInfFreeExtensions(
  4740. IN DWORD cExt,
  4741. IN CERT_EXTENSION *rgExt)
  4742. {
  4743. if (NULL != rgExt)
  4744. {
  4745. DWORD i;
  4746. for (i = 0; i < cExt; i++)
  4747. {
  4748. if (NULL != rgExt[i].pszObjId)
  4749. {
  4750. LocalFree(rgExt[i].pszObjId);
  4751. }
  4752. if (NULL != rgExt[i].Value.pbData)
  4753. {
  4754. LocalFree(rgExt[i].Value.pbData);
  4755. }
  4756. }
  4757. LocalFree(rgExt);
  4758. }
  4759. }
  4760. HRESULT
  4761. infBuildExtension(
  4762. IN OUT INFCONTEXT *pInfContext,
  4763. OPTIONAL OUT CERT_EXTENSION *pExt)
  4764. {
  4765. HRESULT hr;
  4766. WCHAR *pwszKey = NULL;
  4767. char *pszObjId = NULL;
  4768. WCHAR *pwszValue = NULL;
  4769. BYTE *pbData = NULL;
  4770. DWORD cbData;
  4771. hr = infGetCurrentKeyValue(
  4772. pInfContext,
  4773. NULL, // pwszSection
  4774. NULL, // pwszKey
  4775. 0,
  4776. FALSE, // fLastValue
  4777. &pwszKey);
  4778. _JumpIfError(hr, error, "infGetCurrentKeyValue");
  4779. DBGPRINT((DBG_SS_CERTLIBI, "Element = %ws\n", pwszKey));
  4780. if (0 == LSTRCMPIS(pwszKey, wszINFKEY_CRITICAL) ||
  4781. 0 == LSTRCMPIS(pwszKey, wszINFKEY_CONTINUE))
  4782. {
  4783. hr = S_FALSE; // Skip this key
  4784. _JumpError2(hr, error, "skip Critical/_continue_ key", hr);
  4785. }
  4786. if (!myConvertWszToSz(&pszObjId, pwszKey, -1))
  4787. {
  4788. hr = E_OUTOFMEMORY;
  4789. _JumpError(hr, error, "myConvertWszToSz");
  4790. }
  4791. hr = myVerifyObjIdA(pszObjId);
  4792. _JumpIfErrorStr(hr, error, "myVerifyObjIdA", pwszKey);
  4793. DBGPRINT((DBG_SS_CERTLIBI, "OID = %hs\n", pszObjId));
  4794. hr = infGetCurrentKeyValue(
  4795. pInfContext,
  4796. NULL, // pwszSection
  4797. pwszKey,
  4798. 1,
  4799. TRUE, // fLastValue
  4800. &pwszValue);
  4801. _JumpIfErrorStr(hr, error, "infGetCurrentKeyValue", pwszKey);
  4802. DBGPRINT((DBG_SS_CERTLIBI, "%ws = %ws\n", pwszKey, pwszValue));
  4803. cbData = 0;
  4804. if (L'\0' != *pwszValue) // allow empty values
  4805. {
  4806. hr = myCryptStringToBinary(
  4807. pwszValue,
  4808. wcslen(pwszValue),
  4809. CRYPT_STRING_BASE64,
  4810. &pbData,
  4811. &cbData,
  4812. NULL,
  4813. NULL);
  4814. _JumpIfErrorStr(hr, error, "myCryptStringToBinary", pwszKey);
  4815. }
  4816. if (NULL != pExt)
  4817. {
  4818. pExt->pszObjId = pszObjId;
  4819. pExt->Value.pbData = pbData;
  4820. pExt->Value.cbData = cbData;
  4821. pszObjId = NULL;
  4822. pbData = NULL;
  4823. }
  4824. hr = S_OK;
  4825. error:
  4826. if (S_OK != hr && S_FALSE != hr)
  4827. {
  4828. INFSETERROR(hr, NULL, pwszKey, pwszValue);
  4829. }
  4830. if (NULL != pwszKey)
  4831. {
  4832. LocalFree(pwszKey);
  4833. }
  4834. if (NULL != pszObjId)
  4835. {
  4836. LocalFree(pszObjId);
  4837. }
  4838. if (NULL != pwszValue)
  4839. {
  4840. LocalFree(pwszValue);
  4841. }
  4842. if (NULL != pbData)
  4843. {
  4844. LocalFree(pbData);
  4845. }
  4846. return(hr);
  4847. }
  4848. HRESULT
  4849. myInfGetExtensions(
  4850. IN HINF hInf,
  4851. OUT DWORD *pcExt,
  4852. OUT CERT_EXTENSION **ppExt)
  4853. {
  4854. HRESULT hr;
  4855. DWORD i;
  4856. DWORD cExt;
  4857. CERT_EXTENSION *rgExt = NULL;
  4858. DWORD cCritical;
  4859. INFCONTEXT InfContext;
  4860. WCHAR *pwszValue = NULL;
  4861. char *pszObjId = NULL;
  4862. WCHAR *pwszObjIdKey = NULL;
  4863. WCHAR const *pwszSection = wszINFSECTION_EXTENSIONS;
  4864. WCHAR const *pwszKey = wszINFKEY_CRITICAL;
  4865. DWORD j;
  4866. *pcExt = 0;
  4867. *ppExt = NULL;
  4868. cExt = 0;
  4869. if (NULL == hInf || INVALID_HANDLE_VALUE == hInf)
  4870. {
  4871. hr = E_HANDLE;
  4872. _JumpError2(hr, error, "hInf", hr);
  4873. }
  4874. myInfClearError();
  4875. hr = infSetupFindFirstLine(
  4876. hInf,
  4877. pwszSection,
  4878. NULL, // pwszKey
  4879. FALSE, // fUniqueKey
  4880. 0, // cValueMax
  4881. NULL, // apwszKeys
  4882. FALSE, // fUniqueValidKeys
  4883. &InfContext);
  4884. _JumpIfErrorStr2(
  4885. hr,
  4886. error,
  4887. "infSetupFindFirstLine",
  4888. pwszSection,
  4889. ERROR_LINE_NOT_FOUND);
  4890. for (i = 0; ; )
  4891. {
  4892. hr = infBuildExtension(&InfContext, NULL);
  4893. if (S_FALSE != hr)
  4894. {
  4895. _JumpIfErrorStr(hr, error, "infBuildExtension", pwszSection);
  4896. i++;
  4897. }
  4898. if (!SetupFindNextLine(&InfContext, &InfContext))
  4899. {
  4900. hr = myHLastError();
  4901. _PrintErrorStr2(hr, "SetupFindNextLine", pwszSection, hr);
  4902. break;
  4903. }
  4904. }
  4905. cExt = i;
  4906. rgExt = (CERT_EXTENSION *) LocalAlloc(
  4907. LMEM_FIXED | LMEM_ZEROINIT,
  4908. cExt * sizeof(rgExt[0]));
  4909. if (NULL == rgExt)
  4910. {
  4911. hr = E_OUTOFMEMORY;
  4912. _JumpError(hr, error, "LocalAlloc");
  4913. }
  4914. hr = infSetupFindFirstLine(
  4915. hInf,
  4916. pwszSection,
  4917. NULL, // pwszKey
  4918. FALSE, // fUniqueKey
  4919. 0, // cValueMax
  4920. NULL, // apwszKeys
  4921. FALSE, // fUniqueValidKeys
  4922. &InfContext);
  4923. _JumpIfErrorStr(hr, error, "infSetupFindFirstLine", pwszSection);
  4924. for (i = 0; ; )
  4925. {
  4926. // handle one URL or text message
  4927. hr = infBuildExtension(&InfContext, &rgExt[i]);
  4928. if (S_FALSE != hr)
  4929. {
  4930. _JumpIfErrorStr(hr, error, "infBuildExtension", pwszSection);
  4931. for (j = 0; j < i; j++)
  4932. {
  4933. if (0 == strcmp(rgExt[j].pszObjId, rgExt[i].pszObjId))
  4934. {
  4935. if (!myConvertSzToWsz(&pwszObjIdKey, rgExt[i].pszObjId, -1))
  4936. {
  4937. _PrintError(E_OUTOFMEMORY, "myConvertSzToWsz");
  4938. }
  4939. hr = HRESULT_FROM_WIN32(RPC_S_ENTRY_ALREADY_EXISTS);
  4940. INFSETERROR(hr, pwszSection, pwszObjIdKey, NULL);
  4941. _JumpErrorStr(hr, error, "infBuildExtension", pwszObjIdKey);
  4942. }
  4943. }
  4944. i++;
  4945. }
  4946. if (!SetupFindNextLine(&InfContext, &InfContext))
  4947. {
  4948. hr = myHLastError();
  4949. _PrintErrorStr2(hr, "SetupFindNextLine", pwszSection, hr);
  4950. break;
  4951. }
  4952. }
  4953. CSASSERT(i == cExt);
  4954. hr = infSetupFindFirstLine(
  4955. hInf,
  4956. pwszSection,
  4957. pwszKey,
  4958. TRUE, // fUniqueKey
  4959. 0, // cValueMax
  4960. NULL, // apwszKeys
  4961. FALSE, // fUniqueValidKeys
  4962. &InfContext);
  4963. _PrintIfErrorStr2(
  4964. hr,
  4965. "infSetupFindFirstLine",
  4966. pwszKey,
  4967. ERROR_LINE_NOT_FOUND);
  4968. if (S_OK != hr)
  4969. {
  4970. if ((HRESULT) ERROR_LINE_NOT_FOUND != hr)
  4971. {
  4972. INFSETERROR(hr, pwszSection, pwszKey, NULL);
  4973. _JumpErrorStr(hr, error, "infSetupFindFirstLine", pwszKey);
  4974. }
  4975. }
  4976. else
  4977. {
  4978. cCritical = SetupGetFieldCount(&InfContext);
  4979. for (i = 1; i <= cCritical; i++)
  4980. {
  4981. if (NULL != pwszValue)
  4982. {
  4983. LocalFree(pwszValue);
  4984. pwszValue = NULL;
  4985. }
  4986. if (NULL != pszObjId)
  4987. {
  4988. LocalFree(pszObjId);
  4989. pszObjId = NULL;
  4990. }
  4991. hr = infGetCurrentKeyValue(
  4992. &InfContext,
  4993. NULL, // pwszSection
  4994. pwszKey,
  4995. i,
  4996. FALSE, // fLastValue
  4997. &pwszValue);
  4998. _JumpIfErrorStr(hr, error, "infGetCurrentKeyValue", pwszKey);
  4999. if (!myConvertWszToSz(&pszObjId, pwszValue, -1))
  5000. {
  5001. hr = E_OUTOFMEMORY;
  5002. _JumpError(hr, error, "myConvertWszToSz");
  5003. }
  5004. for (j = 0; j < cExt; j++)
  5005. {
  5006. if (NULL != rgExt[j].Value.pbData &&
  5007. 0 != rgExt[j].Value.cbData &&
  5008. 0 == strcmp(rgExt[j].pszObjId, pszObjId))
  5009. {
  5010. if (rgExt[j].fCritical)
  5011. {
  5012. hr = HRESULT_FROM_WIN32(RPC_S_ENTRY_ALREADY_EXISTS);
  5013. INFSETERROR(hr, pwszSection, pwszKey, pwszValue);
  5014. _JumpErrorStr(hr, error, "duplicate OID", pwszValue);
  5015. }
  5016. rgExt[j].fCritical = TRUE;
  5017. break;
  5018. }
  5019. }
  5020. if (j == cExt)
  5021. {
  5022. hr = HRESULT_FROM_WIN32(ERROR_MORE_DATA);
  5023. INFSETERROR(hr, pwszSection, pwszKey, pwszValue);
  5024. _JumpErrorStr(hr, error, "extraneous OID", pwszValue);
  5025. }
  5026. }
  5027. }
  5028. *pcExt = cExt;
  5029. *ppExt = rgExt;
  5030. rgExt = NULL;
  5031. hr = S_OK;
  5032. error:
  5033. if (S_OK != hr && (HRESULT) ERROR_LINE_NOT_FOUND != hr)
  5034. {
  5035. INFSETERROR(hr, pwszSection, NULL, NULL);
  5036. }
  5037. if (NULL != pwszValue)
  5038. {
  5039. LocalFree(pwszValue);
  5040. }
  5041. if (NULL != pszObjId)
  5042. {
  5043. LocalFree(pszObjId);
  5044. }
  5045. if (NULL != pwszObjIdKey)
  5046. {
  5047. LocalFree(pwszObjIdKey);
  5048. }
  5049. myInfFreeExtensions(cExt, rgExt);
  5050. return(hr);
  5051. }