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.

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