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.

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