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.

810 lines
17 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 1995 - 1999
  6. //
  7. // File: csdisp.cpp
  8. //
  9. // Contents: IDispatch helper functions
  10. //
  11. // History: 09-Dec-96 vich created
  12. //
  13. //--------------------------------------------------------------------------
  14. #include <pch.cpp>
  15. #pragma hdrstop
  16. #include <stdlib.h>
  17. #include "csdisp.h"
  18. #ifndef DBG_DISPATCH
  19. # define DBG_DISPATCH 0
  20. #endif
  21. TCHAR szRegKeyClsidValue[] = TEXT("");
  22. HRESULT
  23. DispatchGetReturnValue(
  24. VARIANT *pvar,
  25. IN LONG Type,
  26. OUT VOID *pretval)
  27. {
  28. HRESULT hr = S_OK;
  29. if (VT_EMPTY == pvar->vt)
  30. {
  31. hr = CERTSRV_E_PROPERTY_EMPTY;
  32. _JumpError2(hr, error, "VT_EMPTY", hr);
  33. }
  34. if (Type != pvar->vt)
  35. {
  36. DBGPRINT((
  37. DBG_SS_CERTLIB,
  38. "pvar->vt=%x, expected %x\n",
  39. pvar->vt,
  40. Type));
  41. hr = TYPE_E_WRONGTYPEKIND;
  42. _JumpError(hr, error, "pvar->vt != Type");
  43. }
  44. switch (Type)
  45. {
  46. case VT_I4:
  47. *(LONG *) pretval = pvar->lVal;
  48. break;
  49. case VT_DATE:
  50. *(DATE *) pretval = pvar->date;
  51. break;
  52. case VT_BSTR:
  53. *(BSTR *) pretval = pvar->bstrVal;
  54. pvar->vt = VT_EMPTY;
  55. break;
  56. case VT_DISPATCH:
  57. *(IDispatch **) pretval = pvar->pdispVal;
  58. pvar->vt = VT_EMPTY;
  59. break;
  60. default:
  61. hr = E_INVALIDARG;
  62. goto error;
  63. }
  64. error:
  65. return(hr);
  66. }
  67. HRESULT
  68. DispatchSetErrorInfoSub(
  69. IN HRESULT hrError,
  70. OPTIONAL IN WCHAR const *pwszIDispatchMethod,
  71. OPTIONAL IN WCHAR const *pwszDescription,
  72. OPTIONAL IN WCHAR const *pwszSource,
  73. OPTIONAL IN IID const *piid,
  74. OPTIONAL IN WCHAR const *pwszHelpFile,
  75. IN DWORD dwHelpFileContext)
  76. {
  77. HRESULT hr;
  78. WCHAR const *pwszError = NULL;
  79. ICreateErrorInfo *pCreateErrorInfo = NULL;
  80. IErrorInfo *pErrorInfo = NULL;
  81. #ifdef DBG_CERTSRV_DEBUG_PRINT
  82. if (NULL != pwszIDispatchMethod || DbgIsSSActive(DBG_SS_CERTLIBI))
  83. #else
  84. if (NULL != pwszIDispatchMethod)
  85. #endif
  86. {
  87. pwszError = myGetErrorMessageText(hrError, TRUE);
  88. if (NULL != pwszIDispatchMethod)
  89. {
  90. CONSOLEPRINT1((
  91. MAXDWORD,
  92. "IDispatch->Invoke(%ws) Exception:\n",
  93. pwszIDispatchMethod));
  94. }
  95. else
  96. {
  97. CONSOLEPRINT0((MAXDWORD, "COM Error:\n"));
  98. }
  99. CONSOLEPRINT5((
  100. MAXDWORD,
  101. " Source=%ws\n Description=%ws\n HelpFile=%ws[%x]\n %ws\n",
  102. pwszSource,
  103. pwszDescription,
  104. pwszHelpFile,
  105. dwHelpFileContext,
  106. pwszError));
  107. }
  108. hr = CreateErrorInfo(&pCreateErrorInfo);
  109. _JumpIfError(hr, error, "CreateErrorInfo");
  110. if (NULL != piid)
  111. {
  112. hr = pCreateErrorInfo->SetGUID(*piid);
  113. _PrintIfError(hr, "SetGUID");
  114. }
  115. if (NULL != pwszSource)
  116. {
  117. hr = pCreateErrorInfo->SetSource(const_cast<WCHAR *>(pwszSource));
  118. _PrintIfError(hr, "SetSource");
  119. }
  120. if (NULL != pwszDescription)
  121. {
  122. hr = pCreateErrorInfo->SetDescription(
  123. const_cast<WCHAR *>(pwszDescription));
  124. _PrintIfError(hr, "SetDescription");
  125. }
  126. if (NULL != pwszHelpFile)
  127. {
  128. hr = pCreateErrorInfo->SetHelpFile(const_cast<WCHAR *>(pwszHelpFile));
  129. _PrintIfError(hr, "SetHelpFile");
  130. hr = pCreateErrorInfo->SetHelpContext(dwHelpFileContext);
  131. _PrintIfError(hr, "SetHelpContext");
  132. }
  133. hr = pCreateErrorInfo->QueryInterface(
  134. IID_IErrorInfo,
  135. (VOID **) &pErrorInfo);
  136. _JumpIfError(hr, error, "QueryInterface");
  137. SetErrorInfo(0, pErrorInfo);
  138. hr = S_OK;
  139. error:
  140. if (NULL != pwszError)
  141. {
  142. LocalFree(const_cast<WCHAR *>(pwszError));
  143. }
  144. if (NULL != pErrorInfo)
  145. {
  146. pErrorInfo->Release();
  147. }
  148. if (NULL != pCreateErrorInfo)
  149. {
  150. pCreateErrorInfo->Release();
  151. }
  152. return(hr);
  153. }
  154. HRESULT
  155. DispatchInvoke(
  156. IN DISPATCHINTERFACE *pDispatchInterface,
  157. IN LONG MethodIndex,
  158. IN DWORD cvar,
  159. IN VARIANT avar[],
  160. IN LONG Type,
  161. OUT VOID *pretval)
  162. {
  163. HRESULT hr;
  164. DISPATCHTABLE const *pdt;
  165. EXCEPINFO excepinfo;
  166. VARIANT varResult;
  167. DISPPARAMS parms;
  168. unsigned iArgErr;
  169. DISPID *adispid;
  170. VariantInit(&varResult);
  171. CSASSERT(NULL != pDispatchInterface->pDispatchTable);
  172. CSASSERT((DWORD) MethodIndex < pDispatchInterface->m_cDispatchTable);
  173. pdt = &pDispatchInterface->pDispatchTable[MethodIndex];
  174. adispid = &pDispatchInterface->m_adispid[pdt->idispid];
  175. CSASSERT(NULL != pDispatchInterface->m_adispid);
  176. CSASSERT(pdt->idispid + pdt->cdispid <= pDispatchInterface->m_cdispid);
  177. parms.rgvarg = avar;
  178. parms.rgdispidNamedArgs = &adispid[1];
  179. parms.cArgs = pdt->cdispid - 1;
  180. parms.cNamedArgs = parms.cArgs;
  181. if (parms.cArgs != cvar)
  182. {
  183. CSASSERT(parms.cArgs == cvar);
  184. hr = HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR);
  185. _JumpError(hr, error, "cvar");
  186. }
  187. CSASSERT(NULL != pDispatchInterface->pDispatch);
  188. hr = pDispatchInterface->pDispatch->Invoke(
  189. adispid[0],
  190. IID_NULL,
  191. LOCALE_SYSTEM_DEFAULT,
  192. DISPATCH_METHOD,
  193. &parms,
  194. &varResult,
  195. &excepinfo,
  196. &iArgErr);
  197. if (S_OK != hr)
  198. {
  199. _PrintErrorStr(hr, "Invoke", pdt->apszNames[0]);
  200. if (DISP_E_EXCEPTION == hr)
  201. {
  202. HRESULT hr2;
  203. IID const *piid;
  204. if (FAILED(excepinfo.scode))
  205. {
  206. hr = excepinfo.scode;
  207. }
  208. hr2 = DispatchSetErrorInfoSub(
  209. hr,
  210. pdt->apszNames[0],
  211. excepinfo.bstrDescription,
  212. excepinfo.bstrSource,
  213. pDispatchInterface->GetIID(),
  214. excepinfo.bstrHelpFile,
  215. excepinfo.dwHelpContext);
  216. _PrintIfError(hr2, "DispatchSetErrorInfoSub");
  217. }
  218. goto error;
  219. }
  220. if (CLSCTX_INPROC_SERVER != pDispatchInterface->m_ClassContext)
  221. {
  222. myRegisterMemAlloc(&varResult, 0, CSM_VARIANT);
  223. }
  224. if (NULL != pretval)
  225. {
  226. hr = DispatchGetReturnValue(&varResult, Type, pretval);
  227. _JumpIfErrorStr2(
  228. hr,
  229. error,
  230. "DispatchGetReturnValue",
  231. pdt->apszNames[0],
  232. CERTSRV_E_PROPERTY_EMPTY);
  233. }
  234. error:
  235. VariantClear(&varResult);
  236. return(hr);
  237. }
  238. HRESULT
  239. DispatchGetIds(
  240. IN IDispatch *pDispatch,
  241. IN DWORD cDispatchTable,
  242. IN OUT DISPATCHTABLE *pDispatchTable,
  243. IN OUT DISPATCHINTERFACE *pDispatchInterface)
  244. {
  245. HRESULT hr = S_OK;
  246. DISPATCHTABLE *pdt;
  247. DISPATCHTABLE *pdtEnd;
  248. DISPID *adispid = NULL;
  249. DWORD idispid;
  250. pdtEnd = &pDispatchTable[cDispatchTable];
  251. pDispatchInterface->m_cdispid = 0;
  252. for (pdt = pDispatchTable; pdt < pdtEnd; pdt++)
  253. {
  254. if (0 == pdt->idispid)
  255. {
  256. pdt->idispid = pDispatchInterface->m_cdispid;
  257. }
  258. CSASSERT(pdt->idispid == pDispatchInterface->m_cdispid);
  259. pDispatchInterface->m_cdispid += pdt->cdispid;
  260. }
  261. adispid = (DISPID *) LocalAlloc(
  262. LMEM_FIXED,
  263. pDispatchInterface->m_cdispid * sizeof(adispid[0]));
  264. if (NULL == adispid)
  265. {
  266. hr = E_OUTOFMEMORY;
  267. _JumpError(hr, error, "LocalAlloc");
  268. }
  269. idispid = 0;
  270. for (pdt = pDispatchTable; pdt < pdtEnd; pdt++)
  271. {
  272. CSASSERT(idispid + pdt->cdispid <= pDispatchInterface->m_cdispid);
  273. hr = pDispatch->GetIDsOfNames(
  274. IID_NULL,
  275. pdt->apszNames,
  276. pdt->cdispid,
  277. LOCALE_SYSTEM_DEFAULT,
  278. &adispid[idispid]);
  279. #if DBG_CERTSRV
  280. if (S_OK != hr || DBG_DISPATCH)
  281. {
  282. DWORD i;
  283. DBGPRINT((
  284. MAXDWORD,
  285. "GetIDsOfNames(%ws) --> %x, dispid=%x" szLPAREN,
  286. pdt->apszNames[0],
  287. hr,
  288. adispid[idispid]));
  289. for (i = 1; i < pdt->cdispid; i++)
  290. {
  291. DBGPRINT((
  292. MAXDWORD,
  293. "%ws%x",
  294. i == 1? L"" : L", ",
  295. adispid[idispid + i]));
  296. }
  297. DBGPRINT((MAXDWORD, szRPAREN "\n"));
  298. }
  299. #endif
  300. _JumpIfError(hr, error, "GetIDsOfNames");
  301. idispid += pdt->cdispid;
  302. }
  303. pDispatchInterface->m_cDispatchTable = cDispatchTable;
  304. pDispatchInterface->pDispatchTable = pDispatchTable;
  305. pDispatchInterface->m_adispid = adispid;
  306. adispid = NULL;
  307. error:
  308. if (NULL != adispid)
  309. {
  310. LocalFree(adispid);
  311. }
  312. return(hr);
  313. }
  314. HRESULT
  315. DispatchSetup(
  316. IN DWORD Flags,
  317. IN DWORD ClassContext,
  318. OPTIONAL IN TCHAR const *pszProgID, // for IDispatch
  319. OPTIONAL IN CLSID const *pclsid, // for COM
  320. OPTIONAL IN IID const *piid, // for COM
  321. IN DWORD cDispatchTable, // for IDispatch
  322. IN OUT DISPATCHTABLE *pDispatchTable,
  323. IN OUT DISPATCHINTERFACE *pDispatchInterface)
  324. {
  325. HRESULT hr;
  326. CLSID clsid;
  327. pDispatchInterface->SetIID(piid);
  328. while (TRUE)
  329. {
  330. pDispatchInterface->pDispatch = NULL;
  331. pDispatchInterface->pUnknown = NULL;
  332. pDispatchInterface->m_adispid = NULL;
  333. CSASSERT(NULL != pszProgID || DISPSETUP_COM == Flags);
  334. CSASSERT(NULL != pclsid || DISPSETUP_IDISPATCH == Flags);
  335. CSASSERT(NULL != piid || DISPSETUP_IDISPATCH == Flags);
  336. if (DISPSETUP_IDISPATCH == Flags)
  337. {
  338. // use win32 version, not our own hack
  339. hr = CLSIDFromProgID(pszProgID, &clsid);
  340. _JumpIfError2(
  341. hr,
  342. error,
  343. "ClassNameToCLSID",
  344. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  345. pclsid = &clsid;
  346. piid = &IID_IDispatch;
  347. }
  348. hr = CoCreateInstance(
  349. *pclsid,
  350. NULL, // pUnkOuter
  351. ClassContext,
  352. *piid,
  353. DISPSETUP_IDISPATCH == Flags?
  354. (VOID **) &pDispatchInterface->pDispatch :
  355. (VOID **) &pDispatchInterface->pUnknown);
  356. #if DBG_DISPATCH
  357. printf("CoCreateInstance(%x) --> %x\n", Flags, hr);
  358. #endif
  359. if (S_OK != hr)
  360. {
  361. if (DISPSETUP_COMFIRST != Flags)
  362. {
  363. _JumpError2(hr, error, "CoCreateInstance", E_NOINTERFACE);
  364. }
  365. Flags = DISPSETUP_IDISPATCH;
  366. continue;
  367. }
  368. pDispatchInterface->m_ClassContext = ClassContext;
  369. break;
  370. }
  371. if (DISPSETUP_IDISPATCH == Flags)
  372. {
  373. hr = DispatchGetIds(
  374. pDispatchInterface->pDispatch,
  375. cDispatchTable,
  376. pDispatchTable,
  377. pDispatchInterface);
  378. if (S_OK != hr)
  379. {
  380. DispatchRelease(pDispatchInterface);
  381. _JumpError(hr, error, "DispatchGetIds");
  382. }
  383. }
  384. error:
  385. return(hr);
  386. }
  387. HRESULT
  388. DispatchSetup2(
  389. IN DWORD Flags,
  390. IN DWORD ClassContext,
  391. IN WCHAR const *pwszClass, // wszRegKeyAdminClsid
  392. IN CLSID const *pclsid,
  393. IN DWORD cver,
  394. IN IID const * const *ppiid, // cver elements
  395. IN DWORD const *pcDispatch, // cver elements
  396. IN OUT DISPATCHTABLE *pDispatchTable,
  397. IN OUT DISPATCHINTERFACE *pDispatchInterface)
  398. {
  399. HRESULT hr = E_INVALIDARG;
  400. CSASSERT(0 < cver);
  401. for ( ; 0 < cver; cver--, ppiid++, pcDispatch++)
  402. {
  403. hr = DispatchSetup(
  404. Flags,
  405. ClassContext,
  406. pwszClass,
  407. pclsid,
  408. *ppiid,
  409. *pcDispatch,
  410. pDispatchTable,
  411. pDispatchInterface);
  412. if (S_OK == hr)
  413. {
  414. pDispatchInterface->m_dwVersion = cver;
  415. pDispatchInterface->pDispatchTable = pDispatchTable;
  416. break;
  417. }
  418. if (1 == cver || (E_NOINTERFACE != hr && DISP_E_UNKNOWNNAME != hr))
  419. {
  420. _JumpErrorStr(hr, error, "DispatchSetup", pwszClass);
  421. }
  422. _PrintErrorStr2(hr, "DispatchSetup", pwszClass, hr);
  423. }
  424. error:
  425. return(hr);
  426. }
  427. VOID
  428. DispatchRelease(
  429. IN OUT DISPATCHINTERFACE *pDispatchInterface)
  430. {
  431. if (NULL != pDispatchInterface->pDispatch)
  432. {
  433. pDispatchInterface->pDispatch->Release();
  434. pDispatchInterface->pDispatch = NULL;
  435. }
  436. if (NULL != pDispatchInterface->pUnknown)
  437. {
  438. pDispatchInterface->pUnknown->Release();
  439. pDispatchInterface->pUnknown = NULL;
  440. }
  441. if (NULL != pDispatchInterface->m_adispid)
  442. {
  443. LocalFree(pDispatchInterface->m_adispid);
  444. pDispatchInterface->m_adispid = NULL;
  445. }
  446. }
  447. BOOL
  448. myConvertWszToBstr(
  449. OUT BSTR *pbstr,
  450. IN WCHAR const *pwc,
  451. IN LONG cb)
  452. {
  453. HRESULT hr;
  454. BSTR bstr;
  455. do
  456. {
  457. bstr = NULL;
  458. if (NULL != pwc)
  459. {
  460. if (-1 == cb)
  461. {
  462. cb = wcslen(pwc) * sizeof(WCHAR);
  463. }
  464. bstr = SysAllocStringByteLen((char const *) pwc, cb);
  465. if (NULL == bstr)
  466. {
  467. hr = E_OUTOFMEMORY;
  468. break;
  469. }
  470. }
  471. if (NULL != *pbstr)
  472. {
  473. SysFreeString(*pbstr);
  474. }
  475. *pbstr = bstr;
  476. hr = S_OK;
  477. } while (FALSE);
  478. if (S_OK != hr)
  479. {
  480. SetLastError(hr);
  481. }
  482. return(S_OK == hr);
  483. }
  484. BOOL
  485. myConvertSzToBstr(
  486. OUT BSTR *pbstr,
  487. IN CHAR const *pch,
  488. IN LONG cch)
  489. {
  490. HRESULT hr;
  491. BSTR bstr = NULL;
  492. LONG cwc = 0;
  493. if (-1 == cch)
  494. {
  495. cch = strlen(pch);
  496. }
  497. CSASSERT(0 != cch);
  498. while (TRUE)
  499. {
  500. cwc = MultiByteToWideChar(GetACP(), 0, pch, cch, bstr, cwc);
  501. if (0 >= cwc)
  502. {
  503. hr = myHLastError();
  504. _PrintError(hr, "MultiByteToWideChar");
  505. if (NULL != bstr)
  506. {
  507. SysFreeString(bstr);
  508. }
  509. break;
  510. }
  511. if (NULL != bstr)
  512. {
  513. bstr[cwc] = L'\0';
  514. if (NULL != *pbstr)
  515. {
  516. SysFreeString(*pbstr);
  517. }
  518. *pbstr = bstr;
  519. hr = S_OK;
  520. break;
  521. }
  522. bstr = SysAllocStringLen(NULL, cwc);
  523. if (NULL == bstr)
  524. {
  525. hr = E_OUTOFMEMORY;
  526. break;
  527. }
  528. }
  529. if (S_OK != hr)
  530. {
  531. SetLastError(hr);
  532. }
  533. return(S_OK == hr);
  534. }
  535. HRESULT
  536. DecodeCertString(
  537. IN BSTR const bstrIn,
  538. IN DWORD Flags,
  539. OUT BYTE **ppbOut,
  540. OUT DWORD *pcbOut)
  541. {
  542. HRESULT hr;
  543. DWORD dwSize;
  544. *ppbOut = NULL;
  545. CSASSERT(CR_IN_BASE64HEADER == CRYPT_STRING_BASE64HEADER);
  546. CSASSERT(CR_IN_BASE64 == CRYPT_STRING_BASE64);
  547. CSASSERT(CR_IN_BINARY == CRYPT_STRING_BINARY);
  548. switch (Flags)
  549. {
  550. case CRYPT_STRING_BASE64HEADER:
  551. case CRYPT_STRING_BASE64:
  552. case CRYPT_STRING_BASE64REQUESTHEADER:
  553. case CRYPT_STRING_HEX:
  554. case CRYPT_STRING_HEXASCII:
  555. case CRYPT_STRING_BASE64_ANY:
  556. case CRYPT_STRING_HEX_ANY:
  557. case CRYPT_STRING_BASE64X509CRLHEADER:
  558. case CRYPT_STRING_HEXADDR:
  559. case CRYPT_STRING_HEXASCIIADDR:
  560. CSASSERT(sizeof(WCHAR) * wcslen(bstrIn) == SysStringByteLen(bstrIn));
  561. // FALLTHROUGH
  562. case CRYPT_STRING_ANY:
  563. dwSize = (SysStringByteLen(bstrIn) + sizeof(WCHAR) - 1) / sizeof(WCHAR);
  564. break;
  565. case CRYPT_STRING_BINARY:
  566. dwSize = SysStringByteLen(bstrIn);
  567. break;
  568. default:
  569. hr = E_INVALIDARG;
  570. _JumpError(hr, error, "Flags");
  571. }
  572. hr = myCryptStringToBinary(
  573. bstrIn,
  574. dwSize,
  575. Flags,
  576. ppbOut,
  577. pcbOut,
  578. NULL,
  579. NULL);
  580. _JumpIfError(hr, error, "myCryptStringToBinary");
  581. if (CRYPT_STRING_ANY == Flags &&
  582. (SysStringByteLen(bstrIn) & (sizeof(WCHAR) - 1)))
  583. {
  584. (*pcbOut)--;
  585. CSASSERT(SysStringByteLen(bstrIn) == *pcbOut);
  586. }
  587. hr = S_OK;
  588. error:
  589. return(hr);
  590. }
  591. HRESULT
  592. EncodeCertString(
  593. IN BYTE const *pbIn,
  594. IN DWORD cbIn,
  595. IN DWORD Flags,
  596. OUT BSTR *pbstrOut)
  597. {
  598. HRESULT hr = E_INVALIDARG;
  599. WCHAR *pwcCert = NULL;
  600. DWORD cbCert;
  601. BSTR strCert = NULL;
  602. CSASSERT(CR_OUT_BASE64HEADER == CRYPT_STRING_BASE64HEADER);
  603. CSASSERT(CR_OUT_BASE64 == CRYPT_STRING_BASE64);
  604. CSASSERT(CR_OUT_BINARY == CRYPT_STRING_BINARY);
  605. //CSASSERT(CR_OUT_BASE64REQUESTHEADER == CRYPT_STRING_BASE64REQUESTHEADER);
  606. //CSASSERT(CR_OUT_HEX == CRYPT_STRING_HEX);
  607. CSASSERT(CV_OUT_BASE64HEADER == CRYPT_STRING_BASE64HEADER);
  608. CSASSERT(CV_OUT_BASE64 == CRYPT_STRING_BASE64);
  609. CSASSERT(CV_OUT_BINARY == CRYPT_STRING_BINARY);
  610. CSASSERT(CV_OUT_BASE64REQUESTHEADER == CRYPT_STRING_BASE64REQUESTHEADER);
  611. CSASSERT(CV_OUT_HEX == CRYPT_STRING_HEX);
  612. CSASSERT(CV_OUT_HEXASCII == CRYPT_STRING_HEXASCII);
  613. CSASSERT(CV_OUT_BASE64X509CRLHEADER == CRYPT_STRING_BASE64X509CRLHEADER);
  614. CSASSERT(CV_OUT_HEXADDR == CRYPT_STRING_HEXADDR);
  615. CSASSERT(CV_OUT_HEXASCIIADDR == CRYPT_STRING_HEXASCIIADDR);
  616. if (NULL == pbIn || (~CR_OUT_ENCODEMASK & Flags))
  617. {
  618. goto error;
  619. }
  620. switch (CR_OUT_ENCODEMASK & Flags)
  621. {
  622. case CRYPT_STRING_BASE64HEADER:
  623. case CRYPT_STRING_BASE64:
  624. case CRYPT_STRING_BASE64REQUESTHEADER:
  625. case CRYPT_STRING_HEX:
  626. case CRYPT_STRING_HEXASCII:
  627. case CRYPT_STRING_BASE64X509CRLHEADER:
  628. case CRYPT_STRING_HEXADDR:
  629. case CRYPT_STRING_HEXASCIIADDR:
  630. hr = myCryptBinaryToString(
  631. pbIn,
  632. cbIn,
  633. CR_OUT_ENCODEMASK & Flags,
  634. &pwcCert);
  635. _JumpIfError(hr, error, "myCryptBinaryToString");
  636. cbCert = sizeof(WCHAR) * wcslen(pwcCert);
  637. break;
  638. case CRYPT_STRING_BINARY:
  639. pwcCert = (WCHAR *) pbIn;
  640. cbCert = cbIn;
  641. hr = S_OK;
  642. break;
  643. default:
  644. goto error;
  645. }
  646. if (!ConvertWszToBstr(pbstrOut, pwcCert, cbCert))
  647. {
  648. hr = E_OUTOFMEMORY;
  649. }
  650. hr = S_OK;
  651. error:
  652. if (NULL != pwcCert && pwcCert != (WCHAR *) pbIn)
  653. {
  654. LocalFree(pwcCert);
  655. }
  656. return(hr);
  657. }
  658. HRESULT
  659. DispatchSetErrorInfo(
  660. IN HRESULT hrError,
  661. IN WCHAR const *pwszDescription,
  662. OPTIONAL IN WCHAR const *pwszProgId,
  663. OPTIONAL IN IID const *piid)
  664. {
  665. HRESULT hr;
  666. WCHAR const *pwszError = NULL;
  667. WCHAR *pwszText = NULL;
  668. if (NULL == pwszDescription)
  669. {
  670. hr = E_POINTER;
  671. _JumpError(hr, error, "NULL pointer");
  672. }
  673. CSASSERT(FAILED(hrError));
  674. pwszError = myGetErrorMessageText(hrError, TRUE);
  675. if (NULL == pwszError)
  676. {
  677. _PrintError(E_OUTOFMEMORY, "myGetErrorMessageText");
  678. }
  679. else
  680. {
  681. pwszText = (WCHAR *) LocalAlloc(
  682. LMEM_FIXED,
  683. (wcslen(pwszDescription) + 1 + wcslen(pwszError) + 1) *
  684. sizeof(WCHAR));
  685. if (NULL == pwszText)
  686. {
  687. _PrintError(E_OUTOFMEMORY, "LocalAlloc");
  688. }
  689. else
  690. {
  691. wcscpy(pwszText, pwszDescription);
  692. wcscat(pwszText, L" ");
  693. wcscat(pwszText, pwszError);
  694. }
  695. }
  696. hr = DispatchSetErrorInfoSub(
  697. hrError,
  698. NULL, // pwszIDispatchMethod
  699. NULL != pwszText?
  700. pwszText : const_cast<WCHAR *>(pwszDescription),
  701. pwszProgId,
  702. piid,
  703. NULL, // pwszHelpFile
  704. 0); // dwHelpFileContext
  705. _PrintIfError(hr, "DispatchSetErrorInfoSub");
  706. error:
  707. if (NULL != pwszText)
  708. {
  709. LocalFree(pwszText);
  710. }
  711. if (NULL != pwszError)
  712. {
  713. LocalFree(const_cast<WCHAR *>(pwszError));
  714. }
  715. return(hrError); // return input error!
  716. }