Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

845 lines
16 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: row.cpp
  7. //
  8. // Contents: Cert Server Database interface implementation
  9. //
  10. //---------------------------------------------------------------------------
  11. #include <pch.cpp>
  12. #pragma hdrstop
  13. #include "csdisp.h"
  14. #include "csprop.h"
  15. #include "row.h"
  16. #include "enum.h"
  17. #include "db.h"
  18. #include "dbw.h"
  19. #if DBG
  20. LONG g_cCertDBRow;
  21. LONG g_cCertDBRowTotal;
  22. #endif
  23. CCertDBRow::CCertDBRow()
  24. {
  25. DBGCODE(InterlockedIncrement(&g_cCertDBRow));
  26. DBGCODE(InterlockedIncrement(&g_cCertDBRowTotal));
  27. m_pdb = NULL;
  28. m_pcs = NULL;
  29. m_cRef = 1;
  30. }
  31. CCertDBRow::~CCertDBRow()
  32. {
  33. DBGCODE(InterlockedDecrement(&g_cCertDBRow));
  34. _Cleanup();
  35. }
  36. VOID
  37. CCertDBRow::_Cleanup()
  38. {
  39. HRESULT hr;
  40. if (NULL != m_pdb)
  41. {
  42. if (NULL != m_pcs)
  43. {
  44. hr = ((CCertDB *) m_pdb)->CloseTables(m_pcs);
  45. _PrintIfError(hr, "CloseTables");
  46. hr = ((CCertDB *) m_pdb)->ReleaseSession(m_pcs);
  47. _PrintIfError(hr, "ReleaseSession");
  48. m_pcs = NULL;
  49. }
  50. m_pdb->Release();
  51. m_pdb = NULL;
  52. }
  53. }
  54. HRESULT
  55. CCertDBRow::Open(
  56. IN CERTSESSION *pcs,
  57. IN ICertDB *pdb,
  58. OPTIONAL IN CERTVIEWRESTRICTION const *pcvr)
  59. {
  60. HRESULT hr;
  61. DWORD dwTemp;
  62. DWORD cbActual;
  63. bool fBeginTransaction = false;
  64. _Cleanup();
  65. if (NULL == pcs || NULL == pdb)
  66. {
  67. hr = E_POINTER;
  68. _JumpError(hr, error, "NULL parm");
  69. }
  70. m_pdb = pdb;
  71. m_pdb->AddRef();
  72. CSASSERT(0 == pcs->cTransact);
  73. if (!(CSF_READONLY & pcs->SesFlags))
  74. {
  75. hr = ((CCertDB *) m_pdb)->BeginTransaction(pcs, FALSE);
  76. _JumpIfError(hr, error, "BeginTransaction");
  77. }
  78. fBeginTransaction = true;
  79. hr = ((CCertDB *) m_pdb)->OpenTables(pcs, pcvr);
  80. _JumpIfError2(hr, error, "OpenTables", CERTSRV_E_PROPERTY_EMPTY);
  81. m_pcs = pcs;
  82. error:
  83. if (S_OK != hr)
  84. {
  85. if(fBeginTransaction && !(CSF_READONLY & pcs->SesFlags))
  86. {
  87. HRESULT hr2;
  88. hr2 = ((CCertDB *) m_pdb)->CommitTransaction(pcs, FALSE);
  89. _PrintIfError(hr2, "CommitTransaction");
  90. }
  91. _Cleanup();
  92. }
  93. return(hr);
  94. }
  95. STDMETHODIMP
  96. CCertDBRow::BeginTransaction(VOID)
  97. {
  98. HRESULT hr;
  99. if (NULL == m_pdb)
  100. {
  101. hr = E_UNEXPECTED;
  102. _JumpError(hr, error, "NULL m_pdb");
  103. }
  104. if (CSF_READONLY & m_pcs->SesFlags)
  105. {
  106. hr = E_ACCESSDENIED;
  107. _JumpError(hr, error, "read-only row");
  108. }
  109. hr = ((CCertDB *) m_pdb)->BeginTransaction(m_pcs, TRUE);
  110. _JumpIfError(hr, error, "BeginTransaction");
  111. error:
  112. return(hr);
  113. }
  114. STDMETHODIMP
  115. CCertDBRow::CommitTransaction(
  116. /* [in] */ BOOL fCommit)
  117. {
  118. HRESULT hr;
  119. if (NULL == m_pdb)
  120. {
  121. hr = E_UNEXPECTED;
  122. _JumpError(hr, error, "NULL m_pdb");
  123. }
  124. if (CSF_READONLY & m_pcs->SesFlags)
  125. {
  126. hr = E_ACCESSDENIED;
  127. _JumpError(hr, error, "read-only row");
  128. }
  129. hr = ((CCertDB *) m_pdb)->CommitTransaction(m_pcs, fCommit);
  130. _JumpIfError(hr, error, "CommitTransaction");
  131. error:
  132. return(hr);
  133. }
  134. STDMETHODIMP
  135. CCertDBRow::GetRowId(
  136. /* [out] */ DWORD *pRowId)
  137. {
  138. HRESULT hr;
  139. if (NULL == pRowId)
  140. {
  141. hr = E_POINTER;
  142. _JumpError(hr, error, "NULL parm");
  143. }
  144. if (NULL == m_pcs)
  145. {
  146. hr = E_UNEXPECTED;
  147. _JumpError(hr, error, "m_pcs");
  148. }
  149. *pRowId = m_pcs->RowId;
  150. hr = S_OK;
  151. error:
  152. return(hr);
  153. }
  154. STDMETHODIMP
  155. CCertDBRow::Delete()
  156. {
  157. HRESULT hr;
  158. if (!(CSF_DELETE & m_pcs->SesFlags))
  159. {
  160. hr = E_ACCESSDENIED;
  161. _JumpError(hr, error, "not open for delete");
  162. }
  163. hr = ((CCertDB *) m_pdb)->Delete(m_pcs);
  164. _JumpIfError(hr, error, "Delete");
  165. error:
  166. return(hr);
  167. }
  168. STDMETHODIMP
  169. CCertDBRow::GetProperty(
  170. /* [in] */ WCHAR const *pwszPropName,
  171. /* [in] */ DWORD dwFlags,
  172. /* [in, out] */ DWORD *pcbProp,
  173. /* [out] */ BYTE *pbProp) // OPTIONAL
  174. {
  175. HRESULT hr;
  176. DWORD cchProp;
  177. char szProp[4 * MAX_PATH];
  178. DWORD *pcbPropT = pcbProp;
  179. BYTE *pbPropT = pbProp;
  180. DWORD FlagsT = dwFlags;
  181. if (NULL == pwszPropName || NULL == pcbProp)
  182. {
  183. hr = E_POINTER;
  184. _JumpError(hr, error, "NULL parm");
  185. }
  186. if (NULL == pbProp)
  187. {
  188. *pcbProp = 0;
  189. }
  190. hr = _GetPropertyA(pwszPropName, FlagsT, pcbPropT, pbPropT);
  191. if (CERTSRV_E_PROPERTY_EMPTY == hr)
  192. {
  193. goto error;
  194. }
  195. _JumpIfErrorStr2(
  196. hr,
  197. error,
  198. "_GetPropertyA",
  199. pwszPropName,
  200. HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW));
  201. if (0 == *pcbPropT)
  202. {
  203. hr = CERTSRV_E_PROPERTY_EMPTY;
  204. DBGPRINT((
  205. DBG_SS_CERTDB,
  206. "DB: Empty \"%hs\" property: %ws\n",
  207. PROPTABLE_REQUEST == (PROPTABLE_MASK & dwFlags)?
  208. "Request" :
  209. PROPTABLE_CERTIFICATE == (PROPTABLE_MASK & dwFlags)?
  210. "Certificate" : "CRL",
  211. pwszPropName));
  212. _JumpErrorStr(hr, error, "Empty property", pwszPropName);
  213. }
  214. CSASSERT(_VerifyPropertyLength(FlagsT, *pcbPropT, pbPropT));
  215. CSASSERT(_VerifyPropertyLength(dwFlags, *pcbProp, pbProp));
  216. error:
  217. return(hr);
  218. }
  219. // get a field value
  220. HRESULT
  221. CCertDBRow::_GetPropertyA(
  222. IN WCHAR const *pwszPropName,
  223. IN DWORD dwFlags,
  224. IN OUT DWORD *pcbProp,
  225. OPTIONAL OUT BYTE *pbProp)
  226. {
  227. HRESULT hr;
  228. DWORD dwTable;
  229. DBTABLE dt;
  230. if (PROPTABLE_ATTRIBUTE == (PROPTABLE_MASK & dwFlags))
  231. {
  232. hr = _VerifyPropertyValue(
  233. dwFlags,
  234. 0,
  235. JET_coltypLongText,
  236. CB_DBMAXTEXT_ATTRVALUE);
  237. _JumpIfError(hr, error, "Property value type mismatch");
  238. hr = ((CCertDB *) m_pdb)->GetAttribute(
  239. m_pcs,
  240. pwszPropName,
  241. pcbProp,
  242. pbProp);
  243. _JumpIfErrorStr2(
  244. hr,
  245. error,
  246. "GetAttribute",
  247. pwszPropName,
  248. CERTSRV_E_PROPERTY_EMPTY);
  249. }
  250. else
  251. {
  252. hr = ((CCertDB *) m_pdb)->MapPropId(pwszPropName, dwFlags, &dt);
  253. _JumpIfError(hr, error, "MapPropId");
  254. hr = _VerifyPropertyValue(dwFlags, 0, dt.dbcoltyp, dt.dwcbMax);
  255. _JumpIfError(hr, error, "Property value type mismatch");
  256. hr = ((CCertDB *) m_pdb)->GetProperty(m_pcs, &dt, pcbProp, pbProp);
  257. if (hr == HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW))
  258. {
  259. goto error;
  260. }
  261. _JumpIfError2(hr, error, "GetProperty", CERTSRV_E_PROPERTY_EMPTY);
  262. }
  263. error:
  264. return(hr);
  265. }
  266. BOOL
  267. CCertDBRow::_VerifyPropertyLength(
  268. IN DWORD dwFlags,
  269. IN DWORD cbProp,
  270. IN BYTE const *pbProp)
  271. {
  272. BOOL fOk = FALSE;
  273. switch (dwFlags & PROPTYPE_MASK)
  274. {
  275. case PROPTYPE_LONG:
  276. fOk = sizeof(LONG) == cbProp;
  277. break;
  278. case PROPTYPE_DATE:
  279. fOk = sizeof(FILETIME) == cbProp;
  280. break;
  281. case PROPTYPE_BINARY:
  282. fOk = TRUE; // nothing to check
  283. break;
  284. case PROPTYPE_STRING:
  285. if (MAXDWORD == cbProp)
  286. {
  287. cbProp = wcslen((WCHAR const *) pbProp) * sizeof(WCHAR);
  288. }
  289. fOk =
  290. 0 == cbProp ||
  291. NULL == pbProp ||
  292. wcslen((WCHAR const *) pbProp) * sizeof(WCHAR) == cbProp;
  293. break;
  294. default:
  295. CSASSERT(!"_VerifyPropertyLength: Unexpected type");
  296. break;
  297. }
  298. return(fOk);
  299. }
  300. HRESULT
  301. CCertDBRow::_VerifyPropertyValue(
  302. IN DWORD dwFlags,
  303. IN DWORD cbProp,
  304. IN JET_COLTYP coltyp,
  305. IN DWORD cbMax)
  306. {
  307. JET_COLTYP wType;
  308. HRESULT hr = E_INVALIDARG;
  309. switch (dwFlags & PROPTYPE_MASK)
  310. {
  311. case PROPTYPE_LONG:
  312. wType = JET_coltypLong;
  313. break;
  314. case PROPTYPE_DATE:
  315. wType = JET_coltypDateTime;
  316. break;
  317. case PROPTYPE_BINARY:
  318. wType = JET_coltypLongBinary;
  319. break;
  320. case PROPTYPE_STRING:
  321. // LONG or static-sized version?
  322. if (JET_coltypLongText == coltyp)
  323. {
  324. CSASSERT(CB_DBMAXTEXT_MAXINTERNAL < cbMax);
  325. wType = JET_coltypLongText;
  326. }
  327. else
  328. {
  329. CSASSERT(JET_coltypText == coltyp);
  330. CSASSERT(CB_DBMAXTEXT_MAXINTERNAL >= cbMax);
  331. wType = JET_coltypText;
  332. }
  333. break;
  334. default:
  335. _JumpError(hr, error, "Property value type unknown");
  336. }
  337. if (coltyp != wType)
  338. {
  339. _JumpError(hr, error, "Property value type mismatch");
  340. }
  341. // Note: cbProp and cbMax do not include the trailing '\0'.
  342. if (ISTEXTCOLTYP(wType) && cbMax < cbProp)
  343. {
  344. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  345. DBGCODE(wprintf(
  346. L"_VerifyPropertyValue: len = %u, max = %u\n",
  347. cbProp,
  348. cbMax));
  349. _JumpError(hr, error, "Property value string too long");
  350. }
  351. hr = S_OK;
  352. error:
  353. return(hr);
  354. }
  355. STDMETHODIMP
  356. CCertDBRow::SetProperty(
  357. /* [in] */ WCHAR const *pwszPropName,
  358. /* [in] */ DWORD dwFlags,
  359. /* [in] */ DWORD cbProp,
  360. /* [in] */ BYTE const *pbProp) // OPTIONAL
  361. {
  362. HRESULT hr;
  363. char *pszProp = NULL;
  364. if (NULL == pwszPropName)
  365. {
  366. hr = E_POINTER;
  367. _JumpError(hr, error, "NULL parm");
  368. }
  369. if (NULL == pbProp &&
  370. (0 != cbProp || PROPTYPE_STRING != (dwFlags & PROPTYPE_MASK)))
  371. {
  372. hr = E_POINTER;
  373. _JumpError(hr, error, "NULL pbProp");
  374. }
  375. if ((CSF_DELETE | CSF_READONLY) & m_pcs->SesFlags)
  376. {
  377. hr = E_ACCESSDENIED;
  378. _JumpError(hr, error, "SetProperty: delete/read-only row");
  379. }
  380. CSASSERT(_VerifyPropertyLength(dwFlags, cbProp, pbProp));
  381. if (NULL != pbProp && PROPTYPE_STRING == (dwFlags & PROPTYPE_MASK))
  382. {
  383. cbProp = wcslen((WCHAR const *) pbProp) * sizeof(WCHAR);
  384. }
  385. hr = _SetPropertyA(pwszPropName, dwFlags, cbProp, pbProp);
  386. _JumpIfErrorStr(hr, error, "_SetPropertyA", pwszPropName);
  387. error:
  388. if (NULL != pszProp)
  389. {
  390. LocalFree(pszProp);
  391. }
  392. return(hr);
  393. }
  394. HRESULT
  395. CCertDBRow::_SetPropertyA(
  396. IN WCHAR const *pwszPropName,
  397. IN DWORD dwFlags,
  398. IN DWORD cbProp,
  399. IN BYTE const *pbProp) // OPTIONAL
  400. {
  401. HRESULT hr;
  402. DBTABLE dt;
  403. if ((CSF_DELETE | CSF_READONLY) & m_pcs->SesFlags)
  404. {
  405. hr = E_ACCESSDENIED;
  406. _JumpError(hr, error, "_SetPropertyA: delete/read-only row");
  407. }
  408. CSASSERT(NULL != pwszPropName);
  409. if (!_VerifyPropertyLength(dwFlags, cbProp, pbProp))
  410. {
  411. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  412. _JumpError(hr, error, "Property value length invalid");
  413. }
  414. if (PROPTABLE_ATTRIBUTE == (PROPTABLE_MASK & dwFlags))
  415. {
  416. if (PROPCALLER_POLICY == (PROPCALLER_MASK & dwFlags))
  417. {
  418. hr = E_ACCESSDENIED;
  419. _JumpError(hr, error, "Property write disallowed");
  420. }
  421. hr = _VerifyPropertyValue(
  422. PROPTYPE_STRING, // lie
  423. wcslen(pwszPropName) * sizeof(WCHAR),
  424. JET_coltypText,
  425. CB_DBMAXTEXT_ATTRNAME);
  426. _JumpIfErrorStr(
  427. hr,
  428. error,
  429. "_VerifyPropertyValue(attribute name)",
  430. pwszPropName);
  431. hr = _VerifyPropertyValue(
  432. dwFlags,
  433. cbProp,
  434. JET_coltypLongText,
  435. CB_DBMAXTEXT_ATTRVALUE);
  436. _JumpIfErrorStr(
  437. hr,
  438. error,
  439. "_VerifyPropertyValue(attribute value)",
  440. pwszPropName);
  441. hr = ((CCertDB *) m_pdb)->SetAttribute(
  442. m_pcs,
  443. pwszPropName,
  444. cbProp,
  445. pbProp);
  446. _JumpIfError(hr, error, "SetProperty");
  447. }
  448. else
  449. {
  450. hr = ((CCertDB *) m_pdb)->MapPropId(pwszPropName, dwFlags, &dt);
  451. _JumpIfErrorStr(hr, error, "MapPropId", pwszPropName);
  452. if (PROPCALLER_POLICY == (PROPCALLER_MASK & dwFlags) &&
  453. 0 == (DBTF_POLICYWRITEABLE & dt.dwFlags))
  454. {
  455. hr = E_ACCESSDENIED;
  456. _JumpError(hr, error, "Property write disallowed");
  457. }
  458. hr = _VerifyPropertyValue(dwFlags, cbProp, dt.dbcoltyp, dt.dwcbMax);
  459. _JumpIfErrorStr(hr, error, "_VerifyPropertyValue", pwszPropName);
  460. hr = ((CCertDB *) m_pdb)->SetProperty(m_pcs, &dt, cbProp, pbProp);
  461. _JumpIfError(hr, error, "SetProperty");
  462. }
  463. error:
  464. return(hr);
  465. }
  466. STDMETHODIMP
  467. CCertDBRow::SetExtension(
  468. /* [in] */ WCHAR const *pwszExtensionName,
  469. /* [in] */ DWORD dwExtFlags,
  470. /* [in] */ DWORD cbValue,
  471. /* [in] */ BYTE const *pbValue) // OPTIONAL
  472. {
  473. HRESULT hr;
  474. if (NULL == pwszExtensionName)
  475. {
  476. hr = E_POINTER;
  477. _JumpError(hr, error, "NULL parm");
  478. }
  479. if (NULL == m_pdb)
  480. {
  481. hr = E_UNEXPECTED;
  482. _JumpError(hr, error, "NULL m_pdb");
  483. }
  484. if (TABLE_REQCERTS != (CSF_TABLEMASK & m_pcs->SesFlags))
  485. {
  486. hr = E_INVALIDARG;
  487. _JumpError(hr, error, "bad Table");
  488. }
  489. if ((CSF_DELETE | CSF_READONLY) & m_pcs->SesFlags)
  490. {
  491. hr = E_ACCESSDENIED;
  492. _JumpError(hr, error, "SetExtension: delete/read-only row");
  493. }
  494. hr = ((CCertDB *) m_pdb)->SetExtension(
  495. m_pcs,
  496. pwszExtensionName,
  497. dwExtFlags,
  498. cbValue,
  499. pbValue);
  500. _JumpIfErrorStr(hr, error, "SetExtension", pwszExtensionName);
  501. error:
  502. return(hr);
  503. }
  504. STDMETHODIMP
  505. CCertDBRow::GetExtension(
  506. /* [in] */ WCHAR const *pwszExtensionName,
  507. /* [out] */ DWORD *pdwExtFlags,
  508. /* [in, out] */ DWORD *pcbValue,
  509. /* [out] */ BYTE *pbValue) // OPTIONAL
  510. {
  511. HRESULT hr;
  512. if (NULL == pwszExtensionName || NULL == pcbValue)
  513. {
  514. hr = E_POINTER;
  515. _JumpError(hr, error, "NULL parm");
  516. }
  517. if (NULL == m_pdb)
  518. {
  519. hr = E_UNEXPECTED;
  520. _JumpError(hr, error, "NULL m_pdb");
  521. }
  522. if (TABLE_REQCERTS != (CSF_TABLEMASK & m_pcs->SesFlags))
  523. {
  524. hr = E_INVALIDARG;
  525. _JumpError(hr, error, "bad Table");
  526. }
  527. hr = ((CCertDB *) m_pdb)->GetExtension(
  528. m_pcs,
  529. pwszExtensionName,
  530. pdwExtFlags,
  531. pcbValue,
  532. pbValue);
  533. _JumpIfErrorStr2(
  534. hr,
  535. error,
  536. "GetExtension",
  537. pwszExtensionName,
  538. CERTSRV_E_PROPERTY_EMPTY);
  539. error:
  540. return(hr);
  541. }
  542. STDMETHODIMP
  543. CCertDBRow::CopyRequestNames()
  544. {
  545. HRESULT hr;
  546. if (NULL == m_pdb)
  547. {
  548. hr = E_UNEXPECTED;
  549. _JumpError(hr, error, "NULL m_pdb");
  550. }
  551. if (TABLE_REQCERTS != (CSF_TABLEMASK & m_pcs->SesFlags))
  552. {
  553. hr = E_INVALIDARG;
  554. _JumpError(hr, error, "bad Table");
  555. }
  556. if ((CSF_DELETE | CSF_READONLY) & m_pcs->SesFlags)
  557. {
  558. hr = E_ACCESSDENIED;
  559. _JumpError(hr, error, "CopyRequestNames: delete/read-only row");
  560. }
  561. hr = ((CCertDB *) m_pdb)->CopyRequestNames(m_pcs);
  562. _JumpIfError(hr, error, "CopyRequestNames");
  563. error:
  564. return(hr);
  565. }
  566. STDMETHODIMP
  567. CCertDBRow::EnumCertDBName(
  568. /* [in] */ DWORD dwFlags,
  569. /* [out] */ IEnumCERTDBNAME **ppenum)
  570. {
  571. HRESULT hr;
  572. IEnumCERTDBNAME *penum = NULL;
  573. JET_TABLEID tableid = 0;
  574. if (NULL == ppenum)
  575. {
  576. hr = E_POINTER;
  577. _JumpError(hr, error, "NULL parm");
  578. }
  579. *ppenum = NULL;
  580. if (NULL == m_pdb)
  581. {
  582. hr = E_UNEXPECTED;
  583. _JumpError(hr, error, "NULL m_pdb");
  584. }
  585. if (TABLE_REQCERTS != (CSF_TABLEMASK & m_pcs->SesFlags))
  586. {
  587. hr = E_INVALIDARG;
  588. _JumpError(hr, error, "bad Table");
  589. }
  590. hr = ((CCertDB *) m_pdb)->EnumerateSetup(m_pcs, &dwFlags, &tableid);
  591. _JumpIfError(hr, error, "EnumerateSetup");
  592. penum = new CEnumCERTDBNAME;
  593. if (NULL == penum)
  594. {
  595. hr = E_OUTOFMEMORY;
  596. _JumpError(hr, error, "new CEnumCERTDBNAME");
  597. }
  598. hr = ((CEnumCERTDBNAME *) penum)->Open(this, tableid, dwFlags);
  599. _JumpIfError(hr, error, "Open");
  600. *ppenum = penum;
  601. error:
  602. if (S_OK != hr)
  603. {
  604. HRESULT hr2;
  605. if (0 != tableid)
  606. {
  607. hr2 = ((CCertDB *) m_pdb)->CloseTable(m_pcs, tableid);
  608. _PrintIfError(hr2, "CloseTable");
  609. }
  610. delete penum;
  611. }
  612. return(hr);
  613. }
  614. HRESULT
  615. CCertDBRow::EnumerateNext(
  616. IN OUT DWORD *pFlags,
  617. IN JET_TABLEID tableid,
  618. IN LONG cskip,
  619. IN ULONG celt,
  620. OUT CERTDBNAME *rgelt,
  621. OUT ULONG *pceltFetched)
  622. {
  623. HRESULT hr;
  624. if (NULL == rgelt || NULL == pceltFetched)
  625. {
  626. hr = E_POINTER;
  627. _JumpError(hr, error, "NULL parm");
  628. }
  629. if (NULL == m_pdb)
  630. {
  631. hr = E_UNEXPECTED;
  632. _JumpError(hr, error, "NULL m_pdb");
  633. }
  634. if (TABLE_REQCERTS != (CSF_TABLEMASK & m_pcs->SesFlags))
  635. {
  636. hr = E_INVALIDARG;
  637. _JumpError(hr, error, "bad Table");
  638. }
  639. hr = ((CCertDB *) m_pdb)->EnumerateNext(
  640. m_pcs,
  641. pFlags,
  642. tableid,
  643. cskip,
  644. celt,
  645. rgelt,
  646. pceltFetched);
  647. _JumpIfError2(hr, error, "EnumerateNext", S_FALSE);
  648. error:
  649. return(hr);
  650. }
  651. HRESULT
  652. CCertDBRow::EnumerateClose(
  653. IN JET_TABLEID tableid)
  654. {
  655. return(((CCertDB *) m_pdb)->EnumerateClose(m_pcs, tableid));
  656. }
  657. // IUnknown implementation
  658. STDMETHODIMP
  659. CCertDBRow::QueryInterface(
  660. const IID& iid,
  661. void **ppv)
  662. {
  663. HRESULT hr;
  664. if (NULL == ppv)
  665. {
  666. hr = E_POINTER;
  667. _JumpError(hr, error, "NULL parm");
  668. }
  669. if (iid == IID_IUnknown)
  670. {
  671. *ppv = static_cast<ICertDBRow *>(this);
  672. }
  673. else if (iid == IID_ICertDBRow)
  674. {
  675. *ppv = static_cast<ICertDBRow *>(this);
  676. }
  677. else
  678. {
  679. *ppv = NULL;
  680. hr = E_NOINTERFACE;
  681. _JumpError(hr, error, "IID");
  682. }
  683. reinterpret_cast<IUnknown *>(*ppv)->AddRef();
  684. hr = S_OK;
  685. error:
  686. return(hr);
  687. }
  688. ULONG STDMETHODCALLTYPE
  689. CCertDBRow::AddRef()
  690. {
  691. return(InterlockedIncrement(&m_cRef));
  692. }
  693. ULONG STDMETHODCALLTYPE
  694. CCertDBRow::Release()
  695. {
  696. ULONG cRef = InterlockedDecrement(&m_cRef);
  697. if (0 == cRef)
  698. {
  699. delete this;
  700. }
  701. return(cRef);
  702. }
  703. #if 0
  704. STDMETHODIMP
  705. CCertDBRow::InterfaceSupportsErrorInfo(
  706. IN REFIID riid)
  707. {
  708. static const IID *arr[] =
  709. {
  710. &IID_ICertDBRow,
  711. };
  712. for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
  713. {
  714. if (InlineIsEqualGUID(*arr[i], riid))
  715. {
  716. return(S_OK);
  717. }
  718. }
  719. return(S_FALSE);
  720. }
  721. #endif