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.

1632 lines
50 KiB

  1. // KRDoc.cpp : implementation of the CKeyRingDoc class
  2. //
  3. #include "stdafx.h"
  4. #include "keyobjs.h"
  5. #include "intrlkey.h"
  6. #include <shlobj.h>
  7. #include "machine.h"
  8. #include "KeyRing.h"
  9. #include "KRDoc.h"
  10. #include "KRView.h"
  11. #include "ConctDlg.h"
  12. #include "InfoDlg.h"
  13. #include "passdlg.h"
  14. #include "ImprtDlg.h"
  15. //#include "WizSheet.h"
  16. #include "NKChseCA.h"
  17. #include "NKDN.h"
  18. #include "NKDN2.h"
  19. #include "NKFlInfo.h"
  20. #include "NKKyInfo.h"
  21. #include "NKUsrInf.h"
  22. #include "Creating.h"
  23. #ifdef _DEBUG
  24. #define new DEBUG_NEW
  25. #undef THIS_FILE
  26. static char THIS_FILE[] = __FILE__;
  27. #endif
  28. extern CKeyRingView* g_pTreeView;
  29. extern CString g_szRemoteCommand;
  30. // a global reference to this doc object
  31. CKeyRingDoc* g_pDocument = NULL;
  32. /////////////////////////////////////////////////////////////////////////////
  33. // CKeyRingDoc
  34. IMPLEMENT_DYNCREATE(CKeyRingDoc, CDocument)
  35. BEGIN_MESSAGE_MAP(CKeyRingDoc, CDocument)
  36. //{{AFX_MSG_MAP(CKeyRingDoc)
  37. ON_UPDATE_COMMAND_UI(ID_SERVER_CONNECT, OnUpdateServerConnect)
  38. ON_COMMAND(ID_SERVER_CONNECT, OnServerConnect)
  39. ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
  40. ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
  41. ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)
  42. ON_COMMAND(ID_EDIT_CUT, OnEditCut)
  43. ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
  44. ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
  45. ON_UPDATE_COMMAND_UI(ID_PROPERTIES, OnUpdateProperties)
  46. ON_COMMAND(ID_PROPERTIES, OnProperties)
  47. ON_UPDATE_COMMAND_UI(ID_SERVER_COMMIT_NOW, OnUpdateServerCommitNow)
  48. ON_COMMAND(ID_SERVER_COMMIT_NOW, OnServerCommitNow)
  49. ON_UPDATE_COMMAND_UI(ID_KEY_CREATE_REQUEST, OnUpdateKeyCreateRequest)
  50. ON_COMMAND(ID_KEY_CREATE_REQUEST, OnKeyCreateRequest)
  51. ON_UPDATE_COMMAND_UI(ID_KEY_INSTALL_CERTIFICATE, OnUpdateKeyInstallCertificate)
  52. ON_COMMAND(ID_KEY_INSTALL_CERTIFICATE, OnKeyInstallCertificate)
  53. ON_UPDATE_COMMAND_UI(ID_KEY_SAVE_REQUEST, OnUpdateKeySaveRequest)
  54. ON_COMMAND(ID_KEY_SAVE_REQUEST, OnKeySaveRequest)
  55. ON_UPDATE_COMMAND_UI(ID_KEY_EXPORT_BACKUP, OnUpdateKeyExportBackup)
  56. ON_COMMAND(ID_KEY_EXPORT_BACKUP, OnKeyExportBackup)
  57. ON_UPDATE_COMMAND_UI(ID_KEY_IMPORT_BACKUP, OnUpdateKeyImportBackup)
  58. ON_COMMAND(ID_KEY_IMPORT_BACKUP, OnKeyImportBackup)
  59. ON_UPDATE_COMMAND_UI(ID_KEY_IMPORT_KEYSET, OnUpdateKeyImportKeyset)
  60. ON_COMMAND(ID_KEY_IMPORT_KEYSET, OnKeyImportKeyset)
  61. ON_COMMAND(ID_KEY_DELETE, OnKeyDelete)
  62. ON_UPDATE_COMMAND_UI(ID_KEY_DELETE, OnUpdateKeyDelete)
  63. ON_COMMAND(IDS_NEW_CREATE_NEW, OnNewCreateNew)
  64. ON_UPDATE_COMMAND_UI(IDS_NEW_CREATE_NEW, OnUpdateNewCreateNew)
  65. ON_COMMAND(ID_HELPTOPICS, OnHelptopics)
  66. //}}AFX_MSG_MAP
  67. END_MESSAGE_MAP()
  68. /////////////////////////////////////////////////////////////////////////////
  69. // CKeyRingDoc construction/destruction
  70. //----------------------------------------------------------------
  71. CKeyRingDoc::CKeyRingDoc():
  72. m_pScrapKey(NULL),
  73. m_fDirty( FALSE )
  74. {
  75. g_pDocument = this;
  76. }
  77. //----------------------------------------------------------------
  78. CKeyRingDoc::~CKeyRingDoc()
  79. {
  80. // clean up the add-on services
  81. DeleteAddOnServices();
  82. }
  83. //----------------------------------------------------------------
  84. // this is called once
  85. BOOL CKeyRingDoc::Initialize()
  86. {
  87. // see which machines we were logged into last time and restore their connections
  88. RestoreConnectedMachines();
  89. // set the selection to the first service on the first machine
  90. // get the first item (a machine) in the list
  91. CTreeCtrl* pTree = (CTreeCtrl*)g_pTreeView;
  92. HTREEITEM hItem = pTree->GetRootItem();
  93. // if that worked, get the next sub item. (a service)
  94. if ( hItem )
  95. {
  96. hItem = pTree->GetChildItem(hItem);
  97. // if that worked, select the item
  98. if ( hItem )
  99. pTree->SelectItem(hItem);
  100. }
  101. // return success
  102. return TRUE;
  103. }
  104. //----------------------------------------------------------------
  105. BOOL CKeyRingDoc::OnNewDocument()
  106. {
  107. CLocalMachine *pLocalMachine;
  108. if (!CDocument::OnNewDocument())
  109. return FALSE;
  110. // initialize the add on services
  111. if( !FInitAddOnServices() )
  112. AfxMessageBox( IDS_NO_SERVICE_MODS );
  113. // connect to the local machine
  114. try {
  115. pLocalMachine = new CLocalMachine;
  116. }
  117. catch( CException e )
  118. {
  119. return FALSE;
  120. }
  121. // add it to the tree at the top level
  122. pLocalMachine->FAddToTree( NULL );
  123. // load the services add-ons into the machine
  124. if ( !FLoadAddOnServicesOntoMachine( pLocalMachine ) )
  125. {
  126. pLocalMachine->FRemoveFromTree();
  127. delete pLocalMachine;
  128. }
  129. // return success
  130. return TRUE;
  131. }
  132. /////////////////////////////////////////////////////////////////////////////
  133. // CKeyRingDoc serialization
  134. void CKeyRingDoc::Serialize(CArchive& ar)
  135. {
  136. if (ar.IsStoring())
  137. {
  138. // TODO: add storing code here
  139. }
  140. else
  141. {
  142. // TODO: add loading code here
  143. }
  144. }
  145. /////////////////////////////////////////////////////////////////////////////
  146. // CKeyRingDoc diagnostics
  147. #ifdef _DEBUG
  148. void CKeyRingDoc::AssertValid() const
  149. {
  150. CDocument::AssertValid();
  151. }
  152. void CKeyRingDoc::Dump(CDumpContext& dc) const
  153. {
  154. CDocument::Dump(dc);
  155. }
  156. #endif //_DEBUG
  157. /////////////////////////////////////////////////////////////////////////////
  158. // test what is selected in the treeview
  159. // if the selcted item is not of the requested type (machine, key, etc...)
  160. //--------------------------------------------------------------
  161. // then it returns a NULL
  162. CTreeItem* CKeyRingDoc::PGetSelectedItem()
  163. {
  164. ASSERT( g_pTreeView );
  165. CTreeCtrl* pTree = (CTreeCtrl*)g_pTreeView;
  166. // get the selected item
  167. HTREEITEM hTreeItem = pTree->GetSelectedItem();
  168. // if nothing is selected, return a null
  169. if ( !hTreeItem ) return NULL;
  170. // get the associated internal object and return it
  171. CTreeItem* pItem = (CTreeItem*)pTree->GetItemData( hTreeItem );
  172. return ( pItem );
  173. }
  174. //--------------------------------------------------------------
  175. CMachine* CKeyRingDoc::PGetSelectedMachine()
  176. {
  177. CMachine* pMachine = (CMachine*)PGetSelectedItem();
  178. // make sure it is a machine object
  179. if ( !pMachine || pMachine->IsKindOf(RUNTIME_CLASS(CMachine)) )
  180. return NULL;
  181. // its OK
  182. return pMachine;
  183. }
  184. //--------------------------------------------------------------
  185. CService* CKeyRingDoc::PGetSelectedService()
  186. {
  187. CService* pService = (CService*)PGetSelectedItem();
  188. // make sure it is a machine object
  189. if ( !pService || pService->IsKindOf(RUNTIME_CLASS(CService)) )
  190. return NULL;
  191. // its OK
  192. return pService;
  193. }
  194. //--------------------------------------------------------------
  195. CKey* CKeyRingDoc::PGetSelectedKey()
  196. {
  197. CKey* pKey = (CKey*)PGetSelectedItem();
  198. // make sure it is a machine object
  199. if ( !pKey || pKey->IsKindOf(RUNTIME_CLASS(CKey)) )
  200. return NULL;
  201. // its OK
  202. return pKey;
  203. }
  204. /////////////////////////////////////////////////////////////////////////////
  205. // add-on service management
  206. //----------------------------------------------------------------
  207. // pointers to the add-on services are stored in the registry
  208. //----------------------------------------------------------------
  209. BOOL CKeyRingDoc::FInitAddOnServices()
  210. {
  211. DWORD err;
  212. CString szRegKeyName;
  213. HKEY hKey;
  214. DWORD iValue = 0;
  215. DWORD dwordType;
  216. DWORD cbValName = MAX_PATH+1;
  217. DWORD cbBuff = MAX_PATH+1;
  218. CString szValName, szServiceName;
  219. LPTSTR pValName, pServiceName;
  220. BOOL fLoadedOne = FALSE;
  221. CWaitCursor waitcursor;
  222. // load the registry key name
  223. szRegKeyName.LoadString( IDS_ADDONS_LOCATION );
  224. // open the registry key, if it exists
  225. err = RegOpenKeyEx(
  226. HKEY_LOCAL_MACHINE, // handle of open key
  227. szRegKeyName, // address of name of subkey to open
  228. 0, // reserved
  229. KEY_READ, // security access mask
  230. &hKey // address of handle of open key
  231. );
  232. // if we did not open the key for any reason (say... it doesn't exist)
  233. // then leave right away
  234. if ( err != ERROR_SUCCESS )
  235. return FALSE;
  236. // set up the buffers
  237. pValName = szValName.GetBuffer( MAX_PATH+1 );
  238. pServiceName = szServiceName.GetBuffer( MAX_PATH+1 );
  239. // we opened the key. Now we enumerate the values and reconnect the machines
  240. while ( RegEnumValue(hKey, iValue, pValName,
  241. &cbValName, NULL, &dwordType,
  242. (PUCHAR)pServiceName, &cbBuff) == ERROR_SUCCESS )
  243. {
  244. // release the buffer so we can use the string
  245. szServiceName.ReleaseBuffer();
  246. // attempt to load and initialize the add on service module
  247. CAddOnService* pService;
  248. try {
  249. // create the service object
  250. pService = new CAddOnService;
  251. // initialize it
  252. if ( pService->FInitializeAddOnService( szServiceName ) )
  253. {
  254. // add it to the list
  255. m_AddOnServiceArray.Add( pService );
  256. // we did load one
  257. fLoadedOne = TRUE;
  258. }
  259. else
  260. {
  261. // delete the services object because it didn't work
  262. delete pService;
  263. pService = NULL;
  264. }
  265. }
  266. catch (CException e)
  267. {
  268. // delete the services object because it didn't work
  269. if ( pService )
  270. delete pService;
  271. pService = NULL;
  272. }
  273. // get the buffer again so we can get the next machine
  274. pServiceName = szServiceName.GetBuffer( MAX_PATH+1 );
  275. // increment the value counter
  276. iValue++;
  277. cbValName = MAX_PATH+1;
  278. cbBuff = MAX_PATH+1;
  279. }
  280. // release the name buffers
  281. szValName.ReleaseBuffer();
  282. szServiceName.ReleaseBuffer();
  283. // all done, close the key before leaving
  284. RegCloseKey( hKey );
  285. // return whether or not we loaded something
  286. return fLoadedOne;
  287. }
  288. //----------------------------------------------------------------
  289. BOOL CKeyRingDoc::FLoadAddOnServicesOntoMachine( CMachine* pMachine )
  290. {
  291. BOOL fAddedOne = FALSE;
  292. // loop though the list of add on services and add them to the machine
  293. WORD num = (WORD)m_AddOnServiceArray.GetSize();
  294. for ( WORD i = 0; i < num; i++ )
  295. fAddedOne |= m_AddOnServiceArray[i]->LoadService( pMachine );
  296. // return whether or not we added something
  297. return fAddedOne;
  298. }
  299. //----------------------------------------------------------------
  300. void CKeyRingDoc::DeleteAddOnServices()
  301. {
  302. // loop backwards through the array and delete the objects
  303. for ( LONG i = m_AddOnServiceArray.GetSize()-1; i >= 0; i-- )
  304. delete m_AddOnServiceArray[i];
  305. // clear out the array
  306. m_AddOnServiceArray.RemoveAll();
  307. }
  308. /////////////////////////////////////////////////////////////////////////////
  309. // CKeyRingDoc commands
  310. //----------------------------------------------------------------
  311. void CKeyRingDoc::OnUpdateServerConnect(CCmdUI* pCmdUI)
  312. { pCmdUI->Enable( TRUE ); }
  313. //----------------------------------------------------------------
  314. void CKeyRingDoc::OnServerConnect()
  315. {
  316. BROWSEINFO bi;
  317. LPSTR lpBuffer;
  318. LPITEMIDLIST pidlBrowse, pidlStart; // PIDL selected by user
  319. // Allocate a buffer to receive browse information.
  320. lpBuffer = (LPSTR) GlobalAlloc( GPTR, MAX_PATH );
  321. if ( !lpBuffer )
  322. return;
  323. // load the title
  324. CString szTitle;
  325. szTitle.LoadString( IDS_CHOOSE_COMPUTER );
  326. // tell it where to start looking
  327. SHGetSpecialFolderLocation( AfxGetMainWnd()->m_hWnd, CSIDL_NETWORK, &pidlStart );
  328. // Fill in the BROWSEINFO structure.
  329. bi.hwndOwner = AfxGetMainWnd()->m_hWnd;
  330. bi.pidlRoot = pidlStart;
  331. bi.pszDisplayName = lpBuffer;
  332. bi.lpszTitle = szTitle;
  333. bi.ulFlags = BIF_BROWSEFORCOMPUTER;
  334. bi.lpfn = NULL;
  335. bi.lParam = 0;
  336. // Browse for a folder and return its PIDL.
  337. pidlBrowse = SHBrowseForFolder(&bi);
  338. if (pidlBrowse != NULL)
  339. {
  340. CString sz = lpBuffer;
  341. ConnectToMachine( sz );
  342. // Free the PIDL returned by SHBrowseForFolder.
  343. GlobalFree(pidlBrowse);
  344. }
  345. //clean up the pidl
  346. if ( pidlStart )
  347. GlobalFree(pidlStart);
  348. }
  349. // manage connections to machines
  350. //----------------------------------------------------------------
  351. void CKeyRingDoc::ConnectToMachine( CString &sz )
  352. {
  353. CRemoteMachine *pRemoteMachine;
  354. // don't "remote" connect to the local machine
  355. CString szLocalName;
  356. DWORD cbBuff = MAX_COMPUTERNAME_LENGTH+1;
  357. GetComputerName(szLocalName.GetBuffer((cbBuff)*2), &cbBuff);
  358. szLocalName.ReleaseBuffer();
  359. // if sz is the same as the local machine name, don't connect to it
  360. if ( sz.CompareNoCase(szLocalName) == 0 )
  361. return;
  362. // see if we already are connected
  363. // to the remote machine. If we are, then just hilight that one
  364. if ( g_pTreeView )
  365. {
  366. CString szItem;
  367. CTreeCtrl* pTree = (CTreeCtrl*)g_pTreeView;
  368. HTREEITEM hItem = pTree->GetRootItem();
  369. while ( hItem )
  370. {
  371. szItem = pTree->GetItemText(hItem);
  372. if ( sz.CompareNoCase(szItem) == 0 )
  373. {
  374. // we are already connected to this machine
  375. // select the item in the tree
  376. pTree->Select( hItem, TVGN_CARET );
  377. return;
  378. }
  379. // get the next item
  380. hItem = pTree->GetNextSiblingItem( hItem );
  381. }
  382. }
  383. // since this could take a few seconds, put up a wait cursor
  384. CWaitCursor waitCursor;
  385. // connect to the local machine
  386. try {
  387. pRemoteMachine = new CRemoteMachine( sz );
  388. }
  389. catch( CException e )
  390. {
  391. AfxMessageBox( IDS_ERR_CONNECT );
  392. return;
  393. }
  394. // add it to the tree at the top level
  395. pRemoteMachine->FAddToTree( NULL );
  396. // load the services add-ons into the machine
  397. if ( !FLoadAddOnServicesOntoMachine( pRemoteMachine ) )
  398. {
  399. AfxMessageBox( IDS_ERR_CONNECT );
  400. pRemoteMachine->FRemoveFromTree();
  401. delete pRemoteMachine;
  402. }
  403. }
  404. //----------------------------------------------------------------
  405. // we want to save the machines the user was connected to so they remain connected
  406. // the next time we launch the program
  407. void CKeyRingDoc::StoreConnectedMachines( void )
  408. {
  409. DWORD err, disposition;
  410. CString szRegKeyName;
  411. HKEY hKey;
  412. WORD cMachine = 1;
  413. // load the registry key name
  414. szRegKeyName.LoadString( IDS_REG_SERVER_STORAGE );
  415. // first, we delete the machine subkey to get rid of all the previous values
  416. err = RegDeleteKey( HKEY_CURRENT_USER, szRegKeyName );
  417. // create the registry key. If it already exists it merely opens it
  418. err = RegCreateKeyEx(
  419. HKEY_CURRENT_USER, // handle of an open key
  420. szRegKeyName, // address of subkey name
  421. 0, // reserved
  422. NULL, // address of class string
  423. REG_OPTION_NON_VOLATILE, // special options flag
  424. KEY_ALL_ACCESS, // desired security access
  425. NULL, // address of key security structure
  426. &hKey, // address of buffer for opened handle
  427. &disposition // address of disposition value buffer
  428. );
  429. // if we did not open the key, give up
  430. if ( err != ERROR_SUCCESS )
  431. return;
  432. // loop through the machines
  433. CTreeCtrl* pTree = (CTreeCtrl*)g_pTreeView;
  434. HTREEITEM hItem = pTree->GetRootItem();
  435. while ( hItem )
  436. {
  437. CRemoteMachine* pMachine = (CRemoteMachine*)pTree->GetItemData( hItem );
  438. ASSERT( pMachine->IsKindOf( RUNTIME_CLASS(CMachine) ) );
  439. // only bother if this is a remote machine
  440. if ( pMachine->IsKindOf(RUNTIME_CLASS(CRemoteMachine)) )
  441. {
  442. // build the registry value name
  443. CString szMachineValue;
  444. szMachineValue.Format( "Machine#%d", cMachine );
  445. // get the machine name
  446. CString szMachineName;
  447. pMachine->GetMachineName( szMachineName );
  448. // set the data into place
  449. err = RegSetValueEx(
  450. hKey, // handle of key to set value for
  451. szMachineValue, // address of value to set
  452. 0, // reserved
  453. REG_SZ, // flag for value type
  454. (unsigned char *)LPCSTR(szMachineName), // address of value data
  455. (szMachineName.GetLength() + 1) * sizeof(TCHAR)// size of value data
  456. );
  457. // increment the machine counter
  458. cMachine++;
  459. }
  460. // get the next item
  461. hItem = pTree->GetNextSiblingItem( hItem );
  462. }
  463. // close the key
  464. RegCloseKey( hKey );
  465. }
  466. //----------------------------------------------------------------
  467. void CKeyRingDoc::RestoreConnectedMachines( void )
  468. {
  469. DWORD err;
  470. CString szRegKeyName;
  471. HKEY hKey;
  472. DWORD iValue = 0;
  473. DWORD dwordType;
  474. DWORD cbValName = MAX_PATH+1;
  475. DWORD cbBuff = MAX_PATH+1;
  476. CString szValName, szMachineName;
  477. LPTSTR pValName, pMachineName;
  478. CWaitCursor waitcursor;
  479. // load the registry key name
  480. szRegKeyName.LoadString( IDS_REG_SERVER_STORAGE );
  481. // open the registry key, if it exists
  482. err = RegOpenKeyEx(
  483. HKEY_CURRENT_USER, // handle of open key
  484. szRegKeyName, // address of name of subkey to open
  485. 0, // reserved
  486. KEY_READ, // security access mask
  487. &hKey // address of handle of open key
  488. );
  489. // if we did not open the key for any reason (say... it doesn't exist)
  490. // then leave right away
  491. if ( err != ERROR_SUCCESS )
  492. return;
  493. // set up the buffers
  494. pValName = szValName.GetBuffer( MAX_PATH+1 );
  495. pMachineName = szMachineName.GetBuffer( MAX_PATH+1 );
  496. // we opened the key. Now we enumerate the values and reconnect the machines
  497. while ( RegEnumValue(hKey, iValue, pValName,
  498. &cbValName, NULL, &dwordType,
  499. (PUCHAR)pMachineName, &cbBuff) == ERROR_SUCCESS )
  500. {
  501. // release the buffer so we can use the string
  502. szMachineName.ReleaseBuffer();
  503. // attempt to connect to the remote machine
  504. ConnectToMachine(szMachineName);
  505. // get the buffer again so we can get the next machine
  506. pMachineName = szMachineName.GetBuffer( MAX_PATH+1 );
  507. // increment the value counter
  508. iValue++;
  509. cbValName = MAX_PATH+1;
  510. cbBuff = MAX_PATH+1;
  511. }
  512. // release the name buffers
  513. szValName.ReleaseBuffer();
  514. szMachineName.ReleaseBuffer();
  515. // all done, close the key before leaving
  516. RegCloseKey( hKey );
  517. // finally, if the user requested a specific remote machine
  518. // on the command line, connect to that one too
  519. if ( !g_szRemoteCommand.IsEmpty() )
  520. {
  521. ConnectToMachine( g_szRemoteCommand );
  522. }
  523. }
  524. //----------------------------------------------------------------
  525. void CKeyRingDoc::OnCloseDocument()
  526. {
  527. if ( g_pTreeView )
  528. ((CKeyRingView*)g_pTreeView)->DestroyItems();
  529. // if we have a scrap key, delete it
  530. if ( m_pScrapKey )
  531. {
  532. delete m_pScrapKey;
  533. m_pScrapKey = NULL;
  534. }
  535. CDocument::OnCloseDocument();
  536. }
  537. // actions that depend on the selected item
  538. //----------------------------------------------------------------
  539. void CKeyRingDoc::OnUpdateProperties(CCmdUI* pCmdUI)
  540. {
  541. CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
  542. // let the item decide
  543. if ( pItem )
  544. pItem->OnUpdateProperties( pCmdUI );
  545. else
  546. pCmdUI->Enable( FALSE );
  547. }
  548. //----------------------------------------------------------------
  549. void CKeyRingDoc::OnProperties()
  550. {
  551. CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
  552. ASSERT( pItem );
  553. // let the item handle it
  554. pItem->OnProperties();
  555. }
  556. //----------------------------------------------------------------
  557. void CKeyRingDoc::OnUpdateServerCommitNow(CCmdUI* pCmdUI)
  558. {
  559. pCmdUI->Enable( m_fDirty );
  560. }
  561. //----------------------------------------------------------------
  562. void CKeyRingDoc::OnServerCommitNow()
  563. {
  564. ASSERT( m_fDirty );
  565. // confirm that the user really wants to commit the changes
  566. if ( AfxMessageBox(IDS_SERVER_COMMIT, MB_YESNO) == IDNO )
  567. return;
  568. // commit all the servers
  569. ASSERT(g_pTreeView);
  570. BOOL fSuccess = g_pTreeView->FCommitMachinesNow();
  571. SetDirty( !fSuccess );
  572. }
  573. //----------------------------------------------------------------
  574. void CKeyRingDoc::OnUpdateKeyDelete(CCmdUI* pCmdUI)
  575. {
  576. CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
  577. if ( pItem )
  578. pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
  579. else
  580. pCmdUI->Enable( FALSE );
  581. }
  582. //----------------------------------------------------------------
  583. void CKeyRingDoc::OnKeyDelete()
  584. {
  585. CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem();
  586. ASSERT( pKey );
  587. ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) );
  588. // make sure the user REALLY wants to do this
  589. if ( pKey && (AfxMessageBox(IDS_KEY_DELETE_WARNING, MB_OKCANCEL) == IDOK) )
  590. {
  591. // dirty things first
  592. pKey->SetDirty(TRUE);
  593. // update the view
  594. pKey->FRemoveFromTree();
  595. delete pKey;
  596. }
  597. }
  598. //----------------------------------------------------------------
  599. // set scrap key does NOT make a copy of the key. Thus, CUT would pass in
  600. // the key itself, but COPY would make a copy of the key object first, then
  601. // pass it over to SetScrapKey.
  602. void CKeyRingDoc::SetScrapKey( CKey* pKey )
  603. {
  604. // if there already is a key in the scrap, delete it
  605. if ( m_pScrapKey )
  606. delete m_pScrapKey;
  607. // set the new key into position
  608. m_pScrapKey = pKey;
  609. }
  610. //----------------------------------------------------------------
  611. void CKeyRingDoc::OnUpdateEditCopy(CCmdUI* pCmdUI)
  612. {
  613. CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
  614. if ( pItem )
  615. pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
  616. else
  617. pCmdUI->Enable( FALSE );
  618. }
  619. //----------------------------------------------------------------
  620. void CKeyRingDoc::OnUpdateEditCut(CCmdUI* pCmdUI)
  621. {
  622. CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
  623. if ( pItem )
  624. pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
  625. else
  626. pCmdUI->Enable( FALSE );
  627. }
  628. //----------------------------------------------------------------
  629. void CKeyRingDoc::OnEditCut()
  630. {
  631. CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem();
  632. ASSERT( pKey );
  633. ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) );
  634. // mark the key dirty before we remove it so the dirty is propagated up
  635. // to the machine and the document
  636. pKey->SetDirty( TRUE );
  637. // cut is the easiest. Remove it from the machine and put in on the doc scrap
  638. pKey->FRemoveFromTree();
  639. SetScrapKey( pKey );
  640. }
  641. //----------------------------------------------------------------
  642. void CKeyRingDoc::OnEditCopy()
  643. {
  644. CKey* pKeySel = (CKey*)g_pTreeView->PGetSelectedItem();
  645. CKey* pKeyCopy;
  646. ASSERT( pKeySel );
  647. ASSERT( pKeySel->IsKindOf(RUNTIME_CLASS(CKey)) );
  648. if ( !pKeySel ) return;
  649. // make a full copy of the key
  650. try
  651. {
  652. pKeyCopy = pKeySel->PClone();
  653. }
  654. catch( CException e )
  655. {
  656. return;
  657. }
  658. ASSERT( pKeyCopy );
  659. // put the clone on the doc scrap
  660. SetScrapKey( pKeyCopy );
  661. }
  662. //----------------------------------------------------------------
  663. void CKeyRingDoc::OnUpdateEditPaste(CCmdUI* pCmdUI)
  664. {
  665. CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
  666. if ( pItem )
  667. {
  668. pCmdUI->Enable( (pItem->IsKindOf(RUNTIME_CLASS(CService)) ||
  669. pItem->IsKindOf(RUNTIME_CLASS(CKey))) && PGetScrapKey() );
  670. }
  671. else
  672. pCmdUI->Enable( FALSE );
  673. }
  674. //----------------------------------------------------------------
  675. void CKeyRingDoc::OnEditPaste()
  676. {
  677. ASSERT( PGetScrapKey() );
  678. CService* pService = (CService*)g_pTreeView->PGetSelectedItem();
  679. ASSERT( pService );
  680. ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) ||
  681. pService->IsKindOf(RUNTIME_CLASS(CKey)));
  682. // if the selection is a key, get the key's parent, which should be a service
  683. if ( pService->IsKindOf(RUNTIME_CLASS(CKey)) )
  684. {
  685. pService = (CService*)pService->PGetParent();
  686. ASSERT( pService );
  687. ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) );
  688. }
  689. // clone the scrap key so we put a copy in the machine
  690. CKey* pClone;
  691. try
  692. {
  693. pClone = pService->PNewKey();
  694. pClone->CopyDataFrom( PGetScrapKey() );
  695. // if this is a full key - i.e. it has a certificate - we need to check it
  696. if ( pClone->m_pCertificate )
  697. {
  698. // we are going to re-install the cert anyway, so prevent it from being freed
  699. PVOID pCert = pClone->m_pCertificate;
  700. DWORD cbCert = pClone->m_cbCertificate;
  701. CString szPass = pClone->m_szPassword;
  702. pClone->m_pCertificate = NULL;
  703. pClone->m_cbCertificate = 0;
  704. pClone->m_szPassword.Empty();
  705. // make sure it can deal with the certificate.
  706. if ( !pClone->FInstallCertificate(pCert,cbCert,szPass) )
  707. {
  708. delete pClone;
  709. return;
  710. }
  711. }
  712. // add the key to the service
  713. pClone->FAddToTree( pService );
  714. // make sure the cloned key has a caption
  715. pClone->UpdateCaption();
  716. // select the newly added key
  717. if ( g_pTreeView )
  718. ((CTreeCtrl*)g_pTreeView)->SelectItem(pClone->HGetTreeItem());
  719. // if there is a certificate, then bring up the properties dialog
  720. if ( pClone->m_cbCertificate )
  721. {
  722. pClone->OnProperties();
  723. }
  724. // set the dirty flag
  725. pClone->SetDirty( TRUE );
  726. }
  727. catch( CException e )
  728. {
  729. return;
  730. }
  731. // set the dirty flag
  732. pService->SetDirty( TRUE );
  733. }
  734. //----------------------------------------------------------------
  735. void CKeyRingDoc::OnUpdateKeyCreateRequest(CCmdUI* pCmdUI)
  736. {
  737. CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
  738. if ( pItem )
  739. {
  740. pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CService)) ||
  741. pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
  742. }
  743. else
  744. pCmdUI->Enable( FALSE );
  745. }
  746. //----------------------------------------------------------------
  747. void CKeyRingDoc::OnKeyCreateRequest()
  748. {
  749. }
  750. //----------------------------------------------------------------
  751. // if the key is targeted to an online authority, then we need to take
  752. // special care. Otherwise, just go ahead and let them install a file cert.
  753. void CKeyRingDoc::OnUpdateKeyInstallCertificate(CCmdUI* pCmdUI)
  754. {
  755. CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
  756. BOOL fEnable = FALSE;
  757. // make sure we have a selected item and that it is a key
  758. if ( pItem && pItem->IsKindOf(RUNTIME_CLASS(CKey)) )
  759. {
  760. // cast the key
  761. CKey* pKey = (CKey*)pItem;
  762. // determine if this is a online authority key
  763. LPREQUEST_HEADER pHeader = (LPREQUEST_HEADER)pKey->m_pCertificateRequest;
  764. if ( pHeader &&
  765. pHeader->Identifier == REQUEST_HEADER_IDENTIFIER &&
  766. pHeader->fReqSentToOnlineCA )
  767. {
  768. // this key does target an online authority
  769. // if the fWaitingForApproval is set then allow the action
  770. if ( pHeader->fWaitingForApproval )
  771. fEnable = TRUE;
  772. // can optionally alter the text of the meny item here
  773. }
  774. else
  775. {
  776. // the key does not target an online authority, just
  777. // let the user attach a file-based certificate
  778. fEnable = TRUE;
  779. }
  780. }
  781. // do the enabling
  782. pCmdUI->Enable( fEnable );
  783. }
  784. //----------------------------------------------------------------
  785. void CKeyRingDoc::OnKeyInstallCertificate()
  786. {
  787. CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem();
  788. ASSERT( pKey );
  789. ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) );
  790. // put this in a try/catch to make errors easier to deal with
  791. try {
  792. // start by seeing if this is a online based key waiting for a response
  793. LPREQUEST_HEADER pHeader = (LPREQUEST_HEADER)pKey->m_pCertificateRequest;
  794. if ( pHeader &&
  795. pHeader->Identifier == REQUEST_HEADER_IDENTIFIER &&
  796. pHeader->fReqSentToOnlineCA )
  797. {
  798. // should be waiting for approval
  799. ASSERT( pHeader->fWaitingForApproval );
  800. // contact the online authority to get the certificate
  801. GetOnlineKeyApproval( pKey );
  802. // avoid all the file based stuff and leave now
  803. return;
  804. }
  805. // the old, file based stuff
  806. // prepare the file dialog variables
  807. CFileDialog cfdlg(TRUE);
  808. CString szFilter;
  809. WORD i = 0;
  810. LPSTR lpszBuffer;
  811. // prepare the filter string
  812. szFilter.LoadString( IDS_CERTIFICATE_FILTER );
  813. // replace the "!" characters with nulls
  814. lpszBuffer = szFilter.GetBuffer(MAX_PATH+1);
  815. while( lpszBuffer[i] )
  816. {
  817. if ( lpszBuffer[i] == _T('!') )
  818. lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose
  819. i++;
  820. }
  821. // prep the dialog
  822. cfdlg.m_ofn.lpstrFilter = lpszBuffer;
  823. cfdlg.m_ofn.lpstrDefExt = NULL;
  824. // run the dialog
  825. if ( cfdlg.DoModal() == IDOK )
  826. {
  827. // get the password string
  828. CConfirmPassDlg dlgconfirm;
  829. if ( dlgconfirm.DoModal() == IDOK )
  830. {
  831. // tell the key to install the certificate
  832. if ( pKey->FInstallCertificate( cfdlg.GetPathName(), dlgconfirm.m_szPassword ) )
  833. {
  834. pKey->OnProperties();
  835. pKey->SetDirty( TRUE );
  836. UpdateAllViews( NULL, HINT_None );
  837. }
  838. else
  839. {
  840. // now the plugin is responsible fot telling the user
  841. // that the cert didn't install right
  842. // tell the user that it didn't work
  843. // AfxMessageBox( IDS_ERR_INSTALLING_CERT );
  844. }
  845. }
  846. }
  847. // release the buffer in the filter string
  848. szFilter.ReleaseBuffer(-1);
  849. }
  850. catch ( CException e )
  851. {
  852. }
  853. }
  854. //----------------------------------------------------------------
  855. void CKeyRingDoc::OnUpdateKeySaveRequest(CCmdUI* pCmdUI)
  856. {
  857. BOOL fEnable = FALSE;
  858. CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem();
  859. // quite a few conditions here, so do them one at a time
  860. if ( pKey && pKey->IsKindOf(RUNTIME_CLASS(CKey)) )
  861. {
  862. // determine if this is a online authority key
  863. LPREQUEST_HEADER pHeader = (LPREQUEST_HEADER)pKey->m_pCertificateRequest;
  864. if ( pHeader &&
  865. pHeader->Identifier == REQUEST_HEADER_IDENTIFIER &&
  866. pHeader->fReqSentToOnlineCA )
  867. {
  868. // if we are already waiting for approval, do not ask for a new cert
  869. fEnable = !pHeader->fWaitingForApproval;
  870. }
  871. else
  872. {
  873. // a file-based key
  874. fEnable = TRUE;
  875. if ( fEnable )
  876. fEnable &= (pKey->m_cbCertificateRequest > 0);
  877. if ( fEnable )
  878. fEnable &= (pKey->m_pCertificateRequest != NULL);
  879. }
  880. }
  881. // enable the item
  882. pCmdUI->Enable( fEnable );
  883. }
  884. //----------------------------------------------------------------
  885. void CKeyRingDoc::OnKeySaveRequest()
  886. {
  887. CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem();
  888. ASSERT( pKey );
  889. ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) );
  890. ASSERT( pKey->m_cbCertificateRequest );
  891. ASSERT( pKey->m_pCertificateRequest );
  892. // start by seeing if this is a new style key request
  893. LPREQUEST_HEADER pHeader = (LPREQUEST_HEADER)pKey->m_pCertificateRequest;
  894. if ( pHeader &&
  895. pHeader->Identifier == REQUEST_HEADER_IDENTIFIER )
  896. {
  897. // should not be waiting for approval
  898. ASSERT( !pHeader->fWaitingForApproval );
  899. // send out the online key renewal request
  900. DoKeyRenewal( pKey );
  901. // avoid all the file based stuff and leave now
  902. return;
  903. }
  904. // the old, file based stuff
  905. // get the key name
  906. CString szKeyName = pKey->GetName();
  907. // make the default file name
  908. CString szDefaultFile;
  909. szDefaultFile = _T("C:\\");
  910. szDefaultFile += szKeyName;
  911. szDefaultFile += _T(".req");
  912. CFileDialog cfdlg(FALSE, _T("*.req"), szDefaultFile);
  913. CString szFilter;
  914. WORD i = 0;
  915. LPSTR lpszBuffer;
  916. // prepare the filter string
  917. szFilter.LoadString( IDS_REQUEST_FILTER );
  918. // replace the "!" characters with nulls
  919. lpszBuffer = szFilter.GetBuffer(MAX_PATH+1);
  920. while( lpszBuffer[i] )
  921. {
  922. if ( lpszBuffer[i] == _T('!') )
  923. lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose
  924. i++;
  925. }
  926. // prep the dialog
  927. cfdlg.m_ofn.lpstrFilter = lpszBuffer;
  928. // run the dialog
  929. if ( cfdlg.DoModal() == IDOK )
  930. {
  931. // output the request file
  932. if ( !pKey->FOutputRequestFile(cfdlg.GetPathName()) )
  933. {
  934. AfxMessageBox( IDS_ERR_WRITEREQUEST );
  935. }
  936. else
  937. {
  938. // put up the user information box
  939. CNewKeyInfoDlg dlg;
  940. dlg.m_fNewKeyInfo = FALSE;
  941. dlg.m_szRequestFile = cfdlg.GetPathName();
  942. dlg.DoModal();
  943. }
  944. }
  945. // release the buffer in the filter string
  946. szFilter.ReleaseBuffer(60);
  947. }
  948. //----------------------------------------------------------------
  949. void CKeyRingDoc::OnUpdateKeyImportKeyset(CCmdUI* pCmdUI)
  950. {
  951. CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
  952. if ( pItem )
  953. pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CService)) ||
  954. pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
  955. else
  956. pCmdUI->Enable( FALSE );
  957. }
  958. //----------------------------------------------------------------
  959. void CKeyRingDoc::OnKeyImportKeyset()
  960. {
  961. CService* pService = (CService*)g_pTreeView->PGetSelectedItem();
  962. ASSERT( pService );
  963. ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) ||
  964. pService->IsKindOf(RUNTIME_CLASS(CKey)));
  965. // if the selection is a key, get the key's parent, which should be a service
  966. if ( pService->IsKindOf(RUNTIME_CLASS(CKey)) )
  967. {
  968. pService = (CService*)pService->PGetParent();
  969. ASSERT( pService );
  970. ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) );
  971. }
  972. CString szPrivateKey;
  973. CString szPublicKey;
  974. // get the names of the key files
  975. CImportDialog ImprtDlg;
  976. if ( ImprtDlg.DoModal() != IDOK )
  977. {
  978. // exit because the user canceled
  979. return;
  980. }
  981. // the user must also give a password
  982. CConfirmPassDlg dlgconfirm;
  983. if ( dlgconfirm.DoModal() != IDOK )
  984. return;
  985. try
  986. {
  987. // create the new import key object
  988. CKey* pKey = pService->PNewKey();
  989. // tell it to do the importing
  990. if ( !pKey->FImportKeySetFiles(ImprtDlg.m_cstring_PrivateFile,
  991. ImprtDlg.m_cstring_CertFile, dlgconfirm.m_szPassword) )
  992. {
  993. delete pKey;
  994. return;
  995. }
  996. // make sure its name is untitled
  997. CString szName;
  998. szName.LoadString( IDS_UNTITLED );
  999. pKey->SetName( szName );
  1000. // add the key to the service
  1001. pKey->FAddToTree( pService );
  1002. // make sure the key has a caption
  1003. pKey->UpdateCaption();
  1004. // set the dirty flag
  1005. pKey->SetDirty( TRUE );
  1006. // select the newly added key
  1007. if ( g_pTreeView )
  1008. ((CTreeCtrl*)g_pTreeView)->SelectItem(pKey->HGetTreeItem());
  1009. // force properties dlg
  1010. pKey->OnProperties();
  1011. }
  1012. catch( CException e )
  1013. {
  1014. return;
  1015. }
  1016. }
  1017. //----------------------------------------------------------------
  1018. void CKeyRingDoc::OnUpdateKeyExportBackup(CCmdUI* pCmdUI)
  1019. {
  1020. CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
  1021. if ( pItem )
  1022. pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
  1023. else
  1024. pCmdUI->Enable( FALSE );
  1025. }
  1026. //----------------------------------------------------------------
  1027. void CKeyRingDoc::OnKeyExportBackup()
  1028. {
  1029. CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem();
  1030. ASSERT( pKey );
  1031. ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) );
  1032. CFileDialog cfdlg(FALSE, _T("*.key"));
  1033. CString szFilter;
  1034. WORD i = 0;
  1035. LPSTR lpszBuffer;
  1036. ASSERT(pKey);
  1037. if ( !pKey ) return;
  1038. // warn the user about security
  1039. if ( AfxMessageBox(IDS_KEYFILE_WARNING, MB_OKCANCEL|MB_ICONEXCLAMATION) == IDCANCEL )
  1040. return;
  1041. // prepare the filter string
  1042. szFilter.LoadString( IDS_KEY_FILE_TYPE );
  1043. // replace the "!" characters with nulls
  1044. lpszBuffer = szFilter.GetBuffer(MAX_PATH+1);
  1045. while( lpszBuffer[i] )
  1046. {
  1047. if ( lpszBuffer[i] == _T('!') )
  1048. lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose
  1049. i++;
  1050. }
  1051. // prep the dialog
  1052. cfdlg.m_ofn.lpstrFilter = lpszBuffer;
  1053. // run the dialog
  1054. if ( cfdlg.DoModal() == IDOK )
  1055. {
  1056. // tell the key to export itself
  1057. pKey->FImportExportBackupFile( cfdlg.GetPathName(), FALSE );
  1058. }
  1059. // release the buffer in the filter string
  1060. szFilter.ReleaseBuffer(60);
  1061. }
  1062. //----------------------------------------------------------------
  1063. void CKeyRingDoc::OnUpdateKeyImportBackup(CCmdUI* pCmdUI)
  1064. {
  1065. CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
  1066. if ( pItem )
  1067. pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CService)) ||
  1068. pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
  1069. else
  1070. pCmdUI->Enable( FALSE );
  1071. }
  1072. //----------------------------------------------------------------
  1073. void CKeyRingDoc::OnKeyImportBackup()
  1074. {
  1075. CService* pService = (CService*)g_pTreeView->PGetSelectedItem();
  1076. ASSERT( pService );
  1077. ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) ||
  1078. pService->IsKindOf(RUNTIME_CLASS(CKey)));
  1079. // if the selection is a key, get the key's parent, which should be a service
  1080. if ( pService->IsKindOf(RUNTIME_CLASS(CKey)) )
  1081. {
  1082. pService = (CService*)pService->PGetParent();
  1083. ASSERT( pService );
  1084. ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) );
  1085. }
  1086. CFileDialog cfdlg(TRUE );
  1087. CString szFilter;
  1088. WORD i = 0;
  1089. LPSTR lpszBuffer;
  1090. // make sure we are ok
  1091. if ( !pService )
  1092. return;
  1093. // prepare the filter string
  1094. szFilter.LoadString( IDS_KEY_FILE_TYPE );
  1095. // replace the "!" characters with nulls
  1096. lpszBuffer = szFilter.GetBuffer(MAX_PATH+1);
  1097. while( lpszBuffer[i] )
  1098. {
  1099. if ( lpszBuffer[i] == _T('!') )
  1100. lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose
  1101. i++;
  1102. }
  1103. // prep the dialog
  1104. cfdlg.m_ofn.lpstrFilter = lpszBuffer;
  1105. // run the dialog
  1106. if ( cfdlg.DoModal() == IDOK )
  1107. {
  1108. try
  1109. {
  1110. // create the new import key object
  1111. CKey* pKey = pService->PNewKey();
  1112. // tell it to do the importing
  1113. if ( !pKey->FImportExportBackupFile(cfdlg.GetPathName(), TRUE) )
  1114. {
  1115. delete pKey;
  1116. return;
  1117. }
  1118. // if this is a full key - i.e. it has a certificate - we need to check it
  1119. if ( pKey->m_pCertificate )
  1120. {
  1121. // we are going to re-install the cert anyway, so prevent it from being freed
  1122. PVOID pCert = pKey->m_pCertificate;
  1123. DWORD cbCert = pKey->m_cbCertificate;
  1124. CString szPass = pKey->m_szPassword;
  1125. pKey->m_pCertificate = NULL;
  1126. pKey->m_cbCertificate = 0;
  1127. pKey->m_szPassword.Empty();
  1128. // make sure it can deal with the certificate.
  1129. if ( !pKey->FInstallCertificate(pCert,cbCert,szPass) )
  1130. {
  1131. delete pKey;
  1132. return;
  1133. }
  1134. }
  1135. // add the key to the service
  1136. pKey->FAddToTree( pService );
  1137. // make sure the key has a caption
  1138. pKey->UpdateCaption();
  1139. // set the dirty flag
  1140. pKey->SetDirty( TRUE );
  1141. // select the newly added key
  1142. if ( g_pTreeView )
  1143. ((CTreeCtrl*)g_pTreeView)->SelectItem(pKey->HGetTreeItem());
  1144. // if there is a certificate, then bring up the properties dialog
  1145. if ( pKey->m_cbCertificate )
  1146. {
  1147. pKey->OnProperties();
  1148. }
  1149. }
  1150. catch( CException e )
  1151. {
  1152. return;
  1153. }
  1154. }
  1155. }
  1156. //----------------------------------------------------------------
  1157. BOOL CKeyRingDoc::CanCloseFrame(CFrameWnd* pFrame)
  1158. {
  1159. BOOL fSuccess;
  1160. // if we are dirty, ask the user what to do - they can cancel here
  1161. if ( m_fDirty )
  1162. {
  1163. switch( AfxMessageBox(IDS_SERVER_COMMIT, MB_YESNOCANCEL|MB_ICONQUESTION) )
  1164. {
  1165. case IDYES: // yes, they do want to commit
  1166. // commit all the servers
  1167. ASSERT(g_pTreeView);
  1168. fSuccess = g_pTreeView->FCommitMachinesNow();
  1169. break;
  1170. case IDNO: // no, they don't want to commit
  1171. break;
  1172. case IDCANCEL: // whoa nellie! Stop this
  1173. return FALSE;
  1174. }
  1175. }
  1176. // make a note in the user registry of which machines we are logged into so we
  1177. // administer them again later
  1178. StoreConnectedMachines();
  1179. // of course we can close the frame
  1180. return TRUE;
  1181. }
  1182. //----------------------------------------------------------------
  1183. void CKeyRingDoc::OnUpdateNewCreateNew(CCmdUI* pCmdUI)
  1184. {
  1185. OnUpdateKeyCreateRequest(pCmdUI);
  1186. }
  1187. //----------------------------------------------------------------
  1188. void CKeyRingDoc::OnNewCreateNew()
  1189. {
  1190. CService* pService = (CService*)g_pTreeView->PGetSelectedItem();
  1191. ASSERT( pService );
  1192. ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) ||
  1193. pService->IsKindOf(RUNTIME_CLASS(CKey)));
  1194. // if the selection is a key, get the key's parent, which should be a service
  1195. if ( pService->IsKindOf(RUNTIME_CLASS(CKey)) )
  1196. {
  1197. pService = (CService*)pService->PGetParent();
  1198. ASSERT( pService );
  1199. ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) );
  1200. }
  1201. //run the create key wizard. We start by declaring all the pieces of it
  1202. CPropertySheet propsheet(IDS_TITLE_CREATE_WIZ);
  1203. CNKChooseCA page_Choose_CA;
  1204. CNKUserInfo page_User_Info;
  1205. CNKKeyInfo page_Key_Info;
  1206. CNKDistinguishedName page_DN;
  1207. CNKDistinguisedName2 page_DN2;
  1208. CNKFileInfo page_File_Info;
  1209. // fill in the member variables.
  1210. page_Choose_CA.m_pPropSheet = &propsheet;
  1211. page_Choose_CA.m_pChooseCAPage = &page_Choose_CA;
  1212. page_User_Info.m_pPropSheet = &propsheet;
  1213. page_User_Info.m_pChooseCAPage = &page_Choose_CA;
  1214. page_Key_Info.m_pPropSheet = &propsheet;
  1215. page_Key_Info.m_pChooseCAPage = &page_Choose_CA;
  1216. page_DN.m_pPropSheet = &propsheet;
  1217. page_DN.m_pChooseCAPage = &page_Choose_CA;
  1218. page_DN2.m_pPropSheet = &propsheet;
  1219. page_DN2.m_pChooseCAPage = &page_Choose_CA;
  1220. page_File_Info.m_pPropSheet = &propsheet;
  1221. page_File_Info.m_pChooseCAPage = &page_Choose_CA;
  1222. // clear the help button bits
  1223. if ( propsheet.m_psh.dwFlags & PSH_HASHELP )
  1224. propsheet.m_psh.dwFlags &= ~PSH_HASHELP;
  1225. page_Choose_CA.m_psp.dwFlags &= ~(PSP_HASHELP);
  1226. page_User_Info.m_psp.dwFlags &= ~(PSP_HASHELP);
  1227. page_Key_Info.m_psp.dwFlags &= ~(PSP_HASHELP);
  1228. page_DN.m_psp.dwFlags &= ~(PSP_HASHELP);
  1229. page_DN2.m_psp.dwFlags &= ~(PSP_HASHELP);
  1230. page_File_Info.m_psp.dwFlags &= ~(PSP_HASHELP);
  1231. // add the pages to the property sheet
  1232. propsheet.AddPage( &page_Choose_CA );
  1233. propsheet.AddPage( &page_Key_Info );
  1234. propsheet.AddPage( &page_DN );
  1235. propsheet.AddPage( &page_DN2 );
  1236. propsheet.AddPage( &page_User_Info );
  1237. propsheet.AddPage( &page_File_Info );
  1238. // set the wizard property
  1239. propsheet.SetWizardMode();
  1240. // run the property sheet
  1241. int i = IDOK;
  1242. i = IDCANCEL;
  1243. i = propsheet.DoModal();
  1244. if ( i != IDCANCEL )
  1245. {
  1246. // tell all the pages that it was successful
  1247. page_Choose_CA.OnFinish();
  1248. page_User_Info.OnFinish();
  1249. page_Key_Info.OnFinish();
  1250. page_DN.OnFinish();
  1251. page_DN2.OnFinish();
  1252. page_File_Info.OnFinish();
  1253. // ok, the wizard succeeded, now run the grinder.
  1254. CCreatingKeyDlg grinder;
  1255. // set the grinder up
  1256. grinder.m_ppage_Choose_CA = &page_Choose_CA;
  1257. grinder.m_ppage_User_Info = &page_User_Info;
  1258. grinder.m_ppage_Key_Info = &page_Key_Info;
  1259. grinder.m_ppage_DN = &page_DN;
  1260. grinder.m_ppage_DN2 = &page_DN2;
  1261. grinder.m_pService = pService;
  1262. grinder.m_fGenerateKeyPair = TRUE;
  1263. // let'er rip
  1264. if ( grinder.DoModal() == IDOK )
  1265. {
  1266. ASSERT( grinder.m_pKey );
  1267. // add the new key to the tree
  1268. grinder.m_pKey->FAddToTree( pService );
  1269. // make sure the new key has a caption
  1270. grinder.m_pKey->UpdateCaption();
  1271. // make it dirty too
  1272. grinder.m_pKey->SetDirty(TRUE);
  1273. // select the newly added key
  1274. if ( g_pTreeView )
  1275. ((CTreeCtrl*)g_pTreeView)->SelectItem(grinder.m_pKey->HGetTreeItem());
  1276. // if the key is already complete, then bring up its properties dialog
  1277. if ( grinder.m_pKey->m_pCertificate )
  1278. grinder.m_pKey->OnProperties();
  1279. }
  1280. }
  1281. }
  1282. // online key support utilities
  1283. //----------------------------------------------------------------
  1284. void CKeyRingDoc::DoKeyRenewal( CKey* pKey )
  1285. {
  1286. LPREQUEST_HEADER pHeader = (LPREQUEST_HEADER)pKey->m_pCertificateRequest;
  1287. CPropertySheet propsheet( IDS_TITLE_RENEW );
  1288. CNKChooseCA page_Choose_CA;
  1289. CNKUserInfo page_User_Info;
  1290. page_Choose_CA.m_pPropSheet = &propsheet;
  1291. page_Choose_CA.m_pChooseCAPage = &page_Choose_CA;
  1292. page_User_Info.m_pPropSheet = &propsheet;
  1293. page_User_Info.m_pChooseCAPage = &page_Choose_CA;
  1294. // set the renewal flag on the user page
  1295. page_User_Info.fRenewingKey = TRUE;
  1296. // add the pages to the property sheet
  1297. propsheet.AddPage( &page_Choose_CA );
  1298. propsheet.AddPage( &page_User_Info );
  1299. // set the wizard property
  1300. propsheet.SetWizardMode();
  1301. // get rid of the help button
  1302. DWORD NoHelpMask = 0xFFFFFFFF ^ PSH_HASHELP;
  1303. propsheet.m_psh.dwFlags &= NoHelpMask;
  1304. // run the property sheet
  1305. int i = IDOK;
  1306. i = IDCANCEL;
  1307. i = propsheet.DoModal();
  1308. if ( i != IDCANCEL )
  1309. {
  1310. // tell all the pages that it was successful
  1311. page_Choose_CA.OnFinish();
  1312. page_User_Info.OnFinish();
  1313. // create the grinder and prepare it
  1314. CCreatingKeyDlg grinder;
  1315. // set the grinder up
  1316. grinder.m_ppage_Choose_CA = &page_Choose_CA;
  1317. grinder.m_ppage_User_Info = &page_User_Info;
  1318. grinder.m_ppage_Key_Info = NULL;
  1319. grinder.m_ppage_DN = NULL;
  1320. grinder.m_ppage_DN2 = NULL;
  1321. grinder.m_pService = NULL;
  1322. grinder.m_pKey = pKey;
  1323. grinder.m_fRenewExistingKey = TRUE;
  1324. // let'er rip
  1325. if ( grinder.DoModal() )
  1326. {
  1327. // make it dirty
  1328. grinder.m_pKey->SetDirty(TRUE);
  1329. // it has been decided not to bring up the properties dialog in the event
  1330. // a renewal request - the properties have already been set
  1331. // if ( grinder.m_pKey->m_pCertificate )
  1332. // grinder.m_pKey->OnProperties();
  1333. }
  1334. }
  1335. }
  1336. //----------------------------------------------------------------
  1337. void CKeyRingDoc::GetOnlineKeyApproval( CKey* pKey )
  1338. {
  1339. // create the grinder and prepare it
  1340. CCreatingKeyDlg grinder;
  1341. // set the grinder up
  1342. grinder.m_ppage_Choose_CA = NULL;
  1343. grinder.m_ppage_User_Info = NULL;
  1344. grinder.m_ppage_Key_Info = NULL;
  1345. grinder.m_ppage_DN = NULL;
  1346. grinder.m_ppage_DN2 = NULL;
  1347. grinder.m_pService = NULL;
  1348. grinder.m_pKey = pKey;
  1349. grinder.m_fResubmitKey = TRUE;
  1350. // let'er rip
  1351. if ( grinder.DoModal() )
  1352. {
  1353. // make it dirty
  1354. grinder.m_pKey->SetDirty(TRUE);
  1355. // if the key is already complete, then bring up its properties dialog
  1356. if ( grinder.m_pKey->m_pCertificate )
  1357. grinder.m_pKey->OnProperties();
  1358. }
  1359. }
  1360. //----------------------------------------------------------------
  1361. // invoke the help with a standard help ID
  1362. void CKeyRingDoc::OnHelptopics()
  1363. {
  1364. if ( g_pTreeView )
  1365. g_pTreeView->WinHelp( 0x50000 );
  1366. }