Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1237 lines
32 KiB

// KRDoc.cpp : implementation of the CKeyRingDoc class
//
#include "stdafx.h"
#include "keyobjs.h"
#include "machine.h"
#include "KeyRing.h"
#include "KRDoc.h"
#include "KRView.h"
#include "ConctDlg.h"
#include "NwKeyDlg.h"
#include "Creating.h"
#include "InfoDlg.h"
#include "passdlg.h"
#include "ImprtDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
extern CKeyRingView* g_pTreeView;
// a global reference to this doc object
CKeyRingDoc* g_pDocument = NULL;
/////////////////////////////////////////////////////////////////////////////
// CKeyRingDoc
IMPLEMENT_DYNCREATE(CKeyRingDoc, CDocument)
BEGIN_MESSAGE_MAP(CKeyRingDoc, CDocument)
//{{AFX_MSG_MAP(CKeyRingDoc)
ON_UPDATE_COMMAND_UI(ID_SERVER_CONNECT, OnUpdateServerConnect)
ON_COMMAND(ID_SERVER_CONNECT, OnServerConnect)
ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)
ON_COMMAND(ID_EDIT_CUT, OnEditCut)
ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
ON_UPDATE_COMMAND_UI(ID_PROPERTIES, OnUpdateProperties)
ON_COMMAND(ID_PROPERTIES, OnProperties)
ON_UPDATE_COMMAND_UI(ID_SERVER_COMMIT_NOW, OnUpdateServerCommitNow)
ON_COMMAND(ID_SERVER_COMMIT_NOW, OnServerCommitNow)
ON_UPDATE_COMMAND_UI(ID_KEY_CREATE_REQUEST, OnUpdateKeyCreateRequest)
ON_COMMAND(ID_KEY_CREATE_REQUEST, OnKeyCreateRequest)
ON_UPDATE_COMMAND_UI(ID_KEY_INSTALL_CERTIFICATE, OnUpdateKeyInstallCertificate)
ON_COMMAND(ID_KEY_INSTALL_CERTIFICATE, OnKeyInstallCertificate)
ON_UPDATE_COMMAND_UI(ID_KEY_SAVE_REQUEST, OnUpdateKeySaveRequest)
ON_COMMAND(ID_KEY_SAVE_REQUEST, OnKeySaveRequest)
ON_UPDATE_COMMAND_UI(ID_KEY_EXPORT_BACKUP, OnUpdateKeyExportBackup)
ON_COMMAND(ID_KEY_EXPORT_BACKUP, OnKeyExportBackup)
ON_UPDATE_COMMAND_UI(ID_KEY_IMPORT_BACKUP, OnUpdateKeyImportBackup)
ON_COMMAND(ID_KEY_IMPORT_BACKUP, OnKeyImportBackup)
ON_UPDATE_COMMAND_UI(ID_KEY_IMPORT_KEYSET, OnUpdateKeyImportKeyset)
ON_COMMAND(ID_KEY_IMPORT_KEYSET, OnKeyImportKeyset)
ON_COMMAND(ID_KEY_DELETE, OnKeyDelete)
ON_UPDATE_COMMAND_UI(ID_KEY_DELETE, OnUpdateKeyDelete)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CKeyRingDoc construction/destruction
//----------------------------------------------------------------
CKeyRingDoc::CKeyRingDoc():
m_pScrapKey(NULL),
m_fDirty( FALSE )
{
g_pDocument = this;
}
//----------------------------------------------------------------
CKeyRingDoc::~CKeyRingDoc()
{
// clean up the add-on services
DeleteAddOnServices();
}
//----------------------------------------------------------------
// this is called once
BOOL CKeyRingDoc::Initialize()
{
// see which machines we were logged into last time and restore their connections
RestoreConnectedMachines();
// return success
return TRUE;
}
//----------------------------------------------------------------
BOOL CKeyRingDoc::OnNewDocument()
{
CLocalMachine *pLocalMachine;
if (!CDocument::OnNewDocument())
return FALSE;
// initialize the add on services
if( !FInitAddOnServices() )
AfxMessageBox( IDS_NO_SERVICE_MODS );
// connect to the local machine
try {
pLocalMachine = new CLocalMachine;
}
catch( CException e )
{
return FALSE;
}
// add it to the tree at the top level
pLocalMachine->FAddToTree( NULL );
// load the services add-ons into the machine
if ( !FLoadAddOnServicesOntoMachine( pLocalMachine ) )
{
pLocalMachine->FRemoveFromTree();
delete pLocalMachine;
}
// return success
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CKeyRingDoc serialization
void CKeyRingDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
// TODO: add storing code here
}
else
{
// TODO: add loading code here
}
}
/////////////////////////////////////////////////////////////////////////////
// CKeyRingDoc diagnostics
#ifdef _DEBUG
void CKeyRingDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CKeyRingDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// test what is selected in the treeview
// if the selcted item is not of the requested type (machine, key, etc...)
//--------------------------------------------------------------
// then it returns a NULL
CTreeItem* CKeyRingDoc::PGetSelectedItem()
{
ASSERT( g_pTreeView );
CTreeCtrl* pTree = (CTreeCtrl*)g_pTreeView;
// get the selected item
HTREEITEM hTreeItem = pTree->GetSelectedItem();
// if nothing is selected, return a null
if ( !hTreeItem ) return NULL;
// get the associated internal object and return it
CTreeItem* pItem = (CTreeItem*)pTree->GetItemData( hTreeItem );
return ( pItem );
}
//--------------------------------------------------------------
CMachine* CKeyRingDoc::PGetSelectedMachine()
{
CMachine* pMachine = (CMachine*)PGetSelectedItem();
// make sure it is a machine object
if ( !pMachine || pMachine->IsKindOf(RUNTIME_CLASS(CMachine)) )
return NULL;
// its OK
return pMachine;
}
//--------------------------------------------------------------
CService* CKeyRingDoc::PGetSelectedService()
{
CService* pService = (CService*)PGetSelectedItem();
// make sure it is a machine object
if ( !pService || pService->IsKindOf(RUNTIME_CLASS(CService)) )
return NULL;
// its OK
return pService;
}
//--------------------------------------------------------------
CKey* CKeyRingDoc::PGetSelectedKey()
{
CKey* pKey = (CKey*)PGetSelectedItem();
// make sure it is a machine object
if ( !pKey || pKey->IsKindOf(RUNTIME_CLASS(CKey)) )
return NULL;
// its OK
return pKey;
}
/////////////////////////////////////////////////////////////////////////////
// add-on service management
//----------------------------------------------------------------
// pointers to the add-on services are stored in the registry
//----------------------------------------------------------------
BOOL CKeyRingDoc::FInitAddOnServices()
{
DWORD err;
CString szRegKeyName;
HKEY hKey;
DWORD iValue = 0;
DWORD dwordType;
DWORD cbValName = MAX_PATH+1;
DWORD cbBuff = MAX_PATH+1;
CString szValName, szServiceName;
LPTSTR pValName, pServiceName;
BOOL fLoadedOne = FALSE;
CWaitCursor waitcursor;
// load the registry key name
szRegKeyName.LoadString( IDS_ADDONS_LOCATION );
// open the registry key, if it exists
err = RegOpenKeyEx(
HKEY_LOCAL_MACHINE, // handle of open key
szRegKeyName, // address of name of subkey to open
0, // reserved
KEY_READ, // security access mask
&hKey // address of handle of open key
);
// if we did not open the key for any reason (say... it doesn't exist)
// then leave right away
if ( err != ERROR_SUCCESS )
return FALSE;
// set up the buffers
pValName = szValName.GetBuffer( MAX_PATH+1 );
pServiceName = szServiceName.GetBuffer( MAX_PATH+1 );
// we opened the key. Now we enumerate the values and reconnect the machines
while ( RegEnumValue(hKey, iValue, pValName,
&cbValName, NULL, &dwordType,
(PUCHAR)pServiceName, &cbBuff) == ERROR_SUCCESS )
{
// release the buffer so we can use the string
szServiceName.ReleaseBuffer();
// attempt to load and initialize the add on service module
CAddOnService* pService;
try {
// create the service object
pService = new CAddOnService;
// initialize it
if ( pService->FInitializeAddOnService( szServiceName ) )
{
// add it to the list
m_AddOnServiceArray.Add( pService );
// we did load one
fLoadedOne = TRUE;
}
else
{
// delete the services object because it didn't work
delete pService;
pService = NULL;
}
}
catch (CException e)
{
// delete the services object because it didn't work
if ( pService )
delete pService;
pService = NULL;
}
// get the buffer again so we can get the next machine
pServiceName = szServiceName.GetBuffer( MAX_PATH+1 );
// increment the value counter
iValue++;
cbValName = MAX_PATH+1;
cbBuff = MAX_PATH+1;
}
// release the name buffers
szValName.ReleaseBuffer();
szServiceName.ReleaseBuffer();
// all done, close the key before leaving
RegCloseKey( hKey );
// return whether or not we loaded something
return fLoadedOne;
}
//----------------------------------------------------------------
BOOL CKeyRingDoc::FLoadAddOnServicesOntoMachine( CMachine* pMachine )
{
BOOL fAddedOne = FALSE;
// loop though the list of add on services and add them to the machine
WORD num = m_AddOnServiceArray.GetSize();
for ( WORD i = 0; i < num; i++ )
fAddedOne |= m_AddOnServiceArray[i]->LoadService( pMachine );
// return whether or not we added something
return fAddedOne;
}
//----------------------------------------------------------------
void CKeyRingDoc::DeleteAddOnServices()
{
// loop backwards through the array and delete the objects
for ( LONG i = m_AddOnServiceArray.GetSize()-1; i >= 0; i-- )
delete m_AddOnServiceArray[i];
// clear out the array
m_AddOnServiceArray.RemoveAll();
}
/////////////////////////////////////////////////////////////////////////////
// CKeyRingDoc commands
//----------------------------------------------------------------
void CKeyRingDoc::OnUpdateServerConnect(CCmdUI* pCmdUI)
{ pCmdUI->Enable( TRUE ); }
//----------------------------------------------------------------
void CKeyRingDoc::OnServerConnect()
{
CConnectOneDialog dlg;
// invoke the dialog box
if ( dlg.DoModal() == IDOK )
ConnectToMachine(dlg.m_ServerName);
}
// manage connections to machines
//----------------------------------------------------------------
void CKeyRingDoc::ConnectToMachine( CString &sz )
{
CRemoteMachine *pRemoteMachine;
// since this could take a few seconds, put up a wait cursor
CWaitCursor waitCursor;
// connect to the local machine
try {
pRemoteMachine = new CRemoteMachine( sz );
}
catch( CException e )
{
AfxMessageBox( IDS_ERR_CONNECT );
return;
}
// add it to the tree at the top level
pRemoteMachine->FAddToTree( NULL );
// load the services add-ons into the machine
if ( !FLoadAddOnServicesOntoMachine( pRemoteMachine ) )
{
AfxMessageBox( IDS_ERR_CONNECT );
pRemoteMachine->FRemoveFromTree();
delete pRemoteMachine;
}
}
//----------------------------------------------------------------
// we want to save the machines the user was connected to so they remain connected
// the next time we launch the program
void CKeyRingDoc::StoreConnectedMachines( void )
{
DWORD err, disposition;
CString szRegKeyName;
HKEY hKey;
WORD cMachine = 1;
// load the registry key name
szRegKeyName.LoadString( IDS_REG_SERVER_STORAGE );
// first, we delete the machine subkey to get rid of all the previous values
err = RegDeleteKey( HKEY_CURRENT_USER, szRegKeyName );
// create the registry key. If it already exists it merely opens it
err = RegCreateKeyEx(
HKEY_CURRENT_USER, // handle of an open key
szRegKeyName, // address of subkey name
0, // reserved
NULL, // address of class string
REG_OPTION_NON_VOLATILE, // special options flag
KEY_ALL_ACCESS, // desired security access
NULL, // address of key security structure
&hKey, // address of buffer for opened handle
&disposition // address of disposition value buffer
);
// if we did not open the key, give up
if ( err != ERROR_SUCCESS )
return;
// loop through the machines
CTreeCtrl* pTree = (CTreeCtrl*)g_pTreeView;
HTREEITEM hItem = pTree->GetRootItem();
while ( hItem )
{
CRemoteMachine* pMachine = (CRemoteMachine*)pTree->GetItemData( hItem );
ASSERT( pMachine->IsKindOf( RUNTIME_CLASS(CMachine) ) );
// only bother if this is a remote machine
if ( pMachine->IsKindOf(RUNTIME_CLASS(CRemoteMachine)) )
{
// build the registry value name
CString szMachineValue;
szMachineValue.Format( "Machine#%d", cMachine );
// get the machine name
CString szMachineName;
pMachine->GetMachineName( szMachineName );
// set the data into place
err = RegSetValueEx(
hKey, // handle of key to set value for
szMachineValue, // address of value to set
0, // reserved
REG_SZ, // flag for value type
(unsigned char *)LPCSTR(szMachineName), // address of value data
(szMachineName.GetLength() + 1) * sizeof(TCHAR)// size of value data
);
// increment the machine counter
cMachine++;
}
// get the next item
hItem = pTree->GetNextSiblingItem( hItem );
}
// close the key
RegCloseKey( hKey );
}
//----------------------------------------------------------------
void CKeyRingDoc::RestoreConnectedMachines( void )
{
DWORD err;
CString szRegKeyName;
HKEY hKey;
DWORD iValue = 0;
DWORD dwordType;
DWORD cbValName = MAX_PATH+1;
DWORD cbBuff = MAX_PATH+1;
CString szValName, szMachineName;
LPTSTR pValName, pMachineName;
CWaitCursor waitcursor;
// load the registry key name
szRegKeyName.LoadString( IDS_REG_SERVER_STORAGE );
// open the registry key, if it exists
err = RegOpenKeyEx(
HKEY_CURRENT_USER, // handle of open key
szRegKeyName, // address of name of subkey to open
0, // reserved
KEY_READ, // security access mask
&hKey // address of handle of open key
);
// if we did not open the key for any reason (say... it doesn't exist)
// then leave right away
if ( err != ERROR_SUCCESS )
return;
// set up the buffers
pValName = szValName.GetBuffer( MAX_PATH+1 );
pMachineName = szMachineName.GetBuffer( MAX_PATH+1 );
// we opened the key. Now we enumerate the values and reconnect the machines
while ( RegEnumValue(hKey, iValue, pValName,
&cbValName, NULL, &dwordType,
(PUCHAR)pMachineName, &cbBuff) == ERROR_SUCCESS )
{
// release the buffer so we can use the string
szMachineName.ReleaseBuffer();
// attempt to connect to the remote machine
ConnectToMachine(szMachineName);
// get the buffer again so we can get the next machine
pMachineName = szMachineName.GetBuffer( MAX_PATH+1 );
// increment the value counter
iValue++;
cbValName = MAX_PATH+1;
cbBuff = MAX_PATH+1;
}
// release the name buffers
szValName.ReleaseBuffer();
szMachineName.ReleaseBuffer();
// all done, close the key before leaving
RegCloseKey( hKey );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnCloseDocument()
{
if ( g_pTreeView )
((CKeyRingView*)g_pTreeView)->DestroyItems();
// if we have a scrap key, delete it
if ( m_pScrapKey )
{
delete m_pScrapKey;
m_pScrapKey = NULL;
}
CDocument::OnCloseDocument();
}
// actions that depend on the selected item
//----------------------------------------------------------------
void CKeyRingDoc::OnUpdateProperties(CCmdUI* pCmdUI)
{
CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
// let the item decide
if ( pItem )
pItem->OnUpdateProperties( pCmdUI );
else
pCmdUI->Enable( FALSE );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnProperties()
{
CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
ASSERT( pItem );
// let the item handle it
pItem->OnProperties();
}
//----------------------------------------------------------------
void CKeyRingDoc::OnUpdateServerCommitNow(CCmdUI* pCmdUI)
{
pCmdUI->Enable( m_fDirty );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnServerCommitNow()
{
ASSERT( m_fDirty );
// confirm that the user really wants to commit the changes
if ( AfxMessageBox(IDS_SERVER_COMMIT, MB_YESNO) == IDNO )
return;
// commit all the servers
ASSERT(g_pTreeView);
BOOL fSuccess = g_pTreeView->FCommitMachinesNow();
SetDirty( !fSuccess );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnUpdateKeyDelete(CCmdUI* pCmdUI)
{
CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
if ( pItem )
pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
else
pCmdUI->Enable( FALSE );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnKeyDelete()
{
CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem();
ASSERT( pKey );
ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) );
// make sure the user REALLY wants to do this
if ( pKey && (AfxMessageBox(IDS_KEY_DELETE_WARNING, MB_OKCANCEL) == IDOK) )
{
// dirty things first
pKey->SetDirty(TRUE);
// update the view
pKey->FRemoveFromTree();
delete pKey;
}
}
//----------------------------------------------------------------
// set scrap key does NOT make a copy of the key. Thus, CUT would pass in
// the key itself, but COPY would make a copy of the key object first, then
// pass it over to SetScrapKey.
void CKeyRingDoc::SetScrapKey( CKey* pKey )
{
// if there already is a key in the scrap, delete it
if ( m_pScrapKey )
delete m_pScrapKey;
// set the new key into position
m_pScrapKey = pKey;
}
//----------------------------------------------------------------
void CKeyRingDoc::OnUpdateEditCopy(CCmdUI* pCmdUI)
{
CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
if ( pItem )
pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
else
pCmdUI->Enable( FALSE );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnUpdateEditCut(CCmdUI* pCmdUI)
{
CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
if ( pItem )
pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
else
pCmdUI->Enable( FALSE );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnEditCut()
{
CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem();
ASSERT( pKey );
ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) );
// mark the key dirty before we remove it so the dirty is propagated up
// to the machine and the document
pKey->SetDirty( TRUE );
// cut is the easiest. Remove it from the machine and put in on the doc scrap
pKey->FRemoveFromTree();
SetScrapKey( pKey );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnEditCopy()
{
CKey* pKeySel = (CKey*)g_pTreeView->PGetSelectedItem();
CKey* pKeyCopy;
ASSERT( pKeySel );
ASSERT( pKeySel->IsKindOf(RUNTIME_CLASS(CKey)) );
if ( !pKeySel ) return;
// make a full copy of the key
try
{
pKeyCopy = pKeySel->PClone();
}
catch( CException e )
{
return;
}
ASSERT( pKeyCopy );
// put the clone on the doc scrap
SetScrapKey( pKeyCopy );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnUpdateEditPaste(CCmdUI* pCmdUI)
{
CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
if ( pItem )
{
pCmdUI->Enable( (pItem->IsKindOf(RUNTIME_CLASS(CService)) ||
pItem->IsKindOf(RUNTIME_CLASS(CKey))) && PGetScrapKey() );
}
else
pCmdUI->Enable( FALSE );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnEditPaste()
{
ASSERT( PGetScrapKey() );
CService* pService = (CService*)g_pTreeView->PGetSelectedItem();
ASSERT( pService );
ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) ||
pService->IsKindOf(RUNTIME_CLASS(CKey)));
// if the selection is a key, get the key's parent, which should be a service
if ( pService->IsKindOf(RUNTIME_CLASS(CKey)) )
{
pService = (CService*)pService->PGetParent();
ASSERT( pService );
ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) );
}
// clone the scrap key so we put a copy in the machine
CKey* pClone;
try
{
pClone = pService->PNewKey();
pClone->CopyDataFrom( PGetScrapKey() );
// add the key to the service
pClone->FAddToTree( pService );
// make sure the cloned key has a caption
pClone->UpdateCaption();
}
catch( CException e )
{
return;
}
// set the dirty flag
pService->SetDirty( TRUE );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnUpdateKeyCreateRequest(CCmdUI* pCmdUI)
{
CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
if ( pItem )
{
pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CService)) ||
pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
}
else
pCmdUI->Enable( FALSE );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnKeyCreateRequest()
{
CService* pService = (CService*)g_pTreeView->PGetSelectedItem();
ASSERT( pService );
ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) ||
pService->IsKindOf(RUNTIME_CLASS(CKey)));
// if the selection is a key, get the key's parent, which should be a service
if ( pService->IsKindOf(RUNTIME_CLASS(CKey)) )
{
pService = (CService*)pService->PGetParent();
ASSERT( pService );
ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) );
}
// run the dialog
CCreateKeyDlg dlgCrKey;
if ( dlgCrKey.DoModal() != IDOK )
return;
// create the key and fill it out based on info from the new key dlg
CKey* pNewKey;
try
{
// create the key
pNewKey = pService->PNewKey();
// set the name (easy)
pNewKey->SetName( dlgCrKey.m_szKeyName );
// get the password (also easy)
pNewKey->m_szPassword = dlgCrKey.m_szPassword;
}
catch( CException e )
{
if ( pNewKey )
delete pNewKey;
return;
}
// call the create key pair dialog. It creates the key pair
// while showing a pretty animation.
CCreatingKeyDlg dlgCreating;
dlgCreating.m_pNwDlg = &dlgCrKey;
if ( dlgCreating.DoModal() != IDOK )
{
AfxMessageBox( IDS_GENERATE_KEY_ERROR, MB_OK|MB_ICONINFORMATION );
if ( pNewKey )
delete pNewKey;
return;
}
// bring over the info from the "creating" dialog
ASSERT( dlgCreating.m_cbPrivateKey );
ASSERT( dlgCreating.m_pPrivateKey );
ASSERT( dlgCreating.m_cbCertificateRequest );
ASSERT( dlgCreating.m_pCertificateRequest );
pNewKey->m_cbPrivateKey = dlgCreating.m_cbPrivateKey;
pNewKey->m_pPrivateKey = dlgCreating.m_pPrivateKey;
pNewKey->m_cbCertificateRequest = dlgCreating.m_cbCertificateRequest;
pNewKey->m_pCertificateRequest = dlgCreating.m_pCertificateRequest;
// add the key to the service
pNewKey->FAddToTree( pService );
// make sure the new key has a caption
pNewKey->UpdateCaption();
// output the request file
if ( !pNewKey->FOutputRequestFile( dlgCrKey.m_szCertificateFile, FALSE, (PVOID)&dlgCrKey ) )
AfxMessageBox( IDS_ERR_WRITEREQUEST );
// display the "what to do next" information dialog
CNewKeyInfoDlg dlgInfo;
dlgInfo.m_szRequestFile = dlgCrKey.m_szCertificateFile;
dlgInfo.DoModal();
// set the dirty flag
pNewKey->SetDirty( TRUE );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnUpdateKeyInstallCertificate(CCmdUI* pCmdUI)
{
CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
if ( pItem )
pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
else
pCmdUI->Enable( FALSE );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnKeyInstallCertificate()
{
CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem();
ASSERT( pKey );
ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) );
// put this in a try/catch to make errors easier to deal with
try {
// load the file extension
CString szExtension;
szExtension = _T("*.*");
// prepare the file dialog variables
CFileDialog cfdlg(TRUE, szExtension);
CString szFilter;
WORD i = 0;
LPSTR lpszBuffer;
// prepare the filter string
szFilter.LoadString( IDS_CERTIFICATE_FILTER );
// replace the "!" characters with nulls
lpszBuffer = szFilter.GetBuffer(MAX_PATH+1);
while( lpszBuffer[i] )
{
if ( lpszBuffer[i] == _T('!') )
lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose
i++;
}
// prep the dialog
cfdlg.m_ofn.lpstrFilter = lpszBuffer;
// run the dialog
if ( cfdlg.DoModal() == IDOK )
{
// get the password string
CConfirmPassDlg dlgconfirm;
if ( dlgconfirm.DoModal() == IDOK )
{
// tell the key to install the certificate
if ( pKey->FInstallCertificate( cfdlg.GetPathName(), dlgconfirm.m_szPassword ) )
{
pKey->OnProperties();
pKey->SetDirty( TRUE );
UpdateAllViews( NULL, HINT_None );
}
}
}
// release the buffer in the filter string
szFilter.ReleaseBuffer(-1);
}
catch ( CException e )
{
}
}
//----------------------------------------------------------------
void CKeyRingDoc::OnUpdateKeySaveRequest(CCmdUI* pCmdUI)
{
BOOL fEnable = FALSE;
CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem();
// quite a few conditions here, so do them one at a time
if ( pKey )
{
fEnable = pKey->IsKindOf(RUNTIME_CLASS(CKey));
if ( fEnable )
fEnable &= (pKey->m_cbCertificateRequest > 0);
if ( fEnable )
fEnable &= (pKey->m_pCertificateRequest != NULL);
}
// enable the item
pCmdUI->Enable( fEnable );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnKeySaveRequest()
{
CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem();
ASSERT( pKey );
ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) );
ASSERT( pKey->m_cbCertificateRequest );
ASSERT( pKey->m_pCertificateRequest );
// get the key name
CString szKeyName = pKey->GetName();
// make the default file name
CString szDefaultFile;
szDefaultFile = _T("C:\\");
szDefaultFile += szKeyName;
szDefaultFile += _T(".req");
CFileDialog cfdlg(FALSE, _T("*.req"), szDefaultFile);
CString szFilter;
WORD i = 0;
LPSTR lpszBuffer;
// prepare the filter string
szFilter.LoadString( IDS_REQUEST_FILTER );
// replace the "!" characters with nulls
lpszBuffer = szFilter.GetBuffer(MAX_PATH+1);
while( lpszBuffer[i] )
{
if ( lpszBuffer[i] == _T('!') )
lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose
i++;
}
// prep the dialog
cfdlg.m_ofn.lpstrFilter = lpszBuffer;
// run the dialog
if ( cfdlg.DoModal() == IDOK )
{
// output the request file
if ( !pKey->FOutputRequestFile(cfdlg.GetPathName()) )
{
AfxMessageBox( IDS_ERR_WRITEREQUEST );
}
else
{
// put up the user information box
CNewKeyInfoDlg dlg;
dlg.m_fNewKeyInfo = FALSE;
dlg.m_szRequestFile = cfdlg.GetPathName();
dlg.DoModal();
}
}
// release the buffer in the filter string
szFilter.ReleaseBuffer(60);
}
//----------------------------------------------------------------
void CKeyRingDoc::OnUpdateKeyImportKeyset(CCmdUI* pCmdUI)
{
CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
if ( pItem )
pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CService)) ||
pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
else
pCmdUI->Enable( FALSE );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnKeyImportKeyset()
{
CService* pService = (CService*)g_pTreeView->PGetSelectedItem();
ASSERT( pService );
ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) ||
pService->IsKindOf(RUNTIME_CLASS(CKey)));
// if the selection is a key, get the key's parent, which should be a service
if ( pService->IsKindOf(RUNTIME_CLASS(CKey)) )
{
pService = (CService*)pService->PGetParent();
ASSERT( pService );
ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) );
}
CString szPrivateKey;
CString szPublicKey;
// get the names of the key files
CImportDialog ImprtDlg;
if ( ImprtDlg.DoModal() != IDOK )
{
// exit because the user canceled
return;
}
// the user must also give a password
CConfirmPassDlg dlgconfirm;
if ( dlgconfirm.DoModal() != IDOK )
return;
try
{
// create the new import key object
CKey* pKey = pService->PNewKey();
// tell it to do the importing
if ( !pKey->FImportKeySetFiles(ImprtDlg.m_cstring_PrivateFile,
ImprtDlg.m_cstring_CertFile, dlgconfirm.m_szPassword) )
{
delete pKey;
return;
}
// make sure its name is untitled
CString szName;
szName.LoadString( IDS_UNTITLED );
pKey->SetName( szName );
// add the key to the service
pKey->FAddToTree( pService );
// make sure the key has a caption
pKey->UpdateCaption();
// set the dirty flag
pKey->SetDirty( TRUE );
// force properties dlg
pKey->OnProperties();
}
catch( CException e )
{
return;
}
}
//----------------------------------------------------------------
void CKeyRingDoc::OnUpdateKeyExportBackup(CCmdUI* pCmdUI)
{
CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
if ( pItem )
pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
else
pCmdUI->Enable( FALSE );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnKeyExportBackup()
{
CKey* pKey = (CKey*)g_pTreeView->PGetSelectedItem();
ASSERT( pKey );
ASSERT( pKey->IsKindOf(RUNTIME_CLASS(CKey)) );
CFileDialog cfdlg(FALSE, _T("*.key"));
CString szFilter;
WORD i = 0;
LPSTR lpszBuffer;
ASSERT(pKey);
if ( !pKey ) return;
// warn the user about security
if ( AfxMessageBox(IDS_KEYFILE_WARNING, MB_OKCANCEL|MB_ICONEXCLAMATION) == IDCANCEL )
return;
// prepare the filter string
szFilter.LoadString( IDS_KEY_FILE_TYPE );
// replace the "!" characters with nulls
lpszBuffer = szFilter.GetBuffer(MAX_PATH+1);
while( lpszBuffer[i] )
{
if ( lpszBuffer[i] == _T('!') )
lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose
i++;
}
// prep the dialog
cfdlg.m_ofn.lpstrFilter = lpszBuffer;
// run the dialog
if ( cfdlg.DoModal() == IDOK )
{
// tell the key to export itself
pKey->FImportExportBackupFile( cfdlg.GetPathName(), FALSE );
}
// release the buffer in the filter string
szFilter.ReleaseBuffer(60);
}
//----------------------------------------------------------------
void CKeyRingDoc::OnUpdateKeyImportBackup(CCmdUI* pCmdUI)
{
CTreeItem* pItem = g_pTreeView->PGetSelectedItem();
if ( pItem )
pCmdUI->Enable( pItem->IsKindOf(RUNTIME_CLASS(CService)) ||
pItem->IsKindOf(RUNTIME_CLASS(CKey)) );
else
pCmdUI->Enable( FALSE );
}
//----------------------------------------------------------------
void CKeyRingDoc::OnKeyImportBackup()
{
CService* pService = (CService*)g_pTreeView->PGetSelectedItem();
ASSERT( pService );
ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) ||
pService->IsKindOf(RUNTIME_CLASS(CKey)));
// if the selection is a key, get the key's parent, which should be a service
if ( pService->IsKindOf(RUNTIME_CLASS(CKey)) )
{
pService = (CService*)pService->PGetParent();
ASSERT( pService );
ASSERT( pService->IsKindOf(RUNTIME_CLASS(CService)) );
}
CFileDialog cfdlg(TRUE, _T("*.key") );
CString szFilter;
WORD i = 0;
LPSTR lpszBuffer;
// make sure we are ok
if ( !pService )
return;
// prepare the filter string
szFilter.LoadString( IDS_KEY_FILE_TYPE );
// replace the "!" characters with nulls
lpszBuffer = szFilter.GetBuffer(MAX_PATH+1);
while( lpszBuffer[i] )
{
if ( lpszBuffer[i] == _T('!') )
lpszBuffer[i] = _T('\0'); // yes, set \0 on purpose
i++;
}
// prep the dialog
cfdlg.m_ofn.lpstrFilter = lpszBuffer;
// run the dialog
if ( cfdlg.DoModal() == IDOK )
{
try
{
// create the new import key object
CKey* pKey = pService->PNewKey();
// tell it to do the importing
if ( !pKey->FImportExportBackupFile(cfdlg.GetPathName(), TRUE) )
{
delete pKey;
return;
}
// add the key to the service
pKey->FAddToTree( pService );
// make sure the key has a caption
pKey->UpdateCaption();
// set the dirty flag
pKey->SetDirty( TRUE );
// if there is no Certificate then we can't install on a server.
// so don't try to force the Properties dialog
if ( pKey->m_cbCertificate ) // force properties dlg
{
pKey->OnProperties();
}
}
catch( CException e )
{
return;
}
}
}
//----------------------------------------------------------------
BOOL CKeyRingDoc::CanCloseFrame(CFrameWnd* pFrame)
{
// if we are dirty, ask the user what to do - they can cancel here
if ( m_fDirty )
{
switch( AfxMessageBox(IDS_SERVER_COMMIT, MB_YESNOCANCEL|MB_ICONQUESTION) )
{
case IDYES: // yes, they do want to commit
// commit all the servers
ASSERT(g_pTreeView);
g_pTreeView->FCommitMachinesNow();
break;
case IDNO: // no, they don't want to commit
break;
case IDCANCEL: // whoa nellie! Stop this
return FALSE;
}
}
// make a note in the user registry of which machines we are logged into so we
// administer them again later
StoreConnectedMachines();
// of course we can close the frame
return TRUE;
}