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.

1573 lines
35 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: com.cpp
  7. //
  8. // Contents: Cert Server Policy & Exit module callouts
  9. //
  10. // History: 7-Feb-97 vich created
  11. //
  12. //---------------------------------------------------------------------------
  13. #include <pch.cpp>
  14. #pragma hdrstop
  15. #include <stdio.h>
  16. #include "csdisp.h"
  17. #include "elog.h"
  18. #include "certlog.h"
  19. #include "cscom.h"
  20. #include "csprop.h"
  21. #include "com.h"
  22. #define __dwFILE__ __dwFILE_CERTSRV_COM_CPP__
  23. BSTR g_strPolicyDescription = NULL;
  24. BOOL g_fEnablePolicy = FALSE;
  25. MarshalInterface g_miPolicy;
  26. typedef struct _CERTSRV_COM_CONTEXT_ENTRY
  27. {
  28. USHORT usFlags;
  29. CERTSRV_COM_CONTEXT *pComContext;
  30. } CERTSRV_COM_CONTEXT_ENTRY;
  31. // data structure to pass handles between server and policy/exit modules
  32. CERTSRV_COM_CONTEXT_ENTRY *g_pComContextTable = NULL;
  33. DWORD g_dwComContextCount = 0;
  34. USHORT g_usComContextId = 0; // id increament
  35. CRITICAL_SECTION g_ComCriticalSection;
  36. BOOL g_fComCritSec = FALSE;
  37. CERTSRV_COM_CONTEXT *g_pExitComContext = NULL;
  38. // NOTE: GlobalInterfaceTable better to use than CoMarshalInterface
  39. static IGlobalInterfaceTable* g_pGIT = NULL;
  40. // Clear out any error info
  41. VOID
  42. comClearError(VOID)
  43. {
  44. IErrorInfo *pErrorInfo = NULL;
  45. if (S_OK == GetErrorInfo(0, &pErrorInfo))
  46. {
  47. if (NULL != pErrorInfo)
  48. {
  49. pErrorInfo->Release();
  50. }
  51. }
  52. }
  53. HRESULT
  54. MarshalInterface::SetConfig(
  55. IN LPCWSTR pwszSanitizedName)
  56. {
  57. HRESULT hr = S_OK;
  58. if (NULL == pwszSanitizedName)
  59. {
  60. hr = E_POINTER;
  61. _JumpError(hr, error, "SetConfig");
  62. }
  63. m_szConfig = (LPWSTR) LocalAlloc(
  64. LMEM_FIXED,
  65. (wcslen(g_pwszServerName) + 1 + wcslen(pwszSanitizedName) + 1) * sizeof(WCHAR));
  66. if (NULL == m_szConfig)
  67. {
  68. hr = E_OUTOFMEMORY;
  69. _JumpError(hr, error, "LocalAlloc");
  70. }
  71. // config comes to us without server name: add it
  72. wcscpy((LPWSTR)m_szConfig, g_pwszServerName);
  73. wcscat((LPWSTR)m_szConfig, L"\\");
  74. wcscat((LPWSTR)m_szConfig, pwszSanitizedName);
  75. error:
  76. return hr;
  77. }
  78. HRESULT
  79. MarshalInterface::Initialize(
  80. IN WCHAR const *pwszProgID,
  81. IN CLSID const *pclsid,
  82. IN DWORD cver,
  83. IN IID const * const *ppiid, // cver elements
  84. IN DWORD const *pcDispatch, // cver elements
  85. IN DISPATCHTABLE *adt)
  86. {
  87. HRESULT hr;
  88. if (NULL != pwszProgID)
  89. {
  90. m_pwszProgID = (LPWSTR) LocalAlloc(
  91. LMEM_FIXED,
  92. (wcslen(pwszProgID) + 1) * sizeof(WCHAR));
  93. if (NULL == m_pwszProgID)
  94. {
  95. hr = E_OUTOFMEMORY;
  96. _JumpError(hr, error, "LocalAlloc");
  97. }
  98. wcscpy(m_pwszProgID, pwszProgID);
  99. }
  100. m_pclsid = pclsid;
  101. m_cver = cver;
  102. m_ppiid = ppiid;
  103. m_pcDispatch = pcDispatch;
  104. m_adt = adt;
  105. m_fIDispatch = FALSE;
  106. m_dwIFCookie = 0;
  107. m_fInitialized = TRUE;
  108. hr = S_OK;
  109. error:
  110. return(hr);
  111. }
  112. HRESULT
  113. MarshalInterface::Setup(
  114. OUT DISPATCHINTERFACE **ppDispatchInterface)
  115. {
  116. HRESULT hr;
  117. CSASSERT(m_fInitialized);
  118. *ppDispatchInterface = NULL;
  119. hr = DispatchSetup2(
  120. DISPSETUP_COMFIRST,
  121. CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  122. m_pwszProgID,
  123. m_pclsid,
  124. m_cver,
  125. m_ppiid,
  126. m_pcDispatch,
  127. m_adt,
  128. &m_DispatchInterface);
  129. // Don't complain if no class is registered.
  130. _JumpIfError2(
  131. hr,
  132. error,
  133. "DispatchSetup",
  134. HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  135. m_fIDispatch = NULL != m_DispatchInterface.m_adispid;
  136. CSASSERT(
  137. 0 < m_DispatchInterface.m_dwVersion &&
  138. m_cver >= m_DispatchInterface.m_dwVersion);
  139. m_iiid = m_cver - m_DispatchInterface.m_dwVersion;
  140. // create GIT if it doesn't yet exist
  141. if (NULL == g_pGIT)
  142. {
  143. hr = CoCreateInstance(
  144. CLSID_StdGlobalInterfaceTable,
  145. NULL,
  146. CLSCTX_INPROC_SERVER,
  147. IID_IGlobalInterfaceTable,
  148. (void **) &g_pGIT);
  149. _JumpIfError(hr, error, "CoCreateInstance(GIT)");
  150. }
  151. hr = Marshal(&m_DispatchInterface);
  152. _JumpIfError(hr, error, "Marshal");
  153. *ppDispatchInterface = &m_DispatchInterface;
  154. error:
  155. if (S_OK != hr)
  156. {
  157. TearDown();
  158. }
  159. return(hr);
  160. }
  161. VOID
  162. MarshalInterface::TearDown(VOID)
  163. {
  164. if (m_fInitialized)
  165. {
  166. if (NULL != g_pGIT && 0 != m_dwIFCookie)
  167. {
  168. g_pGIT->RevokeInterfaceFromGlobal(m_dwIFCookie);
  169. m_dwIFCookie = 0;
  170. }
  171. DispatchRelease(&m_DispatchInterface);
  172. m_fInitialized = 0;
  173. }
  174. if (NULL != m_pwszProgID)
  175. {
  176. LocalFree(m_pwszProgID);
  177. m_pwszProgID = NULL;
  178. }
  179. if (NULL != m_szConfig)
  180. {
  181. LocalFree((LPWSTR)m_szConfig);
  182. m_szConfig = NULL;
  183. }
  184. }
  185. HRESULT
  186. MarshalInterface::Marshal(
  187. IN DISPATCHINTERFACE *pDispatchInterface)
  188. {
  189. HRESULT hr;
  190. CSASSERT(g_pGIT);
  191. if (g_pGIT == NULL)
  192. {
  193. hr = E_UNEXPECTED;
  194. _JumpIfError(hr, error, "GlobalInterfaceTable not initialized");
  195. }
  196. hr = g_pGIT->RegisterInterfaceInGlobal(
  197. m_fIDispatch?
  198. pDispatchInterface->pDispatch :
  199. pDispatchInterface->pUnknown,
  200. m_fIDispatch? IID_IDispatch : *m_ppiid[m_iiid],
  201. &m_dwIFCookie);
  202. _JumpIfError(hr, error, "RegisterInterfaceInGlobal");
  203. error:
  204. return(hr);
  205. }
  206. HRESULT
  207. MarshalInterface::Remarshal(
  208. OUT DISPATCHINTERFACE *pDispatchInterface)
  209. {
  210. HRESULT hr;
  211. DBGPRINT((DBG_SS_CERTSRVI, "Remarshal(tid=%d)\n", GetCurrentThreadId()));
  212. CSASSERT(m_fInitialized);
  213. pDispatchInterface->pDispatch = NULL;
  214. pDispatchInterface->pUnknown = NULL;
  215. CSASSERT(g_pGIT);
  216. if (g_pGIT == NULL)
  217. {
  218. hr = E_UNEXPECTED;
  219. _JumpIfError(hr, error, "GlobalInterfaceTable not initialized");
  220. }
  221. hr = g_pGIT->GetInterfaceFromGlobal(
  222. m_dwIFCookie,
  223. m_fIDispatch? IID_IDispatch : *m_ppiid[m_iiid],
  224. m_fIDispatch?
  225. (VOID **) &pDispatchInterface->pDispatch :
  226. (VOID **) &pDispatchInterface->pUnknown);
  227. DBGPRINT((
  228. DBG_SS_CERTSRVI,
  229. "Remarshal(tid=%d) --> 0x%x\n",
  230. GetCurrentThreadId(),
  231. hr));
  232. _JumpIfError(hr, error, "GetInterfaceFromGlobal");
  233. // Copy invariants to the marshaled interface:
  234. pDispatchInterface->SetIID(m_ppiid[m_iiid]);
  235. pDispatchInterface->pDispatchTable = m_DispatchInterface.pDispatchTable;
  236. pDispatchInterface->m_cDispatchTable = m_DispatchInterface.m_cDispatchTable;
  237. pDispatchInterface->m_cdispid = m_DispatchInterface.m_cdispid;
  238. pDispatchInterface->m_adispid = m_DispatchInterface.m_adispid;
  239. error:
  240. return(hr);
  241. }
  242. VOID
  243. MarshalInterface::Unmarshal(
  244. IN OUT DISPATCHINTERFACE *pDispatchInterface)
  245. {
  246. // Don't free global DISPID table from marshaled interface:
  247. pDispatchInterface->m_adispid = NULL;
  248. DispatchRelease(pDispatchInterface);
  249. }
  250. // forwards
  251. VOID PolicyRelease(VOID);
  252. VOID ExitRelease(VOID);
  253. #define COMCONTEXTCOUNTMIN 4
  254. #define COMCONTEXTCOUNTMAX 1024 // must less than 64K
  255. #define COMCONTEXTCOUNTDEFAULT 20
  256. HRESULT
  257. ComInit(VOID)
  258. {
  259. HRESULT hr;
  260. HKEY hKey = NULL;
  261. DWORD dwSize;
  262. CSASSERT(NULL == g_pComContextTable);
  263. hr = RegOpenKey(HKEY_LOCAL_MACHINE, g_wszRegKeyConfigPath, &hKey);
  264. _JumpIfError(hr, error, "RegOpenKey(Config)");
  265. dwSize = sizeof(g_dwComContextCount);
  266. hr = RegQueryValueEx(
  267. hKey,
  268. wszREGDBSESSIONCOUNT, // just use db session count
  269. // bug, may not be logic related
  270. NULL,
  271. NULL,
  272. (BYTE *) &g_dwComContextCount,
  273. &dwSize);
  274. if (S_OK != hr)
  275. {
  276. _PrintErrorStr(hr, "RegQueryValueEx", wszREGDBSESSIONCOUNT);
  277. g_dwComContextCount = COMCONTEXTCOUNTDEFAULT;
  278. }
  279. if (COMCONTEXTCOUNTMIN > g_dwComContextCount)
  280. {
  281. g_dwComContextCount = COMCONTEXTCOUNTMIN;
  282. }
  283. if (COMCONTEXTCOUNTMAX < g_dwComContextCount)
  284. {
  285. g_dwComContextCount = COMCONTEXTCOUNTMAX;
  286. }
  287. g_pComContextTable = (CERTSRV_COM_CONTEXT_ENTRY *) LocalAlloc(
  288. LMEM_FIXED | LMEM_ZEROINIT,
  289. g_dwComContextCount *
  290. sizeof(g_pComContextTable[0]));
  291. if (NULL == g_pComContextTable)
  292. {
  293. hr = E_OUTOFMEMORY;
  294. _JumpError(hr, error, "LocalAlloc");
  295. }
  296. __try
  297. {
  298. InitializeCriticalSection(&g_ComCriticalSection);
  299. g_fComCritSec = TRUE;
  300. hr = S_OK;
  301. }
  302. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  303. {
  304. }
  305. error:
  306. if (NULL != hKey)
  307. {
  308. RegCloseKey(hKey);
  309. }
  310. return hr;
  311. }
  312. VOID
  313. ComShutDown(VOID)
  314. {
  315. if (NULL != g_pComContextTable)
  316. {
  317. PolicyRelease();
  318. ExitRelease();
  319. if (NULL != g_pGIT)
  320. {
  321. g_pGIT->Release();
  322. g_pGIT = NULL;
  323. }
  324. if (g_fComCritSec)
  325. {
  326. DeleteCriticalSection(&g_ComCriticalSection);
  327. g_fComCritSec = FALSE;
  328. }
  329. LocalFree(g_pComContextTable);
  330. g_pComContextTable = NULL;
  331. g_dwComContextCount = 0;
  332. }
  333. }
  334. HRESULT
  335. RegisterComContext(
  336. IN CERTSRV_COM_CONTEXT *pComContext,
  337. IN OUT DWORD *pdwIndex)
  338. {
  339. HRESULT hr = S_OK;
  340. BOOL fCS = FALSE;
  341. DWORD i;
  342. CSASSERT(NULL != pComContext);
  343. CSASSERT(NULL != g_pComContextTable);
  344. if (NULL == pComContext)
  345. {
  346. hr = E_POINTER;
  347. _JumpError(hr, error, "null com context pointer");
  348. }
  349. if (!g_fComCritSec)
  350. {
  351. hr = HRESULT_FROM_WIN32(ERROR_DLL_INIT_FAILED);
  352. _JumpError(hr, error, "InitializeCriticalSection");
  353. }
  354. EnterCriticalSection(&g_ComCriticalSection);
  355. fCS = TRUE;
  356. for (i = 0; NULL != g_pComContextTable[i].pComContext; ++i)
  357. {
  358. if (i + 1 == g_dwComContextCount)
  359. {
  360. //hr = HRESULT_FROM_WIN32(ERROR_BUSY);
  361. hr = HRESULT_FROM_WIN32(RPC_S_SERVER_TOO_BUSY);
  362. _JumpError(hr, error, "com context table full");
  363. }
  364. }
  365. // pick an id
  366. if (0 == g_usComContextId)
  367. {
  368. // it could make module context to be 0 which is a special flag
  369. // avoid 0
  370. ++g_usComContextId;
  371. }
  372. g_pComContextTable[i].usFlags = g_usComContextId++;
  373. // point to com context
  374. g_pComContextTable[i].pComContext = pComContext;
  375. *pdwIndex = i;
  376. error:
  377. if (fCS)
  378. {
  379. LeaveCriticalSection(&g_ComCriticalSection);
  380. }
  381. return hr;
  382. }
  383. VOID
  384. ReleaseComContext(
  385. IN CERTSRV_COM_CONTEXT *pComContext)
  386. {
  387. if (NULL != pComContext->pwszUserDN)
  388. {
  389. LocalFree(pComContext->pwszUserDN);
  390. pComContext->pwszUserDN = NULL;
  391. }
  392. }
  393. VOID
  394. UnregisterComContext(
  395. IN CERTSRV_COM_CONTEXT *DBGCODE(pComContext),
  396. IN DWORD dwIndex)
  397. {
  398. HRESULT hr = S_OK;
  399. BOOL fCS = FALSE;
  400. // if shutdown in progress after wait timeout
  401. if (NULL == g_pComContextTable)
  402. {
  403. hr = HRESULT_FROM_WIN32(ERROR_DLL_INIT_FAILED);
  404. _JumpError(hr, error, "NULL g_pComContextTable");
  405. }
  406. CSASSERT(dwIndex < g_dwComContextCount);
  407. if (!g_fComCritSec)
  408. {
  409. hr = HRESULT_FROM_WIN32(ERROR_DLL_INIT_FAILED);
  410. _JumpError(hr, error, "InitializeCriticalSection");
  411. }
  412. EnterCriticalSection(&g_ComCriticalSection);
  413. fCS = TRUE;
  414. if (dwIndex < g_dwComContextCount)
  415. {
  416. CSASSERT(0 != g_pComContextTable[dwIndex].usFlags);
  417. CSASSERT(NULL != g_pComContextTable[dwIndex].pComContext);
  418. CSASSERT(pComContext == g_pComContextTable[dwIndex].pComContext);
  419. g_pComContextTable[dwIndex].usFlags = 0;
  420. g_pComContextTable[dwIndex].pComContext = NULL;
  421. }
  422. error:
  423. if (fCS)
  424. {
  425. LeaveCriticalSection(&g_ComCriticalSection);
  426. }
  427. }
  428. CERTSRV_COM_CONTEXT *
  429. GetComContextFromIndex(
  430. IN DWORD dwIndex)
  431. {
  432. CERTSRV_COM_CONTEXT *pComContext = NULL;
  433. CSASSERT(NULL != g_pComContextTable);
  434. CSASSERT(dwIndex < g_dwComContextCount);
  435. if (dwIndex < g_dwComContextCount)
  436. {
  437. CSASSERT(0 != g_pComContextTable[dwIndex].usFlags);
  438. CSASSERT(NULL != g_pComContextTable[dwIndex].pComContext);
  439. pComContext = g_pComContextTable[dwIndex].pComContext;
  440. }
  441. return(pComContext);
  442. }
  443. DWORD
  444. ComContextToModuleContext(
  445. IN DWORD dwComContextIndex)
  446. {
  447. CSASSERT(NULL != g_pComContextTable);
  448. CSASSERT(dwComContextIndex < g_dwComContextCount);
  449. CSASSERT(0 != g_pComContextTable[dwComContextIndex].usFlags);
  450. CSASSERT(NULL != g_pComContextTable[dwComContextIndex].pComContext);
  451. DWORD dwHigh =
  452. (dwComContextIndex << 16) & 0xFFFF0000; // move index to high 16 bits
  453. DWORD dwLow =
  454. ((DWORD)g_pComContextTable[dwComContextIndex].usFlags) & 0x0000FFFF;
  455. return(dwHigh | dwLow);
  456. }
  457. HRESULT
  458. ModuleContextToComContextIndex(
  459. IN DWORD dwModuleContext,
  460. OUT DWORD *pdwIndex)
  461. {
  462. HRESULT hr = S_OK;
  463. USHORT usFlags = (USHORT)(dwModuleContext & 0x0000FFFF);
  464. DWORD dwIndex = (dwModuleContext >> 16) & 0x0000FFFF;
  465. CSASSERT(NULL != pdwIndex);
  466. *pdwIndex = MAXDWORD;
  467. if (dwIndex >= g_dwComContextCount ||
  468. 0 == usFlags ||
  469. g_pComContextTable[dwIndex].usFlags != usFlags)
  470. {
  471. // module passed a bogus handle
  472. hr = E_INVALIDARG;
  473. _JumpError(hr, error, "invalid context from policy/exit");
  474. }
  475. CSASSERT(NULL != g_pComContextTable[dwIndex].pComContext);
  476. // for return
  477. *pdwIndex = dwIndex;
  478. error:
  479. return hr;
  480. }
  481. HRESULT
  482. ModuleContextToRequestId(
  483. IN DWORD dwModuleContext,
  484. OUT DWORD *pdwRequestId)
  485. {
  486. DWORD dwIndex;
  487. HRESULT hr = ModuleContextToComContextIndex(dwModuleContext, &dwIndex);
  488. _JumpIfError(hr, error, "ModuleContextToComContextIndex");
  489. // for return
  490. *pdwRequestId = g_pComContextTable[dwIndex].pComContext->RequestId;
  491. error:
  492. return hr;
  493. }
  494. HRESULT
  495. ComVerifyRequestContext(
  496. IN BOOL fAllowZero,
  497. IN DWORD Flags,
  498. IN LONG Context,
  499. OUT DWORD *pRequestId)
  500. {
  501. HRESULT hr;
  502. *pRequestId = 0;
  503. if (0 == Context)
  504. {
  505. hr = S_OK;
  506. if (!fAllowZero)
  507. {
  508. hr = E_HANDLE;
  509. }
  510. }
  511. else
  512. {
  513. switch (PROPCALLER_MASK & Flags)
  514. {
  515. case PROPCALLER_EXIT:
  516. hr = ModuleContextToRequestId(Context, pRequestId);
  517. _JumpIfError(hr, error, "ModuleContextToRequestId");
  518. break;
  519. case PROPCALLER_POLICY:
  520. hr = ModuleContextToRequestId(Context, pRequestId);
  521. _JumpIfError(hr, error, "ModuleContextToRequestId");
  522. break;
  523. default:
  524. CSASSERT(CSExpr(FALSE));
  525. hr = E_HANDLE;
  526. _JumpError(hr, error, "unexpected policy/exit flags");
  527. break;
  528. }
  529. }
  530. error:
  531. return(hr);
  532. }
  533. BOOL
  534. ComParseErrorPrefix(
  535. OPTIONAL IN WCHAR const *pwszIn,
  536. OUT HRESULT *phrPrefix,
  537. OUT WCHAR const **ppwszOut)
  538. {
  539. BOOL fValid = FALSE;
  540. if (NULL != pwszIn && L'0' == pwszIn[0] && L'x' == pwszIn[1])
  541. {
  542. WCHAR const *pwsz = wcschr(pwszIn, L',');
  543. if (NULL != pwsz)
  544. {
  545. WCHAR awchr[cwcDWORDSPRINTF];
  546. DWORD cwc;
  547. cwc = SAFE_SUBTRACT_POINTERS(pwsz, pwszIn);
  548. if (ARRAYSIZE(awchr) > cwc)
  549. {
  550. CopyMemory(awchr, pwszIn, sizeof(WCHAR) * cwc);
  551. awchr[cwc] = L'\0';
  552. *phrPrefix = myWtoI(awchr, &fValid);
  553. if (fValid)
  554. {
  555. while (L' ' == *++pwsz)
  556. ;
  557. *ppwszOut = pwsz;
  558. }
  559. }
  560. }
  561. }
  562. return(fValid);
  563. }
  564. VOID
  565. PatchFormatSpecifiers(
  566. IN OUT WCHAR *pwszError)
  567. {
  568. for (;;)
  569. {
  570. WCHAR *pwsz;
  571. pwsz = wcschr(pwszError, L'%');
  572. if (NULL == pwsz)
  573. {
  574. break;
  575. }
  576. if (L'1' <= pwsz[1] && L'9' >= pwsz[1])
  577. {
  578. *pwsz = L'?';
  579. }
  580. pwsz += 2;
  581. }
  582. }
  583. VOID
  584. LogComError(
  585. OPTIONAL IN WCHAR const *pwszModuleDescription,
  586. IN WCHAR const *pwszMethod,
  587. IN HRESULT ErrCode,
  588. IN BOOL fException,
  589. IN ULONG_PTR ExceptionAddress,
  590. IN IID const *piid,
  591. IN DWORD dwIdEvent)
  592. {
  593. BSTR bstrErrorMessage = NULL;
  594. WCHAR const *pwszStringErr = NULL;
  595. if (CERTLOG_ERROR <= g_dwLogLevel)
  596. {
  597. HRESULT hr;
  598. WCHAR const *apwsz[5];
  599. WCHAR awchr[cwcHRESULTSTRING];
  600. WCHAR awcAddress[cwcULONG_INTEGERSPRINTF];
  601. apwsz[3] = L"";
  602. if (fException)
  603. {
  604. wsprintf(awcAddress, L"0x%p", (VOID *) ExceptionAddress);
  605. apwsz[3] = awcAddress;
  606. }
  607. else
  608. {
  609. IErrorInfo *pErrorInfo = NULL;
  610. // Get the error info
  611. hr = GetErrorInfo(0, &pErrorInfo);
  612. if (S_OK == hr && NULL != pErrorInfo)
  613. {
  614. GUID ErrorGuid;
  615. hr = pErrorInfo->GetGUID(&ErrorGuid);
  616. if (S_OK == hr && InlineIsEqualGUID(ErrorGuid, *piid))
  617. {
  618. hr = pErrorInfo->GetDescription(&bstrErrorMessage);
  619. if (S_OK == hr && NULL != bstrErrorMessage)
  620. {
  621. WCHAR const *pwszT = NULL;
  622. myRegisterMemAlloc(bstrErrorMessage, -1, CSM_SYSALLOC);
  623. if (S_OK != ErrCode ||
  624. !ComParseErrorPrefix(
  625. bstrErrorMessage,
  626. &ErrCode,
  627. &pwszT))
  628. {
  629. pwszT = bstrErrorMessage;
  630. }
  631. if (NULL != pwszT)
  632. {
  633. apwsz[3] = pwszT;
  634. }
  635. }
  636. }
  637. SetErrorInfo(0, pErrorInfo);
  638. pErrorInfo->Release();
  639. }
  640. }
  641. if (S_OK == ErrCode)
  642. {
  643. if (!fException && NULL == bstrErrorMessage)
  644. {
  645. goto error; // skip if no error, no exception & no com error
  646. }
  647. // This is the best generic fit for policy module initialization.
  648. // Hopefully it's generic enough to not be too confusing.
  649. ErrCode = CRYPT_E_NOT_FOUND;
  650. _PrintError(ErrCode, "Invented ErrCode");
  651. }
  652. apwsz[0] = NULL != pwszModuleDescription? pwszModuleDescription : L"";
  653. apwsz[1] = pwszMethod;
  654. // some errors like textual conversions. no HRESULT pasted on here
  655. pwszStringErr = myGetErrorMessageText(ErrCode, FALSE);
  656. PatchFormatSpecifiers(const_cast<WCHAR *>(pwszStringErr));
  657. apwsz[2] = myHResultToStringRaw(awchr, ErrCode);
  658. apwsz[4] = pwszStringErr == NULL? L"" : pwszStringErr;
  659. hr = LogEvent(EVENTLOG_ERROR_TYPE, dwIdEvent, ARRAYSIZE(apwsz), apwsz);
  660. _PrintIfError(hr, "LogEvent");
  661. }
  662. error:
  663. if (NULL != bstrErrorMessage)
  664. {
  665. SysFreeString(bstrErrorMessage);
  666. }
  667. if (NULL != pwszStringErr)
  668. {
  669. LocalFree(const_cast<WCHAR *>(pwszStringErr));
  670. }
  671. }
  672. VOID
  673. LogPolicyError(
  674. IN HRESULT ErrCode,
  675. IN WCHAR const *pwszMethod,
  676. IN BOOL fException,
  677. IN ULONG_PTR ExceptionAddress)
  678. {
  679. LogComError(
  680. g_strPolicyDescription,
  681. pwszMethod,
  682. ErrCode,
  683. fException,
  684. ExceptionAddress,
  685. &IID_ICertPolicy,
  686. fException? MSG_E_POLICY_EXCEPTION : MSG_E_POLICY_ERROR);
  687. }
  688. VOID
  689. LogExitError(
  690. IN HRESULT ErrCode,
  691. IN WCHAR const *pwszDescription,
  692. IN WCHAR const *pwszMethod,
  693. IN BOOL fException,
  694. IN ULONG_PTR ExceptionAddress)
  695. {
  696. LogComError(
  697. pwszDescription,
  698. pwszMethod,
  699. ErrCode,
  700. fException,
  701. ExceptionAddress,
  702. &IID_ICertExit,
  703. fException? MSG_E_EXIT_EXCEPTION : MSG_E_EXIT_ERROR);
  704. }
  705. HRESULT
  706. PolicyInit(
  707. IN WCHAR const *pwszConfig,
  708. IN WCHAR const *pwszSanitizedName)
  709. {
  710. HRESULT hr;
  711. DISPATCHINTERFACE *pdiPolicy;
  712. BOOL fException = FALSE;
  713. ULONG_PTR ExceptionAddress = NULL;
  714. WCHAR const *pwszPolicyMethod = L"";
  715. // support installable modules
  716. CLSID clsidPolicy;
  717. LPOLESTR lpszProgID = NULL;
  718. DBGPRINT((DBG_SS_CERTSRVI, "PolicyInit: tid=%d\n", GetCurrentThreadId()));
  719. comClearError();
  720. hr = S_OK;
  721. __try
  722. {
  723. // get active module
  724. hr = myGetActiveModule(
  725. NULL,
  726. pwszSanitizedName,
  727. TRUE,
  728. 0,
  729. &lpszProgID,
  730. &clsidPolicy);
  731. _LeaveIfError(hr, "myGetActiveModule");
  732. hr = g_miPolicy.Initialize(
  733. lpszProgID,
  734. &clsidPolicy,
  735. ARRAYSIZE(s_acPolicyDispatch),
  736. s_apPolicyiid,
  737. s_acPolicyDispatch,
  738. g_adtPolicy);
  739. _LeaveIfError(hr, "MarshalInterface::Initialize");
  740. // free olestr
  741. CoTaskMemFree(lpszProgID);
  742. hr = g_miPolicy.SetConfig(pwszConfig);
  743. _LeaveIfError(hr, "SetConfig");
  744. hr = g_miPolicy.Setup(&pdiPolicy);
  745. // Don't complain if no class is registered.
  746. _LeaveIfError2(hr, "Setup", HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  747. pwszPolicyMethod = L"GetDescription";
  748. hr = Policy_GetDescription(pdiPolicy, &g_strPolicyDescription);
  749. _PrintIfError(hr, "Policy_GetDescription");
  750. pwszPolicyMethod = L"Initialize";
  751. hr = Policy_Initialize(pdiPolicy, pwszConfig);
  752. _LeaveIfError(hr, "Policy_Initialize");
  753. g_fEnablePolicy = TRUE; // we have a policy module loaded now
  754. hr = S_OK;
  755. CONSOLEPRINT1((
  756. DBG_SS_CERTSRV,
  757. "Policy Module Enabled (%ws)\n",
  758. g_strPolicyDescription));
  759. }
  760. __except(
  761. ExceptionAddress = (ULONG_PTR) (GetExceptionInformation())->ExceptionRecord->ExceptionAddress,
  762. hr = myHEXCEPTIONCODE(),
  763. EXCEPTION_EXECUTE_HANDLER)
  764. {
  765. _PrintError(hr, "Initialize: Exception");
  766. fException = TRUE;
  767. }
  768. //error:
  769. LogPolicyError(hr, pwszPolicyMethod, fException, ExceptionAddress);
  770. return(hr);
  771. }
  772. VOID
  773. PolicyRelease(VOID)
  774. {
  775. HRESULT hr = S_OK;
  776. BOOL fException = FALSE;
  777. ULONG_PTR ExceptionAddress = NULL;
  778. DBGPRINT((DBG_SS_CERTSRV, "PolicyRelease: tid=%d\n", GetCurrentThreadId()));
  779. comClearError();
  780. __try
  781. {
  782. // if we loaded a policy module
  783. if (g_fEnablePolicy)
  784. {
  785. DISPATCHINTERFACE diPolicy;
  786. hr = g_miPolicy.Remarshal(&diPolicy);
  787. _PrintIfError(hr, "Remarshal");
  788. if (hr == S_OK)
  789. {
  790. Policy_ShutDown(&diPolicy);
  791. g_miPolicy.Unmarshal(&diPolicy);
  792. }
  793. g_fEnablePolicy = FALSE;
  794. }
  795. if (NULL != g_strPolicyDescription)
  796. {
  797. SysFreeString(g_strPolicyDescription);
  798. g_strPolicyDescription = NULL;
  799. }
  800. g_miPolicy.TearDown();
  801. }
  802. __except(
  803. ExceptionAddress = (ULONG_PTR) (GetExceptionInformation())->ExceptionRecord->ExceptionAddress,
  804. hr = myHEXCEPTIONCODE(),
  805. EXCEPTION_EXECUTE_HANDLER)
  806. {
  807. _PrintError(hr, "ShutDown: Exception");
  808. fException = TRUE;
  809. }
  810. LogPolicyError(hr, L"ShutDown", fException, ExceptionAddress);
  811. }
  812. HRESULT
  813. PolicyVerifyRequest(
  814. IN WCHAR const *pwszConfig,
  815. IN LONG RequestId,
  816. IN LONG Flags,
  817. IN BOOL fNewRequest,
  818. OPTIONAL IN CERTSRV_RESULT_CONTEXT const *pResult,
  819. IN DWORD dwComContextIndex,
  820. OUT LPWSTR *ppwszDispositionMessage, // LocalAlloced.
  821. OUT DWORD *pVerifyStatus) // VR_PENDING || VR_INSTANT_OK || VR_INSTANT_BAD
  822. {
  823. HRESULT hr;
  824. ULONG_PTR ExceptionAddress = NULL;
  825. DWORD rc;
  826. LONG Result;
  827. DISPATCHINTERFACE diPolicy;
  828. BOOL fMustRelease = FALSE;
  829. BSTR bstrDispositionDetail = NULL;
  830. CERTSRV_COM_CONTEXT *pComContext;
  831. comClearError();
  832. if (!g_fEnablePolicy)
  833. {
  834. hr = S_OK;
  835. rc = VR_INSTANT_OK;
  836. goto error;
  837. }
  838. rc = VR_INSTANT_BAD;
  839. hr = g_miPolicy.Remarshal(&diPolicy);
  840. _JumpIfError(hr, error, "Remarshal");
  841. fMustRelease = TRUE;
  842. pComContext = GetComContextFromIndex(dwComContextIndex);
  843. if (NULL == pComContext)
  844. {
  845. hr = E_HANDLE;
  846. _JumpError(hr, error, "NULL com context");
  847. }
  848. pComContext->RequestId = RequestId;
  849. if (NULL != pResult)
  850. {
  851. pComContext->dwFlags |= CCCF_KEYARCHIVEDSET;
  852. if (NULL != pResult->pbArchivedKey)
  853. {
  854. pComContext->dwFlags |= CCCF_KEYARCHIVED;
  855. }
  856. }
  857. __try
  858. {
  859. hr = Policy_VerifyRequest(
  860. &diPolicy,
  861. pwszConfig,
  862. ComContextToModuleContext(dwComContextIndex),
  863. fNewRequest,
  864. Flags,
  865. &Result);
  866. _LeaveIfError(hr, "Policy_VerifyRequest");
  867. switch (Result)
  868. {
  869. default:
  870. if (SUCCEEDED(Result))
  871. {
  872. hr = E_INVALIDARG;
  873. _LeaveError(Result, "Result");
  874. }
  875. // FALLTHROUGH
  876. case VR_PENDING:
  877. case VR_INSTANT_OK:
  878. case VR_INSTANT_BAD:
  879. rc = Result;
  880. break;
  881. }
  882. }
  883. __except(
  884. ExceptionAddress = (ULONG_PTR) (GetExceptionInformation())->ExceptionRecord->ExceptionAddress,
  885. hr = myHEXCEPTIONCODE(),
  886. EXCEPTION_EXECUTE_HANDLER)
  887. {
  888. _PrintError(hr, "VerifyRequest: Exception");
  889. LogPolicyError(hr, L"VerifyRequest", TRUE, ExceptionAddress);
  890. }
  891. pComContext->RequestId = 0;
  892. error:
  893. // Errors will be logged at the coreVerifyRequest level
  894. if (NULL != ppwszDispositionMessage)
  895. {
  896. HRESULT hr2;
  897. IErrorInfo *pErrorInfo = NULL;
  898. *ppwszDispositionMessage = NULL;
  899. hr2 = GetErrorInfo(0, &pErrorInfo);
  900. if (S_OK == hr2 && NULL != pErrorInfo)
  901. {
  902. GUID ErrorGuid;
  903. hr2 = pErrorInfo->GetGUID(&ErrorGuid);
  904. if (S_OK == hr2 && InlineIsEqualGUID(ErrorGuid, IID_ICertPolicy))
  905. {
  906. hr2 = pErrorInfo->GetDescription(&bstrDispositionDetail);
  907. if (S_OK == hr2 && NULL != bstrDispositionDetail)
  908. {
  909. myRegisterMemAlloc(bstrDispositionDetail, -1, CSM_SYSALLOC);
  910. *ppwszDispositionMessage = (LPWSTR) LocalAlloc(
  911. LMEM_FIXED,
  912. SysStringByteLen(bstrDispositionDetail) + sizeof(WCHAR));
  913. if (NULL != *ppwszDispositionMessage)
  914. {
  915. wcscpy(*ppwszDispositionMessage, bstrDispositionDetail);
  916. }
  917. SysFreeString(bstrDispositionDetail);
  918. }
  919. }
  920. SetErrorInfo(0, pErrorInfo);
  921. pErrorInfo->Release();
  922. }
  923. }
  924. if (fMustRelease)
  925. {
  926. g_miPolicy.Unmarshal(&diPolicy);
  927. }
  928. *pVerifyStatus = rc;
  929. return(hr);
  930. }
  931. typedef struct _EXITMOD
  932. {
  933. MarshalInterface *pmi;
  934. BOOL fEnabled;
  935. BSTR strDescription;
  936. LONG EventMask;
  937. } EXITMOD;
  938. BOOL g_fEnableExit = FALSE;
  939. EXITMOD *g_aExitMod = NULL;
  940. DWORD g_cExitMod;
  941. LONG g_ExitEventMask;
  942. TCHAR g_wszRegKeyExitClsid[] = wszCLASS_CERTEXIT TEXT("\\Clsid");
  943. VOID
  944. ExitModRelease(
  945. OPTIONAL IN OUT EXITMOD *pExitMod)
  946. {
  947. HRESULT hr;
  948. if (NULL != pExitMod)
  949. {
  950. MarshalInterface *pmiExit = pExitMod->pmi;
  951. if (NULL != pmiExit)
  952. {
  953. hr = S_OK;
  954. __try
  955. {
  956. pmiExit->TearDown();
  957. }
  958. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  959. {
  960. _PrintIfError(hr, "TearDown");
  961. }
  962. delete pmiExit;
  963. pExitMod->pmi = NULL;
  964. }
  965. if (NULL != pExitMod->strDescription)
  966. {
  967. SysFreeString(pExitMod->strDescription);
  968. pExitMod->strDescription = NULL;
  969. }
  970. }
  971. }
  972. HRESULT
  973. ExitModInit(
  974. IN WCHAR const *pwszProgId,
  975. IN CLSID const *pclsid,
  976. IN WCHAR const *pwszConfig)
  977. {
  978. HRESULT hr;
  979. EXITMOD *pExitMod = NULL;
  980. DISPATCHINTERFACE *pdiExit;
  981. MarshalInterface *pmiExit;
  982. CERTSRV_COM_CONTEXT ComContext;
  983. BOOL fException = FALSE;
  984. ULONG_PTR ExceptionAddress = NULL;
  985. comClearError();
  986. hr = S_OK;
  987. __try
  988. {
  989. if (0 == g_cExitMod)
  990. {
  991. pExitMod = (EXITMOD *) LocalAlloc(LMEM_FIXED, sizeof(*g_aExitMod));
  992. }
  993. else
  994. {
  995. pExitMod = (EXITMOD *) LocalReAlloc(
  996. g_aExitMod,
  997. (g_cExitMod + 1) * sizeof(*g_aExitMod),
  998. LMEM_MOVEABLE);
  999. }
  1000. if (NULL == pExitMod)
  1001. {
  1002. hr = E_OUTOFMEMORY;
  1003. _JumpError(hr, error, 0 == g_cExitMod? "LocalAlloc" : "LocalReAlloc");
  1004. }
  1005. g_aExitMod = pExitMod;
  1006. pExitMod += g_cExitMod++;
  1007. // Zero structure here because a previous failed Exit Module load may
  1008. // leave garbage in leftover structure, causing LocalReAlloc to do
  1009. // nothing.
  1010. ZeroMemory(pExitMod, sizeof(*pExitMod));
  1011. pmiExit = new MarshalInterface;
  1012. if (NULL == pmiExit)
  1013. {
  1014. hr = E_OUTOFMEMORY;
  1015. _JumpError(hr, error, "new");
  1016. }
  1017. pExitMod->pmi = pmiExit;
  1018. hr = pmiExit->Initialize(
  1019. pwszProgId,
  1020. pclsid,
  1021. ARRAYSIZE(s_acExitDispatch),
  1022. s_apExitiid,
  1023. s_acExitDispatch,
  1024. g_adtExit);
  1025. _JumpIfError(hr, error, "MarshalInterface::Initialize");
  1026. hr = pmiExit->SetConfig(pwszConfig);
  1027. _JumpIfError(hr, error, "SetConfig");
  1028. hr = pmiExit->Setup(&pdiExit);
  1029. // Don't complain if no class is registered.
  1030. _JumpIfError2(hr, error, "Setup", HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  1031. ComContext.iExitModActive = g_cExitMod - 1;
  1032. g_pExitComContext = &ComContext;
  1033. hr = Exit_GetDescription(pdiExit, &pExitMod->strDescription);
  1034. _PrintIfError(hr, "Exit_GetDescription");
  1035. hr = Exit_Initialize(
  1036. pdiExit,
  1037. pwszConfig,
  1038. &pExitMod->EventMask);
  1039. _JumpIfError(hr, error, "Exit_Initialize");
  1040. pExitMod->fEnabled = TRUE;
  1041. g_fEnableExit = TRUE; // we have at least one exit module loaded now
  1042. g_ExitEventMask |= pExitMod->EventMask;
  1043. hr = S_OK;
  1044. CONSOLEPRINT3((
  1045. DBG_SS_CERTSRV,
  1046. "Exit Module[%d] Enabled: %x (%ws)\n",
  1047. g_cExitMod,
  1048. pExitMod->EventMask,
  1049. pExitMod->strDescription));
  1050. }
  1051. __except(
  1052. ExceptionAddress = (ULONG_PTR) (GetExceptionInformation())->ExceptionRecord->ExceptionAddress,
  1053. hr = myHEXCEPTIONCODE(),
  1054. EXCEPTION_EXECUTE_HANDLER)
  1055. {
  1056. _PrintError(hr, "Initialize: Exception");
  1057. fException = TRUE;
  1058. }
  1059. error:
  1060. LogExitError(
  1061. hr,
  1062. NULL != pExitMod? pExitMod->strDescription : NULL,
  1063. L"Initialize",
  1064. fException,
  1065. ExceptionAddress);
  1066. if (S_OK != hr && NULL != pExitMod)
  1067. {
  1068. ExitModRelease(pExitMod);
  1069. CSASSERT(0 != g_cExitMod);
  1070. g_cExitMod--;
  1071. }
  1072. // reset
  1073. g_pExitComContext = NULL;
  1074. return(hr);
  1075. }
  1076. HRESULT
  1077. ExitModNotify(
  1078. IN EXITMOD *pExitMod,
  1079. IN LONG Event,
  1080. IN LONG RequestId,
  1081. IN DWORD dwComContextIndex)
  1082. {
  1083. HRESULT hr;
  1084. DISPATCHINTERFACE diExit;
  1085. BOOL fMustRelease = FALSE;
  1086. CERTSRV_COM_CONTEXT *pComContext;
  1087. BOOL fException = FALSE;
  1088. ULONG_PTR ExceptionAddress = NULL;
  1089. comClearError();
  1090. hr = S_OK;
  1091. __try
  1092. {
  1093. if (!pExitMod->fEnabled || 0 == (Event & pExitMod->EventMask))
  1094. {
  1095. goto error;
  1096. }
  1097. hr = pExitMod->pmi->Remarshal(&diExit);
  1098. _JumpIfError(hr, error, "Remarshal");
  1099. fMustRelease = TRUE;
  1100. pComContext = GetComContextFromIndex(dwComContextIndex);
  1101. if (NULL == pComContext)
  1102. {
  1103. hr = E_HANDLE;
  1104. _JumpError(hr, error, "null com context");
  1105. }
  1106. pComContext->RequestId = RequestId;
  1107. hr = Exit_Notify(
  1108. &diExit,
  1109. Event,
  1110. ComContextToModuleContext(dwComContextIndex));
  1111. pComContext->RequestId = 0;
  1112. if (S_OK != hr)
  1113. {
  1114. //_PrintError(hr, "Exit_Notify");
  1115. goto error;
  1116. }
  1117. }
  1118. __except(
  1119. ExceptionAddress = (ULONG_PTR) (GetExceptionInformation())->ExceptionRecord->ExceptionAddress,
  1120. hr = myHEXCEPTIONCODE(),
  1121. EXCEPTION_EXECUTE_HANDLER)
  1122. {
  1123. _PrintError(hr, "Notify: Exception");
  1124. fException = TRUE;
  1125. }
  1126. error:
  1127. LogExitError(
  1128. hr,
  1129. pExitMod->strDescription,
  1130. L"Notify",
  1131. fException,
  1132. ExceptionAddress);
  1133. if (fMustRelease)
  1134. {
  1135. pExitMod->pmi->Unmarshal(&diExit);
  1136. }
  1137. return(hr);
  1138. }
  1139. HRESULT
  1140. ExitInit(
  1141. IN WCHAR const *pwszConfig,
  1142. IN WCHAR const *pwszSanitizedName)
  1143. {
  1144. HRESULT hr;
  1145. LPOLESTR pwszProgId = NULL;
  1146. CLSID clsid;
  1147. DWORD i;
  1148. CSASSERT(NULL == g_aExitMod);
  1149. CSASSERT(0 == g_cExitMod);
  1150. CSASSERT(0 == g_ExitEventMask);
  1151. CSASSERT(!g_fEnableExit);
  1152. for (i = 0; ; i++)
  1153. {
  1154. if (NULL != pwszProgId)
  1155. {
  1156. CoTaskMemFree(pwszProgId);
  1157. pwszProgId = NULL;
  1158. }
  1159. // get active module
  1160. hr = myGetActiveModule(
  1161. NULL,
  1162. pwszSanitizedName,
  1163. FALSE,
  1164. i,
  1165. &pwszProgId,
  1166. &clsid);
  1167. _JumpIfError(hr, error, "myGetActiveModule");
  1168. hr = ExitModInit(pwszProgId, &clsid, pwszConfig);
  1169. _PrintIfError(hr, "ExitModInit");
  1170. }
  1171. // NOTREACHED
  1172. error:
  1173. if (NULL != pwszProgId)
  1174. {
  1175. CoTaskMemFree(pwszProgId);
  1176. }
  1177. return(hr);
  1178. }
  1179. VOID
  1180. ExitRelease(VOID)
  1181. {
  1182. ExitNotify(EXITEVENT_SHUTDOWN, 0, NULL, MAXDWORD);
  1183. for ( ; 0 != g_cExitMod; g_cExitMod--)
  1184. {
  1185. ExitModRelease(&g_aExitMod[g_cExitMod - 1]);
  1186. }
  1187. if (g_aExitMod)
  1188. {
  1189. LocalFree(g_aExitMod);
  1190. g_aExitMod = NULL;
  1191. }
  1192. }
  1193. HRESULT
  1194. ExitNotify(
  1195. IN LONG Event,
  1196. IN LONG RequestId,
  1197. OPTIONAL IN CERTSRV_RESULT_CONTEXT const *pResult,
  1198. IN DWORD dwComContextIndex)
  1199. {
  1200. HRESULT hr = S_OK;
  1201. HRESULT hr2;
  1202. CERTSRV_COM_CONTEXT ComContext;
  1203. CERTSRV_COM_CONTEXT *pComContext;
  1204. BOOL fRegComContext = FALSE;
  1205. if (MAXDWORD == dwComContextIndex)
  1206. {
  1207. ZeroMemory(&ComContext, sizeof(ComContext));
  1208. pComContext = &ComContext;
  1209. hr = RegisterComContext(pComContext, &dwComContextIndex);
  1210. _JumpIfError(hr, error, "RegisterComContext");
  1211. fRegComContext = TRUE;
  1212. }
  1213. else
  1214. {
  1215. pComContext = GetComContextFromIndex(dwComContextIndex);
  1216. if (NULL == pComContext)
  1217. {
  1218. hr = E_HANDLE;
  1219. _JumpError(hr, error, "null com context");
  1220. }
  1221. }
  1222. if (NULL != pResult)
  1223. {
  1224. pComContext->dwFlags |= CCCF_KEYARCHIVEDSET;
  1225. if (NULL != pResult->pbArchivedKey)
  1226. {
  1227. pComContext->dwFlags |= CCCF_KEYARCHIVED;
  1228. }
  1229. }
  1230. CSASSERT(0 == (Event & (Event >> 1))); // must be a single bit!
  1231. if (!g_fEnableExit || 0 == (Event & g_ExitEventMask))
  1232. {
  1233. goto error;
  1234. }
  1235. for (
  1236. pComContext->iExitModActive = 0;
  1237. pComContext->iExitModActive < g_cExitMod;
  1238. pComContext->iExitModActive++)
  1239. {
  1240. hr2 = ExitModNotify(
  1241. &g_aExitMod[pComContext->iExitModActive],
  1242. Event,
  1243. RequestId,
  1244. dwComContextIndex);
  1245. if (S_OK == hr)
  1246. {
  1247. hr = hr2;
  1248. }
  1249. _PrintIfError(hr2, "ExitModNotify");
  1250. }
  1251. error:
  1252. if (fRegComContext)
  1253. {
  1254. // context is used in local
  1255. UnregisterComContext(&ComContext, dwComContextIndex);
  1256. }
  1257. else if (NULL != pComContext)
  1258. {
  1259. // return index
  1260. pComContext->iExitModActive = 0;
  1261. }
  1262. return(hr);
  1263. }
  1264. HRESULT
  1265. ExitGetActiveModule(
  1266. IN LONG Context,
  1267. OUT MarshalInterface **ppmi)
  1268. {
  1269. HRESULT hr;
  1270. // This is for exit module only, it expects Context
  1271. // to be 0. It will use g_pExitComContext instead of table
  1272. // init
  1273. *ppmi = NULL;
  1274. #if 0
  1275. DWORD dwIndex;
  1276. hr = ModuleContextToComContextIndex(Context, &dwIndex);
  1277. _JumpIfError(hr, error, "ModuleContextToComContextIndex");
  1278. // return
  1279. *ppmi =
  1280. g_aExitMod[g_pComContextTable[dwIndex].pComContext->iExitModActive].pmi;
  1281. #endif
  1282. CSASSERT(0 == Context);
  1283. CSASSERT(NULL != g_pExitComContext);
  1284. if (0 != Context || NULL == g_pExitComContext)
  1285. {
  1286. hr = E_UNEXPECTED;
  1287. _JumpError(hr, error, "unexpected exit context");
  1288. }
  1289. // return
  1290. *ppmi = g_aExitMod[g_pExitComContext->iExitModActive].pmi;
  1291. hr = S_OK;
  1292. error:
  1293. return (hr);
  1294. }
  1295. HRESULT
  1296. ComGetClientInfo(
  1297. IN LONG Context,
  1298. IN DWORD dwComContextIndex,
  1299. OUT CERTSRV_COM_CONTEXT **ppComContext)
  1300. {
  1301. HRESULT hr;
  1302. *ppComContext = NULL;
  1303. if (MAXDWORD == dwComContextIndex)
  1304. {
  1305. hr = ModuleContextToComContextIndex(Context, &dwComContextIndex);
  1306. _JumpIfError(hr, error, "ModuleContextToComContextIndex");
  1307. }
  1308. *ppComContext = g_pComContextTable[dwComContextIndex].pComContext;
  1309. hr = S_OK;
  1310. error:
  1311. return(hr);
  1312. }
  1313. BSTR
  1314. ExitGetDescription(
  1315. IN DWORD iExitMod)
  1316. {
  1317. BSTR str = NULL;
  1318. if (iExitMod < g_cExitMod)
  1319. {
  1320. str = g_aExitMod[iExitMod].strDescription;
  1321. }
  1322. return(str);
  1323. }