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.

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