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.

741 lines
14 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: ext.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_cCertViewExtension;
  22. LONG g_cCertViewExtensionTotal;
  23. #endif
  24. CEnumCERTVIEWEXTENSION::CEnumCERTVIEWEXTENSION()
  25. {
  26. DBGCODE(InterlockedIncrement(&g_cCertViewExtension));
  27. DBGCODE(InterlockedIncrement(&g_cCertViewExtensionTotal));
  28. m_pvw = NULL;
  29. m_aelt = NULL;
  30. m_cRef = 1;
  31. }
  32. CEnumCERTVIEWEXTENSION::~CEnumCERTVIEWEXTENSION()
  33. {
  34. DBGCODE(InterlockedDecrement(&g_cCertViewExtension));
  35. #if DBG_CERTSRV
  36. if (m_cRef > 1)
  37. {
  38. DBGPRINT((
  39. DBG_SS_CERTVIEWI,
  40. "%hs has %d instances left over\n",
  41. "CEnumCERTVIEWEXTENSION",
  42. m_cRef));
  43. }
  44. #endif
  45. if (NULL != m_aelt)
  46. {
  47. LocalFree(m_aelt);
  48. m_aelt = NULL;
  49. }
  50. if (NULL != m_pvw)
  51. {
  52. m_pvw->Release();
  53. m_pvw = NULL;
  54. }
  55. }
  56. HRESULT
  57. CEnumCERTVIEWEXTENSION::Open(
  58. IN LONG RowId,
  59. IN LONG Flags,
  60. IN ICertView *pvw)
  61. {
  62. HRESULT hr;
  63. if (NULL == pvw)
  64. {
  65. hr = E_POINTER;
  66. _JumpError(hr, error, "NULL parm");
  67. }
  68. m_RowId = RowId;
  69. m_Flags = Flags;
  70. m_pvw = pvw;
  71. m_pvw->AddRef();
  72. if (0 != Flags)
  73. {
  74. hr = E_INVALIDARG;
  75. _JumpError(hr, error, "Flags");
  76. }
  77. hr = Reset();
  78. _JumpIfError2(hr, error, "Reset", S_FALSE);
  79. error:
  80. return(hr);
  81. }
  82. STDMETHODIMP
  83. CEnumCERTVIEWEXTENSION::Next(
  84. /* [out, retval] */ LONG *pIndex)
  85. {
  86. HRESULT hr;
  87. DWORD celt;
  88. CERTTRANSBLOB ctbExtensions;
  89. ctbExtensions.pb = NULL;
  90. if (NULL == pIndex)
  91. {
  92. hr = E_POINTER;
  93. _JumpError(hr, error, "NULL parm");
  94. }
  95. *pIndex = -1;
  96. if (m_ieltCurrent + 1 >= m_celtCurrent && !m_fNoMore)
  97. {
  98. hr = ((CCertView *) m_pvw)->EnumAttributesOrExtensions(
  99. m_RowId,
  100. CDBENUM_EXTENSIONS,
  101. NULL == m_aelt?
  102. NULL :
  103. m_aelt[m_ieltCurrent].pwszName,
  104. CEXT_CHUNK,
  105. &celt,
  106. &ctbExtensions);
  107. if (S_FALSE == hr)
  108. {
  109. m_fNoMore = TRUE;
  110. }
  111. else
  112. {
  113. _JumpIfError(hr, error, "EnumAttributesOrExtensions");
  114. }
  115. hr = _SaveExtensions(celt, &ctbExtensions);
  116. _JumpIfError(hr, error, "_SaveExtensions");
  117. m_ieltCurrent = -1;
  118. m_celtCurrent = celt;
  119. }
  120. if (m_ieltCurrent + 1 >= m_celtCurrent)
  121. {
  122. hr = S_FALSE;
  123. goto error;
  124. }
  125. m_ielt++;
  126. m_ieltCurrent++;
  127. *pIndex = m_ielt;
  128. m_fNoCurrentRecord = FALSE;
  129. hr = S_OK;
  130. error:
  131. if (NULL != ctbExtensions.pb)
  132. {
  133. CoTaskMemFree(ctbExtensions.pb);
  134. }
  135. return(_SetErrorInfo(hr, L"CEnumCERTVIEWEXTENSION::Next"));
  136. }
  137. HRESULT
  138. CopyMarshalledString(
  139. IN CERTTRANSBLOB const *pctb,
  140. IN ULONG obwsz,
  141. IN BYTE *pbEnd,
  142. IN BYTE **ppbNext,
  143. OUT WCHAR **ppwszOut)
  144. {
  145. HRESULT hr;
  146. *ppwszOut = NULL;
  147. if (0 != obwsz)
  148. {
  149. WCHAR *pwsz;
  150. WCHAR *pwszEnd;
  151. WCHAR *pwszT;
  152. DWORD cb;
  153. pwsz = (WCHAR *) Add2Ptr(pctb->pb, obwsz);
  154. pwszEnd = &((WCHAR *) pctb->pb)[pctb->cb / sizeof(WCHAR)];
  155. for (pwszT = pwsz; ; pwszT++)
  156. {
  157. if (pwszT >= pwszEnd)
  158. {
  159. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  160. _JumpError(hr, error, "bad marshalled data");
  161. }
  162. if (L'\0' == *pwszT)
  163. {
  164. break;
  165. }
  166. }
  167. cb = (SAFE_SUBTRACT_POINTERS(pwszT, pwsz) + 1) * sizeof(WCHAR);
  168. if (&(*ppbNext)[DWORDROUND(cb)] > pbEnd)
  169. {
  170. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  171. _JumpError(hr, error, "bad marshalled data");
  172. }
  173. CopyMemory(*ppbNext, pwsz, cb);
  174. *ppwszOut = (WCHAR *) *ppbNext;
  175. *ppbNext += DWORDROUND(cb);
  176. }
  177. hr = S_OK;
  178. error:
  179. return(hr);
  180. }
  181. HRESULT
  182. CopyMarshalledBlob(
  183. IN CERTTRANSBLOB const *pctb,
  184. IN DWORD cbValue,
  185. IN ULONG obValue,
  186. IN BYTE *pbEnd,
  187. IN BYTE **ppbNext,
  188. OUT DWORD *pcbOut,
  189. OUT BYTE **ppbOut)
  190. {
  191. HRESULT hr;
  192. *pcbOut = 0;
  193. *ppbOut = NULL;
  194. if (0 != obValue)
  195. {
  196. BYTE *pb;
  197. pb = (BYTE *) Add2Ptr(pctb->pb, obValue);
  198. if (&pb[cbValue] > &pctb->pb[pctb->cb])
  199. {
  200. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  201. _JumpError(hr, error, "bad marshalled data");
  202. }
  203. if (&(*ppbNext)[DWORDROUND(cbValue)] > pbEnd)
  204. {
  205. hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  206. _JumpError(hr, error, "bad marshalled data");
  207. }
  208. CopyMemory(*ppbNext, pb, cbValue);
  209. *pcbOut = cbValue;
  210. *ppbOut = *ppbNext;
  211. *ppbNext += DWORDROUND(cbValue);
  212. }
  213. hr = S_OK;
  214. error:
  215. return(hr);
  216. }
  217. HRESULT
  218. CEnumCERTVIEWEXTENSION::_SaveExtensions(
  219. IN DWORD celt,
  220. IN CERTTRANSBLOB const *pctbExtensions)
  221. {
  222. HRESULT hr;
  223. DWORD cbNew;
  224. CERTDBEXTENSION *peltNew = NULL;
  225. CERTDBEXTENSION *pelt;
  226. CERTTRANSDBEXTENSION *ptelt;
  227. CERTTRANSDBEXTENSION *pteltEnd;
  228. BYTE *pbNext;
  229. BYTE *pbEnd;
  230. if (NULL == pctbExtensions)
  231. {
  232. hr = E_POINTER;
  233. _JumpError(hr, error, "NULL parm");
  234. }
  235. cbNew = pctbExtensions->cb + celt * (sizeof(*pelt) - sizeof(*ptelt));
  236. peltNew = (CERTDBEXTENSION *) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, cbNew);
  237. if (NULL == peltNew)
  238. {
  239. hr = E_OUTOFMEMORY;
  240. _JumpError(hr, error, "LocalAlloc");
  241. }
  242. pteltEnd = &((CERTTRANSDBEXTENSION *) pctbExtensions->pb)[celt];
  243. if ((BYTE *) pteltEnd > &pctbExtensions->pb[pctbExtensions->cb])
  244. {
  245. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  246. _JumpError(hr, error, "bad marshalled data");
  247. }
  248. pelt = peltNew;
  249. pbNext = (BYTE *) &peltNew[celt];
  250. pbEnd = (BYTE *) Add2Ptr(peltNew, cbNew);
  251. for (ptelt = (CERTTRANSDBEXTENSION *) pctbExtensions->pb;
  252. ptelt < pteltEnd;
  253. ptelt++, pelt++)
  254. {
  255. pelt->ExtFlags = ptelt->ExtFlags;
  256. hr = CopyMarshalledString(
  257. pctbExtensions,
  258. ptelt->obwszName,
  259. pbEnd,
  260. &pbNext,
  261. &pelt->pwszName);
  262. _JumpIfError(hr, error, "CopyMarshalledString");
  263. hr = CopyMarshalledBlob(
  264. pctbExtensions,
  265. ptelt->cbValue,
  266. ptelt->obValue,
  267. pbEnd,
  268. &pbNext,
  269. &pelt->cbValue,
  270. &pelt->pbValue);
  271. _JumpIfError(hr, error, "CopyMarshalledBlob");
  272. }
  273. CSASSERT(pbNext == pbEnd);
  274. if (NULL != m_aelt)
  275. {
  276. LocalFree(m_aelt);
  277. }
  278. m_aelt = peltNew;
  279. peltNew = NULL;
  280. hr = S_OK;
  281. error:
  282. if (NULL != peltNew)
  283. {
  284. LocalFree(peltNew);
  285. }
  286. return(hr);
  287. }
  288. HRESULT
  289. CEnumCERTVIEWEXTENSION::_FindExtension(
  290. OUT CERTDBEXTENSION const **ppcde)
  291. {
  292. HRESULT hr;
  293. if (NULL == ppcde)
  294. {
  295. hr = E_POINTER;
  296. _JumpError(hr, error, "NULL parm");
  297. }
  298. if (NULL == m_aelt)
  299. {
  300. hr = E_UNEXPECTED;
  301. _JumpError(hr, error, "NULL m_aelt");
  302. }
  303. if (m_fNoCurrentRecord ||
  304. m_ieltCurrent < 0 ||
  305. m_ieltCurrent >= m_celtCurrent)
  306. {
  307. hr = E_INVALIDARG;
  308. _JumpError(hr, error, "m_fNoCurrentRecord || m_ieltCurrent");
  309. }
  310. *ppcde = &m_aelt[m_ieltCurrent];
  311. hr = S_OK;
  312. error:
  313. return(hr);
  314. }
  315. STDMETHODIMP
  316. CEnumCERTVIEWEXTENSION::GetName(
  317. /* [out, retval] */ BSTR *pstrOut)
  318. {
  319. HRESULT hr;
  320. CERTDBEXTENSION const *pcde;
  321. if (NULL == pstrOut)
  322. {
  323. hr = E_POINTER;
  324. _JumpError(hr, error, "NULL parm");
  325. }
  326. hr = _FindExtension(&pcde);
  327. _JumpIfError(hr, error, "_FindExtension");
  328. if (!ConvertWszToBstr(pstrOut, pcde->pwszName, -1))
  329. {
  330. hr = E_OUTOFMEMORY;
  331. _JumpError(hr, error, "ConvertWszToBstr");
  332. }
  333. error:
  334. return(_SetErrorInfo(hr, L"CEnumCERTVIEWEXTENSION::GetName"));
  335. }
  336. STDMETHODIMP
  337. CEnumCERTVIEWEXTENSION::GetFlags(
  338. /* [out, retval] */ LONG *pFlags)
  339. {
  340. HRESULT hr;
  341. CERTDBEXTENSION const *pcde;
  342. if (NULL == pFlags)
  343. {
  344. hr = E_POINTER;
  345. _JumpError(hr, error, "NULL parm");
  346. }
  347. hr = _FindExtension(&pcde);
  348. _JumpIfError(hr, error, "_FindExtension");
  349. *pFlags = pcde->ExtFlags;
  350. error:
  351. return(_SetErrorInfo(hr, L"CEnumCERTVIEWEXTENSION::GetFlags"));
  352. }
  353. STDMETHODIMP
  354. CEnumCERTVIEWEXTENSION::GetValue(
  355. /* [in] */ LONG Type,
  356. /* [in] */ LONG Flags,
  357. /* [out, retval] */ VARIANT *pvarValue)
  358. {
  359. HRESULT hr;
  360. CERTDBEXTENSION const *pcde;
  361. BYTE *pballoc = NULL;
  362. BYTE *pbValue;
  363. DWORD cbValue;
  364. if (NULL == pvarValue)
  365. {
  366. hr = E_POINTER;
  367. _JumpError(hr, error, "NULL parm");
  368. }
  369. VariantInit(pvarValue);
  370. pvarValue->bstrVal = NULL;
  371. CSASSERT(CV_OUT_BASE64HEADER == CRYPT_STRING_BASE64HEADER);
  372. CSASSERT(CV_OUT_BASE64 == CRYPT_STRING_BASE64);
  373. CSASSERT(CV_OUT_BINARY == CRYPT_STRING_BINARY);
  374. CSASSERT(CV_OUT_BASE64REQUESTHEADER == CRYPT_STRING_BASE64REQUESTHEADER);
  375. CSASSERT(CV_OUT_HEX == CRYPT_STRING_HEX);
  376. CSASSERT(CV_OUT_HEXADDR == CRYPT_STRING_HEXADDR);
  377. CSASSERT(CV_OUT_BASE64X509CRLHEADER == CRYPT_STRING_BASE64X509CRLHEADER);
  378. CSASSERT(CV_OUT_HEXASCII == CRYPT_STRING_HEXASCII);
  379. CSASSERT(CV_OUT_HEXASCIIADDR == CRYPT_STRING_HEXASCIIADDR);
  380. switch (Flags)
  381. {
  382. case CV_OUT_BASE64HEADER:
  383. case CV_OUT_BASE64:
  384. case CV_OUT_BINARY:
  385. case CV_OUT_BASE64REQUESTHEADER:
  386. case CV_OUT_HEX:
  387. case CV_OUT_HEXASCII:
  388. case CV_OUT_BASE64X509CRLHEADER:
  389. case CV_OUT_HEXADDR:
  390. case CV_OUT_HEXASCIIADDR:
  391. break;
  392. default:
  393. hr = E_INVALIDARG;
  394. _JumpError(hr, error, "Flags");
  395. }
  396. hr = _FindExtension(&pcde);
  397. _JumpIfError(hr, error, "_FindExtension");
  398. if (0 == pcde->cbValue || NULL == pcde->pbValue)
  399. {
  400. hr = CERTSRV_E_PROPERTY_EMPTY;
  401. _JumpError(hr, error, "NULL value");
  402. }
  403. if (PROPTYPE_BINARY == (PROPTYPE_MASK & Type))
  404. {
  405. pbValue = pcde->pbValue;
  406. cbValue = pcde->cbValue;
  407. }
  408. else
  409. {
  410. hr = myDecodeExtension(
  411. Type,
  412. pcde->pbValue,
  413. pcde->cbValue,
  414. &pballoc,
  415. &cbValue);
  416. _JumpIfError(hr, error, "myDecodeExtension");
  417. pbValue = pballoc;
  418. }
  419. if (CV_OUT_BINARY == Flags)
  420. {
  421. switch (PROPTYPE_MASK & Type)
  422. {
  423. case PROPTYPE_LONG:
  424. CSASSERT(sizeof(LONG) == cbValue);
  425. pvarValue->lVal = *(LONG *) pbValue;
  426. pvarValue->vt = VT_I4;
  427. break;
  428. case PROPTYPE_DATE:
  429. CSASSERT(sizeof(FILETIME) == cbValue);
  430. hr = myFileTimeToDate(
  431. (FILETIME const *) pbValue,
  432. &pvarValue->date);
  433. _JumpIfError(hr, error, "myFileTimeToDate");
  434. pvarValue->vt = VT_DATE;
  435. break;
  436. case PROPTYPE_STRING:
  437. case PROPTYPE_BINARY:
  438. if (!ConvertWszToBstr(
  439. &pvarValue->bstrVal,
  440. (WCHAR const *) pbValue,
  441. cbValue))
  442. {
  443. hr = E_OUTOFMEMORY;
  444. _JumpError(hr, error, "ConvertWszToBstr");
  445. }
  446. pvarValue->vt = VT_BSTR;
  447. break;
  448. default:
  449. hr = E_INVALIDARG;
  450. _JumpError(hr, error, "Type");
  451. }
  452. }
  453. else
  454. {
  455. hr = EncodeCertString(
  456. pbValue,
  457. cbValue,
  458. Flags,
  459. &pvarValue->bstrVal);
  460. _JumpIfError(hr, error, "EncodeCertString");
  461. pvarValue->vt = VT_BSTR;
  462. }
  463. error:
  464. if (NULL != pballoc)
  465. {
  466. LocalFree(pballoc);
  467. }
  468. return(_SetErrorInfo(hr, L"CEnumCERTVIEWEXTENSION::GetValue"));
  469. }
  470. STDMETHODIMP
  471. CEnumCERTVIEWEXTENSION::Skip(
  472. /* [in] */ LONG celt)
  473. {
  474. HRESULT hr;
  475. LONG ieltnew = m_ielt + celt;
  476. if (-1 > ieltnew)
  477. {
  478. hr = E_INVALIDARG;
  479. _JumpError(hr, error, "Skip back to before start");
  480. }
  481. m_ielt = ieltnew;
  482. m_ieltCurrent += celt;
  483. m_fNoCurrentRecord = TRUE;
  484. hr = S_OK;
  485. error:
  486. return(_SetErrorInfo(hr, L"CEnumCERTVIEWEXTENSION::Skip"));
  487. }
  488. STDMETHODIMP
  489. CEnumCERTVIEWEXTENSION::Reset(VOID)
  490. {
  491. HRESULT hr;
  492. DWORD celt;
  493. CERTTRANSBLOB ctbExtensions;
  494. ctbExtensions.pb = NULL;
  495. m_fNoMore = FALSE;
  496. hr = ((CCertView *) m_pvw)->EnumAttributesOrExtensions(
  497. m_RowId,
  498. CDBENUM_EXTENSIONS,
  499. NULL,
  500. CEXT_CHUNK,
  501. &celt,
  502. &ctbExtensions);
  503. if (S_FALSE == hr)
  504. {
  505. m_fNoMore = TRUE;
  506. }
  507. else
  508. {
  509. _JumpIfError(hr, error, "EnumAttributesOrExtensions");
  510. }
  511. hr = _SaveExtensions(celt, &ctbExtensions);
  512. _JumpIfError(hr, error, "_SaveExtensions");
  513. m_ielt = -1;
  514. m_ieltCurrent = -1;
  515. m_celtCurrent = celt;
  516. m_fNoCurrentRecord = TRUE;
  517. error:
  518. if (NULL != ctbExtensions.pb)
  519. {
  520. CoTaskMemFree(ctbExtensions.pb);
  521. }
  522. return(_SetErrorInfo(hr, L"CEnumCERTVIEWEXTENSION::Reset"));
  523. }
  524. STDMETHODIMP
  525. CEnumCERTVIEWEXTENSION::Clone(
  526. /* [out] */ IEnumCERTVIEWEXTENSION **ppenum)
  527. {
  528. HRESULT hr;
  529. IEnumCERTVIEWEXTENSION *penum = NULL;
  530. if (NULL == ppenum)
  531. {
  532. hr = E_POINTER;
  533. _JumpError(hr, error, "NULL parm");
  534. }
  535. *ppenum = NULL;
  536. penum = new CEnumCERTVIEWEXTENSION;
  537. if (NULL == penum)
  538. {
  539. hr = E_OUTOFMEMORY;
  540. _JumpError(hr, error, "new CEnumCERTVIEWEXTENSION");
  541. }
  542. hr = ((CEnumCERTVIEWEXTENSION *) penum)->Open(m_RowId, m_Flags, m_pvw);
  543. _JumpIfError(hr, error, "Open");
  544. if (-1 != m_ielt)
  545. {
  546. hr = penum->Skip(m_ielt);
  547. _JumpIfError(hr, error, "Skip");
  548. if (!m_fNoCurrentRecord)
  549. {
  550. LONG Index;
  551. hr = penum->Next(&Index);
  552. _JumpIfError(hr, error, "Next");
  553. CSASSERT(Index == m_ielt);
  554. }
  555. }
  556. *ppenum = penum;
  557. penum = NULL;
  558. hr = S_OK;
  559. error:
  560. if (NULL != penum)
  561. {
  562. penum->Release();
  563. }
  564. return(_SetErrorInfo(hr, L"CEnumCERTVIEWEXTENSION::Clone"));
  565. }
  566. HRESULT
  567. CEnumCERTVIEWEXTENSION::_SetErrorInfo(
  568. IN HRESULT hrError,
  569. IN WCHAR const *pwszDescription)
  570. {
  571. CSASSERT(FAILED(hrError) || S_OK == hrError || S_FALSE == hrError);
  572. if (FAILED(hrError))
  573. {
  574. HRESULT hr;
  575. hr = DispatchSetErrorInfo(
  576. hrError,
  577. pwszDescription,
  578. wszCLASS_CERTVIEW L".CEnumCERTVIEWEXTENSION",
  579. &IID_IEnumCERTVIEWEXTENSION);
  580. CSASSERT(hr == hrError);
  581. }
  582. return(hrError);
  583. }
  584. #if 1
  585. // IUnknown implementation
  586. STDMETHODIMP
  587. CEnumCERTVIEWEXTENSION::QueryInterface(
  588. const IID& iid,
  589. void **ppv)
  590. {
  591. HRESULT hr;
  592. if (NULL == ppv)
  593. {
  594. hr = E_POINTER;
  595. _JumpError(hr, error, "NULL parm");
  596. }
  597. if (iid == IID_IUnknown)
  598. {
  599. *ppv = static_cast<IEnumCERTVIEWEXTENSION *>(this);
  600. }
  601. else if (iid == IID_IDispatch)
  602. {
  603. *ppv = static_cast<IEnumCERTVIEWEXTENSION *>(this);
  604. }
  605. else if (iid == IID_IEnumCERTVIEWEXTENSION)
  606. {
  607. *ppv = static_cast<IEnumCERTVIEWEXTENSION *>(this);
  608. }
  609. else
  610. {
  611. *ppv = NULL;
  612. hr = E_NOINTERFACE;
  613. _JumpError(hr, error, "IID");
  614. }
  615. reinterpret_cast<IUnknown *>(*ppv)->AddRef();
  616. hr = S_OK;
  617. error:
  618. return(hr);
  619. }
  620. ULONG STDMETHODCALLTYPE
  621. CEnumCERTVIEWEXTENSION::AddRef()
  622. {
  623. return(InterlockedIncrement(&m_cRef));
  624. }
  625. ULONG STDMETHODCALLTYPE
  626. CEnumCERTVIEWEXTENSION::Release()
  627. {
  628. ULONG cRef = InterlockedDecrement(&m_cRef);
  629. if (0 == cRef)
  630. {
  631. delete this;
  632. }
  633. return(cRef);
  634. }
  635. #endif