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.

1455 lines
32 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: view.cpp
  7. //
  8. // Contents: CertView implementation
  9. //
  10. //---------------------------------------------------------------------------
  11. #include "pch.cpp"
  12. #pragma hdrstop
  13. #include "csprop.h"
  14. #include "csdisp.h"
  15. #include "column.h"
  16. #include "row.h"
  17. #include "view.h"
  18. #define __dwFILE__ __dwFILE_CERTVIEW_VIEW_CPP__
  19. WCHAR const g_wszRequestDot[] = wszPROPREQUESTDOT;
  20. #if DBG_CERTSRV
  21. LONG g_cCertView;
  22. LONG g_cCertViewTotal;
  23. #endif
  24. #define CV_COLUMN_CHUNK 66
  25. //+--------------------------------------------------------------------------
  26. // _cbcolNominal -- Return nominal size for DB column data, based on type.
  27. //
  28. // Assume string binary columns are less than full:
  29. //+--------------------------------------------------------------------------
  30. __inline LONG
  31. _cbcolNominal(
  32. IN LONG Type,
  33. IN LONG cbMax)
  34. {
  35. LONG divisor = 1;
  36. switch (PROPTYPE_MASK & Type)
  37. {
  38. case PROPTYPE_STRING: divisor = 2; break; // one-half full?
  39. case PROPTYPE_BINARY: divisor = 4; break; // one-quarter full?
  40. }
  41. return(cbMax / divisor);
  42. }
  43. //+--------------------------------------------------------------------------
  44. // CCertView::CCertView -- constructor
  45. //+--------------------------------------------------------------------------
  46. CCertView::CCertView()
  47. {
  48. DBGCODE(InterlockedIncrement(&g_cCertView));
  49. DBGCODE(InterlockedIncrement(&g_cCertViewTotal));
  50. ZeroMemory(&m_aaaColumn, sizeof(m_aaaColumn));
  51. m_fOpenConnection = FALSE;
  52. m_dwServerVersion = 0;
  53. m_pICertAdminD = NULL;
  54. m_aColumnResult = NULL;
  55. m_aDBColumnResult = NULL;
  56. m_pwszAuthority = NULL;
  57. m_fAddOk = FALSE;
  58. m_fOpenView = FALSE;
  59. m_fServerOpenView = FALSE;
  60. m_aRestriction = NULL;
  61. m_fTableSet = FALSE;
  62. m_icvTable = ICVTABLE_REQCERT;
  63. m_cvrcTable = CVRC_TABLE_REQCERT;
  64. m_pwszServerName = NULL;
  65. ZeroMemory(&m_aapwszColumnDisplayName, sizeof(m_aapwszColumnDisplayName));
  66. }
  67. //+--------------------------------------------------------------------------
  68. // CCertView::~CCertView -- destructor
  69. //
  70. // free memory associated with this instance
  71. //+--------------------------------------------------------------------------
  72. CCertView::~CCertView()
  73. {
  74. DBGCODE(InterlockedDecrement(&g_cCertView));
  75. #if DBG_CERTSRV
  76. if (m_dwRef > 1)
  77. {
  78. DBGPRINT((
  79. DBG_SS_CERTVIEWI,
  80. "%hs has %d instances left over\n",
  81. "CCertView",
  82. m_dwRef));
  83. }
  84. #endif
  85. _Cleanup();
  86. }
  87. //+--------------------------------------------------------------------------
  88. // CCertView::_Cleanup
  89. //
  90. // free memory associated with this instance
  91. //+--------------------------------------------------------------------------
  92. VOID
  93. CCertView::_Cleanup()
  94. {
  95. LONG i;
  96. myCloseDComConnection((IUnknown **) &m_pICertAdminD, &m_pwszServerName);
  97. m_dwServerVersion = 0;
  98. m_fOpenConnection = FALSE;
  99. if (NULL != m_aColumnResult)
  100. {
  101. LocalFree(m_aColumnResult);
  102. m_aColumnResult = NULL;
  103. }
  104. if (NULL != m_aDBColumnResult)
  105. {
  106. LocalFree(m_aDBColumnResult);
  107. m_aDBColumnResult = NULL;
  108. }
  109. for (i = 0; i < ICVTABLE_MAX; i++)
  110. {
  111. if (NULL != m_aaaColumn[i])
  112. {
  113. CERTDBCOLUMN **ppcol;
  114. for (
  115. ppcol = m_aaaColumn[i];
  116. ppcol < &m_aaaColumn[i][m_acaColumn[i]];
  117. ppcol++)
  118. {
  119. if (NULL != *ppcol)
  120. {
  121. LocalFree(*ppcol);
  122. }
  123. }
  124. LocalFree(m_aaaColumn[i]);
  125. m_aaaColumn[i] = NULL;
  126. }
  127. }
  128. if (NULL != m_aRestriction)
  129. {
  130. for (i = 0; i < m_cRestriction; i++)
  131. {
  132. if (NULL != m_aRestriction[i].pbValue)
  133. {
  134. LocalFree(m_aRestriction[i].pbValue);
  135. }
  136. }
  137. LocalFree(m_aRestriction);
  138. m_aRestriction = NULL;
  139. }
  140. if (NULL != m_pwszAuthority)
  141. {
  142. LocalFree(m_pwszAuthority);
  143. m_pwszAuthority = NULL;
  144. }
  145. for (i = 0; i < ICVTABLE_MAX; i++)
  146. {
  147. if (NULL != m_aapwszColumnDisplayName[i])
  148. {
  149. LocalFree(m_aapwszColumnDisplayName[i]);
  150. m_aapwszColumnDisplayName[i] = NULL;
  151. }
  152. }
  153. }
  154. HRESULT
  155. CCertView::_ValidateFlags(
  156. IN BOOL fSchemaOnly,
  157. IN DWORD Flags)
  158. {
  159. HRESULT hr = E_INVALIDARG;
  160. if (~CVRC_COLUMN_MASK & Flags)
  161. {
  162. _JumpError(hr, error, "invalid bits");
  163. }
  164. switch (CVRC_COLUMN_MASK & Flags)
  165. {
  166. case CVRC_COLUMN_RESULT:
  167. case CVRC_COLUMN_VALUE:
  168. if (fSchemaOnly)
  169. {
  170. _JumpError(hr, error, "RESULT/VALUE");
  171. }
  172. break;
  173. case CVRC_COLUMN_SCHEMA:
  174. break;
  175. default:
  176. _JumpError(hr, error, "bad column");
  177. }
  178. if (!m_fOpenConnection ||
  179. (CVRC_COLUMN_SCHEMA != (CVRC_COLUMN_MASK & Flags) &&
  180. !m_fOpenView))
  181. {
  182. hr = E_UNEXPECTED;
  183. _JumpError(hr, error, "Unexpected");
  184. }
  185. hr = S_OK;
  186. error:
  187. return(hr);
  188. }
  189. HRESULT
  190. CCertView::_SetTable(
  191. IN LONG ColumnIndex) // CVRC_TABLE_* or CV_COLUMN_*_DEFAULT
  192. {
  193. HRESULT hr;
  194. LONG cvrcTable;
  195. LONG icvTable;
  196. if (0 > ColumnIndex)
  197. {
  198. switch (ColumnIndex)
  199. {
  200. case CV_COLUMN_LOG_DEFAULT:
  201. case CV_COLUMN_LOG_FAILED_DEFAULT:
  202. case CV_COLUMN_LOG_REVOKED_DEFAULT:
  203. case CV_COLUMN_QUEUE_DEFAULT:
  204. icvTable = ICVTABLE_REQCERT;
  205. cvrcTable = CVRC_TABLE_REQCERT;
  206. break;
  207. case CV_COLUMN_EXTENSION_DEFAULT:
  208. icvTable = ICVTABLE_EXTENSION;
  209. cvrcTable = CVRC_TABLE_EXTENSIONS;
  210. break;
  211. case CV_COLUMN_ATTRIBUTE_DEFAULT:
  212. icvTable = ICVTABLE_ATTRIBUTE;
  213. cvrcTable = CVRC_TABLE_ATTRIBUTES;
  214. break;
  215. case CV_COLUMN_CRL_DEFAULT:
  216. icvTable = ICVTABLE_CRL;
  217. cvrcTable = CVRC_TABLE_CRL;
  218. break;
  219. default:
  220. hr = E_INVALIDARG;
  221. _JumpError(hr, error, "bad negative ColumnIndex");
  222. }
  223. }
  224. else
  225. {
  226. if (~CVRC_TABLE_MASK & ColumnIndex)
  227. {
  228. hr = E_INVALIDARG;
  229. _JumpError(hr, error, "invalid bits");
  230. }
  231. switch (ColumnIndex)
  232. {
  233. case CVRC_TABLE_REQCERT:
  234. icvTable = ICVTABLE_REQCERT;
  235. break;
  236. case CVRC_TABLE_EXTENSIONS:
  237. icvTable = ICVTABLE_EXTENSION;
  238. break;
  239. case CVRC_TABLE_ATTRIBUTES:
  240. icvTable = ICVTABLE_ATTRIBUTE;
  241. break;
  242. case CVRC_TABLE_CRL:
  243. icvTable = ICVTABLE_CRL;
  244. break;
  245. default:
  246. hr = E_INVALIDARG;
  247. _JumpError(hr, error, "bad table");
  248. }
  249. cvrcTable = CVRC_TABLE_MASK & ColumnIndex;
  250. }
  251. if (m_fTableSet)
  252. {
  253. if (icvTable != m_icvTable || cvrcTable != m_cvrcTable)
  254. {
  255. DBGPRINT((
  256. DBG_SS_CERTVIEW,
  257. "_SetTable: cvrcTable=%x <- %x\n",
  258. m_cvrcTable,
  259. cvrcTable));
  260. hr = E_INVALIDARG;
  261. _JumpError(hr, error, "mixed tables");
  262. }
  263. }
  264. else
  265. {
  266. m_icvTable = icvTable;
  267. m_cvrcTable = cvrcTable;
  268. m_fTableSet = TRUE;
  269. DBGPRINT((DBG_SS_CERTVIEWI, "_SetTable(cvrcTable=%x)\n", m_cvrcTable));
  270. }
  271. hr = S_OK;
  272. error:
  273. return(hr);
  274. }
  275. STDMETHODIMP
  276. CCertView::SetTable(
  277. /* [in] */ LONG Table) // CVRC_TABLE_*
  278. {
  279. HRESULT hr;
  280. hr = _VerifyServerVersion(2);
  281. _JumpIfError(hr, error, "_VerifyServerVersion");
  282. if (0 > Table)
  283. {
  284. hr = E_INVALIDARG;
  285. _JumpError(hr, error, "Table");
  286. }
  287. if (m_fTableSet)
  288. {
  289. hr = E_UNEXPECTED;
  290. _JumpError(hr, error, "Already set");
  291. }
  292. hr = _SetTable(Table);
  293. _JumpIfError(hr, error, "_SetTable");
  294. error:
  295. return(hr);
  296. }
  297. HRESULT
  298. CCertView::GetTable(
  299. OUT LONG *pcvrcTable)
  300. {
  301. HRESULT hr;
  302. if (NULL == pcvrcTable)
  303. {
  304. hr = E_POINTER;
  305. _JumpError(hr, error, "NULL parm");
  306. }
  307. *pcvrcTable = m_cvrcTable;
  308. hr = S_OK;
  309. error:
  310. return(hr);
  311. }
  312. HRESULT
  313. CCertView::FindColumn(
  314. IN LONG Flags, // CVRC_COLUMN_*
  315. IN LONG ColumnIndex,
  316. OUT CERTDBCOLUMN const **ppColumn, // localized for server
  317. OPTIONAL OUT WCHAR const **ppwszDisplayName) // localized for client
  318. {
  319. HRESULT hr;
  320. DWORD i;
  321. DBGCODE(LONG ColumnIndexArg = ColumnIndex);
  322. if (NULL == ppColumn)
  323. {
  324. hr = E_POINTER;
  325. _JumpError(hr, error, "NULL parm");
  326. }
  327. *ppColumn = NULL;
  328. hr = _ValidateFlags(FALSE, Flags);
  329. _JumpIfError(hr, error, "_ValidateFlags");
  330. hr = E_INVALIDARG;
  331. if (CVRC_COLUMN_SCHEMA != (CVRC_COLUMN_MASK & Flags))
  332. {
  333. if (m_cColumnResult <= ColumnIndex)
  334. {
  335. DBGPRINT((
  336. DBG_SS_CERTVIEW,
  337. "FindColumn(Flags=%x, ColumnIndex=%x, m_cColumnResult=%x)\n",
  338. Flags,
  339. ColumnIndex,
  340. m_cColumnResult));
  341. _JumpError(hr, error, "Result ColumnIndex");
  342. }
  343. ColumnIndex = m_aColumnResult[ColumnIndex];
  344. }
  345. if (ColumnIndex >= m_acColumn[m_icvTable])
  346. {
  347. _JumpError(hr, error, "ColumnIndex");
  348. }
  349. i = ColumnIndex / CV_COLUMN_CHUNK;
  350. if (i >= m_acaColumn[m_icvTable])
  351. {
  352. _JumpError(hr, error, "ColumnIndex2");
  353. }
  354. *ppColumn = &m_aaaColumn[m_icvTable][i][ColumnIndex % CV_COLUMN_CHUNK];
  355. CSASSERT(NULL != m_aapwszColumnDisplayName[m_icvTable]);
  356. CSASSERT(NULL != m_aapwszColumnDisplayName[m_icvTable][ColumnIndex]);
  357. if (NULL != ppwszDisplayName)
  358. {
  359. *ppwszDisplayName = m_aapwszColumnDisplayName[m_icvTable][ColumnIndex];
  360. }
  361. DBGPRINT((
  362. DBG_SS_CERTVIEWI,
  363. "FindColumn(Flags=%x, ColumnIndex=%x->%x) --> Type=%x Index=%x %ws/%ws\n",
  364. Flags,
  365. ColumnIndexArg,
  366. ColumnIndex,
  367. (*ppColumn)->Type,
  368. (*ppColumn)->Index,
  369. (*ppColumn)->pwszName,
  370. m_aapwszColumnDisplayName[m_icvTable][ColumnIndex]));
  371. hr = S_OK;
  372. error:
  373. return(hr);
  374. }
  375. HRESULT
  376. CCertView::_SaveColumnInfo(
  377. IN LONG icvTable,
  378. IN DWORD celt,
  379. IN CERTTRANSBLOB const *pctbColumn)
  380. {
  381. HRESULT hr;
  382. DWORD cbNew;
  383. CERTDBCOLUMN *peltNew = NULL;
  384. CERTDBCOLUMN *pelt;
  385. CERTTRANSDBCOLUMN *ptelt;
  386. CERTTRANSDBCOLUMN *pteltEnd;
  387. BYTE *pbNext;
  388. BYTE *pbEnd;
  389. CERTDBCOLUMN **ppColumn;
  390. if (NULL == pctbColumn)
  391. {
  392. hr = E_POINTER;
  393. _JumpError(hr, error, "NULL parm");
  394. }
  395. cbNew = pctbColumn->cb + celt * (sizeof(*pelt) - sizeof(*ptelt));
  396. peltNew = (CERTDBCOLUMN *) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, cbNew);
  397. if (NULL == peltNew)
  398. {
  399. hr = E_OUTOFMEMORY;
  400. _JumpError(hr, error, "LocalAlloc");
  401. }
  402. pteltEnd = &((CERTTRANSDBCOLUMN *) pctbColumn->pb)[celt];
  403. if ((BYTE *) pteltEnd > &pctbColumn->pb[pctbColumn->cb])
  404. {
  405. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  406. _JumpError(hr, error, "bad marshalled data");
  407. }
  408. pelt = peltNew;
  409. pbNext = (BYTE *) &peltNew[celt];
  410. pbEnd = (BYTE *) Add2Ptr(peltNew, cbNew);
  411. for (ptelt = (CERTTRANSDBCOLUMN *) pctbColumn->pb;
  412. ptelt < pteltEnd;
  413. ptelt++, pelt++)
  414. {
  415. pelt->Type = ptelt->Type;
  416. pelt->Index = ptelt->Index;
  417. pelt->cbMax = ptelt->cbMax;
  418. hr = CopyMarshalledString(
  419. pctbColumn,
  420. ptelt->obwszName,
  421. pbEnd,
  422. &pbNext,
  423. &pelt->pwszName);
  424. _JumpIfError(hr, error, "CopyMarshalledString");
  425. hr = CopyMarshalledString(
  426. pctbColumn,
  427. ptelt->obwszDisplayName,
  428. pbEnd,
  429. &pbNext,
  430. &pelt->pwszDisplayName);
  431. _JumpIfError(hr, error, "CopyMarshalledString");
  432. }
  433. CSASSERT(pbNext == pbEnd);
  434. ppColumn = (CERTDBCOLUMN **) LocalAlloc(
  435. LMEM_FIXED,
  436. (m_acaColumn[icvTable] + 1) * sizeof(m_aaaColumn[0]));
  437. if (NULL == ppColumn)
  438. {
  439. hr = E_OUTOFMEMORY;
  440. _JumpError(hr, error, "LocalAlloc ppColumn");
  441. }
  442. if (NULL != m_aaaColumn[icvTable])
  443. {
  444. CopyMemory(
  445. ppColumn,
  446. m_aaaColumn[icvTable],
  447. m_acaColumn[icvTable] * sizeof(m_aaaColumn[0]));
  448. LocalFree(m_aaaColumn[icvTable]);
  449. }
  450. m_aaaColumn[icvTable] = ppColumn;
  451. m_aaaColumn[icvTable][m_acaColumn[icvTable]] = peltNew;
  452. peltNew = NULL;
  453. m_acaColumn[icvTable]++;
  454. m_acColumn[icvTable] += celt;
  455. hr = S_OK;
  456. error:
  457. if (NULL != peltNew)
  458. {
  459. LocalFree(peltNew);
  460. }
  461. return(hr);
  462. }
  463. HRESULT
  464. CCertView::_LoadSchema(
  465. IN LONG icvTable,
  466. IN LONG cvrcTable)
  467. {
  468. HRESULT hr;
  469. DWORD icol;
  470. DWORD ccol;
  471. CERTTRANSBLOB ctbColumn;
  472. ctbColumn.pb = NULL;
  473. icol = 0;
  474. CSASSERT(icvTable < ICVTABLE_MAX);
  475. do
  476. {
  477. ccol = CV_COLUMN_CHUNK;
  478. ctbColumn.cb = 0;
  479. hr = S_OK;
  480. __try
  481. {
  482. if (CVRC_TABLE_REQCERT == cvrcTable)
  483. {
  484. hr = m_pICertAdminD->EnumViewColumn(
  485. m_pwszAuthority,
  486. icol,
  487. ccol,
  488. &ccol,
  489. &ctbColumn);
  490. }
  491. else
  492. {
  493. CSASSERT(S_OK == _VerifyServerVersion(2));
  494. hr = m_pICertAdminD->EnumViewColumnTable(
  495. m_pwszAuthority,
  496. cvrcTable,
  497. icol,
  498. ccol,
  499. &ccol,
  500. &ctbColumn);
  501. }
  502. }
  503. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  504. {
  505. }
  506. if (S_FALSE != hr)
  507. {
  508. _JumpIfError(
  509. hr,
  510. error,
  511. CVRC_TABLE_REQCERT == cvrcTable?
  512. "EnumViewColumn" : "EnumViewColumnTable");
  513. }
  514. myRegisterMemAlloc(ctbColumn.pb, ctbColumn.cb, CSM_MIDLUSERALLOC);
  515. hr = _SaveColumnInfo(icvTable, ccol, &ctbColumn);
  516. _JumpIfError(hr, error, "_SaveColumnInfo");
  517. CoTaskMemFree(ctbColumn.pb);
  518. ctbColumn.pb = NULL;
  519. icol += ccol;
  520. } while (CV_COLUMN_CHUNK == ccol);
  521. m_aapwszColumnDisplayName[icvTable] = (WCHAR const **) LocalAlloc(
  522. LMEM_FIXED | LMEM_ZEROINIT,
  523. m_acColumn[icvTable] * sizeof(m_aapwszColumnDisplayName[icvTable][0]));
  524. if (NULL == m_aapwszColumnDisplayName[icvTable])
  525. {
  526. hr = E_OUTOFMEMORY;
  527. _JumpError(hr, error, "LocalAlloc");
  528. }
  529. for (icol = 0; icol < (DWORD) m_acColumn[icvTable]; icol++)
  530. {
  531. CERTDBCOLUMN const *pColumn;
  532. CSASSERT(icol / CV_COLUMN_CHUNK < m_acaColumn[icvTable]);
  533. pColumn = &m_aaaColumn[icvTable][icol / CV_COLUMN_CHUNK][icol % CV_COLUMN_CHUNK];
  534. hr = myGetColumnDisplayName(
  535. pColumn->pwszName,
  536. &m_aapwszColumnDisplayName[icvTable][icol]);
  537. if (E_INVALIDARG == hr)
  538. {
  539. _PrintErrorStr(hr, "myGetColumnDisplayName", pColumn->pwszName);
  540. m_aapwszColumnDisplayName[icvTable][icol] = pColumn->pwszName;
  541. hr = S_OK;
  542. }
  543. _JumpIfError(hr, error, "myGetColumnDisplayName");
  544. }
  545. hr = S_OK;
  546. error:
  547. if (NULL != ctbColumn.pb)
  548. {
  549. CoTaskMemFree(ctbColumn.pb);
  550. }
  551. return(hr);
  552. }
  553. STDMETHODIMP
  554. CCertView::OpenConnection(
  555. /* [in] */ BSTR const strConfig)
  556. {
  557. HRESULT hr;
  558. DWORD i;
  559. WCHAR const *pwszAuthority;
  560. BOOL fTeardownOnError = FALSE;
  561. static LONG s_aTable[ICVTABLE_MAX] =
  562. {
  563. CVRC_TABLE_REQCERT, // ICVTABLE_REQCERT
  564. CVRC_TABLE_EXTENSIONS, // ICVTABLE_EXTENSION
  565. CVRC_TABLE_ATTRIBUTES, // ICVTABLE_ATTRIBUTE
  566. CVRC_TABLE_CRL, // ICVTABLE_CRL
  567. };
  568. if (NULL == strConfig)
  569. {
  570. hr = E_POINTER;
  571. _JumpError(hr, error, "NULL parm");
  572. }
  573. if (m_fOpenConnection)
  574. {
  575. hr = E_UNEXPECTED;
  576. _JumpError(hr, error, "Connected");
  577. }
  578. fTeardownOnError = TRUE;
  579. m_dwServerVersion = 0;
  580. hr = myOpenAdminDComConnection(
  581. strConfig,
  582. &pwszAuthority,
  583. &m_pwszServerName,
  584. &m_dwServerVersion,
  585. &m_pICertAdminD);
  586. _JumpIfError(hr, error, "myOpenAdminDComConnection");
  587. CSASSERT (0 != m_dwServerVersion);
  588. hr = myDupString(pwszAuthority, &m_pwszAuthority);
  589. _JumpIfError(hr, error, "myDupString");
  590. ZeroMemory(&m_acaColumn, sizeof(m_acaColumn));
  591. ZeroMemory(&m_acColumn, sizeof(m_acColumn));
  592. m_cRestriction = 0;
  593. m_aRestriction = (CERTVIEWRESTRICTION *) LocalAlloc(LMEM_FIXED, 0);
  594. if (NULL == m_aRestriction)
  595. {
  596. hr = E_OUTOFMEMORY;
  597. _JumpError(hr, error, "LocalAlloc");
  598. }
  599. m_fOpenConnection = TRUE;
  600. for (i = 0; i < ICVTABLE_MAX; i++)
  601. {
  602. if (m_dwServerVersion >= 2 || ICVTABLE_REQCERT == i)
  603. {
  604. hr = _LoadSchema(i, s_aTable[i]);
  605. _JumpIfError(hr, error, "_LoadSchema");
  606. }
  607. }
  608. hr = S_OK;
  609. error:
  610. if (S_OK != hr && fTeardownOnError)
  611. {
  612. _Cleanup();
  613. }
  614. return(_SetErrorInfo(hr, L"CCertView::OpenConnection"));
  615. }
  616. //+--------------------------------------------------------------------------
  617. // CCertView::_VerifyServerVersion -- verify server version
  618. //
  619. //+--------------------------------------------------------------------------
  620. HRESULT
  621. CCertView::_VerifyServerVersion(
  622. IN DWORD RequiredVersion)
  623. {
  624. HRESULT hr;
  625. if (!m_fOpenConnection)
  626. {
  627. hr = HRESULT_FROM_WIN32(ERROR_ONLY_IF_CONNECTED);
  628. _JumpError(hr, error, "Not connected");
  629. }
  630. if (m_dwServerVersion < RequiredVersion)
  631. {
  632. hr = RPC_E_VERSION_MISMATCH;
  633. _JumpError(hr, error, "old server");
  634. }
  635. hr = S_OK;
  636. error:
  637. return(hr);
  638. }
  639. STDMETHODIMP
  640. CCertView::EnumCertViewColumn(
  641. /* [in] */ LONG fResultColumn, // CVRC_COLUMN_*
  642. /* [out, retval] */ IEnumCERTVIEWCOLUMN **ppenum)
  643. {
  644. HRESULT hr;
  645. IEnumCERTVIEWCOLUMN *penum = NULL;
  646. if (NULL == ppenum)
  647. {
  648. hr = E_POINTER;
  649. _JumpError(hr, error, "NULL parm");
  650. }
  651. *ppenum = NULL;
  652. penum = new CEnumCERTVIEWCOLUMN;
  653. if (NULL == penum)
  654. {
  655. hr = E_OUTOFMEMORY;
  656. _JumpError(hr, error, "new CEnumCERTVIEWCOLUMN");
  657. }
  658. hr = ((CEnumCERTVIEWCOLUMN *) penum)->Open(fResultColumn, -1, this, NULL);
  659. _JumpIfError(hr, error, "Open");
  660. *ppenum = penum;
  661. penum = NULL;
  662. hr = S_OK;
  663. error:
  664. if (NULL != penum)
  665. {
  666. penum->Release();
  667. }
  668. return(_SetErrorInfo(hr, L"CCertView::EnumCertViewColumn"));
  669. }
  670. STDMETHODIMP
  671. CCertView::GetColumnCount(
  672. /* [in] */ LONG fResultColumn, // CVRC_COLUMN_*
  673. /* [out, retval] */ LONG __RPC_FAR *pcColumn)
  674. {
  675. HRESULT hr;
  676. if (NULL == pcColumn)
  677. {
  678. hr = E_POINTER;
  679. _JumpError(hr, error, "NULL parm");
  680. }
  681. hr = _ValidateFlags(FALSE, fResultColumn);
  682. _JumpIfError(hr, error, "_ValidateFlags");
  683. *pcColumn = CVRC_COLUMN_SCHEMA != (CVRC_COLUMN_MASK & fResultColumn)?
  684. m_cColumnResult : m_acColumn[m_icvTable];
  685. error:
  686. return(_SetErrorInfo(hr, L"CCertView::GetColumnCount"));
  687. }
  688. STDMETHODIMP
  689. CCertView::GetColumnIndex(
  690. /* [in] */ LONG fResultColumn, // CVRC_COLUMN_*
  691. /* [in] */ BSTR const strColumnName,
  692. /* [out, retval] */ LONG *pColumnIndex)
  693. {
  694. HRESULT hr;
  695. CERTDBCOLUMN const *pColumn;
  696. WCHAR const *pwsz;
  697. WCHAR *pwszAlloc = NULL;
  698. WCHAR const *pwszDisplayName;
  699. LONG icol;
  700. LONG i;
  701. if (NULL == strColumnName || NULL == pColumnIndex)
  702. {
  703. hr = E_POINTER;
  704. _JumpError(hr, error, "NULL parm");
  705. }
  706. pwsz = strColumnName;
  707. hr = _ValidateFlags(FALSE, fResultColumn);
  708. _JumpIfError(hr, error, "_ValidateFlags");
  709. // First pass: i == 0 -- compare against unlocalized column name
  710. // Second pass: i == 1 -- compare against localized column name
  711. // Third pass: i == 2 -- compare Request.pwsz against unlocalized colname
  712. for (i = 0; ; i++)
  713. {
  714. if (1 < i)
  715. {
  716. if (ICVTABLE_REQCERT != m_icvTable || NULL != wcschr(pwsz, L'.'))
  717. {
  718. hr = E_INVALIDARG;
  719. _JumpErrorStr(hr, error, "Bad Column Name", strColumnName);
  720. }
  721. pwszAlloc = (WCHAR *) LocalAlloc(
  722. LMEM_FIXED,
  723. wcslen(pwsz) * sizeof(WCHAR) +
  724. sizeof(g_wszRequestDot));
  725. if (NULL == pwszAlloc)
  726. {
  727. hr = E_OUTOFMEMORY;
  728. _JumpError(hr, error, "LocalAlloc");
  729. }
  730. wcscpy(pwszAlloc, g_wszRequestDot);
  731. wcscat(pwszAlloc, pwsz);
  732. pwsz = pwszAlloc;
  733. }
  734. for (icol = 0; icol < m_acColumn[m_icvTable]; icol++)
  735. {
  736. hr = FindColumn(fResultColumn, icol, &pColumn, &pwszDisplayName);
  737. _JumpIfErrorStr(hr, error, "FindColumn", strColumnName);
  738. CSASSERT(NULL != pColumn);
  739. CSASSERT(NULL != pColumn->pwszName);
  740. CSASSERT(NULL != pColumn->pwszDisplayName); // localized for server
  741. CSASSERT(NULL != pwszDisplayName); // localized for client
  742. if (0 == mylstrcmpiL(
  743. pwsz,
  744. 1 == i? pwszDisplayName : pColumn->pwszName))
  745. {
  746. break;
  747. }
  748. }
  749. if (icol < m_acColumn[m_icvTable])
  750. {
  751. break;
  752. }
  753. }
  754. *pColumnIndex = icol;
  755. hr = S_OK;
  756. error:
  757. if (NULL != pwszAlloc)
  758. {
  759. LocalFree(pwszAlloc);
  760. }
  761. return(_SetErrorInfo(hr, L"CCertView::GetColumnIndex"));
  762. }
  763. STDMETHODIMP
  764. CCertView::SetResultColumnCount(
  765. /* [in] */ LONG cResultColumn)
  766. {
  767. HRESULT hr;
  768. CERTTRANSBLOB ctbColumnDefault;
  769. ctbColumnDefault.pb = NULL;
  770. hr = E_UNEXPECTED;
  771. if (!m_fOpenConnection)
  772. {
  773. _JumpError(hr, error, "No Connection");
  774. }
  775. if (NULL != m_aColumnResult)
  776. {
  777. _JumpError(hr, error, "2nd call");
  778. }
  779. if (!m_fTableSet)
  780. {
  781. hr = _SetTable(CVRC_TABLE_REQCERT);
  782. _JumpIfError(hr, error, "_SetTable");
  783. }
  784. m_cbcolResultNominalTotal = 0;
  785. m_fAddOk = TRUE;
  786. if (0 > cResultColumn)
  787. {
  788. DWORD cColumnDefault = 0;
  789. m_fAddOk = FALSE;
  790. ctbColumnDefault.cb = 0;
  791. __try
  792. {
  793. hr = m_pICertAdminD->GetViewDefaultColumnSet(
  794. m_pwszAuthority,
  795. cResultColumn,
  796. &cColumnDefault,
  797. &ctbColumnDefault);
  798. }
  799. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  800. {
  801. }
  802. _JumpIfError(hr, error, "GetViewDefaultColumnSet");
  803. myRegisterMemAlloc(
  804. ctbColumnDefault.pb,
  805. ctbColumnDefault.cb,
  806. CSM_MIDLUSERALLOC);
  807. cResultColumn = cColumnDefault;
  808. CSASSERT(NULL != ctbColumnDefault.pb);
  809. CSASSERT(cResultColumn * sizeof(DWORD) == ctbColumnDefault.cb);
  810. }
  811. else
  812. {
  813. cResultColumn &= CVRC_COLUMN_MASK;
  814. }
  815. m_aColumnResult = (LONG *) LocalAlloc(
  816. LMEM_FIXED,
  817. cResultColumn * sizeof(m_aColumnResult[0]));
  818. if (NULL == m_aColumnResult)
  819. {
  820. hr = E_OUTOFMEMORY;
  821. _JumpError(hr, error, "Result Column array");
  822. }
  823. m_aDBColumnResult = (DWORD *) LocalAlloc(
  824. LMEM_FIXED,
  825. cResultColumn * sizeof(m_aDBColumnResult[0]));
  826. if (NULL == m_aDBColumnResult)
  827. {
  828. hr = E_OUTOFMEMORY;
  829. _JumpError(hr, error, "Result DB Column array");
  830. }
  831. m_cColumnResultMax = cResultColumn;
  832. m_cColumnResult = 0;
  833. if (!m_fAddOk)
  834. {
  835. LONG i;
  836. DWORD const *pIndex;
  837. pIndex = (DWORD const *) ctbColumnDefault.pb;
  838. for (i = 0; i < cResultColumn; pIndex++, i++)
  839. {
  840. LONG icol;
  841. CERTDBCOLUMN const *pColumn;
  842. for (icol = 0; icol < m_acColumn[m_icvTable]; icol++)
  843. {
  844. hr = FindColumn(
  845. CVRC_COLUMN_SCHEMA,
  846. icol,
  847. &pColumn,
  848. NULL);
  849. _JumpIfError(hr, error, "FindColumn");
  850. if (*pIndex == pColumn->Index)
  851. {
  852. m_aDBColumnResult[i] = *pIndex;
  853. m_aColumnResult[i] = icol;
  854. m_cbcolResultNominalTotal += _cbcolNominal(pColumn->Type, pColumn->cbMax);
  855. break;
  856. }
  857. }
  858. if (icol >= m_acColumn[m_icvTable])
  859. {
  860. hr = E_INVALIDARG;
  861. _JumpError(hr, error, "ColumnIndex");
  862. }
  863. }
  864. m_cColumnResult = cResultColumn;
  865. }
  866. hr = S_OK;
  867. error:
  868. if (NULL != ctbColumnDefault.pb)
  869. {
  870. CoTaskMemFree(ctbColumnDefault.pb);
  871. }
  872. return(_SetErrorInfo(hr, L"CCertView::SetResultColumnCount"));
  873. }
  874. STDMETHODIMP
  875. CCertView::SetResultColumn(
  876. /* [in] */ LONG ColumnIndex)
  877. {
  878. HRESULT hr;
  879. CERTDBCOLUMN const *pColumn;
  880. if (m_fOpenView || !m_fAddOk || m_cColumnResultMax <= m_cColumnResult)
  881. {
  882. hr = E_UNEXPECTED;
  883. _JumpError(hr, error, "Unexpected");
  884. }
  885. if (!m_fTableSet)
  886. {
  887. hr = _SetTable(CVRC_TABLE_REQCERT);
  888. _JumpIfError(hr, error, "_SetTable");
  889. }
  890. if (m_acColumn[m_icvTable] <= ColumnIndex)
  891. {
  892. hr = E_INVALIDARG;
  893. _JumpError(hr, error, "ColumnIndex");
  894. }
  895. m_aColumnResult[m_cColumnResult] = ColumnIndex;
  896. hr = FindColumn(
  897. CVRC_COLUMN_SCHEMA,
  898. ColumnIndex,
  899. &pColumn,
  900. NULL);
  901. _JumpIfError(hr, error, "FindColumn");
  902. m_aDBColumnResult[m_cColumnResult] = pColumn->Index;
  903. m_cbcolResultNominalTotal += _cbcolNominal(pColumn->Type, pColumn->cbMax);
  904. m_cColumnResult++;
  905. error:
  906. return(_SetErrorInfo(hr, L"CCertView::SetResultColumn"));
  907. }
  908. STDMETHODIMP
  909. CCertView::SetRestriction(
  910. /* [in] */ LONG ColumnIndex,
  911. /* [in] */ LONG SeekOperator,
  912. /* [in] */ LONG SortOrder,
  913. /* [in] */ VARIANT __RPC_FAR const *pvarValue)
  914. {
  915. HRESULT hr;
  916. CERTDBCOLUMN const *pColumn;
  917. CERTVIEWRESTRICTION cvr;
  918. CERTVIEWRESTRICTION *pcvr;
  919. ZeroMemory(&cvr, sizeof(cvr));
  920. hr = E_UNEXPECTED;
  921. if (!m_fOpenConnection)
  922. {
  923. _JumpError(hr, error, "No Connection");
  924. }
  925. if (!m_fTableSet)
  926. {
  927. hr = _SetTable(CVRC_TABLE_REQCERT);
  928. _JumpIfError(hr, error, "_SetTable");
  929. }
  930. if (0 > ColumnIndex)
  931. {
  932. cvr.ColumnIndex = ColumnIndex;
  933. CSASSERT(CVR_SEEK_NONE == cvr.SeekOperator);
  934. CSASSERT(CVR_SORT_NONE == cvr.SortOrder);
  935. CSASSERT(NULL == cvr.pbValue);
  936. CSASSERT(0 == cvr.cbValue);
  937. hr = S_OK;
  938. }
  939. else
  940. {
  941. if (NULL == pvarValue)
  942. {
  943. hr = E_POINTER;
  944. _JumpError(hr, error, "NULL parm");
  945. }
  946. hr = FindColumn(
  947. CVRC_COLUMN_SCHEMA,
  948. CVRC_COLUMN_MASK & ColumnIndex,
  949. &pColumn,
  950. NULL);
  951. _JumpIfError(hr, error, "FindColumn");
  952. switch (SeekOperator)
  953. {
  954. case CVR_SEEK_EQ:
  955. case CVR_SEEK_LT:
  956. case CVR_SEEK_LE:
  957. case CVR_SEEK_GE:
  958. case CVR_SEEK_GT:
  959. case CVR_SEEK_NONE:
  960. //case CVR_SEEK_SET:
  961. break;
  962. default:
  963. hr = E_INVALIDARG;
  964. _JumpError(hr, error, "Seek Operator");
  965. }
  966. switch (SortOrder)
  967. {
  968. case CVR_SORT_NONE:
  969. case CVR_SORT_ASCEND:
  970. case CVR_SORT_DESCEND:
  971. break;
  972. default:
  973. hr = E_INVALIDARG;
  974. _JumpError(hr, error, "Sort Order");
  975. }
  976. hr = myMarshalVariant(
  977. pvarValue,
  978. pColumn->Type,
  979. &cvr.cbValue,
  980. &cvr.pbValue);
  981. _JumpIfError(hr, error, "myMarshalVariant");
  982. cvr.ColumnIndex = pColumn->Index;
  983. cvr.SeekOperator = SeekOperator;
  984. cvr.SortOrder = SortOrder;
  985. }
  986. pcvr = (CERTVIEWRESTRICTION *) LocalAlloc(
  987. LMEM_FIXED,
  988. (m_cRestriction + 1) * sizeof(*pcvr));
  989. if (NULL == pcvr)
  990. {
  991. hr = E_OUTOFMEMORY;
  992. _JumpError(hr, error, "LocalAlloc");
  993. }
  994. if (NULL != m_aRestriction)
  995. {
  996. CopyMemory(pcvr, m_aRestriction, m_cRestriction * sizeof(*pcvr));
  997. LocalFree(m_aRestriction);
  998. }
  999. CopyMemory(&pcvr[m_cRestriction], &cvr, sizeof(cvr));
  1000. cvr.pbValue = NULL;
  1001. m_aRestriction = pcvr;
  1002. m_cRestriction++;
  1003. error:
  1004. if (NULL != cvr.pbValue)
  1005. {
  1006. LocalFree(cvr.pbValue);
  1007. }
  1008. return(_SetErrorInfo(hr, L"CCertView::SetRestriction"));
  1009. }
  1010. STDMETHODIMP
  1011. CCertView::OpenView(
  1012. /* [out] */ IEnumCERTVIEWROW **ppenum)
  1013. {
  1014. HRESULT hr;
  1015. IEnumCERTVIEWROW *penum = NULL;
  1016. if (NULL == ppenum)
  1017. {
  1018. hr = E_POINTER;
  1019. _JumpError(hr, error, "NULL parm");
  1020. }
  1021. *ppenum = NULL;
  1022. hr = E_UNEXPECTED;
  1023. if (!m_fOpenConnection)
  1024. {
  1025. _JumpError(hr, error, "No Connection");
  1026. }
  1027. if (m_fOpenView)
  1028. {
  1029. _JumpError(hr, error, "2nd call");
  1030. }
  1031. penum = new CEnumCERTVIEWROW;
  1032. if (NULL == penum)
  1033. {
  1034. hr = E_OUTOFMEMORY;
  1035. _JumpError(hr, error, "new CEnumCERTVIEWROW");
  1036. }
  1037. hr = ((CEnumCERTVIEWROW *) penum)->Open(this);
  1038. _JumpIfError(hr, error, "Open");
  1039. *ppenum = penum;
  1040. m_fAddOk = FALSE;
  1041. m_fOpenView = TRUE;
  1042. hr = S_OK;
  1043. error:
  1044. if (S_OK != hr && NULL != penum)
  1045. {
  1046. penum->Release();
  1047. }
  1048. return(_SetErrorInfo(hr, L"CCertView::OpenView"));
  1049. }
  1050. HRESULT
  1051. CCertView::SetViewColumns(
  1052. OUT LONG *pcbrowResultNominal)
  1053. {
  1054. HRESULT hr;
  1055. LONG icol;
  1056. if (NULL == pcbrowResultNominal)
  1057. {
  1058. hr = E_POINTER;
  1059. _JumpError(hr, error, "NULL parm");
  1060. }
  1061. if (m_fServerOpenView)
  1062. {
  1063. hr = E_UNEXPECTED;
  1064. _JumpError(hr, error, "View Already Open");
  1065. }
  1066. if (!m_fTableSet)
  1067. {
  1068. hr = _SetTable(CVRC_TABLE_REQCERT);
  1069. _JumpIfError(hr, error, "_SetTable");
  1070. }
  1071. if (NULL == m_aDBColumnResult)
  1072. {
  1073. hr = SetResultColumnCount(m_acColumn[m_icvTable]);
  1074. _JumpIfError(hr, error, "SetResultColumnCount");
  1075. for (icol = 0; icol < m_acColumn[m_icvTable]; icol++)
  1076. {
  1077. hr = SetResultColumn(icol);
  1078. _JumpIfError(hr, error, "SetResultColumn");
  1079. }
  1080. }
  1081. *pcbrowResultNominal =
  1082. sizeof(CERTDBRESULTROW) +
  1083. sizeof(CERTDBRESULTCOLUMN) * m_cColumnResultMax +
  1084. m_cbcolResultNominalTotal;
  1085. hr = S_OK;
  1086. error:
  1087. return(hr);
  1088. }
  1089. HRESULT
  1090. CCertView::EnumView(
  1091. IN LONG cskip,
  1092. IN ULONG celt,
  1093. OUT ULONG *pceltFetched,
  1094. OUT LONG *pieltNext,
  1095. OUT LONG *pcbResultRows,
  1096. OUT CERTTRANSDBRESULTROW const **ppResultRows)
  1097. {
  1098. HRESULT hr;
  1099. CERTTRANSBLOB ctbResultRows;
  1100. if (NULL == ppResultRows ||
  1101. NULL == pceltFetched ||
  1102. NULL == pieltNext ||
  1103. NULL == pcbResultRows)
  1104. {
  1105. hr = E_POINTER;
  1106. _JumpError(hr, error, "NULL parm");
  1107. }
  1108. *ppResultRows = NULL;
  1109. if (!m_fOpenConnection)
  1110. {
  1111. hr = E_UNEXPECTED;
  1112. _JumpError(hr, error, "No Connection");
  1113. }
  1114. DBGPRINT((
  1115. DBG_SS_CERTVIEWI,
  1116. "%hs: ielt=%d cskip=%d celt=%d\n",
  1117. m_fServerOpenView? "EnumView" : "OpenView",
  1118. m_fServerOpenView? m_ielt : 1,
  1119. cskip,
  1120. celt));
  1121. ctbResultRows.pb = NULL;
  1122. ctbResultRows.cb = 0;
  1123. hr = S_OK;
  1124. if (!m_fServerOpenView)
  1125. {
  1126. if (m_cColumnResultMax != m_cColumnResult)
  1127. {
  1128. hr = E_UNEXPECTED;
  1129. _JumpError(hr, error, "Missing Result Columns");
  1130. }
  1131. m_ielt = 1;
  1132. __try
  1133. {
  1134. hr = m_pICertAdminD->OpenView(
  1135. m_pwszAuthority,
  1136. m_cRestriction,
  1137. m_aRestriction,
  1138. m_cColumnResultMax,
  1139. m_aDBColumnResult,
  1140. m_ielt + cskip,
  1141. celt,
  1142. pceltFetched,
  1143. &ctbResultRows);
  1144. m_fServerOpenView = TRUE;
  1145. }
  1146. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  1147. {
  1148. }
  1149. if (S_FALSE != hr)
  1150. {
  1151. _JumpIfError(hr, error, "OpenView");
  1152. }
  1153. }
  1154. else
  1155. {
  1156. __try
  1157. {
  1158. hr = m_pICertAdminD->EnumView(
  1159. m_pwszAuthority,
  1160. m_ielt + cskip,
  1161. celt,
  1162. pceltFetched,
  1163. &ctbResultRows);
  1164. }
  1165. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  1166. {
  1167. }
  1168. if (S_FALSE != hr)
  1169. {
  1170. _JumpIfError(hr, error, "EnumView");
  1171. }
  1172. }
  1173. myRegisterMemAlloc(ctbResultRows.pb, ctbResultRows.cb, CSM_MIDLUSERALLOC);
  1174. DBGPRINT((
  1175. DBG_SS_CERTVIEWI,
  1176. "%hs: *pceltFetched=%d -> %d @ielt=%d -> %d\n",
  1177. m_fServerOpenView? "EnumView" : "OpenView",
  1178. celt,
  1179. *pceltFetched,
  1180. m_ielt + cskip,
  1181. m_ielt + cskip + *pceltFetched));
  1182. m_ielt += cskip + *pceltFetched;
  1183. *pieltNext = m_ielt;
  1184. DBGPRINT((
  1185. DBG_SS_CERTVIEWI,
  1186. "EnumView: celtFetched=%d ieltNext=%d cb=%d hr=%x\n",
  1187. *pceltFetched,
  1188. *pieltNext,
  1189. ctbResultRows.cb,
  1190. hr));
  1191. *pcbResultRows = ctbResultRows.cb;
  1192. *ppResultRows = (CERTTRANSDBRESULTROW const *) ctbResultRows.pb;
  1193. error:
  1194. return(hr);
  1195. }
  1196. HRESULT
  1197. CCertView::EnumAttributesOrExtensions(
  1198. IN DWORD RowId,
  1199. IN DWORD Flags,
  1200. OPTIONAL IN WCHAR const *pwszLast,
  1201. IN DWORD celt,
  1202. OUT DWORD *pceltFetched,
  1203. CERTTRANSBLOB *pctbOut)
  1204. {
  1205. HRESULT hr;
  1206. if (NULL == pceltFetched || NULL == pctbOut)
  1207. {
  1208. hr = E_POINTER;
  1209. _JumpError(hr, error, "NULL parm");
  1210. }
  1211. if (!m_fOpenConnection)
  1212. {
  1213. hr = E_UNEXPECTED;
  1214. _JumpError(hr, error, "No Connection");
  1215. }
  1216. hr = S_OK;
  1217. __try
  1218. {
  1219. hr = m_pICertAdminD->EnumAttributesOrExtensions(
  1220. m_pwszAuthority,
  1221. RowId,
  1222. Flags,
  1223. pwszLast,
  1224. celt,
  1225. pceltFetched,
  1226. pctbOut);
  1227. }
  1228. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  1229. {
  1230. }
  1231. if (S_FALSE != hr)
  1232. {
  1233. _JumpIfError(hr, error, "EnumAttributesOrExtensions");
  1234. }
  1235. myRegisterMemAlloc(pctbOut->pb, pctbOut->cb, CSM_MIDLUSERALLOC);
  1236. error:
  1237. return(hr);
  1238. }
  1239. HRESULT
  1240. CCertView::_SetErrorInfo(
  1241. IN HRESULT hrError,
  1242. IN WCHAR const *pwszDescription)
  1243. {
  1244. CSASSERT(FAILED(hrError) || S_OK == hrError || S_FALSE == hrError);
  1245. if (FAILED(hrError))
  1246. {
  1247. HRESULT hr;
  1248. hr = DispatchSetErrorInfo(
  1249. hrError,
  1250. pwszDescription,
  1251. wszCLASS_CERTVIEW,
  1252. &IID_ICertView);
  1253. CSASSERT(hr == hrError);
  1254. }
  1255. return(hrError);
  1256. }