Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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