Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1074 lines
32 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1997-2001.
  5. //
  6. // File: locate.cpp
  7. //
  8. // Contents: Implementation of Add EFS Agent Wizard Location Page
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include "AddSheet.h"
  13. #include "Locate.h"
  14. #pragma warning(push, 3)
  15. #include <initguid.h>
  16. #include <cmnquery.h>
  17. #include <dsquery.h>
  18. #include <winldap.h>
  19. #include <dsgetdc.h>
  20. #include <ntdsapi.h>
  21. #include <efsstruc.h>
  22. #pragma warning(pop)
  23. USE_HANDLE_MACROS("CERTMGR(locate.cpp)")
  24. #ifdef _DEBUG
  25. #ifndef ALPHA
  26. #define new DEBUG_NEW
  27. #endif
  28. #undef THIS_FILE
  29. static char THIS_FILE[] = __FILE__;
  30. #endif
  31. #define szCertAttr _T ("?userCertificate")
  32. /////////////////////////////////////////////////////////////////////////////
  33. // CAddEFSWizLocate property page
  34. IMPLEMENT_DYNCREATE(CAddEFSWizLocate, CWizard97PropertyPage)
  35. CAddEFSWizLocate::CAddEFSWizLocate() : CWizard97PropertyPage(CAddEFSWizLocate::IDD)
  36. {
  37. //{{AFX_DATA_INIT(CAddEFSWizLocate)
  38. // NOTE: the ClassWizard will add member initialization here
  39. //}}AFX_DATA_INIT
  40. VERIFY (m_szHeaderTitle.LoadString (IDS_EFS_LOCATE_TITLE));
  41. VERIFY (m_szHeaderSubTitle.LoadString (IDS_EFS_LOCATE_SUBTITLE));
  42. InitWizard97 (FALSE);
  43. }
  44. CAddEFSWizLocate::~CAddEFSWizLocate()
  45. {
  46. }
  47. void CAddEFSWizLocate::DoDataExchange(CDataExchange* pDX)
  48. {
  49. CWizard97PropertyPage::DoDataExchange(pDX);
  50. //{{AFX_DATA_MAP(CAddEFSWizLocate)
  51. DDX_Control (pDX, IDC_ADDLIST, m_UserAddList);
  52. //}}AFX_DATA_MAP
  53. InitWizard97 (FALSE);
  54. }
  55. BEGIN_MESSAGE_MAP(CAddEFSWizLocate, CWizard97PropertyPage)
  56. //{{AFX_MSG_MAP(CAddEFSWizLocate)
  57. ON_BN_CLICKED (IDC_BROWSE_DIR, OnBrowseDir)
  58. ON_BN_CLICKED (IDC_BROWSE_FILE, OnBrowseFile)
  59. //}}AFX_MSG_MAP
  60. END_MESSAGE_MAP()
  61. /////////////////////////////////////////////////////////////////////////////
  62. // CAddEFSWizLocate message handlers
  63. BOOL CAddEFSWizLocate::OnSetActive ()
  64. {
  65. BOOL bResult = CWizard97PropertyPage::OnSetActive ();
  66. if ( bResult )
  67. GetParent ()->PostMessage (PSM_SETWIZBUTTONS, 0, PSWIZB_NEXT | PSWIZB_BACK);
  68. return bResult;
  69. }
  70. void CAddEFSWizLocate::OnBrowseDir ()
  71. {
  72. FindUserFromDir ();
  73. }
  74. void CAddEFSWizLocate::OnBrowseFile ()
  75. {
  76. CString szFileFilter;
  77. VERIFY (szFileFilter.LoadString (IDS_CERTFILEFILTER));
  78. // replace "|" with 0;
  79. const size_t nFilterLen = wcslen (szFileFilter) + 1;
  80. PWSTR pszFileFilter = new WCHAR [nFilterLen];
  81. if ( pszFileFilter )
  82. {
  83. wcscpy (pszFileFilter, szFileFilter);
  84. for (int nIndex = 0; nIndex < nFilterLen; nIndex++)
  85. {
  86. if ( L'|' == pszFileFilter[nIndex] )
  87. pszFileFilter[nIndex] = 0;
  88. }
  89. WCHAR szFile[MAX_PATH];
  90. ::ZeroMemory (szFile, MAX_PATH * sizeof (WCHAR));
  91. OPENFILENAME ofn;
  92. ::ZeroMemory (&ofn, sizeof (OPENFILENAME));
  93. ofn.lStructSize = sizeof (OPENFILENAME);
  94. ofn.hwndOwner = m_hWnd;
  95. ofn.lpstrFilter = (PCWSTR) pszFileFilter;
  96. ofn.lpstrFile = szFile;
  97. ofn.nMaxFile = MAX_PATH;
  98. ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  99. BOOL bResult = ::GetOpenFileName (&ofn);
  100. if ( bResult )
  101. {
  102. CString szFileName = ofn.lpstrFile;
  103. //
  104. // Open cert store from the file
  105. //
  106. HCERTSTORE hCertStore = NULL;
  107. PVOID FileNameVoidP = (PVOID) (LPCWSTR)szFileName;
  108. PCCERT_CONTEXT pCertContext = NULL;
  109. DWORD dwEncodingType = 0;
  110. DWORD dwContentType = 0;
  111. DWORD dwFormatType = 0;
  112. BOOL bReturn = ::CryptQueryObject (
  113. CERT_QUERY_OBJECT_FILE,
  114. FileNameVoidP,
  115. CERT_QUERY_CONTENT_FLAG_ALL,
  116. CERT_QUERY_FORMAT_FLAG_ALL,
  117. 0,
  118. &dwEncodingType,
  119. &dwContentType,
  120. &dwFormatType,
  121. &hCertStore,
  122. NULL,
  123. (const void **)&pCertContext);
  124. ASSERT (bReturn);
  125. if ( bReturn )
  126. {
  127. //
  128. // Success. See what we get back. A store or a cert.
  129. //
  130. if ( (dwContentType == CERT_QUERY_CONTENT_SERIALIZED_STORE)
  131. && hCertStore)
  132. {
  133. CERT_ENHKEY_USAGE enhKeyUsage;
  134. ::ZeroMemory (&enhKeyUsage, sizeof (CERT_ENHKEY_USAGE));
  135. enhKeyUsage.cUsageIdentifier = 1;
  136. enhKeyUsage.rgpszUsageIdentifier[0] = szOID_EFS_RECOVERY;
  137. //
  138. // We get the certificate store
  139. //
  140. pCertContext = ::CertFindCertificateInStore (
  141. hCertStore,
  142. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  143. 0,
  144. CERT_FIND_ENHKEY_USAGE,
  145. &enhKeyUsage,
  146. NULL);
  147. if ( !pCertContext )
  148. {
  149. CString caption;
  150. CString text;
  151. CThemeContextActivator activator;
  152. VERIFY (text.LoadString (IDS_EFS_FILE_HAS_NO_EFS_USAGE));
  153. VERIFY (caption.LoadString (IDS_ADD_RECOVERY_AGENTY));
  154. MessageBox (text, caption, MB_OK);
  155. return;
  156. }
  157. if ( hCertStore )
  158. ::CertCloseStore (hCertStore, 0);
  159. }
  160. else if ( (dwContentType != CERT_QUERY_CONTENT_CERT) || !pCertContext )
  161. {
  162. //
  163. // Neither a valid cert file nor a store file we like.
  164. //
  165. if ( hCertStore )
  166. ::CertCloseStore (hCertStore, 0);
  167. if ( pCertContext )
  168. ::CertFreeCertificateContext (pCertContext);
  169. CString ErrMsg;
  170. CThemeContextActivator activator;
  171. VERIFY (ErrMsg.LoadString (IDS_CERTFILEFORMATERR));
  172. MessageBox (ErrMsg);
  173. return;
  174. }
  175. if ( hCertStore )
  176. {
  177. ::CertCloseStore (hCertStore, 0);
  178. hCertStore = NULL;
  179. }
  180. //
  181. // Add the user
  182. //
  183. if ( CertHasEFSKeyUsage (pCertContext) )
  184. {
  185. //
  186. // We got the cert. Add it to the structure. We need get the subject name first.
  187. //
  188. LPWSTR pszUserCertName = 0;
  189. INT_PTR iRetCode = GetCertNameFromCertContext (
  190. pCertContext,
  191. &pszUserCertName);
  192. if ( ERROR_SUCCESS != iRetCode )
  193. {
  194. if ( pCertContext )
  195. {
  196. ::CertFreeCertificateContext (pCertContext);
  197. }
  198. return;
  199. }
  200. CAddEFSWizSheet* pAddSheet = reinterpret_cast <CAddEFSWizSheet*> (m_pWiz);
  201. ASSERT (pAddSheet);
  202. if ( !pAddSheet )
  203. return;
  204. EFS_CERTIFICATE_BLOB certBlob;
  205. certBlob.cbData = pCertContext->cbCertEncoded;
  206. certBlob.pbData = pCertContext->pbCertEncoded;
  207. certBlob.dwCertEncodingType = pCertContext->dwCertEncodingType;
  208. iRetCode = pAddSheet->Add (
  209. NULL,
  210. pszUserCertName,
  211. (PVOID)&certBlob,
  212. NULL,
  213. USERADDED,
  214. pCertContext);
  215. if ( (ERROR_SUCCESS != iRetCode) && (CRYPT_E_EXISTS != iRetCode) )
  216. {
  217. //
  218. // Error in adding the user
  219. //
  220. ::CertFreeCertificateContext (pCertContext);
  221. pCertContext = NULL;
  222. }
  223. else
  224. {
  225. //
  226. // Add the user to the list box.
  227. //
  228. if ( iRetCode == ERROR_SUCCESS )
  229. {
  230. LV_ITEM fillItem;
  231. CString userUnknown;
  232. try {
  233. if (!userUnknown.LoadString (IDS_UNKNOWNUSER))
  234. {
  235. ASSERT (0);
  236. userUnknown.Empty ();
  237. }
  238. }
  239. catch (...)
  240. {
  241. userUnknown.Empty ();
  242. }
  243. fillItem.mask = LVIF_TEXT;
  244. fillItem.iItem = 0;
  245. fillItem.iSubItem = 0;
  246. if ( userUnknown.IsEmpty () )
  247. {
  248. fillItem.pszText = _T ("");
  249. }
  250. else
  251. {
  252. fillItem.pszText = userUnknown.GetBuffer (userUnknown.GetLength () + 1);
  253. }
  254. fillItem.iItem = m_UserAddList.InsertItem (&fillItem);
  255. if ( !userUnknown.IsEmpty () )
  256. {
  257. userUnknown.ReleaseBuffer ();
  258. }
  259. if ( fillItem.iItem != -1 )
  260. {
  261. fillItem.pszText = pszUserCertName;
  262. fillItem.iSubItem = 1;
  263. m_UserAddList.SetItem (&fillItem);
  264. }
  265. else
  266. {
  267. pAddSheet->Remove (NULL, pszUserCertName);
  268. }
  269. pszUserCertName = NULL;
  270. }
  271. else
  272. {
  273. //
  274. // Already deleted inside the Add.
  275. //
  276. pszUserCertName = NULL;
  277. }
  278. }
  279. if (pszUserCertName)
  280. {
  281. delete [] pszUserCertName;
  282. pszUserCertName = NULL;
  283. }
  284. }
  285. else
  286. {
  287. CString caption;
  288. CString text;
  289. CThemeContextActivator activator;
  290. VERIFY (text.LoadString (IDS_EFS_FILE_HAS_NO_EFS_USAGE));
  291. VERIFY (caption.LoadString (IDS_ADD_RECOVERY_AGENTY));
  292. MessageBox (text, caption, MB_OK);
  293. }
  294. }
  295. else
  296. {
  297. //
  298. // Fail. Get the error code.
  299. //
  300. DWORD dwErr = GetLastError ();
  301. CString text;
  302. CString caption;
  303. CThemeContextActivator activator;
  304. VERIFY (caption.LoadString (IDS_ADD_RECOVERY_AGENTY));
  305. text.FormatMessage (IDS_CERTFILEOPENERR,
  306. szFileName, GetSystemMessage (dwErr));
  307. MessageBox (text, caption);
  308. }
  309. }
  310. delete [] pszFileFilter;
  311. }
  312. }
  313. HRESULT CAddEFSWizLocate::FindUserFromDir ()
  314. {
  315. HRESULT hr = S_OK;
  316. LPWSTR pszListUserName = NULL;
  317. LPWSTR pszUserCertName = NULL;
  318. FORMATETC fmte = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  319. STGMEDIUM medium = { TYMED_NULL, NULL, NULL };
  320. ICommonQuery* pCommonQuery = NULL;
  321. OPENQUERYWINDOW oqw;
  322. DSQUERYINITPARAMS dqip;
  323. bool bCheckDS = false;
  324. HANDLE hDS = NULL;
  325. CAddEFSWizSheet* pAddSheet = reinterpret_cast <CAddEFSWizSheet *> (m_pWiz);
  326. ASSERT (pAddSheet);
  327. if ( !pAddSheet )
  328. return E_POINTER;
  329. hr = ::CoInitialize (NULL);
  330. if ( FAILED (hr) )
  331. return hr;
  332. hr = ::CoCreateInstance (CLSID_CommonQuery, NULL, CLSCTX_INPROC_SERVER,
  333. IID_ICommonQuery, (LPVOID*)&pCommonQuery);
  334. ASSERT (SUCCEEDED (hr));
  335. if ( SUCCEEDED (hr) )
  336. {
  337. dqip.cbStruct = sizeof (dqip);
  338. dqip.dwFlags = DSQPF_SHOWHIDDENOBJECTS |
  339. DSQPF_ENABLEADMINFEATURES;
  340. dqip.pDefaultScope = NULL; //szScopeLocn
  341. oqw.cbStruct = sizeof (oqw);
  342. oqw.dwFlags = OQWF_OKCANCEL |
  343. // OQWF_SINGLESELECT |
  344. OQWF_DEFAULTFORM |
  345. OQWF_REMOVEFORMS ;
  346. oqw.clsidHandler = CLSID_DsQuery;
  347. oqw.pHandlerParameters = &dqip;
  348. oqw.clsidDefaultForm = CLSID_DsFindPeople;
  349. IDataObject* pDataObject = NULL;
  350. hr = pCommonQuery->OpenQueryWindow (m_hWnd, &oqw, &pDataObject);
  351. ASSERT (SUCCEEDED (hr));
  352. if ( SUCCEEDED (hr) && pDataObject )
  353. {
  354. // Fill the list view
  355. fmte.cfFormat = pAddSheet->GetDataFormat ();
  356. hr = pDataObject->GetData (&fmte, &medium);
  357. // A return of DV_E_FORMATETC (0x80040064) here can mean that
  358. // nothing was selected in the query window
  359. if ( SUCCEEDED (hr) )
  360. {
  361. LPDSOBJECTNAMES pDsObjects = (LPDSOBJECTNAMES)medium.hGlobal;
  362. hr = DsBind (NULL, NULL, &hDS);
  363. if ( SUCCEEDED (hr) )
  364. {
  365. //
  366. // We are going to use the DS to crack the names
  367. //
  368. bCheckDS = true;
  369. }
  370. if ( pDsObjects->cItems )
  371. {
  372. // Verify that each user has a cert that allows the necessary
  373. // action (efs decryption)
  374. for ( UINT i = 0 ; i < pDsObjects->cItems ; i++ )
  375. {
  376. LPWSTR pszTemp = (LPWSTR)
  377. ( ( (LPBYTE)pDsObjects)+pDsObjects->aObjects[i].offsetName);
  378. DS_NAME_RESULT* pUserName = NULL;
  379. PSID userSID = NULL;
  380. DWORD cbSid = 0;
  381. LPWSTR pszReferencedDomainName = NULL;
  382. DWORD cbReferencedDomainName = 0;
  383. SID_NAME_USE SidUse;
  384. //
  385. // Get rid of the head :\\
  386. //
  387. LPWSTR pszSearch = _tcschr (pszTemp, _T (':'));
  388. if (pszSearch && (pszSearch[1] == _T ('/')) && (pszSearch[2] == _T ('/')))
  389. {
  390. pszTemp = pszSearch + 3;
  391. }
  392. if ( bCheckDS )
  393. {
  394. hr = DsCrackNames (
  395. hDS,
  396. DS_NAME_NO_FLAGS,
  397. DS_FQDN_1779_NAME,
  398. DS_NT4_ACCOUNT_NAME,
  399. 1,
  400. &pszTemp,
  401. &pUserName
  402. );
  403. if ( SUCCEEDED (hr) && pUserName )
  404. {
  405. if ( ( pUserName->cItems > 0 ) && (DS_NAME_NO_ERROR == pUserName->rItems[0].status))
  406. {
  407. //
  408. // Save the NT4 name first, in case we cannot get the principle name
  409. //
  410. pszListUserName = new WCHAR[_tcslen (pUserName->rItems[0].pName) + 1];
  411. if (pszListUserName)
  412. {
  413. _tcscpy (pszListUserName, pUserName->rItems[0].pName);
  414. }
  415. else
  416. {
  417. hr = E_OUTOFMEMORY;
  418. break;
  419. }
  420. BOOL bReturn = ::LookupAccountName (
  421. NULL,
  422. pUserName->rItems[0].pName,
  423. userSID,
  424. &cbSid,
  425. pszReferencedDomainName,
  426. &cbReferencedDomainName,
  427. &SidUse
  428. );
  429. hr = GetLastError ();
  430. if ( !bReturn && (HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER) == hr) )
  431. {
  432. //
  433. // We are expecting this error
  434. //
  435. userSID = new BYTE[cbSid];
  436. pszReferencedDomainName = new WCHAR[cbReferencedDomainName];
  437. if ( userSID && pszReferencedDomainName )
  438. {
  439. bReturn = ::LookupAccountName (
  440. NULL,
  441. pUserName->rItems[0].pName,
  442. userSID,
  443. &cbSid,
  444. pszReferencedDomainName,
  445. &cbReferencedDomainName,
  446. &SidUse);
  447. delete [] pszReferencedDomainName;
  448. pszReferencedDomainName = NULL;
  449. if (!bReturn)
  450. {
  451. //
  452. // Get SID failed. We can live with it.
  453. //
  454. userSID = NULL;
  455. }
  456. }
  457. else
  458. {
  459. if (userSID)
  460. {
  461. delete [] userSID;
  462. userSID = NULL;
  463. }
  464. if (pszReferencedDomainName)
  465. {
  466. delete [] pszReferencedDomainName;
  467. pszReferencedDomainName = NULL;
  468. }
  469. hr = E_OUTOFMEMORY;
  470. break;
  471. }
  472. }
  473. else
  474. {
  475. ASSERT (!bReturn);
  476. userSID = NULL;
  477. }
  478. }
  479. }
  480. else
  481. {
  482. //
  483. // Cannot get the NT4 name. Set the SID to NULL. Go on.
  484. //
  485. userSID = NULL;
  486. }
  487. if (pUserName)
  488. {
  489. DsFreeNameResult (pUserName);
  490. pUserName = NULL;
  491. }
  492. hr = DsCrackNames (
  493. hDS,
  494. DS_NAME_NO_FLAGS,
  495. DS_FQDN_1779_NAME,
  496. DS_USER_PRINCIPAL_NAME,
  497. 1,
  498. &pszTemp,
  499. &pUserName);
  500. ASSERT (SUCCEEDED (hr));
  501. if ( (HRESULT_FROM_WIN32 (ERROR_SUCCESS) == hr) &&
  502. ( pUserName->cItems > 0 ) &&
  503. (DS_NAME_NO_ERROR == pUserName->rItems[0].status) )
  504. {
  505. //
  506. // We got the principal name
  507. //
  508. LPWSTR pszTmpNameStr =
  509. new WCHAR[_tcslen (pUserName->rItems[0].pName) + 1];
  510. if ( pszTmpNameStr )
  511. {
  512. _tcscpy (pszTmpNameStr, pUserName->rItems[0].pName);
  513. delete [] pszListUserName;
  514. pszListUserName = pszTmpNameStr;
  515. }
  516. else
  517. {
  518. hr = ERROR_OUTOFMEMORY;
  519. }
  520. }
  521. }
  522. if ( (HRESULT_FROM_WIN32 (ERROR_OUTOFMEMORY) != hr) && ( !pszListUserName))
  523. {
  524. //
  525. // Use the LDAP name
  526. //
  527. pszListUserName = new WCHAR[_tcslen (pszTemp)+1];
  528. if ( pszListUserName )
  529. {
  530. _tcscpy (pszListUserName, pszTemp);
  531. }
  532. else
  533. {
  534. hr = ERROR_OUTOFMEMORY;
  535. }
  536. }
  537. if (pUserName)
  538. {
  539. DsFreeNameResult (pUserName);
  540. pUserName = NULL;
  541. }
  542. if ( HRESULT_FROM_WIN32 (ERROR_OUTOFMEMORY) != hr )
  543. {
  544. //
  545. // Now is the time to get the certificate
  546. //
  547. PCWSTR pszHeader1 = L"LDAP://";
  548. PCWSTR pszHeader2 = L"LDAP:///";
  549. PWSTR pszLdapUrl = new WCHAR[wcslen (pszTemp) +
  550. wcslen (pszHeader2) +
  551. wcslen (szCertAttr) + 2];
  552. if ( pszLdapUrl )
  553. {
  554. PCWSTR szCN = L"CN=";
  555. //
  556. // This is really not necessary. MS should make the name convention consistant.
  557. //
  558. if ( !wcsncmp (pszTemp, szCN, wcslen (szCN)) )
  559. {
  560. // pszTemp is object name without server
  561. wcscpy (pszLdapUrl, pszHeader2);
  562. }
  563. else
  564. wcscpy (pszLdapUrl, pszHeader1);
  565. wcscat (pszLdapUrl, pszTemp);
  566. wcscat (pszLdapUrl, szCertAttr);
  567. hr = ERROR_SUCCESS;
  568. HCERTSTORE hDSCertStore = ::CertOpenStore (
  569. sz_CERT_STORE_PROV_LDAP,
  570. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  571. NULL,
  572. CERT_STORE_MAXIMUM_ALLOWED_FLAG,
  573. (void*) pszLdapUrl);
  574. //
  575. // In case delete change the result of GetLastError ()
  576. //
  577. hr = GetLastError ();
  578. if (hDSCertStore)
  579. {
  580. CERT_ENHKEY_USAGE enhKeyUsage;
  581. ::ZeroMemory (&enhKeyUsage, sizeof (CERT_ENHKEY_USAGE));
  582. enhKeyUsage.cUsageIdentifier = 1;
  583. enhKeyUsage.rgpszUsageIdentifier = new LPSTR[1];
  584. if ( enhKeyUsage.rgpszUsageIdentifier )
  585. {
  586. enhKeyUsage.rgpszUsageIdentifier[0] = szOID_EFS_RECOVERY;
  587. //
  588. // We get the certificate store
  589. //
  590. PCCERT_CONTEXT pCertContext =
  591. ::CertFindCertificateInStore (
  592. hDSCertStore,
  593. X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
  594. 0,
  595. CERT_FIND_ENHKEY_USAGE,
  596. &enhKeyUsage,
  597. NULL);
  598. if ( pCertContext )
  599. {
  600. if ( CertHasEFSKeyUsage (pCertContext) )
  601. {
  602. //
  603. // We got the certificate. Add it to the lists.
  604. // Get the certificate display name first
  605. //
  606. hr = GetCertNameFromCertContext (
  607. pCertContext,
  608. &pszUserCertName);
  609. //
  610. // Add the user
  611. //
  612. EFS_CERTIFICATE_BLOB certBlob;
  613. certBlob.cbData = pCertContext->cbCertEncoded;
  614. certBlob.pbData = pCertContext->pbCertEncoded;
  615. certBlob.dwCertEncodingType = pCertContext->dwCertEncodingType;
  616. hr = pAddSheet->Add (
  617. pszListUserName,
  618. pszUserCertName,
  619. (PVOID)&certBlob,
  620. userSID,
  621. USERADDED,
  622. pCertContext);
  623. if ( FAILED (hr) && (HRESULT_FROM_WIN32 (CRYPT_E_EXISTS) != hr) )
  624. {
  625. //
  626. // Error in adding the user
  627. //
  628. ::CertFreeCertificateContext (pCertContext);
  629. pCertContext = NULL;
  630. }
  631. else
  632. {
  633. //
  634. // Add the user to the list box.
  635. //
  636. if ( SUCCEEDED (hr) )
  637. {
  638. LV_ITEM fillItem;
  639. fillItem.mask = LVIF_TEXT;
  640. fillItem.iItem = 0;
  641. fillItem.iSubItem = 0;
  642. fillItem.pszText = pszListUserName;
  643. fillItem.iItem = m_UserAddList.InsertItem (&fillItem);
  644. if ( fillItem.iItem == -1 )
  645. {
  646. pAddSheet->Remove ( pszListUserName, pszUserCertName);
  647. }
  648. else
  649. {
  650. fillItem.pszText = pszUserCertName;
  651. fillItem.iSubItem = 1;
  652. m_UserAddList.SetItem (&fillItem);
  653. }
  654. }
  655. //
  656. //Either deleted (CRYPT_E_EXISTS) or should not be freed (ERROR_SUCCESS)
  657. //
  658. pszListUserName = NULL;
  659. pszUserCertName = NULL;
  660. }
  661. }
  662. else
  663. {
  664. CString caption;
  665. CString text;
  666. CThemeContextActivator activator;
  667. VERIFY (text.LoadString (IDS_USER_OBJECT_HAS_NO_CERTS));
  668. VERIFY (caption.LoadString (IDS_ADD_RECOVERY_AGENTY));
  669. MessageBox (text, caption, MB_OK);
  670. }
  671. }
  672. else
  673. {
  674. CString text;
  675. CString caption;
  676. CThemeContextActivator activator;
  677. VERIFY (text.LoadString (IDS_USER_OBJECT_HAS_NO_CERTS));
  678. VERIFY (caption.LoadString (IDS_ADD_RECOVERY_AGENTY));
  679. MessageBox (text, caption, MB_OK);
  680. }
  681. delete [] enhKeyUsage.rgpszUsageIdentifier;
  682. }
  683. else
  684. {
  685. hr = E_OUTOFMEMORY;
  686. }
  687. delete [] userSID;
  688. userSID = NULL;
  689. if (pszListUserName)
  690. {
  691. delete [] pszListUserName;
  692. pszListUserName = NULL;
  693. }
  694. if (pszUserCertName)
  695. {
  696. delete [] pszUserCertName;
  697. pszUserCertName = NULL;
  698. }
  699. if ( hDSCertStore )
  700. {
  701. CertCloseStore (hDSCertStore, 0);
  702. hDSCertStore = NULL;
  703. }
  704. }
  705. else
  706. {
  707. //
  708. // Failed to open the cert store
  709. //
  710. delete [] userSID;
  711. userSID = NULL;
  712. if (pszListUserName)
  713. {
  714. delete [] pszListUserName;
  715. pszListUserName = NULL;
  716. }
  717. if (pszUserCertName)
  718. {
  719. delete [] pszUserCertName;
  720. pszUserCertName = NULL;
  721. }
  722. CString caption;
  723. CString text;
  724. CThemeContextActivator activator;
  725. VERIFY (caption.LoadString (IDS_CERTIFICATE_MANAGER));
  726. text.FormatMessage (IDS_UNABLE_TO_OPEN_EFS_STORE, pszLdapUrl,
  727. GetSystemMessage (hr));
  728. ::MessageBox (NULL, text, caption, MB_OK);
  729. }
  730. delete [] pszLdapUrl;
  731. pszLdapUrl = NULL;
  732. }
  733. else
  734. {
  735. hr = ERROR_OUTOFMEMORY;
  736. }
  737. }
  738. if ( HRESULT_FROM_WIN32 (ERROR_OUTOFMEMORY) == hr )
  739. {
  740. //
  741. // Free the memory. Delete works for NULL. No check is needed.
  742. //
  743. delete [] userSID;
  744. userSID = NULL;
  745. delete [] pszListUserName;
  746. pszListUserName = NULL;
  747. delete [] pszUserCertName;
  748. pszUserCertName = NULL;
  749. }
  750. }//For
  751. }
  752. if (bCheckDS)
  753. {
  754. DsUnBindW ( &hDS);
  755. }
  756. ReleaseStgMedium (&medium);
  757. }
  758. pDataObject->Release ();
  759. }
  760. pCommonQuery->Release ();
  761. }
  762. return hr;
  763. }
  764. DWORD CAddEFSWizLocate::GetCertNameFromCertContext (
  765. PCCERT_CONTEXT pCertContext,
  766. LPWSTR * pszUserCertName)
  767. //////////////////////////////////////////////////////////////////////
  768. // Routine Description:
  769. // Get the user name from the certificate
  770. // Arguments:
  771. // pCertContext -- Cert Context
  772. // pszUserCertName -- User name
  773. // ( Caller is responsible to delete this memory using delete [] )
  774. // Return Value:
  775. // ERROR_SUCCESS if succeed.
  776. // If No Name if found. "USER_UNKNOWN is returned".
  777. //
  778. //////////////////////////////////////////////////////////////////////
  779. {
  780. if ( !pszUserCertName )
  781. {
  782. return ERROR_INVALID_PARAMETER ;
  783. }
  784. *pszUserCertName = NULL;
  785. CString szSubjectName = ::GetNameString (pCertContext, 0);
  786. if ( !szSubjectName.IsEmpty () )
  787. {
  788. *pszUserCertName = new WCHAR[wcslen (szSubjectName) + 1];
  789. if ( *pszUserCertName )
  790. {
  791. wcscpy (*pszUserCertName, szSubjectName);
  792. }
  793. else
  794. return ERROR_NOT_ENOUGH_MEMORY;
  795. }
  796. else
  797. return ERROR_FILE_NOT_FOUND;
  798. /*
  799. DWORD dwNameLength = CertGetNameString (
  800. pCertContext,
  801. CERT_NAME_EMAIL_TYPE,
  802. 0,
  803. NULL,
  804. NULL,
  805. 0
  806. );
  807. DWORD dwUserNameBufLen = 0;
  808. if ( dwNameLength > 1)
  809. {
  810. //
  811. // The E-Mail name exist. Go get the email name.
  812. //
  813. *pszUserCertName = new WCHAR[dwNameLength];
  814. if ( !(*pszUserCertName) )
  815. {
  816. return ERROR_NOT_ENOUGH_MEMORY;
  817. }
  818. dwUserNameBufLen = dwNameLength;
  819. dwNameLength = CertGetNameString (
  820. pCertContext,
  821. CERT_NAME_EMAIL_TYPE,
  822. 0,
  823. NULL,
  824. *pszUserCertName,
  825. dwUserNameBufLen
  826. );
  827. ASSERT (dwNameLength == dwUserNameBufLen);
  828. }
  829. else
  830. {
  831. //
  832. // Get the subject name in the X500 format
  833. //
  834. DWORD dwStrType = CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG;
  835. dwNameLength = CertGetNameString (
  836. pCertContext,
  837. CERT_NAME_RDN_TYPE,
  838. 0,
  839. &dwStrType,
  840. NULL,
  841. 0
  842. );
  843. if ( dwNameLength > 1 )
  844. {
  845. //
  846. // Name exists. Go get it.
  847. //
  848. *pszUserCertName = new WCHAR[dwNameLength];
  849. if ( !(*pszUserCertName) )
  850. {
  851. return ERROR_NOT_ENOUGH_MEMORY;
  852. }
  853. dwUserNameBufLen = dwNameLength;
  854. dwNameLength = CertGetNameString (
  855. pCertContext,
  856. CERT_NAME_RDN_TYPE,
  857. 0,
  858. &dwStrType,
  859. *pszUserCertName,
  860. dwUserNameBufLen
  861. );
  862. ASSERT (dwNameLength == dwUserNameBufLen);
  863. }
  864. else
  865. {
  866. try {
  867. CString unknownCertName;
  868. VERIFY (unknownCertName.LoadString (IDS_NOCERTNAME));
  869. dwUserNameBufLen = unknownCertName.GetLength ();
  870. *pszUserCertName = new WCHAR[dwUserNameBufLen + 1];
  871. _tcscpy (*pszUserCertName, unknownCertName);
  872. }
  873. catch (...){
  874. return ERROR_NOT_ENOUGH_MEMORY;
  875. }
  876. }
  877. }
  878. */
  879. return ERROR_SUCCESS;
  880. }
  881. BOOL CAddEFSWizLocate::OnInitDialog ()
  882. {
  883. CWizard97PropertyPage::OnInitDialog ();
  884. CString userNameTitle;
  885. CString userDNTitle;
  886. RECT rcList;
  887. try {
  888. m_UserAddList.GetClientRect (&rcList);
  889. DWORD dwColWidth = (rcList.right - rcList.left)/2;
  890. VERIFY (userNameTitle.LoadString (IDS_USERCOLTITLE));
  891. VERIFY (userDNTitle.LoadString (IDS_DNCOLTITLE));
  892. m_UserAddList.InsertColumn (0, userNameTitle, LVCFMT_LEFT, dwColWidth);
  893. m_UserAddList.InsertColumn (1, userDNTitle, LVCFMT_LEFT, dwColWidth);
  894. }
  895. catch (...){
  896. }
  897. CAddEFSWizSheet* pAddSheet = reinterpret_cast <CAddEFSWizSheet*> (m_pWiz);
  898. ASSERT (pAddSheet);
  899. if ( pAddSheet )
  900. {
  901. if ( pAddSheet->m_bMachineIsStandAlone )
  902. GetDlgItem (IDC_BROWSE_DIR)->EnableWindow (FALSE);
  903. }
  904. return TRUE; // return TRUE unless you set the focus to a control
  905. // EXCEPTION: OCX Property Pages should return FALSE
  906. }
  907. LRESULT CAddEFSWizLocate::OnWizardBack ()
  908. {
  909. CAddEFSWizSheet *pAddSheet = reinterpret_cast <CAddEFSWizSheet *> (m_pWiz);
  910. ASSERT (pAddSheet);
  911. if ( !pAddSheet )
  912. return -1;
  913. pAddSheet->ClearUserList ();
  914. m_UserAddList.DeleteAllItems ();
  915. return CWizard97PropertyPage::OnWizardBack ();
  916. }
  917. LRESULT CAddEFSWizLocate::OnWizardNext()
  918. {
  919. if ( m_UserAddList.GetItemCount () <= 0 )
  920. {
  921. CString caption;
  922. CString text;
  923. CThemeContextActivator activator;
  924. VERIFY (caption.LoadString (IDS_ADDTITLE));
  925. VERIFY (text.LoadString (IDS_MUST_ADD_RECOVERY_AGENT));
  926. MessageBox (text, caption, MB_OK);
  927. return -1;
  928. }
  929. return CWizard97PropertyPage::OnWizardNext();
  930. }