mirror of https://github.com/lianthony/NT4.0
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
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;
|
|
}
|
|
|