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.

4017 lines
124 KiB

  1. //--------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation, 1996 - 1999
  3. //
  4. // File: wizards.cpp
  5. //
  6. // Contents: The cpp file to implement the wizards
  7. //
  8. // History: 16-10-1997 xiaohs created
  9. //
  10. //--------------------------------------------------------------
  11. #include "wzrdpvk.h"
  12. #include "certca.h"
  13. #include "cautil.h"
  14. #include "CertRequesterContext.h"
  15. #include "CertDSManager.h"
  16. #include "CertRequester.h"
  17. //need the CLSID and IID for xEnroll
  18. #include <ole2.h>
  19. #include <oleauto.h>
  20. #include "xenroll.h"
  21. #include "xenroll_i.c"
  22. #include <certrpc.h>
  23. #define _SET_XENROLL_PROPERTY_IF(condition, property, arg) \
  24. { \
  25. if ( condition ) { \
  26. if (S_OK != (hr = pIEnroll->put_ ## property ( arg ))) \
  27. goto xEnrollErr; \
  28. } \
  29. }
  30. // Used to provide singleton instances of useful COM objects in a demand-driven fashion.
  31. // See wzrdpvk.h.
  32. extern EnrollmentCOMObjectFactory *g_pEnrollFactory;
  33. extern HMODULE g_hmodRichEdit;
  34. extern HMODULE g_hmodxEnroll;
  35. typedef struct _CERT_ACCEPT_INFO
  36. {
  37. PCCERT_CONTEXT pCertContext;
  38. PCRYPT_DATA_BLOB pPKCS7Blob;
  39. LPWSTR pwszTitle;
  40. }CERT_ACCEPT_INFO;
  41. #define USE_NP
  42. typedef struct _CREATE_REQUEST_WIZARD_STATE {
  43. BOOL fMustFreeRequestBlob;
  44. CRYPT_DATA_BLOB RequestBlob;
  45. CRYPT_DATA_BLOB HashBlob;
  46. DWORD dwMyStoreFlags;
  47. DWORD dwRootStoreFlags;
  48. LPWSTR pwszMyStoreName;
  49. LPWSTR pwszRootStoreName;
  50. LONG lRequestFlags;
  51. BOOL fReusedPrivateKey;
  52. BOOL fNewKey;
  53. } CREATE_REQUEST_WIZARD_STATE, *PCREATE_REQUEST_WIZARD_STATE;
  54. typedef IEnroll4 * (WINAPI *PFNPIEnroll4GetNoCOM)();
  55. BOOL CertAllocAndGetCertificateContextProperty
  56. (IN PCCERT_CONTEXT pCertContext,
  57. IN DWORD dwPropID,
  58. OUT void **ppvData,
  59. OUT DWORD *pcbData)
  60. {
  61. if (NULL == ppvData || NULL == pcbData)
  62. return FALSE;
  63. *ppvData = 0;
  64. *pcbData = 0;
  65. if(!CertGetCertificateContextProperty
  66. (pCertContext,
  67. dwPropID,
  68. NULL,
  69. pcbData) || (0==*pcbData))
  70. return FALSE;
  71. *ppvData = WizardAlloc(*pcbData);
  72. if(NULL == *ppvData)
  73. return FALSE;
  74. if(!CertGetCertificateContextProperty
  75. (pCertContext,
  76. dwPropID,
  77. *ppvData,
  78. pcbData))
  79. return FALSE;
  80. return TRUE;
  81. }
  82. /*typedef HRESULT (WINAPI *pfDllGetClassObject)(REFCLSID rclsid,
  83. REFIID riid,
  84. LPVOID *ppvOut); */
  85. //////////////////////////////////////////////////////////////////////////////////////
  86. //
  87. //////////////////////////////////////////////////////////////////////////////////////
  88. //------------------------------------------------------------------------------
  89. // WizGetOpenFileName
  90. //----------------------------------------------------------------------------
  91. BOOL WizGetOpenFileName(LPOPENFILENAMEW pOpenFileName)
  92. {
  93. BOOL fResult=FALSE;
  94. __try {
  95. fResult=GetOpenFileNameU(pOpenFileName);
  96. } __except(EXCEPTION_EXECUTE_HANDLER) {
  97. SetLastError(GetExceptionCode());
  98. fResult=FALSE;
  99. }
  100. return fResult;
  101. }
  102. //------------------------------------------------------------------------------
  103. // WizGetSaveFileName
  104. //----------------------------------------------------------------------------
  105. BOOL WizGetSaveFileName(LPOPENFILENAMEW pOpenFileName)
  106. {
  107. BOOL fResult=FALSE;
  108. __try {
  109. fResult=GetSaveFileNameU(pOpenFileName);
  110. } __except(EXCEPTION_EXECUTE_HANDLER) {
  111. SetLastError(GetExceptionCode());
  112. fResult=FALSE;
  113. }
  114. return fResult;
  115. }
  116. void FreeProviders( DWORD dwCSPCount,
  117. DWORD *rgdwProviderType,
  118. LPWSTR *rgwszProvider)
  119. {
  120. //free the rgdwProviderType and rgwszProvider;
  121. if(NULL != rgdwProviderType) { WizardFree(rgdwProviderType); }
  122. if(NULL != rgwszProvider)
  123. {
  124. for(DWORD dwIndex=0; dwIndex<dwCSPCount; dwIndex++)
  125. {
  126. if (NULL != rgwszProvider[dwIndex]) { WizardFree(rgwszProvider[dwIndex]); }
  127. }
  128. WizardFree(rgwszProvider);
  129. }
  130. }
  131. //------------------------------------------------------------------------------
  132. // Unicode version of CB_GETLBTEXT
  133. //----------------------------------------------------------------------------
  134. LRESULT
  135. WINAPI
  136. SendDlgItemMessageU_GETLBTEXT
  137. ( HWND hwndDlg,
  138. int nIDDlgItem,
  139. int iIndex,
  140. LPWSTR *ppwsz
  141. )
  142. {
  143. LPSTR sz = NULL;
  144. LPWSTR pwsz=NULL;
  145. LRESULT lRet;
  146. int iLength=0;
  147. iLength=(int)SendDlgItemMessage(hwndDlg, nIDDlgItem,
  148. CB_GETLBTEXTLEN, iIndex, 0);
  149. if(iLength == CB_ERR)
  150. return CB_ERR;
  151. if(FIsWinNT())
  152. {
  153. *ppwsz=(LPWSTR)WizardAlloc(sizeof(WCHAR) * (iLength + 1));
  154. if(NULL == (*ppwsz))
  155. return CB_ERR;
  156. lRet = SendDlgItemMessageW(
  157. hwndDlg,
  158. nIDDlgItem,
  159. CB_GETLBTEXT,
  160. iIndex,
  161. (LPARAM) (*ppwsz)
  162. );
  163. if(CB_ERR == lRet)
  164. {
  165. WizardFree(*ppwsz);
  166. *ppwsz=NULL;
  167. }
  168. return lRet;
  169. }
  170. sz=(LPSTR)WizardAlloc(sizeof(CHAR) * (iLength + 1));
  171. if(NULL == sz)
  172. return CB_ERR;
  173. lRet = SendDlgItemMessageA(
  174. hwndDlg,
  175. nIDDlgItem,
  176. CB_GETLBTEXT,
  177. iIndex,
  178. (LPARAM)sz
  179. );
  180. if(CB_ERR == lRet)
  181. goto CLEANUP;
  182. if(NULL == (pwsz=MkWStr(sz)))
  183. {
  184. lRet=CB_ERR;
  185. goto CLEANUP;
  186. }
  187. *ppwsz=WizardAllocAndCopyWStr(pwsz);
  188. if(NULL == (*ppwsz))
  189. {
  190. lRet=CB_ERR;
  191. goto CLEANUP;
  192. }
  193. CLEANUP:
  194. if(sz)
  195. WizardFree(sz);
  196. if(pwsz)
  197. FreeWStr(pwsz);
  198. return (lRet);
  199. }
  200. //
  201. // A mapping from cert type flags to gen key flags.
  202. //
  203. BOOL CertTypeFlagsToGenKeyFlags(IN OPTIONAL DWORD dwEnrollmentFlags,
  204. IN OPTIONAL DWORD dwSubjectNameFlags,
  205. IN OPTIONAL DWORD dwPrivateKeyFlags,
  206. IN OPTIONAL DWORD dwGeneralFlags,
  207. OUT DWORD *pdwGenKeyFlags)
  208. {
  209. // Define a locally scoped helper function. This allows us to gain the benefits of procedural
  210. // abstraction without corrupting the global namespace.
  211. //
  212. LocalScope(CertTypeMap):
  213. // Maps cert type flags of one category (enrollment flags, private key flags, etc...)
  214. // to their corresponding gen key flags. This function always returns successfully.
  215. //
  216. DWORD mapOneCertTypeCategory(IN DWORD dwOption, IN DWORD dwCertTypeFlags)
  217. {
  218. static DWORD const rgdwEnrollmentFlags[][2] = {
  219. { 0, 0 } // No enrollment flags mapped.
  220. };
  221. static DWORD const rgdwSubjectNameFlags[][2] = {
  222. { 0, 0 } // No subject name flags mapped.
  223. };
  224. static DWORD const rgdwPrivateKeyFlags[][2] = {
  225. { CT_FLAG_EXPORTABLE_KEY, CRYPT_EXPORTABLE },
  226. { CT_FLAG_STRONG_KEY_PROTECTION_REQUIRED, CRYPT_USER_PROTECTED }
  227. };
  228. static DWORD const rgdwGeneralFlags[][2] = {
  229. { 0, 0 } // No general flags mapped.
  230. };
  231. static DWORD const dwEnrollmentLen = sizeof(rgdwEnrollmentFlags) / sizeof(DWORD[2]);
  232. static DWORD const dwSubjectNameLen = sizeof(rgdwSubjectNameFlags) / sizeof(DWORD[2]);
  233. static DWORD const dwPrivateKeyLen = sizeof(rgdwPrivateKeyFlags) / sizeof(DWORD[2]);
  234. static DWORD const dwGeneralLen = sizeof(rgdwGeneralFlags) / sizeof(DWORD[2]);
  235. static DWORD const CERT_TYPE_INDEX = 0;
  236. static DWORD const GEN_KEY_INDEX = 1;
  237. DWORD const *pdwFlags;
  238. DWORD dwLen, dwIndex, dwResult = 0;
  239. switch (dwOption)
  240. {
  241. case CERTTYPE_ENROLLMENT_FLAG:
  242. pdwFlags = &rgdwEnrollmentFlags[0][0];
  243. dwLen = dwEnrollmentLen;
  244. break;
  245. case CERTTYPE_SUBJECT_NAME_FLAG:
  246. pdwFlags = &rgdwSubjectNameFlags[0][0];
  247. dwLen = dwSubjectNameLen;
  248. break;
  249. case CERTTYPE_PRIVATE_KEY_FLAG:
  250. pdwFlags = &rgdwPrivateKeyFlags[0][0];
  251. dwLen = dwPrivateKeyLen;
  252. break;
  253. case CERTTYPE_GENERAL_FLAG:
  254. pdwFlags = &rgdwGeneralFlags[0][0];
  255. dwLen = dwGeneralLen;
  256. break;
  257. }
  258. for (dwIndex = 0; dwIndex < dwLen; dwIndex++)
  259. {
  260. if (0 != (pdwFlags[CERT_TYPE_INDEX] & dwCertTypeFlags))
  261. {
  262. dwResult |= pdwFlags[GEN_KEY_INDEX];
  263. }
  264. pdwFlags += 2;
  265. }
  266. return dwResult;
  267. }
  268. EndLocalScope;
  269. //
  270. // Begin procedure body:
  271. //
  272. BOOL fResult;
  273. DWORD dwResult = 0;
  274. DWORD dwErr = ERROR_SUCCESS;
  275. // Input parameter validation:
  276. _JumpConditionWithExpr(pdwGenKeyFlags == NULL, Error, dwErr = ERROR_INVALID_PARAMETER);
  277. // Compute the gen key flags using the locally scope function.
  278. dwResult |= local.mapOneCertTypeCategory(CERTTYPE_ENROLLMENT_FLAG, dwEnrollmentFlags);
  279. dwResult |= local.mapOneCertTypeCategory(CERTTYPE_SUBJECT_NAME_FLAG, dwSubjectNameFlags);
  280. dwResult |= local.mapOneCertTypeCategory(CERTTYPE_PRIVATE_KEY_FLAG, dwPrivateKeyFlags);
  281. dwResult |= local.mapOneCertTypeCategory(CERTTYPE_GENERAL_FLAG, dwGeneralFlags);
  282. // Assign the out parameter:
  283. *pdwGenKeyFlags = dwResult;
  284. fResult = TRUE;
  285. CommonReturn:
  286. return fResult;
  287. Error:
  288. fResult = FALSE;
  289. SetLastError(dwErr);
  290. goto CommonReturn;
  291. }
  292. HRESULT GetCAExchangeCertificate(IN BSTR bstrCAQualifiedName,
  293. OUT PCCERT_CONTEXT *ppCert)
  294. {
  295. HRESULT hr = S_OK;
  296. // BUGBUG: need to use global enrollment factory.
  297. EnrollmentCOMObjectFactory *pEnrollFactory = NULL;
  298. ICertRequest2 *pCertRequest = NULL;
  299. VARIANT varExchangeCertificate;
  300. // We're using a COM component in this method. It's absolutely necessary that we
  301. // uninitialize COM before we return, because we're running in an RPC thread,
  302. // and failing to uninitialize COM will cause us to step on RPC's toes.
  303. //
  304. // See BUG 404778.
  305. __try {
  306. // Input validation:
  307. if (NULL == bstrCAQualifiedName || NULL == ppCert)
  308. return E_INVALIDARG;
  309. // Init:
  310. *ppCert = NULL;
  311. varExchangeCertificate.vt = VT_EMPTY;
  312. varExchangeCertificate.bstrVal = NULL;
  313. pEnrollFactory = new EnrollmentCOMObjectFactory;
  314. if (NULL == pEnrollFactory)
  315. {
  316. hr = E_OUTOFMEMORY;
  317. goto Error;
  318. }
  319. if (S_OK != (hr = pEnrollFactory->getICertRequest2(&pCertRequest)))
  320. goto Error;
  321. if (S_OK != (hr = pCertRequest->GetCAProperty
  322. (bstrCAQualifiedName, // CA Name/CA Location
  323. CR_PROP_CAXCHGCERT, // Get the exchange certificate from the CA.
  324. 0, // Unused
  325. PROPTYPE_BINARY, //
  326. CR_OUT_BINARY, //
  327. &varExchangeCertificate // Variant type representing the certificate.
  328. )))
  329. goto Error;
  330. if (VT_BSTR != varExchangeCertificate.vt || NULL == varExchangeCertificate.bstrVal)
  331. {
  332. hr = E_UNEXPECTED;
  333. goto Error;
  334. }
  335. *ppCert = CertCreateCertificateContext
  336. (X509_ASN_ENCODING,
  337. (LPBYTE)varExchangeCertificate.bstrVal,
  338. SysStringByteLen(varExchangeCertificate.bstrVal));
  339. if (*ppCert == NULL)
  340. {
  341. hr = CodeToHR(GetLastError());
  342. goto Error;
  343. }
  344. } __except (EXCEPTION_EXECUTE_HANDLER) {
  345. hr = GetExceptionCode();
  346. goto Error;
  347. }
  348. CommonReturn:
  349. if (NULL != pCertRequest) { pCertRequest->Release(); }
  350. if (NULL != pEnrollFactory) { delete pEnrollFactory; }
  351. if (NULL != varExchangeCertificate.bstrVal) { SysFreeString(varExchangeCertificate.bstrVal); }
  352. return hr;
  353. Error:
  354. if (ppCert != NULL && *ppCert != NULL)
  355. {
  356. CertFreeCertificateContext(*ppCert);
  357. *ppCert = NULL;
  358. }
  359. goto CommonReturn;
  360. }
  361. HRESULT
  362. WizardSZToWSZ
  363. (IN LPCSTR psz,
  364. OUT LPWSTR *ppwsz)
  365. {
  366. HRESULT hr = S_OK;
  367. LONG cc = 0;
  368. if (NULL == ppwsz)
  369. return E_INVALIDARG;
  370. //init
  371. *ppwsz = NULL;
  372. cc = MultiByteToWideChar(GetACP(), 0, psz, -1, NULL, 0);
  373. if (0 == cc)
  374. goto Win32Err;
  375. *ppwsz = (LPWSTR)WizardAlloc(sizeof (WCHAR) * cc);
  376. if (NULL == *ppwsz)
  377. goto MemoryErr;
  378. cc = MultiByteToWideChar(GetACP(), 0, psz, -1, *ppwsz, cc);
  379. if (0 == cc)
  380. goto Win32Err;
  381. CommonReturn:
  382. return hr;
  383. ErrorReturn:
  384. if (NULL != ppwsz && NULL != *ppwsz)
  385. {
  386. WizardFree(*ppwsz);
  387. *ppwsz = NULL;
  388. }
  389. goto CommonReturn;
  390. SET_HRESULT(Win32Err, GetLastError());
  391. SET_HRESULT(MemoryErr, E_OUTOFMEMORY);
  392. }
  393. //--------------------------------------------------------------------------
  394. //
  395. // WizardAllocAndCopyStr
  396. //
  397. //--------------------------------------------------------------------------
  398. LPSTR WizardAllocAndCopyStr(LPSTR psz)
  399. {
  400. LPSTR pszReturn;
  401. if (NULL == (pszReturn = (LPSTR) WizardAlloc((strlen(psz)+1) * sizeof(CHAR))))
  402. {
  403. return NULL;
  404. }
  405. strcpy(pszReturn, psz);
  406. return(pszReturn);
  407. }
  408. //--------------------------------------------------------------------------
  409. //
  410. // WizardAllocAndConcatStrU
  411. //
  412. //--------------------------------------------------------------------------
  413. LPWSTR WizardAllocAndConcatStrsU(LPWSTR * rgStrings, DWORD dwStringsLen)
  414. {
  415. DWORD cbReturn = 0;
  416. LPWSTR pwszReturn = NULL;
  417. if (NULL == rgStrings)
  418. return NULL;
  419. for (DWORD dwIndex = 0; dwIndex < dwStringsLen; dwIndex++)
  420. cbReturn += wcslen(rgStrings[dwIndex]);
  421. // Add space for NULL character.
  422. cbReturn = (cbReturn + 1) * sizeof(WCHAR);
  423. if (NULL == (pwszReturn = (LPWSTR)WizardAlloc(cbReturn)))
  424. return NULL;
  425. for (DWORD dwIndex = 0; dwIndex < dwStringsLen; dwIndex++)
  426. wcscat(pwszReturn, rgStrings[dwIndex]);
  427. return (pwszReturn);
  428. }
  429. //--------------------------------------------------------------------------
  430. //
  431. // InitUnicodeString
  432. //
  433. //--------------------------------------------------------------------------
  434. void WizardInitUnicodeString(PKEYSVC_UNICODE_STRING pUnicodeString,
  435. LPCWSTR pszString
  436. )
  437. {
  438. pUnicodeString->Length = (USHORT)(wcslen(pszString) * sizeof(WCHAR));
  439. pUnicodeString->MaximumLength = pUnicodeString->Length + sizeof(WCHAR);
  440. pUnicodeString->Buffer = (USHORT*)pszString;
  441. }
  442. //--------------------------------------------------------------------------
  443. //
  444. // SetControlFont
  445. //
  446. //--------------------------------------------------------------------------
  447. void
  448. SetControlFont(
  449. IN HFONT hFont,
  450. IN HWND hwnd,
  451. IN INT nId
  452. )
  453. {
  454. if( hFont )
  455. {
  456. HWND hwndControl = GetDlgItem(hwnd, nId);
  457. if( hwndControl )
  458. {
  459. SetWindowFont(hwndControl, hFont, TRUE);
  460. }
  461. }
  462. }
  463. //--------------------------------------------------------------------------
  464. //
  465. // SetupFonts
  466. //
  467. //--------------------------------------------------------------------------
  468. BOOL
  469. SetupFonts(
  470. IN HINSTANCE hInstance,
  471. IN HWND hwnd,
  472. IN HFONT *pBigBoldFont,
  473. IN HFONT *pBoldFont
  474. )
  475. {
  476. //
  477. // Create the fonts we need based on the dialog font
  478. //
  479. NONCLIENTMETRICS ncm = {0};
  480. ncm.cbSize = sizeof(ncm);
  481. SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
  482. LOGFONT BigBoldLogFont = ncm.lfMessageFont;
  483. LOGFONT BoldLogFont = ncm.lfMessageFont;
  484. //
  485. // Create Big Bold Font and Bold Font
  486. //
  487. BigBoldLogFont.lfWeight = FW_BOLD;
  488. BoldLogFont.lfWeight = FW_BOLD;
  489. CHAR FontSizeString[24];
  490. INT BigBoldFontSize;
  491. INT BoldFontSize;
  492. //
  493. // Load size and name from resources, since these may change
  494. // from locale to locale based on the size of the system font, etc.
  495. //
  496. /*
  497. //no longer needs to do it. We are loading the default font
  498. if(!LoadStringA(hInstance,IDS_LARGEFONTNAME,BigBoldLogFont.lfFaceName,LF_FACESIZE))
  499. {
  500. lstrcpy(BigBoldLogFont.lfFaceName,TEXT("MS Shell Dlg"));
  501. }
  502. if(!LoadStringA(hInstance,IDS_BOLDFONTNAME,BoldLogFont.lfFaceName,LF_FACESIZE))
  503. {
  504. lstrcpy(BoldLogFont.lfFaceName,TEXT("MS Sans Serif"));
  505. }
  506. */
  507. if(LoadStringA(hInstance,IDS_LARGEFONTSIZE,FontSizeString,sizeof(FontSizeString)))
  508. {
  509. BigBoldFontSize = strtoul( FontSizeString, NULL, 10 );
  510. }
  511. else
  512. {
  513. BigBoldFontSize = 12;
  514. }
  515. /*
  516. if(LoadStringA(hInstance,IDS_BOLDFONTSIZE,FontSizeString,sizeof(FontSizeString)))
  517. {
  518. BoldFontSize = strtoul( FontSizeString, NULL, 10 );
  519. }
  520. else
  521. {
  522. BoldFontSize = 8;
  523. }
  524. */
  525. HDC hdc = GetDC( hwnd );
  526. if( hdc )
  527. {
  528. BigBoldLogFont.lfHeight = 0 - (GetDeviceCaps(hdc,LOGPIXELSY) * BigBoldFontSize / 72);
  529. // BoldLogFont.lfHeight = 0 - (GetDeviceCaps(hdc,LOGPIXELSY) * BoldFontSize / 72);
  530. *pBigBoldFont = CreateFontIndirect(&BigBoldLogFont);
  531. *pBoldFont = CreateFontIndirect(&BoldLogFont);
  532. ReleaseDC(hwnd,hdc);
  533. if(*pBigBoldFont && *pBoldFont)
  534. return TRUE;
  535. else
  536. {
  537. if( *pBigBoldFont )
  538. {
  539. DeleteObject(*pBigBoldFont);
  540. }
  541. if( *pBoldFont )
  542. {
  543. DeleteObject(*pBoldFont);
  544. }
  545. return FALSE;
  546. }
  547. }
  548. return FALSE;
  549. }
  550. //--------------------------------------------------------------------------
  551. //
  552. // DestroyFonts
  553. //
  554. //--------------------------------------------------------------------------
  555. void
  556. DestroyFonts(
  557. IN HFONT hBigBoldFont,
  558. IN HFONT hBoldFont
  559. )
  560. {
  561. if( hBigBoldFont )
  562. {
  563. DeleteObject( hBigBoldFont );
  564. }
  565. if( hBoldFont )
  566. {
  567. DeleteObject( hBoldFont );
  568. }
  569. }
  570. //-------------------------------------------------------------------------
  571. //
  572. // Unicode version of SendMessage
  573. //
  574. //-------------------------------------------------------------------------
  575. LRESULT Send_LB_GETTEXT(
  576. HWND hwnd,
  577. WPARAM wParam,
  578. LPARAM lParam
  579. )
  580. {
  581. int iLength=0;
  582. LPSTR psz=0;
  583. LRESULT lResult;
  584. BOOL fResult=FALSE;
  585. if(FIsWinNT())
  586. {
  587. return SendMessageW(hwnd, LB_GETTEXT, wParam, lParam);
  588. }
  589. //get the length of the buffer
  590. iLength=(int)SendMessageA(hwnd, LB_GETTEXTLEN, wParam, 0);
  591. psz=(LPSTR)WizardAlloc(iLength+1);
  592. if(NULL==psz)
  593. return LB_ERR;
  594. lResult=SendMessageA(hwnd, LB_GETTEXT, wParam, (LPARAM)psz);
  595. if(LB_ERR==lResult)
  596. {
  597. WizardFree(psz);
  598. return LB_ERR;
  599. }
  600. fResult=MultiByteToWideChar(
  601. 0,
  602. 0,
  603. psz,
  604. -1,
  605. (LPWSTR)lParam,
  606. iLength+1);
  607. WizardFree(psz);
  608. if(TRUE==fResult)
  609. return lResult;
  610. else
  611. return LB_ERR;
  612. }
  613. //-------------------------------------------------------------------------
  614. //
  615. // Unicode version of SendMessage
  616. //
  617. //-------------------------------------------------------------------------
  618. LRESULT Send_LB_ADDSTRING(
  619. HWND hwnd,
  620. WPARAM wParam,
  621. LPARAM lParam
  622. )
  623. {
  624. LPSTR psz=NULL;
  625. LRESULT lResult;
  626. if(FIsWinNT())
  627. {
  628. return SendMessageW(hwnd, LB_ADDSTRING, wParam, lParam);
  629. }
  630. psz=(LPSTR)WizardAlloc(wcslen((LPWSTR)lParam)+1);
  631. if(NULL==psz)
  632. return LB_ERRSPACE;
  633. if(0==WideCharToMultiByte(0, 0, (LPWSTR)lParam, -1, psz, wcslen((LPWSTR)lParam)+1, NULL, NULL))
  634. {
  635. WizardFree(psz);
  636. return LB_ERR;
  637. }
  638. lResult=SendMessageA(hwnd, LB_ADDSTRING, wParam, (LPARAM)psz);
  639. WizardFree(psz);
  640. return lResult;
  641. }
  642. //-----------------------------------------------------------------------
  643. // Get the default CSP name based on the provider type
  644. //
  645. //------------------------------------------------------------------------
  646. BOOL CSPSupported(CERT_WIZARD_INFO *pCertWizardInfo)
  647. {
  648. BOOL fResult=FALSE;
  649. DWORD dwIndex=0;
  650. if(!pCertWizardInfo)
  651. goto InvalidArgErr;
  652. if(!(pCertWizardInfo->dwProviderType) || !(pCertWizardInfo->pwszProvider))
  653. goto InvalidArgErr;
  654. for(dwIndex=0; dwIndex < pCertWizardInfo->dwCSPCount; dwIndex++)
  655. {
  656. if((pCertWizardInfo->dwProviderType == pCertWizardInfo->rgdwProviderType[dwIndex] ) &&
  657. (0==_wcsicmp(pCertWizardInfo->pwszProvider, pCertWizardInfo->rgwszProvider[dwIndex]))
  658. )
  659. {
  660. fResult=TRUE;
  661. break;
  662. }
  663. }
  664. CommonReturn:
  665. return fResult;
  666. ErrorReturn:
  667. fResult=FALSE;
  668. goto CommonReturn;
  669. SET_ERROR(InvalidArgErr, E_INVALIDARG);
  670. }
  671. //-----------------------------------------------------------------------
  672. // Get a list of allowed CAs
  673. //
  674. //------------------------------------------------------------------------
  675. BOOL GetCAName(CERT_WIZARD_INFO *pCertWizardInfo)
  676. {
  677. DWORD dwErr=0;
  678. KEYSVC_TYPE dwServiceType=KeySvcMachine;
  679. KEYSVCC_HANDLE hKeyService=NULL;
  680. PKEYSVC_UNICODE_STRING pCA = NULL;
  681. DWORD cCA=0;
  682. LPSTR pszMachineName=NULL;
  683. DWORD cbArray = 0;
  684. DWORD i=0;
  685. LPWSTR wszCurrentCA=NULL;
  686. BOOL fResult=FALSE;
  687. // We're not doing a local enrollment, so we must enroll via keysvc. Get the
  688. // list of acceptable cert types.
  689. if(pCertWizardInfo->pwszAccountName)
  690. dwServiceType=KeySvcService;
  691. else
  692. dwServiceType=KeySvcMachine;
  693. if(!MkMBStr(NULL, 0, pCertWizardInfo->pwszMachineName, &pszMachineName))
  694. goto TraceErr;
  695. dwErr = KeyOpenKeyService(pszMachineName,
  696. dwServiceType,
  697. (LPWSTR)(pCertWizardInfo->pwszAccountName),
  698. NULL, // no authentication string right now
  699. NULL,
  700. &hKeyService);
  701. if(dwErr != ERROR_SUCCESS)
  702. {
  703. SetLastError(dwErr);
  704. goto TraceErr;
  705. }
  706. dwErr = KeyEnumerateCAs(hKeyService,
  707. NULL,
  708. CA_FIND_LOCAL_SYSTEM,
  709. &cCA,
  710. &pCA);
  711. if(dwErr != ERROR_SUCCESS)
  712. {
  713. SetLastError(dwErr);
  714. goto TraceErr;
  715. }
  716. cbArray = (cCA+1)*sizeof(LPWSTR);
  717. // Convert into a simple array
  718. for(i=0; i < cCA; i++)
  719. {
  720. cbArray += pCA[i].Length;
  721. }
  722. pCertWizardInfo->awszValidCA = (LPWSTR *)WizardAlloc(cbArray);
  723. if(pCertWizardInfo->awszValidCA == NULL)
  724. goto MemoryErr;
  725. memset(pCertWizardInfo->awszValidCA, 0, cbArray);
  726. wszCurrentCA = (LPWSTR)(&((pCertWizardInfo->awszValidCA)[cCA + 1]));
  727. for(i=0; i < cCA; i++)
  728. {
  729. (pCertWizardInfo->awszValidCA)[i] = wszCurrentCA;
  730. wcscpy(wszCurrentCA, pCA[i].Buffer);
  731. wszCurrentCA += wcslen(wszCurrentCA)+1;
  732. }
  733. fResult=TRUE;
  734. CommonReturn:
  735. if(pCA)
  736. WizardFree(pCA);
  737. if(hKeyService)
  738. KeyCloseKeyService(hKeyService, NULL);
  739. if(pszMachineName)
  740. FreeMBStr(NULL,pszMachineName);
  741. return fResult;
  742. ErrorReturn:
  743. fResult=FALSE;
  744. goto CommonReturn;
  745. TRACE_ERROR(TraceErr);
  746. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  747. }
  748. //-----------------------------------------------------------------------
  749. // Get a list of allowed cert types
  750. //
  751. //------------------------------------------------------------------------
  752. BOOL GetCertTypeName(CERT_WIZARD_INFO *pCertWizardInfo)
  753. {
  754. DWORD dwErr=0;
  755. KEYSVC_TYPE dwServiceType=KeySvcMachine;
  756. KEYSVCC_HANDLE hKeyService=NULL;
  757. PKEYSVC_UNICODE_STRING pCertTypes = NULL;
  758. DWORD cTypes=0;
  759. LPSTR pszMachineName=NULL;
  760. DWORD cbArray = 0;
  761. DWORD i=0;
  762. LPWSTR wszCurrentType;
  763. BOOL fResult=FALSE;
  764. // We're not doing a local enrollment, so we must enroll via keysvc. Get the
  765. // list of acceptable cert types.
  766. if(pCertWizardInfo->pwszAccountName)
  767. dwServiceType=KeySvcService;
  768. else
  769. dwServiceType=KeySvcMachine;
  770. if(!MkMBStr(NULL, 0, pCertWizardInfo->pwszMachineName, &pszMachineName))
  771. goto TraceErr;
  772. dwErr = KeyOpenKeyService(pszMachineName,
  773. dwServiceType,
  774. (LPWSTR)(pCertWizardInfo->pwszAccountName),
  775. NULL, // no authentication string right now
  776. NULL,
  777. &hKeyService);
  778. if(dwErr != ERROR_SUCCESS)
  779. {
  780. SetLastError(dwErr);
  781. goto TraceErr;
  782. }
  783. dwErr = KeyEnumerateAvailableCertTypes(hKeyService,
  784. NULL,
  785. &cTypes,
  786. &pCertTypes);
  787. if(dwErr != ERROR_SUCCESS)
  788. {
  789. SetLastError(dwErr);
  790. goto TraceErr;
  791. }
  792. cbArray = (cTypes+1)*sizeof(LPWSTR);
  793. // Convert into a simple array
  794. for(i=0; i < cTypes; i++)
  795. {
  796. cbArray += pCertTypes[i].Length;
  797. }
  798. pCertWizardInfo->awszAllowedCertTypes = (LPWSTR *)WizardAlloc(cbArray);
  799. if(pCertWizardInfo->awszAllowedCertTypes == NULL)
  800. goto MemoryErr;
  801. memset(pCertWizardInfo->awszAllowedCertTypes, 0, cbArray);
  802. wszCurrentType = (LPWSTR)(&((pCertWizardInfo->awszAllowedCertTypes)[cTypes + 1]));
  803. for(i=0; i < cTypes; i++)
  804. {
  805. (pCertWizardInfo->awszAllowedCertTypes)[i] = wszCurrentType;
  806. wcscpy(wszCurrentType, pCertTypes[i].Buffer);
  807. wszCurrentType += wcslen(wszCurrentType)+1;
  808. }
  809. fResult=TRUE;
  810. CommonReturn:
  811. if(pCertTypes)
  812. WizardFree(pCertTypes);
  813. if(hKeyService)
  814. KeyCloseKeyService(hKeyService, NULL);
  815. if(pszMachineName)
  816. FreeMBStr(NULL,pszMachineName);
  817. return fResult;
  818. ErrorReturn:
  819. fResult=FALSE;
  820. goto CommonReturn;
  821. TRACE_ERROR(TraceErr);
  822. SET_ERROR(MemoryErr, E_OUTOFMEMORY);
  823. }
  824. //-----------------------------------------------------------------------
  825. // WizardInit
  826. //------------------------------------------------------------------------
  827. BOOL WizardInit(BOOL fLoadRichEdit)
  828. {
  829. if ((fLoadRichEdit) && (g_hmodRichEdit == NULL))
  830. {
  831. g_hmodRichEdit = LoadLibraryA("RichEd32.dll");
  832. if (g_hmodRichEdit == NULL) {
  833. return FALSE;
  834. }
  835. }
  836. INITCOMMONCONTROLSEX initcomm = {
  837. sizeof(initcomm), ICC_NATIVEFNTCTL_CLASS | ICC_LISTVIEW_CLASSES
  838. };
  839. InitCommonControlsEx(&initcomm);
  840. return TRUE;
  841. }
  842. //-----------------------------------------------------------------------
  843. //check for the private key information
  844. //-----------------------------------------------------------------------
  845. BOOL CheckPVKInfoNoDS(DWORD dwFlags,
  846. DWORD dwPvkChoice,
  847. PCCRYPTUI_WIZ_CERT_REQUEST_PVK_CERT pCertRequestPvkContext,
  848. PCCRYPTUI_WIZ_CERT_REQUEST_PVK_NEW pCertRequestPvkNew,
  849. PCCRYPTUI_WIZ_CERT_REQUEST_PVK_EXISTING pCertRequestPvkExisting,
  850. DWORD dwCertChoice,
  851. CERT_WIZARD_INFO *pCertWizardInfo,
  852. CRYPT_KEY_PROV_INFO **ppKeyProvInfo)
  853. {
  854. DWORD cbData = 0;
  855. BOOL fResult = FALSE;
  856. pCertWizardInfo->fIgnore=FALSE;
  857. //check if we need to generate a new private key
  858. switch(dwPvkChoice)
  859. {
  860. case CRYPTUI_WIZ_CERT_REQUEST_PVK_CHOICE_CERT:
  861. if (sizeof(CRYPTUI_WIZ_CERT_REQUEST_PVK_CERT) != pCertRequestPvkContext->dwSize)
  862. return FALSE;
  863. if(NULL==pCertRequestPvkContext->pCertContext)
  864. return FALSE;
  865. //pCertContext should have a property of CRYPT_KEY_PROV_INFO
  866. if(!CertAllocAndGetCertificateContextProperty
  867. (pCertRequestPvkContext->pCertContext,
  868. CERT_KEY_PROV_INFO_PROP_ID,
  869. (LPVOID *)ppKeyProvInfo,
  870. &cbData))
  871. goto CLEANUP;
  872. pCertWizardInfo->fNewKey = FALSE;
  873. pCertWizardInfo->dwProviderType = (*ppKeyProvInfo)->dwProvType;
  874. pCertWizardInfo->pwszProvider = (*ppKeyProvInfo)->pwszProvName;
  875. pCertWizardInfo->dwProviderFlags = (*ppKeyProvInfo)->dwFlags;
  876. pCertWizardInfo->pwszKeyContainer = (*ppKeyProvInfo)->pwszContainerName;
  877. pCertWizardInfo->dwKeySpec = (*ppKeyProvInfo)->dwKeySpec;
  878. break;
  879. case CRYPTUI_WIZ_CERT_REQUEST_PVK_CHOICE_NEW:
  880. //check the size of the struct
  881. if(pCertRequestPvkNew->dwSize!=sizeof(CRYPTUI_WIZ_CERT_REQUEST_PVK_NEW))
  882. goto CLEANUP;
  883. pCertWizardInfo->fNewKey=TRUE;
  884. //we only copy the information if:
  885. //1. Cert type is required
  886. //2. The CSP is specified
  887. if((CRYPTUI_WIZ_CERT_REQUEST_CERT_TYPE == dwCertChoice) || (0 == dwCertChoice))
  888. {
  889. if(pCertRequestPvkNew->pKeyProvInfo)
  890. {
  891. if( (0 == pCertRequestPvkNew->pKeyProvInfo->dwProvType) &&
  892. (NULL == (LPWSTR)(pCertRequestPvkNew->pKeyProvInfo->pwszProvName))
  893. )
  894. pCertWizardInfo->fIgnore=TRUE;
  895. }
  896. else
  897. pCertWizardInfo->fIgnore=TRUE;
  898. }
  899. //see if pKeyProvInfo is not NULL
  900. if(pCertRequestPvkNew->pKeyProvInfo)
  901. {
  902. if(TRUE == pCertWizardInfo->fIgnore)
  903. {
  904. pCertWizardInfo->pwszKeyContainer =pCertRequestPvkNew->pKeyProvInfo->pwszContainerName;
  905. pCertWizardInfo->dwProviderFlags =pCertRequestPvkNew->pKeyProvInfo->dwFlags;
  906. }
  907. else
  908. {
  909. pCertWizardInfo->dwProviderType =pCertRequestPvkNew->pKeyProvInfo->dwProvType;
  910. pCertWizardInfo->pwszProvider =(LPWSTR)(pCertRequestPvkNew->pKeyProvInfo->pwszProvName);
  911. pCertWizardInfo->dwProviderFlags =pCertRequestPvkNew->pKeyProvInfo->dwFlags;
  912. pCertWizardInfo->pwszKeyContainer =pCertRequestPvkNew->pKeyProvInfo->pwszContainerName;
  913. pCertWizardInfo->dwKeySpec =pCertRequestPvkNew->pKeyProvInfo->dwKeySpec;
  914. }
  915. }
  916. if(TRUE == pCertWizardInfo->fIgnore)
  917. //we should ignore the exportable flag
  918. pCertWizardInfo->dwGenKeyFlags=(pCertRequestPvkNew->dwGenKeyFlags & (~CRYPT_EXPORTABLE));
  919. else
  920. pCertWizardInfo->dwGenKeyFlags=pCertRequestPvkNew->dwGenKeyFlags;
  921. break;
  922. case CRYPTUI_WIZ_CERT_REQUEST_PVK_CHOICE_EXISTING:
  923. //check the size of the struct
  924. if(pCertRequestPvkExisting->dwSize!=sizeof(CRYPTUI_WIZ_CERT_REQUEST_PVK_EXISTING))
  925. goto CLEANUP;
  926. pCertWizardInfo->fNewKey=FALSE;
  927. //make sure pKeyProvInfo is not NULL
  928. if(NULL==pCertRequestPvkExisting->pKeyProvInfo)
  929. goto CLEANUP;
  930. pCertWizardInfo->dwProviderType =pCertRequestPvkExisting->pKeyProvInfo->dwProvType;
  931. pCertWizardInfo->pwszProvider =(LPWSTR)(pCertRequestPvkExisting->pKeyProvInfo->pwszProvName);
  932. pCertWizardInfo->dwProviderFlags =pCertRequestPvkExisting->pKeyProvInfo->dwFlags;
  933. pCertWizardInfo->pwszKeyContainer =pCertRequestPvkExisting->pKeyProvInfo->pwszContainerName;
  934. pCertWizardInfo->dwKeySpec =pCertRequestPvkExisting->pKeyProvInfo->dwKeySpec;
  935. break;
  936. default:
  937. goto CLEANUP;
  938. break;
  939. }
  940. //for existing keys, keyContainer and providerType has to set
  941. if(FALSE==pCertWizardInfo->fNewKey)
  942. {
  943. if(NULL==pCertWizardInfo->pwszKeyContainer)
  944. goto CLEANUP;
  945. if(0==pCertWizardInfo->dwProviderType)
  946. goto CLEANUP;
  947. }
  948. //if the provider name is set, the provider type has to be set
  949. if(0 == pCertWizardInfo->dwProviderType)
  950. {
  951. if(pCertWizardInfo->pwszProvider)
  952. goto CLEANUP;
  953. }
  954. fResult=TRUE;
  955. CLEANUP:
  956. if(FALSE==fResult)
  957. {
  958. if(*ppKeyProvInfo)
  959. {
  960. WizardFree(*ppKeyProvInfo);
  961. *ppKeyProvInfo=NULL;
  962. }
  963. }
  964. return fResult;
  965. }
  966. BOOL CheckPVKInfo( DWORD dwFlags,
  967. PCCRYPTUI_WIZ_CERT_REQUEST_INFO pCertRequestInfo,
  968. CERT_WIZARD_INFO *pCertWizardInfo,
  969. CRYPT_KEY_PROV_INFO **ppKeyProvInfo)
  970. {
  971. if(NULL == pCertRequestInfo)
  972. return FALSE;
  973. return CheckPVKInfoNoDS
  974. (dwFlags,
  975. pCertRequestInfo->dwPvkChoice,
  976. pCertRequestInfo->pPvkCert,
  977. pCertRequestInfo->pPvkNew,
  978. pCertRequestInfo->pPvkExisting,
  979. pCertRequestInfo->dwCertChoice,
  980. pCertWizardInfo,
  981. ppKeyProvInfo);
  982. }
  983. //-----------------------------------------------------------------------
  984. // Reset properties on the old certiifcate to the new certificat context
  985. //------------------------------------------------------------------------
  986. void ResetProperties(PCCERT_CONTEXT pOldCertContext, PCCERT_CONTEXT pNewCertContext)
  987. {
  988. DWORD rgProperties[2]={CERT_FRIENDLY_NAME_PROP_ID,
  989. CERT_DESCRIPTION_PROP_ID};
  990. DWORD cbData=0;
  991. BYTE *pbData=NULL;
  992. DWORD dwCount=sizeof(rgProperties)/sizeof(rgProperties[0]);
  993. DWORD dwIndex=0;
  994. if(NULL==pOldCertContext || NULL==pNewCertContext)
  995. return;
  996. //set the properies one at a time
  997. for(dwIndex=0; dwIndex<dwCount; dwIndex++)
  998. {
  999. if (CertAllocAndGetCertificateContextProperty
  1000. (pOldCertContext,
  1001. rgProperties[dwIndex],
  1002. (LPVOID *)&pbData,
  1003. &cbData))
  1004. {
  1005. CertSetCertificateContextProperty
  1006. (pNewCertContext,
  1007. rgProperties[dwIndex],
  1008. 0,
  1009. pbData);
  1010. }
  1011. WizardFree(pbData);
  1012. pbData=NULL;
  1013. }
  1014. if(pbData)
  1015. WizardFree(pbData);
  1016. return;
  1017. }
  1018. //-----------------------------------------------------------------------
  1019. // Private implementation of the message box
  1020. //------------------------------------------------------------------------
  1021. int I_MessageBox(
  1022. HWND hWnd,
  1023. UINT idsText,
  1024. UINT idsCaption,
  1025. LPCWSTR pwszCaption,
  1026. UINT uType
  1027. )
  1028. {
  1029. WCHAR wszText[MAX_STRING_SIZE];
  1030. WCHAR wszCaption[MAX_STRING_SIZE];
  1031. UINT intReturn=0;
  1032. //get the caption string
  1033. if(NULL == pwszCaption)
  1034. {
  1035. if(!LoadStringU(g_hmodThisDll, idsCaption, wszCaption, ARRAYSIZE(wszCaption)))
  1036. return 0;
  1037. pwszCaption = wszCaption;
  1038. }
  1039. //get the text string
  1040. if(!LoadStringU(g_hmodThisDll, idsText, wszText, ARRAYSIZE(wszText)))
  1041. {
  1042. return 0;
  1043. }
  1044. intReturn=MessageBoxExW(hWnd, wszText, pwszCaption, uType, 0);
  1045. return intReturn;
  1046. }
  1047. //-----------------------------------------------------------------------
  1048. //
  1049. // CodeToHR
  1050. //
  1051. //------------------------------------------------------------------------
  1052. HRESULT CodeToHR(HRESULT hr)
  1053. {
  1054. if (S_OK != (DWORD) hr && S_FALSE != (DWORD) hr &&
  1055. (!FAILED(hr) || 0 == HRESULT_FACILITY(hr)))
  1056. {
  1057. hr = HRESULT_FROM_WIN32(hr);
  1058. if (0 == HRESULT_CODE(hr))
  1059. {
  1060. // A call failed without properly setting an error condition!
  1061. hr = E_UNEXPECTED;
  1062. }
  1063. }
  1064. return(hr);
  1065. }
  1066. //-----------------------------------------------------------------------
  1067. //
  1068. // CAUtilAddSMIME
  1069. //
  1070. //------------------------------------------------------------------------
  1071. BOOL CAUtilAddSMIME(DWORD dwExtensions,
  1072. PCERT_EXTENSIONS *prgExtensions)
  1073. {
  1074. BOOL fSMIME = FALSE;
  1075. DWORD dwIndex = 0;
  1076. DWORD dwExt = 0;
  1077. PCERT_EXTENSION pExt = NULL;
  1078. DWORD cb = 0;
  1079. DWORD dwUsage = 0;
  1080. CERT_ENHKEY_USAGE *pUsage = NULL;
  1081. for(dwIndex=0; dwIndex < dwExtensions; dwIndex++)
  1082. {
  1083. for(dwExt=0; dwExt < prgExtensions[dwIndex]->cExtension; dwExt++)
  1084. {
  1085. pExt=&(prgExtensions[dwIndex]->rgExtension[dwExt]);
  1086. if(0==_stricmp(szOID_ENHANCED_KEY_USAGE, pExt->pszObjId))
  1087. {
  1088. if(!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1089. X509_ENHANCED_KEY_USAGE,
  1090. pExt->Value.pbData,
  1091. pExt->Value.cbData,
  1092. 0,
  1093. NULL,
  1094. &cb))
  1095. goto CLEANUP;
  1096. pUsage=(CERT_ENHKEY_USAGE *)WizardAlloc(cb);
  1097. if(NULL==pUsage)
  1098. goto CLEANUP;
  1099. if(!CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  1100. X509_ENHANCED_KEY_USAGE,
  1101. pExt->Value.pbData,
  1102. pExt->Value.cbData,
  1103. 0,
  1104. pUsage,
  1105. &cb))
  1106. goto CLEANUP;
  1107. for(dwUsage=0; dwUsage<pUsage->cUsageIdentifier; dwUsage++)
  1108. {
  1109. if(0==_stricmp(szOID_PKIX_KP_EMAIL_PROTECTION,
  1110. pUsage->rgpszUsageIdentifier[dwUsage]))
  1111. {
  1112. fSMIME=TRUE;
  1113. goto CLEANUP;
  1114. }
  1115. }
  1116. if(pUsage)
  1117. {
  1118. WizardFree(pUsage);
  1119. pUsage=NULL;
  1120. }
  1121. }
  1122. }
  1123. }
  1124. CLEANUP:
  1125. if(pUsage)
  1126. WizardFree(pUsage);
  1127. return fSMIME;
  1128. }
  1129. //-----------------------------------------------------------------------
  1130. //
  1131. // The following are memory routines for certdg_c.c
  1132. //------------------------------------------------------------------------
  1133. void*
  1134. MIDL_user_allocate(size_t cb)
  1135. {
  1136. return(WizardAlloc(cb));
  1137. }
  1138. void
  1139. MIDL_user_free(void *pb)
  1140. {
  1141. WizardFree(pb);
  1142. }
  1143. //-----------------------------------------------------------------------
  1144. //
  1145. // CanUse1024BitKey
  1146. //
  1147. //------------------------------------------------------------------------
  1148. BOOL CanUse1024BitKey(DWORD dwProvType,
  1149. LPCWSTR pwszProvider,
  1150. DWORD dwUserKeySpec)
  1151. {
  1152. DWORD dwKeySpec=0;
  1153. DWORD dwCSPCount=0;
  1154. DWORD dwIndex=0;
  1155. LPWSTR rgwszCSP[]={MS_DEF_PROV_W,
  1156. MS_ENHANCED_PROV_W,
  1157. MS_STRONG_PROV_W,
  1158. MS_DEF_RSA_SCHANNEL_PROV_W,
  1159. MS_DEF_DSS_PROV_W,
  1160. MS_DEF_DSS_DH_PROV_W,
  1161. MS_ENH_DSS_DH_PROV_W,
  1162. MS_DEF_DH_SCHANNEL_PROV_W};
  1163. DWORD dwFlags=0;
  1164. DWORD cbSize=0;
  1165. PROV_ENUMALGS_EX paramData;
  1166. DWORD dwMin=0;
  1167. DWORD dwMax=0;
  1168. HCRYPTPROV hProv = NULL;
  1169. //if dwProvType is 0, we are using the base provider, which supports
  1170. //1024 bit in all key spec
  1171. if(0 == dwProvType)
  1172. return TRUE;
  1173. if(pwszProvider)
  1174. {
  1175. dwCSPCount=sizeof(rgwszCSP)/sizeof(rgwszCSP[0]);
  1176. for(dwIndex=0; dwIndex < dwCSPCount; dwIndex++)
  1177. {
  1178. if(0 == _wcsicmp(pwszProvider, rgwszCSP[dwIndex]))
  1179. break;
  1180. }
  1181. if(dwIndex != dwCSPCount)
  1182. return TRUE;
  1183. }
  1184. dwKeySpec=dwUserKeySpec;
  1185. //xenroll uses AT_SIGNATURE as the default
  1186. if(0 == dwKeySpec)
  1187. dwKeySpec=AT_SIGNATURE;
  1188. if(!CryptAcquireContextU(&hProv,
  1189. NULL,
  1190. pwszProvider,
  1191. dwProvType,
  1192. CRYPT_VERIFYCONTEXT))
  1193. return FALSE;
  1194. //get the max/min of key length for both signature and encryption
  1195. dwFlags=CRYPT_FIRST;
  1196. cbSize=sizeof(paramData);
  1197. memset(&paramData, 0, sizeof(PROV_ENUMALGS_EX));
  1198. while(CryptGetProvParam(
  1199. hProv,
  1200. PP_ENUMALGS_EX,
  1201. (BYTE *) &paramData,
  1202. &cbSize,
  1203. dwFlags))
  1204. {
  1205. if(AT_SIGNATURE == dwKeySpec)
  1206. {
  1207. if (ALG_CLASS_SIGNATURE == GET_ALG_CLASS(paramData.aiAlgid))
  1208. {
  1209. dwMax = paramData.dwMaxLen;
  1210. dwMin = paramData.dwMinLen;
  1211. break;
  1212. }
  1213. }
  1214. else
  1215. {
  1216. if(AT_KEYEXCHANGE == dwKeySpec)
  1217. {
  1218. if (ALG_CLASS_KEY_EXCHANGE == GET_ALG_CLASS(paramData.aiAlgid))
  1219. {
  1220. dwMax = paramData.dwMaxLen;
  1221. dwMin = paramData.dwMinLen;
  1222. break;
  1223. }
  1224. }
  1225. }
  1226. dwFlags=0;
  1227. cbSize=sizeof(paramData);
  1228. memset(&paramData, 0, sizeof(PROV_ENUMALGS_EX));
  1229. }
  1230. if(hProv)
  1231. CryptReleaseContext(hProv, 0);
  1232. if((1024 >= dwMin) && (1024 <= dwMax))
  1233. return TRUE;
  1234. return FALSE;
  1235. }
  1236. BOOL GetValidKeySizes
  1237. (IN LPCWSTR pwszProvider,
  1238. IN DWORD dwProvType,
  1239. IN DWORD dwUserKeySpec,
  1240. OUT DWORD * pdwMinLen,
  1241. OUT DWORD * pdwMaxLen,
  1242. OUT DWORD * pdwInc)
  1243. {
  1244. BOOL fDone = FALSE;
  1245. BOOL fFoundAlgorithm = FALSE;
  1246. BOOL fResult = FALSE;
  1247. DWORD cbSize = 0;
  1248. DWORD dwFlags = 0;
  1249. DWORD dwParam = 0;
  1250. HCRYPTPROV hProv = NULL;
  1251. PROV_ENUMALGS_EX paramData;
  1252. if((NULL==pwszProvider) || (0 == dwProvType))
  1253. goto InvalidArgError;
  1254. if (!CryptAcquireContextU
  1255. (&hProv,
  1256. NULL,
  1257. pwszProvider,
  1258. dwProvType,
  1259. CRYPT_VERIFYCONTEXT))
  1260. goto CryptAcquireContextUError;
  1261. dwFlags = CRYPT_FIRST;
  1262. cbSize = sizeof(paramData);
  1263. while((!fDone) && (!fFoundAlgorithm))
  1264. {
  1265. memset(&paramData, 0, sizeof(PROV_ENUMALGS_EX));
  1266. // We're done searching if CryptGetProvParam fails.
  1267. fDone = !CryptGetProvParam
  1268. (hProv,
  1269. PP_ENUMALGS_EX,
  1270. (BYTE *) &paramData,
  1271. &cbSize,
  1272. dwFlags);
  1273. // We know we've found the algorithm we want if our key spec matches
  1274. // the algorithmic class of the algorithm.
  1275. fFoundAlgorithm =
  1276. (ALG_CLASS_SIGNATURE == GET_ALG_CLASS(paramData.aiAlgid)) &&
  1277. (AT_SIGNATURE == dwUserKeySpec);
  1278. fFoundAlgorithm |=
  1279. (ALG_CLASS_KEY_EXCHANGE == GET_ALG_CLASS(paramData.aiAlgid)) &&
  1280. (AT_KEYEXCHANGE == dwUserKeySpec);
  1281. // Don't want to keep enumerating the first element.
  1282. dwFlags &= ~CRYPT_FIRST;
  1283. }
  1284. // Couldn't find an algorithm based on the keyspec
  1285. if (fDone)
  1286. {
  1287. goto ErrorReturn;
  1288. }
  1289. // Ok, we've found the algorithm we're looking for, assign two of
  1290. // our out parameters.
  1291. *pdwMaxLen = paramData.dwMaxLen;
  1292. *pdwMinLen = paramData.dwMinLen;
  1293. // Now, find the increment.
  1294. dwParam = (AT_SIGNATURE == dwUserKeySpec) ?
  1295. PP_SIG_KEYSIZE_INC : PP_KEYX_KEYSIZE_INC;
  1296. cbSize = sizeof(DWORD);
  1297. if (!CryptGetProvParam
  1298. (hProv,
  1299. dwParam,
  1300. (BYTE *)pdwInc, // Assigns final the out parameter
  1301. &cbSize,
  1302. 0))
  1303. goto CryptGetProvParamError;
  1304. fResult = TRUE;
  1305. ErrorReturn:
  1306. if (NULL != hProv) { CryptReleaseContext(hProv, 0); }
  1307. return fResult;
  1308. TRACE_ERROR(CryptAcquireContextUError);
  1309. TRACE_ERROR(CryptGetProvParamError);
  1310. SET_ERROR(InvalidArgError, E_INVALIDARG);
  1311. }
  1312. HRESULT WINAPI CreateRequest(DWORD dwFlags, //IN Required
  1313. DWORD dwPurpose, //IN Required: Whether it is enrollment or renew
  1314. LPWSTR pwszCAName, //IN Required:
  1315. LPWSTR pwszCALocation, //IN Required:
  1316. CERT_BLOB *pCertBlob, //IN Required: The renewed certifcate
  1317. CERT_REQUEST_PVK_NEW *pRenewKey, //IN Required: The private key on the certificate
  1318. BOOL fNewKey, //IN Required: Set the TRUE if new private key is needed
  1319. CERT_REQUEST_PVK_NEW *pKeyNew, //IN Required: The private key information
  1320. LPWSTR pwszHashAlg, //IN Optional: The hash algorithm
  1321. LPWSTR pwszDesStore, //IN Optional: The destination store
  1322. DWORD dwStoreFlags, //IN Optional: The store flags
  1323. CERT_ENROLL_INFO *pRequestInfo, //IN Required: The information about the cert request
  1324. HANDLE *hRequest //OUT Required: A handle to the PKCS10 request created
  1325. )
  1326. {
  1327. BSTR bstrCA = NULL;
  1328. CRYPT_DATA_BLOB descriptionBlob;
  1329. CRYPT_DATA_BLOB friendlyNameBlob;
  1330. CRYPT_DATA_BLOB hashBlob;
  1331. CRYPT_DATA_BLOB RequestBlob;
  1332. CRYPT_KEY_PROV_INFO KeyProvInfo;
  1333. DWORD dwIndex = 0;
  1334. DWORD dwCAAndRootStoreFlags;
  1335. HRESULT hr = E_FAIL;
  1336. IEnroll4 *pIEnroll = NULL;
  1337. LONG lRequestFlags = 0;
  1338. LPWSTR pwszCA = NULL;
  1339. PCCERT_CONTEXT pRenewCertContext = NULL;
  1340. PCCERT_CONTEXT pArchivalCert = NULL;
  1341. PCREATE_REQUEST_WIZARD_STATE pState = NULL;
  1342. PFNPIEnroll4GetNoCOM pfnPIEnroll4GetNoCOM = NULL;
  1343. BOOL fV2TemplateRequest = FALSE;
  1344. //input param checking
  1345. if(NULL == pKeyNew || NULL == pRequestInfo || NULL == hRequest)
  1346. return E_INVALIDARG;
  1347. // Check for versioning errors:
  1348. if(pKeyNew->dwSize != sizeof(CERT_REQUEST_PVK_NEW) || pRequestInfo->dwSize != sizeof(CERT_ENROLL_INFO))
  1349. return E_INVALIDARG;
  1350. // Init:
  1351. memset(&descriptionBlob, 0, sizeof(descriptionBlob));
  1352. memset(&friendlyNameBlob, 0, sizeof(friendlyNameBlob));
  1353. memset(&RequestBlob, 0, sizeof(RequestBlob));
  1354. memset(&hashBlob, 0, sizeof(hashBlob));
  1355. //////////////////////////////////////////////////////////////
  1356. //
  1357. // Acquire an IEnroll4 object.
  1358. //
  1359. //
  1360. // 1) load the library "xEnroll.dll".
  1361. //
  1362. if(NULL==g_hmodxEnroll)
  1363. {
  1364. if(NULL==(g_hmodxEnroll=LoadLibrary("xenroll.dll")))
  1365. goto Win32Err;
  1366. }
  1367. //
  1368. // 2) Get a pointer to the function that returns an IEnroll 4 object
  1369. // without using COM.
  1370. //
  1371. if(NULL==(pfnPIEnroll4GetNoCOM=(PFNPIEnroll4GetNoCOM)GetProcAddress(g_hmodxEnroll,
  1372. "PIEnroll4GetNoCOM")))
  1373. goto Win32Err;
  1374. //
  1375. // 3) Get the IEnroll4 object:
  1376. //
  1377. if(NULL==(pIEnroll=pfnPIEnroll4GetNoCOM()))
  1378. goto GeneralErr;
  1379. //
  1380. //////////////////////////////////////////////////////////////
  1381. // Set the key size to the default, if it is not specified:
  1382. if(fNewKey)
  1383. {
  1384. //we set the default to 1024 is not specified by user
  1385. if(0 == (0xFFFF0000 & pKeyNew->dwGenKeyFlags))
  1386. {
  1387. if(CanUse1024BitKey(pKeyNew->dwProvType,
  1388. pKeyNew->pwszProvider,
  1389. pKeyNew->dwKeySpec))
  1390. {
  1391. pKeyNew->dwGenKeyFlags=pKeyNew->dwGenKeyFlags | (1024 << 16);
  1392. }
  1393. }
  1394. }
  1395. if(dwStoreFlags)
  1396. {
  1397. //we either open CA and Root on the local machine or the current user
  1398. if(CERT_SYSTEM_STORE_CURRENT_USER != dwStoreFlags)
  1399. dwCAAndRootStoreFlags = CERT_SYSTEM_STORE_LOCAL_MACHINE;
  1400. else
  1401. dwCAAndRootStoreFlags = dwStoreFlags;
  1402. }
  1403. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1404. //
  1405. // Set XENROLL properties.
  1406. // The property corresponding to "Property Name" is set to "Property Value", IF "Condition" evaluates to TRUE:
  1407. //
  1408. // Condition Property Name Property Value
  1409. // -----------------------------------------------------------------------------------------------------------------------------------
  1410. //
  1411. _SET_XENROLL_PROPERTY_IF(dwStoreFlags, CAStoreFlags, dwCAAndRootStoreFlags);
  1412. _SET_XENROLL_PROPERTY_IF(pKeyNew->pwszKeyContainer, ContainerNameWStr, (LPWSTR)(pKeyNew->pwszKeyContainer));
  1413. _SET_XENROLL_PROPERTY_IF(TRUE, EnableSMIMECapabilities, pKeyNew->dwEnrollmentFlags & CT_FLAG_INCLUDE_SYMMETRIC_ALGORITHMS);
  1414. _SET_XENROLL_PROPERTY_IF(pwszHashAlg, HashAlgorithmWStr, pwszHashAlg);
  1415. _SET_XENROLL_PROPERTY_IF(TRUE, GenKeyFlags, pKeyNew->dwGenKeyFlags);
  1416. _SET_XENROLL_PROPERTY_IF(pKeyNew->dwKeySpec, KeySpec, pKeyNew->dwKeySpec);
  1417. _SET_XENROLL_PROPERTY_IF(dwStoreFlags, MyStoreFlags, dwStoreFlags);
  1418. _SET_XENROLL_PROPERTY_IF(pwszDesStore, MyStoreNameWStr, pwszDesStore);
  1419. _SET_XENROLL_PROPERTY_IF(pKeyNew->dwProviderFlags, ProviderFlags, pKeyNew->dwProviderFlags);
  1420. _SET_XENROLL_PROPERTY_IF(pKeyNew->dwProvType, ProviderType, pKeyNew->dwProvType);
  1421. _SET_XENROLL_PROPERTY_IF(dwStoreFlags, RootStoreFlags, dwCAAndRootStoreFlags);
  1422. _SET_XENROLL_PROPERTY_IF(TRUE, UseExistingKeySet, !fNewKey);
  1423. _SET_XENROLL_PROPERTY_IF(TRUE, WriteCertToUserDS, pRequestInfo->dwPostOption & CRYPTUI_WIZ_CERT_REQUEST_POST_ON_DS);
  1424. _SET_XENROLL_PROPERTY_IF(pKeyNew->dwProvType && pKeyNew->pwszProvider, ProviderNameWStr, (LPWSTR)(pKeyNew->pwszProvider));
  1425. _SET_XENROLL_PROPERTY_IF(CRYPTUI_WIZ_NO_INSTALL_ROOT & dwFlags, RootStoreNameWStr, L"CA");
  1426. _SET_XENROLL_PROPERTY_IF(TRUE, ReuseHardwareKeyIfUnableToGenNew, 0 == (dwFlags & CRYPTUI_WIZ_CERT_REQUEST_REQUIRE_NEW_KEY));
  1427. //
  1428. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  1429. //////////////////////////////////////////////////////////////
  1430. //
  1431. // Perform remaining XENROLL configuration:
  1432. //
  1433. // 1) Add the extensions to the certificate request
  1434. //
  1435. for(dwIndex=0; dwIndex < pRequestInfo->dwExtensions; dwIndex++)
  1436. {
  1437. if(NULL != pRequestInfo->prgExtensions[dwIndex])
  1438. {
  1439. PCERT_EXTENSIONS prgExtensions = pRequestInfo->prgExtensions[dwIndex];
  1440. for (DWORD dwIndex2 = 0; dwIndex2 < prgExtensions->cExtension; dwIndex2++)
  1441. {
  1442. CERT_EXTENSION certExtension = prgExtensions->rgExtension[dwIndex2];
  1443. LPWSTR pwszName = NULL;
  1444. if(FALSE == fV2TemplateRequest)
  1445. {
  1446. if(0 == _stricmp(szOID_CERTIFICATE_TEMPLATE, certExtension.pszObjId))
  1447. fV2TemplateRequest = TRUE;
  1448. }
  1449. if (S_OK != (hr = WizardSZToWSZ(certExtension.pszObjId, &pwszName)))
  1450. goto ErrorReturn;
  1451. hr = pIEnroll->addExtensionToRequestWStr
  1452. (certExtension.fCritical,
  1453. pwszName,
  1454. &(certExtension.Value));
  1455. // Make sure we always free pwszName.
  1456. if (NULL != pwszName) { WizardFree(pwszName); }
  1457. if (S_OK != hr)
  1458. goto xEnrollErr;
  1459. }
  1460. }
  1461. }
  1462. //
  1463. // 2) Set the key archival certificate, if requested by the cert template.
  1464. //
  1465. if (pKeyNew->dwPrivateKeyFlags & CT_FLAG_ALLOW_PRIVATE_KEY_ARCHIVAL)
  1466. {
  1467. if (NULL == pwszCAName || NULL == pwszCALocation)
  1468. goto InvalidArgErr;
  1469. LPWSTR rgwszStrsToConcat[] = { pwszCALocation, L"\\", pwszCAName } ;
  1470. pwszCA = WizardAllocAndConcatStrsU(rgwszStrsToConcat, 3);
  1471. bstrCA = SysAllocString(pwszCA);
  1472. if (NULL == bstrCA)
  1473. goto MemoryErr;
  1474. // Cert type specifies key archival.
  1475. if (S_OK != (hr = GetCAExchangeCertificate(bstrCA, &pArchivalCert)))
  1476. goto xEnrollErr;
  1477. if (S_OK != (hr = pIEnroll->SetPrivateKeyArchiveCertificate(pArchivalCert)))
  1478. goto xEnrollErr;
  1479. }
  1480. //
  1481. // 3) If renewing, do the requisite extra work...
  1482. //
  1483. if(CRYPTUI_WIZ_CERT_RENEW & dwPurpose)
  1484. {
  1485. if(NULL == pCertBlob || NULL == pRenewKey)
  1486. goto InvalidArgErr;
  1487. //create a certificate context
  1488. pRenewCertContext=CertCreateCertificateContext(
  1489. X509_ASN_ENCODING,
  1490. pCertBlob->pbData,
  1491. pCertBlob->cbData);
  1492. if(NULL == pRenewCertContext)
  1493. goto CertCliErr;
  1494. //set the property for keyProvInfo
  1495. memset(&KeyProvInfo, 0, sizeof(CRYPT_KEY_PROV_INFO));
  1496. KeyProvInfo.dwProvType=pRenewKey->dwProvType;
  1497. KeyProvInfo.pwszProvName=(LPWSTR)(pRenewKey->pwszProvider);
  1498. KeyProvInfo.dwFlags=pRenewKey->dwProviderFlags;
  1499. KeyProvInfo.pwszContainerName=(LPWSTR)(pRenewKey->pwszKeyContainer);
  1500. KeyProvInfo.dwKeySpec=pRenewKey->dwKeySpec;
  1501. CertSetCertificateContextProperty(
  1502. pRenewCertContext,
  1503. CERT_KEY_PROV_INFO_PROP_ID,
  1504. 0,
  1505. &KeyProvInfo);
  1506. //set the RenewCertContext
  1507. if (0 == (dwFlags & CRYPTUI_WIZ_NO_ARCHIVE_RENEW_CERT))
  1508. {
  1509. if (S_OK !=(hr=pIEnroll->put_RenewalCertificate(pRenewCertContext)))
  1510. goto xEnrollErr;
  1511. }
  1512. else
  1513. {
  1514. // we add the signing certificate
  1515. if(S_OK != (hr = pIEnroll->SetSignerCertificate(pRenewCertContext)))
  1516. goto xEnrollErr;
  1517. }
  1518. }
  1519. // Add certificate context properties to the request:
  1520. // 1) Add the friendly name property
  1521. if (NULL != pRequestInfo->pwszFriendlyName)
  1522. {
  1523. friendlyNameBlob.cbData = sizeof(WCHAR) * (wcslen(pRequestInfo->pwszFriendlyName) + 1);
  1524. friendlyNameBlob.pbData = (LPBYTE)WizardAllocAndCopyWStr((LPWSTR)pRequestInfo->pwszFriendlyName);
  1525. if (NULL == friendlyNameBlob.pbData)
  1526. goto MemoryErr;
  1527. if (S_OK != (hr = pIEnroll-> addBlobPropertyToCertificateWStr
  1528. (CERT_FRIENDLY_NAME_PROP_ID,
  1529. 0,
  1530. &friendlyNameBlob)))
  1531. goto xEnrollErr;
  1532. }
  1533. // 2) Add the description property
  1534. if (NULL != pRequestInfo->pwszDescription)
  1535. {
  1536. descriptionBlob.cbData = sizeof(WCHAR) * (wcslen(pRequestInfo->pwszDescription) + 1);
  1537. descriptionBlob.pbData = (LPBYTE)WizardAllocAndCopyWStr((LPWSTR)pRequestInfo->pwszDescription);
  1538. if (NULL == descriptionBlob.pbData)
  1539. goto MemoryErr;
  1540. if (S_OK != (hr = pIEnroll-> addBlobPropertyToCertificateWStr
  1541. (CERT_DESCRIPTION_PROP_ID,
  1542. 0,
  1543. &descriptionBlob)))
  1544. goto xEnrollErr;
  1545. }
  1546. //////////////////////////////////////////////////////////////////////////////////
  1547. //
  1548. // At last, generate the request, and assign the out parameters:
  1549. //
  1550. //
  1551. // 1) Create the request. For V2 template, use CMC.
  1552. // For V1 template, use a PKCS7 for renewal, and PKCS10 for enrollment.
  1553. //
  1554. {
  1555. if(TRUE == fV2TemplateRequest)
  1556. {
  1557. lRequestFlags = XECR_CMC;
  1558. }
  1559. else
  1560. {
  1561. if (CRYPTUI_WIZ_CERT_RENEW & dwPurpose)
  1562. {
  1563. // We're renewing: use PKCS7.
  1564. lRequestFlags = XECR_PKCS7;
  1565. }
  1566. else
  1567. {
  1568. // Enrolling with no PVK archival support: use PKCS10.
  1569. lRequestFlags = XECR_PKCS10_V2_0;
  1570. }
  1571. }
  1572. if (FAILED(hr=pIEnroll->createRequestWStr
  1573. (lRequestFlags,
  1574. pRequestInfo->pwszCertDNName, //L"CN=Test Certificate",
  1575. pRequestInfo->pwszUsageOID, //pwszUsage
  1576. &RequestBlob)))
  1577. goto xEnrollErr;
  1578. }
  1579. //
  1580. // 2) Get the HASH of the request so we can supply it to xenroll when we submit:
  1581. //
  1582. {
  1583. pState = (PCREATE_REQUEST_WIZARD_STATE)WizardAlloc(sizeof(CREATE_REQUEST_WIZARD_STATE));
  1584. if (pState == NULL)
  1585. goto MemoryErr;
  1586. if (S_OK != (hr = pIEnroll->get_ThumbPrintWStr(&hashBlob)))
  1587. goto xEnrollErr;
  1588. hashBlob.pbData = (LPBYTE)WizardAlloc(hashBlob.cbData);
  1589. if (NULL == hashBlob.pbData)
  1590. goto MemoryErr;
  1591. if (S_OK != (hr = pIEnroll->get_ThumbPrintWStr(&hashBlob)))
  1592. goto xEnrollErr;
  1593. //
  1594. // 3) Create a blob to assign our OUT parameter to.
  1595. // This blob preserves state from the call of CreateRequest() to the call
  1596. // of SubmitRequest()
  1597. //
  1598. pState->fMustFreeRequestBlob = TRUE;
  1599. pState->RequestBlob = RequestBlob;
  1600. pState->HashBlob = hashBlob;
  1601. // Persist certificate store information:
  1602. pState->dwMyStoreFlags = dwStoreFlags;
  1603. pState->dwRootStoreFlags = dwCAAndRootStoreFlags;
  1604. pState->pwszMyStoreName = NULL == pwszDesStore ? NULL : WizardAllocAndCopyWStr(pwszDesStore);
  1605. _JumpCondition(NULL != pwszDesStore && NULL == pState->pwszMyStoreName, MemoryErr);
  1606. pState->pwszRootStoreName = L"CA";
  1607. // Persist the request type:
  1608. pState->lRequestFlags = lRequestFlags;
  1609. // Persist status information: did we need to reuse the private key?
  1610. hr = pIEnroll->get_UseExistingKeySet(&pState->fReusedPrivateKey);
  1611. if (FAILED(hr))
  1612. goto xEnrollErr;
  1613. pState->fNewKey = fNewKey;
  1614. //
  1615. // 4) Assign cast the request to a handle and return it:
  1616. //
  1617. *hRequest = (HANDLE)pState;
  1618. }
  1619. //
  1620. //////////////////////////////////////////////////////////////////////////////////
  1621. // We're done!
  1622. hr = S_OK;
  1623. CommonReturn:
  1624. if (NULL != bstrCA) { SysFreeString(bstrCA); }
  1625. if (NULL != pArchivalCert) { CertFreeCertificateContext(pArchivalCert); }
  1626. if (NULL != pIEnroll) { pIEnroll->Release(); }
  1627. if (NULL != pRenewCertContext) { CertFreeCertificateContext(pRenewCertContext); }
  1628. if (NULL != pwszCA) { WizardFree(pwszCA); }
  1629. if (NULL != descriptionBlob.pbData) { WizardFree(descriptionBlob.pbData); }
  1630. if (NULL != friendlyNameBlob.pbData) { WizardFree(friendlyNameBlob.pbData); }
  1631. //return values
  1632. return hr;
  1633. ErrorReturn:
  1634. if(NULL != RequestBlob.pbData)
  1635. {
  1636. // NOTE: pIEnroll can not be NULL because it is used to allocate RequestBlob
  1637. pIEnroll->freeRequestInfoBlob(RequestBlob);
  1638. // This memory is from xenroll: must use LocalFree().
  1639. LocalFree(RequestBlob.pbData);
  1640. }
  1641. if (NULL != pState)
  1642. {
  1643. WizardFree(pState);
  1644. }
  1645. if (NULL != hashBlob.pbData)
  1646. {
  1647. WizardFree(hashBlob.pbData);
  1648. }
  1649. goto CommonReturn;
  1650. SET_HRESULT(CertCliErr, CodeToHR(GetLastError()));
  1651. SET_HRESULT(GeneralErr, E_FAIL);
  1652. SET_HRESULT(InvalidArgErr, E_INVALIDARG);
  1653. SET_HRESULT(MemoryErr, E_OUTOFMEMORY);
  1654. SET_HRESULT(xEnrollErr, hr);
  1655. SET_HRESULT(Win32Err, CodeToHR(GetLastError()));
  1656. }
  1657. HRESULT WINAPI SubmitRequest(IN HANDLE hRequest,
  1658. IN BOOL fKeyService, //IN Required: Whether the function is called remotely
  1659. IN DWORD dwPurpose, //IN Required: Whether it is enrollment or renew
  1660. IN BOOL fConfirmation, //IN Required: Set the TRUE if confirmation dialogue is needed
  1661. IN HWND hwndParent, //IN Optional: The parent window
  1662. IN LPWSTR pwszConfirmationTitle, //IN Optional: The title for confirmation dialogue
  1663. IN UINT idsConfirmTitle, //IN Optional: The resource ID for the title of the confirmation dialogue
  1664. IN LPWSTR pwszCALocation, //IN Required: The ca machine name
  1665. IN LPWSTR pwszCAName, //IN Required: The ca name
  1666. IN LPWSTR pwszCADisplayName, // IN Optional: The display name of the CA.
  1667. OUT CERT_BLOB *pPKCS7Blob, //OUT Optional: The PKCS7 from the CA
  1668. OUT CERT_BLOB *pHashBlob, //OUT Optioanl: The SHA1 hash of the enrolled/renewed certificate
  1669. OUT DWORD *pdwDisposition, //OUT Optional: The status of the enrollment/renewal
  1670. OUT PCCERT_CONTEXT *ppCertContext //OUT Optional: The enrolled certificate
  1671. )
  1672. {
  1673. BOOL fNewKey;
  1674. BSTR bstrAttribs = NULL; // Always NULL.
  1675. BSTR bstrCA = NULL; // "CA Location\CA Name"
  1676. BSTR bstrCMC = NULL; // BSTR representation of the CMC certificate.
  1677. BSTR bstrPKCS7 = NULL; // BSTR representation of the PKCS7 certificate.
  1678. BSTR bstrReq = NULL; // BSTR representation of the PKCS10 request.
  1679. CRYPT_DATA_BLOB CMCBlob; // CMC encoded issued certificate.
  1680. CRYPT_DATA_BLOB HashBlob;
  1681. CRYPT_DATA_BLOB PKCS7Blob; // PKCS7 encoded issued certificate.
  1682. CRYPT_DATA_BLOB PropertyBlob; // Temporary variable.
  1683. CRYPT_DATA_BLOB RequestBlob;
  1684. DWORD dwIndex = 0; // Temporary variable.
  1685. DWORD dwRequestID; // The request ID of the submitted request.
  1686. DWORD dwDisposition; // The disposition of the submitted request.
  1687. DWORD dwMyStoreFlags = 0;
  1688. DWORD dwRootStoreFlags = 0;
  1689. // BUGBUG: need to use global enrollment factory.
  1690. EnrollmentCOMObjectFactory *pEnrollFactory = NULL;
  1691. HRESULT hr = E_FAIL; // Return code.
  1692. ICertRequest2 *pICertRequest = NULL; // Used to submit request to CA.
  1693. IEnroll4 *pIEnroll = NULL; // Used to install issued certificate.
  1694. LONG lRequestFlags = 0;
  1695. LPVOID *ppvRequest = NULL;
  1696. LPWSTR pwszCA = NULL; // "CA Location\CA Name"
  1697. LPWSTR pwszMyStoreName = NULL;
  1698. LPWSTR pwszRootStoreName = NULL;
  1699. PCCERT_CONTEXT pCertContext = NULL; // The (hopefully) issued certificate.
  1700. PCREATE_REQUEST_WIZARD_STATE pState = NULL;
  1701. PCRYPT_DATA_BLOB pPKCS10Request = NULL; // A pointer to the supplied PKCS10 request.
  1702. PFNPIEnroll4GetNoCOM pfnPIEnroll4GetNoCOM = NULL; // Function that acquires an IEnroll4 object without using COM.
  1703. VARIANT varCMC;
  1704. LocalScope(SubmitRequestHelper):
  1705. DWORD ICEnrollDispositionToCryptUIStatus(DWORD dwDisposition)
  1706. {
  1707. switch (dwDisposition)
  1708. {
  1709. case CR_DISP_INCOMPLETE: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR;
  1710. case CR_DISP_ERROR: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR;
  1711. case CR_DISP_DENIED: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_DENIED;
  1712. case CR_DISP_ISSUED_OUT_OF_BAND: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_ISSUED_SEPARATELY;
  1713. case CR_DISP_UNDER_SUBMISSION: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_UNDER_SUBMISSION;
  1714. case CR_DISP_ISSUED: return CRYPTUI_WIZ_CERT_REQUEST_STATUS_SUCCEEDED;
  1715. default:
  1716. // Something's wrong.
  1717. return CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR;
  1718. }
  1719. }
  1720. EndLocalScope;
  1721. // Input Validation:
  1722. if (NULL == pwszCALocation || NULL == pwszCAName || NULL == hRequest)
  1723. return E_INVALIDARG;
  1724. // Initialization:
  1725. if (NULL != pPKCS7Blob)
  1726. memset(pPKCS7Blob, 0, sizeof(CERT_BLOB));
  1727. if (NULL != pHashBlob)
  1728. memset(pHashBlob, 0, sizeof(CERT_BLOB));
  1729. if (NULL != ppCertContext)
  1730. *ppCertContext=NULL;
  1731. memset(&CMCBlob, 0, sizeof(CRYPT_DATA_BLOB));
  1732. memset(&PKCS7Blob, 0, sizeof(CRYPT_DATA_BLOB));
  1733. memset(&PropertyBlob, 0, sizeof(CRYPT_DATA_BLOB));
  1734. VariantInit(&varCMC);
  1735. dwDisposition = CRYPTUI_WIZ_CERT_REQUEST_STATUS_UNKNOWN;
  1736. // We're using a COM component in this method. It's absolutely necessary that we
  1737. // uninitialize COM before we return, because we're running in an RPC thread,
  1738. // and failing to uninitialize COM will cause us to step on RPC's toes.
  1739. //
  1740. // See BUG 404778.
  1741. pEnrollFactory = new EnrollmentCOMObjectFactory;
  1742. if (NULL == pEnrollFactory)
  1743. goto MemoryErr;
  1744. __try {
  1745. //////////////////////////////////////////////////////////////
  1746. //
  1747. // Extract the data we need from the IN handle.
  1748. //
  1749. pState = (PCREATE_REQUEST_WIZARD_STATE)hRequest;
  1750. RequestBlob = pState->RequestBlob;
  1751. HashBlob = pState->HashBlob;
  1752. dwMyStoreFlags = pState->dwMyStoreFlags;
  1753. dwRootStoreFlags = pState->dwRootStoreFlags;
  1754. pwszMyStoreName = pState->pwszMyStoreName;
  1755. pwszRootStoreName = pState->pwszRootStoreName;
  1756. fNewKey = pState->fNewKey;
  1757. lRequestFlags = CR_IN_BINARY;
  1758. switch (pState->lRequestFlags)
  1759. {
  1760. case XECR_PKCS10_V2_0: lRequestFlags |= CR_IN_PKCS10; break;
  1761. case XECR_PKCS7: lRequestFlags |= CR_IN_PKCS7; break;
  1762. case XECR_CMC: lRequestFlags |= CR_IN_CMC; break;
  1763. default:
  1764. goto InvalidArgErr;
  1765. }
  1766. //////////////////////////////////////////////////////////////
  1767. //
  1768. // Acquire an IEnroll4 object.
  1769. //
  1770. //
  1771. // 1) load the library "xEnroll.dll".
  1772. //
  1773. if(NULL==g_hmodxEnroll)
  1774. {
  1775. if(NULL==(g_hmodxEnroll=LoadLibrary("xenroll.dll")))
  1776. goto Win32Err;
  1777. }
  1778. //
  1779. // 2) Get a pointer to the function that returns an IEnroll 4 object
  1780. // without using COM.
  1781. //
  1782. if(NULL==(pfnPIEnroll4GetNoCOM=(PFNPIEnroll4GetNoCOM)GetProcAddress(g_hmodxEnroll,
  1783. "PIEnroll4GetNoCOM")))
  1784. goto Win32Err;
  1785. //
  1786. // 3) Get the IEnroll4 object:
  1787. //
  1788. if(NULL==(pIEnroll=pfnPIEnroll4GetNoCOM()))
  1789. goto GeneralErr;
  1790. //
  1791. // 4) Set the pending request to use:
  1792. //
  1793. if (S_OK != (hr = pIEnroll->put_ThumbPrintWStr(HashBlob)))
  1794. goto xEnrollErr;
  1795. // 5) Restore the old certificate store information:
  1796. _SET_XENROLL_PROPERTY_IF(dwMyStoreFlags, MyStoreFlags, dwMyStoreFlags);
  1797. _SET_XENROLL_PROPERTY_IF(pwszMyStoreName, MyStoreNameWStr, pwszMyStoreName);
  1798. _SET_XENROLL_PROPERTY_IF(dwRootStoreFlags, RootStoreFlags, dwRootStoreFlags);
  1799. _SET_XENROLL_PROPERTY_IF(pwszRootStoreName, RootStoreNameWStr, pwszRootStoreName);
  1800. _SET_XENROLL_PROPERTY_IF(TRUE, UseExistingKeySet, !fNewKey);
  1801. //
  1802. //////////////////////////////////////////////////////////////
  1803. // Convert request blob to a BSTR:
  1804. bstrReq = SysAllocStringByteLen((LPCSTR)RequestBlob.pbData, RequestBlob.cbData);
  1805. if (NULL == bstrReq)
  1806. goto MemoryErr;
  1807. bstrAttribs = NULL;
  1808. // Acquire and use an ICertRequest2 object to submit the request to the CA:
  1809. if (pICertRequest == NULL)
  1810. {
  1811. if (S_OK != (hr = pEnrollFactory->getICertRequest2(&pICertRequest)))
  1812. goto ErrorReturn;
  1813. }
  1814. // bstrCA <-- pwszCALocation\pwszCAName
  1815. {
  1816. LPWSTR rgwszStrsToConcat[] = { pwszCALocation, L"\\", pwszCAName } ;
  1817. pwszCA = WizardAllocAndConcatStrsU(rgwszStrsToConcat, 3);
  1818. }
  1819. bstrCA = SysAllocString(pwszCA);
  1820. if (NULL == bstrCA)
  1821. goto MemoryErr;
  1822. hr = pICertRequest->Submit
  1823. (lRequestFlags,
  1824. bstrReq,
  1825. bstrAttribs,
  1826. bstrCA,
  1827. (long *)&dwDisposition);
  1828. dwDisposition = local.ICEnrollDispositionToCryptUIStatus(dwDisposition);
  1829. _JumpCondition(S_OK != hr, ErrorReturn);
  1830. // Deal with the possible status codes we could've encountered:
  1831. switch (dwDisposition)
  1832. {
  1833. case CRYPTUI_WIZ_CERT_REQUEST_STATUS_CONNECTION_FAILED:
  1834. case CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR:
  1835. case CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_DENIED:
  1836. case CRYPTUI_WIZ_CERT_REQUEST_STATUS_ISSUED_SEPARATELY:
  1837. if (S_OK == hr)
  1838. {
  1839. pICertRequest->GetLastStatus((LONG *)&hr);
  1840. if(!FAILED(hr))
  1841. hr=E_FAIL;
  1842. }
  1843. goto ErrorReturn;
  1844. case CRYPTUI_WIZ_CERT_REQUEST_STATUS_UNDER_SUBMISSION:
  1845. // The certificate request has pended. Set the pending request info.
  1846. if (S_OK != (hr = pICertRequest->GetRequestId((long *)&dwRequestID)))
  1847. goto ErrorReturn;
  1848. if (S_OK != (hr = pIEnroll->setPendingRequestInfoWStr
  1849. (dwRequestID,
  1850. pwszCALocation,
  1851. pwszCADisplayName ? pwszCADisplayName : pwszCAName,
  1852. NULL)))
  1853. goto setPendingRequestInfoWStrError;
  1854. // The request has pended, we don't need to delete it from the request store...
  1855. pState->fMustFreeRequestBlob = FALSE;
  1856. goto CommonReturn;
  1857. case CRYPTUI_WIZ_CERT_REQUEST_STATUS_SUCCEEDED:
  1858. // 4) Success! Continue processing...
  1859. break;
  1860. default:
  1861. // 5) Invalid error code:
  1862. goto UnexpectedErr;
  1863. }
  1864. if (S_OK != (hr = pICertRequest->GetFullResponseProperty(FR_PROP_FULLRESPONSE, 0, PROPTYPE_BINARY, CR_OUT_BINARY, &varCMC)))
  1865. goto ErrorReturn;
  1866. // Check to make sure we've gotten a BSTR back:
  1867. if (VT_BSTR != varCMC.vt)
  1868. {
  1869. dwDisposition = CRYPTUI_WIZ_CERT_REQUEST_STATUS_INSTALL_FAILED;
  1870. hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
  1871. goto ErrorReturn;
  1872. }
  1873. bstrCMC = varCMC.bstrVal;
  1874. // Marshal the cert into a CRYPT_DATA_BLOB:
  1875. CMCBlob.pbData = (LPBYTE)bstrCMC;
  1876. CMCBlob.cbData = SysStringByteLen(bstrCMC);
  1877. if (S_OK != (hr = pIEnroll->getCertContextFromResponseBlob(&CMCBlob, &pCertContext)))
  1878. {
  1879. dwDisposition = CRYPTUI_WIZ_CERT_REQUEST_STATUS_INSTALL_FAILED;
  1880. goto ErrorReturn;
  1881. }
  1882. // Install the certificate, and delete the request from the request store.
  1883. if(S_OK !=(hr=pIEnroll->acceptResponseBlob(&CMCBlob)))
  1884. {
  1885. dwDisposition = CRYPTUI_WIZ_CERT_REQUEST_STATUS_INSTALL_FAILED;
  1886. goto xEnrollErr;
  1887. }
  1888. // acceptPKCS7Blob cleans up the request store for us ... we don't need to
  1889. // do this explicitly anyone.
  1890. pState->fMustFreeRequestBlob = FALSE;
  1891. ////////////////////////////////////////////////////////////////////////////////
  1892. //
  1893. // Assign the OUT parameters:
  1894. //
  1895. //
  1896. // 1) Assign the PKCS7 Blob to the OUT PKCS7 blob:
  1897. //
  1898. if(NULL != pPKCS7Blob)
  1899. {
  1900. // Get a PKCS7 Blob to return to the client:
  1901. if (S_OK != (hr = pICertRequest->GetCertificate(CR_OUT_BINARY | CR_OUT_CHAIN, &bstrPKCS7)))
  1902. goto ErrorReturn;
  1903. // Marshal the cert into a CRYPT_DATA_BLOB:
  1904. PKCS7Blob.pbData = (LPBYTE)bstrPKCS7;
  1905. PKCS7Blob.cbData = SysStringByteLen(bstrPKCS7);
  1906. pPKCS7Blob->pbData=(BYTE *)WizardAlloc(PKCS7Blob.cbData);
  1907. if(NULL==(pPKCS7Blob->pbData))
  1908. {
  1909. dwDisposition = CRYPTUI_WIZ_CERT_REQUEST_STATUS_INSTALL_FAILED;
  1910. goto MemoryErr;
  1911. }
  1912. memcpy(pPKCS7Blob->pbData, PKCS7Blob.pbData,PKCS7Blob.cbData);
  1913. pPKCS7Blob->cbData=PKCS7Blob.cbData;
  1914. }
  1915. //
  1916. // 2) Assign the SHA1 hash blob of the cert to the OUT hashblob.
  1917. //
  1918. if(NULL != pHashBlob)
  1919. {
  1920. if(!CertAllocAndGetCertificateContextProperty(
  1921. pCertContext,
  1922. CERT_SHA1_HASH_PROP_ID,
  1923. (LPVOID *)&(pHashBlob->pbData),
  1924. &(pHashBlob->cbData)))
  1925. {
  1926. dwDisposition = CRYPTUI_WIZ_CERT_REQUEST_STATUS_INSTALL_FAILED;
  1927. goto CertCliErr;
  1928. }
  1929. }
  1930. //
  1931. // 3) Return the certificate context on the local case
  1932. //
  1933. if((NULL != ppCertContext) && !fKeyService)
  1934. {
  1935. *ppCertContext = CertDuplicateCertificateContext(pCertContext);
  1936. }
  1937. //
  1938. ////////////////////////////////////////////////////////////////////////////////
  1939. } __except (EXCEPTION_EXECUTE_HANDLER) {
  1940. hr = GetExceptionCode();
  1941. goto ErrorReturn;
  1942. }
  1943. dwDisposition = CRYPTUI_WIZ_CERT_REQUEST_STATUS_SUCCEEDED;
  1944. hr=S_OK;
  1945. CommonReturn:
  1946. if (NULL != bstrCA) { SysFreeString(bstrCA); }
  1947. if (NULL != bstrAttribs) { SysFreeString(bstrAttribs); }
  1948. if (NULL != bstrReq) { SysFreeString(bstrReq); }
  1949. if (NULL != pICertRequest) { pICertRequest->Release(); }
  1950. if (NULL != bstrCMC) { SysFreeString(bstrCMC); }
  1951. if (NULL != bstrPKCS7) { SysFreeString(bstrPKCS7); }
  1952. if (NULL != pEnrollFactory) { delete pEnrollFactory; }
  1953. if (NULL != pIEnroll) { pIEnroll->Release(); }
  1954. if (NULL != pwszCA) { WizardFree(pwszCA); }
  1955. if (NULL != pCertContext) { CertFreeCertificateContext(pCertContext); }
  1956. // PKCS7Blob.pbData is aliased to bstrCertificate. Just NULL it out:
  1957. PKCS7Blob.pbData = NULL;
  1958. // Always return a status code:
  1959. if (NULL != pdwDisposition) { *pdwDisposition = dwDisposition; }
  1960. return hr;
  1961. ErrorReturn:
  1962. //free the output parameter
  1963. if (NULL != pPKCS7Blob && NULL != pPKCS7Blob->pbData)
  1964. {
  1965. WizardFree(pPKCS7Blob->pbData);
  1966. memset(pPKCS7Blob, 0, sizeof(CERT_BLOB));
  1967. }
  1968. //free the output parameter
  1969. if (NULL != pHashBlob && NULL != pHashBlob->pbData)
  1970. {
  1971. WizardFree(pHashBlob->pbData);
  1972. memset(pHashBlob, 0, sizeof(CERT_BLOB));
  1973. }
  1974. if (NULL != ppCertContext && NULL != *ppCertContext) { CertFreeCertificateContext(*ppCertContext); }
  1975. goto CommonReturn;
  1976. SET_HRESULT(CertCliErr, CodeToHR(GetLastError()));
  1977. SET_HRESULT(GeneralErr, E_FAIL);
  1978. SET_HRESULT(InvalidArgErr, E_INVALIDARG);
  1979. SET_HRESULT(MemoryErr, E_OUTOFMEMORY);
  1980. SET_HRESULT(setPendingRequestInfoWStrError, hr);
  1981. SET_HRESULT(UnexpectedErr, E_UNEXPECTED);
  1982. SET_HRESULT(xEnrollErr, hr);
  1983. SET_HRESULT(Win32Err, CodeToHR(GetLastError()));
  1984. }
  1985. BOOL WINAPI QueryRequest(IN HANDLE hRequest, OUT CRYPTUI_WIZ_QUERY_CERT_REQUEST_INFO *pQueryInfo)
  1986. {
  1987. BOOL fResult;
  1988. CREATE_REQUEST_WIZARD_STATE *pState;
  1989. CRYPTUI_WIZ_QUERY_CERT_REQUEST_INFO QueryInfo;
  1990. memset(&QueryInfo, 0, sizeof(QueryInfo));
  1991. pState = (CREATE_REQUEST_WIZARD_STATE *)hRequest;
  1992. QueryInfo.dwSize = sizeof(QueryInfo);
  1993. QueryInfo.dwStatus = (pState->fReusedPrivateKey) ? CRYPTUI_WIZ_QUERY_CERT_REQUEST_STATUS_CREATE_REUSED_PRIVATE_KEY : 0;
  1994. *pQueryInfo = QueryInfo;
  1995. fResult = TRUE;
  1996. // CommonReturn:
  1997. return fResult;
  1998. }
  1999. void WINAPI FreeRequest(IN HANDLE hRequest)
  2000. {
  2001. IEnroll4 *pIEnroll = NULL;
  2002. PCREATE_REQUEST_WIZARD_STATE pState = NULL;
  2003. PFNPIEnroll4GetNoCOM pfnPIEnroll4GetNoCOM = NULL;
  2004. if (NULL == hRequest)
  2005. return; // Nothing to free!
  2006. pState = (PCREATE_REQUEST_WIZARD_STATE)hRequest;
  2007. // Make our best effort to get an IEnroll4 pointer:
  2008. if (NULL == g_hmodxEnroll)
  2009. {
  2010. g_hmodxEnroll = LoadLibrary("xenroll.dll");
  2011. }
  2012. // We couldn't load xenroll -- not much we can do about it. In this case,
  2013. // it's likely we ever allocated memory with it anyway, however, so we're
  2014. // probably not leaking.
  2015. _JumpCondition(NULL == g_hmodxEnroll, xEnrollDone);
  2016. pfnPIEnroll4GetNoCOM = (PFNPIEnroll4GetNoCOM)GetProcAddress(g_hmodxEnroll, "PIEnroll4GetNoCOM");
  2017. _JumpCondition(NULL == pfnPIEnroll4GetNoCOM, xEnrollDone);
  2018. pIEnroll = pfnPIEnroll4GetNoCOM();
  2019. _JumpCondition(NULL == pIEnroll, xEnrollDone);
  2020. // Free the request created by xenroll.
  2021. // NOTE: freeRequestInfoBlob does not actually free the memory associated with the request.
  2022. // Rather, it deletes the request from the request store, leaving the caller responsible
  2023. // for the memory free.
  2024. if (pState->fMustFreeRequestBlob)
  2025. {
  2026. if (NULL != pState->RequestBlob.pbData)
  2027. {
  2028. if (NULL != pIEnroll)
  2029. {
  2030. pIEnroll->put_MyStoreFlags(pState->dwMyStoreFlags);
  2031. if (NULL != pState->HashBlob.pbData)
  2032. {
  2033. pIEnroll->put_ThumbPrintWStr(pState->HashBlob);
  2034. }
  2035. pIEnroll->freeRequestInfoBlob(pState->RequestBlob);
  2036. }
  2037. LocalFree(pState->RequestBlob.pbData);
  2038. }
  2039. }
  2040. xEnrollDone:
  2041. // We've finished attempting to free data created by xenroll. Now
  2042. // free data allocated in CreateRequest():
  2043. if (NULL != pState->HashBlob.pbData) { WizardFree(pState->HashBlob.pbData); }
  2044. WizardFree(pState);
  2045. // We're done with the IEnroll4 pointer:
  2046. if (NULL != pIEnroll) { pIEnroll->Release(); }
  2047. }
  2048. HRESULT WINAPI LocalEnrollNoDS( DWORD dwFlags, //IN Required
  2049. LPCWSTR pRequestString, // Reserved: must be NULL.
  2050. void *pReserved, //IN Optional
  2051. BOOL fKeyService, //IN Required: Whether the function is called remotely
  2052. DWORD dwPurpose, //IN Required: Whether it is enrollment or renew
  2053. BOOL fConfirmation, //IN Required: Set the TRUE if confirmation dialogue is needed
  2054. HWND hwndParent, //IN Optional: The parent window
  2055. LPWSTR pwszConfirmationTitle, //IN Optional: The title for confirmation dialogue
  2056. UINT idsConfirmTitle, //IN Optional: The resource ID for the title of the confirmation dialogue
  2057. LPWSTR pwszCALocation, //IN Required: The ca machine name
  2058. LPWSTR pwszCAName, //IN Required: The ca name
  2059. CERT_BLOB *pCertBlob, //IN Required: The renewed certifcate
  2060. CERT_REQUEST_PVK_NEW *pRenewKey, //IN Required: The private key on the certificate
  2061. BOOL fNewKey, //IN Required: Set the TRUE if new private key is needed
  2062. CERT_REQUEST_PVK_NEW *pKeyNew, //IN Required: The private key information
  2063. LPWSTR pwszHashAlg, //IN Optional: The hash algorithm
  2064. LPWSTR pwszDesStore, //IN Optional: The destination store
  2065. DWORD dwStoreFlags, //IN Optional: The store flags
  2066. CERT_ENROLL_INFO *pRequestInfo, //IN Required: The information about the cert request
  2067. CERT_BLOB *pPKCS7Blob, //OUT Optional: The PKCS7 from the CA
  2068. CERT_BLOB *pHashBlob, //OUT Optioanl: The SHA1 hash of the enrolled/renewed certificate
  2069. DWORD *pdwStatus, //OUT Optional: The status of the enrollment/renewal
  2070. HANDLE *pResult //IN OUT Optional: The enrolled certificate
  2071. )
  2072. {
  2073. // When no flags are specified, we still create, submit, and free.
  2074. BOOL fCreateRequest = 0 == (dwFlags & (CRYPTUI_WIZ_NODS_MASK & ~CRYPTUI_WIZ_CREATE_ONLY));
  2075. BOOL fSubmitRequest = 0 == (dwFlags & (CRYPTUI_WIZ_NODS_MASK & ~CRYPTUI_WIZ_SUBMIT_ONLY));
  2076. BOOL fFreeRequest = 0 == (dwFlags & (CRYPTUI_WIZ_NODS_MASK & ~CRYPTUI_WIZ_FREE_ONLY));
  2077. // Query the request only when specifically queried.
  2078. BOOL fQueryRequest = 0 != (dwFlags & CRYPTUI_WIZ_QUERY_ONLY);
  2079. HANDLE hRequest = NULL;
  2080. HRESULT hr = E_FAIL;
  2081. if (fQueryRequest) {
  2082. // Querying the request takes precedence over other operations.
  2083. if (!QueryRequest(*pResult, (CRYPTUI_WIZ_QUERY_CERT_REQUEST_INFO *)pReserved))
  2084. goto QueryRequestErr;
  2085. return S_OK;
  2086. }
  2087. if (NULL != pdwStatus)
  2088. *pdwStatus = CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR;
  2089. if (FALSE == (fCreateRequest || fSubmitRequest || fFreeRequest))
  2090. return E_INVALIDARG;
  2091. if (TRUE == fCreateRequest)
  2092. {
  2093. if (S_OK != (hr = CreateRequest(dwFlags,
  2094. dwPurpose,
  2095. pwszCAName,
  2096. pwszCALocation,
  2097. pCertBlob,
  2098. pRenewKey,
  2099. fNewKey,
  2100. pKeyNew,
  2101. pwszHashAlg,
  2102. pwszDesStore,
  2103. dwStoreFlags,
  2104. pRequestInfo,
  2105. &hRequest)))
  2106. goto ErrorReturn;
  2107. _JumpCondition(NULL == hRequest, UnexpectedErr);
  2108. // Successfully created the request:
  2109. if (NULL != pdwStatus) { *pdwStatus = CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_CREATED; }
  2110. if (NULL != pResult) { *pResult = hRequest; }
  2111. }
  2112. else
  2113. {
  2114. // The created request is passed in through "pResult".
  2115. hRequest = *pResult;
  2116. }
  2117. if (TRUE == fSubmitRequest)
  2118. {
  2119. if (S_OK != (hr = SubmitRequest
  2120. (hRequest,
  2121. fKeyService,
  2122. dwPurpose,
  2123. fConfirmation,
  2124. hwndParent,
  2125. pwszConfirmationTitle,
  2126. idsConfirmTitle,
  2127. pwszCALocation,
  2128. pwszCAName,
  2129. NULL, // pwszCADisplayName,
  2130. pPKCS7Blob,
  2131. pHashBlob,
  2132. pdwStatus,
  2133. (PCCERT_CONTEXT *)pResult)))
  2134. {
  2135. // Assign the created request to the OUT parameter on error.
  2136. if (NULL != pResult) { *pResult = hRequest; }
  2137. goto ErrorReturn;
  2138. }
  2139. }
  2140. if (TRUE == fFreeRequest)
  2141. {
  2142. FreeRequest(hRequest);
  2143. hr = S_OK;
  2144. }
  2145. CommonReturn:
  2146. return hr;
  2147. ErrorReturn:
  2148. goto CommonReturn;
  2149. SET_HRESULT(QueryRequestErr, GetLastError());
  2150. SET_HRESULT(UnexpectedErr, E_UNEXPECTED);
  2151. }
  2152. HRESULT WINAPI LocalEnroll( DWORD dwFlags, //IN Required
  2153. LPCWSTR pRequestString, // Reserved: must be NULL.
  2154. void *pReserved, //IN Optional
  2155. BOOL fKeyService, //IN Required: Whether the function is called remotely
  2156. DWORD dwPurpose, //IN Required: Whether it is enrollment or renew
  2157. BOOL fConfirmation, //IN Required: Set the TRUE if confirmation dialogue is needed
  2158. HWND hwndParent, //IN Optional: The parent window
  2159. LPWSTR pwszConfirmationTitle, //IN Optional: The title for confirmation dialogue
  2160. UINT idsConfirmTitle, //IN Optional: The resource ID for the title of the confirmation dialogue
  2161. LPWSTR pwszCALocation, //IN Required: The ca machine name
  2162. LPWSTR pwszCAName, //IN Required: The ca name
  2163. CERT_BLOB *pCertBlob, //IN Required: The renewed certifcate
  2164. CERT_REQUEST_PVK_NEW *pRenewKey, //IN Required: The private key on the certificate
  2165. BOOL fNewKey, //IN Required: Set the TRUE if new private key is needed
  2166. CERT_REQUEST_PVK_NEW *pKeyNew, //IN Required: The private key information
  2167. LPWSTR pwszHashAlg, //IN Optional: The hash algorithm
  2168. LPWSTR pwszDesStore, //IN Optional: The destination store
  2169. DWORD dwStoreFlags, //IN Optional: The store flags
  2170. CERT_ENROLL_INFO *pRequestInfo, //IN Required: The information about the cert request
  2171. CERT_BLOB *pPKCS7Blob, //OUT Optional: The PKCS7 from the CA
  2172. CERT_BLOB *pHashBlob, //OUT Optioanl: The SHA1 hash of the enrolled/renewed certificate
  2173. DWORD *pdwStatus, //OUT Optional: The status of the enrollment/renewal
  2174. PCERT_CONTEXT *ppCertContext //OUT Optional: The enrolled certificate
  2175. )
  2176. {
  2177. return LocalEnrollNoDS
  2178. ( dwFlags, //IN Required
  2179. pRequestString, // Reserved: must be NULL.
  2180. pReserved, //IN Optional
  2181. fKeyService, //IN Required: Whether the function is called remotely
  2182. dwPurpose, //IN Required: Whether it is enrollment or renew
  2183. fConfirmation, //IN Required: Set the TRUE if confirmation dialogue is needed
  2184. hwndParent, //IN Optional: The parent window
  2185. pwszConfirmationTitle, //IN Optional: The title for confirmation dialogue
  2186. idsConfirmTitle, //IN Optional: The resource ID for the title of the confirmation dialogue
  2187. pwszCALocation, //IN Required: The ca machine name
  2188. pwszCAName, //IN Required: The ca name
  2189. pCertBlob, //IN Required: The renewed certifcate
  2190. pRenewKey, //IN Required: The private key on the certificate
  2191. fNewKey, //IN Required: Set the TRUE if new private key is needed
  2192. pKeyNew, //IN Required: The private key information
  2193. pwszHashAlg, //IN Optional: The hash algorithm
  2194. pwszDesStore, //IN Optional: The destination store
  2195. dwStoreFlags, //IN Optional: The store flags
  2196. pRequestInfo, //IN Required: The information about the cert request
  2197. pPKCS7Blob, //OUT Optional: The PKCS7 from the CA
  2198. pHashBlob, //OUT Optioanl: The SHA1 hash of the enrolled/renewed certificate
  2199. pdwStatus, //OUT Optional: The status of the enrollment/renewal
  2200. (HANDLE *)ppCertContext); //OUT Optional: The enrolled certificate
  2201. }
  2202. //note pCertRenewPvk internal pointers has to be freed by callers
  2203. HRESULT MarshallRequestParameters(IN DWORD dwCSPIndex,
  2204. IN CERT_WIZARD_INFO *pCertWizardInfo,
  2205. IN OUT CERT_BLOB *pCertBlob,
  2206. IN OUT CERT_REQUEST_PVK_NEW *pCertRequestPvkNew,
  2207. IN OUT CERT_REQUEST_PVK_NEW *pCertRenewPvk,
  2208. IN OUT LPWSTR *ppwszHashAlg,
  2209. IN OUT CERT_ENROLL_INFO *pRequestInfo)
  2210. {
  2211. BOOL fCopyPropertiesFromRequestInfo = FALSE;
  2212. BOOL fRevertWizardProvider = FALSE;
  2213. BOOL fSetUpRenewPvk = FALSE;
  2214. CertRequester *pCertRequester = NULL;
  2215. CertRequesterContext *pCertRequesterContext = NULL;
  2216. CRYPT_KEY_PROV_INFO *pKeyProvInfo = NULL;
  2217. CRYPTUI_WIZ_CERT_CA *pCertCA = NULL;
  2218. DWORD dwExtensions = 0;
  2219. DWORD dwIndex = 0;
  2220. DWORD dwGenKeyFlags = 0;
  2221. DWORD dwSize = 0;
  2222. HRESULT hr = E_FAIL;
  2223. LPWSTR pwszOID = NULL;
  2224. LPWSTR pwszUsageOID = NULL;
  2225. PCERT_EXTENSIONS *pExtensions = NULL;
  2226. UINT idsText = 0;
  2227. DWORD dwMinKey = 0;
  2228. DWORD dwMaxKey = 0;
  2229. DWORD dwInc = 0;
  2230. DWORD dwTempGenKeyFlags = 0;
  2231. // Input validation:
  2232. _JumpConditionWithExpr
  2233. (NULL == pCertWizardInfo || NULL == pCertWizardInfo->hRequester || NULL == pCertBlob ||
  2234. NULL == pCertRequestPvkNew || NULL == pCertRenewPvk || NULL == ppwszHashAlg ||
  2235. NULL == pRequestInfo,
  2236. InvalidArgError,
  2237. idsText = IDS_REQUEST_FAIL);
  2238. // Initialization:
  2239. memset(pCertBlob, 0, sizeof(*pCertBlob));
  2240. memset(pCertRequestPvkNew, 0, sizeof(*pCertRequestPvkNew));
  2241. memset(pCertRenewPvk, 0, sizeof(*pCertRenewPvk));
  2242. memset(ppwszHashAlg, 0, sizeof(*ppwszHashAlg));
  2243. memset(pRequestInfo, 0, sizeof(*pRequestInfo));
  2244. pCertRequester = (CertRequester *)pCertWizardInfo->hRequester;
  2245. pCertRequesterContext = pCertRequester->GetContext();
  2246. _JumpCondition(NULL == pCertRequesterContext, InvalidArgError);
  2247. //set up the hash algorithm. Convert to the wchar version
  2248. if(pCertWizardInfo->pszHashAlg)
  2249. (*ppwszHashAlg) = MkWStr((LPSTR)(pCertWizardInfo->pszHashAlg));
  2250. // Build a comma seperated OID usage for enrollment only.
  2251. // The CA index must not exceed the number of CAs:
  2252. _JumpCondition(pCertWizardInfo->dwCAIndex >= pCertWizardInfo->pCertCAInfo->dwCA, UnexpectedError);
  2253. pCertCA=&(pCertWizardInfo->pCertCAInfo->rgCA[pCertWizardInfo->dwCAIndex]);
  2254. //decide if we need to build the list
  2255. if(pCertCA->dwOIDInfo)
  2256. {
  2257. pwszUsageOID=(LPWSTR)WizardAlloc(sizeof(WCHAR));
  2258. _JumpCondition(NULL == pwszUsageOID, MemoryError);
  2259. *pwszUsageOID=L'\0';
  2260. //we are guaranteed that at least one OID should be selected
  2261. for(dwIndex=0; dwIndex<pCertCA->dwOIDInfo; dwIndex++)
  2262. {
  2263. if(TRUE==(pCertCA->rgOIDInfo)[dwIndex].fSelected)
  2264. {
  2265. if(wcslen(pwszUsageOID)!=0)
  2266. wcscat(pwszUsageOID, L",");
  2267. pwszOID=MkWStr((pCertCA->rgOIDInfo)[dwIndex].pszOID);
  2268. _JumpCondition(NULL == pwszOID, MemoryError);
  2269. pwszUsageOID=(LPWSTR)WizardRealloc(pwszUsageOID,
  2270. sizeof(WCHAR)*(wcslen(pwszUsageOID)+wcslen(pwszOID)+wcslen(L",")+1));
  2271. _JumpCondition(NULL==pwszUsageOID, MemoryError);
  2272. wcscat(pwszUsageOID,pwszOID);
  2273. FreeWStr(pwszOID);
  2274. pwszOID=NULL;
  2275. }
  2276. }
  2277. }
  2278. else
  2279. {
  2280. //we need to build the extension list for the certificate types
  2281. dwExtensions=0;
  2282. for(dwIndex=0; dwIndex<pCertCA->dwCertTypeInfo; dwIndex++)
  2283. {
  2284. if(TRUE==(pCertCA->rgCertTypeInfo)[dwIndex].fSelected)
  2285. {
  2286. //add the extensions
  2287. if(NULL !=(pCertCA->rgCertTypeInfo)[dwIndex].pCertTypeExtensions)
  2288. {
  2289. dwExtensions++;
  2290. pExtensions=(PCERT_EXTENSIONS *)WizardRealloc(pExtensions,
  2291. dwExtensions * sizeof(PCERT_EXTENSIONS));
  2292. _JumpCondition(NULL == pExtensions, MemoryError);
  2293. pExtensions[dwExtensions-1]=(pCertCA->rgCertTypeInfo)[dwIndex].pCertTypeExtensions;
  2294. }
  2295. pCertWizardInfo->dwEnrollmentFlags = (pCertCA->rgCertTypeInfo)[dwIndex].dwEnrollmentFlags;
  2296. pCertWizardInfo->dwSubjectNameFlags = (pCertCA->rgCertTypeInfo)[dwIndex].dwSubjectNameFlags;
  2297. pCertWizardInfo->dwPrivateKeyFlags = (pCertCA->rgCertTypeInfo)[dwIndex].dwPrivateKeyFlags;
  2298. pCertWizardInfo->dwGeneralFlags = (pCertCA->rgCertTypeInfo)[dwIndex].dwGeneralFlags;
  2299. //copy the dwKeySpec and genKeyFlags from the
  2300. //cert type to the request information
  2301. //if rgdwCSP is not NULL for the cert type, then we know
  2302. //we need to copy the information since the memory is always
  2303. //allocated
  2304. if((pCertCA->rgCertTypeInfo)[dwIndex].rgdwCSP)
  2305. {
  2306. //if ignored the user's input, we use the one from the certificate
  2307. //template
  2308. if(TRUE == pCertWizardInfo->fIgnore)
  2309. {
  2310. pCertWizardInfo->dwKeySpec=(pCertCA->rgCertTypeInfo)[dwIndex].dwKeySpec;
  2311. if (!CertTypeFlagsToGenKeyFlags
  2312. (pCertWizardInfo->dwEnrollmentFlags,
  2313. pCertWizardInfo->dwSubjectNameFlags,
  2314. pCertWizardInfo->dwPrivateKeyFlags,
  2315. pCertWizardInfo->dwGeneralFlags,
  2316. &dwGenKeyFlags))
  2317. goto CertTypeFlagsToGenKeyFlagsError;
  2318. // Add these flags to whatever flags have already been specified by the user.
  2319. pCertWizardInfo->dwGenKeyFlags |= dwGenKeyFlags;
  2320. pCertWizardInfo->dwGenKeyFlags |= ((pCertCA->rgCertTypeInfo)[dwIndex].dwMinKeySize << 16);
  2321. }
  2322. else
  2323. {
  2324. //we only copy information we need to
  2325. if(0 == pCertWizardInfo->dwKeySpec)
  2326. pCertWizardInfo->dwKeySpec=(pCertCA->rgCertTypeInfo)[dwIndex].dwKeySpec;
  2327. }
  2328. }
  2329. // The user has specified a minimum key size through the advanced options.
  2330. // Use it to override whatever key size is specified in the cert template.
  2331. if (pCertWizardInfo->dwMinKeySize != 0)
  2332. {
  2333. pCertWizardInfo->dwGenKeyFlags &= 0x0000FFFF;
  2334. pCertWizardInfo->dwGenKeyFlags |= (pCertWizardInfo->dwMinKeySize) << 16;
  2335. }
  2336. //deside the CSP to use:
  2337. if(NULL == pCertWizardInfo->pwszProvider)
  2338. {
  2339. if((pCertCA->rgCertTypeInfo)[dwIndex].dwCSPCount && (pCertCA->rgCertTypeInfo)[dwIndex].rgdwCSP)
  2340. {
  2341. //Use the 1st one on the cert type's CSP list
  2342. pCertWizardInfo->pwszProvider=pCertWizardInfo->rgwszProvider[dwCSPIndex];
  2343. pCertWizardInfo->dwProviderType=pCertWizardInfo->rgdwProviderType[dwCSPIndex];
  2344. fRevertWizardProvider = TRUE;
  2345. }
  2346. }
  2347. //the increase the min key size to the minimal of CSP selected
  2348. if(GetValidKeySizes(
  2349. pCertWizardInfo->pwszProvider,
  2350. pCertWizardInfo->dwProviderType,
  2351. pCertWizardInfo->dwKeySpec,
  2352. &dwMinKey,
  2353. &dwMaxKey,
  2354. &dwInc))
  2355. {
  2356. dwTempGenKeyFlags = pCertWizardInfo->dwGenKeyFlags;
  2357. dwTempGenKeyFlags &= 0xFFFF0000;
  2358. dwTempGenKeyFlags = (dwTempGenKeyFlags >> 16);
  2359. //we use 0 for default key size for V1 template
  2360. if(0 != dwTempGenKeyFlags)
  2361. {
  2362. if(dwTempGenKeyFlags < dwMinKey)
  2363. {
  2364. pCertWizardInfo->dwGenKeyFlags &= 0x0000FFFF;
  2365. pCertWizardInfo->dwGenKeyFlags |= ((dwMinKey) << 16);
  2366. }
  2367. }
  2368. }
  2369. }
  2370. }
  2371. }
  2372. //user has to set up the CSP:
  2373. //1. in the UI case. The CSP is always selected
  2374. //2. In the UILess case, the CSP can be:
  2375. // 2.1 User specified in the API.
  2376. // 2.2 We have selected for their dehalf for the CSP list on the cert template
  2377. // 2.3 We default to RSA_FULL for non-cert template case
  2378. if((NULL == pCertWizardInfo->pwszProvider) || (0 == pCertWizardInfo->dwProviderType))
  2379. {
  2380. idsText=IDS_ENROLL_NO_CERT_TYPE;
  2381. hr=E_INVALIDARG;
  2382. }
  2383. //consider the user input extensions
  2384. if(pCertWizardInfo->pCertRequestExtensions)
  2385. {
  2386. dwExtensions++;
  2387. pExtensions=(PCERT_EXTENSIONS *)WizardRealloc(pExtensions,
  2388. dwExtensions * sizeof(PCERT_EXTENSIONS));
  2389. _JumpCondition(NULL == pExtensions, MemoryError);
  2390. pExtensions[dwExtensions-1]=pCertWizardInfo->pCertRequestExtensions;
  2391. }
  2392. //set up the private key information
  2393. pCertRequestPvkNew->dwSize=sizeof(CERT_REQUEST_PVK_NEW);
  2394. pCertRequestPvkNew->dwProvType=pCertWizardInfo->dwProviderType;
  2395. pCertRequestPvkNew->pwszProvider=pCertWizardInfo->pwszProvider;
  2396. pCertRequestPvkNew->dwProviderFlags=pCertWizardInfo->dwProviderFlags;
  2397. //we mark the provider flag SILENT for remote or UIless enrollment
  2398. if (((0 != (pCertWizardInfo->dwFlags & CRYPTUI_WIZ_NO_UI)) &&
  2399. (0 == (pCertWizardInfo->dwFlags & CRYPTUI_WIZ_IGNORE_NO_UI_FLAG_FOR_CSPS))) ||
  2400. (FALSE == pCertWizardInfo->fLocal))
  2401. {
  2402. pCertRequestPvkNew->dwProviderFlags |= CRYPT_SILENT;
  2403. }
  2404. pCertRequestPvkNew->pwszKeyContainer = pCertWizardInfo->pwszKeyContainer;
  2405. pCertRequestPvkNew->dwKeySpec = pCertWizardInfo->dwKeySpec;
  2406. pCertRequestPvkNew->dwGenKeyFlags = pCertWizardInfo->dwGenKeyFlags;
  2407. pCertRequestPvkNew->dwEnrollmentFlags = pCertWizardInfo->dwEnrollmentFlags;
  2408. pCertRequestPvkNew->dwSubjectNameFlags = pCertWizardInfo->dwSubjectNameFlags;
  2409. pCertRequestPvkNew->dwPrivateKeyFlags = pCertWizardInfo->dwPrivateKeyFlags;
  2410. pCertRequestPvkNew->dwGeneralFlags = pCertWizardInfo->dwGeneralFlags;
  2411. //set up the enrollment information
  2412. pRequestInfo->dwSize=sizeof(CERT_ENROLL_INFO);
  2413. pRequestInfo->pwszUsageOID=pwszUsageOID;
  2414. pRequestInfo->pwszCertDNName=pCertWizardInfo->pwszCertDNName;
  2415. pRequestInfo->dwPostOption=pCertWizardInfo->dwPostOption;
  2416. pRequestInfo->dwExtensions=dwExtensions;
  2417. pRequestInfo->prgExtensions=pExtensions;
  2418. // We want to copy the friendlyname and description from the request info if
  2419. // a) if we're enrolling OR
  2420. // b) if we're enrolling with a signing cert
  2421. fCopyPropertiesFromRequestInfo =
  2422. (0 != (CRYPTUI_WIZ_CERT_ENROLL & pCertWizardInfo->dwPurpose)) ||
  2423. (0 != (CRYPTUI_WIZ_NO_ARCHIVE_RENEW_CERT & pCertWizardInfo->dwFlags));
  2424. //set up the friendlyName and pwszDescription separately
  2425. if (fCopyPropertiesFromRequestInfo)
  2426. {
  2427. if (NULL == pCertWizardInfo->pwszFriendlyName) { pRequestInfo->pwszFriendlyName = NULL; }
  2428. else
  2429. {
  2430. pRequestInfo->pwszFriendlyName = WizardAllocAndCopyWStr(pCertWizardInfo->pwszFriendlyName);
  2431. _JumpCondition(NULL == pRequestInfo->pwszFriendlyName, MemoryError);
  2432. }
  2433. if (NULL == pCertWizardInfo->pwszDescription) { pRequestInfo->pwszDescription = NULL; }
  2434. else
  2435. {
  2436. pRequestInfo->pwszDescription = WizardAllocAndCopyWStr(pCertWizardInfo->pwszDescription);
  2437. _JumpCondition(NULL == pRequestInfo->pwszDescription, MemoryError);
  2438. }
  2439. }
  2440. else // copy properties from renew cert context
  2441. {
  2442. //get the friendlyName and description of the cerititificate
  2443. //get the friendly info from the certificate
  2444. CertAllocAndGetCertificateContextProperty
  2445. (pCertWizardInfo->pCertContext,
  2446. CERT_FRIENDLY_NAME_PROP_ID,
  2447. (LPVOID *)&(pRequestInfo->pwszFriendlyName),
  2448. &dwSize);
  2449. //get the description
  2450. CertAllocAndGetCertificateContextProperty
  2451. (pCertWizardInfo->pCertContext,
  2452. CERT_DESCRIPTION_PROP_ID,
  2453. (LPVOID *)&(pRequestInfo->pwszDescription),
  2454. &dwSize);
  2455. }
  2456. // We want to set up renew pvk info if
  2457. // a) We're renewing
  2458. // b) We're enrolling with a signing cert
  2459. fSetUpRenewPvk =
  2460. (0 == (CRYPTUI_WIZ_CERT_ENROLL & pCertWizardInfo->dwPurpose)) ||
  2461. (0 != (CRYPTUI_WIZ_NO_ARCHIVE_RENEW_CERT & pCertWizardInfo->dwFlags));
  2462. if (fSetUpRenewPvk)
  2463. {
  2464. //Set up the private key information and the certBLOBs
  2465. _JumpCondition(NULL == pCertWizardInfo->pCertContext, InvalidArgError);
  2466. pCertBlob->cbData=pCertWizardInfo->pCertContext->cbCertEncoded;
  2467. pCertBlob->pbData=pCertWizardInfo->pCertContext->pbCertEncoded;
  2468. //get the private key info from the certificate
  2469. if(!CertAllocAndGetCertificateContextProperty
  2470. (pCertWizardInfo->pCertContext,
  2471. CERT_KEY_PROV_INFO_PROP_ID,
  2472. (LPVOID *)&pKeyProvInfo,
  2473. &dwSize))
  2474. goto CertAllocAndGetCertificateContextPropertyError;
  2475. //set up the private key information
  2476. pCertRenewPvk->dwSize = sizeof(CERT_REQUEST_PVK_NEW);
  2477. pCertRenewPvk->dwProvType = pKeyProvInfo->dwProvType;
  2478. pCertRenewPvk->dwProviderFlags = pKeyProvInfo->dwFlags;
  2479. //we mark the provider flag SILENT for remote or UIless enrollment
  2480. if (((0 != (pCertWizardInfo->dwFlags & CRYPTUI_WIZ_NO_UI)) &&
  2481. (0 == (pCertWizardInfo->dwFlags & CRYPTUI_WIZ_IGNORE_NO_UI_FLAG_FOR_CSPS))) ||
  2482. (FALSE == pCertWizardInfo->fLocal))
  2483. {
  2484. pCertRenewPvk->dwProviderFlags |= CRYPT_SILENT;
  2485. }
  2486. pCertRenewPvk->dwKeySpec = pKeyProvInfo->dwKeySpec;
  2487. pCertRenewPvk->dwEnrollmentFlags = pCertWizardInfo->dwEnrollmentFlags;
  2488. pCertRenewPvk->dwSubjectNameFlags = pCertWizardInfo->dwSubjectNameFlags;
  2489. pCertRenewPvk->dwPrivateKeyFlags = pCertWizardInfo->dwPrivateKeyFlags;
  2490. pCertRenewPvk->dwGeneralFlags = pCertWizardInfo->dwGeneralFlags;
  2491. pCertRenewPvk->pwszKeyContainer = WizardAllocAndCopyWStr(
  2492. pKeyProvInfo->pwszContainerName);
  2493. _JumpCondition(NULL == pCertRenewPvk->pwszKeyContainer, MemoryError);
  2494. pCertRenewPvk->pwszProvider = WizardAllocAndCopyWStr(
  2495. pKeyProvInfo->pwszProvName);
  2496. _JumpCondition(NULL == pCertRenewPvk->pwszProvider, MemoryError);
  2497. }
  2498. hr = S_OK;
  2499. CLEANUP:
  2500. if (fRevertWizardProvider) { pCertWizardInfo->pwszProvider = NULL; }
  2501. if (S_OK != hr)
  2502. {
  2503. pCertWizardInfo->idsText = idsText;
  2504. pCertWizardInfo->dwStatus = CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR;
  2505. }
  2506. if (NULL != pwszOID) { FreeWStr(pwszOID); }
  2507. if (NULL != pKeyProvInfo) { WizardFree((LPVOID)pKeyProvInfo); }
  2508. return hr;
  2509. ErrorReturn:
  2510. goto CLEANUP;
  2511. SET_HRESULT(CertAllocAndGetCertificateContextPropertyError, CodeToHR(GetLastError()));
  2512. SET_HRESULT(CertTypeFlagsToGenKeyFlagsError, CodeToHR(GetLastError()));
  2513. SET_HRESULT(InvalidArgError, E_INVALIDARG);
  2514. SET_HRESULT(MemoryError, E_OUTOFMEMORY);
  2515. SET_HRESULT(UnexpectedError, E_UNEXPECTED);
  2516. }
  2517. void FreeRequestParameters(IN LPWSTR *ppwszHashAlg,
  2518. IN CERT_ENROLL_INFO *pRequestInfo)
  2519. {
  2520. if (NULL != pRequestInfo)
  2521. {
  2522. if (NULL != pRequestInfo->pwszUsageOID) { WizardFree((LPVOID)pRequestInfo->pwszUsageOID); }
  2523. if (NULL != pRequestInfo->prgExtensions) { WizardFree((LPVOID)pRequestInfo->prgExtensions); }
  2524. if (NULL != pRequestInfo->pwszFriendlyName) { WizardFree((LPVOID)pRequestInfo->pwszFriendlyName); }
  2525. if (NULL != pRequestInfo->pwszDescription) { WizardFree((LPVOID)pRequestInfo->pwszDescription); }
  2526. pRequestInfo->pwszUsageOID = NULL;
  2527. pRequestInfo->prgExtensions = NULL;
  2528. pRequestInfo->pwszFriendlyName = NULL;
  2529. pRequestInfo->pwszDescription = NULL;
  2530. }
  2531. if (NULL != ppwszHashAlg && NULL != *ppwszHashAlg)
  2532. {
  2533. FreeWStr(*ppwszHashAlg);
  2534. *ppwszHashAlg = NULL;
  2535. }
  2536. }
  2537. //-----------------------------------------------------------------------------
  2538. // Memory routines
  2539. //
  2540. //#define malloc(cb) ((void*)LocalAlloc(LPTR, cb))
  2541. //#define free(pv) (LocalFree((HLOCAL)pv))
  2542. //#define realloc(pv, cb) ((void*)LocalReAlloc((HLOCAL)pv, cb, LMEM_MOVEABLE))
  2543. //
  2544. //
  2545. //-----------------------------------------------------------------------------
  2546. LPVOID WizardAlloc (ULONG cbSize)
  2547. {
  2548. return ((void*)LocalAlloc(LPTR, cbSize));
  2549. }
  2550. LPVOID WizardRealloc (
  2551. LPVOID pv,
  2552. ULONG cbSize)
  2553. {
  2554. LPVOID pvTemp=NULL;
  2555. if(NULL==pv)
  2556. return WizardAlloc(cbSize);
  2557. pvTemp=((void*)LocalReAlloc((HLOCAL)pv, cbSize, LMEM_MOVEABLE));
  2558. if(NULL==pvTemp)
  2559. {
  2560. //we are running out memory
  2561. WizardFree(pv);
  2562. }
  2563. return pvTemp;
  2564. }
  2565. VOID MyWizardFree (LPVOID pv)
  2566. {
  2567. if (pv)
  2568. LocalFree((HLOCAL)pv);
  2569. }
  2570. VOID WizardFree (LPVOID pv)
  2571. {
  2572. if (pv)
  2573. LocalFree((HLOCAL)pv);
  2574. }
  2575. //-----------------------------------------------------------------------------
  2576. // the call back function to compare the certificate
  2577. //
  2578. //-----------------------------------------------------------------------------
  2579. int CALLBACK CompareCertificate(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  2580. {
  2581. PCCERT_CONTEXT pCertOne=NULL;
  2582. PCCERT_CONTEXT pCertTwo=NULL;
  2583. DWORD dwColumn=0;
  2584. int iCompare=0;
  2585. LPWSTR pwszOne=NULL;
  2586. LPWSTR pwszTwo=NULL;
  2587. pCertOne=(PCCERT_CONTEXT)lParam1;
  2588. pCertTwo=(PCCERT_CONTEXT)lParam2;
  2589. dwColumn=(DWORD)lParamSort;
  2590. if((NULL==pCertOne) || (NULL==pCertTwo))
  2591. goto CLEANUP;
  2592. switch(dwColumn & 0x0000FFFF)
  2593. {
  2594. case SORT_COLUMN_SUBJECT:
  2595. GetCertSubject(pCertOne, &pwszOne);
  2596. GetCertSubject(pCertTwo, &pwszTwo);
  2597. break;
  2598. case SORT_COLUMN_ISSUER:
  2599. GetCertIssuer(pCertOne, &pwszOne);
  2600. GetCertIssuer(pCertTwo, &pwszTwo);
  2601. break;
  2602. case SORT_COLUMN_PURPOSE:
  2603. GetCertPurpose(pCertOne, &pwszOne);
  2604. GetCertPurpose(pCertTwo, &pwszTwo);
  2605. break;
  2606. case SORT_COLUMN_NAME:
  2607. GetCertFriendlyName(pCertOne, &pwszOne);
  2608. GetCertFriendlyName(pCertTwo, &pwszTwo);
  2609. break;
  2610. case SORT_COLUMN_LOCATION:
  2611. if (!GetCertLocation(pCertOne, &pwszOne))
  2612. {
  2613. pwszOne = NULL;
  2614. goto CLEANUP;
  2615. }
  2616. if (!GetCertLocation(pCertTwo, &pwszTwo))
  2617. {
  2618. pwszTwo = NULL;
  2619. goto CLEANUP;
  2620. }
  2621. break;
  2622. }
  2623. if(SORT_COLUMN_EXPIRATION == (dwColumn & 0x0000FFFF))
  2624. {
  2625. iCompare=CompareFileTime(&(pCertOne->pCertInfo->NotAfter),
  2626. &(pCertTwo->pCertInfo->NotAfter));
  2627. }
  2628. else
  2629. {
  2630. if((NULL==pwszOne) || (NULL==pwszTwo))
  2631. goto CLEANUP;
  2632. //we should use wcsicoll instead of wcsicmp since wcsicoll use the
  2633. //lexicographic order of current code page.
  2634. iCompare=CompareStringU(LOCALE_USER_DEFAULT,
  2635. NORM_IGNORECASE,
  2636. pwszOne,
  2637. -1,
  2638. pwszTwo,
  2639. -1);
  2640. //map to the C run time convention
  2641. iCompare = iCompare -2;
  2642. }
  2643. if(dwColumn & SORT_COLUMN_DESCEND)
  2644. iCompare = 0-iCompare;
  2645. CLEANUP:
  2646. if(pwszOne)
  2647. WizardFree(pwszOne);
  2648. if(pwszTwo)
  2649. WizardFree(pwszTwo);
  2650. return iCompare;
  2651. }
  2652. //-----------------------------------------------------------------------------
  2653. // GetCertIssuer
  2654. //
  2655. //-----------------------------------------------------------------------------
  2656. BOOL GetCertIssuer(PCCERT_CONTEXT pCertContext, LPWSTR *ppwsz)
  2657. {
  2658. BOOL fResult=FALSE;
  2659. DWORD dwChar=0;
  2660. WCHAR wszNone[MAX_TITLE_LENGTH];
  2661. if(!pCertContext || !ppwsz)
  2662. goto CLEANUP;
  2663. *ppwsz=NULL;
  2664. dwChar=CertGetNameStringW(
  2665. pCertContext,
  2666. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  2667. CERT_NAME_ISSUER_FLAG,
  2668. NULL,
  2669. NULL,
  2670. 0);
  2671. if ((dwChar != 0) && (NULL != (*ppwsz = (LPWSTR)WizardAlloc(dwChar * sizeof(WCHAR)))))
  2672. {
  2673. CertGetNameStringW(
  2674. pCertContext,
  2675. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  2676. CERT_NAME_ISSUER_FLAG,
  2677. NULL,
  2678. *ppwsz,
  2679. dwChar);
  2680. }
  2681. else
  2682. {
  2683. if(!LoadStringU(g_hmodThisDll, IDS_NONE, wszNone, MAX_TITLE_LENGTH))
  2684. wszNone[0]=L'\0';
  2685. if(!(*ppwsz=WizardAllocAndCopyWStr(wszNone)))
  2686. goto CLEANUP;
  2687. }
  2688. fResult=TRUE;
  2689. CLEANUP:
  2690. if(FALSE == fResult)
  2691. {
  2692. if(*ppwsz)
  2693. WizardFree(*ppwsz);
  2694. *ppwsz=NULL;
  2695. }
  2696. return fResult;
  2697. }
  2698. //-----------------------------------------------------------------------------
  2699. // GetCertSubject
  2700. //
  2701. //-----------------------------------------------------------------------------
  2702. BOOL GetCertSubject(PCCERT_CONTEXT pCertContext, LPWSTR *ppwsz)
  2703. {
  2704. BOOL fResult=FALSE;
  2705. DWORD dwChar=0;
  2706. WCHAR wszNone[MAX_TITLE_LENGTH];
  2707. if(!pCertContext || !ppwsz)
  2708. goto CLEANUP;
  2709. *ppwsz=NULL;
  2710. dwChar=CertGetNameStringW(
  2711. pCertContext,
  2712. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  2713. 0,
  2714. NULL,
  2715. NULL,
  2716. 0);
  2717. if ((dwChar != 0) && (NULL != (*ppwsz = (LPWSTR)WizardAlloc(dwChar * sizeof(WCHAR)))))
  2718. {
  2719. CertGetNameStringW(
  2720. pCertContext,
  2721. CERT_NAME_SIMPLE_DISPLAY_TYPE,
  2722. 0,
  2723. NULL,
  2724. *ppwsz,
  2725. dwChar);
  2726. }
  2727. else
  2728. {
  2729. if(!LoadStringU(g_hmodThisDll, IDS_NONE, wszNone, MAX_TITLE_LENGTH))
  2730. wszNone[0]=L'\0';
  2731. if(!(*ppwsz=WizardAllocAndCopyWStr(wszNone)))
  2732. goto CLEANUP;
  2733. }
  2734. fResult=TRUE;
  2735. CLEANUP:
  2736. if(FALSE == fResult)
  2737. {
  2738. if(*ppwsz)
  2739. WizardFree(*ppwsz);
  2740. *ppwsz=NULL;
  2741. }
  2742. return fResult;
  2743. }
  2744. //-----------------------------------------------------------------------------
  2745. // MyFormatEnhancedKeyUsageString
  2746. //
  2747. // This functions is here because the FormatEnhancedKeyUsageString function
  2748. // uses malloc and all the wizards use LocalAlloc and LocalFree.
  2749. //
  2750. //-----------------------------------------------------------------------------
  2751. BOOL MyFormatEnhancedKeyUsageString(LPWSTR *ppString,
  2752. PCCERT_CONTEXT pCertContext,
  2753. BOOL fPropertiesOnly,
  2754. BOOL fMultiline)
  2755. {
  2756. LPWSTR pwszTemp = NULL;
  2757. if(!FormatEnhancedKeyUsageString(&pwszTemp, pCertContext, fPropertiesOnly, fMultiline))
  2758. return FALSE;
  2759. *ppString = WizardAllocAndCopyWStr(pwszTemp);
  2760. free(pwszTemp);
  2761. if (*ppString != NULL)
  2762. return TRUE;
  2763. else
  2764. return FALSE;
  2765. }
  2766. //-----------------------------------------------------------------------------
  2767. // GetCertPurpose
  2768. //
  2769. //-----------------------------------------------------------------------------
  2770. BOOL GetCertPurpose(PCCERT_CONTEXT pCertContext, LPWSTR *ppwsz)
  2771. {
  2772. WCHAR wszNone[MAX_TITLE_LENGTH];
  2773. if(!pCertContext || !ppwsz)
  2774. return FALSE;
  2775. *ppwsz=NULL;
  2776. if(MyFormatEnhancedKeyUsageString(ppwsz,pCertContext, FALSE, FALSE))
  2777. return TRUE;
  2778. return FALSE;
  2779. }
  2780. //-----------------------------------------------------------------------------
  2781. // GetCertFriendlyName
  2782. //
  2783. //-----------------------------------------------------------------------------
  2784. BOOL GetCertFriendlyName(PCCERT_CONTEXT pCertContext, LPWSTR *ppwsz)
  2785. {
  2786. BOOL fResult=FALSE;
  2787. DWORD dwChar=0;
  2788. WCHAR wszNone[MAX_TITLE_LENGTH];
  2789. if(!pCertContext || !ppwsz)
  2790. return FALSE;
  2791. *ppwsz=NULL;
  2792. dwChar=0;
  2793. if(CertAllocAndGetCertificateContextProperty(
  2794. pCertContext,
  2795. CERT_FRIENDLY_NAME_PROP_ID,
  2796. (LPVOID *)ppwsz,
  2797. &dwChar))
  2798. {
  2799. return TRUE;
  2800. }
  2801. if(!LoadStringU(g_hmodThisDll, IDS_NONE, wszNone, MAX_TITLE_LENGTH))
  2802. wszNone[0]=L'\0';
  2803. if((*ppwsz=WizardAllocAndCopyWStr(wszNone)))
  2804. return TRUE;
  2805. return FALSE;
  2806. }
  2807. //-----------------------------------------------------------------------------
  2808. // GetCertLocation
  2809. //
  2810. //-----------------------------------------------------------------------------
  2811. BOOL GetCertLocation (PCCERT_CONTEXT pCertContext, LPWSTR *ppwsz)
  2812. {
  2813. DWORD cbName = 0;
  2814. WCHAR wszNotAvailable[MAX_TITLE_LENGTH];
  2815. if (CertGetStoreProperty(
  2816. pCertContext->hCertStore,
  2817. CERT_STORE_LOCALIZED_NAME_PROP_ID,
  2818. NULL,
  2819. &cbName))
  2820. {
  2821. if (NULL == (*ppwsz = (LPWSTR) WizardAlloc(cbName)))
  2822. {
  2823. return FALSE;
  2824. }
  2825. if (!CertGetStoreProperty(
  2826. pCertContext->hCertStore,
  2827. CERT_STORE_LOCALIZED_NAME_PROP_ID,
  2828. *ppwsz,
  2829. &cbName))
  2830. {
  2831. WizardFree(*ppwsz);
  2832. return FALSE;
  2833. }
  2834. }
  2835. else
  2836. {
  2837. if (!LoadStringU(g_hmodThisDll, IDS_NOTAVAILABLE, wszNotAvailable, MAX_TITLE_LENGTH))
  2838. {
  2839. wszNotAvailable[0]=L'\0';
  2840. }
  2841. if (NULL == (*ppwsz = WizardAllocAndCopyWStr(wszNotAvailable)))
  2842. {
  2843. return FALSE;
  2844. }
  2845. }
  2846. return TRUE;
  2847. }
  2848. //-----------------------------------------------------------------------------
  2849. // LoadFilterString
  2850. //
  2851. //-----------------------------------------------------------------------------
  2852. int LoadFilterString(
  2853. HINSTANCE hInstance,
  2854. UINT uID,
  2855. LPWSTR lpBuffer,
  2856. int nBufferMax)
  2857. {
  2858. int size;
  2859. if(size = LoadStringU(hInstance, uID, lpBuffer, nBufferMax))
  2860. {
  2861. lpBuffer[size]= L'\0';
  2862. lpBuffer[size+1]= L'\0';
  2863. return size+1;
  2864. }
  2865. else
  2866. {
  2867. return 0;
  2868. }
  2869. }
  2870. //-----------------------------------------------------------------------------
  2871. // ExpandAndAllocString
  2872. //
  2873. //-----------------------------------------------------------------------------
  2874. LPWSTR ExpandAndAllocString(LPCWSTR pwsz)
  2875. {
  2876. LPWSTR pwszExpandedFileName = NULL;
  2877. DWORD dwExpanded = 0;
  2878. dwExpanded = ExpandEnvironmentStringsU(pwsz, NULL, 0);
  2879. pwszExpandedFileName = (LPWSTR) WizardAlloc(dwExpanded * sizeof(WCHAR));
  2880. if (pwszExpandedFileName == NULL)
  2881. {
  2882. SetLastError(E_OUTOFMEMORY);
  2883. return (NULL);
  2884. }
  2885. if (0 == ExpandEnvironmentStringsU(pwsz, pwszExpandedFileName, dwExpanded))
  2886. {
  2887. WizardFree(pwszExpandedFileName);
  2888. return (NULL);
  2889. }
  2890. return (pwszExpandedFileName);
  2891. }
  2892. //-----------------------------------------------------------------------------
  2893. // ExpandAndCreateFileU
  2894. //
  2895. //-----------------------------------------------------------------------------
  2896. HANDLE WINAPI ExpandAndCreateFileU (
  2897. LPCWSTR lpFileName,
  2898. DWORD dwDesiredAccess,
  2899. DWORD dwShareMode,
  2900. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  2901. DWORD dwCreationDisposition,
  2902. DWORD dwFlagsAndAttributes,
  2903. HANDLE hTemplateFile
  2904. )
  2905. {
  2906. HANDLE hRet = INVALID_HANDLE_VALUE;
  2907. LPWSTR pwszExpandedFileName = NULL;
  2908. pwszExpandedFileName = ExpandAndAllocString(lpFileName);
  2909. if (NULL != pwszExpandedFileName)
  2910. {
  2911. hRet = CreateFileU (
  2912. pwszExpandedFileName,
  2913. dwDesiredAccess,
  2914. dwShareMode,
  2915. lpSecurityAttributes,
  2916. dwCreationDisposition,
  2917. dwFlagsAndAttributes,
  2918. hTemplateFile);
  2919. WizardFree(pwszExpandedFileName);
  2920. }
  2921. return (hRet);
  2922. }
  2923. WINCRYPT32API
  2924. BOOL
  2925. WINAPI
  2926. ExpandAndCryptQueryObject(
  2927. DWORD dwObjectType,
  2928. const void *pvObject,
  2929. DWORD dwExpectedContentTypeFlags,
  2930. DWORD dwExpectedFormatTypeFlags,
  2931. DWORD dwFlags,
  2932. DWORD *pdwMsgAndCertEncodingType,
  2933. DWORD *pdwContentType,
  2934. DWORD *pdwFormatType,
  2935. HCERTSTORE *phCertStore,
  2936. HCRYPTMSG *phMsg,
  2937. const void **ppvContext
  2938. )
  2939. {
  2940. LPWSTR pwszExpandedFileName = NULL;
  2941. BOOL fRet = FALSE;
  2942. if (dwObjectType == CERT_QUERY_OBJECT_FILE)
  2943. {
  2944. pwszExpandedFileName = ExpandAndAllocString((LPWSTR)pvObject);
  2945. if (NULL != pwszExpandedFileName)
  2946. {
  2947. fRet = CryptQueryObject(
  2948. dwObjectType,
  2949. pwszExpandedFileName,
  2950. dwExpectedContentTypeFlags,
  2951. dwExpectedFormatTypeFlags,
  2952. dwFlags,
  2953. pdwMsgAndCertEncodingType,
  2954. pdwContentType,
  2955. pdwFormatType,
  2956. phCertStore,
  2957. phMsg,
  2958. ppvContext
  2959. );
  2960. WizardFree(pwszExpandedFileName);
  2961. }
  2962. else
  2963. {
  2964. fRet = FALSE;
  2965. }
  2966. }
  2967. else
  2968. {
  2969. fRet = CryptQueryObject(
  2970. dwObjectType,
  2971. pvObject,
  2972. dwExpectedContentTypeFlags,
  2973. dwExpectedFormatTypeFlags,
  2974. dwFlags,
  2975. pdwMsgAndCertEncodingType,
  2976. pdwContentType,
  2977. pdwFormatType,
  2978. phCertStore,
  2979. phMsg,
  2980. ppvContext
  2981. );
  2982. }
  2983. return (fRet);
  2984. }
  2985. HRESULT EnrollmentCOMObjectFactory_getInstance
  2986. (EnrollmentCOMObjectFactoryContext *pContext,
  2987. REFCLSID rclsid,
  2988. REFIID riid,
  2989. LPUNKNOWN *pUnknown,
  2990. LPVOID *ppInstance)
  2991. {
  2992. HRESULT hr = S_OK;
  2993. // Input validation.
  2994. // Only ppInstance can be an invalid argument, as the other arguments are supplied
  2995. // directly by other class members.
  2996. if (ppInstance == NULL) { return E_INVALIDARG; }
  2997. // Ensure that COM is initialized.
  2998. if (!pContext->fIsCOMInitialized)
  2999. {
  3000. hr = CoInitialize(NULL);
  3001. if (FAILED(hr))
  3002. goto Error;
  3003. pContext->fIsCOMInitialized = TRUE;
  3004. }
  3005. if (*pUnknown == NULL)
  3006. {
  3007. // We've not yet created an instance of this type, do so now:
  3008. if (S_OK != (hr = CoCreateInstance(rclsid,
  3009. NULL,
  3010. CLSCTX_INPROC_SERVER,
  3011. riid,
  3012. (LPVOID *)pUnknown)))
  3013. goto Error;
  3014. }
  3015. // Increment the reference count and assign the out param:
  3016. (*pUnknown)->AddRef();
  3017. *ppInstance = *pUnknown;
  3018. CommonReturn:
  3019. return hr;
  3020. Error:
  3021. // Some error occured which did not prevent the creation of the COM object.
  3022. // Release the object:
  3023. if (*pUnknown != NULL)
  3024. {
  3025. (*pUnknown)->Release();
  3026. *pUnknown = NULL;
  3027. }
  3028. goto CommonReturn;
  3029. }
  3030. //-----------------------------------------------------------------------
  3031. //
  3032. // RetrivePKCS7FromCA
  3033. //
  3034. // The routine that calls xEnroll and CA to request a certificate
  3035. // This routine also provide confirmation dialogue
  3036. //------------------------------------------------------------------------
  3037. extern "C" HRESULT WINAPI RetrievePKCS7FromCA(DWORD dwPurpose,
  3038. LPWSTR pwszCALocation,
  3039. LPWSTR pwszCAName,
  3040. LPWSTR pwszRequestString,
  3041. CRYPT_DATA_BLOB *pPKCS10Blob,
  3042. CRYPT_DATA_BLOB *pPKCS7Blob,
  3043. DWORD *pdwStatus)
  3044. {
  3045. HRESULT hr=E_FAIL;
  3046. DWORD dwException=0;
  3047. DWORD dwStatus=0;
  3048. DWORD dwDisposition=0;
  3049. DWORD dwFlags=0;
  3050. CERTSERVERENROLL *pCertServerEnroll=NULL;
  3051. //input checking
  3052. if(!pPKCS10Blob || !pPKCS7Blob)
  3053. return E_INVALIDARG;
  3054. //determine the format flag
  3055. if(dwPurpose & CRYPTUI_WIZ_CERT_RENEW )
  3056. dwFlags = CR_IN_BINARY | CR_IN_PKCS7;
  3057. else
  3058. dwFlags = CR_IN_BINARY | CR_IN_PKCS10;
  3059. //submit the request
  3060. __try
  3061. {
  3062. hr= CertServerSubmitRequest(
  3063. dwFlags,
  3064. pPKCS10Blob->pbData,
  3065. pPKCS10Blob->cbData,
  3066. pwszRequestString,
  3067. pwszCALocation,
  3068. pwszCAName,
  3069. &pCertServerEnroll);
  3070. }
  3071. __except(dwException = GetExceptionCode(), EXCEPTION_EXECUTE_HANDLER)
  3072. {
  3073. hr=HRESULT_FROM_WIN32(dwException);
  3074. if(S_OK == hr)
  3075. hr=E_UNEXPECTED;
  3076. }
  3077. //process the error
  3078. //first, filter out the PRC error
  3079. if(hr == HRESULT_FROM_WIN32(RPC_S_UNKNOWN_AUTHN_SERVICE) ||
  3080. hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) ||
  3081. hr == HRESULT_FROM_WIN32(RPC_S_SERVER_TOO_BUSY))
  3082. {
  3083. dwStatus=CRYPTUI_WIZ_CERT_REQUEST_STATUS_CONNECTION_FAILED;
  3084. goto CLEANUP;
  3085. }
  3086. //if hr is S_OK, we have retrieve valid return from the CA
  3087. if(hr==S_OK)
  3088. {
  3089. if(!pCertServerEnroll)
  3090. {
  3091. hr=E_INVALIDARG;
  3092. dwDisposition=CR_DISP_ERROR;
  3093. }
  3094. else
  3095. {
  3096. hr = pCertServerEnroll->hrLastStatus;
  3097. dwDisposition = pCertServerEnroll->Disposition;
  3098. }
  3099. }
  3100. else
  3101. {
  3102. dwDisposition=CR_DISP_ERROR;
  3103. }
  3104. //map the dwDisposition to dwStatus
  3105. switch(dwDisposition)
  3106. {
  3107. case CR_DISP_DENIED:
  3108. dwStatus=CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_DENIED;
  3109. if(!FAILED(hr))
  3110. hr=E_FAIL;
  3111. break;
  3112. case CR_DISP_ISSUED:
  3113. dwStatus=CRYPTUI_WIZ_CERT_REQUEST_STATUS_CERT_ISSUED;
  3114. break;
  3115. case CR_DISP_ISSUED_OUT_OF_BAND:
  3116. dwStatus=CRYPTUI_WIZ_CERT_REQUEST_STATUS_ISSUED_SEPARATELY;
  3117. break;
  3118. case CR_DISP_UNDER_SUBMISSION:
  3119. dwStatus=CRYPTUI_WIZ_CERT_REQUEST_STATUS_UNDER_SUBMISSION;
  3120. break;
  3121. //we should never get CR_DISP_INCOMPLETE or CR_DISP_REVOKED
  3122. //case CR_DISP_INCOMPLETE:
  3123. //case CR_DISP_REVOKED:
  3124. case CR_DISP_ERROR:
  3125. default:
  3126. dwStatus=CRYPTUI_WIZ_CERT_REQUEST_STATUS_REQUEST_ERROR;
  3127. if(!FAILED(hr))
  3128. hr=E_FAIL;
  3129. break;
  3130. }
  3131. //no need to retrieve the enrolled certificate if failed
  3132. if(hr != S_OK)
  3133. goto CLEANUP;
  3134. //copy the PKCS7 blob
  3135. pPKCS7Blob->cbData=pCertServerEnroll->cbCertChain;
  3136. pPKCS7Blob->pbData=(BYTE *)WizardAlloc(pCertServerEnroll->cbCertChain);
  3137. if(NULL==pPKCS7Blob->pbData)
  3138. {
  3139. hr=E_OUTOFMEMORY;
  3140. dwStatus=CRYPTUI_WIZ_CERT_REQUEST_STATUS_INSTALL_FAILED;
  3141. goto CLEANUP;
  3142. }
  3143. memcpy(pPKCS7Blob->pbData,pCertServerEnroll->pbCertChain,pCertServerEnroll->cbCertChain);
  3144. hr=S_OK;
  3145. CLEANUP:
  3146. if(pCertServerEnroll)
  3147. CertServerFreeMemory(pCertServerEnroll);
  3148. if(pdwStatus)
  3149. *pdwStatus=dwStatus;
  3150. return hr;
  3151. }
  3152. IEnumCSP::IEnumCSP(CERT_WIZARD_INFO * pCertWizardInfo)
  3153. {
  3154. if (NULL == pCertWizardInfo)
  3155. {
  3156. m_hr = E_POINTER;
  3157. return; // We're not initialized.
  3158. }
  3159. m_cCSPs = pCertWizardInfo->dwCSPCount;
  3160. m_pfCSPs = (BOOL *)WizardAlloc(sizeof(BOOL) * m_cCSPs);
  3161. if (NULL == m_pfCSPs)
  3162. {
  3163. m_hr = E_OUTOFMEMORY;
  3164. return; // We're not initialized.
  3165. }
  3166. if (NULL != pCertWizardInfo->pwszProvider)
  3167. {
  3168. for (DWORD dwIndex = 0; dwIndex < pCertWizardInfo->dwCSPCount; dwIndex++)
  3169. {
  3170. if (0 == _wcsicmp(pCertWizardInfo->pwszProvider, pCertWizardInfo->rgwszProvider[dwIndex]))
  3171. {
  3172. // Enable only the CSP we've specified.
  3173. m_pfCSPs[dwIndex] = TRUE;
  3174. }
  3175. }
  3176. }
  3177. else
  3178. {
  3179. for (DWORD dwCAIndex = 1; dwCAIndex < pCertWizardInfo->pCertCAInfo->dwCA; dwCAIndex++ )
  3180. {
  3181. CRYPTUI_WIZ_CERT_CA *pCertCA = &(pCertWizardInfo->pCertCAInfo->rgCA[dwCAIndex]);
  3182. // Any cert types available for this CA?
  3183. if(pCertCA->dwCertTypeInfo > 0)
  3184. {
  3185. for(DWORD dwCertTypeIndex = 0; dwCertTypeIndex < pCertCA->dwCertTypeInfo; dwCertTypeIndex++)
  3186. {
  3187. if (TRUE == (pCertCA->rgCertTypeInfo)[dwCertTypeIndex].fSelected)
  3188. {
  3189. if ((pCertCA->rgCertTypeInfo)[dwCertTypeIndex].dwCSPCount && (pCertCA->rgCertTypeInfo)[dwCertTypeIndex].rgdwCSP)
  3190. {
  3191. for (DWORD dwCSPIndex = 0; dwCSPIndex < (pCertCA->rgCertTypeInfo)[dwCertTypeIndex].dwCSPCount; dwCSPIndex++)
  3192. {
  3193. // Turn on this CSP.
  3194. m_pfCSPs[((pCertCA->rgCertTypeInfo)[dwCertTypeIndex].rgdwCSP)[dwCSPIndex]] = TRUE;
  3195. }
  3196. }
  3197. }
  3198. }
  3199. }
  3200. }
  3201. }
  3202. m_dwCSPIndex = 0;
  3203. m_fIsInitialized = TRUE;
  3204. }
  3205. HRESULT IEnumCSP::HasNext(BOOL *pfResult)
  3206. {
  3207. if (FALSE == m_fIsInitialized)
  3208. return m_hr;
  3209. for (; m_dwCSPIndex < m_cCSPs; m_dwCSPIndex++)
  3210. {
  3211. if (m_pfCSPs[m_dwCSPIndex])
  3212. {
  3213. *pfResult = TRUE;
  3214. return S_OK;
  3215. }
  3216. }
  3217. *pfResult = FALSE;
  3218. return S_OK;
  3219. }
  3220. HRESULT IEnumCSP::Next(DWORD *pdwCSP)
  3221. {
  3222. if (FALSE == m_fIsInitialized)
  3223. return m_hr;
  3224. if (NULL == pdwCSP)
  3225. return E_INVALIDARG;
  3226. for (; m_dwCSPIndex < m_cCSPs; m_dwCSPIndex++)
  3227. {
  3228. if (m_pfCSPs[m_dwCSPIndex])
  3229. {
  3230. *pdwCSP = m_dwCSPIndex++;
  3231. return S_OK;
  3232. }
  3233. }
  3234. return HRESULT_FROM_WIN32(CRYPT_E_NOT_FOUND);
  3235. }
  3236. HRESULT IEnumCA::HasNext(BOOL *pfResult)
  3237. {
  3238. BOOL fDontKnowCA;
  3239. if (NULL == pfResult)
  3240. return E_INVALIDARG;
  3241. // We don't know the CA if it wasn't supplied through the API,
  3242. // and if the user did not specify it through advanced options.
  3243. fDontKnowCA = FALSE == m_pCertWizardInfo->fCAInput;
  3244. fDontKnowCA &= FALSE == m_pCertWizardInfo->fUIAdv;
  3245. if (FALSE == fDontKnowCA)
  3246. {
  3247. *pfResult = m_dwCAIndex == 1;
  3248. return S_OK;
  3249. }
  3250. else
  3251. {
  3252. for (; m_dwCAIndex < m_pCertWizardInfo->pCertCAInfo->dwCA; m_dwCAIndex++)
  3253. {
  3254. if (CASupportSpecifiedCertType(&(m_pCertWizardInfo->pCertCAInfo->rgCA[m_dwCAIndex])))
  3255. {
  3256. *pfResult = TRUE;
  3257. return S_OK;
  3258. }
  3259. }
  3260. }
  3261. *pfResult = FALSE;
  3262. return S_OK;
  3263. }
  3264. HRESULT IEnumCA::Next(PCRYPTUI_WIZ_CERT_CA pCertCA)
  3265. {
  3266. BOOL fDontKnowCA;
  3267. if (NULL == pCertCA)
  3268. return E_INVALIDARG;
  3269. // We don't know the CA if it wasn't supplied through the API,
  3270. // and if the user did not specify it through advanced options.
  3271. fDontKnowCA = FALSE == m_pCertWizardInfo->fCAInput;
  3272. fDontKnowCA &= FALSE == m_pCertWizardInfo->fUIAdv;
  3273. if (FALSE == fDontKnowCA)
  3274. {
  3275. if (1 == m_dwCAIndex)
  3276. {
  3277. CRYPTUI_WIZ_CERT_CA CertCA;
  3278. m_dwCAIndex++;
  3279. CertCA.pwszCALocation = m_pCertWizardInfo->pwszCALocation;
  3280. CertCA.pwszCAName = m_pCertWizardInfo->pwszCAName;
  3281. *pCertCA = CertCA;
  3282. return S_OK;
  3283. }
  3284. }
  3285. else
  3286. {
  3287. for (; m_dwCAIndex < m_pCertWizardInfo->pCertCAInfo->dwCA; m_dwCAIndex++)
  3288. {
  3289. if (CASupportSpecifiedCertType(&(m_pCertWizardInfo->pCertCAInfo->rgCA[m_dwCAIndex])))
  3290. {
  3291. *pCertCA = m_pCertWizardInfo->pCertCAInfo->rgCA[m_dwCAIndex++];
  3292. return S_OK;
  3293. }
  3294. }
  3295. }
  3296. return HRESULT_FROM_WIN32(CRYPT_E_NOT_FOUND);
  3297. }