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.
1133 lines
33 KiB
1133 lines
33 KiB
// SERVER.CPP
|
|
|
|
#include "common.h"
|
|
|
|
#define mskTraceLocalDebug 0x00010000
|
|
|
|
CRITICAL_SECTION g_CriticalSection;
|
|
|
|
#ifdef STRESS
|
|
BOOL g_fDbgRunningStress = FALSE;
|
|
TCHAR g_szDbgStressServer[128] = _W"t_danm_1";
|
|
#endif // STRESS
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Keys to store into the registry
|
|
const TCHAR szRegServerCount[] = _W"ServerCount";
|
|
const TCHAR szRegServerFmt[] = _W"Server%03d";
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CServerList::CServerList()
|
|
{
|
|
m_iid = IID_CServerList;
|
|
m_fAutoRefresh = FALSE;
|
|
m_cRefreshThreads = 2;
|
|
m_cOutstandingRunningThreads = 0;
|
|
m_hwndThreadTerminateNotify = NULL;
|
|
InitializeCriticalSection(&g_CriticalSection);
|
|
} // CServerList::CServerList
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CServerList::~CServerList()
|
|
{
|
|
Assert(m_pFirstChild == NULL);
|
|
DeleteCriticalSection(&g_CriticalSection);
|
|
} // CServerList::~CServerList
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ITreeItem::IID CServerList::QueryInterface() const
|
|
{
|
|
Assert(m_iid == IID_CServerList);
|
|
return IID_CServerList;
|
|
} // CServerList::QueryInterface
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServerList::OnSetFocus()
|
|
{
|
|
StatusBar.SetPaneText(szNull);
|
|
HelperMgr.SetHelperDialog(DlgServerListHelper.m_hWnd);
|
|
} // CServerList::OnSetFocus
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServerList::OnRButtonClick(POINT * pptMouse)
|
|
{
|
|
Assert(pptMouse != NULL);
|
|
DoContextMenu(iContextMenu_ServerList, *pptMouse);
|
|
} // CServerList::OnRButtonClick
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServerList::OnLButtonDblClk(POINT * pptMouse)
|
|
{
|
|
UNREF(pptMouse);
|
|
} // CServerList::OnLButtonDblClk
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServerList::OnUpdateMenuUI(HMENU hmenu)
|
|
{
|
|
EnableMenuItemV(IDM_SERVER_ADDSERVER);
|
|
if (m_pFirstChild)
|
|
{
|
|
EnableMenuItemV(IDM_SERVERLIST_REFRESH);
|
|
EnableMenuItemV(IDM_REFRESHITEM);
|
|
}
|
|
} // CServerList::OnUpdateMenuUI
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CServerList::FOnMenuCommand(UINT wCmdId)
|
|
{
|
|
switch (wCmdId)
|
|
{
|
|
case IDM_SERVERLIST_REFRESH:
|
|
case IDM_REFRESHITEM:
|
|
RefreshAll();
|
|
break;
|
|
|
|
case IDM_VK_INSERT:
|
|
case IDM_SERVER_ADDSERVER:
|
|
CServer::DlgAddServer(this);
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
} // CServerList::FOnMenuCommand
|
|
|
|
#ifdef DEBUG
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServerList::AssertValid(UINT uFlags) const
|
|
{
|
|
ITreeItem * pChild;
|
|
|
|
Assert(m_iid == IID_CServerList);
|
|
Assert(m_iid == QueryInterface());
|
|
if (uFlags & AV_mskfCheckNone)
|
|
return;
|
|
Assert(m_pParent == NULL);
|
|
pChild = m_pFirstChild;
|
|
while (pChild != NULL)
|
|
{
|
|
Assert(pChild->QueryInterface() == IID_CServer);
|
|
Assert((CServerList *)pChild->m_pParent == this);
|
|
if (uFlags & AV_mskfCheckRecursive)
|
|
pChild->AssertValid(uFlags);
|
|
pChild = pChild->m_pNextSibling;
|
|
}
|
|
if (uFlags & AV_mskfCheckMinimum)
|
|
return;
|
|
Assert(m_hti != NULL);
|
|
} // CServerList::AssertValid
|
|
#endif // DEBUG
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CServerList::FInit()
|
|
//
|
|
BOOL CServerList::FInit(TCHAR szName[])
|
|
{
|
|
TV_INSERTSTRUCT tvInsert;
|
|
|
|
tvInsert.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_PARAM;
|
|
tvInsert.item.pszText = szName;
|
|
tvInsert.item.lParam = (LPARAM)this;
|
|
tvInsert.item.iImage = CTreeView::iImageRoot;
|
|
tvInsert.item.iSelectedImage = CTreeView::iImageRoot;
|
|
tvInsert.hInsertAfter = TVI_SORT;
|
|
tvInsert.hParent = TVI_ROOT;
|
|
// Insert the item into the tree.
|
|
m_hti = TreeView.HtiInsertItem(&tvInsert);
|
|
Report(m_hti != NULL);
|
|
if (m_hti == NULL)
|
|
return FALSE;
|
|
if (!DlgServerListHelper.FCreate() ||
|
|
!DlgServerHelper.FCreate() ||
|
|
!DlgZoneHelper.FCreate())
|
|
return FALSE;
|
|
// Populate the list found in the Registry
|
|
ReadConfig();
|
|
TreeView.ExpandItem(m_hti);
|
|
// Fire AutoRefresh on StartUp
|
|
//if (m_pFirstChild != NULL)
|
|
// RefreshAll();
|
|
return TRUE;
|
|
} // CServerList::FInit
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServerList::Flush()
|
|
{
|
|
TreeView.SetFocus(m_hti);
|
|
DebugCode( AssertValid(AV_mskfCheckMaximum | AV_mskfCheckRecursive); )
|
|
while (m_pFirstChild != NULL)
|
|
{
|
|
Assert(m_pFirstChild->QueryInterface() == IID_CServer);
|
|
CServer * p = (CServer *)m_pFirstChild;
|
|
m_pFirstChild = p->m_pNextSibling;
|
|
if (!p->FIsLocked())
|
|
delete p;
|
|
#ifdef DEBUG
|
|
else
|
|
{
|
|
Trace1(mskTraceInfo | mskTraceMemFailures,
|
|
"\nINFO: CServerList::Flush() - Object \"%s\" is locked in memory. "
|
|
"Not allowed to delete object; memory leaks expected.", p->PchGetName());
|
|
}
|
|
#endif // DEBUG
|
|
} // while
|
|
} // CServerList::Flush
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServerList::SaveServerInfo()
|
|
{
|
|
|
|
// TreeView.SetFocus(m_hti);
|
|
DebugCode( AssertValid(AV_mskfCheckMaximum | AV_mskfCheckRecursive); )
|
|
CServer * p = (CServer *)m_pFirstChild;
|
|
while (p != NULL) {
|
|
Assert(p->QueryInterface() == IID_CServer);
|
|
p->Save();
|
|
p = (CServer *)p->m_pNextSibling;
|
|
} // while
|
|
} // CServerList::SaveServerInfo
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServerList::RefreshAll()
|
|
{
|
|
CServer * pServer;
|
|
|
|
m_fAutoRefresh = TRUE;
|
|
Trace1(mskTraceThread, "\nTHREAD: ServerList.RefreshAll() using %d thread(s)...", m_cRefreshThreads);
|
|
if (m_pFirstChild != NULL) {
|
|
// Set the servers to the "Ready To Connect" state
|
|
pServer = (CServer *)m_pFirstChild;
|
|
while (pServer != NULL)
|
|
{
|
|
if (!pServer->FIsLocked())
|
|
{
|
|
pServer->m_dwFlags |= CServer::mskfReadyToConnect;
|
|
pServer->UpdateUI();
|
|
}
|
|
pServer = (CServer *)pServer->m_pNextSibling;
|
|
}
|
|
// Start refreshing cRefreshThreads servers
|
|
Assert(m_cRefreshThreads > 0);
|
|
// Get the first UI Child
|
|
Assert(TreeView_GetChild(TreeView.m_hWnd, m_hti) != NULL);
|
|
pServer = (CServer *)TreeView.PTreeItemFromHti(TreeView_GetChild(TreeView.m_hWnd, m_hti));
|
|
Assert(pServer != NULL);
|
|
Assert(pServer->QueryInterface() == IID_CServer);
|
|
int cRefreshThread = m_cRefreshThreads;
|
|
while (pServer != NULL)
|
|
{
|
|
Trace2(mskTraceLocalDebug, "\nTHREAD: RefreshAll() - Object %s %s",
|
|
pServer->PchGetName(), pServer->FIsLocked() ? "(Locked)" : "(StandBy)");
|
|
if (!pServer->FIsLocked())
|
|
{
|
|
pServer->Refresh();
|
|
if (--cRefreshThread <= 0)
|
|
break;
|
|
}
|
|
pServer = (CServer *)TreeView.PNextSiblingFromHti(pServer->m_hti);
|
|
} // while
|
|
}
|
|
} // CServerList::RefreshAll
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServerList::RefreshStats()
|
|
{
|
|
CServer * pServer;
|
|
|
|
m_fAutoRefresh = TRUE;
|
|
if (m_pFirstChild != NULL) {
|
|
pServer = (CServer *)TreeView.PGetFocus();
|
|
if (pServer == NULL) { // no focus was found, oh well, i give up...
|
|
return;
|
|
}
|
|
Assert(pServer != NULL);
|
|
if (pServer->QueryInterface() != IID_CServer) {
|
|
return;
|
|
}
|
|
Assert(pServer->QueryInterface() == IID_CServer);
|
|
Trace1(mskTraceThread,
|
|
"\nTHREAD: ServerList.RefreshStats(%s)...",
|
|
pServer->m_szName);
|
|
|
|
EnterCriticalSection(&g_CriticalSection);
|
|
if (pServer->FIsLocked())
|
|
{
|
|
Trace2(mskTraceAlways,
|
|
"\nTHREAD: CRITICAL SECTION: Object %s is locked into memory %s",
|
|
pServer->PchGetName(),
|
|
(pServer->m_dwFlags & CServer::mskfConnecting) ? _W" (Connecting)" : "");
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
Assert(pServer->m_pParent != NULL);
|
|
pServer->m_dwFlags &= ~(CServer::mskfConnecting);
|
|
return;
|
|
}
|
|
pServer->m_dwFlags |= CServer::mskfConnecting;
|
|
pServer->LockServer();
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
|
|
// ----------------------------------------------------------GetStatistics()
|
|
if (pServer->m_pStatistics != NULL) {
|
|
Free (pServer->m_pStatistics);
|
|
}
|
|
|
|
pServer->m_pStatistics = (DNS_STATISTICS *)
|
|
Malloc(sizeof(DNS_STATISTICS));
|
|
Report(pServer->m_pStatistics != NULL);
|
|
if (pServer->m_pStatistics != NULL)
|
|
{
|
|
|
|
Trace1(mskTraceDNSVerbose, "\n - DnsGetStatistics(%s)...",
|
|
pServer->PchGetName());
|
|
pServer->m_err = ::DnsGetStatistics(pServer->m_szName,
|
|
OUT &pServer->m_pStatistics);
|
|
if (pServer->m_err)
|
|
{
|
|
Trace3(mskTraceDNS,
|
|
"\nERR: DnsGetStatistics(%s) error code = 0x%08X (%d)",
|
|
pServer->PchGetName(), pServer->m_err, pServer->m_err);
|
|
|
|
DnsReportError(pServer->m_err);
|
|
Free(pServer->m_pStatistics);
|
|
pServer->m_pStatistics = NULL;
|
|
pServer->m_dwFlags |= CServer::mskfFailedToConnect;
|
|
|
|
}
|
|
else
|
|
{
|
|
Assert(pServer->m_pStatistics != NULL);
|
|
pServer->m_dwFlags &= ~(CServer::mskfConnecting);
|
|
}
|
|
} // if
|
|
pServer->UpdateUI();
|
|
pServer->UnlockServer();
|
|
}
|
|
} // CServerList::RefreshStats
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServerList::RefreshDone(CServer * pServer)
|
|
{
|
|
Assert(pServer != NULL);
|
|
ReportFSz1(!pServer->FIsLocked(), "Object %s should not be locked anymore", pServer->PchGetName());
|
|
Assert(m_cOutstandingRunningThreads >= 0);
|
|
if (m_hwndThreadTerminateNotify != NULL)
|
|
LSendMessage(m_hwndThreadTerminateNotify, UN_THREADTERMINATED, (WPARAM)pServer, 0);
|
|
if (m_fAutoRefresh)
|
|
{
|
|
while (TRUE)
|
|
{
|
|
pServer = (CServer *)TreeView.PNextSiblingFromHti(pServer->m_hti);
|
|
if (pServer == NULL)
|
|
{
|
|
m_fAutoRefresh = FALSE;
|
|
Trace0(mskTraceThread, "\nTHREAD: ServerList.RefreshAll() - Done.");
|
|
StatusBar.SetText(IDS_READY);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEBUG
|
|
Trace1(mskTraceLocalDebug, "\nTHREAD: RefreshDone() - Object %s ", pServer->PchGetName());
|
|
if (pServer->FIsLocked())
|
|
{
|
|
if (pServer->m_dwFlags & CServer::mskfConnecting)
|
|
Trace0(mskTraceLocalDebug, "(Connecting)");
|
|
else
|
|
Trace0(mskTraceLocalDebug, "(Locked)");
|
|
}
|
|
else if ((pServer->m_dwFlags & CServer::mskfReadyToConnect) == 0)
|
|
Trace0(mskTraceLocalDebug, "(AlreadyConnected)");
|
|
#endif // DEBUG
|
|
if ((pServer->m_dwFlags & CServer::mskfReadyToConnect) && !pServer->FIsLocked())
|
|
{
|
|
Trace0(mskTraceLocalDebug, "(StandBy)");
|
|
pServer->Refresh();
|
|
return;
|
|
}
|
|
} // if...else
|
|
} // while
|
|
} // if
|
|
else
|
|
StatusBar.SetText(IDS_READY);
|
|
} // CServerList::RefreshDone
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServerList::ReadConfig()
|
|
{
|
|
TCHAR szKey[LENGTH(szRegServerFmt) + 16];
|
|
TCHAR szServerName[CServer::cchNameMax];
|
|
int i = 0;
|
|
|
|
// Get the count of servers names
|
|
RegReadInt(IN szRegServerCount, OUT i);
|
|
while (i > 0)
|
|
{
|
|
wsprintf(szKey, szRegServerFmt, --i);
|
|
if (RegReadSz(szKey, szServerName, sizeof(szServerName)))
|
|
{
|
|
(void)FTrimString(szServerName);
|
|
if (szServerName[0])
|
|
{
|
|
(void)new CServer(this, szServerName);
|
|
ReportFSz(m_pFirstChild != NULL, "Out of memory");
|
|
}
|
|
else
|
|
{
|
|
Trace1(mskTraceInfo, "\nINFO: Registry key %s is empty", szKey);
|
|
}
|
|
} // if
|
|
} // while
|
|
} // CServerList::ReadConfig
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServerList::SaveConfig()
|
|
{
|
|
CServer * pServer;
|
|
TCHAR szKey[LENGTH(szRegServerFmt) + 16];
|
|
int i = 0;
|
|
|
|
AssertValid();
|
|
pServer = (CServer *)m_pFirstChild;
|
|
while (pServer)
|
|
{
|
|
DebugCode( pServer->AssertValid(); )
|
|
wsprintf(szKey, szRegServerFmt, i++);
|
|
RegWriteSz(szKey, pServer->PchGetName());
|
|
pServer = (CServer *)pServer->m_pNextSibling;
|
|
}
|
|
RegWriteInt(szRegServerCount, i);
|
|
} // CServerList::SaveConfig
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CServer::CServer(CServerList * pParent, const TCHAR szName[])
|
|
{
|
|
Assert(lstrlen(szName) < LENGTH(m_szName));
|
|
lstrcpyn(m_szName, szName, LENGTH(m_szName));
|
|
|
|
m_iid = IID_CServer;
|
|
m_dwFlags = mskfReadyToConnect;
|
|
m_hti = NULL;
|
|
m_pParent = NULL;
|
|
m_pFirstChild = NULL;
|
|
m_pNextSibling = NULL;
|
|
m_cLockCount = 0;
|
|
m_pServerInfo = NULL;
|
|
m_pStatistics = NULL;
|
|
m_err = 0;
|
|
if (pParent != NULL)
|
|
Attach(pParent);
|
|
} // CServer::CServer
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CServer::~CServer()
|
|
{
|
|
// We should not delete a server is it is locked into memory
|
|
AssertSz1(!FIsLocked(),
|
|
"Object %s is locked in memory (probably by a still running thread)", PchGetName());
|
|
// Delete all the children
|
|
delete m_pFirstChild;
|
|
DebugCode( m_pFirstChild = NULL; )
|
|
Free(m_pStatistics);
|
|
if (m_pServerInfo)
|
|
DnsFreeServerInfo(m_pServerInfo);
|
|
if (m_hti)
|
|
TreeView.DeleteItem(m_hti); // Detach the server from the UI
|
|
GarbageInit(this, sizeof(*this));
|
|
} // CServer::~CServer
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
ITreeItem::IID CServer::QueryInterface() const
|
|
{
|
|
Assert(m_iid == IID_CServer);
|
|
return IID_CServer;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServer::OnSetFocus()
|
|
{
|
|
m_dwFlags |= mskfGotFocus;
|
|
UpdateUI();
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServer::OnKillFocus()
|
|
{
|
|
m_dwFlags &= ~mskfGotFocus;
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServer::OnRButtonClick(POINT * pptMouse)
|
|
{
|
|
Assert(pptMouse != NULL);
|
|
DoContextMenu(iContextMenu_Server, *pptMouse);
|
|
} // CServer::OnRButtonClick
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServer::OnLButtonDblClk(POINT * pptMouse)
|
|
{
|
|
UNREF(pptMouse);
|
|
Report(m_dwFlags & mskfGotFocus);
|
|
if (m_dwFlags & (mskfRpcDataValid | mskfConnecting))
|
|
return;
|
|
if (m_dwFlags & mskfReadyToConnect)
|
|
goto DoRefresh;
|
|
if (m_dwFlags & mskfFailedToConnect)
|
|
{
|
|
if (IDYES != MsgBoxPrintf(
|
|
IDS_MSG_s_SERVERRETRYCONNECT,
|
|
szCaptionApp,
|
|
MB_ICONQUESTION | MB_YESNOCANCEL,
|
|
m_szName)
|
|
)
|
|
return;
|
|
}
|
|
DoRefresh:
|
|
Refresh();
|
|
} // CServer::OnLButtonDblClk
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServer::OnUpdateMenuUI(HMENU hmenu)
|
|
{
|
|
if (m_dwFlags & mskfRpcDataValid)
|
|
EnableMenuItemV(IDM_ZONE_CREATENEWZONE);
|
|
if (!FIsLocked())
|
|
{
|
|
EnableMenuItemV(IDM_SERVER_REFRESH);
|
|
EnableMenuItemV(IDM_REFRESHITEM);
|
|
EnableMenuItemV(IDM_SERVER_DELETESERVER);
|
|
EnableMenuItemV(IDM_DELETEITEM);
|
|
if(m_pServerInfo != NULL)
|
|
{
|
|
EnableMenuItemV(IDM_SERVER_PROPERTIES);
|
|
EnableMenuItemV(IDM_PROPERTIES);
|
|
}
|
|
}
|
|
} // OnUpdateMenuUI
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CServer::FOnMenuCommand(UINT wCmdId)
|
|
{
|
|
switch (wCmdId)
|
|
{
|
|
case IDM_VK_INSERT:
|
|
case IDM_ZONE_CREATENEWZONE:
|
|
{
|
|
CZoneWiz ZoneWiz;
|
|
ZoneWiz.DoWizard(this);
|
|
}
|
|
break;
|
|
|
|
case IDM_SERVER_REFRESH:
|
|
case IDM_REFRESHITEM:
|
|
Refresh();
|
|
break;
|
|
|
|
case IDM_SERVER_ADDSERVER:
|
|
DlgAddServer((CServerList *)m_pParent);
|
|
break;
|
|
|
|
case IDM_VK_DELETE:
|
|
case IDM_DELETEITEM:
|
|
case IDM_SERVER_DELETESERVER:
|
|
DlgDeleteServer();
|
|
break;
|
|
|
|
case IDM_PROPERTIES:
|
|
case IDM_SERVER_PROPERTIES:
|
|
DlgProperties();
|
|
break;
|
|
|
|
case IDM_FLUSH_SERVER:
|
|
Save();
|
|
break;
|
|
default:
|
|
return FALSE;
|
|
} // switch
|
|
|
|
return TRUE;
|
|
} // FOnMenuCommand
|
|
|
|
|
|
#ifdef DEBUG
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServer::AssertValid(UINT uFlags) const
|
|
{
|
|
ITreeItem * pChild;
|
|
|
|
Assert(m_iid == IID_CServer);
|
|
Assert(m_iid == QueryInterface());
|
|
if (uFlags & AV_mskfCheckNone)
|
|
return;
|
|
pChild = m_pFirstChild;
|
|
while (pChild != NULL)
|
|
{
|
|
Assert(pChild->QueryInterface() == IID_CZoneRootDomain);
|
|
Assert((CServer *)pChild->m_pParent == this);
|
|
if (uFlags & AV_mskfCheckRecursive)
|
|
pChild->AssertValid(uFlags);
|
|
pChild = pChild->m_pNextSibling;
|
|
}
|
|
Assert(m_cLockCount >= 0);
|
|
if (m_pParent)
|
|
Assert(m_pParent->QueryInterface() == IID_CServerList);
|
|
if (m_dwFlags & mskfRpcDataValid)
|
|
Assert(m_pServerInfo != NULL);
|
|
if (m_dwFlags & mskfConnecting)
|
|
Assert(FIsLocked());
|
|
if (uFlags & AV_mskfCheckMinimum)
|
|
return;
|
|
Assert(m_pParent != NULL);
|
|
Assert(m_hti != NULL);
|
|
} // CServer::AssertValid
|
|
#endif // DEBUG
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServer::Attach(CServerList * pParent)
|
|
{
|
|
Assert(pParent != NULL);
|
|
SetParent(pParent);
|
|
AddTreeViewItem(m_szName, CTreeView::iImageServerStandBy);
|
|
} // Attach
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServer::Detach()
|
|
{
|
|
DebugCode( AssertValid(AV_mskfCheckMaximum); )
|
|
Assert(!FIsLocked());
|
|
// Delete children
|
|
delete m_pFirstChild;
|
|
m_pFirstChild = NULL;
|
|
// Detach the server from the TreeView
|
|
TreeView.DeleteItem(m_hti);
|
|
m_hti = NULL;
|
|
// Detach the server from its family (parent and sibling)
|
|
Assert(m_pParent != NULL);
|
|
m_pParent->DetachChild(this);
|
|
Assert(m_pParent == NULL);
|
|
} // Detach
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// ThreadProcGetServerInfo()
|
|
//
|
|
// Get the server info and enumerate the zones for the given server.
|
|
// If an error occur, the error code will stored in pServer and will
|
|
// displayed by CDlgServerHelper.
|
|
//
|
|
DWORD CServer::ThreadProcGetServerInfo(CServer * pServer)
|
|
{
|
|
UINT i;
|
|
DWORD dwZoneCount = 0;
|
|
PDNS_ZONE_INFO rgpZoneInfo[DNS_MAX_ENUM_ZONE_INFO] = { 0 };
|
|
|
|
Assert(pServer != NULL);
|
|
Assert(pServer->QueryInterface() == IID_CServer);
|
|
Assert((pServer->m_dwFlags & mskfRpcDataValid) == 0);
|
|
Assert(pServer->m_dwFlags & mskfConnecting);
|
|
Assert(pServer->m_pFirstChild == NULL);
|
|
AssertSz(pServer->FIsLocked(), "Object must be locked in memory");
|
|
AssertSz(FIsZeroInit(rgpZoneInfo, sizeof(rgpZoneInfo)),
|
|
"Block must be filled with zeroes (This is required by DnsEnumZoneInfo() API)");
|
|
Assert(pServer->m_pParent->QueryInterface() == IID_CServerList);
|
|
((CServerList *)pServer->m_pParent)->m_cOutstandingRunningThreads++;
|
|
|
|
// ----------------------------------------------------------GetStatistics()
|
|
Assert(pServer->m_pStatistics == NULL);
|
|
|
|
Trace2(mskTraceDNSVerbose,
|
|
"\n - DnsGetStatistics(%s) Malloc for %ld...",
|
|
pServer->PchGetName(), sizeof(DNS_STATISTICS));
|
|
pServer->m_pStatistics = (DNS_STATISTICS *)
|
|
Malloc(sizeof(DNS_STATISTICS));
|
|
Report(pServer->m_pStatistics != NULL);
|
|
if (pServer->m_pStatistics != NULL)
|
|
{
|
|
|
|
Trace1(mskTraceDNSVerbose, "\n - DnsGetStatistics(%s)...",
|
|
pServer->PchGetName());
|
|
pServer->m_err = ::DnsGetStatistics(pServer->m_szName,
|
|
OUT &pServer->m_pStatistics);
|
|
if (pServer->m_err)
|
|
{
|
|
Trace3(mskTraceDNS,
|
|
"\nERR: DnsGetStatistics(%s) error code = 0x%08X (%d)",
|
|
pServer->PchGetName(), pServer->m_err, pServer->m_err);
|
|
|
|
DnsReportError(pServer->m_err);
|
|
Free(pServer->m_pStatistics);
|
|
pServer->m_pStatistics = NULL;
|
|
pServer->m_dwFlags |= mskfFailedToConnect;
|
|
goto End;
|
|
|
|
}
|
|
else
|
|
{
|
|
Assert(pServer->m_pStatistics != NULL);
|
|
}
|
|
} // if
|
|
|
|
// ----------------------------------------------------------GetServerInfo()
|
|
Assert(pServer->m_pServerInfo == NULL);
|
|
Trace1(mskTraceDNSVerbose, "\n - DnsGetServerInfo(%s)...", pServer->PchGetName());
|
|
pServer->m_err = ::DnsGetServerInfo(pServer->m_szName, OUT &pServer->m_pServerInfo);
|
|
if (pServer->m_err)
|
|
{
|
|
Trace3(mskTraceDNS,
|
|
"\nERR: DnsGetServerInfo(%s) error code = 0x%08X (%d)",
|
|
pServer->PchGetName(), pServer->m_err, pServer->m_err);
|
|
DnsReportError(pServer->m_err);
|
|
AssertSz3(pServer->m_pServerInfo == NULL,
|
|
"DnsGetServerInfo(%s) returned err= 0x%08X (%d) with pServerInfo!=NULL",
|
|
pServer->PchGetName(), pServer->m_err, pServer->m_err);
|
|
if ((pServer->m_err == ERROR_ACCESS_DENIED) &&
|
|
(pServer->m_pStatistics != NULL)) {
|
|
pServer->m_dwFlags |= mskfAdminAccessDenied;
|
|
goto End;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
AssertSz1(pServer->m_pServerInfo != NULL,
|
|
"DnsGetServerInfo(%s) returned err=ERROR_SUCCESS but pServerInfo==NULL",
|
|
pServer->PchGetName());
|
|
}
|
|
|
|
// ----------------------------------------------------------DnsEnumZoneInfo()
|
|
Trace1(mskTraceDNSVerbose, "\n - DnsEnumZoneInfo(%s)...",
|
|
pServer->m_szName);
|
|
pServer->m_err = ::DnsEnumZoneInfo(pServer->m_szName,
|
|
OUT &dwZoneCount,
|
|
LENGTH(rgpZoneInfo), rgpZoneInfo);
|
|
ReportFSz(dwZoneCount < LENGTH(rgpZoneInfo),
|
|
"Buffer rgpZoneInfo is too small!!!");
|
|
|
|
if (pServer->m_err)
|
|
{
|
|
Trace3(mskTraceDNS,
|
|
"\nERR: DnsEnumZoneInfo(%s) error code = 0x%08X (%d)",
|
|
pServer->m_szName, pServer->m_err, pServer->m_err);
|
|
DnsReportError(pServer->m_err);
|
|
if (pServer->m_err != ERROR_MORE_DATA)
|
|
{
|
|
if ((pServer->m_err == ERROR_ACCESS_DENIED) &&
|
|
(pServer->m_pStatistics != NULL)) {
|
|
pServer->m_dwFlags |= mskfAdminAccessDenied;
|
|
goto End;
|
|
}
|
|
pServer->m_dwFlags |= mskfFailedToConnect;
|
|
goto End;
|
|
}
|
|
else
|
|
{
|
|
Assert(dwZoneCount > LENGTH(rgpZoneInfo));
|
|
}
|
|
}
|
|
for (i = 0; i < dwZoneCount && i < LENGTH(rgpZoneInfo); i++)
|
|
{
|
|
Assert(rgpZoneInfo[i] != NULL);
|
|
if (rgpZoneInfo[i] != NULL)
|
|
{
|
|
if ((dnsoptions.fShowAutoCreateZones == FALSE) &&
|
|
(rgpZoneInfo[i]->fAutoCreated)) {
|
|
Trace1 (mskTraceDNS,
|
|
"ThreadProcGetServerInfo: omitting Auto-Created Zone: %s.",
|
|
rgpZoneInfo[i]->pszZoneName);
|
|
;
|
|
} else {
|
|
SideReport(new CZoneRootDomain(pServer,
|
|
rgpZoneInfo[i]));
|
|
}
|
|
}
|
|
} // for
|
|
|
|
|
|
pServer->m_dwFlags |= mskfRpcDataValid;
|
|
if (pServer->m_dwFlags & mskfExpandBranch) {
|
|
TreeView.ExpandItem(pServer->m_hti);
|
|
}
|
|
|
|
End:
|
|
|
|
pServer->m_dwFlags &= ~mskfConnecting;
|
|
pServer->UnlockServer();
|
|
pServer->UpdateUI();
|
|
((CServerList *)pServer->m_pParent)->m_cOutstandingRunningThreads--;
|
|
((CServerList *)pServer->m_pParent)->RefreshDone(pServer);
|
|
#ifdef STRESS
|
|
if (!g_fDbgRunningStress)
|
|
OutputDebugString("\nThreadProcGetServerInfo() - ");
|
|
#endif // STRESS
|
|
return 0;
|
|
} // CServer::ThreadProcGetServerInfo
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServer::UpdateUI()
|
|
{
|
|
int iImage;
|
|
int ids;
|
|
|
|
if (m_dwFlags & mskfConnecting)
|
|
iImage = CTreeView::iImageServerConnecting;
|
|
else if (m_dwFlags & mskfReadyToConnect)
|
|
iImage = CTreeView::iImageServerStandBy;
|
|
else if (m_dwFlags & mskfFailedToConnect)
|
|
iImage = CTreeView::iImageServerError;
|
|
else
|
|
{
|
|
iImage = CTreeView::iImageServerOK;
|
|
}
|
|
SetTreeViewImage(iImage);
|
|
if ((m_dwFlags & mskfGotFocus) == 0)
|
|
return;
|
|
if (m_dwFlags & mskfConnecting)
|
|
ids = IDS_STATUSPANE_CONNECTING;
|
|
else if (m_dwFlags & mskfFailedToConnect)
|
|
{
|
|
ReportFSz(m_err != ERROR_SUCCESS, "How can this happen???");
|
|
if (m_err == RPC_S_SERVER_UNAVAILABLE) {
|
|
ids = IDS_STATUSPANE_SERVERUNAVAILABLE;
|
|
} else {
|
|
ids = IDS_STATUSPANE_CONNECTIONERROR;
|
|
}
|
|
}
|
|
else {
|
|
ids = IDS_NONE;
|
|
}
|
|
if (m_err == ERROR_ACCESS_DENIED) {
|
|
ids = IDS_STATUSPANE_ACCESSDENIED;
|
|
}
|
|
|
|
StatusBar.SetPaneText(ids);
|
|
DlgServerHelper.UpdateUI(this);
|
|
} // UpdateUI
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServer::Refresh()
|
|
{
|
|
AssertValid();
|
|
EnterCriticalSection(&g_CriticalSection);
|
|
if (FIsLocked())
|
|
{
|
|
Trace2(mskTraceAlways,
|
|
"\nTHREAD: CRITICAL SECTION: Object %s is locked into memory %s",
|
|
PchGetName(),
|
|
(m_dwFlags & mskfConnecting) ? _W" (Connecting)" : "");
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
Assert(m_pParent != NULL);
|
|
((CServerList *)m_pParent)->RefreshDone(this);
|
|
return;
|
|
}
|
|
m_dwFlags |= mskfConnecting;
|
|
LockServer();
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
#ifdef STRESS
|
|
if (!g_fDbgRunningStress)
|
|
#endif // STRESS
|
|
StatusBar.SetTextPrintf(IDS_STATUS_s_GETSERVERINFO, PchGetName());
|
|
Trace1(mskTraceDNS, "\nGetting server info for %s...", PchGetName());
|
|
UpdateUI();
|
|
if (m_pServerInfo)
|
|
{
|
|
DnsFreeServerInfo(m_pServerInfo);
|
|
m_pServerInfo = NULL;
|
|
}
|
|
// Clear a bunch of flags
|
|
m_dwFlags &= ~(mskfRpcDataValid | mskfFailedToConnect | mskfReadyToConnect | mskfIsDirty | mskfExpandBranch);
|
|
if (m_dwFlags & mskfGotFocus)
|
|
m_dwFlags |= mskfExpandBranch;
|
|
// Delete any previous zone
|
|
delete m_pFirstChild;
|
|
m_pFirstChild = NULL;
|
|
Free(m_pStatistics);
|
|
m_pStatistics = NULL;
|
|
|
|
#ifdef STRESS
|
|
if (g_fDbgRunningStress)
|
|
{
|
|
ThreadProcGetServerInfo(this);
|
|
return;
|
|
}
|
|
#endif // STRESS
|
|
HANDLE hThread;
|
|
DWORD dwThreadId;
|
|
hThread = CreateThread(
|
|
NULL, // lpSecurity
|
|
0, // cbStack
|
|
(LPTHREAD_START_ROUTINE)&ThreadProcGetServerInfo,
|
|
this, // pvParam
|
|
0, // dwCreate
|
|
OUT &dwThreadId);
|
|
Report(hThread != NULL);
|
|
SideReport(CloseHandle(hThread));
|
|
} // Refresh
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServer::DlgDeleteServer()
|
|
{
|
|
LockServer();
|
|
if (IDYES != MsgBoxPrintf(
|
|
IDS_MSG_s_DELETE_SERVER,
|
|
szCaptionApp,
|
|
MB_ICONQUESTION | MB_YESNO,
|
|
PchGetName()))
|
|
{
|
|
UnlockServer();
|
|
return;
|
|
}
|
|
UnlockServer();
|
|
EnterCriticalSection(&g_CriticalSection);
|
|
if (FIsLocked())
|
|
{
|
|
// This can happen if the server was connecting while the
|
|
// context menu was displayed
|
|
Trace1(mskTraceAlways,
|
|
"\nINFO: Object %s is locked in memory (server is still connecting)", PchGetName());
|
|
}
|
|
else
|
|
{
|
|
Detach();
|
|
delete this;
|
|
}
|
|
LeaveCriticalSection(&g_CriticalSection);
|
|
} // CServer::DlgDeleteServer
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServer::DlgProperties()
|
|
{
|
|
PROPSHEETPAGE rgpsp[3];
|
|
PROPSHEETHEADER psh;;
|
|
TCHAR szT[64 + cchNameMax];
|
|
|
|
AssertSz(m_iid == IID_CServer, "Wrong type cast for CServer");
|
|
LockServer();
|
|
|
|
GarbageInit(rgpsp, sizeof(rgpsp));
|
|
GarbageInit(&psh, sizeof(psh));
|
|
|
|
rgpsp[0].dwSize = sizeof(PROPSHEETPAGE);
|
|
rgpsp[0].dwFlags = 0;
|
|
rgpsp[0].hInstance = hInstanceSave;
|
|
rgpsp[0].pszTemplate = MAKEINTRESOURCE(IDD_SERVER_PROP_GENERAL);
|
|
rgpsp[0].pfnDlgProc = DlgProcPropGeneral;
|
|
|
|
rgpsp[1].dwSize = sizeof(PROPSHEETPAGE);
|
|
rgpsp[1].dwFlags = 0;
|
|
rgpsp[1].hInstance = hInstanceSave;
|
|
rgpsp[1].pszTemplate = MAKEINTRESOURCE(IDD_SERVER_PROP_FORWARDERS);
|
|
rgpsp[1].pfnDlgProc = DlgProcPropForwarders;
|
|
|
|
rgpsp[2].dwSize = sizeof(PROPSHEETPAGE);
|
|
rgpsp[2].dwFlags = 0;
|
|
rgpsp[2].hInstance = hInstanceSave;
|
|
rgpsp[2].pszTemplate = MAKEINTRESOURCE(IDD_SERVER_PROP_BOOTMETHOD);
|
|
rgpsp[2].pfnDlgProc = DlgProcPropBootMethod;
|
|
|
|
psh.dwSize = sizeof(PROPSHEETHEADER);
|
|
psh.dwFlags = PSH_PROPSHEETPAGE | PSH_NOAPPLYNOW;
|
|
psh.pszCaption = szT;
|
|
psh.hwndParent = hwndMain;
|
|
psh.hInstance = hInstanceSave;
|
|
psh.nStartPage = 0;
|
|
psh.nPages = LENGTH(rgpsp);
|
|
psh.ppsp = rgpsp;
|
|
|
|
LoadStringPrintf(IDS_s_SERVERPROP, szT, LENGTH(szT) - 30, PchGetName()) ;
|
|
if (m_pServerInfo == NULL)
|
|
CchLoadString(IDS_UNAVAILABLE_PP, szT + lstrlen(szT), 25);
|
|
Assert((m_dwFlags & mskfIsDirty) == 0);
|
|
Assert(s_pThis == NULL);
|
|
s_pThis = this;
|
|
(void)DoPropertySheet(&psh);
|
|
s_pThis = NULL;
|
|
UnlockServer();
|
|
if (m_dwFlags & mskfIsDirty)
|
|
Refresh();
|
|
} // CServer::DlgProperties
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServer::DlgAddServer(CServerList * pParent)
|
|
{
|
|
Assert(pParent);
|
|
Assert(s_pThis == NULL);
|
|
DoDialogBox(IDD_SERVER_ADDNEWSERVER, hwndMain, DlgProcAddServer);
|
|
if (s_pThis)
|
|
{
|
|
// Add new server
|
|
s_pThis->m_dwFlags |= mskfAttachToEnd;
|
|
s_pThis->Attach(pParent);
|
|
TreeView.ExpandItem(pParent->m_hti);
|
|
TreeView_SelectItem(TreeView.m_hWnd, s_pThis->m_hti);
|
|
s_pThis->Refresh();
|
|
s_pThis = NULL;
|
|
}
|
|
} // CServer::DlgAddServer
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Save()
|
|
//
|
|
// Get the server info and enumerate the zones for the given server.
|
|
// If an error occur, the error code will stored in pServer and will
|
|
// displayed by CDlgServerHelper.
|
|
//
|
|
|
|
DWORD CServer::Save()
|
|
{
|
|
UINT i;
|
|
DWORD dwZoneCount = 0;
|
|
DNS_HANDLE rgpZoneHandles[DNS_MAX_ENUM_ZONE_INFO] = { 0 };
|
|
|
|
Assert(QueryInterface() == IID_CServer);
|
|
AssertSz(FIsZeroInit(rgpZoneHandles, sizeof(rgpZoneHandles)),
|
|
"Block must be filled with zeroes (This is required by DnsEnumZoneInfo() API)");
|
|
Assert(m_pParent->QueryInterface() == IID_CServerList);
|
|
Trace1(mskTraceDNSVerbose, "\n - DnsEnumZoneHandles(%s)...",
|
|
m_szName);
|
|
if ((m_dwFlags & mskfRpcDataValid) == 0) {
|
|
return 0; // no connection, so can't save information
|
|
}
|
|
LockServer();
|
|
m_err = ::DnsEnumZoneHandles(m_szName,
|
|
OUT &dwZoneCount,
|
|
LENGTH(rgpZoneHandles),
|
|
rgpZoneHandles);
|
|
ReportFSz(dwZoneCount < LENGTH(rgpZoneHandles),
|
|
"Buffer rgpZoneHandles is too small!!!");
|
|
if (m_err)
|
|
{
|
|
Trace3(mskTraceDNS,
|
|
"\nERR: DnsEnumZoneHandles(%s) error code = 0x%08X (%d)",
|
|
m_szName, m_err, m_err);
|
|
DnsReportError(m_err);
|
|
if (m_err != ERROR_MORE_DATA)
|
|
{
|
|
m_dwFlags |= mskfFailedToConnect;
|
|
goto End;
|
|
}
|
|
else
|
|
{
|
|
Assert(dwZoneCount > LENGTH(rgpZoneHandles));
|
|
}
|
|
}
|
|
for (i = 0; i < dwZoneCount && i < LENGTH(rgpZoneHandles); i++)
|
|
{
|
|
Assert(rgpZoneHandles[i] != NULL);
|
|
if (rgpZoneHandles[i] != NULL) {
|
|
Trace1(mskTraceDNSVerbose, "\n - DnsIncrementZoneVersion(0x%08x)...",
|
|
rgpZoneHandles[i]);
|
|
m_err = DnsIncrementZoneVersion (m_szName,
|
|
rgpZoneHandles[i]);
|
|
if (m_err) {
|
|
Trace3(mskTraceDNS,
|
|
"\nERR: DnsIncrementZoneHandles(%s) error code = 0x%08X (%d)",
|
|
m_szName, m_err, m_err);
|
|
DnsReportError(m_err);
|
|
}
|
|
}
|
|
} // for
|
|
m_err = 0;
|
|
End:
|
|
UnlockServer();
|
|
return 0;
|
|
} // CServer::Save
|
|
|
|
|
|
#ifdef STRESS
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CALLBACK CServerList::DlgProcRunStress(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
UNREF(lParam);
|
|
FSetDlgItemText(hdlg, IDC_EDIT_SERVERNAME, g_szDbgStressServer);
|
|
SetCtrlDWordValue(HGetDlgItem(hdlg, IDC_EDIT_BUFFERSIZE), cbDnsRpcBufferAlloc);
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
if (!FGetCtrlDWordValue(
|
|
HGetDlgItem(hdlg, IDC_EDIT_BUFFERSIZE),
|
|
OUT (DWORD *)&cbDnsRpcBufferAlloc, 1, 1024*1024))
|
|
break;
|
|
CchGetDlgItemText(hdlg, IDC_EDIT_SERVERNAME,
|
|
g_szDbgStressServer, LENGTH(g_szDbgStressServer));
|
|
(void)FStripSpaces(g_szDbgStressServer);
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hdlg, wParam == IDOK);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
} // switch
|
|
|
|
return TRUE;
|
|
} // CServerList::DlgProcRunStress
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
void CServerList::RunStress()
|
|
{
|
|
TCHAR szT[32];
|
|
int cStressLoop = 0;
|
|
CServer * pServer = NULL;
|
|
|
|
if (IDOK != DoDialogBox(IDD_DEBUG_STRESS, hwndMain, DlgProcRunStress))
|
|
return;
|
|
g_fDbgRunningStress = TRUE;
|
|
while (TRUE)
|
|
{
|
|
StatusBar.SetText("Hold <Shift> to abort stress...");
|
|
wsprintf(szT, _W"Stress: %u", ++cStressLoop);
|
|
StatusBar.SetPaneText(szT);
|
|
UpdateWindow(hwndMain);
|
|
|
|
if (GetAsyncKeyState(VK_SHIFT) < 0)
|
|
{
|
|
if (pServer)
|
|
pServer->UpdateUI();
|
|
break;
|
|
}
|
|
Sleep(500);
|
|
if (pServer)
|
|
{
|
|
pServer->Detach();
|
|
delete pServer;
|
|
}
|
|
pServer = new CServer(this, g_szDbgStressServer);
|
|
ReportFSz(pServer != NULL, "Out of memory");
|
|
if (!pServer)
|
|
break;
|
|
TreeView.SetFocus(pServer->m_hti);
|
|
UpdateWindow(TreeView.m_hWnd);
|
|
pServer->Refresh();
|
|
} // while
|
|
|
|
g_fDbgRunningStress = FALSE;
|
|
StatusBar.SetText("Stress aborted");
|
|
} // CServerList::RunStress
|
|
|
|
#endif // STRESS
|