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.
 
 
 
 
 
 

656 lines
19 KiB

// sscope.cpp
//
// Superscope dialogs.
// - Create Superscope Dialog
// - Superscope Properties Dialog
//
// HISTORY
// 10-Nov-96 t-danmo Creation
//
#include "stdafx.h"
#include "sscope.h"
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CCreateSuperscopeDlg dialog (created by t-danmo)
//
CCreateSuperscopeDlg::CCreateSuperscopeDlg(CWnd* pParent /*=NULL*/)
: CDialog(CCreateSuperscopeDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CCreateSuperscopeDlg)
//}}AFX_DATA_INIT
}
void CCreateSuperscopeDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CCreateSuperscopeDlg)
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CCreateSuperscopeDlg, CDialog)
//{{AFX_MSG_MAP(CCreateSuperscopeDlg)
ON_EN_CHANGE(IDC_EDIT_SUPERSCOPE_NAME, OnChangeEditSuperscopeName)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
BOOL CCreateSuperscopeDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the caption of the dialog
SetWindowTextPrintf(m_hWnd, IDS_s_CREATE_SUPERSCOPE,
m_pHostName->FIsLocalHost() ? (LPCSTR)theApp.m_str_Local : (LPCSTR)m_pHostName->PszGetHostName());
SendDlgItemMessage(IDC_EDIT_SUPERSCOPE_NAME, EM_LIMITTEXT, cchSuperscopeNameMax);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
void CCreateSuperscopeDlg::OnOK()
{
CDialog::OnOK();
}
void CCreateSuperscopeDlg::OnChangeEditSuperscopeName()
{
GetDlgItemText(IDC_EDIT_SUPERSCOPE_NAME, OUT m_strSuperscopeName);
m_strSuperscopeName.TrimLeft();
m_strSuperscopeName.TrimRight();
::EnableWindow(::GetDlgItem(m_hWnd, IDOK), !m_strSuperscopeName.IsEmpty());
}
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// CSuperscopesDlg dialog
//
CSuperscopesDlg::CSuperscopesDlg(CWnd* pParent /*=NULL*/)
: CDialog(CSuperscopesDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CSuperscopesDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_pHostName = NULL;
m_paLbScopes = NULL;
m_paSuperscopes = NULL;
m_pSuperscopeSelect = NULL;
}
/////////////////////////////////////////////////////////////////////////////
CSuperscopesDlg::~CSuperscopesDlg()
{
delete m_paLbScopes;
delete m_paSuperscopes;
}
/////////////////////////////////////////////////////////////////////////////
// Add a scope into a listbox. Return zero-based index to the newly added scope.
INT
CSuperscopesDlg::AddLbScopeItem(CListBox& rListbox, CLbScopeEntry * pLbScopeEntry)
{
ASSERT(pLbScopeEntry != NULL);
INT i = rListbox.AddString(pLbScopeEntry->m_strDisplayName);
ASSERT(i >= 0);
// Set the lParam field of the newly added item
INT j = rListbox.SetItemDataPtr(i, pLbScopeEntry);
ASSERT(j != LB_ERR);
return i;
}
/////////////////////////////////////////////////////////////////////////////
void
CSuperscopesDlg::RemoveLbScopeItem(CListBox& rListbox, INT iListboxItem)
{
rListbox.DeleteString(iListboxItem);
}
/////////////////////////////////////////////////////////////////////////////
// Search the linked-list of superscopes to find a match
// with the superscope name.
// Return NULL if no match found
//
CSuperscopeEntry *
CSuperscopesDlg::PFindSuperscopeEntry(WCHAR wszSupescopeName[])
{
Assert(wszSupescopeName != NULL);
for (CSuperscopeEntry * pSuperscope = m_paSuperscopes;
pSuperscope != NULL;
pSuperscope = pSuperscope->m_pNext)
{
if (0 == lstrcmpiW(pSuperscope->m_wszSuperscopeName, wszSupescopeName))
{
return pSuperscope;
}
} // for
// No match
return NULL;
} // PFindSuperscopeEntry()
/////////////////////////////////////////////////////////////////////////////
// Initialize the superscope dialog data.
//
// 1. Find out which host (server) is selected in the listbox.
// 2. Enumerate the available scopes for the selected host.
// 3. Get the superscopes for the selected host.
//
// Return FALSE if an error occured.
//
// INTERFACE NOTES
// This code is very fragile and highly depends on the UI implementation.
// I have not find any way to enumerate the scopes for a given host
// except by looking into the listbox.
//
// HISTORY
// 13-Nov-96 t-danmo Creation.
//
BOOL
CSuperscopesDlg::FInit(CScopesDlg * pScopesDlg)
{
Assert(pScopesDlg != NULL);
int iCurSel = LB_ERR;
// Get the current selected host on the listbox
m_pHostName = pScopesDlg->QueryCurrentSelectedHost(OUT &iCurSel);
Assert(m_pHostName != NULL);
Assert(iCurSel >= 0);
// Find out all the scopes for the given host (DHCP Server)
// This code was *inspired* from CScopesDlg::CloseHost()
while (TRUE)
{
CLBScope * pScope = (CLBScope *)pScopesDlg->m_list_scopes.GetItemDataPtr(++iCurSel);
Assert(pScope != NULL);
if (pScope == NULL || (int)pScope == LB_ERR)
{
// We have reached the end of list
break;
}
if (!pScope->IsScope())
{
// Listbox item is not a scope, therefore it is a host, so stop here
break;
}
Assert(pScope->QueryDhcpScope() != NULL);
if (pScope->QueryDhcpScope() == NULL)
{
continue; // Just in case
}
// Add the scope to the linked list
CLbScopeEntry * pLbScopeEntry = new CLbScopeEntry(pScope->QueryDhcpScope());
pLbScopeEntry->m_pNext = m_paLbScopes;
m_paLbScopes = pLbScopeEntry;
} // while
// Now get the superscopes
theApp.BeginWaitCursor();
theApp.UpdateStatusBar(IDS_STATUS_GETTING_SUPERSCOPE_INFO);
BOOL f = FBuildSuperscopeList();
theApp.UpdateStatusBar();
theApp.EndWaitCursor();
return f;
} // CSuperscopesDlg::FInit()
/////////////////////////////////////////////////////////////////////////////
// Build a linked list of superscopes for a given DHCP server.
//
// Return FALSE if an error occured.
//
BOOL
CSuperscopesDlg::FBuildSuperscopeList()
{
APIERR err;
DHCP_SUPER_SCOPE_TABLE * paSuperscopeTable = NULL; // Pointer to allocated table
DHCP_SUPER_SCOPE_TABLE_ENTRY * pSuperscopeTableEntry; // Pointer to a single entry in array
err = ::DhcpGetSuperScopeInfoV4(
m_pHostName->QueryWcName(),
OUT &paSuperscopeTable);
if (err != ERROR_SUCCESS)
{
Assert(paSuperscopeTable == NULL);
TRACE1("DhcpGetSuperScopeInfoV4() failed. err=%u.\n", err);
ReportDhcpError(err);
return FALSE;
}
if (paSuperscopeTable == NULL)
{
Assert(FALSE);
return FALSE; // Just in case
}
pSuperscopeTableEntry = paSuperscopeTable->pEntries;
if (pSuperscopeTableEntry == NULL && paSuperscopeTable->cEntries != 0)
{
Assert(FALSE);
return FALSE; // Just in case
}
for (int iSuperscopeEntry = paSuperscopeTable->cEntries;
iSuperscopeEntry > 0;
iSuperscopeEntry--, pSuperscopeTableEntry++)
{
if (pSuperscopeTableEntry->SuperScopeName == NULL)
{
// The API list all the scopes, not just scopes that are members of a superscope.
// You can tell if a scope is a member of a superscope by looking at the SuperScopeName.
// If its NULL, the scope is not a member of a superscope.
continue; // Skip this table entry
}
CSuperscopeEntry * pSuperscope;
// Try to find if the superscope name already exists
pSuperscope = PFindSuperscopeEntry(pSuperscopeTableEntry->SuperScopeName);
if (pSuperscope == NULL)
{
// Allocate a new superscope object
pSuperscope = new CSuperscopeEntry;
pSuperscope->m_pNext = m_paSuperscopes;
m_paSuperscopes = pSuperscope;
lstrcpyW(OUT pSuperscope->m_wszSuperscopeName, pSuperscopeTableEntry->SuperScopeName);
strcpyAnsiFromUnicode(OUT pSuperscope->m_szSuperscopeName, pSuperscopeTableEntry->SuperScopeName);
}
else
{
// Otherwise keep it
}
// Now check if any scope matches (belongs) to the superscope
for (CLbScopeEntry * pLbScopeEntry = m_paLbScopes;
pLbScopeEntry != NULL;
pLbScopeEntry = pLbScopeEntry->m_pNext)
{
// Check if we have a match with the subnet addresses
if (pLbScopeEntry->m_dwScopeAddress == pSuperscopeTableEntry->SubnetAddress)
{
Assert(pLbScopeEntry->m_pSuperscopeOwner == NULL && "Scope already has an owner");
pLbScopeEntry->m_pSuperscopeOwner = pSuperscope;
pLbScopeEntry->m_pSuperscopeOwnerPrevious = pSuperscope;
}
} // for
} // for
// Free the memory
::DhcpRpcFreeMemory(paSuperscopeTable);
return TRUE;
} // FBuildSuperscopeList()
/////////////////////////////////////////////////////////////////////////////
// Write the modified superscopes back into the registry
BOOL
CSuperscopesDlg::FUpdateSuperscopes()
{
APIERR err = ERROR_SUCCESS;
theApp.BeginWaitCursor();
for (CLbScopeEntry * pLbScopeEntry = m_paLbScopes;
pLbScopeEntry != NULL;
pLbScopeEntry = pLbScopeEntry->m_pNext)
{
CSuperscopeEntry * pSuperscopeOwnerNew = pLbScopeEntry->m_pSuperscopeOwner;
CSuperscopeEntry * pSuperscopeOwnerPrev = pLbScopeEntry->m_pSuperscopeOwnerPrevious;
// Check if the scope has changed ownership
if (pSuperscopeOwnerNew == pSuperscopeOwnerPrev)
{
// No, so skip it.
continue;
}
APIERR errT; // Temporary error code
if (pSuperscopeOwnerPrev != NULL)
{
// Remove the scope from its previous superscope owner
errT = ::DhcpSetSuperScopeV4(
m_pHostName->QueryWcName(),
pLbScopeEntry->m_dwScopeAddress,
pSuperscopeOwnerNew->m_wszSuperscopeName,
TRUE /* fRemoveScope */);
if (errT != ERROR_SUCCESS)
{
TRACE1("DhcpSetSuperScopeV4() failed. err=%u.\n", errT);
err = errT;
break;
}
// Success, so the the ownership is now changed
pLbScopeEntry->m_pSuperscopeOwner = pSuperscopeOwnerPrev;
} // if
if (pSuperscopeOwnerNew != NULL)
{
// Add the scope to its new superscope owner
errT = ::DhcpSetSuperScopeV4(
m_pHostName->QueryWcName(),
pLbScopeEntry->m_dwScopeAddress,
pSuperscopeOwnerNew->m_wszSuperscopeName,
FALSE /* fRemoveScope */);
if (errT != ERROR_SUCCESS)
{
TRACE1("DhcpSetSuperScopeV4() failed. err=%u.\n", errT);
err = errT;
break;
}
pLbScopeEntry->m_pSuperscopeOwner = pSuperscopeOwnerPrev;
} // if
} // for
theApp.EndWaitCursor();
if (err != ERROR_SUCCESS)
{
ReportDhcpError(err);
return FALSE;
}
return TRUE;
} // FUpdateSuperscopes()
/////////////////////////////////////////////////////////////////////////////
void CSuperscopesDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CSuperscopesDlg)
DDX_Control(pDX, IDC_COMBO_SUPERSCOPES, m_comboboxSuperscopes);
DDX_Control(pDX, IDC_LIST_AVAILABLE_SCOPE, m_listboxScopesAvail);
DDX_Control(pDX, IDC_LIST_SCOPE_CHILD, m_listboxScopesChild);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CSuperscopesDlg, CDialog)
//{{AFX_MSG_MAP(CSuperscopesDlg)
ON_CBN_SELCHANGE(IDC_COMBO_SUPERSCOPES, OnSelchangeComboSelectSuperscope)
ON_BN_CLICKED(IDC_BUTTON_NEW, OnButtonNewSuperscope)
ON_BN_CLICKED(IDC_BUTTON_DELETE, OnButtonDeleteSuperscope)
ON_BN_CLICKED(IDC_BUTTON_ADD, OnButtonAddScope)
ON_BN_CLICKED(IDC_BUTTON_REMOVE, OnButtonRemoveScope)
ON_LBN_SETFOCUS(IDC_LIST_AVAILABLE_SCOPE, OnSetfocusListAvailableScopes)
ON_LBN_SETFOCUS(IDC_LIST_SCOPE_CHILD, OnSetfocusListChildScopes)
ON_LBN_DBLCLK(IDC_LIST_AVAILABLE_SCOPE, OnDblclkListAvailableScopes)
ON_LBN_DBLCLK(IDC_LIST_SCOPE_CHILD, OnDblclkListChildScopes)
ON_LBN_SELCHANGE(IDC_LIST_AVAILABLE_SCOPE, OnSelchangeListAvailableScopes)
ON_LBN_SELCHANGE(IDC_LIST_SCOPE_CHILD, OnSelchangeListChildScopes)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CSuperscopesDlg message handlers
BOOL CSuperscopesDlg::OnInitDialog()
{
CDialog::OnInitDialog();
Assert(m_pHostName != NULL);
// Set the caption of the dialog
SetWindowTextPrintf(m_hWnd, IDS_s_SUPERSCOPE_PROPERTIES,
m_pHostName->FIsLocalHost() ? (LPCSTR)theApp.m_str_Local : (LPCSTR)m_pHostName->PszGetHostName());
// Fill in the superscope combobox
for (CSuperscopeEntry * pSuperscope = m_paSuperscopes;
pSuperscope != NULL;
pSuperscope = pSuperscope->m_pNext)
{
INT i = m_comboboxSuperscopes.AddString(pSuperscope->m_szSuperscopeName);
Report(i >= 0);
m_comboboxSuperscopes.SetItemDataPtr(i, pSuperscope);
}
// Select the first entry in combobox
m_comboboxSuperscopes.SetCurSel(0);
// Notify the dialog the selection has changed
OnSelchangeComboSelectSuperscope();
// Add any 'free' scope to the listbox
for (CLbScopeEntry * pLbScopeEntry = m_paLbScopes;
pLbScopeEntry != NULL;
pLbScopeEntry = pLbScopeEntry->m_pNext)
{
if (pLbScopeEntry->m_pSuperscopeOwner == NULL)
{
AddLbScopeItem(m_listboxScopesAvail, pLbScopeEntry);
}
} // for
return TRUE;
} // CSuperscopesDlg::OnInitDialog()
// When a superscope is selected, we need to update
// the child listbox.
void CSuperscopesDlg::OnSelchangeComboSelectSuperscope()
{
// Find out which superscope was selected
m_pSuperscopeSelect = (CSuperscopeEntry *)ComboBox_GetSelectedItemData(m_comboboxSuperscopes.m_hWnd);
Assert(m_pSuperscopeSelect != (CSuperscopeEntry *)CB_ERR);
m_listboxScopesChild.ResetContent();
if (m_pSuperscopeSelect == NULL)
{
EnableDlgItem(IDC_BUTTON_DELETE, FALSE);
return;
}
EnableDlgItem(IDC_BUTTON_DELETE, TRUE);
// Add any scope that belong to the superscope to the 'child' listbox
for (CLbScopeEntry * pLbScopeEntry = m_paLbScopes;
pLbScopeEntry != NULL;
pLbScopeEntry = pLbScopeEntry->m_pNext)
{
if (pLbScopeEntry->m_pSuperscopeOwner == m_pSuperscopeSelect)
{
AddLbScopeItem(m_listboxScopesChild, pLbScopeEntry);
}
} // for
} // OnSelchangeComboSelectSuperscope()
// Create a new superscope for the given host
void CSuperscopesDlg::OnButtonNewSuperscope()
{
CCreateSuperscopeDlg dlg;
dlg.m_pHostName = m_pHostName;
if (dlg.DoModal() != IDOK)
return;
Assert(!dlg.m_strSuperscopeName.IsEmpty());
// Search if the superscope name already exists
int i = m_comboboxSuperscopes.FindString(-1, dlg.m_strSuperscopeName);
if (i >= 0)
{
m_comboboxSuperscopes.SetCurSel(i);
MessageBoxPrintf(IDS_s_SUPERSCOPE_ALREADY_EXISTS, MB_OK | MB_ICONEXCLAMATION,
(LPCTSTR)dlg.m_strSuperscopeName);
return;
}
CSuperscopeEntry * pSuperscope = new CSuperscopeEntry;
pSuperscope->m_pNext = m_paSuperscopes;
m_paSuperscopes = pSuperscope;
lstrcpy(OUT pSuperscope->m_szSuperscopeName, dlg.m_strSuperscopeName);
// Make a unicode string out of the name
strcpyUnicodeFromAnsi(OUT pSuperscope->m_wszSuperscopeName, pSuperscope->m_szSuperscopeName);
i = m_comboboxSuperscopes.AddString(pSuperscope->m_szSuperscopeName);
Report(i >= 0);
m_comboboxSuperscopes.SetItemDataPtr(i, pSuperscope);
// Select the new superscope
m_comboboxSuperscopes.SetCurSel(i);
// Notify the dialog the selection has changed
OnSelchangeComboSelectSuperscope();
} // OnButtonNewSuperscope()
// Delete existing superscope from the given host
void CSuperscopesDlg::OnButtonDeleteSuperscope()
{
if (m_pSuperscopeSelect == NULL)
{
Assert(FALSE && "No superscope selected");
return; // Just in case
}
CString str;
LoadStringPrintf(IDS_s_SUPERSCOPE_DELETE, OUT &str, m_pSuperscopeSelect->m_szSuperscopeName);
if (IDYES != AfxMessageBox(str, MB_YESNOCANCEL | MB_ICONQUESTION))
{
return;
}
// Remove (detach) all the child scopes before deleting
// the superscope.
CLbScopeEntry * pLbScopeEntry;
while (TRUE)
{
// Get next scope from listbox.
pLbScopeEntry = (CLbScopeEntry *)m_listboxScopesChild.GetItemDataPtr(0);
Assert(pLbScopeEntry != NULL);
if ((int)pLbScopeEntry == LB_ERR || pLbScopeEntry == NULL)
{
// We have depleted the listbox, so we are done
break;
}
RemoveLbScopeItem(m_listboxScopesChild, 0);
AddLbScopeItem(m_listboxScopesAvail, pLbScopeEntry);
Assert(pLbScopeEntry->m_pSuperscopeOwner == m_pSuperscopeSelect);
pLbScopeEntry->m_pSuperscopeOwner = NULL; // No owner anymore
}
INT iCurSel = m_comboboxSuperscopes.GetCurSel();
Assert(iCurSel >= 0);
Assert(m_pSuperscopeSelect == (CSuperscopeEntry *)ComboBox_GetSelectedItemData(m_comboboxSuperscopes.m_hWnd));
m_comboboxSuperscopes.DeleteString(iCurSel);
// Select the next in combobox
m_comboboxSuperscopes.SetCurSel(0);
// Notify the dialog the selection has changed
OnSelchangeComboSelectSuperscope();
}
/////////////////////////////////////////////////////////////////////
// Add the selected scope to the superscope
void CSuperscopesDlg::OnButtonAddScope()
{
if (m_pSuperscopeSelect == NULL)
return;
int iCurSel; // Index of current selected item
CLbScopeEntry * pLbScopeEntry;
pLbScopeEntry = (CLbScopeEntry *)ListBox_GetSelectedItemData(
m_listboxScopesAvail.m_hWnd, OUT &iCurSel);
if (pLbScopeEntry == NULL)
return;
// Remove the scope from the 'available listbox'
RemoveLbScopeItem(m_listboxScopesAvail, iCurSel);
Assert(pLbScopeEntry->m_pSuperscopeOwner == NULL);
// Add the scope to the 'child listbox'
pLbScopeEntry->m_pSuperscopeOwner = m_pSuperscopeSelect;
iCurSel = AddLbScopeItem(m_listboxScopesChild, pLbScopeEntry);
m_listboxScopesChild.SetCurSel(iCurSel);
m_listboxScopesChild.SetFocus();
} // CSuperscopesDlg::OnButtonAddScope()
/////////////////////////////////////////////////////////////////////
// Remove the selected scope from the child listbox
void CSuperscopesDlg::OnButtonRemoveScope()
{
if (m_pSuperscopeSelect == NULL)
return;
int iCurSel; // Index of current selected item
CLbScopeEntry * pLbScopeEntry;
pLbScopeEntry = (CLbScopeEntry *)ListBox_GetSelectedItemData(
m_listboxScopesChild.m_hWnd, OUT &iCurSel);
if (pLbScopeEntry == NULL)
return;
// Remove the scope from the 'child listbox'
RemoveLbScopeItem(m_listboxScopesChild, iCurSel);
Assert(pLbScopeEntry->m_pSuperscopeOwner == m_pSuperscopeSelect);
// Add the scope to the 'available listbox'
pLbScopeEntry->m_pSuperscopeOwner = NULL;
iCurSel = AddLbScopeItem(m_listboxScopesAvail, pLbScopeEntry);
m_listboxScopesAvail.SetCurSel(iCurSel);
m_listboxScopesAvail.SetFocus();
} // CSuperscopesDlg::OnButtonRemoveScope()
/////////////////////////////////////////////////////////////////////////////
void
CSuperscopesDlg::UpdateUI()
{
OnSelchangeListAvailableScopes();
OnSelchangeListChildScopes();
}
void
CSuperscopesDlg::EnableDlgItem(INT nIdDlgItem, BOOL fEnable)
{
Assert(::IsWindow(::GetDlgItem(m_hWnd, nIdDlgItem)));
::EnableWindow(::GetDlgItem(m_hWnd, nIdDlgItem), fEnable);
}
/////////////////////////////////////////////////////////////////////
void CSuperscopesDlg::OnSelchangeListAvailableScopes()
{
EnableDlgItem(IDC_BUTTON_ADD, m_pSuperscopeSelect != NULL && m_listboxScopesAvail.GetCurSel() >= 0);
}
void CSuperscopesDlg::OnSetfocusListAvailableScopes()
{
// Clear the selection of the 'child listbox'
m_listboxScopesChild.SetCurSel(-1);
UpdateUI();
}
void CSuperscopesDlg::OnDblclkListAvailableScopes()
{
OnButtonAddScope();
}
/////////////////////////////////////////////////////////////////////
void CSuperscopesDlg::OnSelchangeListChildScopes()
{
EnableDlgItem(IDC_BUTTON_REMOVE, m_listboxScopesChild.GetCurSel() >= 0);
}
void CSuperscopesDlg::OnSetfocusListChildScopes()
{
// Clear the selection of the 'available listbox'
m_listboxScopesAvail.SetCurSel(-1);
UpdateUI();
}
void CSuperscopesDlg::OnDblclkListChildScopes()
{
OnButtonRemoveScope();
}
/////////////////////////////////////////////////////////////////////
void CSuperscopesDlg::OnOK()
{
theApp.BeginWaitCursor();
theApp.UpdateStatusBar(IDS_STATUS_UPDATING_SUPERSCOPE_INFO);
BOOL f = FUpdateSuperscopes();
theApp.UpdateStatusBar();
theApp.EndWaitCursor();
if (f)
CDialog::OnOK();
}