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.

816 lines
19 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: exit.cpp
  7. //
  8. // Contents: CCertExitSample implementation
  9. //
  10. //---------------------------------------------------------------------------
  11. #include "pch.cpp"
  12. #pragma hdrstop
  13. #include <assert.h>
  14. #include "celib.h"
  15. #include "exit.h"
  16. #include "module.h"
  17. BOOL fDebug = DBG_CERTSRV;
  18. #ifndef DBG_CERTSRV
  19. #error -- DBG_CERTSRV not defined!
  20. #endif
  21. #define ceEXITEVENTS \
  22. (EXITEVENT_CERTDENIED | \
  23. EXITEVENT_CERTISSUED | \
  24. EXITEVENT_CERTPENDING | \
  25. EXITEVENT_CERTRETRIEVEPENDING | \
  26. EXITEVENT_CERTREVOKED | \
  27. EXITEVENT_CRLISSUED | \
  28. EXITEVENT_SHUTDOWN)
  29. extern HINSTANCE g_hInstance;
  30. HRESULT
  31. GetServerCallbackInterface(
  32. OUT ICertServerExit** ppServer,
  33. IN LONG Context)
  34. {
  35. HRESULT hr;
  36. if (NULL == ppServer)
  37. {
  38. hr = E_POINTER;
  39. _JumpError(hr, error, "Exit:NULL pointer");
  40. }
  41. hr = CoCreateInstance(
  42. CLSID_CCertServerExit,
  43. NULL, // pUnkOuter
  44. CLSCTX_INPROC_SERVER,
  45. IID_ICertServerExit,
  46. (VOID **) ppServer);
  47. _JumpIfError(hr, error, "Exit:CoCreateInstance");
  48. if (*ppServer == NULL)
  49. {
  50. hr = E_UNEXPECTED;
  51. _JumpError(hr, error, "Exit:NULL *ppServer");
  52. }
  53. // only set context if nonzero
  54. if (0 != Context)
  55. {
  56. hr = (*ppServer)->SetContext(Context);
  57. _JumpIfError(hr, error, "Exit: SetContext");
  58. }
  59. error:
  60. return(hr);
  61. }
  62. //+--------------------------------------------------------------------------
  63. // CCertExitSample::~CCertExitSample -- destructor
  64. //
  65. // free memory associated with this instance
  66. //+--------------------------------------------------------------------------
  67. CCertExitSample::~CCertExitSample()
  68. {
  69. if (NULL != m_strCAName)
  70. {
  71. SysFreeString(m_strCAName);
  72. }
  73. if (NULL != m_pwszRegStorageLoc)
  74. {
  75. LocalFree(m_pwszRegStorageLoc);
  76. }
  77. if (NULL != m_hExitKey)
  78. {
  79. RegCloseKey(m_hExitKey);
  80. }
  81. if (NULL != m_strDescription)
  82. {
  83. SysFreeString(m_strDescription);
  84. }
  85. }
  86. //+--------------------------------------------------------------------------
  87. // CCertExitSample::Initialize -- initialize for a CA & return interesting Event Mask
  88. //
  89. // Returns S_OK on success.
  90. //+--------------------------------------------------------------------------
  91. STDMETHODIMP
  92. CCertExitSample::Initialize(
  93. /* [in] */ BSTR const strConfig,
  94. /* [retval][out] */ LONG __RPC_FAR *pEventMask)
  95. {
  96. HRESULT hr = S_OK;
  97. DWORD cbbuf;
  98. DWORD dwType;
  99. ENUM_CATYPES CAType;
  100. ICertServerExit *pServer = NULL;
  101. VARIANT varValue;
  102. WCHAR sz[MAX_PATH];
  103. VariantInit(&varValue);
  104. assert(wcslen(wsz_SAMPLE_DESCRIPTION) < ARRAYSIZE(sz));
  105. wcsncpy(sz, wsz_SAMPLE_DESCRIPTION, ARRAYSIZE(sz));
  106. sz[ARRAYSIZE(sz) - 1] = L'\0';
  107. m_strDescription = SysAllocString(sz);
  108. if (NULL == m_strDescription)
  109. {
  110. hr = E_OUTOFMEMORY;
  111. _JumpError(hr, error, "Exit:SysAllocString");
  112. }
  113. m_strCAName = SysAllocString(strConfig);
  114. if (NULL == m_strCAName)
  115. {
  116. hr = E_OUTOFMEMORY;
  117. _JumpError(hr, error, "Exit:SysAllocString");
  118. }
  119. *pEventMask = ceEXITEVENTS;
  120. DBGPRINT((fDebug, "Exit:Initialize(%ws) ==> %x\n", m_strCAName, *pEventMask));
  121. // get server callbacks
  122. hr = GetServerCallbackInterface(&pServer, 0);
  123. _JumpIfError(hr, error, "Exit:GetServerCallbackInterface");
  124. // get storage location
  125. hr = exitGetProperty(
  126. pServer,
  127. FALSE, // fRequest
  128. wszPROPMODULEREGLOC,
  129. PROPTYPE_STRING,
  130. &varValue);
  131. _JumpIfErrorStr(hr, error, "Exit:exitGetProperty", wszPROPMODULEREGLOC);
  132. m_pwszRegStorageLoc = (LPWSTR)LocalAlloc(LMEM_FIXED, (wcslen(varValue.bstrVal)+1) *sizeof(WCHAR));
  133. if (NULL == m_pwszRegStorageLoc)
  134. {
  135. hr = E_OUTOFMEMORY;
  136. _JumpError(hr, error, "Exit:LocalAlloc");
  137. }
  138. wcscpy(m_pwszRegStorageLoc, varValue.bstrVal);
  139. VariantClear(&varValue);
  140. // get CA type
  141. hr = exitGetProperty(
  142. pServer,
  143. FALSE, // fRequest
  144. wszPROPCATYPE,
  145. PROPTYPE_LONG,
  146. &varValue);
  147. _JumpIfErrorStr(hr, error, "Exit:exitGetProperty", wszPROPCATYPE);
  148. CAType = (ENUM_CATYPES) varValue.lVal;
  149. VariantClear(&varValue);
  150. hr = RegOpenKeyEx(
  151. HKEY_LOCAL_MACHINE,
  152. m_pwszRegStorageLoc,
  153. 0, // dwReserved
  154. KEY_ENUMERATE_SUB_KEYS | KEY_EXECUTE | KEY_QUERY_VALUE,
  155. &m_hExitKey);
  156. if (S_OK != hr)
  157. {
  158. if ((HRESULT) ERROR_FILE_NOT_FOUND == hr)
  159. {
  160. hr = S_OK;
  161. goto error;
  162. }
  163. _JumpError(hr, error, "Exit:RegOpenKeyEx");
  164. }
  165. hr = exitGetProperty(
  166. pServer,
  167. FALSE, // fRequest
  168. wszPROPCERTCOUNT,
  169. PROPTYPE_LONG,
  170. &varValue);
  171. _JumpIfErrorStr(hr, error, "Exit:exitGetProperty", wszPROPCERTCOUNT);
  172. m_cCACert = varValue.lVal;
  173. cbbuf = sizeof(m_dwExitPublishFlags);
  174. hr = RegQueryValueEx(
  175. m_hExitKey,
  176. wszREGCERTPUBLISHFLAGS,
  177. NULL, // lpdwReserved
  178. &dwType,
  179. (BYTE *) &m_dwExitPublishFlags,
  180. &cbbuf);
  181. if (S_OK != hr)
  182. {
  183. m_dwExitPublishFlags = 0;
  184. }
  185. hr = S_OK;
  186. error:
  187. VariantClear(&varValue);
  188. if (NULL != pServer)
  189. {
  190. pServer->Release();
  191. }
  192. return(ceHError(hr));
  193. }
  194. //+--------------------------------------------------------------------------
  195. // CCertExitSample::_ExpandEnvironmentVariables -- Expand environment variables
  196. //
  197. //+--------------------------------------------------------------------------
  198. HRESULT
  199. CCertExitSample::_ExpandEnvironmentVariables(
  200. IN WCHAR const *pwszIn,
  201. OUT WCHAR *pwszOut,
  202. IN DWORD cwcOut)
  203. {
  204. HRESULT hr = HRESULT_FROM_WIN32(ERROR_BUFFER_OVERFLOW);
  205. WCHAR awcVar[MAX_PATH];
  206. WCHAR const *pwszSrc;
  207. WCHAR *pwszDst;
  208. WCHAR *pwszDstEnd;
  209. WCHAR *pwszVar;
  210. DWORD cwc;
  211. pwszSrc = pwszIn;
  212. pwszDst = pwszOut;
  213. pwszDstEnd = &pwszOut[cwcOut];
  214. while (L'\0' != (*pwszDst = *pwszSrc++))
  215. {
  216. if ('%' == *pwszDst)
  217. {
  218. *pwszDst = L'\0';
  219. pwszVar = awcVar;
  220. while (L'\0' != *pwszSrc)
  221. {
  222. if ('%' == *pwszSrc)
  223. {
  224. pwszSrc++;
  225. break;
  226. }
  227. *pwszVar++ = *pwszSrc++;
  228. if (pwszVar >= &awcVar[sizeof(awcVar)/sizeof(awcVar[0]) - 1])
  229. {
  230. _JumpError(hr, error, "Exit:overflow 1");
  231. }
  232. }
  233. *pwszVar = L'\0';
  234. cwc = GetEnvironmentVariable(awcVar, pwszDst, SAFE_SUBTRACT_POINTERS(pwszDstEnd, pwszDst));
  235. if (0 == cwc)
  236. {
  237. hr = ceHLastError();
  238. _JumpError(hr, error, "Exit:GetEnvironmentVariable");
  239. }
  240. if ((DWORD) (pwszDstEnd - pwszDst) <= cwc)
  241. {
  242. _JumpError(hr, error, "Exit:overflow 2");
  243. }
  244. pwszDst += cwc;
  245. }
  246. else
  247. {
  248. pwszDst++;
  249. }
  250. if (pwszDst >= pwszDstEnd)
  251. {
  252. _JumpError(hr, error, "Exit:overflow 3");
  253. }
  254. }
  255. hr = S_OK;
  256. error:
  257. return(hr);
  258. }
  259. HRESULT
  260. exitGetRequestAttribute(
  261. IN ICertServerExit *pServer,
  262. IN WCHAR const *pwszAttributeName,
  263. OUT BSTR *pstrOut)
  264. {
  265. HRESULT hr;
  266. BSTR strName = NULL;
  267. *pstrOut = NULL;
  268. strName = SysAllocString(pwszAttributeName);
  269. if (NULL == strName)
  270. {
  271. hr = E_OUTOFMEMORY;
  272. _JumpError(hr, error, "Exit:SysAllocString");
  273. }
  274. hr = pServer->GetRequestAttribute(strName, pstrOut);
  275. _JumpIfErrorStr2(
  276. hr,
  277. error,
  278. "Exit:GetRequestAttribute",
  279. pwszAttributeName,
  280. CERTSRV_E_PROPERTY_EMPTY);
  281. error:
  282. if (NULL != strName)
  283. {
  284. SysFreeString(strName);
  285. }
  286. return(hr);
  287. }
  288. //+--------------------------------------------------------------------------
  289. // CCertExitSample::_WriteCertToFile -- write binary certificate to a file
  290. //
  291. //+--------------------------------------------------------------------------
  292. HRESULT
  293. CCertExitSample::_WriteCertToFile(
  294. IN ICertServerExit *pServer,
  295. IN BYTE const *pbCert,
  296. IN DWORD cbCert)
  297. {
  298. HRESULT hr;
  299. BSTR strCertFile = NULL;
  300. DWORD cbWritten;
  301. HANDLE hFile = INVALID_HANDLE_VALUE;
  302. WCHAR wszDir[MAX_PATH];
  303. WCHAR *pwszPath = NULL;
  304. WCHAR wszFile[cwcDWORDSPRINTF+5]; //format "requestid.cer"
  305. VARIANT varRequestID;
  306. VariantInit(&varRequestID);
  307. hr = exitGetRequestAttribute(pServer, wszPROPEXITCERTFILE, &strCertFile);
  308. if (S_OK != hr)
  309. {
  310. DBGPRINT((
  311. fDebug,
  312. "Exit:exitGetRequestAttribute(%ws): %x%hs\n",
  313. wszPROPEXITCERTFILE,
  314. hr,
  315. CERTSRV_E_PROPERTY_EMPTY == hr? " EMPTY VALUE" : ""));
  316. if (CERTSRV_E_PROPERTY_EMPTY == hr)
  317. {
  318. hr = S_OK;
  319. }
  320. goto error;
  321. }
  322. // build file name as "requestid.cer"
  323. hr = exitGetProperty(
  324. pServer,
  325. TRUE, // fRequest,
  326. wszPROPREQUESTREQUESTID,
  327. PROPTYPE_LONG,
  328. &varRequestID);
  329. _JumpIfErrorStr(hr, error, "Exit:exitGetProperty", wszPROPREQUESTREQUESTID);
  330. wsprintf(wszFile, L"%d.cer", V_I4(&varRequestID));
  331. hr = _ExpandEnvironmentVariables(
  332. L"%SystemRoot%\\System32\\" wszCERTENROLLSHAREPATH L"\\",
  333. wszDir,
  334. ARRAYSIZE(wszDir));
  335. _JumpIfError(hr, error, "_ExpandEnvironmentVariables");
  336. hr = ceBuildPathAndExt(wszDir, wszFile, NULL, &pwszPath);
  337. _JumpIfError(hr, error, "ceBuildPathAndExt");
  338. // open file & write binary cert out.
  339. hFile = CreateFile(
  340. pwszPath,
  341. GENERIC_WRITE,
  342. 0, // dwShareMode
  343. NULL, // lpSecurityAttributes
  344. CREATE_NEW,
  345. FILE_ATTRIBUTE_NORMAL,
  346. NULL); // hTemplateFile
  347. if (INVALID_HANDLE_VALUE == hFile)
  348. {
  349. hr = ceHLastError();
  350. _JumpErrorStr(hr, error, "Exit:CreateFile", pwszPath);
  351. }
  352. if (!WriteFile(hFile, pbCert, cbCert, &cbWritten, NULL))
  353. {
  354. hr = ceHLastError();
  355. _JumpErrorStr(hr, error, "Exit:WriteFile", pwszPath);
  356. }
  357. if (cbWritten != cbCert)
  358. {
  359. hr = STG_E_WRITEFAULT;
  360. DBGPRINT((
  361. fDebug,
  362. "Exit:WriteFile(%ws): attempted %x, actual %x bytes: %x\n",
  363. pwszPath,
  364. cbCert,
  365. cbWritten,
  366. hr));
  367. goto error;
  368. }
  369. error:
  370. if (INVALID_HANDLE_VALUE != hFile)
  371. {
  372. CloseHandle(hFile);
  373. }
  374. if (NULL != pwszPath)
  375. {
  376. LocalFree(pwszPath);
  377. }
  378. if (NULL != strCertFile)
  379. {
  380. SysFreeString(strCertFile);
  381. }
  382. return(hr);
  383. }
  384. //+--------------------------------------------------------------------------
  385. // CCertExitSample::_NotifyNewCert -- Notify the exit module of a new certificate
  386. //
  387. //+--------------------------------------------------------------------------
  388. HRESULT
  389. CCertExitSample::_NotifyNewCert(
  390. /* [in] */ LONG Context)
  391. {
  392. HRESULT hr;
  393. VARIANT varCert;
  394. ICertServerExit *pServer = NULL;
  395. VariantInit(&varCert);
  396. // only call write fxns if server policy allows
  397. if (m_dwExitPublishFlags & EXITPUB_FILE)
  398. {
  399. hr = CoCreateInstance(
  400. CLSID_CCertServerExit,
  401. NULL, // pUnkOuter
  402. CLSCTX_INPROC_SERVER,
  403. IID_ICertServerExit,
  404. (VOID **) &pServer);
  405. _JumpIfError(hr, error, "Exit:CoCreateInstance");
  406. hr = pServer->SetContext(Context);
  407. _JumpIfError(hr, error, "Exit:SetContext");
  408. hr = exitGetProperty(
  409. pServer,
  410. FALSE, // fRequest,
  411. wszPROPRAWCERTIFICATE,
  412. PROPTYPE_BINARY,
  413. &varCert);
  414. _JumpIfErrorStr(
  415. hr,
  416. error,
  417. "Exit:exitGetProperty",
  418. wszPROPRAWCERTIFICATE);
  419. if (VT_BSTR != varCert.vt)
  420. {
  421. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  422. _JumpError(hr, error, "Exit:BAD cert var type");
  423. }
  424. hr = _WriteCertToFile(
  425. pServer,
  426. (BYTE const *) varCert.bstrVal,
  427. SysStringByteLen(varCert.bstrVal));
  428. _JumpIfError(hr, error, "_WriteCertToFile");
  429. }
  430. hr = S_OK;
  431. error:
  432. VariantClear(&varCert);
  433. if (NULL != pServer)
  434. {
  435. pServer->Release();
  436. }
  437. return(hr);
  438. }
  439. //+--------------------------------------------------------------------------
  440. // CCertExitSample::_NotifyCRLIssued -- Notify the exit module of a new certificate
  441. //
  442. //+--------------------------------------------------------------------------
  443. HRESULT
  444. CCertExitSample::_NotifyCRLIssued(
  445. /* [in] */ LONG Context)
  446. {
  447. HRESULT hr;
  448. ICertServerExit *pServer = NULL;
  449. DWORD i;
  450. VARIANT varBaseCRL;
  451. VARIANT varDeltaCRL;
  452. BOOL fDeltaCRLsDisabled;
  453. VariantInit(&varBaseCRL);
  454. VariantInit(&varDeltaCRL);
  455. hr = CoCreateInstance(
  456. CLSID_CCertServerExit,
  457. NULL, // pUnkOuter
  458. CLSCTX_INPROC_SERVER,
  459. IID_ICertServerExit,
  460. (VOID **) &pServer);
  461. _JumpIfError(hr, error, "Exit:CoCreateInstance");
  462. hr = pServer->SetContext(Context);
  463. _JumpIfError(hr, error, "Exit:SetContext");
  464. hr = exitGetProperty(
  465. pServer,
  466. FALSE, // fRequest,
  467. wszPROPDELTACRLSDISABLED,
  468. PROPTYPE_LONG,
  469. &varBaseCRL);
  470. _JumpIfErrorStr(
  471. hr,
  472. error,
  473. "Exit:exitGetProperty",
  474. wszPROPDELTACRLSDISABLED);
  475. fDeltaCRLsDisabled = varBaseCRL.lVal;
  476. // How many CRLs are there?
  477. // Loop for each CRL
  478. for (i = 0; i < m_cCACert; i++)
  479. {
  480. // array size for wsprintf("%s.%u")
  481. #define MAX_CRL_PROP \
  482. (max( \
  483. max(ARRAYSIZE(wszPROPCRLSTATE), ARRAYSIZE(wszPROPRAWCRL)), \
  484. ARRAYSIZE(wszPROPRAWDELTACRL)) + \
  485. 1 + cwcDWORDSPRINTF)
  486. WCHAR wszCRLPROP[MAX_CRL_PROP];
  487. // Verify the CRL State says we should update this CRL
  488. wsprintf(wszCRLPROP, wszPROPCRLSTATE L".%u", i);
  489. hr = exitGetProperty(
  490. pServer,
  491. FALSE, // fRequest,
  492. wszCRLPROP,
  493. PROPTYPE_LONG,
  494. &varBaseCRL);
  495. _JumpIfErrorStr(hr, error, "Exit:exitGetProperty", wszCRLPROP);
  496. if (CA_DISP_VALID != varBaseCRL.lVal)
  497. {
  498. continue;
  499. }
  500. // Grab the raw base CRL
  501. wsprintf(wszCRLPROP, wszPROPRAWCRL L".%u", i);
  502. hr = exitGetProperty(
  503. pServer,
  504. FALSE, // fRequest,
  505. wszCRLPROP,
  506. PROPTYPE_BINARY,
  507. &varBaseCRL);
  508. _JumpIfErrorStr(hr, error, "Exit:exitGetProperty", wszCRLPROP);
  509. // Grab the raw delta CRL (which may not exist)
  510. wsprintf(wszCRLPROP, wszPROPRAWDELTACRL L".%u", i);
  511. hr = exitGetProperty(
  512. pServer,
  513. FALSE, // fRequest,
  514. wszCRLPROP,
  515. PROPTYPE_BINARY,
  516. &varDeltaCRL);
  517. _PrintIfErrorStr2(
  518. hr,
  519. "Exit:exitGetProperty",
  520. wszCRLPROP,
  521. fDeltaCRLsDisabled?
  522. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) : S_OK);
  523. if (S_OK != hr && !fDeltaCRLsDisabled)
  524. {
  525. goto error;
  526. }
  527. // Publish the CRL(s) ...
  528. }
  529. hr = S_OK;
  530. error:
  531. if (NULL != pServer)
  532. {
  533. pServer->Release();
  534. }
  535. VariantClear(&varBaseCRL);
  536. VariantClear(&varDeltaCRL);
  537. return(hr);
  538. }
  539. //+--------------------------------------------------------------------------
  540. // CCertExitSample::Notify -- Notify the exit module of an event
  541. //
  542. // Returns S_OK.
  543. //+--------------------------------------------------------------------------
  544. STDMETHODIMP
  545. CCertExitSample::Notify(
  546. /* [in] */ LONG ExitEvent,
  547. /* [in] */ LONG Context)
  548. {
  549. char *psz = "UNKNOWN EVENT";
  550. HRESULT hr = S_OK;
  551. switch (ExitEvent)
  552. {
  553. case EXITEVENT_CERTISSUED:
  554. hr = _NotifyNewCert(Context);
  555. psz = "certissued";
  556. break;
  557. case EXITEVENT_CERTPENDING:
  558. psz = "certpending";
  559. break;
  560. case EXITEVENT_CERTDENIED:
  561. psz = "certdenied";
  562. break;
  563. case EXITEVENT_CERTREVOKED:
  564. psz = "certrevoked";
  565. break;
  566. case EXITEVENT_CERTRETRIEVEPENDING:
  567. psz = "retrievepending";
  568. break;
  569. case EXITEVENT_CRLISSUED:
  570. hr = _NotifyCRLIssued(Context);
  571. psz = "crlissued";
  572. break;
  573. case EXITEVENT_SHUTDOWN:
  574. psz = "shutdown";
  575. break;
  576. }
  577. DBGPRINT((
  578. fDebug,
  579. "Exit:Notify(%hs=%x, ctx=%x) rc=%x\n",
  580. psz,
  581. ExitEvent,
  582. Context,
  583. hr));
  584. return(hr);
  585. }
  586. STDMETHODIMP
  587. CCertExitSample::GetDescription(
  588. /* [retval][out] */ BSTR *pstrDescription)
  589. {
  590. HRESULT hr = S_OK;
  591. WCHAR sz[MAX_PATH];
  592. assert(wcslen(wsz_SAMPLE_DESCRIPTION) < ARRAYSIZE(sz));
  593. wcscpy(sz, wsz_SAMPLE_DESCRIPTION);
  594. *pstrDescription = SysAllocString(sz);
  595. if (NULL == *pstrDescription)
  596. {
  597. hr = E_OUTOFMEMORY;
  598. _JumpError(hr, error, "Exit:SysAllocString");
  599. }
  600. error:
  601. return(hr);
  602. }
  603. //+--------------------------------------------------------------------------
  604. // CCertExitSample::GetManageModule
  605. //
  606. // Returns S_OK on success.
  607. //+--------------------------------------------------------------------------
  608. STDMETHODIMP
  609. CCertExitSample::GetManageModule(
  610. /* [out, retval] */ ICertManageModule **ppManageModule)
  611. {
  612. HRESULT hr;
  613. *ppManageModule = NULL;
  614. hr = CoCreateInstance(
  615. CLSID_CCertManageExitModuleSample,
  616. NULL, // pUnkOuter
  617. CLSCTX_INPROC_SERVER,
  618. IID_ICertManageModule,
  619. (VOID **) ppManageModule);
  620. _JumpIfError(hr, error, "CoCreateInstance");
  621. error:
  622. return(hr);
  623. }
  624. /////////////////////////////////////////////////////////////////////////////
  625. //
  626. STDMETHODIMP
  627. CCertExitSample::InterfaceSupportsErrorInfo(REFIID riid)
  628. {
  629. int i;
  630. static const IID *arr[] =
  631. {
  632. &IID_ICertExit,
  633. };
  634. for (i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
  635. {
  636. if (IsEqualGUID(*arr[i],riid))
  637. {
  638. return(S_OK);
  639. }
  640. }
  641. return(S_FALSE);
  642. }
  643. HRESULT
  644. exitGetProperty(
  645. IN ICertServerExit *pServer,
  646. IN BOOL fRequest,
  647. IN WCHAR const *pwszPropertyName,
  648. IN DWORD PropType,
  649. OUT VARIANT *pvarOut)
  650. {
  651. HRESULT hr;
  652. BSTR strName = NULL;
  653. VariantInit(pvarOut);
  654. strName = SysAllocString(pwszPropertyName);
  655. if (NULL == strName)
  656. {
  657. hr = E_OUTOFMEMORY;
  658. _JumpError(hr, error, "Exit:SysAllocString");
  659. }
  660. if (fRequest)
  661. {
  662. hr = pServer->GetRequestProperty(strName, PropType, pvarOut);
  663. _JumpIfErrorStr2(
  664. hr,
  665. error,
  666. "Exit:GetRequestProperty",
  667. pwszPropertyName,
  668. CERTSRV_E_PROPERTY_EMPTY);
  669. }
  670. else
  671. {
  672. hr = pServer->GetCertificateProperty(strName, PropType, pvarOut);
  673. _JumpIfErrorStr2(
  674. hr,
  675. error,
  676. "Exit:GetCertificateProperty",
  677. pwszPropertyName,
  678. CERTSRV_E_PROPERTY_EMPTY);
  679. }
  680. error:
  681. if (NULL != strName)
  682. {
  683. SysFreeString(strName);
  684. }
  685. return(hr);
  686. }