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.

637 lines
12 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 <certdb.h>
  14. #include "csdisp.h"
  15. #include "column.h"
  16. #include "attrib.h"
  17. #include "ext.h"
  18. #include "row.h"
  19. #include "view.h"
  20. #if DBG_CERTSRV
  21. LONG g_cCertViewRow;
  22. LONG g_cCertViewRowTotal;
  23. #endif
  24. #define CB_TARGETBUFFERSIZE (128 * 1024) // remote buffer size target
  25. #define CROW_VIEWCHUNKMIN 35
  26. CEnumCERTVIEWROW::CEnumCERTVIEWROW()
  27. {
  28. DBGCODE(InterlockedIncrement(&g_cCertViewRow));
  29. DBGCODE(InterlockedIncrement(&g_cCertViewRowTotal));
  30. m_pvw = NULL;
  31. m_arowCache = NULL;
  32. m_prowCacheCurrent = NULL;
  33. m_cRef = 1;
  34. m_ieltMax = -1;
  35. }
  36. CEnumCERTVIEWROW::~CEnumCERTVIEWROW()
  37. {
  38. DBGCODE(InterlockedDecrement(&g_cCertViewRow));
  39. #if DBG_CERTSRV
  40. if (m_cRef > 1)
  41. {
  42. DBGPRINT((
  43. DBG_SS_CERTVIEWI,
  44. "%hs has %d instances left over\n",
  45. "CEnumCERTVIEWROW",
  46. m_cRef));
  47. }
  48. #endif
  49. if (NULL != m_arowCache)
  50. {
  51. CoTaskMemFree((VOID *) m_arowCache);
  52. m_arowCache = NULL;
  53. }
  54. if (NULL != m_pvw)
  55. {
  56. m_pvw->Release();
  57. }
  58. }
  59. HRESULT
  60. CEnumCERTVIEWROW::Open(
  61. IN ICertView *pvw)
  62. {
  63. HRESULT hr;
  64. if (NULL == pvw)
  65. {
  66. hr = E_POINTER;
  67. _JumpError(hr, error, "NULL parm");
  68. }
  69. hr = ((CCertView *) pvw)->GetTable(&m_cvrcTable);
  70. _JumpIfError(hr, error, "GetTable");
  71. DBGPRINT((
  72. DBG_SS_CERTVIEWI,
  73. "CEnumCERTVIEWROW::Open(cvrcTable=%x)\n",
  74. m_cvrcTable));
  75. m_pvw = pvw;
  76. m_pvw->AddRef();
  77. m_fNoMoreData = FALSE;
  78. m_cskip = 0;
  79. m_ielt = 0;
  80. m_ieltCacheNext = 1;
  81. m_crowChunk = 0;
  82. hr = S_OK;
  83. error:
  84. return(hr);
  85. }
  86. HRESULT
  87. CEnumCERTVIEWROW::_FindCachedRow(
  88. IN LONG ielt,
  89. OUT CERTTRANSDBRESULTROW const **ppRow)
  90. {
  91. HRESULT hr;
  92. CERTTRANSDBRESULTROW const *prow;
  93. ULONG i;
  94. CSASSERT(NULL != ppRow);
  95. *ppRow = NULL;
  96. // If the server threw in an extra CERTTRANSDBRESULTROW structure containing
  97. // the maximum element count, save the maximum count for later use.
  98. prow = m_arowCache;
  99. if (NULL != prow && m_fNoMoreData)
  100. {
  101. for (i = 0; i < m_celtCache; i++)
  102. {
  103. prow = (CERTTRANSDBRESULTROW const *) Add2ConstPtr(prow, prow->cbrow);
  104. }
  105. if (&prow[1] <=
  106. (CERTTRANSDBRESULTROW const *) Add2ConstPtr(m_arowCache, m_cbCache) &&
  107. prow->rowid == ~prow->ccol)
  108. {
  109. DBGPRINT((
  110. DBG_SS_CERTVIEWI,
  111. "_FindCachedRow: ieltMax = %d -> %d\n",
  112. m_ieltMax,
  113. prow->rowid));
  114. CSASSERT(-1 == m_ieltMax || (LONG) prow->rowid == m_ieltMax);
  115. m_ieltMax = prow->rowid;
  116. }
  117. }
  118. prow = m_arowCache;
  119. if (NULL == prow || ielt < m_ieltCacheFirst || ielt >= m_ieltCacheNext)
  120. {
  121. hr = S_FALSE; // requested row is not in the cached rowset
  122. goto error;
  123. }
  124. for (ielt -= m_ieltCacheFirst; 0 < ielt; ielt--)
  125. {
  126. prow = (CERTTRANSDBRESULTROW const *) Add2ConstPtr(prow, prow->cbrow);
  127. }
  128. *ppRow = prow;
  129. hr = S_OK;
  130. error:
  131. return(hr);
  132. }
  133. STDMETHODIMP
  134. CEnumCERTVIEWROW::GetMaxIndex(
  135. /* [out, retval] */ LONG *pIndex)
  136. {
  137. HRESULT hr;
  138. if (NULL == pIndex)
  139. {
  140. hr = E_POINTER;
  141. _JumpError(hr, error, "NULL parm");
  142. }
  143. if (-1 == m_ieltMax)
  144. {
  145. hr = E_UNEXPECTED;
  146. _JumpError(hr, error, "m_ieltMax not set");
  147. }
  148. *pIndex = m_ieltMax;
  149. hr = S_OK;
  150. error:
  151. return(_SetErrorInfo(hr, L"CEnumCERTVIEWROW::GetMaxIndex"));
  152. }
  153. STDMETHODIMP
  154. CEnumCERTVIEWROW::Next(
  155. /* [out, retval] */ LONG *pIndex)
  156. {
  157. HRESULT hr;
  158. LONG ielt;
  159. LONG ieltNext;
  160. LONG ieltFirst;
  161. LONG cbrowResultNominal;
  162. DBGPRINT((
  163. DBG_SS_CERTVIEWI,
  164. "Trace: hr = pRow->Next(&lNext);\t_PrintIfError(hr, \"Next\");\n"));
  165. if (NULL == pIndex)
  166. {
  167. hr = E_POINTER;
  168. _JumpError(hr, error, "NULL parm");
  169. }
  170. *pIndex = -1;
  171. m_prowCacheCurrent = NULL;
  172. ielt = m_ielt + m_cskip + 1;
  173. hr = _FindCachedRow(ielt, &m_prowCacheCurrent);
  174. if (S_FALSE != hr)
  175. {
  176. _JumpIfError(hr, error, "_FindCachedRow");
  177. }
  178. else
  179. {
  180. if (m_fNoMoreData)
  181. {
  182. hr = S_FALSE;
  183. _JumpError2(hr, error, "NoMoreData", S_FALSE);
  184. }
  185. if (NULL != m_arowCache)
  186. {
  187. CoTaskMemFree((VOID *) m_arowCache);
  188. m_arowCache = NULL;
  189. }
  190. if (0 == m_crowChunk) // First call
  191. {
  192. hr = ((CCertView *) m_pvw)->SetViewColumns(&cbrowResultNominal);
  193. _JumpIfError(hr, error, "SetViewColumns");
  194. m_crowChunk = CB_TARGETBUFFERSIZE / cbrowResultNominal;
  195. DBGPRINT((
  196. DBG_SS_CERTVIEWI,
  197. "ViewRow::Next: cbrowNominal=%d crowChunk=%d\n",
  198. cbrowResultNominal,
  199. m_crowChunk));
  200. if (CROW_VIEWCHUNKMIN > m_crowChunk)
  201. {
  202. m_crowChunk = CROW_VIEWCHUNKMIN;
  203. }
  204. }
  205. hr = ((CCertView *) m_pvw)->EnumView(
  206. ielt - m_ieltCacheNext,
  207. m_crowChunk,
  208. &m_celtCache,
  209. &m_ieltCacheNext,
  210. &m_cbCache,
  211. &m_arowCache);
  212. if (S_FALSE == hr)
  213. {
  214. m_fNoMoreData = TRUE;
  215. }
  216. else
  217. {
  218. _JumpIfError(hr, error, "EnumView");
  219. }
  220. m_ieltCacheFirst = m_ieltCacheNext - m_celtCache;
  221. // workaround for bug 339811 causes this to fail
  222. //CSASSERT(ielt == m_ieltCacheFirst);
  223. hr = _FindCachedRow(ielt, &m_prowCacheCurrent);
  224. _JumpIfError2(hr, error, "_FindCachedRow", S_FALSE);
  225. }
  226. m_cskip = 0;
  227. m_ielt = ielt;
  228. *pIndex = m_ielt;
  229. DBGPRINT((
  230. DBG_SS_CERTVIEWI,
  231. "ViewRow::Next: cskip=%d, ccache=%u:%u-%u, ielt=%u, ieltMax=%d, RowId=%u\n",
  232. m_cskip,
  233. m_celtCache,
  234. m_ieltCacheFirst,
  235. m_ieltCacheNext,
  236. m_ielt,
  237. m_ieltMax,
  238. m_prowCacheCurrent->rowid));
  239. error:
  240. if (S_OK != hr)
  241. {
  242. DBGPRINT((
  243. DBG_SS_CERTVIEWI,
  244. "ViewRow::Next: cskip=%d, ccache=%u:%u-%u, ielt=%u, ieltMax=%d, *pIndex=%d, hr=%x\n",
  245. m_cskip,
  246. m_celtCache,
  247. m_ieltCacheFirst,
  248. m_ieltCacheNext,
  249. m_ielt,
  250. m_ieltMax,
  251. NULL != pIndex? *pIndex : -1,
  252. hr));
  253. }
  254. return(_SetErrorInfo(hr, L"CEnumCERTVIEWROW::Next"));
  255. }
  256. STDMETHODIMP
  257. CEnumCERTVIEWROW::EnumCertViewColumn(
  258. /* [out] */ IEnumCERTVIEWCOLUMN **ppenum)
  259. {
  260. HRESULT hr;
  261. IEnumCERTVIEWCOLUMN *penum = NULL;
  262. if (NULL == ppenum)
  263. {
  264. hr = E_POINTER;
  265. _JumpError(hr, error, "NULL parm");
  266. }
  267. *ppenum = NULL;
  268. if (NULL == m_prowCacheCurrent)
  269. {
  270. hr = E_UNEXPECTED;
  271. _JumpError(hr, error, "NULL m_prowCacheCurrent");
  272. }
  273. penum = new CEnumCERTVIEWCOLUMN;
  274. if (NULL == penum)
  275. {
  276. hr = E_OUTOFMEMORY;
  277. _JumpError(hr, error, "new CEnumCERTVIEWCOLUMN");
  278. }
  279. hr = ((CEnumCERTVIEWCOLUMN *) penum)->Open(
  280. CVRC_COLUMN_VALUE,
  281. m_ielt,
  282. m_pvw,
  283. m_prowCacheCurrent);
  284. _JumpIfError(hr, error, "Open");
  285. *ppenum = penum;
  286. penum = NULL;
  287. hr = S_OK;
  288. error:
  289. if (NULL != penum)
  290. {
  291. penum->Release();
  292. }
  293. return(_SetErrorInfo(hr, L"CEnumCERTVIEWROW::EnumCertViewColumn"));
  294. }
  295. STDMETHODIMP
  296. CEnumCERTVIEWROW::EnumCertViewAttribute(
  297. /* [in] */ LONG Flags,
  298. /* [out, retval] */ IEnumCERTVIEWATTRIBUTE **ppenum)
  299. {
  300. HRESULT hr;
  301. IEnumCERTVIEWATTRIBUTE *penum = NULL;
  302. if (NULL == ppenum)
  303. {
  304. hr = E_POINTER;
  305. _JumpError(hr, error, "NULL parm");
  306. }
  307. *ppenum = NULL;
  308. if (NULL == m_prowCacheCurrent)
  309. {
  310. hr = E_UNEXPECTED;
  311. _JumpError(hr, error, "NULL m_prowCacheCurrent");
  312. }
  313. if (CVRC_TABLE_REQCERT != m_cvrcTable)
  314. {
  315. hr = CERTSRV_E_PROPERTY_EMPTY;
  316. _JumpError(hr, error, "table has no attributes");
  317. }
  318. penum = new CEnumCERTVIEWATTRIBUTE;
  319. if (NULL == penum)
  320. {
  321. hr = E_OUTOFMEMORY;
  322. _JumpError(hr, error, "new CEnumCERTVIEWATTRIBUTE");
  323. }
  324. hr = ((CEnumCERTVIEWATTRIBUTE *) penum)->Open(
  325. m_prowCacheCurrent->rowid,
  326. Flags,
  327. m_pvw);
  328. _JumpIfError(hr, error, "Open");
  329. *ppenum = penum;
  330. penum = NULL;
  331. hr = S_OK;
  332. error:
  333. if (NULL != penum)
  334. {
  335. penum->Release();
  336. }
  337. return(_SetErrorInfo(hr, L"CEnumCERTVIEWROW::EnumCertViewAttribute"));
  338. }
  339. STDMETHODIMP
  340. CEnumCERTVIEWROW::EnumCertViewExtension(
  341. /* [in] */ LONG Flags,
  342. /* [out, retval] */ IEnumCERTVIEWEXTENSION **ppenum)
  343. {
  344. HRESULT hr;
  345. IEnumCERTVIEWEXTENSION *penum = NULL;
  346. if (NULL == ppenum)
  347. {
  348. hr = E_POINTER;
  349. _JumpError(hr, error, "NULL parm");
  350. }
  351. *ppenum = NULL;
  352. if (NULL == m_prowCacheCurrent)
  353. {
  354. hr = E_UNEXPECTED;
  355. _JumpError(hr, error, "NULL m_prowCacheCurrent");
  356. }
  357. if (CVRC_TABLE_REQCERT != m_cvrcTable)
  358. {
  359. hr = CERTSRV_E_PROPERTY_EMPTY;
  360. _JumpError(hr, error, "table has no extensions");
  361. }
  362. penum = new CEnumCERTVIEWEXTENSION;
  363. if (NULL == penum)
  364. {
  365. hr = E_OUTOFMEMORY;
  366. _JumpError(hr, error, "new CEnumCERTVIEWEXTENSION");
  367. }
  368. hr = ((CEnumCERTVIEWEXTENSION *) penum)->Open(
  369. m_prowCacheCurrent->rowid,
  370. Flags,
  371. m_pvw);
  372. _JumpIfError(hr, error, "Open");
  373. *ppenum = penum;
  374. penum = NULL;
  375. hr = S_OK;
  376. error:
  377. if (NULL != penum)
  378. {
  379. penum->Release();
  380. }
  381. return(_SetErrorInfo(hr, L"CEnumCERTVIEWROW::EnumCertViewExtension"));
  382. }
  383. STDMETHODIMP
  384. CEnumCERTVIEWROW::Skip(
  385. /* [in] */ LONG celt)
  386. {
  387. HRESULT hr;
  388. LONG cskipnew;
  389. cskipnew = m_cskip + celt;
  390. DBGPRINT((
  391. DBG_SS_CERTVIEWI,
  392. "Trace: hr = pRow->Skip(%d);\t_PrintIfError(hr, \"Skip(%d)\");\n",
  393. celt,
  394. celt));
  395. DBGPRINT((
  396. DBG_SS_CERTVIEWI,
  397. "ViewRow::Skip(%d) ielt=%d: %d --> %d, skip=%d --> %d\n",
  398. celt,
  399. m_ielt,
  400. m_ielt + m_cskip,
  401. m_ielt + cskipnew,
  402. m_cskip,
  403. cskipnew));
  404. CSASSERT(0 <= m_ielt);
  405. if (0 > celt)
  406. {
  407. if (-1 > m_ielt + cskipnew)
  408. {
  409. hr = E_INVALIDARG;
  410. _JumpError(hr, error, "Skip back to before start");
  411. }
  412. m_fNoMoreData = FALSE;
  413. }
  414. m_prowCacheCurrent = NULL;
  415. m_cskip = cskipnew;
  416. hr = S_OK;
  417. error:
  418. return(_SetErrorInfo(hr, L"CEnumCERTVIEWROW::Skip"));
  419. }
  420. STDMETHODIMP
  421. CEnumCERTVIEWROW::Reset(VOID)
  422. {
  423. HRESULT hr;
  424. // Trailing // and no newline comment out Skip() call we trigger:
  425. DBGPRINT((
  426. DBG_SS_CERTVIEWI,
  427. "Trace: hr = pRow->Reset();\t_PrintIfError(hr, \"Reset\");\n// "));
  428. hr = Skip(-(m_ielt + m_cskip));
  429. _JumpIfError(hr, error, "Skip");
  430. error:
  431. return(_SetErrorInfo(hr, L"CEnumCERTVIEWROW::Reset"));
  432. }
  433. STDMETHODIMP
  434. CEnumCERTVIEWROW::Clone(
  435. /* [out] */ IEnumCERTVIEWROW **ppenum)
  436. {
  437. HRESULT hr;
  438. IEnumCERTVIEWROW *penum = NULL;
  439. LONG ielt;
  440. if (NULL == ppenum)
  441. {
  442. hr = E_POINTER;
  443. _JumpError(hr, error, "NULL parm");
  444. }
  445. hr = m_pvw->OpenView(&penum);
  446. _JumpIfError(hr, error, "OpenView");
  447. ielt = m_ielt + m_cskip;
  448. if (-1 != ielt)
  449. {
  450. if (NULL == m_prowCacheCurrent)
  451. {
  452. hr = penum->Skip(ielt);
  453. _JumpIfError(hr, error, "Skip");
  454. }
  455. else
  456. {
  457. LONG Index;
  458. hr = penum->Skip(ielt - 1);
  459. _JumpIfError(hr, error, "Skip");
  460. hr = penum->Next(&Index);
  461. _JumpIfError(hr, error, "Next");
  462. CSASSERT(Index == ielt);
  463. }
  464. }
  465. error:
  466. if (NULL != ppenum)
  467. {
  468. *ppenum = penum;
  469. }
  470. return(_SetErrorInfo(hr, L"CEnumCERTVIEWROW::Clone"));
  471. }
  472. HRESULT
  473. CEnumCERTVIEWROW::_SetErrorInfo(
  474. IN HRESULT hrError,
  475. IN WCHAR const *pwszDescription)
  476. {
  477. CSASSERT(FAILED(hrError) || S_OK == hrError || S_FALSE == hrError);
  478. if (FAILED(hrError))
  479. {
  480. HRESULT hr;
  481. hr = DispatchSetErrorInfo(
  482. hrError,
  483. pwszDescription,
  484. wszCLASS_CERTVIEW L".CEnumCERTVIEWROW",
  485. &IID_IEnumCERTVIEWROW);
  486. CSASSERT(hr == hrError);
  487. }
  488. return(hrError);
  489. }
  490. // IUnknown implementation
  491. STDMETHODIMP
  492. CEnumCERTVIEWROW::QueryInterface(
  493. const IID& iid,
  494. void **ppv)
  495. {
  496. HRESULT hr;
  497. if (NULL == ppv)
  498. {
  499. hr = E_POINTER;
  500. _JumpError(hr, error, "NULL parm");
  501. }
  502. if (iid == IID_IUnknown)
  503. {
  504. *ppv = static_cast<IEnumCERTVIEWROW *>(this);
  505. }
  506. else if (iid == IID_IDispatch)
  507. {
  508. *ppv = static_cast<IEnumCERTVIEWROW *>(this);
  509. }
  510. else if (iid == IID_IEnumCERTVIEWROW)
  511. {
  512. *ppv = static_cast<IEnumCERTVIEWROW *>(this);
  513. }
  514. else
  515. {
  516. *ppv = NULL;
  517. hr = E_NOINTERFACE;
  518. _JumpError(hr, error, "IID");
  519. }
  520. reinterpret_cast<IUnknown *>(*ppv)->AddRef();
  521. hr = S_OK;
  522. error:
  523. return(hr);
  524. }
  525. ULONG STDMETHODCALLTYPE
  526. CEnumCERTVIEWROW::AddRef()
  527. {
  528. return(InterlockedIncrement(&m_cRef));
  529. }
  530. ULONG STDMETHODCALLTYPE
  531. CEnumCERTVIEWROW::Release()
  532. {
  533. ULONG cRef = InterlockedDecrement(&m_cRef);
  534. if (0 == cRef)
  535. {
  536. delete this;
  537. }
  538. return(cRef);
  539. }