749 lines
24 KiB
C++
749 lines
24 KiB
C++
|
//Copyright (c) 1998 - 1999 Microsoft Corporation
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* domain.cpp
|
||
|
*
|
||
|
* implementation of the CDomain class
|
||
|
*
|
||
|
*
|
||
|
*******************************************************************************/
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "winadmin.h"
|
||
|
#include "admindoc.h"
|
||
|
#include "dialogs.h"
|
||
|
#include <malloc.h> // for alloca used by Unicode conversion macros
|
||
|
#include <mfc42\afxconv.h> // for Unicode conversion macros
|
||
|
static int _convert;
|
||
|
|
||
|
#include <winsta.h>
|
||
|
#include <regapi.h>
|
||
|
#include "..\..\inc\utilsub.h"
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#define new DEBUG_NEW
|
||
|
#undef THIS_FILE
|
||
|
static char THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
#define MIN_MAJOR_VERSION 4
|
||
|
#define MIN_MINOR_VERSION 0
|
||
|
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// CDomain Member Functions
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
CDomain::CDomain(TCHAR *name)
|
||
|
{
|
||
|
m_Flags = 0;
|
||
|
m_PreviousState = DS_NONE;
|
||
|
m_State = DS_NONE;
|
||
|
m_hTreeItem = NULL;
|
||
|
wcscpy(m_Name, name);
|
||
|
m_pBackgroundThread = NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
CDomain::~CDomain()
|
||
|
{
|
||
|
if(m_State == DS_ENUMERATING) StopEnumerating();
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void CDomain::SetState(DOMAIN_STATE state)
|
||
|
{
|
||
|
// remember the previous state
|
||
|
m_PreviousState = m_State;
|
||
|
|
||
|
m_State = state;
|
||
|
|
||
|
CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
|
||
|
|
||
|
CFrameWnd *p = (CFrameWnd*)pDoc->GetMainWnd();
|
||
|
if(p && ::IsWindow(p->GetSafeHwnd())) {
|
||
|
p->SendMessage(WM_ADMIN_UPDATE_DOMAIN, 0, (LPARAM)this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL CDomain::StartEnumerating()
|
||
|
{
|
||
|
BOOL bResult = FALSE;
|
||
|
|
||
|
LockBackgroundThread();
|
||
|
|
||
|
if( m_State == DS_ENUMERATING || m_State == DS_STOPPED_ENUMERATING )
|
||
|
{
|
||
|
UnlockBackgroundThread( );
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Fire off the background thread for this domain
|
||
|
|
||
|
if( m_pBackgroundThread == NULL )
|
||
|
{
|
||
|
DomainProcInfo *pProcInfo = new DomainProcInfo;
|
||
|
|
||
|
if( pProcInfo != NULL )
|
||
|
{
|
||
|
pProcInfo->pDomain = this;
|
||
|
pProcInfo->pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
|
||
|
m_BackgroundContinue = TRUE;
|
||
|
m_pBackgroundThread = AfxBeginThread((AFX_THREADPROC)CDomain::BackgroundThreadProc,
|
||
|
pProcInfo,
|
||
|
0,
|
||
|
CREATE_SUSPENDED,
|
||
|
NULL );
|
||
|
|
||
|
if( m_pBackgroundThread == NULL )
|
||
|
{
|
||
|
ODS( L"CDomain!StartEnumerating AfxBeginThread failed running low on resources\n" );
|
||
|
|
||
|
delete pProcInfo;
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
m_pBackgroundThread->m_bAutoDelete = FALSE;
|
||
|
|
||
|
if (m_pBackgroundThread->ResumeThread() <= 1)
|
||
|
{
|
||
|
bResult = TRUE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
UnlockBackgroundThread();
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
void CDomain::StopEnumerating()
|
||
|
{
|
||
|
// Tell the background thread to terminate and
|
||
|
// wait for it to do so.
|
||
|
LockBackgroundThread();
|
||
|
|
||
|
if(m_pBackgroundThread)
|
||
|
{
|
||
|
CWinThread *pBackgroundThread = m_pBackgroundThread;
|
||
|
HANDLE hThread = m_pBackgroundThread->m_hThread;
|
||
|
|
||
|
// Clear the pointer before releasing the lock
|
||
|
m_pBackgroundThread = NULL;
|
||
|
|
||
|
ClearBackgroundContinue( );
|
||
|
|
||
|
UnlockBackgroundThread();
|
||
|
|
||
|
// Wait for the thread's death
|
||
|
if(WaitForSingleObject(hThread, 1000) == WAIT_TIMEOUT)
|
||
|
{
|
||
|
TerminateThread(hThread, 0);
|
||
|
}
|
||
|
|
||
|
WaitForSingleObject(hThread, INFINITE);
|
||
|
|
||
|
// delete the CWinThread object
|
||
|
delete pBackgroundThread;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
UnlockBackgroundThread();
|
||
|
}
|
||
|
|
||
|
|
||
|
SetState(DS_STOPPED_ENUMERATING);
|
||
|
|
||
|
DBGMSG( L"%s stopped enumerating\n" , GetName( ) );
|
||
|
}
|
||
|
|
||
|
|
||
|
USHORT Buflength(LPWSTR buf)
|
||
|
{
|
||
|
LPWSTR p = buf;
|
||
|
USHORT length = 0;
|
||
|
|
||
|
while(*p) {
|
||
|
USHORT plength = wcslen(p) + 1;
|
||
|
length += plength;
|
||
|
p += plength;
|
||
|
}
|
||
|
|
||
|
return length;
|
||
|
|
||
|
} // end Buflength
|
||
|
|
||
|
|
||
|
LPWSTR ConcatenateBuffers(LPWSTR buf1, LPWSTR buf2)
|
||
|
{
|
||
|
// Make sure both buffer pointers are valid
|
||
|
if(!buf1 && !buf2) return NULL;
|
||
|
if(buf1 && !buf2) return buf1;
|
||
|
if(!buf1 && buf2) return buf2;
|
||
|
|
||
|
// figure out how big a buffer we'll need
|
||
|
USHORT buf1Length = Buflength(buf1);
|
||
|
USHORT buf2Length = Buflength(buf2);
|
||
|
USHORT bufsize = buf1Length + buf2Length + 1;
|
||
|
// allocate a buffer
|
||
|
LPWSTR pBuffer = (LPWSTR)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, bufsize * sizeof(WCHAR));
|
||
|
// If we can't allocate a buffer, free the second buffer and
|
||
|
// return the pointer to the first of the two buffers
|
||
|
if(!pBuffer) {
|
||
|
LocalFree(buf2);
|
||
|
return(buf1);
|
||
|
}
|
||
|
|
||
|
LPWSTR p = pBuffer;
|
||
|
// copy the contents of the first buffer into the new buffer
|
||
|
memcpy((char*)p, (char*)buf1, buf1Length * sizeof(WCHAR));
|
||
|
p += buf1Length;
|
||
|
// copy the contents of the second buffer into the new buffer
|
||
|
memcpy((char*)p, (char*)buf2, buf2Length * sizeof(WCHAR));
|
||
|
|
||
|
LocalFree(buf1);
|
||
|
LocalFree(buf2);
|
||
|
|
||
|
return pBuffer;
|
||
|
|
||
|
} // end ConcatenateBuffers
|
||
|
|
||
|
void CDomain::CreateServers(LPWSTR pBuffer, LPVOID _pDoc)
|
||
|
{
|
||
|
CWinAdminDoc *pDoc = (CWinAdminDoc*)_pDoc;
|
||
|
CWinAdminApp *pApp = (CWinAdminApp*)AfxGetApp();
|
||
|
|
||
|
LPWSTR pTemp = pBuffer;
|
||
|
|
||
|
// Loop through all the WinFrame servers that we found
|
||
|
while(*pTemp)
|
||
|
{
|
||
|
// The server's name is in pTemp
|
||
|
// Find the server in our list
|
||
|
CServer *pServer = pDoc->FindServerByName(pTemp);
|
||
|
// If the server is in our list, set the flag to say we found it
|
||
|
if(pServer)
|
||
|
{
|
||
|
pServer->SetBackgroundFound();
|
||
|
|
||
|
if( pServer->GetTreeItem( ) == NULL )
|
||
|
{
|
||
|
CFrameWnd *p = (CFrameWnd*)pDoc->GetMainWnd();
|
||
|
|
||
|
p->SendMessage(WM_ADMIN_ADD_SERVER, ( WPARAM )TVI_SORT, (LPARAM)pServer);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// We don't want to add the current Server again
|
||
|
if( lstrcmpi( pTemp , pApp->GetCurrentServerName() ) )
|
||
|
{
|
||
|
// Create a new server object
|
||
|
CServer *pNewServer = new CServer(this, pTemp, FALSE, pDoc->ShouldConnect(pTemp));
|
||
|
|
||
|
if(pNewServer != NULL )
|
||
|
{
|
||
|
// Add the server object to our linked list
|
||
|
pDoc->AddServer(pNewServer);
|
||
|
|
||
|
// Set the flag to say we found it
|
||
|
pNewServer->SetBackgroundFound();
|
||
|
|
||
|
CFrameWnd *p = (CFrameWnd*)pDoc->GetMainWnd();
|
||
|
|
||
|
if(p && ::IsWindow(p->GetSafeHwnd()))
|
||
|
{
|
||
|
p->SendMessage(WM_ADMIN_ADD_SERVER, ( WPARAM )TVI_SORT, (LPARAM)pNewServer);
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
// Go to the next server in the buffer
|
||
|
pTemp += (wcslen(pTemp) + 1);
|
||
|
} // end while (*pTemp)
|
||
|
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CDomain::BackgroundThreadProc
|
||
|
//
|
||
|
// Static member function for background thread
|
||
|
// Looks for servers appearing and disappearing
|
||
|
// Called with AfxBeginThread
|
||
|
// Thread terminates when function returns
|
||
|
//
|
||
|
UINT CDomain::BackgroundThreadProc(LPVOID bg)
|
||
|
{
|
||
|
// We need a pointer to the document so we can make
|
||
|
// calls to member functions
|
||
|
CWinAdminDoc *pDoc = (CWinAdminDoc*)((DomainProcInfo*)bg)->pDoc;
|
||
|
CDomain *pDomain = ((DomainProcInfo*)bg)->pDomain;
|
||
|
delete bg;
|
||
|
|
||
|
CWinAdminApp *pApp = (CWinAdminApp*)AfxGetApp();
|
||
|
|
||
|
// We want to keep track of whether or not we've enumerated - so
|
||
|
// that we can update the tree when we're done
|
||
|
BOOL bNotified = FALSE;
|
||
|
|
||
|
// We can't send messages to the view until they're ready
|
||
|
// v-nicbd RESOLVED In case we are exiting tsadmin, we are waiting uselessly here
|
||
|
// - 500ms lapsed is negligible in UI
|
||
|
while( !pDoc->AreAllViewsReady() )
|
||
|
{
|
||
|
Sleep(500);
|
||
|
}
|
||
|
|
||
|
// Don't do this until the views are ready!
|
||
|
pDomain->SetState(DS_INITIAL_ENUMERATION);
|
||
|
|
||
|
// If there is an extension DLL loaded, we will allow it to enumerate
|
||
|
// additional servers
|
||
|
LPFNEXENUMERATEPROC EnumerateProc = pApp->GetExtEnumerationProc();
|
||
|
|
||
|
// The first time we enumerate servers, we want the CServer object
|
||
|
// to put the server in the views when it has enough info.
|
||
|
// On subsequent enumerations, we will add the server to the views
|
||
|
// here.
|
||
|
BOOL bSubsequent = FALSE;
|
||
|
|
||
|
while(pDomain->ShouldBackgroundContinue())
|
||
|
{
|
||
|
|
||
|
BOOL Enumerated = FALSE;
|
||
|
|
||
|
CObList TempServerList;
|
||
|
|
||
|
DBGMSGx( L"CDomain!BackgroundThreadProc %s still going thread %d\n" , pDomain->GetName( ) , GetCurrentThreadId( ) );
|
||
|
|
||
|
// Loop through all the servers and turn off the flag
|
||
|
// that tells this thread that he found it on this pass
|
||
|
pDoc->LockServerList();
|
||
|
CObList *pServerList = pDoc->GetServerList();
|
||
|
|
||
|
POSITION pos = pServerList->GetHeadPosition();
|
||
|
|
||
|
while(pos)
|
||
|
{
|
||
|
POSITION pos2 = pos;
|
||
|
|
||
|
CServer *pServer = (CServer*)pServerList->GetNext(pos);
|
||
|
|
||
|
if(pServer->GetDomain() == pDomain)
|
||
|
{
|
||
|
pServer->ClearBackgroundFound();
|
||
|
|
||
|
// We want to remove a server if we could see it
|
||
|
// the last time we enumerated servers
|
||
|
// NOTE: This should not cause any problems
|
||
|
// The views should no longer have items pointing
|
||
|
// to this server at this point
|
||
|
//
|
||
|
// Move the server object to a temporary list.
|
||
|
// This is so that we can unlock the server list before
|
||
|
// we call the destructor on a CServer object since the
|
||
|
// destructor will end up calling SetState() which does
|
||
|
// a SendMessage. This is not good to do with the list
|
||
|
// locked.
|
||
|
|
||
|
if(pServer->IsServerInactive() && !pServer->IsCurrentServer())
|
||
|
{
|
||
|
pServer = (CServer*)pServerList->GetAt(pos2);
|
||
|
// Remove it from the server list
|
||
|
DBGMSG( L"Adding %s to temp list to destroy\n" , pServer->GetName( ) );
|
||
|
|
||
|
pServerList->RemoveAt(pos2);
|
||
|
// Add it to our temporary list
|
||
|
TempServerList.AddTail(pServer);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pDoc->UnlockServerList();
|
||
|
|
||
|
// do a first loop to signal the servers' background threads that they must stop
|
||
|
pos = TempServerList.GetHeadPosition();
|
||
|
while(pos)
|
||
|
{
|
||
|
CServer *pServer = (CServer*)TempServerList.GetNext(pos);
|
||
|
|
||
|
DBGMSG( L"Clearing %s backgrnd cont\n", pServer->GetName() );
|
||
|
|
||
|
pServer->ClearBackgroundContinue();
|
||
|
}
|
||
|
// do a second loop to disconnect and delete the servers
|
||
|
pos = TempServerList.GetHeadPosition();
|
||
|
|
||
|
while(pos)
|
||
|
{
|
||
|
CServer *pServer = (CServer*)TempServerList.GetNext(pos);
|
||
|
|
||
|
DBGMSG( L"Disconnecting and deleteing %s now!!!\n", pServer->GetName( ) );
|
||
|
|
||
|
pServer->Disconnect( );
|
||
|
|
||
|
delete pServer;
|
||
|
|
||
|
ODS( L"gone.\n" );
|
||
|
}
|
||
|
|
||
|
TempServerList.RemoveAll();
|
||
|
|
||
|
// Make sure we don't have to quit
|
||
|
if(!pDomain->ShouldBackgroundContinue())
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Get all the Servers now (we already got the current server)
|
||
|
LPWSTR pBuffer = NULL;
|
||
|
|
||
|
// Find all WinFrame servers in the domain
|
||
|
pBuffer = pDomain->EnumHydraServers(/*pDomain->GetName(),*/ MIN_MAJOR_VERSION, MIN_MINOR_VERSION);
|
||
|
|
||
|
// Make sure we don't have to quit
|
||
|
if(!pDomain->ShouldBackgroundContinue())
|
||
|
{
|
||
|
if(pBuffer) LocalFree(pBuffer);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Make sure we don't have to quit
|
||
|
if(!pDomain->ShouldBackgroundContinue())
|
||
|
{
|
||
|
if(pBuffer) LocalFree(pBuffer);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if(pBuffer) {
|
||
|
Enumerated = TRUE;
|
||
|
|
||
|
pDomain->CreateServers(pBuffer, (LPVOID)pDoc);
|
||
|
|
||
|
LocalFree(pBuffer);
|
||
|
} // end if(pBuffer)
|
||
|
|
||
|
// Make sure we don't have to quit
|
||
|
if(!pDomain->ShouldBackgroundContinue()) return 0;
|
||
|
|
||
|
if(!bNotified) {
|
||
|
pDomain->SetState(DS_ENUMERATING);
|
||
|
bNotified = TRUE;
|
||
|
}
|
||
|
|
||
|
// If there is an extension DLL loaded, allow it to enumerate additional servers
|
||
|
LPWSTR pExtBuffer = NULL;
|
||
|
|
||
|
if(EnumerateProc) {
|
||
|
pExtBuffer = (*EnumerateProc)(pDomain->GetName());
|
||
|
}
|
||
|
|
||
|
// If the extension DLL found servers, concatenate the two buffers
|
||
|
// The ConcatenateBuffers function will delete both buffers and return a
|
||
|
// pointer to the new buffer
|
||
|
if(pExtBuffer) {
|
||
|
Enumerated = TRUE;
|
||
|
pDomain->CreateServers(pExtBuffer, (LPVOID)pDoc);
|
||
|
LocalFree(pExtBuffer);
|
||
|
}
|
||
|
|
||
|
// Make sure we don't have to quit
|
||
|
if(!pDomain->ShouldBackgroundContinue())
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if(Enumerated)
|
||
|
{
|
||
|
// Mark the current server as found
|
||
|
CServer *pCurrentServer = pDoc->GetCurrentServer();
|
||
|
if(pCurrentServer) pCurrentServer->SetBackgroundFound();
|
||
|
// Go through the list of servers and see which ones don't have
|
||
|
// the flag set saying that we found it
|
||
|
CObList TempList;
|
||
|
|
||
|
pDoc->LockServerList();
|
||
|
pServerList = pDoc->GetServerList();
|
||
|
|
||
|
POSITION pos = pServerList->GetHeadPosition();
|
||
|
|
||
|
while(pos)
|
||
|
{
|
||
|
CServer *pServer = (CServer*)pServerList->GetNext(pos);
|
||
|
|
||
|
if(pServer->GetDomain() == pDomain)
|
||
|
{
|
||
|
// we check to see if this server has been initially inserted to our server list
|
||
|
// manually. If so we don't want it inserted to our templist for deletion.
|
||
|
if( !pServer->IsManualFind() &&
|
||
|
( !pServer->IsBackgroundFound() ||
|
||
|
pServer->HasLostConnection() ||
|
||
|
!pServer->IsServerSane() ) )
|
||
|
{
|
||
|
DBGMSG( L"Removing %s background not found or lost connection\n" , pServer->GetName( ) );
|
||
|
// Set the flag to say that this server is inactive
|
||
|
pServer->SetServerInactive();
|
||
|
// Add it to our temporary list
|
||
|
TempList.AddTail(pServer);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pDoc->UnlockServerList();
|
||
|
|
||
|
pos = TempList.GetHeadPosition();
|
||
|
|
||
|
CFrameWnd *p = (CFrameWnd*)pDoc->GetMainWnd();
|
||
|
|
||
|
while(pos)
|
||
|
{
|
||
|
CServer *pServer = (CServer*)TempList.GetNext(pos);
|
||
|
// Send a message to the mainframe to remove the server
|
||
|
if(p && ::IsWindow(p->GetSafeHwnd()))
|
||
|
{
|
||
|
DBGMSG( L"CDomain!Bkthrd removing %s temped threads from treeview & view\n" , pServer->GetName( ) );
|
||
|
|
||
|
// clean up old node
|
||
|
if( pServer->GetTreeItemFromFav( ) != NULL )
|
||
|
{
|
||
|
// we cannot keep a favnode around if a server node is being deleted
|
||
|
// massive AV's will occurr. So a quick fix is to remove the favnode
|
||
|
// if it exists and create a new server node and mark it as manually
|
||
|
// found. This will prevent this server node from being removed in
|
||
|
// case NetEnumServer fails to pick up this server
|
||
|
p->SendMessage( WM_ADMIN_REMOVESERVERFROMFAV , TRUE , ( LPARAM )pServer );
|
||
|
|
||
|
CServer *ptServer = new CServer( pDomain , pServer->GetName( ) , FALSE , FALSE );
|
||
|
|
||
|
if( ptServer != NULL )
|
||
|
{
|
||
|
ptServer->SetManualFind( );
|
||
|
|
||
|
pDoc->AddServer(ptServer);
|
||
|
|
||
|
p->SendMessage(WM_ADMIN_ADDSERVERTOFAV , 0 , (LPARAM)ptServer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
p->SendMessage(WM_ADMIN_REMOVE_SERVER, TRUE, (LPARAM)pServer);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TempList.RemoveAll();
|
||
|
|
||
|
} // end if(Enumerated)
|
||
|
|
||
|
// We don't want to do this constantly, it eats up processor cycles to enumerate servers
|
||
|
// so we'll now let the user refresh these servers manually
|
||
|
// Document destructor will signal the event to wake us up if he
|
||
|
// wants us to quit
|
||
|
pDomain->m_WakeUpEvent.Lock( INFINITE );
|
||
|
|
||
|
bSubsequent = TRUE;
|
||
|
} // end while(1)
|
||
|
|
||
|
return 0;
|
||
|
|
||
|
} // end CDomain::BackgroundThreadProc
|
||
|
|
||
|
|
||
|
|
||
|
/*******************************************************************************
|
||
|
*
|
||
|
* EnumHydraServers - Hydra helper function (taken from utildll and modified
|
||
|
* to be used along with a version check.
|
||
|
*
|
||
|
* Enumerate the Hydra servers on the network by Domain
|
||
|
* Returns all the servers whose version is >= the version passed.
|
||
|
*
|
||
|
* ENTRY:
|
||
|
* pDomain (input)
|
||
|
* Specifies the domain to enumerate; NULL for current domain.
|
||
|
* verMajor (input)
|
||
|
* specifies the Major version to check for.
|
||
|
* verMinor (input)
|
||
|
* specifies the minor version to check for.
|
||
|
*
|
||
|
* EXIT:
|
||
|
* (LPTSTR) Points to LocalAlloced buffer containing results of the
|
||
|
* enumeration, in multi-string format, if sucessful; NULL if
|
||
|
* error. The caller must perform a LocalFree of this buffer
|
||
|
* when done. If error (NULL), the error code is set for
|
||
|
* retrieval by GetLastError();
|
||
|
*
|
||
|
******************************************************************************/
|
||
|
LPWSTR CDomain::EnumHydraServers( /*LPWSTR pDomain,*/ DWORD verMajor, DWORD verMinor )
|
||
|
|
||
|
{
|
||
|
PSERVER_INFO_101 pInfo = NULL;
|
||
|
DWORD dwByteCount, dwIndex, TotalEntries;
|
||
|
DWORD AvailCount = 0;
|
||
|
LPWSTR pTemp, pBuffer = NULL;
|
||
|
|
||
|
/*
|
||
|
* Enumerate all WF servers on the specified domain.
|
||
|
*/
|
||
|
if ( NetServerEnum ( NULL,
|
||
|
101,
|
||
|
(LPBYTE *)&pInfo,
|
||
|
(DWORD) -1,
|
||
|
&AvailCount,
|
||
|
&TotalEntries,
|
||
|
SV_TYPE_TERMINALSERVER,
|
||
|
m_Name, /*pDomain,*/
|
||
|
NULL ) ||
|
||
|
!AvailCount )
|
||
|
goto done;
|
||
|
|
||
|
//
|
||
|
// Traverse list of the servers that match the major and minor versions'criteria
|
||
|
// and calculate the total byte count for list of
|
||
|
// servers that will be returned.
|
||
|
//
|
||
|
for( dwByteCount = dwIndex = 0; dwIndex < AvailCount; dwIndex++ )
|
||
|
{
|
||
|
if( ((pInfo[dwIndex].sv101_version_major & MAJOR_VERSION_MASK) >=
|
||
|
verMajor) && (pInfo[dwIndex].sv101_version_minor >= verMinor) )
|
||
|
{
|
||
|
dwByteCount += (wcslen(pInfo[dwIndex].sv101_name) + 1) * 2;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
dwByteCount += 2; // for ending null
|
||
|
|
||
|
/*
|
||
|
* Allocate memory.
|
||
|
*/
|
||
|
if( (pBuffer = (LPWSTR)LocalAlloc(LPTR, dwByteCount)) == NULL )
|
||
|
{
|
||
|
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Traverse list again and copy servers to buffer.
|
||
|
*/
|
||
|
for( pTemp = pBuffer, dwIndex = 0; dwIndex < AvailCount; dwIndex++ )
|
||
|
{
|
||
|
if( ((pInfo[dwIndex].sv101_version_major & MAJOR_VERSION_MASK) >=
|
||
|
verMajor) && (pInfo[dwIndex].sv101_version_minor >= verMinor) )
|
||
|
{
|
||
|
// MS Bug 1821
|
||
|
if ( wcslen(pInfo[dwIndex].sv101_name) != 0 )
|
||
|
{
|
||
|
wcscpy(pTemp, pInfo[dwIndex].sv101_name);
|
||
|
|
||
|
pTemp += (wcslen(pInfo[dwIndex].sv101_name) + 1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
*pTemp = L'\0'; // ending null
|
||
|
|
||
|
done:
|
||
|
if( AvailCount && pInfo )
|
||
|
{
|
||
|
NetApiBufferFree( pInfo );
|
||
|
}
|
||
|
|
||
|
return(pBuffer);
|
||
|
|
||
|
} // end CDomain::EnumHydraServers
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CDomain::DisconnectAllServers
|
||
|
//
|
||
|
// Disconnect from all servers in this Domain
|
||
|
//
|
||
|
void CDomain::DisconnectAllServers()
|
||
|
{
|
||
|
CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
|
||
|
|
||
|
CObList *pServerList = pDoc->GetServerList();
|
||
|
|
||
|
CString AString;
|
||
|
CDialog dlgWait;
|
||
|
dlgWait.Create(IDD_SHUTDOWN, NULL);
|
||
|
|
||
|
|
||
|
pDoc->LockServerList();
|
||
|
|
||
|
ODS( L"TSADMIN:CDomain::DisconnectAllServers about to disconnect all connected servers\n" );
|
||
|
|
||
|
// Do a first loop to signal the server background threads that they must stop
|
||
|
POSITION pos = pServerList->GetHeadPosition();
|
||
|
while(pos) {
|
||
|
// Get a pointer to the server
|
||
|
CServer *pServer = (CServer*)pServerList->GetNext(pos);
|
||
|
// If this Server is in the domain and connected, tell the server background thread to stop
|
||
|
if(pServer->GetDomain() == this
|
||
|
&& pServer->GetState() != SS_NOT_CONNECTED) {
|
||
|
pServer->ClearBackgroundContinue();
|
||
|
}
|
||
|
}
|
||
|
// do a second loop to disconnect the servers
|
||
|
pos = pServerList->GetHeadPosition();
|
||
|
while(pos) {
|
||
|
// Get a pointer to the server
|
||
|
CServer *pServer = (CServer*)pServerList->GetNext(pos);
|
||
|
// If this Server is in the domain and connected, disconnect from it
|
||
|
if ((pServer->GetDomain() == this) && (pServer->GetState() != SS_NOT_CONNECTED)) {
|
||
|
AString.Format(IDS_DISCONNECTING, pServer->GetName());
|
||
|
dlgWait.SetDlgItemText(IDC_SHUTDOWN_MSG, AString);
|
||
|
|
||
|
// Tell the server to connect
|
||
|
pServer->Disconnect();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// tell domain not to connect to any more servers
|
||
|
//
|
||
|
|
||
|
|
||
|
pDoc->UnlockServerList();
|
||
|
|
||
|
dlgWait.PostMessage(WM_CLOSE);
|
||
|
|
||
|
} // end CDomain::DisconnectAllServers
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////
|
||
|
// CDomain::ConnectAllServers
|
||
|
//
|
||
|
// Connect to all servers in this Domain
|
||
|
//
|
||
|
void CDomain::ConnectAllServers()
|
||
|
{
|
||
|
CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
|
||
|
|
||
|
CObList *pServerList = pDoc->GetServerList();
|
||
|
|
||
|
pDoc->LockServerList();
|
||
|
|
||
|
POSITION pos = pServerList->GetHeadPosition();
|
||
|
while(pos) {
|
||
|
// Get a pointer to the server
|
||
|
CServer *pServer = (CServer*)pServerList->GetNext(pos);
|
||
|
// If this Server is int the domain and not connected, connect to it
|
||
|
if(pServer->GetDomain() == this
|
||
|
&& pServer->IsState(SS_NOT_CONNECTED)) {
|
||
|
// Tell the server to connect
|
||
|
pServer->Connect();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pDoc->UnlockServerList();
|
||
|
|
||
|
} // end CDomain::ConnectAllServers
|