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.

2035 lines
50 KiB

  1. //+--------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 1999
  5. //
  6. // File: request.cpp
  7. //
  8. // Contents: Implementation of DCOM object for RPC services
  9. //
  10. // History: July-97 xtan created
  11. //
  12. //---------------------------------------------------------------------------
  13. #include <pch.cpp>
  14. #pragma hdrstop
  15. #include <stdio.h>
  16. #include <accctrl.h>
  17. #include "cscom.h"
  18. #include "csprop.h"
  19. #include "certsrvd.h"
  20. #include "request.h"
  21. #include "certacl.h"
  22. #include "tmpllist.h"
  23. #define __dwFILE__ __dwFILE_CERTSRV_REQUEST_CPP__
  24. extern HINSTANCE g_hInstApp;
  25. extern const GUID *g_guidAdmin[1];
  26. extern const GUID *g_guidsReadAdminOfficer[3];
  27. // Global variables
  28. long g_cRequestComponents = 0; // Count of active components
  29. long g_cRequestServerLocks = 0; // Count of locks
  30. DWORD g_dwRequestRegister = 0;
  31. IClassFactory* g_pIRequestFactory = NULL;
  32. // Sequence# incremented every time the CA template list is changed.
  33. // Policy module detects any changes to this number and refreshes its
  34. // template data from DS.
  35. long g_cTemplateUpdateSequenceNum = 0;
  36. #ifdef DBG_CERTSRV_DEBUG_PRINT
  37. DWORD s_ssRequest = DBG_SS_CERTSRVI;
  38. #endif
  39. using namespace CertSrv;
  40. #ifndef CERTSRV_E_UNKNOWN_CERT_TYPE
  41. // begin implementation of component functions
  42. // Request component
  43. // begin implementing cert request services
  44. //
  45. // MessageId: CERTSRV_E_UNKNOWN_CERT_TYPE
  46. //
  47. // MessageText:
  48. //
  49. // One or more certificate templates to be enabled on this certification authority could not be found.
  50. //
  51. #define CERTSRV_E_UNKNOWN_CERT_TYPE _HRESULT_TYPEDEF_(0x80094010L)
  52. //
  53. // MessageId: CERTSRV_E_ENROLL_DENIED
  54. //
  55. // MessageText:
  56. //
  57. // The permissions on this certification authority do not allow current user to enroll for certificates.
  58. //
  59. #define CERTSRV_E_ENROLL_DENIED _HRESULT_TYPEDEF_(0x80094011L)
  60. #endif // CERTSRV_E_UNKNOWN_CERT_TYPE
  61. HRESULT RequestAccessCheck(
  62. OPTIONAL OUT BOOL *pfInRequesterGroup = NULL,
  63. OPTIONAL OUT HANDLE *phToken = NULL)
  64. {
  65. HRESULT hr = S_OK;
  66. CAuditEvent audit(0, g_dwAuditFilter);
  67. BOOL fInRequesterGroup = FALSE;
  68. hr = audit.AccessCheck(
  69. CA_ACCESS_ENROLL,
  70. audit.m_gcNoAuditSuccess |
  71. audit.m_gcNoAuditFailure,
  72. NULL,
  73. phToken);
  74. if(S_OK==hr)
  75. {
  76. fInRequesterGroup = TRUE;
  77. }
  78. if(pfInRequesterGroup)
  79. *pfInRequesterGroup = fInRequesterGroup;
  80. if(E_ACCESSDENIED==hr)
  81. {
  82. // When this flag is set, ICertReq calls should immediately return
  83. // if access is denied. If not set, we ignore access denied error
  84. // but pass down the result to the policy module through fInRequesterGroup
  85. if(g_fLockICertRequest)
  86. {
  87. hr = CERTSRV_E_ENROLL_DENIED;
  88. }
  89. else
  90. {
  91. hr = S_OK;
  92. }
  93. }
  94. _JumpIfError(hr, error, "CAuditEvent::AccessCheck");
  95. error:
  96. return hr;
  97. }
  98. VOID
  99. ReleaseResult(
  100. IN OUT CERTSRV_RESULT_CONTEXT *pResult)
  101. {
  102. if (NULL != pResult->pbSenderNonce)
  103. {
  104. LocalFree(pResult->pbSenderNonce);
  105. }
  106. if (NULL != pResult->pbKeyHashIn)
  107. {
  108. LocalFree(pResult->pbKeyHashIn);
  109. }
  110. if (NULL != pResult->pbKeyHashOut)
  111. {
  112. LocalFree(pResult->pbKeyHashOut);
  113. }
  114. }
  115. STDMETHODIMP
  116. CCertRequestD::Request(
  117. /* [in] */ DWORD dwFlags,
  118. /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority,
  119. /* [ref][out][in] */ DWORD __RPC_FAR *pdwRequestId,
  120. /* [out] */ DWORD __RPC_FAR *pdwDisposition,
  121. /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAttributes,
  122. /* [ref][in] */ CERTTRANSBLOB const __RPC_FAR *pctbRequest,
  123. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbCertChain,
  124. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbEncodedCert,
  125. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbDispositionMessage)
  126. {
  127. HRESULT hr;
  128. WCHAR const *pwszSerialNumber = NULL;
  129. CERTSRV_RESULT_CONTEXT Result;
  130. ZeroMemory(&Result, sizeof(Result));
  131. if (NULL != pctbRequest && NULL == pctbRequest->pb)
  132. {
  133. // RetrievePending by SerialNumber in pwszAttributes
  134. pwszSerialNumber = pwszAttributes;
  135. pwszAttributes = NULL;
  136. }
  137. Result.pdwRequestId = pdwRequestId;
  138. Result.pdwDisposition = pdwDisposition;
  139. Result.pctbDispositionMessage = pctbDispositionMessage;
  140. Result.pctbCert = pctbEncodedCert;
  141. Result.pctbCertChain = pctbCertChain;
  142. hr = _Request(
  143. pwszAuthority,
  144. dwFlags,
  145. pwszSerialNumber,
  146. *pdwRequestId,
  147. pwszAttributes,
  148. pctbRequest,
  149. &Result);
  150. _JumpIfError(hr, error, "Request");
  151. error:
  152. ReleaseResult(&Result);
  153. CSASSERT(S_OK == hr || FAILED(hr));
  154. return(hr);
  155. }
  156. STDMETHODIMP
  157. CCertRequestD::Request2(
  158. /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAuthority,
  159. /* [in] */ DWORD dwFlags,
  160. /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszSerialNumber,
  161. /* [ref][out][in] */ DWORD __RPC_FAR *pdwRequestId,
  162. /* [out] */ DWORD __RPC_FAR *pdwDisposition,
  163. /* [unique][string][in] */ const wchar_t __RPC_FAR *pwszAttributes,
  164. /* [ref][in] */ const CERTTRANSBLOB __RPC_FAR *pctbRequest,
  165. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbFullResponse,
  166. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbEncodedCert,
  167. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbDispositionMessage)
  168. {
  169. HRESULT hr;
  170. CERTSRV_RESULT_CONTEXT Result;
  171. ZeroMemory(&Result, sizeof(Result));
  172. Result.pdwRequestId = pdwRequestId;
  173. Result.pdwDisposition = pdwDisposition;
  174. Result.pctbDispositionMessage = pctbDispositionMessage;
  175. Result.pctbCert = pctbEncodedCert;
  176. if (CR_IN_FULLRESPONSE & dwFlags)
  177. {
  178. Result.pctbFullResponse = pctbFullResponse;
  179. }
  180. else
  181. {
  182. Result.pctbCertChain = pctbFullResponse;
  183. }
  184. hr = _Request(
  185. pwszAuthority,
  186. dwFlags,
  187. pwszSerialNumber,
  188. *pdwRequestId,
  189. pwszAttributes,
  190. pctbRequest,
  191. &Result);
  192. _JumpIfError(hr, error, "Request2");
  193. error:
  194. ReleaseResult(&Result);
  195. CSASSERT(S_OK == hr || FAILED(hr));
  196. return(hr);
  197. }
  198. VOID
  199. requestRegisterMemFreeBlob(
  200. OPTIONAL CERTTRANSBLOB const *pctb)
  201. {
  202. if (NULL != pctb && NULL != pctb->pb)
  203. {
  204. myRegisterMemFree(pctb->pb, CSM_MIDLUSERALLOC);
  205. }
  206. }
  207. HRESULT
  208. CCertRequestD::_Request(
  209. IN WCHAR const *pwszAuthority,
  210. IN DWORD dwFlags,
  211. OPTIONAL IN WCHAR const *pwszSerialNumber,
  212. IN DWORD dwRequestId,
  213. OPTIONAL IN WCHAR const *pwszAttributes,
  214. OPTIONAL IN CERTTRANSBLOB const *pctbRequest,
  215. OUT CERTSRV_RESULT_CONTEXT *pResult)
  216. {
  217. HRESULT hr;
  218. DWORD OpRequest;
  219. WCHAR *pwszUserName = NULL;
  220. DWORD dwComContextIndex = MAXDWORD;
  221. CERTSRV_COM_CONTEXT ComContext;
  222. DWORD State = 0;
  223. DBGPRINT((
  224. s_ssRequest,
  225. "CCertRequestD::Request2(tid=%d)\n",
  226. GetCurrentThreadId()));
  227. ZeroMemory(&ComContext, sizeof(ComContext));
  228. //ComContext.pwszUserDN = NULL;
  229. //ComContext.hAccessToken = NULL;
  230. hr = CertSrvEnterServer(&State);
  231. _JumpIfError(hr, error, "CertSrvEnterServer");
  232. hr = CheckAuthorityName(pwszAuthority);
  233. _JumpIfError(hr, error, "No authority name");
  234. hr = RegisterComContext(&ComContext, &dwComContextIndex);
  235. _JumpIfError(hr, error, "RegsiterComContext");
  236. __try
  237. {
  238. hr = RequestAccessCheck(
  239. &ComContext.fInRequestGroup,
  240. &ComContext.hAccessToken);
  241. _LeaveIfError(hr, "RequestAccessCheck");
  242. // Set up default output parameters:
  243. *pResult->pdwRequestId = 0;
  244. *pResult->pdwDisposition = CR_DISP_ERROR;
  245. OpRequest = CR_IN_RETRIEVE;
  246. if (NULL != pctbRequest->pb)
  247. {
  248. OpRequest = CR_IN_NEW;
  249. }
  250. hr = GetClientUserName(
  251. NULL,
  252. &pwszUserName,
  253. CR_IN_NEW == OpRequest && IsEnterpriseCA(g_CAType)?
  254. &ComContext.pwszUserDN : NULL);
  255. _LeaveIfError(hr, "GetClientUserName");
  256. hr = CoreProcessRequest(
  257. OpRequest | (dwFlags & ~CR_IN_COREMASK),
  258. pwszUserName,
  259. pctbRequest->cb, // cbRequest
  260. pctbRequest->pb, // pbRequest
  261. pwszAttributes,
  262. pwszSerialNumber,
  263. dwComContextIndex,
  264. dwRequestId,
  265. pResult); // Allocates returned memory
  266. if (S_OK != hr)
  267. {
  268. hr = myHError(hr);
  269. _LeaveError(hr, "CoreProcessRequest");
  270. }
  271. requestRegisterMemFreeBlob(pResult->pctbDispositionMessage);
  272. requestRegisterMemFreeBlob(pResult->pctbCert);
  273. requestRegisterMemFreeBlob(pResult->pctbCertChain);
  274. requestRegisterMemFreeBlob(pResult->pctbFullResponse);
  275. }
  276. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  277. {
  278. _PrintError(hr, "Exception");
  279. }
  280. error:
  281. // CloseHandle can throw an exception
  282. if (NULL != ComContext.hAccessToken)
  283. {
  284. __try
  285. {
  286. CloseHandle(ComContext.hAccessToken);
  287. }
  288. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  289. {
  290. _PrintError(hr, "Exception");
  291. }
  292. }
  293. if (NULL != pwszUserName)
  294. {
  295. LocalFree(pwszUserName);
  296. }
  297. if (MAXDWORD != dwComContextIndex)
  298. {
  299. if (NULL != ComContext.pwszUserDN)
  300. {
  301. LocalFree(ComContext.pwszUserDN);
  302. }
  303. UnregisterComContext(&ComContext, dwComContextIndex);
  304. }
  305. CertSrvExitServer(State);
  306. CSASSERT(S_OK == hr || FAILED(hr));
  307. return(hr);
  308. }
  309. #define MAX_VERSION_RESOURCE_SIZE 64
  310. HRESULT
  311. GetVersionString(
  312. IN DWORD type,
  313. OUT WCHAR *pwszVersion)
  314. {
  315. HRESULT hr;
  316. typedef struct _MY_RESOURCE_DATA
  317. {
  318. USHORT TotalSize;
  319. USHORT DataSize;
  320. USHORT Type;
  321. WCHAR Name[16]; // L"VS_VERSION_INFO" + unicode nul
  322. VS_FIXEDFILEINFO FixedFileInfo;
  323. } MY_RESOURCE_DATA;
  324. MY_RESOURCE_DATA *pResource;
  325. HRSRC hrsc;
  326. HGLOBAL hg;
  327. // FindResource: don't need to free hrsc
  328. hrsc = FindResource(g_hInstApp, MAKEINTRESOURCE(1), RT_VERSION);
  329. if (NULL == hrsc)
  330. {
  331. hr = myHLastError();
  332. _JumpError(hr, error, "FindResource");
  333. }
  334. // LoadResource: don't need to free HGLOBAL
  335. hg = LoadResource(g_hInstApp, hrsc);
  336. if (NULL == hg)
  337. {
  338. hr = myHLastError();
  339. _JumpError(hr, error, "LoadResource");
  340. }
  341. // LockResource: don't need to free pResource
  342. pResource = (MY_RESOURCE_DATA *) LockResource(hg);
  343. if (NULL == pResource)
  344. {
  345. hr = myHLastError();
  346. if (S_OK == hr) // LockResource isn't doc'd to use SetLastError
  347. {
  348. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  349. }
  350. _JumpError(hr, error, "LockResource");
  351. }
  352. if (0 != lstrcmpi(pResource->Name, L"VS_VERSION_INFO"))
  353. {
  354. hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
  355. goto error;
  356. }
  357. if (CR_PROP_FILEVERSION == type)
  358. {
  359. wsprintf(
  360. pwszVersion,
  361. L"%d.%d:%d.%d",
  362. HIWORD(pResource->FixedFileInfo.dwFileVersionMS),
  363. LOWORD(pResource->FixedFileInfo.dwFileVersionMS),
  364. HIWORD(pResource->FixedFileInfo.dwFileVersionLS),
  365. LOWORD(pResource->FixedFileInfo.dwFileVersionLS));
  366. }
  367. else
  368. {
  369. wsprintf(
  370. pwszVersion,
  371. L"%d.%d:%d.%d",
  372. HIWORD(pResource->FixedFileInfo.dwProductVersionMS),
  373. LOWORD(pResource->FixedFileInfo.dwProductVersionMS),
  374. HIWORD(pResource->FixedFileInfo.dwProductVersionLS),
  375. LOWORD(pResource->FixedFileInfo.dwProductVersionLS));
  376. }
  377. hr = S_OK;
  378. error:
  379. return(hr);
  380. }
  381. // for ICertRequest2::GetCAProperty & ICertAdmin2::GetCAProperty
  382. LONG g_CAPropIdMax = 0;
  383. CAPROP g_aCAProp[] = {
  384. { CR_PROP_FILEVERSION, PROPTYPE_STRING, },
  385. { CR_PROP_PRODUCTVERSION, PROPTYPE_STRING, },
  386. { CR_PROP_EXITCOUNT, PROPTYPE_LONG, },
  387. { CR_PROP_EXITDESCRIPTION, PROPTYPE_STRING | PROPFLAGS_INDEXED, },
  388. { CR_PROP_POLICYDESCRIPTION, PROPTYPE_STRING, },
  389. { CR_PROP_CANAME, PROPTYPE_STRING, },
  390. { CR_PROP_SANITIZEDCANAME, PROPTYPE_STRING, },
  391. { CR_PROP_SHAREDFOLDER, PROPTYPE_STRING, },
  392. { CR_PROP_PARENTCA, PROPTYPE_STRING, FALSE, },
  393. { CR_PROP_CATYPE, PROPTYPE_LONG, },
  394. { CR_PROP_CASIGCERTCOUNT, PROPTYPE_LONG, },
  395. { CR_PROP_CASIGCERT, PROPTYPE_BINARY | PROPFLAGS_INDEXED, },
  396. { CR_PROP_CASIGCERTCHAIN, PROPTYPE_BINARY | PROPFLAGS_INDEXED, },
  397. { CR_PROP_CAXCHGCERTCOUNT, PROPTYPE_LONG, },
  398. { CR_PROP_CAXCHGCERT, PROPTYPE_BINARY | PROPFLAGS_INDEXED, },
  399. { CR_PROP_CAXCHGCERTCHAIN, PROPTYPE_BINARY | PROPFLAGS_INDEXED, },
  400. { CR_PROP_BASECRL, PROPTYPE_BINARY | PROPFLAGS_INDEXED, },
  401. { CR_PROP_DELTACRL, PROPTYPE_BINARY | PROPFLAGS_INDEXED, },
  402. { CR_PROP_CACERTSTATE, PROPTYPE_LONG | PROPFLAGS_INDEXED, },
  403. { CR_PROP_CRLSTATE, PROPTYPE_LONG | PROPFLAGS_INDEXED, },
  404. { CR_PROP_CAPROPIDMAX, PROPTYPE_LONG, },
  405. { CR_PROP_DNSNAME, PROPTYPE_STRING, },
  406. // { CR_PROP_ROLESEPARATIONENABLED, PROPTYPE_LONG, },
  407. { CR_PROP_KRACERTUSEDCOUNT, PROPTYPE_LONG, },
  408. { CR_PROP_KRACERTCOUNT, PROPTYPE_LONG, },
  409. { CR_PROP_KRACERT, PROPTYPE_BINARY | PROPFLAGS_INDEXED, },
  410. { CR_PROP_KRACERTSTATE, PROPTYPE_LONG | PROPFLAGS_INDEXED, },
  411. { CR_PROP_ADVANCEDSERVER,PROPTYPE_LONG, },
  412. { CR_PROP_TEMPLATES, PROPTYPE_STRING, },
  413. { CR_PROP_BASECRLPUBLISHSTATUS, PROPTYPE_LONG | PROPFLAGS_INDEXED, },
  414. { CR_PROP_DELTACRLPUBLISHSTATUS, PROPTYPE_LONG | PROPFLAGS_INDEXED, },
  415. { CR_PROP_CASIGCERTCRLCHAIN, PROPTYPE_BINARY | PROPFLAGS_INDEXED, },
  416. { CR_PROP_CAXCHGCERTCRLCHAIN,PROPTYPE_BINARY | PROPFLAGS_INDEXED, },
  417. { CR_PROP_CACERTSTATUSCODE, PROPTYPE_LONG | PROPFLAGS_INDEXED, },
  418. };
  419. // Map old ICertRequest::GetCACertificate calls to ICertRequest2::GetCAProperty
  420. typedef struct _GETCERTMAP {
  421. DWORD dwGetCert;
  422. LONG lPropId;
  423. LONG lPropType;
  424. } GETCERTMAP;
  425. GETCERTMAP g_aCAPropMap[] = {
  426. { GETCERT_FILEVERSION, CR_PROP_FILEVERSION, PROPTYPE_STRING, },
  427. { GETCERT_PRODUCTVERSION, CR_PROP_PRODUCTVERSION, PROPTYPE_STRING, },
  428. { GETCERT_EXITVERSIONBYINDEX, CR_PROP_EXITDESCRIPTION, PROPTYPE_STRING, },
  429. { GETCERT_POLICYVERSION, CR_PROP_POLICYDESCRIPTION, PROPTYPE_STRING, },
  430. { GETCERT_CANAME, CR_PROP_CANAME, PROPTYPE_STRING, },
  431. { GETCERT_SANITIZEDCANAME, CR_PROP_SANITIZEDCANAME, PROPTYPE_STRING, },
  432. { GETCERT_SHAREDFOLDER, CR_PROP_SHAREDFOLDER, PROPTYPE_STRING, },
  433. { GETCERT_PARENTCONFIG, CR_PROP_PARENTCA, PROPTYPE_STRING, },
  434. { GETCERT_CAINFO, CR_PROP_CATYPE, PROPTYPE_LONG, },
  435. { GETCERT_CACERTBYINDEX, CR_PROP_CASIGCERT, PROPTYPE_BINARY, },
  436. { GETCERT_CRLBYINDEX, CR_PROP_BASECRL, PROPTYPE_BINARY, },
  437. { GETCERT_CACERTSTATEBYINDEX, CR_PROP_CACERTSTATE, PROPTYPE_LONG, },
  438. { GETCERT_CRLSTATEBYINDEX, CR_PROP_CRLSTATE, PROPTYPE_LONG, },
  439. };
  440. // Handled via code hacks:
  441. //{ GETCERT_CASIGCERT, CR_PROP_CASIGCERTCRLCHAIN, PROPTYPE_BINARY, },
  442. //{ GETCERT_CASIGCERT, CR_PROP_CASIGCERTCHAIN, PROPTYPE_BINARY, },
  443. //{ GETCERT_CASIGCERT, CR_PROP_CASIGCERT, PROPTYPE_BINARY, },
  444. //{ GETCERT_CAXCHGCERT, CR_PROP_CAXCHGCERT, PROPTYPE_BINARY, },
  445. //{ GETCERT_CAXCHGCERT, CR_PROP_CAXCHGCERTCRLCHAIN,PROPTYPE_BINARY, },
  446. //{ GETCERT_CAXCHGCERT, CR_PROP_CAXCHGCERTCHAIN, PROPTYPE_BINARY, },
  447. //{ GETCERT_CURRENTCRL, CR_PROP_BASECRL, PROPTYPE_BINARY, },
  448. //{ GETCERT_CATYPE, CR_PROP_CATYPE, PROPTYPE_LONG, },
  449. HRESULT
  450. RequestInitCAPropertyInfo(VOID)
  451. {
  452. HRESULT hr;
  453. CAPROP *pcap;
  454. g_CAPropIdMax = 0;
  455. for (pcap = g_aCAProp; pcap < &g_aCAProp[ARRAYSIZE(g_aCAProp)]; pcap++)
  456. {
  457. hr = myCAPropGetDisplayName(pcap->lPropId, &pcap->pwszDisplayName);
  458. if (S_OK != hr)
  459. {
  460. DBGPRINT((
  461. DBG_SS_CERTSRVI,
  462. "myCAPropGetDisplayName(%u)\n",
  463. pcap->lPropId));
  464. _PrintError(hr, "myCAPropGetDisplayName");
  465. }
  466. if (g_CAPropIdMax < pcap->lPropId)
  467. {
  468. g_CAPropIdMax = pcap->lPropId;
  469. }
  470. }
  471. return(S_OK);
  472. }
  473. HRESULT
  474. RequestGetCAPropertyInfo(
  475. OUT LONG *pcProperty,
  476. OUT CERTTRANSBLOB *pctbPropInfo)
  477. {
  478. HRESULT hr;
  479. LONG i;
  480. DWORD cb;
  481. DWORD cbT;
  482. CAPROP *rgcap = NULL;
  483. CAPROP *pcap;
  484. CAPROP *pcapEnd;
  485. pctbPropInfo->pb = NULL;
  486. pctbPropInfo->cb = 0;
  487. __try
  488. {
  489. cb = sizeof(g_aCAProp);
  490. for (i = 0; i < ARRAYSIZE(g_aCAProp); i++)
  491. {
  492. if (NULL != g_aCAProp[i].pwszDisplayName)
  493. {
  494. cbT = (wcslen(g_aCAProp[i].pwszDisplayName) + 1) * sizeof(WCHAR);
  495. cb += DWORDROUND(cbT);
  496. }
  497. }
  498. rgcap = (CAPROP *) MIDL_user_allocate(cb);
  499. if (NULL == rgcap)
  500. {
  501. hr = E_OUTOFMEMORY;
  502. _LeaveError(hr, "MIDL_user_allocate rgcap");
  503. }
  504. CopyMemory(rgcap, g_aCAProp, sizeof(g_aCAProp));
  505. cb = sizeof(g_aCAProp);
  506. pcapEnd = &rgcap[ARRAYSIZE(g_aCAProp)];
  507. for (pcap = rgcap; pcap < pcapEnd; pcap++)
  508. {
  509. DBGPRINT((
  510. DBG_SS_CERTSRVI,
  511. "RequestGetCAPropertyInfo: ielt=%d idx=%x t=%x \"%ws\"\n",
  512. pcap - rgcap,
  513. pcap->lPropId,
  514. pcap->lPropFlags,
  515. pcap->pwszDisplayName));
  516. if (NULL != pcap->pwszDisplayName)
  517. {
  518. cbT = (wcslen(pcap->pwszDisplayName) + 1) * sizeof(WCHAR);
  519. CopyMemory(Add2Ptr(rgcap, cb), pcap->pwszDisplayName, cbT);
  520. pcap->pwszDisplayName = (WCHAR *) (ULONG_PTR) cb;
  521. cb += DWORDROUND(cbT);
  522. }
  523. }
  524. pctbPropInfo->cb = cb;
  525. pctbPropInfo->pb = (BYTE *) rgcap;
  526. rgcap = NULL;
  527. *pcProperty = ARRAYSIZE(g_aCAProp);
  528. myRegisterMemFree(pctbPropInfo->pb, CSM_MIDLUSERALLOC);
  529. hr = S_OK;
  530. }
  531. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  532. {
  533. _PrintError(hr, "Exception");
  534. }
  535. //error:
  536. if (NULL != rgcap)
  537. {
  538. MIDL_user_free(rgcap);
  539. }
  540. CSASSERT(S_OK == hr || FAILED(hr));
  541. return(hr);
  542. }
  543. HRESULT
  544. ValidatePropertyParameters(
  545. LONG PropId,
  546. LONG PropIndex,
  547. LONG PropType)
  548. {
  549. HRESULT hr;
  550. CAPROP const * pcap;
  551. hr = E_INVALIDARG;
  552. for (pcap = g_aCAProp; ; pcap++)
  553. {
  554. if (pcap >= &g_aCAProp[ARRAYSIZE(g_aCAProp)])
  555. {
  556. _JumpError(hr, error, "invalid propid");
  557. }
  558. if (PropId == pcap->lPropId)
  559. {
  560. if ((PropType != (PROPTYPE_MASK & pcap->lPropFlags)) ||
  561. (0 == (PROPFLAGS_INDEXED & pcap->lPropFlags) &&
  562. 0 != PropIndex))
  563. {
  564. _JumpError(hr, error, "invalid type/index");
  565. }
  566. break;
  567. }
  568. }
  569. hr = S_OK;
  570. error:
  571. DBGPRINT((
  572. S_OK != hr? DBG_SS_ERROR : DBG_SS_CERTSRVI,
  573. "ValidatePropertyParameters(PropId=%x, PropIndex=%x, PropType=%x) -> %x\n",
  574. PropId,
  575. PropIndex,
  576. PropType,
  577. hr));
  578. return(hr);
  579. }
  580. // Returns a string containing the list of templates supported
  581. // by this CA, one pair of name and string OID for each template,
  582. // separated by new lines:
  583. //
  584. // "name1\nOID1\nname2\OID2...\nnameN\nOIDN\0"
  585. //
  586. // If the template doesn't have an OID (Win2k domain) there will
  587. // be an empty string in its place
  588. HRESULT
  589. GetCATemplates(
  590. BYTE*& rpb,
  591. DWORD& rcb)
  592. {
  593. HRESULT hr = S_OK;
  594. HCAINFO hCAInfo = NULL;
  595. HCERTTYPE hCrtCertType = NULL;
  596. HCERTTYPE hPrevCertType = NULL;
  597. LPWSTR* pwszCertTypeCN = NULL;
  598. LPWSTR* pwszCertTypeOID = NULL;
  599. CTemplateList CATemplateList;
  600. rpb = NULL;
  601. rcb = 0;
  602. hr = CAFindByName(
  603. g_wszSanitizedName,
  604. NULL,
  605. CA_FIND_LOCAL_SYSTEM,
  606. &hCAInfo);
  607. _JumpIfError(hr, error, "CAFindByName");
  608. hr = CAEnumCertTypesForCA(
  609. hCAInfo,
  610. CT_ENUM_MACHINE_TYPES |
  611. CT_ENUM_USER_TYPES |
  612. CT_FIND_LOCAL_SYSTEM |
  613. CT_FLAG_NO_CACHE_LOOKUP,
  614. &hCrtCertType);
  615. _JumpIfError(hr, error, "CAEnumCertTypesForCA");
  616. while(hCrtCertType)
  617. {
  618. hr = CAGetCertTypeProperty(
  619. hCrtCertType,
  620. CERTTYPE_PROP_CN,
  621. &pwszCertTypeCN);
  622. _JumpIfError(hr, error, "CAGetCertTypeProperty CERTTYPE_PROP_CN");
  623. hr = CAGetCertTypeProperty(
  624. hCrtCertType,
  625. CERTTYPE_PROP_OID,
  626. &pwszCertTypeOID);
  627. _JumpIfError(hr, error, "CAGetCertTypeProperty CERTTYPE_PROP_OID");
  628. hr = CATemplateList.AddTemplateInfo(
  629. pwszCertTypeCN?*pwszCertTypeCN:NULL,
  630. pwszCertTypeOID?*pwszCertTypeOID:NULL);
  631. _JumpIfError(hr, error, "CTemplateList::AddTemplate");
  632. if(pwszCertTypeCN)
  633. {
  634. CAFreeCertTypeProperty(hCrtCertType, pwszCertTypeCN);
  635. pwszCertTypeCN = NULL;
  636. }
  637. if(pwszCertTypeOID)
  638. {
  639. CAFreeCertTypeProperty(hCrtCertType, pwszCertTypeOID);
  640. pwszCertTypeOID = NULL;
  641. }
  642. hPrevCertType = hCrtCertType;
  643. hr = CAEnumNextCertType(hCrtCertType, &hCrtCertType);
  644. _JumpIfError(hr, error, "CAEnumNextCertType");
  645. CACloseCertType(hPrevCertType);
  646. }
  647. hCrtCertType = NULL;
  648. hr = CATemplateList.Marshal(rpb, rcb);
  649. _JumpIfError(hr, error, "CTemplateList::Marshal");
  650. error:
  651. if(pwszCertTypeCN)
  652. {
  653. CSASSERT(hCrtCertType);
  654. CAFreeCertTypeProperty(hCrtCertType, pwszCertTypeCN);
  655. }
  656. if(pwszCertTypeOID)
  657. {
  658. CSASSERT(hCrtCertType);
  659. CAFreeCertTypeProperty(hCrtCertType, pwszCertTypeOID);
  660. }
  661. if(hCrtCertType)
  662. {
  663. CACloseCertType(hCrtCertType);
  664. }
  665. if(hCAInfo)
  666. {
  667. CACloseCA(hCAInfo);
  668. }
  669. return hr;
  670. }
  671. HRESULT
  672. SetCATemplates(
  673. const BYTE* pb,
  674. DWORD cb)
  675. {
  676. HRESULT hr = S_OK;
  677. HCAINFO hCAInfo = NULL;
  678. CTemplateList CATemplateList;
  679. CTemplateListEnum CATemplateListEnum(CATemplateList);
  680. CTemplateInfo *pTemplateInfo;
  681. DWORD cTempl;
  682. DWORD nTemplates;
  683. LPCWSTR *ppTemplateList = NULL;
  684. HCERTTYPE hCertType = NULL;
  685. bool fRefreshTemplateCache = true;
  686. hr = CATemplateList.Unmarshal(pb, cb);
  687. _JumpIfError(hr, error, "CTemplateList::Unmarshal");
  688. hr = CAFindByName(
  689. g_wszSanitizedName,
  690. NULL,
  691. CA_FIND_LOCAL_SYSTEM,
  692. &hCAInfo);
  693. _JumpIfError(hr, error, "CAFindByName");
  694. nTemplates = CATemplateList.GetCount();
  695. ppTemplateList = (LPCWSTR*)LocalAlloc(
  696. LMEM_FIXED|LMEM_ZEROINIT,
  697. sizeof(LPWSTR)* (nTemplates+1) );
  698. _JumpIfAllocFailed(ppTemplateList, error);
  699. CATemplateListEnum.Reset();
  700. for(pTemplateInfo=CATemplateListEnum.Next(), cTempl=0;
  701. pTemplateInfo;
  702. pTemplateInfo=CATemplateListEnum.Next(), cTempl++)
  703. {
  704. ppTemplateList[cTempl] = pTemplateInfo->GetName();
  705. // check if this is a valid template
  706. hr = CAFindCertTypeByName(
  707. pTemplateInfo->GetName(),
  708. NULL,
  709. CT_FIND_LOCAL_SYSTEM |
  710. CT_ENUM_MACHINE_TYPES |
  711. CT_ENUM_USER_TYPES |
  712. (fRefreshTemplateCache?CT_FLAG_NO_CACHE_LOOKUP:0),
  713. &hCertType);
  714. fRefreshTemplateCache = false;
  715. if(HRESULT_FROM_WIN32(ERROR_NOT_FOUND) == hr)
  716. {
  717. // try with the OID
  718. hr = CAFindCertTypeByName(
  719. pTemplateInfo->GetOID(),
  720. NULL,
  721. CT_FIND_LOCAL_SYSTEM |
  722. CT_ENUM_MACHINE_TYPES |
  723. CT_ENUM_USER_TYPES |
  724. CT_FIND_BY_OID,
  725. &hCertType);
  726. if(HRESULT_FROM_WIN32(ERROR_NOT_FOUND) == hr)
  727. {
  728. hr = CERTSRV_E_UNKNOWN_CERT_TYPE;
  729. _JumpErrorStr(hr, error, "CAFindCertTypeByOID",
  730. pTemplateInfo->GetOID());
  731. }
  732. _JumpIfErrorStr(hr, error, "CAFindCertTypeByName", pTemplateInfo->GetOID());
  733. }
  734. _JumpIfErrorStr(hr, error, "CAFindCertTypeByName", pTemplateInfo->GetName());
  735. CACloseCertType(hCertType);
  736. hCertType = NULL;
  737. hr = S_OK;
  738. }
  739. ppTemplateList[nTemplates] = NULL;
  740. hr = CASetCAProperty(hCAInfo, CA_PROP_CERT_TYPES,
  741. const_cast<LPWSTR*>(ppTemplateList));
  742. _JumpIfError(hr, error, "CASetCAProperty(CA_PROP_CERT_TYPES)");
  743. hr = CAUpdateCA(hCAInfo);
  744. _JumpIfError(hr, error, "CAUpdateCA");
  745. // Increment sequence number so that policy module can detect
  746. // there was a template change
  747. InterlockedIncrement(&g_cTemplateUpdateSequenceNum);
  748. error:
  749. LOCAL_FREE(ppTemplateList);
  750. if(hCAInfo)
  751. {
  752. CACloseCA(hCAInfo);
  753. }
  754. return hr;
  755. }
  756. STDMETHODIMP
  757. RequestGetCAPropertySub(
  758. IN LONG PropId, // CR_PROP_*
  759. IN LONG PropIndex,
  760. IN LONG PropType, // PROPTYPE_*
  761. OUT CERTTRANSBLOB *pctbOut)
  762. {
  763. HRESULT hr = S_OK;
  764. CAPROP const *pcap;
  765. BYTE *pbReturn;
  766. BYTE *pbAlloc = NULL;
  767. WCHAR wszVersion[MAX_VERSION_RESOURCE_SIZE];
  768. BYTE *pb = NULL;
  769. WCHAR const *pwsz = NULL;
  770. WCHAR *pwszSharedFolder = NULL;
  771. CAINFO CAInfo;
  772. DWORD iCertSig;
  773. CRL_CONTEXT const *pCRL = NULL;
  774. WCHAR *pwszUserName = NULL;
  775. HCERTSTORE hKRAStore = NULL;
  776. CERT_CONTEXT const *pCertContext = NULL;
  777. HRESULT hrCAStatusCode;
  778. switch (PropId)
  779. {
  780. case CR_PROP_FILEVERSION:
  781. case CR_PROP_PRODUCTVERSION:
  782. hr = GetVersionString(PropId, wszVersion);
  783. _JumpIfError(hr, error, "GetVersionString");
  784. pwsz = wszVersion;
  785. break;
  786. case CR_PROP_EXITDESCRIPTION:
  787. case CR_PROP_POLICYDESCRIPTION:
  788. pwsz = CR_PROP_EXITDESCRIPTION == PropId?
  789. ExitGetDescription(PropIndex) :
  790. g_strPolicyDescription;
  791. if (NULL == pwsz)
  792. {
  793. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  794. _JumpError(hr, error, "No description");
  795. }
  796. break;
  797. case CR_PROP_CANAME:
  798. pwsz = g_wszCommonName;
  799. break;
  800. case CR_PROP_SANITIZEDCANAME:
  801. pwsz = g_wszSanitizedName;
  802. break;
  803. case CR_PROP_SHAREDFOLDER:
  804. hr = myGetCertRegStrValue(
  805. NULL,
  806. NULL,
  807. NULL,
  808. wszREGDIRECTORY,
  809. &pwszSharedFolder);
  810. _JumpIfError(hr, error, "myGetCertRegStrValue");
  811. if (NULL == pwszSharedFolder)
  812. {
  813. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  814. _JumpError(hr, error, "No shared folder");
  815. }
  816. pwsz = pwszSharedFolder;
  817. break;
  818. case CR_PROP_PARENTCA:
  819. if (L'\0' == g_wszParentConfig[0])
  820. {
  821. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  822. _JumpError(hr, error, "No parent");
  823. }
  824. pwsz = g_wszParentConfig;
  825. break;
  826. case CR_PROP_CATYPE:
  827. case CR_PROP_CASIGCERTCOUNT:
  828. case CR_PROP_CAXCHGCERTCOUNT:
  829. case CR_PROP_EXITCOUNT:
  830. case CR_PROP_CAPROPIDMAX:
  831. case CR_PROP_ROLESEPARATIONENABLED:
  832. case CR_PROP_KRACERTUSEDCOUNT:
  833. case CR_PROP_KRACERTCOUNT:
  834. case CR_PROP_ADVANCEDSERVER:
  835. ZeroMemory(&CAInfo, sizeof(CAInfo));
  836. CAInfo.cbSize = sizeof(CAInfo);
  837. CAInfo.CAType = g_CAType;
  838. CAInfo.cCASignatureCerts = g_cCACerts;
  839. CAInfo.cCAExchangeCerts = 1; // current Xchg cert only
  840. CAInfo.cExitModules = g_cExitMod;
  841. CAInfo.lPropIdMax = g_CAPropIdMax;
  842. CAInfo.lRoleSeparationEnabled = CAuditEvent::RoleSeparationIsEnabled();
  843. CAInfo.fAdvancedServer = g_fAdvancedServer;
  844. hr = myGetCertRegDWValue(
  845. g_wszSanitizedName,
  846. NULL,
  847. NULL,
  848. wszREGKRACERTCOUNT,
  849. &CAInfo.cKRACertUsedCount);
  850. _JumpIfError(hr, error, "myGetCertRegDWValue wszREGKRACERTCOUNT");
  851. hr = myGetCARegHashCount(
  852. g_wszSanitizedName,
  853. CSRH_CAKRACERT,
  854. &CAInfo.cKRACertCount);
  855. _JumpIfError(hr, error, "myGetCertRegStrValue wszREGKRACERTCOUNT");
  856. pctbOut->cb = sizeof(CAInfo);
  857. pb = (BYTE *) &CAInfo;
  858. break;
  859. case CR_PROP_CASIGCERT:
  860. hr = PKCSGetCACert(PropIndex, &pb, &pctbOut->cb);
  861. _JumpIfError(hr, error, "PKCSGetCACert");
  862. break;
  863. case CR_PROP_CASIGCERTCHAIN:
  864. case CR_PROP_CASIGCERTCRLCHAIN:
  865. hr = PKCSGetCAChain(
  866. PropIndex,
  867. CR_PROP_CASIGCERTCRLCHAIN == PropId,
  868. &pbAlloc,
  869. &pctbOut->cb);
  870. _JumpIfError(hr, error, "PKCSGetCAChain");
  871. pb = pbAlloc; // must be freed
  872. break;
  873. case CR_PROP_CAXCHGCERT:
  874. hr = GetClientUserName(NULL, &pwszUserName, NULL);
  875. _JumpIfError(hr, error, "GetClientUserName");
  876. hr = PKCSGetCAXchgCert(
  877. PropIndex,
  878. pwszUserName,
  879. &iCertSig,
  880. &pb,
  881. &pctbOut->cb);
  882. _JumpIfError(hr, error, "PKCSGetCAXchgCert");
  883. break;
  884. case CR_PROP_CAXCHGCERTCHAIN:
  885. case CR_PROP_CAXCHGCERTCRLCHAIN:
  886. hr = GetClientUserName(NULL, &pwszUserName, NULL);
  887. _JumpIfError(hr, error, "GetClientUserName");
  888. hr = PKCSGetCAXchgChain(
  889. PropIndex,
  890. pwszUserName,
  891. CR_PROP_CAXCHGCERTCRLCHAIN == PropId,
  892. &pbAlloc,
  893. &pctbOut->cb);
  894. _JumpIfError(hr, error, "PKCSGetCAXchgChain");
  895. pb = pbAlloc; // must be freed
  896. break;
  897. case CR_PROP_BASECRL:
  898. case CR_PROP_DELTACRL:
  899. hr = CRLGetCRL(
  900. PropIndex,
  901. CR_PROP_DELTACRL == PropId,
  902. &pCRL,
  903. NULL);
  904. _JumpIfError(hr, error, "CRLGetCRL");
  905. pctbOut->cb = pCRL->cbCrlEncoded;
  906. pb = (BYTE *) pCRL->pbCrlEncoded;
  907. break;
  908. case CR_PROP_CACERTSTATUSCODE:
  909. hr = PKCSGetCACertStatusCode(PropIndex, &hrCAStatusCode);
  910. pctbOut->cb = sizeof(hrCAStatusCode);
  911. pb = (BYTE *) &hrCAStatusCode;
  912. break;
  913. case CR_PROP_CACERTSTATE:
  914. case CR_PROP_CRLSTATE:
  915. pctbOut->cb = g_cCACerts;
  916. pbAlloc = (BYTE *) MIDL_user_allocate(g_cCACerts);
  917. if (NULL == pbAlloc)
  918. {
  919. hr = E_OUTOFMEMORY;
  920. _JumpError(hr, error, "no memory");
  921. }
  922. pb = pbAlloc; // must be freed
  923. hr = PKCSGetCAState(CR_PROP_CACERTSTATE == PropId, pb);
  924. _JumpIfError(hr, error, "PKCSGetCAState");
  925. break;
  926. case CR_PROP_KRACERTSTATE:
  927. hr = myGetCARegHashCount(
  928. g_wszSanitizedName,
  929. CSRH_CAKRACERT,
  930. &pctbOut->cb);
  931. _JumpIfError(hr, error, "myGetCARegHashCount CSRH_CAKRACERT");
  932. pbAlloc = (BYTE *) MIDL_user_allocate(pctbOut->cb);
  933. if (NULL == pbAlloc)
  934. {
  935. hr = E_OUTOFMEMORY;
  936. _JumpError(hr, error, "no memory");
  937. }
  938. pb = pbAlloc; // must be freed
  939. hr = PKCSGetKRAState(pctbOut->cb, pb);
  940. _JumpIfError(hr, error, "PKCSGetKRAState");
  941. break;
  942. case CR_PROP_DNSNAME:
  943. pwsz = g_pwszServerName;
  944. break;
  945. case CR_PROP_KRACERT:
  946. hKRAStore = CertOpenStore(
  947. CERT_STORE_PROV_SYSTEM_W,
  948. X509_ASN_ENCODING,
  949. NULL, // hProv
  950. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  951. wszKRA_CERTSTORE);
  952. hr = myFindCACertByHashIndex(
  953. hKRAStore,
  954. g_wszSanitizedName,
  955. CSRH_CAKRACERT,
  956. PropIndex,
  957. NULL,
  958. &pCertContext);
  959. _JumpIfError(hr, error, "myFindCACertByHashIndex");
  960. pb = pCertContext->pbCertEncoded;
  961. pctbOut->cb = pCertContext->cbCertEncoded;
  962. break;
  963. case CR_PROP_TEMPLATES:
  964. hr = GetCATemplates(pbAlloc, pctbOut->cb);
  965. _JumpIfError(hr, error, "GetCATemplates");
  966. break;
  967. case CR_PROP_BASECRLPUBLISHSTATUS:
  968. case CR_PROP_DELTACRLPUBLISHSTATUS:
  969. pctbOut->cb = sizeof(DWORD);
  970. pbAlloc = (BYTE *) MIDL_user_allocate(pctbOut->cb);
  971. _JumpIfAllocFailed(pbAlloc, error);
  972. pb = pbAlloc; // must be freed
  973. hr = CRLGetCRL(
  974. PropIndex,
  975. CR_PROP_DELTACRLPUBLISHSTATUS == PropId, // fDelta
  976. NULL,
  977. (DWORD *) pbAlloc);
  978. _JumpIfError(hr, error, "CRLGetCRL");
  979. break;
  980. default:
  981. hr = E_INVALIDARG;
  982. _JumpError(hr, error, "Bad PropId");
  983. }
  984. // not yet populated?
  985. if (NULL == pb && NULL != pwsz)
  986. {
  987. pctbOut->cb = (wcslen(pwsz) + 1) * sizeof(WCHAR);
  988. pb = (BYTE *) pwsz;
  989. }
  990. if (NULL != pbAlloc)
  991. {
  992. pctbOut->pb = pbAlloc;
  993. pbAlloc = NULL;
  994. }
  995. else
  996. {
  997. if (NULL == pb)
  998. {
  999. hr = E_POINTER;
  1000. _JumpError(hr, error, "pb NULL");
  1001. }
  1002. pbReturn = (BYTE *) MIDL_user_allocate(pctbOut->cb);
  1003. if (NULL == pbReturn)
  1004. {
  1005. hr = E_OUTOFMEMORY;
  1006. _JumpError(hr, error, "no memory");
  1007. }
  1008. CopyMemory(pbReturn, pb, pctbOut->cb);
  1009. pctbOut->pb = pbReturn;
  1010. }
  1011. error:
  1012. if (NULL != pwszUserName)
  1013. {
  1014. LocalFree(pwszUserName);
  1015. }
  1016. if (NULL != pCRL)
  1017. {
  1018. CertFreeCRLContext(pCRL);
  1019. }
  1020. if (NULL != pbAlloc)
  1021. {
  1022. CoTaskMemFree(pbAlloc);
  1023. }
  1024. if (NULL != pwszSharedFolder)
  1025. {
  1026. LocalFree(pwszSharedFolder);
  1027. }
  1028. if (NULL != hKRAStore)
  1029. {
  1030. CertCloseStore(hKRAStore, CERT_CLOSE_STORE_CHECK_FLAG);
  1031. }
  1032. if (NULL != pCertContext)
  1033. {
  1034. CertFreeCertificateContext(pCertContext);
  1035. }
  1036. CSASSERT(S_OK == hr || FAILED(hr));
  1037. return(hr);
  1038. }
  1039. STDMETHODIMP
  1040. RequestGetCAProperty(
  1041. IN LONG PropId, // CR_PROP_*
  1042. IN LONG PropIndex,
  1043. IN LONG PropType, // PROPTYPE_*
  1044. OUT CERTTRANSBLOB *pctbPropertyValue)
  1045. {
  1046. HRESULT hr;
  1047. pctbPropertyValue->pb = NULL;
  1048. pctbPropertyValue->cb = 0;
  1049. hr = ValidatePropertyParameters(PropId, PropIndex, PropType);
  1050. _JumpIfError(hr, error, "Invalid prop params");
  1051. hr = RequestGetCAPropertySub(
  1052. PropId,
  1053. PropIndex,
  1054. PropType,
  1055. pctbPropertyValue);
  1056. _JumpIfError(hr, error, "RequestGetCAPropertySub");
  1057. myRegisterMemFree(pctbPropertyValue->pb, CSM_COTASKALLOC);
  1058. error:
  1059. CSASSERT(S_OK == hr || FAILED(hr));
  1060. return(hr);
  1061. }
  1062. STDMETHODIMP
  1063. RequestSetCAPropertySub(
  1064. IN LONG PropId, // CR_PROP_*
  1065. IN LONG PropIndex,
  1066. IN LONG PropType, // PROPTYPE_*
  1067. IN CERTTRANSBLOB *pctbIn)
  1068. {
  1069. HRESULT hr = S_OK;
  1070. LONG lVal = 0;
  1071. const CERT_CONTEXT *pCertContext = NULL;
  1072. HCERTSTORE hKRAStore = NULL;
  1073. switch(PropId)
  1074. {
  1075. case CR_PROP_ROLESEPARATIONENABLED:
  1076. {
  1077. lVal = *(LONG *) pctbIn->pb;
  1078. CAuditEvent SaveFlagObj; // used just for saving the flag
  1079. SaveFlagObj.RoleSeparationEnable(lVal? true : false);
  1080. hr = SaveFlagObj.RoleSeparationFlagSave(g_wszSanitizedName);
  1081. _JumpIfError(hr, error, "failed to save ");
  1082. }
  1083. break;
  1084. case CR_PROP_KRACERTUSEDCOUNT:
  1085. CSASSERT(sizeof(DWORD)==pctbIn->cb);
  1086. hr = mySetCertRegDWValue(
  1087. g_wszSanitizedName,
  1088. NULL,
  1089. NULL,
  1090. wszREGKRACERTCOUNT,
  1091. *(DWORD*)pctbIn->pb);
  1092. _JumpIfError(hr, error, "mySetCertRegDWValue ");
  1093. break;
  1094. case CR_PROP_KRACERTCOUNT:
  1095. // New hash count; calling this should follow a sequence of
  1096. // SetCaProperty(CR_PROP_KRACERT) and should be called only if
  1097. // new hash count is smaller than current count. If PropIndex>=current count
  1098. // this fails with E_INVALIDARG;
  1099. CSASSERT(sizeof(DWORD)==pctbIn->cb);
  1100. hr = myShrinkCARegHash(
  1101. g_wszSanitizedName,
  1102. CSRH_CAKRACERT,
  1103. *(DWORD*)pctbIn->pb);
  1104. _JumpIfError(hr, error, "myShrinkCARegHash");
  1105. break;
  1106. case CR_PROP_KRACERT:
  1107. pCertContext = CertCreateCertificateContext(
  1108. X509_ASN_ENCODING,
  1109. pctbIn->pb,
  1110. pctbIn->cb);
  1111. if(!pCertContext)
  1112. {
  1113. hr = HRESULT_FROM_WIN32(GetLastError());
  1114. _JumpError(hr, error, "CertCreateCertificateContext");
  1115. }
  1116. // add certificate to KRA store
  1117. hKRAStore = CertOpenStore(
  1118. CERT_STORE_PROV_SYSTEM_W,
  1119. X509_ASN_ENCODING,
  1120. NULL, // hProv
  1121. CERT_SYSTEM_STORE_LOCAL_MACHINE,
  1122. wszKRA_CERTSTORE);
  1123. if (NULL == hKRAStore)
  1124. {
  1125. hr = myHLastError();
  1126. _JumpError(hr, error, "CertOpenStore");
  1127. }
  1128. if (!CertAddCertificateContextToStore(
  1129. hKRAStore,
  1130. pCertContext,
  1131. CERT_STORE_ADD_NEW,
  1132. NULL))
  1133. {
  1134. hr = myHLastError();
  1135. if (HRESULT_FROM_WIN32(CRYPT_E_EXISTS) != hr)
  1136. {
  1137. _JumpError(hr, error, "CertAddCertificateContextToStore");
  1138. }
  1139. //the cert exists, ignore error
  1140. hr = S_OK;
  1141. }
  1142. // persist the hash
  1143. hr = mySetCARegHash(
  1144. g_wszSanitizedName,
  1145. CSRH_CAKRACERT,
  1146. PropIndex,
  1147. pCertContext);
  1148. _JumpIfError(hr, error, "mySetCARegHash");
  1149. break;
  1150. case CR_PROP_TEMPLATES:
  1151. hr = SetCATemplates(
  1152. pctbIn->pb,
  1153. pctbIn->cb);
  1154. _JumpIfError(hr, error, "GetCATemplates");
  1155. break;
  1156. default:
  1157. hr = E_INVALIDARG;
  1158. _JumpError(hr, error, "Bad PropId");
  1159. }
  1160. error:
  1161. if(pCertContext)
  1162. {
  1163. CertFreeCertificateContext(pCertContext);
  1164. }
  1165. return hr;
  1166. }
  1167. STDMETHODIMP
  1168. RequestSetCAProperty(
  1169. IN wchar_t const *pwszAuthority,
  1170. IN LONG PropId, // CR_PROP_*
  1171. IN LONG PropIndex,
  1172. IN LONG PropType, // PROPTYPE_*
  1173. IN CERTTRANSBLOB *pctbPropertyValue)
  1174. {
  1175. HRESULT hr;
  1176. CAuditEvent audit(SE_AUDITID_CERTSRV_SETCAPROPERTY, g_dwAuditFilter);
  1177. DWORD State = 0;
  1178. hr = CertSrvEnterServer(&State);
  1179. _JumpIfError(hr, error, "CertSrvEnterServer");
  1180. __try
  1181. {
  1182. hr = ValidatePropertyParameters(
  1183. PropId,
  1184. PropIndex,
  1185. PropType);
  1186. _LeaveIfError(hr, "Invalid prop params");
  1187. hr = CheckAuthorityName(pwszAuthority);
  1188. _LeaveIfError(hr, "No authority name");
  1189. // Ignore role separation if setting the role separation flag.
  1190. // This allows an admin to turn the flag off even with role separation
  1191. // enabled so he won't lock himself out.
  1192. if(CR_PROP_ROLESEPARATIONENABLED==PropId)
  1193. {
  1194. audit.EventRoleSeparationEnable(false);
  1195. }
  1196. hr = audit.AddData((DWORD)PropId); // %1 property ID
  1197. _JumpIfError(hr, error, "CAuditEvent::AddData");
  1198. hr = audit.AddData((DWORD)PropIndex); // %2 index
  1199. _JumpIfError(hr, error, "CAuditEvent::AddData");
  1200. hr = audit.AddData((DWORD)PropType); // %3 type
  1201. _JumpIfError(hr, error, "CAuditEvent::AddData");
  1202. hr = audit.AddData(pctbPropertyValue->pb, pctbPropertyValue->cb); // %4 value
  1203. _JumpIfError(hr, error, "CAuditEvent::AddData");
  1204. hr = audit.AccessCheck(
  1205. CA_ACCESS_ADMIN,
  1206. audit.m_gcAuditSuccessOrFailure);
  1207. _LeaveIfError(hr, "CAuditEvent::AccessCheck");
  1208. hr = RequestSetCAPropertySub(
  1209. PropId,
  1210. PropIndex,
  1211. PropType,
  1212. pctbPropertyValue);
  1213. _LeaveIfError(hr, "RequestSetCAPropertySub");
  1214. }
  1215. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  1216. {
  1217. _PrintError(hr, "Exception");
  1218. }
  1219. error:
  1220. CertSrvExitServer(State);
  1221. return(hr);
  1222. }
  1223. STDMETHODIMP
  1224. CCertRequestD::GetCACert(
  1225. /* [in] */ DWORD Flags,
  1226. /* [unique][size_is][in] */ USHORT const __RPC_FAR *pwszAuthority,
  1227. /* [ref][out] */ CERTTRANSBLOB __RPC_FAR *pctbOut)
  1228. {
  1229. HRESULT hr = S_OK;
  1230. DWORD type = GETCERT_VERSIONMASK & Flags;
  1231. LONG PropIndex;
  1232. LONG PropId;
  1233. LONG PropType;
  1234. BOOL fChainAllowed;
  1235. GETCERTMAP const *pmap;
  1236. GETCERTMAP const *pmapFound;
  1237. DWORD State = 0;
  1238. DBGPRINT((
  1239. s_ssRequest,
  1240. "CCertRequestD::GetCACert(tid=%d, Flags=0x%x)\n",
  1241. GetCurrentThreadId(),
  1242. Flags));
  1243. hr = CertSrvEnterServer(&State);
  1244. _JumpIfError(hr, error, "CertSrvEnterServer");
  1245. hr = CheckAuthorityName(pwszAuthority);
  1246. // allow empty name only if the client attempts retrieving the name
  1247. if(hr == E_INVALIDARG &&
  1248. (GETCERT_CANAME == type ||
  1249. GETCERT_SANITIZEDCANAME == type))
  1250. {
  1251. hr = S_OK;
  1252. }
  1253. _JumpIfError(hr, error, "No authority name");
  1254. __try
  1255. {
  1256. hr = RequestAccessCheck();
  1257. _LeaveIfError(hr, "RequestAccessCheck");
  1258. type = GETCERT_VERSIONMASK & Flags;
  1259. PropIndex = 0;
  1260. // NOTE: all of these should return only a single entry --
  1261. // multiple entries will be batched up by the caller
  1262. // (eg multiple CAs on a machine)
  1263. DBGCODE(WCHAR wszArg[10]); // Build up a nice debug print:
  1264. PropId = 0;
  1265. PropType = PROPTYPE_BINARY;
  1266. switch (type)
  1267. {
  1268. case GETCERT_CASIGCERT:
  1269. DBGCODE(wcscpy(wszArg, L"Cert"));
  1270. PropId = CR_PROP_CASIGCERT;
  1271. PropIndex = -1; // return latest Cert
  1272. break;
  1273. case GETCERT_CAXCHGCERT:
  1274. DBGCODE(wcscpy(wszArg, L"XchgCert"));
  1275. PropId = CR_PROP_CAXCHGCERT;
  1276. PropIndex = -1; // return latest Xchg Cert
  1277. break;
  1278. case GETCERT_CURRENTCRL:
  1279. DBGCODE(wcscpy(wszArg, L"CRL"));
  1280. PropId = CR_PROP_BASECRL;
  1281. PropIndex = -1; // return latest CRL
  1282. break;
  1283. default:
  1284. {
  1285. DBGCODE(wszArg[0] = ((char *) &type)[3]);
  1286. DBGCODE(wszArg[1] = ((char *) &type)[2]);
  1287. DBGCODE(wszArg[2] = ((char *) &type)[1]);
  1288. DBGCODE(wszArg[3] = ((char *) &type)[0]);
  1289. DBGCODE(wszArg[4] = L'\0');
  1290. switch (GETCERT_BYINDEXMASK & Flags)
  1291. {
  1292. case GETCERT_CACERTSTATEBYINDEX:
  1293. case GETCERT_CRLSTATEBYINDEX:
  1294. if (0 != (GETCERT_INDEXVALUEMASK & Flags))
  1295. {
  1296. hr = E_INVALIDARG;
  1297. _LeaveError(hr, "Invalid State Index");
  1298. }
  1299. // FALLTHROUGH
  1300. case GETCERT_EXITVERSIONBYINDEX:
  1301. case GETCERT_CACERTBYINDEX:
  1302. case GETCERT_CRLBYINDEX:
  1303. PropIndex = GETCERT_INDEXVALUEMASK & Flags;
  1304. type = GETCERT_BYINDEXMASK & Flags;
  1305. DBGCODE(swprintf(&wszArg[2], L".%u", PropIndex));
  1306. break;
  1307. }
  1308. break;
  1309. }
  1310. }
  1311. DBGPRINT((
  1312. s_ssRequest,
  1313. "CCertRequestD::GetCACert(\"%ws\"%ws)\n",
  1314. wszArg,
  1315. (GETCERT_CHAIN & Flags)? L"+Chain" : L""));
  1316. for (
  1317. pmap = g_aCAPropMap;
  1318. pmap < &g_aCAPropMap[ARRAYSIZE(g_aCAPropMap)];
  1319. pmap++)
  1320. {
  1321. if (type == pmap->dwGetCert)
  1322. {
  1323. PropId = pmap->lPropId;
  1324. PropType = pmap->lPropType;
  1325. break;
  1326. }
  1327. }
  1328. if (CR_PROP_CASIGCERT == PropId)
  1329. {
  1330. if (GETCERT_CHAIN & Flags)
  1331. {
  1332. PropId = CR_PROP_CASIGCERTCHAIN;
  1333. if (GETCERT_CRLS & Flags)
  1334. {
  1335. PropId = CR_PROP_CASIGCERTCRLCHAIN;
  1336. }
  1337. }
  1338. }
  1339. else if (CR_PROP_CAXCHGCERT == PropId)
  1340. {
  1341. if (GETCERT_CHAIN & Flags)
  1342. {
  1343. PropId = CR_PROP_CAXCHGCERTCHAIN;
  1344. if (GETCERT_CRLS & Flags)
  1345. {
  1346. PropId = CR_PROP_CAXCHGCERTCRLCHAIN;
  1347. }
  1348. }
  1349. }
  1350. else if ((GETCERT_CHAIN | GETCERT_CRLS) & Flags)
  1351. {
  1352. hr = E_INVALIDARG;
  1353. _LeaveError(hr, "Chain/CRLS Flag");
  1354. }
  1355. if (0 == PropId)
  1356. {
  1357. BYTE *pb;
  1358. switch (type)
  1359. {
  1360. case GETCERT_CATYPE:
  1361. pctbOut->cb = sizeof(g_CAType);
  1362. pb = (BYTE *) &g_CAType;
  1363. break;
  1364. default:
  1365. hr = E_INVALIDARG;
  1366. _LeaveError(hr, "Invalid GetCert Flags");
  1367. }
  1368. pctbOut->pb = (BYTE *) MIDL_user_allocate(pctbOut->cb);
  1369. if (NULL == pctbOut->pb)
  1370. {
  1371. hr = E_OUTOFMEMORY;
  1372. _LeaveError(hr, "no memory");
  1373. }
  1374. CopyMemory(pctbOut->pb, pb, pctbOut->cb);
  1375. }
  1376. else
  1377. {
  1378. hr = RequestGetCAPropertySub(
  1379. PropId,
  1380. PropIndex,
  1381. PropType,
  1382. pctbOut);
  1383. _LeaveIfError(hr, "RequestGetCAPropertySub");
  1384. }
  1385. myRegisterMemFree(pctbOut->pb, CSM_COTASKALLOC);
  1386. }
  1387. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  1388. {
  1389. _PrintError(hr, "Exception");
  1390. }
  1391. error:
  1392. CertSrvExitServer(State);
  1393. CSASSERT(S_OK == hr || FAILED(hr));
  1394. return(hr);
  1395. }
  1396. STDMETHODIMP
  1397. CCertRequestD::GetCAProperty(
  1398. IN wchar_t const *pwszAuthority,
  1399. IN LONG PropId, // CR_PROP_*
  1400. IN LONG PropIndex,
  1401. IN LONG PropType, // PROPTYPE_*
  1402. OUT CERTTRANSBLOB *pctbPropertyValue)
  1403. {
  1404. HRESULT hr;
  1405. DWORD State = 0;
  1406. DBGPRINT((
  1407. s_ssRequest,
  1408. "CCertRequestD::GetCAProperty(tid=%d, this=%x)\n",
  1409. GetCurrentThreadId(),
  1410. this));
  1411. hr = CertSrvEnterServer(&State);
  1412. _JumpIfError(hr, error, "CertSrvEnterServer");
  1413. if (NULL == pwszAuthority ||
  1414. ((L'\0' != *pwszAuthority ||
  1415. (CR_PROP_CANAME != PropId &&
  1416. CR_PROP_DNSNAME != PropId &&
  1417. CR_PROP_SANITIZEDCANAME != PropId)) &&
  1418. 0 != lstrcmpi(pwszAuthority, g_wszCommonName) &&
  1419. 0 != lstrcmpi(pwszAuthority, g_wszSanitizedName) &&
  1420. 0 != lstrcmpi(pwszAuthority, g_pwszSanitizedDSName)))
  1421. {
  1422. hr = E_INVALIDARG;
  1423. _JumpError(hr, error, "bad authority name");
  1424. }
  1425. __try
  1426. {
  1427. hr = RequestAccessCheck();
  1428. _LeaveIfError(hr, "RequestAccessCheck");
  1429. hr = RequestGetCAProperty(
  1430. PropId,
  1431. PropIndex,
  1432. PropType,
  1433. pctbPropertyValue);
  1434. _LeaveIfError(hr, "RequestGetCAProperty");
  1435. }
  1436. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  1437. {
  1438. _PrintError(hr, "Exception");
  1439. }
  1440. error:
  1441. CertSrvExitServer(State);
  1442. CSASSERT(S_OK == hr || FAILED(hr));
  1443. return(hr);
  1444. }
  1445. STDMETHODIMP
  1446. CCertRequestD::GetCAPropertyInfo(
  1447. IN wchar_t const *pwszAuthority,
  1448. OUT LONG *pcProperty,
  1449. OUT CERTTRANSBLOB *pctbPropInfo)
  1450. {
  1451. HRESULT hr;
  1452. DWORD State = 0;
  1453. DBGPRINT((
  1454. s_ssRequest,
  1455. "CCertRequestD::GetCAPropertyInfo(tid=%d, this=%x)\n",
  1456. GetCurrentThreadId(),
  1457. this));
  1458. hr = CertSrvEnterServer(&State);
  1459. _JumpIfError(hr, error, "CertSrvEnterServer");
  1460. hr = CheckAuthorityName(pwszAuthority);
  1461. _JumpIfError(hr, error, "No authority name");
  1462. __try
  1463. {
  1464. hr = RequestAccessCheck();
  1465. _LeaveIfError(hr, "RequestAccessCheck");
  1466. hr = RequestGetCAPropertyInfo(
  1467. pcProperty,
  1468. pctbPropInfo);
  1469. _JumpIfError(hr, error, "RequestGetCAPropertyInfo");
  1470. }
  1471. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  1472. {
  1473. _PrintError(hr, "Exception");
  1474. }
  1475. error:
  1476. CertSrvExitServer(State);
  1477. CSASSERT(S_OK == hr || FAILED(hr));
  1478. return(hr);
  1479. }
  1480. HRESULT
  1481. CCertRequestD::_Ping(
  1482. IN WCHAR const *pwszAuthority)
  1483. {
  1484. HRESULT hr;
  1485. DWORD State = 0;
  1486. hr = CertSrvEnterServer(&State);
  1487. _JumpIfError(hr, error, "CertSrvEnterServer");
  1488. __try
  1489. {
  1490. hr = CheckAuthorityName(pwszAuthority, true); // allow empty name
  1491. _JumpIfError(hr, error, "No authority name");
  1492. hr = RequestAccessCheck();
  1493. _LeaveIfError(hr, "RequestAccessCheck");
  1494. #if 1
  1495. wprintf(L"."); // may fault if I/O buffer is odd aligned
  1496. fprintf(stdout, ".");
  1497. wprintf(L".\n"); // may fault if I/O buffer is odd aligned
  1498. #endif
  1499. hr = S_OK;
  1500. }
  1501. __except(hr = myHEXCEPTIONCODE(), EXCEPTION_EXECUTE_HANDLER)
  1502. {
  1503. _PrintError(hr, "Exception");
  1504. }
  1505. error:
  1506. CertSrvExitServer(State);
  1507. CSASSERT(S_OK == hr || FAILED(hr));
  1508. return(hr);
  1509. }
  1510. STDMETHODIMP
  1511. CCertRequestD::Ping(
  1512. IN WCHAR const *pwszAuthority)
  1513. {
  1514. HRESULT hr;
  1515. DBGPRINT((
  1516. s_ssRequest,
  1517. "CCertRequestD::Ping(tid=%d, this=%x)\n",
  1518. GetCurrentThreadId(),
  1519. this));
  1520. hr = _Ping(pwszAuthority);
  1521. _JumpIfError(hr, error, "_Ping");
  1522. error:
  1523. CSASSERT(S_OK == hr || FAILED(hr));
  1524. return(hr);
  1525. }
  1526. STDMETHODIMP
  1527. CCertRequestD::Ping2(
  1528. IN WCHAR const *pwszAuthority)
  1529. {
  1530. HRESULT hr;
  1531. DBGPRINT((
  1532. s_ssRequest,
  1533. "CCertRequestD::Ping2(tid=%d, this=%x)\n",
  1534. GetCurrentThreadId(),
  1535. this));
  1536. hr = _Ping(pwszAuthority);
  1537. _JumpIfError(hr, error, "_Ping");
  1538. error:
  1539. CSASSERT(S_OK == hr || FAILED(hr));
  1540. return(hr);
  1541. }
  1542. // Constructor
  1543. CCertRequestD::CCertRequestD() : m_cRef(1)
  1544. {
  1545. InterlockedIncrement(&g_cRequestComponents);
  1546. }
  1547. // Destructor
  1548. CCertRequestD::~CCertRequestD()
  1549. {
  1550. InterlockedDecrement(&g_cRequestComponents);
  1551. if (m_cRef != 0)
  1552. {
  1553. DBGPRINT((
  1554. DBG_SS_CERTSRV,
  1555. "CCertRequestD has %d instances left over\n",
  1556. m_cRef));
  1557. }
  1558. }
  1559. // IUnknown implementation
  1560. STDMETHODIMP
  1561. CCertRequestD::QueryInterface(const IID& iid, void** ppv)
  1562. {
  1563. if (iid == IID_IUnknown)
  1564. {
  1565. *ppv = static_cast<ICertRequestD *>(this);
  1566. }
  1567. else if (iid == IID_ICertRequestD)
  1568. {
  1569. *ppv = static_cast<ICertRequestD *>(this);
  1570. }
  1571. else if (iid == IID_ICertRequestD2)
  1572. {
  1573. *ppv = static_cast<ICertRequestD2 *>(this);
  1574. }
  1575. else
  1576. {
  1577. *ppv = NULL;
  1578. return(E_NOINTERFACE);
  1579. }
  1580. reinterpret_cast<IUnknown *>(*ppv)->AddRef();
  1581. return(S_OK);
  1582. }
  1583. ULONG STDMETHODCALLTYPE
  1584. CCertRequestD::AddRef()
  1585. {
  1586. return(InterlockedIncrement(&m_cRef));
  1587. }
  1588. ULONG STDMETHODCALLTYPE
  1589. CCertRequestD::Release()
  1590. {
  1591. ULONG cRef = InterlockedDecrement(&m_cRef);
  1592. if (0 == cRef)
  1593. {
  1594. delete this;
  1595. }
  1596. return(cRef);
  1597. }
  1598. // Class factory IUnknown implementation
  1599. STDMETHODIMP
  1600. CRequestFactory::QueryInterface(const IID& iid, void** ppv)
  1601. {
  1602. if ((iid == IID_IUnknown) || (iid == IID_IClassFactory))
  1603. {
  1604. *ppv = static_cast<IClassFactory*>(this);
  1605. }
  1606. else
  1607. {
  1608. *ppv = NULL;
  1609. return(E_NOINTERFACE);
  1610. }
  1611. reinterpret_cast<IUnknown *>(*ppv)->AddRef();
  1612. return(S_OK);
  1613. }
  1614. ULONG STDMETHODCALLTYPE
  1615. CRequestFactory::AddRef()
  1616. {
  1617. return(InterlockedIncrement(&m_cRef));
  1618. }
  1619. ULONG STDMETHODCALLTYPE
  1620. CRequestFactory::Release()
  1621. {
  1622. ULONG cRef = InterlockedDecrement(&m_cRef);
  1623. if (0 == cRef)
  1624. {
  1625. delete this;
  1626. return(0);
  1627. }
  1628. return(cRef);
  1629. }
  1630. // IClassFactory implementation
  1631. STDMETHODIMP
  1632. CRequestFactory::CreateInstance(
  1633. IUnknown *pUnknownOuter,
  1634. const IID& iid,
  1635. void **ppv)
  1636. {
  1637. HRESULT hr;
  1638. CCertRequestD *pA;
  1639. // Cannot aggregate.
  1640. if (pUnknownOuter != NULL)
  1641. {
  1642. hr = CLASS_E_NOAGGREGATION;
  1643. _JumpError(hr, error, "pUnknownOuter");
  1644. }
  1645. // Create component.
  1646. pA = new CCertRequestD;
  1647. if (pA == NULL)
  1648. {
  1649. hr = E_OUTOFMEMORY;
  1650. _JumpError(hr, error, "out of memory");
  1651. }
  1652. // Get the requested interface.
  1653. hr = pA->QueryInterface(iid, ppv);
  1654. // Release the IUnknown pointer.
  1655. // (If QueryInterface failed, component will delete itself.)
  1656. pA->Release();
  1657. error:
  1658. CSASSERT(S_OK == hr || FAILED(hr));
  1659. return(hr);
  1660. }
  1661. // LockServer
  1662. STDMETHODIMP
  1663. CRequestFactory::LockServer(
  1664. BOOL bLock)
  1665. {
  1666. if (bLock)
  1667. {
  1668. InterlockedIncrement(&g_cRequestServerLocks);
  1669. }
  1670. else
  1671. {
  1672. InterlockedDecrement(&g_cRequestServerLocks);
  1673. }
  1674. return(S_OK);
  1675. }
  1676. STDMETHODIMP
  1677. CRequestFactory::CanUnloadNow()
  1678. {
  1679. if (g_cRequestComponents || g_cRequestServerLocks)
  1680. {
  1681. return(S_FALSE);
  1682. }
  1683. return(S_OK);
  1684. }
  1685. STDMETHODIMP
  1686. CRequestFactory::StartFactory()
  1687. {
  1688. HRESULT hr;
  1689. g_pIRequestFactory = new CRequestFactory();
  1690. if (NULL == g_pIRequestFactory)
  1691. {
  1692. hr = E_OUTOFMEMORY;
  1693. _JumpError(hr, error, "alloc CRequestFactory");
  1694. }
  1695. hr = CoRegisterClassObject(
  1696. CLSID_CCertRequestD,
  1697. static_cast<IUnknown *>(g_pIRequestFactory),
  1698. CLSCTX_LOCAL_SERVER,
  1699. REGCLS_MULTIPLEUSE,
  1700. &g_dwRequestRegister);
  1701. _JumpIfError(hr, error, "CoRegisterClassObject");
  1702. error:
  1703. if (S_OK != hr)
  1704. {
  1705. // does deletion
  1706. CRequestFactory::StopFactory();
  1707. }
  1708. CSASSERT(S_OK == hr || FAILED(hr));
  1709. return(hr);
  1710. }
  1711. VOID
  1712. CRequestFactory::StopFactory()
  1713. {
  1714. HRESULT hr;
  1715. if (0 != g_dwRequestRegister)
  1716. {
  1717. hr = CoRevokeClassObject(g_dwRequestRegister);
  1718. _PrintIfError(hr, "CoRevokeClassObject");
  1719. g_dwRequestRegister = 0;
  1720. }
  1721. if (NULL != g_pIRequestFactory)
  1722. {
  1723. g_pIRequestFactory->Release();
  1724. g_pIRequestFactory = NULL;
  1725. }
  1726. }